From dddaed1e3023d5c3b833fdba6a842d3f0f7a2dfc Mon Sep 17 00:00:00 2001 From: Giuseppe D'Angelo Date: Mon, 12 Dec 2022 18:57:20 +0100 Subject: [PATCH 001/151] PCRE2: upgrade to 10.42 Upstream released 10.41 and 10.42 in quick succession. [ChangeLog][Third-Party Code] PCRE2 has been updated to 10.42. Change-Id: Iadec8e64e9ce7ddad17afb075157719af76379bd Reviewed-by: Volker Hilsheimer (cherry picked from commit 05e72d53a6b0546d67dc699f922811790a896fb3) Reviewed-by: Qt Cherry-pick Bot --- .../pcre2/import_from_pcre2_tarball.sh | 5 +- src/3rdparty/pcre2/qt_attribution.json | 10 +- src/3rdparty/pcre2/src/pcre2.h | 68 +- src/3rdparty/pcre2/src/pcre2_compile.c | 12 +- src/3rdparty/pcre2/src/pcre2_context.c | 12 +- src/3rdparty/pcre2/src/pcre2_dfa_match.c | 12 +- src/3rdparty/pcre2/src/pcre2_internal.h | 17 +- src/3rdparty/pcre2/src/pcre2_intmodedep.h | 34 +- src/3rdparty/pcre2/src/pcre2_jit_compile.c | 156 +- src/3rdparty/pcre2/src/pcre2_jit_misc.c | 4 +- src/3rdparty/pcre2/src/pcre2_jit_neon_inc.h | 4 +- src/3rdparty/pcre2/src/pcre2_jit_simd_inc.h | 2 +- src/3rdparty/pcre2/src/pcre2_match.c | 176 +- src/3rdparty/pcre2/src/pcre2_match_data.c | 11 +- src/3rdparty/pcre2/src/pcre2_substitute.c | 25 +- src/3rdparty/pcre2/src/sljit/sljitConfig.h | 14 +- .../pcre2/src/sljit/sljitConfigInternal.h | 134 +- src/3rdparty/pcre2/src/sljit/sljitLir.c | 815 +++-- src/3rdparty/pcre2/src/sljit/sljitLir.h | 800 +++-- .../pcre2/src/sljit/sljitNativeARM_32.c | 1004 ++++-- .../pcre2/src/sljit/sljitNativeARM_64.c | 399 ++- .../pcre2/src/sljit/sljitNativeARM_T2_32.c | 860 +++-- .../pcre2/src/sljit/sljitNativeMIPS_32.c | 430 +-- .../pcre2/src/sljit/sljitNativeMIPS_64.c | 460 +-- .../pcre2/src/sljit/sljitNativeMIPS_common.c | 1724 ++++++++-- .../pcre2/src/sljit/sljitNativePPC_32.c | 92 +- .../pcre2/src/sljit/sljitNativePPC_64.c | 166 +- .../pcre2/src/sljit/sljitNativePPC_common.c | 506 ++- .../pcre2/src/sljit/sljitNativeRISCV_32.c | 73 + .../pcre2/src/sljit/sljitNativeRISCV_64.c | 183 ++ .../pcre2/src/sljit/sljitNativeRISCV_common.c | 2762 +++++++++++++++++ .../pcre2/src/sljit/sljitNativeS390X.c | 648 +++- .../pcre2/src/sljit/sljitNativeX86_32.c | 1029 +++--- .../pcre2/src/sljit/sljitNativeX86_64.c | 234 +- .../pcre2/src/sljit/sljitNativeX86_common.c | 543 +++- .../pcre2/src/sljit/sljitWXExecAllocator.c | 53 +- 36 files changed, 9950 insertions(+), 3527 deletions(-) create mode 100644 src/3rdparty/pcre2/src/sljit/sljitNativeRISCV_32.c create mode 100644 src/3rdparty/pcre2/src/sljit/sljitNativeRISCV_64.c create mode 100644 src/3rdparty/pcre2/src/sljit/sljitNativeRISCV_common.c diff --git a/src/3rdparty/pcre2/import_from_pcre2_tarball.sh b/src/3rdparty/pcre2/import_from_pcre2_tarball.sh index a0af3ea2eae..4a454b059be 100755 --- a/src/3rdparty/pcre2/import_from_pcre2_tarball.sh +++ b/src/3rdparty/pcre2/import_from_pcre2_tarball.sh @@ -129,9 +129,10 @@ FILES=" src/sljit/sljitNativePPC_32.c src/sljit/sljitNativePPC_64.c src/sljit/sljitNativePPC_common.c + src/sljit/sljitNativeRISCV_32.c + src/sljit/sljitNativeRISCV_64.c + src/sljit/sljitNativeRISCV_common.c src/sljit/sljitNativeS390X.c - src/sljit/sljitNativeSPARC_32.c - src/sljit/sljitNativeSPARC_common.c src/sljit/sljitNativeX86_32.c src/sljit/sljitNativeX86_64.c src/sljit/sljitNativeX86_common.c diff --git a/src/3rdparty/pcre2/qt_attribution.json b/src/3rdparty/pcre2/qt_attribution.json index 1ec700cd06e..2d8c6586578 100644 --- a/src/3rdparty/pcre2/qt_attribution.json +++ b/src/3rdparty/pcre2/qt_attribution.json @@ -7,13 +7,13 @@ "Description": "The PCRE library is a set of functions that implement regular expression pattern matching using the same syntax and semantics as Perl 5.", "Homepage": "http://www.pcre.org/", - "Version": "10.40", - "DownloadLocation": "https://github.com/PCRE2Project/pcre2/releases/download/pcre2-10.40/pcre2-10.40.tar.bz2", + "Version": "10.42", + "DownloadLocation": "https://github.com/PCRE2Project/pcre2/releases/download/pcre2-10.42/pcre2-10.42.tar.bz2", "License": "BSD 3-clause \"New\" or \"Revised\" License", "LicenseId": "BSD-3-Clause", "LicenseFile": "LICENCE", "Copyright": "Copyright (c) 1997-2022 University of Cambridge -Copyright (c) 2010-2020 Zoltan Herczeg" +Copyright (c) 2010-2022 Zoltan Herczeg" }, { "Id": "pcre2-sljit", @@ -24,8 +24,8 @@ Copyright (c) 2010-2020 Zoltan Herczeg" "Path": "src/sljit", "Description": "The PCRE library is a set of functions that implement regular expression pattern matching using the same syntax and semantics as Perl 5.", "Homepage": "http://www.pcre.org/", - "Version": "10.40", - "DownloadLocation": "https://github.com/PCRE2Project/pcre2/releases/download/pcre2-10.40/pcre2-10.40.tar.bz2", + "Version": "10.42", + "DownloadLocation": "https://github.com/PCRE2Project/pcre2/releases/download/pcre2-10.42/pcre2-10.42.tar.bz2", "License": "BSD 2-clause \"Simplified\" License", "LicenseId": "BSD-2-Clause", "LicenseFile": "LICENCE-SLJIT", diff --git a/src/3rdparty/pcre2/src/pcre2.h b/src/3rdparty/pcre2/src/pcre2.h index 8adcede57cf..1cbecd0e86e 100644 --- a/src/3rdparty/pcre2/src/pcre2.h +++ b/src/3rdparty/pcre2/src/pcre2.h @@ -42,9 +42,9 @@ POSSIBILITY OF SUCH DAMAGE. /* The current PCRE version information. */ #define PCRE2_MAJOR 10 -#define PCRE2_MINOR 40 +#define PCRE2_MINOR 42 #define PCRE2_PRERELEASE -#define PCRE2_DATE 2022-04-14 +#define PCRE2_DATE 2022-12-11 /* When an application links to a PCRE DLL in Windows, the symbols that are imported have to be identified as such. When building PCRE2, the appropriate @@ -572,19 +572,19 @@ PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION pcre2_config(uint32_t, void *); /* Functions for manipulating contexts. */ #define PCRE2_GENERAL_CONTEXT_FUNCTIONS \ -PCRE2_EXP_DECL pcre2_general_context PCRE2_CALL_CONVENTION \ - *pcre2_general_context_copy(pcre2_general_context *); \ -PCRE2_EXP_DECL pcre2_general_context PCRE2_CALL_CONVENTION \ - *pcre2_general_context_create(void *(*)(PCRE2_SIZE, void *), \ +PCRE2_EXP_DECL pcre2_general_context *PCRE2_CALL_CONVENTION \ + pcre2_general_context_copy(pcre2_general_context *); \ +PCRE2_EXP_DECL pcre2_general_context *PCRE2_CALL_CONVENTION \ + pcre2_general_context_create(void *(*)(PCRE2_SIZE, void *), \ void (*)(void *, void *), void *); \ PCRE2_EXP_DECL void PCRE2_CALL_CONVENTION \ pcre2_general_context_free(pcre2_general_context *); #define PCRE2_COMPILE_CONTEXT_FUNCTIONS \ -PCRE2_EXP_DECL pcre2_compile_context PCRE2_CALL_CONVENTION \ - *pcre2_compile_context_copy(pcre2_compile_context *); \ -PCRE2_EXP_DECL pcre2_compile_context PCRE2_CALL_CONVENTION \ - *pcre2_compile_context_create(pcre2_general_context *);\ +PCRE2_EXP_DECL pcre2_compile_context *PCRE2_CALL_CONVENTION \ + pcre2_compile_context_copy(pcre2_compile_context *); \ +PCRE2_EXP_DECL pcre2_compile_context *PCRE2_CALL_CONVENTION \ + pcre2_compile_context_create(pcre2_general_context *);\ PCRE2_EXP_DECL void PCRE2_CALL_CONVENTION \ pcre2_compile_context_free(pcre2_compile_context *); \ PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \ @@ -604,10 +604,10 @@ PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \ int (*)(uint32_t, void *), void *); #define PCRE2_MATCH_CONTEXT_FUNCTIONS \ -PCRE2_EXP_DECL pcre2_match_context PCRE2_CALL_CONVENTION \ - *pcre2_match_context_copy(pcre2_match_context *); \ -PCRE2_EXP_DECL pcre2_match_context PCRE2_CALL_CONVENTION \ - *pcre2_match_context_create(pcre2_general_context *); \ +PCRE2_EXP_DECL pcre2_match_context *PCRE2_CALL_CONVENTION \ + pcre2_match_context_copy(pcre2_match_context *); \ +PCRE2_EXP_DECL pcre2_match_context *PCRE2_CALL_CONVENTION \ + pcre2_match_context_create(pcre2_general_context *); \ PCRE2_EXP_DECL void PCRE2_CALL_CONVENTION \ pcre2_match_context_free(pcre2_match_context *); \ PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \ @@ -631,10 +631,10 @@ PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \ void *(*)(PCRE2_SIZE, void *), void (*)(void *, void *), void *); #define PCRE2_CONVERT_CONTEXT_FUNCTIONS \ -PCRE2_EXP_DECL pcre2_convert_context PCRE2_CALL_CONVENTION \ - *pcre2_convert_context_copy(pcre2_convert_context *); \ -PCRE2_EXP_DECL pcre2_convert_context PCRE2_CALL_CONVENTION \ - *pcre2_convert_context_create(pcre2_general_context *); \ +PCRE2_EXP_DECL pcre2_convert_context *PCRE2_CALL_CONVENTION \ + pcre2_convert_context_copy(pcre2_convert_context *); \ +PCRE2_EXP_DECL pcre2_convert_context *PCRE2_CALL_CONVENTION \ + pcre2_convert_context_create(pcre2_general_context *); \ PCRE2_EXP_DECL void PCRE2_CALL_CONVENTION \ pcre2_convert_context_free(pcre2_convert_context *); \ PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \ @@ -646,15 +646,15 @@ PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \ /* Functions concerned with compiling a pattern to PCRE internal code. */ #define PCRE2_COMPILE_FUNCTIONS \ -PCRE2_EXP_DECL pcre2_code PCRE2_CALL_CONVENTION \ - *pcre2_compile(PCRE2_SPTR, PCRE2_SIZE, uint32_t, int *, PCRE2_SIZE *, \ +PCRE2_EXP_DECL pcre2_code *PCRE2_CALL_CONVENTION \ + pcre2_compile(PCRE2_SPTR, PCRE2_SIZE, uint32_t, int *, PCRE2_SIZE *, \ pcre2_compile_context *); \ PCRE2_EXP_DECL void PCRE2_CALL_CONVENTION \ pcre2_code_free(pcre2_code *); \ -PCRE2_EXP_DECL pcre2_code PCRE2_CALL_CONVENTION \ - *pcre2_code_copy(const pcre2_code *); \ -PCRE2_EXP_DECL pcre2_code PCRE2_CALL_CONVENTION \ - *pcre2_code_copy_with_tables(const pcre2_code *); +PCRE2_EXP_DECL pcre2_code *PCRE2_CALL_CONVENTION \ + pcre2_code_copy(const pcre2_code *); \ +PCRE2_EXP_DECL pcre2_code *PCRE2_CALL_CONVENTION \ + pcre2_code_copy_with_tables(const pcre2_code *); /* Functions that give information about a compiled pattern. */ @@ -670,10 +670,10 @@ PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \ /* Functions for running a match and inspecting the result. */ #define PCRE2_MATCH_FUNCTIONS \ -PCRE2_EXP_DECL pcre2_match_data PCRE2_CALL_CONVENTION \ - *pcre2_match_data_create(uint32_t, pcre2_general_context *); \ -PCRE2_EXP_DECL pcre2_match_data PCRE2_CALL_CONVENTION \ - *pcre2_match_data_create_from_pattern(const pcre2_code *, \ +PCRE2_EXP_DECL pcre2_match_data *PCRE2_CALL_CONVENTION \ + pcre2_match_data_create(uint32_t, pcre2_general_context *); \ +PCRE2_EXP_DECL pcre2_match_data *PCRE2_CALL_CONVENTION \ + pcre2_match_data_create_from_pattern(const pcre2_code *, \ pcre2_general_context *); \ PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \ pcre2_dfa_match(const pcre2_code *, PCRE2_SPTR, PCRE2_SIZE, PCRE2_SIZE, \ @@ -689,8 +689,8 @@ PCRE2_EXP_DECL PCRE2_SIZE PCRE2_CALL_CONVENTION \ pcre2_get_match_data_size(pcre2_match_data *); \ PCRE2_EXP_DECL uint32_t PCRE2_CALL_CONVENTION \ pcre2_get_ovector_count(pcre2_match_data *); \ -PCRE2_EXP_DECL PCRE2_SIZE PCRE2_CALL_CONVENTION \ - *pcre2_get_ovector_pointer(pcre2_match_data *); \ +PCRE2_EXP_DECL PCRE2_SIZE *PCRE2_CALL_CONVENTION \ + pcre2_get_ovector_pointer(pcre2_match_data *); \ PCRE2_EXP_DECL PCRE2_SIZE PCRE2_CALL_CONVENTION \ pcre2_get_startchar(pcre2_match_data *); @@ -770,8 +770,8 @@ PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \ uint32_t, pcre2_match_data *, pcre2_match_context *); \ PCRE2_EXP_DECL void PCRE2_CALL_CONVENTION \ pcre2_jit_free_unused_memory(pcre2_general_context *); \ -PCRE2_EXP_DECL pcre2_jit_stack PCRE2_CALL_CONVENTION \ - *pcre2_jit_stack_create(PCRE2_SIZE, PCRE2_SIZE, pcre2_general_context *); \ +PCRE2_EXP_DECL pcre2_jit_stack *PCRE2_CALL_CONVENTION \ + pcre2_jit_stack_create(PCRE2_SIZE, PCRE2_SIZE, pcre2_general_context *); \ PCRE2_EXP_DECL void PCRE2_CALL_CONVENTION \ pcre2_jit_stack_assign(pcre2_match_context *, pcre2_jit_callback, void *); \ PCRE2_EXP_DECL void PCRE2_CALL_CONVENTION \ @@ -783,8 +783,8 @@ PCRE2_EXP_DECL void PCRE2_CALL_CONVENTION \ #define PCRE2_OTHER_FUNCTIONS \ PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \ pcre2_get_error_message(int, PCRE2_UCHAR *, PCRE2_SIZE); \ -PCRE2_EXP_DECL const uint8_t PCRE2_CALL_CONVENTION \ - *pcre2_maketables(pcre2_general_context *); \ +PCRE2_EXP_DECL const uint8_t *PCRE2_CALL_CONVENTION \ + pcre2_maketables(pcre2_general_context *); \ PCRE2_EXP_DECL void PCRE2_CALL_CONVENTION \ pcre2_maketables_free(pcre2_general_context *, const uint8_t *); diff --git a/src/3rdparty/pcre2/src/pcre2_compile.c b/src/3rdparty/pcre2/src/pcre2_compile.c index de259c9c405..edf7e82e6ee 100644 --- a/src/3rdparty/pcre2/src/pcre2_compile.c +++ b/src/3rdparty/pcre2/src/pcre2_compile.c @@ -1266,8 +1266,10 @@ PCRE2_SIZE* ref_count; if (code != NULL) { +#ifdef SUPPORT_JIT if (code->executable_jit != NULL) PRIV(jit_free)(code->executable_jit, &code->memctl); +#endif if ((code->flags & PCRE2_DEREF_TABLES) != 0) { @@ -2687,7 +2689,7 @@ if ((options & PCRE2_EXTENDED_MORE) != 0) options |= PCRE2_EXTENDED; while (ptr < ptrend) { int prev_expect_cond_assert; - uint32_t min_repeat, max_repeat; + uint32_t min_repeat = 0, max_repeat = 0; uint32_t set, unset, *optset; uint32_t terminator; uint32_t prev_meta_quantifier; @@ -8552,7 +8554,7 @@ do { op == OP_SCBRA || op == OP_SCBRAPOS) { int n = GET2(scode, 1+LINK_SIZE); - int new_map = bracket_map | ((n < 32)? (1u << n) : 1); + unsigned int new_map = bracket_map | ((n < 32)? (1u << n) : 1); if (!is_startline(scode, new_map, cb, atomcount, inassert)) return FALSE; } @@ -10620,4 +10622,10 @@ re = NULL; goto EXIT; } +/* These #undefs are here to enable unity builds with CMake. */ + +#undef NLBLOCK /* Block containing newline information */ +#undef PSSTART /* Field containing processed string start */ +#undef PSEND /* Field containing processed string end */ + /* End of pcre2_compile.c */ diff --git a/src/3rdparty/pcre2/src/pcre2_context.c b/src/3rdparty/pcre2/src/pcre2_context.c index f904a494a01..8e05ede50c2 100644 --- a/src/3rdparty/pcre2/src/pcre2_context.c +++ b/src/3rdparty/pcre2/src/pcre2_context.c @@ -7,7 +7,7 @@ and semantics are as close as possible to those of the Perl 5 language. Written by Philip Hazel Original API code Copyright (c) 1997-2012 University of Cambridge - New API code Copyright (c) 2016-2018 University of Cambridge + New API code Copyright (c) 2016-2022 University of Cambridge ----------------------------------------------------------------------------- Redistribution and use in source and binary forms, with or without @@ -443,8 +443,11 @@ mcontext->offset_limit = limit; return 0; } -/* This function became obsolete at release 10.30. It is kept as a synonym for -backwards compatibility. */ +/* These functions became obsolete at release 10.30. The first is kept as a +synonym for backwards compatibility. The second now does nothing. Exclude both +from coverage reports. */ + +/* LCOV_EXCL_START */ PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION pcre2_set_recursion_limit(pcre2_match_context *mcontext, uint32_t limit) @@ -464,6 +467,9 @@ pcre2_set_recursion_memory_management(pcre2_match_context *mcontext, return 0; } +/* LCOV_EXCL_STOP */ + + /* ------------ Convert context ------------ */ PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION diff --git a/src/3rdparty/pcre2/src/pcre2_dfa_match.c b/src/3rdparty/pcre2/src/pcre2_dfa_match.c index d29130f2d0c..b16e594cc06 100644 --- a/src/3rdparty/pcre2/src/pcre2_dfa_match.c +++ b/src/3rdparty/pcre2/src/pcre2_dfa_match.c @@ -350,7 +350,7 @@ Returns: the return from the callout */ static int -do_callout(PCRE2_SPTR code, PCRE2_SIZE *offsets, PCRE2_SPTR current_subject, +do_callout_dfa(PCRE2_SPTR code, PCRE2_SIZE *offsets, PCRE2_SPTR current_subject, PCRE2_SPTR ptr, dfa_match_block *mb, PCRE2_SIZE extracode, PCRE2_SIZE *lengthptr) { @@ -2799,7 +2799,7 @@ for (;;) || code[LINK_SIZE + 1] == OP_CALLOUT_STR) { PCRE2_SIZE callout_length; - rrc = do_callout(code, offsets, current_subject, ptr, mb, + rrc = do_callout_dfa(code, offsets, current_subject, ptr, mb, 1 + LINK_SIZE, &callout_length); if (rrc < 0) return rrc; /* Abandon */ if (rrc > 0) break; /* Fail this thread */ @@ -3196,7 +3196,7 @@ for (;;) case OP_CALLOUT_STR: { PCRE2_SIZE callout_length; - rrc = do_callout(code, offsets, current_subject, ptr, mb, 0, + rrc = do_callout_dfa(code, offsets, current_subject, ptr, mb, 0, &callout_length); if (rrc < 0) return rrc; /* Abandon */ if (rrc == 0) @@ -4057,4 +4057,10 @@ while (rws->next != NULL) return rc; } +/* These #undefs are here to enable unity builds with CMake. */ + +#undef NLBLOCK /* Block containing newline information */ +#undef PSSTART /* Field containing processed string start */ +#undef PSEND /* Field containing processed string end */ + /* End of pcre2_dfa_match.c */ diff --git a/src/3rdparty/pcre2/src/pcre2_internal.h b/src/3rdparty/pcre2/src/pcre2_internal.h index fe7a0e005a0..92dd3138d4a 100644 --- a/src/3rdparty/pcre2/src/pcre2_internal.h +++ b/src/3rdparty/pcre2/src/pcre2_internal.h @@ -220,18 +220,17 @@ not rely on this. */ #define COMPILE_ERROR_BASE 100 -/* The initial frames vector for remembering backtracking points in -pcre2_match() is allocated on the system stack, of this size (bytes). The size -must be a multiple of sizeof(PCRE2_SPTR) in all environments, so making it a -multiple of 8 is best. Typical frame sizes are a few hundred bytes (it depends -on the number of capturing parentheses) so 20KiB handles quite a few frames. A -larger vector on the heap is obtained for patterns that need more frames. The -maximum size of this can be limited. */ +/* The initial frames vector for remembering pcre2_match() backtracking points +is allocated on the heap, of this size (bytes) or ten times the frame size if +larger, unless the heap limit is smaller. Typical frame sizes are a few hundred +bytes (it depends on the number of capturing parentheses) so 20KiB handles +quite a few frames. A larger vector on the heap is obtained for matches that +need more frames, subject to the heap limit. */ #define START_FRAMES_SIZE 20480 -/* Similarly, for DFA matching, an initial internal workspace vector is -allocated on the stack. */ +/* For DFA matching, an initial internal workspace vector is allocated on the +stack. The heap is used only if this turns out to be too small. */ #define DFA_START_RWS_SIZE 30720 diff --git a/src/3rdparty/pcre2/src/pcre2_intmodedep.h b/src/3rdparty/pcre2/src/pcre2_intmodedep.h index f8a3d25de67..390e737a6ef 100644 --- a/src/3rdparty/pcre2/src/pcre2_intmodedep.h +++ b/src/3rdparty/pcre2/src/pcre2_intmodedep.h @@ -7,7 +7,7 @@ and semantics are as close as possible to those of the Perl 5 language. Written by Philip Hazel Original API code Copyright (c) 1997-2012 University of Cambridge - New API code Copyright (c) 2016-2018 University of Cambridge + New API code Copyright (c) 2016-2022 University of Cambridge ----------------------------------------------------------------------------- Redistribution and use in source and binary forms, with or without @@ -649,19 +649,23 @@ the size varies from call to call. As the maximum number of capturing subpatterns is 65535 we must allow for 65536 strings to include the overall match. (See also the heapframe structure below.) */ +struct heapframe; /* Forward reference */ + typedef struct pcre2_real_match_data { - pcre2_memctl memctl; - const pcre2_real_code *code; /* The pattern used for the match */ - PCRE2_SPTR subject; /* The subject that was matched */ - PCRE2_SPTR mark; /* Pointer to last mark */ - PCRE2_SIZE leftchar; /* Offset to leftmost code unit */ - PCRE2_SIZE rightchar; /* Offset to rightmost code unit */ - PCRE2_SIZE startchar; /* Offset to starting code unit */ - uint8_t matchedby; /* Type of match (normal, JIT, DFA) */ - uint8_t flags; /* Various flags */ - uint16_t oveccount; /* Number of pairs */ - int rc; /* The return code from the match */ - PCRE2_SIZE ovector[131072]; /* Must be last in the structure */ + pcre2_memctl memctl; /* Memory control fields */ + const pcre2_real_code *code; /* The pattern used for the match */ + PCRE2_SPTR subject; /* The subject that was matched */ + PCRE2_SPTR mark; /* Pointer to last mark */ + struct heapframe *heapframes; /* Backtracking frames heap memory */ + PCRE2_SIZE heapframes_size; /* Malloc-ed size */ + PCRE2_SIZE leftchar; /* Offset to leftmost code unit */ + PCRE2_SIZE rightchar; /* Offset to rightmost code unit */ + PCRE2_SIZE startchar; /* Offset to starting code unit */ + uint8_t matchedby; /* Type of match (normal, JIT, DFA) */ + uint8_t flags; /* Various flags */ + uint16_t oveccount; /* Number of pairs */ + int rc; /* The return code from the match */ + PCRE2_SIZE ovector[131072]; /* Must be last in the structure */ } pcre2_real_match_data; @@ -854,10 +858,6 @@ doing traditional NFA matching (pcre2_match() and friends). */ typedef struct match_block { pcre2_memctl memctl; /* For general use */ - PCRE2_SIZE frame_vector_size; /* Size of a backtracking frame */ - heapframe *match_frames; /* Points to vector of frames */ - heapframe *match_frames_top; /* Points after the end of the vector */ - heapframe *stack_frames; /* The original vector on the stack */ PCRE2_SIZE heap_limit; /* As it says */ uint32_t match_limit; /* As it says */ uint32_t match_limit_depth; /* As it says */ diff --git a/src/3rdparty/pcre2/src/pcre2_jit_compile.c b/src/3rdparty/pcre2/src/pcre2_jit_compile.c index d726c3ca049..0afd27c5eed 100644 --- a/src/3rdparty/pcre2/src/pcre2_jit_compile.c +++ b/src/3rdparty/pcre2/src/pcre2_jit_compile.c @@ -542,7 +542,7 @@ typedef struct compare_context { #undef CMP /* Used for accessing the elements of the stack. */ -#define STACK(i) ((i) * (int)sizeof(sljit_sw)) +#define STACK(i) ((i) * SSIZE_OF(sw)) #ifdef SLJIT_PREF_SHIFT_REG #if SLJIT_PREF_SHIFT_REG == SLJIT_R2 @@ -590,8 +590,8 @@ to characters. The vector data is divided into two groups: the first group contains the start / end character pointers, and the second is the start pointers when the end of the capturing group has not yet reached. */ #define OVECTOR_START (common->ovector_start) -#define OVECTOR(i) (OVECTOR_START + (i) * (sljit_sw)sizeof(sljit_sw)) -#define OVECTOR_PRIV(i) (common->cbra_ptr + (i) * (sljit_sw)sizeof(sljit_sw)) +#define OVECTOR(i) (OVECTOR_START + (i) * SSIZE_OF(sw)) +#define OVECTOR_PRIV(i) (common->cbra_ptr + (i) * SSIZE_OF(sw)) #define PRIVATE_DATA(cc) (common->private_data_ptrs[(cc) - common->start]) #if PCRE2_CODE_UNIT_WIDTH == 8 @@ -2151,9 +2151,9 @@ while (cc < ccend) { OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(0)); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, SLJIT_IMM, -OVECTOR(0)); - stackpos -= (int)sizeof(sljit_sw); + stackpos -= SSIZE_OF(sw); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP1, 0); - stackpos -= (int)sizeof(sljit_sw); + stackpos -= SSIZE_OF(sw); setsom_found = TRUE; } cc += 1; @@ -2168,9 +2168,9 @@ while (cc < ccend) { OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->mark_ptr); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, SLJIT_IMM, -common->mark_ptr); - stackpos -= (int)sizeof(sljit_sw); + stackpos -= SSIZE_OF(sw); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP1, 0); - stackpos -= (int)sizeof(sljit_sw); + stackpos -= SSIZE_OF(sw); setmark_found = TRUE; } cc += 1 + 2 + cc[1]; @@ -2181,27 +2181,27 @@ while (cc < ccend) { OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(0)); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, SLJIT_IMM, -OVECTOR(0)); - stackpos -= (int)sizeof(sljit_sw); + stackpos -= SSIZE_OF(sw); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP1, 0); - stackpos -= (int)sizeof(sljit_sw); + stackpos -= SSIZE_OF(sw); setsom_found = TRUE; } if (common->mark_ptr != 0 && !setmark_found) { OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->mark_ptr); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, SLJIT_IMM, -common->mark_ptr); - stackpos -= (int)sizeof(sljit_sw); + stackpos -= SSIZE_OF(sw); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP1, 0); - stackpos -= (int)sizeof(sljit_sw); + stackpos -= SSIZE_OF(sw); setmark_found = TRUE; } if (common->capture_last_ptr != 0 && !capture_last_found) { OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->capture_last_ptr); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, SLJIT_IMM, -common->capture_last_ptr); - stackpos -= (int)sizeof(sljit_sw); + stackpos -= SSIZE_OF(sw); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP1, 0); - stackpos -= (int)sizeof(sljit_sw); + stackpos -= SSIZE_OF(sw); capture_last_found = TRUE; } cc += 1 + LINK_SIZE; @@ -2215,20 +2215,20 @@ while (cc < ccend) { OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->capture_last_ptr); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, SLJIT_IMM, -common->capture_last_ptr); - stackpos -= (int)sizeof(sljit_sw); + stackpos -= SSIZE_OF(sw); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP1, 0); - stackpos -= (int)sizeof(sljit_sw); + stackpos -= SSIZE_OF(sw); capture_last_found = TRUE; } offset = (GET2(cc, 1 + LINK_SIZE)) << 1; OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, SLJIT_IMM, OVECTOR(offset)); - stackpos -= (int)sizeof(sljit_sw); + stackpos -= SSIZE_OF(sw); OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset)); OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset + 1)); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP1, 0); - stackpos -= (int)sizeof(sljit_sw); + stackpos -= SSIZE_OF(sw); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP2, 0); - stackpos -= (int)sizeof(sljit_sw); + stackpos -= SSIZE_OF(sw); cc += 1 + LINK_SIZE + IMM2_SIZE; break; @@ -3144,7 +3144,7 @@ static SLJIT_INLINE void allocate_stack(compiler_common *common, int size) DEFINE_COMPILER; SLJIT_ASSERT(size > 0); -OP2(SLJIT_SUB, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, size * sizeof(sljit_sw)); +OP2(SLJIT_SUB, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, size * SSIZE_OF(sw)); #ifdef DESTROY_REGISTERS OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 12345); OP1(SLJIT_MOV, TMP3, 0, TMP1, 0); @@ -3160,7 +3160,7 @@ static SLJIT_INLINE void free_stack(compiler_common *common, int size) DEFINE_COMPILER; SLJIT_ASSERT(size > 0); -OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, size * sizeof(sljit_sw)); +OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, size * SSIZE_OF(sw)); } static sljit_uw * allocate_read_only_data(compiler_common *common, sljit_uw size) @@ -3200,12 +3200,12 @@ if (length < 8) } else { - if (sljit_emit_mem(compiler, SLJIT_MOV | SLJIT_MEM_SUPP | SLJIT_MEM_STORE | SLJIT_MEM_PRE, SLJIT_R0, SLJIT_MEM1(SLJIT_R1), sizeof(sljit_sw)) == SLJIT_SUCCESS) + if (sljit_emit_mem_update(compiler, SLJIT_MOV | SLJIT_MEM_SUPP | SLJIT_MEM_STORE | SLJIT_MEM_PRE, SLJIT_R0, SLJIT_MEM1(SLJIT_R1), sizeof(sljit_sw)) == SLJIT_SUCCESS) { GET_LOCAL_BASE(SLJIT_R1, 0, OVECTOR_START); OP1(SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, length - 1); loop = LABEL(); - sljit_emit_mem(compiler, SLJIT_MOV | SLJIT_MEM_STORE | SLJIT_MEM_PRE, SLJIT_R0, SLJIT_MEM1(SLJIT_R1), sizeof(sljit_sw)); + sljit_emit_mem_update(compiler, SLJIT_MOV | SLJIT_MEM_STORE | SLJIT_MEM_PRE, SLJIT_R0, SLJIT_MEM1(SLJIT_R1), sizeof(sljit_sw)); OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_R2, 0, SLJIT_R2, 0, SLJIT_IMM, 1); JUMPTO(SLJIT_NOT_ZERO, loop); } @@ -3261,8 +3261,8 @@ OP2(SLJIT_ADD, TMP2, 0, TMP1, 0, SLJIT_IMM, size - uncleared_size); loop = LABEL(); OP1(SLJIT_MOV, SLJIT_MEM1(TMP1), 0, src, 0); OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 3 * sizeof(sljit_sw)); -OP1(SLJIT_MOV, SLJIT_MEM1(TMP1), -2 * (sljit_sw)sizeof(sljit_sw), src, 0); -OP1(SLJIT_MOV, SLJIT_MEM1(TMP1), -1 * (sljit_sw)sizeof(sljit_sw), src, 0); +OP1(SLJIT_MOV, SLJIT_MEM1(TMP1), -2 * SSIZE_OF(sw), src, 0); +OP1(SLJIT_MOV, SLJIT_MEM1(TMP1), -1 * SSIZE_OF(sw), src, 0); CMPTO(SLJIT_LESS, TMP1, 0, TMP2, 0, loop); if (uncleared_size >= sizeof(sljit_sw)) @@ -3289,12 +3289,12 @@ if (length < 8) } else { - if (sljit_emit_mem(compiler, SLJIT_MOV | SLJIT_MEM_SUPP | SLJIT_MEM_STORE | SLJIT_MEM_PRE, TMP1, SLJIT_MEM1(TMP2), sizeof(sljit_sw)) == SLJIT_SUCCESS) + if (sljit_emit_mem_update(compiler, SLJIT_MOV | SLJIT_MEM_SUPP | SLJIT_MEM_STORE | SLJIT_MEM_PRE, TMP1, SLJIT_MEM1(TMP2), sizeof(sljit_sw)) == SLJIT_SUCCESS) { GET_LOCAL_BASE(TMP2, 0, OVECTOR_START + sizeof(sljit_sw)); OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_IMM, length - 2); loop = LABEL(); - sljit_emit_mem(compiler, SLJIT_MOV | SLJIT_MEM_STORE | SLJIT_MEM_PRE, TMP1, SLJIT_MEM1(TMP2), sizeof(sljit_sw)); + sljit_emit_mem_update(compiler, SLJIT_MOV | SLJIT_MEM_STORE | SLJIT_MEM_PRE, TMP1, SLJIT_MEM1(TMP2), sizeof(sljit_sw)); OP2(SLJIT_SUB | SLJIT_SET_Z, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, 1); JUMPTO(SLJIT_NOT_ZERO, loop); } @@ -3386,7 +3386,7 @@ else OP2(SLJIT_ADD, SLJIT_R2, 0, SLJIT_R2, 0, SLJIT_IMM, SLJIT_OFFSETOF(pcre2_match_data, ovector) - sizeof(PCRE2_SIZE)); } -has_pre = sljit_emit_mem(compiler, SLJIT_MOV | SLJIT_MEM_SUPP | SLJIT_MEM_PRE, SLJIT_S1, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw)) == SLJIT_SUCCESS; +has_pre = sljit_emit_mem_update(compiler, SLJIT_MOV | SLJIT_MEM_SUPP | SLJIT_MEM_PRE, SLJIT_S1, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw)) == SLJIT_SUCCESS; GET_LOCAL_BASE(SLJIT_S0, 0, OVECTOR_START - (has_pre ? sizeof(sljit_sw) : 0)); OP1(SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM1(HAS_VIRTUAL_REGISTERS ? SLJIT_R0 : ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, begin)); @@ -3394,7 +3394,7 @@ OP1(SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM1(HAS_VIRTUAL_REGISTERS ? SLJIT_R0 : ARGUME loop = LABEL(); if (has_pre) - sljit_emit_mem(compiler, SLJIT_MOV | SLJIT_MEM_PRE, SLJIT_S1, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw)); + sljit_emit_mem_update(compiler, SLJIT_MOV | SLJIT_MEM_PRE, SLJIT_S1, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw)); else { OP1(SLJIT_MOV, SLJIT_S1, 0, SLJIT_MEM1(SLJIT_S0), 0); @@ -3417,14 +3417,14 @@ JUMPTO(SLJIT_NOT_ZERO, loop); /* Calculate the return value, which is the maximum ovector value. */ if (topbracket > 1) { - if (sljit_emit_mem(compiler, SLJIT_MOV | SLJIT_MEM_SUPP | SLJIT_MEM_PRE, SLJIT_R2, SLJIT_MEM1(SLJIT_R0), -(2 * (sljit_sw)sizeof(sljit_sw))) == SLJIT_SUCCESS) + if (sljit_emit_mem_update(compiler, SLJIT_MOV | SLJIT_MEM_SUPP | SLJIT_MEM_PRE, SLJIT_R2, SLJIT_MEM1(SLJIT_R0), -(2 * SSIZE_OF(sw))) == SLJIT_SUCCESS) { GET_LOCAL_BASE(SLJIT_R0, 0, OVECTOR_START + topbracket * 2 * sizeof(sljit_sw)); OP1(SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, topbracket + 1); /* OVECTOR(0) is never equal to SLJIT_S2. */ loop = LABEL(); - sljit_emit_mem(compiler, SLJIT_MOV | SLJIT_MEM_PRE, SLJIT_R2, SLJIT_MEM1(SLJIT_R0), -(2 * (sljit_sw)sizeof(sljit_sw))); + sljit_emit_mem_update(compiler, SLJIT_MOV | SLJIT_MEM_PRE, SLJIT_R2, SLJIT_MEM1(SLJIT_R0), -(2 * SSIZE_OF(sw))); OP2(SLJIT_SUB, SLJIT_R1, 0, SLJIT_R1, 0, SLJIT_IMM, 1); CMPTO(SLJIT_EQUAL, SLJIT_R2, 0, SLJIT_S2, 0, loop); OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_R1, 0); @@ -3437,7 +3437,7 @@ if (topbracket > 1) /* OVECTOR(0) is never equal to SLJIT_S2. */ loop = LABEL(); OP1(SLJIT_MOV, SLJIT_R2, 0, SLJIT_MEM1(SLJIT_R0), 0); - OP2(SLJIT_SUB, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, 2 * (sljit_sw)sizeof(sljit_sw)); + OP2(SLJIT_SUB, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, 2 * SSIZE_OF(sw)); OP2(SLJIT_SUB, SLJIT_R1, 0, SLJIT_R1, 0, SLJIT_IMM, 1); CMPTO(SLJIT_EQUAL, SLJIT_R2, 0, SLJIT_S2, 0, loop); OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_R1, 0); @@ -4652,8 +4652,8 @@ if (common->nltype != NLTYPE_ANY) /* All newlines are ascii, just skip intermediate octets. */ jump[0] = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); loop = LABEL(); - if (sljit_emit_mem(compiler, MOV_UCHAR | SLJIT_MEM_SUPP | SLJIT_MEM_POST, TMP2, SLJIT_MEM1(STR_PTR), IN_UCHARS(1)) == SLJIT_SUCCESS) - sljit_emit_mem(compiler, MOV_UCHAR | SLJIT_MEM_POST, TMP2, SLJIT_MEM1(STR_PTR), IN_UCHARS(1)); + if (sljit_emit_mem_update(compiler, MOV_UCHAR | SLJIT_MEM_SUPP | SLJIT_MEM_POST, TMP2, SLJIT_MEM1(STR_PTR), IN_UCHARS(1)) == SLJIT_SUCCESS) + sljit_emit_mem_update(compiler, MOV_UCHAR | SLJIT_MEM_POST, TMP2, SLJIT_MEM1(STR_PTR), IN_UCHARS(1)); else { OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0)); @@ -5886,7 +5886,7 @@ static BOOL check_fast_forward_char_pair_simd(compiler_common *common, fast_forw while (j < i) { b_pri = chars[j].last_count; - if (b_pri > 2 && a_pri + b_pri >= max_pri) + if (b_pri > 2 && (sljit_u32)a_pri + (sljit_u32)b_pri >= max_pri) { b1 = chars[j].chars[0]; b2 = chars[j].chars[1]; @@ -6572,21 +6572,21 @@ GET_LOCAL_BASE(TMP1, 0, 0); /* Drop frames until we reach STACK_TOP. */ mainloop = LABEL(); -OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), -sizeof(sljit_sw)); +OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), -SSIZE_OF(sw)); jump = CMP(SLJIT_SIG_LESS_EQUAL, TMP2, 0, SLJIT_IMM, 0); OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, TMP1, 0); if (HAS_VIRTUAL_REGISTERS) { - OP1(SLJIT_MOV, SLJIT_MEM1(TMP2), 0, SLJIT_MEM1(STACK_TOP), -(2 * sizeof(sljit_sw))); - OP1(SLJIT_MOV, SLJIT_MEM1(TMP2), sizeof(sljit_sw), SLJIT_MEM1(STACK_TOP), -(3 * sizeof(sljit_sw))); - OP2(SLJIT_SUB, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, 3 * sizeof(sljit_sw)); + OP1(SLJIT_MOV, SLJIT_MEM1(TMP2), 0, SLJIT_MEM1(STACK_TOP), -(2 * SSIZE_OF(sw))); + OP1(SLJIT_MOV, SLJIT_MEM1(TMP2), sizeof(sljit_sw), SLJIT_MEM1(STACK_TOP), -(3 * SSIZE_OF(sw))); + OP2(SLJIT_SUB, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, 3 * SSIZE_OF(sw)); } else { - OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), -(2 * sizeof(sljit_sw))); - OP1(SLJIT_MOV, TMP3, 0, SLJIT_MEM1(STACK_TOP), -(3 * sizeof(sljit_sw))); - OP2(SLJIT_SUB, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, 3 * sizeof(sljit_sw)); + OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), -(2 * SSIZE_OF(sw))); + OP1(SLJIT_MOV, TMP3, 0, SLJIT_MEM1(STACK_TOP), -(3 * SSIZE_OF(sw))); + OP2(SLJIT_SUB, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, 3 * SSIZE_OF(sw)); OP1(SLJIT_MOV, SLJIT_MEM1(TMP2), 0, TMP1, 0); GET_LOCAL_BASE(TMP1, 0, 0); OP1(SLJIT_MOV, SLJIT_MEM1(TMP2), sizeof(sljit_sw), TMP3, 0); @@ -6603,13 +6603,13 @@ OP2(SLJIT_SUB, TMP2, 0, SLJIT_IMM, 0, TMP2, 0); OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, TMP1, 0); if (HAS_VIRTUAL_REGISTERS) { - OP1(SLJIT_MOV, SLJIT_MEM1(TMP2), 0, SLJIT_MEM1(STACK_TOP), -(2 * sizeof(sljit_sw))); - OP2(SLJIT_SUB, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, 2 * sizeof(sljit_sw)); + OP1(SLJIT_MOV, SLJIT_MEM1(TMP2), 0, SLJIT_MEM1(STACK_TOP), -(2 * SSIZE_OF(sw))); + OP2(SLJIT_SUB, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, 2 * SSIZE_OF(sw)); } else { - OP1(SLJIT_MOV, TMP3, 0, SLJIT_MEM1(STACK_TOP), -(2 * sizeof(sljit_sw))); - OP2(SLJIT_SUB, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, 2 * sizeof(sljit_sw)); + OP1(SLJIT_MOV, TMP3, 0, SLJIT_MEM1(STACK_TOP), -(2 * SSIZE_OF(sw))); + OP2(SLJIT_SUB, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, 2 * SSIZE_OF(sw)); OP1(SLJIT_MOV, SLJIT_MEM1(TMP2), 0, TMP3, 0); } JUMPTO(SLJIT_JUMP, mainloop); @@ -7159,11 +7159,11 @@ if (char1_reg == STR_END) OP1(SLJIT_MOV, RETURN_ADDR, 0, char2_reg, 0); } -if (sljit_emit_mem(compiler, MOV_UCHAR | SLJIT_MEM_SUPP | SLJIT_MEM_POST, char1_reg, SLJIT_MEM1(TMP1), IN_UCHARS(1)) == SLJIT_SUCCESS) +if (sljit_emit_mem_update(compiler, MOV_UCHAR | SLJIT_MEM_SUPP | SLJIT_MEM_POST, char1_reg, SLJIT_MEM1(TMP1), IN_UCHARS(1)) == SLJIT_SUCCESS) { label = LABEL(); - sljit_emit_mem(compiler, MOV_UCHAR | SLJIT_MEM_POST, char1_reg, SLJIT_MEM1(TMP1), IN_UCHARS(1)); - sljit_emit_mem(compiler, MOV_UCHAR | SLJIT_MEM_POST, char2_reg, SLJIT_MEM1(STR_PTR), IN_UCHARS(1)); + sljit_emit_mem_update(compiler, MOV_UCHAR | SLJIT_MEM_POST, char1_reg, SLJIT_MEM1(TMP1), IN_UCHARS(1)); + sljit_emit_mem_update(compiler, MOV_UCHAR | SLJIT_MEM_POST, char2_reg, SLJIT_MEM1(STR_PTR), IN_UCHARS(1)); jump = CMP(SLJIT_NOT_EQUAL, char1_reg, 0, char2_reg, 0); OP2(SLJIT_SUB | SLJIT_SET_Z, TMP2, 0, TMP2, 0, SLJIT_IMM, IN_UCHARS(1)); JUMPTO(SLJIT_NOT_ZERO, label); @@ -7171,14 +7171,14 @@ if (sljit_emit_mem(compiler, MOV_UCHAR | SLJIT_MEM_SUPP | SLJIT_MEM_POST, char1_ JUMPHERE(jump); OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), LOCALS0); } -else if (sljit_emit_mem(compiler, MOV_UCHAR | SLJIT_MEM_SUPP | SLJIT_MEM_PRE, char1_reg, SLJIT_MEM1(TMP1), IN_UCHARS(1)) == SLJIT_SUCCESS) +else if (sljit_emit_mem_update(compiler, MOV_UCHAR | SLJIT_MEM_SUPP | SLJIT_MEM_PRE, char1_reg, SLJIT_MEM1(TMP1), IN_UCHARS(1)) == SLJIT_SUCCESS) { OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, IN_UCHARS(1)); OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); label = LABEL(); - sljit_emit_mem(compiler, MOV_UCHAR | SLJIT_MEM_PRE, char1_reg, SLJIT_MEM1(TMP1), IN_UCHARS(1)); - sljit_emit_mem(compiler, MOV_UCHAR | SLJIT_MEM_PRE, char2_reg, SLJIT_MEM1(STR_PTR), IN_UCHARS(1)); + sljit_emit_mem_update(compiler, MOV_UCHAR | SLJIT_MEM_PRE, char1_reg, SLJIT_MEM1(TMP1), IN_UCHARS(1)); + sljit_emit_mem_update(compiler, MOV_UCHAR | SLJIT_MEM_PRE, char2_reg, SLJIT_MEM1(STR_PTR), IN_UCHARS(1)); jump = CMP(SLJIT_NOT_EQUAL, char1_reg, 0, char2_reg, 0); OP2(SLJIT_SUB | SLJIT_SET_Z, TMP2, 0, TMP2, 0, SLJIT_IMM, IN_UCHARS(1)); JUMPTO(SLJIT_NOT_ZERO, label); @@ -7232,9 +7232,9 @@ else lcc_table = TMP3; } -if (sljit_emit_mem(compiler, MOV_UCHAR | SLJIT_MEM_SUPP | SLJIT_MEM_POST, char1_reg, SLJIT_MEM1(TMP1), IN_UCHARS(1)) == SLJIT_SUCCESS) +if (sljit_emit_mem_update(compiler, MOV_UCHAR | SLJIT_MEM_SUPP | SLJIT_MEM_POST, char1_reg, SLJIT_MEM1(TMP1), IN_UCHARS(1)) == SLJIT_SUCCESS) opt_type = 1; -else if (sljit_emit_mem(compiler, MOV_UCHAR | SLJIT_MEM_SUPP | SLJIT_MEM_PRE, char1_reg, SLJIT_MEM1(TMP1), IN_UCHARS(1)) == SLJIT_SUCCESS) +else if (sljit_emit_mem_update(compiler, MOV_UCHAR | SLJIT_MEM_SUPP | SLJIT_MEM_PRE, char1_reg, SLJIT_MEM1(TMP1), IN_UCHARS(1)) == SLJIT_SUCCESS) opt_type = 2; sljit_emit_fast_enter(compiler, SLJIT_MEM1(SLJIT_SP), LOCALS0); @@ -7253,8 +7253,8 @@ OP1(SLJIT_MOV, lcc_table, 0, SLJIT_IMM, common->lcc); if (opt_type == 1) { label = LABEL(); - sljit_emit_mem(compiler, MOV_UCHAR | SLJIT_MEM_POST, char1_reg, SLJIT_MEM1(TMP1), IN_UCHARS(1)); - sljit_emit_mem(compiler, MOV_UCHAR | SLJIT_MEM_POST, char2_reg, SLJIT_MEM1(STR_PTR), IN_UCHARS(1)); + sljit_emit_mem_update(compiler, MOV_UCHAR | SLJIT_MEM_POST, char1_reg, SLJIT_MEM1(TMP1), IN_UCHARS(1)); + sljit_emit_mem_update(compiler, MOV_UCHAR | SLJIT_MEM_POST, char2_reg, SLJIT_MEM1(STR_PTR), IN_UCHARS(1)); } else if (opt_type == 2) { @@ -7262,8 +7262,8 @@ else if (opt_type == 2) OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); label = LABEL(); - sljit_emit_mem(compiler, MOV_UCHAR | SLJIT_MEM_PRE, char1_reg, SLJIT_MEM1(TMP1), IN_UCHARS(1)); - sljit_emit_mem(compiler, MOV_UCHAR | SLJIT_MEM_PRE, char2_reg, SLJIT_MEM1(STR_PTR), IN_UCHARS(1)); + sljit_emit_mem_update(compiler, MOV_UCHAR | SLJIT_MEM_PRE, char1_reg, SLJIT_MEM1(TMP1), IN_UCHARS(1)); + sljit_emit_mem_update(compiler, MOV_UCHAR | SLJIT_MEM_PRE, char2_reg, SLJIT_MEM1(STR_PTR), IN_UCHARS(1)); } else { @@ -9689,7 +9689,7 @@ BACKTRACK_AS(recurse_backtrack)->matchingpath = LABEL(); return cc + 1 + LINK_SIZE; } -static sljit_s32 SLJIT_FUNC do_callout(struct jit_arguments *arguments, pcre2_callout_block *callout_block, PCRE2_SPTR *jit_ovector) +static sljit_s32 SLJIT_FUNC do_callout_jit(struct jit_arguments *arguments, pcre2_callout_block *callout_block, PCRE2_SPTR *jit_ovector) { PCRE2_SPTR begin; PCRE2_SIZE *ovector; @@ -9756,7 +9756,7 @@ unsigned int callout_length = (*cc == OP_CALLOUT) sljit_sw value1; sljit_sw value2; sljit_sw value3; -sljit_uw callout_arg_size = (common->re->top_bracket + 1) * 2 * sizeof(sljit_sw); +sljit_uw callout_arg_size = (common->re->top_bracket + 1) * 2 * SSIZE_OF(sw); PUSH_BACKTRACK(sizeof(backtrack_common), cc, NULL); @@ -9806,7 +9806,7 @@ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCALS0, STR_PTR, 0); /* SLJIT_R0 = arguments */ OP1(SLJIT_MOV, SLJIT_R1, 0, STACK_TOP, 0); GET_LOCAL_BASE(SLJIT_R2, 0, OVECTOR_START); -sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_ARGS3(32, W, W, W), SLJIT_IMM, SLJIT_FUNC_ADDR(do_callout)); +sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_ARGS3(32, W, W, W), SLJIT_IMM, SLJIT_FUNC_ADDR(do_callout_jit)); OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), LOCALS0); free_stack(common, callout_arg_size); @@ -11451,7 +11451,7 @@ struct sljit_label *label; int private_data_ptr = PRIVATE_DATA(cc); int base = (private_data_ptr == 0) ? SLJIT_MEM1(STACK_TOP) : SLJIT_MEM1(SLJIT_SP); int offset0 = (private_data_ptr == 0) ? STACK(0) : private_data_ptr; -int offset1 = (private_data_ptr == 0) ? STACK(1) : private_data_ptr + (int)sizeof(sljit_sw); +int offset1 = (private_data_ptr == 0) ? STACK(1) : private_data_ptr + SSIZE_OF(sw); int tmp_base, tmp_offset; #if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32 BOOL use_tmp; @@ -11517,19 +11517,19 @@ if (exact > 1) } } else if (exact == 1) - { compile_char1_matchingpath(common, type, cc, &backtrack->topbacktracks, TRUE); - if (early_fail_type == type_fail_range) - { - OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), early_fail_ptr); - OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), early_fail_ptr + (int)sizeof(sljit_sw)); - OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, TMP2, 0); - OP2(SLJIT_SUB, TMP2, 0, STR_PTR, 0, TMP2, 0); - add_jump(compiler, &backtrack->topbacktracks, CMP(SLJIT_LESS_EQUAL, TMP2, 0, TMP1, 0)); +if (early_fail_type == type_fail_range) + { + /* Range end first, followed by range start. */ + OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), early_fail_ptr); + OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), early_fail_ptr + SSIZE_OF(sw)); + OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, TMP2, 0); + OP2(SLJIT_SUB, TMP2, 0, STR_PTR, 0, TMP2, 0); + add_jump(compiler, &backtrack->topbacktracks, CMP(SLJIT_LESS_EQUAL, TMP2, 0, TMP1, 0)); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), early_fail_ptr + (int)sizeof(sljit_sw), STR_PTR, 0); - } + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), early_fail_ptr, STR_PTR, 0); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), early_fail_ptr + SSIZE_OF(sw), STR_PTR, 0); } switch(opcode) @@ -12428,7 +12428,7 @@ PCRE2_SPTR end; int private_data_ptr = PRIVATE_DATA(cc); int base = (private_data_ptr == 0) ? SLJIT_MEM1(STACK_TOP) : SLJIT_MEM1(SLJIT_SP); int offset0 = (private_data_ptr == 0) ? STACK(0) : private_data_ptr; -int offset1 = (private_data_ptr == 0) ? STACK(1) : private_data_ptr + (int)sizeof(sljit_sw); +int offset1 = (private_data_ptr == 0) ? STACK(1) : private_data_ptr + SSIZE_OF(sw); cc = get_iterator_parameters(common, cc, &opcode, &type, &max, &exact, &end); @@ -14148,7 +14148,7 @@ quit_label = common->quit_label; if (common->currententry != NULL) { /* A free bit for each private data. */ - common->recurse_bitset_size = ((private_data_size / (int)sizeof(sljit_sw)) + 7) >> 3; + common->recurse_bitset_size = ((private_data_size / SSIZE_OF(sw)) + 7) >> 3; SLJIT_ASSERT(common->recurse_bitset_size > 0); common->recurse_bitset = (sljit_u8*)SLJIT_MALLOC(common->recurse_bitset_size, allocator_data);; @@ -14384,7 +14384,7 @@ pcre2_jit_compile(pcre2_code *code, uint32_t options) pcre2_real_code *re = (pcre2_real_code *)code; #ifdef SUPPORT_JIT executable_functions *functions; -static int executable_allocator_is_working = 0; +static int executable_allocator_is_working = -1; #endif if (code == NULL) @@ -14447,23 +14447,21 @@ return PCRE2_ERROR_JIT_BADOPTION; if ((re->flags & PCRE2_NOJIT) != 0) return 0; -if (executable_allocator_is_working == 0) +if (executable_allocator_is_working == -1) { /* Checks whether the executable allocator is working. This check might run multiple times in multi-threaded environments, but the result should not be affected by it. */ void *ptr = SLJIT_MALLOC_EXEC(32, NULL); - - executable_allocator_is_working = -1; - if (ptr != NULL) { SLJIT_FREE_EXEC(((sljit_u8*)(ptr)) + SLJIT_EXEC_OFFSET(ptr), NULL); executable_allocator_is_working = 1; } + else executable_allocator_is_working = 0; } -if (executable_allocator_is_working < 0) +if (!executable_allocator_is_working) return PCRE2_ERROR_NOMEMORY; if ((re->overall_options & PCRE2_MATCH_INVALID_UTF) != 0) diff --git a/src/3rdparty/pcre2/src/pcre2_jit_misc.c b/src/3rdparty/pcre2/src/pcre2_jit_misc.c index e57afad065b..bb6a5589cb7 100644 --- a/src/3rdparty/pcre2/src/pcre2_jit_misc.c +++ b/src/3rdparty/pcre2/src/pcre2_jit_misc.c @@ -110,8 +110,10 @@ pcre2_jit_free_unused_memory(pcre2_general_context *gcontext) (void)gcontext; /* Suppress warning */ #else /* SUPPORT_JIT */ SLJIT_UNUSED_ARG(gcontext); +#if (defined SLJIT_EXECUTABLE_ALLOCATOR && SLJIT_EXECUTABLE_ALLOCATOR) sljit_free_unused_memory_exec(); -#endif /* SUPPORT_JIT */ +#endif /* SLJIT_EXECUTABLE_ALLOCATOR */ +#endif /* SUPPORT_JIT */ } diff --git a/src/3rdparty/pcre2/src/pcre2_jit_neon_inc.h b/src/3rdparty/pcre2/src/pcre2_jit_neon_inc.h index 150da29eba7..165602edc0c 100644 --- a/src/3rdparty/pcre2/src/pcre2_jit_neon_inc.h +++ b/src/3rdparty/pcre2/src/pcre2_jit_neon_inc.h @@ -183,6 +183,8 @@ restart:; #endif #if defined(FFCPS) +if (str_ptr >= str_end) + return NULL; sljit_u8 *p1 = str_ptr - diff; #endif sljit_s32 align_offset = ((uint64_t)str_ptr & 0xf); @@ -327,7 +329,7 @@ match:; return NULL; #if defined(FF_UTF) - if (utf_continue(str_ptr + IN_UCHARS(-offs1))) + if (utf_continue((PCRE2_SPTR)str_ptr - offs1)) { /* Not a match. */ str_ptr += IN_UCHARS(1); diff --git a/src/3rdparty/pcre2/src/pcre2_jit_simd_inc.h b/src/3rdparty/pcre2/src/pcre2_jit_simd_inc.h index d99cfc5ce46..1a5ce4ed09f 100644 --- a/src/3rdparty/pcre2/src/pcre2_jit_simd_inc.h +++ b/src/3rdparty/pcre2/src/pcre2_jit_simd_inc.h @@ -776,7 +776,7 @@ typedef union { } int_char; #if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32 -static SLJIT_INLINE int utf_continue(sljit_u8 *s) +static SLJIT_INLINE int utf_continue(PCRE2_SPTR s) { #if PCRE2_CODE_UNIT_WIDTH == 8 return (*s & 0xc0) == 0x80; diff --git a/src/3rdparty/pcre2/src/pcre2_match.c b/src/3rdparty/pcre2/src/pcre2_match.c index 6354e1bb9e2..168b9fad019 100644 --- a/src/3rdparty/pcre2/src/pcre2_match.c +++ b/src/3rdparty/pcre2/src/pcre2_match.c @@ -204,6 +204,7 @@ Arguments: P a previous frame of interest frame_size the frame size mb points to the match block + match_data points to the match data block s identification text Returns: nothing @@ -211,7 +212,7 @@ Returns: nothing static void display_frames(FILE *f, heapframe *F, heapframe *P, PCRE2_SIZE frame_size, - match_block *mb, const char *s, ...) + match_block *mb, pcre2_match_data *match_data, const char *s, ...) { uint32_t i; heapframe *Q; @@ -223,10 +224,10 @@ vfprintf(f, s, ap); va_end(ap); if (P != NULL) fprintf(f, " P=%lu", - ((char *)P - (char *)(mb->match_frames))/frame_size); + ((char *)P - (char *)(match_data->heapframes))/frame_size); fprintf(f, "\n"); -for (i = 0, Q = mb->match_frames; +for (i = 0, Q = match_data->heapframes; Q <= F; i++, Q = (heapframe *)((char *)Q + frame_size)) { @@ -490,10 +491,16 @@ A version did exist that used individual frames on the heap instead of calling match() recursively, but this ran substantially slower. The current version is a refactoring that uses a vector of frames to remember backtracking points. This runs no slower, and possibly even a bit faster than the original recursive -implementation. An initial vector of size START_FRAMES_SIZE (enough for maybe -50 frames) is allocated on the system stack. If this is not big enough, the -heap is used for a larger vector. +implementation. +At first, an initial vector of size START_FRAMES_SIZE (enough for maybe 50 +frames) was allocated on the system stack. If this was not big enough, the heap +was used for a larger vector. However, it turns out that there are environments +where taking as little as 20KiB from the system stack is an embarrassment. +After another refactoring, the heap is used exclusively, but a pointer the +frames vector and its size are cached in the match_data block, so that there is +no new memory allocation if the same match_data block is used for multiple +matches (unless the frames vector has to be extended). ******************************************************************************* ******************************************************************************/ @@ -566,10 +573,9 @@ made performance worse. Arguments: start_eptr starting character in subject start_ecode starting position in compiled code - ovector pointer to the final output vector - oveccount number of pairs in ovector top_bracket number of capturing parentheses in the pattern frame_size size of each backtracking frame + match_data pointer to the match_data block mb pointer to "static" variables block Returns: MATCH_MATCH if matched ) these values are >= 0 @@ -580,17 +586,19 @@ Returns: MATCH_MATCH if matched ) these values are >= 0 */ static int -match(PCRE2_SPTR start_eptr, PCRE2_SPTR start_ecode, PCRE2_SIZE *ovector, - uint16_t oveccount, uint16_t top_bracket, PCRE2_SIZE frame_size, - match_block *mb) +match(PCRE2_SPTR start_eptr, PCRE2_SPTR start_ecode, uint16_t top_bracket, + PCRE2_SIZE frame_size, pcre2_match_data *match_data, match_block *mb) { /* Frame-handling variables */ heapframe *F; /* Current frame pointer */ heapframe *N = NULL; /* Temporary frame pointers */ heapframe *P = NULL; + +heapframe *frames_top; /* End of frames vector */ heapframe *assert_accept_frame = NULL; /* For passing back a frame with captures */ -PCRE2_SIZE frame_copy_size; /* Amount to copy when creating a new frame */ +PCRE2_SIZE heapframes_size; /* Usable size of frames vector */ +PCRE2_SIZE frame_copy_size; /* Amount to copy when creating a new frame */ /* Local variables that do not need to be preserved over calls to RRMATCH(). */ @@ -627,10 +635,14 @@ copied when a new frame is created. */ frame_copy_size = frame_size - offsetof(heapframe, eptr); -/* Set up the first current frame at the start of the vector, and initialize -fields that are not reset for new frames. */ +/* Set up the first frame and the end of the frames vector. We set the local +heapframes_size to the usuable amount of the vector, that is, a whole number of +frames. */ + +F = match_data->heapframes; +heapframes_size = (match_data->heapframes_size / frame_size) * frame_size; +frames_top = (heapframe *)((char *)F + heapframes_size); -F = mb->match_frames; Frdepth = 0; /* "Recursion" depth */ Fcapture_last = 0; /* Number of most recent capture */ Fcurrent_recurse = RECURSE_UNSET; /* Not pattern recursing. */ @@ -646,34 +658,35 @@ backtracking point. */ MATCH_RECURSE: -/* Set up a new backtracking frame. If the vector is full, get a new one -on the heap, doubling the size, but constrained by the heap limit. */ +/* Set up a new backtracking frame. If the vector is full, get a new one, +doubling the size, but constrained by the heap limit (which is in KiB). */ N = (heapframe *)((char *)F + frame_size); -if (N >= mb->match_frames_top) +if (N >= frames_top) { - PCRE2_SIZE newsize = mb->frame_vector_size * 2; heapframe *new; + PCRE2_SIZE newsize = match_data->heapframes_size * 2; - if ((newsize / 1024) > mb->heap_limit) + if (newsize > mb->heap_limit) { - PCRE2_SIZE maxsize = ((mb->heap_limit * 1024)/frame_size) * frame_size; - if (mb->frame_vector_size >= maxsize) return PCRE2_ERROR_HEAPLIMIT; + PCRE2_SIZE maxsize = (mb->heap_limit/frame_size) * frame_size; + if (match_data->heapframes_size >= maxsize) return PCRE2_ERROR_HEAPLIMIT; newsize = maxsize; } - new = mb->memctl.malloc(newsize, mb->memctl.memory_data); + new = match_data->memctl.malloc(newsize, match_data->memctl.memory_data); if (new == NULL) return PCRE2_ERROR_NOMEMORY; - memcpy(new, mb->match_frames, mb->frame_vector_size); + memcpy(new, match_data->heapframes, heapframes_size); - F = (heapframe *)((char *)new + ((char *)F - (char *)mb->match_frames)); + F = (heapframe *)((char *)new + ((char *)F - (char *)match_data->heapframes)); N = (heapframe *)((char *)F + frame_size); - if (mb->match_frames != mb->stack_frames) - mb->memctl.free(mb->match_frames, mb->memctl.memory_data); - mb->match_frames = new; - mb->match_frames_top = (heapframe *)((char *)mb->match_frames + newsize); - mb->frame_vector_size = newsize; + match_data->memctl.free(match_data->heapframes, match_data->memctl.memory_data); + match_data->heapframes = new; + match_data->heapframes_size = newsize; + + heapframes_size = (newsize / frame_size) * frame_size; + frames_top = (heapframe *)((char *)new + heapframes_size); } #ifdef DEBUG_SHOW_RMATCH @@ -731,7 +744,7 @@ recursion value. */ if (group_frame_type != 0) { - Flast_group_offset = (char *)F - (char *)mb->match_frames; + Flast_group_offset = (char *)F - (char *)match_data->heapframes; if (GF_IDMASK(group_frame_type) == GF_RECURSE) Fcurrent_recurse = GF_DATAMASK(group_frame_type); group_frame_type = 0; @@ -773,7 +786,7 @@ fprintf(stderr, "++ op=%d\n", *Fecode); for(;;) { if (offset == PCRE2_UNSET) return PCRE2_ERROR_INTERNAL; - N = (heapframe *)((char *)mb->match_frames + offset); + N = (heapframe *)((char *)match_data->heapframes + offset); P = (heapframe *)((char *)N - frame_size); if (N->group_frame_type == (GF_CAPTURE | number)) break; offset = P->last_group_offset; @@ -811,7 +824,7 @@ fprintf(stderr, "++ op=%d\n", *Fecode); for(;;) { if (offset == PCRE2_UNSET) return PCRE2_ERROR_INTERNAL; - N = (heapframe *)((char *)mb->match_frames + offset); + N = (heapframe *)((char *)match_data->heapframes + offset); P = (heapframe *)((char *)N - frame_size); if (GF_IDMASK(N->group_frame_type) == GF_RECURSE) break; offset = P->last_group_offset; @@ -864,14 +877,15 @@ fprintf(stderr, "++ op=%d\n", *Fecode); mb->mark = Fmark; /* and the last success mark */ if (Feptr > mb->last_used_ptr) mb->last_used_ptr = Feptr; - ovector[0] = Fstart_match - mb->start_subject; - ovector[1] = Feptr - mb->start_subject; + match_data->ovector[0] = Fstart_match - mb->start_subject; + match_data->ovector[1] = Feptr - mb->start_subject; /* Set i to the smaller of the sizes of the external and frame ovectors. */ - i = 2 * ((top_bracket + 1 > oveccount)? oveccount : top_bracket + 1); - memcpy(ovector + 2, Fovector, (i - 2) * sizeof(PCRE2_SIZE)); - while (--i >= Foffset_top + 2) ovector[i] = PCRE2_UNSET; + i = 2 * ((top_bracket + 1 > match_data->oveccount)? + match_data->oveccount : top_bracket + 1); + memcpy(match_data->ovector + 2, Fovector, (i - 2) * sizeof(PCRE2_SIZE)); + while (--i >= Foffset_top + 2) match_data->ovector[i] = PCRE2_UNSET; return MATCH_MATCH; /* Note: NOT RRETURN */ @@ -5328,7 +5342,7 @@ fprintf(stderr, "++ op=%d\n", *Fecode); offset = Flast_group_offset; while (offset != PCRE2_UNSET) { - N = (heapframe *)((char *)mb->match_frames + offset); + N = (heapframe *)((char *)match_data->heapframes + offset); P = (heapframe *)((char *)N - frame_size); if (N->group_frame_type == (GF_RECURSE | number)) { @@ -5729,7 +5743,7 @@ fprintf(stderr, "++ op=%d\n", *Fecode); if (*bracode != OP_BRA && *bracode != OP_COND) { - N = (heapframe *)((char *)mb->match_frames + Flast_group_offset); + N = (heapframe *)((char *)match_data->heapframes + Flast_group_offset); P = (heapframe *)((char *)N - frame_size); Flast_group_offset = P->last_group_offset; @@ -6346,6 +6360,7 @@ BOOL jit_checked_utf = FALSE; #endif /* SUPPORT_UNICODE */ PCRE2_SIZE frame_size; +PCRE2_SIZE heapframes_size; /* We need to have mb as a pointer to a match block, because the IS_NEWLINE macro is used below, and it expects NLBLOCK to be defined as a pointer. */ @@ -6354,15 +6369,6 @@ pcre2_callout_block cb; match_block actual_match_block; match_block *mb = &actual_match_block; -/* Allocate an initial vector of backtracking frames on the stack. If this -proves to be too small, it is replaced by a larger one on the heap. To get a -vector of the size required that is aligned for pointers, allocate it as a -vector of pointers. */ - -PCRE2_SPTR stack_frames_vector[START_FRAMES_SIZE/sizeof(PCRE2_SPTR)] - PCRE2_KEEP_UNINITIALIZED; -mb->stack_frames = (heapframe *)stack_frames_vector; - /* Recognize NULL, length 0 as an empty string. */ if (subject == NULL && length == 0) subject = (PCRE2_SPTR)""; @@ -6793,15 +6799,11 @@ switch(re->newline_convention) vector at the end, whose size depends on the number of capturing parentheses in the pattern. It is not used at all if there are no capturing parentheses. - frame_size is the total size of each frame - mb->frame_vector_size is the total usable size of the vector (rounded down - to a whole number of frames) + frame_size is the total size of each frame + match_data->heapframes is the pointer to the frames vector + match_data->heapframes_size is the total size of the vector -The last of these is changed within the match() function if the frame vector -has to be expanded. We therefore put it into the match block so that it is -correct when calling match() more than once for non-anchored patterns. - -We must also pad frame_size for alignment to ensure subsequent frames are as +We must pad the frame_size for alignment to ensure subsequent frames are as aligned as heapframe. Whilst ovector is word-aligned due to being a PCRE2_SIZE array, that does not guarantee it is suitably aligned for pointers, as some architectures have pointers that are larger than a size_t. */ @@ -6813,8 +6815,8 @@ frame_size = (offsetof(heapframe, ovector) + /* Limits set in the pattern override the match context only if they are smaller. */ -mb->heap_limit = (mcontext->heap_limit < re->limit_heap)? - mcontext->heap_limit : re->limit_heap; +mb->heap_limit = ((mcontext->heap_limit < re->limit_heap)? + mcontext->heap_limit : re->limit_heap) * 1024; mb->match_limit = (mcontext->match_limit < re->limit_match)? mcontext->match_limit : re->limit_match; @@ -6823,35 +6825,40 @@ mb->match_limit_depth = (mcontext->depth_limit < re->limit_depth)? mcontext->depth_limit : re->limit_depth; /* If a pattern has very many capturing parentheses, the frame size may be very -large. Ensure that there are at least 10 available frames by getting an initial -vector on the heap if necessary, except when the heap limit prevents this. Get -fewer if possible. (The heap limit is in kibibytes.) */ +large. Set the initial frame vector size to ensure that there are at least 10 +available frames, but enforce a minimum of START_FRAMES_SIZE. If this is +greater than the heap limit, get as large a vector as possible. Always round +the size to a multiple of the frame size. */ -if (frame_size <= START_FRAMES_SIZE/10) +heapframes_size = frame_size * 10; +if (heapframes_size < START_FRAMES_SIZE) heapframes_size = START_FRAMES_SIZE; +if (heapframes_size > mb->heap_limit) { - mb->match_frames = mb->stack_frames; /* Initial frame vector on the stack */ - mb->frame_vector_size = ((START_FRAMES_SIZE/frame_size) * frame_size); + if (frame_size > mb->heap_limit ) return PCRE2_ERROR_HEAPLIMIT; + heapframes_size = mb->heap_limit; } -else + +/* If an existing frame vector in the match_data block is large enough, we can +use it.Otherwise, free any pre-existing vector and get a new one. */ + +if (match_data->heapframes_size < heapframes_size) { - mb->frame_vector_size = frame_size * 10; - if ((mb->frame_vector_size / 1024) > mb->heap_limit) + match_data->memctl.free(match_data->heapframes, + match_data->memctl.memory_data); + match_data->heapframes = match_data->memctl.malloc(heapframes_size, + match_data->memctl.memory_data); + if (match_data->heapframes == NULL) { - if (frame_size > mb->heap_limit * 1024) return PCRE2_ERROR_HEAPLIMIT; - mb->frame_vector_size = ((mb->heap_limit * 1024)/frame_size) * frame_size; + match_data->heapframes_size = 0; + return PCRE2_ERROR_NOMEMORY; } - mb->match_frames = mb->memctl.malloc(mb->frame_vector_size, - mb->memctl.memory_data); - if (mb->match_frames == NULL) return PCRE2_ERROR_NOMEMORY; + match_data->heapframes_size = heapframes_size; } -mb->match_frames_top = - (heapframe *)((char *)mb->match_frames + mb->frame_vector_size); - /* Write to the ovector within the first frame to mark every capture unset and to avoid uninitialized memory read errors when it is copied to a new frame. */ -memset((char *)(mb->match_frames) + offsetof(heapframe, ovector), 0xff, +memset((char *)(match_data->heapframes) + offsetof(heapframe, ovector), 0xff, frame_size - offsetof(heapframe, ovector)); /* Pointers to the individual character tables */ @@ -7279,8 +7286,8 @@ for(;;) mb->end_offset_top = 0; mb->skip_arg_count = 0; - rc = match(start_match, mb->start_code, match_data->ovector, - match_data->oveccount, re->top_bracket, frame_size, mb); + rc = match(start_match, mb->start_code, re->top_bracket, frame_size, + match_data, mb); if (mb->hitend && start_partial == NULL) { @@ -7463,11 +7470,6 @@ if (utf && end_subject != true_end_subject && } #endif /* SUPPORT_UNICODE */ -/* Release an enlarged frame vector that is on the heap. */ - -if (mb->match_frames != mb->stack_frames) - mb->memctl.free(mb->match_frames, mb->memctl.memory_data); - /* Fill in fields that are always returned in the match data. */ match_data->code = re; @@ -7533,4 +7535,10 @@ else match_data->rc = PCRE2_ERROR_NOMATCH; return match_data->rc; } +/* These #undefs are here to enable unity builds with CMake. */ + +#undef NLBLOCK /* Block containing newline information */ +#undef PSSTART /* Field containing processed string start */ +#undef PSEND /* Field containing processed string end */ + /* End of pcre2_match.c */ diff --git a/src/3rdparty/pcre2/src/pcre2_match_data.c b/src/3rdparty/pcre2/src/pcre2_match_data.c index 53e46987079..fa129b8bc5e 100644 --- a/src/3rdparty/pcre2/src/pcre2_match_data.c +++ b/src/3rdparty/pcre2/src/pcre2_match_data.c @@ -7,7 +7,7 @@ and semantics are as close as possible to those of the Perl 5 language. Written by Philip Hazel Original API code Copyright (c) 1997-2012 University of Cambridge - New API code Copyright (c) 2016-2019 University of Cambridge + New API code Copyright (c) 2016-2022 University of Cambridge ----------------------------------------------------------------------------- Redistribution and use in source and binary forms, with or without @@ -51,19 +51,23 @@ POSSIBILITY OF SUCH DAMAGE. * Create a match data block given ovector size * *************************************************/ -/* A minimum of 1 is imposed on the number of ovector pairs. */ +/* A minimum of 1 is imposed on the number of ovector pairs. A maximum is also +imposed because the oveccount field in a match data block is uintt6_t. */ PCRE2_EXP_DEFN pcre2_match_data * PCRE2_CALL_CONVENTION pcre2_match_data_create(uint32_t oveccount, pcre2_general_context *gcontext) { pcre2_match_data *yield; if (oveccount < 1) oveccount = 1; +if (oveccount > UINT16_MAX) oveccount = UINT16_MAX; yield = PRIV(memctl_malloc)( offsetof(pcre2_match_data, ovector) + 2*oveccount*sizeof(PCRE2_SIZE), (pcre2_memctl *)gcontext); if (yield == NULL) return NULL; yield->oveccount = oveccount; yield->flags = 0; +yield->heapframes = NULL; +yield->heapframes_size = 0; return yield; } @@ -95,6 +99,9 @@ pcre2_match_data_free(pcre2_match_data *match_data) { if (match_data != NULL) { + if (match_data->heapframes != NULL) + match_data->memctl.free(match_data->heapframes, + match_data->memctl.memory_data); if ((match_data->flags & PCRE2_MD_COPIED_SUBJECT) != 0) match_data->memctl.free((void *)match_data->subject, match_data->memctl.memory_data); diff --git a/src/3rdparty/pcre2/src/pcre2_substitute.c b/src/3rdparty/pcre2/src/pcre2_substitute.c index 8b2c369cccd..edbb78c6d78 100644 --- a/src/3rdparty/pcre2/src/pcre2_substitute.c +++ b/src/3rdparty/pcre2/src/pcre2_substitute.c @@ -7,7 +7,7 @@ and semantics are as close as possible to those of the Perl 5 language. Written by Philip Hazel Original API code Copyright (c) 1997-2012 University of Cambridge - New API code Copyright (c) 2016-2021 University of Cambridge + New API code Copyright (c) 2016-2022 University of Cambridge ----------------------------------------------------------------------------- Redistribution and use in source and binary forms, with or without @@ -259,16 +259,16 @@ PCRE2_UNSET, so as not to imply an offset in the replacement. */ if ((options & (PCRE2_PARTIAL_HARD|PCRE2_PARTIAL_SOFT)) != 0) return PCRE2_ERROR_BADOPTION; - -/* Validate length and find the end of the replacement. A NULL replacement of + +/* Validate length and find the end of the replacement. A NULL replacement of zero length is interpreted as an empty string. */ -if (replacement == NULL) +if (replacement == NULL) { if (rlength != 0) return PCRE2_ERROR_NULL; - replacement = (PCRE2_SPTR)""; - } - + replacement = (PCRE2_SPTR)""; + } + if (rlength == PCRE2_ZERO_TERMINATED) rlength = PRIV(strlen)(replacement); repend = replacement + rlength; @@ -282,8 +282,9 @@ replacement_only = ((options & PCRE2_SUBSTITUTE_REPLACEMENT_ONLY) != 0); match data block. We create an internal match_data block in two cases: (a) an external one is not supplied (and we are not starting from an existing match); (b) an existing match is to be used for the first substitution. In the latter -case, we copy the existing match into the internal block. This ensures that no -changes are made to the existing match data block. */ +case, we copy the existing match into the internal block, except for any cached +heap frame size and pointer. This ensures that no changes are made to the +external match data block. */ if (match_data == NULL) { @@ -309,6 +310,8 @@ else if (use_existing_match) if (internal_match_data == NULL) return PCRE2_ERROR_NOMEMORY; memcpy(internal_match_data, match_data, offsetof(pcre2_match_data, ovector) + 2*pairs*sizeof(PCRE2_SIZE)); + internal_match_data->heapframes = NULL; + internal_match_data->heapframes_size = 0; match_data = internal_match_data; } @@ -328,9 +331,9 @@ scb.ovector = ovector; if (subject == NULL) { - if (length != 0) return PCRE2_ERROR_NULL; + if (length != 0) return PCRE2_ERROR_NULL; subject = (PCRE2_SPTR)""; - } + } /* Find length of zero-terminated subject */ diff --git a/src/3rdparty/pcre2/src/sljit/sljitConfig.h b/src/3rdparty/pcre2/src/sljit/sljitConfig.h index 1c821d287d8..5fba7aa6380 100644 --- a/src/3rdparty/pcre2/src/sljit/sljitConfig.h +++ b/src/3rdparty/pcre2/src/sljit/sljitConfig.h @@ -53,7 +53,8 @@ extern "C" { /* #define SLJIT_CONFIG_PPC_64 1 */ /* #define SLJIT_CONFIG_MIPS_32 1 */ /* #define SLJIT_CONFIG_MIPS_64 1 */ -/* #define SLJIT_CONFIG_SPARC_32 1 */ +/* #define SLJIT_CONFIG_RISCV_32 1 */ +/* #define SLJIT_CONFIG_RISCV_64 1 */ /* #define SLJIT_CONFIG_S390X 1 */ /* #define SLJIT_CONFIG_AUTO 1 */ @@ -127,17 +128,6 @@ extern "C" { #endif /* !SLJIT_EXECUTABLE_ALLOCATOR */ -/* Force cdecl calling convention even if a better calling - convention (e.g. fastcall) is supported by the C compiler. - If this option is disabled (this is the default), functions - called from JIT should be defined with SLJIT_FUNC attribute. - Standard C functions can still be called by using the - SLJIT_CALL_CDECL jump type. */ -#ifndef SLJIT_USE_CDECL_CALLING_CONVENTION -/* Disabled by default */ -#define SLJIT_USE_CDECL_CALLING_CONVENTION 0 -#endif - /* Return with error when an invalid argument is passed. */ #ifndef SLJIT_ARGUMENT_CHECKS /* Disabled by default */ diff --git a/src/3rdparty/pcre2/src/sljit/sljitConfigInternal.h b/src/3rdparty/pcre2/src/sljit/sljitConfigInternal.h index 55e4e39f137..cd3ce697346 100644 --- a/src/3rdparty/pcre2/src/sljit/sljitConfigInternal.h +++ b/src/3rdparty/pcre2/src/sljit/sljitConfigInternal.h @@ -59,7 +59,8 @@ extern "C" { SLJIT_64BIT_ARCHITECTURE : 64 bit architecture SLJIT_LITTLE_ENDIAN : little endian architecture SLJIT_BIG_ENDIAN : big endian architecture - SLJIT_UNALIGNED : allows unaligned memory accesses for non-fpu operations (only!) + SLJIT_UNALIGNED : unaligned memory accesses for non-fpu operations are supported + SLJIT_FPU_UNALIGNED : unaligned memory accesses for fpu operations are supported SLJIT_INDIRECT_CALL : see SLJIT_FUNC_ADDR() for more information Constants: @@ -98,7 +99,8 @@ extern "C" { + (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) \ + (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) \ + (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64) \ - + (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32) \ + + (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32) \ + + (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64) \ + (defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X) \ + (defined SLJIT_CONFIG_AUTO && SLJIT_CONFIG_AUTO) \ + (defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED) >= 2 @@ -115,7 +117,8 @@ extern "C" { && !(defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) \ && !(defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) \ && !(defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64) \ - && !(defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32) \ + && !(defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32) \ + && !(defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64) \ && !(defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X) \ && !(defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED) \ && !(defined SLJIT_CONFIG_AUTO && SLJIT_CONFIG_AUTO) @@ -156,8 +159,10 @@ extern "C" { #define SLJIT_CONFIG_MIPS_32 1 #elif defined(__mips64) #define SLJIT_CONFIG_MIPS_64 1 -#elif (defined(__sparc__) || defined(__sparc)) && !defined(_LP64) -#define SLJIT_CONFIG_SPARC_32 1 +#elif defined (__riscv_xlen) && (__riscv_xlen == 32) +#define SLJIT_CONFIG_RISCV_32 1 +#elif defined (__riscv_xlen) && (__riscv_xlen == 64) +#define SLJIT_CONFIG_RISCV_64 1 #elif defined(__s390x__) #define SLJIT_CONFIG_S390X 1 #else @@ -205,8 +210,8 @@ extern "C" { #define SLJIT_CONFIG_PPC 1 #elif (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) || (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64) #define SLJIT_CONFIG_MIPS 1 -#elif (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32) || (defined SLJIT_CONFIG_SPARC_64 && SLJIT_CONFIG_SPARC_64) -#define SLJIT_CONFIG_SPARC 1 +#elif (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32) || (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64) +#define SLJIT_CONFIG_RISCV 1 #endif /***********************************************************/ @@ -330,8 +335,14 @@ extern "C" { * older versions are known to abort in some targets * https://github.com/PhilipHazel/pcre2/issues/92 * - * beware APPLE is known to have removed the code in iOS so - * it will need to be excempted or result in broken builds + * beware some vendors (ex: Microsoft, Apple) are known to have + * removed the code to support this builtin even if the call for + * __has_builtin reports it is available. + * + * make sure linking doesn't fail because __clear_cache() is + * missing before changing it or add an exception so that the + * system provided method that should be defined below is used + * instead. */ #if (!defined SLJIT_CACHE_FLUSH && defined __has_builtin) #if __has_builtin(__builtin___clear_cache) && !defined(__clang__) @@ -339,9 +350,9 @@ extern "C" { /* * https://gcc.gnu.org/bugzilla//show_bug.cgi?id=91248 * https://gcc.gnu.org/bugzilla//show_bug.cgi?id=93811 - * gcc's clear_cache builtin for power and sparc are broken + * gcc's clear_cache builtin for power is broken */ -#if !defined(SLJIT_CONFIG_PPC) && !defined(SLJIT_CONFIG_SPARC_32) +#if !defined(SLJIT_CONFIG_PPC) #define SLJIT_CACHE_FLUSH(from, to) \ __builtin___clear_cache((char*)(from), (char*)(to)) #endif @@ -373,12 +384,10 @@ extern "C" { ppc_cache_flush((from), (to)) #define SLJIT_CACHE_FLUSH_OWN_IMPL 1 -#elif (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32) +#elif defined(_WIN32) -/* The __clear_cache() implementation of GCC is a dummy function on Sparc. */ #define SLJIT_CACHE_FLUSH(from, to) \ - sparc_cache_flush((from), (to)) -#define SLJIT_CACHE_FLUSH_OWN_IMPL 1 + FlushInstructionCache(GetCurrentProcess(), (void*)(from), (char*)(to) - (char*)(from)) #elif (defined(__GNUC__) && (__GNUC__ >= 5 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3))) || defined(__clang__) @@ -392,11 +401,6 @@ extern "C" { #define SLJIT_CACHE_FLUSH(from, to) \ cacheflush((long)(from), (long)(to), 0) -#elif defined _WIN32 - -#define SLJIT_CACHE_FLUSH(from, to) \ - FlushInstructionCache(GetCurrentProcess(), (void*)(from), (char*)(to) - (char*)(from)) - #else /* Call __ARM_NR_cacheflush on ARM-Linux or the corresponding MIPS syscall. */ @@ -435,6 +439,7 @@ typedef long int sljit_sw; && !(defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64) \ && !(defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) \ && !(defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64) \ + && !(defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64) \ && !(defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X) #define SLJIT_32BIT_ARCHITECTURE 1 #define SLJIT_WORD_SHIFT 2 @@ -495,8 +500,7 @@ typedef double sljit_f64; #if !defined(SLJIT_BIG_ENDIAN) && !defined(SLJIT_LITTLE_ENDIAN) /* These macros are mostly useful for the applications. */ -#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) \ - || (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) +#if (defined SLJIT_CONFIG_PPC && SLJIT_CONFIG_PPC) #ifdef __LITTLE_ENDIAN__ #define SLJIT_LITTLE_ENDIAN 1 @@ -504,8 +508,7 @@ typedef double sljit_f64; #define SLJIT_BIG_ENDIAN 1 #endif -#elif (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) \ - || (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64) +#elif (defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS) #ifdef __MIPSEL__ #define SLJIT_LITTLE_ENDIAN 1 @@ -532,8 +535,7 @@ typedef double sljit_f64; #endif /* !SLJIT_MIPS_REV */ -#elif (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32) \ - || (defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X) +#elif (defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X) #define SLJIT_BIG_ENDIAN 1 @@ -554,19 +556,30 @@ typedef double sljit_f64; #ifndef SLJIT_UNALIGNED -#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) \ - || (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) \ +#if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86) \ || (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7) \ || (defined SLJIT_CONFIG_ARM_THUMB2 && SLJIT_CONFIG_ARM_THUMB2) \ || (defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64) \ - || (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) \ - || (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) \ + || (defined SLJIT_CONFIG_PPC && SLJIT_CONFIG_PPC) \ + || (defined SLJIT_CONFIG_RISCV && SLJIT_CONFIG_RISCV) \ || (defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X) #define SLJIT_UNALIGNED 1 #endif #endif /* !SLJIT_UNALIGNED */ +#ifndef SLJIT_FPU_UNALIGNED + +#if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86) \ + || (defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64) \ + || (defined SLJIT_CONFIG_PPC && SLJIT_CONFIG_PPC) \ + || (defined SLJIT_CONFIG_RISCV && SLJIT_CONFIG_RISCV) \ + || (defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X) +#define SLJIT_FPU_UNALIGNED 1 +#endif + +#endif /* !SLJIT_FPU_UNALIGNED */ + #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) /* Auto detect SSE2 support using CPUID. On 64 bit x86 cpus, sse2 must be present. */ @@ -578,38 +591,7 @@ typedef double sljit_f64; /*****************************************************************************************/ #ifndef SLJIT_FUNC - -#if (defined SLJIT_USE_CDECL_CALLING_CONVENTION && SLJIT_USE_CDECL_CALLING_CONVENTION) \ - || !(defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) - #define SLJIT_FUNC - -#elif defined(__GNUC__) && !defined(__APPLE__) - -#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) -#define SLJIT_FUNC __attribute__ ((fastcall)) -#define SLJIT_X86_32_FASTCALL 1 -#else -#define SLJIT_FUNC -#endif /* gcc >= 3.4 */ - -#elif defined(_MSC_VER) - -#define SLJIT_FUNC __fastcall -#define SLJIT_X86_32_FASTCALL 1 - -#elif defined(__BORLANDC__) - -#define SLJIT_FUNC __msfastcall -#define SLJIT_X86_32_FASTCALL 1 - -#else /* Unknown compiler. */ - -/* The cdecl calling convention is usually the x86 default. */ -#define SLJIT_FUNC - -#endif /* SLJIT_USE_CDECL_CALLING_CONVENTION */ - #endif /* !SLJIT_FUNC */ #ifndef SLJIT_INDIRECT_CALL @@ -621,14 +603,10 @@ typedef double sljit_f64; #endif #endif /* SLJIT_INDIRECT_CALL */ -/* The offset which needs to be substracted from the return address to +/* The offset which needs to be subtracted from the return address to determine the next executed instruction after return. */ #ifndef SLJIT_RETURN_ADDRESS_OFFSET -#if (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32) -#define SLJIT_RETURN_ADDRESS_OFFSET 8 -#else #define SLJIT_RETURN_ADDRESS_OFFSET 0 -#endif #endif /* SLJIT_RETURN_ADDRESS_OFFSET */ /***************************************************/ @@ -666,10 +644,10 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_sw sljit_exec_offset(void* ptr); #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) #define SLJIT_NUMBER_OF_REGISTERS 12 -#define SLJIT_NUMBER_OF_SAVED_REGISTERS 9 +#define SLJIT_NUMBER_OF_SAVED_REGISTERS 7 #define SLJIT_NUMBER_OF_FLOAT_REGISTERS 7 #define SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS 0 -#define SLJIT_LOCALS_OFFSET_BASE (compiler->locals_offset) +#define SLJIT_LOCALS_OFFSET_BASE (8 * SSIZE_OF(sw)) #define SLJIT_PREF_SHIFT_REG SLJIT_R2 #elif (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) @@ -683,7 +661,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_sw sljit_exec_offset(void* ptr); #else /* _WIN64 */ #define SLJIT_NUMBER_OF_SAVED_REGISTERS 8 #define SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS 10 -#define SLJIT_LOCALS_OFFSET_BASE (4 * (sljit_s32)sizeof(sljit_sw)) +#define SLJIT_LOCALS_OFFSET_BASE (4 * SSIZE_OF(sw)) #endif /* !_WIN64 */ #define SLJIT_PREF_SHIFT_REG SLJIT_R3 @@ -740,17 +718,13 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_sw sljit_exec_offset(void* ptr); #define SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS 8 #endif -#elif (defined SLJIT_CONFIG_SPARC && SLJIT_CONFIG_SPARC) +#elif (defined SLJIT_CONFIG_RISCV && SLJIT_CONFIG_RISCV) -#define SLJIT_NUMBER_OF_REGISTERS 18 -#define SLJIT_NUMBER_OF_SAVED_REGISTERS 14 -#define SLJIT_NUMBER_OF_FLOAT_REGISTERS 14 -#define SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS 0 -#if (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32) -/* saved registers (16), return struct pointer (1), space for 6 argument words (1), - 4th double arg (2), double alignment (1). */ -#define SLJIT_LOCALS_OFFSET_BASE ((16 + 1 + 6 + 2 + 1) * (sljit_s32)sizeof(sljit_sw)) -#endif +#define SLJIT_NUMBER_OF_REGISTERS 23 +#define SLJIT_NUMBER_OF_SAVED_REGISTERS 12 +#define SLJIT_LOCALS_OFFSET_BASE 0 +#define SLJIT_NUMBER_OF_FLOAT_REGISTERS 30 +#define SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS 12 #elif (defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X) @@ -806,7 +780,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_sw sljit_exec_offset(void* ptr); #if (defined SLJIT_CONFIG_ARM && SLJIT_CONFIG_ARM) \ || (defined SLJIT_CONFIG_PPC && SLJIT_CONFIG_PPC) \ || (defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS) \ - || (defined SLJIT_CONFIG_SPARC && SLJIT_CONFIG_SPARC) \ + || (defined SLJIT_CONFIG_RISCV && SLJIT_CONFIG_RISCV) \ || (defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X) #define SLJIT_HAS_STATUS_FLAGS_STATE 1 #endif diff --git a/src/3rdparty/pcre2/src/sljit/sljitLir.c b/src/3rdparty/pcre2/src/sljit/sljitLir.c index 313a061dd3f..abafe1add97 100644 --- a/src/3rdparty/pcre2/src/sljit/sljitLir.c +++ b/src/3rdparty/pcre2/src/sljit/sljitLir.c @@ -133,6 +133,14 @@ #define SLJIT_ARG_MASK 0x7 #define SLJIT_ARG_FULL_MASK (SLJIT_ARG_MASK | SLJIT_ARG_TYPE_SCRATCH_REG) +/* Mask for sljit_emit_mem. */ +#define REG_PAIR_MASK 0xff00 +#define REG_PAIR_FIRST(reg) ((reg) & 0xff) +#define REG_PAIR_SECOND(reg) ((reg) >> 8) + +/* Mask for sljit_emit_enter. */ +#define SLJIT_KEPT_SAVEDS_COUNT(options) ((options) & 0x3) + /* Jump flags. */ #define JUMP_LABEL 0x1 #define JUMP_ADDR 0x2 @@ -145,16 +153,16 @@ # define PATCH_MD 0x10 #endif # define TYPE_SHIFT 13 -#endif +#endif /* SLJIT_CONFIG_X86 */ #if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) || (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7) # define IS_BL 0x4 # define PATCH_B 0x8 -#endif +#endif /* SLJIT_CONFIG_ARM_V5 || SLJIT_CONFIG_ARM_V7 */ #if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) # define CPOOL_SIZE 512 -#endif +#endif /* SLJIT_CONFIG_ARM_V5 */ #if (defined SLJIT_CONFIG_ARM_THUMB2 && SLJIT_CONFIG_ARM_THUMB2) # define IS_COND 0x04 @@ -172,7 +180,7 @@ /* BL + imm24 */ # define PATCH_BL 0x60 /* 0xf00 cc code for branches */ -#endif +#endif /* SLJIT_CONFIG_ARM_THUMB2 */ #if (defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64) # define IS_COND 0x004 @@ -182,7 +190,7 @@ # define PATCH_COND 0x040 # define PATCH_ABS48 0x080 # define PATCH_ABS64 0x100 -#endif +#endif /* SLJIT_CONFIG_ARM_64 */ #if (defined SLJIT_CONFIG_PPC && SLJIT_CONFIG_PPC) # define IS_COND 0x004 @@ -192,9 +200,9 @@ #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) # define PATCH_ABS32 0x040 # define PATCH_ABS48 0x080 -#endif +#endif /* SLJIT_CONFIG_PPC_64 */ # define REMOVE_COND 0x100 -#endif +#endif /* SLJIT_CONFIG_PPC */ #if (defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS) # define IS_MOVABLE 0x004 @@ -212,7 +220,7 @@ #if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64) # define PATCH_ABS32 0x400 # define PATCH_ABS48 0x800 -#endif +#endif /* SLJIT_CONFIG_MIPS_64 */ /* instruction types */ # define MOVABLE_INS 0 @@ -221,28 +229,24 @@ # define UNMOVABLE_INS 32 /* FPU status register */ # define FCSR_FCC 33 -#endif +#endif /* SLJIT_CONFIG_MIPS */ -#if (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32) -# define IS_MOVABLE 0x04 -# define IS_COND 0x08 -# define IS_CALL 0x10 +#if (defined SLJIT_CONFIG_RISCV && SLJIT_CONFIG_RISCV) +# define IS_COND 0x004 +# define IS_CALL 0x008 -# define PATCH_B 0x20 -# define PATCH_CALL 0x40 +# define PATCH_B 0x010 +# define PATCH_J 0x020 - /* instruction types */ -# define MOVABLE_INS 0 - /* 1 - 31 last destination register */ - /* no destination (i.e: store) */ -# define UNMOVABLE_INS 32 - -# define DST_INS_MASK 0xff - - /* ICC_SET is the same as SET_FLAGS. */ -# define ICC_IS_SET (1 << 23) -# define FCC_IS_SET (1 << 24) -#endif +#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64) +# define PATCH_REL32 0x040 +# define PATCH_ABS32 0x080 +# define PATCH_ABS44 0x100 +# define PATCH_ABS52 0x200 +#else /* !SLJIT_CONFIG_RISCV_64 */ +# define PATCH_REL32 0x0 +#endif /* SLJIT_CONFIG_RISCV_64 */ +#endif /* SLJIT_CONFIG_RISCV */ /* Stack management. */ @@ -385,7 +389,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_compiler* sljit_create_compiler(void *allo invalid_integer_types); SLJIT_COMPILE_ASSERT(SLJIT_REWRITABLE_JUMP != SLJIT_32, rewritable_jump_and_single_op_must_not_be_the_same); - SLJIT_COMPILE_ASSERT(!(SLJIT_EQUAL & 0x1) && !(SLJIT_LESS & 0x1) && !(SLJIT_EQUAL_F64 & 0x1) && !(SLJIT_JUMP & 0x1), + SLJIT_COMPILE_ASSERT(!(SLJIT_EQUAL & 0x1) && !(SLJIT_LESS & 0x1) && !(SLJIT_F_EQUAL & 0x1) && !(SLJIT_JUMP & 0x1), conditional_flags_must_be_even_numbers); /* Only the non-zero members must be set. */ @@ -437,10 +441,6 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_compiler* sljit_create_compiler(void *allo compiler->delay_slot = UNMOVABLE_INS; #endif -#if (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32) - compiler->delay_slot = UNMOVABLE_INS; -#endif - #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) \ || (defined SLJIT_DEBUG && SLJIT_DEBUG) compiler->last_flags = 0; @@ -822,6 +822,9 @@ static sljit_s32 function_check_src_mem(struct sljit_compiler *compiler, sljit_s if (!(p & SLJIT_MEM)) return 0; + if (p == SLJIT_MEM1(SLJIT_SP)) + return (i >= 0 && i < compiler->logical_local_size); + if (!(!(p & REG_MASK) || FUNCTION_CHECK_IS_REG(p & REG_MASK))) return 0; @@ -859,9 +862,6 @@ static sljit_s32 function_check_src(struct sljit_compiler *compiler, sljit_s32 p if (p == SLJIT_IMM) return 1; - if (p == SLJIT_MEM1(SLJIT_SP)) - return (i >= 0 && i < compiler->logical_local_size); - return function_check_src_mem(compiler, p, i); } @@ -876,9 +876,6 @@ static sljit_s32 function_check_dst(struct sljit_compiler *compiler, sljit_s32 p if (FUNCTION_CHECK_IS_REG(p)) return (i == 0); - if (p == SLJIT_MEM1(SLJIT_SP)) - return (i >= 0 && i < compiler->logical_local_size); - return function_check_src_mem(compiler, p, i); } @@ -893,9 +890,6 @@ static sljit_s32 function_fcheck(struct sljit_compiler *compiler, sljit_s32 p, s if (FUNCTION_CHECK_IS_FREG(p)) return (i == 0); - if (p == SLJIT_MEM1(SLJIT_SP)) - return (i >= 0 && i < compiler->logical_local_size); - return function_check_src_mem(compiler, p, i); } @@ -913,7 +907,11 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_compiler_verbose(struct sljit_compiler *comp #if (defined SLJIT_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE) #ifdef _WIN64 +#ifdef __GNUC__ +# define SLJIT_PRINT_D "ll" +#else # define SLJIT_PRINT_D "I64" +#endif #else # define SLJIT_PRINT_D "l" #endif @@ -995,13 +993,14 @@ static const char* op0_names[] = { static const char* op1_names[] = { "", ".u8", ".s8", ".u16", ".s16", ".u32", ".s32", "32", - ".p", "not", "clz", + ".p", "not", "clz", "ctz" }; static const char* op2_names[] = { "add", "addc", "sub", "subc", "mul", "and", "or", "xor", - "shl", "lshr", "ashr", + "shl", "mshl", "lshr", "mlshr", + "ashr", "mashr", "rotl", "rotr" }; static const char* op_src_names[] = { @@ -1020,10 +1019,6 @@ static const char* fop2_names[] = { "add", "sub", "mul", "div" }; -#define JUMP_POSTFIX(type) \ - ((type & 0xff) <= SLJIT_NOT_OVERFLOW ? ((type & SLJIT_32) ? "32" : "") \ - : ((type & 0xff) <= SLJIT_ORDERED_F64 ? ((type & SLJIT_32) ? ".f32" : ".f64") : "")) - static const char* jump_names[] = { "equal", "not_equal", "less", "greater_equal", @@ -1032,12 +1027,18 @@ static const char* jump_names[] = { "sig_greater", "sig_less_equal", "overflow", "not_overflow", "carry", "", - "equal", "not_equal", - "less", "greater_equal", - "greater", "less_equal", + "f_equal", "f_not_equal", + "f_less", "f_greater_equal", + "f_greater", "f_less_equal", "unordered", "ordered", + "ordered_equal", "unordered_or_not_equal", + "ordered_less", "unordered_or_greater_equal", + "ordered_greater", "unordered_or_less_equal", + "unordered_or_equal", "ordered_not_equal", + "unordered_or_less", "ordered_greater_equal", + "unordered_or_greater", "ordered_less_equal", "jump", "fast_call", - "call", "call.cdecl" + "call", "call_reg_arg" }; static const char* call_arg_names[] = { @@ -1053,6 +1054,8 @@ static const char* call_arg_names[] = { #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) \ || (defined SLJIT_VERBOSE && SLJIT_VERBOSE) +#define SLJIT_SKIP_CHECKS(compiler) (compiler)->skip_checks = 1 + static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_generate_code(struct sljit_compiler *compiler) { #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) @@ -1080,7 +1083,12 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_enter(struct sljit_compil SLJIT_UNUSED_ARG(compiler); #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) - CHECK_ARGUMENT(!(options & ~SLJIT_ENTER_CDECL)); + if (options & SLJIT_ENTER_REG_ARG) { + CHECK_ARGUMENT(!(options & ~(0x3 | SLJIT_ENTER_REG_ARG))); + } else { + CHECK_ARGUMENT(options == 0); + } + CHECK_ARGUMENT(SLJIT_KEPT_SAVEDS_COUNT(options) <= 3 && SLJIT_KEPT_SAVEDS_COUNT(options) <= saveds); CHECK_ARGUMENT(scratches >= 0 && scratches <= SLJIT_NUMBER_OF_REGISTERS); CHECK_ARGUMENT(saveds >= 0 && saveds <= SLJIT_NUMBER_OF_SAVED_REGISTERS); CHECK_ARGUMENT(scratches + saveds <= SLJIT_NUMBER_OF_REGISTERS); @@ -1088,8 +1096,8 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_enter(struct sljit_compil CHECK_ARGUMENT(fsaveds >= 0 && fsaveds <= SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS); CHECK_ARGUMENT(fscratches + fsaveds <= SLJIT_NUMBER_OF_FLOAT_REGISTERS); CHECK_ARGUMENT(local_size >= 0 && local_size <= SLJIT_MAX_LOCAL_SIZE); - CHECK_ARGUMENT((arg_types & SLJIT_ARG_FULL_MASK) < SLJIT_ARG_TYPE_F64); - CHECK_ARGUMENT(function_check_arguments(arg_types, scratches, saveds, fscratches)); + CHECK_ARGUMENT((arg_types & SLJIT_ARG_FULL_MASK) <= SLJIT_ARG_TYPE_F32); + CHECK_ARGUMENT(function_check_arguments(arg_types, scratches, (options & SLJIT_ENTER_REG_ARG) ? 0 : saveds, fscratches)); compiler->last_flags = 0; #endif @@ -1109,8 +1117,16 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_enter(struct sljit_compil } while (arg_types); } - fprintf(compiler->verbose, "],%s scratches:%d, saveds:%d, fscratches:%d, fsaveds:%d, local_size:%d\n", - (options & SLJIT_ENTER_CDECL) ? " enter:cdecl," : "", + fprintf(compiler->verbose, "],"); + + if (options & SLJIT_ENTER_REG_ARG) { + fprintf(compiler->verbose, " enter:reg_arg,"); + + if (SLJIT_KEPT_SAVEDS_COUNT(options) > 0) + fprintf(compiler->verbose, " keep:%d,", SLJIT_KEPT_SAVEDS_COUNT(options)); + } + + fprintf(compiler->verbose, "scratches:%d, saveds:%d, fscratches:%d, fsaveds:%d, local_size:%d\n", scratches, saveds, fscratches, fsaveds, local_size); } #endif @@ -1124,7 +1140,12 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_set_context(struct sljit_compi SLJIT_UNUSED_ARG(compiler); #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) - CHECK_ARGUMENT(!(options & ~SLJIT_ENTER_CDECL)); + if (options & SLJIT_ENTER_REG_ARG) { + CHECK_ARGUMENT(!(options & ~(0x3 | SLJIT_ENTER_REG_ARG))); + } else { + CHECK_ARGUMENT(options == 0); + } + CHECK_ARGUMENT(SLJIT_KEPT_SAVEDS_COUNT(options) <= 3 && SLJIT_KEPT_SAVEDS_COUNT(options) <= saveds); CHECK_ARGUMENT(scratches >= 0 && scratches <= SLJIT_NUMBER_OF_REGISTERS); CHECK_ARGUMENT(saveds >= 0 && saveds <= SLJIT_NUMBER_OF_SAVED_REGISTERS); CHECK_ARGUMENT(scratches + saveds <= SLJIT_NUMBER_OF_REGISTERS); @@ -1133,7 +1154,7 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_set_context(struct sljit_compi CHECK_ARGUMENT(fscratches + fsaveds <= SLJIT_NUMBER_OF_FLOAT_REGISTERS); CHECK_ARGUMENT(local_size >= 0 && local_size <= SLJIT_MAX_LOCAL_SIZE); CHECK_ARGUMENT((arg_types & SLJIT_ARG_FULL_MASK) < SLJIT_ARG_TYPE_F64); - CHECK_ARGUMENT(function_check_arguments(arg_types, scratches, saveds, fscratches)); + CHECK_ARGUMENT(function_check_arguments(arg_types, scratches, (options & SLJIT_ENTER_REG_ARG) ? 0 : saveds, fscratches)); compiler->last_flags = 0; #endif @@ -1153,8 +1174,16 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_set_context(struct sljit_compi } while (arg_types); } - fprintf(compiler->verbose, "],%s scratches:%d, saveds:%d, fscratches:%d, fsaveds:%d, local_size:%d\n", - (options & SLJIT_ENTER_CDECL) ? " enter:cdecl," : "", + fprintf(compiler->verbose, "],"); + + if (options & SLJIT_ENTER_REG_ARG) { + fprintf(compiler->verbose, " enter:reg_arg,"); + + if (SLJIT_KEPT_SAVEDS_COUNT(options) > 0) + fprintf(compiler->verbose, " keep:%d,", SLJIT_KEPT_SAVEDS_COUNT(options)); + } + + fprintf(compiler->verbose, " scratches:%d, saveds:%d, fscratches:%d, fsaveds:%d, local_size:%d\n", scratches, saveds, fscratches, fsaveds, local_size); } #endif @@ -1195,18 +1224,52 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_return(struct sljit_compi case SLJIT_ARG_TYPE_P: CHECK_ARGUMENT(op == SLJIT_MOV_P); break; + case SLJIT_ARG_TYPE_F64: + CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_FPU)); + CHECK_ARGUMENT(op == SLJIT_MOV_F64); + break; + case SLJIT_ARG_TYPE_F32: + CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_FPU)); + CHECK_ARGUMENT(op == SLJIT_MOV_F32); + break; default: /* Context not initialized, void, etc. */ CHECK_ARGUMENT(0); break; } - FUNCTION_CHECK_SRC(src, srcw); + + if (GET_OPCODE(op) < SLJIT_MOV_F64) { + FUNCTION_CHECK_SRC(src, srcw); + } else { + FUNCTION_FCHECK(src, srcw); + } compiler->last_flags = 0; #endif #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) if (SLJIT_UNLIKELY(!!compiler->verbose)) { - fprintf(compiler->verbose, " return%s%s ", !(op & SLJIT_32) ? "" : "32", - op1_names[GET_OPCODE(op) - SLJIT_OP1_BASE]); + if (GET_OPCODE(op) < SLJIT_MOV_F64) { + fprintf(compiler->verbose, " return%s%s ", !(op & SLJIT_32) ? "" : "32", + op1_names[GET_OPCODE(op) - SLJIT_OP1_BASE]); + sljit_verbose_param(compiler, src, srcw); + } else { + fprintf(compiler->verbose, " return%s ", !(op & SLJIT_32) ? ".f64" : ".f32"); + sljit_verbose_fparam(compiler, src, srcw); + } + fprintf(compiler->verbose, "\n"); + } +#endif + CHECK_RETURN_OK; +} + +static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_return_to(struct sljit_compiler *compiler, + sljit_s32 src, sljit_sw srcw) +{ +#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) + FUNCTION_CHECK_SRC(src, srcw); +#endif +#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) + if (SLJIT_UNLIKELY(!!compiler->verbose)) { + fprintf(compiler->verbose, " return_to "); sljit_verbose_param(compiler, src, srcw); fprintf(compiler->verbose, "\n"); } @@ -1263,7 +1326,7 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op1(struct sljit_compiler } #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) - CHECK_ARGUMENT(GET_OPCODE(op) >= SLJIT_MOV && GET_OPCODE(op) <= SLJIT_CLZ); + CHECK_ARGUMENT(GET_OPCODE(op) >= SLJIT_MOV && GET_OPCODE(op) <= SLJIT_CTZ); switch (GET_OPCODE(op)) { case SLJIT_NOT: @@ -1324,15 +1387,18 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op2(struct sljit_compiler } #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) - CHECK_ARGUMENT(GET_OPCODE(op) >= SLJIT_ADD && GET_OPCODE(op) <= SLJIT_ASHR); + CHECK_ARGUMENT(GET_OPCODE(op) >= SLJIT_ADD && GET_OPCODE(op) <= SLJIT_ROTR); switch (GET_OPCODE(op)) { case SLJIT_AND: case SLJIT_OR: case SLJIT_XOR: case SLJIT_SHL: + case SLJIT_MSHL: case SLJIT_LSHR: + case SLJIT_MLSHR: case SLJIT_ASHR: + case SLJIT_MASHR: CHECK_ARGUMENT(!(op & VARIABLE_FLAG_MASK)); break; case SLJIT_MUL: @@ -1357,6 +1423,10 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op2(struct sljit_compiler CHECK_ARGUMENT((compiler->last_flags & 0xff) == GET_FLAG_TYPE(SLJIT_SET_CARRY)); CHECK_ARGUMENT((op & SLJIT_32) == (compiler->last_flags & SLJIT_32)); break; + case SLJIT_ROTL: + case SLJIT_ROTR: + CHECK_ARGUMENT(!(op & (SLJIT_SET_Z | VARIABLE_FLAG_MASK))); + break; default: SLJIT_UNREACHABLE(); break; @@ -1390,6 +1460,35 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op2(struct sljit_compiler CHECK_RETURN_OK; } +static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_shift_into(struct sljit_compiler *compiler, sljit_s32 op, + sljit_s32 src_dst, + sljit_s32 src1, sljit_sw src1w, + sljit_s32 src2, sljit_sw src2w) +{ +#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) + CHECK_ARGUMENT(GET_OPCODE(op) == SLJIT_SHL || GET_OPCODE(op) == SLJIT_LSHR + || GET_OPCODE(op) == SLJIT_MSHL || GET_OPCODE(op) == SLJIT_MLSHR); + CHECK_ARGUMENT((op & ~(0xff | SLJIT_32 | SLJIT_SHIFT_INTO_NON_ZERO)) == 0); + CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(src_dst)); + FUNCTION_CHECK_SRC(src1, src1w); + FUNCTION_CHECK_SRC(src2, src2w); +#endif +#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) + if (SLJIT_UNLIKELY(!!compiler->verbose)) { + fprintf(compiler->verbose, " %s%s.into%s ", op2_names[GET_OPCODE(op) - SLJIT_OP2_BASE], !(op & SLJIT_32) ? "" : "32", + (op & SLJIT_SHIFT_INTO_NON_ZERO) ? ".nz" : ""); + + sljit_verbose_reg(compiler, src_dst); + fprintf(compiler->verbose, ", "); + sljit_verbose_param(compiler, src1, src1w); + fprintf(compiler->verbose, ", "); + sljit_verbose_param(compiler, src2, src2w); + fprintf(compiler->verbose, "\n"); + } +#endif + CHECK_RETURN_OK; +} + static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op_src(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 src, sljit_sw srcw) { @@ -1510,7 +1609,7 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fop1_cmp(struct sljit_com sljit_s32 src2, sljit_sw src2w) { #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) - compiler->last_flags = GET_FLAG_TYPE(op) | (op & (SLJIT_32 | SLJIT_SET_Z)); + compiler->last_flags = GET_FLAG_TYPE(op) | (op & SLJIT_32); #endif if (SLJIT_UNLIKELY(compiler->skip_checks)) { @@ -1523,7 +1622,7 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fop1_cmp(struct sljit_com CHECK_ARGUMENT(GET_OPCODE(op) == SLJIT_CMP_F64); CHECK_ARGUMENT(!(op & SLJIT_SET_Z)); CHECK_ARGUMENT((op & VARIABLE_FLAG_MASK) - || (GET_FLAG_TYPE(op) >= SLJIT_EQUAL_F64 && GET_FLAG_TYPE(op) <= SLJIT_ORDERED_F64)); + || (GET_FLAG_TYPE(op) >= SLJIT_F_EQUAL && GET_FLAG_TYPE(op) <= SLJIT_ORDERED_LESS_EQUAL)); FUNCTION_FCHECK(src1, src1w); FUNCTION_FCHECK(src2, src2w); #endif @@ -1531,7 +1630,7 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fop1_cmp(struct sljit_com if (SLJIT_UNLIKELY(!!compiler->verbose)) { fprintf(compiler->verbose, " %s%s", fop1_names[SLJIT_CMP_F64 - SLJIT_FOP1_BASE], (op & SLJIT_32) ? ".f32" : ".f64"); if (op & VARIABLE_FLAG_MASK) { - fprintf(compiler->verbose, ".%s_f", jump_names[GET_FLAG_TYPE(op)]); + fprintf(compiler->verbose, ".%s", jump_names[GET_FLAG_TYPE(op)]); } fprintf(compiler->verbose, " "); sljit_verbose_fparam(compiler, src1, src1w); @@ -1650,6 +1749,17 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_label(struct sljit_compil CHECK_RETURN_OK; } +#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) +#if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86) \ + || (defined SLJIT_CONFIG_ARM && SLJIT_CONFIG_ARM) +#define CHECK_UNORDERED(type, last_flags) \ + ((((type) & 0xff) == SLJIT_UNORDERED || ((type) & 0xff) == SLJIT_ORDERED) && \ + ((last_flags) & 0xff) >= SLJIT_UNORDERED && ((last_flags) & 0xff) <= SLJIT_ORDERED_LESS_EQUAL) +#else +#define CHECK_UNORDERED(type, last_flags) 0 +#endif +#endif /* SLJIT_ARGUMENT_CHECKS */ + static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_jump(struct sljit_compiler *compiler, sljit_s32 type) { if (SLJIT_UNLIKELY(compiler->skip_checks)) { @@ -1658,9 +1768,8 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_jump(struct sljit_compile } #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) - CHECK_ARGUMENT(!(type & ~(0xff | SLJIT_REWRITABLE_JUMP | SLJIT_32))); + CHECK_ARGUMENT(!(type & ~(0xff | SLJIT_REWRITABLE_JUMP))); CHECK_ARGUMENT((type & 0xff) >= SLJIT_EQUAL && (type & 0xff) <= SLJIT_FAST_CALL); - CHECK_ARGUMENT((type & 0xff) < SLJIT_JUMP || !(type & SLJIT_32)); if ((type & 0xff) < SLJIT_JUMP) { if ((type & 0xff) <= SLJIT_NOT_ZERO) @@ -1670,13 +1779,14 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_jump(struct sljit_compile compiler->last_flags = 0; } else CHECK_ARGUMENT((type & 0xff) == (compiler->last_flags & 0xff) - || ((type & 0xff) == SLJIT_NOT_OVERFLOW && (compiler->last_flags & 0xff) == SLJIT_OVERFLOW)); + || ((type & 0xff) == SLJIT_NOT_OVERFLOW && (compiler->last_flags & 0xff) == SLJIT_OVERFLOW) + || CHECK_UNORDERED(type, compiler->last_flags)); } #endif #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) if (SLJIT_UNLIKELY(!!compiler->verbose)) - fprintf(compiler->verbose, " jump%s %s%s\n", !(type & SLJIT_REWRITABLE_JUMP) ? "" : ".r", - jump_names[type & 0xff], JUMP_POSTFIX(type)); + fprintf(compiler->verbose, " jump%s %s\n", !(type & SLJIT_REWRITABLE_JUMP) ? "" : ".r", + jump_names[type & 0xff]); #endif CHECK_RETURN_OK; } @@ -1686,11 +1796,17 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_call(struct sljit_compile { #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) CHECK_ARGUMENT(!(type & ~(0xff | SLJIT_REWRITABLE_JUMP | SLJIT_CALL_RETURN))); - CHECK_ARGUMENT((type & 0xff) == SLJIT_CALL || (type & 0xff) == SLJIT_CALL_CDECL); + CHECK_ARGUMENT((type & 0xff) >= SLJIT_CALL && (type & 0xff) <= SLJIT_CALL_REG_ARG); CHECK_ARGUMENT(function_check_arguments(arg_types, compiler->scratches, -1, compiler->fscratches)); if (type & SLJIT_CALL_RETURN) { CHECK_ARGUMENT((arg_types & SLJIT_ARG_MASK) == compiler->last_return); + + if (compiler->options & SLJIT_ENTER_REG_ARG) { + CHECK_ARGUMENT((type & 0xff) == SLJIT_CALL_REG_ARG); + } else { + CHECK_ARGUMENT((type & 0xff) != SLJIT_CALL_REG_ARG); + } } #endif #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) @@ -1729,8 +1845,8 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_cmp(struct sljit_compiler #endif #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) if (SLJIT_UNLIKELY(!!compiler->verbose)) { - fprintf(compiler->verbose, " cmp%s %s%s, ", !(type & SLJIT_REWRITABLE_JUMP) ? "" : ".r", - jump_names[type & 0xff], (type & SLJIT_32) ? "32" : ""); + fprintf(compiler->verbose, " cmp%s%s %s, ", (type & SLJIT_32) ? "32" : "", + !(type & SLJIT_REWRITABLE_JUMP) ? "" : ".r", jump_names[type & 0xff]); sljit_verbose_param(compiler, src1, src1w); fprintf(compiler->verbose, ", "); sljit_verbose_param(compiler, src2, src2w); @@ -1747,15 +1863,16 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fcmp(struct sljit_compile #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_FPU)); CHECK_ARGUMENT(!(type & ~(0xff | SLJIT_REWRITABLE_JUMP | SLJIT_32))); - CHECK_ARGUMENT((type & 0xff) >= SLJIT_EQUAL_F64 && (type & 0xff) <= SLJIT_ORDERED_F64); + CHECK_ARGUMENT((type & 0xff) >= SLJIT_F_EQUAL && (type & 0xff) <= SLJIT_ORDERED_LESS_EQUAL + && ((type & 0xff) <= SLJIT_ORDERED || sljit_cmp_info(type & 0xff))); FUNCTION_FCHECK(src1, src1w); FUNCTION_FCHECK(src2, src2w); compiler->last_flags = 0; #endif #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) if (SLJIT_UNLIKELY(!!compiler->verbose)) { - fprintf(compiler->verbose, " fcmp%s %s%s, ", !(type & SLJIT_REWRITABLE_JUMP) ? "" : ".r", - jump_names[type & 0xff], (type & SLJIT_32) ? ".f32" : ".f64"); + fprintf(compiler->verbose, " fcmp%s%s %s, ", (type & SLJIT_32) ? ".f32" : ".f64", + !(type & SLJIT_REWRITABLE_JUMP) ? "" : ".r", jump_names[type & 0xff]); sljit_verbose_fparam(compiler, src1, src1w); fprintf(compiler->verbose, ", "); sljit_verbose_fparam(compiler, src2, src2w); @@ -1793,12 +1910,18 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_icall(struct sljit_compil { #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) CHECK_ARGUMENT(!(type & ~(0xff | SLJIT_CALL_RETURN))); - CHECK_ARGUMENT((type & 0xff) == SLJIT_CALL || (type & 0xff) == SLJIT_CALL_CDECL); + CHECK_ARGUMENT((type & 0xff) >= SLJIT_CALL && (type & 0xff) <= SLJIT_CALL_REG_ARG); CHECK_ARGUMENT(function_check_arguments(arg_types, compiler->scratches, -1, compiler->fscratches)); FUNCTION_CHECK_SRC(src, srcw); if (type & SLJIT_CALL_RETURN) { CHECK_ARGUMENT((arg_types & SLJIT_ARG_MASK) == compiler->last_return); + + if (compiler->options & SLJIT_ENTER_REG_ARG) { + CHECK_ARGUMENT((type & 0xff) == SLJIT_CALL_REG_ARG); + } else { + CHECK_ARGUMENT((type & 0xff) != SLJIT_CALL_REG_ARG); + } } #endif #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) @@ -1830,18 +1953,18 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op_flags(struct sljit_com sljit_s32 type) { #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) - CHECK_ARGUMENT(!(type & ~(0xff | SLJIT_32))); - CHECK_ARGUMENT((type & 0xff) >= SLJIT_EQUAL && (type & 0xff) <= SLJIT_ORDERED_F64); + CHECK_ARGUMENT(type >= SLJIT_EQUAL && type <= SLJIT_ORDERED_LESS_EQUAL); CHECK_ARGUMENT(op == SLJIT_MOV || op == SLJIT_MOV32 || (GET_OPCODE(op) >= SLJIT_AND && GET_OPCODE(op) <= SLJIT_XOR)); CHECK_ARGUMENT(!(op & VARIABLE_FLAG_MASK)); - if ((type & 0xff) <= SLJIT_NOT_ZERO) + if (type <= SLJIT_NOT_ZERO) CHECK_ARGUMENT(compiler->last_flags & SLJIT_SET_Z); else - CHECK_ARGUMENT((type & 0xff) == (compiler->last_flags & 0xff) - || ((type & 0xff) == SLJIT_NOT_CARRY && (compiler->last_flags & 0xff) == SLJIT_CARRY) - || ((type & 0xff) == SLJIT_NOT_OVERFLOW && (compiler->last_flags & 0xff) == SLJIT_OVERFLOW)); + CHECK_ARGUMENT(type == (compiler->last_flags & 0xff) + || (type == SLJIT_NOT_CARRY && (compiler->last_flags & 0xff) == SLJIT_CARRY) + || (type == SLJIT_NOT_OVERFLOW && (compiler->last_flags & 0xff) == SLJIT_OVERFLOW) + || CHECK_UNORDERED(type, compiler->last_flags)); FUNCTION_CHECK_DST(dst, dstw); @@ -1850,12 +1973,12 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op_flags(struct sljit_com #endif #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) if (SLJIT_UNLIKELY(!!compiler->verbose)) { - fprintf(compiler->verbose, " flags%s %s%s, ", - !(op & SLJIT_SET_Z) ? "" : ".z", + fprintf(compiler->verbose, " flags.%s%s%s ", GET_OPCODE(op) < SLJIT_OP2_BASE ? "mov" : op2_names[GET_OPCODE(op) - SLJIT_OP2_BASE], - GET_OPCODE(op) < SLJIT_OP2_BASE ? op1_names[GET_OPCODE(op) - SLJIT_OP1_BASE] : ((op & SLJIT_32) ? "32" : "")); + GET_OPCODE(op) < SLJIT_OP2_BASE ? op1_names[GET_OPCODE(op) - SLJIT_OP1_BASE] : ((op & SLJIT_32) ? "32" : ""), + !(op & SLJIT_SET_Z) ? "" : ".z"); sljit_verbose_param(compiler, dst, dstw); - fprintf(compiler->verbose, ", %s%s\n", jump_names[type & 0xff], JUMP_POSTFIX(type)); + fprintf(compiler->verbose, ", %s\n", jump_names[type]); } #endif CHECK_RETURN_OK; @@ -1866,28 +1989,31 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_cmov(struct sljit_compile sljit_s32 src, sljit_sw srcw) { #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) - CHECK_ARGUMENT(!(type & ~(0xff | SLJIT_32))); - CHECK_ARGUMENT((type & 0xff) >= SLJIT_EQUAL && (type & 0xff) <= SLJIT_ORDERED_F64); + sljit_s32 cond = type & ~SLJIT_32; + + CHECK_ARGUMENT(cond >= SLJIT_EQUAL && cond <= SLJIT_ORDERED_LESS_EQUAL); CHECK_ARGUMENT(compiler->scratches != -1 && compiler->saveds != -1); - CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(dst_reg & ~SLJIT_32)); + CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(dst_reg)); if (src != SLJIT_IMM) { CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(src)); CHECK_ARGUMENT(srcw == 0); } - if ((type & 0xff) <= SLJIT_NOT_ZERO) + if (cond <= SLJIT_NOT_ZERO) CHECK_ARGUMENT(compiler->last_flags & SLJIT_SET_Z); else - CHECK_ARGUMENT((type & 0xff) == (compiler->last_flags & 0xff) - || ((type & 0xff) == SLJIT_NOT_OVERFLOW && (compiler->last_flags & 0xff) == SLJIT_OVERFLOW)); + CHECK_ARGUMENT(cond == (compiler->last_flags & 0xff) + || (cond == SLJIT_NOT_CARRY && (compiler->last_flags & 0xff) == SLJIT_CARRY) + || (cond == SLJIT_NOT_OVERFLOW && (compiler->last_flags & 0xff) == SLJIT_OVERFLOW) + || CHECK_UNORDERED(cond, compiler->last_flags)); #endif #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) if (SLJIT_UNLIKELY(!!compiler->verbose)) { - fprintf(compiler->verbose, " cmov%s %s%s, ", - !(dst_reg & SLJIT_32) ? "" : "32", - jump_names[type & 0xff], JUMP_POSTFIX(type)); - sljit_verbose_reg(compiler, dst_reg & ~SLJIT_32); + fprintf(compiler->verbose, " cmov%s %s, ", + !(type & SLJIT_32) ? "" : "32", + jump_names[type & ~SLJIT_32]); + sljit_verbose_reg(compiler, dst_reg); fprintf(compiler->verbose, ", "); sljit_verbose_param(compiler, src, srcw); fprintf(compiler->verbose, "\n"); @@ -1900,28 +2026,123 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_mem(struct sljit_compiler sljit_s32 reg, sljit_s32 mem, sljit_sw memw) { + if (SLJIT_UNLIKELY(compiler->skip_checks)) { + compiler->skip_checks = 0; + CHECK_RETURN_OK; + } + #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) - CHECK_ARGUMENT((type & 0xff) >= SLJIT_MOV && (type & 0xff) <= SLJIT_MOV_P); - CHECK_ARGUMENT(!(type & SLJIT_32) || ((type & 0xff) != SLJIT_MOV && (type & 0xff) != SLJIT_MOV_U32 && (type & 0xff) != SLJIT_MOV_P)); - CHECK_ARGUMENT((type & SLJIT_MEM_PRE) || (type & SLJIT_MEM_POST)); - CHECK_ARGUMENT((type & (SLJIT_MEM_PRE | SLJIT_MEM_POST)) != (SLJIT_MEM_PRE | SLJIT_MEM_POST)); - CHECK_ARGUMENT((type & ~(0xff | SLJIT_32 | SLJIT_MEM_STORE | SLJIT_MEM_SUPP | SLJIT_MEM_PRE | SLJIT_MEM_POST)) == 0); + sljit_s32 allowed_flags; + + if (type & SLJIT_MEM_UNALIGNED) { + CHECK_ARGUMENT(!(type & (SLJIT_MEM_UNALIGNED_16 | SLJIT_MEM_UNALIGNED_32))); + } else if (type & SLJIT_MEM_UNALIGNED_16) { + CHECK_ARGUMENT(!(type & SLJIT_MEM_UNALIGNED_32)); + } else { + CHECK_ARGUMENT((reg & REG_PAIR_MASK) || (type & SLJIT_MEM_UNALIGNED_32)); + } + + allowed_flags = SLJIT_MEM_UNALIGNED; + + switch (type & 0xff) { + case SLJIT_MOV_U32: + case SLJIT_MOV_S32: + case SLJIT_MOV32: + allowed_flags = SLJIT_MEM_UNALIGNED | SLJIT_MEM_UNALIGNED_16; + break; + case SLJIT_MOV: + case SLJIT_MOV_P: + allowed_flags = SLJIT_MEM_UNALIGNED | SLJIT_MEM_UNALIGNED_16 | SLJIT_MEM_UNALIGNED_32; + break; + } + + CHECK_ARGUMENT((type & ~(0xff | SLJIT_32 | SLJIT_MEM_STORE | allowed_flags)) == 0); + + if (reg & REG_PAIR_MASK) { + CHECK_ARGUMENT((type & 0xff) == SLJIT_MOV); + CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(REG_PAIR_FIRST(reg))); + CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(REG_PAIR_SECOND(reg))); + CHECK_ARGUMENT(REG_PAIR_FIRST(reg) != REG_PAIR_SECOND(reg)); + } else { + CHECK_ARGUMENT((type & 0xff) >= SLJIT_MOV && (type & 0xff) <= SLJIT_MOV_P); + CHECK_ARGUMENT(!(type & SLJIT_32) || ((type & 0xff) >= SLJIT_MOV_U8 && (type & 0xff) <= SLJIT_MOV_S16)); + CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(reg)); + } FUNCTION_CHECK_SRC_MEM(mem, memw); - CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(reg)); - - CHECK_ARGUMENT((mem & REG_MASK) != 0 && (mem & REG_MASK) != reg); #endif #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) - if (!(type & SLJIT_MEM_SUPP) && SLJIT_UNLIKELY(!!compiler->verbose)) { - if (sljit_emit_mem(compiler, type | SLJIT_MEM_SUPP, reg, mem, memw) == SLJIT_ERR_UNSUPPORTED) - fprintf(compiler->verbose, " //"); + if (SLJIT_UNLIKELY(!!compiler->verbose)) { + if ((type & 0xff) == SLJIT_MOV32) + fprintf(compiler->verbose, " %s32", + (type & SLJIT_MEM_STORE) ? "store" : "load"); + else + fprintf(compiler->verbose, " %s%s%s", + (type & SLJIT_MEM_STORE) ? "store" : "load", + !(type & SLJIT_32) ? "" : "32", + op1_names[(type & 0xff) - SLJIT_OP1_BASE]); + + if (type & SLJIT_MEM_UNALIGNED) + printf(".un"); + else if (type & SLJIT_MEM_UNALIGNED_16) + printf(".un16"); + else if (type & SLJIT_MEM_UNALIGNED_32) + printf(".un32"); + + if (reg & REG_PAIR_MASK) { + fprintf(compiler->verbose, " {"); + sljit_verbose_reg(compiler, REG_PAIR_FIRST(reg)); + fprintf(compiler->verbose, ", "); + sljit_verbose_reg(compiler, REG_PAIR_SECOND(reg)); + fprintf(compiler->verbose, "}, "); + } else { + fprintf(compiler->verbose, " "); + sljit_verbose_reg(compiler, reg); + fprintf(compiler->verbose, ", "); + } + sljit_verbose_param(compiler, mem, memw); + fprintf(compiler->verbose, "\n"); + } +#endif + CHECK_RETURN_OK; +} + +static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_mem_update(struct sljit_compiler *compiler, sljit_s32 type, + sljit_s32 reg, + sljit_s32 mem, sljit_sw memw) +{ + if (SLJIT_UNLIKELY(compiler->skip_checks)) { + compiler->skip_checks = 0; + CHECK_RETURN_OK; + } + +#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) + CHECK_ARGUMENT((type & 0xff) >= SLJIT_MOV && (type & 0xff) <= SLJIT_MOV_P); + CHECK_ARGUMENT((type & ~(0xff | SLJIT_32 | SLJIT_MEM_STORE | SLJIT_MEM_SUPP | SLJIT_MEM_POST)) == 0); + CHECK_ARGUMENT((mem & REG_MASK) != 0 && (mem & REG_MASK) != reg); + + FUNCTION_CHECK_SRC_MEM(mem, memw); +#endif +#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) + if (SLJIT_UNLIKELY(!!compiler->verbose)) { + if (type & SLJIT_MEM_SUPP) + CHECK_RETURN_OK; + if (sljit_emit_mem_update(compiler, type | SLJIT_MEM_SUPP, reg, mem, memw) == SLJIT_ERR_UNSUPPORTED) { + fprintf(compiler->verbose, " # mem: unsupported form, no instructions are emitted\n"); + CHECK_RETURN_OK; + } + + if ((type & 0xff) == SLJIT_MOV32) + fprintf(compiler->verbose, " %s32.%s ", + (type & SLJIT_MEM_STORE) ? "store" : "load", + (type & SLJIT_MEM_POST) ? "post" : "pre"); + else + fprintf(compiler->verbose, " %s%s%s.%s ", + (type & SLJIT_MEM_STORE) ? "store" : "load", + !(type & SLJIT_32) ? "" : "32", + op1_names[(type & 0xff) - SLJIT_OP1_BASE], + (type & SLJIT_MEM_POST) ? "post" : "pre"); - fprintf(compiler->verbose, " mem%s.%s%s%s ", - !(type & SLJIT_32) ? "" : "32", - (type & SLJIT_MEM_STORE) ? "st" : "ld", - op1_names[(type & 0xff) - SLJIT_OP1_BASE], - (type & SLJIT_MEM_PRE) ? ".pre" : ".post"); sljit_verbose_reg(compiler, reg); fprintf(compiler->verbose, ", "); sljit_verbose_param(compiler, mem, memw); @@ -1937,22 +2158,34 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fmem(struct sljit_compile { #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) CHECK_ARGUMENT((type & 0xff) == SLJIT_MOV_F64); - CHECK_ARGUMENT((type & SLJIT_MEM_PRE) || (type & SLJIT_MEM_POST)); - CHECK_ARGUMENT((type & (SLJIT_MEM_PRE | SLJIT_MEM_POST)) != (SLJIT_MEM_PRE | SLJIT_MEM_POST)); - CHECK_ARGUMENT((type & ~(0xff | SLJIT_32 | SLJIT_MEM_STORE | SLJIT_MEM_SUPP | SLJIT_MEM_PRE | SLJIT_MEM_POST)) == 0); - FUNCTION_CHECK_SRC_MEM(mem, memw); + if (type & SLJIT_MEM_UNALIGNED) { + CHECK_ARGUMENT(!(type & (SLJIT_MEM_UNALIGNED_16 | SLJIT_MEM_UNALIGNED_32))); + } else if (type & SLJIT_MEM_UNALIGNED_16) { + CHECK_ARGUMENT(!(type & SLJIT_MEM_UNALIGNED_32)); + } else { + CHECK_ARGUMENT(type & SLJIT_MEM_UNALIGNED_32); + CHECK_ARGUMENT(!(type & SLJIT_32)); + } + + CHECK_ARGUMENT(!(type & ~(0xff | SLJIT_32 | SLJIT_MEM_STORE | SLJIT_MEM_UNALIGNED | SLJIT_MEM_UNALIGNED_16 | SLJIT_MEM_UNALIGNED_32))); CHECK_ARGUMENT(FUNCTION_CHECK_IS_FREG(freg)); + FUNCTION_CHECK_SRC_MEM(mem, memw); #endif #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) - if (!(type & SLJIT_MEM_SUPP) && SLJIT_UNLIKELY(!!compiler->verbose)) { - if (sljit_emit_fmem(compiler, type | SLJIT_MEM_SUPP, freg, mem, memw) == SLJIT_ERR_UNSUPPORTED) - fprintf(compiler->verbose, " //"); + if (SLJIT_UNLIKELY(!!compiler->verbose)) { + fprintf(compiler->verbose, " %s.%s", + (type & SLJIT_MEM_STORE) ? "store" : "load", + !(type & SLJIT_32) ? "f64" : "f32"); - fprintf(compiler->verbose, " fmem.%s%s%s ", - (type & SLJIT_MEM_STORE) ? "st" : "ld", - !(type & SLJIT_32) ? ".f64" : ".f32", - (type & SLJIT_MEM_PRE) ? ".pre" : ".post"); + if (type & SLJIT_MEM_UNALIGNED) + printf(".un"); + else if (type & SLJIT_MEM_UNALIGNED_16) + printf(".un16"); + else if (type & SLJIT_MEM_UNALIGNED_32) + printf(".un32"); + + fprintf(compiler->verbose, " "); sljit_verbose_freg(compiler, freg); fprintf(compiler->verbose, ", "); sljit_verbose_param(compiler, mem, memw); @@ -1962,6 +2195,40 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fmem(struct sljit_compile CHECK_RETURN_OK; } +static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fmem_update(struct sljit_compiler *compiler, sljit_s32 type, + sljit_s32 freg, + sljit_s32 mem, sljit_sw memw) +{ +#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) + CHECK_ARGUMENT((type & 0xff) == SLJIT_MOV_F64); + CHECK_ARGUMENT((type & ~(0xff | SLJIT_32 | SLJIT_MEM_STORE | SLJIT_MEM_SUPP | SLJIT_MEM_POST)) == 0); + FUNCTION_CHECK_SRC_MEM(mem, memw); + CHECK_ARGUMENT(FUNCTION_CHECK_IS_FREG(freg)); +#endif +#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) + if (SLJIT_UNLIKELY(!!compiler->verbose)) { + if (type & SLJIT_MEM_SUPP) + CHECK_RETURN_OK; + if (sljit_emit_fmem_update(compiler, type | SLJIT_MEM_SUPP, freg, mem, memw) == SLJIT_ERR_UNSUPPORTED) { + fprintf(compiler->verbose, " # fmem: unsupported form, no instructions are emitted\n"); + CHECK_RETURN_OK; + } + + fprintf(compiler->verbose, " %s.%s.%s ", + (type & SLJIT_MEM_STORE) ? "store" : "load", + !(type & SLJIT_32) ? "f64" : "f32", + (type & SLJIT_MEM_POST) ? "post" : "pre"); + + sljit_verbose_freg(compiler, freg); + fprintf(compiler->verbose, ", "); + sljit_verbose_param(compiler, mem, memw); + fprintf(compiler->verbose, "\n"); + } +#endif + CHECK_RETURN_OK; + +} + static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_get_local_base(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw offset) { /* Any offset is allowed. */ @@ -2012,6 +2279,10 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_put_label(struct sljit_co CHECK_RETURN_OK; } +#else /* !SLJIT_ARGUMENT_CHECKS && !SLJIT_VERBOSE */ + +#define SLJIT_SKIP_CHECKS(compiler) + #endif /* SLJIT_ARGUMENT_CHECKS || SLJIT_VERBOSE */ #define SELECT_FOP1_OPERATION_WITH_CHECKS(compiler, op, dst, dstw, src, srcw) \ @@ -2039,46 +2310,11 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_put_label(struct sljit_co ADJUST_LOCAL_OFFSET(dst, dstw); \ ADJUST_LOCAL_OFFSET(src, srcw); -static SLJIT_INLINE sljit_s32 emit_mov_before_return(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 src, sljit_sw srcw) -{ -#if (defined SLJIT_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE) - /* At the moment the pointer size is always equal to sljit_sw. May be changed in the future. */ - if (src == SLJIT_RETURN_REG && (op == SLJIT_MOV || op == SLJIT_MOV_P)) - return SLJIT_SUCCESS; -#else - if (src == SLJIT_RETURN_REG && (op == SLJIT_MOV || op == SLJIT_MOV_U32 || op == SLJIT_MOV_S32 || op == SLJIT_MOV_P)) - return SLJIT_SUCCESS; -#endif - -#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) \ - || (defined SLJIT_VERBOSE && SLJIT_VERBOSE) - compiler->skip_checks = 1; -#endif - return sljit_emit_op1(compiler, op, SLJIT_RETURN_REG, 0, src, srcw); -} - -#if !(defined SLJIT_CONFIG_SPARC && SLJIT_CONFIG_SPARC) - -SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 src, sljit_sw srcw) -{ - CHECK_ERROR(); - CHECK(check_sljit_emit_return(compiler, op, src, srcw)); - - FAIL_IF(emit_mov_before_return(compiler, op, src, srcw)); - -#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) \ - || (defined SLJIT_VERBOSE && SLJIT_VERBOSE) - compiler->skip_checks = 1; -#endif - return sljit_emit_return_void(compiler); -} - -#endif - #if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86) \ || (defined SLJIT_CONFIG_PPC && SLJIT_CONFIG_PPC) \ - || (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32) \ - || ((defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS) && !(defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1 && SLJIT_MIPS_REV < 6)) + || ((defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS) && !(defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1 && SLJIT_MIPS_REV < 6)) \ + || (defined SLJIT_CONFIG_RISCV && SLJIT_CONFIG_RISCV) \ + || (defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X) static SLJIT_INLINE sljit_s32 sljit_emit_cmov_generic(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 dst_reg, @@ -2086,33 +2322,57 @@ static SLJIT_INLINE sljit_s32 sljit_emit_cmov_generic(struct sljit_compiler *com { struct sljit_label *label; struct sljit_jump *jump; - sljit_s32 op = (dst_reg & SLJIT_32) ? SLJIT_MOV32 : SLJIT_MOV; + sljit_s32 op = (type & SLJIT_32) ? SLJIT_MOV32 : SLJIT_MOV; -#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \ - || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) - compiler->skip_checks = 1; -#endif - jump = sljit_emit_jump(compiler, type ^ 0x1); + SLJIT_SKIP_CHECKS(compiler); + jump = sljit_emit_jump(compiler, (type & ~SLJIT_32) ^ 0x1); FAIL_IF(!jump); -#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \ - || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) - compiler->skip_checks = 1; -#endif - FAIL_IF(sljit_emit_op1(compiler, op, dst_reg & ~SLJIT_32, 0, src, srcw)); + SLJIT_SKIP_CHECKS(compiler); + FAIL_IF(sljit_emit_op1(compiler, op, dst_reg, 0, src, srcw)); -#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \ - || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) - compiler->skip_checks = 1; -#endif + SLJIT_SKIP_CHECKS(compiler); label = sljit_emit_label(compiler); FAIL_IF(!label); + sljit_set_label(jump, label); return SLJIT_SUCCESS; } #endif +#if (!(defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS) || (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)) \ + && !(defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) + +static sljit_s32 sljit_emit_mem_unaligned(struct sljit_compiler *compiler, sljit_s32 type, + sljit_s32 reg, + sljit_s32 mem, sljit_sw memw) +{ + SLJIT_SKIP_CHECKS(compiler); + + if (type & SLJIT_MEM_STORE) + return sljit_emit_op1(compiler, type & (0xff | SLJIT_32), mem, memw, reg, 0); + return sljit_emit_op1(compiler, type & (0xff | SLJIT_32), reg, 0, mem, memw); +} + +#endif /* (!SLJIT_CONFIG_MIPS || SLJIT_MIPS_REV >= 6) && !SLJIT_CONFIG_ARM_V5 */ + +#if (!(defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS) || (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)) \ + && !(defined SLJIT_CONFIG_ARM_32 && SLJIT_CONFIG_ARM_32) + +static sljit_s32 sljit_emit_fmem_unaligned(struct sljit_compiler *compiler, sljit_s32 type, + sljit_s32 freg, + sljit_s32 mem, sljit_sw memw) +{ + SLJIT_SKIP_CHECKS(compiler); + + if (type & SLJIT_MEM_STORE) + return sljit_emit_fop1(compiler, type & (0xff | SLJIT_32), mem, memw, freg, 0); + return sljit_emit_fop1(compiler, type & (0xff | SLJIT_32), freg, 0, mem, memw); +} + +#endif /* (!SLJIT_CONFIG_MIPS || SLJIT_MIPS_REV >= 6) && !SLJIT_CONFIG_ARM */ + /* CPU description section */ #if (defined SLJIT_32BIT_ARCHITECTURE && SLJIT_32BIT_ARCHITECTURE) @@ -2153,13 +2413,58 @@ static SLJIT_INLINE sljit_s32 sljit_emit_cmov_generic(struct sljit_compiler *com # include "sljitNativePPC_common.c" #elif (defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS) # include "sljitNativeMIPS_common.c" -#elif (defined SLJIT_CONFIG_SPARC && SLJIT_CONFIG_SPARC) -# include "sljitNativeSPARC_common.c" +#elif (defined SLJIT_CONFIG_RISCV && SLJIT_CONFIG_RISCV) +# include "sljitNativeRISCV_common.c" #elif (defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X) # include "sljitNativeS390X.c" #endif -#if !(defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS) +static SLJIT_INLINE sljit_s32 emit_mov_before_return(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 src, sljit_sw srcw) +{ +#if (defined SLJIT_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE) + /* At the moment the pointer size is always equal to sljit_sw. May be changed in the future. */ + if (src == SLJIT_RETURN_REG && (op == SLJIT_MOV || op == SLJIT_MOV_P)) + return SLJIT_SUCCESS; +#else + if (src == SLJIT_RETURN_REG && (op == SLJIT_MOV || op == SLJIT_MOV_U32 || op == SLJIT_MOV_S32 || op == SLJIT_MOV_P)) + return SLJIT_SUCCESS; +#endif + + SLJIT_SKIP_CHECKS(compiler); + return sljit_emit_op1(compiler, op, SLJIT_RETURN_REG, 0, src, srcw); +} + +#if !(defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) \ + && !((defined SLJIT_CONFIG_ARM_32 && SLJIT_CONFIG_ARM_32) && defined __SOFTFP__) + +static SLJIT_INLINE sljit_s32 emit_fmov_before_return(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 src, sljit_sw srcw) +{ + if (src == SLJIT_FR0) + return SLJIT_SUCCESS; + + SLJIT_SKIP_CHECKS(compiler); + return sljit_emit_fop1(compiler, op, SLJIT_RETURN_FREG, 0, src, srcw); +} + +#endif /* !SLJIT_CONFIG_X86_32 && !(SLJIT_CONFIG_ARM_32 && __SOFTFP__) */ + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 src, sljit_sw srcw) +{ + CHECK_ERROR(); + CHECK(check_sljit_emit_return(compiler, op, src, srcw)); + + if (GET_OPCODE(op) < SLJIT_MOV_F64) { + FAIL_IF(emit_mov_before_return(compiler, op, src, srcw)); + } else { + FAIL_IF(emit_fmov_before_return(compiler, op, src, srcw)); + } + + SLJIT_SKIP_CHECKS(compiler); + return sljit_emit_return_void(compiler); +} + +#if !(defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS) \ + && !(defined SLJIT_CONFIG_RISCV && SLJIT_CONFIG_RISCV) SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_cmp(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 src1, sljit_sw src1w, @@ -2229,20 +2534,33 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_cmp(struct sljit_compiler else flags = condition << VARIABLE_FLAG_SHIFT; -#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \ - || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) - compiler->skip_checks = 1; -#endif + SLJIT_SKIP_CHECKS(compiler); PTR_FAIL_IF(sljit_emit_op2u(compiler, SLJIT_SUB | flags | (type & SLJIT_32), src1, src1w, src2, src2w)); -#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \ - || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) - compiler->skip_checks = 1; -#endif + + SLJIT_SKIP_CHECKS(compiler); return sljit_emit_jump(compiler, condition | (type & (SLJIT_REWRITABLE_JUMP | SLJIT_32))); } -#endif +#endif /* !SLJIT_CONFIG_MIPS */ + +#if (defined SLJIT_CONFIG_ARM && SLJIT_CONFIG_ARM) + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_cmp_info(sljit_s32 type) +{ + if (type < SLJIT_UNORDERED || type > SLJIT_ORDERED_LESS_EQUAL) + return 0; + + switch (type) { + case SLJIT_UNORDERED_OR_EQUAL: + case SLJIT_ORDERED_NOT_EQUAL: + return 0; + } + + return 1; +} + +#endif /* SLJIT_CONFIG_ARM */ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_fcmp(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 src1, sljit_sw src1w, @@ -2251,61 +2569,65 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_fcmp(struct sljit_compile CHECK_ERROR_PTR(); CHECK_PTR(check_sljit_emit_fcmp(compiler, type, src1, src1w, src2, src2w)); -#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \ - || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) - compiler->skip_checks = 1; -#endif + SLJIT_SKIP_CHECKS(compiler); sljit_emit_fop1(compiler, SLJIT_CMP_F64 | ((type & 0xff) << VARIABLE_FLAG_SHIFT) | (type & SLJIT_32), src1, src1w, src2, src2w); -#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \ - || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) - compiler->skip_checks = 1; -#endif + SLJIT_SKIP_CHECKS(compiler); return sljit_emit_jump(compiler, type); } -#if !(defined SLJIT_CONFIG_ARM_32 && SLJIT_CONFIG_ARM_32) \ - && !(defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64) \ +#if !(defined SLJIT_CONFIG_ARM && SLJIT_CONFIG_ARM) \ && !(defined SLJIT_CONFIG_PPC && SLJIT_CONFIG_PPC) -SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compiler, sljit_s32 type, +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem_update(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 reg, sljit_s32 mem, sljit_sw memw) { - SLJIT_UNUSED_ARG(compiler); + CHECK_ERROR(); + CHECK(check_sljit_emit_mem_update(compiler, type, reg, mem, memw)); SLJIT_UNUSED_ARG(type); SLJIT_UNUSED_ARG(reg); SLJIT_UNUSED_ARG(mem); SLJIT_UNUSED_ARG(memw); - CHECK_ERROR(); - CHECK(check_sljit_emit_mem(compiler, type, reg, mem, memw)); - return SLJIT_ERR_UNSUPPORTED; } -#endif +#endif /* !SLJIT_CONFIG_ARM && !SLJIT_CONFIG_PPC */ -#if !(defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64) \ - && !(defined SLJIT_CONFIG_PPC && SLJIT_CONFIG_PPC) +#if !(defined SLJIT_CONFIG_ARM_32 && SLJIT_CONFIG_ARM_32) \ + && !(defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS) SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fmem(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 freg, sljit_s32 mem, sljit_sw memw) { - SLJIT_UNUSED_ARG(compiler); + CHECK_ERROR(); + CHECK(check_sljit_emit_fmem(compiler, type, freg, mem, memw)); + + return sljit_emit_fmem_unaligned(compiler, type, freg, mem, memw); +} + +#endif /* !SLJIT_CONFIG_ARM_32 && !SLJIT_CONFIG_MIPS */ + +#if !(defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64) \ + && !(defined SLJIT_CONFIG_PPC && SLJIT_CONFIG_PPC) + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fmem_update(struct sljit_compiler *compiler, sljit_s32 type, + sljit_s32 freg, + sljit_s32 mem, sljit_sw memw) +{ + CHECK_ERROR(); + CHECK(check_sljit_emit_fmem_update(compiler, type, freg, mem, memw)); SLJIT_UNUSED_ARG(type); SLJIT_UNUSED_ARG(freg); SLJIT_UNUSED_ARG(mem); SLJIT_UNUSED_ARG(memw); - CHECK_ERROR(); - CHECK(check_sljit_emit_fmem(compiler, type, freg, mem, memw)); - return SLJIT_ERR_UNSUPPORTED; } -#endif +#endif /* !SLJIT_CONFIG_ARM_64 && !SLJIT_CONFIG_PPC */ #if !(defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86) \ && !(defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64) @@ -2316,10 +2638,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_local_base(struct sljit_compiler *c CHECK(check_sljit_get_local_base(compiler, dst, dstw, offset)); ADJUST_LOCAL_OFFSET(SLJIT_MEM1(SLJIT_SP), offset); -#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \ - || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) - compiler->skip_checks = 1; -#endif + + SLJIT_SKIP_CHECKS(compiler); + if (offset != 0) return sljit_emit_op2(compiler, SLJIT_ADD, dst, dstw, SLJIT_SP, 0, SLJIT_IMM, offset); return sljit_emit_op1(compiler, SLJIT_MOV, dst, dstw, SLJIT_SP, 0); @@ -2387,6 +2708,13 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type) return 0; } +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_cmp_info(sljit_s32 type) +{ + SLJIT_UNUSED_ARG(type); + SLJIT_UNREACHABLE(); + return 0; +} + SLJIT_API_FUNC_ATTRIBUTE void sljit_free_code(void* code, void *exec_allocator_data) { SLJIT_UNUSED_ARG(code); @@ -2426,6 +2754,13 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *comp return SLJIT_ERR_UNSUPPORTED; } +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_void(struct sljit_compiler *compiler) +{ + SLJIT_UNUSED_ARG(compiler); + SLJIT_UNREACHABLE(); + return SLJIT_ERR_UNSUPPORTED; +} + SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 src, sljit_sw srcw) { SLJIT_UNUSED_ARG(compiler); @@ -2436,9 +2771,11 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return(struct sljit_compiler *comp return SLJIT_ERR_UNSUPPORTED; } -SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_void(struct sljit_compiler *compiler) +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_to(struct sljit_compiler *compiler, sljit_s32 src, sljit_sw srcw) { SLJIT_UNUSED_ARG(compiler); + SLJIT_UNUSED_ARG(src); + SLJIT_UNUSED_ARG(srcw); SLJIT_UNREACHABLE(); return SLJIT_ERR_UNSUPPORTED; } @@ -2505,6 +2842,22 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2u(struct sljit_compiler *compil return SLJIT_ERR_UNSUPPORTED; } +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_shift_into(struct sljit_compiler *compiler, sljit_s32 op, + sljit_s32 src_dst, + sljit_s32 src1, sljit_sw src1w, + sljit_s32 src2, sljit_sw src2w) +{ + SLJIT_UNUSED_ARG(compiler); + SLJIT_UNUSED_ARG(op); + SLJIT_UNUSED_ARG(src_dst); + SLJIT_UNUSED_ARG(src1); + SLJIT_UNUSED_ARG(src1w); + SLJIT_UNUSED_ARG(src2); + SLJIT_UNUSED_ARG(src2w); + SLJIT_UNREACHABLE(); + return SLJIT_ERR_UNSUPPORTED; +} + SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_src(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 src, sljit_sw srcw) { @@ -2703,6 +3056,17 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compile return SLJIT_ERR_UNSUPPORTED; } +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem_update(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 reg, sljit_s32 mem, sljit_sw memw) +{ + SLJIT_UNUSED_ARG(compiler); + SLJIT_UNUSED_ARG(type); + SLJIT_UNUSED_ARG(reg); + SLJIT_UNUSED_ARG(mem); + SLJIT_UNUSED_ARG(memw); + SLJIT_UNREACHABLE(); + return SLJIT_ERR_UNSUPPORTED; +} + SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fmem(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 freg, sljit_s32 mem, sljit_sw memw) { SLJIT_UNUSED_ARG(compiler); @@ -2714,6 +3078,17 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fmem(struct sljit_compiler *compil return SLJIT_ERR_UNSUPPORTED; } +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fmem_update(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 freg, sljit_s32 mem, sljit_sw memw) +{ + SLJIT_UNUSED_ARG(compiler); + SLJIT_UNUSED_ARG(type); + SLJIT_UNUSED_ARG(freg); + SLJIT_UNUSED_ARG(mem); + SLJIT_UNUSED_ARG(memw); + SLJIT_UNREACHABLE(); + return SLJIT_ERR_UNSUPPORTED; +} + SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_local_base(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw offset) { SLJIT_UNUSED_ARG(compiler); diff --git a/src/3rdparty/pcre2/src/sljit/sljitLir.h b/src/3rdparty/pcre2/src/sljit/sljitLir.h index 11626581563..c6a0832ef87 100644 --- a/src/3rdparty/pcre2/src/sljit/sljitLir.h +++ b/src/3rdparty/pcre2/src/sljit/sljitLir.h @@ -36,26 +36,24 @@ Advantages: - The execution can be continued from any LIR instruction. In other words, it is possible to jump to any label from anywhere, even from - a code fragment, which is compiled later, if both compiled code - shares the same context. See sljit_emit_enter for more details - - Supports self modifying code: target of (conditional) jump and call + a code fragment, which is compiled later, as long as the compiling + context is the same. See sljit_emit_enter for more details. + - Supports self modifying code: target of any jump and call instructions and some constant values can be dynamically modified - during runtime + during runtime. See SLJIT_REWRITABLE_JUMP. - although it is not suggested to do it frequently - can be used for inline caching: save an important value once in the instruction stream - - since this feature limits the optimization possibilities, a - special flag must be passed at compile time when these - instructions are emitted - A fixed stack space can be allocated for local variables - The compiler is thread-safe - The compiler is highly configurable through preprocessor macros. You can disable unneeded features (multithreading in single threaded applications), and you can use your own system functions - (including memory allocators). See sljitConfig.h + (including memory allocators). See sljitConfig.h. Disadvantages: - - No automatic register allocation, and temporary results are - not stored on the stack. (hence the name comes) + - The compiler is more like a platform independent assembler, so + there is no built-in variable management. Registers and stack must + be managed manually (the name of the compiler refers to this). In practice: - This approach is very effective for interpreters - One of the saved registers typically points to a stack interface @@ -77,7 +75,7 @@ #include "sljitConfig.h" /* The following header file defines useful macros for fine tuning -sljit based code generators. They are listed in the beginning +SLJIT based code generators. They are listed in the beginning of sljitConfigInternal.h */ #include "sljitConfigInternal.h" @@ -90,6 +88,10 @@ of sljitConfigInternal.h */ extern "C" { #endif +/* Version numbers. */ +#define SLJIT_MAJOR_VERSION 0 +#define SLJIT_MINOR_VERSION 95 + /* --------------------------------------------------------------------- */ /* Error codes */ /* --------------------------------------------------------------------- */ @@ -97,33 +99,31 @@ extern "C" { /* Indicates no error. */ #define SLJIT_SUCCESS 0 /* After the call of sljit_generate_code(), the error code of the compiler - is set to this value to avoid future sljit calls (in debug mode at least). + is set to this value to avoid further code generation. The complier should be freed after sljit_generate_code(). */ #define SLJIT_ERR_COMPILED 1 -/* Cannot allocate non executable memory. */ +/* Cannot allocate non-executable memory. */ #define SLJIT_ERR_ALLOC_FAILED 2 /* Cannot allocate executable memory. - Only for sljit_generate_code() */ + Only sljit_generate_code() returns with this error code. */ #define SLJIT_ERR_EX_ALLOC_FAILED 3 /* Return value for SLJIT_CONFIG_UNSUPPORTED placeholder architecture. */ #define SLJIT_ERR_UNSUPPORTED 4 /* An ivalid argument is passed to any SLJIT function. */ #define SLJIT_ERR_BAD_ARGUMENT 5 -/* Dynamic code modification is not enabled. */ -#define SLJIT_ERR_DYN_CODE_MOD 6 /* --------------------------------------------------------------------- */ /* Registers */ /* --------------------------------------------------------------------- */ /* - Scratch (R) registers: registers whose may not preserve their values + Scratch (R) registers: registers which may not preserve their values across function calls. - Saved (S) registers: registers whose preserve their values across + Saved (S) registers: registers which preserve their values across function calls. - The scratch and saved register sets are overlap. The last scratch register + The scratch and saved register sets overlap. The last scratch register is the first saved register, the one before the last is the second saved register, and so on. @@ -209,7 +209,7 @@ extern "C" { /* The SLJIT_SP provides direct access to the linear stack space allocated by sljit_emit_enter. It can only be used in the following form: SLJIT_MEM1(SLJIT_SP). The immediate offset is extended by the relative stack offset automatically. - The sljit_get_local_base can be used to obtain the absolute offset. */ + The sljit_get_local_base can be used to obtain the real address of a value. */ #define SLJIT_SP (SLJIT_NUMBER_OF_REGISTERS + 1) /* Return with machine word. */ @@ -249,6 +249,10 @@ extern "C" { /* Float registers >= SLJIT_FIRST_SAVED_FLOAT_REG are saved registers. */ #define SLJIT_FIRST_SAVED_FLOAT_REG (SLJIT_FS0 - SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS + 1) +/* Return with floating point arg. */ + +#define SLJIT_RETURN_FREG SLJIT_FR0 + /* --------------------------------------------------------------------- */ /* Argument type definitions */ /* --------------------------------------------------------------------- */ @@ -386,6 +390,7 @@ struct sljit_label { struct sljit_jump { struct sljit_jump *next; sljit_uw addr; + /* Architecture dependent flags. */ sljit_uw flags; union { sljit_uw target; @@ -423,17 +428,17 @@ struct sljit_compiler { struct sljit_memory_fragment *buf; struct sljit_memory_fragment *abuf; - /* Used scratch registers. */ + /* Available scratch registers. */ sljit_s32 scratches; - /* Used saved registers. */ + /* Available saved registers. */ sljit_s32 saveds; - /* Used float scratch registers. */ + /* Available float scratch registers. */ sljit_s32 fscratches; - /* Used float saved registers. */ + /* Available float saved registers. */ sljit_s32 fsaveds; /* Local stack size. */ sljit_s32 local_size; - /* Code size. */ + /* Maximum code size. */ sljit_uw size; /* Relative offset of the executable mapping from the writable mapping. */ sljit_sw executable_offset; @@ -446,8 +451,6 @@ struct sljit_compiler { #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) sljit_s32 args_size; - sljit_s32 locals_offset; - sljit_s32 scratches_offset; #endif #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) @@ -488,8 +491,7 @@ struct sljit_compiler { sljit_uw args_size; #endif -#if (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32) - sljit_s32 delay_slot; +#if (defined SLJIT_CONFIG_RISCV && SLJIT_CONFIG_RISCV) sljit_s32 cache_arg; sljit_sw cache_argw; #endif @@ -517,7 +519,8 @@ struct sljit_compiler { #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) \ || (defined SLJIT_DEBUG && SLJIT_DEBUG) \ || (defined SLJIT_VERBOSE && SLJIT_VERBOSE) - /* Trust arguments when the API function is called. */ + /* Trust arguments when an API function is called. + Used internally for calling API functions. */ sljit_s32 skip_checks; #endif }; @@ -526,7 +529,7 @@ struct sljit_compiler { /* Main functions */ /* --------------------------------------------------------------------- */ -/* Creates an sljit compiler. The allocator_data is required by some +/* Creates an SLJIT compiler. The allocator_data is required by some custom memory managers. This pointer is passed to SLJIT_MALLOC and SLJIT_FREE macros. Most allocators (including the default one) ignores this value, and it is recommended to pass NULL @@ -540,19 +543,19 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_compiler* sljit_create_compiler(void *allo /* Frees everything except the compiled machine code. */ SLJIT_API_FUNC_ATTRIBUTE void sljit_free_compiler(struct sljit_compiler *compiler); -/* Returns the current error code. If an error is occurred, future sljit - calls which uses the same compiler argument returns early with the same +/* Returns the current error code. If an error occurres, future calls + which uses the same compiler argument returns early with the same error code. Thus there is no need for checking the error after every - call, it is enough to do it before the code is compiled. Removing + call, it is enough to do it after the code is compiled. Removing these checks increases the performance of the compiling process. */ static SLJIT_INLINE sljit_s32 sljit_get_compiler_error(struct sljit_compiler *compiler) { return compiler->error; } /* Sets the compiler error code to SLJIT_ERR_ALLOC_FAILED except if an error was detected before. After the error code is set the compiler behaves as if the allocation failure happened - during an sljit function call. This can greatly simplify error - checking, since only the compiler status needs to be checked - after the compilation. */ + during an SLJIT function call. This can greatly simplify error + checking, since it is enough to check the compiler status + after the code is compiled. */ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_compiler_memory_error(struct sljit_compiler *compiler); /* @@ -560,8 +563,8 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_compiler_memory_error(struct sljit_compi and <= 128 bytes on 64 bit architectures. The memory area is owned by the compiler, and freed by sljit_free_compiler. The returned pointer is sizeof(sljit_sw) aligned. Excellent for allocating small blocks during - the compiling, and no need to worry about freeing them. The size is - enough to contain at most 16 pointers. If the size is outside of the range, + compiling, and no need to worry about freeing them. The size is enough + to contain at most 16 pointers. If the size is outside of the range, the function will return with NULL. However, this return value does not indicate that there is no more memory (does not set the current error code of the compiler to out-of-memory status). @@ -574,8 +577,8 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_compiler_verbose(struct sljit_compiler *comp #endif /* - Create executable code from the sljit instruction stream. This is the final step - of the code generation so no more instructions can be added after this call. + Create executable code from the instruction stream. This is the final step + of the code generation so no more instructions can be emitted after this call. */ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compiler); @@ -606,13 +609,14 @@ static SLJIT_INLINE sljit_sw sljit_get_executable_offset(struct sljit_compiler * static SLJIT_INLINE sljit_uw sljit_get_generated_code_size(struct sljit_compiler *compiler) { return compiler->executable_size; } /* Returns with non-zero if the feature or limitation type passed as its - argument is present on the current CPU. + argument is present on the current CPU. The return value is one, if a + feature is fully supported, and it is two, if partially supported. Some features (e.g. floating point operations) require hardware (CPU) support while others (e.g. move with update) are emulated if not available. - However even if a feature is emulated, specialized code paths can be faster - than the emulation. Some limitations are emulated as well so their general - case is supported but it has extra performance costs. */ + However, even when a feature is emulated, specialized code paths may be + faster than the emulation. Some limitations are emulated as well so their + general case is supported but it has extra performance costs. */ /* [Not emulated] Floating-point support is available. */ #define SLJIT_HAS_FPU 0 @@ -622,10 +626,14 @@ static SLJIT_INLINE sljit_uw sljit_get_generated_code_size(struct sljit_compiler #define SLJIT_HAS_ZERO_REGISTER 2 /* [Emulated] Count leading zero is supported. */ #define SLJIT_HAS_CLZ 3 +/* [Emulated] Count trailing zero is supported. */ +#define SLJIT_HAS_CTZ 4 +/* [Emulated] Rotate left/right is supported. */ +#define SLJIT_HAS_ROT 5 /* [Emulated] Conditional move is supported. */ -#define SLJIT_HAS_CMOV 4 -/* [Emulated] Conditional move is supported. */ -#define SLJIT_HAS_PREFETCH 5 +#define SLJIT_HAS_CMOV 6 +/* [Emulated] Prefetch instruction is available (emulated as a nop). */ +#define SLJIT_HAS_PREFETCH 7 #if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86) /* [Not emulated] SSE2 support is available on x86. */ @@ -634,8 +642,23 @@ static SLJIT_INLINE sljit_uw sljit_get_generated_code_size(struct sljit_compiler SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type); -/* Instruction generation. Returns with any error code. If there is no - error, they return with SLJIT_SUCCESS. */ +/* If type is between SLJIT_ORDERED_EQUAL and SLJIT_ORDERED_LESS_EQUAL, + sljit_cmp_info returns one, if the cpu supports the passed floating + point comparison type. + + If type is SLJIT_UNORDERED or SLJIT_ORDERED, sljit_cmp_info returns + one, if the cpu supports checking the unordered comparison result + regardless of the comparison type passed to the comparison instruction. + The returned value is always one, if there is at least one type between + SLJIT_ORDERED_EQUAL and SLJIT_ORDERED_LESS_EQUAL where sljit_cmp_info + returns with a zero value. + + Otherwise it returns zero. */ +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_cmp_info(sljit_s32 type); + +/* The following functions generate machine code. If there is no + error, they return with SLJIT_SUCCESS, otherwise they return + with an error code. */ /* The executable code is a function from the viewpoint of the C @@ -643,30 +666,29 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type) Binary Interface) of the platform, which specify the purpose of machine registers and stack handling among other things. The sljit_emit_enter function emits the necessary instructions for - setting up a new context for the executable code and moves function - arguments to the saved registers. Furthermore the options argument + setting up a new context for the executable code. This is often + called as function prologue. Furthermore the options argument can be used to pass configuration options to the compiler. The available options are listed before sljit_emit_enter. - The function argument list is the combination of SLJIT_ARGx - (SLJIT_DEF_ARG1) macros. Currently maximum 4 arguments are - supported. The first integer argument is loaded into SLJIT_S0, - the second one is loaded into SLJIT_S1, and so on. Similarly, - the first floating point argument is loaded into SLJIT_FR0, - the second one is loaded into SLJIT_FR1, and so on. Furthermore - the register set used by the function must be declared as well. - The number of scratch and saved registers used by the function - must be passed to sljit_emit_enter. Only R registers between R0 + The function argument list is specified by the SLJIT_ARGSx + (SLJIT_ARGS0 .. SLJIT_ARGS4) macros. Currently maximum four + arguments are supported. See the description of SLJIT_ARGSx + macros about argument passing. Furthermore the register set + used by the function must be declared as well. The number of + scratch and saved registers available to the function must + be passed to sljit_emit_enter. Only R registers between R0 and "scratches" argument can be used later. E.g. if "scratches" - is set to 2, the scratch register set will be limited to SLJIT_R0 - and SLJIT_R1. The S registers and the floating point registers - ("fscratches" and "fsaveds") are specified in a similar manner. - The sljit_emit_enter is also capable of allocating a stack space - for local variables. The "local_size" argument contains the size - in bytes of this local area and its staring address is stored - in SLJIT_SP. The memory area between SLJIT_SP (inclusive) and - SLJIT_SP + local_size (exclusive) can be modified freely until - the function returns. The stack space is not initialized. + is set to two, the scratch register set will be limited to + SLJIT_R0 and SLJIT_R1. The S registers and the floating point + registers ("fscratches" and "fsaveds") are specified in a + similar manner. The sljit_emit_enter is also capable of + allocating a stack space for local data. The "local_size" + argument contains the size in bytes of this local area, and + it can be accessed using SLJIT_MEM1(SLJIT_SP). The memory + area between SLJIT_SP (inclusive) and SLJIT_SP + local_size + (exclusive) can be modified freely until the function returns. + The stack space is not initialized to zero. Note: the following conditions must met: 0 <= scratches <= SLJIT_NUMBER_OF_REGISTERS @@ -683,9 +705,20 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type) overwrites the previous context. */ -/* The compiled function uses cdecl calling - * convention instead of SLJIT_FUNC. */ -#define SLJIT_ENTER_CDECL 0x00000001 +/* Saved registers between SLJIT_S0 and SLJIT_S(n - 1) (inclusive) + are not saved / restored on function enter / return. Instead, + these registers can be used to pass / return data (such as + global / local context pointers) across function calls. The + value of n must be between 1 and 3. This option is only + supported by SLJIT_ENTER_REG_ARG calling convention. */ +#define SLJIT_ENTER_KEEP(n) (n) + +/* The compiled function uses an SLJIT specific register argument + calling convention. This is a lightweight function call type where + both the caller and the called functions must be compiled by + SLJIT. The type argument of the call must be SLJIT_CALL_REG_ARG + and all arguments must be stored in scratch registers. */ +#define SLJIT_ENTER_REG_ARG 0x00000004 /* The local_size must be >= 0 and <= SLJIT_MAX_LOCAL_SIZE. */ #define SLJIT_MAX_LOCAL_SIZE 65536 @@ -694,12 +727,15 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds, sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size); -/* The machine code has a context (which contains the local stack space size, - number of used registers, etc.) which initialized by sljit_emit_enter. Several - functions (such as sljit_emit_return) requres this context to be able to generate - the appropriate code. However, some code fragments (like inline cache) may have - no normal entry point so their context is unknown for the compiler. Their context - can be provided to the compiler by the sljit_set_context function. +/* The SLJIT compiler has a current context (which contains the local + stack space size, number of used registers, etc.) which is initialized + by sljit_emit_enter. Several functions (such as sljit_emit_return) + requires this context to be able to generate the appropriate code. + However, some code fragments (compiled separately) may have no + normal entry point so their context is unknown for the compiler. + + The sljit_set_context and sljit_emit_enter have the same arguments, + but sljit_set_context does not generate any machine code. Note: every call of sljit_emit_enter and sljit_set_context overwrites the previous context. */ @@ -708,16 +744,29 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *comp sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds, sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size); -/* Return from machine code. The sljit_emit_return_void function does not return with - any value. The sljit_emit_return function returns with a single value which stores - the result of a data move instruction. The instruction is specified by the op - argument, and must be between SLJIT_MOV and SLJIT_MOV_P (see sljit_emit_op1). */ +/* Return to the caller function. The sljit_emit_return_void function + does not return with any value. The sljit_emit_return function returns + with a single value loaded from its source operand. The load operation + can be between SLJIT_MOV and SLJIT_MOV_P (see sljit_emit_op1) and + SLJIT_MOV_F32/SLJIT_MOV_F64 (see sljit_emit_fop1) depending on the + return value specified by sljit_emit_enter/sljit_set_context. */ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_void(struct sljit_compiler *compiler); SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 src, sljit_sw srcw); +/* Restores the saved registers and free the stack area, then the execution + continues from the address specified by the source operand. This + operation is similar to sljit_emit_return, but it ignores the return + address. The code where the exection continues should use the same context + as the caller function (see sljit_set_context). A word (pointer) value + can be passed in the SLJIT_RETURN_REG register. This function can be used + to jump to exception handlers. */ + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_to(struct sljit_compiler *compiler, + sljit_s32 src, sljit_sw srcw); + /* Generating entry and exit points for fast call functions (see SLJIT_FAST_CALL). Both sljit_emit_fast_enter and SLJIT_FAST_RETURN operations preserve the values of all registers and stack frame. The return address is stored in the @@ -726,9 +775,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return(struct sljit_compiler *comp Fast calls are cheap operations (usually only a single call instruction is emitted) but they do not preserve any registers. However the callee function - can freely use / update any registers and stack values which can be + can freely use / update any registers and the local area which can be efficiently exploited by various optimizations. Registers can be saved - manually by the callee function if needed. + and restored manually if needed. Although returning to different address by SLJIT_FAST_RETURN is possible, this address usually cannot be predicted by the return address predictor of @@ -743,16 +792,16 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_enter(struct sljit_compiler * /* Source and destination operands for arithmetical instructions imm - a simple immediate value (cannot be used as a destination) - reg - any of the registers (immediate argument must be 0) - [imm] - absolute immediate memory address + reg - any of the available registers (immediate argument must be 0) + [imm] - absolute memory address [reg+imm] - indirect memory address [reg+(reg<> 1) >> (src2 ^ value_mask)) + SLJIT_MSHL or SLJIT_MSHL32: + src2 &= value_mask + perform the SLJIT_SHL or SLJIT_SHL32 operation + SLJIT_LSHR or SLJIT_LSHR32: + src_dst >>= src2 + src_dst |= ((src1 << 1) << (src2 ^ value_mask)) + SLJIT_MLSHR or SLJIT_MLSHR32: + src2 &= value_mask + perform the SLJIT_LSHR or SLJIT_LSHR32 operation + + op can be combined (or'ed) with SLJIT_SHIFT_INTO_NON_ZERO + + src_dst must be a register which content is updated after + the operation is completed + src1 / src1w contains the bits which shifted into src_dst + src2 / src2w contains the shift amount + + Note: a rotate operation can be performed if src_dst and + src1 are set to the same register + + Flags: - (may destroy flags) */ + +/* The src2 contains a non-zero value. Improves the generated + code on certain architectures, which provides a small + performance improvement. */ +#define SLJIT_SHIFT_INTO_NON_ZERO 0x200 + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_shift_into(struct sljit_compiler *compiler, sljit_s32 op, + sljit_s32 src_dst, + sljit_s32 src1, sljit_sw src1w, + sljit_s32 src2, sljit_sw src2w); + /* Starting index of opcodes for sljit_emit_op2. */ #define SLJIT_OP_SRC_BASE 128 @@ -1116,8 +1253,8 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_src(struct sljit_compiler *comp #define SLJIT_MOV_F64 (SLJIT_FOP1_BASE + 0) #define SLJIT_MOV_F32 (SLJIT_MOV_F64 | SLJIT_32) /* Convert opcodes: CONV[DST_TYPE].FROM[SRC_TYPE] - SRC/DST TYPE can be: D - double, S - single, W - signed word, I - signed int - Rounding mode when the destination is W or I: round towards zero. */ + SRC/DST TYPE can be: F64, F32, S32, SW + Rounding mode when the destination is SW or S32: round towards zero. */ /* Flags: - (may destroy flags) */ #define SLJIT_CONV_F64_FROM_F32 (SLJIT_FOP1_BASE + 1) #define SLJIT_CONV_F32_FROM_F64 (SLJIT_CONV_F64_FROM_F32 | SLJIT_32) @@ -1133,7 +1270,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_src(struct sljit_compiler *comp /* Flags: - (may destroy flags) */ #define SLJIT_CONV_F64_FROM_S32 (SLJIT_FOP1_BASE + 5) #define SLJIT_CONV_F32_FROM_S32 (SLJIT_CONV_F64_FROM_S32 | SLJIT_32) -/* Note: dst is the left and src is the right operand for SLJIT_CMPD. +/* Note: dst is the left and src is the right operand for SLJIT_CMP_F32/64. Flags: EQUAL_F | LESS_F | GREATER_EQUAL_F | GREATER_F | LESS_EQUAL_F */ #define SLJIT_CMP_F64 (SLJIT_FOP1_BASE + 6) #define SLJIT_CMP_F32 (SLJIT_CMP_F64 | SLJIT_32) @@ -1202,46 +1339,75 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compi #define SLJIT_SET_OVERFLOW SLJIT_SET(SLJIT_OVERFLOW) #define SLJIT_NOT_OVERFLOW 11 -/* Unlike other flags, sljit_emit_jump may destroy this flag. */ +/* Unlike other flags, sljit_emit_jump may destroy the carry flag. */ #define SLJIT_CARRY 12 #define SLJIT_SET_CARRY SLJIT_SET(SLJIT_CARRY) #define SLJIT_NOT_CARRY 13 -/* Floating point comparison types. */ -#define SLJIT_EQUAL_F64 14 -#define SLJIT_EQUAL_F32 (SLJIT_EQUAL_F64 | SLJIT_32) -#define SLJIT_SET_EQUAL_F SLJIT_SET(SLJIT_EQUAL_F64) -#define SLJIT_NOT_EQUAL_F64 15 -#define SLJIT_NOT_EQUAL_F32 (SLJIT_NOT_EQUAL_F64 | SLJIT_32) -#define SLJIT_SET_NOT_EQUAL_F SLJIT_SET(SLJIT_NOT_EQUAL_F64) -#define SLJIT_LESS_F64 16 -#define SLJIT_LESS_F32 (SLJIT_LESS_F64 | SLJIT_32) -#define SLJIT_SET_LESS_F SLJIT_SET(SLJIT_LESS_F64) -#define SLJIT_GREATER_EQUAL_F64 17 -#define SLJIT_GREATER_EQUAL_F32 (SLJIT_GREATER_EQUAL_F64 | SLJIT_32) -#define SLJIT_SET_GREATER_EQUAL_F SLJIT_SET(SLJIT_GREATER_EQUAL_F64) -#define SLJIT_GREATER_F64 18 -#define SLJIT_GREATER_F32 (SLJIT_GREATER_F64 | SLJIT_32) -#define SLJIT_SET_GREATER_F SLJIT_SET(SLJIT_GREATER_F64) -#define SLJIT_LESS_EQUAL_F64 19 -#define SLJIT_LESS_EQUAL_F32 (SLJIT_LESS_EQUAL_F64 | SLJIT_32) -#define SLJIT_SET_LESS_EQUAL_F SLJIT_SET(SLJIT_LESS_EQUAL_F64) -#define SLJIT_UNORDERED_F64 20 -#define SLJIT_UNORDERED_F32 (SLJIT_UNORDERED_F64 | SLJIT_32) -#define SLJIT_SET_UNORDERED_F SLJIT_SET(SLJIT_UNORDERED_F64) -#define SLJIT_ORDERED_F64 21 -#define SLJIT_ORDERED_F32 (SLJIT_ORDERED_F64 | SLJIT_32) -#define SLJIT_SET_ORDERED_F SLJIT_SET(SLJIT_ORDERED_F64) +/* Basic floating point comparison types. + + Note: when the comparison result is unordered, their behaviour is unspecified. */ + +#define SLJIT_F_EQUAL 14 +#define SLJIT_SET_F_EQUAL SLJIT_SET(SLJIT_F_EQUAL) +#define SLJIT_F_NOT_EQUAL 15 +#define SLJIT_SET_F_NOT_EQUAL SLJIT_SET(SLJIT_F_NOT_EQUAL) +#define SLJIT_F_LESS 16 +#define SLJIT_SET_F_LESS SLJIT_SET(SLJIT_F_LESS) +#define SLJIT_F_GREATER_EQUAL 17 +#define SLJIT_SET_F_GREATER_EQUAL SLJIT_SET(SLJIT_F_GREATER_EQUAL) +#define SLJIT_F_GREATER 18 +#define SLJIT_SET_F_GREATER SLJIT_SET(SLJIT_F_GREATER) +#define SLJIT_F_LESS_EQUAL 19 +#define SLJIT_SET_F_LESS_EQUAL SLJIT_SET(SLJIT_F_LESS_EQUAL) + +/* Jumps when either argument contains a NaN value. */ +#define SLJIT_UNORDERED 20 +#define SLJIT_SET_UNORDERED SLJIT_SET(SLJIT_UNORDERED) +/* Jumps when neither argument contains a NaN value. */ +#define SLJIT_ORDERED 21 +#define SLJIT_SET_ORDERED SLJIT_SET(SLJIT_ORDERED) + +/* Ordered / unordered floating point comparison types. + + Note: each comparison type has an ordered and unordered form. Some + architectures supports only either of them (see: sljit_cmp_info). */ + +#define SLJIT_ORDERED_EQUAL 22 +#define SLJIT_SET_ORDERED_EQUAL SLJIT_SET(SLJIT_ORDERED_EQUAL) +#define SLJIT_UNORDERED_OR_NOT_EQUAL 23 +#define SLJIT_SET_UNORDERED_OR_NOT_EQUAL SLJIT_SET(SLJIT_UNORDERED_OR_NOT_EQUAL) +#define SLJIT_ORDERED_LESS 24 +#define SLJIT_SET_ORDERED_LESS SLJIT_SET(SLJIT_ORDERED_LESS) +#define SLJIT_UNORDERED_OR_GREATER_EQUAL 25 +#define SLJIT_SET_UNORDERED_OR_GREATER_EQUAL SLJIT_SET(SLJIT_UNORDERED_OR_GREATER_EQUAL) +#define SLJIT_ORDERED_GREATER 26 +#define SLJIT_SET_ORDERED_GREATER SLJIT_SET(SLJIT_ORDERED_GREATER) +#define SLJIT_UNORDERED_OR_LESS_EQUAL 27 +#define SLJIT_SET_UNORDERED_OR_LESS_EQUAL SLJIT_SET(SLJIT_UNORDERED_OR_LESS_EQUAL) + +#define SLJIT_UNORDERED_OR_EQUAL 28 +#define SLJIT_SET_UNORDERED_OR_EQUAL SLJIT_SET(SLJIT_UNORDERED_OR_EQUAL) +#define SLJIT_ORDERED_NOT_EQUAL 29 +#define SLJIT_SET_ORDERED_NOT_EQUAL SLJIT_SET(SLJIT_ORDERED_NOT_EQUAL) +#define SLJIT_UNORDERED_OR_LESS 30 +#define SLJIT_SET_UNORDERED_OR_LESS SLJIT_SET(SLJIT_UNORDERED_OR_LESS) +#define SLJIT_ORDERED_GREATER_EQUAL 31 +#define SLJIT_SET_ORDERED_GREATER_EQUAL SLJIT_SET(SLJIT_ORDERED_GREATER_EQUAL) +#define SLJIT_UNORDERED_OR_GREATER 32 +#define SLJIT_SET_UNORDERED_OR_GREATER SLJIT_SET(SLJIT_UNORDERED_OR_GREATER) +#define SLJIT_ORDERED_LESS_EQUAL 33 +#define SLJIT_SET_ORDERED_LESS_EQUAL SLJIT_SET(SLJIT_ORDERED_LESS_EQUAL) /* Unconditional jump types. */ -#define SLJIT_JUMP 22 - /* Fast calling method. See sljit_emit_fast_enter / SLJIT_FAST_RETURN. */ -#define SLJIT_FAST_CALL 23 - /* Called function must be declared with the SLJIT_FUNC attribute. */ -#define SLJIT_CALL 24 - /* Called function must be declared with cdecl attribute. - This is the default attribute for C functions. */ -#define SLJIT_CALL_CDECL 25 +#define SLJIT_JUMP 34 +/* Fast calling method. See sljit_emit_fast_enter / SLJIT_FAST_RETURN. */ +#define SLJIT_FAST_CALL 35 +/* Default C calling convention. */ +#define SLJIT_CALL 36 +/* Called function must be compiled by SLJIT. + See SLJIT_ENTER_REG_ARG option. */ +#define SLJIT_CALL_REG_ARG 37 /* The target can be changed during runtime (see: sljit_set_jump_addr). */ #define SLJIT_REWRITABLE_JUMP 0x1000 @@ -1249,11 +1415,8 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compi the called function returns to the caller of the current function. The stack usage is reduced before the call, but it is not necessarily reduced to zero. In the latter case the compiler needs to allocate space for some - arguments and the return register must be kept as well. - - This feature is highly experimental and not supported on SPARC platform - at the moment. */ -#define SLJIT_CALL_RETURN 0x2000 + arguments and the return address must be stored on the stack as well. */ +#define SLJIT_CALL_RETURN 0x2000 /* Emit a jump instruction. The destination is not set, only the type of the jump. type must be between SLJIT_EQUAL and SLJIT_FAST_CALL @@ -1263,18 +1426,18 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compi SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compiler *compiler, sljit_s32 type); /* Emit a C compiler (ABI) compatible function call. - type must be SLJIT_CALL or SLJIT_CALL_CDECL - type can be combined (or'ed) with SLJIT_REWRITABLE_JUMP and SLJIT_CALL_RETURN - arg_types is the combination of SLJIT_RET / SLJIT_ARGx (SLJIT_DEF_RET / SLJIT_DEF_ARGx) macros + type must be SLJIT_CALL or SLJIT_CALL_REG_ARG + type can be combined (or'ed) with SLJIT_REWRITABLE_JUMP and/or SLJIT_CALL_RETURN + arg_types can be specified by SLJIT_ARGSx (SLJIT_ARG_RETURN / SLJIT_ARG_VALUE) macros Flags: destroy all flags. */ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 arg_types); /* Basic arithmetic comparison. In most architectures it is implemented as - an compare operation followed by a sljit_emit_jump. However some - architectures (i.e: ARM64 or MIPS) may employ special optimizations here. - It is suggested to use this comparison form when appropriate. - type must be between SLJIT_EQUAL and SLJIT_I_SIG_LESS_EQUAL + a compare operation followed by a sljit_emit_jump. However some + architectures (i.e: ARM64 or MIPS) may employ special optimizations + here. It is suggested to use this comparison form when appropriate. + type must be between SLJIT_EQUAL and SLJIT_SIG_LESS_EQUAL type can be combined (or'ed) with SLJIT_REWRITABLE_JUMP Flags: may destroy flags. */ @@ -1283,15 +1446,14 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_cmp(struct sljit_compiler sljit_s32 src2, sljit_sw src2w); /* Basic floating point comparison. In most architectures it is implemented as - an SLJIT_FCMP operation (setting appropriate flags) followed by a + a SLJIT_CMP_F32/64 operation (setting appropriate flags) followed by a sljit_emit_jump. However some architectures (i.e: MIPS) may employ special optimizations here. It is suggested to use this comparison form when appropriate. - type must be between SLJIT_EQUAL_F64 and SLJIT_ORDERED_F32 + type must be between SLJIT_F_EQUAL and SLJIT_ORDERED_LESS_EQUAL type can be combined (or'ed) with SLJIT_REWRITABLE_JUMP Flags: destroy flags. - Note: if either operand is NaN, the behaviour is undefined for - types up to SLJIT_S_LESS_EQUAL. */ + Note: when an operand is NaN the behaviour depends on the comparison type. */ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_fcmp(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 src1, sljit_sw src1w, sljit_s32 src2, sljit_sw src2w); @@ -1312,22 +1474,22 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compi /* Emit a C compiler (ABI) compatible function call. Direct form: set src to SLJIT_IMM() and srcw to the address Indirect form: any other valid addressing mode - type must be SLJIT_CALL or SLJIT_CALL_CDECL + type must be SLJIT_CALL or SLJIT_CALL_REG_ARG type can be combined (or'ed) with SLJIT_CALL_RETURN - arg_types is the combination of SLJIT_RET / SLJIT_ARGx (SLJIT_DEF_RET / SLJIT_DEF_ARGx) macros + arg_types can be specified by SLJIT_ARGSx (SLJIT_ARG_RETURN / SLJIT_ARG_VALUE) macros Flags: destroy all flags. */ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 arg_types, sljit_s32 src, sljit_sw srcw); -/* Perform the operation using the conditional flags as the second argument. - Type must always be between SLJIT_EQUAL and SLJIT_ORDERED_F64. The value - represented by the type is 1, if the condition represented by the type - is fulfilled, and 0 otherwise. +/* Perform an operation using the conditional flags as the second argument. + Type must always be between SLJIT_EQUAL and SLJIT_ORDERED_LESS_EQUAL. + The value represented by the type is 1, if the condition represented + by the type is fulfilled, and 0 otherwise. - If op == SLJIT_MOV, SLJIT_MOV32: + When op is SLJIT_MOV or SLJIT_MOV32: Set dst to the value represented by the type (0 or 1). Flags: - (does not modify flags) - If op == SLJIT_OR, op == SLJIT_AND, op == SLJIT_XOR + When op is SLJIT_AND, SLJIT_AND32, SLJIT_OR, SLJIT_OR32, SLJIT_XOR, or SLJIT_XOR32 Performs the binary operation using dst as the first, and the value represented by type as the second argument. Result is written into dst. Flags: Z (may destroy flags) */ @@ -1339,69 +1501,139 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *co if the condition is satisfied. Unlike other arithmetic operations this instruction does not support memory access. - type must be between SLJIT_EQUAL and SLJIT_ORDERED_F64 - dst_reg must be a valid register and it can be combined - with SLJIT_32 to perform a 32 bit arithmetic operation - src must be register or immediate (SLJIT_IMM) + type must be between SLJIT_EQUAL and SLJIT_ORDERED_LESS_EQUAL + type can be combined (or'ed) with SLJIT_32 + dst_reg must be a valid register + src must be a valid register or immediate (SLJIT_IMM) Flags: - (does not modify flags) */ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_cmov(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 dst_reg, sljit_s32 src, sljit_sw srcw); +/* The following flags are used by sljit_emit_mem(), sljit_emit_mem_update(), + sljit_emit_fmem(), and sljit_emit_fmem_update(). */ + +/* Memory load operation. This is the default. */ +#define SLJIT_MEM_LOAD 0x000000 +/* Memory store operation. */ +#define SLJIT_MEM_STORE 0x000200 + /* The following flags are used by sljit_emit_mem() and sljit_emit_fmem(). */ +/* Load or stora data from an unaligned (byte aligned) address. */ +#define SLJIT_MEM_UNALIGNED 0x000400 +/* Load or stora data from a 16 bit aligned address. */ +#define SLJIT_MEM_UNALIGNED_16 0x000800 +/* Load or stora data from a 32 bit aligned address. */ +#define SLJIT_MEM_UNALIGNED_32 0x001000 + +/* The following flags are used by sljit_emit_mem_update(), + and sljit_emit_fmem_update(). */ + +/* Base register is updated before the memory access (default). */ +#define SLJIT_MEM_PRE 0x000000 +/* Base register is updated after the memory access. */ +#define SLJIT_MEM_POST 0x000400 + /* When SLJIT_MEM_SUPP is passed, no instructions are emitted. Instead the function returns with SLJIT_SUCCESS if the instruction form is supported and SLJIT_ERR_UNSUPPORTED otherwise. This flag allows runtime checking of available instruction forms. */ -#define SLJIT_MEM_SUPP 0x0200 -/* Memory load operation. This is the default. */ -#define SLJIT_MEM_LOAD 0x0000 -/* Memory store operation. */ -#define SLJIT_MEM_STORE 0x0400 -/* Base register is updated before the memory access. */ -#define SLJIT_MEM_PRE 0x0800 -/* Base register is updated after the memory access. */ -#define SLJIT_MEM_POST 0x1000 +#define SLJIT_MEM_SUPP 0x000800 -/* Emit a single memory load or store with update instruction. When the - requested instruction form is not supported by the CPU, it returns - with SLJIT_ERR_UNSUPPORTED instead of emulating the instruction. This - allows specializing tight loops based on the supported instruction - forms (see SLJIT_MEM_SUPP flag). +/* The sljit_emit_mem emits instructions for various memory operations: + + When SLJIT_MEM_UNALIGNED / SLJIT_MEM_UNALIGNED_16 / + SLJIT_MEM_UNALIGNED_32 is set in type argument: + Emit instructions for unaligned memory loads or stores. When + SLJIT_UNALIGNED is not defined, the only way to access unaligned + memory data is using sljit_emit_mem. Otherwise all operations (e.g. + sljit_emit_op1/2, or sljit_emit_fop1/2) supports unaligned access. + In general, the performance of unaligned memory accesses are often + lower than aligned and should be avoided. + + When a pair of registers is passed in reg argument: + Emit instructions for moving data between a register pair and + memory. The register pair can be specified by the SLJIT_REG_PAIR + macro. The first register is loaded from or stored into the + location specified by the mem/memw arguments, and the end address + of this operation is the starting address of the data transfer + between the second register and memory. The type argument must + be SLJIT_MOV. The SLJIT_MEM_UNALIGNED* options are allowed for + this operation. type must be between SLJIT_MOV and SLJIT_MOV_P and can be - combined with SLJIT_MEM_* flags. Either SLJIT_MEM_PRE - or SLJIT_MEM_POST must be specified. - reg is the source or destination register, and must be - different from the base register of the mem operand - mem must be a SLJIT_MEM1() or SLJIT_MEM2() operand + combined (or'ed) with SLJIT_MEM_* flags + reg is a register or register pair, which is the source or + destination of the operation + mem must be a memory operand Flags: - (does not modify flags) */ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 reg, sljit_s32 mem, sljit_sw memw); +/* Emit a single memory load or store with update instruction. + When the requested instruction form is not supported by the CPU, + it returns with SLJIT_ERR_UNSUPPORTED instead of emulating the + instruction. This allows specializing tight loops based on + the supported instruction forms (see SLJIT_MEM_SUPP flag). + Absolute address (SLJIT_MEM0) forms are never supported + and the base (first) register specified by the mem argument + must not be SLJIT_SP and must also be different from the + register specified by the reg argument. + + type must be between SLJIT_MOV and SLJIT_MOV_P and can be + combined (or'ed) with SLJIT_MEM_* flags + reg is the source or destination register of the operation + mem must be a memory operand + + Flags: - (does not modify flags) */ + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem_update(struct sljit_compiler *compiler, sljit_s32 type, + sljit_s32 reg, + sljit_s32 mem, sljit_sw memw); + /* Same as sljit_emit_mem except the followings: + Loading or storing a pair of registers is not supported. + type must be SLJIT_MOV_F64 or SLJIT_MOV_F32 and can be - combined with SLJIT_MEM_* flags. Either SLJIT_MEM_PRE - or SLJIT_MEM_POST must be specified. - freg is the source or destination floating point register */ + combined (or'ed) with SLJIT_MEM_* flags. + freg is the source or destination floating point register + of the operation + mem must be a memory operand + + Flags: - (does not modify flags) */ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fmem(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 freg, sljit_s32 mem, sljit_sw memw); -/* Copies the base address of SLJIT_SP + offset to dst. The offset can be - anything to negate the effect of relative addressing. For example if an - array of sljit_sw values is stored on the stack from offset 0x40, and R0 - contains the offset of an array item plus 0x120, this item can be - overwritten by two SLJIT instructions: +/* Same as sljit_emit_mem_update except the followings: + + type must be SLJIT_MOV_F64 or SLJIT_MOV_F32 and can be + combined (or'ed) with SLJIT_MEM_* flags + freg is the source or destination floating point register + of the operation + mem must be a memory operand + + Flags: - (does not modify flags) */ + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fmem_update(struct sljit_compiler *compiler, sljit_s32 type, + sljit_s32 freg, + sljit_s32 mem, sljit_sw memw); + +/* Copies the base address of SLJIT_SP + offset to dst. The offset can + represent the starting address of a value in the local data (stack). + The offset is not limited by the local data limits, it can be any value. + For example if an array of bytes are stored on the stack from + offset 0x40, and R0 contains the offset of an array item plus 0x120, + this item can be changed by two SLJIT instructions: sljit_get_local_base(compiler, SLJIT_R1, 0, 0x40 - 0x120); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM2(SLJIT_R1, SLJIT_R0), 0, SLJIT_IMM, 0x5); + sljit_emit_op1(compiler, SLJIT_MOV_U8, SLJIT_MEM2(SLJIT_R1, SLJIT_R0), 0, SLJIT_IMM, 0x5); Flags: - (may destroy flags) */ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_local_base(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw offset); @@ -1429,16 +1661,68 @@ static SLJIT_INLINE sljit_uw sljit_get_const_addr(struct sljit_const *const_) { SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_target, sljit_sw executable_offset); SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant, sljit_sw executable_offset); +/* --------------------------------------------------------------------- */ +/* CPU specific functions */ +/* --------------------------------------------------------------------- */ + +/* The following function is a helper function for sljit_emit_op_custom. + It returns with the real machine register index ( >=0 ) of any SLJIT_R, + SLJIT_S and SLJIT_SP registers. + + Note: it returns with -1 for virtual registers (only on x86-32). */ + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 reg); + +/* The following function is a helper function for sljit_emit_op_custom. + It returns with the real machine register ( >= 0 ) index of any SLJIT_FR, + and SLJIT_FS register. + + Note: the index is always an even number on ARM-32, MIPS. */ + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_float_register_index(sljit_s32 reg); + +/* Any instruction can be inserted into the instruction stream by + sljit_emit_op_custom. It has a similar purpose as inline assembly. + The size parameter must match to the instruction size of the target + architecture: + + x86: 0 < size <= 15. The instruction argument can be byte aligned. + Thumb2: if size == 2, the instruction argument must be 2 byte aligned. + if size == 4, the instruction argument must be 4 byte aligned. + Otherwise: size must be 4 and instruction argument must be 4 byte aligned. */ + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *compiler, + void *instruction, sljit_u32 size); + +/* Flags were set by a 32 bit operation. */ +#define SLJIT_CURRENT_FLAGS_32 SLJIT_32 + +/* Flags were set by an ADD or ADDC operations. */ +#define SLJIT_CURRENT_FLAGS_ADD 0x01 +/* Flags were set by a SUB, SUBC, or NEG operation. */ +#define SLJIT_CURRENT_FLAGS_SUB 0x02 + +/* Flags were set by sljit_emit_op2u with SLJIT_SUB opcode. + Must be combined with SLJIT_CURRENT_FLAGS_SUB. */ +#define SLJIT_CURRENT_FLAGS_COMPARE 0x04 + +/* Define the currently available CPU status flags. It is usually used after + an sljit_emit_label or sljit_emit_op_custom operations to define which CPU + status flags are available. + + The current_flags must be a valid combination of SLJIT_SET_* and + SLJIT_CURRENT_FLAGS_* constants. */ + +SLJIT_API_FUNC_ATTRIBUTE void sljit_set_current_flags(struct sljit_compiler *compiler, + sljit_s32 current_flags); + /* --------------------------------------------------------------------- */ /* Miscellaneous utility functions */ /* --------------------------------------------------------------------- */ -#define SLJIT_MAJOR_VERSION 0 -#define SLJIT_MINOR_VERSION 94 - /* Get the human readable name of the platform. Can be useful on platforms - like ARM, where ARM and Thumb2 functions can be mixed, and - it is useful to know the type of the code generator. */ + like ARM, where ARM and Thumb2 functions can be mixed, and it is useful + to know the type of the code generator. */ SLJIT_API_FUNC_ATTRIBUTE const char* sljit_get_platform_name(void); /* Portable helper function to get an offset of a member. */ @@ -1532,60 +1816,6 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_function_context(void** func_ptr, struct SLJIT_API_FUNC_ATTRIBUTE void sljit_free_unused_memory_exec(void); #endif -/* --------------------------------------------------------------------- */ -/* CPU specific functions */ -/* --------------------------------------------------------------------- */ - -/* The following function is a helper function for sljit_emit_op_custom. - It returns with the real machine register index ( >=0 ) of any SLJIT_R, - SLJIT_S and SLJIT_SP registers. - - Note: it returns with -1 for virtual registers (only on x86-32). */ - -SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 reg); - -/* The following function is a helper function for sljit_emit_op_custom. - It returns with the real machine register index of any SLJIT_FLOAT register. - - Note: the index is always an even number on ARM (except ARM-64), MIPS, and SPARC. */ - -SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_float_register_index(sljit_s32 reg); - -/* Any instruction can be inserted into the instruction stream by - sljit_emit_op_custom. It has a similar purpose as inline assembly. - The size parameter must match to the instruction size of the target - architecture: - - x86: 0 < size <= 15. The instruction argument can be byte aligned. - Thumb2: if size == 2, the instruction argument must be 2 byte aligned. - if size == 4, the instruction argument must be 4 byte aligned. - Otherwise: size must be 4 and instruction argument must be 4 byte aligned. */ - -SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *compiler, - void *instruction, sljit_u32 size); - -/* Flags were set by a 32 bit operation. */ -#define SLJIT_CURRENT_FLAGS_32 SLJIT_32 - -/* Flags were set by an ADD or ADDC operations. */ -#define SLJIT_CURRENT_FLAGS_ADD 0x01 -/* Flags were set by a SUB, SUBC, or NEG operation. */ -#define SLJIT_CURRENT_FLAGS_SUB 0x02 - -/* Flags were set by sljit_emit_op2u with SLJIT_SUB opcode. - Must be combined with SLJIT_CURRENT_FLAGS_SUB. */ -#define SLJIT_CURRENT_FLAGS_COMPARE 0x04 - -/* Define the currently available CPU status flags. It is usually used after - an sljit_emit_label or sljit_emit_op_custom operations to define which CPU - status flags are available. - - The current_flags must be a valid combination of SLJIT_SET_* and - SLJIT_CURRENT_FLAGS_* constants. */ - -SLJIT_API_FUNC_ATTRIBUTE void sljit_set_current_flags(struct sljit_compiler *compiler, - sljit_s32 current_flags); - #ifdef __cplusplus } /* extern "C" */ #endif diff --git a/src/3rdparty/pcre2/src/sljit/sljitNativeARM_32.c b/src/3rdparty/pcre2/src/sljit/sljitNativeARM_32.c index 7b87f5907a8..54b8ade0636 100644 --- a/src/3rdparty/pcre2/src/sljit/sljitNativeARM_32.c +++ b/src/3rdparty/pcre2/src/sljit/sljitNativeARM_32.c @@ -100,6 +100,8 @@ static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 3] = { #define CMP 0xe1400000 #define BKPT 0xe1200070 #define EOR 0xe0200000 +#define LDR 0xe5100000 +#define LDR_POST 0xe4100000 #define MOV 0xe1a00000 #define MUL 0xe0000090 #define MVN 0xe1e00000 @@ -107,10 +109,12 @@ static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 3] = { #define ORR 0xe1800000 #define PUSH 0xe92d0000 #define POP 0xe8bd0000 +#define RBIT 0xe6ff0f30 #define RSB 0xe0600000 #define RSC 0xe0e00000 #define SBC 0xe0c00000 #define SMULL 0xe0c00090 +#define STR 0xe5000000 #define SUB 0xe0400000 #define TST 0xe1000000 #define UMULL 0xe0800090 @@ -564,6 +568,7 @@ static SLJIT_INLINE void inline_set_jump_addr(sljit_uw jump_ptr, sljit_sw execut static sljit_uw get_imm(sljit_uw imm); static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 reg, sljit_uw imm); +static sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg, sljit_s32 arg, sljit_sw argw, sljit_s32 tmp_reg); static SLJIT_INLINE void inline_set_const(sljit_uw addr, sljit_sw executable_offset, sljit_uw new_constant, sljit_s32 flush_cache) { @@ -955,12 +960,19 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type) #endif case SLJIT_HAS_CLZ: + case SLJIT_HAS_ROT: case SLJIT_HAS_CMOV: #if (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7) + case SLJIT_HAS_CTZ: case SLJIT_HAS_PREFETCH: #endif return 1; +#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) + case SLJIT_HAS_CTZ: + return 2; +#endif + default: return 0; } @@ -1049,7 +1061,8 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size) { sljit_uw imm, offset; - sljit_s32 i, tmp, size, word_arg_count, saved_arg_count; + sljit_s32 i, tmp, size, word_arg_count; + sljit_s32 saved_arg_count = SLJIT_KEPT_SAVEDS_COUNT(options); #ifdef __SOFTFP__ sljit_u32 float_arg_count; #else @@ -1065,7 +1078,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi imm = 0; tmp = SLJIT_S0 - saveds; - for (i = SLJIT_S0; i > tmp; i--) + for (i = SLJIT_S0 - saved_arg_count; i > tmp; i--) imm |= (sljit_uw)1 << reg_map[i]; for (i = scratches; i >= SLJIT_FIRST_SAVED_REG; i--) @@ -1082,7 +1095,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi FAIL_IF(push_inst(compiler, 0xe52d0004 | RD(TMP_REG2))); /* Stack must be aligned to 8 bytes: */ - size = GET_SAVED_REGISTERS_SIZE(scratches, saveds, 1); + size = GET_SAVED_REGISTERS_SIZE(scratches, saveds - saved_arg_count, 1); if (fsaveds > 0 || fscratches >= SLJIT_FIRST_SAVED_FLOAT_REG) { if ((size & SSIZE_OF(sw)) != 0) { @@ -1103,6 +1116,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi local_size = ((size + local_size + 0x7) & ~0x7) - size; compiler->local_size = local_size; + if (options & SLJIT_ENTER_REG_ARG) + arg_types = 0; + arg_types >>= SLJIT_ARG_SHIFT; word_arg_count = 0; saved_arg_count = 0; @@ -1148,8 +1164,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi if (offset < 4 * sizeof(sljit_sw)) FAIL_IF(push_inst(compiler, MOV | RD(tmp) | (offset >> 2))); else - FAIL_IF(push_inst(compiler, data_transfer_insts[WORD_SIZE | LOAD_DATA] | 0x800000 - | RN(SLJIT_SP) | RD(tmp) | (offset + (sljit_uw)size - 4 * sizeof(sljit_sw)))); + FAIL_IF(push_inst(compiler, LDR | 0x800000 | RN(SLJIT_SP) | RD(tmp) | (offset + (sljit_uw)size - 4 * sizeof(sljit_sw)))); break; } @@ -1217,7 +1232,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *comp CHECK(check_sljit_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size)); set_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size); - size = GET_SAVED_REGISTERS_SIZE(scratches, saveds, 1); + size = GET_SAVED_REGISTERS_SIZE(scratches, saveds - SLJIT_KEPT_SAVEDS_COUNT(options), 1); if ((size & SSIZE_OF(sw)) != 0 && (fsaveds > 0 || fscratches >= SLJIT_FIRST_SAVED_FLOAT_REG)) size += SSIZE_OF(sw); @@ -1231,8 +1246,11 @@ static sljit_s32 emit_add_sp(struct sljit_compiler *compiler, sljit_uw imm) sljit_uw imm2 = get_imm(imm); if (imm2 == 0) { - FAIL_IF(load_immediate(compiler, TMP_REG2, imm)); - imm2 = RM(TMP_REG2); + imm2 = (imm & ~(sljit_uw)0x3ff) >> 10; + imm = (imm & 0x3ff) >> 2; + + FAIL_IF(push_inst(compiler, ADD | SRC2_IMM | RD(SLJIT_SP) | RN(SLJIT_SP) | 0xb00 | imm2)); + return push_inst(compiler, ADD | SRC2_IMM | RD(SLJIT_SP) | RN(SLJIT_SP) | 0xf00 | (imm & 0xff)); } return push_inst(compiler, ADD | RD(SLJIT_SP) | RN(SLJIT_SP) | imm2); @@ -1241,10 +1259,11 @@ static sljit_s32 emit_add_sp(struct sljit_compiler *compiler, sljit_uw imm) static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler, sljit_s32 frame_size) { sljit_s32 local_size, fscratches, fsaveds, i, tmp; + sljit_s32 restored_reg = 0; sljit_s32 lr_dst = TMP_PC; - sljit_uw reg_list; + sljit_uw reg_list = 0; - SLJIT_ASSERT(reg_map[TMP_REG2] == 14); + SLJIT_ASSERT(reg_map[TMP_REG2] == 14 && frame_size <= 128); local_size = compiler->local_size; fscratches = compiler->fscratches; @@ -1269,45 +1288,84 @@ static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler, sljit if (frame_size < 0) { lr_dst = TMP_REG2; frame_size = 0; - } else if (frame_size > 0) + } else if (frame_size > 0) { + SLJIT_ASSERT(frame_size == 1 || (frame_size & 0x7) == 0); lr_dst = 0; + frame_size &= ~0x7; + } - reg_list = 0; if (lr_dst != 0) reg_list |= (sljit_uw)1 << reg_map[lr_dst]; tmp = SLJIT_S0 - compiler->saveds; - for (i = SLJIT_S0; i > tmp; i--) - reg_list |= (sljit_uw)1 << reg_map[i]; + i = SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options); + if (tmp < i) { + restored_reg = i; + do { + reg_list |= (sljit_uw)1 << reg_map[i]; + } while (--i > tmp); + } - for (i = compiler->scratches; i >= SLJIT_FIRST_SAVED_REG; i--) - reg_list |= (sljit_uw)1 << reg_map[i]; + i = compiler->scratches; + if (i >= SLJIT_FIRST_SAVED_REG) { + restored_reg = i; + do { + reg_list |= (sljit_uw)1 << reg_map[i]; + } while (--i >= SLJIT_FIRST_SAVED_REG); + } + + if (lr_dst == TMP_REG2 && reg_list == 0) { + restored_reg = TMP_REG2; + lr_dst = 0; + } if (lr_dst == 0 && (reg_list & (reg_list - 1)) == 0) { /* The local_size does not include the saved registers. */ - local_size += SSIZE_OF(sw); + tmp = 0; + if (reg_list != 0) { + tmp = 2; + if (local_size <= 0xfff) { + if (local_size == 0) { + SLJIT_ASSERT(restored_reg != TMP_REG2); + if (frame_size == 0) + return push_inst(compiler, LDR_POST | RN(SLJIT_SP) | RD(restored_reg) | 0x800008); + if (frame_size > 2 * SSIZE_OF(sw)) + return push_inst(compiler, LDR_POST | RN(SLJIT_SP) | RD(restored_reg) | (sljit_uw)(frame_size - (2 * SSIZE_OF(sw)))); + } - if (reg_list != 0) - local_size += SSIZE_OF(sw); + FAIL_IF(push_inst(compiler, LDR | 0x800000 | RN(SLJIT_SP) | RD(restored_reg) | (sljit_uw)local_size)); + tmp = 1; + } else if (frame_size == 0) { + frame_size = (restored_reg == TMP_REG2) ? SSIZE_OF(sw) : 2 * SSIZE_OF(sw); + tmp = 3; + } + + /* Place for the saved register. */ + if (restored_reg != TMP_REG2) + local_size += SSIZE_OF(sw); + } + + /* Place for the lr register. */ + local_size += SSIZE_OF(sw); if (frame_size > local_size) FAIL_IF(push_inst(compiler, SUB | RD(SLJIT_SP) | RN(SLJIT_SP) | (1 << 25) | (sljit_uw)(frame_size - local_size))); else if (frame_size < local_size) FAIL_IF(emit_add_sp(compiler, (sljit_uw)(local_size - frame_size))); - if (reg_list == 0) + if (tmp <= 1) return SLJIT_SUCCESS; - if (compiler->saveds > 0) { - SLJIT_ASSERT(reg_list == ((sljit_uw)1 << reg_map[SLJIT_S0])); - lr_dst = SLJIT_S0; - } else { - SLJIT_ASSERT(reg_list == ((sljit_uw)1 << reg_map[SLJIT_FIRST_SAVED_REG])); - lr_dst = SLJIT_FIRST_SAVED_REG; + if (tmp == 2) { + frame_size -= SSIZE_OF(sw); + if (restored_reg != TMP_REG2) + frame_size -= SSIZE_OF(sw); + + return push_inst(compiler, LDR | 0x800000 | RN(SLJIT_SP) | RD(restored_reg) | (sljit_uw)frame_size); } - return push_inst(compiler, data_transfer_insts[WORD_SIZE | LOAD_DATA] | 0x800000 - | RN(SLJIT_SP) | RD(lr_dst) | (sljit_uw)(frame_size - 2 * SSIZE_OF(sw))); + tmp = (restored_reg == TMP_REG2) ? 0x800004 : 0x800008; + return push_inst(compiler, LDR_POST | RN(SLJIT_SP) | RD(restored_reg) | (sljit_uw)tmp); } if (local_size > 0) @@ -1320,13 +1378,18 @@ static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler, sljit SLJIT_ASSERT(lr_dst != 0); SLJIT_ASSERT(reg_list == (sljit_uw)1 << reg_map[lr_dst]); - return push_inst(compiler, 0xe49d0004 | RD(lr_dst)); + return push_inst(compiler, LDR_POST | RN(SLJIT_SP) | RD(lr_dst) | 0x800004); } FAIL_IF(push_inst(compiler, POP | reg_list)); + if (frame_size > 0) return push_inst(compiler, SUB | RD(SLJIT_SP) | RN(SLJIT_SP) | (1 << 25) | ((sljit_uw)frame_size - sizeof(sljit_sw))); - return SLJIT_SUCCESS; + + if (lr_dst != 0) + return SLJIT_SUCCESS; + + return push_inst(compiler, ADD | RD(SLJIT_SP) | RN(SLJIT_SP) | (1 << 25) | sizeof(sljit_sw)); } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_void(struct sljit_compiler *compiler) @@ -1337,28 +1400,38 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_void(struct sljit_compiler return emit_stack_frame_release(compiler, 0); } +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_to(struct sljit_compiler *compiler, + sljit_s32 src, sljit_sw srcw) +{ + CHECK_ERROR(); + CHECK(check_sljit_emit_return_to(compiler, src, srcw)); + + if (src & SLJIT_MEM) { + FAIL_IF(emit_op_mem(compiler, WORD_SIZE | LOAD_DATA, TMP_REG1, src, srcw, TMP_REG1)); + src = TMP_REG1; + srcw = 0; + } else if (src >= SLJIT_FIRST_SAVED_REG && src <= (SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options))) { + FAIL_IF(push_inst(compiler, MOV | RD(TMP_REG1) | RM(src))); + src = TMP_REG1; + srcw = 0; + } + + FAIL_IF(emit_stack_frame_release(compiler, 1)); + + SLJIT_SKIP_CHECKS(compiler); + return sljit_emit_ijump(compiler, SLJIT_JUMP, src, srcw); +} + /* --------------------------------------------------------------------- */ /* Operators */ /* --------------------------------------------------------------------- */ -#define EMIT_SHIFT_INS_AND_RETURN(opcode) \ - SLJIT_ASSERT(!(flags & INV_IMM) && !(src2 & SRC2_IMM)); \ - if (compiler->shift_imm != 0x20) { \ - SLJIT_ASSERT(src1 == TMP_REG1); \ - SLJIT_ASSERT(!(flags & ARGS_SWAPPED)); \ - \ - if (compiler->shift_imm != 0) \ - return push_inst(compiler, MOV | (flags & SET_FLAGS) | \ - RD(dst) | (compiler->shift_imm << 7) | (opcode << 5) | RM(src2)); \ - return push_inst(compiler, MOV | (flags & SET_FLAGS) | RD(dst) | RM(src2)); \ - } \ - return push_inst(compiler, MOV | (flags & SET_FLAGS) | RD(dst) \ - | RM8((flags & ARGS_SWAPPED) ? src1 : src2) | (sljit_uw)(opcode << 5) \ - | 0x10 | RM((flags & ARGS_SWAPPED) ? src2 : src1)); - static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 flags, sljit_uw dst, sljit_uw src1, sljit_uw src2) { + sljit_s32 is_masked; + sljit_uw shift_type; + switch (GET_OPCODE(op)) { case SLJIT_MOV: SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & ARGS_SWAPPED)); @@ -1413,11 +1486,24 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl return push_inst(compiler, MVN | (flags & SET_FLAGS) | RD(dst) | RM(src2)); case SLJIT_CLZ: - SLJIT_ASSERT(!(flags & INV_IMM)); - SLJIT_ASSERT(!(src2 & SRC2_IMM)); + SLJIT_ASSERT(!(flags & INV_IMM) && !(src2 & SRC2_IMM)); FAIL_IF(push_inst(compiler, CLZ | RD(dst) | RM(src2))); return SLJIT_SUCCESS; + case SLJIT_CTZ: + SLJIT_ASSERT(!(flags & INV_IMM) && !(src2 & SRC2_IMM)); + SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & ARGS_SWAPPED)); +#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) + FAIL_IF(push_inst(compiler, RSB | SRC2_IMM | RD(TMP_REG1) | RN(src2) | 0)); + FAIL_IF(push_inst(compiler, AND | RD(TMP_REG2) | RN(src2) | RM(TMP_REG1))); + FAIL_IF(push_inst(compiler, CLZ | RD(dst) | RM(TMP_REG2))); + FAIL_IF(push_inst(compiler, CMP | SET_FLAGS | SRC2_IMM | RN(dst) | 32)); + return push_inst(compiler, (EOR ^ 0xf0000000) | SRC2_IMM | RD(dst) | RN(dst) | 0x1f); +#else /* !SLJIT_CONFIG_ARM_V5 */ + FAIL_IF(push_inst(compiler, RBIT | RD(dst) | RM(src2))); + return push_inst(compiler, CLZ | RD(dst) | RM(dst)); +#endif /* SLJIT_CONFIG_ARM_V5 */ + case SLJIT_ADD: SLJIT_ASSERT(!(flags & INV_IMM)); @@ -1471,17 +1557,61 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl return push_inst(compiler, EOR | (flags & SET_FLAGS) | RD(dst) | RN(src1) | ((src2 & SRC2_IMM) ? src2 : RM(src2))); case SLJIT_SHL: - EMIT_SHIFT_INS_AND_RETURN(0); + case SLJIT_MSHL: + shift_type = 0; + is_masked = GET_OPCODE(op) == SLJIT_MSHL; + break; case SLJIT_LSHR: - EMIT_SHIFT_INS_AND_RETURN(1); + case SLJIT_MLSHR: + shift_type = 1; + is_masked = GET_OPCODE(op) == SLJIT_MLSHR; + break; case SLJIT_ASHR: - EMIT_SHIFT_INS_AND_RETURN(2); + case SLJIT_MASHR: + shift_type = 2; + is_masked = GET_OPCODE(op) == SLJIT_MASHR; + break; + + case SLJIT_ROTL: + if (compiler->shift_imm == 0x20) { + FAIL_IF(push_inst(compiler, RSB | SRC2_IMM | RD(TMP_REG2) | RN(src2) | 0)); + src2 = TMP_REG2; + } else + compiler->shift_imm = (sljit_uw)(-(sljit_sw)compiler->shift_imm) & 0x1f; + /* fallthrough */ + + case SLJIT_ROTR: + shift_type = 3; + is_masked = 0; + break; + + default: + SLJIT_UNREACHABLE(); + return SLJIT_SUCCESS; } - SLJIT_UNREACHABLE(); - return SLJIT_SUCCESS; + SLJIT_ASSERT(!(flags & ARGS_SWAPPED) && !(flags & INV_IMM) && !(src2 & SRC2_IMM)); + + if (compiler->shift_imm != 0x20) { + SLJIT_ASSERT(src1 == TMP_REG1); + + if (compiler->shift_imm != 0) + return push_inst(compiler, MOV | (flags & SET_FLAGS) | + RD(dst) | (compiler->shift_imm << 7) | (shift_type << 5) | RM(src2)); + return push_inst(compiler, MOV | (flags & SET_FLAGS) | RD(dst) | RM(src2)); + } + + SLJIT_ASSERT(src1 != TMP_REG2); + + if (is_masked) { + FAIL_IF(push_inst(compiler, AND | RD(TMP_REG2) | RN(src2) | SRC2_IMM | 0x1f)); + src2 = TMP_REG2; + } + + return push_inst(compiler, MOV | (flags & SET_FLAGS) | RD(dst) + | RM8(src2) | (sljit_uw)(shift_type << 5) | 0x10 | RM(src1)); } #undef EMIT_SHIFT_INS_AND_RETURN @@ -1670,27 +1800,32 @@ static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 reg, #endif } -static SLJIT_INLINE sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg, +static sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg, sljit_s32 arg, sljit_sw argw, sljit_s32 tmp_reg) { - sljit_uw imm, offset_reg; - sljit_uw is_type1_transfer = IS_TYPE1_TRANSFER(flags); + sljit_uw imm, offset_reg, tmp; + sljit_sw mask = IS_TYPE1_TRANSFER(flags) ? 0xfff : 0xff; + sljit_sw sign = IS_TYPE1_TRANSFER(flags) ? 0x1000 : 0x100; - SLJIT_ASSERT (arg & SLJIT_MEM); - SLJIT_ASSERT((arg & REG_MASK) != tmp_reg); + SLJIT_ASSERT(arg & SLJIT_MEM); + SLJIT_ASSERT((arg & REG_MASK) != tmp_reg || (arg == SLJIT_MEM1(tmp_reg) && argw >= -mask && argw <= mask)); - if (!(arg & REG_MASK)) { - if (is_type1_transfer) { - FAIL_IF(load_immediate(compiler, tmp_reg, (sljit_uw)argw & ~(sljit_uw)0xfff)); - argw &= 0xfff; - } - else { - FAIL_IF(load_immediate(compiler, tmp_reg, (sljit_uw)argw & ~(sljit_uw)0xff)); - argw &= 0xff; + if (SLJIT_UNLIKELY(!(arg & REG_MASK))) { + tmp = (sljit_uw)(argw & (sign | mask)); + tmp = (sljit_uw)((argw + (tmp <= (sljit_uw)sign ? 0 : sign)) & ~mask); + + FAIL_IF(load_immediate(compiler, tmp_reg, tmp)); + + argw -= (sljit_sw)tmp; + tmp = 1; + + if (argw < 0) { + argw = -argw; + tmp = 0; } - return push_inst(compiler, EMIT_DATA_TRANSFER(flags, 1, reg, tmp_reg, - is_type1_transfer ? argw : TYPE2_TRANSFER_IMM(argw))); + return push_inst(compiler, EMIT_DATA_TRANSFER(flags, tmp, reg, tmp_reg, + (mask == 0xff) ? TYPE2_TRANSFER_IMM(argw) : argw)); } if (arg & OFFS_REG_MASK) { @@ -1698,72 +1833,62 @@ static SLJIT_INLINE sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit arg &= REG_MASK; argw &= 0x3; - if (argw != 0 && !is_type1_transfer) { + if (argw != 0 && (mask == 0xff)) { FAIL_IF(push_inst(compiler, ADD | RD(tmp_reg) | RN(arg) | RM(offset_reg) | ((sljit_uw)argw << 7))); return push_inst(compiler, EMIT_DATA_TRANSFER(flags, 1, reg, tmp_reg, TYPE2_TRANSFER_IMM(0))); } /* Bit 25: RM is offset. */ return push_inst(compiler, EMIT_DATA_TRANSFER(flags, 1, reg, arg, - RM(offset_reg) | (is_type1_transfer ? (1 << 25) : 0) | ((sljit_uw)argw << 7))); + RM(offset_reg) | (mask == 0xff ? 0 : (1 << 25)) | ((sljit_uw)argw << 7))); } arg &= REG_MASK; - if (is_type1_transfer) { - if (argw > 0xfff) { - imm = get_imm((sljit_uw)argw & ~(sljit_uw)0xfff); - if (imm) { - FAIL_IF(push_inst(compiler, ADD | RD(tmp_reg) | RN(arg) | imm)); - argw = argw & 0xfff; - arg = tmp_reg; - } - } - else if (argw < -0xfff) { - imm = get_imm((sljit_uw)-argw & ~(sljit_uw)0xfff); - if (imm) { - FAIL_IF(push_inst(compiler, SUB | RD(tmp_reg) | RN(arg) | imm)); - argw = -(-argw & 0xfff); - arg = tmp_reg; - } - } + if (argw > mask) { + tmp = (sljit_uw)(argw & (sign | mask)); + tmp = (sljit_uw)((argw + (tmp <= (sljit_uw)sign ? 0 : sign)) & ~mask); + imm = get_imm(tmp); - if (argw >= 0 && argw <= 0xfff) - return push_inst(compiler, EMIT_DATA_TRANSFER(flags, 1, reg, arg, argw)); + if (imm) { + FAIL_IF(push_inst(compiler, ADD | RD(tmp_reg) | RN(arg) | imm)); + argw -= (sljit_sw)tmp; + arg = tmp_reg; - if (argw < 0 && argw >= -0xfff) - return push_inst(compiler, EMIT_DATA_TRANSFER(flags, 0, reg, arg, -argw)); + SLJIT_ASSERT(argw >= -mask && argw <= mask); + } + } else if (argw < -mask) { + tmp = (sljit_uw)(-argw & (sign | mask)); + tmp = (sljit_uw)((-argw + (tmp <= (sljit_uw)sign ? 0 : sign)) & ~mask); + imm = get_imm(tmp); + + if (imm) { + FAIL_IF(push_inst(compiler, SUB | RD(tmp_reg) | RN(arg) | imm)); + argw += (sljit_sw)tmp; + arg = tmp_reg; + + SLJIT_ASSERT(argw >= -mask && argw <= mask); + } } - else { - if (argw > 0xff) { - imm = get_imm((sljit_uw)argw & ~(sljit_uw)0xff); - if (imm) { - FAIL_IF(push_inst(compiler, ADD | RD(tmp_reg) | RN(arg) | imm)); - argw = argw & 0xff; - arg = tmp_reg; - } - } - else if (argw < -0xff) { - imm = get_imm((sljit_uw)-argw & ~(sljit_uw)0xff); - if (imm) { - FAIL_IF(push_inst(compiler, SUB | RD(tmp_reg) | RN(arg) | imm)); - argw = -(-argw & 0xff); - arg = tmp_reg; - } + + if (argw <= mask && argw >= -mask) { + if (argw >= 0) { + if (mask == 0xff) + argw = TYPE2_TRANSFER_IMM(argw); + return push_inst(compiler, EMIT_DATA_TRANSFER(flags, 1, reg, arg, argw)); } - if (argw >= 0 && argw <= 0xff) - return push_inst(compiler, EMIT_DATA_TRANSFER(flags, 1, reg, arg, TYPE2_TRANSFER_IMM(argw))); + argw = -argw; - if (argw < 0 && argw >= -0xff) { - argw = -argw; - return push_inst(compiler, EMIT_DATA_TRANSFER(flags, 0, reg, arg, TYPE2_TRANSFER_IMM(argw))); - } + if (mask == 0xff) + argw = TYPE2_TRANSFER_IMM(argw); + + return push_inst(compiler, EMIT_DATA_TRANSFER(flags, 0, reg, arg, argw)); } FAIL_IF(load_immediate(compiler, tmp_reg, (sljit_uw)argw)); return push_inst(compiler, EMIT_DATA_TRANSFER(flags, 1, reg, arg, - RM(tmp_reg) | (is_type1_transfer ? (1 << 25) : 0))); + RM(tmp_reg) | (mask == 0xff ? 0 : (1 << 25)))); } static sljit_s32 emit_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 inp_flags, @@ -1961,15 +2086,15 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compile saved_reg_list[saved_reg_count++] = 1; if (saved_reg_count > 0) { - FAIL_IF(push_inst(compiler, 0xe52d0000 | (saved_reg_count >= 3 ? 16 : 8) + FAIL_IF(push_inst(compiler, STR | 0x2d0000 | (saved_reg_count >= 3 ? 16 : 8) | (saved_reg_list[0] << 12) /* str rX, [sp, #-8/-16]! */)); if (saved_reg_count >= 2) { SLJIT_ASSERT(saved_reg_list[1] < 8); - FAIL_IF(push_inst(compiler, 0xe58d0004 | (saved_reg_list[1] << 12) /* str rX, [sp, #4] */)); + FAIL_IF(push_inst(compiler, STR | 0x8d0004 | (saved_reg_list[1] << 12) /* str rX, [sp, #4] */)); } if (saved_reg_count >= 3) { SLJIT_ASSERT(saved_reg_list[2] < 8); - FAIL_IF(push_inst(compiler, 0xe58d0008 | (saved_reg_list[2] << 12) /* str rX, [sp, #8] */)); + FAIL_IF(push_inst(compiler, STR | 0x8d0008 | (saved_reg_list[2] << 12) /* str rX, [sp, #8] */)); } } @@ -1983,13 +2108,13 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compile if (saved_reg_count > 0) { if (saved_reg_count >= 3) { SLJIT_ASSERT(saved_reg_list[2] < 8); - FAIL_IF(push_inst(compiler, 0xe59d0008 | (saved_reg_list[2] << 12) /* ldr rX, [sp, #8] */)); + FAIL_IF(push_inst(compiler, LDR | 0x8d0008 | (saved_reg_list[2] << 12) /* ldr rX, [sp, #8] */)); } if (saved_reg_count >= 2) { SLJIT_ASSERT(saved_reg_list[1] < 8); - FAIL_IF(push_inst(compiler, 0xe59d0004 | (saved_reg_list[1] << 12) /* ldr rX, [sp, #4] */)); + FAIL_IF(push_inst(compiler, LDR | 0x8d0004 | (saved_reg_list[1] << 12) /* ldr rX, [sp, #4] */)); } - return push_inst(compiler, 0xe49d0000 | (sljit_uw)(saved_reg_count >= 3 ? 16 : 8) + return push_inst(compiler, (LDR ^ (1 << 24)) | 0x8d0000 | (sljit_uw)(saved_reg_count >= 3 ? 16 : 8) | (saved_reg_list[0] << 12) /* ldr rX, [sp], #8/16 */); } return SLJIT_SUCCESS; @@ -2034,6 +2159,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile return emit_op(compiler, op, ALLOW_ANY_IMM, dst, dstw, TMP_REG1, 0, src, srcw); case SLJIT_CLZ: + case SLJIT_CTZ: return emit_op(compiler, op, 0, dst, dstw, TMP_REG1, 0, src, srcw); } @@ -2069,13 +2195,17 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compile return emit_op(compiler, op, ALLOW_ANY_IMM, dst, dstw, src1, src1w, src2, src2w); case SLJIT_SHL: + case SLJIT_MSHL: case SLJIT_LSHR: + case SLJIT_MLSHR: case SLJIT_ASHR: + case SLJIT_MASHR: + case SLJIT_ROTL: + case SLJIT_ROTR: if (src2 & SLJIT_IMM) { compiler->shift_imm = src2w & 0x1f; return emit_op(compiler, op, 0, dst, dstw, TMP_REG1, 0, src1, src1w); - } - else { + } else { compiler->shift_imm = 0x20; return emit_op(compiler, op, 0, dst, dstw, src1, src1w, src2, src2w); } @@ -2091,13 +2221,67 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2u(struct sljit_compiler *compil CHECK_ERROR(); CHECK(check_sljit_emit_op2(compiler, op, 1, 0, 0, src1, src1w, src2, src2w)); -#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \ - || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) - compiler->skip_checks = 1; -#endif + SLJIT_SKIP_CHECKS(compiler); return sljit_emit_op2(compiler, op, TMP_REG2, 0, src1, src1w, src2, src2w); } +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_shift_into(struct sljit_compiler *compiler, sljit_s32 op, + sljit_s32 src_dst, + sljit_s32 src1, sljit_sw src1w, + sljit_s32 src2, sljit_sw src2w) +{ + sljit_s32 is_left; + + CHECK_ERROR(); + CHECK(check_sljit_emit_shift_into(compiler, op, src_dst, src1, src1w, src2, src2w)); + + op = GET_OPCODE(op); + is_left = (op == SLJIT_SHL || op == SLJIT_MSHL); + + if (src_dst == src1) { + SLJIT_SKIP_CHECKS(compiler); + return sljit_emit_op2(compiler, is_left ? SLJIT_ROTL : SLJIT_ROTR, src_dst, 0, src_dst, 0, src2, src2w); + } + + ADJUST_LOCAL_OFFSET(src1, src1w); + ADJUST_LOCAL_OFFSET(src2, src2w); + + /* Shift type of ROR is 3. */ + if (src2 & SLJIT_IMM) { + src2w &= 0x1f; + + if (src2w == 0) + return SLJIT_SUCCESS; + } else if (src2 & SLJIT_MEM) { + FAIL_IF(emit_op_mem(compiler, WORD_SIZE | LOAD_DATA, TMP_REG2, src2, src2w, TMP_REG2)); + src2 = TMP_REG2; + } + + if (src1 & SLJIT_MEM) { + FAIL_IF(emit_op_mem(compiler, WORD_SIZE | LOAD_DATA, TMP_REG1, src1, src1w, TMP_REG1)); + src1 = TMP_REG1; + } else if (src1 & SLJIT_IMM) { + FAIL_IF(load_immediate(compiler, TMP_REG1, (sljit_uw)src1w)); + src1 = TMP_REG1; + } + + if (src2 & SLJIT_IMM) { + FAIL_IF(push_inst(compiler, MOV | RD(src_dst) | RM(src_dst) | ((sljit_uw)(is_left ? 0 : 1) << 5) | ((sljit_uw)src2w << 7))); + src2w = (src2w ^ 0x1f) + 1; + return push_inst(compiler, ORR | RD(src_dst) | RN(src_dst) | RM(src1) | ((sljit_uw)(is_left ? 1 : 0) << 5) | ((sljit_uw)src2w << 7)); + } + + if (op == SLJIT_MSHL || op == SLJIT_MLSHR) { + FAIL_IF(push_inst(compiler, AND | SRC2_IMM | RD(TMP_REG2) | RN(src2) | 0x1f)); + src2 = TMP_REG2; + } + + FAIL_IF(push_inst(compiler, MOV | RD(src_dst) | RM8(src2) | ((sljit_uw)(is_left ? 0 : 1) << 5) | 0x10 | RM(src_dst))); + FAIL_IF(push_inst(compiler, MOV | RD(TMP_REG1) | RM(src1) | ((sljit_uw)(is_left ? 1 : 0) << 5) | (1 << 7))); + FAIL_IF(push_inst(compiler, EOR | SRC2_IMM | RD(TMP_REG2) | RN(src2) | 0x1f)); + return push_inst(compiler, ORR | RD(src_dst) | RN(src_dst) | RM(TMP_REG1) | ((sljit_uw)(is_left ? 1 : 0) << 5) | 0x10 | RM8(TMP_REG2)); +} + SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_src(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 src, sljit_sw srcw) { @@ -2370,7 +2554,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop2(struct sljit_compiler *compil return SLJIT_SUCCESS; } -#undef FPU_LOAD #undef EMIT_FPU_DATA_TRANSFER /* --------------------------------------------------------------------- */ @@ -2400,11 +2583,15 @@ static sljit_uw get_cc(struct sljit_compiler *compiler, sljit_s32 type) { switch (type) { case SLJIT_EQUAL: - case SLJIT_EQUAL_F64: + case SLJIT_F_EQUAL: + case SLJIT_ORDERED_EQUAL: + case SLJIT_UNORDERED_OR_EQUAL: /* Not supported. */ return 0x00000000; case SLJIT_NOT_EQUAL: - case SLJIT_NOT_EQUAL_F64: + case SLJIT_F_NOT_EQUAL: + case SLJIT_UNORDERED_OR_NOT_EQUAL: + case SLJIT_ORDERED_NOT_EQUAL: /* Not supported. */ return 0x10000000; case SLJIT_CARRY: @@ -2413,7 +2600,6 @@ static sljit_uw get_cc(struct sljit_compiler *compiler, sljit_s32 type) /* fallthrough */ case SLJIT_LESS: - case SLJIT_LESS_F64: return 0x30000000; case SLJIT_NOT_CARRY: @@ -2422,27 +2608,33 @@ static sljit_uw get_cc(struct sljit_compiler *compiler, sljit_s32 type) /* fallthrough */ case SLJIT_GREATER_EQUAL: - case SLJIT_GREATER_EQUAL_F64: return 0x20000000; case SLJIT_GREATER: - case SLJIT_GREATER_F64: + case SLJIT_UNORDERED_OR_GREATER: return 0x80000000; case SLJIT_LESS_EQUAL: - case SLJIT_LESS_EQUAL_F64: + case SLJIT_F_LESS_EQUAL: + case SLJIT_ORDERED_LESS_EQUAL: return 0x90000000; case SLJIT_SIG_LESS: + case SLJIT_UNORDERED_OR_LESS: return 0xb0000000; case SLJIT_SIG_GREATER_EQUAL: + case SLJIT_F_GREATER_EQUAL: + case SLJIT_ORDERED_GREATER_EQUAL: return 0xa0000000; case SLJIT_SIG_GREATER: + case SLJIT_F_GREATER: + case SLJIT_ORDERED_GREATER: return 0xc0000000; case SLJIT_SIG_LESS_EQUAL: + case SLJIT_UNORDERED_OR_LESS_EQUAL: return 0xd0000000; case SLJIT_OVERFLOW: @@ -2450,7 +2642,7 @@ static sljit_uw get_cc(struct sljit_compiler *compiler, sljit_s32 type) return 0x10000000; /* fallthrough */ - case SLJIT_UNORDERED_F64: + case SLJIT_UNORDERED: return 0x60000000; case SLJIT_NOT_OVERFLOW: @@ -2458,11 +2650,18 @@ static sljit_uw get_cc(struct sljit_compiler *compiler, sljit_s32 type) return 0x00000000; /* fallthrough */ - case SLJIT_ORDERED_F64: + case SLJIT_ORDERED: return 0x70000000; + case SLJIT_F_LESS: + case SLJIT_ORDERED_LESS: + return 0x40000000; + + case SLJIT_UNORDERED_OR_GREATER_EQUAL: + return 0x50000000; + default: - SLJIT_ASSERT(type >= SLJIT_JUMP && type <= SLJIT_CALL_CDECL); + SLJIT_ASSERT(type >= SLJIT_JUMP && type <= SLJIT_CALL_REG_ARG); return 0xe0000000; } } @@ -2639,7 +2838,7 @@ static sljit_s32 softfloat_call_with_args(struct sljit_compiler *compiler, sljit } FAIL_IF(push_inst(compiler, MOV | (offset << 10) | (word_arg_offset >> 2))); } else - FAIL_IF(push_inst(compiler, data_transfer_insts[WORD_SIZE] | 0x800000 | RN(SLJIT_SP) | (word_arg_offset << 10) | (offset - 4 * sizeof(sljit_sw)))); + FAIL_IF(push_inst(compiler, STR | 0x800000 | RN(SLJIT_SP) | (word_arg_offset << 10) | (offset - 4 * sizeof(sljit_sw)))); } break; } @@ -2718,51 +2917,48 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compile CHECK_PTR(check_sljit_emit_call(compiler, type, arg_types)); #ifdef __SOFTFP__ - PTR_FAIL_IF(softfloat_call_with_args(compiler, arg_types, NULL, &extra_space)); - SLJIT_ASSERT((extra_space & 0x7) == 0); + if ((type & 0xff) != SLJIT_CALL_REG_ARG) { + PTR_FAIL_IF(softfloat_call_with_args(compiler, arg_types, NULL, &extra_space)); + SLJIT_ASSERT((extra_space & 0x7) == 0); - if ((type & SLJIT_CALL_RETURN) && extra_space == 0) - type = SLJIT_JUMP | (type & SLJIT_REWRITABLE_JUMP); + if ((type & SLJIT_CALL_RETURN) && extra_space == 0) + type = SLJIT_JUMP | (type & SLJIT_REWRITABLE_JUMP); -#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \ - || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) - compiler->skip_checks = 1; -#endif + SLJIT_SKIP_CHECKS(compiler); + jump = sljit_emit_jump(compiler, type); + PTR_FAIL_IF(jump == NULL); - jump = sljit_emit_jump(compiler, type); - PTR_FAIL_IF(jump == NULL); + if (extra_space > 0) { + if (type & SLJIT_CALL_RETURN) + PTR_FAIL_IF(push_inst(compiler, EMIT_DATA_TRANSFER(WORD_SIZE | LOAD_DATA, 1, + TMP_REG2, SLJIT_SP, extra_space - sizeof(sljit_sw)))); - if (extra_space > 0) { - if (type & SLJIT_CALL_RETURN) - PTR_FAIL_IF(push_inst(compiler, EMIT_DATA_TRANSFER(WORD_SIZE | LOAD_DATA, 1, - TMP_REG2, SLJIT_SP, extra_space - sizeof(sljit_sw)))); + PTR_FAIL_IF(push_inst(compiler, ADD | RD(SLJIT_SP) | RN(SLJIT_SP) | SRC2_IMM | extra_space)); - PTR_FAIL_IF(push_inst(compiler, ADD | RD(SLJIT_SP) | RN(SLJIT_SP) | SRC2_IMM | extra_space)); - - if (type & SLJIT_CALL_RETURN) { - PTR_FAIL_IF(push_inst(compiler, BX | RM(TMP_REG2))); - return jump; + if (type & SLJIT_CALL_RETURN) { + PTR_FAIL_IF(push_inst(compiler, BX | RM(TMP_REG2))); + return jump; + } } - } - SLJIT_ASSERT(!(type & SLJIT_CALL_RETURN)); - PTR_FAIL_IF(softfloat_post_call_with_args(compiler, arg_types)); - return jump; -#else /* !__SOFTFP__ */ + SLJIT_ASSERT(!(type & SLJIT_CALL_RETURN)); + PTR_FAIL_IF(softfloat_post_call_with_args(compiler, arg_types)); + return jump; + } +#endif /* __SOFTFP__ */ + if (type & SLJIT_CALL_RETURN) { PTR_FAIL_IF(emit_stack_frame_release(compiler, -1)); type = SLJIT_JUMP | (type & SLJIT_REWRITABLE_JUMP); } - PTR_FAIL_IF(hardfloat_call_with_args(compiler, arg_types)); - -#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \ - || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) - compiler->skip_checks = 1; -#endif +#ifndef __SOFTFP__ + if ((type & 0xff) != SLJIT_CALL_REG_ARG) + PTR_FAIL_IF(hardfloat_call_with_args(compiler, arg_types)); +#endif /* !__SOFTFP__ */ + SLJIT_SKIP_CHECKS(compiler); return sljit_emit_jump(compiler, type); -#endif /* __SOFTFP__ */ } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 src, sljit_sw srcw) @@ -2822,55 +3018,79 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compi src = TMP_REG1; } - if ((type & SLJIT_CALL_RETURN) && (src >= SLJIT_FIRST_SAVED_REG && src <= SLJIT_S0)) { + if ((type & SLJIT_CALL_RETURN) && (src >= SLJIT_FIRST_SAVED_REG && src <= (SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options)))) { FAIL_IF(push_inst(compiler, MOV | RD(TMP_REG1) | RM(src))); src = TMP_REG1; } #ifdef __SOFTFP__ - FAIL_IF(softfloat_call_with_args(compiler, arg_types, &src, &extra_space)); - SLJIT_ASSERT((extra_space & 0x7) == 0); + if ((type & 0xff) != SLJIT_CALL_REG_ARG) { + FAIL_IF(softfloat_call_with_args(compiler, arg_types, &src, &extra_space)); + SLJIT_ASSERT((extra_space & 0x7) == 0); - if ((type & SLJIT_CALL_RETURN) && extra_space == 0) - type = SLJIT_JUMP; + if ((type & SLJIT_CALL_RETURN) && extra_space == 0) + type = SLJIT_JUMP; -#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \ - || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) - compiler->skip_checks = 1; -#endif + SLJIT_SKIP_CHECKS(compiler); + FAIL_IF(sljit_emit_ijump(compiler, type, src, srcw)); - FAIL_IF(sljit_emit_ijump(compiler, type, src, srcw)); + if (extra_space > 0) { + if (type & SLJIT_CALL_RETURN) + FAIL_IF(push_inst(compiler, EMIT_DATA_TRANSFER(WORD_SIZE | LOAD_DATA, 1, + TMP_REG2, SLJIT_SP, extra_space - sizeof(sljit_sw)))); - if (extra_space > 0) { - if (type & SLJIT_CALL_RETURN) - FAIL_IF(push_inst(compiler, EMIT_DATA_TRANSFER(WORD_SIZE | LOAD_DATA, 1, - TMP_REG2, SLJIT_SP, extra_space - sizeof(sljit_sw)))); + FAIL_IF(push_inst(compiler, ADD | RD(SLJIT_SP) | RN(SLJIT_SP) | SRC2_IMM | extra_space)); - FAIL_IF(push_inst(compiler, ADD | RD(SLJIT_SP) | RN(SLJIT_SP) | SRC2_IMM | extra_space)); + if (type & SLJIT_CALL_RETURN) + return push_inst(compiler, BX | RM(TMP_REG2)); + } - if (type & SLJIT_CALL_RETURN) - return push_inst(compiler, BX | RM(TMP_REG2)); + SLJIT_ASSERT(!(type & SLJIT_CALL_RETURN)); + return softfloat_post_call_with_args(compiler, arg_types); } +#endif /* __SOFTFP__ */ - SLJIT_ASSERT(!(type & SLJIT_CALL_RETURN)); - return softfloat_post_call_with_args(compiler, arg_types); -#else /* !__SOFTFP__ */ if (type & SLJIT_CALL_RETURN) { FAIL_IF(emit_stack_frame_release(compiler, -1)); type = SLJIT_JUMP; } - FAIL_IF(hardfloat_call_with_args(compiler, arg_types)); - -#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \ - || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) - compiler->skip_checks = 1; -#endif +#ifndef __SOFTFP__ + if ((type & 0xff) != SLJIT_CALL_REG_ARG) + FAIL_IF(hardfloat_call_with_args(compiler, arg_types)); +#endif /* !__SOFTFP__ */ + SLJIT_SKIP_CHECKS(compiler); return sljit_emit_ijump(compiler, type, src, srcw); -#endif /* __SOFTFP__ */ } +#ifdef __SOFTFP__ + +static SLJIT_INLINE sljit_s32 emit_fmov_before_return(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 src, sljit_sw srcw) +{ + if (compiler->options & SLJIT_ENTER_REG_ARG) { + if (src == SLJIT_FR0) + return SLJIT_SUCCESS; + + SLJIT_SKIP_CHECKS(compiler); + return sljit_emit_fop1(compiler, op, SLJIT_RETURN_FREG, 0, src, srcw); + } + + if (FAST_IS_REG(src)) { + if (op & SLJIT_32) + return push_inst(compiler, VMOV | (1 << 20) | RD(SLJIT_R0) | VN(src)); + return push_inst(compiler, VMOV2 | (1 << 20) | RD(SLJIT_R0) | RN(SLJIT_R1) | VM(src)); + } + + SLJIT_SKIP_CHECKS(compiler); + + if (op & SLJIT_32) + return sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, src, srcw); + return sljit_emit_mem(compiler, SLJIT_MOV, SLJIT_REG_PAIR(SLJIT_R0, SLJIT_R1), src, srcw); +} + +#endif /* __SOFTFP__ */ + SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw dstw, sljit_s32 type) @@ -2883,7 +3103,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *co ADJUST_LOCAL_OFFSET(dst, dstw); op = GET_OPCODE(op); - cc = get_cc(compiler, type & 0xff); + cc = get_cc(compiler, type); dst_reg = FAST_IS_REG(dst) ? dst : TMP_REG1; if (op < SLJIT_ADD) { @@ -2921,9 +3141,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_cmov(struct sljit_compiler *compil CHECK_ERROR(); CHECK(check_sljit_emit_cmov(compiler, type, dst_reg, src, srcw)); - dst_reg &= ~SLJIT_32; - - cc = get_cc(compiler, type & 0xff); + cc = get_cc(compiler, type & ~SLJIT_32); if (SLJIT_UNLIKELY(src & SLJIT_IMM)) { tmp = get_imm((sljit_uw)srcw); @@ -2949,15 +3167,284 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_cmov(struct sljit_compiler *compil return push_inst(compiler, ((MOV | RD(dst_reg) | RM(src)) & ~COND_MASK) | cc); } +static sljit_s32 update_mem_addr(struct sljit_compiler *compiler, sljit_s32 *mem, sljit_sw *memw, sljit_s32 max_offset) +{ + sljit_s32 arg = *mem; + sljit_sw argw = *memw; + sljit_uw imm, tmp; +#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) + sljit_sw mask = max_offset >= 0xf00 ? 0xfff : 0xff; + sljit_sw sign = max_offset >= 0xf00 ? 0x1000 : 0x100; +#else /* !SLJIT_CONFIG_ARM_V5 */ + sljit_sw mask = 0xfff; + sljit_sw sign = 0x1000; + + SLJIT_ASSERT(max_offset >= 0xf00); +#endif /* SLJIT_CONFIG_ARM_V5 */ + + *mem = TMP_REG1; + + if (SLJIT_UNLIKELY(arg & OFFS_REG_MASK)) { + *memw = 0; + return push_inst(compiler, ADD | RD(TMP_REG1) | RN(arg & REG_MASK) | RM(OFFS_REG(arg)) | ((sljit_uw)(argw & 0x3) << 7)); + } + + arg &= REG_MASK; + + if (arg) { + if (argw <= max_offset && argw >= -mask) { + *mem = arg; + return SLJIT_SUCCESS; + } + + if (argw >= 0) { + tmp = (sljit_uw)(argw & (sign | mask)); + tmp = (sljit_uw)((argw + ((tmp <= (sljit_uw)max_offset || tmp == (sljit_uw)sign) ? 0 : sign)) & ~mask); + imm = get_imm(tmp); + + if (imm) { + *memw = argw - (sljit_sw)tmp; + SLJIT_ASSERT(*memw >= -mask && *memw <= max_offset); + + return push_inst(compiler, ADD | RD(TMP_REG1) | RN(arg) | imm); + } + } else { + tmp = (sljit_uw)(-argw & (sign | mask)); + tmp = (sljit_uw)((-argw + ((tmp <= (sljit_uw)((sign << 1) - max_offset - 1)) ? 0 : sign)) & ~mask); + imm = get_imm(tmp); + + if (imm) { + *memw = argw + (sljit_sw)tmp; + SLJIT_ASSERT(*memw >= -mask && *memw <= max_offset); + + return push_inst(compiler, SUB | RD(TMP_REG1) | RN(arg) | imm); + } + } + } + + tmp = (sljit_uw)(argw & (sign | mask)); + tmp = (sljit_uw)((argw + ((tmp <= (sljit_uw)max_offset || tmp == (sljit_uw)sign) ? 0 : sign)) & ~mask); + *memw = argw - (sljit_sw)tmp; + + FAIL_IF(load_immediate(compiler, TMP_REG1, tmp)); + + if (arg == 0) + return SLJIT_SUCCESS; + + return push_inst(compiler, ADD | RD(TMP_REG1) | RN(TMP_REG1) | RM(arg)); +} + +#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) + +static sljit_s32 sljit_emit_mem_unaligned(struct sljit_compiler *compiler, sljit_s32 type, + sljit_s32 reg, + sljit_s32 mem, sljit_sw memw) +{ + sljit_s32 flags, steps, tmp_reg; + sljit_uw add, shift; + + switch (type & 0xff) { + case SLJIT_MOV_U8: + case SLJIT_MOV_S8: + flags = BYTE_SIZE; + if (!(type & SLJIT_MEM_STORE)) + flags |= LOAD_DATA; + if ((type & 0xff) == SLJIT_MOV_S8) + flags |= SIGNED; + + return emit_op_mem(compiler, flags, reg, mem, memw, TMP_REG1); + + case SLJIT_MOV_U16: + FAIL_IF(update_mem_addr(compiler, &mem, &memw, 0xfff - 1)); + flags = BYTE_SIZE; + steps = 1; + break; + + case SLJIT_MOV_S16: + FAIL_IF(update_mem_addr(compiler, &mem, &memw, 0xff - 1)); + flags = BYTE_SIZE | SIGNED; + steps = 1; + break; + + default: + if (type & SLJIT_MEM_UNALIGNED_32) { + flags = WORD_SIZE; + if (!(type & SLJIT_MEM_STORE)) + flags |= LOAD_DATA; + + return emit_op_mem(compiler, flags, reg, mem, memw, TMP_REG1); + } + + if (!(type & SLJIT_MEM_UNALIGNED_16)) { + FAIL_IF(update_mem_addr(compiler, &mem, &memw, 0xfff - 3)); + flags = BYTE_SIZE; + steps = 3; + break; + } + + FAIL_IF(update_mem_addr(compiler, &mem, &memw, 0xff - 2)); + + add = 1; + if (memw < 0) { + add = 0; + memw = -memw; + } + + tmp_reg = reg; + + if (type & SLJIT_MEM_STORE) { + FAIL_IF(push_inst(compiler, EMIT_DATA_TRANSFER(HALF_SIZE, add, reg, mem, TYPE2_TRANSFER_IMM(memw)))); + FAIL_IF(push_inst(compiler, MOV | RD(TMP_REG2) | RM(reg) | (16 << 7) | (2 << 4))); + } else { + if (reg == mem) { + SLJIT_ASSERT(reg != TMP_REG1); + tmp_reg = TMP_REG1; + } + + FAIL_IF(push_inst(compiler, EMIT_DATA_TRANSFER(HALF_SIZE | LOAD_DATA, add, tmp_reg, mem, TYPE2_TRANSFER_IMM(memw)))); + } + + if (!add) { + memw -= 2; + if (memw <= 0) { + memw = -memw; + add = 1; + } + } else + memw += 2; + + if (type & SLJIT_MEM_STORE) + return push_inst(compiler, EMIT_DATA_TRANSFER(HALF_SIZE, add, TMP_REG2, mem, TYPE2_TRANSFER_IMM(memw))); + + FAIL_IF(push_inst(compiler, EMIT_DATA_TRANSFER(HALF_SIZE | LOAD_DATA, add, TMP_REG2, mem, TYPE2_TRANSFER_IMM(memw)))); + return push_inst(compiler, ORR | RD(reg) | RN(tmp_reg) | RM(TMP_REG2) | (16 << 7)); + } + + SLJIT_ASSERT(steps > 0); + + add = 1; + if (memw < 0) { + add = 0; + memw = -memw; + } + + if (type & SLJIT_MEM_STORE) { + FAIL_IF(push_inst(compiler, EMIT_DATA_TRANSFER(BYTE_SIZE, add, reg, mem, memw))); + FAIL_IF(push_inst(compiler, MOV | RD(TMP_REG2) | RM(reg) | (8 << 7) | (2 << 4))); + + while (1) { + if (!add) { + memw -= 1; + if (memw == 0) + add = 1; + } else + memw += 1; + + FAIL_IF(push_inst(compiler, EMIT_DATA_TRANSFER(BYTE_SIZE, add, TMP_REG2, mem, memw))); + + if (--steps == 0) + return SLJIT_SUCCESS; + + FAIL_IF(push_inst(compiler, MOV | RD(TMP_REG2) | RM(TMP_REG2) | (8 << 7) | (2 << 4))); + } + } + + tmp_reg = reg; + + if (reg == mem) { + SLJIT_ASSERT(reg != TMP_REG1); + tmp_reg = TMP_REG1; + } + + shift = 8; + FAIL_IF(push_inst(compiler, EMIT_DATA_TRANSFER(BYTE_SIZE | LOAD_DATA, add, tmp_reg, mem, memw))); + + do { + if (!add) { + memw -= 1; + if (memw == 0) + add = 1; + } else + memw += 1; + + if (steps > 1) { + FAIL_IF(push_inst(compiler, EMIT_DATA_TRANSFER(BYTE_SIZE | LOAD_DATA, add, TMP_REG2, mem, memw))); + FAIL_IF(push_inst(compiler, ORR | RD(tmp_reg) | RN(tmp_reg) | RM(TMP_REG2) | (shift << 7))); + shift += 8; + } + } while (--steps != 0); + + flags |= LOAD_DATA; + + if (flags & SIGNED) + FAIL_IF(push_inst(compiler, EMIT_DATA_TRANSFER(flags, add, TMP_REG2, mem, TYPE2_TRANSFER_IMM(memw)))); + else + FAIL_IF(push_inst(compiler, EMIT_DATA_TRANSFER(flags, add, TMP_REG2, mem, memw))); + + return push_inst(compiler, ORR | RD(reg) | RN(tmp_reg) | RM(TMP_REG2) | (shift << 7)); +} + +#endif /* SLJIT_CONFIG_ARM_V5 */ + SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 reg, sljit_s32 mem, sljit_sw memw) { sljit_s32 flags; + + CHECK_ERROR(); + CHECK(check_sljit_emit_mem(compiler, type, reg, mem, memw)); + + if (!(reg & REG_PAIR_MASK)) { +#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) + ADJUST_LOCAL_OFFSET(mem, memw); +#endif /* SLJIT_CONFIG_ARM_V5 */ + + return sljit_emit_mem_unaligned(compiler, type, reg, mem, memw); + } + + ADJUST_LOCAL_OFFSET(mem, memw); + +#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) + if (type & (SLJIT_MEM_UNALIGNED | SLJIT_MEM_UNALIGNED_16)) { + FAIL_IF(update_mem_addr(compiler, &mem, &memw, (type & SLJIT_MEM_UNALIGNED_16) ? 0xfff - 6 : 0xfff - 7)); + + if (!(type & SLJIT_MEM_STORE) && REG_PAIR_FIRST(reg) == (mem & REG_MASK)) { + FAIL_IF(sljit_emit_mem_unaligned(compiler, type, REG_PAIR_SECOND(reg), SLJIT_MEM1(mem), memw + SSIZE_OF(sw))); + return sljit_emit_mem_unaligned(compiler, type, REG_PAIR_FIRST(reg), SLJIT_MEM1(mem), memw); + } + + FAIL_IF(sljit_emit_mem_unaligned(compiler, type, REG_PAIR_FIRST(reg), SLJIT_MEM1(mem), memw)); + return sljit_emit_mem_unaligned(compiler, type, REG_PAIR_SECOND(reg), SLJIT_MEM1(mem), memw + SSIZE_OF(sw)); + } +#endif /* SLJIT_CONFIG_ARM_V5 */ + + FAIL_IF(update_mem_addr(compiler, &mem, &memw, 0xfff - 4)); + + flags = WORD_SIZE; + + if (!(type & SLJIT_MEM_STORE)) { + if (REG_PAIR_FIRST(reg) == (mem & REG_MASK)) { + FAIL_IF(emit_op_mem(compiler, WORD_SIZE | LOAD_DATA, REG_PAIR_SECOND(reg), SLJIT_MEM1(mem), memw + SSIZE_OF(sw), TMP_REG1)); + return emit_op_mem(compiler, WORD_SIZE | LOAD_DATA, REG_PAIR_FIRST(reg), SLJIT_MEM1(mem), memw, TMP_REG1); + } + + flags = WORD_SIZE | LOAD_DATA; + } + + FAIL_IF(emit_op_mem(compiler, flags, REG_PAIR_FIRST(reg), SLJIT_MEM1(mem), memw, TMP_REG1)); + return emit_op_mem(compiler, flags, REG_PAIR_SECOND(reg), SLJIT_MEM1(mem), memw + SSIZE_OF(sw), TMP_REG1); +} + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem_update(struct sljit_compiler *compiler, sljit_s32 type, + sljit_s32 reg, + sljit_s32 mem, sljit_sw memw) +{ + sljit_s32 flags; sljit_uw is_type1_transfer, inst; CHECK_ERROR(); - CHECK(check_sljit_emit_mem(compiler, type, reg, mem, memw)); + CHECK(check_sljit_emit_mem_update(compiler, type, reg, mem, memw)); is_type1_transfer = 1; @@ -2999,16 +3486,12 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compile if (SLJIT_UNLIKELY(mem & OFFS_REG_MASK)) { if (!is_type1_transfer && memw != 0) return SLJIT_ERR_UNSUPPORTED; - } - else { + } else { if (is_type1_transfer) { if (memw > 4095 || memw < -4095) return SLJIT_ERR_UNSUPPORTED; - } - else { - if (memw > 255 || memw < -255) - return SLJIT_ERR_UNSUPPORTED; - } + } else if (memw > 255 || memw < -255) + return SLJIT_ERR_UNSUPPORTED; } if (type & SLJIT_MEM_SUPP) @@ -3022,20 +3505,20 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compile if (is_type1_transfer) inst |= (1 << 25); - if (type & SLJIT_MEM_PRE) - inst |= (1 << 21); - else + if (type & SLJIT_MEM_POST) inst ^= (1 << 24); + else + inst |= (1 << 21); return push_inst(compiler, inst); } inst = EMIT_DATA_TRANSFER(flags, 0, reg, mem & REG_MASK, 0); - if (type & SLJIT_MEM_PRE) - inst |= (1 << 21); - else + if (type & SLJIT_MEM_POST) inst ^= (1 << 24); + else + inst |= (1 << 21); if (is_type1_transfer) { if (memw >= 0) @@ -3054,6 +3537,103 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compile return push_inst(compiler, inst | TYPE2_TRANSFER_IMM((sljit_uw)memw)); } +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fmem(struct sljit_compiler *compiler, sljit_s32 type, + sljit_s32 freg, + sljit_s32 mem, sljit_sw memw) +{ +#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) + sljit_s32 max_offset; + sljit_s32 dst; +#endif /* SLJIT_CONFIG_ARM_V5 */ + + CHECK_ERROR(); + CHECK(check_sljit_emit_fmem(compiler, type, freg, mem, memw)); + + if (type & SLJIT_MEM_UNALIGNED_32) + return emit_fop_mem(compiler, ((type ^ SLJIT_32) & SLJIT_32) | ((type & SLJIT_MEM_STORE) ? 0 : FPU_LOAD), freg, mem, memw); + +#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) + if (type & SLJIT_MEM_STORE) { + FAIL_IF(push_inst(compiler, VMOV | (1 << 20) | VN(freg) | RD(TMP_REG2))); + + if (type & SLJIT_32) + return sljit_emit_mem_unaligned(compiler, SLJIT_MOV | SLJIT_MEM_STORE | (type & SLJIT_MEM_UNALIGNED_16), TMP_REG2, mem, memw); + + max_offset = 0xfff - 7; + if (type & SLJIT_MEM_UNALIGNED_16) + max_offset++; + + FAIL_IF(update_mem_addr(compiler, &mem, &memw, max_offset)); + mem |= SLJIT_MEM; + + FAIL_IF(sljit_emit_mem_unaligned(compiler, SLJIT_MOV | SLJIT_MEM_STORE | (type & SLJIT_MEM_UNALIGNED_16), TMP_REG2, mem, memw)); + + FAIL_IF(push_inst(compiler, VMOV | (1 << 20) | VN(freg) | 0x80 | RD(TMP_REG2))); + return sljit_emit_mem_unaligned(compiler, SLJIT_MOV | SLJIT_MEM_STORE | (type & SLJIT_MEM_UNALIGNED_16), TMP_REG2, mem, memw + 4); + } + + max_offset = (type & SLJIT_32) ? 0xfff - 3 : 0xfff - 7; + if (type & SLJIT_MEM_UNALIGNED_16) + max_offset++; + + FAIL_IF(update_mem_addr(compiler, &mem, &memw, max_offset)); + + dst = TMP_REG1; + + /* Stack offset adjustment is not needed because dst + is not stored on the stack when mem is SLJIT_SP. */ + + if (mem == TMP_REG1) { + dst = SLJIT_R3; + + if (compiler->scratches >= 4) + FAIL_IF(push_inst(compiler, STR | (1 << 21) | RN(SLJIT_SP) | RD(SLJIT_R3) | 8)); + } + + mem |= SLJIT_MEM; + + FAIL_IF(sljit_emit_mem_unaligned(compiler, SLJIT_MOV | (type & SLJIT_MEM_UNALIGNED_16), dst, mem, memw)); + FAIL_IF(push_inst(compiler, VMOV | VN(freg) | RD(dst))); + + if (!(type & SLJIT_32)) { + FAIL_IF(sljit_emit_mem_unaligned(compiler, SLJIT_MOV | (type & SLJIT_MEM_UNALIGNED_16), dst, mem, memw + 4)); + FAIL_IF(push_inst(compiler, VMOV | VN(freg) | 0x80 | RD(dst))); + } + + if (dst == SLJIT_R3 && compiler->scratches >= 4) + FAIL_IF(push_inst(compiler, (LDR ^ (0x1 << 24)) | (0x1 << 23) | RN(SLJIT_SP) | RD(SLJIT_R3) | 8)); + return SLJIT_SUCCESS; +#else /* !SLJIT_CONFIG_ARM_V5 */ + if (type & SLJIT_MEM_STORE) { + FAIL_IF(push_inst(compiler, VMOV | (1 << 20) | VN(freg) | RD(TMP_REG2))); + + if (type & SLJIT_32) + return emit_op_mem(compiler, WORD_SIZE, TMP_REG2, mem, memw, TMP_REG1); + + FAIL_IF(update_mem_addr(compiler, &mem, &memw, 0xfff - 4)); + mem |= SLJIT_MEM; + + FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_REG2, mem, memw, TMP_REG1)); + FAIL_IF(push_inst(compiler, VMOV | (1 << 20) | VN(freg) | 0x80 | RD(TMP_REG2))); + return emit_op_mem(compiler, WORD_SIZE, TMP_REG2, mem, memw + 4, TMP_REG1); + } + + if (type & SLJIT_32) { + FAIL_IF(emit_op_mem(compiler, WORD_SIZE | LOAD_DATA, TMP_REG2, mem, memw, TMP_REG1)); + return push_inst(compiler, VMOV | VN(freg) | RD(TMP_REG2)); + } + + FAIL_IF(update_mem_addr(compiler, &mem, &memw, 0xfff - 4)); + mem |= SLJIT_MEM; + + FAIL_IF(emit_op_mem(compiler, WORD_SIZE | LOAD_DATA, TMP_REG2, mem, memw, TMP_REG1)); + FAIL_IF(emit_op_mem(compiler, WORD_SIZE | LOAD_DATA, TMP_REG1, mem, memw + 4, TMP_REG1)); + return push_inst(compiler, VMOV2 | VM(freg) | RD(TMP_REG2) | RN(TMP_REG1)); +#endif /* SLJIT_CONFIG_ARM_V5 */ +} + +#undef FPU_LOAD + SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw init_value) { struct sljit_const *const_; diff --git a/src/3rdparty/pcre2/src/sljit/sljitNativeARM_64.c b/src/3rdparty/pcre2/src/sljit/sljitNativeARM_64.c index 96453b4abeb..89f747e7c89 100644 --- a/src/3rdparty/pcre2/src/sljit/sljitNativeARM_64.c +++ b/src/3rdparty/pcre2/src/sljit/sljitNativeARM_64.c @@ -86,6 +86,7 @@ static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 3] = { #define CSINC 0x9a800400 #define EOR 0xca000000 #define EORI 0xd2000000 +#define EXTR 0x93c00000 #define FABS 0x1e60c000 #define FADD 0x1e602800 #define FCMP 0x1e602000 @@ -98,6 +99,7 @@ static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 3] = { #define FSUB 0x1e603800 #define LDRI 0xf9400000 #define LDRI_F64 0xfd400000 +#define LDRI_POST 0xf8400400 #define LDP 0xa9400000 #define LDP_F64 0x6d400000 #define LDP_POST 0xa8c00000 @@ -112,7 +114,9 @@ static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 3] = { #define ORN 0xaa200000 #define ORR 0xaa000000 #define ORRI 0xb2000000 +#define RBIT 0xdac00000 #define RET 0xd65f0000 +#define RORV 0x9ac02c00 #define SBC 0xda000000 #define SBFM 0x93000000 #define SCVTF 0x9e620000 @@ -137,8 +141,6 @@ static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 3] = { #define UDIV 0x9ac00800 #define UMULH 0x9bc03c00 -/* dest_reg is the absolute name of the register - Useful for reordering instructions in the delay slot. */ static sljit_s32 push_inst(struct sljit_compiler *compiler, sljit_ins ins) { sljit_ins *ptr = (sljit_ins*)ensure_buf(compiler, sizeof(sljit_ins)); @@ -296,8 +298,8 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil } next_addr = compute_next_addr(label, jump, const_, put_label); } - code_ptr ++; - word_count ++; + code_ptr++; + word_count++; } while (buf_ptr < buf_end); buf = buf->next; @@ -391,6 +393,8 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type) #endif case SLJIT_HAS_CLZ: + case SLJIT_HAS_CTZ: + case SLJIT_HAS_ROT: case SLJIT_HAS_CMOV: case SLJIT_HAS_PREFETCH: return 1; @@ -631,6 +635,7 @@ static sljit_s32 emit_op_imm(struct sljit_compiler *compiler, sljit_s32 flags, s switch (op) { case SLJIT_MUL: case SLJIT_CLZ: + case SLJIT_CTZ: case SLJIT_ADDC: case SLJIT_SUBC: /* No form with immediate operand (except imm 0, which @@ -701,36 +706,50 @@ static sljit_s32 emit_op_imm(struct sljit_compiler *compiler, sljit_s32 flags, s FAIL_IF(push_inst(compiler, (inst_bits ^ inv_bits) | RD(dst) | RN(reg))); goto set_flags; case SLJIT_SHL: + case SLJIT_MSHL: if (flags & ARG1_IMM) break; + if (flags & INT_OP) { imm &= 0x1f; - FAIL_IF(push_inst(compiler, (UBFM ^ inv_bits) | RD(dst) | RN(arg1) - | (((sljit_ins)-imm & 0x1f) << 16) | ((31 - (sljit_ins)imm) << 10))); - } - else { + inst_bits = (((sljit_ins)-imm & 0x1f) << 16) | ((31 - (sljit_ins)imm) << 10); + } else { imm &= 0x3f; - FAIL_IF(push_inst(compiler, (UBFM ^ inv_bits) | RD(dst) | RN(arg1) | (1 << 22) - | (((sljit_ins)-imm & 0x3f) << 16) | ((63 - (sljit_ins)imm) << 10))); + inst_bits = ((sljit_ins)1 << 22) | (((sljit_ins)-imm & 0x3f) << 16) | ((63 - (sljit_ins)imm) << 10); } + + FAIL_IF(push_inst(compiler, (UBFM ^ inv_bits) | RD(dst) | RN(arg1) | inst_bits)); goto set_flags; case SLJIT_LSHR: + case SLJIT_MLSHR: case SLJIT_ASHR: + case SLJIT_MASHR: if (flags & ARG1_IMM) break; - if (op == SLJIT_ASHR) + + if (op >= SLJIT_ASHR) inv_bits |= 1 << 30; + if (flags & INT_OP) { imm &= 0x1f; - FAIL_IF(push_inst(compiler, (UBFM ^ inv_bits) | RD(dst) | RN(arg1) - | ((sljit_ins)imm << 16) | (31 << 10))); - } - else { + inst_bits = ((sljit_ins)imm << 16) | (31 << 10); + } else { imm &= 0x3f; - FAIL_IF(push_inst(compiler, (UBFM ^ inv_bits) | RD(dst) | RN(arg1) - | (1 << 22) | ((sljit_ins)imm << 16) | (63 << 10))); + inst_bits = ((sljit_ins)1 << 22) | ((sljit_ins)imm << 16) | (63 << 10); } + + FAIL_IF(push_inst(compiler, (UBFM ^ inv_bits) | RD(dst) | RN(arg1) | inst_bits)); goto set_flags; + case SLJIT_ROTL: + case SLJIT_ROTR: + if (flags & ARG1_IMM) + break; + + if (op == SLJIT_ROTL) + imm = -imm; + + imm &= (flags & INT_OP) ? 0x1f : 0x3f; + return push_inst(compiler, (EXTR ^ (inv_bits | (inv_bits >> 9))) | RD(dst) | RN(arg1) | RM(arg1) | ((sljit_ins)imm << 10)); default: SLJIT_UNREACHABLE(); break; @@ -796,6 +815,10 @@ static sljit_s32 emit_op_imm(struct sljit_compiler *compiler, sljit_s32 flags, s case SLJIT_CLZ: SLJIT_ASSERT(arg1 == TMP_REG1); return push_inst(compiler, (CLZ ^ inv_bits) | RD(dst) | RN(arg2)); + case SLJIT_CTZ: + SLJIT_ASSERT(arg1 == TMP_REG1); + FAIL_IF(push_inst(compiler, (RBIT ^ inv_bits) | RD(dst) | RN(arg2))); + return push_inst(compiler, (CLZ ^ inv_bits) | RD(dst) | RN(dst)); case SLJIT_ADD: compiler->status_flags_state = SLJIT_CURRENT_FLAGS_ADD; CHECK_FLAGS(1 << 29); @@ -834,14 +857,23 @@ static sljit_s32 emit_op_imm(struct sljit_compiler *compiler, sljit_s32 flags, s FAIL_IF(push_inst(compiler, (EOR ^ inv_bits) | RD(dst) | RN(arg1) | RM(arg2))); break; /* Set flags. */ case SLJIT_SHL: + case SLJIT_MSHL: FAIL_IF(push_inst(compiler, (LSLV ^ inv_bits) | RD(dst) | RN(arg1) | RM(arg2))); break; /* Set flags. */ case SLJIT_LSHR: + case SLJIT_MLSHR: FAIL_IF(push_inst(compiler, (LSRV ^ inv_bits) | RD(dst) | RN(arg1) | RM(arg2))); break; /* Set flags. */ case SLJIT_ASHR: + case SLJIT_MASHR: FAIL_IF(push_inst(compiler, (ASRV ^ inv_bits) | RD(dst) | RN(arg1) | RM(arg2))); break; /* Set flags. */ + case SLJIT_ROTL: + FAIL_IF(push_inst(compiler, (SUB ^ inv_bits) | RD(TMP_REG2) | RN(TMP_ZERO) | RM(arg2))); + arg2 = TMP_REG2; + /* fallthrough */ + case SLJIT_ROTR: + return push_inst(compiler, (RORV ^ inv_bits) | RD(dst) | RN(arg1) | RM(arg2)); default: SLJIT_UNREACHABLE(); return SLJIT_SUCCESS; @@ -895,21 +927,37 @@ static sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit_s32 flags, s return push_inst(compiler, STRBI | type | RT(reg) | RN(tmp_reg) | ((sljit_ins)argw << 10)); } - if (argw >= 0 && (argw & ((1 << shift) - 1)) == 0) { - if ((argw >> shift) <= 0xfff) - return push_inst(compiler, STRBI | type | RT(reg) | RN(arg) | ((sljit_ins)argw << (10 - shift))); + if ((argw & ((1 << shift) - 1)) == 0) { + if (argw >= 0) { + if ((argw >> shift) <= 0xfff) + return push_inst(compiler, STRBI | type | RT(reg) | RN(arg) | ((sljit_ins)argw << (10 - shift))); - if (argw <= 0xffffff) { - FAIL_IF(push_inst(compiler, ADDI | (1 << 22) | RD(tmp_reg) | RN(arg) | (((sljit_ins)argw >> 12) << 10))); + if (argw <= 0xffffff) { + FAIL_IF(push_inst(compiler, ADDI | (1 << 22) | RD(tmp_reg) | RN(arg) | (((sljit_ins)argw >> 12) << 10))); - argw = ((argw & 0xfff) >> shift); + argw = ((argw & 0xfff) >> shift); + return push_inst(compiler, STRBI | type | RT(reg) | RN(tmp_reg) | ((sljit_ins)argw << 10)); + } + } else if (argw < -256 && argw >= -0xfff000) { + FAIL_IF(push_inst(compiler, SUBI | (1 << 22) | RD(tmp_reg) | RN(arg) | (((sljit_ins)(-argw + 0xfff) >> 12) << 10))); + argw = ((0x1000 + argw) & 0xfff) >> shift; return push_inst(compiler, STRBI | type | RT(reg) | RN(tmp_reg) | ((sljit_ins)argw << 10)); } } - if (argw <= 255 && argw >= -256) + if (argw <= 0xff && argw >= -0x100) return push_inst(compiler, STURBI | type | RT(reg) | RN(arg) | (((sljit_ins)argw & 0x1ff) << 12)); + if (argw >= 0) { + if (argw <= 0xfff0ff && ((argw + 0x100) & 0xfff) <= 0x1ff) { + FAIL_IF(push_inst(compiler, ADDI | (1 << 22) | RD(tmp_reg) | RN(arg) | (((sljit_ins)argw >> 12) << 10))); + return push_inst(compiler, STURBI | type | RT(reg) | RN(tmp_reg) | (((sljit_ins)argw & 0x1ff) << 12)); + } + } else if (argw >= -0xfff100 && ((-argw + 0xff) & 0xfff) <= 0x1ff) { + FAIL_IF(push_inst(compiler, SUBI | (1 << 22) | RD(tmp_reg) | RN(arg) | (((sljit_ins)-argw >> 12) << 10))); + return push_inst(compiler, STURBI | type | RT(reg) | RN(tmp_reg) | (((sljit_ins)argw & 0x1ff) << 12)); + } + FAIL_IF(load_immediate(compiler, tmp_reg, argw)); return push_inst(compiler, STRB | type | RT(reg) | RN(arg) | RM(tmp_reg)); @@ -924,14 +972,14 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size) { sljit_s32 prev, fprev, saved_regs_size, i, tmp; - sljit_s32 word_arg_count = 0; + sljit_s32 saved_arg_count = SLJIT_KEPT_SAVEDS_COUNT(options); sljit_ins offs; CHECK_ERROR(); CHECK(check_sljit_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size)); set_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size); - saved_regs_size = GET_SAVED_REGISTERS_SIZE(scratches, saveds, 2); + saved_regs_size = GET_SAVED_REGISTERS_SIZE(scratches, saveds - saved_arg_count, 2); saved_regs_size += GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, SSIZE_OF(f64)); local_size = (local_size + saved_regs_size + 0xf) & ~0xf; @@ -954,7 +1002,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi prev = -1; tmp = SLJIT_S0 - saveds; - for (i = SLJIT_S0; i > tmp; i--) { + for (i = SLJIT_S0 - saved_arg_count; i > tmp; i--) { if (prev == -1) { prev = i; continue; @@ -1003,23 +1051,27 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi if (prev != -1) FAIL_IF(push_inst(compiler, STRI | RT(prev) | RN(SLJIT_SP) | (offs >> 5) | ((fprev == -1) ? (1 << 10) : 0))); - arg_types >>= SLJIT_ARG_SHIFT; #ifdef _WIN32 if (local_size > 4096) FAIL_IF(push_inst(compiler, SUBI | RD(SLJIT_SP) | RN(SLJIT_SP) | (1 << 10) | (1 << 22))); #endif /* _WIN32 */ - tmp = 0; - while (arg_types > 0) { - if ((arg_types & SLJIT_ARG_MASK) < SLJIT_ARG_TYPE_F64) { - if (!(arg_types & SLJIT_ARG_TYPE_SCRATCH_REG)) { - FAIL_IF(push_inst(compiler, ORR | RD(SLJIT_S0 - tmp) | RN(TMP_ZERO) | RM(SLJIT_R0 + word_arg_count))); + if (!(options & SLJIT_ENTER_REG_ARG)) { + arg_types >>= SLJIT_ARG_SHIFT; + saved_arg_count = 0; + tmp = SLJIT_R0; + + while (arg_types) { + if ((arg_types & SLJIT_ARG_MASK) < SLJIT_ARG_TYPE_F64) { + if (!(arg_types & SLJIT_ARG_TYPE_SCRATCH_REG)) { + FAIL_IF(push_inst(compiler, ORR | RD(SLJIT_S0 - saved_arg_count) | RN(TMP_ZERO) | RM(tmp))); + saved_arg_count++; + } tmp++; } - word_arg_count++; + arg_types >>= SLJIT_ARG_SHIFT; } - arg_types >>= SLJIT_ARG_SHIFT; } #ifdef _WIN32 @@ -1100,26 +1152,34 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *comp CHECK(check_sljit_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size)); set_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size); - saved_regs_size = GET_SAVED_REGISTERS_SIZE(scratches, saveds, 2); + saved_regs_size = GET_SAVED_REGISTERS_SIZE(scratches, saveds - SLJIT_KEPT_SAVEDS_COUNT(options), 2); saved_regs_size += GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, SSIZE_OF(f64)); compiler->local_size = (local_size + saved_regs_size + 0xf) & ~0xf; return SLJIT_SUCCESS; } -static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler) +static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler, sljit_s32 is_return_to) { sljit_s32 local_size, prev, fprev, i, tmp; sljit_ins offs; local_size = compiler->local_size; - if (local_size > 512 && local_size <= 512 + 496) { - FAIL_IF(push_inst(compiler, LDP_POST | RT(TMP_FP) | RT2(TMP_LR) - | RN(SLJIT_SP) | ((sljit_ins)(local_size - 512) << (15 - 3)))); - local_size = 512; - } else - FAIL_IF(push_inst(compiler, LDP | RT(TMP_FP) | RT2(TMP_LR) | RN(SLJIT_SP))); + if (!is_return_to) { + if (local_size > 512 && local_size <= 512 + 496) { + FAIL_IF(push_inst(compiler, LDP_POST | RT(TMP_FP) | RT2(TMP_LR) + | RN(SLJIT_SP) | ((sljit_ins)(local_size - 512) << (15 - 3)))); + local_size = 512; + } else + FAIL_IF(push_inst(compiler, LDP | RT(TMP_FP) | RT2(TMP_LR) | RN(SLJIT_SP))); + } else { + if (local_size > 512 && local_size <= 512 + 248) { + FAIL_IF(push_inst(compiler, LDRI_POST | RT(TMP_FP) | RN(SLJIT_SP) | ((sljit_ins)(local_size - 512) << 12))); + local_size = 512; + } else + FAIL_IF(push_inst(compiler, LDRI | RT(TMP_FP) | RN(SLJIT_SP) | 0)); + } if (local_size > 512) { local_size -= 512; @@ -1137,7 +1197,7 @@ static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler) prev = -1; tmp = SLJIT_S0 - compiler->saveds; - for (i = SLJIT_S0; i > tmp; i--) { + for (i = SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options); i > tmp; i--) { if (prev == -1) { prev = i; continue; @@ -1195,11 +1255,34 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_void(struct sljit_compiler CHECK_ERROR(); CHECK(check_sljit_emit_return_void(compiler)); - FAIL_IF(emit_stack_frame_release(compiler)); + FAIL_IF(emit_stack_frame_release(compiler, 0)); return push_inst(compiler, RET | RN(TMP_LR)); } +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_to(struct sljit_compiler *compiler, + sljit_s32 src, sljit_sw srcw) +{ + CHECK_ERROR(); + CHECK(check_sljit_emit_return_to(compiler, src, srcw)); + + if (src & SLJIT_MEM) { + ADJUST_LOCAL_OFFSET(src, srcw); + FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_REG1, src, srcw, TMP_REG1)); + src = TMP_REG1; + srcw = 0; + } else if (src >= SLJIT_FIRST_SAVED_REG && src <= (SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options))) { + FAIL_IF(push_inst(compiler, ORR | RD(TMP_REG1) | RN(TMP_ZERO) | RM(src))); + src = TMP_REG1; + srcw = 0; + } + + FAIL_IF(emit_stack_frame_release(compiler, 1)); + + SLJIT_SKIP_CHECKS(compiler); + return sljit_emit_ijump(compiler, SLJIT_JUMP, src, srcw); +} + /* --------------------------------------------------------------------- */ /* Operators */ /* --------------------------------------------------------------------- */ @@ -1392,13 +1475,84 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2u(struct sljit_compiler *compil CHECK_ERROR(); CHECK(check_sljit_emit_op2(compiler, op, 1, 0, 0, src1, src1w, src2, src2w)); -#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \ - || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) - compiler->skip_checks = 1; -#endif + SLJIT_SKIP_CHECKS(compiler); return sljit_emit_op2(compiler, op, TMP_REG1, 0, src1, src1w, src2, src2w); } +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_shift_into(struct sljit_compiler *compiler, sljit_s32 op, + sljit_s32 src_dst, + sljit_s32 src1, sljit_sw src1w, + sljit_s32 src2, sljit_sw src2w) +{ + sljit_ins inv_bits, imm; + sljit_s32 is_left; + sljit_sw mask; + + CHECK_ERROR(); + CHECK(check_sljit_emit_shift_into(compiler, op, src_dst, src1, src1w, src2, src2w)); + + is_left = (GET_OPCODE(op) == SLJIT_SHL || GET_OPCODE(op) == SLJIT_MSHL); + + if (src_dst == src1) { + SLJIT_SKIP_CHECKS(compiler); + return sljit_emit_op2(compiler, (is_left ? SLJIT_ROTL : SLJIT_ROTR) | (op & SLJIT_32), src_dst, 0, src_dst, 0, src2, src2w); + } + + ADJUST_LOCAL_OFFSET(src1, src1w); + ADJUST_LOCAL_OFFSET(src2, src2w); + + inv_bits = (op & SLJIT_32) ? W_OP : 0; + mask = inv_bits ? 0x1f : 0x3f; + + if (src2 & SLJIT_IMM) { + src2w &= mask; + + if (src2w == 0) + return SLJIT_SUCCESS; + } else if (src2 & SLJIT_MEM) { + FAIL_IF(emit_op_mem(compiler, inv_bits ? INT_SIZE : WORD_SIZE, TMP_REG2, src2, src2w, TMP_REG2)); + src2 = TMP_REG2; + } + + if (src1 & SLJIT_MEM) { + FAIL_IF(emit_op_mem(compiler, inv_bits ? INT_SIZE : WORD_SIZE, TMP_REG1, src1, src1w, TMP_REG1)); + src1 = TMP_REG1; + } else if (src1 & SLJIT_IMM) { + FAIL_IF(load_immediate(compiler, TMP_REG1, src1w)); + src1 = TMP_REG1; + } + + if (src2 & SLJIT_IMM) { + if (is_left) + src2w = (src2w ^ mask) + 1; + + return push_inst(compiler, (EXTR ^ (inv_bits | (inv_bits >> 9))) | RD(src_dst) + | RN(is_left ? src_dst : src1) | RM(is_left ? src1 : src_dst) | ((sljit_ins)src2w << 10)); + } + + FAIL_IF(push_inst(compiler, ((is_left ? LSLV : LSRV) ^ inv_bits) | RD(src_dst) | RN(src_dst) | RM(src2))); + + if (!(op & SLJIT_SHIFT_INTO_NON_ZERO)) { + /* Shift left/right by 1. */ + if (is_left) + imm = (sljit_ins)(inv_bits ? ((1 << 16) | (31 << 10)) : ((1 << 16) | (63 << 10) | (1 << 22))); + else + imm = (sljit_ins)(inv_bits ? ((31 << 16) | (30 << 10)) : ((63 << 16) | (62 << 10) | (1 << 22))); + + FAIL_IF(push_inst(compiler, (UBFM ^ inv_bits) | RD(TMP_REG1) | RN(src1) | imm)); + + /* Set imm to mask. */ + imm = (sljit_ins)(inv_bits ? (4 << 10) : ((5 << 10) | (1 << 22))); + FAIL_IF(push_inst(compiler, (EORI ^ inv_bits) | RD(TMP_REG2) | RN(src2) | imm)); + + src1 = TMP_REG1; + } else + FAIL_IF(push_inst(compiler, (SUB ^ inv_bits) | RD(TMP_REG2) | RN(TMP_ZERO) | RM(src2))); + + FAIL_IF(push_inst(compiler, ((is_left ? LSRV : LSLV) ^ inv_bits) | RD(TMP_REG1) | RN(src1) | RM(TMP_REG2))); + return push_inst(compiler, (ORR ^ inv_bits) | RD(src_dst) | RN(src_dst) | RM(TMP_REG1)); +} + SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_src(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 src, sljit_sw srcw) { @@ -1550,10 +1704,9 @@ static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_sw(struct sljit_comp emit_op_mem(compiler, ((GET_OPCODE(op) == SLJIT_CONV_F64_FROM_S32) ? INT_SIZE : WORD_SIZE), TMP_REG1, src, srcw, TMP_REG1); src = TMP_REG1; } else if (src & SLJIT_IMM) { -#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_S32) srcw = (sljit_s32)srcw; -#endif + FAIL_IF(load_immediate(compiler, TMP_REG1, srcw)); src = TMP_REG1; } @@ -1699,11 +1852,15 @@ static sljit_ins get_cc(struct sljit_compiler *compiler, sljit_s32 type) { switch (type) { case SLJIT_EQUAL: - case SLJIT_EQUAL_F64: + case SLJIT_F_EQUAL: + case SLJIT_ORDERED_EQUAL: + case SLJIT_UNORDERED_OR_EQUAL: /* Not supported. */ return 0x1; case SLJIT_NOT_EQUAL: - case SLJIT_NOT_EQUAL_F64: + case SLJIT_F_NOT_EQUAL: + case SLJIT_UNORDERED_OR_NOT_EQUAL: + case SLJIT_ORDERED_NOT_EQUAL: /* Not supported. */ return 0x0; case SLJIT_CARRY: @@ -1712,7 +1869,6 @@ static sljit_ins get_cc(struct sljit_compiler *compiler, sljit_s32 type) /* fallthrough */ case SLJIT_LESS: - case SLJIT_LESS_F64: return 0x2; case SLJIT_NOT_CARRY: @@ -1721,27 +1877,33 @@ static sljit_ins get_cc(struct sljit_compiler *compiler, sljit_s32 type) /* fallthrough */ case SLJIT_GREATER_EQUAL: - case SLJIT_GREATER_EQUAL_F64: return 0x3; case SLJIT_GREATER: - case SLJIT_GREATER_F64: + case SLJIT_UNORDERED_OR_GREATER: return 0x9; case SLJIT_LESS_EQUAL: - case SLJIT_LESS_EQUAL_F64: + case SLJIT_F_LESS_EQUAL: + case SLJIT_ORDERED_LESS_EQUAL: return 0x8; case SLJIT_SIG_LESS: + case SLJIT_UNORDERED_OR_LESS: return 0xa; case SLJIT_SIG_GREATER_EQUAL: + case SLJIT_F_GREATER_EQUAL: + case SLJIT_ORDERED_GREATER_EQUAL: return 0xb; case SLJIT_SIG_GREATER: + case SLJIT_F_GREATER: + case SLJIT_ORDERED_GREATER: return 0xd; case SLJIT_SIG_LESS_EQUAL: + case SLJIT_UNORDERED_OR_LESS_EQUAL: return 0xc; case SLJIT_OVERFLOW: @@ -1749,7 +1911,7 @@ static sljit_ins get_cc(struct sljit_compiler *compiler, sljit_s32 type) return 0x0; /* fallthrough */ - case SLJIT_UNORDERED_F64: + case SLJIT_UNORDERED: return 0x7; case SLJIT_NOT_OVERFLOW: @@ -1757,9 +1919,16 @@ static sljit_ins get_cc(struct sljit_compiler *compiler, sljit_s32 type) return 0x1; /* fallthrough */ - case SLJIT_ORDERED_F64: + case SLJIT_ORDERED: return 0x6; + case SLJIT_F_LESS: + case SLJIT_ORDERED_LESS: + return 0x5; + + case SLJIT_UNORDERED_OR_GREATER_EQUAL: + return 0x4; + default: SLJIT_UNREACHABLE(); return 0xe; @@ -1816,15 +1985,11 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compile CHECK_PTR(check_sljit_emit_call(compiler, type, arg_types)); if (type & SLJIT_CALL_RETURN) { - PTR_FAIL_IF(emit_stack_frame_release(compiler)); + PTR_FAIL_IF(emit_stack_frame_release(compiler, 0)); type = SLJIT_JUMP | (type & SLJIT_REWRITABLE_JUMP); } -#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \ - || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) - compiler->skip_checks = 1; -#endif - + SLJIT_SKIP_CHECKS(compiler); return sljit_emit_jump(compiler, type); } @@ -1869,10 +2034,10 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compi CHECK_ERROR(); CHECK(check_sljit_emit_ijump(compiler, type, src, srcw)); - ADJUST_LOCAL_OFFSET(src, srcw); if (!(src & SLJIT_IMM)) { if (src & SLJIT_MEM) { + ADJUST_LOCAL_OFFSET(src, srcw); FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_REG1, src, srcw, TMP_REG1)); src = TMP_REG1; } @@ -1897,28 +2062,24 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compi SLJIT_UNUSED_ARG(arg_types); CHECK_ERROR(); CHECK(check_sljit_emit_icall(compiler, type, arg_types, src, srcw)); - ADJUST_LOCAL_OFFSET(src, srcw); if (src & SLJIT_MEM) { + ADJUST_LOCAL_OFFSET(src, srcw); FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_REG1, src, srcw, TMP_REG1)); src = TMP_REG1; } if (type & SLJIT_CALL_RETURN) { - if (src >= SLJIT_FIRST_SAVED_REG && src <= SLJIT_S0) { + if (src >= SLJIT_FIRST_SAVED_REG && src <= (SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options))) { FAIL_IF(push_inst(compiler, ORR | RD(TMP_REG1) | RN(TMP_ZERO) | RM(src))); src = TMP_REG1; } - FAIL_IF(emit_stack_frame_release(compiler)); + FAIL_IF(emit_stack_frame_release(compiler, 0)); type = SLJIT_JUMP; } -#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \ - || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) - compiler->skip_checks = 1; -#endif - + SLJIT_SKIP_CHECKS(compiler); return sljit_emit_ijump(compiler, type, src, srcw); } @@ -1933,7 +2094,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *co CHECK(check_sljit_emit_op_flags(compiler, op, dst, dstw, type)); ADJUST_LOCAL_OFFSET(dst, dstw); - cc = get_cc(compiler, type & 0xff); + cc = get_cc(compiler, type); dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1; if (GET_OPCODE(op) < SLJIT_ADD) { @@ -1974,22 +2135,21 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_cmov(struct sljit_compiler *compil sljit_s32 dst_reg, sljit_s32 src, sljit_sw srcw) { - sljit_ins inv_bits = (dst_reg & SLJIT_32) ? W_OP : 0; + sljit_ins inv_bits = (type & SLJIT_32) ? W_OP : 0; sljit_ins cc; CHECK_ERROR(); CHECK(check_sljit_emit_cmov(compiler, type, dst_reg, src, srcw)); if (SLJIT_UNLIKELY(src & SLJIT_IMM)) { - if (dst_reg & SLJIT_32) + if (type & SLJIT_32) srcw = (sljit_s32)srcw; FAIL_IF(load_immediate(compiler, TMP_REG1, srcw)); src = TMP_REG1; srcw = 0; } - cc = get_cc(compiler, type & 0xff); - dst_reg &= ~SLJIT_32; + cc = get_cc(compiler, type & ~SLJIT_32); return push_inst(compiler, (CSEL ^ inv_bits) | (cc << 12) | RD(dst_reg) | RN(dst_reg) | RM(src)); } @@ -1998,11 +2158,82 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compile sljit_s32 reg, sljit_s32 mem, sljit_sw memw) { - sljit_u32 sign = 0, inst; + sljit_u32 inst; CHECK_ERROR(); CHECK(check_sljit_emit_mem(compiler, type, reg, mem, memw)); + if (!(reg & REG_PAIR_MASK)) + return sljit_emit_mem_unaligned(compiler, type, reg, mem, memw); + + ADJUST_LOCAL_OFFSET(mem, memw); + + if (!(mem & REG_MASK)) { + FAIL_IF(load_immediate(compiler, TMP_REG1, memw & ~0x1f8)); + + mem = SLJIT_MEM1(TMP_REG1); + memw &= 0x1f8; + } else if (mem & OFFS_REG_MASK) { + FAIL_IF(push_inst(compiler, ADD | RD(TMP_REG1) | RN(mem & REG_MASK) | RM(OFFS_REG(mem)) | ((sljit_ins)(memw & 0x3) << 10))); + + mem = SLJIT_MEM1(TMP_REG1); + memw = 0; + } else if ((memw & 0x7) != 0 || memw > 0x1f8 || memw < -0x200) { + inst = ADDI; + + if (memw < 0) { + /* Remains negative for integer min. */ + memw = -memw; + inst = SUBI; + } else if ((memw & 0x7) == 0 && memw <= 0x7ff0) { + if (!(type & SLJIT_MEM_STORE) && (mem & REG_MASK) == REG_PAIR_FIRST(reg)) { + FAIL_IF(push_inst(compiler, LDRI | RD(REG_PAIR_SECOND(reg)) | RN(mem & REG_MASK) | ((sljit_ins)memw << 7))); + return push_inst(compiler, LDRI | RD(REG_PAIR_FIRST(reg)) | RN(mem & REG_MASK) | ((sljit_ins)(memw + 0x8) << 7)); + } + + inst = (type & SLJIT_MEM_STORE) ? STRI : LDRI; + + FAIL_IF(push_inst(compiler, inst | RD(REG_PAIR_FIRST(reg)) | RN(mem & REG_MASK) | ((sljit_ins)memw << 7))); + return push_inst(compiler, inst | RD(REG_PAIR_SECOND(reg)) | RN(mem & REG_MASK) | ((sljit_ins)(memw + 0x8) << 7)); + } + + if ((sljit_uw)memw <= 0xfff) { + FAIL_IF(push_inst(compiler, inst | RD(TMP_REG1) | RN(mem & REG_MASK) | ((sljit_ins)memw << 10))); + memw = 0; + } else if ((sljit_uw)memw <= 0xffffff) { + FAIL_IF(push_inst(compiler, inst | (1 << 22) | RD(TMP_REG1) | RN(mem & REG_MASK) | (((sljit_ins)memw >> 12) << 10))); + + if ((memw & 0xe07) != 0) { + FAIL_IF(push_inst(compiler, inst | RD(TMP_REG1) | RN(TMP_REG1) | (((sljit_ins)memw & 0xfff) << 10))); + memw = 0; + } else { + memw &= 0xfff; + } + } else { + FAIL_IF(load_immediate(compiler, TMP_REG1, memw)); + FAIL_IF(push_inst(compiler, (inst == ADDI ? ADD : SUB) | RD(TMP_REG1) | RN(mem & REG_MASK) | RM(TMP_REG1))); + memw = 0; + } + + mem = SLJIT_MEM1(TMP_REG1); + + if (inst == SUBI) + memw = -memw; + } + + SLJIT_ASSERT((memw & 0x7) == 0 && memw <= 0x1f8 && memw >= -0x200); + return push_inst(compiler, ((type & SLJIT_MEM_STORE) ? STP : LDP) | RT(REG_PAIR_FIRST(reg)) | RT2(REG_PAIR_SECOND(reg)) | RN(mem & REG_MASK) | (sljit_ins)((memw & 0x3f8) << 12)); +} + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem_update(struct sljit_compiler *compiler, sljit_s32 type, + sljit_s32 reg, + sljit_s32 mem, sljit_sw memw) +{ + sljit_u32 sign = 0, inst; + + CHECK_ERROR(); + CHECK(check_sljit_emit_mem_update(compiler, type, reg, mem, memw)); + if ((mem & OFFS_REG_MASK) || (memw > 255 || memw < -256)) return SLJIT_ERR_UNSUPPORTED; @@ -2042,20 +2273,20 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compile if (!(type & SLJIT_MEM_STORE)) inst |= sign ? 0x00800000 : 0x00400000; - if (type & SLJIT_MEM_PRE) + if (!(type & SLJIT_MEM_POST)) inst |= 0x800; return push_inst(compiler, inst | RT(reg) | RN(mem & REG_MASK) | (sljit_ins)((memw & 0x1ff) << 12)); } -SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fmem(struct sljit_compiler *compiler, sljit_s32 type, +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fmem_update(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 freg, sljit_s32 mem, sljit_sw memw) { sljit_u32 inst; CHECK_ERROR(); - CHECK(check_sljit_emit_fmem(compiler, type, freg, mem, memw)); + CHECK(check_sljit_emit_fmem_update(compiler, type, freg, mem, memw)); if ((mem & OFFS_REG_MASK) || (memw > 255 || memw < -256)) return SLJIT_ERR_UNSUPPORTED; @@ -2071,7 +2302,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fmem(struct sljit_compiler *compil if (!(type & SLJIT_MEM_STORE)) inst |= 0x00400000; - if (type & SLJIT_MEM_PRE) + if (!(type & SLJIT_MEM_POST)) inst |= 0x800; return push_inst(compiler, inst | VT(freg) | RN(mem & REG_MASK) | (sljit_ins)((memw & 0x1ff) << 12)); diff --git a/src/3rdparty/pcre2/src/sljit/sljitNativeARM_T2_32.c b/src/3rdparty/pcre2/src/sljit/sljitNativeARM_T2_32.c index ed21ea7daa5..7d6bac077e2 100644 --- a/src/3rdparty/pcre2/src/sljit/sljitNativeARM_T2_32.c +++ b/src/3rdparty/pcre2/src/sljit/sljitNativeARM_T2_32.c @@ -100,7 +100,6 @@ static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 3] = { #define ADDS 0x1800 #define ADDSI3 0x1c00 #define ADDSI8 0x3000 -#define ADD_W 0xeb000000 #define ADDWI 0xf2000000 #define ADD_SP 0x4485 #define ADD_SP_I 0xb000 @@ -131,6 +130,7 @@ static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 3] = { #define IT 0xbf00 #define LDR_SP 0x9800 #define LDR 0xf8d00000 +#define LDRD 0xe9500000 #define LDRI 0xf8500800 #define LSLS 0x4080 #define LSLSI 0x0000 @@ -160,6 +160,10 @@ static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 3] = { #define POP_W 0xe8bd0000 #define PUSH 0xb400 #define PUSH_W 0xe92d0000 +#define RBIT 0xfa90f0a0 +#define RORS 0x41c0 +#define ROR_W 0xfa60f000 +#define ROR_WI 0xea4f0030 #define RSB_WI 0xf1c00000 #define RSBSI 0x4240 #define SBCI 0xf1600000 @@ -167,6 +171,7 @@ static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 3] = { #define SBC_W 0xeb600000 #define SDIV 0xfb90f0f0 #define SMULL 0xfb800000 +#define STRD 0xe9400000 #define STR_SP 0x9000 #define SUBS 0x1a00 #define SUBSI3 0x1e00 @@ -434,8 +439,8 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil } next_addr = compute_next_addr(label, jump, const_, put_label); } - code_ptr ++; - half_count ++; + code_ptr++; + half_count++; } while (buf_ptr < buf_end); buf = buf->next; @@ -491,6 +496,8 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type) #endif case SLJIT_HAS_CLZ: + case SLJIT_HAS_CTZ: + case SLJIT_HAS_ROT: case SLJIT_HAS_CMOV: case SLJIT_HAS_PREFETCH: return 1; @@ -592,7 +599,7 @@ static sljit_s32 emit_op_imm(struct sljit_compiler *compiler, sljit_s32 flags, s arg1 must be register, imm arg2 must be register, imm */ sljit_s32 reg; - sljit_uw imm, nimm; + sljit_uw imm, imm2; if (SLJIT_UNLIKELY((flags & (ARG1_IMM | ARG2_IMM)) == (ARG1_IMM | ARG2_IMM))) { /* Both are immediates, no temporaries are used. */ @@ -607,6 +614,7 @@ static sljit_s32 emit_op_imm(struct sljit_compiler *compiler, sljit_s32 flags, s switch (flags & 0xffff) { case SLJIT_CLZ: + case SLJIT_CTZ: case SLJIT_MUL: /* No form with immediate operand. */ break; @@ -621,31 +629,31 @@ static sljit_s32 emit_op_imm(struct sljit_compiler *compiler, sljit_s32 flags, s break; case SLJIT_ADD: compiler->status_flags_state = SLJIT_CURRENT_FLAGS_ADD; - nimm = NEGATE(imm); + imm2 = NEGATE(imm); if (IS_2_LO_REGS(reg, dst)) { if (imm <= 0x7) return push_inst16(compiler, ADDSI3 | IMM3(imm) | RD3(dst) | RN3(reg)); - if (nimm <= 0x7) - return push_inst16(compiler, SUBSI3 | IMM3(nimm) | RD3(dst) | RN3(reg)); + if (imm2 <= 0x7) + return push_inst16(compiler, SUBSI3 | IMM3(imm2) | RD3(dst) | RN3(reg)); if (reg == dst) { if (imm <= 0xff) return push_inst16(compiler, ADDSI8 | IMM8(imm) | RDN3(dst)); - if (nimm <= 0xff) - return push_inst16(compiler, SUBSI8 | IMM8(nimm) | RDN3(dst)); + if (imm2 <= 0xff) + return push_inst16(compiler, SUBSI8 | IMM8(imm2) | RDN3(dst)); } } if (!(flags & SET_FLAGS)) { if (imm <= 0xfff) return push_inst32(compiler, ADDWI | RD4(dst) | RN4(reg) | IMM12(imm)); - if (nimm <= 0xfff) - return push_inst32(compiler, SUBWI | RD4(dst) | RN4(reg) | IMM12(nimm)); + if (imm2 <= 0xfff) + return push_inst32(compiler, SUBWI | RD4(dst) | RN4(reg) | IMM12(imm2)); } - nimm = get_imm(imm); - if (nimm != INVALID_IMM) - return push_inst32(compiler, ADD_WI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | nimm); - nimm = get_imm(NEGATE(imm)); - if (nimm != INVALID_IMM) - return push_inst32(compiler, SUB_WI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | nimm); + imm2 = get_imm(imm); + if (imm2 != INVALID_IMM) + return push_inst32(compiler, ADD_WI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | imm2); + imm = get_imm(NEGATE(imm)); + if (imm != INVALID_IMM) + return push_inst32(compiler, SUB_WI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | imm); break; case SLJIT_ADDC: compiler->status_flags_state = SLJIT_CURRENT_FLAGS_ADD; @@ -666,39 +674,39 @@ static sljit_s32 emit_op_imm(struct sljit_compiler *compiler, sljit_s32 flags, s if (flags & UNUSED_RETURN) { if (imm <= 0xff && reg_map[reg] <= 7) return push_inst16(compiler, CMPI | IMM8(imm) | RDN3(reg)); - nimm = get_imm(imm); - if (nimm != INVALID_IMM) - return push_inst32(compiler, CMPI_W | RN4(reg) | nimm); - nimm = get_imm(NEGATE(imm)); - if (nimm != INVALID_IMM) - return push_inst32(compiler, CMNI_W | RN4(reg) | nimm); + imm2 = get_imm(imm); + if (imm2 != INVALID_IMM) + return push_inst32(compiler, CMPI_W | RN4(reg) | imm2); + imm = get_imm(NEGATE(imm)); + if (imm != INVALID_IMM) + return push_inst32(compiler, CMNI_W | RN4(reg) | imm); break; } - nimm = NEGATE(imm); + imm2 = NEGATE(imm); if (IS_2_LO_REGS(reg, dst)) { if (imm <= 0x7) return push_inst16(compiler, SUBSI3 | IMM3(imm) | RD3(dst) | RN3(reg)); - if (nimm <= 0x7) - return push_inst16(compiler, ADDSI3 | IMM3(nimm) | RD3(dst) | RN3(reg)); + if (imm2 <= 0x7) + return push_inst16(compiler, ADDSI3 | IMM3(imm2) | RD3(dst) | RN3(reg)); if (reg == dst) { if (imm <= 0xff) return push_inst16(compiler, SUBSI8 | IMM8(imm) | RDN3(dst)); - if (nimm <= 0xff) - return push_inst16(compiler, ADDSI8 | IMM8(nimm) | RDN3(dst)); + if (imm2 <= 0xff) + return push_inst16(compiler, ADDSI8 | IMM8(imm2) | RDN3(dst)); } } if (!(flags & SET_FLAGS)) { if (imm <= 0xfff) return push_inst32(compiler, SUBWI | RD4(dst) | RN4(reg) | IMM12(imm)); - if (nimm <= 0xfff) - return push_inst32(compiler, ADDWI | RD4(dst) | RN4(reg) | IMM12(nimm)); + if (imm2 <= 0xfff) + return push_inst32(compiler, ADDWI | RD4(dst) | RN4(reg) | IMM12(imm2)); } - nimm = get_imm(imm); - if (nimm != INVALID_IMM) - return push_inst32(compiler, SUB_WI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | nimm); - nimm = get_imm(NEGATE(imm)); - if (nimm != INVALID_IMM) - return push_inst32(compiler, ADD_WI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | nimm); + imm2 = get_imm(imm); + if (imm2 != INVALID_IMM) + return push_inst32(compiler, SUB_WI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | imm2); + imm = get_imm(NEGATE(imm)); + if (imm != INVALID_IMM) + return push_inst32(compiler, ADD_WI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | imm); break; case SLJIT_SUBC: compiler->status_flags_state = SLJIT_CURRENT_FLAGS_SUB; @@ -709,17 +717,17 @@ static sljit_s32 emit_op_imm(struct sljit_compiler *compiler, sljit_s32 flags, s return push_inst32(compiler, SBCI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | imm); break; case SLJIT_AND: - nimm = get_imm(imm); - if (nimm != INVALID_IMM) - return push_inst32(compiler, ((flags & UNUSED_RETURN) ? TSTI : ANDI) | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | nimm); + imm2 = get_imm(imm); + if (imm2 != INVALID_IMM) + return push_inst32(compiler, ((flags & UNUSED_RETURN) ? TSTI : ANDI) | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | imm2); imm = get_imm(~imm); if (imm != INVALID_IMM) return push_inst32(compiler, BICI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | imm); break; case SLJIT_OR: - nimm = get_imm(imm); - if (nimm != INVALID_IMM) - return push_inst32(compiler, ORRI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | nimm); + imm2 = get_imm(imm); + if (imm2 != INVALID_IMM) + return push_inst32(compiler, ORRI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | imm2); imm = get_imm(~imm); if (imm != INVALID_IMM) return push_inst32(compiler, ORNI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | imm); @@ -730,11 +738,17 @@ static sljit_s32 emit_op_imm(struct sljit_compiler *compiler, sljit_s32 flags, s return push_inst32(compiler, EORI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | imm); break; case SLJIT_SHL: + case SLJIT_MSHL: case SLJIT_LSHR: + case SLJIT_MLSHR: case SLJIT_ASHR: + case SLJIT_MASHR: + case SLJIT_ROTL: + case SLJIT_ROTR: if (flags & ARG1_IMM) break; imm &= 0x1f; + if (imm == 0) { if (!(flags & SET_FLAGS)) return push_inst16(compiler, MOV | SET_REGS44(dst, reg)); @@ -742,19 +756,28 @@ static sljit_s32 emit_op_imm(struct sljit_compiler *compiler, sljit_s32 flags, s return push_inst16(compiler, MOVS | RD3(dst) | RN3(reg)); return push_inst32(compiler, MOV_W | SET_FLAGS | RD4(dst) | RM4(reg)); } + switch (flags & 0xffff) { case SLJIT_SHL: + case SLJIT_MSHL: if (IS_2_LO_REGS(dst, reg)) return push_inst16(compiler, LSLSI | RD3(dst) | RN3(reg) | (imm << 6)); return push_inst32(compiler, LSL_WI | (flags & SET_FLAGS) | RD4(dst) | RM4(reg) | IMM5(imm)); case SLJIT_LSHR: + case SLJIT_MLSHR: if (IS_2_LO_REGS(dst, reg)) return push_inst16(compiler, LSRSI | RD3(dst) | RN3(reg) | (imm << 6)); return push_inst32(compiler, LSR_WI | (flags & SET_FLAGS) | RD4(dst) | RM4(reg) | IMM5(imm)); - default: /* SLJIT_ASHR */ + case SLJIT_ASHR: + case SLJIT_MASHR: if (IS_2_LO_REGS(dst, reg)) return push_inst16(compiler, ASRSI | RD3(dst) | RN3(reg) | (imm << 6)); return push_inst32(compiler, ASR_WI | (flags & SET_FLAGS) | RD4(dst) | RM4(reg) | IMM5(imm)); + case SLJIT_ROTL: + imm = (imm ^ 0x1f) + 1; + /* fallthrough */ + default: /* SLJIT_ROTR */ + return push_inst32(compiler, ROR_WI | RD4(dst) | RM4(reg) | IMM5(imm)); } default: SLJIT_UNREACHABLE(); @@ -813,8 +836,11 @@ static sljit_s32 emit_op_imm(struct sljit_compiler *compiler, sljit_s32 flags, s return push_inst32(compiler, MVN_W | (flags & SET_FLAGS) | RD4(dst) | RM4(arg2)); case SLJIT_CLZ: SLJIT_ASSERT(arg1 == TMP_REG2); - FAIL_IF(push_inst32(compiler, CLZ | RN4(arg2) | RD4(dst) | RM4(arg2))); - return SLJIT_SUCCESS; + return push_inst32(compiler, CLZ | RN4(arg2) | RD4(dst) | RM4(arg2)); + case SLJIT_CTZ: + SLJIT_ASSERT(arg1 == TMP_REG2); + FAIL_IF(push_inst32(compiler, RBIT | RN4(arg2) | RD4(dst) | RM4(arg2))); + return push_inst32(compiler, CLZ | RN4(dst) | RD4(dst) | RM4(dst)); case SLJIT_ADD: compiler->status_flags_state = SLJIT_CURRENT_FLAGS_ADD; if (IS_3_LO_REGS(dst, arg1, arg2)) @@ -864,18 +890,38 @@ static sljit_s32 emit_op_imm(struct sljit_compiler *compiler, sljit_s32 flags, s if (dst == (sljit_s32)arg1 && IS_2_LO_REGS(dst, arg2)) return push_inst16(compiler, EORS | RD3(dst) | RN3(arg2)); return push_inst32(compiler, EOR_W | (flags & SET_FLAGS) | RD4(dst) | RN4(arg1) | RM4(arg2)); + case SLJIT_MSHL: + FAIL_IF(push_inst32(compiler, ANDI | RD4(TMP_REG2) | RN4(arg2) | 0x1f)); + arg2 = TMP_REG2; + /* fallthrough */ case SLJIT_SHL: if (dst == (sljit_s32)arg1 && IS_2_LO_REGS(dst, arg2)) return push_inst16(compiler, LSLS | RD3(dst) | RN3(arg2)); return push_inst32(compiler, LSL_W | (flags & SET_FLAGS) | RD4(dst) | RN4(arg1) | RM4(arg2)); + case SLJIT_MLSHR: + FAIL_IF(push_inst32(compiler, ANDI | RD4(TMP_REG2) | RN4(arg2) | 0x1f)); + arg2 = TMP_REG2; + /* fallthrough */ case SLJIT_LSHR: if (dst == (sljit_s32)arg1 && IS_2_LO_REGS(dst, arg2)) return push_inst16(compiler, LSRS | RD3(dst) | RN3(arg2)); return push_inst32(compiler, LSR_W | (flags & SET_FLAGS) | RD4(dst) | RN4(arg1) | RM4(arg2)); + case SLJIT_MASHR: + FAIL_IF(push_inst32(compiler, ANDI | RD4(TMP_REG2) | RN4(arg2) | 0x1f)); + arg2 = TMP_REG2; + /* fallthrough */ case SLJIT_ASHR: if (dst == (sljit_s32)arg1 && IS_2_LO_REGS(dst, arg2)) return push_inst16(compiler, ASRS | RD3(dst) | RN3(arg2)); return push_inst32(compiler, ASR_W | (flags & SET_FLAGS) | RD4(dst) | RN4(arg1) | RM4(arg2)); + case SLJIT_ROTL: + FAIL_IF(push_inst32(compiler, RSB_WI | RD4(TMP_REG2) | RN4(arg2) | 0)); + arg2 = TMP_REG2; + /* fallthrough */ + case SLJIT_ROTR: + if (dst == (sljit_s32)arg1 && IS_2_LO_REGS(dst, arg2)) + return push_inst16(compiler, RORS | RD3(dst) | RN3(arg2)); + return push_inst32(compiler, ROR_W | RD4(dst) | RN4(arg1) | RM4(arg2)); } SLJIT_UNREACHABLE(); @@ -890,8 +936,8 @@ static sljit_s32 emit_op_imm(struct sljit_compiler *compiler, sljit_s32 flags, s #define HALF_SIZE 0x08 #define PRELOAD 0x0c -#define IS_WORD_SIZE(flags) (!(flags & (BYTE_SIZE | HALF_SIZE))) -#define OFFSET_CHECK(imm, shift) (!(argw & ~(imm << shift))) +#define IS_WORD_SIZE(flags) (!((flags) & (BYTE_SIZE | HALF_SIZE))) +#define ALIGN_CHECK(argw, imm, shift) (!((argw) & ~((imm) << (shift)))) /* 1st letter: @@ -990,16 +1036,15 @@ static SLJIT_INLINE sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit sljit_s32 arg, sljit_sw argw, sljit_s32 tmp_reg) { sljit_s32 other_r; - sljit_uw tmp; + sljit_uw imm, tmp; SLJIT_ASSERT(arg & SLJIT_MEM); - SLJIT_ASSERT((arg & REG_MASK) != tmp_reg); - arg &= ~SLJIT_MEM; + SLJIT_ASSERT((arg & REG_MASK) != tmp_reg || (arg == SLJIT_MEM1(tmp_reg) && argw >= -0xff && argw <= 0xfff)); if (SLJIT_UNLIKELY(!(arg & REG_MASK))) { - tmp = get_imm((sljit_uw)argw & ~(sljit_uw)0xfff); - if (tmp != INVALID_IMM) { - FAIL_IF(push_inst32(compiler, MOV_WI | RD4(tmp_reg) | tmp)); + imm = get_imm((sljit_uw)argw & ~(sljit_uw)0xfff); + if (imm != INVALID_IMM) { + FAIL_IF(push_inst32(compiler, MOV_WI | RD4(tmp_reg) | imm)); return push_inst32(compiler, sljit_mem32[flags] | MEM_IMM12 | RT4(reg) | RN4(tmp_reg) | (argw & 0xfff)); } @@ -1012,51 +1057,59 @@ static SLJIT_INLINE sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit if (SLJIT_UNLIKELY(arg & OFFS_REG_MASK)) { argw &= 0x3; other_r = OFFS_REG(arg); - arg &= 0xf; + arg &= REG_MASK; if (!argw && IS_3_LO_REGS(reg, arg, other_r)) return push_inst16(compiler, sljit_mem16[flags] | RD3(reg) | RN3(arg) | RM3(other_r)); return push_inst32(compiler, sljit_mem32[flags] | RT4(reg) | RN4(arg) | RM4(other_r) | ((sljit_ins)argw << 4)); } + arg &= REG_MASK; + if (argw > 0xfff) { - tmp = get_imm((sljit_uw)argw & ~(sljit_uw)0xfff); - if (tmp != INVALID_IMM) { - push_inst32(compiler, ADD_WI | RD4(tmp_reg) | RN4(arg) | tmp); + imm = get_imm((sljit_uw)(argw & ~0xfff)); + if (imm != INVALID_IMM) { + push_inst32(compiler, ADD_WI | RD4(tmp_reg) | RN4(arg) | imm); arg = tmp_reg; argw = argw & 0xfff; } } else if (argw < -0xff) { - tmp = get_imm((sljit_uw)-argw & ~(sljit_uw)0xff); - if (tmp != INVALID_IMM) { - push_inst32(compiler, SUB_WI | RD4(tmp_reg) | RN4(arg) | tmp); + tmp = (sljit_uw)((-argw + 0xfff) & ~0xfff); + SLJIT_ASSERT(tmp >= (sljit_uw)-argw); + imm = get_imm(tmp); + + if (imm != INVALID_IMM) { + push_inst32(compiler, SUB_WI | RD4(tmp_reg) | RN4(arg) | imm); arg = tmp_reg; - argw = -(-argw & 0xff); + argw += (sljit_sw)tmp; + + SLJIT_ASSERT(argw >= 0 && argw <= 0xfff); } } + /* 16 bit instruction forms. */ if (IS_2_LO_REGS(reg, arg) && sljit_mem16_imm5[flags]) { tmp = 3; if (IS_WORD_SIZE(flags)) { - if (OFFSET_CHECK(0x1f, 2)) + if (ALIGN_CHECK(argw, 0x1f, 2)) tmp = 2; } else if (flags & BYTE_SIZE) { - if (OFFSET_CHECK(0x1f, 0)) + if (ALIGN_CHECK(argw, 0x1f, 0)) tmp = 0; } else { SLJIT_ASSERT(flags & HALF_SIZE); - if (OFFSET_CHECK(0x1f, 1)) + if (ALIGN_CHECK(argw, 0x1f, 1)) tmp = 1; } if (tmp < 3) return push_inst16(compiler, sljit_mem16_imm5[flags] | RD3(reg) | RN3(arg) | ((sljit_ins)argw << (6 - tmp))); } - else if (SLJIT_UNLIKELY(arg == SLJIT_SP) && IS_WORD_SIZE(flags) && OFFSET_CHECK(0xff, 2) && reg_map[reg] <= 7) { + else if (SLJIT_UNLIKELY(arg == SLJIT_SP) && IS_WORD_SIZE(flags) && ALIGN_CHECK(argw, 0xff, 2) && reg_map[reg] <= 7) { /* SP based immediate. */ return push_inst16(compiler, STR_SP | (sljit_ins)((flags & STORE) ? 0 : 0x800) | RDN3(reg) | ((sljit_ins)argw >> 2)); } @@ -1074,6 +1127,9 @@ static SLJIT_INLINE sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit return push_inst32(compiler, sljit_mem32[flags] | RT4(reg) | RN4(arg) | RM4(tmp_reg)); } +#undef ALIGN_CHECK +#undef IS_WORD_SIZE + /* --------------------------------------------------------------------- */ /* Entry, exit */ /* --------------------------------------------------------------------- */ @@ -1082,7 +1138,8 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds, sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size) { - sljit_s32 size, i, tmp, word_arg_count, saved_arg_count; + sljit_s32 size, i, tmp, word_arg_count; + sljit_s32 saved_arg_count = SLJIT_KEPT_SAVEDS_COUNT(options); sljit_uw offset; sljit_uw imm = 0; #ifdef __SOFTFP__ @@ -1098,7 +1155,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi set_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size); tmp = SLJIT_S0 - saveds; - for (i = SLJIT_S0; i > tmp; i--) + for (i = SLJIT_S0 - saved_arg_count; i > tmp; i--) imm |= (sljit_uw)1 << reg_map[i]; for (i = scratches; i >= SLJIT_FIRST_SAVED_REG; i--) @@ -1110,7 +1167,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi : push_inst16(compiler, PUSH | (1 << 8) | imm)); /* Stack must be aligned to 8 bytes: (LR, R4) */ - size = GET_SAVED_REGISTERS_SIZE(scratches, saveds, 1); + size = GET_SAVED_REGISTERS_SIZE(scratches, saveds - saved_arg_count, 1); if (fsaveds > 0 || fscratches >= SLJIT_FIRST_SAVED_FLOAT_REG) { if ((size & SSIZE_OF(sw)) != 0) { @@ -1131,6 +1188,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi local_size = ((size + local_size + 0x7) & ~0x7) - size; compiler->local_size = local_size; + if (options & SLJIT_ENTER_REG_ARG) + arg_types = 0; + arg_types >>= SLJIT_ARG_SHIFT; word_arg_count = 0; saved_arg_count = 0; @@ -1173,13 +1233,14 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi else break; - SLJIT_ASSERT(reg_map[tmp] <= 7); - if (offset < 4 * sizeof(sljit_sw)) - FAIL_IF(push_inst16(compiler, MOV | RD3(tmp) | (offset << 1))); - else + FAIL_IF(push_inst16(compiler, MOV | ((sljit_ins)reg_map[tmp] & 0x7) | (((sljit_ins)reg_map[tmp] & 0x8) << 4) | (offset << 1))); + else if (reg_map[tmp] <= 7) FAIL_IF(push_inst16(compiler, LDR_SP | RDN3(tmp) | ((offset + (sljit_uw)size - 4 * sizeof(sljit_sw)) >> 2))); + else + FAIL_IF(push_inst32(compiler, LDR | RT4(tmp) | RN4(SLJIT_SP) + | ((offset + (sljit_uw)size - 4 * sizeof(sljit_sw))))); break; } @@ -1293,7 +1354,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *comp CHECK(check_sljit_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size)); set_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size); - size = GET_SAVED_REGISTERS_SIZE(scratches, saveds, 1); + size = GET_SAVED_REGISTERS_SIZE(scratches, saveds - SLJIT_KEPT_SAVEDS_COUNT(options), 1); if ((size & SSIZE_OF(sw)) != 0 && (fsaveds > 0 || fscratches >= SLJIT_FIRST_SAVED_FLOAT_REG)) size += SSIZE_OF(sw); @@ -1325,8 +1386,9 @@ static sljit_s32 emit_add_sp(struct sljit_compiler *compiler, sljit_uw imm) static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler, sljit_s32 frame_size) { sljit_s32 local_size, fscratches, fsaveds, i, tmp; + sljit_s32 restored_reg = 0; sljit_s32 lr_dst = TMP_PC; - sljit_uw reg_list; + sljit_uw reg_list = 0; SLJIT_ASSERT(reg_map[TMP_REG2] == 14 && frame_size <= 128); @@ -1353,46 +1415,88 @@ static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler, sljit if (frame_size < 0) { lr_dst = TMP_REG2; frame_size = 0; - } else if (frame_size > 0) + } else if (frame_size > 0) { + SLJIT_ASSERT(frame_size == 1 || (frame_size & 0x7) == 0); lr_dst = 0; + frame_size &= ~0x7; + } - reg_list = 0; tmp = SLJIT_S0 - compiler->saveds; - for (i = SLJIT_S0; i > tmp; i--) - reg_list |= (sljit_uw)1 << reg_map[i]; + i = SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options); + if (tmp < i) { + restored_reg = i; + do { + reg_list |= (sljit_uw)1 << reg_map[i]; + } while (--i > tmp); + } - for (i = compiler->scratches; i >= SLJIT_FIRST_SAVED_REG; i--) - reg_list |= (sljit_uw)1 << reg_map[i]; + i = compiler->scratches; + if (i >= SLJIT_FIRST_SAVED_REG) { + restored_reg = i; + do { + reg_list |= (sljit_uw)1 << reg_map[i]; + } while (--i >= SLJIT_FIRST_SAVED_REG); + } + + if (lr_dst == TMP_REG2 && reg_list == 0) { + reg_list |= (sljit_uw)1 << reg_map[TMP_REG2]; + restored_reg = TMP_REG2; + lr_dst = 0; + } if (lr_dst == 0 && (reg_list & (reg_list - 1)) == 0) { /* The local_size does not include the saved registers. */ + tmp = 0; + if (reg_list != 0) { + tmp = 2; + if (local_size <= 0xfff) { + if (local_size == 0) { + SLJIT_ASSERT(restored_reg != TMP_REG2); + if (frame_size == 0) + return push_inst32(compiler, LDRI | RT4(restored_reg) | RN4(SLJIT_SP) | 0x308); + if (frame_size > 2 * SSIZE_OF(sw)) + return push_inst32(compiler, LDRI | RT4(restored_reg) | RN4(SLJIT_SP) | 0x100 | (sljit_ins)(frame_size - (2 * SSIZE_OF(sw)))); + } + + if (reg_map[restored_reg] <= 7 && local_size <= 0x3fc) + FAIL_IF(push_inst16(compiler, STR_SP | 0x800 | RDN3(restored_reg) | (sljit_ins)(local_size >> 2))); + else + FAIL_IF(push_inst32(compiler, LDR | RT4(restored_reg) | RN4(SLJIT_SP) | (sljit_ins)local_size)); + tmp = 1; + } else if (frame_size == 0) { + frame_size = (restored_reg == TMP_REG2) ? SSIZE_OF(sw) : 2 * SSIZE_OF(sw); + tmp = 3; + } + + /* Place for the saved register. */ + if (restored_reg != TMP_REG2) + local_size += SSIZE_OF(sw); + } + + /* Place for the lr register. */ local_size += SSIZE_OF(sw); - if (reg_list != 0) - local_size += SSIZE_OF(sw); - if (frame_size > local_size) - FAIL_IF(push_inst16(compiler, SUB_SP_I | ((sljit_uw)(frame_size - local_size) >> 2))); + FAIL_IF(push_inst16(compiler, SUB_SP_I | ((sljit_ins)(frame_size - local_size) >> 2))); else if (frame_size < local_size) FAIL_IF(emit_add_sp(compiler, (sljit_uw)(local_size - frame_size))); - if (reg_list == 0) + if (tmp <= 1) return SLJIT_SUCCESS; - if (compiler->saveds > 0) { - SLJIT_ASSERT(reg_list == ((sljit_uw)1 << reg_map[SLJIT_S0])); - lr_dst = SLJIT_S0; - } else { - SLJIT_ASSERT(reg_list == ((sljit_uw)1 << reg_map[SLJIT_FIRST_SAVED_REG])); - lr_dst = SLJIT_FIRST_SAVED_REG; + if (tmp == 2) { + frame_size -= SSIZE_OF(sw); + if (restored_reg != TMP_REG2) + frame_size -= SSIZE_OF(sw); + + if (reg_map[restored_reg] <= 7) + return push_inst16(compiler, STR_SP | 0x800 | RDN3(restored_reg) | (sljit_ins)(frame_size >> 2)); + + return push_inst32(compiler, LDR | RT4(restored_reg) | RN4(SLJIT_SP) | (sljit_ins)frame_size); } - frame_size -= 2 * SSIZE_OF(sw); - - if (reg_map[lr_dst] <= 7) - return push_inst16(compiler, STR_SP | 0x800 | RDN3(lr_dst) | (sljit_uw)(frame_size >> 2)); - - return push_inst32(compiler, LDR | RT4(lr_dst) | RN4(SLJIT_SP) | (sljit_uw)frame_size); + tmp = (restored_reg == TMP_REG2) ? 0x304 : 0x308; + return push_inst32(compiler, LDRI | RT4(restored_reg) | RN4(SLJIT_SP) | (sljit_ins)tmp); } if (local_size > 0) @@ -1407,12 +1511,8 @@ static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler, sljit FAIL_IF(push_inst16(compiler, POP | reg_list)); } else { - if (lr_dst != 0) { - if (reg_list == 0) - return push_inst32(compiler, 0xf85d0b04 | RT4(lr_dst)); - + if (lr_dst != 0) reg_list |= (sljit_uw)1 << reg_map[lr_dst]; - } /* At least two registers must be set for POP_W instruction. */ SLJIT_ASSERT((reg_list & (reg_list - 1)) != 0); @@ -1421,8 +1521,12 @@ static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler, sljit } if (frame_size > 0) - return push_inst16(compiler, SUB_SP_I | (((sljit_uw)frame_size - sizeof(sljit_sw)) >> 2)); - return SLJIT_SUCCESS; + return push_inst16(compiler, SUB_SP_I | (((sljit_ins)frame_size - sizeof(sljit_sw)) >> 2)); + + if (lr_dst != 0) + return SLJIT_SUCCESS; + + return push_inst16(compiler, ADD_SP_I | 1); } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_void(struct sljit_compiler *compiler) @@ -1433,6 +1537,28 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_void(struct sljit_compiler return emit_stack_frame_release(compiler, 0); } +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_to(struct sljit_compiler *compiler, + sljit_s32 src, sljit_sw srcw) +{ + CHECK_ERROR(); + CHECK(check_sljit_emit_return_to(compiler, src, srcw)); + + if (src & SLJIT_MEM) { + FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_REG1, src, srcw, TMP_REG1)); + src = TMP_REG1; + srcw = 0; + } else if (src >= SLJIT_FIRST_SAVED_REG && src <= (SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options))) { + FAIL_IF(push_inst16(compiler, MOV | SET_REGS44(TMP_REG1, src))); + src = TMP_REG1; + srcw = 0; + } + + FAIL_IF(emit_stack_frame_release(compiler, 1)); + + SLJIT_SKIP_CHECKS(compiler); + return sljit_emit_ijump(compiler, SLJIT_JUMP, src, srcw); +} + /* --------------------------------------------------------------------- */ /* Operators */ /* --------------------------------------------------------------------- */ @@ -1685,13 +1811,75 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2u(struct sljit_compiler *compil CHECK_ERROR(); CHECK(check_sljit_emit_op2(compiler, op, 1, 0, 0, src1, src1w, src2, src2w)); -#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \ - || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) - compiler->skip_checks = 1; -#endif + SLJIT_SKIP_CHECKS(compiler); return sljit_emit_op2(compiler, op, TMP_REG1, 0, src1, src1w, src2, src2w); } +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_shift_into(struct sljit_compiler *compiler, sljit_s32 op, + sljit_s32 src_dst, + sljit_s32 src1, sljit_sw src1w, + sljit_s32 src2, sljit_sw src2w) +{ + sljit_s32 is_left; + + CHECK_ERROR(); + CHECK(check_sljit_emit_shift_into(compiler, op, src_dst, src1, src1w, src2, src2w)); + + op = GET_OPCODE(op); + is_left = (op == SLJIT_SHL || op == SLJIT_MSHL); + + if (src_dst == src1) { + SLJIT_SKIP_CHECKS(compiler); + return sljit_emit_op2(compiler, is_left ? SLJIT_ROTL : SLJIT_ROTR, src_dst, 0, src_dst, 0, src2, src2w); + } + + ADJUST_LOCAL_OFFSET(src1, src1w); + ADJUST_LOCAL_OFFSET(src2, src2w); + + if (src2 & SLJIT_IMM) { + src2w &= 0x1f; + + if (src2w == 0) + return SLJIT_SUCCESS; + } else if (src2 & SLJIT_MEM) { + FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_REG2, src2, src2w, TMP_REG2)); + src2 = TMP_REG2; + } + + if (src1 & SLJIT_MEM) { + FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_REG1, src1, src1w, TMP_REG1)); + src1 = TMP_REG1; + } else if (src1 & SLJIT_IMM) { + FAIL_IF(load_immediate(compiler, TMP_REG1, (sljit_uw)src1w)); + src1 = TMP_REG1; + } + + if (src2 & SLJIT_IMM) { + if (reg_map[src_dst] <= 7) + FAIL_IF(push_inst16(compiler, (is_left ? LSLSI : LSRSI) | RD3(src_dst) | RN3(src_dst) | ((sljit_ins)src2w << 6))); + else + FAIL_IF(push_inst32(compiler, (is_left ? LSL_WI : LSR_WI) | RD4(src_dst) | RM4(src_dst) | IMM5(src2w))); + + src2w = (src2w ^ 0x1f) + 1; + return push_inst32(compiler, ORR_W | RD4(src_dst) | RN4(src_dst) | RM4(src1) | (is_left ? 0x10 : 0x0) | IMM5(src2w)); + } + + if (op == SLJIT_MSHL || op == SLJIT_MLSHR) { + FAIL_IF(push_inst32(compiler, ANDI | RD4(TMP_REG2) | RN4(src2) | 0x1f)); + src2 = TMP_REG2; + } + + if (IS_2_LO_REGS(src_dst, src2)) + FAIL_IF(push_inst16(compiler, (is_left ? LSLS : LSRS) | RD3(src_dst) | RN3(src2))); + else + FAIL_IF(push_inst32(compiler, (is_left ? LSL_W : LSR_W) | RD4(src_dst) | RN4(src_dst) | RM4(src2))); + + FAIL_IF(push_inst32(compiler, (is_left ? LSR_WI : LSL_WI) | RD4(TMP_REG1) | RM4(src1) | (1 << 6))); + FAIL_IF(push_inst32(compiler, EORI | RD4(TMP_REG2) | RN4(src2) | 0x1f)); + FAIL_IF(push_inst32(compiler, (is_left ? LSR_W : LSL_W) | RD4(TMP_REG1) | RN4(TMP_REG1) | RM4(TMP_REG2))); + return push_inst32(compiler, ORR_W | RD4(src_dst) | RN4(src_dst) | RM4(TMP_REG1)); +} + SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_src(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 src, sljit_sw srcw) { @@ -1955,8 +2143,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop2(struct sljit_compiler *compil return emit_fop_mem(compiler, (op & SLJIT_32), TMP_FREG1, dst, dstw); } -#undef FPU_LOAD - /* --------------------------------------------------------------------- */ /* Other instructions */ /* --------------------------------------------------------------------- */ @@ -1984,11 +2170,15 @@ static sljit_uw get_cc(struct sljit_compiler *compiler, sljit_s32 type) { switch (type) { case SLJIT_EQUAL: - case SLJIT_EQUAL_F64: + case SLJIT_F_EQUAL: + case SLJIT_ORDERED_EQUAL: + case SLJIT_UNORDERED_OR_EQUAL: /* Not supported. */ return 0x0; case SLJIT_NOT_EQUAL: - case SLJIT_NOT_EQUAL_F64: + case SLJIT_F_NOT_EQUAL: + case SLJIT_UNORDERED_OR_NOT_EQUAL: + case SLJIT_ORDERED_NOT_EQUAL: /* Not supported. */ return 0x1; case SLJIT_CARRY: @@ -1997,7 +2187,6 @@ static sljit_uw get_cc(struct sljit_compiler *compiler, sljit_s32 type) /* fallthrough */ case SLJIT_LESS: - case SLJIT_LESS_F64: return 0x3; case SLJIT_NOT_CARRY: @@ -2006,27 +2195,33 @@ static sljit_uw get_cc(struct sljit_compiler *compiler, sljit_s32 type) /* fallthrough */ case SLJIT_GREATER_EQUAL: - case SLJIT_GREATER_EQUAL_F64: return 0x2; case SLJIT_GREATER: - case SLJIT_GREATER_F64: + case SLJIT_UNORDERED_OR_GREATER: return 0x8; case SLJIT_LESS_EQUAL: - case SLJIT_LESS_EQUAL_F64: + case SLJIT_F_LESS_EQUAL: + case SLJIT_ORDERED_LESS_EQUAL: return 0x9; case SLJIT_SIG_LESS: + case SLJIT_UNORDERED_OR_LESS: return 0xb; case SLJIT_SIG_GREATER_EQUAL: + case SLJIT_F_GREATER_EQUAL: + case SLJIT_ORDERED_GREATER_EQUAL: return 0xa; case SLJIT_SIG_GREATER: + case SLJIT_F_GREATER: + case SLJIT_ORDERED_GREATER: return 0xc; case SLJIT_SIG_LESS_EQUAL: + case SLJIT_UNORDERED_OR_LESS_EQUAL: return 0xd; case SLJIT_OVERFLOW: @@ -2034,7 +2229,7 @@ static sljit_uw get_cc(struct sljit_compiler *compiler, sljit_s32 type) return 0x1; /* fallthrough */ - case SLJIT_UNORDERED_F64: + case SLJIT_UNORDERED: return 0x6; case SLJIT_NOT_OVERFLOW: @@ -2042,9 +2237,16 @@ static sljit_uw get_cc(struct sljit_compiler *compiler, sljit_s32 type) return 0x0; /* fallthrough */ - case SLJIT_ORDERED_F64: + case SLJIT_ORDERED: return 0x7; + case SLJIT_F_LESS: + case SLJIT_ORDERED_LESS: + return 0x4; + + case SLJIT_UNORDERED_OR_GREATER_EQUAL: + return 0x5; + default: /* SLJIT_JUMP */ SLJIT_UNREACHABLE(); return 0xe; @@ -2289,52 +2491,49 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compile CHECK_PTR(check_sljit_emit_call(compiler, type, arg_types)); #ifdef __SOFTFP__ - PTR_FAIL_IF(softfloat_call_with_args(compiler, arg_types, NULL, &extra_space)); - SLJIT_ASSERT((extra_space & 0x7) == 0); + if ((type & 0xff) != SLJIT_CALL_REG_ARG) { + PTR_FAIL_IF(softfloat_call_with_args(compiler, arg_types, NULL, &extra_space)); + SLJIT_ASSERT((extra_space & 0x7) == 0); - if ((type & SLJIT_CALL_RETURN) && extra_space == 0) - type = SLJIT_JUMP | (type & SLJIT_REWRITABLE_JUMP); + if ((type & SLJIT_CALL_RETURN) && extra_space == 0) + type = SLJIT_JUMP | (type & SLJIT_REWRITABLE_JUMP); -#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \ - || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) - compiler->skip_checks = 1; -#endif + SLJIT_SKIP_CHECKS(compiler); + jump = sljit_emit_jump(compiler, type); + PTR_FAIL_IF(jump == NULL); - jump = sljit_emit_jump(compiler, type); - PTR_FAIL_IF(jump == NULL); + if (extra_space > 0) { + if (type & SLJIT_CALL_RETURN) + PTR_FAIL_IF(push_inst32(compiler, LDR | RT4(TMP_REG2) + | RN4(SLJIT_SP) | (extra_space - sizeof(sljit_sw)))); - if (extra_space > 0) { - if (type & SLJIT_CALL_RETURN) - PTR_FAIL_IF(push_inst32(compiler, LDR | RT4(TMP_REG2) - | RN4(SLJIT_SP) | (extra_space - sizeof(sljit_sw)))); + PTR_FAIL_IF(push_inst16(compiler, ADD_SP_I | (extra_space >> 2))); - PTR_FAIL_IF(push_inst16(compiler, ADD_SP_I | (extra_space >> 2))); - - if (type & SLJIT_CALL_RETURN) { - PTR_FAIL_IF(push_inst16(compiler, BX | RN3(TMP_REG2))); - return jump; + if (type & SLJIT_CALL_RETURN) { + PTR_FAIL_IF(push_inst16(compiler, BX | RN3(TMP_REG2))); + return jump; + } } - } - SLJIT_ASSERT(!(type & SLJIT_CALL_RETURN)); - PTR_FAIL_IF(softfloat_post_call_with_args(compiler, arg_types)); - return jump; -#else + SLJIT_ASSERT(!(type & SLJIT_CALL_RETURN)); + PTR_FAIL_IF(softfloat_post_call_with_args(compiler, arg_types)); + return jump; + } +#endif /* __SOFTFP__ */ + if (type & SLJIT_CALL_RETURN) { /* ldmia sp!, {..., lr} */ PTR_FAIL_IF(emit_stack_frame_release(compiler, -1)); type = SLJIT_JUMP | (type & SLJIT_REWRITABLE_JUMP); } - PTR_FAIL_IF(hardfloat_call_with_args(compiler, arg_types)); - -#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \ - || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) - compiler->skip_checks = 1; -#endif +#ifndef __SOFTFP__ + if ((type & 0xff) != SLJIT_CALL_REG_ARG) + PTR_FAIL_IF(hardfloat_call_with_args(compiler, arg_types)); +#endif /* !__SOFTFP__ */ + SLJIT_SKIP_CHECKS(compiler); return sljit_emit_jump(compiler, type); -#endif } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 src, sljit_sw srcw) @@ -2385,56 +2584,80 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compi src = TMP_REG1; } - if ((type & SLJIT_CALL_RETURN) && (src >= SLJIT_FIRST_SAVED_REG && src <= SLJIT_S0)) { + if ((type & SLJIT_CALL_RETURN) && (src >= SLJIT_FIRST_SAVED_REG && src <= (SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options)))) { FAIL_IF(push_inst16(compiler, MOV | SET_REGS44(TMP_REG1, src))); src = TMP_REG1; } #ifdef __SOFTFP__ - FAIL_IF(softfloat_call_with_args(compiler, arg_types, &src, &extra_space)); - SLJIT_ASSERT((extra_space & 0x7) == 0); + if ((type & 0xff) != SLJIT_CALL_REG_ARG) { + FAIL_IF(softfloat_call_with_args(compiler, arg_types, &src, &extra_space)); + SLJIT_ASSERT((extra_space & 0x7) == 0); - if ((type & SLJIT_CALL_RETURN) && extra_space == 0) - type = SLJIT_JUMP; + if ((type & SLJIT_CALL_RETURN) && extra_space == 0) + type = SLJIT_JUMP; -#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \ - || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) - compiler->skip_checks = 1; -#endif + SLJIT_SKIP_CHECKS(compiler); + FAIL_IF(sljit_emit_ijump(compiler, type, src, srcw)); - FAIL_IF(sljit_emit_ijump(compiler, type, src, srcw)); + if (extra_space > 0) { + if (type & SLJIT_CALL_RETURN) + FAIL_IF(push_inst32(compiler, LDR | RT4(TMP_REG2) + | RN4(SLJIT_SP) | (extra_space - sizeof(sljit_sw)))); - if (extra_space > 0) { - if (type & SLJIT_CALL_RETURN) - FAIL_IF(push_inst32(compiler, LDR | RT4(TMP_REG2) - | RN4(SLJIT_SP) | (extra_space - sizeof(sljit_sw)))); + FAIL_IF(push_inst16(compiler, ADD_SP_I | (extra_space >> 2))); - FAIL_IF(push_inst16(compiler, ADD_SP_I | (extra_space >> 2))); + if (type & SLJIT_CALL_RETURN) + return push_inst16(compiler, BX | RN3(TMP_REG2)); + } - if (type & SLJIT_CALL_RETURN) - return push_inst16(compiler, BX | RN3(TMP_REG2)); + SLJIT_ASSERT(!(type & SLJIT_CALL_RETURN)); + return softfloat_post_call_with_args(compiler, arg_types); } +#endif /* __SOFTFP__ */ - SLJIT_ASSERT(!(type & SLJIT_CALL_RETURN)); - return softfloat_post_call_with_args(compiler, arg_types); -#else /* !__SOFTFP__ */ if (type & SLJIT_CALL_RETURN) { /* ldmia sp!, {..., lr} */ FAIL_IF(emit_stack_frame_release(compiler, -1)); type = SLJIT_JUMP; } - FAIL_IF(hardfloat_call_with_args(compiler, arg_types)); - -#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \ - || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) - compiler->skip_checks = 1; -#endif +#ifndef __SOFTFP__ + if ((type & 0xff) != SLJIT_CALL_REG_ARG) + FAIL_IF(hardfloat_call_with_args(compiler, arg_types)); +#endif /* !__SOFTFP__ */ + SLJIT_SKIP_CHECKS(compiler); return sljit_emit_ijump(compiler, type, src, srcw); -#endif /* __SOFTFP__ */ } +#ifdef __SOFTFP__ + +static SLJIT_INLINE sljit_s32 emit_fmov_before_return(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 src, sljit_sw srcw) +{ + if (compiler->options & SLJIT_ENTER_REG_ARG) { + if (src == SLJIT_FR0) + return SLJIT_SUCCESS; + + SLJIT_SKIP_CHECKS(compiler); + return sljit_emit_fop1(compiler, op, SLJIT_RETURN_FREG, 0, src, srcw); + } + + if (FAST_IS_REG(src)) { + if (op & SLJIT_32) + return push_inst32(compiler, VMOV | (1 << 20) | DN4(src) | RT4(SLJIT_R0)); + return push_inst32(compiler, VMOV2 | (1 << 20) | DM4(src) | RT4(SLJIT_R0) | RN4(SLJIT_R1)); + } + + SLJIT_SKIP_CHECKS(compiler); + + if (op & SLJIT_32) + return sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, src, srcw); + return sljit_emit_mem(compiler, SLJIT_MOV, SLJIT_REG_PAIR(SLJIT_R0, SLJIT_R1), src, srcw); +} + +#endif /* __SOFTFP__ */ + SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw dstw, sljit_s32 type) @@ -2447,7 +2670,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *co ADJUST_LOCAL_OFFSET(dst, dstw); op = GET_OPCODE(op); - cc = get_cc(compiler, type & 0xff); + cc = get_cc(compiler, type); dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1; if (op < SLJIT_ADD) { @@ -2497,9 +2720,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_cmov(struct sljit_compiler *compil CHECK_ERROR(); CHECK(check_sljit_emit_cmov(compiler, type, dst_reg, src, srcw)); - dst_reg &= ~SLJIT_32; - - cc = get_cc(compiler, type & 0xff); + cc = get_cc(compiler, type & ~SLJIT_32); if (!(src & SLJIT_IMM)) { FAIL_IF(push_inst16(compiler, IT | (cc << 4) | 0x8)); @@ -2541,11 +2762,186 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compile sljit_s32 mem, sljit_sw memw) { sljit_s32 flags; - sljit_ins inst; + sljit_uw imm, tmp; CHECK_ERROR(); CHECK(check_sljit_emit_mem(compiler, type, reg, mem, memw)); + if (!(reg & REG_PAIR_MASK)) + return sljit_emit_mem_unaligned(compiler, type, reg, mem, memw); + + if (type & (SLJIT_MEM_UNALIGNED | SLJIT_MEM_UNALIGNED_16 | SLJIT_MEM_UNALIGNED_32)) { + if ((mem & REG_MASK) == 0) { + if ((memw & 0xfff) >= (0x1000 - SSIZE_OF(sw))) { + imm = get_imm((sljit_uw)((memw + 0x1000) & ~0xfff)); + + if (imm != INVALID_IMM) + memw = (memw & 0xfff) - 0x1000; + } else { + imm = get_imm((sljit_uw)(memw & ~0xfff)); + + if (imm != INVALID_IMM) + memw &= 0xff; + } + + if (imm == INVALID_IMM) { + FAIL_IF(load_immediate(compiler, TMP_REG1, (sljit_uw)memw)); + memw = 0; + } else + FAIL_IF(push_inst32(compiler, MOV_WI | RD4(TMP_REG1) | imm)); + + mem = SLJIT_MEM1(TMP_REG1); + } else if (mem & OFFS_REG_MASK) { + FAIL_IF(push_inst32(compiler, ADD_W | RD4(TMP_REG1) | RN4(mem & REG_MASK) | RM4(OFFS_REG(mem)) | ((sljit_uw)(memw & 0x3) << 6))); + memw = 0; + mem = SLJIT_MEM1(TMP_REG1); + } else if (memw < -0xff) { + /* Zero value can be included in the first case. */ + if ((-memw & 0xfff) <= SSIZE_OF(sw)) + tmp = (sljit_uw)((-memw + 0x7ff) & ~0x7ff); + else + tmp = (sljit_uw)((-memw + 0xfff) & ~0xfff); + + SLJIT_ASSERT(tmp >= (sljit_uw)-memw); + imm = get_imm(tmp); + + if (imm != INVALID_IMM) { + FAIL_IF(push_inst32(compiler, SUB_WI | RD4(TMP_REG1) | RN4(mem & REG_MASK) | imm)); + memw += (sljit_sw)tmp; + SLJIT_ASSERT(memw >= 0 && memw <= 0xfff - SSIZE_OF(sw)); + } else { + FAIL_IF(load_immediate(compiler, TMP_REG1, (sljit_uw)memw)); + FAIL_IF(push_inst16(compiler, ADD | SET_REGS44(TMP_REG1, mem & REG_MASK))); + memw = 0; + } + + mem = SLJIT_MEM1(TMP_REG1); + } else if (memw >= (0x1000 - SSIZE_OF(sw))) { + if ((memw & 0xfff) >= (0x1000 - SSIZE_OF(sw))) { + imm = get_imm((sljit_uw)((memw + 0x1000) & ~0xfff)); + + if (imm != INVALID_IMM) + memw = (memw & 0xfff) - 0x1000; + } else { + imm = get_imm((sljit_uw)(memw & ~0xfff)); + + if (imm != INVALID_IMM) + memw &= 0xfff; + } + + if (imm != INVALID_IMM) { + SLJIT_ASSERT(memw >= -0xff && memw <= 0xfff); + FAIL_IF(push_inst32(compiler, ADD_WI | RD4(TMP_REG1) | RN4(mem & REG_MASK) | imm)); + } else { + FAIL_IF(load_immediate(compiler, TMP_REG1, (sljit_uw)memw)); + FAIL_IF(push_inst16(compiler, ADD | SET_REGS44(TMP_REG1, mem & REG_MASK))); + memw = 0; + } + + mem = SLJIT_MEM1(TMP_REG1); + } + + flags = WORD_SIZE; + + SLJIT_ASSERT(memw <= 0xfff - SSIZE_OF(sw) && memw >= -0xff); + + if (type & SLJIT_MEM_STORE) { + flags |= STORE; + } else if (REG_PAIR_FIRST(reg) == (mem & REG_MASK)) { + FAIL_IF(emit_op_mem(compiler, WORD_SIZE, REG_PAIR_SECOND(reg), mem, memw + SSIZE_OF(sw), TMP_REG2)); + return emit_op_mem(compiler, WORD_SIZE, REG_PAIR_FIRST(reg), mem, memw, TMP_REG2); + } + + FAIL_IF(emit_op_mem(compiler, flags, REG_PAIR_FIRST(reg), mem, memw, TMP_REG2)); + return emit_op_mem(compiler, flags, REG_PAIR_SECOND(reg), mem, memw + SSIZE_OF(sw), TMP_REG2); + } + + flags = 1 << 23; + + if ((mem & REG_MASK) == 0) { + tmp = (sljit_uw)(memw & 0x7fc); + imm = get_imm((sljit_uw)((memw + (tmp <= 0x400 ? 0 : 0x400)) & ~0x3fc)); + + if (imm == INVALID_IMM) { + FAIL_IF(load_immediate(compiler, TMP_REG1, (sljit_uw)memw)); + memw = 0; + } else { + FAIL_IF(push_inst32(compiler, MOV_WI | RD4(TMP_REG1) | imm)); + memw = (memw & 0x3fc) >> 2; + + if (tmp > 0x400) { + memw = 0x100 - memw; + flags = 0; + } + + SLJIT_ASSERT(memw >= 0 && memw <= 0xff); + } + + mem = SLJIT_MEM1(TMP_REG1); + } else if (mem & OFFS_REG_MASK) { + FAIL_IF(push_inst32(compiler, ADD_W | RD4(TMP_REG1) | RN4(mem & REG_MASK) | RM4(OFFS_REG(mem)) | ((sljit_uw)(memw & 0x3) << 6))); + memw = 0; + mem = SLJIT_MEM1(TMP_REG1); + } else if (memw < 0) { + if ((-memw & ~0x3fc) == 0) { + flags = 0; + memw = -memw >> 2; + } else { + tmp = (sljit_uw)(-memw & 0x7fc); + imm = get_imm((sljit_uw)((-memw + (tmp <= 0x400 ? 0 : 0x400)) & ~0x3fc)); + + if (imm != INVALID_IMM) { + FAIL_IF(push_inst32(compiler, SUB_WI | RD4(TMP_REG1) | RN4(mem & REG_MASK) | imm)); + memw = (-memw & 0x3fc) >> 2; + + if (tmp <= 0x400) + flags = 0; + else + memw = 0x100 - memw; + } else { + FAIL_IF(load_immediate(compiler, TMP_REG1, (sljit_uw)memw)); + FAIL_IF(push_inst16(compiler, ADD | SET_REGS44(TMP_REG1, mem & REG_MASK))); + memw = 0; + } + + mem = SLJIT_MEM1(TMP_REG1); + } + } else if ((memw & ~0x3fc) != 0) { + tmp = (sljit_uw)(memw & 0x7fc); + imm = get_imm((sljit_uw)((memw + (tmp <= 0x400 ? 0 : 0x400)) & ~0x3fc)); + + if (imm != INVALID_IMM) { + FAIL_IF(push_inst32(compiler, ADD_WI | RD4(TMP_REG1) | RN4(mem & REG_MASK) | imm)); + memw = (memw & 0x3fc) >> 2; + + if (tmp > 0x400) { + memw = 0x100 - memw; + flags = 0; + } + } else { + FAIL_IF(load_immediate(compiler, TMP_REG1, (sljit_uw)memw)); + FAIL_IF(push_inst16(compiler, ADD | SET_REGS44(TMP_REG1, mem & REG_MASK))); + memw = 0; + } + + mem = SLJIT_MEM1(TMP_REG1); + } else + memw >>= 2; + + SLJIT_ASSERT(memw >= 0 && memw <= 0xff); + return push_inst32(compiler, ((type & SLJIT_MEM_STORE) ? STRD : LDRD) | (sljit_ins)flags | RN4(mem & REG_MASK) | RT4(REG_PAIR_FIRST(reg)) | RD4(REG_PAIR_SECOND(reg)) | (sljit_ins)memw); +} + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem_update(struct sljit_compiler *compiler, sljit_s32 type, + sljit_s32 reg, + sljit_s32 mem, sljit_sw memw) +{ + sljit_s32 flags; + sljit_ins inst; + + CHECK_ERROR(); + CHECK(check_sljit_emit_mem_update(compiler, type, reg, mem, memw)); + if ((mem & OFFS_REG_MASK) || (memw > 255 || memw < -255)) return SLJIT_ERR_UNSUPPORTED; @@ -2583,7 +2979,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compile inst = sljit_mem32[flags] | 0x900; - if (type & SLJIT_MEM_PRE) + if (!(type & SLJIT_MEM_POST)) inst |= 0x400; if (memw >= 0) @@ -2594,6 +2990,106 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compile return push_inst32(compiler, inst | RT4(reg) | RN4(mem & REG_MASK) | (sljit_ins)memw); } +static sljit_s32 update_mem_addr(struct sljit_compiler *compiler, sljit_s32 *mem, sljit_sw *memw, sljit_s32 max_offset) +{ + sljit_s32 arg = *mem; + sljit_sw argw = *memw; + sljit_uw imm; + + *mem = TMP_REG1; + + if (SLJIT_UNLIKELY(arg & OFFS_REG_MASK)) { + *memw = 0; + return push_inst32(compiler, ADD_W | RD4(TMP_REG1) | RN4(arg & REG_MASK) | RM4(OFFS_REG(arg)) | ((sljit_uw)(argw & 0x3) << 6)); + } + + arg &= REG_MASK; + + if (arg) { + if (argw <= max_offset && argw >= -0xff) { + *mem = arg; + return SLJIT_SUCCESS; + } + + if (argw < 0) { + imm = get_imm((sljit_uw)(-argw & ~0xff)); + + if (imm) { + *memw = -(-argw & 0xff); + return push_inst32(compiler, SUB_WI | RD4(TMP_REG1) | RN4(arg) | imm); + } + } else if ((argw & 0xfff) <= max_offset) { + imm = get_imm((sljit_uw)(argw & ~0xfff)); + + if (imm) { + *memw = argw & 0xfff; + return push_inst32(compiler, ADD_WI | RD4(TMP_REG1) | RN4(arg) | imm); + } + } else { + imm = get_imm((sljit_uw)((argw | 0xfff) + 1)); + + if (imm) { + *memw = (argw & 0xfff) - 0x1000; + return push_inst32(compiler, ADD_WI | RD4(TMP_REG1) | RN4(arg) | imm); + } + } + } + + imm = (sljit_uw)(argw & ~0xfff); + + if ((argw & 0xfff) > max_offset) { + imm += 0x1000; + *memw = (argw & 0xfff) - 0x1000; + } else + *memw = argw & 0xfff; + + FAIL_IF(load_immediate(compiler, TMP_REG1, imm)); + + if (arg == 0) + return SLJIT_SUCCESS; + + return push_inst16(compiler, ADD | SET_REGS44(TMP_REG1, arg)); +} + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fmem(struct sljit_compiler *compiler, sljit_s32 type, + sljit_s32 freg, + sljit_s32 mem, sljit_sw memw) +{ + CHECK_ERROR(); + CHECK(check_sljit_emit_fmem(compiler, type, freg, mem, memw)); + + if (type & SLJIT_MEM_UNALIGNED_32) + return emit_fop_mem(compiler, ((type ^ SLJIT_32) & SLJIT_32) | ((type & SLJIT_MEM_STORE) ? 0 : FPU_LOAD), freg, mem, memw); + + if (type & SLJIT_MEM_STORE) { + FAIL_IF(push_inst32(compiler, VMOV | (1 << 20) | DN4(freg) | RT4(TMP_REG2))); + + if (type & SLJIT_32) + return emit_op_mem(compiler, WORD_SIZE | STORE, TMP_REG2, mem, memw, TMP_REG1); + + FAIL_IF(update_mem_addr(compiler, &mem, &memw, 0xfff - 4)); + mem |= SLJIT_MEM; + + FAIL_IF(emit_op_mem(compiler, WORD_SIZE | STORE, TMP_REG2, mem, memw, TMP_REG1)); + FAIL_IF(push_inst32(compiler, VMOV | (1 << 20) | DN4(freg) | 0x80 | RT4(TMP_REG2))); + return emit_op_mem(compiler, WORD_SIZE | STORE, TMP_REG2, mem, memw + 4, TMP_REG1); + } + + if (type & SLJIT_32) { + FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_REG2, mem, memw, TMP_REG1)); + return push_inst32(compiler, VMOV | DN4(freg) | RT4(TMP_REG2)); + } + + FAIL_IF(update_mem_addr(compiler, &mem, &memw, 0xfff - 4)); + mem |= SLJIT_MEM; + + FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_REG2, mem, memw, TMP_REG1)); + FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_REG1, mem, memw + 4, TMP_REG1)); + return push_inst32(compiler, VMOV2 | DM4(freg) | RT4(TMP_REG2) | RN4(TMP_REG1)); +} + +#undef FPU_LOAD + SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw init_value) { struct sljit_const *const_; diff --git a/src/3rdparty/pcre2/src/sljit/sljitNativeMIPS_32.c b/src/3rdparty/pcre2/src/sljit/sljitNativeMIPS_32.c index 1a06b17d129..e6853c98f67 100644 --- a/src/3rdparty/pcre2/src/sljit/sljitNativeMIPS_32.c +++ b/src/3rdparty/pcre2/src/sljit/sljitNativeMIPS_32.c @@ -38,383 +38,6 @@ static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 dst_a return (imm & 0xffff) ? push_inst(compiler, ORI | SA(dst_ar) | TA(dst_ar) | IMM(imm), dst_ar) : SLJIT_SUCCESS; } -#define EMIT_LOGICAL(op_imm, op_norm) \ - if (flags & SRC2_IMM) { \ - if (op & SLJIT_SET_Z) \ - FAIL_IF(push_inst(compiler, op_imm | S(src1) | TA(EQUAL_FLAG) | IMM(src2), EQUAL_FLAG)); \ - if (!(flags & UNUSED_DEST)) \ - FAIL_IF(push_inst(compiler, op_imm | S(src1) | T(dst) | IMM(src2), DR(dst))); \ - } \ - else { \ - if (op & SLJIT_SET_Z) \ - FAIL_IF(push_inst(compiler, op_norm | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG)); \ - if (!(flags & UNUSED_DEST)) \ - FAIL_IF(push_inst(compiler, op_norm | S(src1) | T(src2) | D(dst), DR(dst))); \ - } - -#define EMIT_SHIFT(op_imm, op_v) \ - if (flags & SRC2_IMM) { \ - if (op & SLJIT_SET_Z) \ - FAIL_IF(push_inst(compiler, op_imm | T(src1) | DA(EQUAL_FLAG) | SH_IMM(src2), EQUAL_FLAG)); \ - if (!(flags & UNUSED_DEST)) \ - FAIL_IF(push_inst(compiler, op_imm | T(src1) | D(dst) | SH_IMM(src2), DR(dst))); \ - } \ - else { \ - if (op & SLJIT_SET_Z) \ - FAIL_IF(push_inst(compiler, op_v | S(src2) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG)); \ - if (!(flags & UNUSED_DEST)) \ - FAIL_IF(push_inst(compiler, op_v | S(src2) | T(src1) | D(dst), DR(dst))); \ - } - -static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 flags, - sljit_s32 dst, sljit_s32 src1, sljit_sw src2) -{ - sljit_s32 is_overflow, is_carry, is_handled; - - switch (GET_OPCODE(op)) { - case SLJIT_MOV: - SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM)); - if (dst != src2) - return push_inst(compiler, ADDU | S(src2) | TA(0) | D(dst), DR(dst)); - return SLJIT_SUCCESS; - - case SLJIT_MOV_U8: - SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM)); - if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) - return push_inst(compiler, ANDI | S(src2) | T(dst) | IMM(0xff), DR(dst)); - SLJIT_ASSERT(dst == src2); - return SLJIT_SUCCESS; - - case SLJIT_MOV_S8: - SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM)); - if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) { -#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1) - return push_inst(compiler, SEB | T(src2) | D(dst), DR(dst)); -#else /* SLJIT_MIPS_REV < 1 */ - FAIL_IF(push_inst(compiler, SLL | T(src2) | D(dst) | SH_IMM(24), DR(dst))); - return push_inst(compiler, SRA | T(dst) | D(dst) | SH_IMM(24), DR(dst)); -#endif /* SLJIT_MIPS_REV >= 1 */ - } - SLJIT_ASSERT(dst == src2); - return SLJIT_SUCCESS; - - case SLJIT_MOV_U16: - SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM)); - if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) - return push_inst(compiler, ANDI | S(src2) | T(dst) | IMM(0xffff), DR(dst)); - SLJIT_ASSERT(dst == src2); - return SLJIT_SUCCESS; - - case SLJIT_MOV_S16: - SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM)); - if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) { -#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1) - return push_inst(compiler, SEH | T(src2) | D(dst), DR(dst)); -#else /* SLJIT_MIPS_REV < 1 */ - FAIL_IF(push_inst(compiler, SLL | T(src2) | D(dst) | SH_IMM(16), DR(dst))); - return push_inst(compiler, SRA | T(dst) | D(dst) | SH_IMM(16), DR(dst)); -#endif /* SLJIT_MIPS_REV >= 1 */ - } - SLJIT_ASSERT(dst == src2); - return SLJIT_SUCCESS; - - case SLJIT_NOT: - SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM)); - if (op & SLJIT_SET_Z) - FAIL_IF(push_inst(compiler, NOR | S(src2) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG)); - if (!(flags & UNUSED_DEST)) - FAIL_IF(push_inst(compiler, NOR | S(src2) | T(src2) | D(dst), DR(dst))); - return SLJIT_SUCCESS; - - case SLJIT_CLZ: - SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM)); -#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1) - if (op & SLJIT_SET_Z) - FAIL_IF(push_inst(compiler, CLZ | S(src2) | TA(EQUAL_FLAG) | DA(EQUAL_FLAG), EQUAL_FLAG)); - if (!(flags & UNUSED_DEST)) - FAIL_IF(push_inst(compiler, CLZ | S(src2) | T(dst) | D(dst), DR(dst))); -#else /* SLJIT_MIPS_REV < 1 */ - if (SLJIT_UNLIKELY(flags & UNUSED_DEST)) { - FAIL_IF(push_inst(compiler, SRL | T(src2) | DA(EQUAL_FLAG) | SH_IMM(31), EQUAL_FLAG)); - return push_inst(compiler, XORI | SA(EQUAL_FLAG) | TA(EQUAL_FLAG) | IMM(1), EQUAL_FLAG); - } - /* Nearly all instructions are unmovable in the following sequence. */ - FAIL_IF(push_inst(compiler, ADDU | S(src2) | TA(0) | D(TMP_REG1), DR(TMP_REG1))); - /* Check zero. */ - FAIL_IF(push_inst(compiler, BEQ | S(TMP_REG1) | TA(0) | IMM(5), UNMOVABLE_INS)); - FAIL_IF(push_inst(compiler, ORI | SA(0) | T(dst) | IMM(32), UNMOVABLE_INS)); - FAIL_IF(push_inst(compiler, ADDIU | SA(0) | T(dst) | IMM(-1), DR(dst))); - /* Loop for searching the highest bit. */ - FAIL_IF(push_inst(compiler, ADDIU | S(dst) | T(dst) | IMM(1), DR(dst))); - FAIL_IF(push_inst(compiler, BGEZ | S(TMP_REG1) | IMM(-2), UNMOVABLE_INS)); - FAIL_IF(push_inst(compiler, SLL | T(TMP_REG1) | D(TMP_REG1) | SH_IMM(1), UNMOVABLE_INS)); -#endif /* SLJIT_MIPS_REV >= 1 */ - return SLJIT_SUCCESS; - - case SLJIT_ADD: - is_overflow = GET_FLAG_TYPE(op) == SLJIT_OVERFLOW; - is_carry = GET_FLAG_TYPE(op) == GET_FLAG_TYPE(SLJIT_SET_CARRY); - - if (flags & SRC2_IMM) { - if (is_overflow) { - if (src2 >= 0) - FAIL_IF(push_inst(compiler, OR | S(src1) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG)); - else - FAIL_IF(push_inst(compiler, NOR | S(src1) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG)); - } - else if (op & SLJIT_SET_Z) - FAIL_IF(push_inst(compiler, ADDIU | S(src1) | TA(EQUAL_FLAG) | IMM(src2), EQUAL_FLAG)); - - if (is_overflow || is_carry) { - if (src2 >= 0) - FAIL_IF(push_inst(compiler, ORI | S(src1) | TA(OTHER_FLAG) | IMM(src2), OTHER_FLAG)); - else { - FAIL_IF(push_inst(compiler, ADDIU | SA(0) | TA(OTHER_FLAG) | IMM(src2), OTHER_FLAG)); - FAIL_IF(push_inst(compiler, OR | S(src1) | TA(OTHER_FLAG) | DA(OTHER_FLAG), OTHER_FLAG)); - } - } - /* dst may be the same as src1 or src2. */ - if (!(flags & UNUSED_DEST) || (op & VARIABLE_FLAG_MASK)) - FAIL_IF(push_inst(compiler, ADDIU | S(src1) | T(dst) | IMM(src2), DR(dst))); - } - else { - if (is_overflow) - FAIL_IF(push_inst(compiler, XOR | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG)); - else if (op & SLJIT_SET_Z) - FAIL_IF(push_inst(compiler, ADDU | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG)); - - if (is_overflow || is_carry) - FAIL_IF(push_inst(compiler, OR | S(src1) | T(src2) | DA(OTHER_FLAG), OTHER_FLAG)); - /* dst may be the same as src1 or src2. */ - if (!(flags & UNUSED_DEST) || (op & VARIABLE_FLAG_MASK)) - FAIL_IF(push_inst(compiler, ADDU | S(src1) | T(src2) | D(dst), DR(dst))); - } - - /* a + b >= a | b (otherwise, the carry should be set to 1). */ - if (is_overflow || is_carry) - FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(OTHER_FLAG) | DA(OTHER_FLAG), OTHER_FLAG)); - if (!is_overflow) - return SLJIT_SUCCESS; - FAIL_IF(push_inst(compiler, SLL | TA(OTHER_FLAG) | D(TMP_REG1) | SH_IMM(31), DR(TMP_REG1))); - FAIL_IF(push_inst(compiler, XOR | S(TMP_REG1) | TA(EQUAL_FLAG) | DA(EQUAL_FLAG), EQUAL_FLAG)); - FAIL_IF(push_inst(compiler, XOR | S(dst) | TA(EQUAL_FLAG) | DA(OTHER_FLAG), OTHER_FLAG)); - if (op & SLJIT_SET_Z) - FAIL_IF(push_inst(compiler, ADDU | S(dst) | TA(0) | DA(EQUAL_FLAG), EQUAL_FLAG)); - return push_inst(compiler, SRL | TA(OTHER_FLAG) | DA(OTHER_FLAG) | SH_IMM(31), OTHER_FLAG); - - case SLJIT_ADDC: - is_carry = GET_FLAG_TYPE(op) == GET_FLAG_TYPE(SLJIT_SET_CARRY); - - if (flags & SRC2_IMM) { - if (is_carry) { - if (src2 >= 0) - FAIL_IF(push_inst(compiler, ORI | S(src1) | TA(EQUAL_FLAG) | IMM(src2), EQUAL_FLAG)); - else { - FAIL_IF(push_inst(compiler, ADDIU | SA(0) | TA(EQUAL_FLAG) | IMM(src2), EQUAL_FLAG)); - FAIL_IF(push_inst(compiler, OR | S(src1) | TA(EQUAL_FLAG) | DA(EQUAL_FLAG), EQUAL_FLAG)); - } - } - FAIL_IF(push_inst(compiler, ADDIU | S(src1) | T(dst) | IMM(src2), DR(dst))); - } else { - if (is_carry) - FAIL_IF(push_inst(compiler, OR | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG)); - /* dst may be the same as src1 or src2. */ - FAIL_IF(push_inst(compiler, ADDU | S(src1) | T(src2) | D(dst), DR(dst))); - } - if (is_carry) - FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(EQUAL_FLAG) | DA(EQUAL_FLAG), EQUAL_FLAG)); - - FAIL_IF(push_inst(compiler, ADDU | S(dst) | TA(OTHER_FLAG) | D(dst), DR(dst))); - if (!is_carry) - return SLJIT_SUCCESS; - - /* Set ULESS_FLAG (dst == 0) && (OTHER_FLAG == 1). */ - FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(OTHER_FLAG) | DA(OTHER_FLAG), OTHER_FLAG)); - /* Set carry flag. */ - return push_inst(compiler, OR | SA(OTHER_FLAG) | TA(EQUAL_FLAG) | DA(OTHER_FLAG), OTHER_FLAG); - - case SLJIT_SUB: - if ((flags & SRC2_IMM) && src2 == SIMM_MIN) { - FAIL_IF(push_inst(compiler, ADDIU | SA(0) | T(TMP_REG2) | IMM(src2), DR(TMP_REG2))); - src2 = TMP_REG2; - flags &= ~SRC2_IMM; - } - - is_handled = 0; - - if (flags & SRC2_IMM) { - if (GET_FLAG_TYPE(op) == SLJIT_LESS || GET_FLAG_TYPE(op) == SLJIT_GREATER_EQUAL) { - FAIL_IF(push_inst(compiler, SLTIU | S(src1) | TA(OTHER_FLAG) | IMM(src2), OTHER_FLAG)); - is_handled = 1; - } - else if (GET_FLAG_TYPE(op) == SLJIT_SIG_LESS || GET_FLAG_TYPE(op) == SLJIT_SIG_GREATER_EQUAL) { - FAIL_IF(push_inst(compiler, SLTI | S(src1) | TA(OTHER_FLAG) | IMM(src2), OTHER_FLAG)); - is_handled = 1; - } - } - - if (!is_handled && GET_FLAG_TYPE(op) >= SLJIT_LESS && GET_FLAG_TYPE(op) <= SLJIT_SIG_LESS_EQUAL) { - is_handled = 1; - - if (flags & SRC2_IMM) { - FAIL_IF(push_inst(compiler, ADDIU | SA(0) | T(TMP_REG2) | IMM(src2), DR(TMP_REG2))); - src2 = TMP_REG2; - flags &= ~SRC2_IMM; - } - - if (GET_FLAG_TYPE(op) == SLJIT_LESS || GET_FLAG_TYPE(op) == SLJIT_GREATER_EQUAL) { - FAIL_IF(push_inst(compiler, SLTU | S(src1) | T(src2) | DA(OTHER_FLAG), OTHER_FLAG)); - } - else if (GET_FLAG_TYPE(op) == SLJIT_GREATER || GET_FLAG_TYPE(op) == SLJIT_LESS_EQUAL) - { - FAIL_IF(push_inst(compiler, SLTU | S(src2) | T(src1) | DA(OTHER_FLAG), OTHER_FLAG)); - } - else if (GET_FLAG_TYPE(op) == SLJIT_SIG_LESS || GET_FLAG_TYPE(op) == SLJIT_SIG_GREATER_EQUAL) { - FAIL_IF(push_inst(compiler, SLT | S(src1) | T(src2) | DA(OTHER_FLAG), OTHER_FLAG)); - } - else if (GET_FLAG_TYPE(op) == SLJIT_SIG_GREATER || GET_FLAG_TYPE(op) == SLJIT_SIG_LESS_EQUAL) - { - FAIL_IF(push_inst(compiler, SLT | S(src2) | T(src1) | DA(OTHER_FLAG), OTHER_FLAG)); - } - } - - if (is_handled) { - if (flags & SRC2_IMM) { - if (op & SLJIT_SET_Z) - FAIL_IF(push_inst(compiler, ADDIU | S(src1) | TA(EQUAL_FLAG) | IMM(-src2), EQUAL_FLAG)); - if (!(flags & UNUSED_DEST)) - return push_inst(compiler, ADDIU | S(src1) | T(dst) | IMM(-src2), DR(dst)); - } - else { - if (op & SLJIT_SET_Z) - FAIL_IF(push_inst(compiler, SUBU | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG)); - if (!(flags & UNUSED_DEST)) - return push_inst(compiler, SUBU | S(src1) | T(src2) | D(dst), DR(dst)); - } - return SLJIT_SUCCESS; - } - - is_overflow = GET_FLAG_TYPE(op) == SLJIT_OVERFLOW; - is_carry = GET_FLAG_TYPE(op) == GET_FLAG_TYPE(SLJIT_SET_CARRY); - - if (flags & SRC2_IMM) { - if (is_overflow) { - if (src2 >= 0) - FAIL_IF(push_inst(compiler, OR | S(src1) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG)); - else - FAIL_IF(push_inst(compiler, NOR | S(src1) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG)); - } - else if (op & SLJIT_SET_Z) - FAIL_IF(push_inst(compiler, ADDIU | S(src1) | TA(EQUAL_FLAG) | IMM(-src2), EQUAL_FLAG)); - - if (is_overflow || is_carry) - FAIL_IF(push_inst(compiler, SLTIU | S(src1) | TA(OTHER_FLAG) | IMM(src2), OTHER_FLAG)); - /* dst may be the same as src1 or src2. */ - if (!(flags & UNUSED_DEST) || (op & VARIABLE_FLAG_MASK)) - FAIL_IF(push_inst(compiler, ADDIU | S(src1) | T(dst) | IMM(-src2), DR(dst))); - } - else { - if (is_overflow) - FAIL_IF(push_inst(compiler, XOR | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG)); - else if (op & SLJIT_SET_Z) - FAIL_IF(push_inst(compiler, SUBU | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG)); - - if (is_overflow || is_carry) - FAIL_IF(push_inst(compiler, SLTU | S(src1) | T(src2) | DA(OTHER_FLAG), OTHER_FLAG)); - /* dst may be the same as src1 or src2. */ - if (!(flags & UNUSED_DEST) || (op & VARIABLE_FLAG_MASK)) - FAIL_IF(push_inst(compiler, SUBU | S(src1) | T(src2) | D(dst), DR(dst))); - } - - if (!is_overflow) - return SLJIT_SUCCESS; - FAIL_IF(push_inst(compiler, SLL | TA(OTHER_FLAG) | D(TMP_REG1) | SH_IMM(31), DR(TMP_REG1))); - FAIL_IF(push_inst(compiler, XOR | S(TMP_REG1) | TA(EQUAL_FLAG) | DA(EQUAL_FLAG), EQUAL_FLAG)); - FAIL_IF(push_inst(compiler, XOR | S(dst) | TA(EQUAL_FLAG) | DA(OTHER_FLAG), OTHER_FLAG)); - if (op & SLJIT_SET_Z) - FAIL_IF(push_inst(compiler, ADDU | S(dst) | TA(0) | DA(EQUAL_FLAG), EQUAL_FLAG)); - return push_inst(compiler, SRL | TA(OTHER_FLAG) | DA(OTHER_FLAG) | SH_IMM(31), OTHER_FLAG); - - case SLJIT_SUBC: - if ((flags & SRC2_IMM) && src2 == SIMM_MIN) { - FAIL_IF(push_inst(compiler, ADDIU | SA(0) | T(TMP_REG2) | IMM(src2), DR(TMP_REG2))); - src2 = TMP_REG2; - flags &= ~SRC2_IMM; - } - - is_carry = GET_FLAG_TYPE(op) == GET_FLAG_TYPE(SLJIT_SET_CARRY); - - if (flags & SRC2_IMM) { - if (is_carry) - FAIL_IF(push_inst(compiler, SLTIU | S(src1) | TA(EQUAL_FLAG) | IMM(src2), EQUAL_FLAG)); - /* dst may be the same as src1 or src2. */ - FAIL_IF(push_inst(compiler, ADDIU | S(src1) | T(dst) | IMM(-src2), DR(dst))); - } - else { - if (is_carry) - FAIL_IF(push_inst(compiler, SLTU | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG)); - /* dst may be the same as src1 or src2. */ - FAIL_IF(push_inst(compiler, SUBU | S(src1) | T(src2) | D(dst), DR(dst))); - } - - if (is_carry) - FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(OTHER_FLAG) | D(TMP_REG1), DR(TMP_REG1))); - - FAIL_IF(push_inst(compiler, SUBU | S(dst) | TA(OTHER_FLAG) | D(dst), DR(dst))); - return (is_carry) ? push_inst(compiler, OR | SA(EQUAL_FLAG) | T(TMP_REG1) | DA(OTHER_FLAG), OTHER_FLAG) : SLJIT_SUCCESS; - - case SLJIT_MUL: - SLJIT_ASSERT(!(flags & SRC2_IMM)); - - if (GET_FLAG_TYPE(op) != SLJIT_OVERFLOW) { -#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1) - return push_inst(compiler, MUL | S(src1) | T(src2) | D(dst), DR(dst)); -#else /* SLJIT_MIPS_REV < 1 */ - FAIL_IF(push_inst(compiler, MULT | S(src1) | T(src2), MOVABLE_INS)); - return push_inst(compiler, MFLO | D(dst), DR(dst)); -#endif /* SLJIT_MIPS_REV >= 1 */ - } - -#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6) - FAIL_IF(push_inst(compiler, MUL | S(src1) | T(src2) | D(dst), DR(dst))); - FAIL_IF(push_inst(compiler, MUH | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG)); -#else /* SLJIT_MIPS_REV < 6 */ - FAIL_IF(push_inst(compiler, MULT | S(src1) | T(src2), MOVABLE_INS)); - FAIL_IF(push_inst(compiler, MFHI | DA(EQUAL_FLAG), EQUAL_FLAG)); - FAIL_IF(push_inst(compiler, MFLO | D(dst), DR(dst))); -#endif /* SLJIT_MIPS_REV >= 6 */ - FAIL_IF(push_inst(compiler, SRA | T(dst) | DA(OTHER_FLAG) | SH_IMM(31), OTHER_FLAG)); - return push_inst(compiler, SUBU | SA(EQUAL_FLAG) | TA(OTHER_FLAG) | DA(OTHER_FLAG), OTHER_FLAG); - - case SLJIT_AND: - EMIT_LOGICAL(ANDI, AND); - return SLJIT_SUCCESS; - - case SLJIT_OR: - EMIT_LOGICAL(ORI, OR); - return SLJIT_SUCCESS; - - case SLJIT_XOR: - EMIT_LOGICAL(XORI, XOR); - return SLJIT_SUCCESS; - - case SLJIT_SHL: - EMIT_SHIFT(SLL, SLLV); - return SLJIT_SUCCESS; - - case SLJIT_LSHR: - EMIT_SHIFT(SRL, SRLV); - return SLJIT_SUCCESS; - - case SLJIT_ASHR: - EMIT_SHIFT(SRA, SRAV); - return SLJIT_SUCCESS; - } - - SLJIT_UNREACHABLE(); - return SLJIT_SUCCESS; -} - static SLJIT_INLINE sljit_s32 emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw init_value) { FAIL_IF(push_inst(compiler, LUI | T(dst) | IMM(init_value >> 16), DR(dst))); @@ -573,8 +196,8 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compile sljit_s32 arg_types) { struct sljit_jump *jump; - sljit_u32 extra_space = (sljit_u32)type; - sljit_ins ins; + sljit_u32 extra_space = 0; + sljit_ins ins = NOP; CHECK_ERROR_PTR(); CHECK_PTR(check_sljit_emit_call(compiler, type, arg_types)); @@ -583,14 +206,23 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compile PTR_FAIL_IF(!jump); set_jump(jump, compiler, type & SLJIT_REWRITABLE_JUMP); - PTR_FAIL_IF(call_with_args(compiler, arg_types, &ins, &extra_space)); + if ((type & 0xff) != SLJIT_CALL_REG_ARG) { + extra_space = (sljit_u32)type; + PTR_FAIL_IF(call_with_args(compiler, arg_types, &ins, &extra_space)); + } else if (type & SLJIT_CALL_RETURN) + PTR_FAIL_IF(emit_stack_frame_release(compiler, 0, &ins)); SLJIT_ASSERT(DR(PIC_ADDR_REG) == 25 && PIC_ADDR_REG == TMP_REG2); - PTR_FAIL_IF(emit_const(compiler, PIC_ADDR_REG, 0)); + if (ins == NOP && compiler->delay_slot != UNMOVABLE_INS) + jump->flags |= IS_MOVABLE; if (!(type & SLJIT_CALL_RETURN) || extra_space > 0) { - jump->flags |= IS_JAL | IS_CALL; + jump->flags |= IS_JAL; + + if ((type & 0xff) != SLJIT_CALL_REG_ARG) + jump->flags |= IS_CALL; + PTR_FAIL_IF(push_inst(compiler, JALR | S(PIC_ADDR_REG) | DA(RETURN_ADDR_REG), UNMOVABLE_INS)); } else PTR_FAIL_IF(push_inst(compiler, JR | S(PIC_ADDR_REG), UNMOVABLE_INS)); @@ -598,6 +230,9 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compile jump->addr = compiler->size; PTR_FAIL_IF(push_inst(compiler, ins, UNMOVABLE_INS)); + /* Maximum number of instructions required for generating a constant. */ + compiler->size += 2; + if (extra_space == 0) return jump; @@ -623,16 +258,37 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compi CHECK_ERROR(); CHECK(check_sljit_emit_icall(compiler, type, arg_types, src, srcw)); + if (src & SLJIT_MEM) { + ADJUST_LOCAL_OFFSET(src, srcw); + FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, DR(PIC_ADDR_REG), src, srcw)); + src = PIC_ADDR_REG; + srcw = 0; + } + + if ((type & 0xff) == SLJIT_CALL_REG_ARG) { + if (type & SLJIT_CALL_RETURN) { + if (src >= SLJIT_FIRST_SAVED_REG && src <= (SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options))) { + FAIL_IF(push_inst(compiler, ADDU | S(src) | TA(0) | D(PIC_ADDR_REG), DR(PIC_ADDR_REG))); + src = PIC_ADDR_REG; + srcw = 0; + } + + FAIL_IF(emit_stack_frame_release(compiler, 0, &ins)); + + if (ins != NOP) + FAIL_IF(push_inst(compiler, ins, MOVABLE_INS)); + } + + SLJIT_SKIP_CHECKS(compiler); + return sljit_emit_ijump(compiler, type, src, srcw); + } + SLJIT_ASSERT(DR(PIC_ADDR_REG) == 25 && PIC_ADDR_REG == TMP_REG2); if (src & SLJIT_IMM) FAIL_IF(load_immediate(compiler, DR(PIC_ADDR_REG), srcw)); - else if (FAST_IS_REG(src)) + else if (src != PIC_ADDR_REG) FAIL_IF(push_inst(compiler, ADDU | S(src) | TA(0) | D(PIC_ADDR_REG), DR(PIC_ADDR_REG))); - else if (src & SLJIT_MEM) { - ADJUST_LOCAL_OFFSET(src, srcw); - FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, DR(PIC_ADDR_REG), src, srcw)); - } FAIL_IF(call_with_args(compiler, arg_types, &ins, &extra_space)); diff --git a/src/3rdparty/pcre2/src/sljit/sljitNativeMIPS_64.c b/src/3rdparty/pcre2/src/sljit/sljitNativeMIPS_64.c index c2b3d839c23..d2a5924f8e9 100644 --- a/src/3rdparty/pcre2/src/sljit/sljitNativeMIPS_64.c +++ b/src/3rdparty/pcre2/src/sljit/sljitNativeMIPS_64.c @@ -118,421 +118,6 @@ static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 dst_a return !(imm & 0xffff) ? SLJIT_SUCCESS : push_inst(compiler, ORI | SA(dst_ar) | TA(dst_ar) | IMM(imm), dst_ar); } -#define SELECT_OP(a, b) \ - (!(op & SLJIT_32) ? a : b) - -#define EMIT_LOGICAL(op_imm, op_norm) \ - if (flags & SRC2_IMM) { \ - if (op & SLJIT_SET_Z) \ - FAIL_IF(push_inst(compiler, op_imm | S(src1) | TA(EQUAL_FLAG) | IMM(src2), EQUAL_FLAG)); \ - if (!(flags & UNUSED_DEST)) \ - FAIL_IF(push_inst(compiler, op_imm | S(src1) | T(dst) | IMM(src2), DR(dst))); \ - } \ - else { \ - if (op & SLJIT_SET_Z) \ - FAIL_IF(push_inst(compiler, op_norm | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG)); \ - if (!(flags & UNUSED_DEST)) \ - FAIL_IF(push_inst(compiler, op_norm | S(src1) | T(src2) | D(dst), DR(dst))); \ - } - -#define EMIT_SHIFT(op_dimm, op_dimm32, op_imm, op_dv, op_v) \ - if (flags & SRC2_IMM) { \ - if (src2 >= 32) { \ - SLJIT_ASSERT(!(op & SLJIT_32)); \ - ins = op_dimm32; \ - src2 -= 32; \ - } \ - else \ - ins = (op & SLJIT_32) ? op_imm : op_dimm; \ - if (op & SLJIT_SET_Z) \ - FAIL_IF(push_inst(compiler, ins | T(src1) | DA(EQUAL_FLAG) | SH_IMM(src2), EQUAL_FLAG)); \ - if (!(flags & UNUSED_DEST)) \ - FAIL_IF(push_inst(compiler, ins | T(src1) | D(dst) | SH_IMM(src2), DR(dst))); \ - } \ - else { \ - ins = (op & SLJIT_32) ? op_v : op_dv; \ - if (op & SLJIT_SET_Z) \ - FAIL_IF(push_inst(compiler, ins | S(src2) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG)); \ - if (!(flags & UNUSED_DEST)) \ - FAIL_IF(push_inst(compiler, ins | S(src2) | T(src1) | D(dst), DR(dst))); \ - } - -static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 flags, - sljit_s32 dst, sljit_s32 src1, sljit_sw src2) -{ - sljit_ins ins; - sljit_s32 is_overflow, is_carry, is_handled; - - switch (GET_OPCODE(op)) { - case SLJIT_MOV: - SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM)); - if (dst != src2) - return push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(src2) | TA(0) | D(dst), DR(dst)); - return SLJIT_SUCCESS; - - case SLJIT_MOV_U8: - SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM)); - if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) - return push_inst(compiler, ANDI | S(src2) | T(dst) | IMM(0xff), DR(dst)); - SLJIT_ASSERT(dst == src2); - return SLJIT_SUCCESS; - - case SLJIT_MOV_S8: - SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM)); - if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) { -#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1) - if (op & SLJIT_32) - return push_inst(compiler, SEB | T(src2) | D(dst), DR(dst)); -#endif /* SLJIT_MIPS_REV >= 1 */ - FAIL_IF(push_inst(compiler, DSLL32 | T(src2) | D(dst) | SH_IMM(24), DR(dst))); - return push_inst(compiler, DSRA32 | T(dst) | D(dst) | SH_IMM(24), DR(dst)); - } - SLJIT_ASSERT(dst == src2); - return SLJIT_SUCCESS; - - case SLJIT_MOV_U16: - SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM)); - if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) - return push_inst(compiler, ANDI | S(src2) | T(dst) | IMM(0xffff), DR(dst)); - SLJIT_ASSERT(dst == src2); - return SLJIT_SUCCESS; - - case SLJIT_MOV_S16: - SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM)); - if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) { -#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1) - if (op & SLJIT_32) - return push_inst(compiler, SEH | T(src2) | D(dst), DR(dst)); -#endif /* SLJIT_MIPS_REV >= 1 */ - FAIL_IF(push_inst(compiler, DSLL32 | T(src2) | D(dst) | SH_IMM(16), DR(dst))); - return push_inst(compiler, DSRA32 | T(dst) | D(dst) | SH_IMM(16), DR(dst)); - } - SLJIT_ASSERT(dst == src2); - return SLJIT_SUCCESS; - - case SLJIT_MOV_U32: - SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM) && !(op & SLJIT_32)); - if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) { -#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 2) - if (dst == src2) - return push_inst(compiler, DINSU | T(src2) | SA(0) | (31 << 11) | (0 << 11), DR(dst)); -#endif /* SLJIT_MIPS_REV >= 2 */ - FAIL_IF(push_inst(compiler, DSLL32 | T(src2) | D(dst) | SH_IMM(0), DR(dst))); - return push_inst(compiler, DSRL32 | T(dst) | D(dst) | SH_IMM(0), DR(dst)); - } - SLJIT_ASSERT(dst == src2); - return SLJIT_SUCCESS; - - case SLJIT_MOV_S32: - SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM) && !(op & SLJIT_32)); - if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) { - return push_inst(compiler, SLL | T(src2) | D(dst) | SH_IMM(0), DR(dst)); - } - SLJIT_ASSERT(dst == src2); - return SLJIT_SUCCESS; - - case SLJIT_NOT: - SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM)); - if (op & SLJIT_SET_Z) - FAIL_IF(push_inst(compiler, NOR | S(src2) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG)); - if (!(flags & UNUSED_DEST)) - FAIL_IF(push_inst(compiler, NOR | S(src2) | T(src2) | D(dst), DR(dst))); - return SLJIT_SUCCESS; - - case SLJIT_CLZ: - SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM)); -#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1) - if (op & SLJIT_SET_Z) - FAIL_IF(push_inst(compiler, SELECT_OP(DCLZ, CLZ) | S(src2) | TA(EQUAL_FLAG) | DA(EQUAL_FLAG), EQUAL_FLAG)); - if (!(flags & UNUSED_DEST)) - FAIL_IF(push_inst(compiler, SELECT_OP(DCLZ, CLZ) | S(src2) | T(dst) | D(dst), DR(dst))); -#else /* SLJIT_MIPS_REV < 1 */ - if (SLJIT_UNLIKELY(flags & UNUSED_DEST)) { - FAIL_IF(push_inst(compiler, SELECT_OP(DSRL32, SRL) | T(src2) | DA(EQUAL_FLAG) | SH_IMM(31), EQUAL_FLAG)); - return push_inst(compiler, XORI | SA(EQUAL_FLAG) | TA(EQUAL_FLAG) | IMM(1), EQUAL_FLAG); - } - /* Nearly all instructions are unmovable in the following sequence. */ - FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(src2) | TA(0) | D(TMP_REG1), DR(TMP_REG1))); - /* Check zero. */ - FAIL_IF(push_inst(compiler, BEQ | S(TMP_REG1) | TA(0) | IMM(5), UNMOVABLE_INS)); - FAIL_IF(push_inst(compiler, ORI | SA(0) | T(dst) | IMM((op & SLJIT_32) ? 32 : 64), UNMOVABLE_INS)); - FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | SA(0) | T(dst) | IMM(-1), DR(dst))); - /* Loop for searching the highest bit. */ - FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(dst) | T(dst) | IMM(1), DR(dst))); - FAIL_IF(push_inst(compiler, BGEZ | S(TMP_REG1) | IMM(-2), UNMOVABLE_INS)); - FAIL_IF(push_inst(compiler, SELECT_OP(DSLL, SLL) | T(TMP_REG1) | D(TMP_REG1) | SH_IMM(1), UNMOVABLE_INS)); -#endif /* SLJIT_MIPS_REV >= 1 */ - return SLJIT_SUCCESS; - - case SLJIT_ADD: - is_overflow = GET_FLAG_TYPE(op) == SLJIT_OVERFLOW; - is_carry = GET_FLAG_TYPE(op) == GET_FLAG_TYPE(SLJIT_SET_CARRY); - - if (flags & SRC2_IMM) { - if (is_overflow) { - if (src2 >= 0) - FAIL_IF(push_inst(compiler, OR | S(src1) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG)); - else - FAIL_IF(push_inst(compiler, NOR | S(src1) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG)); - } - else if (op & SLJIT_SET_Z) - FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | TA(EQUAL_FLAG) | IMM(src2), EQUAL_FLAG)); - - if (is_overflow || is_carry) { - if (src2 >= 0) - FAIL_IF(push_inst(compiler, ORI | S(src1) | TA(OTHER_FLAG) | IMM(src2), OTHER_FLAG)); - else { - FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | SA(0) | TA(OTHER_FLAG) | IMM(src2), OTHER_FLAG)); - FAIL_IF(push_inst(compiler, OR | S(src1) | TA(OTHER_FLAG) | DA(OTHER_FLAG), OTHER_FLAG)); - } - } - /* dst may be the same as src1 or src2. */ - if (!(flags & UNUSED_DEST) || (op & VARIABLE_FLAG_MASK)) - FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | T(dst) | IMM(src2), DR(dst))); - } - else { - if (is_overflow) - FAIL_IF(push_inst(compiler, XOR | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG)); - else if (op & SLJIT_SET_Z) - FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG)); - - if (is_overflow || is_carry) - FAIL_IF(push_inst(compiler, OR | S(src1) | T(src2) | DA(OTHER_FLAG), OTHER_FLAG)); - /* dst may be the same as src1 or src2. */ - if (!(flags & UNUSED_DEST) || (op & VARIABLE_FLAG_MASK)) - FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(src1) | T(src2) | D(dst), DR(dst))); - } - - /* a + b >= a | b (otherwise, the carry should be set to 1). */ - if (is_overflow || is_carry) - FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(OTHER_FLAG) | DA(OTHER_FLAG), OTHER_FLAG)); - if (!is_overflow) - return SLJIT_SUCCESS; - FAIL_IF(push_inst(compiler, SELECT_OP(DSLL32, SLL) | TA(OTHER_FLAG) | D(TMP_REG1) | SH_IMM(31), DR(TMP_REG1))); - FAIL_IF(push_inst(compiler, XOR | S(TMP_REG1) | TA(EQUAL_FLAG) | DA(EQUAL_FLAG), EQUAL_FLAG)); - FAIL_IF(push_inst(compiler, XOR | S(dst) | TA(EQUAL_FLAG) | DA(OTHER_FLAG), OTHER_FLAG)); - if (op & SLJIT_SET_Z) - FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(dst) | TA(0) | DA(EQUAL_FLAG), EQUAL_FLAG)); - return push_inst(compiler, SELECT_OP(DSRL32, SRL) | TA(OTHER_FLAG) | DA(OTHER_FLAG) | SH_IMM(31), OTHER_FLAG); - - case SLJIT_ADDC: - is_carry = GET_FLAG_TYPE(op) == GET_FLAG_TYPE(SLJIT_SET_CARRY); - - if (flags & SRC2_IMM) { - if (is_carry) { - if (src2 >= 0) - FAIL_IF(push_inst(compiler, ORI | S(src1) | TA(EQUAL_FLAG) | IMM(src2), EQUAL_FLAG)); - else { - FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | SA(0) | TA(EQUAL_FLAG) | IMM(src2), EQUAL_FLAG)); - FAIL_IF(push_inst(compiler, OR | S(src1) | TA(EQUAL_FLAG) | DA(EQUAL_FLAG), EQUAL_FLAG)); - } - } - FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | T(dst) | IMM(src2), DR(dst))); - } else { - if (is_carry) - FAIL_IF(push_inst(compiler, OR | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG)); - /* dst may be the same as src1 or src2. */ - FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(src1) | T(src2) | D(dst), DR(dst))); - } - if (is_carry) - FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(EQUAL_FLAG) | DA(EQUAL_FLAG), EQUAL_FLAG)); - - FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(dst) | TA(OTHER_FLAG) | D(dst), DR(dst))); - if (!is_carry) - return SLJIT_SUCCESS; - - /* Set ULESS_FLAG (dst == 0) && (OTHER_FLAG == 1). */ - FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(OTHER_FLAG) | DA(OTHER_FLAG), OTHER_FLAG)); - /* Set carry flag. */ - return push_inst(compiler, OR | SA(OTHER_FLAG) | TA(EQUAL_FLAG) | DA(OTHER_FLAG), OTHER_FLAG); - - case SLJIT_SUB: - if ((flags & SRC2_IMM) && src2 == SIMM_MIN) { - FAIL_IF(push_inst(compiler, ADDIU | SA(0) | T(TMP_REG2) | IMM(src2), DR(TMP_REG2))); - src2 = TMP_REG2; - flags &= ~SRC2_IMM; - } - - is_handled = 0; - - if (flags & SRC2_IMM) { - if (GET_FLAG_TYPE(op) == SLJIT_LESS || GET_FLAG_TYPE(op) == SLJIT_GREATER_EQUAL) { - FAIL_IF(push_inst(compiler, SLTIU | S(src1) | TA(OTHER_FLAG) | IMM(src2), OTHER_FLAG)); - is_handled = 1; - } - else if (GET_FLAG_TYPE(op) == SLJIT_SIG_LESS || GET_FLAG_TYPE(op) == SLJIT_SIG_GREATER_EQUAL) { - FAIL_IF(push_inst(compiler, SLTI | S(src1) | TA(OTHER_FLAG) | IMM(src2), OTHER_FLAG)); - is_handled = 1; - } - } - - if (!is_handled && GET_FLAG_TYPE(op) >= SLJIT_LESS && GET_FLAG_TYPE(op) <= SLJIT_SIG_LESS_EQUAL) { - is_handled = 1; - - if (flags & SRC2_IMM) { - FAIL_IF(push_inst(compiler, ADDIU | SA(0) | T(TMP_REG2) | IMM(src2), DR(TMP_REG2))); - src2 = TMP_REG2; - flags &= ~SRC2_IMM; - } - - if (GET_FLAG_TYPE(op) == SLJIT_LESS || GET_FLAG_TYPE(op) == SLJIT_GREATER_EQUAL) { - FAIL_IF(push_inst(compiler, SLTU | S(src1) | T(src2) | DA(OTHER_FLAG), OTHER_FLAG)); - } - else if (GET_FLAG_TYPE(op) == SLJIT_GREATER || GET_FLAG_TYPE(op) == SLJIT_LESS_EQUAL) - { - FAIL_IF(push_inst(compiler, SLTU | S(src2) | T(src1) | DA(OTHER_FLAG), OTHER_FLAG)); - } - else if (GET_FLAG_TYPE(op) == SLJIT_SIG_LESS || GET_FLAG_TYPE(op) == SLJIT_SIG_GREATER_EQUAL) { - FAIL_IF(push_inst(compiler, SLT | S(src1) | T(src2) | DA(OTHER_FLAG), OTHER_FLAG)); - } - else if (GET_FLAG_TYPE(op) == SLJIT_SIG_GREATER || GET_FLAG_TYPE(op) == SLJIT_SIG_LESS_EQUAL) - { - FAIL_IF(push_inst(compiler, SLT | S(src2) | T(src1) | DA(OTHER_FLAG), OTHER_FLAG)); - } - } - - if (is_handled) { - if (flags & SRC2_IMM) { - if (op & SLJIT_SET_Z) - FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | TA(EQUAL_FLAG) | IMM(-src2), EQUAL_FLAG)); - if (!(flags & UNUSED_DEST)) - return push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | T(dst) | IMM(-src2), DR(dst)); - } - else { - if (op & SLJIT_SET_Z) - FAIL_IF(push_inst(compiler, SELECT_OP(DSUBU, SUBU) | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG)); - if (!(flags & UNUSED_DEST)) - return push_inst(compiler, SELECT_OP(DSUBU, SUBU) | S(src1) | T(src2) | D(dst), DR(dst)); - } - return SLJIT_SUCCESS; - } - - is_overflow = GET_FLAG_TYPE(op) == SLJIT_OVERFLOW; - is_carry = GET_FLAG_TYPE(op) == GET_FLAG_TYPE(SLJIT_SET_CARRY); - - if (flags & SRC2_IMM) { - if (is_overflow) { - if (src2 >= 0) - FAIL_IF(push_inst(compiler, OR | S(src1) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG)); - else - FAIL_IF(push_inst(compiler, NOR | S(src1) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG)); - } - else if (op & SLJIT_SET_Z) - FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | TA(EQUAL_FLAG) | IMM(-src2), EQUAL_FLAG)); - - if (is_overflow || is_carry) - FAIL_IF(push_inst(compiler, SLTIU | S(src1) | TA(OTHER_FLAG) | IMM(src2), OTHER_FLAG)); - /* dst may be the same as src1 or src2. */ - if (!(flags & UNUSED_DEST) || (op & VARIABLE_FLAG_MASK)) - FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | T(dst) | IMM(-src2), DR(dst))); - } - else { - if (is_overflow) - FAIL_IF(push_inst(compiler, XOR | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG)); - else if (op & SLJIT_SET_Z) - FAIL_IF(push_inst(compiler, SELECT_OP(DSUBU, SUBU) | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG)); - - if (is_overflow || is_carry) - FAIL_IF(push_inst(compiler, SLTU | S(src1) | T(src2) | DA(OTHER_FLAG), OTHER_FLAG)); - /* dst may be the same as src1 or src2. */ - if (!(flags & UNUSED_DEST) || (op & VARIABLE_FLAG_MASK)) - FAIL_IF(push_inst(compiler, SELECT_OP(DSUBU, SUBU) | S(src1) | T(src2) | D(dst), DR(dst))); - } - - if (!is_overflow) - return SLJIT_SUCCESS; - FAIL_IF(push_inst(compiler, SELECT_OP(DSLL32, SLL) | TA(OTHER_FLAG) | D(TMP_REG1) | SH_IMM(31), DR(TMP_REG1))); - FAIL_IF(push_inst(compiler, XOR | S(TMP_REG1) | TA(EQUAL_FLAG) | DA(EQUAL_FLAG), EQUAL_FLAG)); - FAIL_IF(push_inst(compiler, XOR | S(dst) | TA(EQUAL_FLAG) | DA(OTHER_FLAG), OTHER_FLAG)); - if (op & SLJIT_SET_Z) - FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(dst) | TA(0) | DA(EQUAL_FLAG), EQUAL_FLAG)); - return push_inst(compiler, SELECT_OP(DSRL32, SRL) | TA(OTHER_FLAG) | DA(OTHER_FLAG) | SH_IMM(31), OTHER_FLAG); - - case SLJIT_SUBC: - if ((flags & SRC2_IMM) && src2 == SIMM_MIN) { - FAIL_IF(push_inst(compiler, ADDIU | SA(0) | T(TMP_REG2) | IMM(src2), DR(TMP_REG2))); - src2 = TMP_REG2; - flags &= ~SRC2_IMM; - } - - is_carry = GET_FLAG_TYPE(op) == GET_FLAG_TYPE(SLJIT_SET_CARRY); - - if (flags & SRC2_IMM) { - if (is_carry) - FAIL_IF(push_inst(compiler, SLTIU | S(src1) | TA(EQUAL_FLAG) | IMM(src2), EQUAL_FLAG)); - /* dst may be the same as src1 or src2. */ - FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | T(dst) | IMM(-src2), DR(dst))); - } - else { - if (is_carry) - FAIL_IF(push_inst(compiler, SLTU | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG)); - /* dst may be the same as src1 or src2. */ - FAIL_IF(push_inst(compiler, SELECT_OP(DSUBU, SUBU) | S(src1) | T(src2) | D(dst), DR(dst))); - } - - if (is_carry) - FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(OTHER_FLAG) | D(TMP_REG1), DR(TMP_REG1))); - - FAIL_IF(push_inst(compiler, SELECT_OP(DSUBU, SUBU) | S(dst) | TA(OTHER_FLAG) | D(dst), DR(dst))); - return (is_carry) ? push_inst(compiler, OR | SA(EQUAL_FLAG) | T(TMP_REG1) | DA(OTHER_FLAG), OTHER_FLAG) : SLJIT_SUCCESS; - - case SLJIT_MUL: - SLJIT_ASSERT(!(flags & SRC2_IMM)); - - if (GET_FLAG_TYPE(op) != SLJIT_OVERFLOW) { -#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6) - return push_inst(compiler, SELECT_OP(DMUL, MUL) | S(src1) | T(src2) | D(dst), DR(dst)); -#elif (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1) - if (op & SLJIT_32) - return push_inst(compiler, MUL | S(src1) | T(src2) | D(dst), DR(dst)); - FAIL_IF(push_inst(compiler, DMULT | S(src1) | T(src2), MOVABLE_INS)); - return push_inst(compiler, MFLO | D(dst), DR(dst)); -#else /* SLJIT_MIPS_REV < 1 */ - FAIL_IF(push_inst(compiler, SELECT_OP(DMULT, MULT) | S(src1) | T(src2), MOVABLE_INS)); - return push_inst(compiler, MFLO | D(dst), DR(dst)); -#endif /* SLJIT_MIPS_REV >= 6 */ - } - -#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6) - FAIL_IF(push_inst(compiler, SELECT_OP(DMUL, MUL) | S(src1) | T(src2) | D(dst), DR(dst))); - FAIL_IF(push_inst(compiler, SELECT_OP(DMUH, MUH) | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG)); -#else /* SLJIT_MIPS_REV < 6 */ - FAIL_IF(push_inst(compiler, SELECT_OP(DMULT, MULT) | S(src1) | T(src2), MOVABLE_INS)); - FAIL_IF(push_inst(compiler, MFHI | DA(EQUAL_FLAG), EQUAL_FLAG)); - FAIL_IF(push_inst(compiler, MFLO | D(dst), DR(dst))); -#endif /* SLJIT_MIPS_REV >= 6 */ - FAIL_IF(push_inst(compiler, SELECT_OP(DSRA32, SRA) | T(dst) | DA(OTHER_FLAG) | SH_IMM(31), OTHER_FLAG)); - return push_inst(compiler, SELECT_OP(DSUBU, SUBU) | SA(EQUAL_FLAG) | TA(OTHER_FLAG) | DA(OTHER_FLAG), OTHER_FLAG); - - case SLJIT_AND: - EMIT_LOGICAL(ANDI, AND); - return SLJIT_SUCCESS; - - case SLJIT_OR: - EMIT_LOGICAL(ORI, OR); - return SLJIT_SUCCESS; - - case SLJIT_XOR: - EMIT_LOGICAL(XORI, XOR); - return SLJIT_SUCCESS; - - case SLJIT_SHL: - EMIT_SHIFT(DSLL, DSLL32, SLL, DSLLV, SLLV); - return SLJIT_SUCCESS; - - case SLJIT_LSHR: - EMIT_SHIFT(DSRL, DSRL32, SRL, DSRLV, SRLV); - return SLJIT_SUCCESS; - - case SLJIT_ASHR: - EMIT_SHIFT(DSRA, DSRA32, SRA, DSRAV, SRAV); - return SLJIT_SUCCESS; - } - - SLJIT_UNREACHABLE(); - return SLJIT_SUCCESS; -} - static SLJIT_INLINE sljit_s32 emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw init_value) { FAIL_IF(push_inst(compiler, LUI | T(dst) | IMM(init_value >> 48), DR(dst))); @@ -653,14 +238,20 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compile if (type & SLJIT_CALL_RETURN) PTR_FAIL_IF(emit_stack_frame_release(compiler, 0, &ins)); - PTR_FAIL_IF(call_with_args(compiler, arg_types, &ins)); + if ((type & 0xff) != SLJIT_CALL_REG_ARG) + PTR_FAIL_IF(call_with_args(compiler, arg_types, &ins)); SLJIT_ASSERT(DR(PIC_ADDR_REG) == 25 && PIC_ADDR_REG == TMP_REG2); - PTR_FAIL_IF(emit_const(compiler, PIC_ADDR_REG, 0)); + if (ins == NOP && compiler->delay_slot != UNMOVABLE_INS) + jump->flags |= IS_MOVABLE; if (!(type & SLJIT_CALL_RETURN)) { - jump->flags |= IS_JAL | IS_CALL; + jump->flags |= IS_JAL; + + if ((type & 0xff) != SLJIT_CALL_REG_ARG) + jump->flags |= IS_CALL; + PTR_FAIL_IF(push_inst(compiler, JALR | S(PIC_ADDR_REG) | DA(RETURN_ADDR_REG), UNMOVABLE_INS)); } else PTR_FAIL_IF(push_inst(compiler, JR | S(PIC_ADDR_REG), UNMOVABLE_INS)); @@ -668,6 +259,8 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compile jump->addr = compiler->size; PTR_FAIL_IF(push_inst(compiler, ins, UNMOVABLE_INS)); + /* Maximum number of instructions required for generating a constant. */ + compiler->size += 6; return jump; } @@ -680,16 +273,37 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compi CHECK_ERROR(); CHECK(check_sljit_emit_icall(compiler, type, arg_types, src, srcw)); + if (src & SLJIT_MEM) { + ADJUST_LOCAL_OFFSET(src, srcw); + FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, DR(PIC_ADDR_REG), src, srcw)); + src = PIC_ADDR_REG; + srcw = 0; + } + + if ((type & 0xff) == SLJIT_CALL_REG_ARG) { + if (type & SLJIT_CALL_RETURN) { + if (src >= SLJIT_FIRST_SAVED_REG && src <= (SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options))) { + FAIL_IF(push_inst(compiler, DADDU | S(src) | TA(0) | D(PIC_ADDR_REG), DR(PIC_ADDR_REG))); + src = PIC_ADDR_REG; + srcw = 0; + } + + FAIL_IF(emit_stack_frame_release(compiler, 0, &ins)); + + if (ins != NOP) + FAIL_IF(push_inst(compiler, ins, MOVABLE_INS)); + } + + SLJIT_SKIP_CHECKS(compiler); + return sljit_emit_ijump(compiler, type, src, srcw); + } + SLJIT_ASSERT(DR(PIC_ADDR_REG) == 25 && PIC_ADDR_REG == TMP_REG2); if (src & SLJIT_IMM) FAIL_IF(load_immediate(compiler, DR(PIC_ADDR_REG), srcw)); - else if (FAST_IS_REG(src)) + else if (src != PIC_ADDR_REG) FAIL_IF(push_inst(compiler, DADDU | S(src) | TA(0) | D(PIC_ADDR_REG), DR(PIC_ADDR_REG))); - else if (src & SLJIT_MEM) { - ADJUST_LOCAL_OFFSET(src, srcw); - FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, DR(PIC_ADDR_REG), src, srcw)); - } if (type & SLJIT_CALL_RETURN) FAIL_IF(emit_stack_frame_release(compiler, 0, &ins)); diff --git a/src/3rdparty/pcre2/src/sljit/sljitNativeMIPS_common.c b/src/3rdparty/pcre2/src/sljit/sljitNativeMIPS_common.c index be5cb22a232..9afe901c382 100644 --- a/src/3rdparty/pcre2/src/sljit/sljitNativeMIPS_common.c +++ b/src/3rdparty/pcre2/src/sljit/sljitNativeMIPS_common.c @@ -42,6 +42,14 @@ SLJIT_API_FUNC_ATTRIBUTE const char* sljit_get_platform_name(void) return "MIPS64-R6" SLJIT_CPUINFO; #endif /* SLJIT_CONFIG_MIPS_32 */ +#elif (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 2) + +#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) + return "MIPS32-R2" SLJIT_CPUINFO; +#else /* !SLJIT_CONFIG_MIPS_32 */ + return "MIPS64-R2" SLJIT_CPUINFO; +#endif /* SLJIT_CONFIG_MIPS_32 */ + #elif (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1) #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) @@ -151,12 +159,18 @@ static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 4] = { #define BREAK (HI(0) | LO(13)) #define CFC1 (HI(17) | (2 << 21)) #if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6) +#define C_EQ_S (HI(17) | CMP_FMT_S | LO(2)) +#define C_OLE_S (HI(17) | CMP_FMT_S | LO(6)) +#define C_OLT_S (HI(17) | CMP_FMT_S | LO(4)) #define C_UEQ_S (HI(17) | CMP_FMT_S | LO(3)) #define C_ULE_S (HI(17) | CMP_FMT_S | LO(7)) #define C_ULT_S (HI(17) | CMP_FMT_S | LO(5)) #define C_UN_S (HI(17) | CMP_FMT_S | LO(1)) #define C_FD (FD(TMP_FREG3)) #else /* SLJIT_MIPS_REV < 6 */ +#define C_EQ_S (HI(17) | FMT_S | LO(50)) +#define C_OLE_S (HI(17) | FMT_S | LO(54)) +#define C_OLT_S (HI(17) | FMT_S | LO(52)) #define C_UEQ_S (HI(17) | FMT_S | LO(51)) #define C_ULE_S (HI(17) | FMT_S | LO(55)) #define C_ULT_S (HI(17) | FMT_S | LO(53)) @@ -187,6 +201,9 @@ static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 4] = { #endif /* SLJIT_MIPS_REV >= 6 */ #define DIV_S (HI(17) | FMT_S | LO(3)) #define DINSU (HI(31) | LO(6)) +#define DROTR (HI(0) | (1 << 21) | LO(58)) +#define DROTR32 (HI(0) | (1 << 21) | LO(62)) +#define DROTRV (HI(0) | (1 << 6) | LO(22)) #define DSLL (HI(0) | LO(56)) #define DSLL32 (HI(0) | LO(60)) #define DSLLV (HI(0) | LO(20)) @@ -206,9 +223,13 @@ static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 4] = { #define JR (HI(0) | LO(8)) #endif /* SLJIT_MIPS_REV >= 6 */ #define LD (HI(55)) +#define LDL (HI(26)) +#define LDR (HI(27)) #define LDC1 (HI(53)) #define LUI (HI(15)) #define LW (HI(35)) +#define LWL (HI(34)) +#define LWR (HI(38)) #define LWC1 (HI(49)) #define MFC1 (HI(17)) #if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6) @@ -235,7 +256,11 @@ static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 4] = { #define NOR (HI(0) | LO(39)) #define OR (HI(0) | LO(37)) #define ORI (HI(13)) +#define ROTR (HI(0) | (1 << 21) | LO(2)) +#define ROTRV (HI(0) | (1 << 6) | LO(6)) #define SD (HI(63)) +#define SDL (HI(44)) +#define SDR (HI(45)) #define SDC1 (HI(61)) #define SLT (HI(0) | LO(42)) #define SLTI (HI(10)) @@ -250,6 +275,8 @@ static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 4] = { #define SUB_S (HI(17) | FMT_S | LO(1)) #define SUBU (HI(0) | LO(35)) #define SW (HI(43)) +#define SWL (HI(42)) +#define SWR (HI(46)) #define SWC1 (HI(57)) #define TRUNC_W_S (HI(17) | FMT_S | LO(13)) #define XOR (HI(0) | LO(38)) @@ -277,12 +304,18 @@ static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 4] = { #define ADDU_W ADDU #define ADDIU_W ADDIU #define SLL_W SLL +#define SRA_W SRA #define SUBU_W SUBU +#define STORE_W SW +#define LOAD_W LW #else #define ADDU_W DADDU #define ADDIU_W DADDIU #define SLL_W DSLL +#define SRA_W DSRA #define SUBU_W DSUBU +#define STORE_W SD +#define LOAD_W LD #endif #define SIMM_MAX (0x7fff) @@ -315,19 +348,21 @@ static SLJIT_INLINE sljit_ins invert_branch(sljit_uw flags) return (1 << 16); } -static SLJIT_INLINE sljit_ins* detect_jump_type(struct sljit_jump *jump, sljit_ins *code_ptr, sljit_ins *code, sljit_sw executable_offset) +static SLJIT_INLINE sljit_ins* detect_jump_type(struct sljit_jump *jump, sljit_ins *code, sljit_sw executable_offset) { sljit_sw diff; sljit_uw target_addr; sljit_ins *inst; sljit_ins saved_inst; + inst = (sljit_ins *)jump->addr; + #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) if (jump->flags & (SLJIT_REWRITABLE_JUMP | IS_CALL)) - return code_ptr; + goto exit; #else if (jump->flags & SLJIT_REWRITABLE_JUMP) - return code_ptr; + goto exit; #endif if (jump->flags & JUMP_ADDR) @@ -337,13 +372,12 @@ static SLJIT_INLINE sljit_ins* detect_jump_type(struct sljit_jump *jump, sljit_i target_addr = (sljit_uw)(code + jump->u.label->size) + (sljit_uw)executable_offset; } - inst = (sljit_ins *)jump->addr; if (jump->flags & IS_COND) inst--; #if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64) if (jump->flags & IS_CALL) - goto keep_address; + goto preserve_addr; #endif /* B instructions. */ @@ -364,15 +398,14 @@ static SLJIT_INLINE sljit_ins* detect_jump_type(struct sljit_jump *jump, sljit_i jump->addr -= 2 * sizeof(sljit_ins); return inst; } - } - else { + } else { diff = ((sljit_sw)target_addr - (sljit_sw)(inst + 1) - executable_offset) >> 2; if (diff <= SIMM_MAX && diff >= SIMM_MIN) { jump->flags |= PATCH_B; if (!(jump->flags & IS_COND)) { inst[0] = (jump->flags & IS_JAL) ? BAL : B; - inst[1] = NOP; + /* Keep inst[1] */ return inst + 1; } inst[0] ^= invert_branch(jump->flags); @@ -415,36 +448,46 @@ static SLJIT_INLINE sljit_ins* detect_jump_type(struct sljit_jump *jump, sljit_i if ((target_addr & ~(sljit_uw)0xfffffff) == ((jump->addr + sizeof(sljit_ins)) & ~(sljit_uw)0xfffffff)) { jump->flags |= PATCH_J; inst[0] = (jump->flags & IS_JAL) ? JAL : J; - inst[1] = NOP; + /* Keep inst[1] */ return inst + 1; } } + if (jump->flags & IS_COND) + inst++; + #if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64) -keep_address: +preserve_addr: if (target_addr <= 0x7fffffff) { jump->flags |= PATCH_ABS32; - if (jump->flags & IS_COND) { - inst[0] -= 4; - inst++; - } - inst[2] = inst[6]; - inst[3] = inst[7]; + if (jump->flags & IS_COND) + inst[-1] -= 4; + + inst[2] = inst[0]; + inst[3] = inst[1]; return inst + 3; } if (target_addr <= 0x7fffffffffffl) { jump->flags |= PATCH_ABS48; - if (jump->flags & IS_COND) { - inst[0] -= 2; - inst++; - } - inst[4] = inst[6]; - inst[5] = inst[7]; + if (jump->flags & IS_COND) + inst[-1] -= 2; + + inst[4] = inst[0]; + inst[5] = inst[1]; return inst + 5; } #endif - return code_ptr; +exit: +#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) + inst[2] = inst[0]; + inst[3] = inst[1]; + return inst + 3; +#else + inst[6] = inst[0]; + inst[7] = inst[1]; + return inst + 7; +#endif } #ifdef __GNUC__ @@ -459,30 +502,52 @@ static __attribute__ ((noinline)) void sljit_cache_flush(void* code, void* code_ static SLJIT_INLINE sljit_sw put_label_get_length(struct sljit_put_label *put_label, sljit_uw max_label) { if (max_label < 0x80000000l) { - put_label->flags = 0; + put_label->flags = PATCH_ABS32; return 1; } if (max_label < 0x800000000000l) { - put_label->flags = 1; + put_label->flags = PATCH_ABS48; return 3; } - put_label->flags = 2; + put_label->flags = 0; return 5; } -static SLJIT_INLINE void put_label_set(struct sljit_put_label *put_label) -{ - sljit_uw addr = put_label->label->addr; - sljit_ins *inst = (sljit_ins *)put_label->addr; - sljit_u32 reg = *inst; +#endif /* SLJIT_CONFIG_MIPS_64 */ - if (put_label->flags == 0) { +static SLJIT_INLINE void load_addr_to_reg(void *dst, sljit_u32 reg) +{ + struct sljit_jump *jump; + struct sljit_put_label *put_label; + sljit_uw flags; + sljit_ins *inst; + sljit_uw addr; + + if (reg != 0) { + jump = (struct sljit_jump*)dst; + flags = jump->flags; + inst = (sljit_ins*)jump->addr; + addr = (flags & JUMP_LABEL) ? jump->u.label->addr : jump->u.target; + } else { + put_label = (struct sljit_put_label*)dst; +#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64) + flags = put_label->flags; +#endif + inst = (sljit_ins*)put_label->addr; + addr = put_label->label->addr; + reg = *inst; + } + +#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) + inst[0] = LUI | T(reg) | IMM(addr >> 16); +#else /* !SLJIT_CONFIG_MIPS_32 */ + if (flags & PATCH_ABS32) { SLJIT_ASSERT(addr < 0x80000000l); inst[0] = LUI | T(reg) | IMM(addr >> 16); } - else if (put_label->flags == 1) { + else if (flags & PATCH_ABS48) { SLJIT_ASSERT(addr < 0x800000000000l); inst[0] = LUI | T(reg) | IMM(addr >> 32); inst[1] = ORI | S(reg) | T(reg) | IMM((addr >> 16) & 0xffff); @@ -497,12 +562,11 @@ static SLJIT_INLINE void put_label_set(struct sljit_put_label *put_label) inst[4] = DSLL | T(reg) | D(reg) | SH_IMM(16); inst += 4; } +#endif /* SLJIT_CONFIG_MIPS_32 */ inst[1] = ORI | S(reg) | T(reg) | IMM(addr & 0xffff); } -#endif - SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compiler) { struct sljit_memory_fragment *buf; @@ -557,11 +621,12 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil } if (jump && jump->addr == word_count) { #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) - jump->addr = (sljit_uw)(code_ptr - 3); + word_count += 2; #else - jump->addr = (sljit_uw)(code_ptr - 7); + word_count += 6; #endif - code_ptr = detect_jump_type(jump, code_ptr, code, executable_offset); + jump->addr = (sljit_uw)(code_ptr - 1); + code_ptr = detect_jump_type(jump, code, executable_offset); jump = jump->next; } if (const_ && const_->addr == word_count) { @@ -571,7 +636,10 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil if (put_label && put_label->addr == word_count) { SLJIT_ASSERT(put_label->label); put_label->addr = (sljit_uw)code_ptr; -#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64) +#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) + code_ptr += 1; + word_count += 1; +#else code_ptr += put_label_get_length(put_label, (sljit_uw)(SLJIT_ADD_EXEC_OFFSET(code, executable_offset) + put_label->label->size)); word_count += 5; #endif @@ -579,8 +647,8 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil } next_addr = compute_next_addr(label, jump, const_, put_label); } - code_ptr ++; - word_count ++; + code_ptr++; + word_count++; } while (buf_ptr < buf_end); buf = buf->next; @@ -617,51 +685,14 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil break; } - /* Set the fields of immediate loads. */ -#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) - SLJIT_ASSERT(((buf_ptr[0] | buf_ptr[1]) & 0xffff) == 0); - buf_ptr[0] |= (sljit_ins)(addr >> 16) & 0xffff; - buf_ptr[1] |= (sljit_ins)addr & 0xffff; -#else - if (jump->flags & PATCH_ABS32) { - SLJIT_ASSERT(addr <= 0x7fffffff); - SLJIT_ASSERT(((buf_ptr[0] | buf_ptr[1]) & 0xffff) == 0); - buf_ptr[0] |= (sljit_ins)(addr >> 16) & 0xffff; - buf_ptr[1] |= (sljit_ins)addr & 0xffff; - break; - } - - if (jump->flags & PATCH_ABS48) { - SLJIT_ASSERT(addr <= 0x7fffffffffffl); - SLJIT_ASSERT(((buf_ptr[0] | buf_ptr[1] | buf_ptr[3]) & 0xffff) == 0); - buf_ptr[0] |= (sljit_ins)(addr >> 32) & 0xffff; - buf_ptr[1] |= (sljit_ins)(addr >> 16) & 0xffff; - buf_ptr[3] |= (sljit_ins)addr & 0xffff; - break; - } - - SLJIT_ASSERT(((buf_ptr[0] | buf_ptr[1] | buf_ptr[3] | buf_ptr[5]) & 0xffff) == 0); - buf_ptr[0] |= (sljit_ins)(addr >> 48) & 0xffff; - buf_ptr[1] |= (sljit_ins)(addr >> 32) & 0xffff; - buf_ptr[3] |= (sljit_ins)(addr >> 16) & 0xffff; - buf_ptr[5] |= (sljit_ins)addr & 0xffff; -#endif + load_addr_to_reg(jump, PIC_ADDR_REG); } while (0); jump = jump->next; } put_label = compiler->put_labels; while (put_label) { -#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) - addr = put_label->label->addr; - buf_ptr = (sljit_ins *)put_label->addr; - - SLJIT_ASSERT((buf_ptr[0] & 0xffe00000) == LUI && (buf_ptr[1] & 0xfc000000) == ORI); - buf_ptr[0] |= (addr >> 16) & 0xffff; - buf_ptr[1] |= addr & 0xffff; -#else - put_label_set(put_label); -#endif + load_addr_to_reg(put_label, 0); put_label = put_label->next; } @@ -700,19 +731,29 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type) #endif case SLJIT_HAS_ZERO_REGISTER: return 1; - #if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1) case SLJIT_HAS_CLZ: case SLJIT_HAS_CMOV: case SLJIT_HAS_PREFETCH: return 1; -#endif /* SLJIT_MIPS_REV >= 1 */ + case SLJIT_HAS_CTZ: + return 2; +#endif /* SLJIT_MIPS_REV >= 1 */ +#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 2) + case SLJIT_HAS_ROT: + return 1; +#endif /* SLJIT_MIPS_REV >= 2 */ default: return 0; } } +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_cmp_info(sljit_s32 type) +{ + return (type >= SLJIT_ORDERED_EQUAL && type <= SLJIT_ORDERED_LESS_EQUAL); +} + /* --------------------------------------------------------------------- */ /* Entry, exit */ /* --------------------------------------------------------------------- */ @@ -747,14 +788,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type) #define SLOW_SRC2 0x20000 #define SLOW_DEST 0x40000 -#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) -#define STACK_STORE SW -#define STACK_LOAD LW -#else -#define STACK_STORE SD -#define STACK_LOAD LD -#endif - static sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg_ar, sljit_s32 arg, sljit_sw argw); static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler, sljit_s32 frame_size, sljit_ins *ins_ptr); @@ -770,13 +803,14 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi { sljit_ins base; sljit_s32 i, tmp, offset; - sljit_s32 arg_count, word_arg_count, saved_arg_count, float_arg_count; + sljit_s32 arg_count, word_arg_count, float_arg_count; + sljit_s32 saved_arg_count = SLJIT_KEPT_SAVEDS_COUNT(options); CHECK_ERROR(); CHECK(check_sljit_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size)); set_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size); - local_size += GET_SAVED_REGISTERS_SIZE(scratches, saveds, 1); + local_size += GET_SAVED_REGISTERS_SIZE(scratches, saveds - saved_arg_count, 1); #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) if (fsaveds > 0 || fscratches >= SLJIT_FIRST_SAVED_FLOAT_REG) { if ((local_size & SSIZE_OF(sw)) != 0) @@ -791,27 +825,27 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi #endif compiler->local_size = local_size; -#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) - tmp = arg_types >> SLJIT_ARG_SHIFT; - arg_count = 0; offset = 0; +#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) + if (!(options & SLJIT_ENTER_REG_ARG)) { + tmp = arg_types >> SLJIT_ARG_SHIFT; + arg_count = 0; - while (tmp) { - offset = arg_count; - if ((tmp & SLJIT_ARG_MASK) == SLJIT_ARG_TYPE_F64) { - if ((arg_count & 0x1) != 0) + while (tmp) { + offset = arg_count; + if ((tmp & SLJIT_ARG_MASK) == SLJIT_ARG_TYPE_F64) { + if ((arg_count & 0x1) != 0) + arg_count++; arg_count++; + } + arg_count++; + tmp >>= SLJIT_ARG_SHIFT; } - arg_count++; - tmp >>= SLJIT_ARG_SHIFT; + compiler->args_size = (sljit_uw)arg_count << 2; + offset = (offset >= 4) ? (offset << 2) : 0; } - - compiler->args_size = (sljit_uw)arg_count << 2; - offset = (offset >= 4) ? (offset << 2) : 0; -#else /* !SLJIT_CONFIG_MIPS_32 */ - offset = 0; #endif /* SLJIT_CONFIG_MIPS_32 */ if (local_size + offset <= -SIMM_MIN) { @@ -820,9 +854,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi base = S(SLJIT_SP); offset = local_size - SSIZE_OF(sw); } else { - FAIL_IF(load_immediate(compiler, DR(OTHER_FLAG), local_size)); + FAIL_IF(load_immediate(compiler, OTHER_FLAG, local_size)); FAIL_IF(push_inst(compiler, ADDU_W | S(SLJIT_SP) | TA(0) | D(TMP_REG2), DR(TMP_REG2))); - FAIL_IF(push_inst(compiler, SUBU_W | S(SLJIT_SP) | T(OTHER_FLAG) | D(SLJIT_SP), DR(SLJIT_SP))); + FAIL_IF(push_inst(compiler, SUBU_W | S(SLJIT_SP) | TA(OTHER_FLAG) | D(SLJIT_SP), DR(SLJIT_SP))); base = S(TMP_REG2); offset = -SSIZE_OF(sw); #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) @@ -830,17 +864,17 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi #endif } - FAIL_IF(push_inst(compiler, STACK_STORE | base | TA(RETURN_ADDR_REG) | IMM(offset), MOVABLE_INS)); + FAIL_IF(push_inst(compiler, STORE_W | base | TA(RETURN_ADDR_REG) | IMM(offset), UNMOVABLE_INS)); tmp = SLJIT_S0 - saveds; - for (i = SLJIT_S0; i > tmp; i--) { + for (i = SLJIT_S0 - saved_arg_count; i > tmp; i--) { offset -= SSIZE_OF(sw); - FAIL_IF(push_inst(compiler, STACK_STORE | base | T(i) | IMM(offset), MOVABLE_INS)); + FAIL_IF(push_inst(compiler, STORE_W | base | T(i) | IMM(offset), MOVABLE_INS)); } for (i = scratches; i >= SLJIT_FIRST_SAVED_REG; i--) { offset -= SSIZE_OF(sw); - FAIL_IF(push_inst(compiler, STACK_STORE | base | T(i) | IMM(offset), MOVABLE_INS)); + FAIL_IF(push_inst(compiler, STORE_W | base | T(i) | IMM(offset), MOVABLE_INS)); } #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) @@ -860,10 +894,12 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi FAIL_IF(push_inst(compiler, SDC1 | base | FT(i) | IMM(offset), MOVABLE_INS)); } + if (options & SLJIT_ENTER_REG_ARG) + return SLJIT_SUCCESS; + arg_types >>= SLJIT_ARG_SHIFT; arg_count = 0; word_arg_count = 0; - saved_arg_count = 0; float_arg_count = 0; #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) @@ -970,7 +1006,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *comp CHECK(check_sljit_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size)); set_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size); - local_size += GET_SAVED_REGISTERS_SIZE(scratches, saveds, 1); + local_size += GET_SAVED_REGISTERS_SIZE(scratches, saveds - SLJIT_KEPT_SAVEDS_COUNT(options), 1); #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) if (fsaveds > 0 || fscratches >= SLJIT_FIRST_SAVED_FLOAT_REG) { if ((local_size & SSIZE_OF(sw)) != 0) @@ -989,14 +1025,19 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *comp static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler, sljit_s32 frame_size, sljit_ins *ins_ptr) { sljit_s32 local_size, i, tmp, offset; + sljit_s32 load_return_addr = (frame_size == 0); sljit_s32 scratches = compiler->scratches; sljit_s32 saveds = compiler->saveds; sljit_s32 fsaveds = compiler->fsaveds; sljit_s32 fscratches = compiler->fscratches; + sljit_s32 kept_saveds_count = SLJIT_KEPT_SAVEDS_COUNT(compiler->options); + + SLJIT_ASSERT(frame_size == 1 || (frame_size & 0xf) == 0); + frame_size &= ~0xf; local_size = compiler->local_size; - tmp = GET_SAVED_REGISTERS_SIZE(scratches, saveds, 1); + tmp = GET_SAVED_REGISTERS_SIZE(scratches, saveds - kept_saveds_count, 1); #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) if (fsaveds > 0 || fscratches >= SLJIT_FIRST_SAVED_FLOAT_REG) { if ((tmp & SSIZE_OF(sw)) != 0) @@ -1024,18 +1065,18 @@ static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler, sljit SLJIT_ASSERT(local_size >= frame_size); offset = local_size - SSIZE_OF(sw); - if (frame_size == 0) - FAIL_IF(push_inst(compiler, STACK_LOAD | S(SLJIT_SP) | TA(RETURN_ADDR_REG) | IMM(offset), RETURN_ADDR_REG)); + if (load_return_addr) + FAIL_IF(push_inst(compiler, LOAD_W | S(SLJIT_SP) | TA(RETURN_ADDR_REG) | IMM(offset), RETURN_ADDR_REG)); tmp = SLJIT_S0 - saveds; - for (i = SLJIT_S0; i > tmp; i--) { + for (i = SLJIT_S0 - kept_saveds_count; i > tmp; i--) { offset -= SSIZE_OF(sw); - FAIL_IF(push_inst(compiler, STACK_LOAD | S(SLJIT_SP) | T(i) | IMM(offset), MOVABLE_INS)); + FAIL_IF(push_inst(compiler, LOAD_W | S(SLJIT_SP) | T(i) | IMM(offset), MOVABLE_INS)); } for (i = scratches; i >= SLJIT_FIRST_SAVED_REG; i--) { offset -= SSIZE_OF(sw); - FAIL_IF(push_inst(compiler, STACK_LOAD | S(SLJIT_SP) | T(i) | IMM(offset), MOVABLE_INS)); + FAIL_IF(push_inst(compiler, LOAD_W | S(SLJIT_SP) | T(i) | IMM(offset), MOVABLE_INS)); } #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) @@ -1076,8 +1117,38 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_void(struct sljit_compiler return push_inst(compiler, ins, UNMOVABLE_INS); } -#undef STACK_STORE -#undef STACK_LOAD +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_to(struct sljit_compiler *compiler, + sljit_s32 src, sljit_sw srcw) +{ + sljit_ins ins; + + CHECK_ERROR(); + CHECK(check_sljit_emit_return_to(compiler, src, srcw)); + + if (src & SLJIT_MEM) { + ADJUST_LOCAL_OFFSET(src, srcw); + FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, DR(PIC_ADDR_REG), src, srcw)); + src = PIC_ADDR_REG; + srcw = 0; + } else if (src >= SLJIT_FIRST_SAVED_REG && src <= (SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options))) { + FAIL_IF(push_inst(compiler, ADDU_W | S(src) | TA(0) | D(PIC_ADDR_REG), DR(PIC_ADDR_REG))); + src = PIC_ADDR_REG; + srcw = 0; + } + + FAIL_IF(emit_stack_frame_release(compiler, 1, &ins)); + + if (!(src & SLJIT_IMM)) { + FAIL_IF(push_inst(compiler, JR | S(src), UNMOVABLE_INS)); + return push_inst(compiler, ins, UNMOVABLE_INS); + } + + if (ins != NOP) + FAIL_IF(push_inst(compiler, ins, MOVABLE_INS)); + + SLJIT_SKIP_CHECKS(compiler); + return sljit_emit_ijump(compiler, SLJIT_JUMP, src, srcw); +} /* --------------------------------------------------------------------- */ /* Operators */ @@ -1134,9 +1205,10 @@ static sljit_s32 getput_arg_fast(struct sljit_compiler *compiler, sljit_s32 flag return 0; } +#define TO_ARGW_HI(argw) (((argw) & ~0xffff) + (((argw) & 0x8000) ? 0x10000 : 0)) + /* See getput_arg below. - Note: can_cache is called only for binary operators. Those - operators always uses word arguments without write back. */ + Note: can_cache is called only for binary operators. */ static sljit_s32 can_cache(sljit_s32 arg, sljit_sw argw, sljit_s32 next_arg, sljit_sw next_argw) { SLJIT_ASSERT((arg & SLJIT_MEM) && (next_arg & SLJIT_MEM)); @@ -1151,7 +1223,8 @@ static sljit_s32 can_cache(sljit_s32 arg, sljit_sw argw, sljit_s32 next_arg, slj } if (arg == next_arg) { - if (((next_argw - argw) <= SIMM_MAX && (next_argw - argw) >= SIMM_MIN)) + if (((next_argw - argw) <= SIMM_MAX && (next_argw - argw) >= SIMM_MIN) + || TO_ARGW_HI(argw) == TO_ARGW_HI(next_argw)) return 1; return 0; } @@ -1163,6 +1236,7 @@ static sljit_s32 can_cache(sljit_s32 arg, sljit_sw argw, sljit_s32 next_arg, slj static sljit_s32 getput_arg(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg_ar, sljit_s32 arg, sljit_sw argw, sljit_s32 next_arg, sljit_sw next_argw) { sljit_s32 tmp_ar, base, delay_slot; + sljit_sw offset, argw_hi; SLJIT_ASSERT(arg & SLJIT_MEM); if (!(next_arg & SLJIT_MEM)) { @@ -1170,6 +1244,8 @@ static sljit_s32 getput_arg(struct sljit_compiler *compiler, sljit_s32 flags, sl next_argw = 0; } + /* Since tmp can be the same as base or offset registers, + * these might be unavailable after modifying tmp. */ if ((flags & MEM_MASK) <= GPR_REG && (flags & LOAD_DATA)) { tmp_ar = reg_ar; delay_slot = reg_ar; @@ -1217,35 +1293,39 @@ static sljit_s32 getput_arg(struct sljit_compiler *compiler, sljit_s32 flags, sl return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | SA(tmp_ar) | TA(reg_ar), delay_slot); } - if (compiler->cache_arg == arg && argw - compiler->cache_argw <= SIMM_MAX && argw - compiler->cache_argw >= SIMM_MIN) { - if (argw != compiler->cache_argw) { - FAIL_IF(push_inst(compiler, ADDIU_W | S(TMP_REG3) | T(TMP_REG3) | IMM(argw - compiler->cache_argw), DR(TMP_REG3))); - compiler->cache_argw = argw; - } - return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | S(TMP_REG3) | TA(reg_ar), delay_slot); - } + if (compiler->cache_arg == arg && argw - compiler->cache_argw <= SIMM_MAX && argw - compiler->cache_argw >= SIMM_MIN) + return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | S(TMP_REG3) | TA(reg_ar) | IMM(argw - compiler->cache_argw), delay_slot); - if (compiler->cache_arg == SLJIT_MEM && argw - compiler->cache_argw <= SIMM_MAX && argw - compiler->cache_argw >= SIMM_MIN) { - if (argw != compiler->cache_argw) - FAIL_IF(push_inst(compiler, ADDIU_W | S(TMP_REG3) | T(TMP_REG3) | IMM(argw - compiler->cache_argw), DR(TMP_REG3))); - } - else { + if (compiler->cache_arg == SLJIT_MEM && (argw - compiler->cache_argw) <= SIMM_MAX && (argw - compiler->cache_argw) >= SIMM_MIN) { + offset = argw - compiler->cache_argw; + } else { compiler->cache_arg = SLJIT_MEM; - FAIL_IF(load_immediate(compiler, DR(TMP_REG3), argw)); + + argw_hi = TO_ARGW_HI(argw); + + if (next_arg && next_argw - argw <= SIMM_MAX && next_argw - argw >= SIMM_MIN && argw_hi != TO_ARGW_HI(next_argw)) { + FAIL_IF(load_immediate(compiler, DR(TMP_REG3), argw)); + compiler->cache_argw = argw; + offset = 0; + } else { + FAIL_IF(load_immediate(compiler, DR(TMP_REG3), argw_hi)); + compiler->cache_argw = argw_hi; + offset = argw & 0xffff; + argw = argw_hi; + } } - compiler->cache_argw = argw; if (!base) - return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | S(TMP_REG3) | TA(reg_ar), delay_slot); + return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | S(TMP_REG3) | TA(reg_ar) | IMM(offset), delay_slot); if (arg == next_arg && next_argw - argw <= SIMM_MAX && next_argw - argw >= SIMM_MIN) { compiler->cache_arg = arg; FAIL_IF(push_inst(compiler, ADDU_W | S(TMP_REG3) | T(base) | D(TMP_REG3), DR(TMP_REG3))); - return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | S(TMP_REG3) | TA(reg_ar), delay_slot); + return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | S(TMP_REG3) | TA(reg_ar) | IMM(offset), delay_slot); } FAIL_IF(push_inst(compiler, ADDU_W | S(TMP_REG3) | T(base) | DA(tmp_ar), tmp_ar)); - return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | SA(tmp_ar) | TA(reg_ar), delay_slot); + return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | SA(tmp_ar) | TA(reg_ar) | IMM(offset), delay_slot); } static sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg_ar, sljit_s32 arg, sljit_sw argw) @@ -1270,19 +1350,19 @@ static sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit_s32 flags, s if (SLJIT_UNLIKELY(argw)) { FAIL_IF(push_inst(compiler, SLL_W | T(OFFS_REG(arg)) | DA(tmp_ar) | SH_IMM(argw), tmp_ar)); - FAIL_IF(push_inst(compiler, ADDU_W | S(base) | TA(tmp_ar) | DA(tmp_ar), tmp_ar)); + FAIL_IF(push_inst(compiler, ADDU_W | SA(tmp_ar) | T(base) | DA(tmp_ar), tmp_ar)); } else FAIL_IF(push_inst(compiler, ADDU_W | S(base) | T(OFFS_REG(arg)) | DA(tmp_ar), tmp_ar)); return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | SA(tmp_ar) | TA(reg_ar), delay_slot); } - FAIL_IF(load_immediate(compiler, tmp_ar, argw)); + FAIL_IF(load_immediate(compiler, tmp_ar, TO_ARGW_HI(argw))); if (base != 0) - FAIL_IF(push_inst(compiler, ADDU_W | S(base) | TA(tmp_ar) | DA(tmp_ar), tmp_ar)); + FAIL_IF(push_inst(compiler, ADDU_W | SA(tmp_ar) | T(base) | DA(tmp_ar), tmp_ar)); - return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | SA(tmp_ar) | TA(reg_ar), delay_slot); + return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | SA(tmp_ar) | TA(reg_ar) | IMM(argw), delay_slot); } static SLJIT_INLINE sljit_s32 emit_op_mem2(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg, sljit_s32 arg1, sljit_sw arg1w, sljit_s32 arg2, sljit_sw arg2w) @@ -1292,6 +1372,649 @@ static SLJIT_INLINE sljit_s32 emit_op_mem2(struct sljit_compiler *compiler, slji return getput_arg(compiler, flags, reg, arg1, arg1w, arg2, arg2w); } +#define EMIT_LOGICAL(op_imm, op_reg) \ + if (flags & SRC2_IMM) { \ + if (op & SLJIT_SET_Z) \ + FAIL_IF(push_inst(compiler, op_imm | S(src1) | TA(EQUAL_FLAG) | IMM(src2), EQUAL_FLAG)); \ + if (!(flags & UNUSED_DEST)) \ + FAIL_IF(push_inst(compiler, op_imm | S(src1) | T(dst) | IMM(src2), DR(dst))); \ + } \ + else { \ + if (op & SLJIT_SET_Z) \ + FAIL_IF(push_inst(compiler, op_reg | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG)); \ + if (!(flags & UNUSED_DEST)) \ + FAIL_IF(push_inst(compiler, op_reg | S(src1) | T(src2) | D(dst), DR(dst))); \ + } + +#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) + +#define SELECT_OP(a, b) (b) + +#define EMIT_SHIFT(dimm, dimm32, imm, dv, v) \ + op_imm = (imm); \ + op_v = (v); + +#else /* !SLJIT_CONFIG_MIPS_32 */ + +#define SELECT_OP(a, b) \ + (!(op & SLJIT_32) ? a : b) + +#define EMIT_SHIFT(dimm, dimm32, imm, dv, v) \ + op_dimm = (dimm); \ + op_dimm32 = (dimm32); \ + op_imm = (imm); \ + op_dv = (dv); \ + op_v = (v); + +#endif /* SLJIT_CONFIG_MIPS_32 */ + +#if (!defined SLJIT_MIPS_REV || SLJIT_MIPS_REV < 1) + +static sljit_s32 emit_clz_ctz(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw src) +{ + sljit_s32 is_clz = (GET_OPCODE(op) == SLJIT_CLZ); +#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64) + sljit_ins max = (op & SLJIT_32) ? 32 : 64; +#else /* !SLJIT_CONFIG_RISCV_64 */ + sljit_ins max = 32; +#endif /* SLJIT_CONFIG_RISCV_64 */ + + /* The TMP_REG2 is the next value. */ + if (src != TMP_REG2) + FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(src) | TA(0) | D(TMP_REG2), DR(TMP_REG2))); + + FAIL_IF(push_inst(compiler, BEQ | S(TMP_REG2) | TA(0) | IMM(is_clz ? 13 : 14), UNMOVABLE_INS)); + /* The OTHER_FLAG is the counter. Delay slot. */ + FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | SA(0) | TA(OTHER_FLAG) | IMM(max), OTHER_FLAG)); + + if (!is_clz) { + FAIL_IF(push_inst(compiler, ANDI | S(TMP_REG2) | T(TMP_REG1) | IMM(1), DR(TMP_REG1))); + FAIL_IF(push_inst(compiler, BNE | S(TMP_REG1) | TA(0) | IMM(11), UNMOVABLE_INS)); + } else + FAIL_IF(push_inst(compiler, BLTZ | S(TMP_REG2) | TA(0) | IMM(11), UNMOVABLE_INS)); + + /* Delay slot. */ + FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | SA(0) | TA(OTHER_FLAG) | IMM(0), OTHER_FLAG)); + + /* The TMP_REG1 is the next shift. */ + FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | SA(0) | T(TMP_REG1) | IMM(max), DR(TMP_REG1))); + + FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(TMP_REG2) | TA(0) | DA(EQUAL_FLAG), EQUAL_FLAG)); + FAIL_IF(push_inst(compiler, SELECT_OP(DSRL, SRL) | T(TMP_REG1) | D(TMP_REG1) | SH_IMM(1), DR(TMP_REG1))); + + FAIL_IF(push_inst(compiler, (is_clz ? SELECT_OP(DSRLV, SRLV) : SELECT_OP(DSLLV, SLLV)) | S(TMP_REG1) | TA(EQUAL_FLAG) | D(TMP_REG2), DR(TMP_REG2))); + FAIL_IF(push_inst(compiler, BNE | S(TMP_REG2) | TA(0) | IMM(-4), UNMOVABLE_INS)); + /* Delay slot. */ + FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS)); + + FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(TMP_REG1) | T(TMP_REG2) | IMM(-1), DR(TMP_REG2))); + FAIL_IF(push_inst(compiler, (is_clz ? SELECT_OP(DSRLV, SRLV) : SELECT_OP(DSLLV, SLLV)) | S(TMP_REG2) | TA(EQUAL_FLAG) | D(TMP_REG2), DR(TMP_REG2))); + + FAIL_IF(push_inst(compiler, BEQ | S(TMP_REG2) | TA(0) | IMM(-7), UNMOVABLE_INS)); + /* Delay slot. */ + FAIL_IF(push_inst(compiler, OR | SA(OTHER_FLAG) | T(TMP_REG1) | DA(OTHER_FLAG), OTHER_FLAG)); + + return push_inst(compiler, SELECT_OP(DADDU, ADDU) | SA(OTHER_FLAG) | TA(0) | D(dst), DR(dst)); +} + +#endif /* SLJIT_MIPS_REV < 1 */ + +static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 flags, + sljit_s32 dst, sljit_s32 src1, sljit_sw src2) +{ + sljit_s32 is_overflow, is_carry, carry_src_ar, is_handled; + sljit_ins op_imm, op_v; +#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64) + sljit_ins ins, op_dimm, op_dimm32, op_dv; +#endif + + switch (GET_OPCODE(op)) { + case SLJIT_MOV: + SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM)); + if (dst != src2) + return push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(src2) | TA(0) | D(dst), DR(dst)); + return SLJIT_SUCCESS; + + case SLJIT_MOV_U8: + SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM)); + if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) + return push_inst(compiler, ANDI | S(src2) | T(dst) | IMM(0xff), DR(dst)); + SLJIT_ASSERT(dst == src2); + return SLJIT_SUCCESS; + + case SLJIT_MOV_S8: + SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM)); + if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) { +#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) +#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1) + return push_inst(compiler, SEB | T(src2) | D(dst), DR(dst)); +#else /* SLJIT_MIPS_REV < 1 */ + FAIL_IF(push_inst(compiler, SLL | T(src2) | D(dst) | SH_IMM(24), DR(dst))); + return push_inst(compiler, SRA | T(dst) | D(dst) | SH_IMM(24), DR(dst)); +#endif /* SLJIT_MIPS_REV >= 1 */ +#else /* !SLJIT_CONFIG_MIPS_32 */ +#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1) + if (op & SLJIT_32) + return push_inst(compiler, SEB | T(src2) | D(dst), DR(dst)); +#endif /* SLJIT_MIPS_REV >= 1 */ + FAIL_IF(push_inst(compiler, DSLL32 | T(src2) | D(dst) | SH_IMM(24), DR(dst))); + return push_inst(compiler, DSRA32 | T(dst) | D(dst) | SH_IMM(24), DR(dst)); +#endif /* SLJIT_CONFIG_MIPS_32 */ + } + SLJIT_ASSERT(dst == src2); + return SLJIT_SUCCESS; + + case SLJIT_MOV_U16: + SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM)); + if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) + return push_inst(compiler, ANDI | S(src2) | T(dst) | IMM(0xffff), DR(dst)); + SLJIT_ASSERT(dst == src2); + return SLJIT_SUCCESS; + + case SLJIT_MOV_S16: + SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM)); + if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) { +#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) +#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1) + return push_inst(compiler, SEH | T(src2) | D(dst), DR(dst)); +#else /* SLJIT_MIPS_REV < 1 */ + FAIL_IF(push_inst(compiler, SLL | T(src2) | D(dst) | SH_IMM(16), DR(dst))); + return push_inst(compiler, SRA | T(dst) | D(dst) | SH_IMM(16), DR(dst)); +#endif /* SLJIT_MIPS_REV >= 1 */ +#else /* !SLJIT_CONFIG_MIPS_32 */ +#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1) + if (op & SLJIT_32) + return push_inst(compiler, SEH | T(src2) | D(dst), DR(dst)); +#endif /* SLJIT_MIPS_REV >= 1 */ + FAIL_IF(push_inst(compiler, DSLL32 | T(src2) | D(dst) | SH_IMM(16), DR(dst))); + return push_inst(compiler, DSRA32 | T(dst) | D(dst) | SH_IMM(16), DR(dst)); +#endif /* SLJIT_CONFIG_MIPS_32 */ + } + SLJIT_ASSERT(dst == src2); + return SLJIT_SUCCESS; + +#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64) + case SLJIT_MOV_U32: + SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM) && !(op & SLJIT_32)); + if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) { +#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 2) + if (dst == src2) + return push_inst(compiler, DINSU | T(src2) | SA(0) | (31 << 11) | (0 << 11), DR(dst)); +#endif /* SLJIT_MIPS_REV >= 2 */ + FAIL_IF(push_inst(compiler, DSLL32 | T(src2) | D(dst) | SH_IMM(0), DR(dst))); + return push_inst(compiler, DSRL32 | T(dst) | D(dst) | SH_IMM(0), DR(dst)); + } + SLJIT_ASSERT(dst == src2); + return SLJIT_SUCCESS; + + case SLJIT_MOV_S32: + SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM) && !(op & SLJIT_32)); + if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) { + return push_inst(compiler, SLL | T(src2) | D(dst) | SH_IMM(0), DR(dst)); + } + SLJIT_ASSERT(dst == src2); + return SLJIT_SUCCESS; +#endif /* SLJIT_CONFIG_MIPS_64 */ + + case SLJIT_NOT: + SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM)); + if (op & SLJIT_SET_Z) + FAIL_IF(push_inst(compiler, NOR | S(src2) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG)); + if (!(flags & UNUSED_DEST)) + FAIL_IF(push_inst(compiler, NOR | S(src2) | T(src2) | D(dst), DR(dst))); + return SLJIT_SUCCESS; + +#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1) + case SLJIT_CLZ: + SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM)); +#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6) + return push_inst(compiler, SELECT_OP(DCLZ, CLZ) | S(src2) | D(dst), DR(dst)); +#else /* SLJIT_MIPS_REV < 6 */ + return push_inst(compiler, SELECT_OP(DCLZ, CLZ) | S(src2) | T(dst) | D(dst), DR(dst)); +#endif /* SLJIT_MIPS_REV >= 6 */ + case SLJIT_CTZ: + SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM)); + FAIL_IF(push_inst(compiler, SELECT_OP(DSUBU, SUBU) | SA(0) | T(src2) | D(TMP_REG1), DR(TMP_REG1))); + FAIL_IF(push_inst(compiler, AND | S(src2) | T(TMP_REG1) | D(dst), DR(dst))); +#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6) + FAIL_IF(push_inst(compiler, SELECT_OP(DCLZ, CLZ) | S(dst) | D(dst), DR(dst))); +#else /* SLJIT_MIPS_REV < 6 */ + FAIL_IF(push_inst(compiler, SELECT_OP(DCLZ, CLZ) | S(dst) | T(dst) | D(dst), DR(dst))); +#endif /* SLJIT_MIPS_REV >= 6 */ + FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(dst) | T(TMP_REG1) | IMM(SELECT_OP(-64, -32)), DR(TMP_REG1))); + FAIL_IF(push_inst(compiler, SELECT_OP(DSRL32, SRL) | T(TMP_REG1) | D(TMP_REG1) | SH_IMM(SELECT_OP(26, 27)), DR(TMP_REG1))); + return push_inst(compiler, XOR | S(dst) | T(TMP_REG1) | D(dst), DR(dst)); +#else /* SLJIT_MIPS_REV < 1 */ + case SLJIT_CLZ: + case SLJIT_CTZ: + SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM)); + return emit_clz_ctz(compiler, op, dst, src2); +#endif /* SLJIT_MIPS_REV >= 1 */ + + case SLJIT_ADD: + /* Overflow computation (both add and sub): overflow = src1_sign ^ src2_sign ^ result_sign ^ carry_flag */ + is_overflow = GET_FLAG_TYPE(op) == SLJIT_OVERFLOW; + carry_src_ar = GET_FLAG_TYPE(op) == GET_FLAG_TYPE(SLJIT_SET_CARRY); + + if (flags & SRC2_IMM) { + if (is_overflow) { + if (src2 >= 0) + FAIL_IF(push_inst(compiler, OR | S(src1) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG)); + else + FAIL_IF(push_inst(compiler, NOR | S(src1) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG)); + } + else if (op & SLJIT_SET_Z) + FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | TA(EQUAL_FLAG) | IMM(src2), EQUAL_FLAG)); + + /* Only the zero flag is needed. */ + if (!(flags & UNUSED_DEST) || (op & VARIABLE_FLAG_MASK)) + FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | T(dst) | IMM(src2), DR(dst))); + } + else { + if (is_overflow) + FAIL_IF(push_inst(compiler, XOR | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG)); + else if (op & SLJIT_SET_Z) + FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG)); + + if (is_overflow || carry_src_ar != 0) { + if (src1 != dst) + carry_src_ar = DR(src1); + else if (src2 != dst) + carry_src_ar = DR(src2); + else { + FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(src1) | TA(0) | DA(OTHER_FLAG), OTHER_FLAG)); + carry_src_ar = OTHER_FLAG; + } + } + + /* Only the zero flag is needed. */ + if (!(flags & UNUSED_DEST) || (op & VARIABLE_FLAG_MASK)) + FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(src1) | T(src2) | D(dst), DR(dst))); + } + + /* Carry is zero if a + b >= a or a + b >= b, otherwise it is 1. */ + if (is_overflow || carry_src_ar != 0) { + if (flags & SRC2_IMM) + FAIL_IF(push_inst(compiler, SLTIU | S(dst) | TA(OTHER_FLAG) | IMM(src2), OTHER_FLAG)); + else + FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(carry_src_ar) | DA(OTHER_FLAG), OTHER_FLAG)); + } + + if (!is_overflow) + return SLJIT_SUCCESS; + + FAIL_IF(push_inst(compiler, XOR | S(dst) | TA(EQUAL_FLAG) | D(TMP_REG1), DR(TMP_REG1))); + if (op & SLJIT_SET_Z) + FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(dst) | TA(0) | DA(EQUAL_FLAG), EQUAL_FLAG)); + FAIL_IF(push_inst(compiler, SELECT_OP(DSRL32, SRL) | T(TMP_REG1) | D(TMP_REG1) | SH_IMM(31), DR(TMP_REG1))); + return push_inst(compiler, XOR | S(TMP_REG1) | TA(OTHER_FLAG) | DA(OTHER_FLAG), OTHER_FLAG); + + case SLJIT_ADDC: + carry_src_ar = GET_FLAG_TYPE(op) == GET_FLAG_TYPE(SLJIT_SET_CARRY); + + if (flags & SRC2_IMM) { + FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | T(dst) | IMM(src2), DR(dst))); + } else { + if (carry_src_ar != 0) { + if (src1 != dst) + carry_src_ar = DR(src1); + else if (src2 != dst) + carry_src_ar = DR(src2); + else { + FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(src1) | TA(0) | DA(EQUAL_FLAG), EQUAL_FLAG)); + carry_src_ar = EQUAL_FLAG; + } + } + + FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(src1) | T(src2) | D(dst), DR(dst))); + } + + /* Carry is zero if a + b >= a or a + b >= b, otherwise it is 1. */ + if (carry_src_ar != 0) { + if (flags & SRC2_IMM) + FAIL_IF(push_inst(compiler, SLTIU | S(dst) | TA(EQUAL_FLAG) | IMM(src2), EQUAL_FLAG)); + else + FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(carry_src_ar) | DA(EQUAL_FLAG), EQUAL_FLAG)); + } + + FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(dst) | TA(OTHER_FLAG) | D(dst), DR(dst))); + + if (carry_src_ar == 0) + return SLJIT_SUCCESS; + + /* Set ULESS_FLAG (dst == 0) && (OTHER_FLAG == 1). */ + FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(OTHER_FLAG) | DA(OTHER_FLAG), OTHER_FLAG)); + /* Set carry flag. */ + return push_inst(compiler, OR | SA(OTHER_FLAG) | TA(EQUAL_FLAG) | DA(OTHER_FLAG), OTHER_FLAG); + + case SLJIT_SUB: + if ((flags & SRC2_IMM) && src2 == SIMM_MIN) { + FAIL_IF(push_inst(compiler, ADDIU | SA(0) | T(TMP_REG2) | IMM(src2), DR(TMP_REG2))); + src2 = TMP_REG2; + flags &= ~SRC2_IMM; + } + + is_handled = 0; + + if (flags & SRC2_IMM) { + if (GET_FLAG_TYPE(op) == SLJIT_LESS || GET_FLAG_TYPE(op) == SLJIT_GREATER_EQUAL) { + FAIL_IF(push_inst(compiler, SLTIU | S(src1) | TA(OTHER_FLAG) | IMM(src2), OTHER_FLAG)); + is_handled = 1; + } + else if (GET_FLAG_TYPE(op) == SLJIT_SIG_LESS || GET_FLAG_TYPE(op) == SLJIT_SIG_GREATER_EQUAL) { + FAIL_IF(push_inst(compiler, SLTI | S(src1) | TA(OTHER_FLAG) | IMM(src2), OTHER_FLAG)); + is_handled = 1; + } + } + + if (!is_handled && GET_FLAG_TYPE(op) >= SLJIT_LESS && GET_FLAG_TYPE(op) <= SLJIT_SIG_LESS_EQUAL) { + is_handled = 1; + + if (flags & SRC2_IMM) { + FAIL_IF(push_inst(compiler, ADDIU | SA(0) | T(TMP_REG2) | IMM(src2), DR(TMP_REG2))); + src2 = TMP_REG2; + flags &= ~SRC2_IMM; + } + + switch (GET_FLAG_TYPE(op)) { + case SLJIT_LESS: + case SLJIT_GREATER_EQUAL: + FAIL_IF(push_inst(compiler, SLTU | S(src1) | T(src2) | DA(OTHER_FLAG), OTHER_FLAG)); + break; + case SLJIT_GREATER: + case SLJIT_LESS_EQUAL: + FAIL_IF(push_inst(compiler, SLTU | S(src2) | T(src1) | DA(OTHER_FLAG), OTHER_FLAG)); + break; + case SLJIT_SIG_LESS: + case SLJIT_SIG_GREATER_EQUAL: + FAIL_IF(push_inst(compiler, SLT | S(src1) | T(src2) | DA(OTHER_FLAG), OTHER_FLAG)); + break; + case SLJIT_SIG_GREATER: + case SLJIT_SIG_LESS_EQUAL: + FAIL_IF(push_inst(compiler, SLT | S(src2) | T(src1) | DA(OTHER_FLAG), OTHER_FLAG)); + break; + } + } + + if (is_handled) { + if (flags & SRC2_IMM) { + if (op & SLJIT_SET_Z) + FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | TA(EQUAL_FLAG) | IMM(-src2), EQUAL_FLAG)); + if (!(flags & UNUSED_DEST)) + return push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | T(dst) | IMM(-src2), DR(dst)); + } + else { + if (op & SLJIT_SET_Z) + FAIL_IF(push_inst(compiler, SELECT_OP(DSUBU, SUBU) | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG)); + if (!(flags & UNUSED_DEST)) + return push_inst(compiler, SELECT_OP(DSUBU, SUBU) | S(src1) | T(src2) | D(dst), DR(dst)); + } + return SLJIT_SUCCESS; + } + + is_overflow = GET_FLAG_TYPE(op) == SLJIT_OVERFLOW; + is_carry = GET_FLAG_TYPE(op) == GET_FLAG_TYPE(SLJIT_SET_CARRY); + + if (flags & SRC2_IMM) { + if (is_overflow) { + if (src2 >= 0) + FAIL_IF(push_inst(compiler, OR | S(src1) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG)); + else + FAIL_IF(push_inst(compiler, NOR | S(src1) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG)); + } + else if (op & SLJIT_SET_Z) + FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | TA(EQUAL_FLAG) | IMM(-src2), EQUAL_FLAG)); + + if (is_overflow || is_carry) + FAIL_IF(push_inst(compiler, SLTIU | S(src1) | TA(OTHER_FLAG) | IMM(src2), OTHER_FLAG)); + + /* Only the zero flag is needed. */ + if (!(flags & UNUSED_DEST) || (op & VARIABLE_FLAG_MASK)) + FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | T(dst) | IMM(-src2), DR(dst))); + } + else { + if (is_overflow) + FAIL_IF(push_inst(compiler, XOR | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG)); + else if (op & SLJIT_SET_Z) + FAIL_IF(push_inst(compiler, SELECT_OP(DSUBU, SUBU) | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG)); + + if (is_overflow || is_carry) + FAIL_IF(push_inst(compiler, SLTU | S(src1) | T(src2) | DA(OTHER_FLAG), OTHER_FLAG)); + + /* Only the zero flag is needed. */ + if (!(flags & UNUSED_DEST) || (op & VARIABLE_FLAG_MASK)) + FAIL_IF(push_inst(compiler, SELECT_OP(DSUBU, SUBU) | S(src1) | T(src2) | D(dst), DR(dst))); + } + + if (!is_overflow) + return SLJIT_SUCCESS; + + FAIL_IF(push_inst(compiler, XOR | S(dst) | TA(EQUAL_FLAG) | D(TMP_REG1), DR(TMP_REG1))); + if (op & SLJIT_SET_Z) + FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(dst) | TA(0) | DA(EQUAL_FLAG), EQUAL_FLAG)); + FAIL_IF(push_inst(compiler, SELECT_OP(DSRL32, SRL) | T(TMP_REG1) | D(TMP_REG1) | SH_IMM(31), DR(TMP_REG1))); + return push_inst(compiler, XOR | S(TMP_REG1) | TA(OTHER_FLAG) | DA(OTHER_FLAG), OTHER_FLAG); + + case SLJIT_SUBC: + if ((flags & SRC2_IMM) && src2 == SIMM_MIN) { + FAIL_IF(push_inst(compiler, ADDIU | SA(0) | T(TMP_REG2) | IMM(src2), DR(TMP_REG2))); + src2 = TMP_REG2; + flags &= ~SRC2_IMM; + } + + is_carry = GET_FLAG_TYPE(op) == GET_FLAG_TYPE(SLJIT_SET_CARRY); + + if (flags & SRC2_IMM) { + if (is_carry) + FAIL_IF(push_inst(compiler, SLTIU | S(src1) | TA(EQUAL_FLAG) | IMM(src2), EQUAL_FLAG)); + + FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | T(dst) | IMM(-src2), DR(dst))); + } + else { + if (is_carry) + FAIL_IF(push_inst(compiler, SLTU | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG)); + + FAIL_IF(push_inst(compiler, SELECT_OP(DSUBU, SUBU) | S(src1) | T(src2) | D(dst), DR(dst))); + } + + if (is_carry) + FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(OTHER_FLAG) | D(TMP_REG1), DR(TMP_REG1))); + + FAIL_IF(push_inst(compiler, SELECT_OP(DSUBU, SUBU) | S(dst) | TA(OTHER_FLAG) | D(dst), DR(dst))); + + if (!is_carry) + return SLJIT_SUCCESS; + + return push_inst(compiler, OR | SA(EQUAL_FLAG) | T(TMP_REG1) | DA(OTHER_FLAG), OTHER_FLAG); + + case SLJIT_MUL: + SLJIT_ASSERT(!(flags & SRC2_IMM)); + + if (GET_FLAG_TYPE(op) != SLJIT_OVERFLOW) { +#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6) + return push_inst(compiler, SELECT_OP(DMUL, MUL) | S(src1) | T(src2) | D(dst), DR(dst)); +#elif (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1) +#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) + return push_inst(compiler, MUL | S(src1) | T(src2) | D(dst), DR(dst)); +#else /* !SLJIT_CONFIG_MIPS_32 */ + if (op & SLJIT_32) + return push_inst(compiler, MUL | S(src1) | T(src2) | D(dst), DR(dst)); + FAIL_IF(push_inst(compiler, DMULT | S(src1) | T(src2), MOVABLE_INS)); + return push_inst(compiler, MFLO | D(dst), DR(dst)); +#endif /* SLJIT_CONFIG_MIPS_32 */ +#else /* SLJIT_MIPS_REV < 1 */ + FAIL_IF(push_inst(compiler, SELECT_OP(DMULT, MULT) | S(src1) | T(src2), MOVABLE_INS)); + return push_inst(compiler, MFLO | D(dst), DR(dst)); +#endif /* SLJIT_MIPS_REV >= 6 */ + } + +#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6) + FAIL_IF(push_inst(compiler, SELECT_OP(DMUL, MUL) | S(src1) | T(src2) | D(dst), DR(dst))); + FAIL_IF(push_inst(compiler, SELECT_OP(DMUH, MUH) | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG)); +#else /* SLJIT_MIPS_REV < 6 */ + FAIL_IF(push_inst(compiler, SELECT_OP(DMULT, MULT) | S(src1) | T(src2), MOVABLE_INS)); + FAIL_IF(push_inst(compiler, MFHI | DA(EQUAL_FLAG), EQUAL_FLAG)); + FAIL_IF(push_inst(compiler, MFLO | D(dst), DR(dst))); +#endif /* SLJIT_MIPS_REV >= 6 */ + FAIL_IF(push_inst(compiler, SELECT_OP(DSRA32, SRA) | T(dst) | DA(OTHER_FLAG) | SH_IMM(31), OTHER_FLAG)); + return push_inst(compiler, SELECT_OP(DSUBU, SUBU) | SA(EQUAL_FLAG) | TA(OTHER_FLAG) | DA(OTHER_FLAG), OTHER_FLAG); + + case SLJIT_AND: + EMIT_LOGICAL(ANDI, AND); + return SLJIT_SUCCESS; + + case SLJIT_OR: + EMIT_LOGICAL(ORI, OR); + return SLJIT_SUCCESS; + + case SLJIT_XOR: + EMIT_LOGICAL(XORI, XOR); + return SLJIT_SUCCESS; + + case SLJIT_SHL: + case SLJIT_MSHL: + EMIT_SHIFT(DSLL, DSLL32, SLL, DSLLV, SLLV); + break; + + case SLJIT_LSHR: + case SLJIT_MLSHR: + EMIT_SHIFT(DSRL, DSRL32, SRL, DSRLV, SRLV); + break; + + case SLJIT_ASHR: + case SLJIT_MASHR: + EMIT_SHIFT(DSRA, DSRA32, SRA, DSRAV, SRAV); + break; + +#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 2) + case SLJIT_ROTL: + if ((flags & SRC2_IMM) || src2 == 0) { +#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) + src2 = -src2 & 0x1f; +#else /* !SLJIT_CONFIG_MIPS_32 */ + src2 = -src2 & ((op & SLJIT_32) ? 0x1f : 0x3f); +#endif /* SLJIT_CONFIG_MIPS_32 */ + } else { + FAIL_IF(push_inst(compiler, SELECT_OP(DSUBU, SUBU) | SA(0) | T(src2) | D(TMP_REG2), DR(TMP_REG2))); + src2 = TMP_REG2; + } + /* fallthrough */ + + case SLJIT_ROTR: + EMIT_SHIFT(DROTR, DROTR32, ROTR, DROTRV, ROTRV); + break; +#else /* SLJIT_MIPS_REV < 1 */ + case SLJIT_ROTL: + case SLJIT_ROTR: + if (flags & SRC2_IMM) { + SLJIT_ASSERT(src2 != 0); +#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64) + if (!(op & SLJIT_32)) { + if (GET_OPCODE(op) == SLJIT_ROTL) + op_imm = ((src2 < 32) ? DSLL : DSLL32); + else + op_imm = ((src2 < 32) ? DSRL : DSRL32); + + FAIL_IF(push_inst(compiler, op_imm | T(src1) | DA(OTHER_FLAG) | (((sljit_ins)src2 & 0x1f) << 6), OTHER_FLAG)); + + src2 = 64 - src2; + if (GET_OPCODE(op) == SLJIT_ROTL) + op_imm = ((src2 < 32) ? DSRL : DSRL32); + else + op_imm = ((src2 < 32) ? DSLL : DSLL32); + + FAIL_IF(push_inst(compiler, op_imm | T(src1) | D(dst) | (((sljit_ins)src2 & 0x1f) << 6), DR(dst))); + return push_inst(compiler, OR | S(dst) | TA(OTHER_FLAG) | D(dst), DR(dst)); + } +#endif /* SLJIT_CONFIG_MIPS_64 */ + + op_imm = (GET_OPCODE(op) == SLJIT_ROTL) ? SLL : SRL; + FAIL_IF(push_inst(compiler, op_imm | T(src1) | DA(OTHER_FLAG) | ((sljit_ins)src2 << 6), OTHER_FLAG)); + + src2 = 32 - src2; + op_imm = (GET_OPCODE(op) == SLJIT_ROTL) ? SRL : SLL; + FAIL_IF(push_inst(compiler, op_imm | T(src1) | D(dst) | (((sljit_ins)src2 & 0x1f) << 6), DR(dst))); + return push_inst(compiler, OR | S(dst) | TA(OTHER_FLAG) | D(dst), DR(dst)); + } + + if (src2 == 0) { + if (dst != src1) + return push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(src1) | TA(0) | D(dst), DR(dst)); + return SLJIT_SUCCESS; + } + + FAIL_IF(push_inst(compiler, SELECT_OP(DSUBU, SUBU) | SA(0) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG)); + +#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64) + if (!(op & SLJIT_32)) { + op_v = (GET_OPCODE(op) == SLJIT_ROTL) ? DSLLV : DSRLV; + FAIL_IF(push_inst(compiler, op_v | S(src2) | T(src1) | DA(OTHER_FLAG), OTHER_FLAG)); + op_v = (GET_OPCODE(op) == SLJIT_ROTL) ? DSRLV : DSLLV; + FAIL_IF(push_inst(compiler, op_v | SA(EQUAL_FLAG) | T(src1) | D(dst), DR(dst))); + return push_inst(compiler, OR | S(dst) | TA(OTHER_FLAG) | D(dst), DR(dst)); + } +#endif /* SLJIT_CONFIG_MIPS_64 */ + + op_v = (GET_OPCODE(op) == SLJIT_ROTL) ? SLLV : SRLV; + FAIL_IF(push_inst(compiler, op_v | S(src2) | T(src1) | DA(OTHER_FLAG), OTHER_FLAG)); + op_v = (GET_OPCODE(op) == SLJIT_ROTL) ? SRLV : SLLV; + FAIL_IF(push_inst(compiler, op_v | SA(EQUAL_FLAG) | T(src1) | D(dst), DR(dst))); + return push_inst(compiler, OR | S(dst) | TA(OTHER_FLAG) | D(dst), DR(dst)); +#endif /* SLJIT_MIPS_REV >= 2 */ + + default: + SLJIT_UNREACHABLE(); + return SLJIT_SUCCESS; + } + +#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) + if ((flags & SRC2_IMM) || src2 == 0) { + if (op & SLJIT_SET_Z) + FAIL_IF(push_inst(compiler, op_imm | T(src1) | DA(EQUAL_FLAG) | SH_IMM(src2), EQUAL_FLAG)); + + if (flags & UNUSED_DEST) + return SLJIT_SUCCESS; + return push_inst(compiler, op_imm | T(src1) | D(dst) | SH_IMM(src2), DR(dst)); + } + + if (op & SLJIT_SET_Z) + FAIL_IF(push_inst(compiler, op_v | S(src2) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG)); + + if (flags & UNUSED_DEST) + return SLJIT_SUCCESS; + return push_inst(compiler, op_v | S(src2) | T(src1) | D(dst), DR(dst)); +#else /* !SLJIT_CONFIG_MIPS_32 */ + if ((flags & SRC2_IMM) || src2 == 0) { + if (src2 >= 32) { + SLJIT_ASSERT(!(op & SLJIT_32)); + ins = op_dimm32; + src2 -= 32; + } + else + ins = (op & SLJIT_32) ? op_imm : op_dimm; + + if (op & SLJIT_SET_Z) + FAIL_IF(push_inst(compiler, ins | T(src1) | DA(EQUAL_FLAG) | SH_IMM(src2), EQUAL_FLAG)); + + if (flags & UNUSED_DEST) + return SLJIT_SUCCESS; + return push_inst(compiler, ins | T(src1) | D(dst) | SH_IMM(src2), DR(dst)); + } + + ins = (op & SLJIT_32) ? op_v : op_dv; + if (op & SLJIT_SET_Z) + FAIL_IF(push_inst(compiler, ins | S(src2) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG)); + + if (flags & UNUSED_DEST) + return SLJIT_SUCCESS; + return push_inst(compiler, ins | S(src2) | T(src1) | D(dst), DR(dst)); +#endif /* SLJIT_CONFIG_MIPS_32 */ +} + +#define CHECK_IMM(flags, srcw) \ + ((!((flags) & LOGICAL_OP) && ((srcw) <= SIMM_MAX && (srcw) >= SIMM_MIN)) \ + || (((flags) & LOGICAL_OP) && !((srcw) & ~UIMM_MAX))) + static sljit_s32 emit_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 flags, sljit_s32 dst, sljit_sw dstw, sljit_s32 src1, sljit_sw src1w, @@ -1325,25 +2048,18 @@ static sljit_s32 emit_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s3 flags |= SLOW_DEST; if (flags & IMM_OP) { - if ((src2 & SLJIT_IMM) && src2w) { - if ((!(flags & LOGICAL_OP) && (src2w <= SIMM_MAX && src2w >= SIMM_MIN)) - || ((flags & LOGICAL_OP) && !(src2w & ~UIMM_MAX))) { - flags |= SRC2_IMM; - src2_r = src2w; - } - } - if (!(flags & SRC2_IMM) && (flags & CUMULATIVE_OP) && (src1 & SLJIT_IMM) && src1w) { - if ((!(flags & LOGICAL_OP) && (src1w <= SIMM_MAX && src1w >= SIMM_MIN)) - || ((flags & LOGICAL_OP) && !(src1w & ~UIMM_MAX))) { - flags |= SRC2_IMM; - src2_r = src1w; + if ((src2 & SLJIT_IMM) && src2w != 0 && CHECK_IMM(flags, src2w)) { + flags |= SRC2_IMM; + src2_r = src2w; + } else if ((flags & CUMULATIVE_OP) && (src1 & SLJIT_IMM) && src1w != 0 && CHECK_IMM(flags, src1w)) { + flags |= SRC2_IMM; + src2_r = src1w; - /* And swap arguments. */ - src1 = src2; - src1w = src2w; - src2 = SLJIT_IMM; - /* src2w = src2_r unneeded. */ - } + /* And swap arguments. */ + src1 = src2; + src1w = src2w; + src2 = SLJIT_IMM; + /* src2w = src2_r unneeded. */ } } @@ -1429,6 +2145,8 @@ static sljit_s32 emit_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s3 return SLJIT_SUCCESS; } +#undef CHECK_IMM + SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compiler, sljit_s32 op) { #if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64) @@ -1584,6 +2302,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile return emit_op(compiler, op, flags, dst, dstw, TMP_REG1, 0, src, srcw); case SLJIT_CLZ: + case SLJIT_CTZ: return emit_op(compiler, op, flags, dst, dstw, TMP_REG1, 0, src, srcw); } @@ -1635,8 +2354,13 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compile return emit_op(compiler, op, flags | CUMULATIVE_OP | LOGICAL_OP | IMM_OP, dst, dstw, src1, src1w, src2, src2w); case SLJIT_SHL: + case SLJIT_MSHL: case SLJIT_LSHR: + case SLJIT_MLSHR: case SLJIT_ASHR: + case SLJIT_MASHR: + case SLJIT_ROTL: + case SLJIT_ROTR: #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) if (src2 & SLJIT_IMM) src2w &= 0x1f; @@ -1662,13 +2386,106 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2u(struct sljit_compiler *compil CHECK_ERROR(); CHECK(check_sljit_emit_op2(compiler, op, 1, 0, 0, src1, src1w, src2, src2w)); -#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \ - || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) - compiler->skip_checks = 1; -#endif + SLJIT_SKIP_CHECKS(compiler); return sljit_emit_op2(compiler, op, TMP_REG2, 0, src1, src1w, src2, src2w); } +#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64) +#define SELECT_OP3(op, src2w, D, D32, W) (((op & SLJIT_32) ? (W) : ((src2w) < 32) ? (D) : (D32)) | (((sljit_ins)src2w & 0x1f) << 6)) +#define SELECT_OP2(op, D, W) ((op & SLJIT_32) ? (W) : (D)) +#else /* !SLJIT_CONFIG_MIPS_64 */ +#define SELECT_OP3(op, src2w, D, D32, W) ((W) | ((sljit_ins)(src2w) << 6)) +#define SELECT_OP2(op, D, W) (W) +#endif /* SLJIT_CONFIG_MIPS_64 */ + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_shift_into(struct sljit_compiler *compiler, sljit_s32 op, + sljit_s32 src_dst, + sljit_s32 src1, sljit_sw src1w, + sljit_s32 src2, sljit_sw src2w) +{ + sljit_s32 is_left; + sljit_ins ins1, ins2, ins3; +#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64) + sljit_s32 inp_flags = ((op & SLJIT_32) ? INT_DATA : WORD_DATA) | LOAD_DATA; + sljit_sw bit_length = (op & SLJIT_32) ? 32 : 64; +#else /* !SLJIT_CONFIG_MIPS_64 */ + sljit_s32 inp_flags = WORD_DATA | LOAD_DATA; + sljit_sw bit_length = 32; +#endif /* SLJIT_CONFIG_MIPS_64 */ + + CHECK_ERROR(); + CHECK(check_sljit_emit_shift_into(compiler, op, src_dst, src1, src1w, src2, src2w)); + + is_left = (GET_OPCODE(op) == SLJIT_SHL || GET_OPCODE(op) == SLJIT_MSHL); + + if (src_dst == src1) { + SLJIT_SKIP_CHECKS(compiler); + return sljit_emit_op2(compiler, (is_left ? SLJIT_ROTL : SLJIT_ROTR) | (op & SLJIT_32), src_dst, 0, src_dst, 0, src2, src2w); + } + + ADJUST_LOCAL_OFFSET(src1, src1w); + ADJUST_LOCAL_OFFSET(src2, src2w); + + if (src2 & SLJIT_IMM) { + src2w &= bit_length - 1; + + if (src2w == 0) + return SLJIT_SUCCESS; + } else if (src2 & SLJIT_MEM) { + FAIL_IF(emit_op_mem(compiler, inp_flags, DR(TMP_REG2), src2, src2w)); + src2 = TMP_REG2; + } + + if (src1 & SLJIT_MEM) { + FAIL_IF(emit_op_mem(compiler, inp_flags, DR(TMP_REG1), src1, src1w)); + src1 = TMP_REG1; + } else if (src1 & SLJIT_IMM) { + FAIL_IF(load_immediate(compiler, DR(TMP_REG1), src1w)); + src1 = TMP_REG1; + } + + if (src2 & SLJIT_IMM) { + if (is_left) { + ins1 = SELECT_OP3(op, src2w, DSLL, DSLL32, SLL); + src2w = bit_length - src2w; + ins2 = SELECT_OP3(op, src2w, DSRL, DSRL32, SRL); + } else { + ins1 = SELECT_OP3(op, src2w, DSRL, DSRL32, SRL); + src2w = bit_length - src2w; + ins2 = SELECT_OP3(op, src2w, DSLL, DSLL32, SLL); + } + + FAIL_IF(push_inst(compiler, ins1 | T(src_dst) | D(src_dst), DR(src_dst))); + FAIL_IF(push_inst(compiler, ins2 | T(src1) | D(TMP_REG1), DR(TMP_REG1))); + return push_inst(compiler, OR | S(src_dst) | T(TMP_REG1) | D(src_dst), DR(src_dst)); + } + + if (is_left) { + ins1 = SELECT_OP2(op, DSRL, SRL); + ins2 = SELECT_OP2(op, DSLLV, SLLV); + ins3 = SELECT_OP2(op, DSRLV, SRLV); + } else { + ins1 = SELECT_OP2(op, DSLL, SLL); + ins2 = SELECT_OP2(op, DSRLV, SRLV); + ins3 = SELECT_OP2(op, DSLLV, SLLV); + } + + FAIL_IF(push_inst(compiler, ins2 | S(src2) | T(src_dst) | D(src_dst), DR(src_dst))); + + if (!(op & SLJIT_SHIFT_INTO_NON_ZERO)) { + FAIL_IF(push_inst(compiler, ins1 | T(src1) | D(TMP_REG1) | (1 << 6), DR(TMP_REG1))); + FAIL_IF(push_inst(compiler, XORI | S(src2) | T(TMP_REG2) | ((sljit_ins)bit_length - 1), DR(TMP_REG2))); + src1 = TMP_REG1; + } else + FAIL_IF(push_inst(compiler, SELECT_OP2(op, DSUBU, SUBU) | SA(0) | T(src2) | D(TMP_REG2), DR(TMP_REG2))); + + FAIL_IF(push_inst(compiler, ins3 | S(TMP_REG2) | T(src1) | D(TMP_REG1), DR(TMP_REG1))); + return push_inst(compiler, OR | S(src_dst) | T(TMP_REG1) | D(src_dst), DR(src_dst)); +} + +#undef SELECT_OP3 +#undef SELECT_OP2 + SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_src(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 src, sljit_sw srcw) { @@ -1746,14 +2563,19 @@ static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_sw_from_f64(struct sljit_comp FAIL_IF(push_inst(compiler, (TRUNC_W_S ^ (flags >> 19)) | FMT(op) | FS(src) | FD(TMP_FREG1), MOVABLE_INS)); - if (FAST_IS_REG(dst)) - return push_inst(compiler, MFC1 | flags | T(dst) | FS(TMP_FREG1), MOVABLE_INS); + if (FAST_IS_REG(dst)) { + FAIL_IF(push_inst(compiler, MFC1 | flags | T(dst) | FS(TMP_FREG1), MOVABLE_INS)); +#if (!defined SLJIT_MIPS_REV || SLJIT_MIPS_REV <= 3) + FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS)); +#endif + return SLJIT_SUCCESS; + } /* Store the integer value from a VFP register. */ return emit_op_mem2(compiler, flags ? DOUBLE_DATA : SINGLE_DATA, FR(TMP_FREG1), dst, dstw, 0, 0); #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) -# undef is_long +# undef flags #endif } @@ -1769,19 +2591,25 @@ static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_sw(struct sljit_comp sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1; - if (FAST_IS_REG(src)) + if (FAST_IS_REG(src)) { FAIL_IF(push_inst(compiler, MTC1 | flags | T(src) | FS(TMP_FREG1), MOVABLE_INS)); - else if (src & SLJIT_MEM) { +#if (!defined SLJIT_MIPS_REV || SLJIT_MIPS_REV <= 3) + FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS)); +#endif + } else if (src & SLJIT_MEM) { /* Load the integer value into a VFP register. */ - FAIL_IF(emit_op_mem2(compiler, ((flags) ? DOUBLE_DATA : SINGLE_DATA) | LOAD_DATA, FR(TMP_FREG1), src, srcw, dst, dstw)); + FAIL_IF(emit_op_mem2(compiler, (flags ? DOUBLE_DATA : SINGLE_DATA) | LOAD_DATA, FR(TMP_FREG1), src, srcw, dst, dstw)); } else { -#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) +#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64) if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_S32) srcw = (sljit_s32)srcw; #endif FAIL_IF(load_immediate(compiler, DR(TMP_REG1), srcw)); FAIL_IF(push_inst(compiler, MTC1 | flags | T(TMP_REG1) | FS(TMP_FREG1), MOVABLE_INS)); +#if (!defined SLJIT_MIPS_REV || SLJIT_MIPS_REV <= 3) + FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS)); +#endif } FAIL_IF(push_inst(compiler, CVT_S_S | flags | (4 << 21) | ((((sljit_ins)op & SLJIT_32) ^ SLJIT_32) >> 8) | FS(TMP_FREG1) | FD(dst_r), MOVABLE_INS)); @@ -1812,20 +2640,38 @@ static SLJIT_INLINE sljit_s32 sljit_emit_fop1_cmp(struct sljit_compiler *compile } switch (GET_FLAG_TYPE(op)) { - case SLJIT_EQUAL_F64: - case SLJIT_NOT_EQUAL_F64: + case SLJIT_F_EQUAL: + case SLJIT_ORDERED_EQUAL: + case SLJIT_UNORDERED_OR_NOT_EQUAL: + inst = C_EQ_S; + break; + case SLJIT_F_NOT_EQUAL: + case SLJIT_UNORDERED_OR_EQUAL: + case SLJIT_ORDERED_NOT_EQUAL: inst = C_UEQ_S; break; - case SLJIT_LESS_F64: - case SLJIT_GREATER_EQUAL_F64: + case SLJIT_F_LESS: + case SLJIT_ORDERED_LESS: + case SLJIT_UNORDERED_OR_GREATER_EQUAL: + inst = C_OLT_S; + break; + case SLJIT_F_GREATER_EQUAL: + case SLJIT_UNORDERED_OR_LESS: + case SLJIT_ORDERED_GREATER_EQUAL: inst = C_ULT_S; break; - case SLJIT_GREATER_F64: - case SLJIT_LESS_EQUAL_F64: + case SLJIT_F_GREATER: + case SLJIT_ORDERED_GREATER: + case SLJIT_UNORDERED_OR_LESS_EQUAL: inst = C_ULE_S; break; + case SLJIT_F_LESS_EQUAL: + case SLJIT_UNORDERED_OR_GREATER: + case SLJIT_ORDERED_LESS_EQUAL: + inst = C_OLE_S; + break; default: - SLJIT_ASSERT(GET_FLAG_TYPE(op) == SLJIT_UNORDERED_F64 || GET_FLAG_TYPE(op) == SLJIT_ORDERED_F64); + SLJIT_ASSERT(GET_FLAG_TYPE(op) == SLJIT_UNORDERED || GET_FLAG_TYPE(op) == SLJIT_ORDERED); inst = C_UN_S; break; } @@ -1871,6 +2717,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop1(struct sljit_compiler *compil FAIL_IF(push_inst(compiler, ABS_S | FMT(op) | FS(src) | FD(dst_r), MOVABLE_INS)); break; case SLJIT_CONV_F64_FROM_F32: + /* The SLJIT_32 bit is inverted because sljit_f32 needs to be loaded from the memory. */ FAIL_IF(push_inst(compiler, CVT_S_S | (sljit_ins)((op & SLJIT_32) ? 1 : (1 << 21)) | FS(src) | FD(dst_r), MOVABLE_INS)); op ^= SLJIT_32; break; @@ -1959,6 +2806,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop2(struct sljit_compiler *compil return SLJIT_SUCCESS; } +#undef FLOAT_DATA +#undef FMT + /* --------------------------------------------------------------------- */ /* Other instructions */ /* --------------------------------------------------------------------- */ @@ -2000,18 +2850,18 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compi } #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) -#define JUMP_LENGTH 4 +#define BRANCH_LENGTH 4 #else -#define JUMP_LENGTH 8 +#define BRANCH_LENGTH 8 #endif #define BR_Z(src) \ - inst = BEQ | SA(src) | TA(0) | JUMP_LENGTH; \ + inst = BEQ | SA(src) | TA(0) | BRANCH_LENGTH; \ flags = IS_BIT26_COND; \ delay_check = src; #define BR_NZ(src) \ - inst = BNE | SA(src) | TA(0) | JUMP_LENGTH; \ + inst = BNE | SA(src) | TA(0) | BRANCH_LENGTH; \ flags = IS_BIT26_COND; \ delay_check = src; @@ -2029,11 +2879,11 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compi #else /* SLJIT_MIPS_REV < 6 */ #define BR_T() \ - inst = BC1T | JUMP_LENGTH; \ + inst = BC1T | BRANCH_LENGTH; \ flags = IS_BIT16_COND; \ delay_check = FCSR_FCC; #define BR_F() \ - inst = BC1F | JUMP_LENGTH; \ + inst = BC1F | BRANCH_LENGTH; \ flags = IS_BIT16_COND; \ delay_check = FCSR_FCC; @@ -2077,16 +2927,28 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compile case SLJIT_NOT_CARRY: BR_NZ(OTHER_FLAG); break; - case SLJIT_NOT_EQUAL_F64: - case SLJIT_GREATER_EQUAL_F64: - case SLJIT_GREATER_F64: - case SLJIT_ORDERED_F64: + case SLJIT_F_NOT_EQUAL: + case SLJIT_F_GREATER_EQUAL: + case SLJIT_F_GREATER: + case SLJIT_UNORDERED_OR_NOT_EQUAL: + case SLJIT_ORDERED_NOT_EQUAL: + case SLJIT_UNORDERED_OR_GREATER_EQUAL: + case SLJIT_ORDERED_GREATER_EQUAL: + case SLJIT_ORDERED_GREATER: + case SLJIT_UNORDERED_OR_GREATER: + case SLJIT_ORDERED: BR_T(); break; - case SLJIT_EQUAL_F64: - case SLJIT_LESS_F64: - case SLJIT_LESS_EQUAL_F64: - case SLJIT_UNORDERED_F64: + case SLJIT_F_EQUAL: + case SLJIT_F_LESS: + case SLJIT_F_LESS_EQUAL: + case SLJIT_ORDERED_EQUAL: + case SLJIT_UNORDERED_OR_EQUAL: + case SLJIT_ORDERED_LESS: + case SLJIT_UNORDERED_OR_LESS: + case SLJIT_UNORDERED_OR_LESS_EQUAL: + case SLJIT_ORDERED_LESS_EQUAL: + case SLJIT_UNORDERED: BR_F(); break; default: @@ -2102,8 +2964,6 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compile if (inst) PTR_FAIL_IF(push_inst(compiler, inst, UNMOVABLE_INS)); - PTR_FAIL_IF(emit_const(compiler, TMP_REG2, 0)); - if (type <= SLJIT_JUMP) PTR_FAIL_IF(push_inst(compiler, JR | S(TMP_REG2), UNMOVABLE_INS)); else { @@ -2113,6 +2973,13 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compile jump->addr = compiler->size; PTR_FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS)); + + /* Maximum number of instructions required for generating a constant. */ +#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) + compiler->size += 2; +#else + compiler->size += 6; +#endif return jump; } @@ -2151,11 +3018,17 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_cmp(struct sljit_compiler compiler->cache_arg = 0; compiler->cache_argw = 0; +#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) + flags = WORD_DATA | LOAD_DATA; +#else /* !SLJIT_CONFIG_MIPS_32 */ flags = ((type & SLJIT_32) ? INT_DATA : WORD_DATA) | LOAD_DATA; +#endif /* SLJIT_CONFIG_MIPS_32 */ + if (src1 & SLJIT_MEM) { PTR_FAIL_IF(emit_op_mem2(compiler, flags, DR(TMP_REG1), src1, src1w, src2, src2w)); src1 = TMP_REG1; } + if (src2 & SLJIT_MEM) { PTR_FAIL_IF(emit_op_mem2(compiler, flags, DR(TMP_REG2), src2, src2w, 0, 0)); src2 = TMP_REG2; @@ -2172,7 +3045,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_cmp(struct sljit_compiler jump->flags |= IS_BIT26_COND; if (compiler->delay_slot == MOVABLE_INS || (compiler->delay_slot != UNMOVABLE_INS && compiler->delay_slot != DR(src1) && compiler->delay_slot != DR(src2))) jump->flags |= IS_MOVABLE; - PTR_FAIL_IF(push_inst(compiler, (type == SLJIT_EQUAL ? BNE : BEQ) | S(src1) | T(src2) | JUMP_LENGTH, UNMOVABLE_INS)); + PTR_FAIL_IF(push_inst(compiler, (type == SLJIT_EQUAL ? BNE : BEQ) | S(src1) | T(src2) | BRANCH_LENGTH, UNMOVABLE_INS)); } else if (type >= SLJIT_SIG_LESS && (((src1 & SLJIT_IMM) && (src1w == 0)) || ((src2 & SLJIT_IMM) && (src2w == 0)))) { inst = NOP; @@ -2219,7 +3092,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_cmp(struct sljit_compiler break; } } - PTR_FAIL_IF(push_inst(compiler, inst | S(src1) | JUMP_LENGTH, UNMOVABLE_INS)); + PTR_FAIL_IF(push_inst(compiler, inst | S(src1) | BRANCH_LENGTH, UNMOVABLE_INS)); } else { if (type == SLJIT_LESS || type == SLJIT_GREATER_EQUAL || type == SLJIT_SIG_LESS || type == SLJIT_SIG_GREATER_EQUAL) { @@ -2244,20 +3117,26 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_cmp(struct sljit_compiler } jump->flags |= IS_BIT26_COND; - PTR_FAIL_IF(push_inst(compiler, (type == SLJIT_EQUAL ? BNE : BEQ) | S(TMP_REG1) | TA(0) | JUMP_LENGTH, UNMOVABLE_INS)); + PTR_FAIL_IF(push_inst(compiler, (type == SLJIT_EQUAL ? BNE : BEQ) | S(TMP_REG1) | TA(0) | BRANCH_LENGTH, UNMOVABLE_INS)); } - PTR_FAIL_IF(emit_const(compiler, TMP_REG2, 0)); PTR_FAIL_IF(push_inst(compiler, JR | S(TMP_REG2), UNMOVABLE_INS)); jump->addr = compiler->size; PTR_FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS)); + + /* Maximum number of instructions required for generating a constant. */ +#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) + compiler->size += 2; +#else + compiler->size += 6; +#endif return jump; } #undef RESOLVE_IMM1 #undef RESOLVE_IMM2 -#undef JUMP_LENGTH +#undef BRANCH_LENGTH #undef BR_Z #undef BR_NZ #undef BR_T @@ -2272,7 +3151,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compi CHECK_ERROR(); CHECK(check_sljit_emit_ijump(compiler, type, src, srcw)); - ADJUST_LOCAL_OFFSET(src, srcw); if (src & SLJIT_IMM) { jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump)); @@ -2283,17 +3161,29 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compi if (compiler->delay_slot != UNMOVABLE_INS) jump->flags |= IS_MOVABLE; - FAIL_IF(emit_const(compiler, TMP_REG2, 0)); src = TMP_REG2; - } - else if (src & SLJIT_MEM) { + } else if (src & SLJIT_MEM) { + ADJUST_LOCAL_OFFSET(src, srcw); FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, DR(TMP_REG2), src, srcw)); src = TMP_REG2; } - FAIL_IF(push_inst(compiler, JR | S(src), UNMOVABLE_INS)); - if (jump) + if (type <= SLJIT_JUMP) + FAIL_IF(push_inst(compiler, JR | S(src), UNMOVABLE_INS)); + else + FAIL_IF(push_inst(compiler, JALR | S(src) | DA(RETURN_ADDR_REG), UNMOVABLE_INS)); + + if (jump != NULL) { jump->addr = compiler->size; + + /* Maximum number of instructions required for generating a constant. */ +#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) + compiler->size += 2; +#else + compiler->size += 6; +#endif + } + FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS)); return SLJIT_SUCCESS; } @@ -2302,7 +3192,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *co sljit_s32 dst, sljit_sw dstw, sljit_s32 type) { - sljit_s32 src_ar, dst_ar; + sljit_s32 src_ar, dst_ar, invert; sljit_s32 saved_op = op; #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) sljit_s32 mem_type = WORD_DATA; @@ -2323,32 +3213,45 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *co if (op >= SLJIT_ADD && (dst & SLJIT_MEM)) FAIL_IF(emit_op_mem2(compiler, mem_type | LOAD_DATA, DR(TMP_REG1), dst, dstw, dst, dstw)); - switch (type & 0xff) { - case SLJIT_EQUAL: - case SLJIT_NOT_EQUAL: - FAIL_IF(push_inst(compiler, SLTIU | SA(EQUAL_FLAG) | TA(dst_ar) | IMM(1), dst_ar)); - src_ar = dst_ar; - break; - case SLJIT_OVERFLOW: - case SLJIT_NOT_OVERFLOW: - if (compiler->status_flags_state & (SLJIT_CURRENT_FLAGS_ADD | SLJIT_CURRENT_FLAGS_SUB)) { - src_ar = OTHER_FLAG; + if (type < SLJIT_F_EQUAL) { + src_ar = OTHER_FLAG; + invert = type & 0x1; + + switch (type) { + case SLJIT_EQUAL: + case SLJIT_NOT_EQUAL: + FAIL_IF(push_inst(compiler, SLTIU | SA(EQUAL_FLAG) | TA(dst_ar) | IMM(1), dst_ar)); + src_ar = dst_ar; + break; + case SLJIT_OVERFLOW: + case SLJIT_NOT_OVERFLOW: + if (compiler->status_flags_state & (SLJIT_CURRENT_FLAGS_ADD | SLJIT_CURRENT_FLAGS_SUB)) { + src_ar = OTHER_FLAG; + break; + } + FAIL_IF(push_inst(compiler, SLTIU | SA(OTHER_FLAG) | TA(dst_ar) | IMM(1), dst_ar)); + src_ar = dst_ar; + invert ^= 0x1; break; } - FAIL_IF(push_inst(compiler, SLTIU | SA(OTHER_FLAG) | TA(dst_ar) | IMM(1), dst_ar)); - src_ar = dst_ar; - type ^= 0x1; /* Flip type bit for the XORI below. */ - break; - case SLJIT_GREATER_F64: - case SLJIT_LESS_EQUAL_F64: - type ^= 0x1; /* Flip type bit for the XORI below. */ - /* fallthrough */ - case SLJIT_EQUAL_F64: - case SLJIT_NOT_EQUAL_F64: - case SLJIT_LESS_F64: - case SLJIT_GREATER_EQUAL_F64: - case SLJIT_UNORDERED_F64: - case SLJIT_ORDERED_F64: + } else { + invert = 0; + + switch (type) { + case SLJIT_F_NOT_EQUAL: + case SLJIT_F_GREATER_EQUAL: + case SLJIT_F_GREATER: + case SLJIT_UNORDERED_OR_NOT_EQUAL: + case SLJIT_ORDERED_NOT_EQUAL: + case SLJIT_UNORDERED_OR_GREATER_EQUAL: + case SLJIT_ORDERED_GREATER_EQUAL: + case SLJIT_ORDERED_GREATER: + case SLJIT_UNORDERED_OR_GREATER: + case SLJIT_ORDERED: + invert = 1; + break; + } + #if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6) FAIL_IF(push_inst(compiler, MFC1 | TA(dst_ar) | FS(TMP_FREG3), dst_ar)); #else /* SLJIT_MIPS_REV < 6 */ @@ -2357,14 +3260,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *co FAIL_IF(push_inst(compiler, SRL | TA(dst_ar) | DA(dst_ar) | SH_IMM(23), dst_ar)); FAIL_IF(push_inst(compiler, ANDI | SA(dst_ar) | TA(dst_ar) | IMM(1), dst_ar)); src_ar = dst_ar; - break; - - default: - src_ar = OTHER_FLAG; - break; } - if (type & 0x1) { + if (invert) { FAIL_IF(push_inst(compiler, XORI | SA(src_ar) | TA(dst_ar) | IMM(1), dst_ar)); src_ar = dst_ar; } @@ -2404,7 +3302,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_cmov(struct sljit_compiler *compil if (SLJIT_UNLIKELY(src & SLJIT_IMM)) { #if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64) - if (dst_reg & SLJIT_32) + if (type & SLJIT_32) srcw = (sljit_s32)srcw; #endif FAIL_IF(load_immediate(compiler, DR(TMP_REG1), srcw)); @@ -2412,9 +3310,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_cmov(struct sljit_compiler *compil srcw = 0; } - dst_reg &= ~SLJIT_32; - - switch (type & 0xff) { + switch (type & ~SLJIT_32) { case SLJIT_EQUAL: ins = MOVZ | TA(EQUAL_FLAG); break; @@ -2435,16 +3331,28 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_cmov(struct sljit_compiler *compil case SLJIT_NOT_OVERFLOW: ins = MOVZ | TA(OTHER_FLAG); break; - case SLJIT_EQUAL_F64: - case SLJIT_LESS_F64: - case SLJIT_LESS_EQUAL_F64: - case SLJIT_UNORDERED_F64: + case SLJIT_F_EQUAL: + case SLJIT_F_LESS: + case SLJIT_F_LESS_EQUAL: + case SLJIT_ORDERED_EQUAL: + case SLJIT_UNORDERED_OR_EQUAL: + case SLJIT_ORDERED_LESS: + case SLJIT_UNORDERED_OR_LESS: + case SLJIT_UNORDERED_OR_LESS_EQUAL: + case SLJIT_ORDERED_LESS_EQUAL: + case SLJIT_UNORDERED: ins = MOVT; break; - case SLJIT_NOT_EQUAL_F64: - case SLJIT_GREATER_EQUAL_F64: - case SLJIT_GREATER_F64: - case SLJIT_ORDERED_F64: + case SLJIT_F_NOT_EQUAL: + case SLJIT_F_GREATER_EQUAL: + case SLJIT_F_GREATER: + case SLJIT_UNORDERED_OR_NOT_EQUAL: + case SLJIT_ORDERED_NOT_EQUAL: + case SLJIT_UNORDERED_OR_GREATER_EQUAL: + case SLJIT_ORDERED_GREATER_EQUAL: + case SLJIT_ORDERED_GREATER: + case SLJIT_UNORDERED_OR_GREATER: + case SLJIT_ORDERED: ins = MOVF; break; default: @@ -2460,6 +3368,308 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_cmov(struct sljit_compiler *compil #endif /* SLJIT_MIPS_REV >= 1 */ } +static sljit_s32 update_mem_addr(struct sljit_compiler *compiler, sljit_s32 *mem, sljit_sw *memw, sljit_s16 max_offset) +{ + sljit_s32 arg = *mem; + sljit_sw argw = *memw; + + if (SLJIT_UNLIKELY(arg & OFFS_REG_MASK)) { + argw &= 0x3; + + if (SLJIT_UNLIKELY(argw)) { + FAIL_IF(push_inst(compiler, SLL_W | T(OFFS_REG(arg)) | D(TMP_REG1) | SH_IMM(argw), DR(TMP_REG1))); + FAIL_IF(push_inst(compiler, ADDU_W | S(TMP_REG1) | T(arg & REG_MASK) | D(TMP_REG1), DR(TMP_REG1))); + } else + FAIL_IF(push_inst(compiler, ADDU_W | S(arg & REG_MASK) | T(OFFS_REG(arg)) | D(TMP_REG1), DR(TMP_REG1))); + + *mem = TMP_REG1; + *memw = 0; + + return SLJIT_SUCCESS; + } + + if (argw <= max_offset && argw >= SIMM_MIN) { + *mem = arg & REG_MASK; + return SLJIT_SUCCESS; + } + + *mem = TMP_REG1; + + if ((sljit_s16)argw > max_offset) { + FAIL_IF(load_immediate(compiler, DR(TMP_REG1), argw)); + *memw = 0; + } else { + FAIL_IF(load_immediate(compiler, DR(TMP_REG1), TO_ARGW_HI(argw))); + *memw = (sljit_s16)argw; + } + + if ((arg & REG_MASK) == 0) + return SLJIT_SUCCESS; + + return push_inst(compiler, ADDU_W | S(TMP_REG1) | T(arg & REG_MASK) | D(TMP_REG1), DR(TMP_REG1)); +} + +#if (defined SLJIT_LITTLE_ENDIAN && SLJIT_LITTLE_ENDIAN) +#define MEM16_IMM_FIRST(memw) IMM((memw) + 1) +#define MEM16_IMM_SECOND(memw) IMM(memw) +#define MEMF64_FS_FIRST(freg) FS(freg) +#define MEMF64_FS_SECOND(freg) (FS(freg) | ((sljit_ins)1 << 11)) +#else /* !SLJIT_LITTLE_ENDIAN */ +#define MEM16_IMM_FIRST(memw) IMM(memw) +#define MEM16_IMM_SECOND(memw) IMM((memw) + 1) +#define MEMF64_FS_FIRST(freg) (FS(freg) | ((sljit_ins)1 << 11)) +#define MEMF64_FS_SECOND(freg) FS(freg) +#endif /* SLJIT_LITTLE_ENDIAN */ + +#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) +#define MEM_CHECK_UNALIGNED(type) ((type) & (SLJIT_MEM_UNALIGNED | SLJIT_MEM_UNALIGNED_16)) +#else /* !SLJIT_CONFIG_MIPS_32 */ +#define MEM_CHECK_UNALIGNED(type) ((type) & (SLJIT_MEM_UNALIGNED | SLJIT_MEM_UNALIGNED_16 | SLJIT_MEM_UNALIGNED_32)) +#endif /* SLJIT_CONFIG_MIPS_32 */ + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compiler, sljit_s32 type, + sljit_s32 reg, + sljit_s32 mem, sljit_sw memw) +{ + sljit_s32 op = type & 0xff; + sljit_s32 flags = 0; + sljit_ins ins; +#if !(defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6) + sljit_ins ins_right; +#endif /* !(SLJIT_MIPS_REV >= 6) */ + + CHECK_ERROR(); + CHECK(check_sljit_emit_mem(compiler, type, reg, mem, memw)); + + if (reg & REG_PAIR_MASK) { + ADJUST_LOCAL_OFFSET(mem, memw); + +#if !(defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6) + if (MEM_CHECK_UNALIGNED(type)) { + FAIL_IF(update_mem_addr(compiler, &mem, &memw, SIMM_MAX - (2 * SSIZE_OF(sw) - 1))); + + if (!(type & SLJIT_MEM_STORE) && (mem == REG_PAIR_FIRST(reg) || mem == REG_PAIR_SECOND(reg))) { + FAIL_IF(push_inst(compiler, ADDU_W | S(mem) | TA(0) | D(TMP_REG1), DR(TMP_REG1))); + mem = TMP_REG1; + } + +#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) + ins = ((type & SLJIT_MEM_STORE) ? SWL : LWL) | S(mem); + ins_right = ((type & SLJIT_MEM_STORE) ? SWR : LWR) | S(mem); +#else /* !SLJIT_CONFIG_MIPS_32 */ + ins = ((type & SLJIT_MEM_STORE) ? SDL : LDL) | S(mem); + ins_right = ((type & SLJIT_MEM_STORE) ? SDR : LDR) | S(mem); +#endif /* SLJIT_CONFIG_MIPS_32 */ + + FAIL_IF(push_inst(compiler, ins | T(REG_PAIR_FIRST(reg)) | IMM(memw), DR(REG_PAIR_FIRST(reg)))); + FAIL_IF(push_inst(compiler, ins_right | T(REG_PAIR_FIRST(reg)) | IMM(memw + (SSIZE_OF(sw) - 1)), DR(REG_PAIR_FIRST(reg)))); + FAIL_IF(push_inst(compiler, ins | T(REG_PAIR_SECOND(reg)) | IMM(memw + SSIZE_OF(sw)), DR(REG_PAIR_SECOND(reg)))); + return push_inst(compiler, ins_right | T(REG_PAIR_SECOND(reg)) | IMM((memw + 2 * SSIZE_OF(sw) - 1)), DR(REG_PAIR_SECOND(reg))); + } +#endif /* !(SLJIT_MIPS_REV >= 6) */ + + FAIL_IF(update_mem_addr(compiler, &mem, &memw, SIMM_MAX - SSIZE_OF(sw))); + + ins = ((type & SLJIT_MEM_STORE) ? STORE_W : LOAD_W) | S(mem); + + if (!(type & SLJIT_MEM_STORE) && mem == REG_PAIR_FIRST(reg)) { + FAIL_IF(push_inst(compiler, ins | T(REG_PAIR_SECOND(reg)) | IMM(memw + SSIZE_OF(sw)), DR(REG_PAIR_SECOND(reg)))); + return push_inst(compiler, ins | T(REG_PAIR_FIRST(reg)) | IMM(memw), DR(REG_PAIR_FIRST(reg))); + } + + FAIL_IF(push_inst(compiler, ins | T(REG_PAIR_FIRST(reg)) | IMM(memw), DR(REG_PAIR_FIRST(reg)))); + return push_inst(compiler, ins | T(REG_PAIR_SECOND(reg)) | IMM(memw + SSIZE_OF(sw)), DR(REG_PAIR_SECOND(reg))); + } + +#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6) + return sljit_emit_mem_unaligned(compiler, type, reg, mem, memw); +#else /* !(SLJIT_MIPS_REV >= 6) */ + ADJUST_LOCAL_OFFSET(mem, memw); + + switch (op) { + case SLJIT_MOV_U8: + case SLJIT_MOV_S8: + flags = BYTE_DATA; + if (!(type & SLJIT_MEM_STORE)) + flags |= LOAD_DATA; + + if (op == SLJIT_MOV_S8) + flags |= SIGNED_DATA; + + return emit_op_mem(compiler, flags, DR(reg), mem, memw); + + case SLJIT_MOV_U16: + case SLJIT_MOV_S16: + FAIL_IF(update_mem_addr(compiler, &mem, &memw, SIMM_MAX - 1)); + SLJIT_ASSERT(FAST_IS_REG(mem) && mem != TMP_REG2); + + if (type & SLJIT_MEM_STORE) { + FAIL_IF(push_inst(compiler, SRA_W | T(reg) | D(TMP_REG2) | SH_IMM(8), DR(TMP_REG2))); + FAIL_IF(push_inst(compiler, data_transfer_insts[BYTE_DATA] | S(mem) | T(TMP_REG2) | MEM16_IMM_FIRST(memw), MOVABLE_INS)); + return push_inst(compiler, data_transfer_insts[BYTE_DATA] | S(mem) | T(reg) | MEM16_IMM_SECOND(memw), MOVABLE_INS); + } + + flags = BYTE_DATA | LOAD_DATA; + + if (op == SLJIT_MOV_S16) + flags |= SIGNED_DATA; + + FAIL_IF(push_inst(compiler, data_transfer_insts[flags] | S(mem) | T(TMP_REG2) | MEM16_IMM_FIRST(memw), DR(TMP_REG2))); + FAIL_IF(push_inst(compiler, data_transfer_insts[BYTE_DATA | LOAD_DATA] | S(mem) | T(reg) | MEM16_IMM_SECOND(memw), DR(reg))); + FAIL_IF(push_inst(compiler, SLL_W | T(TMP_REG2) | D(TMP_REG2) | SH_IMM(8), DR(TMP_REG2))); + return push_inst(compiler, OR | S(reg) | T(TMP_REG2) | D(reg), DR(reg)); + + case SLJIT_MOV: + case SLJIT_MOV_P: +#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) + if (type & SLJIT_MEM_UNALIGNED_32) { + flags = WORD_DATA; + if (!(type & SLJIT_MEM_STORE)) + flags |= LOAD_DATA; + + return emit_op_mem(compiler, flags, DR(reg), mem, memw); + } +#else /* !SLJIT_CONFIG_MIPS_32 */ + FAIL_IF(update_mem_addr(compiler, &mem, &memw, SIMM_MAX - 7)); + SLJIT_ASSERT(FAST_IS_REG(mem) && mem != TMP_REG2); + + if (type & SLJIT_MEM_STORE) { + FAIL_IF(push_inst(compiler, SDL | S(mem) | T(reg) | IMM(memw), MOVABLE_INS)); + return push_inst(compiler, SDR | S(mem) | T(reg) | IMM(memw + 7), MOVABLE_INS); + } + + if (mem == reg) { + FAIL_IF(push_inst(compiler, ADDU_W | S(mem) | TA(0) | D(TMP_REG1), DR(TMP_REG1))); + mem = TMP_REG1; + } + + FAIL_IF(push_inst(compiler, LDL | S(mem) | T(reg) | IMM(memw), DR(reg))); + return push_inst(compiler, LDR | S(mem) | T(reg) | IMM(memw + 7), DR(reg)); +#endif /* SLJIT_CONFIG_MIPS_32 */ + } + + FAIL_IF(update_mem_addr(compiler, &mem, &memw, SIMM_MAX - 3)); + SLJIT_ASSERT(FAST_IS_REG(mem) && mem != TMP_REG2); + + if (type & SLJIT_MEM_STORE) { + FAIL_IF(push_inst(compiler, SWL | S(mem) | T(reg) | IMM(memw), MOVABLE_INS)); + return push_inst(compiler, SWR | S(mem) | T(reg) | IMM(memw + 3), MOVABLE_INS); + } + + if (mem == reg) { + FAIL_IF(push_inst(compiler, ADDU_W | S(mem) | TA(0) | D(TMP_REG1), DR(TMP_REG1))); + mem = TMP_REG1; + } + + FAIL_IF(push_inst(compiler, LWL | S(mem) | T(reg) | IMM(memw), DR(reg))); +#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) + return push_inst(compiler, LWR | S(mem) | T(reg) | IMM(memw + 3), DR(reg)); +#else /* !SLJIT_CONFIG_MIPS_32 */ + FAIL_IF(push_inst(compiler, LWR | S(mem) | T(reg) | IMM(memw + 3), DR(reg))); + + if (op != SLJIT_MOV_U32) + return SLJIT_SUCCESS; + +#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 2) + return push_inst(compiler, DINSU | T(reg) | SA(0) | (31 << 11) | (0 << 11), DR(reg)); +#else /* SLJIT_MIPS_REV < 1 */ + FAIL_IF(push_inst(compiler, DSLL32 | T(reg) | D(reg) | SH_IMM(0), DR(reg))); + return push_inst(compiler, DSRL32 | T(reg) | D(reg) | SH_IMM(0), DR(reg)); +#endif /* SLJIT_MIPS_REV >= 2 */ +#endif /* SLJIT_CONFIG_MIPS_32 */ +#endif /* SLJIT_MIPS_REV >= 6 */ +} + +#if !(defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6) + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fmem(struct sljit_compiler *compiler, sljit_s32 type, + sljit_s32 freg, + sljit_s32 mem, sljit_sw memw) +{ + CHECK_ERROR(); + CHECK(check_sljit_emit_fmem(compiler, type, freg, mem, memw)); + + FAIL_IF(update_mem_addr(compiler, &mem, &memw, SIMM_MAX - (type & SLJIT_32) ? 3 : 7)); + SLJIT_ASSERT(FAST_IS_REG(mem) && mem != TMP_REG2); + + if (type & SLJIT_MEM_STORE) { + if (type & SLJIT_32) { + FAIL_IF(push_inst(compiler, MFC1 | T(TMP_REG2) | FS(freg), DR(TMP_REG2))); +#if (!defined SLJIT_MIPS_REV || SLJIT_MIPS_REV <= 3) + FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS)); +#endif + FAIL_IF(push_inst(compiler, SWL | S(mem) | T(TMP_REG2) | IMM(memw), MOVABLE_INS)); + return push_inst(compiler, SWR | S(mem) | T(TMP_REG2) | IMM(memw + 3), MOVABLE_INS); + } + +#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) + FAIL_IF(push_inst(compiler, MFC1 | T(TMP_REG2) | MEMF64_FS_FIRST(freg), DR(TMP_REG2))); +#if (!defined SLJIT_MIPS_REV || SLJIT_MIPS_REV <= 3) + FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS)); +#endif + FAIL_IF(push_inst(compiler, SWL | S(mem) | T(TMP_REG2) | IMM(memw), MOVABLE_INS)); + FAIL_IF(push_inst(compiler, SWR | S(mem) | T(TMP_REG2) | IMM(memw + 3), MOVABLE_INS)); + + FAIL_IF(push_inst(compiler, MFC1 | T(TMP_REG2) | MEMF64_FS_SECOND(freg), DR(TMP_REG2))); +#if (!defined SLJIT_MIPS_REV || SLJIT_MIPS_REV <= 3) + FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS)); +#endif + FAIL_IF(push_inst(compiler, SWL | S(mem) | T(TMP_REG2) | IMM(memw + 4), MOVABLE_INS)); + return push_inst(compiler, SWR | S(mem) | T(TMP_REG2) | IMM(memw + 7), MOVABLE_INS); +#else /* !SLJIT_CONFIG_MIPS_32 */ + FAIL_IF(push_inst(compiler, MFC1 | (1 << 21) | T(TMP_REG2) | FS(freg), DR(TMP_REG2))); +#if (!defined SLJIT_MIPS_REV || SLJIT_MIPS_REV <= 3) + FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS)); +#endif + FAIL_IF(push_inst(compiler, SDL | S(mem) | T(TMP_REG2) | IMM(memw), MOVABLE_INS)); + return push_inst(compiler, SDR | S(mem) | T(TMP_REG2) | IMM(memw + 7), MOVABLE_INS); +#endif /* SLJIT_CONFIG_MIPS_32 */ + } + + if (type & SLJIT_32) { + FAIL_IF(push_inst(compiler, LWL | S(mem) | T(TMP_REG2) | IMM(memw), DR(TMP_REG2))); + FAIL_IF(push_inst(compiler, LWR | S(mem) | T(TMP_REG2) | IMM(memw + 3), DR(TMP_REG2))); + + FAIL_IF(push_inst(compiler, MTC1 | T(TMP_REG2) | FS(freg), MOVABLE_INS)); +#if (!defined SLJIT_MIPS_REV || SLJIT_MIPS_REV <= 3) + FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS)); +#endif + return SLJIT_SUCCESS; + } + +#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) + FAIL_IF(push_inst(compiler, LWL | S(mem) | T(TMP_REG2) | IMM(memw), DR(TMP_REG2))); + FAIL_IF(push_inst(compiler, LWR | S(mem) | T(TMP_REG2) | IMM(memw + 3), DR(TMP_REG2))); + FAIL_IF(push_inst(compiler, MTC1 | T(TMP_REG2) | MEMF64_FS_FIRST(freg), MOVABLE_INS)); + + FAIL_IF(push_inst(compiler, LWL | S(mem) | T(TMP_REG2) | IMM(memw + 4), DR(TMP_REG2))); + FAIL_IF(push_inst(compiler, LWR | S(mem) | T(TMP_REG2) | IMM(memw + 7), DR(TMP_REG2))); + FAIL_IF(push_inst(compiler, MTC1 | T(TMP_REG2) | MEMF64_FS_SECOND(freg), MOVABLE_INS)); +#if (!defined SLJIT_MIPS_REV || SLJIT_MIPS_REV <= 3) + FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS)); +#endif +#else /* !SLJIT_CONFIG_MIPS_32 */ + FAIL_IF(push_inst(compiler, LDL | S(mem) | T(TMP_REG2) | IMM(memw), DR(TMP_REG2))); + FAIL_IF(push_inst(compiler, LDR | S(mem) | T(TMP_REG2) | IMM(memw + 7), DR(TMP_REG2))); + + FAIL_IF(push_inst(compiler, MTC1 | (1 << 21) | T(TMP_REG2) | FS(freg), MOVABLE_INS)); +#if (!defined SLJIT_MIPS_REV || SLJIT_MIPS_REV <= 3) + FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS)); +#endif +#endif /* SLJIT_CONFIG_MIPS_32 */ + return SLJIT_SUCCESS; +} + +#endif /* !SLJIT_MIPS_REV || SLJIT_MIPS_REV < 6 */ + +#undef MEM16_IMM_FIRST +#undef MEM16_IMM_SECOND +#undef MEMF64_FS_FIRST +#undef MEMF64_FS_SECOND +#undef MEM_CHECK_UNALIGNED + +#undef TO_ARGW_HI + SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw init_value) { struct sljit_const *const_; @@ -2477,7 +3687,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compi PTR_FAIL_IF(emit_const(compiler, dst_r, init_value)); if (dst & SLJIT_MEM) - PTR_FAIL_IF(emit_op(compiler, SLJIT_MOV, WORD_DATA, dst, dstw, TMP_REG1, 0, TMP_REG2, 0)); + PTR_FAIL_IF(emit_op_mem(compiler, WORD_DATA, DR(TMP_REG2), dst, dstw)); return const_; } @@ -2496,15 +3706,15 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_put_label* sljit_emit_put_label(struct slj set_put_label(put_label, compiler, 0); dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2; -#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) - PTR_FAIL_IF(emit_const(compiler, dst_r, 0)); -#else PTR_FAIL_IF(push_inst(compiler, (sljit_ins)dst_r, UNMOVABLE_INS)); +#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) + compiler->size += 1; +#else compiler->size += 5; #endif if (dst & SLJIT_MEM) - PTR_FAIL_IF(emit_op(compiler, SLJIT_MOV, WORD_DATA, dst, dstw, TMP_REG1, 0, TMP_REG2, 0)); + PTR_FAIL_IF(emit_op_mem(compiler, WORD_DATA, DR(TMP_REG2), dst, dstw)); return put_label; } diff --git a/src/3rdparty/pcre2/src/sljit/sljitNativePPC_32.c b/src/3rdparty/pcre2/src/sljit/sljitNativePPC_32.c index 95fe6bbe0ec..9449e4b9d76 100644 --- a/src/3rdparty/pcre2/src/sljit/sljitNativePPC_32.c +++ b/src/3rdparty/pcre2/src/sljit/sljitNativePPC_32.c @@ -38,12 +38,15 @@ static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 reg, return (imm & 0xffff) ? push_inst(compiler, ORI | S(reg) | A(reg) | IMM(imm)) : SLJIT_SUCCESS; } +/* Simplified mnemonics: clrlwi. */ #define INS_CLEAR_LEFT(dst, src, from) \ - (RLWINM | S(src) | A(dst) | ((from) << 6) | (31 << 1)) + (RLWINM | S(src) | A(dst) | RLWI_MBE(from, 31)) static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 flags, sljit_s32 dst, sljit_s32 src1, sljit_s32 src2) { + sljit_u32 imm; + switch (op) { case SLJIT_MOV: case SLJIT_MOV_U32: @@ -90,6 +93,16 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl SLJIT_ASSERT(src1 == TMP_REG1); return push_inst(compiler, CNTLZW | S(src2) | A(dst)); + case SLJIT_CTZ: + SLJIT_ASSERT(src1 == TMP_REG1); + FAIL_IF(push_inst(compiler, NEG | D(TMP_REG1) | A(src2))); + FAIL_IF(push_inst(compiler, AND | S(src2) | A(dst) | B(TMP_REG1))); + FAIL_IF(push_inst(compiler, CNTLZW | S(dst) | A(dst))); + FAIL_IF(push_inst(compiler, ADDI | D(TMP_REG1) | A(dst) | IMM(-32))); + /* The highest bits are set, if dst < 32, zero otherwise. */ + FAIL_IF(push_inst(compiler, SRWI(27) | S(TMP_REG1) | A(TMP_REG1))); + return push_inst(compiler, XOR | S(dst) | A(dst) | B(TMP_REG1)); + case SLJIT_ADD: if (flags & ALT_FORM1) { /* Setting XER SO is not enough, CR SO is also needed. */ @@ -103,12 +116,14 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl if (flags & ALT_FORM3) return push_inst(compiler, ADDIS | D(dst) | A(src1) | compiler->imm); + imm = compiler->imm; + if (flags & ALT_FORM4) { - FAIL_IF(push_inst(compiler, ADDIS | D(dst) | A(src1) | (((compiler->imm >> 16) & 0xffff) + ((compiler->imm >> 15) & 0x1)))); + FAIL_IF(push_inst(compiler, ADDIS | D(dst) | A(src1) | (((imm >> 16) & 0xffff) + ((imm >> 15) & 0x1)))); src1 = dst; } - return push_inst(compiler, ADDI | D(dst) | A(src1) | (compiler->imm & 0xffff)); + return push_inst(compiler, ADDI | D(dst) | A(src1) | (imm & 0xffff)); } if (flags & ALT_FORM3) { SLJIT_ASSERT(src2 == TMP_REG2); @@ -208,8 +223,10 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl } if (flags & ALT_FORM3) { SLJIT_ASSERT(src2 == TMP_REG2); - FAIL_IF(push_inst(compiler, ORI | S(src1) | A(dst) | IMM(compiler->imm))); - return push_inst(compiler, ORIS | S(dst) | A(dst) | IMM(compiler->imm >> 16)); + imm = compiler->imm; + + FAIL_IF(push_inst(compiler, ORI | S(src1) | A(dst) | IMM(imm))); + return push_inst(compiler, ORIS | S(dst) | A(dst) | IMM(imm >> 16)); } return push_inst(compiler, OR | RC(flags) | S(src1) | A(dst) | B(src2)); @@ -224,34 +241,78 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl } if (flags & ALT_FORM3) { SLJIT_ASSERT(src2 == TMP_REG2); - FAIL_IF(push_inst(compiler, XORI | S(src1) | A(dst) | IMM(compiler->imm))); - return push_inst(compiler, XORIS | S(dst) | A(dst) | IMM(compiler->imm >> 16)); + imm = compiler->imm; + + FAIL_IF(push_inst(compiler, XORI | S(src1) | A(dst) | IMM(imm))); + return push_inst(compiler, XORIS | S(dst) | A(dst) | IMM(imm >> 16)); } return push_inst(compiler, XOR | RC(flags) | S(src1) | A(dst) | B(src2)); case SLJIT_SHL: + case SLJIT_MSHL: if (flags & ALT_FORM1) { SLJIT_ASSERT(src2 == TMP_REG2); - compiler->imm &= 0x1f; - return push_inst(compiler, RLWINM | RC(flags) | S(src1) | A(dst) | (compiler->imm << 11) | ((31 - compiler->imm) << 1)); + imm = compiler->imm & 0x1f; + return push_inst(compiler, SLWI(imm) | RC(flags) | S(src1) | A(dst)); } + + if (op == SLJIT_MSHL) { + FAIL_IF(push_inst(compiler, ANDI | S(src2) | A(TMP_REG2) | 0x1f)); + src2 = TMP_REG2; + } + return push_inst(compiler, SLW | RC(flags) | S(src1) | A(dst) | B(src2)); case SLJIT_LSHR: + case SLJIT_MLSHR: if (flags & ALT_FORM1) { SLJIT_ASSERT(src2 == TMP_REG2); - compiler->imm &= 0x1f; - return push_inst(compiler, RLWINM | RC(flags) | S(src1) | A(dst) | (((32 - compiler->imm) & 0x1f) << 11) | (compiler->imm << 6) | (31 << 1)); + imm = compiler->imm & 0x1f; + /* Since imm can be 0, SRWI() cannot be used. */ + return push_inst(compiler, RLWINM | RC(flags) | S(src1) | A(dst) | RLWI_SH((32 - imm) & 0x1f) | RLWI_MBE(imm, 31)); } + + if (op == SLJIT_MLSHR) { + FAIL_IF(push_inst(compiler, ANDI | S(src2) | A(TMP_REG2) | 0x1f)); + src2 = TMP_REG2; + } + return push_inst(compiler, SRW | RC(flags) | S(src1) | A(dst) | B(src2)); case SLJIT_ASHR: + case SLJIT_MASHR: if (flags & ALT_FORM1) { SLJIT_ASSERT(src2 == TMP_REG2); - compiler->imm &= 0x1f; - return push_inst(compiler, SRAWI | RC(flags) | S(src1) | A(dst) | (compiler->imm << 11)); + imm = compiler->imm & 0x1f; + return push_inst(compiler, SRAWI | RC(flags) | S(src1) | A(dst) | (imm << 11)); } + + if (op == SLJIT_MASHR) { + FAIL_IF(push_inst(compiler, ANDI | S(src2) | A(TMP_REG2) | 0x1f)); + src2 = TMP_REG2; + } + return push_inst(compiler, SRAW | RC(flags) | S(src1) | A(dst) | B(src2)); + + case SLJIT_ROTL: + case SLJIT_ROTR: + if (flags & ALT_FORM1) { + SLJIT_ASSERT(src2 == TMP_REG2); + imm = compiler->imm; + + if (op == SLJIT_ROTR) + imm = (sljit_u32)(-(sljit_s32)imm); + + imm &= 0x1f; + return push_inst(compiler, RLWINM | S(src1) | A(dst) | RLWI_SH(imm) | RLWI_MBE(0, 31)); + } + + if (op == SLJIT_ROTR) { + FAIL_IF(push_inst(compiler, SUBFIC | D(TMP_REG2) | A(src2) | 0)); + src2 = TMP_REG2; + } + + return push_inst(compiler, RLWNM | S(src1) | A(dst) | B(src2) | RLWI_MBE(0, 31)); } SLJIT_UNREACHABLE(); @@ -277,8 +338,3 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_ta inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset); SLJIT_CACHE_FLUSH(inst, inst + 2); } - -SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant, sljit_sw executable_offset) -{ - sljit_set_jump_addr(addr, (sljit_uw)new_constant, executable_offset); -} diff --git a/src/3rdparty/pcre2/src/sljit/sljitNativePPC_64.c b/src/3rdparty/pcre2/src/sljit/sljitNativePPC_64.c index d104f6d75ff..80549108bfb 100644 --- a/src/3rdparty/pcre2/src/sljit/sljitNativePPC_64.c +++ b/src/3rdparty/pcre2/src/sljit/sljitNativePPC_64.c @@ -35,8 +35,9 @@ #error "Must implement count leading zeroes" #endif -#define PUSH_RLDICR(reg, shift) \ - push_inst(compiler, RLDI(reg, reg, 63 - shift, shift, 1)) +/* Computes SLDI(63 - shift). */ +#define PUSH_SLDI_NEG(reg, shift) \ + push_inst(compiler, RLDICR | S(reg) | A(reg) | RLDI_SH(63 - shift) | RLDI_ME(shift)) static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 reg, sljit_sw imm) { @@ -66,14 +67,14 @@ static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 reg, if ((tmp & ~0xffff000000000000ul) == 0) { FAIL_IF(push_inst(compiler, ADDI | D(reg) | A(0) | (sljit_ins)(tmp >> 48))); shift += 15; - return PUSH_RLDICR(reg, shift); + return PUSH_SLDI_NEG(reg, shift); } if ((tmp & ~0xffffffff00000000ul) == 0) { FAIL_IF(push_inst(compiler, ADDIS | D(reg) | A(0) | (sljit_ins)(tmp >> 48))); FAIL_IF(push_inst(compiler, ORI | S(reg) | A(reg) | IMM(tmp >> 32))); shift += 31; - return PUSH_RLDICR(reg, shift); + return PUSH_SLDI_NEG(reg, shift); } /* Cut out the 16 bit from immediate. */ @@ -82,13 +83,13 @@ static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 reg, if (tmp2 <= 0xffff) { FAIL_IF(push_inst(compiler, ADDI | D(reg) | A(0) | (sljit_ins)(tmp >> 48))); - FAIL_IF(PUSH_RLDICR(reg, shift)); + FAIL_IF(PUSH_SLDI_NEG(reg, shift)); return push_inst(compiler, ORI | S(reg) | A(reg) | (sljit_ins)tmp2); } if (tmp2 <= 0xffffffff) { FAIL_IF(push_inst(compiler, ADDI | D(reg) | A(0) | IMM(tmp >> 48))); - FAIL_IF(PUSH_RLDICR(reg, shift)); + FAIL_IF(PUSH_SLDI_NEG(reg, shift)); FAIL_IF(push_inst(compiler, ORIS | S(reg) | A(reg) | (sljit_ins)(tmp2 >> 16))); return (imm & 0xffff) ? push_inst(compiler, ORI | S(reg) | A(reg) | IMM(tmp2)) : SLJIT_SUCCESS; } @@ -100,22 +101,23 @@ static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 reg, FAIL_IF(push_inst(compiler, ADDI | D(reg) | A(0) | (sljit_ins)(tmp >> 48))); shift2 += 15; shift += (63 - shift2); - FAIL_IF(PUSH_RLDICR(reg, shift)); + FAIL_IF(PUSH_SLDI_NEG(reg, shift)); FAIL_IF(push_inst(compiler, ORI | S(reg) | A(reg) | (sljit_ins)(tmp2 >> 48))); - return PUSH_RLDICR(reg, shift2); + return PUSH_SLDI_NEG(reg, shift2); } /* The general version. */ FAIL_IF(push_inst(compiler, ADDIS | D(reg) | A(0) | (sljit_ins)((sljit_uw)imm >> 48))); FAIL_IF(push_inst(compiler, ORI | S(reg) | A(reg) | IMM(imm >> 32))); - FAIL_IF(PUSH_RLDICR(reg, 31)); + FAIL_IF(PUSH_SLDI_NEG(reg, 31)); FAIL_IF(push_inst(compiler, ORIS | S(reg) | A(reg) | IMM(imm >> 16))); return push_inst(compiler, ORI | S(reg) | A(reg) | IMM(imm)); } -/* Simplified mnemonics: clrldi. */ -#define INS_CLEAR_LEFT(dst, src, from) \ - (RLDICL | S(src) | A(dst) | ((from) << 6) | (1 << 5)) +#undef PUSH_SLDI_NEG + +#define CLRLDI(dst, src, n) \ + (RLDICL | S(src) | A(dst) | RLDI_SH(0) | RLDI_MB(n)) /* Sign extension for integer operations. */ #define UN_EXTS() \ @@ -145,6 +147,8 @@ static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 reg, static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 flags, sljit_s32 dst, sljit_s32 src1, sljit_s32 src2) { + sljit_u32 imm; + switch (op) { case SLJIT_MOV: case SLJIT_MOV_P: @@ -159,7 +163,7 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) { if (op == SLJIT_MOV_S32) return push_inst(compiler, EXTSW | S(src2) | A(dst)); - return push_inst(compiler, INS_CLEAR_LEFT(dst, src2, 0)); + return push_inst(compiler, CLRLDI(dst, src2, 32)); } else { SLJIT_ASSERT(dst == src2); @@ -172,7 +176,7 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) { if (op == SLJIT_MOV_S8) return push_inst(compiler, EXTSB | S(src2) | A(dst)); - return push_inst(compiler, INS_CLEAR_LEFT(dst, src2, 24)); + return push_inst(compiler, CLRLDI(dst, src2, 56)); } else if ((flags & REG_DEST) && op == SLJIT_MOV_S8) return push_inst(compiler, EXTSB | S(src2) | A(dst)); @@ -187,7 +191,7 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) { if (op == SLJIT_MOV_S16) return push_inst(compiler, EXTSH | S(src2) | A(dst)); - return push_inst(compiler, INS_CLEAR_LEFT(dst, src2, 16)); + return push_inst(compiler, CLRLDI(dst, src2, 48)); } else { SLJIT_ASSERT(dst == src2); @@ -201,22 +205,30 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl case SLJIT_CLZ: SLJIT_ASSERT(src1 == TMP_REG1); - if (flags & ALT_FORM1) - return push_inst(compiler, CNTLZW | S(src2) | A(dst)); - return push_inst(compiler, CNTLZD | S(src2) | A(dst)); + return push_inst(compiler, ((flags & ALT_FORM1) ? CNTLZW : CNTLZD) | S(src2) | A(dst)); + + case SLJIT_CTZ: + SLJIT_ASSERT(src1 == TMP_REG1); + FAIL_IF(push_inst(compiler, NEG | D(TMP_REG1) | A(src2))); + FAIL_IF(push_inst(compiler, AND | S(src2) | A(dst) | B(TMP_REG1))); + FAIL_IF(push_inst(compiler, ((flags & ALT_FORM1) ? CNTLZW : CNTLZD) | S(dst) | A(dst))); + FAIL_IF(push_inst(compiler, ADDI | D(TMP_REG1) | A(dst) | IMM((flags & ALT_FORM1) ? -32 : -64))); + /* The highest bits are set, if dst < bit width, zero otherwise. */ + FAIL_IF(push_inst(compiler, ((flags & ALT_FORM1) ? SRWI(27) : SRDI(58)) | S(TMP_REG1) | A(TMP_REG1))); + return push_inst(compiler, XOR | S(dst) | A(dst) | B(TMP_REG1)); case SLJIT_ADD: if (flags & ALT_FORM1) { if (flags & ALT_SIGN_EXT) { - FAIL_IF(push_inst(compiler, RLDI(TMP_REG1, src1, 32, 31, 1))); + FAIL_IF(push_inst(compiler, SLDI(32) | S(src1) | A(TMP_REG1))); src1 = TMP_REG1; - FAIL_IF(push_inst(compiler, RLDI(TMP_REG2, src2, 32, 31, 1))); + FAIL_IF(push_inst(compiler, SLDI(32) | S(src2) | A(TMP_REG2))); src2 = TMP_REG2; } /* Setting XER SO is not enough, CR SO is also needed. */ FAIL_IF(push_inst(compiler, ADD | OE(ALT_SET_FLAGS) | RC(ALT_SET_FLAGS) | D(dst) | A(src1) | B(src2))); if (flags & ALT_SIGN_EXT) - return push_inst(compiler, RLDI(dst, dst, 32, 32, 0)); + return push_inst(compiler, SRDI(32) | S(dst) | A(dst)); return SLJIT_SUCCESS; } @@ -227,12 +239,14 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl if (flags & ALT_FORM3) return push_inst(compiler, ADDIS | D(dst) | A(src1) | compiler->imm); + imm = compiler->imm; + if (flags & ALT_FORM4) { - FAIL_IF(push_inst(compiler, ADDIS | D(dst) | A(src1) | (((compiler->imm >> 16) & 0xffff) + ((compiler->imm >> 15) & 0x1)))); + FAIL_IF(push_inst(compiler, ADDIS | D(dst) | A(src1) | (((imm >> 16) & 0xffff) + ((imm >> 15) & 0x1)))); src1 = dst; } - return push_inst(compiler, ADDI | D(dst) | A(src1) | (compiler->imm & 0xffff)); + return push_inst(compiler, ADDI | D(dst) | A(src1) | (imm & 0xffff)); } if (flags & ALT_FORM3) { SLJIT_ASSERT(src2 == TMP_REG2); @@ -287,11 +301,11 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl if (flags & ALT_FORM3) { if (flags & ALT_SIGN_EXT) { if (src1 != TMP_ZERO) { - FAIL_IF(push_inst(compiler, RLDI(TMP_REG1, src1, 32, 31, 1))); + FAIL_IF(push_inst(compiler, SLDI(32) | S(src1) | A(TMP_REG1))); src1 = TMP_REG1; } if (src2 != TMP_ZERO) { - FAIL_IF(push_inst(compiler, RLDI(TMP_REG2, src2, 32, 31, 1))); + FAIL_IF(push_inst(compiler, SLDI(32) | S(src2) | A(TMP_REG2))); src2 = TMP_REG2; } } @@ -303,7 +317,7 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl FAIL_IF(push_inst(compiler, NEG | OE(ALT_SET_FLAGS) | RC(ALT_SET_FLAGS) | D(dst) | A(src2))); if (flags & ALT_SIGN_EXT) - return push_inst(compiler, RLDI(dst, dst, 32, 32, 0)); + return push_inst(compiler, SRDI(32) | S(dst) | A(dst)); return SLJIT_SUCCESS; } @@ -362,8 +376,10 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl } if (flags & ALT_FORM3) { SLJIT_ASSERT(src2 == TMP_REG2); - FAIL_IF(push_inst(compiler, ORI | S(src1) | A(dst) | IMM(compiler->imm))); - return push_inst(compiler, ORIS | S(dst) | A(dst) | IMM(compiler->imm >> 16)); + imm = compiler->imm; + + FAIL_IF(push_inst(compiler, ORI | S(src1) | A(dst) | IMM(imm))); + return push_inst(compiler, ORIS | S(dst) | A(dst) | IMM(imm >> 16)); } return push_inst(compiler, OR | RC(flags) | S(src1) | A(dst) | B(src2)); @@ -378,46 +394,105 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl } if (flags & ALT_FORM3) { SLJIT_ASSERT(src2 == TMP_REG2); - FAIL_IF(push_inst(compiler, XORI | S(src1) | A(dst) | IMM(compiler->imm))); - return push_inst(compiler, XORIS | S(dst) | A(dst) | IMM(compiler->imm >> 16)); + imm = compiler->imm; + + FAIL_IF(push_inst(compiler, XORI | S(src1) | A(dst) | IMM(imm))); + return push_inst(compiler, XORIS | S(dst) | A(dst) | IMM(imm >> 16)); } return push_inst(compiler, XOR | RC(flags) | S(src1) | A(dst) | B(src2)); case SLJIT_SHL: + case SLJIT_MSHL: if (flags & ALT_FORM1) { SLJIT_ASSERT(src2 == TMP_REG2); + imm = compiler->imm; + if (flags & ALT_FORM2) { - compiler->imm &= 0x1f; - return push_inst(compiler, RLWINM | RC(flags) | S(src1) | A(dst) | (compiler->imm << 11) | ((31 - compiler->imm) << 1)); + imm &= 0x1f; + return push_inst(compiler, SLWI(imm) | RC(flags) | S(src1) | A(dst)); } - compiler->imm &= 0x3f; - return push_inst(compiler, RLDI(dst, src1, compiler->imm, 63 - compiler->imm, 1) | RC(flags)); + + imm &= 0x3f; + return push_inst(compiler, SLDI(imm) | RC(flags) | S(src1) | A(dst)); } + + if (op == SLJIT_MSHL) { + FAIL_IF(push_inst(compiler, ANDI | S(src2) | A(TMP_REG2) | ((flags & ALT_FORM2) ? 0x1f : 0x3f))); + src2 = TMP_REG2; + } + return push_inst(compiler, ((flags & ALT_FORM2) ? SLW : SLD) | RC(flags) | S(src1) | A(dst) | B(src2)); case SLJIT_LSHR: + case SLJIT_MLSHR: if (flags & ALT_FORM1) { SLJIT_ASSERT(src2 == TMP_REG2); + imm = compiler->imm; + if (flags & ALT_FORM2) { - compiler->imm &= 0x1f; - return push_inst(compiler, RLWINM | RC(flags) | S(src1) | A(dst) | (((32 - compiler->imm) & 0x1f) << 11) | (compiler->imm << 6) | (31 << 1)); + imm &= 0x1f; + /* Since imm can be 0, SRWI() cannot be used. */ + return push_inst(compiler, RLWINM | RC(flags) | S(src1) | A(dst) | RLWI_SH((32 - imm) & 0x1f) | RLWI_MBE(imm, 31)); } - compiler->imm &= 0x3f; - return push_inst(compiler, RLDI(dst, src1, 64 - compiler->imm, compiler->imm, 0) | RC(flags)); + + imm &= 0x3f; + /* Since imm can be 0, SRDI() cannot be used. */ + return push_inst(compiler, RLDICL | RC(flags) | S(src1) | A(dst) | RLDI_SH((64 - imm) & 0x3f) | RLDI_MB(imm)); } + + if (op == SLJIT_MLSHR) { + FAIL_IF(push_inst(compiler, ANDI | S(src2) | A(TMP_REG2) | ((flags & ALT_FORM2) ? 0x1f : 0x3f))); + src2 = TMP_REG2; + } + return push_inst(compiler, ((flags & ALT_FORM2) ? SRW : SRD) | RC(flags) | S(src1) | A(dst) | B(src2)); case SLJIT_ASHR: + case SLJIT_MASHR: if (flags & ALT_FORM1) { SLJIT_ASSERT(src2 == TMP_REG2); + imm = compiler->imm; + if (flags & ALT_FORM2) { - compiler->imm &= 0x1f; - return push_inst(compiler, SRAWI | RC(flags) | S(src1) | A(dst) | (compiler->imm << 11)); + imm &= 0x1f; + return push_inst(compiler, SRAWI | RC(flags) | S(src1) | A(dst) | (imm << 11)); } - compiler->imm &= 0x3f; - return push_inst(compiler, SRADI | RC(flags) | S(src1) | A(dst) | ((compiler->imm & 0x1f) << 11) | ((compiler->imm & 0x20) >> 4)); + + imm &= 0x3f; + return push_inst(compiler, SRADI | RC(flags) | S(src1) | A(dst) | RLDI_SH(imm)); } + + if (op == SLJIT_MASHR) { + FAIL_IF(push_inst(compiler, ANDI | S(src2) | A(TMP_REG2) | ((flags & ALT_FORM2) ? 0x1f : 0x3f))); + src2 = TMP_REG2; + } + return push_inst(compiler, ((flags & ALT_FORM2) ? SRAW : SRAD) | RC(flags) | S(src1) | A(dst) | B(src2)); + + case SLJIT_ROTL: + case SLJIT_ROTR: + if (flags & ALT_FORM1) { + SLJIT_ASSERT(src2 == TMP_REG2); + imm = compiler->imm; + + if (op == SLJIT_ROTR) + imm = (sljit_u32)(-(sljit_s32)imm); + + if (flags & ALT_FORM2) { + imm &= 0x1f; + return push_inst(compiler, RLWINM | S(src1) | A(dst) | RLWI_SH(imm) | RLWI_MBE(0, 31)); + } + + imm &= 0x3f; + return push_inst(compiler, RLDICL | S(src1) | A(dst) | RLDI_SH(imm)); + } + + if (op == SLJIT_ROTR) { + FAIL_IF(push_inst(compiler, SUBFIC | D(TMP_REG2) | A(src2) | 0)); + src2 = TMP_REG2; + } + + return push_inst(compiler, ((flags & ALT_FORM2) ? (RLWNM | RLWI_MBE(0, 31)) : (RLDCL | RLDI_MB(0))) | S(src1) | A(dst) | B(src2)); } SLJIT_UNREACHABLE(); @@ -483,7 +558,7 @@ static SLJIT_INLINE sljit_s32 emit_const(struct sljit_compiler *compiler, sljit_ { FAIL_IF(push_inst(compiler, ADDIS | D(reg) | A(0) | IMM(init_value >> 48))); FAIL_IF(push_inst(compiler, ORI | S(reg) | A(reg) | IMM(init_value >> 32))); - FAIL_IF(PUSH_RLDICR(reg, 31)); + FAIL_IF(push_inst(compiler, SLDI(32) | S(reg) | A(reg))); FAIL_IF(push_inst(compiler, ORIS | S(reg) | A(reg) | IMM(init_value >> 16))); return push_inst(compiler, ORI | S(reg) | A(reg) | IMM(init_value)); } @@ -502,8 +577,3 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_ta inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset); SLJIT_CACHE_FLUSH(inst, inst + 5); } - -SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant, sljit_sw executable_offset) -{ - sljit_set_jump_addr(addr, (sljit_uw)new_constant, executable_offset); -} diff --git a/src/3rdparty/pcre2/src/sljit/sljitNativePPC_common.c b/src/3rdparty/pcre2/src/sljit/sljitNativePPC_common.c index 8bfdc69522a..f387114733b 100644 --- a/src/3rdparty/pcre2/src/sljit/sljitNativePPC_common.c +++ b/src/3rdparty/pcre2/src/sljit/sljitNativePPC_common.c @@ -203,8 +203,13 @@ static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 3] = { #define OR (HI(31) | LO(444)) #define ORI (HI(24)) #define ORIS (HI(25)) -#define RLDICL (HI(30)) +#define RLDCL (HI(30) | LO(8)) +#define RLDICL (HI(30) | LO(0 << 1)) +#define RLDICR (HI(30) | LO(1 << 1)) +#define RLDIMI (HI(30) | LO(3 << 1)) +#define RLWIMI (HI(20)) #define RLWINM (HI(21)) +#define RLWNM (HI(23)) #define SLD (HI(31) | LO(27)) #define SLW (HI(31) | LO(24)) #define SRAD (HI(31) | LO(794)) @@ -233,9 +238,24 @@ static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 3] = { #define SIMM_MIN (-0x8000) #define UIMM_MAX (0xffff) -#define RLDI(dst, src, sh, mb, type) \ - (HI(30) | S(src) | A(dst) | ((sljit_ins)(type) << 2) | (((sljit_ins)(sh) & 0x1f) << 11) \ - | (((sljit_ins)(sh) & 0x20) >> 4) | (((sljit_ins)(mb) & 0x1f) << 6) | ((sljit_ins)(mb) & 0x20)) +/* Shift helpers. */ +#define RLWI_SH(sh) ((sljit_ins)(sh) << 11) +#define RLWI_MBE(mb, me) (((sljit_ins)(mb) << 6) | ((sljit_ins)(me) << 1)) +#define RLDI_SH(sh) ((((sljit_ins)(sh) & 0x1f) << 11) | (((sljit_ins)(sh) & 0x20) >> 4)) +#define RLDI_MB(mb) ((((sljit_ins)(mb) & 0x1f) << 6) | ((sljit_ins)(mb) & 0x20)) +#define RLDI_ME(me) RLDI_MB(me) + +#define SLWI(shift) (RLWINM | RLWI_SH(shift) | RLWI_MBE(0, 31 - (shift))) +#define SLDI(shift) (RLDICR | RLDI_SH(shift) | RLDI_ME(63 - (shift))) +/* shift > 0 */ +#define SRWI(shift) (RLWINM | RLWI_SH(32 - (shift)) | RLWI_MBE((shift), 31)) +#define SRDI(shift) (RLDICL | RLDI_SH(64 - (shift)) | RLDI_MB(shift)) + +#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) +#define SLWI_W(shift) SLWI(shift) +#else /* !SLJIT_CONFIG_PPC_32 */ +#define SLWI_W(shift) SLDI(shift) +#endif /* SLJIT_CONFIG_PPC_32 */ #if (defined SLJIT_INDIRECT_CALL && SLJIT_INDIRECT_CALL) SLJIT_API_FUNC_ATTRIBUTE void sljit_set_function_context(void** func_ptr, struct sljit_function_context* context, sljit_uw addr, void* func) @@ -368,10 +388,10 @@ static SLJIT_INLINE void put_label_set(struct sljit_put_label *put_label) else { inst[0] = ORIS | S(TMP_ZERO) | A(reg) | IMM(addr >> 48); inst[1] = ORI | S(reg) | A(reg) | IMM((addr >> 32) & 0xffff); - inst ++; + inst++; } - inst[1] = RLDI(reg, reg, 32, 31, 1); + inst[1] = SLDI(32) | S(reg) | A(reg); inst[2] = ORIS | S(reg) | A(reg) | IMM((addr >> 16) & 0xffff); inst += 2; } @@ -379,7 +399,7 @@ static SLJIT_INLINE void put_label_set(struct sljit_put_label *put_label) inst[1] = ORI | S(reg) | A(reg) | IMM(addr & 0xffff); } -#endif +#endif /* SLJIT_CONFIG_PPC_64 */ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compiler) { @@ -497,8 +517,8 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil } next_addr = compute_next_addr(label, jump, const_, put_label); } - code_ptr ++; - word_count ++; + code_ptr++; + word_count++; } while (buf_ptr < buf_end); buf = buf->next; @@ -641,14 +661,23 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type) /* A saved register is set to a zero value. */ case SLJIT_HAS_ZERO_REGISTER: case SLJIT_HAS_CLZ: + case SLJIT_HAS_ROT: case SLJIT_HAS_PREFETCH: return 1; + case SLJIT_HAS_CTZ: + return 2; + default: return 0; } } +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_cmp_info(sljit_s32 type) +{ + return (type >= SLJIT_UNORDERED && type <= SLJIT_ORDERED_LESS_EQUAL); +} + /* --------------------------------------------------------------------- */ /* Entry, exit */ /* --------------------------------------------------------------------- */ @@ -715,13 +744,16 @@ ALT_FORM5 0x010000 */ #define STACK_MAX_DISTANCE (0x8000 - SSIZE_OF(sw) - LR_SAVE_OFFSET) +static sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit_s32 inp_flags, sljit_s32 reg, + sljit_s32 arg, sljit_sw argw, sljit_s32 tmp_reg); + SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compiler, sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds, sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size) { sljit_s32 i, tmp, base, offset; sljit_s32 word_arg_count = 0; - sljit_s32 saved_arg_count = 0; + sljit_s32 saved_arg_count = SLJIT_KEPT_SAVEDS_COUNT(options); #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) sljit_s32 arg_count = 0; #endif @@ -730,8 +762,12 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi CHECK(check_sljit_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size)); set_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size); - local_size += GET_SAVED_REGISTERS_SIZE(scratches, saveds, 1) + local_size += GET_SAVED_REGISTERS_SIZE(scratches, saveds - saved_arg_count, 0) + GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, sizeof(sljit_f64)); + + if (!(options & SLJIT_ENTER_REG_ARG)) + local_size += SSIZE_OF(sw); + local_size = (local_size + SLJIT_LOCALS_OFFSET + 15) & ~0xf; compiler->local_size = local_size; @@ -770,11 +806,13 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi FAIL_IF(push_inst(compiler, STFD | FS(i) | A(base) | IMM(offset))); } - offset -= SSIZE_OF(sw); - FAIL_IF(push_inst(compiler, STACK_STORE | S(TMP_ZERO) | A(base) | IMM(offset))); + if (!(options & SLJIT_ENTER_REG_ARG)) { + offset -= SSIZE_OF(sw); + FAIL_IF(push_inst(compiler, STACK_STORE | S(TMP_ZERO) | A(base) | IMM(offset))); + } tmp = SLJIT_S0 - saveds; - for (i = SLJIT_S0; i > tmp; i--) { + for (i = SLJIT_S0 - saved_arg_count; i > tmp; i--) { offset -= SSIZE_OF(sw); FAIL_IF(push_inst(compiler, STACK_STORE | S(i) | A(base) | IMM(offset))); } @@ -785,9 +823,14 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi } FAIL_IF(push_inst(compiler, STACK_STORE | S(0) | A(base) | IMM(local_size + LR_SAVE_OFFSET))); + + if (options & SLJIT_ENTER_REG_ARG) + return SLJIT_SUCCESS; + FAIL_IF(push_inst(compiler, ADDI | D(TMP_ZERO) | A(0) | 0)); arg_types >>= SLJIT_ARG_SHIFT; + saved_arg_count = 0; while (arg_types > 0) { if ((arg_types & SLJIT_ARG_MASK) < SLJIT_ARG_TYPE_F64) { @@ -829,14 +872,17 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *comp CHECK(check_sljit_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size)); set_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size); - local_size += GET_SAVED_REGISTERS_SIZE(scratches, saveds, 1) + local_size += GET_SAVED_REGISTERS_SIZE(scratches, saveds - SLJIT_KEPT_SAVEDS_COUNT(options), 0) + GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, sizeof(sljit_f64)); + + if (!(options & SLJIT_ENTER_REG_ARG)) + local_size += SSIZE_OF(sw); + compiler->local_size = (local_size + SLJIT_LOCALS_OFFSET + 15) & ~0xf; return SLJIT_SUCCESS; } - -static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler) +static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler, sljit_s32 is_return_to) { sljit_s32 i, tmp, base, offset; sljit_s32 local_size = compiler->local_size; @@ -854,7 +900,8 @@ static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler) } offset = local_size; - FAIL_IF(push_inst(compiler, STACK_LOAD | S(0) | A(base) | IMM(offset + LR_SAVE_OFFSET))); + if (!is_return_to) + FAIL_IF(push_inst(compiler, STACK_LOAD | S(0) | A(base) | IMM(offset + LR_SAVE_OFFSET))); tmp = SLJIT_FS0 - compiler->fsaveds; for (i = SLJIT_FS0; i > tmp; i--) { @@ -867,11 +914,13 @@ static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler) FAIL_IF(push_inst(compiler, LFD | FS(i) | A(base) | IMM(offset))); } - offset -= SSIZE_OF(sw); - FAIL_IF(push_inst(compiler, STACK_LOAD | S(TMP_ZERO) | A(base) | IMM(offset))); + if (!(compiler->options & SLJIT_ENTER_REG_ARG)) { + offset -= SSIZE_OF(sw); + FAIL_IF(push_inst(compiler, STACK_LOAD | S(TMP_ZERO) | A(base) | IMM(offset))); + } tmp = SLJIT_S0 - compiler->saveds; - for (i = SLJIT_S0; i > tmp; i--) { + for (i = SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options); i > tmp; i--) { offset -= SSIZE_OF(sw); FAIL_IF(push_inst(compiler, STACK_LOAD | S(i) | A(base) | IMM(offset))); } @@ -881,7 +930,8 @@ static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler) FAIL_IF(push_inst(compiler, STACK_LOAD | S(i) | A(base) | IMM(offset))); } - push_inst(compiler, MTLR | S(0)); + if (!is_return_to) + push_inst(compiler, MTLR | S(0)); if (local_size > 0) return push_inst(compiler, ADDI | D(SLJIT_SP) | A(base) | IMM(local_size)); @@ -890,17 +940,40 @@ static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler) return push_inst(compiler, OR | S(base) | A(SLJIT_SP) | B(base)); } +#undef STACK_STORE +#undef STACK_LOAD + SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_void(struct sljit_compiler *compiler) { CHECK_ERROR(); CHECK(check_sljit_emit_return_void(compiler)); - FAIL_IF(emit_stack_frame_release(compiler)); + FAIL_IF(emit_stack_frame_release(compiler, 0)); return push_inst(compiler, BLR); } -#undef STACK_STORE -#undef STACK_LOAD +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_to(struct sljit_compiler *compiler, + sljit_s32 src, sljit_sw srcw) +{ + CHECK_ERROR(); + CHECK(check_sljit_emit_return_to(compiler, src, srcw)); + + if (src & SLJIT_MEM) { + ADJUST_LOCAL_OFFSET(src, srcw); + FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, TMP_CALL_REG, src, srcw, TMP_CALL_REG)); + src = TMP_CALL_REG; + srcw = 0; + } else if (src >= SLJIT_FIRST_SAVED_REG && src <= (SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options))) { + FAIL_IF(push_inst(compiler, OR | S(src) | A(TMP_CALL_REG) | B(src))); + src = TMP_CALL_REG; + srcw = 0; + } + + FAIL_IF(emit_stack_frame_release(compiler, 1)); + + SLJIT_SKIP_CHECKS(compiler); + return sljit_emit_ijump(compiler, SLJIT_JUMP, src, srcw); +} /* --------------------------------------------------------------------- */ /* Operators */ @@ -1066,7 +1139,6 @@ static sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit_s32 inp_flag { sljit_ins inst; sljit_s32 offs_reg; - sljit_sw high_short; /* Should work when (arg & REG_MASK) == 0. */ SLJIT_ASSERT(A(0) == 0); @@ -1077,11 +1149,7 @@ static sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit_s32 inp_flag offs_reg = OFFS_REG(arg); if (argw != 0) { -#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) - FAIL_IF(push_inst(compiler, RLWINM | S(OFFS_REG(arg)) | A(tmp_reg) | ((sljit_ins)argw << 11) | ((31 - (sljit_ins)argw) << 1))); -#else - FAIL_IF(push_inst(compiler, RLDI(tmp_reg, OFFS_REG(arg), argw, 63 - argw, 1))); -#endif + FAIL_IF(push_inst(compiler, SLWI_W(argw) | S(OFFS_REG(arg)) | A(tmp_reg))); offs_reg = tmp_reg; } @@ -1089,7 +1157,7 @@ static sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit_s32 inp_flag #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) SLJIT_ASSERT(!(inst & INT_ALIGNED)); -#endif +#endif /* SLJIT_CONFIG_PPC_64 */ return push_inst(compiler, INST_CODE_AND_DST(inst, inp_flags, reg) | A(arg & REG_MASK) | B(offs_reg)); } @@ -1104,36 +1172,24 @@ static sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit_s32 inp_flag inst = data_transfer_insts[(inp_flags | INDEXED) & MEM_MASK]; return push_inst(compiler, INST_CODE_AND_DST(inst, inp_flags, reg) | A(arg) | B(tmp_reg)); } -#endif +#endif /* SLJIT_CONFIG_PPC_64 */ if (argw <= SIMM_MAX && argw >= SIMM_MIN) return push_inst(compiler, INST_CODE_AND_DST(inst, inp_flags, reg) | A(arg) | IMM(argw)); #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) if (argw <= 0x7fff7fffl && argw >= -0x80000000l) { -#endif - - high_short = (sljit_s32)(argw + ((argw & 0x8000) << 1)) & ~0xffff; - -#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) - SLJIT_ASSERT(high_short && high_short <= 0x7fffffffl && high_short >= -0x80000000l); -#else - SLJIT_ASSERT(high_short); -#endif - - FAIL_IF(push_inst(compiler, ADDIS | D(tmp_reg) | A(arg) | IMM(high_short >> 16))); +#endif /* SLJIT_CONFIG_PPC_64 */ + FAIL_IF(push_inst(compiler, ADDIS | D(tmp_reg) | A(arg) | IMM((argw + 0x8000) >> 16))); return push_inst(compiler, INST_CODE_AND_DST(inst, inp_flags, reg) | A(tmp_reg) | IMM(argw)); - #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) } - /* The rest is PPC-64 only. */ - FAIL_IF(load_immediate(compiler, tmp_reg, argw)); inst = data_transfer_insts[(inp_flags | INDEXED) & MEM_MASK]; return push_inst(compiler, INST_CODE_AND_DST(inst, inp_flags, reg) | A(arg) | B(tmp_reg)); -#endif +#endif /* SLJIT_CONFIG_PPC_64 */ } static sljit_s32 emit_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 input_flags, @@ -1273,11 +1329,7 @@ static sljit_s32 emit_prefetch(struct sljit_compiler *compiler, if (srcw == 0) return push_inst(compiler, DCBT | A(src & REG_MASK) | B(OFFS_REG(src))); -#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) - FAIL_IF(push_inst(compiler, RLWINM | S(OFFS_REG(src)) | A(TMP_REG1) | ((sljit_ins)srcw << 11) | ((31 - (sljit_ins)srcw) << 1))); -#else - FAIL_IF(push_inst(compiler, RLDI(TMP_REG1, OFFS_REG(src), srcw, 63 - srcw, 1))); -#endif + FAIL_IF(push_inst(compiler, SLWI_W(srcw) | S(OFFS_REG(src)) | A(TMP_REG1))); return push_inst(compiler, DCBT | A(src & REG_MASK) | B(TMP_REG1)); } @@ -1362,10 +1414,11 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile return emit_op(compiler, SLJIT_NOT, flags, dst, dstw, TMP_REG1, 0, src, srcw); case SLJIT_CLZ: + case SLJIT_CTZ: #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) - return emit_op(compiler, SLJIT_CLZ, flags | (!(op_flags & SLJIT_32) ? 0 : ALT_FORM1), dst, dstw, TMP_REG1, 0, src, srcw); + return emit_op(compiler, op, flags | (!(op_flags & SLJIT_32) ? 0 : ALT_FORM1), dst, dstw, TMP_REG1, 0, src, srcw); #else - return emit_op(compiler, SLJIT_CLZ, flags, dst, dstw, TMP_REG1, 0, src, srcw); + return emit_op(compiler, op, flags, dst, dstw, TMP_REG1, 0, src, srcw); #endif } @@ -1626,7 +1679,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compile return emit_op(compiler, GET_OPCODE(op), flags | ALT_FORM2, dst, dstw, src2, src2w, TMP_REG2, 0); } } - if (GET_OPCODE(op) != SLJIT_AND) { + if (!HAS_FLAGS(op) && GET_OPCODE(op) != SLJIT_AND) { /* Unlike or and xor, the and resets unwanted bits as well. */ if (TEST_UI_IMM(src2, src2w)) { compiler->imm = (sljit_ins)src2w; @@ -1640,8 +1693,13 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compile return emit_op(compiler, GET_OPCODE(op), flags, dst, dstw, src1, src1w, src2, src2w); case SLJIT_SHL: + case SLJIT_MSHL: case SLJIT_LSHR: + case SLJIT_MLSHR: case SLJIT_ASHR: + case SLJIT_MASHR: + case SLJIT_ROTL: + case SLJIT_ROTR: #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) if (op & SLJIT_32) flags |= ALT_FORM2; @@ -1663,10 +1721,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2u(struct sljit_compiler *compil CHECK_ERROR(); CHECK(check_sljit_emit_op2(compiler, op, 1, 0, 0, src1, src1w, src2, src2w)); -#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \ - || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) - compiler->skip_checks = 1; -#endif + SLJIT_SKIP_CHECKS(compiler); return sljit_emit_op2(compiler, op, TMP_REG2, 0, src1, src1w, src2, src2w); } @@ -1674,6 +1729,102 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2u(struct sljit_compiler *compil #undef TEST_SUB_FORM2 #undef TEST_SUB_FORM3 +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_shift_into(struct sljit_compiler *compiler, sljit_s32 op, + sljit_s32 src_dst, + sljit_s32 src1, sljit_sw src1w, + sljit_s32 src2, sljit_sw src2w) +{ + sljit_s32 is_right; +#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) + sljit_s32 inp_flags = ((op & SLJIT_32) ? INT_DATA : WORD_DATA) | LOAD_DATA; + sljit_sw bit_length = (op & SLJIT_32) ? 32 : 64; +#else /* !SLJIT_CONFIG_PPC_64 */ + sljit_s32 inp_flags = WORD_DATA | LOAD_DATA; + sljit_sw bit_length = 32; +#endif /* SLJIT_CONFIG_PPC_64 */ + + CHECK_ERROR(); + CHECK(check_sljit_emit_shift_into(compiler, op, src_dst, src1, src1w, src2, src2w)); + + is_right = (GET_OPCODE(op) == SLJIT_LSHR || GET_OPCODE(op) == SLJIT_MLSHR); + + if (src_dst == src1) { + SLJIT_SKIP_CHECKS(compiler); + return sljit_emit_op2(compiler, (is_right ? SLJIT_ROTR : SLJIT_ROTL) | (op & SLJIT_32), src_dst, 0, src_dst, 0, src2, src2w); + } + + ADJUST_LOCAL_OFFSET(src1, src1w); + ADJUST_LOCAL_OFFSET(src2, src2w); + + if (src2 & SLJIT_IMM) { + src2w &= bit_length - 1; + + if (src2w == 0) + return SLJIT_SUCCESS; + } else if (src2 & SLJIT_MEM) { + FAIL_IF(emit_op_mem(compiler, inp_flags, TMP_REG2, src2, src2w, TMP_REG2)); + src2 = TMP_REG2; + } + + if (src1 & SLJIT_MEM) { + FAIL_IF(emit_op_mem(compiler, inp_flags, TMP_REG1, src1, src1w, TMP_REG1)); + src1 = TMP_REG1; + } else if (src1 & SLJIT_IMM) { + FAIL_IF(load_immediate(compiler, TMP_REG1, src1w)); + src1 = TMP_REG1; + } + + if (src2 & SLJIT_IMM) { +#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) + if (!(op & SLJIT_32)) { + if (is_right) { + FAIL_IF(push_inst(compiler, SRDI(src2w) | S(src_dst) | A(src_dst))); + return push_inst(compiler, RLDIMI | S(src1) | A(src_dst) | RLDI_SH(64 - src2w) | RLDI_MB(0)); + } + + FAIL_IF(push_inst(compiler, SLDI(src2w) | S(src_dst) | A(src_dst))); + /* Computes SRDI(64 - src2w). */ + FAIL_IF(push_inst(compiler, RLDICL | S(src1) | A(TMP_REG1) | RLDI_SH(src2w) | RLDI_MB(64 - src2w))); + return push_inst(compiler, OR | S(src_dst) | A(src_dst) | B(TMP_REG1)); + } +#endif /* SLJIT_CONFIG_PPC_64 */ + + if (is_right) { + FAIL_IF(push_inst(compiler, SRWI(src2w) | S(src_dst) | A(src_dst))); + return push_inst(compiler, RLWIMI | S(src1) | A(src_dst) | RLWI_SH(32 - src2w) | RLWI_MBE(0, src2w - 1)); + } + + FAIL_IF(push_inst(compiler, SLWI(src2w) | S(src_dst) | A(src_dst))); + return push_inst(compiler, RLWIMI | S(src1) | A(src_dst) | RLWI_SH(src2w) | RLWI_MBE(32 - src2w, 31)); + } + +#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) + if (!(op & SLJIT_32)) { + if (GET_OPCODE(op) == SLJIT_MSHL || GET_OPCODE(op) == SLJIT_MLSHR) { + FAIL_IF(push_inst(compiler, ANDI | S(src2) | A(TMP_REG2) | 0x3f)); + src2 = TMP_REG2; + } + + FAIL_IF(push_inst(compiler, (is_right ? SRD : SLD) | S(src_dst) | A(src_dst) | B(src2))); + FAIL_IF(push_inst(compiler, (is_right ? SLDI(1) : SRDI(1)) | S(src1) | A(TMP_REG1))); + FAIL_IF(push_inst(compiler, XORI | S(src2) | A(TMP_REG2) | 0x3f)); + FAIL_IF(push_inst(compiler, (is_right ? SLD : SRD) | S(TMP_REG1) | A(TMP_REG1) | B(TMP_REG2))); + return push_inst(compiler, OR | S(src_dst) | A(src_dst) | B(TMP_REG1)); + } +#endif /* SLJIT_CONFIG_PPC_64 */ + + if (GET_OPCODE(op) == SLJIT_MSHL || GET_OPCODE(op) == SLJIT_MLSHR) { + FAIL_IF(push_inst(compiler, ANDI | S(src2) | A(TMP_REG2) | 0x1f)); + src2 = TMP_REG2; + } + + FAIL_IF(push_inst(compiler, (is_right ? SRW : SLW) | S(src_dst) | A(src_dst) | B(src2))); + FAIL_IF(push_inst(compiler, (is_right ? SLWI(1) : SRWI(1)) | S(src1) | A(TMP_REG1))); + FAIL_IF(push_inst(compiler, XORI | S(src2) | A(TMP_REG2) | 0x1f)); + FAIL_IF(push_inst(compiler, (is_right ? SLW : SRW) | S(TMP_REG1) | A(TMP_REG1) | B(TMP_REG2))); + return push_inst(compiler, OR | S(src_dst) | A(src_dst) | B(TMP_REG1)); +} + SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_src(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 src, sljit_sw srcw) { @@ -1686,7 +1837,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_src(struct sljit_compiler *comp if (FAST_IS_REG(src)) FAIL_IF(push_inst(compiler, MTLR | S(src))); else { - FAIL_IF(emit_op(compiler, SLJIT_MOV, WORD_DATA, TMP_REG2, 0, TMP_REG1, 0, src, srcw)); + FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, TMP_REG2, src, srcw, TMP_REG2)); FAIL_IF(push_inst(compiler, MTLR | S(TMP_REG2))); } @@ -1782,11 +1933,7 @@ static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_sw_from_f64(struct sljit_comp if (dst & OFFS_REG_MASK) { dstw &= 0x3; if (dstw) { -#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) - FAIL_IF(push_inst(compiler, RLWINM | S(OFFS_REG(dst)) | A(TMP_REG1) | ((sljit_ins)dstw << 11) | ((31 - (sljit_ins)dstw) << 1))); -#else - FAIL_IF(push_inst(compiler, RLDI(TMP_REG1, OFFS_REG(dst), dstw, 63 - dstw, 1))); -#endif + FAIL_IF(push_inst(compiler, SLWI_W(dstw) | S(OFFS_REG(dst)) | A(TMP_REG1))); dstw = TMP_REG1; } else @@ -1818,6 +1965,7 @@ static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_sw(struct sljit_comp if (src & SLJIT_IMM) { if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_S32) srcw = (sljit_s32)srcw; + FAIL_IF(load_immediate(compiler, TMP_REG1, srcw)); src = TMP_REG1; } @@ -1863,7 +2011,7 @@ static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_sw(struct sljit_comp The double precision format has exactly 53 bit precision, so the lower 32 bit represents the lower 32 bit of such value. The result of xor 2^31 is the same as adding 0x80000000 to the input, which shifts it into the 0 - 0xffffffff range. To get the converted floating - point value, we need to substract 2^53 + 2^31 from the constructed value. */ + point value, we need to subtract 2^53 + 2^31 from the constructed value. */ FAIL_IF(push_inst(compiler, ADDIS | D(TMP_REG2) | A(0) | 0x4330)); if (invert_sign) FAIL_IF(push_inst(compiler, XORIS | S(src) | A(TMP_REG1) | 0x8000)); @@ -1899,7 +2047,21 @@ static SLJIT_INLINE sljit_s32 sljit_emit_fop1_cmp(struct sljit_compiler *compile src2 = TMP_FREG2; } - return push_inst(compiler, FCMPU | CRD(4) | FA(src1) | FB(src2)); + FAIL_IF(push_inst(compiler, FCMPU | CRD(4) | FA(src1) | FB(src2))); + + switch (GET_FLAG_TYPE(op)) { + case SLJIT_UNORDERED_OR_EQUAL: + case SLJIT_ORDERED_NOT_EQUAL: + return push_inst(compiler, CROR | ((4 + 2) << 21) | ((4 + 2) << 16) | ((4 + 3) << 11)); + case SLJIT_UNORDERED_OR_LESS: + case SLJIT_ORDERED_GREATER_EQUAL: + return push_inst(compiler, CROR | ((4 + 0) << 21) | ((4 + 0) << 16) | ((4 + 3) << 11)); + case SLJIT_UNORDERED_OR_GREATER: + case SLJIT_ORDERED_LESS_EQUAL: + return push_inst(compiler, CROR | ((4 + 1) << 21) | ((4 + 1) << 16) | ((4 + 3) << 11)); + } + + return SLJIT_SUCCESS; } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop1(struct sljit_compiler *compiler, sljit_s32 op, @@ -2076,38 +2238,50 @@ static sljit_ins get_bo_bi_flags(struct sljit_compiler *compiler, sljit_s32 type case SLJIT_SIG_LESS_EQUAL: return (4 << 21) | (1 << 16); - case SLJIT_LESS_F64: - return (12 << 21) | ((4 + 0) << 16); - - case SLJIT_GREATER_EQUAL_F64: - return (4 << 21) | ((4 + 0) << 16); - - case SLJIT_GREATER_F64: - return (12 << 21) | ((4 + 1) << 16); - - case SLJIT_LESS_EQUAL_F64: - return (4 << 21) | ((4 + 1) << 16); - case SLJIT_OVERFLOW: return (12 << 21) | (3 << 16); case SLJIT_NOT_OVERFLOW: return (4 << 21) | (3 << 16); - case SLJIT_EQUAL_F64: + case SLJIT_F_LESS: + case SLJIT_ORDERED_LESS: + case SLJIT_UNORDERED_OR_LESS: + return (12 << 21) | ((4 + 0) << 16); + + case SLJIT_F_GREATER_EQUAL: + case SLJIT_ORDERED_GREATER_EQUAL: + case SLJIT_UNORDERED_OR_GREATER_EQUAL: + return (4 << 21) | ((4 + 0) << 16); + + case SLJIT_F_GREATER: + case SLJIT_ORDERED_GREATER: + case SLJIT_UNORDERED_OR_GREATER: + return (12 << 21) | ((4 + 1) << 16); + + case SLJIT_F_LESS_EQUAL: + case SLJIT_ORDERED_LESS_EQUAL: + case SLJIT_UNORDERED_OR_LESS_EQUAL: + return (4 << 21) | ((4 + 1) << 16); + + case SLJIT_F_EQUAL: + case SLJIT_ORDERED_EQUAL: + case SLJIT_UNORDERED_OR_EQUAL: return (12 << 21) | ((4 + 2) << 16); - case SLJIT_NOT_EQUAL_F64: + case SLJIT_F_NOT_EQUAL: + case SLJIT_ORDERED_NOT_EQUAL: + case SLJIT_UNORDERED_OR_NOT_EQUAL: return (4 << 21) | ((4 + 2) << 16); - case SLJIT_UNORDERED_F64: + case SLJIT_UNORDERED: return (12 << 21) | ((4 + 3) << 16); - case SLJIT_ORDERED_F64: + case SLJIT_ORDERED: return (4 << 21) | ((4 + 3) << 16); default: - SLJIT_ASSERT(type >= SLJIT_JUMP && type <= SLJIT_CALL_CDECL); + SLJIT_ASSERT(type >= SLJIT_JUMP && type <= SLJIT_CALL_REG_ARG); return (20 << 21); } } @@ -2154,19 +2328,16 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compile CHECK_PTR(check_sljit_emit_call(compiler, type, arg_types)); #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) - PTR_FAIL_IF(call_with_args(compiler, arg_types, NULL)); + if ((type & 0xff) != SLJIT_CALL_REG_ARG) + PTR_FAIL_IF(call_with_args(compiler, arg_types, NULL)); #endif if (type & SLJIT_CALL_RETURN) { - PTR_FAIL_IF(emit_stack_frame_release(compiler)); + PTR_FAIL_IF(emit_stack_frame_release(compiler, 0)); type = SLJIT_JUMP | (type & SLJIT_REWRITABLE_JUMP); } -#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \ - || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) - compiler->skip_checks = 1; -#endif - + SLJIT_SKIP_CHECKS(compiler); return sljit_emit_jump(compiler, type); } @@ -2177,7 +2348,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compi CHECK_ERROR(); CHECK(check_sljit_emit_ijump(compiler, type, src, srcw)); - ADJUST_LOCAL_OFFSET(src, srcw); if (FAST_IS_REG(src)) { #if (defined SLJIT_PASS_ENTRY_ADDR_TO_CALL && SLJIT_PASS_ENTRY_ADDR_TO_CALL) @@ -2204,9 +2374,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compi FAIL_IF(emit_const(compiler, TMP_CALL_REG, 0)); src_r = TMP_CALL_REG; - } - else { - FAIL_IF(emit_op(compiler, SLJIT_MOV, WORD_DATA, TMP_CALL_REG, 0, TMP_REG1, 0, src, srcw)); + } else { + ADJUST_LOCAL_OFFSET(src, srcw); + FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, TMP_CALL_REG, src, srcw, TMP_CALL_REG)); src_r = TMP_CALL_REG; } @@ -2225,29 +2395,26 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compi if (src & SLJIT_MEM) { ADJUST_LOCAL_OFFSET(src, srcw); - FAIL_IF(emit_op(compiler, SLJIT_MOV, WORD_DATA, TMP_CALL_REG, 0, TMP_REG1, 0, src, srcw)); + FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, TMP_CALL_REG, src, srcw, TMP_CALL_REG)); src = TMP_CALL_REG; } if (type & SLJIT_CALL_RETURN) { - if (src >= SLJIT_FIRST_SAVED_REG && src <= SLJIT_S0) { + if (src >= SLJIT_FIRST_SAVED_REG && src <= (SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options))) { FAIL_IF(push_inst(compiler, OR | S(src) | A(TMP_CALL_REG) | B(src))); src = TMP_CALL_REG; } - FAIL_IF(emit_stack_frame_release(compiler)); + FAIL_IF(emit_stack_frame_release(compiler, 0)); type = SLJIT_JUMP; } #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) - FAIL_IF(call_with_args(compiler, arg_types, &src)); -#endif - -#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \ - || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) - compiler->skip_checks = 1; + if ((type & 0xff) != SLJIT_CALL_REG_ARG) + FAIL_IF(call_with_args(compiler, arg_types, &src)); #endif + SLJIT_SKIP_CHECKS(compiler); return sljit_emit_ijump(compiler, type, src, srcw); } @@ -2279,7 +2446,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *co bit = 0; from_xer = 0; - switch (type & 0xff) { + switch (type) { case SLJIT_LESS: case SLJIT_SIG_LESS: break; @@ -2332,38 +2499,50 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *co invert = (compiler->status_flags_state & SLJIT_CURRENT_FLAGS_ADD) != 0; break; - case SLJIT_LESS_F64: + case SLJIT_F_LESS: + case SLJIT_ORDERED_LESS: + case SLJIT_UNORDERED_OR_LESS: bit = 4 + 0; break; - case SLJIT_GREATER_EQUAL_F64: + case SLJIT_F_GREATER_EQUAL: + case SLJIT_ORDERED_GREATER_EQUAL: + case SLJIT_UNORDERED_OR_GREATER_EQUAL: bit = 4 + 0; invert = 1; break; - case SLJIT_GREATER_F64: + case SLJIT_F_GREATER: + case SLJIT_ORDERED_GREATER: + case SLJIT_UNORDERED_OR_GREATER: bit = 4 + 1; break; - case SLJIT_LESS_EQUAL_F64: + case SLJIT_F_LESS_EQUAL: + case SLJIT_ORDERED_LESS_EQUAL: + case SLJIT_UNORDERED_OR_LESS_EQUAL: bit = 4 + 1; invert = 1; break; - case SLJIT_EQUAL_F64: + case SLJIT_F_EQUAL: + case SLJIT_ORDERED_EQUAL: + case SLJIT_UNORDERED_OR_EQUAL: bit = 4 + 2; break; - case SLJIT_NOT_EQUAL_F64: + case SLJIT_F_NOT_EQUAL: + case SLJIT_ORDERED_NOT_EQUAL: + case SLJIT_UNORDERED_OR_NOT_EQUAL: bit = 4 + 2; invert = 1; break; - case SLJIT_UNORDERED_F64: + case SLJIT_UNORDERED: bit = 4 + 3; break; - case SLJIT_ORDERED_F64: + case SLJIT_ORDERED: bit = 4 + 3; invert = 1; break; @@ -2374,7 +2553,8 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *co } FAIL_IF(push_inst(compiler, (from_xer ? MFXER : MFCR) | D(reg))); - FAIL_IF(push_inst(compiler, RLWINM | S(reg) | A(reg) | ((1 + bit) << 11) | (31 << 6) | (31 << 1))); + /* Simplified mnemonics: extrwi. */ + FAIL_IF(push_inst(compiler, RLWINM | S(reg) | A(reg) | RLWI_SH(1 + bit) | RLWI_MBE(31, 31))); if (invert) FAIL_IF(push_inst(compiler, XORI | S(reg) | A(reg) | 0x1)); @@ -2385,10 +2565,8 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *co return emit_op_mem(compiler, input_flags, reg, dst, dstw, TMP_REG1); } -#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \ - || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) - compiler->skip_checks = 1; -#endif + SLJIT_SKIP_CHECKS(compiler); + if (dst & SLJIT_MEM) return sljit_emit_op2(compiler, saved_op, dst, saved_dstw, TMP_REG1, 0, TMP_REG2, 0); return sljit_emit_op2(compiler, saved_op, dst, 0, dst, 0, TMP_REG2, 0); @@ -2404,15 +2582,94 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_cmov(struct sljit_compiler *compil return sljit_emit_cmov_generic(compiler, type, dst_reg, src, srcw);; } +#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) + +#define EMIT_MEM_LOAD_IMM(inst, mem, memw) \ + ((sljit_s16)(memw) > SIMM_MAX - SSIZE_OF(sw)) + +#else /* !SLJIT_CONFIG_PPC_32 */ + +#define EMIT_MEM_LOAD_IMM(inst, mem, memw) \ + ((((inst) & INT_ALIGNED) && ((memw) & 0x3) != 0) \ + || ((sljit_s16)(memw) > SIMM_MAX - SSIZE_OF(sw)) \ + || ((memw) > 0x7fff7fffl || (memw) < -0x80000000l)) \ + +#endif /* SLJIT_CONFIG_PPC_32 */ + SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 reg, sljit_s32 mem, sljit_sw memw) +{ + sljit_ins inst; + + CHECK_ERROR(); + CHECK(check_sljit_emit_mem(compiler, type, reg, mem, memw)); + + if (!(reg & REG_PAIR_MASK)) + return sljit_emit_mem_unaligned(compiler, type, reg, mem, memw); + + ADJUST_LOCAL_OFFSET(mem, memw); + + inst = data_transfer_insts[WORD_DATA | ((type & SLJIT_MEM_STORE) ? 0 : LOAD_DATA)]; + + if (SLJIT_UNLIKELY(mem & OFFS_REG_MASK)) { + memw &= 0x3; + + if (memw != 0) { + FAIL_IF(push_inst(compiler, SLWI_W(memw) | S(OFFS_REG(mem)) | A(TMP_REG1))); + FAIL_IF(push_inst(compiler, ADD | D(TMP_REG1) | A(TMP_REG1) | B(mem & REG_MASK))); + } else + FAIL_IF(push_inst(compiler, ADD | D(TMP_REG1) | A(mem & REG_MASK) | B(OFFS_REG(mem)))); + + mem = TMP_REG1; + memw = 0; + } else { + if (EMIT_MEM_LOAD_IMM(inst, mem, memw)) { + if ((mem & REG_MASK) != 0) { + SLJIT_SKIP_CHECKS(compiler); + FAIL_IF(sljit_emit_op2(compiler, SLJIT_ADD, TMP_REG1, 0, mem & REG_MASK, 0, SLJIT_IMM, memw)); + } else + FAIL_IF(load_immediate(compiler, TMP_REG1, memw)); + + memw = 0; + mem = TMP_REG1; + } else if (memw > SIMM_MAX || memw < SIMM_MIN) { + FAIL_IF(push_inst(compiler, ADDIS | D(TMP_REG1) | A(mem & REG_MASK) | IMM((memw + 0x8000) >> 16))); + + memw &= 0xffff; + mem = TMP_REG1; + } else { + memw &= 0xffff; + mem &= REG_MASK; + } + } + + SLJIT_ASSERT((memw >= 0 && memw <= SIMM_MAX - SSIZE_OF(sw)) || (memw >= 0x8000 && memw <= 0xffff)); + +#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) + inst &= (sljit_ins)~INT_ALIGNED; +#endif /* SLJIT_CONFIG_PPC_64 */ + + if (!(type & SLJIT_MEM_STORE) && mem == REG_PAIR_FIRST(reg)) { + FAIL_IF(push_inst(compiler, inst | D(REG_PAIR_SECOND(reg)) | A(mem) | IMM(memw + SSIZE_OF(sw)))); + return push_inst(compiler, inst | D(REG_PAIR_FIRST(reg)) | A(mem) | IMM(memw)); + } + + FAIL_IF(push_inst(compiler, inst | D(REG_PAIR_FIRST(reg)) | A(mem) | IMM(memw))); + return push_inst(compiler, inst | D(REG_PAIR_SECOND(reg)) | A(mem) | IMM(memw + SSIZE_OF(sw))); +} + +#undef EMIT_MEM_LOAD_IMM + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem_update(struct sljit_compiler *compiler, sljit_s32 type, + sljit_s32 reg, + sljit_s32 mem, sljit_sw memw) { sljit_s32 mem_flags; sljit_ins inst; CHECK_ERROR(); - CHECK(check_sljit_emit_mem(compiler, type, reg, mem, memw)); + CHECK(check_sljit_emit_mem_update(compiler, type, reg, mem, memw)); if (type & SLJIT_MEM_POST) return SLJIT_ERR_UNSUPPORTED; @@ -2500,7 +2757,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compile return SLJIT_SUCCESS; } -SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fmem(struct sljit_compiler *compiler, sljit_s32 type, +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fmem_update(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 freg, sljit_s32 mem, sljit_sw memw) { @@ -2508,7 +2765,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fmem(struct sljit_compiler *compil sljit_ins inst; CHECK_ERROR(); - CHECK(check_sljit_emit_fmem(compiler, type, freg, mem, memw)); + CHECK(check_sljit_emit_fmem_update(compiler, type, freg, mem, memw)); if (type & SLJIT_MEM_POST) return SLJIT_ERR_UNSUPPORTED; @@ -2587,3 +2844,8 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_put_label* sljit_emit_put_label(struct slj return put_label; } + +SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant, sljit_sw executable_offset) +{ + sljit_set_jump_addr(addr, (sljit_uw)new_constant, executable_offset); +} diff --git a/src/3rdparty/pcre2/src/sljit/sljitNativeRISCV_32.c b/src/3rdparty/pcre2/src/sljit/sljitNativeRISCV_32.c new file mode 100644 index 00000000000..b38e6924c80 --- /dev/null +++ b/src/3rdparty/pcre2/src/sljit/sljitNativeRISCV_32.c @@ -0,0 +1,73 @@ +/* + * Stack-less Just-In-Time compiler + * + * Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. 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 HOLDER(S) 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 HOLDER(S) 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. + */ + +static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 dst_r, sljit_sw imm, sljit_s32 tmp_r) +{ + SLJIT_UNUSED_ARG(tmp_r); + SLJIT_ASSERT(dst_r != tmp_r); + + if (imm <= SIMM_MAX && imm >= SIMM_MIN) + return push_inst(compiler, ADDI | RD(dst_r) | RS1(TMP_ZERO) | IMM_I(imm)); + + if (imm & 0x800) + imm += 0x1000; + + FAIL_IF(push_inst(compiler, LUI | RD(dst_r) | (sljit_ins)(imm & ~0xfff))); + + if ((imm & 0xfff) == 0) + return SLJIT_SUCCESS; + + return push_inst(compiler, ADDI | RD(dst_r) | RS1(dst_r) | IMM_I(imm)); +} + +static SLJIT_INLINE sljit_s32 emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw init_value, sljit_ins last_ins) +{ + if ((init_value & 0x800) != 0) + init_value += 0x1000; + + FAIL_IF(push_inst(compiler, LUI | RD(dst) | (sljit_ins)(init_value & ~0xfff))); + return push_inst(compiler, last_ins | RS1(dst) | IMM_I(init_value)); +} + +SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_target, sljit_sw executable_offset) +{ + sljit_ins *inst = (sljit_ins*)addr; + SLJIT_UNUSED_ARG(executable_offset); + + if ((new_target & 0x800) != 0) + new_target += 0x1000; + + SLJIT_UPDATE_WX_FLAGS(inst, inst + 5, 0); + + SLJIT_ASSERT((inst[0] & 0x7f) == LUI); + inst[0] = (inst[0] & 0xfff) | (sljit_ins)((sljit_sw)new_target & ~0xfff); + SLJIT_ASSERT((inst[1] & 0x707f) == ADDI || (inst[1] & 0x707f) == JALR); + inst[1] = (inst[1] & 0xfffff) | IMM_I(new_target); + + SLJIT_UPDATE_WX_FLAGS(inst, inst + 5, 1); + inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset); + SLJIT_CACHE_FLUSH(inst, inst + 5); +} diff --git a/src/3rdparty/pcre2/src/sljit/sljitNativeRISCV_64.c b/src/3rdparty/pcre2/src/sljit/sljitNativeRISCV_64.c new file mode 100644 index 00000000000..32cec7848d2 --- /dev/null +++ b/src/3rdparty/pcre2/src/sljit/sljitNativeRISCV_64.c @@ -0,0 +1,183 @@ +/* + * Stack-less Just-In-Time compiler + * + * Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. 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 HOLDER(S) 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 HOLDER(S) 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. + */ + +static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 dst_r, sljit_sw imm, sljit_s32 tmp_r) +{ + sljit_sw high; + + SLJIT_ASSERT(dst_r != tmp_r); + + if (imm <= SIMM_MAX && imm >= SIMM_MIN) + return push_inst(compiler, ADDI | RD(dst_r) | RS1(TMP_ZERO) | IMM_I(imm)); + + if (imm <= 0x7fffffffl && imm >= S32_MIN) { + if (imm > S32_MAX) { + SLJIT_ASSERT((imm & 0x800) != 0); + FAIL_IF(push_inst(compiler, LUI | RD(dst_r) | (sljit_ins)0x80000000u)); + return push_inst(compiler, XORI | RD(dst_r) | RS1(dst_r) | IMM_I(imm)); + } + + if ((imm & 0x800) != 0) + imm += 0x1000; + + FAIL_IF(push_inst(compiler, LUI | RD(dst_r) | (sljit_ins)(imm & ~0xfff))); + + if ((imm & 0xfff) == 0) + return SLJIT_SUCCESS; + + return push_inst(compiler, ADDI | RD(dst_r) | RS1(dst_r) | IMM_I(imm)); + } + + /* Trailing zeroes could be used to produce shifted immediates. */ + + if (imm <= 0x7ffffffffffl && imm >= -0x80000000000l) { + high = imm >> 12; + + if (imm & 0x800) + high = ~high; + + if (high > S32_MAX) { + SLJIT_ASSERT((high & 0x800) != 0); + FAIL_IF(push_inst(compiler, LUI | RD(dst_r) | (sljit_ins)0x80000000u)); + FAIL_IF(push_inst(compiler, XORI | RD(dst_r) | RS1(dst_r) | IMM_I(high))); + } else { + if ((high & 0x800) != 0) + high += 0x1000; + + FAIL_IF(push_inst(compiler, LUI | RD(dst_r) | (sljit_ins)(high & ~0xfff))); + + if ((high & 0xfff) != 0) + FAIL_IF(push_inst(compiler, ADDI | RD(dst_r) | RS1(dst_r) | IMM_I(high))); + } + + FAIL_IF(push_inst(compiler, SLLI | RD(dst_r) | RS1(dst_r) | IMM_I(12))); + + if ((imm & 0xfff) != 0) + return push_inst(compiler, XORI | RD(dst_r) | RS1(dst_r) | IMM_I(imm)); + + return SLJIT_SUCCESS; + } + + high = imm >> 32; + imm = (sljit_s32)imm; + + if ((imm & 0x80000000l) != 0) + high = ~high; + + if (high <= 0x7ffff && high >= -0x80000) { + FAIL_IF(push_inst(compiler, LUI | RD(tmp_r) | (sljit_ins)(high << 12))); + high = 0x1000; + } else { + if ((high & 0x800) != 0) + high += 0x1000; + + FAIL_IF(push_inst(compiler, LUI | RD(tmp_r) | (sljit_ins)(high & ~0xfff))); + high &= 0xfff; + } + + if (imm <= SIMM_MAX && imm >= SIMM_MIN) { + FAIL_IF(push_inst(compiler, ADDI | RD(dst_r) | RS1(TMP_ZERO) | IMM_I(imm))); + imm = 0; + } else if (imm > S32_MAX) { + SLJIT_ASSERT((imm & 0x800) != 0); + + FAIL_IF(push_inst(compiler, LUI | RD(dst_r) | (sljit_ins)0x80000000u)); + imm = 0x1000 | (imm & 0xfff); + } else { + if ((imm & 0x800) != 0) + imm += 0x1000; + + FAIL_IF(push_inst(compiler, LUI | RD(dst_r) | (sljit_ins)(imm & ~0xfff))); + imm &= 0xfff; + } + + if ((high & 0xfff) != 0) + FAIL_IF(push_inst(compiler, ADDI | RD(tmp_r) | RS1(tmp_r) | IMM_I(high))); + + if (imm & 0x1000) + FAIL_IF(push_inst(compiler, XORI | RD(dst_r) | RS1(dst_r) | IMM_I(imm))); + else if (imm != 0) + FAIL_IF(push_inst(compiler, ADDI | RD(dst_r) | RS1(dst_r) | IMM_I(imm))); + + FAIL_IF(push_inst(compiler, SLLI | RD(tmp_r) | RS1(tmp_r) | IMM_I((high & 0x1000) ? 20 : 32))); + return push_inst(compiler, XOR | RD(dst_r) | RS1(dst_r) | RS2(tmp_r)); +} + +static SLJIT_INLINE sljit_s32 emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw init_value, sljit_ins last_ins) +{ + sljit_sw high; + + if ((init_value & 0x800) != 0) + init_value += 0x1000; + + high = init_value >> 32; + + if ((init_value & 0x80000000l) != 0) + high = ~high; + + if ((high & 0x800) != 0) + high += 0x1000; + + FAIL_IF(push_inst(compiler, LUI | RD(TMP_REG3) | (sljit_ins)(high & ~0xfff))); + FAIL_IF(push_inst(compiler, ADDI | RD(TMP_REG3) | RS1(TMP_REG3) | IMM_I(high))); + FAIL_IF(push_inst(compiler, LUI | RD(dst) | (sljit_ins)(init_value & ~0xfff))); + FAIL_IF(push_inst(compiler, SLLI | RD(TMP_REG3) | RS1(TMP_REG3) | IMM_I(32))); + FAIL_IF(push_inst(compiler, XOR | RD(dst) | RS1(dst) | RS2(TMP_REG3))); + return push_inst(compiler, last_ins | RS1(dst) | IMM_I(init_value)); +} + +SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_target, sljit_sw executable_offset) +{ + sljit_ins *inst = (sljit_ins*)addr; + sljit_sw high; + SLJIT_UNUSED_ARG(executable_offset); + + if ((new_target & 0x800) != 0) + new_target += 0x1000; + + high = (sljit_sw)new_target >> 32; + + if ((new_target & 0x80000000l) != 0) + high = ~high; + + if ((high & 0x800) != 0) + high += 0x1000; + + SLJIT_UPDATE_WX_FLAGS(inst, inst + 5, 0); + + SLJIT_ASSERT((inst[0] & 0x7f) == LUI); + inst[0] = (inst[0] & 0xfff) | (sljit_ins)(high & ~0xfff); + SLJIT_ASSERT((inst[1] & 0x707f) == ADDI); + inst[1] = (inst[1] & 0xfffff) | IMM_I(high); + SLJIT_ASSERT((inst[2] & 0x7f) == LUI); + inst[2] = (inst[2] & 0xfff) | (sljit_ins)((sljit_sw)new_target & ~0xfff); + SLJIT_ASSERT((inst[5] & 0x707f) == ADDI || (inst[5] & 0x707f) == JALR); + inst[5] = (inst[5] & 0xfffff) | IMM_I(new_target); + SLJIT_UPDATE_WX_FLAGS(inst, inst + 5, 1); + + inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset); + SLJIT_CACHE_FLUSH(inst, inst + 5); +} diff --git a/src/3rdparty/pcre2/src/sljit/sljitNativeRISCV_common.c b/src/3rdparty/pcre2/src/sljit/sljitNativeRISCV_common.c new file mode 100644 index 00000000000..58a48c649c9 --- /dev/null +++ b/src/3rdparty/pcre2/src/sljit/sljitNativeRISCV_common.c @@ -0,0 +1,2762 @@ +/* + * Stack-less Just-In-Time compiler + * + * Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. 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 HOLDER(S) 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 HOLDER(S) 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. + */ + +SLJIT_API_FUNC_ATTRIBUTE const char* sljit_get_platform_name(void) +{ +#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32) + return "RISC-V-32" SLJIT_CPUINFO; +#else /* !SLJIT_CONFIG_RISCV_32 */ + return "RISC-V-64" SLJIT_CPUINFO; +#endif /* SLJIT_CONFIG_RISCV_32 */ +} + +/* Length of an instruction word + Both for riscv-32 and riscv-64 */ +typedef sljit_u32 sljit_ins; + +#define TMP_REG1 (SLJIT_NUMBER_OF_REGISTERS + 2) +#define TMP_REG2 (SLJIT_NUMBER_OF_REGISTERS + 3) +#define TMP_REG3 (SLJIT_NUMBER_OF_REGISTERS + 4) +#define TMP_ZERO 0 + +/* Flags are kept in volatile registers. */ +#define EQUAL_FLAG (SLJIT_NUMBER_OF_REGISTERS + 5) +#define RETURN_ADDR_REG TMP_REG2 +#define OTHER_FLAG (SLJIT_NUMBER_OF_REGISTERS + 6) + +#define TMP_FREG1 (SLJIT_NUMBER_OF_FLOAT_REGISTERS + 1) +#define TMP_FREG2 (SLJIT_NUMBER_OF_FLOAT_REGISTERS + 2) + +static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 7] = { + 0, 10, 11, 12, 13, 14, 15, 16, 17, 29, 30, 31, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 9, 8, 2, 6, 1, 7, 5, 28 +}; + +static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 3] = { + 0, 10, 11, 12, 13, 14, 15, 16, 17, 2, 3, 4, 5, 6, 7, 28, 29, 30, 31, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 9, 8, 0, 1, +}; + +/* --------------------------------------------------------------------- */ +/* Instrucion forms */ +/* --------------------------------------------------------------------- */ + +#define RD(rd) ((sljit_ins)reg_map[rd] << 7) +#define RS1(rs1) ((sljit_ins)reg_map[rs1] << 15) +#define RS2(rs2) ((sljit_ins)reg_map[rs2] << 20) +#define FRD(rd) ((sljit_ins)freg_map[rd] << 7) +#define FRS1(rs1) ((sljit_ins)freg_map[rs1] << 15) +#define FRS2(rs2) ((sljit_ins)freg_map[rs2] << 20) +#define IMM_I(imm) ((sljit_ins)(imm) << 20) +#define IMM_S(imm) ((((sljit_ins)(imm) & 0xfe0) << 20) | (((sljit_ins)(imm) & 0x1f) << 7)) + +/* Represents funct(i) parts of the instructions. */ +#define OPC(o) ((sljit_ins)(o)) +#define F3(f) ((sljit_ins)(f) << 12) +#define F12(f) ((sljit_ins)(f) << 20) +#define F7(f) ((sljit_ins)(f) << 25) + +#define ADD (F7(0x0) | F3(0x0) | OPC(0x33)) +#define ADDI (F3(0x0) | OPC(0x13)) +#define AND (F7(0x0) | F3(0x7) | OPC(0x33)) +#define ANDI (F3(0x7) | OPC(0x13)) +#define AUIPC (OPC(0x17)) +#define BEQ (F3(0x0) | OPC(0x63)) +#define BNE (F3(0x1) | OPC(0x63)) +#define BLT (F3(0x4) | OPC(0x63)) +#define BGE (F3(0x5) | OPC(0x63)) +#define BLTU (F3(0x6) | OPC(0x63)) +#define BGEU (F3(0x7) | OPC(0x63)) +#define DIV (F7(0x1) | F3(0x4) | OPC(0x33)) +#define DIVU (F7(0x1) | F3(0x5) | OPC(0x33)) +#define EBREAK (F12(0x1) | F3(0x0) | OPC(0x73)) +#define FADD_S (F7(0x0) | F3(0x7) | OPC(0x53)) +#define FDIV_S (F7(0xc) | F3(0x7) | OPC(0x53)) +#define FEQ_S (F7(0x50) | F3(0x2) | OPC(0x53)) +#define FLD (F3(0x3) | OPC(0x7)) +#define FLE_S (F7(0x50) | F3(0x0) | OPC(0x53)) +#define FLT_S (F7(0x50) | F3(0x1) | OPC(0x53)) +#define FSD (F3(0x3) | OPC(0x27)) +/* These conversion opcodes are partly defined. */ +#define FCVT_S_D (F7(0x20) | OPC(0x53)) +#define FCVT_S_W (F7(0x68) | OPC(0x53)) +#define FCVT_W_S (F7(0x60) | F3(0x1) | OPC(0x53)) +#define FMUL_S (F7(0x8) | F3(0x7) | OPC(0x53)) +#define FSGNJ_S (F7(0x10) | F3(0x0) | OPC(0x53)) +#define FSGNJN_S (F7(0x10) | F3(0x1) | OPC(0x53)) +#define FSGNJX_S (F7(0x10) | F3(0x2) | OPC(0x53)) +#define FSUB_S (F7(0x4) | F3(0x7) | OPC(0x53)) +#define JAL (OPC(0x6f)) +#define JALR (F3(0x0) | OPC(0x67)) +#define LD (F3(0x3) | OPC(0x3)) +#define LUI (OPC(0x37)) +#define LW (F3(0x2) | OPC(0x3)) +#define MUL (F7(0x1) | F3(0x0) | OPC(0x33)) +#define MULH (F7(0x1) | F3(0x1) | OPC(0x33)) +#define MULHU (F7(0x1) | F3(0x3) | OPC(0x33)) +#define OR (F7(0x0) | F3(0x6) | OPC(0x33)) +#define ORI (F3(0x6) | OPC(0x13)) +#define REM (F7(0x1) | F3(0x6) | OPC(0x33)) +#define REMU (F7(0x1) | F3(0x7) | OPC(0x33)) +#define SD (F3(0x3) | OPC(0x23)) +#define SLL (F7(0x0) | F3(0x1) | OPC(0x33)) +#define SLLI (IMM_I(0x0) | F3(0x1) | OPC(0x13)) +#define SLT (F7(0x0) | F3(0x2) | OPC(0x33)) +#define SLTI (F3(0x2) | OPC(0x13)) +#define SLTU (F7(0x0) | F3(0x3) | OPC(0x33)) +#define SLTUI (F3(0x3) | OPC(0x13)) +#define SRL (F7(0x0) | F3(0x5) | OPC(0x33)) +#define SRLI (IMM_I(0x0) | F3(0x5) | OPC(0x13)) +#define SRA (F7(0x20) | F3(0x5) | OPC(0x33)) +#define SRAI (IMM_I(0x400) | F3(0x5) | OPC(0x13)) +#define SUB (F7(0x20) | F3(0x0) | OPC(0x33)) +#define SW (F3(0x2) | OPC(0x23)) +#define XOR (F7(0x0) | F3(0x4) | OPC(0x33)) +#define XORI (F3(0x4) | OPC(0x13)) + +#define SIMM_MAX (0x7ff) +#define SIMM_MIN (-0x800) +#define BRANCH_MAX (0xfff) +#define BRANCH_MIN (-0x1000) +#define JUMP_MAX (0xfffff) +#define JUMP_MIN (-0x100000) + +#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64) +#define S32_MAX (0x7ffff7ffl) +#define S32_MIN (-0x80000000l) +#define S44_MAX (0x7fffffff7ffl) +#define S52_MAX (0x7ffffffffffffl) +#endif + +static sljit_s32 push_inst(struct sljit_compiler *compiler, sljit_ins ins) +{ + sljit_ins *ptr = (sljit_ins*)ensure_buf(compiler, sizeof(sljit_ins)); + FAIL_IF(!ptr); + *ptr = ins; + compiler->size++; + return SLJIT_SUCCESS; +} + +static sljit_s32 push_imm_s_inst(struct sljit_compiler *compiler, sljit_ins ins, sljit_sw imm) +{ + return push_inst(compiler, ins | IMM_S(imm)); +} + +static SLJIT_INLINE sljit_ins* detect_jump_type(struct sljit_jump *jump, sljit_ins *code, sljit_sw executable_offset) +{ + sljit_sw diff; + sljit_uw target_addr; + sljit_ins *inst; + + inst = (sljit_ins *)jump->addr; + + if (jump->flags & SLJIT_REWRITABLE_JUMP) + goto exit; + + if (jump->flags & JUMP_ADDR) + target_addr = jump->u.target; + else { + SLJIT_ASSERT(jump->flags & JUMP_LABEL); + target_addr = (sljit_uw)(code + jump->u.label->size) + (sljit_uw)executable_offset; + } + + diff = (sljit_sw)target_addr - (sljit_sw)inst - executable_offset; + + if (jump->flags & IS_COND) { + inst--; + diff += SSIZE_OF(ins); + + if (diff >= BRANCH_MIN && diff <= BRANCH_MAX) { + jump->flags |= PATCH_B; + inst[0] = (inst[0] & 0x1fff07f) ^ 0x1000; + jump->addr = (sljit_uw)inst; + return inst; + } + + inst++; + diff -= SSIZE_OF(ins); + } + + if (diff >= JUMP_MIN && diff <= JUMP_MAX) { + if (jump->flags & IS_COND) { +#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32) + inst[-1] -= (sljit_ins)(1 * sizeof(sljit_ins)) << 7; +#else + inst[-1] -= (sljit_ins)(5 * sizeof(sljit_ins)) << 7; +#endif + } + + jump->flags |= PATCH_J; + return inst; + } + +#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64) + if (diff >= S32_MIN && diff <= S32_MAX) { + if (jump->flags & IS_COND) + inst[-1] -= (sljit_ins)(4 * sizeof(sljit_ins)) << 7; + + jump->flags |= PATCH_REL32; + inst[1] = inst[0]; + return inst + 1; + } + + if (target_addr <= (sljit_uw)S32_MAX) { + if (jump->flags & IS_COND) + inst[-1] -= (sljit_ins)(4 * sizeof(sljit_ins)) << 7; + + jump->flags |= PATCH_ABS32; + inst[1] = inst[0]; + return inst + 1; + } + + if (target_addr <= S44_MAX) { + if (jump->flags & IS_COND) + inst[-1] -= (sljit_ins)(2 * sizeof(sljit_ins)) << 7; + + jump->flags |= PATCH_ABS44; + inst[3] = inst[0]; + return inst + 3; + } + + if (target_addr <= S52_MAX) { + if (jump->flags & IS_COND) + inst[-1] -= (sljit_ins)(1 * sizeof(sljit_ins)) << 7; + + jump->flags |= PATCH_ABS52; + inst[4] = inst[0]; + return inst + 4; + } +#endif + +exit: +#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32) + inst[1] = inst[0]; + return inst + 1; +#else + inst[5] = inst[0]; + return inst + 5; +#endif +} + +#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64) + +static SLJIT_INLINE sljit_sw put_label_get_length(struct sljit_put_label *put_label, sljit_uw max_label) +{ + if (max_label <= (sljit_uw)S32_MAX) { + put_label->flags = PATCH_ABS32; + return 1; + } + + if (max_label <= S44_MAX) { + put_label->flags = PATCH_ABS44; + return 3; + } + + if (max_label <= S52_MAX) { + put_label->flags = PATCH_ABS52; + return 4; + } + + put_label->flags = 0; + return 5; +} + +#endif /* SLJIT_CONFIG_RISCV_64 */ + +static SLJIT_INLINE void load_addr_to_reg(void *dst, sljit_u32 reg) +{ + struct sljit_jump *jump = NULL; + struct sljit_put_label *put_label; + sljit_uw flags; + sljit_ins *inst; +#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64) + sljit_sw high; +#endif + sljit_uw addr; + + if (reg != 0) { + jump = (struct sljit_jump*)dst; + flags = jump->flags; + inst = (sljit_ins*)jump->addr; + addr = (flags & JUMP_LABEL) ? jump->u.label->addr : jump->u.target; + } else { + put_label = (struct sljit_put_label*)dst; +#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64) + flags = put_label->flags; +#endif + inst = (sljit_ins*)put_label->addr; + addr = put_label->label->addr; + reg = *inst; + } + + if ((addr & 0x800) != 0) + addr += 0x1000; + +#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32) + inst[0] = LUI | RD(reg) | (sljit_ins)((sljit_sw)addr & ~0xfff); +#else /* !SLJIT_CONFIG_RISCV_32 */ + + if (flags & PATCH_ABS32) { + SLJIT_ASSERT(addr <= S32_MAX); + inst[0] = LUI | RD(reg) | (sljit_ins)((sljit_sw)addr & ~0xfff); + } else if (flags & PATCH_ABS44) { + high = (sljit_sw)addr >> 12; + SLJIT_ASSERT((sljit_uw)high <= 0x7fffffff); + + if (high > S32_MAX) { + SLJIT_ASSERT((high & 0x800) != 0); + inst[0] = LUI | RD(reg) | (sljit_ins)0x80000000u; + inst[1] = XORI | RD(reg) | RS1(reg) | IMM_I(high); + } else { + if ((high & 0x800) != 0) + high += 0x1000; + + inst[0] = LUI | RD(reg) | (sljit_ins)(high & ~0xfff); + inst[1] = ADDI | RD(reg) | RS1(reg) | IMM_I(high); + } + + inst[2] = SLLI | RD(reg) | RS1(reg) | IMM_I(12); + inst += 2; + } else { + high = (sljit_sw)addr >> 32; + + if ((addr & 0x80000000l) != 0) + high = ~high; + + if ((high & 0x800) != 0) + high += 0x1000; + + if (flags & PATCH_ABS52) { + SLJIT_ASSERT(addr <= S52_MAX); + inst[0] = LUI | RD(TMP_REG3) | (sljit_ins)(high << 12); + } else { + inst[0] = LUI | RD(TMP_REG3) | (sljit_ins)(high & ~0xfff); + inst[1] = ADDI | RD(TMP_REG3) | RS1(TMP_REG3) | IMM_I(high); + inst++; + } + + inst[1] = LUI | RD(reg) | (sljit_ins)((sljit_sw)addr & ~0xfff); + inst[2] = SLLI | RD(TMP_REG3) | RS1(TMP_REG3) | IMM_I((flags & PATCH_ABS52) ? 20 : 32); + inst[3] = XOR | RD(reg) | RS1(reg) | RS2(TMP_REG3); + inst += 3; + } +#endif /* !SLJIT_CONFIG_RISCV_32 */ + + if (jump != NULL) { + SLJIT_ASSERT((inst[1] & 0x707f) == JALR); + inst[1] = (inst[1] & 0xfffff) | IMM_I(addr); + } else + inst[1] = ADDI | RD(reg) | RS1(reg) | IMM_I(addr); +} + +SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compiler) +{ + struct sljit_memory_fragment *buf; + sljit_ins *code; + sljit_ins *code_ptr; + sljit_ins *buf_ptr; + sljit_ins *buf_end; + sljit_uw word_count; + sljit_uw next_addr; + sljit_sw executable_offset; + sljit_uw addr; + + struct sljit_label *label; + struct sljit_jump *jump; + struct sljit_const *const_; + struct sljit_put_label *put_label; + + CHECK_ERROR_PTR(); + CHECK_PTR(check_sljit_generate_code(compiler)); + reverse_buf(compiler); + + code = (sljit_ins*)SLJIT_MALLOC_EXEC(compiler->size * sizeof(sljit_ins), compiler->exec_allocator_data); + PTR_FAIL_WITH_EXEC_IF(code); + buf = compiler->buf; + + code_ptr = code; + word_count = 0; + next_addr = 0; + executable_offset = SLJIT_EXEC_OFFSET(code); + + label = compiler->labels; + jump = compiler->jumps; + const_ = compiler->consts; + put_label = compiler->put_labels; + + do { + buf_ptr = (sljit_ins*)buf->memory; + buf_end = buf_ptr + (buf->used_size >> 2); + do { + *code_ptr = *buf_ptr++; + if (next_addr == word_count) { + SLJIT_ASSERT(!label || label->size >= word_count); + SLJIT_ASSERT(!jump || jump->addr >= word_count); + SLJIT_ASSERT(!const_ || const_->addr >= word_count); + SLJIT_ASSERT(!put_label || put_label->addr >= word_count); + + /* These structures are ordered by their address. */ + if (label && label->size == word_count) { + label->addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset); + label->size = (sljit_uw)(code_ptr - code); + label = label->next; + } + if (jump && jump->addr == word_count) { +#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32) + word_count += 1; +#else + word_count += 5; +#endif + jump->addr = (sljit_uw)code_ptr; + code_ptr = detect_jump_type(jump, code, executable_offset); + jump = jump->next; + } + if (const_ && const_->addr == word_count) { + const_->addr = (sljit_uw)code_ptr; + const_ = const_->next; + } + if (put_label && put_label->addr == word_count) { + SLJIT_ASSERT(put_label->label); + put_label->addr = (sljit_uw)code_ptr; +#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32) + code_ptr += 1; + word_count += 1; +#else + code_ptr += put_label_get_length(put_label, (sljit_uw)(SLJIT_ADD_EXEC_OFFSET(code, executable_offset) + put_label->label->size)); + word_count += 5; +#endif + put_label = put_label->next; + } + next_addr = compute_next_addr(label, jump, const_, put_label); + } + code_ptr++; + word_count++; + } while (buf_ptr < buf_end); + + buf = buf->next; + } while (buf); + + if (label && label->size == word_count) { + label->addr = (sljit_uw)code_ptr; + label->size = (sljit_uw)(code_ptr - code); + label = label->next; + } + + SLJIT_ASSERT(!label); + SLJIT_ASSERT(!jump); + SLJIT_ASSERT(!const_); + SLJIT_ASSERT(!put_label); + SLJIT_ASSERT(code_ptr - code <= (sljit_sw)compiler->size); + + jump = compiler->jumps; + while (jump) { + do { + if (!(jump->flags & (PATCH_B | PATCH_J | PATCH_REL32))) { + load_addr_to_reg(jump, TMP_REG1); + break; + } + + addr = (jump->flags & JUMP_LABEL) ? jump->u.label->addr : jump->u.target; + buf_ptr = (sljit_ins *)jump->addr; + addr -= (sljit_uw)SLJIT_ADD_EXEC_OFFSET(buf_ptr, executable_offset); + + if (jump->flags & PATCH_B) { + SLJIT_ASSERT((sljit_sw)addr >= BRANCH_MIN && (sljit_sw)addr <= BRANCH_MAX); + addr = ((addr & 0x800) >> 4) | ((addr & 0x1e) << 7) | ((addr & 0x7e0) << 20) | ((addr & 0x1000) << 19); + buf_ptr[0] |= (sljit_ins)addr; + break; + } + +#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64) + if (jump->flags & PATCH_REL32) { + SLJIT_ASSERT((sljit_sw)addr >= S32_MIN && (sljit_sw)addr <= S32_MAX); + + if ((addr & 0x800) != 0) + addr += 0x1000; + + buf_ptr[0] = AUIPC | RD(TMP_REG1) | (sljit_ins)((sljit_sw)addr & ~0xfff); + SLJIT_ASSERT((buf_ptr[1] & 0x707f) == JALR); + buf_ptr[1] |= IMM_I(addr); + break; + } +#endif + + SLJIT_ASSERT((sljit_sw)addr >= JUMP_MIN && (sljit_sw)addr <= JUMP_MAX); + addr = (addr & 0xff000) | ((addr & 0x800) << 9) | ((addr & 0x7fe) << 20) | ((addr & 0x100000) << 11); + buf_ptr[0] = JAL | RD((jump->flags & IS_CALL) ? RETURN_ADDR_REG : TMP_ZERO) | (sljit_ins)addr; + } while (0); + jump = jump->next; + } + + put_label = compiler->put_labels; + while (put_label) { + load_addr_to_reg(put_label, 0); + put_label = put_label->next; + } + + compiler->error = SLJIT_ERR_COMPILED; + compiler->executable_offset = executable_offset; + compiler->executable_size = (sljit_uw)(code_ptr - code) * sizeof(sljit_ins); + + code = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(code, executable_offset); + code_ptr = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset); + + SLJIT_CACHE_FLUSH(code, code_ptr); + SLJIT_UPDATE_WX_FLAGS(code, code_ptr, 1); + return code; +} + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type) +{ + switch (feature_type) { + case SLJIT_HAS_FPU: + case SLJIT_HAS_ZERO_REGISTER: + return 1; + default: + return 0; + } +} + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_cmp_info(sljit_s32 type) +{ + return (type >= SLJIT_ORDERED_EQUAL && type <= SLJIT_ORDERED_LESS_EQUAL); +} + +/* --------------------------------------------------------------------- */ +/* Entry, exit */ +/* --------------------------------------------------------------------- */ + +/* Creates an index in data_transfer_insts array. */ +#define LOAD_DATA 0x01 +#define WORD_DATA 0x00 +#define BYTE_DATA 0x02 +#define HALF_DATA 0x04 +#define INT_DATA 0x06 +#define SIGNED_DATA 0x08 +/* Separates integer and floating point registers */ +#define GPR_REG 0x0f +#define DOUBLE_DATA 0x10 +#define SINGLE_DATA 0x12 + +#define MEM_MASK 0x1f + +#define ARG_TEST 0x00020 +#define ALT_KEEP_CACHE 0x00040 +#define CUMULATIVE_OP 0x00080 +#define IMM_OP 0x00100 +#define MOVE_OP 0x00200 +#define SRC2_IMM 0x00400 + +#define UNUSED_DEST 0x00800 +#define REG_DEST 0x01000 +#define REG1_SOURCE 0x02000 +#define REG2_SOURCE 0x04000 +#define SLOW_SRC1 0x08000 +#define SLOW_SRC2 0x10000 +#define SLOW_DEST 0x20000 + +#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32) +#define STACK_STORE SW +#define STACK_LOAD LW +#else +#define STACK_STORE SD +#define STACK_LOAD LD +#endif + +#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32) +#include "sljitNativeRISCV_32.c" +#else +#include "sljitNativeRISCV_64.c" +#endif + +#define STACK_MAX_DISTANCE (-SIMM_MIN) + +static sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg, sljit_s32 arg, sljit_sw argw); + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compiler, + sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds, + sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size) +{ + sljit_s32 i, tmp, offset; + sljit_s32 saved_arg_count = SLJIT_KEPT_SAVEDS_COUNT(options); + + CHECK_ERROR(); + CHECK(check_sljit_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size)); + set_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size); + + local_size += GET_SAVED_REGISTERS_SIZE(scratches, saveds - saved_arg_count, 1); +#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32) + if (fsaveds > 0 || fscratches >= SLJIT_FIRST_SAVED_FLOAT_REG) { + if ((local_size & SSIZE_OF(sw)) != 0) + local_size += SSIZE_OF(sw); + local_size += GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, sizeof(sljit_f64)); + } +#else + local_size += GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, sizeof(sljit_f64)); +#endif + local_size = (local_size + SLJIT_LOCALS_OFFSET + 15) & ~0xf; + compiler->local_size = local_size; + + if (local_size <= STACK_MAX_DISTANCE) { + /* Frequent case. */ + FAIL_IF(push_inst(compiler, ADDI | RD(SLJIT_SP) | RS1(SLJIT_SP) | IMM_I(-local_size))); + offset = local_size - SSIZE_OF(sw); + local_size = 0; + } else { + FAIL_IF(push_inst(compiler, ADDI | RD(SLJIT_SP) | RS1(SLJIT_SP) | IMM_I(STACK_MAX_DISTANCE))); + local_size -= STACK_MAX_DISTANCE; + + if (local_size > STACK_MAX_DISTANCE) + FAIL_IF(load_immediate(compiler, TMP_REG1, local_size, TMP_REG3)); + offset = STACK_MAX_DISTANCE - SSIZE_OF(sw); + } + + FAIL_IF(push_imm_s_inst(compiler, STACK_STORE | RS1(SLJIT_SP) | RS2(RETURN_ADDR_REG), offset)); + + tmp = SLJIT_S0 - saveds; + for (i = SLJIT_S0 - saved_arg_count; i > tmp; i--) { + offset -= SSIZE_OF(sw); + FAIL_IF(push_imm_s_inst(compiler, STACK_STORE | RS1(SLJIT_SP) | RS2(i), offset)); + } + + for (i = scratches; i >= SLJIT_FIRST_SAVED_REG; i--) { + offset -= SSIZE_OF(sw); + FAIL_IF(push_imm_s_inst(compiler, STACK_STORE | RS1(SLJIT_SP) | RS2(i), offset)); + } + +#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32) + /* This alignment is valid because offset is not used after storing FPU regs. */ + if ((offset & SSIZE_OF(sw)) != 0) + offset -= SSIZE_OF(sw); +#endif + + tmp = SLJIT_FS0 - fsaveds; + for (i = SLJIT_FS0; i > tmp; i--) { + offset -= SSIZE_OF(f64); + FAIL_IF(push_imm_s_inst(compiler, FSD | RS1(SLJIT_SP) | FRS2(i), offset)); + } + + for (i = fscratches; i >= SLJIT_FIRST_SAVED_FLOAT_REG; i--) { + offset -= SSIZE_OF(f64); + FAIL_IF(push_imm_s_inst(compiler, FSD | RS1(SLJIT_SP) | FRS2(i), offset)); + } + + if (local_size > STACK_MAX_DISTANCE) + FAIL_IF(push_inst(compiler, SUB | RD(SLJIT_SP) | RS1(SLJIT_SP) | RS2(TMP_REG1))); + else if (local_size > 0) + FAIL_IF(push_inst(compiler, ADDI | RD(SLJIT_SP) | RS1(SLJIT_SP) | IMM_I(-local_size))); + + if (options & SLJIT_ENTER_REG_ARG) + return SLJIT_SUCCESS; + + arg_types >>= SLJIT_ARG_SHIFT; + saved_arg_count = 0; + tmp = SLJIT_R0; + + while (arg_types > 0) { + if ((arg_types & SLJIT_ARG_MASK) < SLJIT_ARG_TYPE_F64) { + if (!(arg_types & SLJIT_ARG_TYPE_SCRATCH_REG)) { + FAIL_IF(push_inst(compiler, ADDI | RD(SLJIT_S0 - saved_arg_count) | RS1(tmp) | IMM_I(0))); + saved_arg_count++; + } + tmp++; + } + + arg_types >>= SLJIT_ARG_SHIFT; + } + + return SLJIT_SUCCESS; +} + +#undef STACK_MAX_DISTANCE + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *compiler, + sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds, + sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size) +{ + CHECK_ERROR(); + CHECK(check_sljit_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size)); + set_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size); + + local_size += GET_SAVED_REGISTERS_SIZE(scratches, saveds - SLJIT_KEPT_SAVEDS_COUNT(options), 1); +#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32) + if (fsaveds > 0 || fscratches >= SLJIT_FIRST_SAVED_FLOAT_REG) { + if ((local_size & SSIZE_OF(sw)) != 0) + local_size += SSIZE_OF(sw); + local_size += GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, sizeof(sljit_f64)); + } +#else + local_size += GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, sizeof(sljit_f64)); +#endif + compiler->local_size = (local_size + SLJIT_LOCALS_OFFSET + 15) & ~0xf; + + return SLJIT_SUCCESS; +} + +#define STACK_MAX_DISTANCE (-SIMM_MIN - 16) + +static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler, sljit_s32 is_return_to) +{ + sljit_s32 i, tmp, offset; + sljit_s32 local_size = compiler->local_size; + + if (local_size > STACK_MAX_DISTANCE) { + local_size -= STACK_MAX_DISTANCE; + + if (local_size > STACK_MAX_DISTANCE) { + FAIL_IF(load_immediate(compiler, TMP_REG2, local_size, TMP_REG3)); + FAIL_IF(push_inst(compiler, ADD | RD(SLJIT_SP) | RS1(SLJIT_SP) | RS2(TMP_REG2))); + } else + FAIL_IF(push_inst(compiler, ADDI | RD(SLJIT_SP) | RS1(SLJIT_SP) | IMM_I(local_size))); + + local_size = STACK_MAX_DISTANCE; + } + + SLJIT_ASSERT(local_size > 0); + + offset = local_size - SSIZE_OF(sw); + if (!is_return_to) + FAIL_IF(push_inst(compiler, STACK_LOAD | RD(RETURN_ADDR_REG) | RS1(SLJIT_SP) | IMM_I(offset))); + + tmp = SLJIT_S0 - compiler->saveds; + for (i = SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options); i > tmp; i--) { + offset -= SSIZE_OF(sw); + FAIL_IF(push_inst(compiler, STACK_LOAD | RD(i) | RS1(SLJIT_SP) | IMM_I(offset))); + } + + for (i = compiler->scratches; i >= SLJIT_FIRST_SAVED_REG; i--) { + offset -= SSIZE_OF(sw); + FAIL_IF(push_inst(compiler, STACK_LOAD | RD(i) | RS1(SLJIT_SP) | IMM_I(offset))); + } + +#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32) + /* This alignment is valid because offset is not used after storing FPU regs. */ + if ((offset & SSIZE_OF(sw)) != 0) + offset -= SSIZE_OF(sw); +#endif + + tmp = SLJIT_FS0 - compiler->fsaveds; + for (i = SLJIT_FS0; i > tmp; i--) { + offset -= SSIZE_OF(f64); + FAIL_IF(push_inst(compiler, FLD | FRD(i) | RS1(SLJIT_SP) | IMM_I(offset))); + } + + for (i = compiler->fscratches; i >= SLJIT_FIRST_SAVED_FLOAT_REG; i--) { + offset -= SSIZE_OF(f64); + FAIL_IF(push_inst(compiler, FLD | FRD(i) | RS1(SLJIT_SP) | IMM_I(offset))); + } + + return push_inst(compiler, ADDI | RD(SLJIT_SP) | RS1(SLJIT_SP) | IMM_I(local_size)); +} + +#undef STACK_MAX_DISTANCE + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_void(struct sljit_compiler *compiler) +{ + CHECK_ERROR(); + CHECK(check_sljit_emit_return_void(compiler)); + + FAIL_IF(emit_stack_frame_release(compiler, 0)); + return push_inst(compiler, JALR | RD(TMP_ZERO) | RS1(RETURN_ADDR_REG) | IMM_I(0)); +} + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_to(struct sljit_compiler *compiler, + sljit_s32 src, sljit_sw srcw) +{ + CHECK_ERROR(); + CHECK(check_sljit_emit_return_to(compiler, src, srcw)); + + if (src & SLJIT_MEM) { + ADJUST_LOCAL_OFFSET(src, srcw); + FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, TMP_REG1, src, srcw)); + src = TMP_REG1; + srcw = 0; + } else if (src >= SLJIT_FIRST_SAVED_REG && src <= (SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options))) { + FAIL_IF(push_inst(compiler, ADDI | RD(TMP_REG1) | RS1(src) | IMM_I(0))); + src = TMP_REG1; + srcw = 0; + } + + FAIL_IF(emit_stack_frame_release(compiler, 1)); + + SLJIT_SKIP_CHECKS(compiler); + return sljit_emit_ijump(compiler, SLJIT_JUMP, src, srcw); +} + +/* --------------------------------------------------------------------- */ +/* Operators */ +/* --------------------------------------------------------------------- */ + +#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32) +#define ARCH_32_64(a, b) a +#else +#define ARCH_32_64(a, b) b +#endif + +static const sljit_ins data_transfer_insts[16 + 4] = { +/* u w s */ ARCH_32_64(F3(0x2) | OPC(0x23) /* sw */, F3(0x3) | OPC(0x23) /* sd */), +/* u w l */ ARCH_32_64(F3(0x2) | OPC(0x3) /* lw */, F3(0x3) | OPC(0x3) /* ld */), +/* u b s */ F3(0x0) | OPC(0x23) /* sb */, +/* u b l */ F3(0x4) | OPC(0x3) /* lbu */, +/* u h s */ F3(0x1) | OPC(0x23) /* sh */, +/* u h l */ F3(0x5) | OPC(0x3) /* lhu */, +/* u i s */ F3(0x2) | OPC(0x23) /* sw */, +/* u i l */ ARCH_32_64(F3(0x2) | OPC(0x3) /* lw */, F3(0x6) | OPC(0x3) /* lwu */), + +/* s w s */ ARCH_32_64(F3(0x2) | OPC(0x23) /* sw */, F3(0x3) | OPC(0x23) /* sd */), +/* s w l */ ARCH_32_64(F3(0x2) | OPC(0x3) /* lw */, F3(0x3) | OPC(0x3) /* ld */), +/* s b s */ F3(0x0) | OPC(0x23) /* sb */, +/* s b l */ F3(0x0) | OPC(0x3) /* lb */, +/* s h s */ F3(0x1) | OPC(0x23) /* sh */, +/* s h l */ F3(0x1) | OPC(0x3) /* lh */, +/* s i s */ F3(0x2) | OPC(0x23) /* sw */, +/* s i l */ F3(0x2) | OPC(0x3) /* lw */, + +/* d s */ F3(0x3) | OPC(0x27) /* fsd */, +/* d l */ F3(0x3) | OPC(0x7) /* fld */, +/* s s */ F3(0x2) | OPC(0x27) /* fsw */, +/* s l */ F3(0x2) | OPC(0x7) /* flw */, +}; + +#undef ARCH_32_64 + +static sljit_s32 push_mem_inst(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg, sljit_s32 base, sljit_sw offset) +{ + sljit_ins ins; + + SLJIT_ASSERT(FAST_IS_REG(base) && offset <= 0xfff && offset >= SIMM_MIN); + + ins = data_transfer_insts[flags & MEM_MASK] | RS1(base); + if (flags & LOAD_DATA) + ins |= ((flags & MEM_MASK) <= GPR_REG ? RD(reg) : FRD(reg)) | IMM_I(offset); + else + ins |= ((flags & MEM_MASK) <= GPR_REG ? RS2(reg) : FRS2(reg)) | IMM_S(offset); + + return push_inst(compiler, ins); +} + +/* Can perform an operation using at most 1 instruction. */ +static sljit_s32 getput_arg_fast(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg, sljit_s32 arg, sljit_sw argw) +{ + + SLJIT_ASSERT(arg & SLJIT_MEM); + + if (!(arg & OFFS_REG_MASK) && argw <= SIMM_MAX && argw >= SIMM_MIN) { + /* Works for both absoulte and relative addresses. */ + if (SLJIT_UNLIKELY(flags & ARG_TEST)) + return 1; + + FAIL_IF(push_mem_inst(compiler, flags, reg, arg & REG_MASK, argw)); + return -1; + } + return 0; +} + +#define TO_ARGW_HI(argw) (((argw) & ~0xfff) + (((argw) & 0x800) ? 0x1000 : 0)) + +/* See getput_arg below. + Note: can_cache is called only for binary operators. */ +static sljit_s32 can_cache(sljit_s32 arg, sljit_sw argw, sljit_s32 next_arg, sljit_sw next_argw) +{ + SLJIT_ASSERT((arg & SLJIT_MEM) && (next_arg & SLJIT_MEM)); + + /* Simple operation except for updates. */ + if (arg & OFFS_REG_MASK) { + argw &= 0x3; + next_argw &= 0x3; + if (argw && argw == next_argw && (arg == next_arg || (arg & OFFS_REG_MASK) == (next_arg & OFFS_REG_MASK))) + return 1; + return 0; + } + + if (arg == next_arg) { + if (((next_argw - argw) <= SIMM_MAX && (next_argw - argw) >= SIMM_MIN) + || TO_ARGW_HI(argw) == TO_ARGW_HI(next_argw)) + return 1; + return 0; + } + + return 0; +} + +/* Emit the necessary instructions. See can_cache above. */ +static sljit_s32 getput_arg(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg, sljit_s32 arg, sljit_sw argw, sljit_s32 next_arg, sljit_sw next_argw) +{ + sljit_s32 base = arg & REG_MASK; + sljit_s32 tmp_r = TMP_REG1; + sljit_sw offset, argw_hi; + + SLJIT_ASSERT(arg & SLJIT_MEM); + if (!(next_arg & SLJIT_MEM)) { + next_arg = 0; + next_argw = 0; + } + + /* Since tmp can be the same as base or offset registers, + * these might be unavailable after modifying tmp. */ + if ((flags & MEM_MASK) <= GPR_REG && (flags & LOAD_DATA)) + tmp_r = reg; + + if (SLJIT_UNLIKELY(arg & OFFS_REG_MASK)) { + argw &= 0x3; + + /* Using the cache. */ + if (argw == compiler->cache_argw) { + if (arg == compiler->cache_arg) + return push_mem_inst(compiler, flags, reg, TMP_REG3, 0); + + if ((SLJIT_MEM | (arg & OFFS_REG_MASK)) == compiler->cache_arg) { + if (arg == next_arg && argw == (next_argw & 0x3)) { + compiler->cache_arg = arg; + compiler->cache_argw = argw; + FAIL_IF(push_inst(compiler, ADD | RD(TMP_REG3) | RS1(TMP_REG3) | RS2(base))); + return push_mem_inst(compiler, flags, reg, TMP_REG3, 0); + } + FAIL_IF(push_inst(compiler, ADD | RD(tmp_r) | RS1(base) | RS2(TMP_REG3))); + return push_mem_inst(compiler, flags, reg, tmp_r, 0); + } + } + + if (SLJIT_UNLIKELY(argw)) { + compiler->cache_arg = SLJIT_MEM | (arg & OFFS_REG_MASK); + compiler->cache_argw = argw; + FAIL_IF(push_inst(compiler, SLLI | RD(TMP_REG3) | RS1(OFFS_REG(arg)) | IMM_I(argw))); + } + + if (arg == next_arg && argw == (next_argw & 0x3)) { + compiler->cache_arg = arg; + compiler->cache_argw = argw; + FAIL_IF(push_inst(compiler, ADD | RD(TMP_REG3) | RS1(base) | RS2(!argw ? OFFS_REG(arg) : TMP_REG3))); + tmp_r = TMP_REG3; + } + else + FAIL_IF(push_inst(compiler, ADD | RD(tmp_r) | RS1(base) | RS2(!argw ? OFFS_REG(arg) : TMP_REG3))); + return push_mem_inst(compiler, flags, reg, tmp_r, 0); + } + + if (compiler->cache_arg == arg && argw - compiler->cache_argw <= SIMM_MAX && argw - compiler->cache_argw >= SIMM_MIN) + return push_mem_inst(compiler, flags, reg, TMP_REG3, argw - compiler->cache_argw); + + if (compiler->cache_arg == SLJIT_MEM && (argw - compiler->cache_argw <= SIMM_MAX) && (argw - compiler->cache_argw >= SIMM_MIN)) { + offset = argw - compiler->cache_argw; + } else { + compiler->cache_arg = SLJIT_MEM; + + argw_hi = TO_ARGW_HI(argw); + + if (next_arg && next_argw - argw <= SIMM_MAX && next_argw - argw >= SIMM_MIN && argw_hi != TO_ARGW_HI(next_argw)) { + FAIL_IF(load_immediate(compiler, TMP_REG3, argw, tmp_r)); + compiler->cache_argw = argw; + offset = 0; + } else { + FAIL_IF(load_immediate(compiler, TMP_REG3, argw_hi, tmp_r)); + compiler->cache_argw = argw_hi; + offset = argw & 0xfff; + argw = argw_hi; + } + } + + if (!base) + return push_mem_inst(compiler, flags, reg, TMP_REG3, offset); + + if (arg == next_arg && next_argw - argw <= SIMM_MAX && next_argw - argw >= SIMM_MIN) { + compiler->cache_arg = arg; + FAIL_IF(push_inst(compiler, ADD | RD(TMP_REG3) | RS1(TMP_REG3) | RS2(base))); + return push_mem_inst(compiler, flags, reg, TMP_REG3, offset); + } + + FAIL_IF(push_inst(compiler, ADD | RD(tmp_r) | RS1(TMP_REG3) | RS2(base))); + return push_mem_inst(compiler, flags, reg, tmp_r, offset); +} + +static sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg, sljit_s32 arg, sljit_sw argw) +{ + sljit_s32 base = arg & REG_MASK; + sljit_s32 tmp_r = TMP_REG1; + + if (getput_arg_fast(compiler, flags, reg, arg, argw)) + return compiler->error; + + if ((flags & MEM_MASK) <= GPR_REG && (flags & LOAD_DATA)) + tmp_r = reg; + + if (SLJIT_UNLIKELY(arg & OFFS_REG_MASK)) { + argw &= 0x3; + + if (SLJIT_UNLIKELY(argw)) { + FAIL_IF(push_inst(compiler, SLLI | RD(tmp_r) | RS1(OFFS_REG(arg)) | IMM_I(argw))); + FAIL_IF(push_inst(compiler, ADD | RD(tmp_r) | RS1(tmp_r) | RS2(base))); + } + else + FAIL_IF(push_inst(compiler, ADD | RD(tmp_r) | RS1(base) | RS2(OFFS_REG(arg)))); + + argw = 0; + } else { + FAIL_IF(load_immediate(compiler, tmp_r, TO_ARGW_HI(argw), TMP_REG3)); + + if (base != 0) + FAIL_IF(push_inst(compiler, ADD | RD(tmp_r) | RS1(tmp_r) | RS2(base))); + } + + return push_mem_inst(compiler, flags, reg, tmp_r, argw & 0xfff); +} + +static SLJIT_INLINE sljit_s32 emit_op_mem2(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg, sljit_s32 arg1, sljit_sw arg1w, sljit_s32 arg2, sljit_sw arg2w) +{ + if (getput_arg_fast(compiler, flags, reg, arg1, arg1w)) + return compiler->error; + return getput_arg(compiler, flags, reg, arg1, arg1w, arg2, arg2w); +} + +#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32) +#define WORD 0 +#define IMM_EXTEND(v) (IMM_I(v)) +#else /* !SLJIT_CONFIG_RISCV_32 */ +#define WORD word +#define IMM_EXTEND(v) (IMM_I((op & SLJIT_32) ? (v) : (32 + (v)))) +#endif /* SLJIT_CONFIG_RISCV_32 */ + +static sljit_s32 emit_clz_ctz(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw src) +{ + sljit_s32 is_clz = (GET_OPCODE(op) == SLJIT_CLZ); +#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64) + sljit_ins word = (op & SLJIT_32) >> 5; + sljit_ins max = (op & SLJIT_32) ? 32 : 64; +#else /* !SLJIT_CONFIG_RISCV_64 */ + sljit_ins max = 32; +#endif /* SLJIT_CONFIG_RISCV_64 */ + + SLJIT_ASSERT(WORD == 0 || WORD == 0x8); + + /* The OTHER_FLAG is the counter. */ + FAIL_IF(push_inst(compiler, ADDI | WORD | RD(OTHER_FLAG) | RS1(TMP_ZERO) | IMM_I(max))); + + /* The TMP_REG2 is the next value. */ + if (src != TMP_REG2) + FAIL_IF(push_inst(compiler, ADDI | WORD | RD(TMP_REG2) | RS1(src) | IMM_I(0))); + + FAIL_IF(push_inst(compiler, BEQ | RS1(TMP_REG2) | RS2(TMP_ZERO) | ((sljit_ins)((is_clz ? 4 : 5) * SSIZE_OF(ins)) << 7) | ((sljit_ins)(8 * SSIZE_OF(ins)) << 20))); + + FAIL_IF(push_inst(compiler, ADDI | WORD | RD(OTHER_FLAG) | RS1(TMP_ZERO) | IMM_I(0))); + if (!is_clz) { + FAIL_IF(push_inst(compiler, ANDI | RD(TMP_REG1) | RS1(TMP_REG2) | IMM_I(1))); + FAIL_IF(push_inst(compiler, BNE | RS1(TMP_REG1) | RS2(TMP_ZERO) | ((sljit_ins)(2 * SSIZE_OF(ins)) << 7) | ((sljit_ins)(8 * SSIZE_OF(ins)) << 20))); + } else + FAIL_IF(push_inst(compiler, BLT | RS1(TMP_REG2) | RS2(TMP_ZERO) | ((sljit_ins)(2 * SSIZE_OF(ins)) << 7) | ((sljit_ins)(8 * SSIZE_OF(ins)) << 20))); + + /* The TMP_REG1 is the next shift. */ + FAIL_IF(push_inst(compiler, ADDI | WORD | RD(TMP_REG1) | RS1(TMP_ZERO) | IMM_I(max))); + + FAIL_IF(push_inst(compiler, ADDI | WORD | RD(EQUAL_FLAG) | RS1(TMP_REG2) | IMM_I(0))); + FAIL_IF(push_inst(compiler, SRLI | WORD | RD(TMP_REG1) | RS1(TMP_REG1) | IMM_I(1))); + + FAIL_IF(push_inst(compiler, (is_clz ? SRL : SLL) | WORD | RD(TMP_REG2) | RS1(EQUAL_FLAG) | RS2(TMP_REG1))); + FAIL_IF(push_inst(compiler, BNE | RS1(TMP_REG2) | RS2(TMP_ZERO) | ((sljit_ins)0xfe000e80 - ((2 * SSIZE_OF(ins)) << 7)))); + FAIL_IF(push_inst(compiler, ADDI | WORD | RD(TMP_REG2) | RS1(TMP_REG1) | IMM_I(-1))); + FAIL_IF(push_inst(compiler, (is_clz ? SRL : SLL) | WORD | RD(TMP_REG2) | RS1(EQUAL_FLAG) | RS2(TMP_REG2))); + FAIL_IF(push_inst(compiler, OR | RD(OTHER_FLAG) | RS1(OTHER_FLAG) | RS2(TMP_REG1))); + FAIL_IF(push_inst(compiler, BEQ | RS1(TMP_REG2) | RS2(TMP_ZERO) | ((sljit_ins)0xfe000e80 - ((5 * SSIZE_OF(ins)) << 7)))); + + return push_inst(compiler, ADDI | WORD | RD(dst) | RS1(OTHER_FLAG) | IMM_I(0)); +} + +#define EMIT_LOGICAL(op_imm, op_reg) \ + if (flags & SRC2_IMM) { \ + if (op & SLJIT_SET_Z) \ + FAIL_IF(push_inst(compiler, op_imm | RD(EQUAL_FLAG) | RS1(src1) | IMM_I(src2))); \ + if (!(flags & UNUSED_DEST)) \ + FAIL_IF(push_inst(compiler, op_imm | RD(dst) | RS1(src1) | IMM_I(src2))); \ + } \ + else { \ + if (op & SLJIT_SET_Z) \ + FAIL_IF(push_inst(compiler, op_reg | RD(EQUAL_FLAG) | RS1(src1) | RS2(src2))); \ + if (!(flags & UNUSED_DEST)) \ + FAIL_IF(push_inst(compiler, op_reg | RD(dst) | RS1(src1) | RS2(src2))); \ + } + +#define EMIT_SHIFT(imm, reg) \ + op_imm = (imm); \ + op_reg = (reg); + +static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 flags, + sljit_s32 dst, sljit_s32 src1, sljit_sw src2) +{ + sljit_s32 is_overflow, is_carry, carry_src_r, is_handled; + sljit_ins op_imm, op_reg; +#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64) + sljit_ins word = (op & SLJIT_32) >> 5; +#endif /* SLJIT_CONFIG_RISCV_64 */ + + SLJIT_ASSERT(WORD == 0 || WORD == 0x8); + + switch (GET_OPCODE(op)) { + case SLJIT_MOV: + SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM)); + if (dst != src2) + return push_inst(compiler, ADDI | RD(dst) | RS1(src2) | IMM_I(0)); + return SLJIT_SUCCESS; + + case SLJIT_MOV_U8: + SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM)); + if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) + return push_inst(compiler, ANDI | RD(dst) | RS1(src2) | IMM_I(0xff)); + SLJIT_ASSERT(dst == src2); + return SLJIT_SUCCESS; + + case SLJIT_MOV_S8: + SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM)); + if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) { + FAIL_IF(push_inst(compiler, SLLI | WORD | RD(dst) | RS1(src2) | IMM_EXTEND(24))); + return push_inst(compiler, SRAI | WORD | RD(dst) | RS1(dst) | IMM_EXTEND(24)); + } + SLJIT_ASSERT(dst == src2); + return SLJIT_SUCCESS; + + case SLJIT_MOV_U16: + SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM)); + if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) { + FAIL_IF(push_inst(compiler, SLLI | WORD | RD(dst) | RS1(src2) | IMM_EXTEND(16))); + return push_inst(compiler, SRLI | WORD | RD(dst) | RS1(dst) | IMM_EXTEND(16)); + } + SLJIT_ASSERT(dst == src2); + return SLJIT_SUCCESS; + + case SLJIT_MOV_S16: + SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM)); + if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) { + FAIL_IF(push_inst(compiler, SLLI | WORD | RD(dst) | RS1(src2) | IMM_EXTEND(16))); + return push_inst(compiler, SRAI | WORD | RD(dst) | RS1(dst) | IMM_EXTEND(16)); + } + SLJIT_ASSERT(dst == src2); + return SLJIT_SUCCESS; + +#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64) + case SLJIT_MOV_U32: + SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM)); + if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) { + FAIL_IF(push_inst(compiler, SLLI | RD(dst) | RS1(src2) | IMM_I(32))); + return push_inst(compiler, SRLI | RD(dst) | RS1(dst) | IMM_I(32)); + } + SLJIT_ASSERT(dst == src2); + return SLJIT_SUCCESS; + + case SLJIT_MOV_S32: + SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM)); + if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) + return push_inst(compiler, ADDI | 0x8 | RD(dst) | RS1(src2) | IMM_I(0)); + SLJIT_ASSERT(dst == src2); + return SLJIT_SUCCESS; +#endif /* SLJIT_CONFIG_RISCV_64 */ + + case SLJIT_CLZ: + case SLJIT_CTZ: + SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM)); + return emit_clz_ctz(compiler, op, dst, src2); + + case SLJIT_ADD: + /* Overflow computation (both add and sub): overflow = src1_sign ^ src2_sign ^ result_sign ^ carry_flag */ + is_overflow = GET_FLAG_TYPE(op) == SLJIT_OVERFLOW; + carry_src_r = GET_FLAG_TYPE(op) == GET_FLAG_TYPE(SLJIT_SET_CARRY); + + if (flags & SRC2_IMM) { + if (is_overflow) { + if (src2 >= 0) + FAIL_IF(push_inst(compiler, ADDI | RD(EQUAL_FLAG) | RS1(src1) | IMM_I(0))); + else + FAIL_IF(push_inst(compiler, XORI | RD(EQUAL_FLAG) | RS1(src1) | IMM_I(-1))); + } + else if (op & SLJIT_SET_Z) + FAIL_IF(push_inst(compiler, ADDI | WORD | RD(EQUAL_FLAG) | RS1(src1) | IMM_I(src2))); + + /* Only the zero flag is needed. */ + if (!(flags & UNUSED_DEST) || (op & VARIABLE_FLAG_MASK)) + FAIL_IF(push_inst(compiler, ADDI | WORD | RD(dst) | RS1(src1) | IMM_I(src2))); + } + else { + if (is_overflow) + FAIL_IF(push_inst(compiler, XOR | RD(EQUAL_FLAG) | RS1(src1) | RS2(src2))); + else if (op & SLJIT_SET_Z) + FAIL_IF(push_inst(compiler, ADD | WORD | RD(EQUAL_FLAG) | RS1(src1) | RS2(src2))); + + if (is_overflow || carry_src_r != 0) { + if (src1 != dst) + carry_src_r = (sljit_s32)src1; + else if (src2 != dst) + carry_src_r = (sljit_s32)src2; + else { + FAIL_IF(push_inst(compiler, ADDI | RD(OTHER_FLAG) | RS1(src1) | IMM_I(0))); + carry_src_r = OTHER_FLAG; + } + } + + /* Only the zero flag is needed. */ + if (!(flags & UNUSED_DEST) || (op & VARIABLE_FLAG_MASK)) + FAIL_IF(push_inst(compiler, ADD | WORD | RD(dst) | RS1(src1) | RS2(src2))); + } + + /* Carry is zero if a + b >= a or a + b >= b, otherwise it is 1. */ + if (is_overflow || carry_src_r != 0) { + if (flags & SRC2_IMM) + FAIL_IF(push_inst(compiler, SLTUI | RD(OTHER_FLAG) | RS1(dst) | IMM_I(src2))); + else + FAIL_IF(push_inst(compiler, SLTU | RD(OTHER_FLAG) | RS1(dst) | RS2(carry_src_r))); + } + + if (!is_overflow) + return SLJIT_SUCCESS; + + FAIL_IF(push_inst(compiler, XOR | RD(TMP_REG1) | RS1(dst) | RS2(EQUAL_FLAG))); + if (op & SLJIT_SET_Z) + FAIL_IF(push_inst(compiler, ADDI | RD(EQUAL_FLAG) | RS1(dst) | IMM_I(0))); + FAIL_IF(push_inst(compiler, SRLI | WORD | RD(TMP_REG1) | RS1(TMP_REG1) | IMM_EXTEND(31))); + return push_inst(compiler, XOR | RD(OTHER_FLAG) | RS1(TMP_REG1) | RS2(OTHER_FLAG)); + + case SLJIT_ADDC: + carry_src_r = GET_FLAG_TYPE(op) == GET_FLAG_TYPE(SLJIT_SET_CARRY); + + if (flags & SRC2_IMM) { + FAIL_IF(push_inst(compiler, ADDI | WORD | RD(dst) | RS1(src1) | IMM_I(src2))); + } else { + if (carry_src_r != 0) { + if (src1 != dst) + carry_src_r = (sljit_s32)src1; + else if (src2 != dst) + carry_src_r = (sljit_s32)src2; + else { + FAIL_IF(push_inst(compiler, ADDI | RD(EQUAL_FLAG) | RS1(src1) | IMM_I(0))); + carry_src_r = EQUAL_FLAG; + } + } + + FAIL_IF(push_inst(compiler, ADD | WORD | RD(dst) | RS1(src1) | RS2(src2))); + } + + /* Carry is zero if a + b >= a or a + b >= b, otherwise it is 1. */ + if (carry_src_r != 0) { + if (flags & SRC2_IMM) + FAIL_IF(push_inst(compiler, SLTUI | RD(EQUAL_FLAG) | RS1(dst) | IMM_I(src2))); + else + FAIL_IF(push_inst(compiler, SLTU | RD(EQUAL_FLAG) | RS1(dst) | RS2(carry_src_r))); + } + + FAIL_IF(push_inst(compiler, ADD | WORD | RD(dst) | RS1(dst) | RS2(OTHER_FLAG))); + + if (carry_src_r == 0) + return SLJIT_SUCCESS; + + /* Set ULESS_FLAG (dst == 0) && (OTHER_FLAG == 1). */ + FAIL_IF(push_inst(compiler, SLTU | RD(OTHER_FLAG) | RS1(dst) | RS2(OTHER_FLAG))); + /* Set carry flag. */ + return push_inst(compiler, OR | RD(OTHER_FLAG) | RS1(OTHER_FLAG) | RS2(EQUAL_FLAG)); + + case SLJIT_SUB: + if ((flags & SRC2_IMM) && src2 == SIMM_MIN) { + FAIL_IF(push_inst(compiler, ADDI | RD(TMP_REG2) | RS1(TMP_ZERO) | IMM_I(src2))); + src2 = TMP_REG2; + flags &= ~SRC2_IMM; + } + + is_handled = 0; + + if (flags & SRC2_IMM) { + if (GET_FLAG_TYPE(op) == SLJIT_LESS || GET_FLAG_TYPE(op) == SLJIT_GREATER_EQUAL) { + FAIL_IF(push_inst(compiler, SLTUI | RD(OTHER_FLAG) | RS1(src1) | IMM_I(src2))); + is_handled = 1; + } + else if (GET_FLAG_TYPE(op) == SLJIT_SIG_LESS || GET_FLAG_TYPE(op) == SLJIT_SIG_GREATER_EQUAL) { + FAIL_IF(push_inst(compiler, SLTI | RD(OTHER_FLAG) | RS1(src1) | IMM_I(src2))); + is_handled = 1; + } + } + + if (!is_handled && GET_FLAG_TYPE(op) >= SLJIT_LESS && GET_FLAG_TYPE(op) <= SLJIT_SIG_LESS_EQUAL) { + is_handled = 1; + + if (flags & SRC2_IMM) { + FAIL_IF(push_inst(compiler, ADDI | RD(TMP_REG2) | RS1(TMP_ZERO) | IMM_I(src2))); + src2 = TMP_REG2; + flags &= ~SRC2_IMM; + } + + switch (GET_FLAG_TYPE(op)) { + case SLJIT_LESS: + case SLJIT_GREATER_EQUAL: + FAIL_IF(push_inst(compiler, SLTU | RD(OTHER_FLAG) | RS1(src1) | RS2(src2))); + break; + case SLJIT_GREATER: + case SLJIT_LESS_EQUAL: + FAIL_IF(push_inst(compiler, SLTU | RD(OTHER_FLAG) | RS1(src2) | RS2(src1))); + break; + case SLJIT_SIG_LESS: + case SLJIT_SIG_GREATER_EQUAL: + FAIL_IF(push_inst(compiler, SLT | RD(OTHER_FLAG) | RS1(src1) | RS2(src2))); + break; + case SLJIT_SIG_GREATER: + case SLJIT_SIG_LESS_EQUAL: + FAIL_IF(push_inst(compiler, SLT | RD(OTHER_FLAG) | RS1(src2) | RS2(src1))); + break; + } + } + + if (is_handled) { + if (flags & SRC2_IMM) { + if (op & SLJIT_SET_Z) + FAIL_IF(push_inst(compiler, ADDI | WORD | RD(EQUAL_FLAG) | RS1(src1) | IMM_I(-src2))); + if (!(flags & UNUSED_DEST)) + return push_inst(compiler, ADDI | WORD | RD(dst) | RS1(src1) | IMM_I(-src2)); + } + else { + if (op & SLJIT_SET_Z) + FAIL_IF(push_inst(compiler, SUB | WORD | RD(EQUAL_FLAG) | RS1(src1) | RS2(src2))); + if (!(flags & UNUSED_DEST)) + return push_inst(compiler, SUB | WORD | RD(dst) | RS1(src1) | RS2(src2)); + } + return SLJIT_SUCCESS; + } + + is_overflow = GET_FLAG_TYPE(op) == SLJIT_OVERFLOW; + is_carry = GET_FLAG_TYPE(op) == GET_FLAG_TYPE(SLJIT_SET_CARRY); + + if (flags & SRC2_IMM) { + if (is_overflow) { + if (src2 >= 0) + FAIL_IF(push_inst(compiler, ADDI | RD(EQUAL_FLAG) | RS1(src1) | IMM_I(0))); + else + FAIL_IF(push_inst(compiler, XORI | RD(EQUAL_FLAG) | RS1(src1) | IMM_I(-1))); + } + else if (op & SLJIT_SET_Z) + FAIL_IF(push_inst(compiler, ADDI | WORD | RD(EQUAL_FLAG) | RS1(src1) | IMM_I(-src2))); + + if (is_overflow || is_carry) + FAIL_IF(push_inst(compiler, SLTUI | RD(OTHER_FLAG) | RS1(src1) | IMM_I(src2))); + + /* Only the zero flag is needed. */ + if (!(flags & UNUSED_DEST) || (op & VARIABLE_FLAG_MASK)) + FAIL_IF(push_inst(compiler, ADDI | WORD | RD(dst) | RS1(src1) | IMM_I(-src2))); + } + else { + if (is_overflow) + FAIL_IF(push_inst(compiler, XOR | RD(EQUAL_FLAG) | RS1(src1) | RS2(src2))); + else if (op & SLJIT_SET_Z) + FAIL_IF(push_inst(compiler, SUB | WORD | RD(EQUAL_FLAG) | RS1(src1) | RS2(src2))); + + if (is_overflow || is_carry) + FAIL_IF(push_inst(compiler, SLTU | RD(OTHER_FLAG) | RS1(src1) | RS2(src2))); + + /* Only the zero flag is needed. */ + if (!(flags & UNUSED_DEST) || (op & VARIABLE_FLAG_MASK)) + FAIL_IF(push_inst(compiler, SUB | WORD | RD(dst) | RS1(src1) | RS2(src2))); + } + + if (!is_overflow) + return SLJIT_SUCCESS; + + FAIL_IF(push_inst(compiler, XOR | RD(TMP_REG1) | RS1(dst) | RS2(EQUAL_FLAG))); + if (op & SLJIT_SET_Z) + FAIL_IF(push_inst(compiler, ADDI | RD(EQUAL_FLAG) | RS1(dst) | IMM_I(0))); + FAIL_IF(push_inst(compiler, SRLI | WORD | RD(TMP_REG1) | RS1(TMP_REG1) | IMM_EXTEND(31))); + return push_inst(compiler, XOR | RD(OTHER_FLAG) | RS1(TMP_REG1) | RS2(OTHER_FLAG)); + + case SLJIT_SUBC: + if ((flags & SRC2_IMM) && src2 == SIMM_MIN) { + FAIL_IF(push_inst(compiler, ADDI | RD(TMP_REG2) | RS1(TMP_ZERO) | IMM_I(src2))); + src2 = TMP_REG2; + flags &= ~SRC2_IMM; + } + + is_carry = GET_FLAG_TYPE(op) == GET_FLAG_TYPE(SLJIT_SET_CARRY); + + if (flags & SRC2_IMM) { + if (is_carry) + FAIL_IF(push_inst(compiler, SLTUI | RD(EQUAL_FLAG) | RS1(src1) | IMM_I(src2))); + + FAIL_IF(push_inst(compiler, ADDI | WORD | RD(dst) | RS1(src1) | IMM_I(-src2))); + } + else { + if (is_carry) + FAIL_IF(push_inst(compiler, SLTU | RD(EQUAL_FLAG) | RS1(src1) | RS2(src2))); + + FAIL_IF(push_inst(compiler, SUB | WORD | RD(dst) | RS1(src1) | RS2(src2))); + } + + if (is_carry) + FAIL_IF(push_inst(compiler, SLTU | RD(TMP_REG1) | RS1(dst) | RS2(OTHER_FLAG))); + + FAIL_IF(push_inst(compiler, SUB | WORD | RD(dst) | RS1(dst) | RS2(OTHER_FLAG))); + + if (!is_carry) + return SLJIT_SUCCESS; + + return push_inst(compiler, OR | RD(OTHER_FLAG) | RS1(EQUAL_FLAG) | RS2(TMP_REG1)); + + case SLJIT_MUL: + SLJIT_ASSERT(!(flags & SRC2_IMM)); + + if (GET_FLAG_TYPE(op) != SLJIT_OVERFLOW) + return push_inst(compiler, MUL | WORD | RD(dst) | RS1(src1) | RS2(src2)); + +#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64) + if (word) { + FAIL_IF(push_inst(compiler, MUL | RD(OTHER_FLAG) | RS1(src1) | RS2(src2))); + FAIL_IF(push_inst(compiler, MUL | 0x8 | RD(dst) | RS1(src1) | RS2(src2))); + return push_inst(compiler, SUB | RD(OTHER_FLAG) | RS1(dst) | RS2(OTHER_FLAG)); + } +#endif /* SLJIT_CONFIG_RISCV_64 */ + + FAIL_IF(push_inst(compiler, MULH | RD(EQUAL_FLAG) | RS1(src1) | RS2(src2))); + FAIL_IF(push_inst(compiler, MUL | RD(dst) | RS1(src1) | RS2(src2))); +#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32) + FAIL_IF(push_inst(compiler, SRAI | RD(OTHER_FLAG) | RS1(dst) | IMM_I(31))); +#else /* !SLJIT_CONFIG_RISCV_32 */ + FAIL_IF(push_inst(compiler, SRAI | RD(OTHER_FLAG) | RS1(dst) | IMM_I(63))); +#endif /* SLJIT_CONFIG_RISCV_32 */ + return push_inst(compiler, SUB | RD(OTHER_FLAG) | RS1(EQUAL_FLAG) | RS2(OTHER_FLAG)); + + case SLJIT_AND: + EMIT_LOGICAL(ANDI, AND); + return SLJIT_SUCCESS; + + case SLJIT_OR: + EMIT_LOGICAL(ORI, OR); + return SLJIT_SUCCESS; + + case SLJIT_XOR: + EMIT_LOGICAL(XORI, XOR); + return SLJIT_SUCCESS; + + case SLJIT_SHL: + case SLJIT_MSHL: + EMIT_SHIFT(SLLI, SLL); + break; + + case SLJIT_LSHR: + case SLJIT_MLSHR: + EMIT_SHIFT(SRLI, SRL); + break; + + case SLJIT_ASHR: + case SLJIT_MASHR: + EMIT_SHIFT(SRAI, SRA); + break; + + case SLJIT_ROTL: + case SLJIT_ROTR: + if (flags & SRC2_IMM) { + SLJIT_ASSERT(src2 != 0); + + op_imm = (GET_OPCODE(op) == SLJIT_ROTL) ? SLLI : SRLI; + FAIL_IF(push_inst(compiler, op_imm | WORD | RD(OTHER_FLAG) | RS1(src1) | IMM_I(src2))); + +#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64) + src2 = ((op & SLJIT_32) ? 32 : 64) - src2; +#else /* !SLJIT_CONFIG_RISCV_64 */ + src2 = 32 - src2; +#endif /* SLJIT_CONFIG_RISCV_64 */ + op_imm = (GET_OPCODE(op) == SLJIT_ROTL) ? SRLI : SLLI; + FAIL_IF(push_inst(compiler, op_imm | WORD | RD(dst) | RS1(src1) | IMM_I(src2))); + return push_inst(compiler, OR | RD(dst) | RS1(dst) | RS2(OTHER_FLAG)); + } + + if (src2 == TMP_ZERO) { + if (dst != src1) + return push_inst(compiler, ADDI | WORD | RD(dst) | RS1(src1) | IMM_I(0)); + return SLJIT_SUCCESS; + } + + FAIL_IF(push_inst(compiler, SUB | WORD | RD(EQUAL_FLAG) | RS1(TMP_ZERO) | RS2(src2))); + op_reg = (GET_OPCODE(op) == SLJIT_ROTL) ? SLL : SRL; + FAIL_IF(push_inst(compiler, op_reg | WORD | RD(OTHER_FLAG) | RS1(src1) | RS2(src2))); + op_reg = (GET_OPCODE(op) == SLJIT_ROTL) ? SRL : SLL; + FAIL_IF(push_inst(compiler, op_reg | WORD | RD(dst) | RS1(src1) | RS2(EQUAL_FLAG))); + return push_inst(compiler, OR | RD(dst) | RS1(dst) | RS2(OTHER_FLAG)); + + default: + SLJIT_UNREACHABLE(); + return SLJIT_SUCCESS; + } + + if (flags & SRC2_IMM) { + if (op & SLJIT_SET_Z) + FAIL_IF(push_inst(compiler, op_imm | WORD | RD(EQUAL_FLAG) | RS1(src1) | IMM_I(src2))); + + if (flags & UNUSED_DEST) + return SLJIT_SUCCESS; + return push_inst(compiler, op_imm | WORD | RD(dst) | RS1(src1) | IMM_I(src2)); + } + + if (op & SLJIT_SET_Z) + FAIL_IF(push_inst(compiler, op_reg | WORD | RD(EQUAL_FLAG) | RS1(src1) | RS2(src2))); + + if (flags & UNUSED_DEST) + return SLJIT_SUCCESS; + return push_inst(compiler, op_reg | WORD | RD(dst) | RS1(src1) | RS2(src2)); +} + +#undef IMM_EXTEND + +static sljit_s32 emit_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 flags, + sljit_s32 dst, sljit_sw dstw, + sljit_s32 src1, sljit_sw src1w, + sljit_s32 src2, sljit_sw src2w) +{ + /* arg1 goes to TMP_REG1 or src reg + arg2 goes to TMP_REG2, imm or src reg + TMP_REG3 can be used for caching + result goes to TMP_REG2, so put result can use TMP_REG1 and TMP_REG3. */ + sljit_s32 dst_r = TMP_REG2; + sljit_s32 src1_r; + sljit_sw src2_r = 0; + sljit_s32 sugg_src2_r = TMP_REG2; + + if (!(flags & ALT_KEEP_CACHE)) { + compiler->cache_arg = 0; + compiler->cache_argw = 0; + } + + if (dst == TMP_REG2) { + SLJIT_ASSERT(HAS_FLAGS(op)); + flags |= UNUSED_DEST; + } + else if (FAST_IS_REG(dst)) { + dst_r = dst; + flags |= REG_DEST; + if (flags & MOVE_OP) + sugg_src2_r = dst_r; + } + else if ((dst & SLJIT_MEM) && !getput_arg_fast(compiler, flags | ARG_TEST, TMP_REG1, dst, dstw)) + flags |= SLOW_DEST; + + if (flags & IMM_OP) { + if ((src2 & SLJIT_IMM) && src2w != 0 && src2w <= SIMM_MAX && src2w >= SIMM_MIN) { + flags |= SRC2_IMM; + src2_r = src2w; + } + else if ((flags & CUMULATIVE_OP) && (src1 & SLJIT_IMM) && src1w != 0 && src1w <= SIMM_MAX && src1w >= SIMM_MIN) { + flags |= SRC2_IMM; + src2_r = src1w; + + /* And swap arguments. */ + src1 = src2; + src1w = src2w; + src2 = SLJIT_IMM; + /* src2w = src2_r unneeded. */ + } + } + + /* Source 1. */ + if (FAST_IS_REG(src1)) { + src1_r = src1; + flags |= REG1_SOURCE; + } + else if (src1 & SLJIT_IMM) { + if (src1w) { + FAIL_IF(load_immediate(compiler, TMP_REG1, src1w, TMP_REG3)); + src1_r = TMP_REG1; + } + else + src1_r = TMP_ZERO; + } + else { + if (getput_arg_fast(compiler, flags | LOAD_DATA, TMP_REG1, src1, src1w)) + FAIL_IF(compiler->error); + else + flags |= SLOW_SRC1; + src1_r = TMP_REG1; + } + + /* Source 2. */ + if (FAST_IS_REG(src2)) { + src2_r = src2; + flags |= REG2_SOURCE; + if ((flags & (REG_DEST | MOVE_OP)) == MOVE_OP) + dst_r = (sljit_s32)src2_r; + } + else if (src2 & SLJIT_IMM) { + if (!(flags & SRC2_IMM)) { + if (src2w) { + FAIL_IF(load_immediate(compiler, sugg_src2_r, src2w, TMP_REG3)); + src2_r = sugg_src2_r; + } + else { + src2_r = TMP_ZERO; + if (flags & MOVE_OP) { + if (dst & SLJIT_MEM) + dst_r = 0; + else + op = SLJIT_MOV; + } + } + } + } + else { + if (getput_arg_fast(compiler, flags | LOAD_DATA, sugg_src2_r, src2, src2w)) + FAIL_IF(compiler->error); + else + flags |= SLOW_SRC2; + src2_r = sugg_src2_r; + } + + if ((flags & (SLOW_SRC1 | SLOW_SRC2)) == (SLOW_SRC1 | SLOW_SRC2)) { + SLJIT_ASSERT(src2_r == TMP_REG2); + if (!can_cache(src1, src1w, src2, src2w) && can_cache(src1, src1w, dst, dstw)) { + FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, TMP_REG2, src2, src2w, src1, src1w)); + FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, TMP_REG1, src1, src1w, dst, dstw)); + } + else { + FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, TMP_REG1, src1, src1w, src2, src2w)); + FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, TMP_REG2, src2, src2w, dst, dstw)); + } + } + else if (flags & SLOW_SRC1) + FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, TMP_REG1, src1, src1w, dst, dstw)); + else if (flags & SLOW_SRC2) + FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, sugg_src2_r, src2, src2w, dst, dstw)); + + FAIL_IF(emit_single_op(compiler, op, flags, dst_r, src1_r, src2_r)); + + if (dst & SLJIT_MEM) { + if (!(flags & SLOW_DEST)) { + getput_arg_fast(compiler, flags, dst_r, dst, dstw); + return compiler->error; + } + return getput_arg(compiler, flags, dst_r, dst, dstw, 0, 0); + } + + return SLJIT_SUCCESS; +} + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compiler, sljit_s32 op) +{ +#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64) + sljit_ins word = (op & SLJIT_32) >> 5; + + SLJIT_ASSERT(word == 0 || word == 0x8); +#endif /* SLJIT_CONFIG_RISCV_64 */ + + CHECK_ERROR(); + CHECK(check_sljit_emit_op0(compiler, op)); + + switch (GET_OPCODE(op)) { + case SLJIT_BREAKPOINT: + return push_inst(compiler, EBREAK); + case SLJIT_NOP: + return push_inst(compiler, ADDI | RD(TMP_ZERO) | RS1(TMP_ZERO) | IMM_I(0)); + case SLJIT_LMUL_UW: + FAIL_IF(push_inst(compiler, ADDI | RD(TMP_REG1) | RS1(SLJIT_R1) | IMM_I(0))); + FAIL_IF(push_inst(compiler, MULHU | RD(SLJIT_R1) | RS1(SLJIT_R0) | RS2(SLJIT_R1))); + return push_inst(compiler, MUL | RD(SLJIT_R0) | RS1(SLJIT_R0) | RS2(TMP_REG1)); + case SLJIT_LMUL_SW: + FAIL_IF(push_inst(compiler, ADDI | RD(TMP_REG1) | RS1(SLJIT_R1) | IMM_I(0))); + FAIL_IF(push_inst(compiler, MULH | RD(SLJIT_R1) | RS1(SLJIT_R0) | RS2(SLJIT_R1))); + return push_inst(compiler, MUL | RD(SLJIT_R0) | RS1(SLJIT_R0) | RS2(TMP_REG1)); + case SLJIT_DIVMOD_UW: + FAIL_IF(push_inst(compiler, ADDI | RD(TMP_REG1) | RS1(SLJIT_R0) | IMM_I(0))); + FAIL_IF(push_inst(compiler, DIVU | WORD | RD(SLJIT_R0) | RS1(SLJIT_R0) | RS2(SLJIT_R1))); + return push_inst(compiler, REMU | WORD | RD(SLJIT_R1) | RS1(TMP_REG1) | RS2(SLJIT_R1)); + case SLJIT_DIVMOD_SW: + FAIL_IF(push_inst(compiler, ADDI | RD(TMP_REG1) | RS1(SLJIT_R0) | IMM_I(0))); + FAIL_IF(push_inst(compiler, DIV | WORD | RD(SLJIT_R0) | RS1(SLJIT_R0) | RS2(SLJIT_R1))); + return push_inst(compiler, REM | WORD | RD(SLJIT_R1) | RS1(TMP_REG1) | RS2(SLJIT_R1)); + case SLJIT_DIV_UW: + return push_inst(compiler, DIVU | WORD | RD(SLJIT_R0) | RS1(SLJIT_R0) | RS2(SLJIT_R1)); + case SLJIT_DIV_SW: + return push_inst(compiler, DIV | WORD | RD(SLJIT_R0) | RS1(SLJIT_R0) | RS2(SLJIT_R1)); + case SLJIT_ENDBR: + case SLJIT_SKIP_FRAMES_BEFORE_RETURN: + return SLJIT_SUCCESS; + } + + return SLJIT_SUCCESS; +} + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compiler, sljit_s32 op, + sljit_s32 dst, sljit_sw dstw, + sljit_s32 src, sljit_sw srcw) +{ + sljit_s32 flags = 0; + + CHECK_ERROR(); + CHECK(check_sljit_emit_op1(compiler, op, dst, dstw, src, srcw)); + ADJUST_LOCAL_OFFSET(dst, dstw); + ADJUST_LOCAL_OFFSET(src, srcw); + +#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64) + if (op & SLJIT_32) + flags = INT_DATA | SIGNED_DATA; +#endif + + switch (GET_OPCODE(op)) { + case SLJIT_MOV: +#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32) + case SLJIT_MOV_U32: + case SLJIT_MOV_S32: + case SLJIT_MOV32: +#endif + case SLJIT_MOV_P: + return emit_op(compiler, SLJIT_MOV, WORD_DATA | MOVE_OP, dst, dstw, TMP_REG1, 0, src, srcw); + +#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64) + case SLJIT_MOV_U32: + return emit_op(compiler, SLJIT_MOV_U32, INT_DATA | MOVE_OP, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_u32)srcw : srcw); + + case SLJIT_MOV_S32: + /* Logical operators have no W variant, so sign extended input is necessary for them. */ + case SLJIT_MOV32: + return emit_op(compiler, SLJIT_MOV_S32, INT_DATA | SIGNED_DATA | MOVE_OP, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_s32)srcw : srcw); +#endif + + case SLJIT_MOV_U8: + return emit_op(compiler, op, BYTE_DATA | MOVE_OP, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_u8)srcw : srcw); + + case SLJIT_MOV_S8: + return emit_op(compiler, op, BYTE_DATA | SIGNED_DATA | MOVE_OP, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_s8)srcw : srcw); + + case SLJIT_MOV_U16: + return emit_op(compiler, op, HALF_DATA | MOVE_OP, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_u16)srcw : srcw); + + case SLJIT_MOV_S16: + return emit_op(compiler, op, HALF_DATA | SIGNED_DATA | MOVE_OP, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_s16)srcw : srcw); + + case SLJIT_NOT: + return emit_op(compiler, SLJIT_XOR | (op & (SLJIT_32 | SLJIT_SET_Z)), flags, dst, dstw, src, srcw, SLJIT_IMM, -1); + + case SLJIT_CLZ: + case SLJIT_CTZ: + return emit_op(compiler, op, flags, dst, dstw, TMP_REG1, 0, src, srcw); + } + + SLJIT_UNREACHABLE(); + return SLJIT_SUCCESS; +} + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compiler, sljit_s32 op, + sljit_s32 dst, sljit_sw dstw, + sljit_s32 src1, sljit_sw src1w, + sljit_s32 src2, sljit_sw src2w) +{ + sljit_s32 flags = 0; + + CHECK_ERROR(); + CHECK(check_sljit_emit_op2(compiler, op, 0, dst, dstw, src1, src1w, src2, src2w)); + ADJUST_LOCAL_OFFSET(dst, dstw); + ADJUST_LOCAL_OFFSET(src1, src1w); + ADJUST_LOCAL_OFFSET(src2, src2w); + +#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64) + if (op & SLJIT_32) { + flags |= INT_DATA | SIGNED_DATA; + if (src1 & SLJIT_IMM) + src1w = (sljit_s32)src1w; + if (src2 & SLJIT_IMM) + src2w = (sljit_s32)src2w; + } +#endif + + switch (GET_OPCODE(op)) { + case SLJIT_ADD: + case SLJIT_ADDC: + compiler->status_flags_state = SLJIT_CURRENT_FLAGS_ADD; + return emit_op(compiler, op, flags | CUMULATIVE_OP | IMM_OP, dst, dstw, src1, src1w, src2, src2w); + + case SLJIT_SUB: + case SLJIT_SUBC: + compiler->status_flags_state = SLJIT_CURRENT_FLAGS_SUB; + return emit_op(compiler, op, flags | IMM_OP, dst, dstw, src1, src1w, src2, src2w); + + case SLJIT_MUL: + compiler->status_flags_state = 0; + return emit_op(compiler, op, flags | CUMULATIVE_OP, dst, dstw, src1, src1w, src2, src2w); + + case SLJIT_AND: + case SLJIT_OR: + case SLJIT_XOR: + return emit_op(compiler, op, flags | CUMULATIVE_OP | IMM_OP, dst, dstw, src1, src1w, src2, src2w); + + case SLJIT_SHL: + case SLJIT_MSHL: + case SLJIT_LSHR: + case SLJIT_MLSHR: + case SLJIT_ASHR: + case SLJIT_MASHR: + case SLJIT_ROTL: + case SLJIT_ROTR: + if (src2 & SLJIT_IMM) { +#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32) + src2w &= 0x1f; +#else /* !SLJIT_CONFIG_RISCV_32 */ + if (op & SLJIT_32) + src2w &= 0x1f; + else + src2w &= 0x3f; +#endif /* SLJIT_CONFIG_RISCV_32 */ + } + + return emit_op(compiler, op, flags | IMM_OP, dst, dstw, src1, src1w, src2, src2w); + } + + SLJIT_UNREACHABLE(); + return SLJIT_SUCCESS; +} + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2u(struct sljit_compiler *compiler, sljit_s32 op, + sljit_s32 src1, sljit_sw src1w, + sljit_s32 src2, sljit_sw src2w) +{ + CHECK_ERROR(); + CHECK(check_sljit_emit_op2(compiler, op, 1, 0, 0, src1, src1w, src2, src2w)); + + SLJIT_SKIP_CHECKS(compiler); + return sljit_emit_op2(compiler, op, TMP_REG2, 0, src1, src1w, src2, src2w); +} + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_shift_into(struct sljit_compiler *compiler, sljit_s32 op, + sljit_s32 src_dst, + sljit_s32 src1, sljit_sw src1w, + sljit_s32 src2, sljit_sw src2w) +{ + sljit_s32 is_left; + sljit_ins ins1, ins2, ins3; +#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64) + sljit_ins word = (op & SLJIT_32) >> 5; + sljit_s32 inp_flags = ((op & SLJIT_32) ? INT_DATA : WORD_DATA) | LOAD_DATA; + sljit_sw bit_length = (op & SLJIT_32) ? 32 : 64; +#else /* !SLJIT_CONFIG_RISCV_64 */ + sljit_s32 inp_flags = WORD_DATA | LOAD_DATA; + sljit_sw bit_length = 32; +#endif /* SLJIT_CONFIG_RISCV_64 */ + + SLJIT_ASSERT(WORD == 0 || WORD == 0x8); + + CHECK_ERROR(); + CHECK(check_sljit_emit_shift_into(compiler, op, src_dst, src1, src1w, src2, src2w)); + + is_left = (GET_OPCODE(op) == SLJIT_SHL || GET_OPCODE(op) == SLJIT_MSHL); + + if (src_dst == src1) { + SLJIT_SKIP_CHECKS(compiler); + return sljit_emit_op2(compiler, (is_left ? SLJIT_ROTL : SLJIT_ROTR) | (op & SLJIT_32), src_dst, 0, src_dst, 0, src2, src2w); + } + + ADJUST_LOCAL_OFFSET(src1, src1w); + ADJUST_LOCAL_OFFSET(src2, src2w); + + if (src2 & SLJIT_IMM) { + src2w &= bit_length - 1; + + if (src2w == 0) + return SLJIT_SUCCESS; + } else if (src2 & SLJIT_MEM) { + FAIL_IF(emit_op_mem(compiler, inp_flags, TMP_REG2, src2, src2w)); + src2 = TMP_REG2; + } + + if (src1 & SLJIT_MEM) { + FAIL_IF(emit_op_mem(compiler, inp_flags, TMP_REG1, src1, src1w)); + src1 = TMP_REG1; + } else if (src1 & SLJIT_IMM) { + FAIL_IF(load_immediate(compiler, TMP_REG1, src1w, TMP_REG3)); + src1 = TMP_REG1; + } + + if (src2 & SLJIT_IMM) { + if (is_left) { + ins1 = SLLI | WORD | IMM_I(src2w); + src2w = bit_length - src2w; + ins2 = SRLI | WORD | IMM_I(src2w); + } else { + ins1 = SRLI | WORD | IMM_I(src2w); + src2w = bit_length - src2w; + ins2 = SLLI | WORD | IMM_I(src2w); + } + + FAIL_IF(push_inst(compiler, ins1 | RD(src_dst) | RS1(src_dst))); + FAIL_IF(push_inst(compiler, ins2 | RD(TMP_REG1) | RS1(src1))); + return push_inst(compiler, OR | RD(src_dst) | RS1(src_dst) | RS2(TMP_REG1)); + } + + if (is_left) { + ins1 = SLL; + ins2 = SRLI; + ins3 = SRL; + } else { + ins1 = SRL; + ins2 = SLLI; + ins3 = SLL; + } + + FAIL_IF(push_inst(compiler, ins1 | WORD | RD(src_dst) | RS1(src_dst) | RS2(src2))); + + if (!(op & SLJIT_SHIFT_INTO_NON_ZERO)) { + FAIL_IF(push_inst(compiler, ins2 | WORD | RD(TMP_REG1) | RS1(src1) | IMM_I(1))); + FAIL_IF(push_inst(compiler, XORI | RD(TMP_REG2) | RS1(src2) | IMM_I((sljit_ins)bit_length - 1))); + src1 = TMP_REG1; + } else + FAIL_IF(push_inst(compiler, SUB | WORD | RD(TMP_REG2) | RS1(TMP_ZERO) | RS2(src2))); + + FAIL_IF(push_inst(compiler, ins3 | WORD | RD(TMP_REG1) | RS1(src1) | RS2(TMP_REG2))); + return push_inst(compiler, OR | RD(src_dst) | RS1(src_dst) | RS2(TMP_REG1)); +} + +#undef WORD + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_src(struct sljit_compiler *compiler, sljit_s32 op, + sljit_s32 src, sljit_sw srcw) +{ + CHECK_ERROR(); + CHECK(check_sljit_emit_op_src(compiler, op, src, srcw)); + ADJUST_LOCAL_OFFSET(src, srcw); + + switch (op) { + case SLJIT_FAST_RETURN: + if (FAST_IS_REG(src)) + FAIL_IF(push_inst(compiler, ADDI | RD(RETURN_ADDR_REG) | RS1(src) | IMM_I(0))); + else + FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, RETURN_ADDR_REG, src, srcw)); + + return push_inst(compiler, JALR | RD(TMP_ZERO) | RS1(RETURN_ADDR_REG) | IMM_I(0)); + case SLJIT_SKIP_FRAMES_BEFORE_FAST_RETURN: + return SLJIT_SUCCESS; + case SLJIT_PREFETCH_L1: + case SLJIT_PREFETCH_L2: + case SLJIT_PREFETCH_L3: + case SLJIT_PREFETCH_ONCE: + return SLJIT_SUCCESS; + } + + return SLJIT_SUCCESS; +} + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 reg) +{ + CHECK_REG_INDEX(check_sljit_get_register_index(reg)); + return reg_map[reg]; +} + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_float_register_index(sljit_s32 reg) +{ + CHECK_REG_INDEX(check_sljit_get_float_register_index(reg)); + return freg_map[reg]; +} + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *compiler, + void *instruction, sljit_u32 size) +{ + CHECK_ERROR(); + CHECK(check_sljit_emit_op_custom(compiler, instruction, size)); + + return push_inst(compiler, *(sljit_ins*)instruction); +} + +/* --------------------------------------------------------------------- */ +/* Floating point operators */ +/* --------------------------------------------------------------------- */ + +#define FLOAT_DATA(op) (DOUBLE_DATA | ((op & SLJIT_32) >> 7)) +#define FMT(op) ((sljit_ins)((op & SLJIT_32) ^ SLJIT_32) << 17) + +static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_sw_from_f64(struct sljit_compiler *compiler, sljit_s32 op, + sljit_s32 dst, sljit_sw dstw, + sljit_s32 src, sljit_sw srcw) +{ +#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32) +# define flags (sljit_u32)0 +#else + sljit_u32 flags = ((sljit_u32)(GET_OPCODE(op) == SLJIT_CONV_SW_FROM_F64)) << 21; +#endif + sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2; + + if (src & SLJIT_MEM) { + FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src, srcw, dst, dstw)); + src = TMP_FREG1; + } + + FAIL_IF(push_inst(compiler, FCVT_W_S | FMT(op) | flags | RD(dst_r) | FRS1(src))); + + /* Store the integer value from a VFP register. */ + if (dst & SLJIT_MEM) { +#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32) + return emit_op_mem2(compiler, WORD_DATA, TMP_REG2, dst, dstw, 0, 0); +#else + return emit_op_mem2(compiler, flags ? WORD_DATA : INT_DATA, TMP_REG2, dst, dstw, 0, 0); +#endif + } + return SLJIT_SUCCESS; + +#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32) +# undef flags +#endif +} + +static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_sw(struct sljit_compiler *compiler, sljit_s32 op, + sljit_s32 dst, sljit_sw dstw, + sljit_s32 src, sljit_sw srcw) +{ + sljit_ins inst; +#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64) + sljit_u32 flags = ((sljit_u32)(GET_OPCODE(op) == SLJIT_CONV_F64_FROM_SW)) << 21; +#endif + + sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1; + + if (src & SLJIT_MEM) { +#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32) + FAIL_IF(emit_op_mem2(compiler, WORD_DATA | LOAD_DATA, TMP_REG1, src, srcw, dst, dstw)); +#else + FAIL_IF(emit_op_mem2(compiler, (flags ? WORD_DATA : INT_DATA) | LOAD_DATA, TMP_REG1, src, srcw, dst, dstw)); +#endif + src = TMP_REG1; + } else if (src & SLJIT_IMM) { +#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64) + if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_S32) + srcw = (sljit_s32)srcw; +#endif + + FAIL_IF(load_immediate(compiler, TMP_REG1, srcw, TMP_REG3)); + src = TMP_REG1; + } + + inst = FCVT_S_W | FMT(op) | FRD(dst_r) | RS1(src); + +#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32) + if (op & SLJIT_32) + inst |= F3(0x7); +#else + inst |= flags; + + if (op != SLJIT_CONV_F64_FROM_S32) + inst |= F3(0x7); +#endif + + FAIL_IF(push_inst(compiler, inst)); + + if (dst & SLJIT_MEM) + return emit_op_mem2(compiler, FLOAT_DATA(op), TMP_FREG1, dst, dstw, 0, 0); + return SLJIT_SUCCESS; +} + +static SLJIT_INLINE sljit_s32 sljit_emit_fop1_cmp(struct sljit_compiler *compiler, sljit_s32 op, + sljit_s32 src1, sljit_sw src1w, + sljit_s32 src2, sljit_sw src2w) +{ + sljit_ins inst; + + if (src1 & SLJIT_MEM) { + FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src1, src1w, src2, src2w)); + src1 = TMP_FREG1; + } + + if (src2 & SLJIT_MEM) { + FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG2, src2, src2w, 0, 0)); + src2 = TMP_FREG2; + } + + switch (GET_FLAG_TYPE(op)) { + case SLJIT_F_EQUAL: + case SLJIT_F_NOT_EQUAL: + case SLJIT_ORDERED_EQUAL: + case SLJIT_UNORDERED_OR_NOT_EQUAL: + inst = FEQ_S | FMT(op) | RD(OTHER_FLAG) | FRS1(src1) | FRS2(src2); + break; + case SLJIT_F_LESS: + case SLJIT_F_GREATER_EQUAL: + case SLJIT_ORDERED_LESS: + case SLJIT_UNORDERED_OR_GREATER_EQUAL: + inst = FLT_S | FMT(op) | RD(OTHER_FLAG) | FRS1(src1) | FRS2(src2); + break; + case SLJIT_ORDERED_GREATER: + case SLJIT_UNORDERED_OR_LESS_EQUAL: + inst = FLT_S | FMT(op) | RD(OTHER_FLAG) | FRS1(src2) | FRS2(src1); + break; + case SLJIT_F_GREATER: + case SLJIT_F_LESS_EQUAL: + case SLJIT_UNORDERED_OR_GREATER: + case SLJIT_ORDERED_LESS_EQUAL: + inst = FLE_S | FMT(op) | RD(OTHER_FLAG) | FRS1(src1) | FRS2(src2); + break; + case SLJIT_UNORDERED_OR_LESS: + case SLJIT_ORDERED_GREATER_EQUAL: + inst = FLE_S | FMT(op) | RD(OTHER_FLAG) | FRS1(src2) | FRS2(src1); + break; + case SLJIT_UNORDERED_OR_EQUAL: /* Not supported. */ + case SLJIT_ORDERED_NOT_EQUAL: /* Not supported. */ + FAIL_IF(push_inst(compiler, FLT_S | FMT(op) | RD(OTHER_FLAG) | FRS1(src1) | FRS2(src2))); + FAIL_IF(push_inst(compiler, FLT_S | FMT(op) | RD(TMP_REG1) | FRS1(src2) | FRS2(src1))); + inst = OR | RD(OTHER_FLAG) | RS1(OTHER_FLAG) | RS2(TMP_REG1); + break; + default: /* SLJIT_UNORDERED, SLJIT_ORDERED */ + FAIL_IF(push_inst(compiler, FADD_S | FMT(op) | FRD(TMP_FREG1) | FRS1(src1) | FRS2(src2))); + inst = FEQ_S | FMT(op) | RD(OTHER_FLAG) | FRS1(TMP_FREG1) | FRS2(TMP_FREG1); + break; + } + + return push_inst(compiler, inst); +} + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop1(struct sljit_compiler *compiler, sljit_s32 op, + sljit_s32 dst, sljit_sw dstw, + sljit_s32 src, sljit_sw srcw) +{ + sljit_s32 dst_r; + + CHECK_ERROR(); + compiler->cache_arg = 0; + compiler->cache_argw = 0; + + SLJIT_COMPILE_ASSERT((SLJIT_32 == 0x100) && !(DOUBLE_DATA & 0x2), float_transfer_bit_error); + SELECT_FOP1_OPERATION_WITH_CHECKS(compiler, op, dst, dstw, src, srcw); + + if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_F32) + op ^= SLJIT_32; + + dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1; + + if (src & SLJIT_MEM) { + FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, dst_r, src, srcw, dst, dstw)); + src = dst_r; + } + + switch (GET_OPCODE(op)) { + case SLJIT_MOV_F64: + if (src != dst_r) { + if (dst_r != TMP_FREG1) + FAIL_IF(push_inst(compiler, FSGNJ_S | FMT(op) | FRD(dst_r) | FRS1(src) | FRS2(src))); + else + dst_r = src; + } + break; + case SLJIT_NEG_F64: + FAIL_IF(push_inst(compiler, FSGNJN_S | FMT(op) | FRD(dst_r) | FRS1(src) | FRS2(src))); + break; + case SLJIT_ABS_F64: + FAIL_IF(push_inst(compiler, FSGNJX_S | FMT(op) | FRD(dst_r) | FRS1(src) | FRS2(src))); + break; + case SLJIT_CONV_F64_FROM_F32: + /* The SLJIT_32 bit is inverted because sljit_f32 needs to be loaded from the memory. */ + FAIL_IF(push_inst(compiler, FCVT_S_D | ((op & SLJIT_32) ? (1 << 25) : ((1 << 20) | F3(7))) | FRD(dst_r) | FRS1(src))); + op ^= SLJIT_32; + break; + } + + if (dst & SLJIT_MEM) + return emit_op_mem2(compiler, FLOAT_DATA(op), dst_r, dst, dstw, 0, 0); + return SLJIT_SUCCESS; +} + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop2(struct sljit_compiler *compiler, sljit_s32 op, + sljit_s32 dst, sljit_sw dstw, + sljit_s32 src1, sljit_sw src1w, + sljit_s32 src2, sljit_sw src2w) +{ + sljit_s32 dst_r, flags = 0; + + CHECK_ERROR(); + CHECK(check_sljit_emit_fop2(compiler, op, dst, dstw, src1, src1w, src2, src2w)); + ADJUST_LOCAL_OFFSET(dst, dstw); + ADJUST_LOCAL_OFFSET(src1, src1w); + ADJUST_LOCAL_OFFSET(src2, src2w); + + compiler->cache_arg = 0; + compiler->cache_argw = 0; + + dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG2; + + if (src1 & SLJIT_MEM) { + if (getput_arg_fast(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src1, src1w)) { + FAIL_IF(compiler->error); + src1 = TMP_FREG1; + } else + flags |= SLOW_SRC1; + } + + if (src2 & SLJIT_MEM) { + if (getput_arg_fast(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG2, src2, src2w)) { + FAIL_IF(compiler->error); + src2 = TMP_FREG2; + } else + flags |= SLOW_SRC2; + } + + if ((flags & (SLOW_SRC1 | SLOW_SRC2)) == (SLOW_SRC1 | SLOW_SRC2)) { + if (!can_cache(src1, src1w, src2, src2w) && can_cache(src1, src1w, dst, dstw)) { + FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG2, src2, src2w, src1, src1w)); + FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src1, src1w, dst, dstw)); + } + else { + FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src1, src1w, src2, src2w)); + FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG2, src2, src2w, dst, dstw)); + } + } + else if (flags & SLOW_SRC1) + FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src1, src1w, dst, dstw)); + else if (flags & SLOW_SRC2) + FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG2, src2, src2w, dst, dstw)); + + if (flags & SLOW_SRC1) + src1 = TMP_FREG1; + if (flags & SLOW_SRC2) + src2 = TMP_FREG2; + + switch (GET_OPCODE(op)) { + case SLJIT_ADD_F64: + FAIL_IF(push_inst(compiler, FADD_S | FMT(op) | FRD(dst_r) | FRS1(src1) | FRS2(src2))); + break; + + case SLJIT_SUB_F64: + FAIL_IF(push_inst(compiler, FSUB_S | FMT(op) | FRD(dst_r) | FRS1(src1) | FRS2(src2))); + break; + + case SLJIT_MUL_F64: + FAIL_IF(push_inst(compiler, FMUL_S | FMT(op) | FRD(dst_r) | FRS1(src1) | FRS2(src2))); + break; + + case SLJIT_DIV_F64: + FAIL_IF(push_inst(compiler, FDIV_S | FMT(op) | FRD(dst_r) | FRS1(src1) | FRS2(src2))); + break; + } + + if (dst_r == TMP_FREG2) + FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op), TMP_FREG2, dst, dstw, 0, 0)); + + return SLJIT_SUCCESS; +} + +#undef FLOAT_DATA +#undef FMT + +/* --------------------------------------------------------------------- */ +/* Other instructions */ +/* --------------------------------------------------------------------- */ + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_enter(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw) +{ + CHECK_ERROR(); + CHECK(check_sljit_emit_fast_enter(compiler, dst, dstw)); + ADJUST_LOCAL_OFFSET(dst, dstw); + + if (FAST_IS_REG(dst)) + return push_inst(compiler, ADDI | RD(dst) | RS1(RETURN_ADDR_REG) | IMM_I(0)); + + /* Memory. */ + return emit_op_mem(compiler, WORD_DATA, RETURN_ADDR_REG, dst, dstw); +} + +/* --------------------------------------------------------------------- */ +/* Conditional instructions */ +/* --------------------------------------------------------------------- */ + +SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compiler *compiler) +{ + struct sljit_label *label; + + CHECK_ERROR_PTR(); + CHECK_PTR(check_sljit_emit_label(compiler)); + + if (compiler->last_label && compiler->last_label->size == compiler->size) + return compiler->last_label; + + label = (struct sljit_label*)ensure_abuf(compiler, sizeof(struct sljit_label)); + PTR_FAIL_IF(!label); + set_label(label, compiler); + return label; +} + +#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32) +#define BRANCH_LENGTH ((sljit_ins)(3 * sizeof(sljit_ins)) << 7) +#else +#define BRANCH_LENGTH ((sljit_ins)(7 * sizeof(sljit_ins)) << 7) +#endif + +SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compiler *compiler, sljit_s32 type) +{ + struct sljit_jump *jump; + sljit_ins inst; + + CHECK_ERROR_PTR(); + CHECK_PTR(check_sljit_emit_jump(compiler, type)); + + jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump)); + PTR_FAIL_IF(!jump); + set_jump(jump, compiler, type & SLJIT_REWRITABLE_JUMP); + type &= 0xff; + + switch (type) { + case SLJIT_EQUAL: + inst = BNE | RS1(EQUAL_FLAG) | RS2(TMP_ZERO) | BRANCH_LENGTH; + break; + case SLJIT_NOT_EQUAL: + inst = BEQ | RS1(EQUAL_FLAG) | RS2(TMP_ZERO) | BRANCH_LENGTH; + break; + case SLJIT_LESS: + case SLJIT_GREATER: + case SLJIT_SIG_LESS: + case SLJIT_SIG_GREATER: + case SLJIT_OVERFLOW: + case SLJIT_CARRY: + case SLJIT_F_EQUAL: + case SLJIT_ORDERED_EQUAL: + case SLJIT_ORDERED_NOT_EQUAL: /* Not supported. */ + case SLJIT_F_LESS: + case SLJIT_ORDERED_LESS: + case SLJIT_ORDERED_GREATER: + case SLJIT_F_LESS_EQUAL: + case SLJIT_ORDERED_LESS_EQUAL: + case SLJIT_ORDERED_GREATER_EQUAL: + case SLJIT_ORDERED: + inst = BEQ | RS1(OTHER_FLAG) | RS2(TMP_ZERO) | BRANCH_LENGTH; + break; + case SLJIT_GREATER_EQUAL: + case SLJIT_LESS_EQUAL: + case SLJIT_SIG_GREATER_EQUAL: + case SLJIT_SIG_LESS_EQUAL: + case SLJIT_NOT_OVERFLOW: + case SLJIT_NOT_CARRY: + case SLJIT_F_NOT_EQUAL: + case SLJIT_UNORDERED_OR_NOT_EQUAL: + case SLJIT_UNORDERED_OR_EQUAL: /* Not supported. */ + case SLJIT_F_GREATER_EQUAL: + case SLJIT_UNORDERED_OR_GREATER_EQUAL: + case SLJIT_UNORDERED_OR_LESS_EQUAL: + case SLJIT_F_GREATER: + case SLJIT_UNORDERED_OR_GREATER: + case SLJIT_UNORDERED_OR_LESS: + case SLJIT_UNORDERED: + inst = BNE | RS1(OTHER_FLAG) | RS2(TMP_ZERO) | BRANCH_LENGTH; + break; + default: + /* Not conditional branch. */ + inst = 0; + break; + } + + if (inst != 0) { + PTR_FAIL_IF(push_inst(compiler, inst)); + jump->flags |= IS_COND; + } + + jump->addr = compiler->size; + inst = JALR | RS1(TMP_REG1) | IMM_I(0); + + if (type >= SLJIT_FAST_CALL) { + jump->flags |= IS_CALL; + inst |= RD(RETURN_ADDR_REG); + } + + PTR_FAIL_IF(push_inst(compiler, inst)); + + /* Maximum number of instructions required for generating a constant. */ +#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32) + compiler->size += 1; +#else + compiler->size += 5; +#endif + return jump; +} + +SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compiler *compiler, sljit_s32 type, + sljit_s32 arg_types) +{ + SLJIT_UNUSED_ARG(arg_types); + CHECK_ERROR_PTR(); + CHECK_PTR(check_sljit_emit_call(compiler, type, arg_types)); + + if (type & SLJIT_CALL_RETURN) { + PTR_FAIL_IF(emit_stack_frame_release(compiler, 0)); + type = SLJIT_JUMP | (type & SLJIT_REWRITABLE_JUMP); + } + + SLJIT_SKIP_CHECKS(compiler); + return sljit_emit_jump(compiler, type); +} + +SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_cmp(struct sljit_compiler *compiler, sljit_s32 type, + sljit_s32 src1, sljit_sw src1w, + sljit_s32 src2, sljit_sw src2w) +{ + struct sljit_jump *jump; + sljit_s32 flags; + sljit_ins inst; + + CHECK_ERROR_PTR(); + CHECK_PTR(check_sljit_emit_cmp(compiler, type, src1, src1w, src2, src2w)); + ADJUST_LOCAL_OFFSET(src1, src1w); + ADJUST_LOCAL_OFFSET(src2, src2w); + + compiler->cache_arg = 0; + compiler->cache_argw = 0; +#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32) + flags = WORD_DATA | LOAD_DATA; +#else /* !SLJIT_CONFIG_RISCV_32 */ + flags = ((type & SLJIT_32) ? INT_DATA : WORD_DATA) | LOAD_DATA; +#endif /* SLJIT_CONFIG_RISCV_32 */ + + if (src1 & SLJIT_MEM) { + PTR_FAIL_IF(emit_op_mem2(compiler, flags, TMP_REG1, src1, src1w, src2, src2w)); + src1 = TMP_REG1; + } + + if (src2 & SLJIT_MEM) { + PTR_FAIL_IF(emit_op_mem2(compiler, flags, TMP_REG2, src2, src2w, 0, 0)); + src2 = TMP_REG2; + } + + if (src1 & SLJIT_IMM) { + if (src1w != 0) { + PTR_FAIL_IF(load_immediate(compiler, TMP_REG1, src1w, TMP_REG3)); + src1 = TMP_REG1; + } + else + src1 = TMP_ZERO; + } + + if (src2 & SLJIT_IMM) { + if (src2w != 0) { + PTR_FAIL_IF(load_immediate(compiler, TMP_REG2, src2w, TMP_REG3)); + src2 = TMP_REG2; + } + else + src2 = TMP_ZERO; + } + + jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump)); + PTR_FAIL_IF(!jump); + set_jump(jump, compiler, (sljit_u32)((type & SLJIT_REWRITABLE_JUMP) | IS_COND)); + type &= 0xff; + + switch (type) { + case SLJIT_EQUAL: + inst = BNE | RS1(src1) | RS2(src2) | BRANCH_LENGTH; + break; + case SLJIT_NOT_EQUAL: + inst = BEQ | RS1(src1) | RS2(src2) | BRANCH_LENGTH; + break; + case SLJIT_LESS: + inst = BGEU | RS1(src1) | RS2(src2) | BRANCH_LENGTH; + break; + case SLJIT_GREATER_EQUAL: + inst = BLTU | RS1(src1) | RS2(src2) | BRANCH_LENGTH; + break; + case SLJIT_GREATER: + inst = BGEU | RS1(src2) | RS2(src1) | BRANCH_LENGTH; + break; + case SLJIT_LESS_EQUAL: + inst = BLTU | RS1(src2) | RS2(src1) | BRANCH_LENGTH; + break; + case SLJIT_SIG_LESS: + inst = BGE | RS1(src1) | RS2(src2) | BRANCH_LENGTH; + break; + case SLJIT_SIG_GREATER_EQUAL: + inst = BLT | RS1(src1) | RS2(src2) | BRANCH_LENGTH; + break; + case SLJIT_SIG_GREATER: + inst = BGE | RS1(src2) | RS2(src1) | BRANCH_LENGTH; + break; + case SLJIT_SIG_LESS_EQUAL: + inst = BLT | RS1(src2) | RS2(src1) | BRANCH_LENGTH; + break; + } + + PTR_FAIL_IF(push_inst(compiler, inst)); + + jump->addr = compiler->size; + PTR_FAIL_IF(push_inst(compiler, JALR | RD(TMP_ZERO) | RS1(TMP_REG1) | IMM_I(0))); + + /* Maximum number of instructions required for generating a constant. */ +#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32) + compiler->size += 1; +#else + compiler->size += 5; +#endif + return jump; +} + +#undef BRANCH_LENGTH + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 src, sljit_sw srcw) +{ + struct sljit_jump *jump; + + CHECK_ERROR(); + CHECK(check_sljit_emit_ijump(compiler, type, src, srcw)); + + if (!(src & SLJIT_IMM)) { + if (src & SLJIT_MEM) { + ADJUST_LOCAL_OFFSET(src, srcw); + FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, TMP_REG1, src, srcw)); + src = TMP_REG1; + } + return push_inst(compiler, JALR | RD((type >= SLJIT_FAST_CALL) ? RETURN_ADDR_REG : TMP_ZERO) | RS1(src) | IMM_I(0)); + } + + /* These jumps are converted to jump/call instructions when possible. */ + jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump)); + FAIL_IF(!jump); + set_jump(jump, compiler, JUMP_ADDR | ((type >= SLJIT_FAST_CALL) ? IS_CALL : 0)); + jump->u.target = (sljit_uw)srcw; + + jump->addr = compiler->size; + FAIL_IF(push_inst(compiler, JALR | RD((type >= SLJIT_FAST_CALL) ? RETURN_ADDR_REG : TMP_ZERO) | RS1(TMP_REG1) | IMM_I(0))); + + /* Maximum number of instructions required for generating a constant. */ +#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32) + compiler->size += 1; +#else + compiler->size += 5; +#endif + return SLJIT_SUCCESS; +} + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compiler, sljit_s32 type, + sljit_s32 arg_types, + sljit_s32 src, sljit_sw srcw) +{ + SLJIT_UNUSED_ARG(arg_types); + CHECK_ERROR(); + CHECK(check_sljit_emit_icall(compiler, type, arg_types, src, srcw)); + + if (src & SLJIT_MEM) { + ADJUST_LOCAL_OFFSET(src, srcw); + FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, TMP_REG1, src, srcw)); + src = TMP_REG1; + } + + if (type & SLJIT_CALL_RETURN) { + if (src >= SLJIT_FIRST_SAVED_REG && src <= (SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options))) { + FAIL_IF(push_inst(compiler, ADDI | RD(TMP_REG1) | RS1(src) | IMM_I(0))); + src = TMP_REG1; + } + + FAIL_IF(emit_stack_frame_release(compiler, 0)); + type = SLJIT_JUMP; + } + + SLJIT_SKIP_CHECKS(compiler); + return sljit_emit_ijump(compiler, type, src, srcw); +} + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *compiler, sljit_s32 op, + sljit_s32 dst, sljit_sw dstw, + sljit_s32 type) +{ + sljit_s32 src_r, dst_r, invert; + sljit_s32 saved_op = op; +#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32) + sljit_s32 mem_type = WORD_DATA; +#else + sljit_s32 mem_type = ((op & SLJIT_32) || op == SLJIT_MOV32) ? (INT_DATA | SIGNED_DATA) : WORD_DATA; +#endif + + CHECK_ERROR(); + CHECK(check_sljit_emit_op_flags(compiler, op, dst, dstw, type)); + ADJUST_LOCAL_OFFSET(dst, dstw); + + op = GET_OPCODE(op); + dst_r = (op < SLJIT_ADD && FAST_IS_REG(dst)) ? dst : TMP_REG2; + + compiler->cache_arg = 0; + compiler->cache_argw = 0; + + if (op >= SLJIT_ADD && (dst & SLJIT_MEM)) + FAIL_IF(emit_op_mem2(compiler, mem_type | LOAD_DATA, TMP_REG1, dst, dstw, dst, dstw)); + + if (type < SLJIT_F_EQUAL) { + src_r = OTHER_FLAG; + invert = type & 0x1; + + switch (type) { + case SLJIT_EQUAL: + case SLJIT_NOT_EQUAL: + FAIL_IF(push_inst(compiler, SLTUI | RD(dst_r) | RS1(EQUAL_FLAG) | IMM_I(1))); + src_r = dst_r; + break; + case SLJIT_OVERFLOW: + case SLJIT_NOT_OVERFLOW: + if (compiler->status_flags_state & (SLJIT_CURRENT_FLAGS_ADD | SLJIT_CURRENT_FLAGS_SUB)) { + src_r = OTHER_FLAG; + break; + } + FAIL_IF(push_inst(compiler, SLTUI | RD(dst_r) | RS1(OTHER_FLAG) | IMM_I(1))); + src_r = dst_r; + invert ^= 0x1; + break; + } + } else { + invert = 0; + src_r = OTHER_FLAG; + + switch (type) { + case SLJIT_F_NOT_EQUAL: + case SLJIT_UNORDERED_OR_NOT_EQUAL: + case SLJIT_UNORDERED_OR_EQUAL: /* Not supported. */ + case SLJIT_F_GREATER_EQUAL: + case SLJIT_UNORDERED_OR_GREATER_EQUAL: + case SLJIT_UNORDERED_OR_LESS_EQUAL: + case SLJIT_F_GREATER: + case SLJIT_UNORDERED_OR_GREATER: + case SLJIT_UNORDERED_OR_LESS: + case SLJIT_UNORDERED: + invert = 1; + break; + } + } + + if (invert) { + FAIL_IF(push_inst(compiler, XORI | RD(dst_r) | RS1(src_r) | IMM_I(1))); + src_r = dst_r; + } + + if (op < SLJIT_ADD) { + if (dst & SLJIT_MEM) + return emit_op_mem(compiler, mem_type, src_r, dst, dstw); + + if (src_r != dst_r) + return push_inst(compiler, ADDI | RD(dst_r) | RS1(src_r) | IMM_I(0)); + return SLJIT_SUCCESS; + } + + mem_type |= CUMULATIVE_OP | IMM_OP | ALT_KEEP_CACHE; + + if (dst & SLJIT_MEM) + return emit_op(compiler, saved_op, mem_type, dst, dstw, TMP_REG1, 0, src_r, 0); + return emit_op(compiler, saved_op, mem_type, dst, dstw, dst, dstw, src_r, 0); +} + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_cmov(struct sljit_compiler *compiler, sljit_s32 type, + sljit_s32 dst_reg, + sljit_s32 src, sljit_sw srcw) +{ + CHECK_ERROR(); + CHECK(check_sljit_emit_cmov(compiler, type, dst_reg, src, srcw)); + + return sljit_emit_cmov_generic(compiler, type, dst_reg, src, srcw);; +} + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compiler, sljit_s32 type, + sljit_s32 reg, + sljit_s32 mem, sljit_sw memw) +{ + sljit_s32 flags; + + CHECK_ERROR(); + CHECK(check_sljit_emit_mem(compiler, type, reg, mem, memw)); + + if (!(reg & REG_PAIR_MASK)) + return sljit_emit_mem_unaligned(compiler, type, reg, mem, memw); + + if (SLJIT_UNLIKELY(mem & OFFS_REG_MASK)) { + memw &= 0x3; + + if (SLJIT_UNLIKELY(memw != 0)) { + FAIL_IF(push_inst(compiler, SLLI | RD(TMP_REG1) | RS1(OFFS_REG(mem)) | IMM_I(memw))); + FAIL_IF(push_inst(compiler, ADD | RD(TMP_REG1) | RS1(TMP_REG1) | RS2(mem & REG_MASK))); + } else + FAIL_IF(push_inst(compiler, ADD | RD(TMP_REG1) | RS1(mem & REG_MASK) | RS2(OFFS_REG(mem)))); + + mem = TMP_REG1; + memw = 0; + } else if (memw > SIMM_MAX - SSIZE_OF(sw) || memw < SIMM_MIN) { + if (((memw + 0x800) & 0xfff) <= 0xfff - SSIZE_OF(sw)) { + FAIL_IF(load_immediate(compiler, TMP_REG1, TO_ARGW_HI(memw), TMP_REG3)); + memw &= 0xfff; + } else { + FAIL_IF(load_immediate(compiler, TMP_REG1, memw, TMP_REG3)); + memw = 0; + } + + if (mem & REG_MASK) + FAIL_IF(push_inst(compiler, ADD | RD(TMP_REG1) | RS1(TMP_REG1) | RS2(mem & REG_MASK))); + + mem = TMP_REG1; + } else { + mem &= REG_MASK; + memw &= 0xfff; + } + + SLJIT_ASSERT((memw >= 0 && memw <= SIMM_MAX - SSIZE_OF(sw)) || (memw > SIMM_MAX && memw <= 0xfff)); + + if (!(type & SLJIT_MEM_STORE) && mem == REG_PAIR_FIRST(reg)) { + FAIL_IF(push_mem_inst(compiler, WORD_DATA | LOAD_DATA, REG_PAIR_SECOND(reg), mem, (memw + SSIZE_OF(sw)) & 0xfff)); + return push_mem_inst(compiler, WORD_DATA | LOAD_DATA, REG_PAIR_FIRST(reg), mem, memw); + } + + flags = WORD_DATA | (!(type & SLJIT_MEM_STORE) ? LOAD_DATA : 0); + + FAIL_IF(push_mem_inst(compiler, flags, REG_PAIR_FIRST(reg), mem, memw)); + return push_mem_inst(compiler, flags, REG_PAIR_SECOND(reg), mem, (memw + SSIZE_OF(sw)) & 0xfff); +} + +#undef TO_ARGW_HI + +SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw init_value) +{ + struct sljit_const *const_; + sljit_s32 dst_r; + + CHECK_ERROR_PTR(); + CHECK_PTR(check_sljit_emit_const(compiler, dst, dstw, init_value)); + ADJUST_LOCAL_OFFSET(dst, dstw); + + const_ = (struct sljit_const*)ensure_abuf(compiler, sizeof(struct sljit_const)); + PTR_FAIL_IF(!const_); + set_const(const_, compiler); + + dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2; + PTR_FAIL_IF(emit_const(compiler, dst_r, init_value, ADDI | RD(dst_r))); + + if (dst & SLJIT_MEM) + PTR_FAIL_IF(emit_op_mem(compiler, WORD_DATA, TMP_REG2, dst, dstw)); + + return const_; +} + +SLJIT_API_FUNC_ATTRIBUTE struct sljit_put_label* sljit_emit_put_label(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw) +{ + struct sljit_put_label *put_label; + sljit_s32 dst_r; + + CHECK_ERROR_PTR(); + CHECK_PTR(check_sljit_emit_put_label(compiler, dst, dstw)); + ADJUST_LOCAL_OFFSET(dst, dstw); + + put_label = (struct sljit_put_label*)ensure_abuf(compiler, sizeof(struct sljit_put_label)); + PTR_FAIL_IF(!put_label); + set_put_label(put_label, compiler, 0); + + dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2; + PTR_FAIL_IF(push_inst(compiler, (sljit_ins)dst_r)); +#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32) + compiler->size += 1; +#else + compiler->size += 5; +#endif + + if (dst & SLJIT_MEM) + PTR_FAIL_IF(emit_op_mem(compiler, WORD_DATA, TMP_REG2, dst, dstw)); + + return put_label; +} + +SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant, sljit_sw executable_offset) +{ + sljit_set_jump_addr(addr, (sljit_uw)new_constant, executable_offset); +} diff --git a/src/3rdparty/pcre2/src/sljit/sljitNativeS390X.c b/src/3rdparty/pcre2/src/sljit/sljitNativeS390X.c index 8eef910c425..8b51bad9bc3 100644 --- a/src/3rdparty/pcre2/src/sljit/sljitNativeS390X.c +++ b/src/3rdparty/pcre2/src/sljit/sljitNativeS390X.c @@ -103,11 +103,8 @@ static const sljit_gpr r15 = 15; /* reg_map[SLJIT_NUMBER_OF_REGISTERS + 1]: stac /* When reg cannot be unused. */ #define IS_GPR_REG(reg) ((reg > 0) && (reg) <= SLJIT_SP) -/* Link registers. The normal link register is r14, but since - we use that for flags we need to use r0 instead to do fast - calls so that flags are preserved. */ +/* Link register. */ static const sljit_gpr link_r = 14; /* r14 */ -static const sljit_gpr fast_link_r = 0; /* r0 */ #define TMP_FREG1 (0) @@ -220,7 +217,8 @@ static SLJIT_INLINE sljit_u8 get_cc(struct sljit_compiler *compiler, sljit_s32 t } /* fallthrough */ - case SLJIT_EQUAL_F64: + case SLJIT_F_EQUAL: + case SLJIT_ORDERED_EQUAL: return cc0; case SLJIT_NOT_EQUAL: @@ -234,13 +232,14 @@ static SLJIT_INLINE sljit_u8 get_cc(struct sljit_compiler *compiler, sljit_s32 t } /* fallthrough */ - case SLJIT_NOT_EQUAL_F64: + case SLJIT_UNORDERED_OR_NOT_EQUAL: return (cc1 | cc2 | cc3); case SLJIT_LESS: return cc1; case SLJIT_GREATER_EQUAL: + case SLJIT_UNORDERED_OR_GREATER_EQUAL: return (cc0 | cc2 | cc3); case SLJIT_GREATER: @@ -254,7 +253,8 @@ static SLJIT_INLINE sljit_u8 get_cc(struct sljit_compiler *compiler, sljit_s32 t return (cc0 | cc1 | cc2); case SLJIT_SIG_LESS: - case SLJIT_LESS_F64: + case SLJIT_F_LESS: + case SLJIT_ORDERED_LESS: return cc1; case SLJIT_NOT_CARRY: @@ -263,7 +263,8 @@ static SLJIT_INLINE sljit_u8 get_cc(struct sljit_compiler *compiler, sljit_s32 t /* fallthrough */ case SLJIT_SIG_LESS_EQUAL: - case SLJIT_LESS_EQUAL_F64: + case SLJIT_F_LESS_EQUAL: + case SLJIT_ORDERED_LESS_EQUAL: return (cc0 | cc1); case SLJIT_CARRY: @@ -272,6 +273,7 @@ static SLJIT_INLINE sljit_u8 get_cc(struct sljit_compiler *compiler, sljit_s32 t /* fallthrough */ case SLJIT_SIG_GREATER: + case SLJIT_UNORDERED_OR_GREATER: /* Overflow is considered greater, see SLJIT_SUB. */ return cc2 | cc3; @@ -283,7 +285,7 @@ static SLJIT_INLINE sljit_u8 get_cc(struct sljit_compiler *compiler, sljit_s32 t return (cc2 | cc3); /* fallthrough */ - case SLJIT_UNORDERED_F64: + case SLJIT_UNORDERED: return cc3; case SLJIT_NOT_OVERFLOW: @@ -291,14 +293,29 @@ static SLJIT_INLINE sljit_u8 get_cc(struct sljit_compiler *compiler, sljit_s32 t return (cc0 | cc1); /* fallthrough */ - case SLJIT_ORDERED_F64: + case SLJIT_ORDERED: return (cc0 | cc1 | cc2); - case SLJIT_GREATER_F64: + case SLJIT_F_NOT_EQUAL: + case SLJIT_ORDERED_NOT_EQUAL: + return (cc1 | cc2); + + case SLJIT_F_GREATER: + case SLJIT_ORDERED_GREATER: return cc2; - case SLJIT_GREATER_EQUAL_F64: + case SLJIT_F_GREATER_EQUAL: + case SLJIT_ORDERED_GREATER_EQUAL: return (cc0 | cc2); + + case SLJIT_UNORDERED_OR_LESS_EQUAL: + return (cc0 | cc1 | cc3); + + case SLJIT_UNORDERED_OR_EQUAL: + return (cc0 | cc3); + + case SLJIT_UNORDERED_OR_LESS: + return (cc1 | cc3); } SLJIT_UNREACHABLE(); @@ -978,7 +995,7 @@ static sljit_s32 make_addr_bx(struct sljit_compiler *compiler, (cond) ? EVAL(i1, r, addr) : EVAL(i2, r, addr) /* May clobber tmp1. */ -static sljit_s32 load_word(struct sljit_compiler *compiler, sljit_gpr dst, +static sljit_s32 load_word(struct sljit_compiler *compiler, sljit_gpr dst_r, sljit_s32 src, sljit_sw srcw, sljit_s32 is_32bit) { @@ -986,21 +1003,36 @@ static sljit_s32 load_word(struct sljit_compiler *compiler, sljit_gpr dst, sljit_ins ins; SLJIT_ASSERT(src & SLJIT_MEM); - if (have_ldisp() || !is_32bit) - FAIL_IF(make_addr_bxy(compiler, &addr, src, srcw, tmp1)); - else + + if (is_32bit && ((src & OFFS_REG_MASK) || is_u12(srcw) || !is_s20(srcw))) { FAIL_IF(make_addr_bx(compiler, &addr, src, srcw, tmp1)); + return push_inst(compiler, 0x58000000 /* l */ | R20A(dst_r) | R16A(addr.index) | R12A(addr.base) | (sljit_ins)addr.offset); + } - if (is_32bit) - ins = WHEN(is_u12(addr.offset), dst, l, ly, addr); - else - ins = lg(dst, addr.offset, addr.index, addr.base); + FAIL_IF(make_addr_bxy(compiler, &addr, src, srcw, tmp1)); - return push_inst(compiler, ins); + ins = is_32bit ? 0xe30000000058 /* ly */ : 0xe30000000004 /* lg */; + return push_inst(compiler, ins | R36A(dst_r) | R32A(addr.index) | R28A(addr.base) | disp_s20(addr.offset)); } /* May clobber tmp1. */ -static sljit_s32 store_word(struct sljit_compiler *compiler, sljit_gpr src, +static sljit_s32 load_unsigned_word(struct sljit_compiler *compiler, sljit_gpr dst_r, + sljit_s32 src, sljit_sw srcw, + sljit_s32 is_32bit) +{ + struct addr addr; + sljit_ins ins; + + SLJIT_ASSERT(src & SLJIT_MEM); + + FAIL_IF(make_addr_bxy(compiler, &addr, src, srcw, tmp1)); + + ins = is_32bit ? 0xe30000000016 /* llgf */ : 0xe30000000004 /* lg */; + return push_inst(compiler, ins | R36A(dst_r) | R32A(addr.index) | R28A(addr.base) | disp_s20(addr.offset)); +} + +/* May clobber tmp1. */ +static sljit_s32 store_word(struct sljit_compiler *compiler, sljit_gpr src_r, sljit_s32 dst, sljit_sw dstw, sljit_s32 is_32bit) { @@ -1008,17 +1040,16 @@ static sljit_s32 store_word(struct sljit_compiler *compiler, sljit_gpr src, sljit_ins ins; SLJIT_ASSERT(dst & SLJIT_MEM); - if (have_ldisp() || !is_32bit) - FAIL_IF(make_addr_bxy(compiler, &addr, dst, dstw, tmp1)); - else + + if (is_32bit && ((dst & OFFS_REG_MASK) || is_u12(dstw) || !is_s20(dstw))) { FAIL_IF(make_addr_bx(compiler, &addr, dst, dstw, tmp1)); + return push_inst(compiler, 0x50000000 /* st */ | R20A(src_r) | R16A(addr.index) | R12A(addr.base) | (sljit_ins)addr.offset); + } - if (is_32bit) - ins = WHEN(is_u12(addr.offset), src, st, sty, addr); - else - ins = stg(src, addr.offset, addr.index, addr.base); + FAIL_IF(make_addr_bxy(compiler, &addr, dst, dstw, tmp1)); - return push_inst(compiler, ins); + ins = is_32bit ? 0xe30000000050 /* sty */ : 0xe30000000024 /* stg */; + return push_inst(compiler, ins | R36A(src_r) | R32A(addr.index) | R28A(addr.base) | disp_s20(addr.offset)); } #undef WHEN @@ -1618,16 +1649,24 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type) { /* TODO(mundaym): implement all */ switch (feature_type) { + case SLJIT_HAS_FPU: case SLJIT_HAS_CLZ: - return have_eimm() ? 1 : 0; /* FLOGR instruction */ + case SLJIT_HAS_ROT: + case SLJIT_HAS_PREFETCH: + return 1; + case SLJIT_HAS_CTZ: + return 2; case SLJIT_HAS_CMOV: return have_lscond1() ? 1 : 0; - case SLJIT_HAS_FPU: - return 1; } return 0; } +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_cmp_info(sljit_s32 type) +{ + return (type >= SLJIT_UNORDERED && type <= SLJIT_ORDERED_LESS_EQUAL); +} + /* --------------------------------------------------------------------- */ /* Entry, exit */ /* --------------------------------------------------------------------- */ @@ -1636,7 +1675,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds, sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size) { - sljit_s32 word_arg_count = 0; + sljit_s32 saved_arg_count = SLJIT_KEPT_SAVEDS_COUNT(options); sljit_s32 offset, i, tmp; CHECK_ERROR(); @@ -1648,8 +1687,13 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi offset = 2 * SSIZE_OF(sw); if (saveds + scratches >= SLJIT_NUMBER_OF_REGISTERS) { - FAIL_IF(push_inst(compiler, stmg(r6, r14, offset, r15))); /* save registers TODO(MGM): optimize */ - offset += 9 * SSIZE_OF(sw); + if (saved_arg_count == 0) { + FAIL_IF(push_inst(compiler, stmg(r6, r14, offset, r15))); + offset += 9 * SSIZE_OF(sw); + } else { + FAIL_IF(push_inst(compiler, stmg(r6, r13 - (sljit_gpr)saved_arg_count, offset, r15))); + offset += (8 - saved_arg_count) * SSIZE_OF(sw); + } } else { if (scratches == SLJIT_FIRST_SAVED_REG) { FAIL_IF(push_inst(compiler, stg(r6, offset, 0, r15))); @@ -1659,15 +1703,30 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi offset += (scratches - (SLJIT_FIRST_SAVED_REG - 1)) * SSIZE_OF(sw); } - if (saveds == 0) { - FAIL_IF(push_inst(compiler, stg(r14, offset, 0, r15))); - offset += SSIZE_OF(sw); - } else { - FAIL_IF(push_inst(compiler, stmg(r14 - (sljit_gpr)saveds, r14, offset, r15))); - offset += (saveds + 1) * SSIZE_OF(sw); + if (saved_arg_count == 0) { + if (saveds == 0) { + FAIL_IF(push_inst(compiler, stg(r14, offset, 0, r15))); + offset += SSIZE_OF(sw); + } else { + FAIL_IF(push_inst(compiler, stmg(r14 - (sljit_gpr)saveds, r14, offset, r15))); + offset += (saveds + 1) * SSIZE_OF(sw); + } + } else if (saveds > saved_arg_count) { + if (saveds == saved_arg_count + 1) { + FAIL_IF(push_inst(compiler, stg(r14 - (sljit_gpr)saveds, offset, 0, r15))); + offset += SSIZE_OF(sw); + } else { + FAIL_IF(push_inst(compiler, stmg(r14 - (sljit_gpr)saveds, r13 - (sljit_gpr)saved_arg_count, offset, r15))); + offset += (saveds - saved_arg_count) * SSIZE_OF(sw); + } } } + if (saved_arg_count > 0) { + FAIL_IF(push_inst(compiler, stg(r14, offset, 0, r15))); + offset += SSIZE_OF(sw); + } + tmp = SLJIT_FS0 - fsaveds; for (i = SLJIT_FS0; i > tmp; i--) { FAIL_IF(push_inst(compiler, 0x60000000 /* std */ | F20(i) | R12A(r15) | (sljit_ins)offset)); @@ -1684,15 +1743,19 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi FAIL_IF(push_inst(compiler, 0xe30000000071 /* lay */ | R36A(r15) | R28A(r15) | disp_s20(-local_size))); + if (options & SLJIT_ENTER_REG_ARG) + return SLJIT_SUCCESS; + arg_types >>= SLJIT_ARG_SHIFT; + saved_arg_count = 0; tmp = 0; while (arg_types > 0) { if ((arg_types & SLJIT_ARG_MASK) < SLJIT_ARG_TYPE_F64) { if (!(arg_types & SLJIT_ARG_TYPE_SCRATCH_REG)) { - FAIL_IF(push_inst(compiler, lgr(gpr(SLJIT_S0 - tmp), gpr(SLJIT_R0 + word_arg_count)))); - tmp++; + FAIL_IF(push_inst(compiler, lgr(gpr(SLJIT_S0 - saved_arg_count), gpr(SLJIT_R0 + tmp)))); + saved_arg_count++; } - word_arg_count++; + tmp++; } arg_types >>= SLJIT_ARG_SHIFT; @@ -1713,12 +1776,13 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *comp return SLJIT_SUCCESS; } -static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler) +static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler, sljit_gpr last_reg) { sljit_s32 offset, i, tmp; sljit_s32 local_size = compiler->local_size; sljit_s32 saveds = compiler->saveds; sljit_s32 scratches = compiler->scratches; + sljit_s32 kept_saveds_count = SLJIT_KEPT_SAVEDS_COUNT(compiler->options); if (is_u12(local_size)) FAIL_IF(push_inst(compiler, 0x41000000 /* ly */ | R20A(r15) | R12A(r15) | (sljit_ins)local_size)); @@ -1727,8 +1791,13 @@ static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler) offset = 2 * SSIZE_OF(sw); if (saveds + scratches >= SLJIT_NUMBER_OF_REGISTERS) { - FAIL_IF(push_inst(compiler, lmg(r6, r14, offset, r15))); /* save registers TODO(MGM): optimize */ - offset += 9 * SSIZE_OF(sw); + if (kept_saveds_count == 0) { + FAIL_IF(push_inst(compiler, lmg(r6, last_reg, offset, r15))); + offset += 9 * SSIZE_OF(sw); + } else { + FAIL_IF(push_inst(compiler, lmg(r6, r13 - (sljit_gpr)kept_saveds_count, offset, r15))); + offset += (8 - kept_saveds_count) * SSIZE_OF(sw); + } } else { if (scratches == SLJIT_FIRST_SAVED_REG) { FAIL_IF(push_inst(compiler, lg(r6, offset, 0, r15))); @@ -1738,15 +1807,35 @@ static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler) offset += (scratches - (SLJIT_FIRST_SAVED_REG - 1)) * SSIZE_OF(sw); } - if (saveds == 0) { - FAIL_IF(push_inst(compiler, lg(r14, offset, 0, r15))); - offset += SSIZE_OF(sw); - } else { - FAIL_IF(push_inst(compiler, lmg(r14 - (sljit_gpr)saveds, r14, offset, r15))); - offset += (saveds + 1) * SSIZE_OF(sw); + if (kept_saveds_count == 0) { + if (saveds == 0) { + if (last_reg == r14) + FAIL_IF(push_inst(compiler, lg(r14, offset, 0, r15))); + offset += SSIZE_OF(sw); + } else if (saveds == 1 && last_reg == r13) { + FAIL_IF(push_inst(compiler, lg(r13, offset, 0, r15))); + offset += 2 * SSIZE_OF(sw); + } else { + FAIL_IF(push_inst(compiler, lmg(r14 - (sljit_gpr)saveds, last_reg, offset, r15))); + offset += (saveds + 1) * SSIZE_OF(sw); + } + } else if (saveds > kept_saveds_count) { + if (saveds == kept_saveds_count + 1) { + FAIL_IF(push_inst(compiler, lg(r14 - (sljit_gpr)saveds, offset, 0, r15))); + offset += SSIZE_OF(sw); + } else { + FAIL_IF(push_inst(compiler, lmg(r14 - (sljit_gpr)saveds, r13 - (sljit_gpr)kept_saveds_count, offset, r15))); + offset += (saveds - kept_saveds_count) * SSIZE_OF(sw); + } } } + if (kept_saveds_count > 0) { + if (last_reg == r14) + FAIL_IF(push_inst(compiler, lg(r14, offset, 0, r15))); + offset += SSIZE_OF(sw); + } + tmp = SLJIT_FS0 - compiler->fsaveds; for (i = SLJIT_FS0; i > tmp; i--) { FAIL_IF(push_inst(compiler, 0x68000000 /* ld */ | F20(i) | R12A(r15) | (sljit_ins)offset)); @@ -1766,10 +1855,33 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_void(struct sljit_compiler CHECK_ERROR(); CHECK(check_sljit_emit_return_void(compiler)); - FAIL_IF(emit_stack_frame_release(compiler)); + FAIL_IF(emit_stack_frame_release(compiler, r14)); return push_inst(compiler, br(r14)); /* return */ } +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_to(struct sljit_compiler *compiler, + sljit_s32 src, sljit_sw srcw) +{ + CHECK_ERROR(); + CHECK(check_sljit_emit_return_to(compiler, src, srcw)); + + if (src & SLJIT_MEM) { + ADJUST_LOCAL_OFFSET(src, srcw); + FAIL_IF(load_word(compiler, tmp1, src, srcw, 0 /* 64-bit */)); + src = TMP_REG2; + srcw = 0; + } else if (src >= SLJIT_FIRST_SAVED_REG && src <= (SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options))) { + FAIL_IF(push_inst(compiler, lgr(tmp1, gpr(src)))); + src = TMP_REG2; + srcw = 0; + } + + FAIL_IF(emit_stack_frame_release(compiler, r13)); + + SLJIT_SKIP_CHECKS(compiler); + return sljit_emit_ijump(compiler, SLJIT_JUMP, src, srcw); +} + /* --------------------------------------------------------------------- */ /* Operators */ /* --------------------------------------------------------------------- */ @@ -1858,6 +1970,47 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compile return push_inst(compiler, lgr(arg1, tmp0)); } +static sljit_s32 sljit_emit_clz_ctz(struct sljit_compiler *compiler, sljit_s32 op, sljit_gpr dst_r, sljit_gpr src_r) +{ + sljit_s32 is_ctz = (GET_OPCODE(op) == SLJIT_CTZ); + + if ((op & SLJIT_32) && src_r != tmp0) { + FAIL_IF(push_inst(compiler, 0xb9160000 /* llgfr */ | R4A(tmp0) | R0A(src_r))); + src_r = tmp0; + } + + if (is_ctz) { + FAIL_IF(push_inst(compiler, ((op & SLJIT_32) ? 0x1300 /* lcr */ : 0xb9030000 /* lcgr */) | R4A(tmp1) | R0A(src_r))); + + if (src_r == tmp0) + FAIL_IF(push_inst(compiler, ((op & SLJIT_32) ? 0x1400 /* nr */ : 0xb9800000 /* ngr */) | R4A(tmp0) | R0A(tmp1))); + else + FAIL_IF(push_inst(compiler, 0xb9e40000 /* ngrk */ | R12A(tmp1) | R4A(tmp0) | R0A(src_r))); + + src_r = tmp0; + } + + FAIL_IF(push_inst(compiler, 0xb9830000 /* flogr */ | R4A(tmp0) | R0A(src_r))); + + if (is_ctz) + FAIL_IF(push_inst(compiler, 0xec00000000d9 /* aghik */ | R36A(tmp1) | R32A(tmp0) | ((sljit_ins)(-64 & 0xffff) << 16))); + + if (op & SLJIT_32) { + if (!is_ctz && dst_r != tmp0) + return push_inst(compiler, 0xec00000000d9 /* aghik */ | R36A(dst_r) | R32A(tmp0) | ((sljit_ins)(-32 & 0xffff) << 16)); + + FAIL_IF(push_inst(compiler, 0xc20800000000 /* agfi */ | R36A(tmp0) | (sljit_u32)-32)); + } + + if (is_ctz) + FAIL_IF(push_inst(compiler, 0xec0000000057 /* rxsbg */ | R36A(tmp0) | R32A(tmp1) | ((sljit_ins)((op & SLJIT_32) ? 59 : 58) << 24) | (63 << 16) | ((sljit_ins)((op & SLJIT_32) ? 5 : 6) << 8))); + + if (dst_r == tmp0) + return SLJIT_SUCCESS; + + return push_inst(compiler, ((op & SLJIT_32) ? 0x1800 /* lr */ : 0xb9040000 /* lgr */) | R4A(dst_r) | R0A(tmp0)); +} + /* LEVAL will be defined later with different parameters as needed */ #define WHEN2(cond, i1, i2) (cond) ? LEVAL(i1) : LEVAL(i2) @@ -2091,23 +2244,25 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile dst_r = FAST_IS_REG(dst) ? gpr(REG_MASK & dst) : tmp0; src_r = FAST_IS_REG(src) ? gpr(REG_MASK & src) : tmp0; - if (src & SLJIT_MEM) - FAIL_IF(load_word(compiler, src_r, src, srcw, src & SLJIT_32)); compiler->status_flags_state = op & (VARIABLE_FLAG_MASK | SLJIT_SET_Z); /* TODO(mundaym): optimize loads and stores */ - switch (opcode | (op & SLJIT_32)) { + switch (opcode) { case SLJIT_NOT: - /* emulate ~x with x^-1 */ - FAIL_IF(push_load_imm_inst(compiler, tmp1, -1)); - if (src_r != dst_r) - FAIL_IF(push_inst(compiler, lgr(dst_r, src_r))); + if (src & SLJIT_MEM) + FAIL_IF(load_word(compiler, src_r, src, srcw, op & SLJIT_32)); - FAIL_IF(push_inst(compiler, xgr(dst_r, tmp1))); - break; - case SLJIT_NOT32: /* emulate ~x with x^-1 */ + if (!(op & SLJIT_32)) { + FAIL_IF(push_load_imm_inst(compiler, tmp1, -1)); + if (src_r != dst_r) + FAIL_IF(push_inst(compiler, lgr(dst_r, src_r))); + + FAIL_IF(push_inst(compiler, xgr(dst_r, tmp1))); + break; + } + if (have_eimm()) FAIL_IF(push_inst(compiler, xilf(dst_r, 0xffffffff))); else { @@ -2119,24 +2274,11 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile } break; case SLJIT_CLZ: - if (have_eimm()) { - FAIL_IF(push_inst(compiler, flogr(tmp0, src_r))); /* clobbers tmp1 */ - if (dst_r != tmp0) - FAIL_IF(push_inst(compiler, lgr(dst_r, tmp0))); - } else { - abort(); /* TODO(mundaym): no eimm (?) */ - } - break; - case SLJIT_CLZ32: - if (have_eimm()) { - FAIL_IF(push_inst(compiler, sllg(tmp1, src_r, 32, 0))); - FAIL_IF(push_inst(compiler, iilf(tmp1, 0xffffffff))); - FAIL_IF(push_inst(compiler, flogr(tmp0, tmp1))); /* clobbers tmp1 */ - if (dst_r != tmp0) - FAIL_IF(push_inst(compiler, lr(dst_r, tmp0))); - } else { - abort(); /* TODO(mundaym): no eimm (?) */ - } + case SLJIT_CTZ: + if (src & SLJIT_MEM) + FAIL_IF(load_unsigned_word(compiler, src_r, src, srcw, op & SLJIT_32)); + + FAIL_IF(sljit_emit_clz_ctz(compiler, op, dst_r, src_r)); break; default: SLJIT_UNREACHABLE(); @@ -2145,9 +2287,8 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile if ((op & (SLJIT_SET_Z | VARIABLE_FLAG_MASK)) == (SLJIT_SET_Z | SLJIT_SET_OVERFLOW)) FAIL_IF(update_zero_overflow(compiler, op, dst_r)); - /* TODO(carenas): doesn't need FAIL_IF */ if (dst & SLJIT_MEM) - FAIL_IF(store_word(compiler, dst_r, dst, dstw, op & SLJIT_32)); + return store_word(compiler, dst_r, dst, dstw, op & SLJIT_32); return SLJIT_SUCCESS; } @@ -2166,11 +2307,6 @@ static SLJIT_INLINE int is_commutative(sljit_s32 op) return 0; } -static SLJIT_INLINE int is_shift(sljit_s32 op) { - sljit_s32 v = GET_OPCODE(op); - return (v == SLJIT_SHL || v == SLJIT_ASHR || v == SLJIT_LSHR) ? 1 : 0; -} - static const struct ins_forms add_forms = { 0x1a00, /* ar */ 0xb9080000, /* agr */ @@ -2604,33 +2740,41 @@ static sljit_s32 sljit_emit_shift(struct sljit_compiler *compiler, sljit_s32 op, sljit_ins ins; if (FAST_IS_REG(src1)) - src_r = gpr(src1 & REG_MASK); + src_r = gpr(src1); else FAIL_IF(emit_move(compiler, tmp0, src1, src1w)); - if (src2 & SLJIT_IMM) + if (!(src2 & SLJIT_IMM)) { + if (FAST_IS_REG(src2)) + base_r = gpr(src2); + else { + FAIL_IF(emit_move(compiler, tmp1, src2, src2w)); + base_r = tmp1; + } + + if ((op & SLJIT_32) && (type == SLJIT_MSHL || type == SLJIT_MLSHR || type == SLJIT_MASHR)) { + if (base_r != tmp1) { + FAIL_IF(push_inst(compiler, 0xec0000000055 /* risbg */ | R36A(tmp1) | R32A(base_r) | (59 << 24) | (1 << 23) | (63 << 16))); + base_r = tmp1; + } else + FAIL_IF(push_inst(compiler, 0xa5070000 /* nill */ | R20A(tmp1) | 0x1f)); + } + } else imm = (sljit_ins)(src2w & ((op & SLJIT_32) ? 0x1f : 0x3f)); - else if (FAST_IS_REG(src2)) - base_r = gpr(src2 & REG_MASK); - else { - FAIL_IF(emit_move(compiler, tmp1, src2, src2w)); - base_r = tmp1; - } if ((op & SLJIT_32) && dst_r == src_r) { - if (type == SLJIT_SHL) + if (type == SLJIT_SHL || type == SLJIT_MSHL) ins = 0x89000000 /* sll */; - else if (type == SLJIT_LSHR) + else if (type == SLJIT_LSHR || type == SLJIT_MLSHR) ins = 0x88000000 /* srl */; else ins = 0x8a000000 /* sra */; FAIL_IF(push_inst(compiler, ins | R20A(dst_r) | R12A(base_r) | imm)); - } - else { - if (type == SLJIT_SHL) + } else { + if (type == SLJIT_SHL || type == SLJIT_MSHL) ins = (op & SLJIT_32) ? 0xeb00000000df /* sllk */ : 0xeb000000000d /* sllg */; - else if (type == SLJIT_LSHR) + else if (type == SLJIT_LSHR || type == SLJIT_MLSHR) ins = (op & SLJIT_32) ? 0xeb00000000de /* srlk */ : 0xeb000000000c /* srlg */; else ins = (op & SLJIT_32) ? 0xeb00000000dc /* srak */ : 0xeb000000000a /* srag */; @@ -2644,6 +2788,47 @@ static sljit_s32 sljit_emit_shift(struct sljit_compiler *compiler, sljit_s32 op, return SLJIT_SUCCESS; } +static sljit_s32 sljit_emit_rotate(struct sljit_compiler *compiler, sljit_s32 op, + sljit_s32 dst, + sljit_s32 src1, sljit_sw src1w, + sljit_s32 src2, sljit_sw src2w) +{ + sljit_gpr dst_r = FAST_IS_REG(dst) ? gpr(dst & REG_MASK) : tmp0; + sljit_gpr src_r = tmp0; + sljit_gpr base_r = tmp0; + sljit_ins imm = 0; + sljit_ins ins; + + if (FAST_IS_REG(src1)) + src_r = gpr(src1); + else + FAIL_IF(emit_move(compiler, tmp0, src1, src1w)); + + if (!(src2 & SLJIT_IMM)) { + if (FAST_IS_REG(src2)) + base_r = gpr(src2); + else { + FAIL_IF(emit_move(compiler, tmp1, src2, src2w)); + base_r = tmp1; + } + } + + if (GET_OPCODE(op) == SLJIT_ROTR) { + if (!(src2 & SLJIT_IMM)) { + ins = (op & SLJIT_32) ? 0x1300 /* lcr */ : 0xb9030000 /* lcgr */; + FAIL_IF(push_inst(compiler, ins | R4A(tmp1) | R0A(base_r))); + base_r = tmp1; + } else + src2w = -src2w; + } + + if (src2 & SLJIT_IMM) + imm = (sljit_ins)(src2w & ((op & SLJIT_32) ? 0x1f : 0x3f)); + + ins = (op & SLJIT_32) ? 0xeb000000001d /* rll */ : 0xeb000000001c /* rllg */; + return push_inst(compiler, ins | R36A(dst_r) | R32A(src_r) | R28A(base_r) | (imm << 16)); +} + static const struct ins_forms addc_forms = { 0xb9980000, /* alcr */ 0xb9880000, /* alcgr */ @@ -2716,10 +2901,17 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compile FAIL_IF(sljit_emit_bitwise(compiler, op, dst, src1, src1w, src2, src2w)); break; case SLJIT_SHL: + case SLJIT_MSHL: case SLJIT_LSHR: + case SLJIT_MLSHR: case SLJIT_ASHR: + case SLJIT_MASHR: FAIL_IF(sljit_emit_shift(compiler, op, dst, src1, src1w, src2, src2w)); break; + case SLJIT_ROTL: + case SLJIT_ROTR: + FAIL_IF(sljit_emit_rotate(compiler, op, dst, src1, src1w, src2, src2w)); + break; } if (dst & SLJIT_MEM) @@ -2734,18 +2926,130 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2u(struct sljit_compiler *compil CHECK_ERROR(); CHECK(check_sljit_emit_op2(compiler, op, 1, 0, 0, src1, src1w, src2, src2w)); -#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \ - || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) - compiler->skip_checks = 1; -#endif + SLJIT_SKIP_CHECKS(compiler); return sljit_emit_op2(compiler, op, (sljit_s32)tmp0, 0, src1, src1w, src2, src2w); } +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_shift_into(struct sljit_compiler *compiler, sljit_s32 op, + sljit_s32 src_dst, + sljit_s32 src1, sljit_sw src1w, + sljit_s32 src2, sljit_sw src2w) +{ + sljit_s32 is_right; + sljit_sw bit_length = (op & SLJIT_32) ? 32 : 64; + sljit_gpr src_dst_r = gpr(src_dst); + sljit_gpr src1_r = tmp0; + sljit_gpr src2_r = tmp1; + sljit_ins ins; + + CHECK_ERROR(); + CHECK(check_sljit_emit_shift_into(compiler, op, src_dst, src1, src1w, src2, src2w)); + + is_right = (GET_OPCODE(op) == SLJIT_LSHR || GET_OPCODE(op) == SLJIT_MLSHR); + + if (src_dst == src1) { + SLJIT_SKIP_CHECKS(compiler); + return sljit_emit_op2(compiler, (is_right ? SLJIT_ROTR : SLJIT_ROTL) | (op & SLJIT_32), src_dst, 0, src_dst, 0, src2, src2w); + } + + ADJUST_LOCAL_OFFSET(src1, src1w); + ADJUST_LOCAL_OFFSET(src2, src2w); + + if (src1 & SLJIT_MEM) + FAIL_IF(load_word(compiler, tmp0, src1, src1w, op & SLJIT_32)); + else if (src1 & SLJIT_IMM) + FAIL_IF(push_load_imm_inst(compiler, tmp0, src1w)); + else + src1_r = gpr(src1); + + if (src2 & SLJIT_IMM) { + src2w &= bit_length - 1; + + if (src2w == 0) + return SLJIT_SUCCESS; + } else if (!(src2 & SLJIT_MEM)) + src2_r = gpr(src2); + else + FAIL_IF(load_word(compiler, tmp1, src2, src2w, op & SLJIT_32)); + + if (src2 & SLJIT_IMM) { + if (op & SLJIT_32) { + ins = is_right ? 0x88000000 /* srl */ : 0x89000000 /* sll */; + FAIL_IF(push_inst(compiler, ins | R20A(src_dst_r) | (sljit_ins)src2w)); + } else { + ins = is_right ? 0xeb000000000c /* srlg */ : 0xeb000000000d /* sllg */; + FAIL_IF(push_inst(compiler, ins | R36A(src_dst_r) | R32A(src_dst_r) | ((sljit_ins)src2w << 16))); + } + + ins = 0xec0000000055 /* risbg */; + + if (is_right) { + src2w = bit_length - src2w; + ins |= ((sljit_ins)(64 - bit_length) << 24) | ((sljit_ins)(63 - src2w) << 16) | ((sljit_ins)src2w << 8); + } else + ins |= ((sljit_ins)(64 - src2w) << 24) | ((sljit_ins)63 << 16) | ((sljit_ins)src2w << 8); + + return push_inst(compiler, ins | R36A(src_dst_r) | R32A(src1_r)); + } + + if (op & SLJIT_32) { + if (GET_OPCODE(op) == SLJIT_MSHL || GET_OPCODE(op) == SLJIT_MLSHR) { + if (src2_r != tmp1) { + FAIL_IF(push_inst(compiler, 0xec0000000055 /* risbg */ | R36A(tmp1) | R32A(src2_r) | (59 << 24) | (1 << 23) | (63 << 16))); + src2_r = tmp1; + } else + FAIL_IF(push_inst(compiler, 0xa5070000 /* nill */ | R20A(tmp1) | 0x1f)); + } + + ins = is_right ? 0x88000000 /* srl */ : 0x89000000 /* sll */; + FAIL_IF(push_inst(compiler, ins | R20A(src_dst_r) | R12A(src2_r))); + + if (src2_r != tmp1) { + FAIL_IF(push_inst(compiler, 0xa50f0000 /* llill */ | R20A(tmp1) | 0x1f)); + FAIL_IF(push_inst(compiler, 0x1700 /* xr */ | R4A(tmp1) | R0A(src2_r))); + } else + FAIL_IF(push_inst(compiler, 0xc00700000000 /* xilf */ | R36A(tmp1) | 0x1f)); + + if (src1_r == tmp0) { + ins = is_right ? 0x89000000 /* sll */ : 0x88000000 /* srl */; + FAIL_IF(push_inst(compiler, ins | R20A(tmp0) | R12A(tmp1) | 0x1)); + } else { + ins = is_right ? 0xeb00000000df /* sllk */ : 0xeb00000000de /* srlk */; + FAIL_IF(push_inst(compiler, ins | R36A(tmp0) | R32A(src1_r) | R28A(tmp1) | (0x1 << 16))); + } + + return push_inst(compiler, 0x1600 /* or */ | R4A(src_dst_r) | R0A(tmp0)); + } + + ins = is_right ? 0xeb000000000c /* srlg */ : 0xeb000000000d /* sllg */; + FAIL_IF(push_inst(compiler, ins | R36A(src_dst_r) | R32A(src_dst_r) | R28A(src2_r))); + + ins = is_right ? 0xeb000000000d /* sllg */ : 0xeb000000000c /* srlg */; + + if (!(op & SLJIT_SHIFT_INTO_NON_ZERO)) { + if (src2_r != tmp1) + FAIL_IF(push_inst(compiler, 0xa50f0000 /* llill */ | R20A(tmp1) | 0x3f)); + + FAIL_IF(push_inst(compiler, ins | R36A(tmp0) | R32A(src1_r) | (0x1 << 16))); + src1_r = tmp0; + + if (src2_r != tmp1) + FAIL_IF(push_inst(compiler, 0xb9820000 /* xgr */ | R4A(tmp1) | R0A(src2_r))); + else + FAIL_IF(push_inst(compiler, 0xc00700000000 /* xilf */ | R36A(tmp1) | 0x3f)); + } else + FAIL_IF(push_inst(compiler, 0xb9030000 /* lcgr */ | R4A(tmp1) | R0A(src2_r))); + + FAIL_IF(push_inst(compiler, ins | R36A(tmp0) | R32A(src1_r) | R28A(tmp1))); + return push_inst(compiler, 0xb9810000 /* ogr */ | R4A(src_dst_r) | R0A(tmp0)); +} + SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_src( struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 src, sljit_sw srcw) { sljit_gpr src_r; + struct addr addr; CHECK_ERROR(); CHECK(check_sljit_emit_op_src(compiler, op, src, srcw)); @@ -2759,16 +3063,14 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_src( return push_inst(compiler, br(src_r)); case SLJIT_SKIP_FRAMES_BEFORE_FAST_RETURN: - /* TODO(carenas): implement? */ return SLJIT_SUCCESS; case SLJIT_PREFETCH_L1: case SLJIT_PREFETCH_L2: case SLJIT_PREFETCH_L3: case SLJIT_PREFETCH_ONCE: - /* TODO(carenas): implement */ - return SLJIT_SUCCESS; + FAIL_IF(make_addr_bxy(compiler, &addr, src, srcw, tmp1)); + return push_inst(compiler, 0xe31000000036 /* pfd */ | R32A(addr.index) | R28A(addr.base) | disp_s20(addr.offset)); default: - /* TODO(carenas): probably should not success by default */ return SLJIT_SUCCESS; } @@ -3064,10 +3366,10 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_enter(struct sljit_compiler * ADJUST_LOCAL_OFFSET(dst, dstw); if (FAST_IS_REG(dst)) - return push_inst(compiler, lgr(gpr(dst), fast_link_r)); + return push_inst(compiler, lgr(gpr(dst), link_r)); /* memory */ - return store_word(compiler, fast_link_r, dst, dstw, 0); + return store_word(compiler, link_r, dst, dstw, 0); } /* --------------------------------------------------------------------- */ @@ -3107,7 +3409,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compile /* emit jump instruction */ type &= 0xff; if (type >= SLJIT_FAST_CALL) - PTR_FAIL_IF(push_inst(compiler, brasl(type == SLJIT_FAST_CALL ? fast_link_r : link_r, 0))); + PTR_FAIL_IF(push_inst(compiler, brasl(link_r, 0))); else PTR_FAIL_IF(push_inst(compiler, brcl(mask, 0))); @@ -3117,19 +3419,16 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compile SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 arg_types) { + SLJIT_UNUSED_ARG(arg_types); CHECK_ERROR_PTR(); CHECK_PTR(check_sljit_emit_call(compiler, type, arg_types)); if (type & SLJIT_CALL_RETURN) { - PTR_FAIL_IF(emit_stack_frame_release(compiler)); + PTR_FAIL_IF(emit_stack_frame_release(compiler, r14)); type = SLJIT_JUMP | (type & SLJIT_REWRITABLE_JUMP); } -#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \ - || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) - compiler->skip_checks = 1; -#endif - + SLJIT_SKIP_CHECKS(compiler); return sljit_emit_jump(compiler, type); } @@ -3151,7 +3450,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compi /* emit jump instruction */ if (type >= SLJIT_FAST_CALL) - return push_inst(compiler, basr(type == SLJIT_FAST_CALL ? fast_link_r : link_r, src_r)); + return push_inst(compiler, basr(link_r, src_r)); return push_inst(compiler, br(src_r)); } @@ -3169,23 +3468,21 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compi ADJUST_LOCAL_OFFSET(src, srcw); FAIL_IF(load_word(compiler, tmp1, src, srcw, 0 /* 64-bit */)); src = TMP_REG2; + srcw = 0; } if (type & SLJIT_CALL_RETURN) { - if (src >= SLJIT_FIRST_SAVED_REG && src <= SLJIT_S0) { + if (src >= SLJIT_FIRST_SAVED_REG && src <= (SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options))) { FAIL_IF(push_inst(compiler, lgr(tmp1, gpr(src)))); src = TMP_REG2; + srcw = 0; } - FAIL_IF(emit_stack_frame_release(compiler)); + FAIL_IF(emit_stack_frame_release(compiler, r14)); type = SLJIT_JUMP; } -#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \ - || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) - compiler->skip_checks = 1; -#endif - + SLJIT_SKIP_CHECKS(compiler); return sljit_emit_ijump(compiler, type, src, srcw); } @@ -3193,7 +3490,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *co sljit_s32 dst, sljit_sw dstw, sljit_s32 type) { - sljit_u8 mask = get_cc(compiler, type & 0xff); + sljit_u8 mask = get_cc(compiler, type); CHECK_ERROR(); CHECK(check_sljit_emit_op_flags(compiler, op, dst, dstw, type)); @@ -3263,27 +3560,92 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_cmov(struct sljit_compiler *compil sljit_s32 dst_reg, sljit_s32 src, sljit_sw srcw) { - sljit_u8 mask = get_cc(compiler, type & 0xff); - sljit_gpr dst_r = gpr(dst_reg & ~SLJIT_32); - sljit_gpr src_r = FAST_IS_REG(src) ? gpr(src) : tmp0; + sljit_ins mask = get_cc(compiler, type & ~SLJIT_32); + sljit_gpr src_r; + sljit_ins ins; CHECK_ERROR(); CHECK(check_sljit_emit_cmov(compiler, type, dst_reg, src, srcw)); - if (src & SLJIT_IMM) { - /* TODO(mundaym): fast path with lscond2 */ - FAIL_IF(push_load_imm_inst(compiler, src_r, srcw)); + if (type & SLJIT_32) + srcw = (sljit_s32)srcw; + + if (have_lscond2() && (src & SLJIT_IMM) && is_s16(srcw)) { + ins = (type & SLJIT_32) ? 0xec0000000042 /* lochi */ : 0xec0000000046 /* locghi */; + return push_inst(compiler, ins | R36A(gpr(dst_reg)) | (mask << 32) | (sljit_ins)(srcw & 0xffff) << 16); } - #define LEVAL(i) i(dst_r, src_r, mask) - if (have_lscond1()) - return push_inst(compiler, - WHEN2(dst_reg & SLJIT_32, locr, locgr)); + if (src & SLJIT_IMM) { + FAIL_IF(push_load_imm_inst(compiler, tmp0, srcw)); + src_r = tmp0; + } else + src_r = gpr(src); - #undef LEVAL + if (have_lscond1()) { + ins = (type & SLJIT_32) ? 0xb9f20000 /* locr */ : 0xb9e20000 /* locgr */; + return push_inst(compiler, ins | (mask << 12) | R4A(gpr(dst_reg)) | R0A(src_r)); + } - /* TODO(mundaym): implement */ - return SLJIT_ERR_UNSUPPORTED; + return sljit_emit_cmov_generic(compiler, type, dst_reg, src, srcw); +} + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compiler, sljit_s32 type, + sljit_s32 reg, + sljit_s32 mem, sljit_sw memw) +{ + sljit_ins ins, reg1, reg2, base, offs = 0; + + CHECK_ERROR(); + CHECK(check_sljit_emit_mem(compiler, type, reg, mem, memw)); + + if (!(reg & REG_PAIR_MASK)) + return sljit_emit_mem_unaligned(compiler, type, reg, mem, memw); + + ADJUST_LOCAL_OFFSET(mem, memw); + + base = gpr(mem & REG_MASK); + reg1 = gpr(REG_PAIR_FIRST(reg)); + reg2 = gpr(REG_PAIR_SECOND(reg)); + + if (mem & OFFS_REG_MASK) { + memw &= 0x3; + offs = gpr(OFFS_REG(mem)); + + if (memw != 0) { + FAIL_IF(push_inst(compiler, 0xeb000000000d /* sllg */ | R36A(tmp1) | R32A(offs) | ((sljit_ins)memw << 16))); + offs = tmp1; + } else if (!(type & SLJIT_MEM_STORE) && (base == reg1 || base == reg2) && (offs == reg1 || offs == reg2)) { + FAIL_IF(push_inst(compiler, 0xb9f80000 | R12A(tmp1) | R4A(base) | R0A(offs))); + base = tmp1; + offs = 0; + } + + memw = 0; + } else if (memw < -0x80000 || memw > 0x7ffff - ((reg2 == reg1 + 1) ? 0 : SSIZE_OF(sw))) { + FAIL_IF(push_load_imm_inst(compiler, tmp1, memw)); + + if (base == 0) + base = tmp1; + else + offs = tmp1; + + memw = 0; + } + + if (offs == 0 && reg2 == (reg1 + 1)) { + ins = (type & SLJIT_MEM_STORE) ? 0xeb0000000024 /* stmg */ : 0xeb0000000004 /* lmg */; + return push_inst(compiler, ins | R36A(reg1) | R32A(reg2) | R28A(base) | disp_s20((sljit_s32)memw)); + } + + ins = ((type & SLJIT_MEM_STORE) ? 0xe30000000024 /* stg */ : 0xe30000000004 /* lg */) | R32A(offs) | R28A(base); + + if (!(type & SLJIT_MEM_STORE) && base == reg1) { + FAIL_IF(push_inst(compiler, ins | R36A(reg2) | disp_s20((sljit_s32)memw + SSIZE_OF(sw)))); + return push_inst(compiler, ins | R36A(reg1) | disp_s20((sljit_s32)memw)); + } + + FAIL_IF(push_inst(compiler, ins | R36A(reg1) | disp_s20((sljit_s32)memw))); + return push_inst(compiler, ins | R36A(reg2) | disp_s20((sljit_s32)memw + SSIZE_OF(sw))); } /* --------------------------------------------------------------------- */ diff --git a/src/3rdparty/pcre2/src/sljit/sljitNativeX86_32.c b/src/3rdparty/pcre2/src/sljit/sljitNativeX86_32.c index b9a7b397899..08da03026d4 100644 --- a/src/3rdparty/pcre2/src/sljit/sljitNativeX86_32.c +++ b/src/3rdparty/pcre2/src/sljit/sljitNativeX86_32.c @@ -80,21 +80,28 @@ static sljit_u8* emit_x86_instruction(struct sljit_compiler *compiler, sljit_uw if (b & SLJIT_MEM) { if (!(b & REG_MASK)) inst_size += sizeof(sljit_sw); - else if (immb != 0 && !(b & OFFS_REG_MASK)) { - /* Immediate operand. */ - if (immb <= 127 && immb >= -128) - inst_size += sizeof(sljit_s8); - else - inst_size += sizeof(sljit_sw); + else { + if (immb != 0 && !(b & OFFS_REG_MASK)) { + /* Immediate operand. */ + if (immb <= 127 && immb >= -128) + inst_size += sizeof(sljit_s8); + else + inst_size += sizeof(sljit_sw); + } + else if (reg_map[b & REG_MASK] == 5) { + /* Swap registers if possible. */ + if ((b & OFFS_REG_MASK) && (immb & 0x3) == 0 && reg_map[OFFS_REG(b)] != 5) + b = SLJIT_MEM | OFFS_REG(b) | TO_OFFS_REG(b & REG_MASK); + else + inst_size += sizeof(sljit_s8); + } + + if (reg_map[b & REG_MASK] == 4 && !(b & OFFS_REG_MASK)) + b |= TO_OFFS_REG(SLJIT_SP); + + if (b & OFFS_REG_MASK) + inst_size += 1; /* SIB byte. */ } - else if (reg_map[b & REG_MASK] == 5) - inst_size += sizeof(sljit_s8); - - if ((b & REG_MASK) == SLJIT_SP && !(b & OFFS_REG_MASK)) - b |= TO_OFFS_REG(SLJIT_SP); - - if (b & OFFS_REG_MASK) - inst_size += 1; /* SIB byte. */ } /* Calculate size of a. */ @@ -107,9 +114,9 @@ static sljit_u8* emit_x86_instruction(struct sljit_compiler *compiler, sljit_uw inst_size += 4; } else if (flags & EX86_SHIFT_INS) { - imma &= 0x1f; + SLJIT_ASSERT(imma <= 0x1f); if (imma != 1) { - inst_size ++; + inst_size++; flags |= EX86_BYTE_ARG; } } else if (flags & EX86_BYTE_ARG) @@ -165,7 +172,7 @@ static sljit_u8* emit_x86_instruction(struct sljit_compiler *compiler, sljit_uw } else if (b & REG_MASK) { reg_map_b = reg_map[b & REG_MASK]; - if (!(b & OFFS_REG_MASK) || (b & OFFS_REG_MASK) == TO_OFFS_REG(SLJIT_SP) || reg_map_b == 5) { + if (!(b & OFFS_REG_MASK) || (b & OFFS_REG_MASK) == TO_OFFS_REG(SLJIT_SP)) { if (immb != 0 || reg_map_b == 5) { if (immb <= 127 && immb >= -128) *buf_ptr |= 0x40; @@ -190,8 +197,14 @@ static sljit_u8* emit_x86_instruction(struct sljit_compiler *compiler, sljit_uw } } else { + if (reg_map_b == 5) + *buf_ptr |= 0x40; + *buf_ptr++ |= 0x04; *buf_ptr++ = U8(reg_map_b | (reg_map[OFFS_REG(b)] << 3) | (immb << 6)); + + if (reg_map_b == 5) + *buf_ptr++ = 0; } } else { @@ -243,19 +256,16 @@ static sljit_u8* generate_far_jump_code(struct sljit_jump *jump, sljit_u8 *code_ return code_ptr; } -#define ENTER_R2_USED 0x00001 -#define ENTER_R2_TO_S 0x00002 -#define ENTER_R2_TO_R0 0x00004 -#define ENTER_R1_TO_S 0x00008 -#define ENTER_TMP_TO_R4 0x00010 -#define ENTER_TMP_TO_S 0x00020 +#define ENTER_TMP_TO_R4 0x00001 +#define ENTER_TMP_TO_S 0x00002 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compiler, sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds, sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size) { sljit_s32 word_arg_count, saved_arg_count, float_arg_count; - sljit_s32 size, locals_offset, args_size, types, status; + sljit_s32 size, args_size, types, status; + sljit_s32 kept_saveds_count = SLJIT_KEPT_SAVEDS_COUNT(options); sljit_u8 *inst; #ifdef _WIN32 sljit_s32 r2_offset = -1; @@ -271,108 +281,97 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi SLJIT_COMPILE_ASSERT(SLJIT_FR0 == 1, float_register_index_start); arg_types >>= SLJIT_ARG_SHIFT; - types = arg_types; word_arg_count = 0; - saved_arg_count = 0; - float_arg_count = 0; - args_size = SSIZE_OF(sw); status = 0; - while (types) { - switch (types & SLJIT_ARG_MASK) { - case SLJIT_ARG_TYPE_F64: - float_arg_count++; - FAIL_IF(emit_sse2_load(compiler, 0, float_arg_count, SLJIT_MEM1(SLJIT_SP), args_size)); - args_size += SSIZE_OF(f64); - break; - case SLJIT_ARG_TYPE_F32: - float_arg_count++; - FAIL_IF(emit_sse2_load(compiler, 1, float_arg_count, SLJIT_MEM1(SLJIT_SP), args_size)); - args_size += SSIZE_OF(f32); - break; - default: - word_arg_count++; - if (!(types & SLJIT_ARG_TYPE_SCRATCH_REG)) { - saved_arg_count++; - if (saved_arg_count == 4) - status |= ENTER_TMP_TO_S; - } else { - if (word_arg_count == 4) + if (options & SLJIT_ENTER_REG_ARG) { + args_size = 3 * SSIZE_OF(sw); + + while (arg_types) { + if ((arg_types & SLJIT_ARG_MASK) < SLJIT_ARG_TYPE_F64) { + word_arg_count++; + if (word_arg_count >= 4) status |= ENTER_TMP_TO_R4; -#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL) - if (word_arg_count == 3) - status |= ENTER_R2_USED; -#endif } -#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL) - if (word_arg_count <= 2 && !(options & SLJIT_ENTER_CDECL)) - break; -#endif - - args_size += SSIZE_OF(sw); - break; + arg_types >>= SLJIT_ARG_SHIFT; } - types >>= SLJIT_ARG_SHIFT; + + compiler->args_size = 0; + } else { + types = arg_types; + saved_arg_count = 0; + float_arg_count = 0; + args_size = SSIZE_OF(sw); + while (types) { + switch (types & SLJIT_ARG_MASK) { + case SLJIT_ARG_TYPE_F64: + float_arg_count++; + FAIL_IF(emit_sse2_load(compiler, 0, float_arg_count, SLJIT_MEM1(SLJIT_SP), args_size)); + args_size += SSIZE_OF(f64); + break; + case SLJIT_ARG_TYPE_F32: + float_arg_count++; + FAIL_IF(emit_sse2_load(compiler, 1, float_arg_count, SLJIT_MEM1(SLJIT_SP), args_size)); + args_size += SSIZE_OF(f32); + break; + default: + word_arg_count++; + + if (!(types & SLJIT_ARG_TYPE_SCRATCH_REG)) + saved_arg_count++; + + if (word_arg_count == 4) { + if (types & SLJIT_ARG_TYPE_SCRATCH_REG) { + status |= ENTER_TMP_TO_R4; + arg_types &= ~(SLJIT_ARG_FULL_MASK << 3 * SLJIT_ARG_SHIFT); + } else if (saved_arg_count == 4) { + status |= ENTER_TMP_TO_S; + arg_types &= ~(SLJIT_ARG_FULL_MASK << 3 * SLJIT_ARG_SHIFT); + } + } + + args_size += SSIZE_OF(sw); + break; + } + types >>= SLJIT_ARG_SHIFT; + } + + args_size -= SSIZE_OF(sw); + compiler->args_size = args_size; } - args_size -= SSIZE_OF(sw); - compiler->args_size = args_size; + size = (scratches > 9 ? (scratches - 9) : 0) + (saveds <= 3 ? saveds : 3) - kept_saveds_count; + if (!(options & SLJIT_ENTER_REG_ARG)) + size++; - /* [esp+0] for saving temporaries and function calls. */ - locals_offset = 2 * SSIZE_OF(sw); + if (size != 0) { + inst = (sljit_u8*)ensure_buf(compiler, (sljit_uw)(size + 1)); + FAIL_IF(!inst); -#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL) - if ((options & SLJIT_ENTER_CDECL) && scratches >= 3) - locals_offset = 4 * SSIZE_OF(sw); -#else - if (scratches >= 3) - locals_offset = 4 * SSIZE_OF(sw); -#endif + INC_SIZE((sljit_uw)size); - compiler->scratches_offset = locals_offset; + if (!(options & SLJIT_ENTER_REG_ARG)) + PUSH_REG(reg_map[TMP_REG1]); - if (scratches > 3) - locals_offset += ((scratches > (3 + 6)) ? 6 : (scratches - 3)) * SSIZE_OF(sw); + if ((saveds > 2 && kept_saveds_count <= 2) || scratches > 9) + PUSH_REG(reg_map[SLJIT_S2]); + if ((saveds > 1 && kept_saveds_count <= 1) || scratches > 10) + PUSH_REG(reg_map[SLJIT_S1]); + if ((saveds > 0 && kept_saveds_count == 0) || scratches > 11) + PUSH_REG(reg_map[SLJIT_S0]); - if (saveds > 3) - locals_offset += (saveds - 3) * SSIZE_OF(sw); - - compiler->locals_offset = locals_offset; - - size = 1 + (scratches > 9 ? (scratches - 9) : 0) + (saveds <= 3 ? saveds : 3); - inst = (sljit_u8*)ensure_buf(compiler, (sljit_uw)(size + 1)); - FAIL_IF(!inst); - - INC_SIZE((sljit_uw)size); - PUSH_REG(reg_map[TMP_REG1]); - if (saveds > 2 || scratches > 9) - PUSH_REG(reg_map[SLJIT_S2]); - if (saveds > 1 || scratches > 10) - PUSH_REG(reg_map[SLJIT_S1]); - if (saveds > 0 || scratches > 11) - PUSH_REG(reg_map[SLJIT_S0]); - - size *= SSIZE_OF(sw); + size *= SSIZE_OF(sw); + } if (status & (ENTER_TMP_TO_R4 | ENTER_TMP_TO_S)) EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_MEM1(SLJIT_SP), args_size + size); size += SSIZE_OF(sw); -#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL) - if (!(options & SLJIT_ENTER_CDECL)) - size += args_size; -#endif - - local_size = ((locals_offset + local_size + size + 0xf) & ~0xf) - size; + local_size = ((SLJIT_LOCALS_OFFSET_BASE + local_size + size + 0xf) & ~0xf) - size; compiler->local_size = local_size; -#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL) - if (!(options & SLJIT_ENTER_CDECL)) - size -= args_size; -#endif - word_arg_count = 0; saved_arg_count = 0; args_size = size; @@ -386,64 +385,27 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi break; default: word_arg_count++; + SLJIT_ASSERT(word_arg_count <= 3 || (word_arg_count == 4 && !(status & (ENTER_TMP_TO_R4 | ENTER_TMP_TO_S)))); -#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL) - if (!(options & SLJIT_ENTER_CDECL) && word_arg_count <= 2) { - if (word_arg_count == 1) { - if (status & ENTER_R2_USED) { - EMIT_MOV(compiler, (arg_types & SLJIT_ARG_TYPE_SCRATCH_REG) ? SLJIT_R0 : SLJIT_S0, 0, SLJIT_R2, 0); - } else if (!(arg_types & SLJIT_ARG_TYPE_SCRATCH_REG)) { - status |= ENTER_R2_TO_S; - saved_arg_count++; - } else - status |= ENTER_R2_TO_R0; - } else if (!(arg_types & SLJIT_ARG_TYPE_SCRATCH_REG)) { - status |= ENTER_R1_TO_S; - saved_arg_count++; - } - break; - } -#endif if (arg_types & SLJIT_ARG_TYPE_SCRATCH_REG) { - SLJIT_ASSERT(word_arg_count <= 3 || (status & ENTER_TMP_TO_R4)); - - if (word_arg_count <= 3) { #ifdef _WIN32 - if (word_arg_count == 3 && local_size > 4 * 4096) - r2_offset = local_size + args_size; - else + if (word_arg_count == 3 && local_size > 4 * 4096) + r2_offset = local_size + args_size; + else #endif - EMIT_MOV(compiler, word_arg_count, 0, SLJIT_MEM1(SLJIT_SP), args_size); - } - } else { - SLJIT_ASSERT(saved_arg_count <= 3 || (status & ENTER_TMP_TO_S)); + EMIT_MOV(compiler, word_arg_count, 0, SLJIT_MEM1(SLJIT_SP), args_size); - if (saved_arg_count <= 3) - EMIT_MOV(compiler, SLJIT_S0 - saved_arg_count, 0, SLJIT_MEM1(SLJIT_SP), args_size); + } else { + EMIT_MOV(compiler, SLJIT_S0 - saved_arg_count, 0, SLJIT_MEM1(SLJIT_SP), args_size); saved_arg_count++; } + args_size += SSIZE_OF(sw); break; } arg_types >>= SLJIT_ARG_SHIFT; } -#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL) - if (!(options & SLJIT_ENTER_CDECL)) { - if (status & ENTER_R2_TO_R0) - EMIT_MOV(compiler, SLJIT_R0, 0, SLJIT_R2, 0); - - saved_arg_count = 0; - if (status & ENTER_R2_TO_S) { - EMIT_MOV(compiler, SLJIT_S0, 0, SLJIT_R2, 0); - saved_arg_count++; - } - - if (status & ENTER_R1_TO_S) - EMIT_MOV(compiler, SLJIT_S0 - saved_arg_count, 0, SLJIT_R1, 0); - } -#endif - SLJIT_ASSERT(SLJIT_LOCALS_OFFSET > 0); #ifdef _WIN32 @@ -459,6 +421,18 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi BINARY_IMM32(OR, 0, SLJIT_MEM1(SLJIT_SP), -4096 * 3); } else { + if (options & SLJIT_ENTER_REG_ARG) { + SLJIT_ASSERT(r2_offset == -1); + + inst = (sljit_u8*)ensure_buf(compiler, (sljit_uw)(1 + 1)); + FAIL_IF(!inst); + INC_SIZE(1); + PUSH_REG(reg_map[SLJIT_R2]); + + local_size -= SSIZE_OF(sw); + r2_offset = local_size; + } + EMIT_MOV(compiler, SLJIT_R2, 0, SLJIT_IMM, local_size >> 12); BINARY_IMM32(OR, 0, SLJIT_MEM1(SLJIT_SP), -4096); @@ -490,8 +464,20 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi #endif /* _WIN32 */ + size = SLJIT_LOCALS_OFFSET_BASE - SSIZE_OF(sw); + kept_saveds_count = SLJIT_R3 - kept_saveds_count; + + while (saved_arg_count > 3) { + EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), size, kept_saveds_count, 0); + kept_saveds_count++; + size -= SSIZE_OF(sw); + saved_arg_count--; + } + if (status & (ENTER_TMP_TO_R4 | ENTER_TMP_TO_S)) { - size = (status & ENTER_TMP_TO_R4) ? compiler->scratches_offset : compiler->locals_offset - SSIZE_OF(sw); + if (status & ENTER_TMP_TO_R4) + size = 2 * SSIZE_OF(sw); + EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), size, TMP_REG1, 0); } @@ -502,10 +488,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *comp sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds, sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size) { - sljit_s32 args_size, locals_offset; -#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL) - sljit_s32 word_arg_count = 0; -#endif + sljit_s32 args_size; CHECK_ERROR(); CHECK(check_sljit_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size)); @@ -513,87 +496,88 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *comp arg_types >>= SLJIT_ARG_SHIFT; args_size = 0; - while (arg_types) { - switch (arg_types & SLJIT_ARG_MASK) { - case SLJIT_ARG_TYPE_F64: - args_size += SSIZE_OF(f64); - break; - case SLJIT_ARG_TYPE_F32: - args_size += SSIZE_OF(f32); - break; - default: -#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL) - if (word_arg_count >= 2) + + if (!(options & SLJIT_ENTER_REG_ARG)) { + while (arg_types) { + switch (arg_types & SLJIT_ARG_MASK) { + case SLJIT_ARG_TYPE_F64: + args_size += SSIZE_OF(f64); + break; + case SLJIT_ARG_TYPE_F32: + args_size += SSIZE_OF(f32); + break; + default: args_size += SSIZE_OF(sw); - word_arg_count++; -#else - args_size += SSIZE_OF(sw); -#endif - break; + break; + } + arg_types >>= SLJIT_ARG_SHIFT; } - arg_types >>= SLJIT_ARG_SHIFT; } compiler->args_size = args_size; - /* [esp+0] for saving temporaries and function calls. */ - locals_offset = 2 * SSIZE_OF(sw); + /* [esp+0] for saving temporaries and for function calls. */ -#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL) - if ((options & SLJIT_ENTER_CDECL) && scratches >= 3) - locals_offset = 4 * SSIZE_OF(sw); -#else - if (scratches >= 3) - locals_offset = 4 * SSIZE_OF(sw); -#endif + saveds = (1 + (scratches > 9 ? (scratches - 9) : 0) + (saveds <= 3 ? saveds : 3) - SLJIT_KEPT_SAVEDS_COUNT(options)) * SSIZE_OF(sw); - compiler->scratches_offset = locals_offset; + /* Saving ebp. */ + if (!(options & SLJIT_ENTER_REG_ARG)) + saveds += SSIZE_OF(sw); - if (scratches > 3) - locals_offset += ((scratches > (3 + 6)) ? 6 : (scratches - 3)) * SSIZE_OF(sw); - - if (saveds > 3) - locals_offset += (saveds - 3) * SSIZE_OF(sw); - - compiler->locals_offset = locals_offset; - - saveds = (2 + (scratches > 9 ? (scratches - 9) : 0) + (saveds <= 3 ? saveds : 3)) * SSIZE_OF(sw); - -#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL) - if (!(options & SLJIT_ENTER_CDECL)) - saveds += args_size; -#endif - - compiler->local_size = ((locals_offset + local_size + saveds + 0xf) & ~0xf) - saveds; + compiler->local_size = ((SLJIT_LOCALS_OFFSET_BASE + local_size + saveds + 0xf) & ~0xf) - saveds; return SLJIT_SUCCESS; } -static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler) +static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler, sljit_s32 is_return_to) { + sljit_s32 kept_saveds_count = SLJIT_KEPT_SAVEDS_COUNT(compiler->options); + sljit_s32 local_size, saveds; sljit_uw size; sljit_u8 *inst; - size = (sljit_uw)(1 + (compiler->scratches > 9 ? (compiler->scratches - 9) : 0) + - (compiler->saveds <= 3 ? compiler->saveds : 3)); + size = (sljit_uw)((compiler->scratches > 9 ? (compiler->scratches - 9) : 0) + + (compiler->saveds <= 3 ? compiler->saveds : 3) - kept_saveds_count); + + local_size = compiler->local_size; + + if (!(compiler->options & SLJIT_ENTER_REG_ARG)) + size++; + else if (is_return_to && size == 0) { + local_size += SSIZE_OF(sw); + is_return_to = 0; + } + + if (local_size > 0) + BINARY_IMM32(ADD, local_size, SLJIT_SP, 0); + + if (size == 0) + return SLJIT_SUCCESS; + inst = (sljit_u8*)ensure_buf(compiler, 1 + size); FAIL_IF(!inst); INC_SIZE(size); - if (compiler->saveds > 0 || compiler->scratches > 11) + saveds = compiler->saveds; + + if ((saveds > 0 && kept_saveds_count == 0) || compiler->scratches > 11) POP_REG(reg_map[SLJIT_S0]); - if (compiler->saveds > 1 || compiler->scratches > 10) + if ((saveds > 1 && kept_saveds_count <= 1) || compiler->scratches > 10) POP_REG(reg_map[SLJIT_S1]); - if (compiler->saveds > 2 || compiler->scratches > 9) + if ((saveds > 2 && kept_saveds_count <= 2) || compiler->scratches > 9) POP_REG(reg_map[SLJIT_S2]); - POP_REG(reg_map[TMP_REG1]); + + if (!(compiler->options & SLJIT_ENTER_REG_ARG)) + POP_REG(reg_map[TMP_REG1]); + + if (is_return_to) + BINARY_IMM32(ADD, sizeof(sljit_sw), SLJIT_SP, 0); return SLJIT_SUCCESS; } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_void(struct sljit_compiler *compiler) { - sljit_uw size; sljit_u8 *inst; CHECK_ERROR(); @@ -602,143 +586,45 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_void(struct sljit_compiler SLJIT_ASSERT(compiler->args_size >= 0); SLJIT_ASSERT(compiler->local_size > 0); - BINARY_IMM32(ADD, compiler->local_size, SLJIT_SP, 0); + FAIL_IF(emit_stack_frame_release(compiler, 0)); - FAIL_IF(emit_stack_frame_release(compiler)); - - size = 1; -#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL) - if (compiler->args_size > 0 && !(compiler->options & SLJIT_ENTER_CDECL)) - size = 3; -#endif - inst = (sljit_u8*)ensure_buf(compiler, 1 + size); + inst = (sljit_u8*)ensure_buf(compiler, 1 + 1); FAIL_IF(!inst); - - INC_SIZE(size); - -#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL) - if (compiler->args_size > 0 && !(compiler->options & SLJIT_ENTER_CDECL)) { - RET_I16(U8(compiler->args_size)); - return SLJIT_SUCCESS; - } -#endif - + INC_SIZE(1); RET(); return SLJIT_SUCCESS; } +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_to(struct sljit_compiler *compiler, + sljit_s32 src, sljit_sw srcw) +{ + sljit_s32 src_r; + + CHECK_ERROR(); + CHECK(check_sljit_emit_return_to(compiler, src, srcw)); + + if ((src & SLJIT_MEM) || (src > SLJIT_R2 && src <= (SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options)))) { + ADJUST_LOCAL_OFFSET(src, srcw); + CHECK_EXTRA_REGS(src, srcw, (void)0); + + src_r = (compiler->options & SLJIT_ENTER_REG_ARG) ? TMP_REG1 : SLJIT_R1; + + EMIT_MOV(compiler, src_r, 0, src, srcw); + src = src_r; + srcw = 0; + } + + FAIL_IF(emit_stack_frame_release(compiler, 1)); + + SLJIT_SKIP_CHECKS(compiler); + return sljit_emit_ijump(compiler, SLJIT_JUMP, src, srcw); +} + /* --------------------------------------------------------------------- */ /* Call / return instructions */ /* --------------------------------------------------------------------- */ -#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL) - -static sljit_sw c_fast_call_get_stack_size(sljit_s32 arg_types, sljit_s32 *word_arg_count_ptr) -{ - sljit_sw stack_size = 0; - sljit_s32 word_arg_count = 0; - - arg_types >>= SLJIT_ARG_SHIFT; - - while (arg_types) { - switch (arg_types & SLJIT_ARG_MASK) { - case SLJIT_ARG_TYPE_F64: - stack_size += SSIZE_OF(f64); - break; - case SLJIT_ARG_TYPE_F32: - stack_size += SSIZE_OF(f32); - break; - default: - word_arg_count++; - if (word_arg_count > 2) - stack_size += SSIZE_OF(sw); - break; - } - - arg_types >>= SLJIT_ARG_SHIFT; - } - - if (word_arg_count_ptr) - *word_arg_count_ptr = word_arg_count; - - return stack_size; -} - -static sljit_s32 c_fast_call_with_args(struct sljit_compiler *compiler, - sljit_s32 arg_types, sljit_sw stack_size, sljit_s32 word_arg_count, sljit_s32 swap_args) -{ - sljit_u8 *inst; - sljit_s32 float_arg_count; - - if (stack_size == SSIZE_OF(sw) && word_arg_count == 3) { - inst = (sljit_u8*)ensure_buf(compiler, 1 + 1); - FAIL_IF(!inst); - INC_SIZE(1); - PUSH_REG(reg_map[SLJIT_R2]); - } - else if (stack_size > 0) { - if (word_arg_count >= 4) - EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_MEM1(SLJIT_SP), compiler->scratches_offset); - - BINARY_IMM32(SUB, stack_size, SLJIT_SP, 0); - - stack_size = 0; - arg_types >>= SLJIT_ARG_SHIFT; - word_arg_count = 0; - float_arg_count = 0; - while (arg_types) { - switch (arg_types & SLJIT_ARG_MASK) { - case SLJIT_ARG_TYPE_F64: - float_arg_count++; - FAIL_IF(emit_sse2_store(compiler, 0, SLJIT_MEM1(SLJIT_SP), stack_size, float_arg_count)); - stack_size += SSIZE_OF(f64); - break; - case SLJIT_ARG_TYPE_F32: - float_arg_count++; - FAIL_IF(emit_sse2_store(compiler, 1, SLJIT_MEM1(SLJIT_SP), stack_size, float_arg_count)); - stack_size += SSIZE_OF(f32); - break; - default: - word_arg_count++; - if (word_arg_count == 3) { - EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), stack_size, SLJIT_R2, 0); - stack_size += SSIZE_OF(sw); - } - else if (word_arg_count == 4) { - EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), stack_size, TMP_REG1, 0); - stack_size += SSIZE_OF(sw); - } - break; - } - - arg_types >>= SLJIT_ARG_SHIFT; - } - } - - if (word_arg_count > 0) { - if (swap_args) { - inst = (sljit_u8*)ensure_buf(compiler, 1 + 1); - FAIL_IF(!inst); - INC_SIZE(1); - - *inst++ = U8(XCHG_EAX_r | reg_map[SLJIT_R2]); - } - else { - inst = (sljit_u8*)ensure_buf(compiler, 1 + 2); - FAIL_IF(!inst); - INC_SIZE(2); - - *inst++ = MOV_r_rm; - *inst++ = U8(MOD_REG | (reg_map[SLJIT_R2] << 3) | reg_map[SLJIT_R0]); - } - } - - return SLJIT_SUCCESS; -} - -#endif - -static sljit_s32 cdecl_call_get_stack_size(struct sljit_compiler *compiler, sljit_s32 arg_types, sljit_s32 *word_arg_count_ptr) +static sljit_s32 call_get_stack_size(sljit_s32 arg_types, sljit_s32 *word_arg_count_ptr) { sljit_sw stack_size = 0; sljit_s32 word_arg_count = 0; @@ -765,25 +651,31 @@ static sljit_s32 cdecl_call_get_stack_size(struct sljit_compiler *compiler, slji if (word_arg_count_ptr) *word_arg_count_ptr = word_arg_count; - if (stack_size <= compiler->scratches_offset) + if (stack_size <= 4 * SSIZE_OF(sw)) return 0; - return ((stack_size - compiler->scratches_offset + 0xf) & ~0xf); + return ((stack_size - (4 * SSIZE_OF(sw)) + 0xf) & ~0xf); } -static sljit_s32 cdecl_call_with_args(struct sljit_compiler *compiler, - sljit_s32 arg_types, sljit_sw stack_size, sljit_s32 word_arg_count) +static sljit_s32 call_with_args(struct sljit_compiler *compiler, + sljit_s32 arg_types, sljit_sw stack_size, sljit_s32 word_arg_count, sljit_s32 keep_tmp1) { - sljit_s32 float_arg_count = 0; + sljit_s32 float_arg_count = 0, arg4_reg = 0, arg_offset; sljit_u8 *inst; - if (word_arg_count >= 4) - EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_MEM1(SLJIT_SP), compiler->scratches_offset); + if (word_arg_count >= 4) { + arg4_reg = SLJIT_R0; + + if (!keep_tmp1) { + EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_MEM1(SLJIT_SP), 2 * SSIZE_OF(sw)); + arg4_reg = TMP_REG1; + } + } if (stack_size > 0) BINARY_IMM32(SUB, stack_size, SLJIT_SP, 0); - stack_size = 0; + arg_offset = 0; word_arg_count = 0; arg_types >>= SLJIT_ARG_SHIFT; @@ -791,18 +683,22 @@ static sljit_s32 cdecl_call_with_args(struct sljit_compiler *compiler, switch (arg_types & SLJIT_ARG_MASK) { case SLJIT_ARG_TYPE_F64: float_arg_count++; - FAIL_IF(emit_sse2_store(compiler, 0, SLJIT_MEM1(SLJIT_SP), stack_size, float_arg_count)); - stack_size += SSIZE_OF(f64); + FAIL_IF(emit_sse2_store(compiler, 0, SLJIT_MEM1(SLJIT_SP), arg_offset, float_arg_count)); + arg_offset += SSIZE_OF(f64); break; case SLJIT_ARG_TYPE_F32: float_arg_count++; - FAIL_IF(emit_sse2_store(compiler, 1, SLJIT_MEM1(SLJIT_SP), stack_size, float_arg_count)); - stack_size += SSIZE_OF(f32); + FAIL_IF(emit_sse2_store(compiler, 1, SLJIT_MEM1(SLJIT_SP), arg_offset, float_arg_count)); + arg_offset += SSIZE_OF(f32); break; default: word_arg_count++; - EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), stack_size, (word_arg_count >= 4) ? TMP_REG1 : word_arg_count, 0); - stack_size += SSIZE_OF(sw); + EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), arg_offset, (word_arg_count >= 4) ? arg4_reg : word_arg_count, 0); + + if (word_arg_count == 1 && arg4_reg == SLJIT_R0) + EMIT_MOV(compiler, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_SP), 2 * SSIZE_OF(sw) + stack_size); + + arg_offset += SSIZE_OF(sw); break; } @@ -840,21 +736,19 @@ static sljit_s32 tail_call_with_args(struct sljit_compiler *compiler, sljit_s32 *extra_space, sljit_s32 arg_types, sljit_s32 src, sljit_sw srcw) { - sljit_sw args_size, prev_args_size, saved_regs_size; + sljit_sw args_size, saved_regs_size; sljit_sw types, word_arg_count, float_arg_count; sljit_sw stack_size, prev_stack_size, min_size, offset; sljit_sw word_arg4_offset; sljit_u8 r2_offset = 0; -#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL) - sljit_u8 fast_call = (*extra_space & 0xff) == SLJIT_CALL; -#endif + sljit_s32 kept_saveds_count = SLJIT_KEPT_SAVEDS_COUNT(compiler->options); sljit_u8* inst; ADJUST_LOCAL_OFFSET(src, srcw); CHECK_EXTRA_REGS(src, srcw, (void)0); saved_regs_size = (1 + (compiler->scratches > 9 ? (compiler->scratches - 9) : 0) - + (compiler->saveds <= 3 ? compiler->saveds : 3)) * SSIZE_OF(sw); + + (compiler->saveds <= 3 ? compiler->saveds : 3) - kept_saveds_count) * SSIZE_OF(sw); word_arg_count = 0; float_arg_count = 0; @@ -876,30 +770,15 @@ static sljit_s32 tail_call_with_args(struct sljit_compiler *compiler, break; default: word_arg_count++; -#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL) - if (!fast_call || word_arg_count > 2) - args_size += SSIZE_OF(sw); -#else args_size += SSIZE_OF(sw); -#endif break; } arg_types >>= SLJIT_ARG_SHIFT; } - if (args_size <= compiler->args_size -#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL) - && (!(compiler->options & SLJIT_ENTER_CDECL) || args_size == 0 || !fast_call) -#endif /* SLJIT_X86_32_FASTCALL */ - && 1) { -#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL) - *extra_space = fast_call ? 0 : args_size; - prev_args_size = compiler->args_size; - stack_size = prev_args_size + SSIZE_OF(sw) + saved_regs_size; -#else /* !SLJIT_X86_32_FASTCALL */ + if (args_size <= compiler->args_size) { *extra_space = 0; stack_size = args_size + SSIZE_OF(sw) + saved_regs_size; -#endif /* SLJIT_X86_32_FASTCALL */ offset = stack_size + compiler->local_size; @@ -911,37 +790,6 @@ static sljit_s32 tail_call_with_args(struct sljit_compiler *compiler, EMIT_MOV(compiler, SLJIT_R0, 0, src, srcw); } -#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL) - if (!(compiler->options & SLJIT_ENTER_CDECL)) { - if (!fast_call) - offset -= SSIZE_OF(sw); - - if (word_arg_count >= 3) { - word_arg4_offset = SSIZE_OF(sw); - - if (word_arg_count + float_arg_count >= 4) { - word_arg4_offset = SSIZE_OF(sw) + SSIZE_OF(sw); - if ((types & SLJIT_ARG_MASK) == SLJIT_ARG_TYPE_F64) - word_arg4_offset = SSIZE_OF(sw) + SSIZE_OF(f64); - } - - /* In cdecl mode, at least one more word value must - * be present on the stack before the return address. */ - EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), offset - word_arg4_offset, SLJIT_R2, 0); - } - - if (fast_call) { - if (args_size < prev_args_size) { - EMIT_MOV(compiler, SLJIT_R2, 0, SLJIT_MEM1(SLJIT_SP), offset - prev_args_size - SSIZE_OF(sw)); - EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), offset - args_size - SSIZE_OF(sw), SLJIT_R2, 0); - } - } else if (prev_args_size > 0) { - EMIT_MOV(compiler, SLJIT_R2, 0, SLJIT_MEM1(SLJIT_SP), offset - prev_args_size); - EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), offset, SLJIT_R2, 0); - } - } -#endif /* SLJIT_X86_32_FASTCALL */ - while (types != 0) { switch (types & SLJIT_ARG_MASK) { case SLJIT_ARG_TYPE_F64: @@ -957,12 +805,6 @@ static sljit_s32 tail_call_with_args(struct sljit_compiler *compiler, default: switch (word_arg_count) { case 1: -#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL) - if (fast_call) { - EMIT_MOV(compiler, SLJIT_R2, 0, r2_offset != 0 ? SLJIT_MEM1(SLJIT_SP) : SLJIT_R0, 0); - break; - } -#endif offset -= SSIZE_OF(sw); if (r2_offset != 0) { EMIT_MOV(compiler, SLJIT_R2, 0, SLJIT_MEM1(SLJIT_SP), 0); @@ -971,10 +813,6 @@ static sljit_s32 tail_call_with_args(struct sljit_compiler *compiler, EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), offset, SLJIT_R0, 0); break; case 2: -#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL) - if (fast_call) - break; -#endif offset -= SSIZE_OF(sw); EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), offset, SLJIT_R1, 0); break; @@ -983,7 +821,7 @@ static sljit_s32 tail_call_with_args(struct sljit_compiler *compiler, break; case 4: offset -= SSIZE_OF(sw); - EMIT_MOV(compiler, SLJIT_R2, 0, SLJIT_MEM1(SLJIT_SP), compiler->scratches_offset); + EMIT_MOV(compiler, SLJIT_R2, 0, SLJIT_MEM1(SLJIT_SP), 2 * SSIZE_OF(sw)); EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), offset, SLJIT_R2, 0); break; } @@ -993,15 +831,7 @@ static sljit_s32 tail_call_with_args(struct sljit_compiler *compiler, types >>= SLJIT_ARG_SHIFT; } - BINARY_IMM32(ADD, compiler->local_size, SLJIT_SP, 0); - FAIL_IF(emit_stack_frame_release(compiler)); - -#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL) - if (args_size < prev_args_size) - BINARY_IMM32(ADD, prev_args_size - args_size, SLJIT_SP, 0); -#endif - - return SLJIT_SUCCESS; + return emit_stack_frame_release(compiler, 0); } stack_size = args_size + SSIZE_OF(sw); @@ -1014,16 +844,10 @@ static sljit_s32 tail_call_with_args(struct sljit_compiler *compiler, if (word_arg_count >= 3) stack_size += SSIZE_OF(sw); - prev_args_size = 0; -#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL) - if (!(compiler->options & SLJIT_ENTER_CDECL)) - prev_args_size = compiler->args_size; -#endif - - prev_stack_size = prev_args_size + SSIZE_OF(sw) + saved_regs_size; + prev_stack_size = SSIZE_OF(sw) + saved_regs_size; min_size = prev_stack_size + compiler->local_size; - word_arg4_offset = compiler->scratches_offset; + word_arg4_offset = 2 * SSIZE_OF(sw); if (stack_size > min_size) { BINARY_IMM32(SUB, stack_size - min_size, SLJIT_SP, 0); @@ -1050,75 +874,30 @@ static sljit_s32 tail_call_with_args(struct sljit_compiler *compiler, } /* Restore saved registers. */ - offset = stack_size - prev_args_size - 2 * SSIZE_OF(sw); + offset = stack_size - 2 * SSIZE_OF(sw); EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_MEM1(SLJIT_SP), offset); if (compiler->saveds > 2 || compiler->scratches > 9) { offset -= SSIZE_OF(sw); EMIT_MOV(compiler, SLJIT_S2, 0, SLJIT_MEM1(SLJIT_SP), offset); } - if (compiler->saveds > 1 || compiler->scratches > 10) { + if ((compiler->saveds > 1 && kept_saveds_count <= 1) || compiler->scratches > 10) { offset -= SSIZE_OF(sw); EMIT_MOV(compiler, SLJIT_S1, 0, SLJIT_MEM1(SLJIT_SP), offset); } - if (compiler->saveds > 0 || compiler->scratches > 11) { + if ((compiler->saveds > 0 && kept_saveds_count == 0) || compiler->scratches > 11) { offset -= SSIZE_OF(sw); EMIT_MOV(compiler, SLJIT_S0, 0, SLJIT_MEM1(SLJIT_SP), offset); } /* Copy fourth argument and return address. */ -#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL) - if (fast_call) { - offset = stack_size; - *extra_space = 0; + offset = stack_size - SSIZE_OF(sw); + *extra_space = args_size; - if (word_arg_count >= 4 && prev_args_size == 0) { - offset -= SSIZE_OF(sw); - inst = emit_x86_instruction(compiler, 1, SLJIT_R2, 0, SLJIT_MEM1(SLJIT_SP), offset); - FAIL_IF(!inst); - *inst = XCHG_r_rm; - - SLJIT_ASSERT(args_size != prev_args_size); - } else { - if (word_arg_count >= 4) { - offset -= SSIZE_OF(sw); - EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), offset, SLJIT_R2, 0); - } - - if (args_size != prev_args_size) - EMIT_MOV(compiler, SLJIT_R2, 0, SLJIT_MEM1(SLJIT_SP), stack_size - prev_args_size - SSIZE_OF(sw)); - } - - if (args_size != prev_args_size) - EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), stack_size - args_size - SSIZE_OF(sw), SLJIT_R2, 0); - } else { -#endif /* SLJIT_X86_32_FASTCALL */ - offset = stack_size - SSIZE_OF(sw); - *extra_space = args_size; - - if (word_arg_count >= 4 && prev_args_size == SSIZE_OF(sw)) { - offset -= SSIZE_OF(sw); - inst = emit_x86_instruction(compiler, 1, SLJIT_R2, 0, SLJIT_MEM1(SLJIT_SP), offset); - FAIL_IF(!inst); - *inst = XCHG_r_rm; - - SLJIT_ASSERT(prev_args_size > 0); - } else { - if (word_arg_count >= 4) { - offset -= SSIZE_OF(sw); - EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), offset, SLJIT_R2, 0); - } - - if (prev_args_size > 0) - EMIT_MOV(compiler, SLJIT_R2, 0, SLJIT_MEM1(SLJIT_SP), stack_size - prev_args_size - SSIZE_OF(sw)); - } - - /* Copy return address. */ - if (prev_args_size > 0) - EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), stack_size - SSIZE_OF(sw), SLJIT_R2, 0); -#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL) + if (word_arg_count >= 4) { + offset -= SSIZE_OF(sw); + EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), offset, SLJIT_R2, 0); } -#endif /* SLJIT_X86_32_FASTCALL */ while (types != 0) { switch (types & SLJIT_ARG_MASK) { @@ -1135,12 +914,6 @@ static sljit_s32 tail_call_with_args(struct sljit_compiler *compiler, default: switch (word_arg_count) { case 1: -#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL) - if (fast_call) { - EMIT_MOV(compiler, SLJIT_R2, 0, r2_offset != 0 ? SLJIT_MEM1(SLJIT_SP) : SLJIT_R0, 0); - break; - } -#endif offset -= SSIZE_OF(sw); if (r2_offset != 0) { EMIT_MOV(compiler, SLJIT_R2, 0, SLJIT_MEM1(SLJIT_SP), 0); @@ -1149,10 +922,6 @@ static sljit_s32 tail_call_with_args(struct sljit_compiler *compiler, EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), offset, SLJIT_R0, 0); break; case 2: -#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL) - if (fast_call) - break; -#endif offset -= SSIZE_OF(sw); EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), offset, SLJIT_R1, 0); break; @@ -1168,12 +937,6 @@ static sljit_s32 tail_call_with_args(struct sljit_compiler *compiler, types >>= SLJIT_ARG_SHIFT; } -#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL) - /* Skip return address. */ - if (fast_call) - offset -= SSIZE_OF(sw); -#endif - SLJIT_ASSERT(offset >= 0); if (offset == 0) @@ -1198,6 +961,38 @@ static sljit_s32 emit_tail_call_end(struct sljit_compiler *compiler, sljit_s32 e return SLJIT_SUCCESS; } +static sljit_s32 tail_call_reg_arg_with_args(struct sljit_compiler *compiler, sljit_s32 arg_types) +{ + sljit_s32 word_arg_count = 0; + sljit_s32 kept_saveds_count, offset; + + arg_types >>= SLJIT_ARG_SHIFT; + + while (arg_types) { + if ((arg_types & SLJIT_ARG_MASK) < SLJIT_ARG_TYPE_F64) + word_arg_count++; + + arg_types >>= SLJIT_ARG_SHIFT; + } + + if (word_arg_count < 4) + return SLJIT_SUCCESS; + + EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_MEM1(SLJIT_SP), 2 * SSIZE_OF(sw)); + + kept_saveds_count = SLJIT_KEPT_SAVEDS_COUNT(compiler->options); + offset = compiler->local_size + 3 * SSIZE_OF(sw); + + if ((compiler->saveds > 0 && kept_saveds_count == 0) || compiler->scratches > 11) + offset += SSIZE_OF(sw); + if ((compiler->saveds > 1 && kept_saveds_count <= 1) || compiler->scratches > 10) + offset += SSIZE_OF(sw); + if ((compiler->saveds > 2 && kept_saveds_count <= 2) || compiler->scratches > 9) + offset += SSIZE_OF(sw); + + return emit_mov(compiler, SLJIT_MEM1(SLJIT_SP), offset, TMP_REG1, 0); +} + SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 arg_types) { @@ -1209,18 +1004,21 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compile CHECK_PTR(check_sljit_emit_call(compiler, type, arg_types)); if (type & SLJIT_CALL_RETURN) { + if ((type & 0xff) == SLJIT_CALL_REG_ARG) { + PTR_FAIL_IF(tail_call_reg_arg_with_args(compiler, arg_types)); + PTR_FAIL_IF(emit_stack_frame_release(compiler, 0)); + + SLJIT_SKIP_CHECKS(compiler); + return sljit_emit_jump(compiler, SLJIT_JUMP | (type & SLJIT_REWRITABLE_JUMP)); + } + stack_size = type; PTR_FAIL_IF(tail_call_with_args(compiler, &stack_size, arg_types, SLJIT_IMM, 0)); -#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \ - || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) - compiler->skip_checks = 1; -#endif + SLJIT_SKIP_CHECKS(compiler); - if (stack_size == 0) { - type = SLJIT_JUMP | (type & SLJIT_REWRITABLE_JUMP); - return sljit_emit_jump(compiler, type); - } + if (stack_size == 0) + return sljit_emit_jump(compiler, SLJIT_JUMP | (type & SLJIT_REWRITABLE_JUMP)); jump = sljit_emit_jump(compiler, type); PTR_FAIL_IF(jump == NULL); @@ -1229,32 +1027,15 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compile return jump; } -#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL) - if ((type & 0xff) == SLJIT_CALL) { - stack_size = c_fast_call_get_stack_size(arg_types, &word_arg_count); - PTR_FAIL_IF(c_fast_call_with_args(compiler, arg_types, stack_size, word_arg_count, 0)); - -#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \ - || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) - compiler->skip_checks = 1; -#endif - - jump = sljit_emit_jump(compiler, type); - PTR_FAIL_IF(jump == NULL); - - PTR_FAIL_IF(post_call_with_args(compiler, arg_types, 0)); - return jump; + if ((type & 0xff) == SLJIT_CALL_REG_ARG) { + SLJIT_SKIP_CHECKS(compiler); + return sljit_emit_jump(compiler, type); } -#endif - stack_size = cdecl_call_get_stack_size(compiler, arg_types, &word_arg_count); - PTR_FAIL_IF(cdecl_call_with_args(compiler, arg_types, stack_size, word_arg_count)); - -#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \ - || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) - compiler->skip_checks = 1; -#endif + stack_size = call_get_stack_size(arg_types, &word_arg_count); + PTR_FAIL_IF(call_with_args(compiler, arg_types, stack_size, word_arg_count, 0)); + SLJIT_SKIP_CHECKS(compiler); jump = sljit_emit_jump(compiler, type); PTR_FAIL_IF(jump == NULL); @@ -1268,14 +1049,29 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compi { sljit_sw stack_size = 0; sljit_s32 word_arg_count; -#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL) - sljit_s32 swap_args; -#endif CHECK_ERROR(); CHECK(check_sljit_emit_icall(compiler, type, arg_types, src, srcw)); if (type & SLJIT_CALL_RETURN) { + if ((type & 0xff) == SLJIT_CALL_REG_ARG) { + FAIL_IF(tail_call_reg_arg_with_args(compiler, arg_types)); + + if ((src & SLJIT_MEM) || (src > SLJIT_R2 && src <= (SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options)))) { + ADJUST_LOCAL_OFFSET(src, srcw); + CHECK_EXTRA_REGS(src, srcw, (void)0); + + EMIT_MOV(compiler, TMP_REG1, 0, src, srcw); + src = TMP_REG1; + srcw = 0; + } + + FAIL_IF(emit_stack_frame_release(compiler, 0)); + + SLJIT_SKIP_CHECKS(compiler); + return sljit_emit_ijump(compiler, SLJIT_JUMP, src, srcw); + } + stack_size = type; FAIL_IF(tail_call_with_args(compiler, &stack_size, arg_types, src, srcw)); @@ -1284,10 +1080,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compi srcw = 0; } -#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \ - || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) - compiler->skip_checks = 1; -#endif + SLJIT_SKIP_CHECKS(compiler); if (stack_size == 0) return sljit_emit_ijump(compiler, SLJIT_JUMP, src, srcw); @@ -1296,59 +1089,59 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compi return emit_tail_call_end(compiler, stack_size); } -#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL) - SLJIT_ASSERT(reg_map[SLJIT_R0] == 0 && reg_map[SLJIT_R2] == 1 && SLJIT_R0 == 1 && SLJIT_R2 == 3); - - if ((type & 0xff) == SLJIT_CALL) { - stack_size = c_fast_call_get_stack_size(arg_types, &word_arg_count); - swap_args = 0; - - if (word_arg_count > 0) { - if ((src & REG_MASK) == SLJIT_R2 || OFFS_REG(src) == SLJIT_R2) { - swap_args = 1; - if (((src & REG_MASK) | 0x2) == SLJIT_R2) - src ^= 0x2; - if ((OFFS_REG(src) | 0x2) == SLJIT_R2) - src ^= TO_OFFS_REG(0x2); - } - } - - FAIL_IF(c_fast_call_with_args(compiler, arg_types, stack_size, word_arg_count, swap_args)); - - compiler->scratches_offset += stack_size; - compiler->locals_offset += stack_size; - -#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \ - || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) - compiler->skip_checks = 1; -#endif - FAIL_IF(sljit_emit_ijump(compiler, type, src, srcw)); - - compiler->scratches_offset -= stack_size; - compiler->locals_offset -= stack_size; - - return post_call_with_args(compiler, arg_types, 0); + if ((type & 0xff) == SLJIT_CALL_REG_ARG) { + SLJIT_SKIP_CHECKS(compiler); + return sljit_emit_ijump(compiler, type, src, srcw); } -#endif - stack_size = cdecl_call_get_stack_size(compiler, arg_types, &word_arg_count); - FAIL_IF(cdecl_call_with_args(compiler, arg_types, stack_size, word_arg_count)); + ADJUST_LOCAL_OFFSET(src, srcw); + CHECK_EXTRA_REGS(src, srcw, (void)0); - compiler->scratches_offset += stack_size; - compiler->locals_offset += stack_size; + if (src & SLJIT_MEM) { + EMIT_MOV(compiler, TMP_REG1, 0, src, srcw); + src = TMP_REG1; + srcw = 0; + } -#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \ - || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) - compiler->skip_checks = 1; -#endif + stack_size = call_get_stack_size(arg_types, &word_arg_count); + FAIL_IF(call_with_args(compiler, arg_types, stack_size, word_arg_count, src == TMP_REG1)); + + if (stack_size > 0 && src == SLJIT_MEM1(SLJIT_SP)) + srcw += stack_size; + + SLJIT_SKIP_CHECKS(compiler); FAIL_IF(sljit_emit_ijump(compiler, type, src, srcw)); - compiler->scratches_offset -= stack_size; - compiler->locals_offset -= stack_size; - return post_call_with_args(compiler, arg_types, stack_size); } +static SLJIT_INLINE sljit_s32 emit_fmov_before_return(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 src, sljit_sw srcw) +{ + sljit_u8* inst; + + if (compiler->options & SLJIT_ENTER_REG_ARG) { + if (src == SLJIT_FR0) + return SLJIT_SUCCESS; + + SLJIT_SKIP_CHECKS(compiler); + return sljit_emit_fop1(compiler, op, SLJIT_RETURN_FREG, 0, src, srcw); + } + + if (FAST_IS_REG(src)) { + FAIL_IF(emit_sse2_store(compiler, op & SLJIT_32, SLJIT_MEM1(SLJIT_SP), 0, src)); + + src = SLJIT_MEM1(SLJIT_SP); + srcw = 0; + } else { + ADJUST_LOCAL_OFFSET(src, srcw); + } + + inst = emit_x86_instruction(compiler, 1 | EX86_SSE2_OP1, 0, 0, src, srcw); + *inst = (op & SLJIT_32) ? FLDS : FLDL; + + return SLJIT_SUCCESS; +} + SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_enter(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw) { sljit_u8 *inst; @@ -1404,6 +1197,88 @@ static sljit_s32 emit_fast_return(struct sljit_compiler *compiler, sljit_s32 src return SLJIT_SUCCESS; } +/* --------------------------------------------------------------------- */ +/* Other operations */ +/* --------------------------------------------------------------------- */ + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compiler, sljit_s32 type, + sljit_s32 reg, + sljit_s32 mem, sljit_sw memw) +{ + sljit_u8* inst; + sljit_s32 i, next, reg_idx, offset; + sljit_u8 regs[2]; + + CHECK_ERROR(); + CHECK(check_sljit_emit_mem(compiler, type, reg, mem, memw)); + + if (!(reg & REG_PAIR_MASK)) + return sljit_emit_mem_unaligned(compiler, type, reg, mem, memw); + + ADJUST_LOCAL_OFFSET(mem, memw); + + regs[0] = U8(REG_PAIR_FIRST(reg)); + regs[1] = U8(REG_PAIR_SECOND(reg)); + + next = SSIZE_OF(sw); + + if (!(type & SLJIT_MEM_STORE) && (regs[0] == (mem & REG_MASK) || regs[0] == OFFS_REG(mem))) { + if (regs[1] == (mem & REG_MASK) || regs[1] == OFFS_REG(mem)) { + /* None of them are virtual register so TMP_REG1 will not be used. */ + EMIT_MOV(compiler, TMP_REG1, 0, OFFS_REG(mem), 0); + + if (regs[1] == OFFS_REG(mem)) + next = -SSIZE_OF(sw); + + mem = (mem & ~OFFS_REG_MASK) | TO_OFFS_REG(TMP_REG1); + } else { + next = -SSIZE_OF(sw); + + if (!(mem & OFFS_REG_MASK)) + memw += SSIZE_OF(sw); + } + } + + for (i = 0; i < 2; i++) { + reg_idx = next > 0 ? i : (i ^ 0x1); + reg = regs[reg_idx]; + + offset = -1; + + if (reg >= SLJIT_R3 && reg <= SLJIT_S3) { + offset = (2 * SSIZE_OF(sw)) + ((reg) - SLJIT_R3) * SSIZE_OF(sw); + reg = TMP_REG1; + + if (type & SLJIT_MEM_STORE) + EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_MEM1(SLJIT_SP), offset); + } + + if ((mem & OFFS_REG_MASK) && (reg_idx == 1)) { + inst = (sljit_u8*)ensure_buf(compiler, (sljit_uw)(1 + 4)); + FAIL_IF(!inst); + + INC_SIZE(4); + + inst[0] = (type & SLJIT_MEM_STORE) ? MOV_rm_r : MOV_r_rm; + inst[1] = 0x44 | U8(reg_map[reg] << 3); + inst[2] = U8(memw << 6) | U8(reg_map[OFFS_REG(mem)] << 3) | reg_map[mem & REG_MASK]; + inst[3] = sizeof(sljit_sw); + } else if (type & SLJIT_MEM_STORE) { + EMIT_MOV(compiler, mem, memw, reg, 0); + } else { + EMIT_MOV(compiler, reg, 0, mem, memw); + } + + if (!(mem & OFFS_REG_MASK)) + memw += next; + + if (!(type & SLJIT_MEM_STORE) && offset != -1) + EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), offset, TMP_REG1, 0); + } + + return SLJIT_SUCCESS; +} + static sljit_s32 skip_frames_before_return(struct sljit_compiler *compiler) { sljit_sw size; diff --git a/src/3rdparty/pcre2/src/sljit/sljitNativeX86_64.c b/src/3rdparty/pcre2/src/sljit/sljitNativeX86_64.c index f37df6e1bf0..4e938ffcf31 100644 --- a/src/3rdparty/pcre2/src/sljit/sljitNativeX86_64.c +++ b/src/3rdparty/pcre2/src/sljit/sljitNativeX86_64.c @@ -101,34 +101,38 @@ static sljit_u8* emit_x86_instruction(struct sljit_compiler *compiler, sljit_uw /* Calculate size of b. */ inst_size += 1; /* mod r/m byte. */ if (b & SLJIT_MEM) { - if (!(b & OFFS_REG_MASK)) { - if (NOT_HALFWORD(immb)) { - PTR_FAIL_IF(emit_load_imm64(compiler, TMP_REG2, immb)); - immb = 0; - if (b & REG_MASK) - b |= TO_OFFS_REG(TMP_REG2); - else - b |= TMP_REG2; - } - else if (reg_lmap[b & REG_MASK] == 4) - b |= TO_OFFS_REG(SLJIT_SP); + if (!(b & OFFS_REG_MASK) && NOT_HALFWORD(immb)) { + PTR_FAIL_IF(emit_load_imm64(compiler, TMP_REG2, immb)); + immb = 0; + if (b & REG_MASK) + b |= TO_OFFS_REG(TMP_REG2); + else + b |= TMP_REG2; } if (!(b & REG_MASK)) inst_size += 1 + sizeof(sljit_s32); /* SIB byte required to avoid RIP based addressing. */ else { - if (reg_map[b & REG_MASK] >= 8) - rex |= REX_B; - - if (immb != 0 && (!(b & OFFS_REG_MASK) || (b & OFFS_REG_MASK) == TO_OFFS_REG(SLJIT_SP))) { + if (immb != 0 && !(b & OFFS_REG_MASK)) { /* Immediate operand. */ if (immb <= 127 && immb >= -128) inst_size += sizeof(sljit_s8); else inst_size += sizeof(sljit_s32); } - else if (reg_lmap[b & REG_MASK] == 5) - inst_size += sizeof(sljit_s8); + else if (reg_lmap[b & REG_MASK] == 5) { + /* Swap registers if possible. */ + if ((b & OFFS_REG_MASK) && (immb & 0x3) == 0 && reg_lmap[OFFS_REG(b)] != 5) + b = SLJIT_MEM | OFFS_REG(b) | TO_OFFS_REG(b & REG_MASK); + else + inst_size += sizeof(sljit_s8); + } + + if (reg_map[b & REG_MASK] >= 8) + rex |= REX_B; + + if (reg_lmap[b & REG_MASK] == 4 && !(b & OFFS_REG_MASK)) + b |= TO_OFFS_REG(SLJIT_SP); if (b & OFFS_REG_MASK) { inst_size += 1; /* SIB byte. */ @@ -153,9 +157,9 @@ static sljit_u8* emit_x86_instruction(struct sljit_compiler *compiler, sljit_uw inst_size += 4; } else if (flags & EX86_SHIFT_INS) { - imma &= compiler->mode32 ? 0x1f : 0x3f; + SLJIT_ASSERT(imma <= (compiler->mode32 ? 0x1f : 0x3f)); if (imma != 1) { - inst_size ++; + inst_size++; flags |= EX86_BYTE_ARG; } } else if (flags & EX86_BYTE_ARG) @@ -223,7 +227,7 @@ static sljit_u8* emit_x86_instruction(struct sljit_compiler *compiler, sljit_uw } else if (b & REG_MASK) { reg_lmap_b = reg_lmap[b & REG_MASK]; - if (!(b & OFFS_REG_MASK) || (b & OFFS_REG_MASK) == TO_OFFS_REG(SLJIT_SP) || reg_lmap_b == 5) { + if (!(b & OFFS_REG_MASK) || (b & OFFS_REG_MASK) == TO_OFFS_REG(SLJIT_SP)) { if (immb != 0 || reg_lmap_b == 5) { if (immb <= 127 && immb >= -128) *buf_ptr |= 0x40; @@ -248,8 +252,14 @@ static sljit_u8* emit_x86_instruction(struct sljit_compiler *compiler, sljit_uw } } else { + if (reg_lmap_b == 5) + *buf_ptr |= 0x40; + *buf_ptr++ |= 0x04; *buf_ptr++ = U8(reg_lmap_b | (reg_lmap[OFFS_REG(b)] << 3) | (immb << 6)); + + if (reg_lmap_b == 5) + *buf_ptr++ = 0; } } else { @@ -366,7 +376,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi { sljit_uw size; sljit_s32 word_arg_count = 0; - sljit_s32 saved_arg_count = 0; + sljit_s32 saved_arg_count = SLJIT_KEPT_SAVEDS_COUNT(options); sljit_s32 saved_regs_size, tmp, i; #ifdef _WIN64 sljit_s32 saved_float_regs_size; @@ -379,16 +389,19 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi CHECK(check_sljit_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size)); set_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size); + if (options & SLJIT_ENTER_REG_ARG) + arg_types = 0; + /* Emit ENDBR64 at function entry if needed. */ FAIL_IF(emit_endbranch(compiler)); compiler->mode32 = 0; /* Including the return address saved by the call instruction. */ - saved_regs_size = GET_SAVED_REGISTERS_SIZE(scratches, saveds, 1); + saved_regs_size = GET_SAVED_REGISTERS_SIZE(scratches, saveds - saved_arg_count, 1); tmp = SLJIT_S0 - saveds; - for (i = SLJIT_S0; i > tmp; i--) { + for (i = SLJIT_S0 - saved_arg_count; i > tmp; i--) { size = reg_map[i] >= 8 ? 2 : 1; inst = (sljit_u8*)ensure_buf(compiler, 1 + size); FAIL_IF(!inst); @@ -561,15 +574,15 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *comp #endif /* _WIN64 */ /* Including the return address saved by the call instruction. */ - saved_regs_size = GET_SAVED_REGISTERS_SIZE(scratches, saveds, 1); + saved_regs_size = GET_SAVED_REGISTERS_SIZE(scratches, saveds - SLJIT_KEPT_SAVEDS_COUNT(options), 1); compiler->local_size = ((local_size + saved_regs_size + 0xf) & ~0xf) - saved_regs_size; return SLJIT_SUCCESS; } -static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler) +static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler, sljit_s32 is_return_to) { sljit_uw size; - sljit_s32 i, tmp; + sljit_s32 local_size, i, tmp; sljit_u8 *inst; #ifdef _WIN64 sljit_s32 saved_float_regs_offset; @@ -598,30 +611,21 @@ static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler) *inst = MOVAPS_x_xm; saved_float_regs_offset += 16; } + + compiler->mode32 = 0; } #endif /* _WIN64 */ - if (compiler->local_size > 0) { - if (compiler->local_size <= 127) { - inst = (sljit_u8*)ensure_buf(compiler, 1 + 4); - FAIL_IF(!inst); - INC_SIZE(4); - *inst++ = REX_W; - *inst++ = GROUP_BINARY_83; - *inst++ = MOD_REG | ADD | 4; - *inst = U8(compiler->local_size); - } - else { - inst = (sljit_u8*)ensure_buf(compiler, 1 + 7); - FAIL_IF(!inst); - INC_SIZE(7); - *inst++ = REX_W; - *inst++ = GROUP_BINARY_81; - *inst++ = MOD_REG | ADD | 4; - sljit_unaligned_store_s32(inst, compiler->local_size); - } + local_size = compiler->local_size; + + if (is_return_to && compiler->scratches < SLJIT_FIRST_SAVED_REG && (compiler->saveds == SLJIT_KEPT_SAVEDS_COUNT(compiler->options))) { + local_size += SSIZE_OF(sw); + is_return_to = 0; } + if (local_size > 0) + BINARY_IMM32(ADD, local_size, SLJIT_SP, 0); + tmp = compiler->scratches; for (i = SLJIT_FIRST_SAVED_REG; i <= tmp; i++) { size = reg_map[i] >= 8 ? 2 : 1; @@ -633,8 +637,8 @@ static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler) POP_REG(reg_lmap[i]); } - tmp = compiler->saveds < SLJIT_NUMBER_OF_SAVED_REGISTERS ? (SLJIT_S0 + 1 - compiler->saveds) : SLJIT_FIRST_SAVED_REG; - for (i = tmp; i <= SLJIT_S0; i++) { + tmp = SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options); + for (i = SLJIT_S0 + 1 - compiler->saveds; i <= tmp; i++) { size = reg_map[i] >= 8 ? 2 : 1; inst = (sljit_u8*)ensure_buf(compiler, 1 + size); FAIL_IF(!inst); @@ -644,6 +648,9 @@ static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler) POP_REG(reg_lmap[i]); } + if (is_return_to) + BINARY_IMM32(ADD, sizeof(sljit_sw), SLJIT_SP, 0); + return SLJIT_SUCCESS; } @@ -654,7 +661,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_void(struct sljit_compiler CHECK_ERROR(); CHECK(check_sljit_emit_return_void(compiler)); - FAIL_IF(emit_stack_frame_release(compiler)); + compiler->mode32 = 0; + + FAIL_IF(emit_stack_frame_release(compiler, 0)); inst = (sljit_u8*)ensure_buf(compiler, 1 + 1); FAIL_IF(!inst); @@ -663,6 +672,28 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_void(struct sljit_compiler return SLJIT_SUCCESS; } +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_to(struct sljit_compiler *compiler, + sljit_s32 src, sljit_sw srcw) +{ + CHECK_ERROR(); + CHECK(check_sljit_emit_return_to(compiler, src, srcw)); + + compiler->mode32 = 0; + + if ((src & SLJIT_MEM) || (src >= SLJIT_FIRST_SAVED_REG && src <= (SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options)))) { + ADJUST_LOCAL_OFFSET(src, srcw); + + EMIT_MOV(compiler, TMP_REG2, 0, src, srcw); + src = TMP_REG2; + srcw = 0; + } + + FAIL_IF(emit_stack_frame_release(compiler, 1)); + + SLJIT_SKIP_CHECKS(compiler); + return sljit_emit_ijump(compiler, SLJIT_JUMP, src, srcw); +} + /* --------------------------------------------------------------------- */ /* Call / return instructions */ /* --------------------------------------------------------------------- */ @@ -786,17 +817,15 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compile compiler->mode32 = 0; - PTR_FAIL_IF(call_with_args(compiler, arg_types, NULL)); + if ((type & 0xff) != SLJIT_CALL_REG_ARG) + PTR_FAIL_IF(call_with_args(compiler, arg_types, NULL)); if (type & SLJIT_CALL_RETURN) { - PTR_FAIL_IF(emit_stack_frame_release(compiler)); + PTR_FAIL_IF(emit_stack_frame_release(compiler, 0)); type = SLJIT_JUMP | (type & SLJIT_REWRITABLE_JUMP); } -#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \ - || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) - compiler->skip_checks = 1; -#endif + SLJIT_SKIP_CHECKS(compiler); return sljit_emit_jump(compiler, type); } @@ -816,22 +845,21 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compi } if (type & SLJIT_CALL_RETURN) { - if (src >= SLJIT_FIRST_SAVED_REG && src <= SLJIT_S0) { + if (src >= SLJIT_FIRST_SAVED_REG && src <= (SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options))) { EMIT_MOV(compiler, TMP_REG2, 0, src, srcw); src = TMP_REG2; } - FAIL_IF(emit_stack_frame_release(compiler)); - type = SLJIT_JUMP; + FAIL_IF(emit_stack_frame_release(compiler, 0)); } - FAIL_IF(call_with_args(compiler, arg_types, &src)); + if ((type & 0xff) != SLJIT_CALL_REG_ARG) + FAIL_IF(call_with_args(compiler, arg_types, &src)); -#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \ - || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) - compiler->skip_checks = 1; -#endif + if (type & SLJIT_CALL_RETURN) + type = SLJIT_JUMP; + SLJIT_SKIP_CHECKS(compiler); return sljit_emit_ijump(compiler, type, src, srcw); } @@ -907,9 +935,89 @@ static sljit_s32 emit_fast_return(struct sljit_compiler *compiler, sljit_s32 src } /* --------------------------------------------------------------------- */ -/* Extend input */ +/* Other operations */ /* --------------------------------------------------------------------- */ +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compiler, sljit_s32 type, + sljit_s32 reg, + sljit_s32 mem, sljit_sw memw) +{ + sljit_u8* inst; + sljit_s32 i, next, reg_idx; + sljit_u8 regs[2]; + + CHECK_ERROR(); + CHECK(check_sljit_emit_mem(compiler, type, reg, mem, memw)); + + if (!(reg & REG_PAIR_MASK)) + return sljit_emit_mem_unaligned(compiler, type, reg, mem, memw); + + ADJUST_LOCAL_OFFSET(mem, memw); + + compiler->mode32 = 0; + + if ((mem & REG_MASK) == 0) { + EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_IMM, memw); + + mem = SLJIT_MEM1(TMP_REG1); + memw = 0; + } else if (!(mem & OFFS_REG_MASK) && ((memw < HALFWORD_MIN) || (memw > HALFWORD_MAX - SSIZE_OF(sw)))) { + EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_IMM, memw); + + mem = SLJIT_MEM2(mem & REG_MASK, TMP_REG1); + memw = 0; + } + + regs[0] = U8(REG_PAIR_FIRST(reg)); + regs[1] = U8(REG_PAIR_SECOND(reg)); + + next = SSIZE_OF(sw); + + if (!(type & SLJIT_MEM_STORE) && (regs[0] == (mem & REG_MASK) || regs[0] == OFFS_REG(mem))) { + if (regs[1] == (mem & REG_MASK) || regs[1] == OFFS_REG(mem)) { + /* Base and offset cannot be TMP_REG1. */ + EMIT_MOV(compiler, TMP_REG1, 0, OFFS_REG(mem), 0); + + if (regs[1] == OFFS_REG(mem)) + next = -SSIZE_OF(sw); + + mem = (mem & ~OFFS_REG_MASK) | TO_OFFS_REG(TMP_REG1); + } else { + next = -SSIZE_OF(sw); + + if (!(mem & OFFS_REG_MASK)) + memw += SSIZE_OF(sw); + } + } + + for (i = 0; i < 2; i++) { + reg_idx = next > 0 ? i : (i ^ 0x1); + reg = regs[reg_idx]; + + if ((mem & OFFS_REG_MASK) && (reg_idx == 1)) { + inst = (sljit_u8*)ensure_buf(compiler, (sljit_uw)(1 + 5)); + FAIL_IF(!inst); + + INC_SIZE(5); + + inst[0] = U8(REX_W | ((reg_map[reg] >= 8) ? REX_R : 0) | ((reg_map[mem & REG_MASK] >= 8) ? REX_B : 0) | ((reg_map[OFFS_REG(mem)] >= 8) ? REX_X : 0)); + inst[1] = (type & SLJIT_MEM_STORE) ? MOV_rm_r : MOV_r_rm; + inst[2] = 0x44 | U8(reg_lmap[reg] << 3); + inst[3] = U8(memw << 6) | U8(reg_lmap[OFFS_REG(mem)] << 3) | reg_lmap[mem & REG_MASK]; + inst[4] = sizeof(sljit_sw); + } else if (type & SLJIT_MEM_STORE) { + EMIT_MOV(compiler, mem, memw, reg, 0); + } else { + EMIT_MOV(compiler, reg, 0, mem, memw); + } + + if (!(mem & OFFS_REG_MASK)) + memw += next; + } + + return SLJIT_SUCCESS; +} + static sljit_s32 emit_mov_int(struct sljit_compiler *compiler, sljit_s32 sign, sljit_s32 dst, sljit_sw dstw, sljit_s32 src, sljit_sw srcw) diff --git a/src/3rdparty/pcre2/src/sljit/sljitNativeX86_common.c b/src/3rdparty/pcre2/src/sljit/sljitNativeX86_common.c index c7dd9be8fd7..651942be80a 100644 --- a/src/3rdparty/pcre2/src/sljit/sljitNativeX86_common.c +++ b/src/3rdparty/pcre2/src/sljit/sljitNativeX86_common.c @@ -26,11 +26,7 @@ SLJIT_API_FUNC_ATTRIBUTE const char* sljit_get_platform_name(void) { -#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL) - return "x86" SLJIT_CPUINFO " ABI:fastcall"; -#else return "x86" SLJIT_CPUINFO; -#endif } /* @@ -78,10 +74,7 @@ static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 3] = { #define CHECK_EXTRA_REGS(p, w, do) \ if (p >= SLJIT_R3 && p <= SLJIT_S3) { \ - if (p <= compiler->scratches) \ - w = compiler->scratches_offset + ((p) - SLJIT_R3) * SSIZE_OF(sw); \ - else \ - w = compiler->locals_offset + ((p) - SLJIT_S2) * SSIZE_OF(sw); \ + w = (2 * SSIZE_OF(sw)) + ((p) - SLJIT_R3) * SSIZE_OF(sw); \ p = SLJIT_MEM1(SLJIT_SP); \ do; \ } @@ -181,6 +174,7 @@ static const sljit_u8 freg_lmap[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 1] = { #define AND_rm_r 0x21 #define ANDPD_x_xm 0x54 #define BSR_r_rm (/* GROUP_0F */ 0xbd) +#define BSF_r_rm (/* GROUP_0F */ 0xbc) #define CALL_i32 0xe8 #define CALL_rm (/* GROUP_FF */ 2 << 3) #define CDQ 0x99 @@ -194,6 +188,8 @@ static const sljit_u8 freg_lmap[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 1] = { #define CVTTSD2SI_r_xm 0x2c #define DIV (/* GROUP_F7 */ 6 << 3) #define DIVSD_x_xm 0x5e +#define FLDS 0xd9 +#define FLDL 0xdd #define FSTPS 0xd9 #define FSTPD 0xdd #define INT3 0xcc @@ -209,6 +205,7 @@ static const sljit_u8 freg_lmap[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 1] = { #define JMP_rm (/* GROUP_FF */ 4 << 3) #define LEA_r_m 0x8d #define LOOP_i8 0xe2 +#define LZCNT_r_rm (/* GROUP_F3 */ /* GROUP_0F */ 0xbd) #define MOV_r_rm 0x8b #define MOV_r_i32 0xb8 #define MOV_rm_r 0x89 @@ -242,6 +239,8 @@ static const sljit_u8 freg_lmap[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 1] = { #define PUSH_r 0x50 #define PUSH_rm (/* GROUP_FF */ 6 << 3) #define PUSHF 0x9c +#define ROL (/* SHIFT */ 0 << 3) +#define ROR (/* SHIFT */ 1 << 3) #define RET_near 0xc3 #define RET_i16 0xc2 #define SBB (/* BINARY */ 3 << 3) @@ -250,6 +249,8 @@ static const sljit_u8 freg_lmap[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 1] = { #define SBB_rm_r 0x19 #define SAR (/* SHIFT */ 7 << 3) #define SHL (/* SHIFT */ 4 << 3) +#define SHLD (/* GROUP_0F */ 0xa5) +#define SHRD (/* GROUP_0F */ 0xad) #define SHR (/* SHIFT */ 5 << 3) #define SUB (/* BINARY */ 5 << 3) #define SUB_EAX_i32 0x2d @@ -258,6 +259,7 @@ static const sljit_u8 freg_lmap[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 1] = { #define SUBSD_x_xm 0x5c #define TEST_EAX_i32 0xa9 #define TEST_rm_r 0x85 +#define TZCNT_r_rm (/* GROUP_F3 */ /* GROUP_0F */ 0xbc) #define UCOMISD_x_xm 0x2e #define UNPCKLPD_x_xm 0x14 #define XCHG_EAX_r 0x90 @@ -269,6 +271,7 @@ static const sljit_u8 freg_lmap[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 1] = { #define XORPD_x_xm 0x57 #define GROUP_0F 0x0f +#define GROUP_F3 0xf3 #define GROUP_F7 0xf7 #define GROUP_FF 0xff #define GROUP_BINARY_81 0x81 @@ -290,10 +293,15 @@ static const sljit_u8 freg_lmap[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 1] = { /* Multithreading does not affect these static variables, since they store built-in CPU features. Therefore they can be overwritten by different threads if they detect the CPU features in the same time. */ +#define CPU_FEATURE_DETECTED 0x001 #if (defined SLJIT_DETECT_SSE2 && SLJIT_DETECT_SSE2) -static sljit_s32 cpu_has_sse2 = -1; +#define CPU_FEATURE_SSE2 0x002 #endif -static sljit_s32 cpu_has_cmov = -1; +#define CPU_FEATURE_LZCNT 0x004 +#define CPU_FEATURE_TZCNT 0x008 +#define CPU_FEATURE_CMOV 0x010 + +static sljit_u32 cpu_feature_list = 0; #ifdef _WIN32_WCE #include @@ -326,17 +334,64 @@ static SLJIT_INLINE void sljit_unaligned_store_sw(void *addr, sljit_sw value) static void get_cpu_features(void) { - sljit_u32 features; + sljit_u32 feature_list = CPU_FEATURE_DETECTED; + sljit_u32 value; #if defined(_MSC_VER) && _MSC_VER >= 1400 int CPUInfo[4]; + + __cpuid(CPUInfo, 0); + if (CPUInfo[0] >= 7) { + __cpuidex(CPUInfo, 7, 0); + if (CPUInfo[1] & 0x8) + feature_list |= CPU_FEATURE_TZCNT; + } + + __cpuid(CPUInfo, (int)0x80000001); + if (CPUInfo[2] & 0x20) + feature_list |= CPU_FEATURE_LZCNT; + __cpuid(CPUInfo, 1); - features = (sljit_u32)CPUInfo[3]; + value = (sljit_u32)CPUInfo[3]; #elif defined(__GNUC__) || defined(__INTEL_COMPILER) || defined(__SUNPRO_C) /* AT&T syntax. */ + __asm__ ( + "movl $0x0, %%eax\n" + "lzcnt %%eax, %%eax\n" + "setnz %%al\n" + "movl %%eax, %0\n" + : "=g" (value) + : +#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) + : "eax" +#else + : "rax" +#endif + ); + + if (value & 0x1) + feature_list |= CPU_FEATURE_LZCNT; + + __asm__ ( + "movl $0x0, %%eax\n" + "tzcnt %%eax, %%eax\n" + "setnz %%al\n" + "movl %%eax, %0\n" + : "=g" (value) + : +#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) + : "eax" +#else + : "rax" +#endif + ); + + if (value & 0x1) + feature_list |= CPU_FEATURE_TZCNT; + __asm__ ( "movl $0x1, %%eax\n" #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) @@ -349,7 +404,7 @@ static void get_cpu_features(void) "pop %%ebx\n" #endif "movl %%edx, %0\n" - : "=g" (features) + : "=g" (value) : #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) : "%eax", "%ecx", "%edx" @@ -361,47 +416,83 @@ static void get_cpu_features(void) #else /* _MSC_VER && _MSC_VER >= 1400 */ /* Intel syntax. */ + __asm { + mov eax, 0 + lzcnt eax, eax + setnz al + mov value, eax + } + + if (value & 0x1) + feature_list |= CPU_FEATURE_LZCNT; + + __asm { + mov eax, 0 + tzcnt eax, eax + setnz al + mov value, eax + } + + if (value & 0x1) + feature_list |= CPU_FEATURE_TZCNT; + __asm { mov eax, 1 cpuid - mov features, edx + mov value, edx } #endif /* _MSC_VER && _MSC_VER >= 1400 */ #if (defined SLJIT_DETECT_SSE2 && SLJIT_DETECT_SSE2) - cpu_has_sse2 = (features >> 26) & 0x1; + if (value & 0x4000000) + feature_list |= CPU_FEATURE_SSE2; #endif - cpu_has_cmov = (features >> 15) & 0x1; + if (value & 0x8000) + feature_list |= CPU_FEATURE_CMOV; + + cpu_feature_list = feature_list; } static sljit_u8 get_jump_code(sljit_uw type) { switch (type) { case SLJIT_EQUAL: - case SLJIT_EQUAL_F64: + case SLJIT_F_EQUAL: + case SLJIT_UNORDERED_OR_EQUAL: + case SLJIT_ORDERED_EQUAL: /* Not supported. */ return 0x84 /* je */; case SLJIT_NOT_EQUAL: - case SLJIT_NOT_EQUAL_F64: + case SLJIT_F_NOT_EQUAL: + case SLJIT_ORDERED_NOT_EQUAL: + case SLJIT_UNORDERED_OR_NOT_EQUAL: /* Not supported. */ return 0x85 /* jne */; case SLJIT_LESS: case SLJIT_CARRY: - case SLJIT_LESS_F64: + case SLJIT_F_LESS: + case SLJIT_UNORDERED_OR_LESS: + case SLJIT_UNORDERED_OR_GREATER: return 0x82 /* jc */; case SLJIT_GREATER_EQUAL: case SLJIT_NOT_CARRY: - case SLJIT_GREATER_EQUAL_F64: + case SLJIT_F_GREATER_EQUAL: + case SLJIT_ORDERED_GREATER_EQUAL: + case SLJIT_ORDERED_LESS_EQUAL: return 0x83 /* jae */; case SLJIT_GREATER: - case SLJIT_GREATER_F64: + case SLJIT_F_GREATER: + case SLJIT_ORDERED_LESS: + case SLJIT_ORDERED_GREATER: return 0x87 /* jnbe */; case SLJIT_LESS_EQUAL: - case SLJIT_LESS_EQUAL_F64: + case SLJIT_F_LESS_EQUAL: + case SLJIT_UNORDERED_OR_GREATER_EQUAL: + case SLJIT_UNORDERED_OR_LESS_EQUAL: return 0x86 /* jbe */; case SLJIT_SIG_LESS: @@ -422,10 +513,10 @@ static sljit_u8 get_jump_code(sljit_uw type) case SLJIT_NOT_OVERFLOW: return 0x81 /* jno */; - case SLJIT_UNORDERED_F64: + case SLJIT_UNORDERED: return 0x8a /* jp */; - case SLJIT_ORDERED_F64: + case SLJIT_ORDERED: return 0x8b /* jpo */; } return 0; @@ -449,13 +540,13 @@ static sljit_u8* generate_near_jump_code(struct sljit_jump *jump, sljit_u8 *code else label_addr = jump->u.target - (sljit_uw)executable_offset; - short_jump = (sljit_sw)(label_addr - (jump->addr + 2)) >= -128 && (sljit_sw)(label_addr - (jump->addr + 2)) <= 127; - #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) if ((sljit_sw)(label_addr - (jump->addr + 1)) > HALFWORD_MAX || (sljit_sw)(label_addr - (jump->addr + 1)) < HALFWORD_MIN) return generate_far_jump_code(jump, code_ptr); #endif + short_jump = (sljit_sw)(label_addr - (jump->addr + 2)) >= -128 && (sljit_sw)(label_addr - (jump->addr + 2)) <= 127; + if (type == SLJIT_JUMP) { if (short_jump) *code_ptr++ = JMP_i8; @@ -581,32 +672,33 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil jump = compiler->jumps; while (jump) { - jump_addr = jump->addr + (sljit_uw)executable_offset; + if (jump->flags & (PATCH_MB | PATCH_MW)) { + if (jump->flags & JUMP_LABEL) + jump_addr = jump->u.label->addr; + else + jump_addr = jump->u.target; - if (jump->flags & PATCH_MB) { - SLJIT_ASSERT((sljit_sw)(jump->u.label->addr - (jump_addr + sizeof(sljit_s8))) >= -128 && (sljit_sw)(jump->u.label->addr - (jump_addr + sizeof(sljit_s8))) <= 127); - *(sljit_u8*)jump->addr = U8(jump->u.label->addr - (jump_addr + sizeof(sljit_s8))); - } else if (jump->flags & PATCH_MW) { - if (jump->flags & JUMP_LABEL) { + jump_addr -= jump->addr + (sljit_uw)executable_offset; + + if (jump->flags & PATCH_MB) { + jump_addr -= sizeof(sljit_s8); + SLJIT_ASSERT((sljit_sw)jump_addr >= -128 && (sljit_sw)jump_addr <= 127); + *(sljit_u8*)jump->addr = U8(jump_addr); + } else { + jump_addr -= sizeof(sljit_s32); #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) - sljit_unaligned_store_sw((void*)jump->addr, (sljit_sw)(jump->u.label->addr - (jump_addr + sizeof(sljit_sw)))); + sljit_unaligned_store_sw((void*)jump->addr, (sljit_sw)jump_addr); #else - SLJIT_ASSERT((sljit_sw)(jump->u.label->addr - (jump_addr + sizeof(sljit_s32))) >= HALFWORD_MIN && (sljit_sw)(jump->u.label->addr - (jump_addr + sizeof(sljit_s32))) <= HALFWORD_MAX); - sljit_unaligned_store_s32((void*)jump->addr, (sljit_s32)(jump->u.label->addr - (jump_addr + sizeof(sljit_s32)))); -#endif - } - else { -#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) - sljit_unaligned_store_sw((void*)jump->addr, (sljit_sw)(jump->u.target - (jump_addr + sizeof(sljit_sw)))); -#else - SLJIT_ASSERT((sljit_sw)(jump->u.target - (jump_addr + sizeof(sljit_s32))) >= HALFWORD_MIN && (sljit_sw)(jump->u.target - (jump_addr + sizeof(sljit_s32))) <= HALFWORD_MAX); - sljit_unaligned_store_s32((void*)jump->addr, (sljit_s32)(jump->u.target - (jump_addr + sizeof(sljit_s32)))); + SLJIT_ASSERT((sljit_sw)jump_addr >= HALFWORD_MIN && (sljit_sw)jump_addr <= HALFWORD_MAX); + sljit_unaligned_store_s32((void*)jump->addr, (sljit_s32)jump_addr); #endif } } #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) - else if (jump->flags & PATCH_MD) - sljit_unaligned_store_sw((void*)jump->addr, (sljit_sw)jump->u.label->addr); + else if (jump->flags & PATCH_MD) { + SLJIT_ASSERT(jump->flags & JUMP_LABEL); + sljit_unaligned_store_sw((void*)jump->addr, (sljit_sw)jump->u.label->addr); + } #endif jump = jump->next; @@ -647,9 +739,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type) #ifdef SLJIT_IS_FPU_AVAILABLE return SLJIT_IS_FPU_AVAILABLE; #elif (defined SLJIT_DETECT_SSE2 && SLJIT_DETECT_SSE2) - if (cpu_has_sse2 == -1) + if (cpu_feature_list == 0) get_cpu_features(); - return cpu_has_sse2; + return (cpu_feature_list & CPU_FEATURE_SSE2) != 0; #else /* SLJIT_DETECT_SSE2 */ return 1; #endif /* SLJIT_DETECT_SSE2 */ @@ -657,31 +749,57 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type) #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) case SLJIT_HAS_VIRTUAL_REGISTERS: return 1; -#endif +#endif /* SLJIT_CONFIG_X86_32 */ case SLJIT_HAS_CLZ: - case SLJIT_HAS_CMOV: - if (cpu_has_cmov == -1) + if (cpu_feature_list == 0) get_cpu_features(); - return cpu_has_cmov; + return (cpu_feature_list & CPU_FEATURE_LZCNT) ? 1 : 2; + + case SLJIT_HAS_CTZ: + if (cpu_feature_list == 0) + get_cpu_features(); + + return (cpu_feature_list & CPU_FEATURE_TZCNT) ? 1 : 2; + + case SLJIT_HAS_CMOV: + if (cpu_feature_list == 0) + get_cpu_features(); + return (cpu_feature_list & CPU_FEATURE_CMOV) != 0; + + case SLJIT_HAS_ROT: case SLJIT_HAS_PREFETCH: return 1; case SLJIT_HAS_SSE2: #if (defined SLJIT_DETECT_SSE2 && SLJIT_DETECT_SSE2) - if (cpu_has_sse2 == -1) + if (cpu_feature_list == 0) get_cpu_features(); - return cpu_has_sse2; -#else + return (cpu_feature_list & CPU_FEATURE_SSE2) != 0; +#else /* !SLJIT_DETECT_SSE2 */ return 1; -#endif +#endif /* SLJIT_DETECT_SSE2 */ default: return 0; } } +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_cmp_info(sljit_s32 type) +{ + if (type < SLJIT_UNORDERED || type > SLJIT_ORDERED_LESS_EQUAL) + return 0; + + switch (type) { + case SLJIT_ORDERED_EQUAL: + case SLJIT_UNORDERED_OR_NOT_EQUAL: + return 0; + } + + return 1; +} + /* --------------------------------------------------------------------- */ /* Operators */ /* --------------------------------------------------------------------- */ @@ -1385,47 +1503,75 @@ static sljit_s32 emit_not_with_flags(struct sljit_compiler *compiler, #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) static const sljit_sw emit_clz_arg = 32 + 31; +static const sljit_sw emit_ctz_arg = 32; #endif -static sljit_s32 emit_clz(struct sljit_compiler *compiler, sljit_s32 op_flags, +static sljit_s32 emit_clz_ctz(struct sljit_compiler *compiler, sljit_s32 is_clz, sljit_s32 dst, sljit_sw dstw, sljit_s32 src, sljit_sw srcw) { sljit_u8* inst; sljit_s32 dst_r; + sljit_sw max; - SLJIT_UNUSED_ARG(op_flags); - - if (cpu_has_cmov == -1) + if (cpu_feature_list == 0) get_cpu_features(); dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1; + if (is_clz ? (cpu_feature_list & CPU_FEATURE_LZCNT) : (cpu_feature_list & CPU_FEATURE_TZCNT)) { + /* Group prefix added separately. */ + inst = (sljit_u8*)ensure_buf(compiler, 1 + 1); + FAIL_IF(!inst); + INC_SIZE(1); + *inst++ = GROUP_F3; + + inst = emit_x86_instruction(compiler, 2, dst_r, 0, src, srcw); + FAIL_IF(!inst); + *inst++ = GROUP_0F; + *inst = is_clz ? LZCNT_r_rm : TZCNT_r_rm; + + if (dst & SLJIT_MEM) + EMIT_MOV(compiler, dst, dstw, TMP_REG1, 0); + return SLJIT_SUCCESS; + } + inst = emit_x86_instruction(compiler, 2, dst_r, 0, src, srcw); FAIL_IF(!inst); *inst++ = GROUP_0F; - *inst = BSR_r_rm; + *inst = is_clz ? BSR_r_rm : BSF_r_rm; #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) - if (cpu_has_cmov) { + max = is_clz ? (32 + 31) : 32; + + if (cpu_feature_list & CPU_FEATURE_CMOV) { if (dst_r != TMP_REG1) { - EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_IMM, 32 + 31); + EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_IMM, max); inst = emit_x86_instruction(compiler, 2, dst_r, 0, TMP_REG1, 0); } else - inst = emit_x86_instruction(compiler, 2, dst_r, 0, SLJIT_MEM0(), (sljit_sw)&emit_clz_arg); + inst = emit_x86_instruction(compiler, 2, dst_r, 0, SLJIT_MEM0(), is_clz ? (sljit_sw)&emit_clz_arg : (sljit_sw)&emit_ctz_arg); FAIL_IF(!inst); *inst++ = GROUP_0F; *inst = CMOVE_r_rm; } else - FAIL_IF(sljit_emit_cmov_generic(compiler, SLJIT_EQUAL, dst_r, SLJIT_IMM, 32 + 31)); + FAIL_IF(sljit_emit_cmov_generic(compiler, SLJIT_EQUAL, dst_r, SLJIT_IMM, max)); - inst = emit_x86_instruction(compiler, 1 | EX86_BIN_INS, SLJIT_IMM, 31, dst_r, 0); + if (is_clz) { + inst = emit_x86_instruction(compiler, 1 | EX86_BIN_INS, SLJIT_IMM, 31, dst_r, 0); + FAIL_IF(!inst); + *(inst + 1) |= XOR; + } #else - if (cpu_has_cmov) { - EMIT_MOV(compiler, TMP_REG2, 0, SLJIT_IMM, !(op_flags & SLJIT_32) ? (64 + 63) : (32 + 31)); + if (is_clz) + max = compiler->mode32 ? (32 + 31) : (64 + 63); + else + max = compiler->mode32 ? 32 : 64; + + if (cpu_feature_list & CPU_FEATURE_CMOV) { + EMIT_MOV(compiler, TMP_REG2, 0, SLJIT_IMM, max); inst = emit_x86_instruction(compiler, 2, dst_r, 0, TMP_REG2, 0); FAIL_IF(!inst); @@ -1433,14 +1579,15 @@ static sljit_s32 emit_clz(struct sljit_compiler *compiler, sljit_s32 op_flags, *inst = CMOVE_r_rm; } else - FAIL_IF(sljit_emit_cmov_generic(compiler, SLJIT_EQUAL, dst_r, SLJIT_IMM, !(op_flags & SLJIT_32) ? (64 + 63) : (32 + 31))); + FAIL_IF(sljit_emit_cmov_generic(compiler, SLJIT_EQUAL, dst_r, SLJIT_IMM, max)); - inst = emit_x86_instruction(compiler, 1 | EX86_BIN_INS, SLJIT_IMM, !(op_flags & SLJIT_32) ? 63 : 31, dst_r, 0); + if (is_clz) { + inst = emit_x86_instruction(compiler, 1 | EX86_BIN_INS, SLJIT_IMM, max >> 1, dst_r, 0); + FAIL_IF(!inst); + *(inst + 1) |= XOR; + } #endif - FAIL_IF(!inst); - *(inst + 1) |= XOR; - if (dst & SLJIT_MEM) EMIT_MOV(compiler, dst, dstw, TMP_REG1, 0); return SLJIT_SUCCESS; @@ -1578,7 +1725,8 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile return emit_unary(compiler, NOT_rm, dst, dstw, src, srcw); case SLJIT_CLZ: - return emit_clz(compiler, op_flags, dst, dstw, src, srcw); + case SLJIT_CTZ: + return emit_clz_ctz(compiler, (op == SLJIT_CLZ), dst, dstw, src, srcw); } return SLJIT_SUCCESS; @@ -2116,6 +2264,9 @@ static sljit_s32 emit_shift(struct sljit_compiler *compiler, sljit_s32 src1, sljit_sw src1w, sljit_s32 src2, sljit_sw src2w) { +#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) + sljit_s32 mode32; +#endif sljit_u8* inst; if ((src2 & SLJIT_IMM) || (src2 == SLJIT_PREF_SHIFT_REG)) { @@ -2155,41 +2306,62 @@ static sljit_s32 emit_shift(struct sljit_compiler *compiler, inst = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, SLJIT_PREF_SHIFT_REG, 0, TMP_REG1, 0); FAIL_IF(!inst); *inst |= mode; - EMIT_MOV(compiler, SLJIT_PREF_SHIFT_REG, 0, TMP_REG1, 0); + return emit_mov(compiler, SLJIT_PREF_SHIFT_REG, 0, TMP_REG1, 0); } - else if (FAST_IS_REG(dst) && dst != src2 && dst != TMP_REG1 && !ADDRESSING_DEPENDS_ON(src2, dst)) { + + if (FAST_IS_REG(dst) && dst != src2 && dst != TMP_REG1 && !ADDRESSING_DEPENDS_ON(src2, dst)) { if (src1 != dst) EMIT_MOV(compiler, dst, 0, src1, src1w); +#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) + mode32 = compiler->mode32; + compiler->mode32 = 0; +#endif EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_PREF_SHIFT_REG, 0); +#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) + compiler->mode32 = mode32; +#endif EMIT_MOV(compiler, SLJIT_PREF_SHIFT_REG, 0, src2, src2w); inst = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, SLJIT_PREF_SHIFT_REG, 0, dst, 0); FAIL_IF(!inst); *inst |= mode; - EMIT_MOV(compiler, SLJIT_PREF_SHIFT_REG, 0, TMP_REG1, 0); - } - else { - /* This case is complex since ecx itself may be used for - addressing, and this case must be supported as well. */ - EMIT_MOV(compiler, TMP_REG1, 0, src1, src1w); -#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) - EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), 0, SLJIT_PREF_SHIFT_REG, 0); - EMIT_MOV(compiler, SLJIT_PREF_SHIFT_REG, 0, src2, src2w); - inst = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, SLJIT_PREF_SHIFT_REG, 0, TMP_REG1, 0); - FAIL_IF(!inst); - *inst |= mode; - EMIT_MOV(compiler, SLJIT_PREF_SHIFT_REG, 0, SLJIT_MEM1(SLJIT_SP), 0); -#else - EMIT_MOV(compiler, TMP_REG2, 0, SLJIT_PREF_SHIFT_REG, 0); - EMIT_MOV(compiler, SLJIT_PREF_SHIFT_REG, 0, src2, src2w); - inst = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, SLJIT_PREF_SHIFT_REG, 0, TMP_REG1, 0); - FAIL_IF(!inst); - *inst |= mode; - EMIT_MOV(compiler, SLJIT_PREF_SHIFT_REG, 0, TMP_REG2, 0); +#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) + compiler->mode32 = 0; #endif - if (dst != TMP_REG1) - return emit_mov(compiler, dst, dstw, TMP_REG1, 0); + EMIT_MOV(compiler, SLJIT_PREF_SHIFT_REG, 0, TMP_REG1, 0); +#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) + compiler->mode32 = mode32; +#endif + return SLJIT_SUCCESS; } + /* This case is complex since ecx itself may be used for + addressing, and this case must be supported as well. */ + EMIT_MOV(compiler, TMP_REG1, 0, src1, src1w); +#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) + EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), 0, SLJIT_PREF_SHIFT_REG, 0); +#else /* !SLJIT_CONFIG_X86_32 */ + mode32 = compiler->mode32; + compiler->mode32 = 0; + EMIT_MOV(compiler, TMP_REG2, 0, SLJIT_PREF_SHIFT_REG, 0); + compiler->mode32 = mode32; +#endif /* SLJIT_CONFIG_X86_32 */ + + EMIT_MOV(compiler, SLJIT_PREF_SHIFT_REG, 0, src2, src2w); + inst = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, SLJIT_PREF_SHIFT_REG, 0, TMP_REG1, 0); + FAIL_IF(!inst); + *inst |= mode; + +#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) + EMIT_MOV(compiler, SLJIT_PREF_SHIFT_REG, 0, SLJIT_MEM1(SLJIT_SP), 0); +#else + compiler->mode32 = 0; + EMIT_MOV(compiler, SLJIT_PREF_SHIFT_REG, 0, TMP_REG2, 0); + compiler->mode32 = mode32; +#endif /* SLJIT_CONFIG_X86_32 */ + + if (dst != TMP_REG1) + return emit_mov(compiler, dst, dstw, TMP_REG1, 0); + return SLJIT_SUCCESS; } @@ -2202,12 +2374,13 @@ static sljit_s32 emit_shift_with_flags(struct sljit_compiler *compiler, /* The CPU does not set flags if the shift count is 0. */ if (src2 & SLJIT_IMM) { #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) - if ((src2w & 0x3f) != 0 || (compiler->mode32 && (src2w & 0x1f) != 0)) + src2w &= compiler->mode32 ? 0x1f : 0x3f; +#else /* !SLJIT_CONFIG_X86_64 */ + src2w &= 0x1f; +#endif /* SLJIT_CONFIG_X86_64 */ + if (src2w != 0) return emit_shift(compiler, mode, dst, dstw, src1, src1w, src2, src2w); -#else - if ((src2w & 0x1f) != 0) - return emit_shift(compiler, mode, dst, dstw, src1, src1w, src2, src2w); -#endif + if (!set_flags) return emit_mov(compiler, dst, dstw, src1, src1w); /* OR dst, src, 0 */ @@ -2289,14 +2462,23 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compile return emit_cum_binary(compiler, BINARY_OPCODE(XOR), dst, dstw, src1, src1w, src2, src2w); case SLJIT_SHL: + case SLJIT_MSHL: return emit_shift_with_flags(compiler, SHL, HAS_FLAGS(op), dst, dstw, src1, src1w, src2, src2w); case SLJIT_LSHR: + case SLJIT_MLSHR: return emit_shift_with_flags(compiler, SHR, HAS_FLAGS(op), dst, dstw, src1, src1w, src2, src2w); case SLJIT_ASHR: + case SLJIT_MASHR: return emit_shift_with_flags(compiler, SAR, HAS_FLAGS(op), dst, dstw, src1, src1w, src2, src2w); + case SLJIT_ROTL: + return emit_shift_with_flags(compiler, ROL, 0, + dst, dstw, src1, src1w, src2, src2w); + case SLJIT_ROTR: + return emit_shift_with_flags(compiler, ROR, 0, + dst, dstw, src1, src1w, src2, src2w); } return SLJIT_SUCCESS; @@ -2312,10 +2494,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2u(struct sljit_compiler *compil CHECK(check_sljit_emit_op2(compiler, op, 1, 0, 0, src1, src1w, src2, src2w)); if (opcode != SLJIT_SUB && opcode != SLJIT_AND) { -#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \ - || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) - compiler->skip_checks = 1; -#endif + SLJIT_SKIP_CHECKS(compiler); return sljit_emit_op2(compiler, op, TMP_REG1, 0, src1, src1w, src2, src2w); } @@ -2334,6 +2513,122 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2u(struct sljit_compiler *compil return emit_test_binary(compiler, src1, src1w, src2, src2w); } +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_shift_into(struct sljit_compiler *compiler, sljit_s32 op, + sljit_s32 src_dst, + sljit_s32 src1, sljit_sw src1w, + sljit_s32 src2, sljit_sw src2w) +{ + sljit_s32 restore_ecx = 0; + sljit_s32 is_rotate, is_left; + sljit_u8* inst; + sljit_sw dstw = 0; +#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) + sljit_s32 tmp2 = SLJIT_MEM1(SLJIT_SP); +#else /* !SLJIT_CONFIG_X86_32 */ + sljit_s32 tmp2 = TMP_REG2; +#endif /* SLJIT_CONFIG_X86_32 */ + + CHECK_ERROR(); + CHECK(check_sljit_emit_shift_into(compiler, op, src_dst, src1, src1w, src2, src2w)); + ADJUST_LOCAL_OFFSET(src1, src1w); + ADJUST_LOCAL_OFFSET(src2, src2w); + + CHECK_EXTRA_REGS(src1, src1w, (void)0); + CHECK_EXTRA_REGS(src2, src2w, (void)0); + +#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) + compiler->mode32 = op & SLJIT_32; +#endif + + if (src2 & SLJIT_IMM) { +#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) + src2w &= 0x1f; +#else /* !SLJIT_CONFIG_X86_32 */ + src2w &= (op & SLJIT_32) ? 0x1f : 0x3f; +#endif /* SLJIT_CONFIG_X86_32 */ + + if (src2w == 0) + return SLJIT_SUCCESS; + } + + is_left = (GET_OPCODE(op) == SLJIT_SHL || GET_OPCODE(op) == SLJIT_MSHL); + + is_rotate = (src_dst == src1); + CHECK_EXTRA_REGS(src_dst, dstw, (void)0); + + if (is_rotate) + return emit_shift(compiler, is_left ? ROL : ROR, src_dst, dstw, src1, src1w, src2, src2w); + + if ((src2 & SLJIT_IMM) || src2 == SLJIT_PREF_SHIFT_REG) { + if (!FAST_IS_REG(src1)) { + EMIT_MOV(compiler, TMP_REG1, 0, src1, src1w); + src1 = TMP_REG1; + } + } else if (FAST_IS_REG(src1)) { +#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) + compiler->mode32 = 0; +#endif + EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_PREF_SHIFT_REG, 0); +#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) + compiler->mode32 = op & SLJIT_32; +#endif + EMIT_MOV(compiler, SLJIT_PREF_SHIFT_REG, 0, src2, src2w); + + if (src1 == SLJIT_PREF_SHIFT_REG) + src1 = TMP_REG1; + + if (src_dst == SLJIT_PREF_SHIFT_REG) + src_dst = TMP_REG1; + + restore_ecx = 1; + } else { + EMIT_MOV(compiler, TMP_REG1, 0, src1, src1w); +#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) + compiler->mode32 = 0; +#endif + EMIT_MOV(compiler, tmp2, 0, SLJIT_PREF_SHIFT_REG, 0); +#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) + compiler->mode32 = op & SLJIT_32; +#endif + EMIT_MOV(compiler, SLJIT_PREF_SHIFT_REG, 0, src2, src2w); + + src1 = TMP_REG1; + + if (src_dst == SLJIT_PREF_SHIFT_REG) { + src_dst = tmp2; + SLJIT_ASSERT(dstw == 0); + } + + restore_ecx = 2; + } + + inst = emit_x86_instruction(compiler, 2, src1, 0, src_dst, dstw); + FAIL_IF(!inst); + inst[0] = GROUP_0F; + + if (src2 & SLJIT_IMM) { + inst[1] = U8((is_left ? SHLD : SHRD) - 1); + + /* Immedate argument is added separately. */ + inst = (sljit_u8*)ensure_buf(compiler, 1 + 1); + FAIL_IF(!inst); + INC_SIZE(1); + *inst = U8(src2w); + } else + inst[1] = U8(is_left ? SHLD : SHRD); + +#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) + compiler->mode32 = 0; +#endif + + if (restore_ecx == 1) + return emit_mov(compiler, SLJIT_PREF_SHIFT_REG, 0, TMP_REG1, 0); + if (restore_ecx == 2) + return emit_mov(compiler, SLJIT_PREF_SHIFT_REG, 0, tmp2, 0); + + return SLJIT_SUCCESS; +} + SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_src(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 src, sljit_sw srcw) { @@ -2516,6 +2811,19 @@ static SLJIT_INLINE sljit_s32 sljit_emit_fop1_cmp(struct sljit_compiler *compile sljit_s32 src1, sljit_sw src1w, sljit_s32 src2, sljit_sw src2w) { + switch (GET_FLAG_TYPE(op)) { + case SLJIT_ORDERED_LESS: + case SLJIT_UNORDERED_OR_GREATER_EQUAL: + case SLJIT_UNORDERED_OR_GREATER: + case SLJIT_ORDERED_LESS_EQUAL: + if (!FAST_IS_REG(src2)) { + FAIL_IF(emit_sse2_load(compiler, op & SLJIT_32, TMP_FREG, src2, src2w)); + src2 = TMP_FREG; + } + + return emit_sse2_logic(compiler, UCOMISD_x_xm, !(op & SLJIT_32), src2, src1, src1w); + } + if (!FAST_IS_REG(src1)) { FAIL_IF(emit_sse2_load(compiler, op & SLJIT_32, TMP_FREG, src1, src1w)); src1 = TMP_FREG; @@ -2769,7 +3077,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *co ADJUST_LOCAL_OFFSET(dst, dstw); CHECK_EXTRA_REGS(dst, dstw, (void)0); - type &= 0xff; /* setcc = jcc + 0x10. */ cond_set = U8(get_jump_code((sljit_uw)type) + 0x10); @@ -2813,10 +3120,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *co return emit_mov(compiler, dst, dstw, TMP_REG1, 0); } -#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \ - || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) - compiler->skip_checks = 1; -#endif + SLJIT_SKIP_CHECKS(compiler); return sljit_emit_op2(compiler, op, dst_save, dstw_save, dst_save, dstw_save, TMP_REG1, 0); #else @@ -2839,10 +3143,10 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *co } /* Low byte is not accessible. */ - if (cpu_has_cmov == -1) + if (cpu_feature_list == 0) get_cpu_features(); - if (cpu_has_cmov) { + if (cpu_feature_list & CPU_FEATURE_CMOV) { EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_IMM, 1); /* a xor reg, reg operation would overwrite the flags. */ EMIT_MOV(compiler, dst, 0, SLJIT_IMM, 0); @@ -2927,10 +3231,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *co if (GET_OPCODE(op) < SLJIT_ADD) return emit_mov(compiler, dst, dstw, TMP_REG1, 0); -#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \ - || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) - compiler->skip_checks = 1; -#endif + SLJIT_SKIP_CHECKS(compiler); return sljit_emit_op2(compiler, op, dst_save, dstw_save, dst_save, dstw_save, TMP_REG1, 0); #endif /* SLJIT_CONFIG_X86_64 */ } @@ -2945,7 +3246,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_cmov(struct sljit_compiler *compil CHECK(check_sljit_emit_cmov(compiler, type, dst_reg, src, srcw)); #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) - dst_reg &= ~SLJIT_32; + type &= ~SLJIT_32; if (!sljit_has_cpu_feature(SLJIT_HAS_CMOV) || (dst_reg >= SLJIT_R3 && dst_reg <= SLJIT_S3)) return sljit_emit_cmov_generic(compiler, type, dst_reg, src, srcw); @@ -2958,8 +3259,8 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_cmov(struct sljit_compiler *compil CHECK_EXTRA_REGS(src, srcw, (void)0); #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) - compiler->mode32 = dst_reg & SLJIT_32; - dst_reg &= ~SLJIT_32; + compiler->mode32 = type & SLJIT_32; + type &= ~SLJIT_32; #endif if (SLJIT_UNLIKELY(src & SLJIT_IMM)) { @@ -2971,7 +3272,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_cmov(struct sljit_compiler *compil inst = emit_x86_instruction(compiler, 2, dst_reg, 0, src, srcw); FAIL_IF(!inst); *inst++ = GROUP_0F; - *inst = U8(get_jump_code(type & 0xff) - 0x40); + *inst = U8(get_jump_code((sljit_uw)type) - 0x40); return SLJIT_SUCCESS; } diff --git a/src/3rdparty/pcre2/src/sljit/sljitWXExecAllocator.c b/src/3rdparty/pcre2/src/sljit/sljitWXExecAllocator.c index 72d5b8dd2b3..68938131559 100644 --- a/src/3rdparty/pcre2/src/sljit/sljitWXExecAllocator.c +++ b/src/3rdparty/pcre2/src/sljit/sljitWXExecAllocator.c @@ -59,38 +59,15 @@ #include #ifdef __NetBSD__ -#if defined(PROT_MPROTECT) -#define check_se_protected(ptr, size) (0) #define SLJIT_PROT_WX PROT_MPROTECT(PROT_EXEC) -#else /* !PROT_MPROTECT */ -#ifdef _NETBSD_SOURCE -#include -#else /* !_NETBSD_SOURCE */ -typedef unsigned int u_int; -#define devmajor_t sljit_s32 -#endif /* _NETBSD_SOURCE */ -#include -#include - -#define check_se_protected(ptr, size) netbsd_se_protected() - -static SLJIT_INLINE int netbsd_se_protected(void) -{ - int mib[3]; - int paxflags; - size_t len = sizeof(paxflags); - - mib[0] = CTL_PROC; - mib[1] = getpid(); - mib[2] = PROC_PID_PAXFLAGS; - - if (SLJIT_UNLIKELY(sysctl(mib, 3, &paxflags, &len, NULL, 0) < 0)) - return -1; - - return (paxflags & CTL_PROC_PAXFLAGS_MPROTECT) ? -1 : 0; -} -#endif /* PROT_MPROTECT */ +#define check_se_protected(ptr, size) (0) #else /* POSIX */ +#if !(defined SLJIT_SINGLE_THREADED && SLJIT_SINGLE_THREADED) +#include +#define SLJIT_SE_LOCK() pthread_mutex_lock(&se_lock) +#define SLJIT_SE_UNLOCK() pthread_mutex_unlock(&se_lock) +#endif /* !SLJIT_SINGLE_THREADED */ + #define check_se_protected(ptr, size) generic_se_protected(ptr, size) static SLJIT_INLINE int generic_se_protected(void *ptr, sljit_uw size) @@ -102,22 +79,20 @@ static SLJIT_INLINE int generic_se_protected(void *ptr, sljit_uw size) } #endif /* NetBSD */ -#if defined SLJIT_SINGLE_THREADED && SLJIT_SINGLE_THREADED +#ifndef SLJIT_SE_LOCK #define SLJIT_SE_LOCK() +#endif +#ifndef SLJIT_SE_UNLOCK #define SLJIT_SE_UNLOCK() -#else /* !SLJIT_SINGLE_THREADED */ -#include -#define SLJIT_SE_LOCK() pthread_mutex_lock(&se_lock) -#define SLJIT_SE_UNLOCK() pthread_mutex_unlock(&se_lock) -#endif /* SLJIT_SINGLE_THREADED */ - +#endif #ifndef SLJIT_PROT_WX #define SLJIT_PROT_WX 0 -#endif /* !SLJIT_PROT_WX */ +#endif SLJIT_API_FUNC_ATTRIBUTE void* sljit_malloc_exec(sljit_uw size) { -#if !(defined SLJIT_SINGLE_THREADED && SLJIT_SINGLE_THREADED) +#if !(defined SLJIT_SINGLE_THREADED && SLJIT_SINGLE_THREADED) \ + && !defined(__NetBSD__) static pthread_mutex_t se_lock = PTHREAD_MUTEX_INITIALIZER; #endif static int se_protected = !SLJIT_PROT_WX; From 22af26890f997ecf9b04eb1ab429c86016630ffa Mon Sep 17 00:00:00 2001 From: Alexey Edelev Date: Fri, 19 May 2023 15:48:47 +0200 Subject: [PATCH 002/151] Fix Clang platform detecting mechanism CMake not necessarly sets MSVC or MINGW when detecting Clang compiler. We should rely on CMAKE_CXX_COMPILER_FRONTEND_VARIANT instead when detecting Clang platform. Fixes: QTBUG-113630 Change-Id: I8c14939ddc0839ddf2b3419392aa843deeef4bb5 Reviewed-by: Amir Masoud Abdol Reviewed-by: Alexandru Croitor Reviewed-by: Qt CI Bot (cherry picked from commit 5cf79c2b9b196b3915d8babc46724f400806e64e) Reviewed-by: Qt Cherry-pick Bot --- cmake/QtBuild.cmake | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/cmake/QtBuild.cmake b/cmake/QtBuild.cmake index 7c57629b769..b5a7575e6e6 100644 --- a/cmake/QtBuild.cmake +++ b/cmake/QtBuild.cmake @@ -269,21 +269,21 @@ if(WIN32) if(CMAKE_SIZEOF_VOID_P EQUAL 8) list(APPEND QT_DEFAULT_PLATFORM_DEFINITIONS WIN64 _WIN64) endif() - if(MSVC) - if (CLANG) + + if(CLANG) + if(CMAKE_CXX_COMPILER_FRONTEND_VARIANT STREQUAL "MSVC" OR MSVC) set(QT_DEFAULT_MKSPEC win32-clang-msvc) - elseif(CMAKE_SYSTEM_PROCESSOR STREQUAL "arm64") + elseif(CMAKE_CXX_COMPILER_FRONTEND_VARIANT STREQUAL "GNU" OR MINGW) + set(QT_DEFAULT_MKSPEC win32-clang-g++) + endif() + elseif(MSVC) + if(CMAKE_SYSTEM_PROCESSOR STREQUAL "arm64") set(QT_DEFAULT_MKSPEC win32-arm64-msvc) else() set(QT_DEFAULT_MKSPEC win32-msvc) endif() - elseif(CLANG AND MINGW) - set(QT_DEFAULT_MKSPEC win32-clang-g++) elseif(MINGW) set(QT_DEFAULT_MKSPEC win32-g++) - endif() - - if (MINGW) list(APPEND QT_DEFAULT_PLATFORM_DEFINITIONS MINGW_HAS_SECURE_API=1) endif() elseif(LINUX) From c89278f5dfc03c6d1f1a01d18d1281d0f36fdfe3 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Wed, 31 May 2023 09:49:28 +0200 Subject: [PATCH 003/151] QVariant: remove outdated docs about reimplementing clear() QVariant::clear() hasn't been virtual since at least Qt 4... Change-Id: If6b5669d91f8d9c7ed2d152d18852a8d6f8e491a Reviewed-by: Giuseppe D'Angelo Reviewed-by: Fabian Kosmale (cherry picked from commit 496bd9e9755f4636aa4086af7942feee023ff780) Reviewed-by: Qt Cherry-pick Bot --- src/corelib/kernel/qvariant.cpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/corelib/kernel/qvariant.cpp b/src/corelib/kernel/qvariant.cpp index fb7b4b9cbc2..8981521640f 100644 --- a/src/corelib/kernel/qvariant.cpp +++ b/src/corelib/kernel/qvariant.cpp @@ -506,11 +506,6 @@ void QVariant::create(QMetaType type, const void *copy) \fn QVariant::~QVariant() Destroys the QVariant and the contained object. - - Note that subclasses that reimplement clear() should reimplement - the destructor to call clear(). This destructor calls clear(), but - because it is the destructor, QVariant::clear() is called rather - than a subclass's clear(). */ QVariant::~QVariant() From 6db61454eab4815d73e6a85ca1347c9d8a6efd69 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Thu, 1 Jun 2023 11:00:26 +0200 Subject: [PATCH 004/151] QVariant::fromStdVariant(): protect against accidental fromValue() ADL pick-ups The use of unqualified fromValue(arg) in the visitor implementation invites non-QVariant fromValue(T) overloads to be found using ADL, which just happen to compile because their return value implicitly converts to QVariant (like most stuff does). To rule this out, use FQN QVariant::fromValue() to switch off ADL. [ChangeLog][QtCore][QVariant] The fromStdVariant() function used an unqualifed fromValue() call to convert each alternative type in the std::variant. It now uses qualified QVariant::fromValue() to avoid picking up unrelated fromValue() overloads whose return value just happens to implicitly convert to QVariant. Amends 5927acaf652e2dfacd777a7491c217aefd1118ef. Change-Id: Ica21b08c919459d0a740af03f451e4ffe224b641 Reviewed-by: Fabian Kosmale (cherry picked from commit 6f529c38ce9fcd94fc7ef74d4a1a51cb3b0cf463) Reviewed-by: Qt Cherry-pick Bot --- src/corelib/kernel/qvariant.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/corelib/kernel/qvariant.h b/src/corelib/kernel/qvariant.h index 55cc6910019..8dd1b8bb6f0 100644 --- a/src/corelib/kernel/qvariant.h +++ b/src/corelib/kernel/qvariant.h @@ -408,7 +408,7 @@ class Q_CORE_EXPORT QVariant { if (value.valueless_by_exception()) return QVariant(); - return std::visit([](const auto &arg) { return fromValue(arg); }, value); + return std::visit([](const auto &arg) { return QVariant::fromValue(arg); }, value); } #endif From c7c7f766e267583a65bbd7aadc16cc242f91ce04 Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Thu, 1 Jun 2023 07:53:31 +0200 Subject: [PATCH 005/151] Upgrade Harfbuzz to 7.3.0 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes: QTBUG-114098 Change-Id: I7bc766e6edada6f964c2dc40f18ff710249fb159 Reviewed-by: Tor Arne Vestbø (cherry picked from commit d390ac99f2c2a0f70319df5f6ed3068cc5cbd6fe) Reviewed-by: Volker Hilsheimer --- src/3rdparty/harfbuzz-ng/CMakeLists.txt | 1 + src/3rdparty/harfbuzz-ng/NEWS | 21 + src/3rdparty/harfbuzz-ng/qt_attribution.json | 2 +- .../harfbuzz-ng/src/OT/Color/COLR/COLR.hh | 8 +- .../src/OT/Layout/Common/Coverage.hh | 23 +- .../src/OT/Layout/Common/CoverageFormat2.hh | 17 +- .../src/OT/Layout/Common/RangeRecord.hh | 12 + .../harfbuzz-ng/src/OT/Layout/GDEF/GDEF.hh | 24 + .../src/OT/Layout/GPOS/CursivePosFormat1.hh | 4 +- .../harfbuzz-ng/src/OT/Layout/GPOS/GPOS.hh | 2 +- .../src/OT/Layout/GPOS/MarkMarkPosFormat1.hh | 6 +- .../src/OT/Layout/GPOS/PairPosFormat1.hh | 4 +- .../src/OT/Layout/GPOS/PairPosFormat2.hh | 35 +- .../harfbuzz-ng/src/OT/Layout/GPOS/PairSet.hh | 4 +- .../src/OT/Layout/GSUB/Ligature.hh | 2 +- .../src/OT/Layout/GSUB/LigatureSet.hh | 62 +- .../src/OT/Layout/GSUB/SingleSubst.hh | 2 +- .../harfbuzz-ng/src/OT/glyf/CompositeGlyph.hh | 36 +- src/3rdparty/harfbuzz-ng/src/OT/glyf/Glyph.hh | 93 +-- .../harfbuzz-ng/src/OT/glyf/SimpleGlyph.hh | 33 +- .../src/OT/glyf/VarCompositeGlyph.hh | 244 ++++---- .../harfbuzz-ng/src/OT/glyf/path-builder.hh | 8 +- src/3rdparty/harfbuzz-ng/src/graph/graph.hh | 64 ++- .../src/graph/markbasepos-graph.hh | 5 +- .../harfbuzz-ng/src/graph/serialize.hh | 4 +- src/3rdparty/harfbuzz-ng/src/hb-aat-layout.cc | 8 +- src/3rdparty/harfbuzz-ng/src/hb-algs.hh | 6 +- src/3rdparty/harfbuzz-ng/src/hb-array.hh | 34 +- src/3rdparty/harfbuzz-ng/src/hb-bit-set.hh | 7 +- src/3rdparty/harfbuzz-ng/src/hb-buffer.cc | 2 +- src/3rdparty/harfbuzz-ng/src/hb-buffer.hh | 2 +- src/3rdparty/harfbuzz-ng/src/hb-config.hh | 40 +- src/3rdparty/harfbuzz-ng/src/hb-map.hh | 3 +- src/3rdparty/harfbuzz-ng/src/hb-null.hh | 2 +- .../harfbuzz-ng/src/hb-ot-cff1-table.hh | 4 +- .../harfbuzz-ng/src/hb-ot-cff2-table.hh | 4 +- src/3rdparty/harfbuzz-ng/src/hb-ot-font.cc | 32 +- .../harfbuzz-ng/src/hb-ot-layout-common.hh | 31 +- .../harfbuzz-ng/src/hb-ot-layout-gsubgpos.hh | 48 +- src/3rdparty/harfbuzz-ng/src/hb-ot-layout.cc | 22 +- src/3rdparty/harfbuzz-ng/src/hb-ot-math.cc | 2 +- src/3rdparty/harfbuzz-ng/src/hb-ot-metrics.cc | 2 +- .../harfbuzz-ng/src/hb-ot-shape-normalize.cc | 15 +- .../src/hb-ot-shaper-indic-machine.hh | 14 +- .../harfbuzz-ng/src/hb-ot-var-common.hh | 3 +- .../harfbuzz-ng/src/hb-ot-var-cvar-table.hh | 1 - .../harfbuzz-ng/src/hb-ot-var-gvar-table.hh | 111 ++-- src/3rdparty/harfbuzz-ng/src/hb-set-digest.hh | 12 +- .../harfbuzz-ng/src/hb-subset-accelerator.hh | 2 + .../harfbuzz-ng/src/hb-subset-input.cc | 31 + .../harfbuzz-ng/src/hb-subset-input.hh | 1 + .../src/hb-subset-plan-member-list.hh | 128 +++++ .../harfbuzz-ng/src/hb-subset-plan.cc | 94 +++- .../harfbuzz-ng/src/hb-subset-plan.hh | 88 +-- src/3rdparty/harfbuzz-ng/src/hb-subset.cc | 8 +- src/3rdparty/harfbuzz-ng/src/hb-subset.h | 3 + src/3rdparty/harfbuzz-ng/src/hb-vector.hh | 4 +- src/3rdparty/harfbuzz-ng/src/hb-version.h | 4 +- src/3rdparty/harfbuzz-ng/src/hb.hh | 4 +- src/3rdparty/harfbuzz-ng/src/main.cc | 532 ------------------ src/3rdparty/harfbuzz-ng/src/test.cc | 95 ---- 61 files changed, 984 insertions(+), 1131 deletions(-) create mode 100644 src/3rdparty/harfbuzz-ng/src/hb-subset-plan-member-list.hh delete mode 100644 src/3rdparty/harfbuzz-ng/src/main.cc delete mode 100644 src/3rdparty/harfbuzz-ng/src/test.cc diff --git a/src/3rdparty/harfbuzz-ng/CMakeLists.txt b/src/3rdparty/harfbuzz-ng/CMakeLists.txt index c6dfe80d352..529e47e50ef 100644 --- a/src/3rdparty/harfbuzz-ng/CMakeLists.txt +++ b/src/3rdparty/harfbuzz-ng/CMakeLists.txt @@ -60,6 +60,7 @@ qt_internal_add_3rdparty_library(BundledHarfbuzz src/hb-subset-input.cc src/hb-subset-instancer-solver.cc src/hb-subset-plan.cc + src/hb-subset-plan-member-list.hh src/hb-subset-repacker.cc src/hb-subset-repacker.h src/hb-unicode.cc src/hb-unicode.h src/hb-unicode.hh src/hb-utf.hh diff --git a/src/3rdparty/harfbuzz-ng/NEWS b/src/3rdparty/harfbuzz-ng/NEWS index e53a244f1b3..ff35843192d 100644 --- a/src/3rdparty/harfbuzz-ng/NEWS +++ b/src/3rdparty/harfbuzz-ng/NEWS @@ -1,3 +1,24 @@ +Overview of changes leading to 7.3.0 +Tuesday, May 9, 2023 +==================================== +- Speedup applying glyph variation in VarComposites fonts (over 40% speedup). + (Behdad Esfahbod) +- Speedup instancing some fonts (over 20% speedup in instancing RobotoFlex). + (Behdad Esfahbod) +- Speedup shaping some fonts (over 30% speedup in shaping Roboto). + (Behdad Esfahbod) +- Support subsetting VarComposites and beyond-64k fonts. (Behdad Esfahbod) +- New configuration macro HB_MINIMIZE_MEMORY_USAGE to favor optimizing memory + usage over speed. (Behdad Esfahbod) +- Supporting setting the mapping between old and new glyph indices during + subsetting. (Garret Rieger) +- Various fixes and improvements. + (Behdad Esfahbod, Denis Rochette, Garret Rieger, Han Seung Min, Qunxin Liu) + +- New API: ++hb_subset_input_old_to_new_glyph_mapping() + + Overview of changes leading to 7.2.0 Thursday, April 27, 2023 ==================================== diff --git a/src/3rdparty/harfbuzz-ng/qt_attribution.json b/src/3rdparty/harfbuzz-ng/qt_attribution.json index 6fec976f27f..a372205968b 100644 --- a/src/3rdparty/harfbuzz-ng/qt_attribution.json +++ b/src/3rdparty/harfbuzz-ng/qt_attribution.json @@ -6,7 +6,7 @@ "Description": "HarfBuzz is an OpenType text shaping engine.", "Homepage": "http://harfbuzz.org", - "Version": "7.2.0", + "Version": "7.3.0", "License": "MIT License", "LicenseId": "MIT", "LicenseFile": "COPYING", diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Color/COLR/COLR.hh b/src/3rdparty/harfbuzz-ng/src/OT/Color/COLR/COLR.hh index 191812f48ee..2a479842941 100644 --- a/src/3rdparty/harfbuzz-ng/src/OT/Color/COLR/COLR.hh +++ b/src/3rdparty/harfbuzz-ng/src/OT/Color/COLR/COLR.hh @@ -1514,10 +1514,10 @@ struct ClipBoxFormat2 : Variable value.get_clip_box(clip_box, instancer); if (instancer) { - clip_box.xMin += _hb_roundf (instancer (varIdxBase, 0)); - clip_box.yMin += _hb_roundf (instancer (varIdxBase, 1)); - clip_box.xMax += _hb_roundf (instancer (varIdxBase, 2)); - clip_box.yMax += _hb_roundf (instancer (varIdxBase, 3)); + clip_box.xMin += roundf (instancer (varIdxBase, 0)); + clip_box.yMin += roundf (instancer (varIdxBase, 1)); + clip_box.xMax += roundf (instancer (varIdxBase, 2)); + clip_box.yMax += roundf (instancer (varIdxBase, 3)); } } }; diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/Common/Coverage.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/Common/Coverage.hh index d35654e2457..9ca88f788a9 100644 --- a/src/3rdparty/harfbuzz-ng/src/OT/Layout/Common/Coverage.hh +++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/Common/Coverage.hh @@ -113,22 +113,33 @@ struct Coverage TRACE_SERIALIZE (this); if (unlikely (!c->extend_min (this))) return_trace (false); - unsigned count = 0; + unsigned count = hb_len (glyphs); unsigned num_ranges = 0; hb_codepoint_t last = (hb_codepoint_t) -2; + hb_codepoint_t max = 0; + bool unsorted = false; for (auto g: glyphs) { + if (last != (hb_codepoint_t) -2 && g < last) + unsorted = true; if (last + 1 != g) - num_ranges++; + num_ranges++; last = g; - count++; + if (g > max) max = g; } - u.format = count <= num_ranges * 3 ? 1 : 2; + u.format = !unsorted && count <= num_ranges * 3 ? 1 : 2; #ifndef HB_NO_BEYOND_64K - if (count && last > 0xFFFFu) + if (max > 0xFFFFu) u.format += 2; + if (unlikely (max > 0xFFFFFFu)) +#else + if (unlikely (max > 0xFFFFu)) #endif + { + c->check_success (false, HB_SERIALIZE_ERROR_INT_OVERFLOW); + return_trace (false); + } switch (u.format) { @@ -148,8 +159,8 @@ struct Coverage auto it = + iter () | hb_take (c->plan->source->get_num_glyphs ()) - | hb_filter (c->plan->glyph_map_gsub) | hb_map_retains_sorting (c->plan->glyph_map_gsub) + | hb_filter ([] (hb_codepoint_t glyph) { return glyph != HB_MAP_VALUE_INVALID; }) ; // Cache the iterator result as it will be iterated multiple times diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/Common/CoverageFormat2.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/Common/CoverageFormat2.hh index d7fcc352028..fa501d659d5 100644 --- a/src/3rdparty/harfbuzz-ng/src/OT/Layout/Common/CoverageFormat2.hh +++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/Common/CoverageFormat2.hh @@ -95,19 +95,26 @@ struct CoverageFormat2_4 unsigned count = 0; unsigned range = (unsigned) -1; last = (hb_codepoint_t) -2; + unsigned unsorted = false; for (auto g: glyphs) { if (last + 1 != g) { + if (unlikely (last != (hb_codepoint_t) -2 && last + 1 > g)) + unsorted = true; + range++; - rangeRecord[range].first = g; - rangeRecord[range].value = count; + rangeRecord.arrayZ[range].first = g; + rangeRecord.arrayZ[range].value = count; } - rangeRecord[range].last = g; + rangeRecord.arrayZ[range].last = g; last = g; count++; } + if (unlikely (unsorted)) + rangeRecord.as_array ().qsort (RangeRecord::cmp_range); + return_trace (true); } @@ -185,8 +192,8 @@ struct CoverageFormat2_4 if (__more__ ()) { unsigned int old = coverage; - j = c->rangeRecord[i].first; - coverage = c->rangeRecord[i].value; + j = c->rangeRecord.arrayZ[i].first; + coverage = c->rangeRecord.arrayZ[i].value; if (unlikely (coverage != old + 1)) { /* Broken table. Skip. Important to avoid DoS. diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/Common/RangeRecord.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/Common/RangeRecord.hh index a62629fad34..85aacace9a7 100644 --- a/src/3rdparty/harfbuzz-ng/src/OT/Layout/Common/RangeRecord.hh +++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/Common/RangeRecord.hh @@ -51,6 +51,18 @@ struct RangeRecord int cmp (hb_codepoint_t g) const { return g < first ? -1 : g <= last ? 0 : +1; } + HB_INTERNAL static int cmp_range (const void *pa, const void *pb) { + const RangeRecord *a = (const RangeRecord *) pa; + const RangeRecord *b = (const RangeRecord *) pb; + if (a->first < b->first) return -1; + if (a->first > b->first) return +1; + if (a->last < b->last) return -1; + if (a->last > b->last) return +1; + if (a->value < b->value) return -1; + if (a->value > b->value) return +1; + return 0; + } + unsigned get_population () const { if (unlikely (last < first)) return 0; diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GDEF/GDEF.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GDEF/GDEF.hh index 0551fcf812a..c1ff7961996 100644 --- a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GDEF/GDEF.hh +++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GDEF/GDEF.hh @@ -32,6 +32,7 @@ #include "../../../hb-ot-layout-common.hh" #include "../../../hb-font.hh" +#include "../../../hb-cache.hh" namespace OT { @@ -861,7 +862,30 @@ struct GDEF } ~accelerator_t () { table.destroy (); } + unsigned int get_glyph_props (hb_codepoint_t glyph) const + { + unsigned v; + +#ifndef HB_NO_GDEF_CACHE + if (glyph_props_cache.get (glyph, &v)) + return v; +#endif + + v = table->get_glyph_props (glyph); + +#ifndef HB_NO_GDEF_CACHE + if (likely (table.get_blob ())) // Don't try setting if we are the null instance! + glyph_props_cache.set (glyph, v); +#endif + + return v; + + } + hb_blob_ptr_t table; +#ifndef HB_NO_GDEF_CACHE + mutable hb_cache_t<21, 3, 8> glyph_props_cache; +#endif }; void collect_variation_indices (hb_collect_variation_indices_context_t *c) const diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/CursivePosFormat1.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/CursivePosFormat1.hh index ff255e090a2..b8773ba0aaa 100644 --- a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/CursivePosFormat1.hh +++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/CursivePosFormat1.hh @@ -122,9 +122,9 @@ struct CursivePosFormat1 if (!this_record.entryAnchor) return_trace (false); hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input; - skippy_iter.reset (buffer->idx, 1); + skippy_iter.reset_fast (buffer->idx, 1); unsigned unsafe_from; - if (!skippy_iter.prev (&unsafe_from)) + if (unlikely (!skippy_iter.prev (&unsafe_from))) { buffer->unsafe_to_concat_from_outbuffer (unsafe_from, buffer->idx + 1); return_trace (false); diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/GPOS.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/GPOS.hh index 9493ec987e8..f4af98b25fd 100644 --- a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/GPOS.hh +++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/GPOS.hh @@ -156,7 +156,7 @@ GPOS::position_finish_offsets (hb_font_t *font, hb_buffer_t *buffer) { for (unsigned i = 0; i < len; i++) if (unlikely (pos[i].y_offset)) - pos[i].x_offset += _hb_roundf (font->slant_xy * pos[i].y_offset); + pos[i].x_offset += roundf (font->slant_xy * pos[i].y_offset); } } diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/MarkMarkPosFormat1.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/MarkMarkPosFormat1.hh index fbcebb80441..9dae5ce5dac 100644 --- a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/MarkMarkPosFormat1.hh +++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/MarkMarkPosFormat1.hh @@ -100,16 +100,16 @@ struct MarkMarkPosFormat1_2 /* now we search backwards for a suitable mark glyph until a non-mark glyph */ hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input; - skippy_iter.reset (buffer->idx, 1); + skippy_iter.reset_fast (buffer->idx, 1); skippy_iter.set_lookup_props (c->lookup_props & ~(uint32_t)LookupFlag::IgnoreFlags); unsigned unsafe_from; - if (!skippy_iter.prev (&unsafe_from)) + if (unlikely (!skippy_iter.prev (&unsafe_from))) { buffer->unsafe_to_concat_from_outbuffer (unsafe_from, buffer->idx + 1); return_trace (false); } - if (!_hb_glyph_info_is_mark (&buffer->info[skippy_iter.idx])) + if (likely (!_hb_glyph_info_is_mark (&buffer->info[skippy_iter.idx]))) { buffer->unsafe_to_concat_from_outbuffer (skippy_iter.idx, buffer->idx + 1); return_trace (false); diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/PairPosFormat1.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/PairPosFormat1.hh index 4dada1c8301..714b4bec724 100644 --- a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/PairPosFormat1.hh +++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/PairPosFormat1.hh @@ -110,9 +110,9 @@ struct PairPosFormat1_3 if (likely (index == NOT_COVERED)) return_trace (false); hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input; - skippy_iter.reset (buffer->idx, 1); + skippy_iter.reset_fast (buffer->idx, 1); unsigned unsafe_to; - if (!skippy_iter.next (&unsafe_to)) + if (unlikely (!skippy_iter.next (&unsafe_to))) { buffer->unsafe_to_concat (buffer->idx, unsafe_to); return_trace (false); diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/PairPosFormat2.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/PairPosFormat2.hh index de15a29e3cf..31329dfcb59 100644 --- a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/PairPosFormat2.hh +++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/PairPosFormat2.hh @@ -50,11 +50,10 @@ struct PairPosFormat2_4 unsigned int len1 = valueFormat1.get_len (); unsigned int len2 = valueFormat2.get_len (); unsigned int stride = HBUINT16::static_size * (len1 + len2); - unsigned int record_size = valueFormat1.get_size () + valueFormat2.get_size (); unsigned int count = (unsigned int) class1Count * (unsigned int) class2Count; return_trace (c->check_range ((const void *) values, count, - record_size) && + stride) && valueFormat1.sanitize_values_stride_unsafe (c, this, &values[0], count, stride) && valueFormat2.sanitize_values_stride_unsafe (c, this, &values[len1], count, stride)); } @@ -131,26 +130,32 @@ struct PairPosFormat2_4 if (likely (index == NOT_COVERED)) return_trace (false); hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input; - skippy_iter.reset (buffer->idx, 1); + skippy_iter.reset_fast (buffer->idx, 1); unsigned unsafe_to; - if (!skippy_iter.next (&unsafe_to)) + if (unlikely (!skippy_iter.next (&unsafe_to))) { buffer->unsafe_to_concat (buffer->idx, unsafe_to); return_trace (false); } + unsigned int klass2 = (this+classDef2).get_class (buffer->info[skippy_iter.idx].codepoint); + if (!klass2) + { + buffer->unsafe_to_concat (buffer->idx, skippy_iter.idx + 1); + return_trace (false); + } + + unsigned int klass1 = (this+classDef1).get_class (buffer->cur().codepoint); + if (unlikely (klass1 >= class1Count || klass2 >= class2Count)) + { + buffer->unsafe_to_concat (buffer->idx, skippy_iter.idx + 1); + return_trace (false); + } + unsigned int len1 = valueFormat1.get_len (); unsigned int len2 = valueFormat2.get_len (); unsigned int record_len = len1 + len2; - unsigned int klass1 = (this+classDef1).get_class (buffer->cur().codepoint); - unsigned int klass2 = (this+classDef2).get_class (buffer->info[skippy_iter.idx].codepoint); - if (unlikely (klass1 >= class1Count || klass2 >= class2Count)) - { - buffer->unsafe_to_concat (buffer->idx, skippy_iter.idx + 1); - return_trace (false); - } - const Value *v = &values[record_len * (klass1 * class2Count + klass2)]; bool applied_first = false, applied_second = false; @@ -164,7 +169,7 @@ struct PairPosFormat2_4 * https://github.com/harfbuzz/harfbuzz/pull/3235#issuecomment-1029814978 */ #ifndef HB_SPLIT_KERN - if (0) + if (false) #endif { if (!len2) @@ -224,8 +229,8 @@ struct PairPosFormat2_4 c->buffer->idx, skippy_iter.idx); } - applied_first = valueFormat1.apply_value (c, this, v, buffer->cur_pos()); - applied_second = valueFormat2.apply_value (c, this, v + len1, buffer->pos[skippy_iter.idx]); + applied_first = len1 && valueFormat1.apply_value (c, this, v, buffer->cur_pos()); + applied_second = len2 && valueFormat2.apply_value (c, this, v + len1, buffer->pos[skippy_iter.idx]); if (applied_first || applied_second) if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ()) diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/PairSet.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/PairSet.hh index 147b8e00ea6..9faff49909a 100644 --- a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/PairSet.hh +++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/PairSet.hh @@ -120,8 +120,8 @@ struct PairSet c->buffer->idx, pos); } - bool applied_first = valueFormats[0].apply_value (c, this, &record->values[0], buffer->cur_pos()); - bool applied_second = valueFormats[1].apply_value (c, this, &record->values[len1], buffer->pos[pos]); + bool applied_first = len1 && valueFormats[0].apply_value (c, this, &record->values[0], buffer->cur_pos()); + bool applied_second = len2 && valueFormats[1].apply_value (c, this, &record->values[len1], buffer->pos[pos]); if (applied_first || applied_second) if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ()) diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/Ligature.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/Ligature.hh index 38057cb60c9..8674a52fb52 100644 --- a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/Ligature.hh +++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/Ligature.hh @@ -10,7 +10,7 @@ namespace GSUB_impl { template struct Ligature { - protected: + public: typename Types::HBGlyphID ligGlyph; /* GlyphID of ligature to substitute */ HeadlessArrayOf diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/LigatureSet.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/LigatureSet.hh index 9db25cf567b..0ba262e9017 100644 --- a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/LigatureSet.hh +++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/LigatureSet.hh @@ -72,15 +72,73 @@ struct LigatureSet ; } + static bool match_always (hb_glyph_info_t &info HB_UNUSED, unsigned value HB_UNUSED, const void *data HB_UNUSED) + { + return true; + } + bool apply (hb_ot_apply_context_t *c) const { TRACE_APPLY (this); + unsigned int num_ligs = ligature.len; + +#ifndef HB_NO_OT_LIGATURES_FAST_PATH + if (HB_OPTIMIZE_SIZE_VAL || num_ligs <= 2) +#endif + { + slow: + for (unsigned int i = 0; i < num_ligs; i++) + { + const auto &lig = this+ligature.arrayZ[i]; + if (lig.apply (c)) return_trace (true); + } + return_trace (false); + } + + /* This version is optimized for speed by matching the first component + * of the ligature here, instead of calling into the ligation code. */ + + hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input; + skippy_iter.reset (c->buffer->idx, 1); + skippy_iter.set_match_func (match_always, nullptr); + skippy_iter.set_glyph_data ((HBUINT16 *) nullptr); + unsigned unsafe_to; + hb_codepoint_t first = (unsigned) -1; + bool matched = skippy_iter.next (&unsafe_to); + if (likely (matched)) + { + first = c->buffer->info[skippy_iter.idx].codepoint; + unsafe_to = skippy_iter.idx + 1; + + if (skippy_iter.may_skip (c->buffer->info[skippy_iter.idx])) + { + /* Can't use the fast path if eg. the next char is a default-ignorable + * or other skippable. */ + goto slow; + } + } + + bool unsafe_to_concat = false; + for (unsigned int i = 0; i < num_ligs; i++) { - const auto &lig = this+ligature[i]; - if (lig.apply (c)) return_trace (true); + const auto &lig = this+ligature.arrayZ[i]; + if (unlikely (lig.component.lenP1 <= 1) || + lig.component[1] == first) + { + if (lig.apply (c)) + { + if (unsafe_to_concat) + c->buffer->unsafe_to_concat (c->buffer->idx, unsafe_to); + return_trace (true); + } + } + else if (likely (lig.component.lenP1 > 1)) + unsafe_to_concat = true; } + if (likely (unsafe_to_concat)) + c->buffer->unsafe_to_concat (c->buffer->idx, unsafe_to); return_trace (false); } diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/SingleSubst.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/SingleSubst.hh index 4529927ba6d..181c9e52e5c 100644 --- a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/SingleSubst.hh +++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/SingleSubst.hh @@ -57,7 +57,7 @@ struct SingleSubst #ifndef HB_NO_BEYOND_64K if (+ glyphs - | hb_map_retains_sorting (hb_first) + | hb_map_retains_sorting (hb_second) | hb_filter ([] (hb_codepoint_t gid) { return gid > 0xFFFFu; })) { format += 2; diff --git a/src/3rdparty/harfbuzz-ng/src/OT/glyf/CompositeGlyph.hh b/src/3rdparty/harfbuzz-ng/src/OT/glyf/CompositeGlyph.hh index 94e00d3aea3..d81fadf7c88 100644 --- a/src/3rdparty/harfbuzz-ng/src/OT/glyf/CompositeGlyph.hh +++ b/src/3rdparty/harfbuzz-ng/src/OT/glyf/CompositeGlyph.hh @@ -87,19 +87,42 @@ struct CompositeGlyphRecord } } - void transform_points (contour_point_vector_t &points, + static void transform (const float (&matrix)[4], + hb_array_t points) + { + auto arrayZ = points.arrayZ; + unsigned count = points.length; + + if (matrix[0] != 1.f || matrix[1] != 0.f || + matrix[2] != 0.f || matrix[3] != 1.f) + for (unsigned i = 0; i < count; i++) + arrayZ[i].transform (matrix); + } + + static void translate (const contour_point_t &trans, + hb_array_t points) + { + auto arrayZ = points.arrayZ; + unsigned count = points.length; + + if (trans.x != 0.f || trans.y != 0.f) + for (unsigned i = 0; i < count; i++) + arrayZ[i].translate (trans); + } + + void transform_points (hb_array_t points, const float (&matrix)[4], const contour_point_t &trans) const { if (scaled_offsets ()) { - points.translate (trans); - points.transform (matrix); + translate (trans, points); + transform (matrix, points); } else { - points.transform (matrix); - points.translate (trans); + transform (matrix, points); + translate (trans, points); } } @@ -108,8 +131,9 @@ struct CompositeGlyphRecord float matrix[4]; contour_point_t trans; get_transformation (matrix, trans); + points.alloc (points.length + 4); // For phantom points if (unlikely (!points.resize (points.length + 1))) return false; - points[points.length - 1] = trans; + points.arrayZ[points.length - 1] = trans; return true; } diff --git a/src/3rdparty/harfbuzz-ng/src/OT/glyf/Glyph.hh b/src/3rdparty/harfbuzz-ng/src/OT/glyf/Glyph.hh index 9e15a6e6d03..2bd5fe8206d 100644 --- a/src/3rdparty/harfbuzz-ng/src/OT/glyf/Glyph.hh +++ b/src/3rdparty/harfbuzz-ng/src/OT/glyf/Glyph.hh @@ -155,24 +155,28 @@ struct Glyph { xMin = xMax = all_points[0].x; yMin = yMax = all_points[0].y; + + unsigned count = all_points.length - 4; + for (unsigned i = 1; i < count; i++) + { + float x = all_points[i].x; + float y = all_points[i].y; + xMin = hb_min (xMin, x); + xMax = hb_max (xMax, x); + yMin = hb_min (yMin, y); + yMax = hb_max (yMax, y); + } } - for (unsigned i = 1; i < all_points.length - 4; i++) - { - float x = all_points[i].x; - float y = all_points[i].y; - xMin = hb_min (xMin, x); - xMax = hb_max (xMax, x); - yMin = hb_min (yMin, y); - yMax = hb_max (yMax, y); - } - update_mtx (plan, roundf (xMin), roundf (xMax), roundf (yMin), roundf (yMax), all_points); - - int rounded_xMin = roundf (xMin); - int rounded_xMax = roundf (xMax); - int rounded_yMin = roundf (yMin); - int rounded_yMax = roundf (yMax); + // These are destined for storage in a 16 bit field to clamp the values to + // fit into a 16 bit signed integer. + int rounded_xMin = hb_clamp (roundf (xMin), -32768.0f, 32767.0f); + int rounded_xMax = hb_clamp (roundf (xMax), -32768.0f, 32767.0f); + int rounded_yMin = hb_clamp (roundf (yMin), -32768.0f, 32767.0f); + int rounded_yMax = hb_clamp (roundf (yMax), -32768.0f, 32767.0f); + + update_mtx (plan, rounded_xMin, rounded_xMax, rounded_yMin, rounded_yMax, all_points); if (type != EMPTY) { @@ -295,7 +299,7 @@ struct Glyph if (!edge_count) edge_count = &stack_edge_count; if (unlikely (*edge_count > HB_GLYF_MAX_EDGE_COUNT)) return false; (*edge_count)++; - + if (head_maxp_info) { head_maxp_info->maxComponentDepth = hb_max (head_maxp_info->maxComponentDepth, depth); @@ -305,9 +309,8 @@ struct Glyph coords = hb_array (font->coords, font->num_coords); contour_point_vector_t stack_points; - bool inplace = type == SIMPLE && all_points.length == 0; - /* Load into all_points if it's empty, as an optimization. */ - contour_point_vector_t &points = inplace ? all_points : stack_points; + contour_point_vector_t &points = type == SIMPLE ? all_points : stack_points; + unsigned old_length = points.length; switch (type) { case SIMPLE: @@ -315,7 +318,7 @@ struct Glyph head_maxp_info->maxContours = hb_max (head_maxp_info->maxContours, (unsigned) header->numberOfContours); if (depth > 0 && composite_contours) *composite_contours += (unsigned) header->numberOfContours; - if (unlikely (!SimpleGlyph (*header, bytes).get_contour_points (points, phantom_only))) + if (unlikely (!SimpleGlyph (*header, bytes).get_contour_points (all_points, phantom_only))) return false; break; case COMPOSITE: @@ -329,6 +332,7 @@ struct Glyph { for (auto &item : get_var_composite_iterator ()) if (unlikely (!item.get_points (points))) return false; + break; } #endif case EMPTY: @@ -367,7 +371,7 @@ struct Glyph #ifndef HB_NO_VAR glyf_accelerator.gvar->apply_deltas_to_points (gid, coords, - points.as_array ()); + points.as_array ().sub_array (old_length)); #endif // mainly used by CompositeGlyph calculating new X/Y offset value so no need to extend it @@ -381,21 +385,20 @@ struct Glyph switch (type) { case SIMPLE: if (depth == 0 && head_maxp_info) - head_maxp_info->maxPoints = hb_max (head_maxp_info->maxPoints, points.length - 4); - if (!inplace) - all_points.extend (points.as_array ()); + head_maxp_info->maxPoints = hb_max (head_maxp_info->maxPoints, all_points.length - old_length - 4); break; case COMPOSITE: { - contour_point_vector_t comp_points; unsigned int comp_index = 0; for (auto &item : get_composite_iterator ()) { - comp_points.reset (); - if (unlikely (!glyf_accelerator.glyph_for_gid (item.get_gid ()) + unsigned old_count = all_points.length; + + if (unlikely ((!phantom_only || (use_my_metrics && item.is_use_my_metrics ())) && + !glyf_accelerator.glyph_for_gid (item.get_gid ()) .get_points (font, glyf_accelerator, - comp_points, + all_points, points_with_deltas, head_maxp_info, composite_contours, @@ -407,6 +410,8 @@ struct Glyph edge_count))) return false; + auto comp_points = all_points.as_array ().sub_array (old_count); + /* Copy phantom points from component if USE_MY_METRICS flag set */ if (use_my_metrics && item.is_use_my_metrics ()) for (unsigned int i = 0; i < PHANTOM_COUNT; i++) @@ -429,11 +434,11 @@ struct Glyph delta.init (all_points[p1].x - comp_points[p2].x, all_points[p1].y - comp_points[p2].y); - comp_points.translate (delta); + item.translate (delta, comp_points); } } - all_points.extend (comp_points.as_array ().sub_array (0, comp_points.length - PHANTOM_COUNT)); + all_points.resize (all_points.length - PHANTOM_COUNT); if (all_points.length > HB_GLYF_MAX_POINTS) return false; @@ -453,14 +458,12 @@ struct Glyph #ifndef HB_NO_VAR_COMPOSITES case VAR_COMPOSITE: { - contour_point_vector_t comp_points; hb_array_t points_left = points.as_array (); for (auto &item : get_var_composite_iterator ()) { unsigned item_num_points = item.get_num_points (); hb_array_t record_points = points_left.sub_array (0, item_num_points); - - comp_points.reset (); + assert (record_points.length == item_num_points); auto component_coords = coords; if (item.is_reset_unspecified_axes ()) @@ -469,10 +472,13 @@ struct Glyph coord_setter_t coord_setter (component_coords); item.set_variations (coord_setter, record_points); - if (unlikely (!glyf_accelerator.glyph_for_gid (item.get_gid ()) + unsigned old_count = all_points.length; + + if (unlikely ((!phantom_only || (use_my_metrics && item.is_use_my_metrics ())) && + !glyf_accelerator.glyph_for_gid (item.get_gid ()) .get_points (font, glyf_accelerator, - comp_points, + all_points, points_with_deltas, head_maxp_info, nullptr, @@ -484,15 +490,18 @@ struct Glyph edge_count))) return false; + auto comp_points = all_points.as_array ().sub_array (old_count); + /* Apply component transformation */ - item.transform_points (record_points, comp_points); + if (comp_points) // Empty in case of phantom_only + item.transform_points (record_points, comp_points); /* Copy phantom points from component if USE_MY_METRICS flag set */ if (use_my_metrics && item.is_use_my_metrics ()) for (unsigned int i = 0; i < PHANTOM_COUNT; i++) phantoms[i] = comp_points[comp_points.length - PHANTOM_COUNT + i]; - all_points.extend (comp_points.as_array ().sub_array (0, comp_points.length - PHANTOM_COUNT)); + all_points.resize (all_points.length - PHANTOM_COUNT); if (all_points.length > HB_GLYF_MAX_POINTS) return false; @@ -512,9 +521,10 @@ struct Glyph /* Undocumented rasterizer behavior: * Shift points horizontally by the updated left side bearing */ - contour_point_t delta; - delta.init (-phantoms[PHANTOM_LEFT].x, 0.f); - if (delta.x) all_points.translate (delta); + int v = -phantoms[PHANTOM_LEFT].x; + if (v) + for (auto &point : all_points) + point.x += v; } return !all_points.in_error (); @@ -545,10 +555,11 @@ struct Glyph int num_contours = header->numberOfContours; if (unlikely (num_contours == 0)) type = EMPTY; else if (num_contours > 0) type = SIMPLE; + else if (num_contours == -1) type = COMPOSITE; #ifndef HB_NO_VAR_COMPOSITES else if (num_contours == -2) type = VAR_COMPOSITE; #endif - else type = COMPOSITE; /* negative numbers */ + else type = EMPTY; // Spec deviation; Spec says COMPOSITE, but not seen in the wild. } protected: diff --git a/src/3rdparty/harfbuzz-ng/src/OT/glyf/SimpleGlyph.hh b/src/3rdparty/harfbuzz-ng/src/OT/glyf/SimpleGlyph.hh index b6679b2dae8..555bcee346e 100644 --- a/src/3rdparty/harfbuzz-ng/src/OT/glyf/SimpleGlyph.hh +++ b/src/3rdparty/harfbuzz-ng/src/OT/glyf/SimpleGlyph.hh @@ -124,7 +124,7 @@ struct SimpleGlyph } static bool read_flags (const HBUINT8 *&p /* IN/OUT */, - contour_point_vector_t &points_ /* IN/OUT */, + hb_array_t points_ /* IN/OUT */, const HBUINT8 *end) { unsigned count = points_.length; @@ -146,7 +146,7 @@ struct SimpleGlyph } static bool read_points (const HBUINT8 *&p /* IN/OUT */, - contour_point_vector_t &points_ /* IN/OUT */, + hb_array_t points_ /* IN/OUT */, const HBUINT8 *end, float contour_point_t::*m, const simple_glyph_flag_t short_flag, @@ -157,7 +157,7 @@ struct SimpleGlyph unsigned count = points_.length; for (unsigned i = 0; i < count; i++) { - unsigned flag = points_[i].flag; + unsigned flag = points_.arrayZ[i].flag; if (flag & short_flag) { if (unlikely (p + 1 > end)) return false; @@ -180,18 +180,21 @@ struct SimpleGlyph return true; } - bool get_contour_points (contour_point_vector_t &points_ /* OUT */, + bool get_contour_points (contour_point_vector_t &points /* OUT */, bool phantom_only = false) const { const HBUINT16 *endPtsOfContours = &StructAfter (header); int num_contours = header.numberOfContours; - assert (num_contours); + assert (num_contours > 0); /* One extra item at the end, for the instruction-count below. */ if (unlikely (!bytes.check_range (&endPtsOfContours[num_contours]))) return false; unsigned int num_points = endPtsOfContours[num_contours - 1] + 1; - points_.alloc (num_points + 4, true); // Allocate for phantom points, to avoid a possible copy - if (!points_.resize (num_points)) return false; + unsigned old_length = points.length; + points.alloc (points.length + num_points + 4, true); // Allocate for phantom points, to avoid a possible copy + if (!points.resize (points.length + num_points, false)) return false; + auto points_ = points.as_array ().sub_array (old_length); + hb_memset (points_.arrayZ, 0, sizeof (contour_point_t) * num_points); if (phantom_only) return true; for (int i = 0; i < num_contours; i++) @@ -214,7 +217,7 @@ struct SimpleGlyph } static void encode_coord (int value, - uint8_t &flag, + unsigned &flag, const simple_glyph_flag_t short_flag, const simple_glyph_flag_t same_flag, hb_vector_t &coords /* OUT */) @@ -239,9 +242,9 @@ struct SimpleGlyph } } - static void encode_flag (uint8_t &flag, - uint8_t &repeat, - uint8_t lastflag, + static void encode_flag (unsigned flag, + unsigned &repeat, + unsigned lastflag, hb_vector_t &flags /* OUT */) { if (flag == lastflag && repeat != 255) @@ -262,7 +265,7 @@ struct SimpleGlyph else { repeat = 0; - flags.push (flag); + flags.arrayZ[flags.length++] = flag; } } @@ -282,13 +285,13 @@ struct SimpleGlyph if (unlikely (!x_coords.alloc (2*num_points, true))) return false; if (unlikely (!y_coords.alloc (2*num_points, true))) return false; - uint8_t lastflag = 255, repeat = 0; + unsigned lastflag = 255, repeat = 0; int prev_x = 0, prev_y = 0; for (unsigned i = 0; i < num_points; i++) { - uint8_t flag = all_points.arrayZ[i].flag; - flag &= FLAG_ON_CURVE + FLAG_OVERLAP_SIMPLE; + unsigned flag = all_points.arrayZ[i].flag; + flag &= FLAG_ON_CURVE | FLAG_OVERLAP_SIMPLE | FLAG_CUBIC; int cur_x = roundf (all_points.arrayZ[i].x); int cur_y = roundf (all_points.arrayZ[i].y); diff --git a/src/3rdparty/harfbuzz-ng/src/OT/glyf/VarCompositeGlyph.hh b/src/3rdparty/harfbuzz-ng/src/OT/glyf/VarCompositeGlyph.hh index 309ec473aa2..6dc6fd9ded1 100644 --- a/src/3rdparty/harfbuzz-ng/src/OT/glyf/VarCompositeGlyph.hh +++ b/src/3rdparty/harfbuzz-ng/src/OT/glyf/VarCompositeGlyph.hh @@ -36,24 +36,21 @@ struct VarCompositeGlyphRecord unsigned int get_size () const { + unsigned fl = flags; unsigned int size = min_size; - unsigned axis_width = (flags & AXIS_INDICES_ARE_SHORT) ? 4 : 3; + unsigned axis_width = (fl & AXIS_INDICES_ARE_SHORT) ? 4 : 3; size += numAxes * axis_width; - // gid - size += 2; - if (flags & GID_IS_24BIT) size += 1; + if (fl & GID_IS_24BIT) size += 1; - if (flags & HAVE_TRANSLATE_X) size += 2; - if (flags & HAVE_TRANSLATE_Y) size += 2; - if (flags & HAVE_ROTATION) size += 2; - if (flags & HAVE_SCALE_X) size += 2; - if (flags & HAVE_SCALE_Y) size += 2; - if (flags & HAVE_SKEW_X) size += 2; - if (flags & HAVE_SKEW_Y) size += 2; - if (flags & HAVE_TCENTER_X) size += 2; - if (flags & HAVE_TCENTER_Y) size += 2; + // 2 bytes each for the following flags + fl = fl & (HAVE_TRANSLATE_X | HAVE_TRANSLATE_Y | + HAVE_ROTATION | + HAVE_SCALE_X | HAVE_SCALE_Y | + HAVE_SKEW_X | HAVE_SKEW_Y | + HAVE_TCENTER_X | HAVE_TCENTER_Y); + size += hb_popcount (fl) * 2; return size; } @@ -66,17 +63,17 @@ struct VarCompositeGlyphRecord hb_codepoint_t get_gid () const { if (flags & GID_IS_24BIT) - return StructAfter (numAxes); + return * (const HBGlyphID24 *) &pad; else - return StructAfter (numAxes); + return * (const HBGlyphID16 *) &pad; } void set_gid (hb_codepoint_t gid) { if (flags & GID_IS_24BIT) - StructAfter (numAxes) = gid; + * (HBGlyphID24 *) &pad = gid; else - StructAfter (numAxes) = gid; + * (HBGlyphID16 *) &pad = gid; } unsigned get_numAxes () const @@ -86,26 +83,44 @@ struct VarCompositeGlyphRecord unsigned get_num_points () const { + unsigned fl = flags; unsigned num = 0; - if (flags & AXES_HAVE_VARIATION) num += numAxes; - if (flags & (HAVE_TRANSLATE_X | HAVE_TRANSLATE_Y)) num++; - if (flags & HAVE_ROTATION) num++; - if (flags & (HAVE_SCALE_X | HAVE_SCALE_Y)) num++; - if (flags & (HAVE_SKEW_X | HAVE_SKEW_Y)) num++; - if (flags & (HAVE_TCENTER_X | HAVE_TCENTER_Y)) num++; + if (fl & AXES_HAVE_VARIATION) num += numAxes; + + /* Hopefully faster code, relying on the value of the flags. */ + fl = (((fl & (HAVE_TRANSLATE_Y | HAVE_SCALE_Y | HAVE_SKEW_Y | HAVE_TCENTER_Y)) >> 1) | fl) & + (HAVE_TRANSLATE_X | HAVE_ROTATION | HAVE_SCALE_X | HAVE_SKEW_X | HAVE_TCENTER_X); + num += hb_popcount (fl); + return num; + + /* Slower but more readable code. */ + if (fl & (HAVE_TRANSLATE_X | HAVE_TRANSLATE_Y)) num++; + if (fl & HAVE_ROTATION) num++; + if (fl & (HAVE_SCALE_X | HAVE_SCALE_Y)) num++; + if (fl & (HAVE_SKEW_X | HAVE_SKEW_Y)) num++; + if (fl & (HAVE_TCENTER_X | HAVE_TCENTER_Y)) num++; return num; } - void transform_points (hb_array_t record_points, - contour_point_vector_t &points) const + void transform_points (hb_array_t record_points, + hb_array_t points) const { float matrix[4]; contour_point_t trans; - get_transformation_from_points (record_points, matrix, trans); + get_transformation_from_points (record_points.arrayZ, matrix, trans); - points.transform (matrix); - points.translate (trans); + auto arrayZ = points.arrayZ; + unsigned count = points.length; + + if (matrix[0] != 1.f || matrix[1] != 0.f || + matrix[2] != 0.f || matrix[3] != 1.f) + for (unsigned i = 0; i < count; i++) + arrayZ[i].transform (matrix); + + if (trans.x != 0.f || trans.y != 0.f) + for (unsigned i = 0; i < count; i++) + arrayZ[i].translate (trans); } static inline void transform (float (&matrix)[4], contour_point_t &trans, @@ -136,26 +151,41 @@ struct VarCompositeGlyphRecord static void translate (float (&matrix)[4], contour_point_t &trans, float translateX, float translateY) { - // https://github.com/fonttools/fonttools/blob/f66ee05f71c8b57b5f519ee975e95edcd1466e14/Lib/fontTools/misc/transform.py#L213 - float other[6] = {1.f, 0.f, 0.f, 1.f, translateX, translateY}; - transform (matrix, trans, other); + if (!translateX && !translateY) + return; + + trans.x += matrix[0] * translateX + matrix[2] * translateY; + trans.y += matrix[1] * translateX + matrix[3] * translateY; } static void scale (float (&matrix)[4], contour_point_t &trans, float scaleX, float scaleY) { - // https://github.com/fonttools/fonttools/blob/f66ee05f71c8b57b5f519ee975e95edcd1466e14/Lib/fontTools/misc/transform.py#L224 - float other[6] = {scaleX, 0.f, 0.f, scaleY, 0.f, 0.f}; - transform (matrix, trans, other); + if (scaleX == 1.f && scaleY == 1.f) + return; + + matrix[0] *= scaleX; + matrix[1] *= scaleX; + matrix[2] *= scaleY; + matrix[3] *= scaleY; } static void rotate (float (&matrix)[4], contour_point_t &trans, float rotation) { + if (!rotation) + return; + // https://github.com/fonttools/fonttools/blob/f66ee05f71c8b57b5f519ee975e95edcd1466e14/Lib/fontTools/misc/transform.py#L240 rotation = rotation * HB_PI; - float c = cosf (rotation); - float s = sinf (rotation); + float c; + float s; +#ifdef HAVE_SINCOSF + sincosf (rotation, &s, &c); +#else + c = cosf (rotation); + s = sinf (rotation); +#endif float other[6] = {c, s, -s, c, 0.f, 0.f}; transform (matrix, trans, other); } @@ -163,101 +193,100 @@ struct VarCompositeGlyphRecord static void skew (float (&matrix)[4], contour_point_t &trans, float skewX, float skewY) { + if (!skewX && !skewY) + return; + // https://github.com/fonttools/fonttools/blob/f66ee05f71c8b57b5f519ee975e95edcd1466e14/Lib/fontTools/misc/transform.py#L255 skewX = skewX * HB_PI; skewY = skewY * HB_PI; - float other[6] = {1.f, tanf (skewY), tanf (skewX), 1.f, 0.f, 0.f}; + float other[6] = {1.f, + skewY ? tanf (skewY) : 0.f, + skewX ? tanf (skewX) : 0.f, + 1.f, + 0.f, 0.f}; transform (matrix, trans, other); } bool get_points (contour_point_vector_t &points) const { - float translateX = 0.f; - float translateY = 0.f; - float rotation = 0.f; - float scaleX = 1.f * (1 << 10); - float scaleY = 1.f * (1 << 10); - float skewX = 0.f; - float skewY = 0.f; - float tCenterX = 0.f; - float tCenterY = 0.f; - unsigned num_points = get_num_points (); - if (unlikely (!points.resize (points.length + num_points))) return false; + points.alloc (points.length + num_points + 4); // For phantom points + if (unlikely (!points.resize (points.length + num_points, false))) return false; + contour_point_t *rec_points = points.arrayZ + (points.length - num_points); + memset (rec_points, 0, num_points * sizeof (rec_points[0])); - unsigned axis_width = (flags & AXIS_INDICES_ARE_SHORT) ? 2 : 1; - unsigned axes_size = numAxes * axis_width; + unsigned fl = flags; + + unsigned num_axes = numAxes; + unsigned axis_width = (fl & AXIS_INDICES_ARE_SHORT) ? 2 : 1; + unsigned axes_size = num_axes * axis_width; const F2DOT14 *q = (const F2DOT14 *) (axes_size + - (flags & GID_IS_24BIT ? 3 : 2) + - &StructAfter (numAxes)); + (fl & GID_IS_24BIT ? 3 : 2) + + (const HBUINT8 *) &pad); - hb_array_t rec_points = points.as_array ().sub_array (points.length - num_points); - - unsigned count = numAxes; - if (flags & AXES_HAVE_VARIATION) + unsigned count = num_axes; + if (fl & AXES_HAVE_VARIATION) { for (unsigned i = 0; i < count; i++) - rec_points[i].x = q++->to_int (); - rec_points += count; + rec_points++->x = q++->to_int (); } else q += count; const HBUINT16 *p = (const HBUINT16 *) q; - if (flags & HAVE_TRANSLATE_X) translateX = * (const FWORD *) p++; - if (flags & HAVE_TRANSLATE_Y) translateY = * (const FWORD *) p++; - if (flags & HAVE_ROTATION) rotation = ((const F4DOT12 *) p++)->to_int (); - if (flags & HAVE_SCALE_X) scaleX = ((const F6DOT10 *) p++)->to_int (); - if (flags & HAVE_SCALE_Y) scaleY = ((const F6DOT10 *) p++)->to_int (); - if (flags & HAVE_SKEW_X) skewX = ((const F4DOT12 *) p++)->to_int (); - if (flags & HAVE_SKEW_Y) skewY = ((const F4DOT12 *) p++)->to_int (); - if (flags & HAVE_TCENTER_X) tCenterX = * (const FWORD *) p++; - if (flags & HAVE_TCENTER_Y) tCenterY = * (const FWORD *) p++; - - if ((flags & UNIFORM_SCALE) && !(flags & HAVE_SCALE_Y)) - scaleY = scaleX; - - if (flags & (HAVE_TRANSLATE_X | HAVE_TRANSLATE_Y)) + if (fl & (HAVE_TRANSLATE_X | HAVE_TRANSLATE_Y)) { - rec_points[0].x = translateX; - rec_points[0].y = translateY; + int translateX = (fl & HAVE_TRANSLATE_X) ? * (const FWORD *) p++ : 0; + int translateY = (fl & HAVE_TRANSLATE_Y) ? * (const FWORD *) p++ : 0; + rec_points->x = translateX; + rec_points->y = translateY; rec_points++; } - if (flags & HAVE_ROTATION) + if (fl & HAVE_ROTATION) { - rec_points[0].x = rotation; + int rotation = (fl & HAVE_ROTATION) ? ((const F4DOT12 *) p++)->to_int () : 0; + rec_points->x = rotation; rec_points++; } - if (flags & (HAVE_SCALE_X | HAVE_SCALE_Y)) + if (fl & (HAVE_SCALE_X | HAVE_SCALE_Y)) { - rec_points[0].x = scaleX; - rec_points[0].y = scaleY; + int scaleX = (fl & HAVE_SCALE_X) ? ((const F6DOT10 *) p++)->to_int () : 1 << 10; + int scaleY = (fl & HAVE_SCALE_Y) ? ((const F6DOT10 *) p++)->to_int () : 1 << 10; + if ((fl & UNIFORM_SCALE) && !(fl & HAVE_SCALE_Y)) + scaleY = scaleX; + rec_points->x = scaleX; + rec_points->y = scaleY; rec_points++; } - if (flags & (HAVE_SKEW_X | HAVE_SKEW_Y)) + if (fl & (HAVE_SKEW_X | HAVE_SKEW_Y)) { - rec_points[0].x = skewX; - rec_points[0].y = skewY; + int skewX = (fl & HAVE_SKEW_X) ? ((const F4DOT12 *) p++)->to_int () : 0; + int skewY = (fl & HAVE_SKEW_Y) ? ((const F4DOT12 *) p++)->to_int () : 0; + rec_points->x = skewX; + rec_points->y = skewY; rec_points++; } - if (flags & (HAVE_TCENTER_X | HAVE_TCENTER_Y)) + if (fl & (HAVE_TCENTER_X | HAVE_TCENTER_Y)) { - rec_points[0].x = tCenterX; - rec_points[0].y = tCenterY; + int tCenterX = (fl & HAVE_TCENTER_X) ? * (const FWORD *) p++ : 0; + int tCenterY = (fl & HAVE_TCENTER_Y) ? * (const FWORD *) p++ : 0; + rec_points->x = tCenterX; + rec_points->y = tCenterY; rec_points++; } - assert (!rec_points); return true; } - void get_transformation_from_points (hb_array_t rec_points, + void get_transformation_from_points (const contour_point_t *rec_points, float (&matrix)[4], contour_point_t &trans) const { - if (flags & AXES_HAVE_VARIATION) + unsigned fl = flags; + + if (fl & AXES_HAVE_VARIATION) rec_points += numAxes; matrix[0] = matrix[3] = 1.f; @@ -274,36 +303,35 @@ struct VarCompositeGlyphRecord float tCenterX = 0.f; float tCenterY = 0.f; - if (flags & (HAVE_TRANSLATE_X | HAVE_TRANSLATE_Y)) + if (fl & (HAVE_TRANSLATE_X | HAVE_TRANSLATE_Y)) { - translateX = rec_points[0].x; - translateY = rec_points[0].y; + translateX = rec_points->x; + translateY = rec_points->y; rec_points++; } - if (flags & HAVE_ROTATION) + if (fl & HAVE_ROTATION) { - rotation = rec_points[0].x / (1 << 12); + rotation = rec_points->x / (1 << 12); rec_points++; } - if (flags & (HAVE_SCALE_X | HAVE_SCALE_Y)) + if (fl & (HAVE_SCALE_X | HAVE_SCALE_Y)) { - scaleX = rec_points[0].x / (1 << 10); - scaleY = rec_points[0].y / (1 << 10); + scaleX = rec_points->x / (1 << 10); + scaleY = rec_points->y / (1 << 10); rec_points++; } - if (flags & (HAVE_SKEW_X | HAVE_SKEW_Y)) + if (fl & (HAVE_SKEW_X | HAVE_SKEW_Y)) { - skewX = rec_points[0].x / (1 << 12); - skewY = rec_points[0].y / (1 << 12); + skewX = rec_points->x / (1 << 12); + skewY = rec_points->y / (1 << 12); rec_points++; } - if (flags & (HAVE_TCENTER_X | HAVE_TCENTER_Y)) + if (fl & (HAVE_TCENTER_X | HAVE_TCENTER_Y)) { - tCenterX = rec_points[0].x; - tCenterY = rec_points[0].y; + tCenterX = rec_points->x; + tCenterY = rec_points->y; rec_points++; } - assert (!rec_points); translate (matrix, trans, translateX + tCenterX, translateY + tCenterY); rotate (matrix, trans, rotation); @@ -317,18 +345,19 @@ struct VarCompositeGlyphRecord { bool have_variations = flags & AXES_HAVE_VARIATION; unsigned axis_width = (flags & AXIS_INDICES_ARE_SHORT) ? 2 : 1; + unsigned num_axes = numAxes; const HBUINT8 *p = (const HBUINT8 *) (((HBUINT8 *) &numAxes) + numAxes.static_size + (flags & GID_IS_24BIT ? 3 : 2)); const HBUINT16 *q = (const HBUINT16 *) (((HBUINT8 *) &numAxes) + numAxes.static_size + (flags & GID_IS_24BIT ? 3 : 2)); - const F2DOT14 *a = (const F2DOT14 *) ((HBUINT8 *) (axis_width == 1 ? (p + numAxes) : (HBUINT8 *) (q + numAxes))); + const F2DOT14 *a = (const F2DOT14 *) ((HBUINT8 *) (axis_width == 1 ? (p + num_axes) : (HBUINT8 *) (q + num_axes))); - unsigned count = numAxes; + unsigned count = num_axes; for (unsigned i = 0; i < count; i++) { unsigned axis_index = axis_width == 1 ? (unsigned) *p++ : (unsigned) *q++; - signed v = have_variations ? rec_points[i].x : a++->to_int (); + signed v = have_variations ? rec_points.arrayZ[i].x : a++->to_int (); v = hb_clamp (v, -(1<<14), (1<<14)); setter[axis_index] = v; @@ -338,8 +367,9 @@ struct VarCompositeGlyphRecord protected: HBUINT16 flags; HBUINT8 numAxes; + HBUINT16 pad; public: - DEFINE_SIZE_MIN (3); + DEFINE_SIZE_MIN (5); }; using var_composite_iter_t = composite_iter_tmpl; diff --git a/src/3rdparty/harfbuzz-ng/src/OT/glyf/path-builder.hh b/src/3rdparty/harfbuzz-ng/src/OT/glyf/path-builder.hh index 8916241f76e..f7f732d3363 100644 --- a/src/3rdparty/harfbuzz-ng/src/OT/glyf/path-builder.hh +++ b/src/3rdparty/harfbuzz-ng/src/OT/glyf/path-builder.hh @@ -28,12 +28,8 @@ struct path_builder_t { return optional_point_t (x + t * (p.x - x), y + t * (p.y - y)); } } first_oncurve, first_offcurve, first_offcurve2, last_offcurve, last_offcurve2; - path_builder_t (hb_font_t *font_, hb_draw_session_t &draw_session_) - { - font = font_; - draw_session = &draw_session_; - first_oncurve = first_offcurve = first_offcurve2 = last_offcurve = last_offcurve2 = optional_point_t (); - } + path_builder_t (hb_font_t *font_, hb_draw_session_t &draw_session_) : + font (font_), draw_session (&draw_session_) {} /* based on https://github.com/RazrFalcon/ttf-parser/blob/4f32821/src/glyf.rs#L287 See also: diff --git a/src/3rdparty/harfbuzz-ng/src/graph/graph.hh b/src/3rdparty/harfbuzz-ng/src/graph/graph.hh index 38ca5db0961..294a9999185 100644 --- a/src/3rdparty/harfbuzz-ng/src/graph/graph.hh +++ b/src/3rdparty/harfbuzz-ng/src/graph/graph.hh @@ -173,9 +173,10 @@ struct graph_t void remove_parent (unsigned parent_index) { - for (unsigned i = 0; i < parents.length; i++) + unsigned count = parents.length; + for (unsigned i = 0; i < count; i++) { - if (parents[i] != parent_index) continue; + if (parents.arrayZ[i] != parent_index) continue; parents.remove_unordered (i); break; } @@ -183,7 +184,8 @@ struct graph_t void remove_real_link (unsigned child_index, const void* offset) { - for (unsigned i = 0; i < obj.real_links.length; i++) + unsigned count = obj.real_links.length; + for (unsigned i = 0; i < count; i++) { auto& link = obj.real_links.arrayZ[i]; if (link.objidx != child_index) @@ -199,16 +201,18 @@ struct graph_t void remap_parents (const hb_vector_t& id_map) { - for (unsigned i = 0; i < parents.length; i++) - parents[i] = id_map[parents[i]]; + unsigned count = parents.length; + for (unsigned i = 0; i < count; i++) + parents.arrayZ[i] = id_map[parents.arrayZ[i]]; } void remap_parent (unsigned old_index, unsigned new_index) { - for (unsigned i = 0; i < parents.length; i++) + unsigned count = parents.length; + for (unsigned i = 0; i < count; i++) { - if (parents[i] == old_index) - parents[i] = new_index; + if (parents.arrayZ[i] == old_index) + parents.arrayZ[i] = new_index; } } @@ -328,11 +332,12 @@ struct graph_t bool removed_nil = false; vertices_.alloc (objects.length); vertices_scratch_.alloc (objects.length); - for (unsigned i = 0; i < objects.length; i++) + unsigned count = objects.length; + for (unsigned i = 0; i < count; i++) { // If this graph came from a serialization buffer object 0 is the // nil object. We don't need it for our purposes here so drop it. - if (i == 0 && !objects[i]) + if (i == 0 && !objects.arrayZ[i]) { removed_nil = true; continue; @@ -340,9 +345,9 @@ struct graph_t vertex_t* v = vertices_.push (); if (check_success (!vertices_.in_error ())) - v->obj = *objects[i]; + v->obj = *objects.arrayZ[i]; - check_success (v->link_positions_valid (objects.length, removed_nil)); + check_success (v->link_positions_valid (count, removed_nil)); if (!removed_nil) continue; // Fix indices to account for removed nil object. @@ -579,8 +584,8 @@ struct graph_t const auto& node = object (node_idx); if (offset < node.head || offset >= node.tail) return -1; - unsigned length = node.real_links.length; - for (unsigned i = 0; i < length; i++) + unsigned count = node.real_links.length; + for (unsigned i = 0; i < count; i++) { // Use direct access for increased performance, this is a hot method. const auto& link = node.real_links.arrayZ[i]; @@ -1135,8 +1140,9 @@ struct graph_t size_t total_size_in_bytes () const { size_t total_size = 0; - for (unsigned i = 0; i < vertices_.length; i++) { - size_t size = vertices_[i].obj.tail - vertices_[i].obj.head; + unsigned count = vertices_.length; + for (unsigned i = 0; i < count; i++) { + size_t size = vertices_.arrayZ[i].obj.tail - vertices_.arrayZ[i].obj.head; total_size += size; } return total_size; @@ -1183,21 +1189,23 @@ struct graph_t { if (!parents_invalid) return; - for (unsigned i = 0; i < vertices_.length; i++) - vertices_[i].parents.reset (); + unsigned count = vertices_.length; - for (unsigned p = 0; p < vertices_.length; p++) + for (unsigned i = 0; i < count; i++) + vertices_.arrayZ[i].parents.reset (); + + for (unsigned p = 0; p < count; p++) { - for (auto& l : vertices_[p].obj.all_links ()) + for (auto& l : vertices_.arrayZ[p].obj.all_links ()) { vertices_[l.objidx].parents.push (p); } } - for (unsigned i = 0; i < vertices_.length; i++) + for (unsigned i = 0; i < count; i++) // parents arrays must be accurate or downstream operations like cycle detection // and sorting won't work correctly. - check_success (!vertices_[i].parents.in_error ()); + check_success (!vertices_.arrayZ[i].parents.in_error ()); parents_invalid = false; } @@ -1239,12 +1247,13 @@ struct graph_t // According to https://www3.cs.stonybrook.edu/~rezaul/papers/TR-07-54.pdf // for practical performance this is faster then using a more advanced queue // (such as a fibonacci queue) with a fast decrease priority. - for (unsigned i = 0; i < vertices_.length; i++) + unsigned count = vertices_.length; + for (unsigned i = 0; i < count; i++) { if (i == vertices_.length - 1) - vertices_[i].distance = 0; + vertices_.arrayZ[i].distance = 0; else - vertices_[i].distance = hb_int_max (int64_t); + vertices_.arrayZ[i].distance = hb_int_max (int64_t); } hb_priority_queue_t queue; @@ -1332,10 +1341,11 @@ struct graph_t void remap_all_obj_indices (const hb_vector_t& id_map, hb_vector_t* sorted_graph) const { - for (unsigned i = 0; i < sorted_graph->length; i++) + unsigned count = sorted_graph->length; + for (unsigned i = 0; i < count; i++) { (*sorted_graph)[i].remap_parents (id_map); - for (auto& link : (*sorted_graph)[i].obj.all_links_writer ()) + for (auto& link : sorted_graph->arrayZ[i].obj.all_links_writer ()) { link.objidx = id_map[link.objidx]; } diff --git a/src/3rdparty/harfbuzz-ng/src/graph/markbasepos-graph.hh b/src/3rdparty/harfbuzz-ng/src/graph/markbasepos-graph.hh index 84ef5f71b93..5e9d5aea3a5 100644 --- a/src/3rdparty/harfbuzz-ng/src/graph/markbasepos-graph.hh +++ b/src/3rdparty/harfbuzz-ng/src/graph/markbasepos-graph.hh @@ -319,7 +319,8 @@ struct MarkBasePosFormat1 : public OT::Layout::GPOS_impl::MarkBasePosFormat1_2 class_to_info; unsigned class_count= classCount; - class_to_info.resize (class_count); + if (!class_to_info.resize (class_count)) + return hb_vector_t(); auto mark_array = c.graph.as_table (this_index, &markArray); if (!mark_array) return hb_vector_t (); @@ -327,6 +328,7 @@ struct MarkBasePosFormat1 : public OT::Layout::GPOS_impl::MarkBasePosFormat1_2= class_count) continue; class_to_info[klass].marks.add (mark); } @@ -335,6 +337,7 @@ struct MarkBasePosFormat1 : public OT::Layout::GPOS_impl::MarkBasePosFormat1_2= class_count) continue; class_to_info[klass].child_indices.push (link.objidx); } diff --git a/src/3rdparty/harfbuzz-ng/src/graph/serialize.hh b/src/3rdparty/harfbuzz-ng/src/graph/serialize.hh index 040fd1de5fd..2e0b845baa9 100644 --- a/src/3rdparty/harfbuzz-ng/src/graph/serialize.hh +++ b/src/3rdparty/harfbuzz-ng/src/graph/serialize.hh @@ -116,10 +116,10 @@ will_overflow (graph_t& graph, for (int parent_idx = vertices.length - 1; parent_idx >= 0; parent_idx--) { // Don't need to check virtual links for overflow - for (const auto& link : vertices[parent_idx].obj.real_links) + for (const auto& link : vertices.arrayZ[parent_idx].obj.real_links) { int64_t offset = compute_offset (graph, parent_idx, link); - if (is_valid_offset (offset, link)) + if (likely (is_valid_offset (offset, link))) continue; if (!overflows) return true; diff --git a/src/3rdparty/harfbuzz-ng/src/hb-aat-layout.cc b/src/3rdparty/harfbuzz-ng/src/hb-aat-layout.cc index c9147ff73b1..5e4cea22249 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-aat-layout.cc +++ b/src/3rdparty/harfbuzz-ng/src/hb-aat-layout.cc @@ -55,7 +55,13 @@ AAT::hb_aat_apply_context_t::hb_aat_apply_context_t (const hb_ot_shape_plan_t *p buffer (buffer_), sanitizer (), ankr_table (&Null (AAT::ankr)), - gdef_table (face->table.GDEF->table), + gdef_table ( +#ifndef HB_NO_OT_LAYOUT + face->table.GDEF->table +#else + &Null (GDEF) +#endif + ), lookup_index (0) { sanitizer.init (blob); diff --git a/src/3rdparty/harfbuzz-ng/src/hb-algs.hh b/src/3rdparty/harfbuzz-ng/src/hb-algs.hh index 13587eac017..da383e050a9 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-algs.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-algs.hh @@ -626,8 +626,10 @@ hb_popcount (T v) if (sizeof (T) == 8) { - unsigned int shift = 32; - return hb_popcount ((uint32_t) v) + hb_popcount ((uint32_t) (v >> shift)); + uint64_t y = (uint64_t) v; + y -= ((y >> 1) & 0x5555555555555555ull); + y = (y & 0x3333333333333333ull) + (y >> 2 & 0x3333333333333333ull); + return ((y + (y >> 4)) & 0xf0f0f0f0f0f0f0full) * 0x101010101010101ull >> 56; } if (sizeof (T) == 16) diff --git a/src/3rdparty/harfbuzz-ng/src/hb-array.hh b/src/3rdparty/harfbuzz-ng/src/hb-array.hh index e82c081535e..1a22e15c0fb 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-array.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-array.hh @@ -122,9 +122,13 @@ struct hb_array_t : hb_iter_with_fallback_t, Type&> uint32_t hash () const { - uint32_t current = 0; + // FNV-1a hash function + uint32_t current = /*cbf29ce4*/0x84222325; for (auto &v : *this) - current = current * 31 + hb_hash (v); + { + current = current ^ hb_hash (v); + current = current * 16777619; + } return current; } @@ -452,36 +456,50 @@ inline bool hb_array_t::operator == (const hb_array_t inline uint32_t hb_array_t::hash () const { - uint32_t current = 0; + // FNV-1a hash function + uint32_t current = /*cbf29ce4*/0x84222325; unsigned i = 0; #if defined(__OPTIMIZE__) && !defined(HB_NO_PACKED) && \ ((defined(__GNUC__) && __GNUC__ >= 5) || defined(__clang__)) struct __attribute__((packed)) packed_uint32_t { uint32_t v; }; for (; i + 4 <= this->length; i += 4) - current = current * 31 + hb_hash ((uint32_t) ((packed_uint32_t *) &this->arrayZ[i])->v); + { + current = current ^ hb_hash ((uint32_t) ((const packed_uint32_t *) &this->arrayZ[i])->v); + current = current * 16777619; + } #endif for (; i < this->length; i++) - current = current * 31 + hb_hash (this->arrayZ[i]); + { + current = current ^ hb_hash (this->arrayZ[i]); + current = current * 16777619; + } return current; } template <> inline uint32_t hb_array_t::hash () const { - uint32_t current = 0; + // FNV-1a hash function + uint32_t current = /*cbf29ce4*/0x84222325; unsigned i = 0; #if defined(__OPTIMIZE__) && !defined(HB_NO_PACKED) && \ ((defined(__GNUC__) && __GNUC__ >= 5) || defined(__clang__)) struct __attribute__((packed)) packed_uint32_t { uint32_t v; }; for (; i + 4 <= this->length; i += 4) - current = current * 31 + hb_hash ((uint32_t) ((packed_uint32_t *) &this->arrayZ[i])->v); + { + current = current ^ hb_hash ((uint32_t) ((const packed_uint32_t *) &this->arrayZ[i])->v); + current = current * 16777619; + } #endif for (; i < this->length; i++) - current = current * 31 + hb_hash (this->arrayZ[i]); + { + current = current ^ hb_hash (this->arrayZ[i]); + current = current * 16777619; + } return current; } diff --git a/src/3rdparty/harfbuzz-ng/src/hb-bit-set.hh b/src/3rdparty/harfbuzz-ng/src/hb-bit-set.hh index c30b2af7b0d..d290f6114cf 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-bit-set.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-bit-set.hh @@ -402,7 +402,6 @@ struct hb_bit_set_t uint32_t spm = page_map[spi].major; uint32_t lpm = larger_set.page_map[lpi].major; auto sp = page_at (spi); - auto lp = larger_set.page_at (lpi); if (spm < lpm && !sp.is_empty ()) return false; @@ -410,6 +409,7 @@ struct hb_bit_set_t if (lpm < spm) continue; + auto lp = larger_set.page_at (lpi); if (!sp.is_subset (lp)) return false; @@ -623,6 +623,7 @@ struct hb_bit_set_t *codepoint = INVALID; return false; } + last_page_lookup = i; } const auto* pages_array = pages.arrayZ; @@ -632,7 +633,6 @@ struct hb_bit_set_t if (pages_array[current.index].next (codepoint)) { *codepoint += current.major * page_t::PAGE_BITS; - last_page_lookup = i; return true; } i++; @@ -649,7 +649,6 @@ struct hb_bit_set_t return true; } } - last_page_lookup = 0; *codepoint = INVALID; return false; } @@ -921,7 +920,7 @@ struct hb_bit_set_t memmove (page_map.arrayZ + i + 1, page_map.arrayZ + i, (page_map.length - 1 - i) * page_map.item_size); - page_map[i] = map; + page_map.arrayZ[i] = map; } last_page_lookup = i; diff --git a/src/3rdparty/harfbuzz-ng/src/hb-buffer.cc b/src/3rdparty/harfbuzz-ng/src/hb-buffer.cc index 616cee807f6..ace2a104fd0 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-buffer.cc +++ b/src/3rdparty/harfbuzz-ng/src/hb-buffer.cc @@ -268,7 +268,7 @@ hb_buffer_t::similar (const hb_buffer_t &src) unicode = hb_unicode_funcs_reference (src.unicode); flags = src.flags; cluster_level = src.cluster_level; - replacement = src.invisible; + replacement = src.replacement; invisible = src.invisible; not_found = src.not_found; } diff --git a/src/3rdparty/harfbuzz-ng/src/hb-buffer.hh b/src/3rdparty/harfbuzz-ng/src/hb-buffer.hh index 5a43cabcb75..7a97fc71688 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-buffer.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-buffer.hh @@ -553,7 +553,7 @@ struct hb_buffer_t bool message (hb_font_t *font, const char *fmt, ...) HB_PRINTF_FUNC(3, 4) { #ifdef HB_NO_BUFFER_MESSAGE - return true; + return true; #else if (likely (!messaging ())) return true; diff --git a/src/3rdparty/harfbuzz-ng/src/hb-config.hh b/src/3rdparty/harfbuzz-ng/src/hb-config.hh index 52adaad4384..26f7cba83e2 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-config.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-config.hh @@ -44,14 +44,14 @@ #ifdef HB_TINY #define HB_LEAN #define HB_MINI +#define HB_OPTIMIZE_SIZE +#define HB_OPTIMIZE_SIZE_MORE +#define HB_MINIMIZE_MEMORY_USAGE #define HB_NO_MT #define HB_NO_UCD_UNASSIGNED #ifndef NDEBUG #define NDEBUG #endif -#ifndef __OPTIMIZE_SIZE__ -#define __OPTIMIZE_SIZE__ -#endif #endif #ifdef HB_LEAN @@ -97,6 +97,12 @@ #define HB_NO_BORING_EXPANSION #endif +#ifdef __OPTIMIZE_SIZE__ +#ifndef HB_OPTIMIZE_SIZE +#define HB_OPTIMIZE_SIZE +#endif +#endif + #if defined(HAVE_CONFIG_OVERRIDE_H) || defined(HB_CONFIG_OVERRIDE_H) #ifndef HB_CONFIG_OVERRIDE_H #define HB_CONFIG_OVERRIDE_H "config-override.h" @@ -107,8 +113,10 @@ /* Closure of options. */ #ifdef HB_NO_BORING_EXPANSION -#define HB_NO_BEYOND_64K #define HB_NO_AVAR2 +#define HB_NO_BEYOND_64K +#define HB_NO_CUBIC_GLYF +#define HB_NO_VAR_COMPOSITES #endif #ifdef HB_DISABLE_DEPRECATED @@ -175,21 +183,27 @@ #define HB_NO_OT_SHAPER_MYANMAR_ZAWGYI #endif -#ifdef NDEBUG -#ifndef HB_NDEBUG -#define HB_NDEBUG -#endif +#ifdef HB_OPTIMIZE_SIZE_MORE +#define HB_NO_OT_LIGATURES_FAST_PATH #endif -#ifdef __OPTIMIZE_SIZE__ -#ifndef HB_OPTIMIZE_SIZE -#define HB_OPTIMIZE_SIZE -#endif +#ifdef HB_MINIMIZE_MEMORY_USAGE +#define HB_NO_GDEF_CACHE +#define HB_NO_OT_LAYOUT_LOOKUP_CACHE +#define HB_NO_OT_FONT_ADVANCE_CACHE +#define HB_NO_OT_FONT_CMAP_CACHE #endif #ifdef HB_OPTIMIZE_SIZE -#define HB_NO_OT_LAYOUT_LOOKUP_CACHE +#define HB_OPTIMIZE_SIZE_VAL 1 +#else +#define HB_OPTIMIZE_SIZE_VAL 0 #endif +#ifdef HB_MINIMIZE_MEMORY_USAGE +#define HB_MINIMIZE_MEMORY_USAGE_VAL 1 +#else +#define HB_MINIMIZE_MEMORY_USAGE_VAL 0 +#endif #endif /* HB_CONFIG_HH */ diff --git a/src/3rdparty/harfbuzz-ng/src/hb-map.hh b/src/3rdparty/harfbuzz-ng/src/hb-map.hh index 041b8829afb..c685a9a3e13 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-map.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-map.hh @@ -401,7 +401,8 @@ struct hb_hashmap_t unsigned int tombstone = (unsigned) -1; while (items[i].is_used ()) { - if (items[i].hash == hash && items[i] == key) + if ((hb_is_same (K, hb_codepoint_t) || items[i].hash == hash) && + items[i] == key) return items[i]; if (tombstone == (unsigned) -1 && items[i].is_tombstone ()) tombstone = i; diff --git a/src/3rdparty/harfbuzz-ng/src/hb-null.hh b/src/3rdparty/harfbuzz-ng/src/hb-null.hh index 0d7f4da79e7..3da2d75ef5e 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-null.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-null.hh @@ -37,7 +37,7 @@ /* Global nul-content Null pool. Enlarge as necessary. */ -#define HB_NULL_POOL_SIZE 448 +#define HB_NULL_POOL_SIZE 520 template struct _hb_has_min_size : hb_false_type {}; diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-cff1-table.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-cff1-table.hh index f461a230449..4d0a965eee9 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-ot-cff1-table.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-cff1-table.hh @@ -44,7 +44,7 @@ namespace CFF { * CFF -- Compact Font Format (CFF) * https://www.adobe.com/content/dam/acom/en/devnet/font/pdfs/5176.CFF.pdf */ -#define HB_OT_TAG_cff1 HB_TAG('C','F','F',' ') +#define HB_OT_TAG_CFF1 HB_TAG('C','F','F',' ') #define CFF_UNDEF_SID CFF_UNDEF_CODE @@ -1019,7 +1019,7 @@ using namespace CFF; struct cff1 { - static constexpr hb_tag_t tableTag = HB_OT_TAG_cff1; + static constexpr hb_tag_t tableTag = HB_OT_TAG_CFF1; bool sanitize (hb_sanitize_context_t *c) const { diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-cff2-table.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-cff2-table.hh index b9a8819ab85..2134d486603 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-ot-cff2-table.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-cff2-table.hh @@ -38,7 +38,7 @@ namespace CFF { * CFF2 -- Compact Font Format (CFF) Version 2 * https://docs.microsoft.com/en-us/typography/opentype/spec/cff2 */ -#define HB_OT_TAG_cff2 HB_TAG('C','F','F','2') +#define HB_OT_TAG_CFF2 HB_TAG('C','F','F','2') typedef CFFIndex CFF2Index; template struct CFF2IndexOf : CFFIndexOf {}; @@ -379,7 +379,7 @@ using namespace CFF; struct cff2 { - static constexpr hb_tag_t tableTag = HB_OT_TAG_cff2; + static constexpr hb_tag_t tableTag = HB_OT_TAG_CFF2; bool sanitize (hb_sanitize_context_t *c) const { diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-font.cc b/src/3rdparty/harfbuzz-ng/src/hb-ot-font.cc index 06f7092a59d..c89a1954a98 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-ot-font.cc +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-font.cc @@ -64,13 +64,17 @@ using hb_ot_font_cmap_cache_t = hb_cache_t<21, 16, 8, true>; using hb_ot_font_advance_cache_t = hb_cache_t<24, 16, 8, true>; +#ifndef HB_NO_OT_FONT_CMAP_CACHE static hb_user_data_key_t hb_ot_font_cmap_cache_user_data_key; +#endif struct hb_ot_font_t { const hb_ot_face_t *ot_face; +#ifndef HB_NO_OT_FONT_CMAP_CACHE hb_ot_font_cmap_cache_t *cmap_cache; +#endif /* h_advance caching */ mutable hb_atomic_int_t cached_coords_serial; @@ -86,6 +90,7 @@ _hb_ot_font_create (hb_font_t *font) ot_font->ot_face = &font->face->table; +#ifndef HB_NO_OT_FONT_CMAP_CACHE // retry: auto *cmap_cache = (hb_ot_font_cmap_cache_t *) hb_face_get_user_data (font->face, &hb_ot_font_cmap_cache_user_data_key); @@ -112,6 +117,7 @@ _hb_ot_font_create (hb_font_t *font) } out: ot_font->cmap_cache = cmap_cache; +#endif return ot_font; } @@ -136,7 +142,11 @@ hb_ot_get_nominal_glyph (hb_font_t *font HB_UNUSED, { const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data; const hb_ot_face_t *ot_face = ot_font->ot_face; - return ot_face->cmap->get_nominal_glyph (unicode, glyph, ot_font->cmap_cache); + hb_ot_font_cmap_cache_t *cmap_cache = nullptr; +#ifndef HB_NO_OT_FONT_CMAP_CACHE + cmap_cache = ot_font->cmap_cache; +#endif + return ot_face->cmap->get_nominal_glyph (unicode, glyph, cmap_cache); } static unsigned int @@ -151,10 +161,14 @@ hb_ot_get_nominal_glyphs (hb_font_t *font HB_UNUSED, { const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data; const hb_ot_face_t *ot_face = ot_font->ot_face; + hb_ot_font_cmap_cache_t *cmap_cache = nullptr; +#ifndef HB_NO_OT_FONT_CMAP_CACHE + cmap_cache = ot_font->cmap_cache; +#endif return ot_face->cmap->get_nominal_glyphs (count, first_unicode, unicode_stride, first_glyph, glyph_stride, - ot_font->cmap_cache); + cmap_cache); } static hb_bool_t @@ -167,9 +181,13 @@ hb_ot_get_variation_glyph (hb_font_t *font HB_UNUSED, { const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data; const hb_ot_face_t *ot_face = ot_font->ot_face; + hb_ot_font_cmap_cache_t *cmap_cache = nullptr; +#ifndef HB_NO_OT_FONT_CMAP_CACHE + cmap_cache = ot_font->cmap_cache; +#endif return ot_face->cmap->get_variation_glyph (unicode, variation_selector, glyph, - ot_font->cmap_cache); + cmap_cache); } static void @@ -188,7 +206,7 @@ hb_ot_get_glyph_h_advances (hb_font_t* font, void* font_data, hb_position_t *orig_first_advance = first_advance; -#ifndef HB_NO_VAR +#if !defined(HB_NO_VAR) && !defined(HB_NO_OT_FONT_ADVANCE_CACHE) const OT::HVAR &HVAR = *hmtx.var_table; const OT::VariationStore &varStore = &HVAR + HVAR.varStore; OT::VariationStore::cache_t *varStore_cache = font->num_coords * count >= 128 ? varStore.create_cache () : nullptr; @@ -258,7 +276,7 @@ hb_ot_get_glyph_h_advances (hb_font_t* font, void* font_data, } } -#ifndef HB_NO_VAR +#if !defined(HB_NO_VAR) && !defined(HB_NO_OT_FONT_ADVANCE_CACHE) OT::VariationStore::destroy_cache (varStore_cache); #endif @@ -293,7 +311,7 @@ hb_ot_get_glyph_v_advances (hb_font_t* font, void* font_data, if (vmtx.has_data ()) { -#ifndef HB_NO_VAR +#if !defined(HB_NO_VAR) && !defined(HB_NO_OT_FONT_ADVANCE_CACHE) const OT::VVAR &VVAR = *vmtx.var_table; const OT::VariationStore &varStore = &VVAR + VVAR.varStore; OT::VariationStore::cache_t *varStore_cache = font->num_coords ? varStore.create_cache () : nullptr; @@ -308,7 +326,7 @@ hb_ot_get_glyph_v_advances (hb_font_t* font, void* font_data, first_advance = &StructAtOffsetUnaligned (first_advance, advance_stride); } -#ifndef HB_NO_VAR +#if !defined(HB_NO_VAR) && !defined(HB_NO_OT_FONT_ADVANCE_CACHE) OT::VariationStore::destroy_cache (varStore_cache); #endif } diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-common.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-common.hh index 52b7dc254bb..36f123b559b 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-common.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-common.hh @@ -189,7 +189,7 @@ struct hb_collect_variation_indices_context_t : hb_set_t *layout_variation_indices; hb_hashmap_t> *varidx_delta_map; - hb_font_t *font; + hb_vector_t *normalized_coords; const VariationStore *var_store; const hb_set_t *glyph_set; const hb_map_t *gpos_lookups; @@ -197,14 +197,14 @@ struct hb_collect_variation_indices_context_t : hb_collect_variation_indices_context_t (hb_set_t *layout_variation_indices_, hb_hashmap_t> *varidx_delta_map_, - hb_font_t *font_, + hb_vector_t *normalized_coords_, const VariationStore *var_store_, const hb_set_t *glyph_set_, const hb_map_t *gpos_lookups_, float *store_cache_) : layout_variation_indices (layout_variation_indices_), varidx_delta_map (varidx_delta_map_), - font (font_), + normalized_coords (normalized_coords_), var_store (var_store_), glyph_set (glyph_set_), gpos_lookups (gpos_lookups_), @@ -1769,6 +1769,7 @@ struct ClassDefFormat2_4 return_trace (true); } + unsigned unsorted = false; unsigned num_ranges = 1; hb_codepoint_t prev_gid = (*it).first; unsigned prev_klass = (*it).second; @@ -1789,6 +1790,10 @@ struct ClassDefFormat2_4 if (cur_gid != prev_gid + 1 || cur_klass != prev_klass) { + + if (unlikely (cur_gid < prev_gid)) + unsorted = true; + if (unlikely (!record)) break; record->last = prev_gid; num_ranges++; @@ -1804,8 +1809,14 @@ struct ClassDefFormat2_4 prev_gid = cur_gid; } + if (unlikely (c->in_error ())) return_trace (false); + if (likely (record)) record->last = prev_gid; rangeRecord.len = num_ranges; + + if (unlikely (unsorted)) + rangeRecord.as_array ().qsort (RangeRecord::cmp_range); + return_trace (true); } @@ -2097,8 +2108,15 @@ struct ClassDef #ifndef HB_NO_BEYOND_64K if (glyph_max > 0xFFFFu) - format += 2; + u.format += 2; + if (unlikely (glyph_max > 0xFFFFFFu)) +#else + if (unlikely (glyph_max > 0xFFFFu)) #endif + { + c->check_success (false, HB_SERIALIZE_ERROR_INT_OVERFLOW); + return_trace (false); + } u.format = format; @@ -3547,8 +3565,9 @@ struct VariationDevice { c->layout_variation_indices->add (varIdx); int delta = 0; - if (c->font && c->var_store) - delta = roundf (get_delta (c->font, *c->var_store, c->store_cache)); + if (c->normalized_coords && c->var_store) + delta = roundf (c->var_store->get_delta (varIdx, c->normalized_coords->arrayZ, + c->normalized_coords->length, c->store_cache)); /* set new varidx to HB_OT_LAYOUT_NO_VARIATIONS_INDEX here, will remap * varidx later*/ diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-gsubgpos.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-gsubgpos.hh index e1b66a199a3..8e5be92d12e 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-gsubgpos.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-gsubgpos.hh @@ -476,6 +476,7 @@ struct hb_ot_apply_context_t : void init (hb_ot_apply_context_t *c_, bool context_match = false) { c = c_; + end = c->buffer->len; match_glyph_data16 = nullptr; #ifndef HB_NO_BEYOND_64K match_glyph_data24 = nullptr; @@ -489,6 +490,7 @@ struct hb_ot_apply_context_t : matcher.set_mask (context_match ? -1 : c->lookup_mask); /* Per syllable matching is only for GSUB. */ matcher.set_per_syllable (c->table_index == 0 && c->per_syllable); + matcher.set_syllable (0); } void set_lookup_props (unsigned int lookup_props) { @@ -523,6 +525,14 @@ struct hb_ot_apply_context_t : matcher.set_syllable (start_index_ == c->buffer->idx ? c->buffer->cur().syllable () : 0); } + void reset_fast (unsigned int start_index_, + unsigned int num_items_) + { + // Doesn't set end or syllable. Used by GPOS which doesn't care / change. + idx = start_index_; + num_items = num_items_; + } + void reject () { num_items++; @@ -695,6 +705,7 @@ struct hb_ot_apply_context_t : hb_buffer_t *buffer; recurse_func_t recurse_func = nullptr; const GDEF &gdef; + const GDEF::accelerator_t &gdef_accel; const VariationStore &var_store; VariationStore::cache_t *var_store_cache; hb_set_digest_t digest; @@ -726,6 +737,13 @@ struct hb_ot_apply_context_t : *face->table.GDEF->table #else Null (GDEF) +#endif + ), + gdef_accel ( +#ifndef HB_NO_OT_LAYOUT + *face->table.GDEF +#else + Null (GDEF::accelerator_t) #endif ), var_store (gdef.get_var_store ()), @@ -754,10 +772,10 @@ struct hb_ot_apply_context_t : iter_context.init (this, true); } - void set_lookup_mask (hb_mask_t mask) { lookup_mask = mask; last_base = -1; last_base_until = 0; init_iters (); } - void set_auto_zwj (bool auto_zwj_) { auto_zwj = auto_zwj_; init_iters (); } - void set_auto_zwnj (bool auto_zwnj_) { auto_zwnj = auto_zwnj_; init_iters (); } - void set_per_syllable (bool per_syllable_) { per_syllable = per_syllable_; init_iters (); } + void set_lookup_mask (hb_mask_t mask, bool init = true) { lookup_mask = mask; last_base = -1; last_base_until = 0; if (init) init_iters (); } + void set_auto_zwj (bool auto_zwj_, bool init = true) { auto_zwj = auto_zwj_; if (init) init_iters (); } + void set_auto_zwnj (bool auto_zwnj_, bool init = true) { auto_zwnj = auto_zwnj_; if (init) init_iters (); } + void set_per_syllable (bool per_syllable_, bool init = true) { per_syllable = per_syllable_; if (init) init_iters (); } void set_random (bool random_) { random = random_; } void set_recurse_func (recurse_func_t func) { recurse_func = func; } void set_lookup_index (unsigned int lookup_index_) { lookup_index = lookup_index_; } @@ -793,7 +811,6 @@ struct hb_ot_apply_context_t : bool check_glyph_property (const hb_glyph_info_t *info, unsigned int match_props) const { - hb_codepoint_t glyph = info->codepoint; unsigned int glyph_props = _hb_glyph_info_get_glyph_props (info); /* Not covered, if, for example, glyph class is ligature and @@ -803,7 +820,7 @@ struct hb_ot_apply_context_t : return false; if (unlikely (glyph_props & HB_OT_LAYOUT_GLYPH_PROPS_MARK)) - return match_properties_mark (glyph, glyph_props, match_props); + return match_properties_mark (info->codepoint, glyph_props, match_props); return true; } @@ -836,7 +853,7 @@ struct hb_ot_apply_context_t : if (likely (has_glyph_classes)) { props &= HB_OT_LAYOUT_GLYPH_PROPS_PRESERVE; - _hb_glyph_info_set_glyph_props (&buffer->cur(), props | gdef.get_glyph_props (glyph_index)); + _hb_glyph_info_set_glyph_props (&buffer->cur(), props | gdef_accel.get_glyph_props (glyph_index)); } else if (class_guess) { @@ -884,7 +901,7 @@ struct hb_accelerate_subtables_context_t : #ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE template - static inline auto apply_cached_ (const T *obj, hb_ot_apply_context_t *c, hb_priority<1>) HB_RETURN (bool, obj->apply (c, true) ) + static inline auto apply_cached_ (const T *obj, hb_ot_apply_context_t *c, hb_priority<1>) HB_RETURN (bool, obj->apply_cached (c) ) template static inline auto apply_cached_ (const T *obj, hb_ot_apply_context_t *c, hb_priority<0>) HB_RETURN (bool, obj->apply (c) ) template @@ -1241,7 +1258,6 @@ static inline bool match_input (hb_ot_apply_context_t *c, */ unsigned int total_component_count = 0; - total_component_count += _hb_glyph_info_get_lig_num_comps (&buffer->cur()); unsigned int first_lig_id = _hb_glyph_info_get_lig_id (&buffer->cur()); unsigned int first_lig_comp = _hb_glyph_info_get_lig_comp (&buffer->cur()); @@ -1252,7 +1268,6 @@ static inline bool match_input (hb_ot_apply_context_t *c, LIGBASE_MAY_SKIP } ligbase = LIGBASE_NOT_CHECKED; - match_positions[0] = buffer->idx; for (unsigned int i = 1; i < count; i++) { unsigned unsafe_to; @@ -1317,7 +1332,12 @@ static inline bool match_input (hb_ot_apply_context_t *c, *end_position = skippy_iter.idx + 1; if (p_total_component_count) + { + total_component_count += _hb_glyph_info_get_lig_num_comps (&buffer->cur()); *p_total_component_count = total_component_count; + } + + match_positions[0] = buffer->idx; return_trace (true); } @@ -2431,7 +2451,9 @@ struct ContextFormat2_5 } } - bool apply (hb_ot_apply_context_t *c, bool cached = false) const + bool apply_cached (hb_ot_apply_context_t *c) const { return _apply (c, true); } + bool apply (hb_ot_apply_context_t *c) const { return _apply (c, false); } + bool _apply (hb_ot_apply_context_t *c, bool cached) const { TRACE_APPLY (this); unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint); @@ -3534,7 +3556,9 @@ struct ChainContextFormat2_5 } } - bool apply (hb_ot_apply_context_t *c, bool cached = false) const + bool apply_cached (hb_ot_apply_context_t *c) const { return _apply (c, true); } + bool apply (hb_ot_apply_context_t *c) const { return _apply (c, false); } + bool _apply (hb_ot_apply_context_t *c, bool cached) const { TRACE_APPLY (this); unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint); diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-layout.cc b/src/3rdparty/harfbuzz-ng/src/hb-ot-layout.cc index 256a055863b..c66ee8cfd06 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-ot-layout.cc +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-layout.cc @@ -64,8 +64,8 @@ using OT::Layout::GPOS; * @include: hb-ot.h * * Functions for querying OpenType Layout features in the font face. - * See the OpenType - * specification for details. + * See the [OpenType specification](http://www.microsoft.com/typography/otspec/) + * for details. **/ @@ -257,12 +257,13 @@ _hb_ot_layout_set_glyph_props (hb_font_t *font, { _hb_buffer_assert_gsubgpos_vars (buffer); - const OT::GDEF &gdef = *font->face->table.GDEF->table; + const auto &gdef = *font->face->table.GDEF; unsigned int count = buffer->len; + hb_glyph_info_t *info = buffer->info; for (unsigned int i = 0; i < count; i++) { - _hb_glyph_info_set_glyph_props (&buffer->info[i], gdef.get_glyph_props (buffer->info[i].codepoint)); - _hb_glyph_info_clear_lig_props (&buffer->info[i]); + _hb_glyph_info_set_glyph_props (&info[i], gdef.get_glyph_props (info[i].codepoint)); + _hb_glyph_info_clear_lig_props (&info[i]); } } @@ -1895,7 +1896,7 @@ apply_backward (OT::hb_ot_apply_context_t *c, if (accel.digest.may_have (buffer->cur().codepoint) && (buffer->cur().mask & c->lookup_mask) && c->check_glyph_property (&buffer->cur(), c->lookup_props)) - ret |= accel.apply (c, subtable_count, false); + ret |= accel.apply (c, subtable_count, false); /* The reverse lookup doesn't "advance" cursor (for good reason). */ buffer->idx--; @@ -1977,11 +1978,12 @@ inline void hb_ot_map_t::apply (const Proxy &proxy, if (accel->digest.may_have (c.digest)) { c.set_lookup_index (lookup_index); - c.set_lookup_mask (lookup.mask); - c.set_auto_zwj (lookup.auto_zwj); - c.set_auto_zwnj (lookup.auto_zwnj); + c.set_lookup_mask (lookup.mask, false); + c.set_auto_zwj (lookup.auto_zwj, false); + c.set_auto_zwnj (lookup.auto_zwnj, false); c.set_random (lookup.random); - c.set_per_syllable (lookup.per_syllable); + c.set_per_syllable (lookup.per_syllable, false); + /* apply_string's set_lookup_props initializes the iterators. */ apply_string (&c, proxy.accel.table->get_lookup (lookup_index), diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-math.cc b/src/3rdparty/harfbuzz-ng/src/hb-ot-math.cc index c515867bdf1..876ad258e39 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-ot-math.cc +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-math.cc @@ -76,7 +76,7 @@ hb_ot_math_has_data (hb_face_t *face) * * However, if the requested constant is #HB_OT_MATH_CONSTANT_SCRIPT_PERCENT_SCALE_DOWN, * #HB_OT_MATH_CONSTANT_SCRIPT_SCRIPT_PERCENT_SCALE_DOWN or - * #HB_OT_MATH_CONSTANT_SCRIPT_PERCENT_SCALE_DOWN, then the return value is + * #HB_OT_MATH_CONSTANT_RADICAL_DEGREE_BOTTOM_RAISE_PERCENT, then the return value is * an integer between 0 and 100 representing that percentage. * * Return value: the requested constant or zero diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-metrics.cc b/src/3rdparty/harfbuzz-ng/src/hb-ot-metrics.cc index 5b12482b979..e314d946b62 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-ot-metrics.cc +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-metrics.cc @@ -196,7 +196,7 @@ hb_ot_metrics_get_position (hb_font_t *font, *position *= mult; if (font->slant) - *position += _hb_roundf (mult * font->slant_xy * rise); + *position += roundf (mult * font->slant_xy * rise); } return ret; diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-normalize.cc b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-normalize.cc index 897377aa158..69dbec0783b 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-normalize.cc +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-normalize.cc @@ -383,14 +383,15 @@ _hb_ot_shape_normalize (const hb_ot_shape_plan_t *plan, if (!all_simple && buffer->message(font, "start reorder")) { count = buffer->len; + hb_glyph_info_t *info = buffer->info; for (unsigned int i = 0; i < count; i++) { - if (_hb_glyph_info_get_modified_combining_class (&buffer->info[i]) == 0) + if (_hb_glyph_info_get_modified_combining_class (&info[i]) == 0) continue; unsigned int end; for (end = i + 1; end < count; end++) - if (_hb_glyph_info_get_modified_combining_class (&buffer->info[end]) == 0) + if (_hb_glyph_info_get_modified_combining_class (&info[end]) == 0) break; /* We are going to do a O(n^2). Only do this if the sequence is short. */ @@ -414,11 +415,13 @@ _hb_ot_shape_normalize (const hb_ot_shape_plan_t *plan, * If it did NOT, then make it skippable. * https://github.com/harfbuzz/harfbuzz/issues/554 */ - for (unsigned int i = 1; i + 1 < buffer->len; i++) - if (buffer->info[i].codepoint == 0x034Fu/*CGJ*/ && - (info_cc(buffer->info[i+1]) == 0 || info_cc(buffer->info[i-1]) <= info_cc(buffer->info[i+1]))) + unsigned count = buffer->len; + hb_glyph_info_t *info = buffer->info; + for (unsigned int i = 1; i + 1 < count; i++) + if (info[i].codepoint == 0x034Fu/*CGJ*/ && + (info_cc(info[i+1]) == 0 || info_cc(info[i-1]) <= info_cc(info[i+1]))) { - _hb_glyph_info_unhide (&buffer->info[i]); + _hb_glyph_info_unhide (&info[i]); } } diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-indic-machine.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-indic-machine.hh index 7dd47755af0..353e32d32c0 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-indic-machine.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-indic-machine.hh @@ -53,7 +53,7 @@ enum indic_syllable_type_t { }; -#line 54 "hb-ot-shaper-indic-machine.hh" +#line 57 "hb-ot-shaper-indic-machine.hh" #define indic_syllable_machine_ex_A 9u #define indic_syllable_machine_ex_C 1u #define indic_syllable_machine_ex_CM 16u @@ -76,7 +76,7 @@ enum indic_syllable_type_t { #define indic_syllable_machine_ex_ZWNJ 5u -#line 75 "hb-ot-shaper-indic-machine.hh" +#line 80 "hb-ot-shaper-indic-machine.hh" static const unsigned char _indic_syllable_machine_trans_keys[] = { 8u, 8u, 4u, 13u, 5u, 13u, 5u, 13u, 13u, 13u, 4u, 13u, 4u, 13u, 4u, 13u, 8u, 8u, 5u, 13u, 5u, 13u, 13u, 13u, 4u, 13u, 4u, 13u, 4u, 13u, 4u, 13u, @@ -460,7 +460,7 @@ find_syllables_indic (hb_buffer_t *buffer) int cs; hb_glyph_info_t *info = buffer->info; -#line 453 "hb-ot-shaper-indic-machine.hh" +#line 464 "hb-ot-shaper-indic-machine.hh" { cs = indic_syllable_machine_start; ts = 0; @@ -476,7 +476,7 @@ find_syllables_indic (hb_buffer_t *buffer) unsigned int syllable_serial = 1; -#line 465 "hb-ot-shaper-indic-machine.hh" +#line 480 "hb-ot-shaper-indic-machine.hh" { int _slen; int _trans; @@ -490,7 +490,7 @@ _resume: #line 1 "NONE" {ts = p;} break; -#line 477 "hb-ot-shaper-indic-machine.hh" +#line 494 "hb-ot-shaper-indic-machine.hh" } _keys = _indic_syllable_machine_trans_keys + (cs<<1); @@ -593,7 +593,7 @@ _eof_trans: #line 114 "hb-ot-shaper-indic-machine.rl" {act = 6;} break; -#line 559 "hb-ot-shaper-indic-machine.hh" +#line 597 "hb-ot-shaper-indic-machine.hh" } _again: @@ -602,7 +602,7 @@ _again: #line 1 "NONE" {ts = 0;} break; -#line 566 "hb-ot-shaper-indic-machine.hh" +#line 606 "hb-ot-shaper-indic-machine.hh" } if ( ++p != pe ) diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-var-common.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-var-common.hh index 853fe3839bd..7d4bf2241ca 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-ot-var-common.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-var-common.hh @@ -270,7 +270,8 @@ struct TupleVariationHeader if (shared_tuple_active_idx) { - assert (index < shared_tuple_active_idx->length); + if (unlikely (index >= shared_tuple_active_idx->length)) + return 0.f; int v = (*shared_tuple_active_idx).arrayZ[index]; if (v != -1) { diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-var-cvar-table.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-var-cvar-table.hh index bdb2b6b23bd..7fd0f1d79d6 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-ot-var-cvar-table.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-var-cvar-table.hh @@ -126,7 +126,6 @@ struct cvar hb_blob_destroy (cvt_prime_blob); return false; } - hb_memset (cvt_deltas.arrayZ, 0, cvt_deltas.get_size ()); if (!calculate_cvt_deltas (plan->normalized_coords.length, plan->normalized_coords.as_array (), num_cvt_item, tuple_var_data, base, cvt_deltas)) diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-var-gvar-table.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-var-gvar-table.hh index 4752a08fbe0..ece892e1dd5 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-ot-var-gvar-table.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-var-gvar-table.hh @@ -44,8 +44,15 @@ struct contour_point_t void init (float x_ = 0.f, float y_ = 0.f, bool is_end_point_ = false) { flag = 0; x = x_; y = y_; is_end_point = is_end_point_; } + void transform (const float (&matrix)[4]) + { + float x_ = x * matrix[0] + y * matrix[2]; + y = x * matrix[1] + y * matrix[3]; + x = x_; + } void translate (const contour_point_t &p) { x += p.x; y += p.y; } + float x = 0.f; float y = 0.f; uint8_t flag = 0; @@ -63,32 +70,6 @@ struct contour_point_vector_t : hb_vector_t unsigned count = a.length; hb_memcpy (arrayZ, a.arrayZ, count * sizeof (arrayZ[0])); } - - void transform (const float (&matrix)[4]) - { - if (matrix[0] == 1.f && matrix[1] == 0.f && - matrix[2] == 0.f && matrix[3] == 1.f) - return; - auto arrayZ = this->arrayZ; - unsigned count = length; - for (unsigned i = 0; i < count; i++) - { - contour_point_t &p = arrayZ[i]; - float x_ = p.x * matrix[0] + p.y * matrix[2]; - p.y = p.x * matrix[1] + p.y * matrix[3]; - p.x = x_; - } - } - - void translate (const contour_point_t& delta) - { - if (delta.x == 0.f && delta.y == 0.f) - return; - auto arrayZ = this->arrayZ; - unsigned count = length; - for (unsigned i = 0; i < count; i++) - arrayZ[i].translate (delta); - } }; struct GlyphVariationData : TupleVariationData @@ -238,7 +219,7 @@ struct gvar int idx = -1; for (unsigned j = 0; j < axis_count; j++) { - F2DOT14 peak = tuple.arrayZ[j]; + const F2DOT14 &peak = tuple.arrayZ[j]; if (peak.to_int () != 0) { if (idx != -1) @@ -249,7 +230,7 @@ struct gvar idx = j; } } - shared_tuple_active_idx[i] = idx; + shared_tuple_active_idx.arrayZ[i] = idx; } } ~accelerator_t () { table.destroy (); } @@ -311,7 +292,7 @@ struct gvar hb_vector_t end_points; // Populated lazily unsigned num_coords = table->axisCount; - hb_array_t shared_tuples = (table+table->sharedTuples).as_array (table->sharedTupleCount * table->axisCount); + hb_array_t shared_tuples = (table+table->sharedTuples).as_array (table->sharedTupleCount * num_coords); hb_vector_t private_indices; hb_vector_t x_deltas; @@ -320,7 +301,7 @@ struct gvar do { float scalar = iterator.current_tuple->calculate_scalar (coords, num_coords, shared_tuples, - shared_tuple_active_idx.in_error () ? nullptr : &shared_tuple_active_idx); + &shared_tuple_active_idx); if (scalar == 0.f) continue; const HBUINT8 *p = iterator.get_serialized_data (); unsigned int length = iterator.current_tuple->get_data_size (); @@ -329,8 +310,9 @@ struct gvar if (!deltas) { - if (unlikely (!deltas_vec.resize (points.length))) return false; + if (unlikely (!deltas_vec.resize (points.length, false))) return false; deltas = deltas_vec.as_array (); + hb_memset (deltas.arrayZ, 0, deltas.get_size ()); // Faster than vector resize } const HBUINT8 *end = p + length; @@ -359,7 +341,8 @@ struct gvar if (flush) { - for (unsigned int i = 0; i < points.length; i++) + unsigned count = points.length; + for (unsigned int i = 0; i < count; i++) points.arrayZ[i].translate (deltas.arrayZ[i]); flush = false; @@ -367,7 +350,8 @@ struct gvar hb_memset (deltas.arrayZ, 0, deltas.get_size ()); } - if (scalar != 1.0f) + if (HB_OPTIMIZE_SIZE_VAL) + { for (unsigned int i = 0; i < num_deltas; i++) { unsigned int pt_index; @@ -383,29 +367,61 @@ struct gvar delta.x += x_deltas.arrayZ[i] * scalar; delta.y += y_deltas.arrayZ[i] * scalar; } + } else - for (unsigned int i = 0; i < num_deltas; i++) + { + /* Ouch. Four cases... for optimization. */ + if (scalar != 1.0f) { - unsigned int pt_index; if (apply_to_all) - pt_index = i; + for (unsigned int i = 0; i < num_deltas; i++) + { + unsigned int pt_index = i; + auto &delta = deltas.arrayZ[pt_index]; + delta.x += x_deltas.arrayZ[i] * scalar; + delta.y += y_deltas.arrayZ[i] * scalar; + } else - { - pt_index = indices[i]; - if (unlikely (pt_index >= deltas.length)) continue; - } - auto &delta = deltas.arrayZ[pt_index]; - delta.flag = 1; /* this point is referenced, i.e., explicit deltas specified */ - delta.x += x_deltas.arrayZ[i]; - delta.y += y_deltas.arrayZ[i]; + for (unsigned int i = 0; i < num_deltas; i++) + { + unsigned int pt_index = indices[i]; + if (unlikely (pt_index >= deltas.length)) continue; + auto &delta = deltas.arrayZ[pt_index]; + delta.flag = 1; /* this point is referenced, i.e., explicit deltas specified */ + delta.x += x_deltas.arrayZ[i] * scalar; + delta.y += y_deltas.arrayZ[i] * scalar; + } } + else + { + if (apply_to_all) + for (unsigned int i = 0; i < num_deltas; i++) + { + unsigned int pt_index = i; + auto &delta = deltas.arrayZ[pt_index]; + delta.x += x_deltas.arrayZ[i]; + delta.y += y_deltas.arrayZ[i]; + } + else + for (unsigned int i = 0; i < num_deltas; i++) + { + unsigned int pt_index = indices[i]; + if (unlikely (pt_index >= deltas.length)) continue; + auto &delta = deltas.arrayZ[pt_index]; + delta.flag = 1; /* this point is referenced, i.e., explicit deltas specified */ + delta.x += x_deltas.arrayZ[i]; + delta.y += y_deltas.arrayZ[i]; + } + } + } /* infer deltas for unreferenced points */ if (!apply_to_all) { if (!end_points) { - for (unsigned i = 0; i < points.length; ++i) + unsigned count = points.length; + for (unsigned i = 0; i < count; ++i) if (points.arrayZ[i].is_end_point) end_points.push (i); if (unlikely (end_points.in_error ())) return false; @@ -465,8 +481,11 @@ struct gvar } while (iterator.move_to_next ()); if (flush) - for (unsigned int i = 0; i < points.length; i++) + { + unsigned count = points.length; + for (unsigned int i = 0; i < count; i++) points.arrayZ[i].translate (deltas.arrayZ[i]); + } return true; } diff --git a/src/3rdparty/harfbuzz-ng/src/hb-set-digest.hh b/src/3rdparty/harfbuzz-ng/src/hb-set-digest.hh index e8409111f2d..dab713729b7 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-set-digest.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-set-digest.hh @@ -45,10 +45,16 @@ * a lookup's or subtable's Coverage table(s), and then when we * want to apply the lookup or subtable to a glyph, before trying * to apply, we ask the filter if the glyph may be covered. If it's - * not, we return early. + * not, we return early. We can also match a digest against another + * digest. * - * We use these filters both at the lookup-level, and then again, - * at the subtable-level. Both have performance win. + * We use these filters at three levels: + * - If the digest for all the glyphs in the buffer as a whole + * does not match the digest for the lookup, skip the lookup. + * - For each glyph, if it doesn't match the lookup digest, + * skip it. + * - For each glyph, if it doesn't match the subtable digest, + * skip it. * * The main filter we use is a combination of three bits-pattern * filters. A bits-pattern filter checks a number of bits (5 or 6) diff --git a/src/3rdparty/harfbuzz-ng/src/hb-subset-accelerator.hh b/src/3rdparty/harfbuzz-ng/src/hb-subset-accelerator.hh index e523c258203..bb7c62d064f 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-subset-accelerator.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-subset-accelerator.hh @@ -58,6 +58,8 @@ struct hb_subset_accelerator_t hb_subset_accelerator_t* accel = (hb_subset_accelerator_t*) hb_calloc (1, sizeof(hb_subset_accelerator_t)); + if (unlikely (!accel)) return accel; + new (accel) hb_subset_accelerator_t (unicode_to_gid_, gid_to_unicodes_, unicodes_, diff --git a/src/3rdparty/harfbuzz-ng/src/hb-subset-input.cc b/src/3rdparty/harfbuzz-ng/src/hb-subset-input.cc index 5f001ac2511..465af508141 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-subset-input.cc +++ b/src/3rdparty/harfbuzz-ng/src/hb-subset-input.cc @@ -520,6 +520,37 @@ hb_subset_preprocess (hb_face_t *source) return new_source; } +/** + * hb_subset_input_old_to_new_glyph_mapping: + * @input: a #hb_subset_input_t object. + * + * Returns a map which can be used to provide an explicit mapping from old to new glyph + * id's in the produced subset. The caller should populate the map as desired. + * If this map is left empty then glyph ids will be automatically mapped to new + * values by the subsetter. If populated, the mapping must be unique. That + * is no two original glyph ids can be mapped to the same new id. + * Additionally, if a mapping is provided then the retain gids option cannot + * be enabled. + * + * Any glyphs that are retained in the subset which are not specified + * in this mapping will be assigned glyph ids after the highest glyph + * id in the mapping. + * + * Note: this will accept and apply non-monotonic mappings, however this + * may result in unsorted Coverage tables. Such fonts may not work for all + * use cases (for example ots will reject unsorted coverage tables). So it's + * recommended, if possible, to supply a monotonic mapping. + * + * Return value: (transfer none): pointer to the #hb_map_t of the custom glyphs ID map. + * + * Since: 7.3.0 + **/ +HB_EXTERN hb_map_t* +hb_subset_input_old_to_new_glyph_mapping (hb_subset_input_t *input) +{ + return &input->glyph_map; +} + #ifdef HB_EXPERIMENTAL_API /** * hb_subset_input_override_name_table: diff --git a/src/3rdparty/harfbuzz-ng/src/hb-subset-input.hh b/src/3rdparty/harfbuzz-ng/src/hb-subset-input.hh index 1550e8b2c30..1970f795b98 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-subset-input.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-subset-input.hh @@ -119,6 +119,7 @@ struct hb_subset_input_t bool force_long_loca = false; hb_hashmap_t axes_location; + hb_map_t glyph_map; #ifdef HB_EXPERIMENTAL_API hb_hashmap_t name_table_overrides; #endif diff --git a/src/3rdparty/harfbuzz-ng/src/hb-subset-plan-member-list.hh b/src/3rdparty/harfbuzz-ng/src/hb-subset-plan-member-list.hh new file mode 100644 index 00000000000..acf508c32da --- /dev/null +++ b/src/3rdparty/harfbuzz-ng/src/hb-subset-plan-member-list.hh @@ -0,0 +1,128 @@ +/* + * Copyright © 2018 Google, Inc. + * Copyright © 2023 Behdad Esfahbod + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + * Google Author(s): Garret Rieger, Roderick Sheeter + */ + +#ifndef HB_SUBSET_PLAN_MEMBER_LIST_HH +#define HB_SUBSET_PLAN_MEMBER_LIST_HH +#endif /* HB_SUBSET_PLAN_MEMBER_LIST_HH */ /* Dummy header guards */ + +#define E(x, y) x, y + +// For each cp that we'd like to retain maps to the corresponding gid. +HB_SUBSET_PLAN_MEMBER (hb_set_t, unicodes) +HB_SUBSET_PLAN_MEMBER (hb_sorted_vector_t E(>), unicode_to_new_gid_list) + +// name_ids we would like to retain +HB_SUBSET_PLAN_MEMBER (hb_set_t, name_ids) + +// name_languages we would like to retain +HB_SUBSET_PLAN_MEMBER (hb_set_t, name_languages) + +//layout features which will be preserved +HB_SUBSET_PLAN_MEMBER (hb_set_t, layout_features) + +// layout scripts which will be preserved. +HB_SUBSET_PLAN_MEMBER (hb_set_t, layout_scripts) + +//glyph ids requested to retain +HB_SUBSET_PLAN_MEMBER (hb_set_t, glyphs_requested) + +// Tables which should not be processed, just pass them through. +HB_SUBSET_PLAN_MEMBER (hb_set_t, no_subset_tables) + +// Tables which should be dropped. +HB_SUBSET_PLAN_MEMBER (hb_set_t, drop_tables) + +// Old -> New glyph id mapping +HB_SUBSET_PLAN_MEMBER (hb_map_t, glyph_map_gsub) + +HB_SUBSET_PLAN_MEMBER (hb_set_t, _glyphset) +HB_SUBSET_PLAN_MEMBER (hb_set_t, _glyphset_gsub) +HB_SUBSET_PLAN_MEMBER (hb_set_t, _glyphset_mathed) +HB_SUBSET_PLAN_MEMBER (hb_set_t, _glyphset_colred) + +//active lookups we'd like to retain +HB_SUBSET_PLAN_MEMBER (hb_map_t, gsub_lookups) +HB_SUBSET_PLAN_MEMBER (hb_map_t, gpos_lookups) + +//active langsys we'd like to retain +HB_SUBSET_PLAN_MEMBER (hb_hashmap_t E(>), gsub_langsys) +HB_SUBSET_PLAN_MEMBER (hb_hashmap_t E(>), gpos_langsys) + +//active features after removing redundant langsys and prune_features +HB_SUBSET_PLAN_MEMBER (hb_map_t, gsub_features) +HB_SUBSET_PLAN_MEMBER (hb_map_t, gpos_features) + +//active feature variation records/condition index with variations +HB_SUBSET_PLAN_MEMBER (hb_hashmap_t E(>), gsub_feature_record_cond_idx_map) +HB_SUBSET_PLAN_MEMBER (hb_hashmap_t E(>), gpos_feature_record_cond_idx_map) + +//feature index-> address of substituation feature table mapping with +//variations +HB_SUBSET_PLAN_MEMBER (hb_hashmap_t E(), gsub_feature_substitutes_map) +HB_SUBSET_PLAN_MEMBER (hb_hashmap_t E(), gpos_feature_substitutes_map) + +//active layers/palettes we'd like to retain +HB_SUBSET_PLAN_MEMBER (hb_map_t, colrv1_layers) +HB_SUBSET_PLAN_MEMBER (hb_map_t, colr_palettes) + +//Old layout item variation index -> (New varidx, delta) mapping +HB_SUBSET_PLAN_MEMBER (hb_hashmap_t E()>), layout_variation_idx_delta_map) + +//gdef varstore retained varidx mapping +HB_SUBSET_PLAN_MEMBER (hb_vector_t, gdef_varstore_inner_maps) + +HB_SUBSET_PLAN_MEMBER (hb_hashmap_t E(>), sanitized_table_cache) + +//normalized axes location map +HB_SUBSET_PLAN_MEMBER (hb_hashmap_t E(), axes_location) +HB_SUBSET_PLAN_MEMBER (hb_vector_t, normalized_coords) + +//user specified axes location map +HB_SUBSET_PLAN_MEMBER (hb_hashmap_t E(), user_axes_location) + +//retained old axis index -> new axis index mapping in fvar axis array +HB_SUBSET_PLAN_MEMBER (hb_map_t, axes_index_map) + +//axis_index->axis_tag mapping in fvar axis array +HB_SUBSET_PLAN_MEMBER (hb_map_t, axes_old_index_tag_map) + +//hmtx metrics map: new gid->(advance, lsb) +HB_SUBSET_PLAN_MEMBER (mutable hb_hashmap_t E()>), hmtx_map) +//vmtx metrics map: new gid->(advance, lsb) +HB_SUBSET_PLAN_MEMBER (mutable hb_hashmap_t E()>), vmtx_map) +//boundsWidth map: new gid->boundsWidth, boundWidth=xMax - xMin +HB_SUBSET_PLAN_MEMBER (mutable hb_map_t, bounds_width_map) +//boundsHeight map: new gid->boundsHeight, boundsHeight=yMax - yMin +HB_SUBSET_PLAN_MEMBER (mutable hb_map_t, bounds_height_map) + +#ifdef HB_EXPERIMENTAL_API +// name table overrides map: hb_ot_name_record_ids_t-> name string new value or +// None to indicate should remove +HB_SUBSET_PLAN_MEMBER (hb_hashmap_t E(), name_table_overrides) +#endif + +#undef E diff --git a/src/3rdparty/harfbuzz-ng/src/hb-subset-plan.cc b/src/3rdparty/harfbuzz-ng/src/hb-subset-plan.cc index aea886864d5..791f92d02d5 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-subset-plan.cc +++ b/src/3rdparty/harfbuzz-ng/src/hb-subset-plan.cc @@ -381,18 +381,10 @@ _collect_layout_variation_indices (hb_subset_plan_t* plan) const OT::VariationStore *var_store = nullptr; hb_set_t varidx_set; - hb_font_t *font = nullptr; float *store_cache = nullptr; bool collect_delta = plan->pinned_at_default ? false : true; if (collect_delta) { - if (unlikely (!plan->check_success (font = _get_hb_font_with_variations (plan)))) { - hb_font_destroy (font); - gdef.destroy (); - gpos.destroy (); - return; - } - if (gdef->has_var_store ()) { var_store = &(gdef->get_var_store ()); @@ -402,7 +394,8 @@ _collect_layout_variation_indices (hb_subset_plan_t* plan) OT::hb_collect_variation_indices_context_t c (&varidx_set, &plan->layout_variation_idx_delta_map, - font, var_store, + plan->normalized_coords ? &(plan->normalized_coords) : nullptr, + var_store, &plan->_glyphset_gsub, &plan->gpos_lookups, store_cache); @@ -411,7 +404,6 @@ _collect_layout_variation_indices (hb_subset_plan_t* plan) if (hb_ot_layout_has_positioning (plan->source)) gpos->collect_variation_indices (&c); - hb_font_destroy (font); var_store->destroy_cache (store_cache); gdef->remap_layout_variation_indices (&varidx_set, &plan->layout_variation_idx_delta_map); @@ -616,13 +608,14 @@ _glyf_add_gid_and_children (const OT::glyf_accelerator_t &glyf, int operation_count, unsigned depth = 0) { - if (unlikely (depth++ > HB_MAX_NESTING_LEVEL)) return operation_count; - if (unlikely (--operation_count < 0)) return operation_count; /* Check if is already visited */ if (gids_to_retain->has (gid)) return operation_count; gids_to_retain->add (gid); + if (unlikely (depth++ > HB_MAX_NESTING_LEVEL)) return operation_count; + if (unlikely (--operation_count < 0)) return operation_count; + for (auto &item : glyf.glyph_for_gid (gid).get_composite_iterator ()) operation_count = _glyf_add_gid_and_children (glyf, @@ -775,10 +768,11 @@ _create_glyph_map_gsub (const hb_set_t* glyph_set_gsub, ; } -static void +static bool _create_old_gid_to_new_gid_map (const hb_face_t *face, bool retain_gids, const hb_set_t *all_gids_to_retain, + const hb_map_t *requested_glyph_map, hb_map_t *glyph_map, /* OUT */ hb_map_t *reverse_glyph_map, /* OUT */ unsigned int *num_glyphs /* OUT */) @@ -787,7 +781,54 @@ _create_old_gid_to_new_gid_map (const hb_face_t *face, reverse_glyph_map->resize (pop); glyph_map->resize (pop); - if (!retain_gids) + if (*requested_glyph_map) + { + hb_set_t new_gids(requested_glyph_map->values()); + if (new_gids.get_population() != requested_glyph_map->get_population()) + { + DEBUG_MSG (SUBSET, nullptr, "The provided custom glyph mapping is not unique."); + return false; + } + + if (retain_gids) + { + DEBUG_MSG (SUBSET, nullptr, + "HB_SUBSET_FLAGS_RETAIN_GIDS cannot be set if " + "a custom glyph mapping has been provided."); + return false; + } + + hb_codepoint_t max_glyph = 0; + hb_set_t remaining; + for (auto old_gid : all_gids_to_retain->iter ()) + { + if (old_gid == 0) { + reverse_glyph_map->set(0, 0); + continue; + } + + hb_codepoint_t* new_gid; + if (!requested_glyph_map->has (old_gid, &new_gid)) + { + remaining.add(old_gid); + continue; + } + + if (*new_gid > max_glyph) + max_glyph = *new_gid; + reverse_glyph_map->set (*new_gid, old_gid); + } + + // Anything that wasn't mapped by the requested mapping should + // be placed after the requested mapping. + for (auto old_gid : remaining) + { + reverse_glyph_map->set(++max_glyph, old_gid); + } + + *num_glyphs = max_glyph + 1; + } + else if (!retain_gids) { + hb_enumerate (hb_iter (all_gids_to_retain), (hb_codepoint_t) 0) | hb_sink (reverse_glyph_map) @@ -813,6 +854,8 @@ _create_old_gid_to_new_gid_map (const hb_face_t *face, | hb_map (&hb_pair_t::reverse) | hb_sink (glyph_map) ; + + return true; } #ifndef HB_NO_VAR @@ -1002,7 +1045,6 @@ hb_subset_plan_t::hb_subset_plan_t (hb_face_t *face, if (accel) accelerator = (hb_subset_accelerator_t*) accel; - if (unlikely (in_error ())) return; @@ -1016,12 +1058,16 @@ hb_subset_plan_t::hb_subset_plan_t (hb_face_t *face, if (unlikely (in_error ())) return; - _create_old_gid_to_new_gid_map (face, - input->flags & HB_SUBSET_FLAGS_RETAIN_GIDS, - &_glyphset, - glyph_map, - reverse_glyph_map, - &_num_output_glyphs); + if (!check_success(_create_old_gid_to_new_gid_map( + face, + input->flags & HB_SUBSET_FLAGS_RETAIN_GIDS, + &_glyphset, + &input->glyph_map, + glyph_map, + reverse_glyph_map, + &_num_output_glyphs))) { + return; + } _create_glyph_map_gsub ( &_glyphset_gsub, @@ -1060,7 +1106,13 @@ hb_subset_plan_t::hb_subset_plan_t (hb_face_t *face, gid_to_unicodes, unicodes, has_seac); + + check_success (inprogress_accelerator); } + +#define HB_SUBSET_PLAN_MEMBER(Type, Name) check_success (!Name.in_error ()); +#include "hb-subset-plan-member-list.hh" +#undef HB_SUBSET_PLAN_MEMBER } /** diff --git a/src/3rdparty/harfbuzz-ng/src/hb-subset-plan.hh b/src/3rdparty/harfbuzz-ng/src/hb-subset-plan.hh index e34eeb89ae8..19470ff83e9 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-subset-plan.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-subset-plan.hh @@ -97,112 +97,30 @@ struct hb_subset_plan_t bool attach_accelerator_data = false; bool force_long_loca = false; - // For each cp that we'd like to retain maps to the corresponding gid. - hb_set_t unicodes; - hb_sorted_vector_t> unicode_to_new_gid_list; - - // name_ids we would like to retain - hb_set_t name_ids; - - // name_languages we would like to retain - hb_set_t name_languages; - - //layout features which will be preserved - hb_set_t layout_features; - - // layout scripts which will be preserved. - hb_set_t layout_scripts; - - //glyph ids requested to retain - hb_set_t glyphs_requested; - - // Tables which should not be processed, just pass them through. - hb_set_t no_subset_tables; - - // Tables which should be dropped. - hb_set_t drop_tables; - // The glyph subset hb_map_t *codepoint_to_glyph; // Needs to be heap-allocated // Old -> New glyph id mapping hb_map_t *glyph_map; // Needs to be heap-allocated hb_map_t *reverse_glyph_map; // Needs to be heap-allocated - hb_map_t glyph_map_gsub; // Plan is only good for a specific source/dest so keep them with it hb_face_t *source; hb_face_t *dest; unsigned int _num_output_glyphs; - hb_set_t _glyphset; - hb_set_t _glyphset_gsub; - hb_set_t _glyphset_mathed; - hb_set_t _glyphset_colred; - //active lookups we'd like to retain - hb_map_t gsub_lookups; - hb_map_t gpos_lookups; - - //active langsys we'd like to retain - hb_hashmap_t> gsub_langsys; - hb_hashmap_t> gpos_langsys; - - //active features after removing redundant langsys and prune_features - hb_map_t gsub_features; - hb_map_t gpos_features; - - //active feature variation records/condition index with variations - hb_hashmap_t> gsub_feature_record_cond_idx_map; - hb_hashmap_t> gpos_feature_record_cond_idx_map; - - //feature index-> address of substituation feature table mapping with - //variations - hb_hashmap_t gsub_feature_substitutes_map; - hb_hashmap_t gpos_feature_substitutes_map; - - //active layers/palettes we'd like to retain - hb_map_t colrv1_layers; - hb_map_t colr_palettes; - - //Old layout item variation index -> (New varidx, delta) mapping - hb_hashmap_t> layout_variation_idx_delta_map; - - //gdef varstore retained varidx mapping - hb_vector_t gdef_varstore_inner_maps; - - hb_hashmap_t> sanitized_table_cache; - //normalized axes location map - hb_hashmap_t axes_location; - hb_vector_t normalized_coords; - //user specified axes location map - hb_hashmap_t user_axes_location; - //retained old axis index -> new axis index mapping in fvar axis array - hb_map_t axes_index_map; - //axis_index->axis_tag mapping in fvar axis array - hb_map_t axes_old_index_tag_map; bool all_axes_pinned; bool pinned_at_default; bool has_seac; - //hmtx metrics map: new gid->(advance, lsb) - mutable hb_hashmap_t> hmtx_map; - //vmtx metrics map: new gid->(advance, lsb) - mutable hb_hashmap_t> vmtx_map; - //boundsWidth map: new gid->boundsWidth, boundWidth=xMax - xMin - mutable hb_map_t bounds_width_map; - //boundsHeight map: new gid->boundsHeight, boundsHeight=yMax - yMin - mutable hb_map_t bounds_height_map; +#define HB_SUBSET_PLAN_MEMBER(Type, Name) Type Name; +#include "hb-subset-plan-member-list.hh" +#undef HB_SUBSET_PLAN_MEMBER //recalculated head/maxp table info after instancing mutable head_maxp_info_t head_maxp_info; -#ifdef HB_EXPERIMENTAL_API - // name table overrides map: hb_ot_name_record_ids_t-> name string new value or - // None to indicate should remove - hb_hashmap_t name_table_overrides; -#endif - const hb_subset_accelerator_t* accelerator; hb_subset_accelerator_t* inprogress_accelerator; diff --git a/src/3rdparty/harfbuzz-ng/src/hb-subset.cc b/src/3rdparty/harfbuzz-ng/src/hb-subset.cc index 5ea422983c5..9c066e6d782 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-subset.cc +++ b/src/3rdparty/harfbuzz-ng/src/hb-subset.cc @@ -96,8 +96,8 @@ static hb_tag_t known_tables[] { HB_OT_TAG_BASE, HB_OT_TAG_CBDT, HB_OT_TAG_CBLC, - HB_OT_TAG_cff1, - HB_OT_TAG_cff2, + HB_OT_TAG_CFF1, + HB_OT_TAG_CFF2, HB_OT_TAG_cmap, HB_OT_TAG_COLR, HB_OT_TAG_CPAL, @@ -457,8 +457,8 @@ _subset_table (hb_subset_plan_t *plan, case HB_OT_TAG_MATH: return _subset (plan, buf); #ifndef HB_NO_SUBSET_CFF - case HB_OT_TAG_cff1: return _subset (plan, buf); - case HB_OT_TAG_cff2: return _subset (plan, buf); + case HB_OT_TAG_CFF1: return _subset (plan, buf); + case HB_OT_TAG_CFF2: return _subset (plan, buf); case HB_OT_TAG_VORG: return _subset (plan, buf); #endif diff --git a/src/3rdparty/harfbuzz-ng/src/hb-subset.h b/src/3rdparty/harfbuzz-ng/src/hb-subset.h index 41d9587052a..6368ff93f02 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-subset.h +++ b/src/3rdparty/harfbuzz-ng/src/hb-subset.h @@ -154,6 +154,9 @@ hb_subset_input_glyph_set (hb_subset_input_t *input); HB_EXTERN hb_set_t * hb_subset_input_set (hb_subset_input_t *input, hb_subset_sets_t set_type); +HB_EXTERN hb_map_t* +hb_subset_input_old_to_new_glyph_mapping (hb_subset_input_t *input); + HB_EXTERN hb_subset_flags_t hb_subset_input_get_flags (hb_subset_input_t *input); diff --git a/src/3rdparty/harfbuzz-ng/src/hb-vector.hh b/src/3rdparty/harfbuzz-ng/src/hb-vector.hh index 58d467a405f..d61ce48c01e 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-vector.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-vector.hh @@ -290,13 +290,11 @@ struct hb_vector_t copy_vector (const hb_vector_t &other) { length = other.length; -#ifndef HB_OPTIMIZE_SIZE - if (sizeof (T) >= sizeof (long long)) + if (!HB_OPTIMIZE_SIZE_VAL && sizeof (T) >= sizeof (long long)) /* This runs faster because of alignment. */ for (unsigned i = 0; i < length; i++) arrayZ[i] = other.arrayZ[i]; else -#endif hb_memcpy ((void *) arrayZ, (const void *) other.arrayZ, length * item_size); } template -#include -#include -#include - -#ifdef HB_NO_OPEN -#define hb_blob_create_from_file_or_fail(x) hb_blob_get_empty () -#endif - -#if !defined(HB_NO_COLOR) && !defined(HB_NO_DRAW) -static void -svg_dump (hb_face_t *face, unsigned face_index) -{ - unsigned glyph_count = hb_face_get_glyph_count (face); - - for (unsigned glyph_id = 0; glyph_id < glyph_count; ++glyph_id) - { - hb_blob_t *blob = hb_ot_color_glyph_reference_svg (face, glyph_id); - - if (hb_blob_get_length (blob) == 0) continue; - - unsigned length; - const char *data = hb_blob_get_data (blob, &length); - - char output_path[255]; - snprintf (output_path, sizeof output_path, - "out/svg-%u-%u.svg%s", - glyph_id, - face_index, - // append "z" if the content is gzipped, https://stackoverflow.com/a/6059405 - (length > 2 && (data[0] == '\x1F') && (data[1] == '\x8B')) ? "z" : ""); - - FILE *f = fopen (output_path, "wb"); - fwrite (data, 1, length, f); - fclose (f); - - hb_blob_destroy (blob); - } -} - -/* _png API is so easy to use unlike the below code, don't get confused */ -static void -png_dump (hb_face_t *face, unsigned face_index) -{ - unsigned glyph_count = hb_face_get_glyph_count (face); - hb_font_t *font = hb_font_create (face); - - /* scans the font for strikes */ - unsigned sample_glyph_id; - /* we don't care about different strikes for different glyphs at this point */ - for (sample_glyph_id = 0; sample_glyph_id < glyph_count; ++sample_glyph_id) - { - hb_blob_t *blob = hb_ot_color_glyph_reference_png (font, sample_glyph_id); - unsigned blob_length = hb_blob_get_length (blob); - hb_blob_destroy (blob); - if (blob_length != 0) - break; - } - - unsigned upem = hb_face_get_upem (face); - unsigned blob_length = 0; - unsigned strike = 0; - for (unsigned ppem = 1; ppem < upem; ++ppem) - { - hb_font_set_ppem (font, ppem, ppem); - hb_blob_t *blob = hb_ot_color_glyph_reference_png (font, sample_glyph_id); - unsigned new_blob_length = hb_blob_get_length (blob); - hb_blob_destroy (blob); - if (new_blob_length != blob_length) - { - for (unsigned glyph_id = 0; glyph_id < glyph_count; ++glyph_id) - { - hb_blob_t *blob = hb_ot_color_glyph_reference_png (font, glyph_id); - - if (hb_blob_get_length (blob) == 0) continue; - - unsigned length; - const char *data = hb_blob_get_data (blob, &length); - - char output_path[255]; - snprintf (output_path, sizeof output_path, "out/png-%u-%u-%u.png", glyph_id, strike, face_index); - - FILE *f = fopen (output_path, "wb"); - fwrite (data, 1, length, f); - fclose (f); - - hb_blob_destroy (blob); - } - - strike++; - blob_length = new_blob_length; - } - } - - hb_font_destroy (font); -} - -struct draw_data_t -{ - FILE *f; - hb_position_t ascender; -}; - -static void -move_to (hb_draw_funcs_t *, draw_data_t *draw_data, - hb_draw_state_t *, - float to_x, float to_y, - void *) -{ - fprintf (draw_data->f, "M%g,%g", to_x, draw_data->ascender - to_y); -} - -static void -line_to (hb_draw_funcs_t *, draw_data_t *draw_data, - hb_draw_state_t *, - float to_x, float to_y, - void *) -{ - fprintf (draw_data->f, "L%g,%g", to_x, draw_data->ascender - to_y); -} - -static void -quadratic_to (hb_draw_funcs_t *, draw_data_t *draw_data, - hb_draw_state_t *, - float control_x, float control_y, - float to_x, float to_y, - void *) -{ - fprintf (draw_data->f, "Q%g,%g %g,%g", control_x, draw_data->ascender - control_y, - to_x, draw_data->ascender - to_y); -} - -static void -cubic_to (hb_draw_funcs_t *, draw_data_t *draw_data, - hb_draw_state_t *, - float control1_x, float control1_y, - float control2_x, float control2_y, - float to_x, float to_y, - void *) -{ - fprintf (draw_data->f, "C%g,%g %g,%g %g,%g", control1_x, draw_data->ascender - control1_y, - control2_x, draw_data->ascender - control2_y, - to_x, draw_data->ascender - to_y); -} - -static void -close_path (hb_draw_funcs_t *, draw_data_t *draw_data, - hb_draw_state_t *, - void *) -{ - fprintf (draw_data->f, "Z"); -} - -static void -layered_glyph_dump (hb_font_t *font, hb_draw_funcs_t *funcs, unsigned face_index) -{ - hb_face_t *face = hb_font_get_face (font); - unsigned palette_count = hb_ot_color_palette_get_count (face); - for (unsigned palette = 0; palette < palette_count; ++palette) - { - unsigned num_colors = hb_ot_color_palette_get_colors (face, palette, 0, nullptr, nullptr); - if (!num_colors) continue; - - hb_color_t *colors = (hb_color_t*) calloc (num_colors, sizeof (hb_color_t)); - hb_ot_color_palette_get_colors (face, palette, 0, &num_colors, colors); - if (!num_colors) - { - free (colors); - continue; - } - - unsigned num_glyphs = hb_face_get_glyph_count (face); - for (hb_codepoint_t gid = 0; gid < num_glyphs; ++gid) - { - unsigned num_layers = hb_ot_color_glyph_get_layers (face, gid, 0, nullptr, nullptr); - if (!num_layers) continue; - - hb_ot_color_layer_t *layers = (hb_ot_color_layer_t*) malloc (num_layers * sizeof (hb_ot_color_layer_t)); - - hb_ot_color_glyph_get_layers (face, gid, 0, &num_layers, layers); - if (num_layers) - { - hb_font_extents_t font_extents; - hb_font_get_extents_for_direction (font, HB_DIRECTION_LTR, &font_extents); - hb_glyph_extents_t extents = {0}; - if (!hb_font_get_glyph_extents (font, gid, &extents)) - { - printf ("Skip gid: %u\n", gid); - continue; - } - - char output_path[255]; - snprintf (output_path, sizeof output_path, "out/colr-%u-%u-%u.svg", gid, palette, face_index); - FILE *f = fopen (output_path, "wb"); - fprintf (f, "\n", - extents.x_bearing, 0, - extents.x_bearing + extents.width, -extents.height); - draw_data_t draw_data; - draw_data.ascender = extents.y_bearing; - draw_data.f = f; - - for (unsigned layer = 0; layer < num_layers; ++layer) - { - hb_color_t color = 0x000000FF; - if (layers[layer].color_index != 0xFFFF) - color = colors[layers[layer].color_index]; - fprintf (f, "\n"); - } - - fprintf (f, ""); - fclose (f); - } - free (layers); - } - - free (colors); - } -} - -static void -dump_glyphs (hb_font_t *font, hb_draw_funcs_t *funcs, unsigned face_index) -{ - unsigned num_glyphs = hb_face_get_glyph_count (hb_font_get_face (font)); - for (unsigned gid = 0; gid < num_glyphs; ++gid) - { - hb_font_extents_t font_extents; - hb_font_get_extents_for_direction (font, HB_DIRECTION_LTR, &font_extents); - hb_glyph_extents_t extents = {0}; - if (!hb_font_get_glyph_extents (font, gid, &extents)) - { - printf ("Skip gid: %u\n", gid); - continue; - } - - char output_path[255]; - snprintf (output_path, sizeof output_path, "out/%u-%u.svg", face_index, gid); - FILE *f = fopen (output_path, "wb"); - fprintf (f, ""); - fclose (f); - } -} - -static void -dump_glyphs (hb_blob_t *blob, const char *font_name) -{ - FILE *font_name_file = fopen ("out/.dumped_font_name", "r"); - if (font_name_file) - { - fprintf (stderr, "Purge or rename ./out folder if you like to run a glyph dump,\n" - "run it like `rm -rf out && mkdir out && src/main font-file.ttf`\n"); - return; - } - - font_name_file = fopen ("out/.dumped_font_name", "w"); - if (!font_name_file) - { - fprintf (stderr, "./out is not accessible as a folder, create it please\n"); - return; - } - fwrite (font_name, 1, strlen (font_name), font_name_file); - fclose (font_name_file); - - hb_draw_funcs_t *funcs = hb_draw_funcs_create (); - hb_draw_funcs_set_move_to_func (funcs, (hb_draw_move_to_func_t) move_to, nullptr, nullptr); - hb_draw_funcs_set_line_to_func (funcs, (hb_draw_line_to_func_t) line_to, nullptr, nullptr); - hb_draw_funcs_set_quadratic_to_func (funcs, (hb_draw_quadratic_to_func_t) quadratic_to, nullptr, nullptr); - hb_draw_funcs_set_cubic_to_func (funcs, (hb_draw_cubic_to_func_t) cubic_to, nullptr, nullptr); - hb_draw_funcs_set_close_path_func (funcs, (hb_draw_close_path_func_t) close_path, nullptr, nullptr); - - unsigned num_faces = hb_face_count (blob); - for (unsigned face_index = 0; face_index < num_faces; ++face_index) - { - hb_face_t *face = hb_face_create (blob, face_index); - hb_font_t *font = hb_font_create (face); - - if (hb_ot_color_has_png (face)) - printf ("Dumping png (CBDT/sbix)...\n"); - png_dump (face, face_index); - - if (hb_ot_color_has_svg (face)) - printf ("Dumping svg (SVG )...\n"); - svg_dump (face, face_index); - - if (hb_ot_color_has_layers (face) && hb_ot_color_has_palettes (face)) - printf ("Dumping layered color glyphs (COLR/CPAL)...\n"); - layered_glyph_dump (font, funcs, face_index); - - dump_glyphs (font, funcs, face_index); - - hb_font_destroy (font); - hb_face_destroy (face); - } - - hb_draw_funcs_destroy (funcs); -} -#endif - -#ifndef MAIN_CC_NO_PRIVATE_API -/* Only this part of this mini app uses private API */ -#include "hb-static.cc" -#include "hb-open-file.hh" -#include "hb-ot-layout-gdef-table.hh" -#include "hb-ot-layout-gsubgpos.hh" - -using namespace OT; - -static void -print_layout_info_using_private_api (hb_blob_t *blob) -{ - const char *font_data = hb_blob_get_data (blob, nullptr); - hb_blob_t *font_blob = hb_sanitize_context_t ().sanitize_blob (blob); - const OpenTypeFontFile* sanitized = font_blob->as (); - if (!font_blob->data) - { - printf ("Sanitization of the file wasn't successful. Exit"); - exit (1); - } - const OpenTypeFontFile& ot = *sanitized; - - switch (ot.get_tag ()) - { - case OpenTypeFontFile::TrueTypeTag: - printf ("OpenType font with TrueType outlines\n"); - break; - case OpenTypeFontFile::CFFTag: - printf ("OpenType font with CFF (Type1) outlines\n"); - break; - case OpenTypeFontFile::TTCTag: - printf ("TrueType Collection of OpenType fonts\n"); - break; - case OpenTypeFontFile::TrueTag: - printf ("Obsolete Apple TrueType font\n"); - break; - case OpenTypeFontFile::Typ1Tag: - printf ("Obsolete Apple Type1 font in SFNT container\n"); - break; - case OpenTypeFontFile::DFontTag: - printf ("DFont Mac Resource Fork\n"); - break; - default: - printf ("Unknown font format\n"); - break; - } - - unsigned num_faces = hb_face_count (blob); - printf ("%u font(s) found in file\n", num_faces); - for (unsigned n_font = 0; n_font < num_faces; ++n_font) - { - const OpenTypeFontFace &font = ot.get_face (n_font); - printf ("Font %u of %u:\n", n_font, num_faces); - - unsigned num_tables = font.get_table_count (); - printf (" %u table(s) found in font\n", num_tables); - for (unsigned n_table = 0; n_table < num_tables; ++n_table) - { - const OpenTypeTable &table = font.get_table (n_table); - printf (" Table %2u of %2u: %.4s (0x%08x+0x%08x)\n", n_table, num_tables, - (const char *) table.tag, - (unsigned) table.offset, - (unsigned) table.length); - - switch (table.tag) - { - - case HB_OT_TAG_GSUB: - case HB_OT_TAG_GPOS: - { - - const GSUBGPOS &g = *reinterpret_cast (font_data + table.offset); - - unsigned num_scripts = g.get_script_count (); - printf (" %u script(s) found in table\n", num_scripts); - for (unsigned n_script = 0; n_script < num_scripts; ++n_script) - { - const Script &script = g.get_script (n_script); - printf (" Script %2u of %2u: %.4s\n", n_script, num_scripts, - (const char *) g.get_script_tag (n_script)); - - if (!script.has_default_lang_sys ()) - printf (" No default language system\n"); - int num_langsys = script.get_lang_sys_count (); - printf (" %d language system(s) found in script\n", num_langsys); - for (int n_langsys = script.has_default_lang_sys () ? -1 : 0; n_langsys < num_langsys; ++n_langsys) - { - const LangSys &langsys = n_langsys == -1 - ? script.get_default_lang_sys () - : script.get_lang_sys (n_langsys); - if (n_langsys == -1) - printf (" Default Language System\n"); - else - printf (" Language System %2d of %2d: %.4s\n", n_langsys, num_langsys, - (const char *) script.get_lang_sys_tag (n_langsys)); - if (!langsys.has_required_feature ()) - printf (" No required feature\n"); - else - printf (" Required feature index: %u\n", - langsys.get_required_feature_index ()); - - unsigned num_features = langsys.get_feature_count (); - printf (" %u feature(s) found in language system\n", num_features); - for (unsigned n_feature = 0; n_feature < num_features; ++n_feature) - { - printf (" Feature index %2u of %2u: %u\n", n_feature, num_features, - langsys.get_feature_index (n_feature)); - } - } - } - - unsigned num_features = g.get_feature_count (); - printf (" %u feature(s) found in table\n", num_features); - for (unsigned n_feature = 0; n_feature < num_features; ++n_feature) - { - const Feature &feature = g.get_feature (n_feature); - unsigned num_lookups = feature.get_lookup_count (); - printf (" Feature %2u of %2u: %c%c%c%c\n", n_feature, num_features, - HB_UNTAG (g.get_feature_tag (n_feature))); - - printf (" %u lookup(s) found in feature\n", num_lookups); - for (unsigned n_lookup = 0; n_lookup < num_lookups; ++n_lookup) { - printf (" Lookup index %2u of %2u: %u\n", n_lookup, num_lookups, - feature.get_lookup_index (n_lookup)); - } - } - - unsigned num_lookups = g.get_lookup_count (); - printf (" %u lookup(s) found in table\n", num_lookups); - for (unsigned n_lookup = 0; n_lookup < num_lookups; ++n_lookup) - { - const Lookup &lookup = g.get_lookup (n_lookup); - printf (" Lookup %2u of %2u: type %u, props 0x%04X\n", n_lookup, num_lookups, - lookup.get_type (), lookup.get_props ()); - } - - } - break; - - case GDEF::tableTag: - { - - const GDEF &gdef = *reinterpret_cast (font_data + table.offset); - - printf (" Has %sglyph classes\n", - gdef.has_glyph_classes () ? "" : "no "); - printf (" Has %smark attachment types\n", - gdef.has_mark_attachment_types () ? "" : "no "); - printf (" Has %sattach list\n", - gdef.has_attach_list () ? "" : "no "); - printf (" Has %slig carets\n", - gdef.has_lig_carets () ? "" : "no "); - printf (" Has %smark glyph sets\n", - gdef.has_mark_glyph_sets () ? "" : "no "); - break; - } - } - } - } -} -/* end of private API use */ -#endif - -int -main (int argc, char **argv) -{ - if (argc != 2) - { - fprintf (stderr, "usage: %s font-file.ttf\n", argv[0]); - exit (1); - } - - hb_blob_t *blob = hb_blob_create_from_file_or_fail (argv[1]); - assert (blob); - printf ("Opened font file %s: %u bytes long\n", argv[1], hb_blob_get_length (blob)); -#ifndef MAIN_CC_NO_PRIVATE_API - print_layout_info_using_private_api (blob); -#endif -#if !defined(HB_NO_COLOR) && !defined(HB_NO_DRAW) - dump_glyphs (blob, argv[1]); -#endif - hb_blob_destroy (blob); - - return 0; -} diff --git a/src/3rdparty/harfbuzz-ng/src/test.cc b/src/3rdparty/harfbuzz-ng/src/test.cc deleted file mode 100644 index f7e4e7ecde8..00000000000 --- a/src/3rdparty/harfbuzz-ng/src/test.cc +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright © 2010,2011 Google, Inc. - * - * This is part of HarfBuzz, a text shaping library. - * - * Permission is hereby granted, without written agreement and without - * license or royalty fees, to use, copy, modify, and distribute this - * software and its documentation for any purpose, provided that the - * above copyright notice and the following two paragraphs appear in - * all copies of this software. - * - * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR - * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES - * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN - * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH - * DAMAGE. - * - * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, - * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS - * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO - * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. - * - * Google Author(s): Behdad Esfahbod - */ - -#include "hb.hh" - -#ifdef HAVE_FREETYPE -#include "hb-ft.h" -#endif - -#ifdef HB_NO_OPEN -#define hb_blob_create_from_file_or_fail(x) hb_blob_get_empty () -#endif - -int -main (int argc, char **argv) -{ - if (argc != 2) { - fprintf (stderr, "usage: %s font-file.ttf\n", argv[0]); - exit (1); - } - - hb_blob_t *blob = hb_blob_create_from_file_or_fail (argv[1]); - assert (blob); - printf ("Opened font file %s: %u bytes long\n", argv[1], hb_blob_get_length (blob)); - - /* Create the face */ - hb_face_t *face = hb_face_create (blob, 0 /* first face */); - hb_blob_destroy (blob); - blob = nullptr; - unsigned int upem = hb_face_get_upem (face); - - hb_font_t *font = hb_font_create (face); - hb_font_set_scale (font, upem, upem); - -#ifdef HAVE_FREETYPE - hb_ft_font_set_funcs (font); -#endif - - hb_buffer_t *buffer = hb_buffer_create (); - - hb_buffer_add_utf8 (buffer, "\xe0\xa4\x95\xe0\xa5\x8d\xe0\xa4\xb0\xe0\xa5\x8d\xe0\xa4\x95", -1, 0, -1); - hb_buffer_guess_segment_properties (buffer); - - hb_shape (font, buffer, nullptr, 0); - - unsigned int count = hb_buffer_get_length (buffer); - hb_glyph_info_t *infos = hb_buffer_get_glyph_infos (buffer, nullptr); - hb_glyph_position_t *positions = hb_buffer_get_glyph_positions (buffer, nullptr); - - for (unsigned int i = 0; i < count; i++) - { - hb_glyph_info_t *info = &infos[i]; - hb_glyph_position_t *pos = &positions[i]; - - printf ("cluster %u glyph 0x%x at (%d,%d)+(%d,%d)\n", - info->cluster, - info->codepoint, - pos->x_offset, - pos->y_offset, - pos->x_advance, - pos->y_advance); - - } - - hb_buffer_destroy (buffer); - hb_font_destroy (font); - hb_face_destroy (face); - - return 0; -} - - From ef07474a2a9b5124331e75f7f96b1a52caf81557 Mon Sep 17 00:00:00 2001 From: Sze Howe Koh Date: Sun, 4 Jun 2023 23:01:04 +0800 Subject: [PATCH 006/151] Doc: Clarify how to use QPainter with QTextEdit The documentation suggests that it is possible to reimplement QTextEdit::paintEvent(), but doing so might produce cryptic runtime warnings: QWidget::paintEngine: Should no longer be called QPainter::begin: Paint device returned engine == 0, type: 1 The correct way to reimplement this function is noted under QAbstractScrollArea::paintEvent(). This patch updates the note and copies it to QTextEdit for clarity. Change-Id: Ib7d8dadeb2358475bcdb0b2e624857700f9a004e Reviewed-by: Safiyyah Moosa Reviewed-by: Andreas Eliasson Reviewed-by: Volker Hilsheimer (cherry picked from commit 5a2474b2dd0472948c53b16c4bf566db489dcfb9) Reviewed-by: Qt Cherry-pick Bot --- src/widgets/widgets/qabstractscrollarea.cpp | 2 +- src/widgets/widgets/qtextedit.cpp | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/widgets/widgets/qabstractscrollarea.cpp b/src/widgets/widgets/qabstractscrollarea.cpp index 932c15435d6..ae0e31b1934 100644 --- a/src/widgets/widgets/qabstractscrollarea.cpp +++ b/src/widgets/widgets/qabstractscrollarea.cpp @@ -1136,7 +1136,7 @@ void QAbstractScrollArea::resizeEvent(QResizeEvent *) This event handler can be reimplemented in a subclass to receive paint events (passed in \a event), for the viewport() widget. - \note If you open a painter, make sure to open it on the viewport(). + \note If you create a QPainter, it must operate on the viewport(). \sa QWidget::paintEvent() */ diff --git a/src/widgets/widgets/qtextedit.cpp b/src/widgets/widgets/qtextedit.cpp index 90119fe65a4..4a474cb945f 100644 --- a/src/widgets/widgets/qtextedit.cpp +++ b/src/widgets/widgets/qtextedit.cpp @@ -1634,6 +1634,8 @@ void QTextEditPrivate::paint(QPainter *p, QPaintEvent *e) This event handler can be reimplemented in a subclass to receive paint events passed in \a event. It is usually unnecessary to reimplement this function in a subclass of QTextEdit. +\note If you create a QPainter, it must operate on the \l{QAbstractScrollArea::}{viewport()}. + \warning The underlying text document must not be modified from within a reimplementation of this function. */ From cbcd7aa394c11ea7298adab7f5f1203ffab61085 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Wed, 7 Jun 2023 15:50:17 +0200 Subject: [PATCH 007/151] qnetworkreplyfileimpl_p.h: fix header guard name It was missing the _P. Change-Id: Ic07b4145f06ba3b1bea52349cf9b3f8215f30313 Reviewed-by: Thiago Macieira Reviewed-by: Fabian Kosmale (cherry picked from commit b2244a252ca36da3b566112464655a70e887f178) Reviewed-by: Qt Cherry-pick Bot --- src/network/access/qnetworkreplyfileimpl_p.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/network/access/qnetworkreplyfileimpl_p.h b/src/network/access/qnetworkreplyfileimpl_p.h index 5cc810eea51..ad798da01e1 100644 --- a/src/network/access/qnetworkreplyfileimpl_p.h +++ b/src/network/access/qnetworkreplyfileimpl_p.h @@ -37,8 +37,8 @@ ** ******************************************************************************/ -#ifndef QNETWORKREPLYFILEIMPL_H -#define QNETWORKREPLYFILEIMPL_H +#ifndef QNETWORKREPLYFILEIMPL_P_H +#define QNETWORKREPLYFILEIMPL_P_H // // W A R N I N G @@ -99,4 +99,4 @@ QT_END_NAMESPACE Q_DECLARE_METATYPE(QNetworkRequest::KnownHeaders) -#endif // QNETWORKREPLYFILEIMPL_H +#endif // QNETWORKREPLYFILEIMPL_P_H From 6bb1a8480be43a74a33326dda14f3d7996958832 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A5rten=20Nordheim?= Date: Fri, 26 May 2023 12:49:06 +0200 Subject: [PATCH 008/151] tst_QSslSocket: ignore order of sslErrors list In Schannel it is not guaranteed CertificateBlacklisted will be the first error emitted. And it really does not make a difference anyway. Change-Id: If041f913db9e78ac54e6f8bb2ba1bda110e7d64a Reviewed-by: Timur Pocheptsov (cherry picked from commit e09b1373c2b761f20cd930f95119306d59068c80) Reviewed-by: Qt Cherry-pick Bot --- tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp b/tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp index afcf5fe722c..bfa679cc601 100644 --- a/tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp +++ b/tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp @@ -3058,7 +3058,14 @@ void tst_QSslSocket::blacklistedCertificates() QList sslErrors = receiver->sslHandshakeErrors(); QVERIFY(sslErrors.count() > 0); // there are more errors (self signed cert and hostname mismatch), but we only care about the blacklist error - QCOMPARE(sslErrors.at(0).error(), QSslError::CertificateBlacklisted); + std::optional blacklistedError; + for (const QSslError &error : sslErrors) { + if (error.error() == QSslError::CertificateBlacklisted) { + blacklistedError = error; + break; + } + } + QVERIFY2(blacklistedError, "CertificateBlacklisted error not found!"); } void tst_QSslSocket::versionAccessors() From fe0c1f110fd4ec45536b46d56f55def9cb1766bb Mon Sep 17 00:00:00 2001 From: Axel Spoerl Date: Sun, 23 Apr 2023 13:39:02 +0200 Subject: [PATCH 009/151] iOS: Ignore next touch event if keyboard has lost focus during touch If the iOS virtual keyboard as lost focus because it was slided down, the next touch event on an inactive screen area will be mapped to the keyboard. This kicks an assertion, because the keyboard is expected to be visible. The case that the keyboard has been deactivated by sliding it down is not covered. This patch replaces the assertion by setting self.enabled to NO, which reflects the keyboard deactivation. Fixes: QTBUG-112246 Change-Id: I4873b7a702178acfd3cb8c988134facc050d642a Reviewed-by: Timur Pocheptsov (cherry picked from commit 58ea69aaab62f31247dcd9b12f55de8fc001ea3a) Reviewed-by: Qt Cherry-pick Bot --- src/plugins/platforms/ios/qiosinputcontext.mm | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/plugins/platforms/ios/qiosinputcontext.mm b/src/plugins/platforms/ios/qiosinputcontext.mm index 3398f778a66..28674a5e90c 100644 --- a/src/plugins/platforms/ios/qiosinputcontext.mm +++ b/src/plugins/platforms/ios/qiosinputcontext.mm @@ -210,7 +210,11 @@ static QUIView *focusView() { [super touchesBegan:touches withEvent:event]; - Q_ASSERT(m_context->isInputPanelVisible()); + if (!m_context->isInputPanelVisible()) { + qImDebug("keyboard was hidden by sliding it down, disabling hide-keyboard gesture"); + self.enabled = NO; + return; + } if ([touches count] != 1) self.state = UIGestureRecognizerStateFailed; From 09b46a9f331df44e771ad2fe55a0379b7f44f9a7 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Mon, 5 Jun 2023 22:15:14 +0200 Subject: [PATCH 010/151] QPixmapCache: fix leaking of QStrings and Keys on clear() QPixmapCache maintains a mapping from QString to QPixmapCache::Key, in the form of the cacheKeys QHash, but QPixmapCache::clear() didn't touch it, leading to the string data (as well as the Keys) being retained after any possible use. This can lead to memory slowly being eaten up, as reported in QTBUG-112200, and prevents a periodic calling of QPixmapCache::clear() from being a work-around for the issue in the bug report. Fix by clearing cacheKeys in QPixmapCache::clear(). This is designed as a low-risk enabler of a work-around, not a fix for the issue. The work-around enabled by this is periodic calling of QPixmapCache::clear(). [ChangeLog][QtGui][QPixmapCache] Fixed QString key data not being freed on clear(). Manual conflict resolutions: - u""_s -> QStringLiteral - QCOMPARE_LT -> QVERIFY( < ) Task-number: QTBUG-112200 Change-Id: Ica6fa0e27e1b47b8df58d5e996378a2ececa5f9c Reviewed-by: Volker Hilsheimer Reviewed-by: Qt CI Bot (cherry picked from commit 6ab0d25a09f5aeb7a5a062f7fd44e95ca761e21e) --- src/gui/image/qpixmapcache.cpp | 1 + .../image/qpixmapcache/tst_qpixmapcache.cpp | 34 +++++++++++++++++++ 2 files changed, 35 insertions(+) diff --git a/src/gui/image/qpixmapcache.cpp b/src/gui/image/qpixmapcache.cpp index dee020d40e0..92c48dd0bac 100644 --- a/src/gui/image/qpixmapcache.cpp +++ b/src/gui/image/qpixmapcache.cpp @@ -473,6 +473,7 @@ void QPMCache::clear() killTimer(theid); theid = 0; } + cacheKeys.clear(); } QPixmapCache::KeyData* QPMCache::getKeyData(QPixmapCache::Key *key) diff --git a/tests/auto/gui/image/qpixmapcache/tst_qpixmapcache.cpp b/tests/auto/gui/image/qpixmapcache/tst_qpixmapcache.cpp index a87ec5d0250..c28db8b814f 100644 --- a/tests/auto/gui/image/qpixmapcache/tst_qpixmapcache.cpp +++ b/tests/auto/gui/image/qpixmapcache/tst_qpixmapcache.cpp @@ -55,6 +55,7 @@ private slots: void clear(); void pixmapKey(); void noLeak(); + void clearDoesNotLeakStringKeys(); void strictCacheLimit(); void noCrashOnLargeInsert(); }; @@ -503,6 +504,39 @@ void tst_QPixmapCache::noLeak() QCOMPARE(oldSize, newSize); } +void tst_QPixmapCache::clearDoesNotLeakStringKeys() +{ + QPixmapCache::setCacheLimit(20); // 20KiB + // + // GIVEN: a QPixmap with QString key `key` in QPixmapCache + // + QString key; + { + QPixmap pm(64, 64); + QVERIFY(pm.width() * pm.height() * std::ceil(pm.depth() / 8.0) + < QPixmapCache::cacheLimit() * 1024); + pm.fill(Qt::transparent); + key = QStringLiteral("theKey").repeated(20); // avoid eventual QString SSO + QVERIFY(key.isDetached()); + QPixmapCache::insert(key, pm); + } + QVERIFY(!key.isDetached()); // was saved inside QPixmapCache + + // + // WHEN: clearing the cache: + // + QPixmapCache::clear(); + + // + // THEN: `key` is no longer referenced by QPixmapCache: + // + QVERIFY(key.isDetached()); + // verify that the pixmap is really gone from the cache + // (do it after the key check, because QPixmapCache cleans up `key` on a failed lookup) + QPixmap r; + QVERIFY(!QPixmapCache::find(key, &r)); +} + void tst_QPixmapCache::strictCacheLimit() { From 41389ce13a16821e43272310d6ed2da219d47cb6 Mon Sep 17 00:00:00 2001 From: Volker Hilsheimer Date: Tue, 6 Jun 2023 13:17:37 +0200 Subject: [PATCH 011/151] QMenu: don't crash when nested tear-off menus are closed QMenu's causedStack maintains a list of menus on the way to the menu, and might contain nullptr if one of the entries was a tear-off menu that got closed (and thus destroyed, due to DeleteOnClose). If the entry we get from the stack is nullptr, fall back to the passed- in parent widget pointer, and test for nullptr before accessing. Add a test case that crashes without the fix. Fixes: QTBUG-112217 Change-Id: I958182db47c3cc8733e1780f7efef43881ffae11 Reviewed-by: Axel Spoerl (cherry picked from commit f0049873d2ce0742a2df7ce265db70ca8baa8442) Reviewed-by: Volker Hilsheimer --- src/widgets/widgets/qmenu.cpp | 4 +- .../auto/widgets/widgets/qmenu/tst_qmenu.cpp | 78 +++++++++++++++++++ 2 files changed, 81 insertions(+), 1 deletion(-) diff --git a/src/widgets/widgets/qmenu.cpp b/src/widgets/widgets/qmenu.cpp index 8de375106b4..ba93f53aecc 100644 --- a/src/widgets/widgets/qmenu.cpp +++ b/src/widgets/widgets/qmenu.cpp @@ -129,7 +129,9 @@ public: Q_D(QTornOffMenu); // make the torn-off menu a sibling of p (instead of a child) QWidget *parentWidget = d->causedStack.isEmpty() ? p : d->causedStack.constLast(); - if (parentWidget->parentWidget()) + if (!parentWidget && p) + parentWidget = p; + if (parentWidget && parentWidget->parentWidget()) parentWidget = parentWidget->parentWidget(); setParent(parentWidget, Qt::Window | Qt::Tool); setAttribute(Qt::WA_DeleteOnClose, true); diff --git a/tests/auto/widgets/widgets/qmenu/tst_qmenu.cpp b/tests/auto/widgets/widgets/qmenu/tst_qmenu.cpp index c17980e2e31..48a5593e95c 100644 --- a/tests/auto/widgets/widgets/qmenu/tst_qmenu.cpp +++ b/tests/auto/widgets/widgets/qmenu/tst_qmenu.cpp @@ -137,6 +137,8 @@ private slots: void screenOrientationChangedCloseMenu(); void deleteWhenTriggered(); + void nestedTearOffDetached(); + protected slots: void onActivated(QAction*); void onHighlighted(QAction*); @@ -1995,5 +1997,81 @@ void tst_QMenu::deleteWhenTriggered() QTRY_VERIFY(!menu); } +/* + QMenu uses the caused-stack to create the parent/child relationship + for tear-off menus. Since QTornOffMenu set the DeleteOnClose flag, closing a + tear-off in the parent chain will result in a null-pointer in the caused-stack. + Verify that we don't crash when traversing the chain, as reported in QTBUG-112217. + + The test has to open the submenus by hovering of the menu action, otherwise + the caused-stack remains empty and the issue doesn't reproduce. Due to QMenu's + timing and "sloppiness", we need to move the mouse within the action, with some + waiting and event processing in between to trigger the opening of the submenu. + If this fails we skip, as we then can't test what we are trying to test. +*/ +void tst_QMenu::nestedTearOffDetached() +{ + // Since QTornOffMenu is not declared in qmenuprivate.h we can't access the + // object even through QMenuPrivate. So use an event filter to watch out for + // a QTornOffMenu showing. + class TearOffWatcher : public QObject + { + public: + QMenu *tornOffMenu = nullptr; + protected: + bool eventFilter(QObject *receiver, QEvent *event) { + if (event->type() == QEvent::Show && receiver->inherits("QTornOffMenu")) + tornOffMenu = qobject_cast(receiver); + return QObject::eventFilter(receiver, event); + } + } watcher; + qApp->installEventFilter(&watcher); + + QWidget widget; + QMenu *menu = new QMenu("Context", &widget); + + MenuMetrics mm(menu); + const int tearOffOffset = mm.fw + mm.vmargin + mm.tearOffHeight / 2; + + QMenu *subMenu = menu->addMenu("SubMenu"); + menu->setTearOffEnabled(true); + QMenu *subSubMenu = subMenu->addMenu("SubSubMenu"); + subMenu->setTearOffEnabled(true); + subSubMenu->addAction("Action!"); + subSubMenu->setTearOffEnabled(true); + + widget.show(); + QVERIFY(QTest::qWaitForWindowExposed(&widget)); + + // open and tear off context menu + menu->popup(widget.geometry().center()); + QTest::mouseClick(menu, Qt::LeftButton, {}, QPoint(menu->width() / 2, tearOffOffset)); + + QMenu *menuTorn = watcher.tornOffMenu; + watcher.tornOffMenu = nullptr; + QVERIFY(menuTorn); + QVERIFY(QTest::qWaitForWindowExposed(menuTorn)); + + // open second menu and tear-off + QTest::mouseMove(menuTorn, menuTorn->actionGeometry(subMenu->menuAction()).topLeft()); + QTest::qWait(100); + QTest::mouseMove(menuTorn, menuTorn->actionGeometry(subMenu->menuAction()).center()); + if (!QTest::qWaitFor([subMenu]{ return subMenu->isVisible(); })) + QSKIP("Menu failed to show, skipping test"); + + QTest::mouseClick(subMenu, Qt::LeftButton, {}, QPoint(subMenu->width() / 2, tearOffOffset)); + menuTorn = watcher.tornOffMenu; + QVERIFY(menuTorn); + QVERIFY(QTest::qWaitForWindowExposed(menuTorn)); + // close the top level tear off + menu->hideTearOffMenu(); + // open third menu and tear-off + QTest::mouseMove(menuTorn, menuTorn->actionGeometry(subSubMenu->menuAction()).topLeft()); + QTest::qWait(100); + QTest::mouseMove(menuTorn, menuTorn->actionGeometry(subSubMenu->menuAction()).center()); + QTRY_VERIFY(subSubMenu->isVisible()); + QTest::mouseClick(subSubMenu, Qt::LeftButton, {}, QPoint(subSubMenu->width() / 2, tearOffOffset)); +} + QTEST_MAIN(tst_QMenu) #include "tst_qmenu.moc" From fd1c04fda78db6b87eafe646ecdcfe83a66f6e0d Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Wed, 7 Jun 2023 16:33:17 +0200 Subject: [PATCH 012/151] tst_QPixmapCache: rewrite QVERIFY(x != 0) to QVERIFY(x) This is just confusing. QPixmapCache::find() already returns bool, comparing it to a literal zero just makes it hard to read. Change-Id: I43c000890377cca2111daa48799f10cc99aad8cf Reviewed-by: Volker Hilsheimer (cherry picked from commit 6032845ca2fc69fb67971ea9f7e06588ffcbe9f3) Reviewed-by: Qt Cherry-pick Bot --- .../image/qpixmapcache/tst_qpixmapcache.cpp | 32 +++++++++---------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/tests/auto/gui/image/qpixmapcache/tst_qpixmapcache.cpp b/tests/auto/gui/image/qpixmapcache/tst_qpixmapcache.cpp index c28db8b814f..a33cc2a3785 100644 --- a/tests/auto/gui/image/qpixmapcache/tst_qpixmapcache.cpp +++ b/tests/auto/gui/image/qpixmapcache/tst_qpixmapcache.cpp @@ -124,16 +124,16 @@ void tst_QPixmapCache::setCacheLimit() //The int part of the API p1 = new QPixmap(2, 3); QPixmapCache::Key key = QPixmapCache::insert(*p1); - QVERIFY(QPixmapCache::find(key, p1) != 0); + QVERIFY(QPixmapCache::find(key, p1)); delete p1; QPixmapCache::setCacheLimit(0); - QVERIFY(QPixmapCache::find(key, p1) == 0); + QVERIFY(!QPixmapCache::find(key, p1)); p1 = new QPixmap(2, 3); QPixmapCache::setCacheLimit(1000); QPixmapCache::replace(key, *p1); - QVERIFY(QPixmapCache::find(key, p1) == 0); + QVERIFY(!QPixmapCache::find(key, p1)); delete p1; @@ -142,10 +142,10 @@ void tst_QPixmapCache::setCacheLimit() QPixmapCache::clear(); p1 = new QPixmap(2, 3); key = QPixmapCache::insert(*p1); - QVERIFY(QPixmapCache::find(key, p1) != 0); + QVERIFY(QPixmapCache::find(key, p1)); p1->detach(); // dectach so that the cache thinks no-one is using it. QPixmapCache::setCacheLimit(0); - QVERIFY(QPixmapCache::find(key, p1) == 0); + QVERIFY(!QPixmapCache::find(key, p1)); QPixmapCache::setCacheLimit(1000); key = QPixmapCache::insert(*p1); QVERIFY(key.isValid()); @@ -159,7 +159,7 @@ void tst_QPixmapCache::setCacheLimit() QPixmap p2; p1 = new QPixmap(2, 3); key = QPixmapCache::insert(*p1); - QVERIFY(QPixmapCache::find(key, &p2) != 0); + QVERIFY(QPixmapCache::find(key, &p2)); //we flush the cache p1->detach(); p2.detach(); @@ -167,8 +167,8 @@ void tst_QPixmapCache::setCacheLimit() QPixmapCache::setCacheLimit(1000); QPixmapCache::Key key2 = QPixmapCache::insert(*p1); QCOMPARE(getPrivate(key2)->key, 1); - QVERIFY(QPixmapCache::find(key, &p2) == 0); - QVERIFY(QPixmapCache::find(key2, &p2) != 0); + QVERIFY(!QPixmapCache::find(key, &p2)); + QVERIFY(QPixmapCache::find(key2, &p2)); QCOMPARE(p2, *p1); delete p1; @@ -191,7 +191,7 @@ void tst_QPixmapCache::setCacheLimit() QCOMPARE(getPrivate(key2)->key, 1); //This old key is not valid anymore after the flush QVERIFY(!key.isValid()); - QVERIFY(QPixmapCache::find(key, &p2) == 0); + QVERIFY(!QPixmapCache::find(key, &p2)); delete p1; } @@ -229,7 +229,7 @@ void tst_QPixmapCache::find() QPixmapCache::insert(p5); //at that time the first key has been erase because no more place in the cache - QVERIFY(QPixmapCache::find(key, &p1) == 0); + QVERIFY(!QPixmapCache::find(key, &p1)); QVERIFY(!key.isValid()); } @@ -362,11 +362,11 @@ void tst_QPixmapCache::remove() QVERIFY(p1.toImage() == p1.toImage()); // sanity check QPixmapCache::remove(key); - QVERIFY(QPixmapCache::find(key, &p1) == 0); + QVERIFY(!QPixmapCache::find(key, &p1)); //Broken key QPixmapCache::remove(QPixmapCache::Key()); - QVERIFY(QPixmapCache::find(QPixmapCache::Key(), &p1) == 0); + QVERIFY(!QPixmapCache::find(QPixmapCache::Key(), &p1)); //Test if keys are release QPixmapCache::clear(); @@ -380,7 +380,7 @@ void tst_QPixmapCache::remove() QPixmapCache::clear(); key = QPixmapCache::insert(p1); QCOMPARE(getPrivate(key)->key, 1); - QVERIFY(QPixmapCache::find(key, &p1) != 0); + QVERIFY(QPixmapCache::find(key, &p1)); QPixmapCache::remove(key); QCOMPARE(p1.isDetached(), true); @@ -390,8 +390,8 @@ void tst_QPixmapCache::remove() QPixmapCache::insert("red", p1); key = QPixmapCache::insert(p1); QPixmapCache::remove(key); - QVERIFY(QPixmapCache::find(key, &p1) == 0); - QVERIFY(QPixmapCache::find("red", &p1) != 0); + QVERIFY(!QPixmapCache::find(key, &p1)); + QVERIFY(QPixmapCache::find("red", &p1)); } void tst_QPixmapCache::clear() @@ -435,7 +435,7 @@ void tst_QPixmapCache::clear() QPixmapCache::clear(); for (int k = 0; k < numberOfKeys; ++k) { - QVERIFY(QPixmapCache::find(keys.at(k), &p1) == 0); + QVERIFY(!QPixmapCache::find(keys.at(k), &p1)); QVERIFY(!keys[k].isValid()); } } From 04d26e8a5c3f6bd6499706b8d89643bfec2968dc Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Wed, 7 Jun 2023 07:29:31 +0200 Subject: [PATCH 013/151] QPixmapCache: add a comment on how failed insert() invalidates cacheKey It wasn't obvious to me, at least, and I only found out about it when I failed to construct a test failure based on this. Change-Id: I339132d7bb2cb8a76f0f1feec37891d6131c4d7b Reviewed-by: Volker Hilsheimer (cherry picked from commit 588ca25e4a31642bf8d18cd1948c50fa514ac0a7) Reviewed-by: Qt Cherry-pick Bot --- src/gui/image/qpixmapcache.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/image/qpixmapcache.cpp b/src/gui/image/qpixmapcache.cpp index 92c48dd0bac..3afa9401d4c 100644 --- a/src/gui/image/qpixmapcache.cpp +++ b/src/gui/image/qpixmapcache.cpp @@ -374,7 +374,7 @@ bool QPMCache::insert(const QString& key, const QPixmap &pixmap, int cost) QPixmapCache::Key QPMCache::insert(const QPixmap &pixmap, int cost) { - QPixmapCache::Key cacheKey = createKey(); + QPixmapCache::Key cacheKey = createKey(); // invalidated by ~QPixmapCacheEntry on failed insert bool success = QCache::insert(cacheKey, new QPixmapCacheEntry(cacheKey, pixmap), cost); if (success) { if (!theid) { From 710fece56007b26eb607368659c05e73d99b39fc Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Wed, 7 Jun 2023 07:15:30 +0200 Subject: [PATCH 014/151] tst_QPixmapCache: check insert() reports failure None of the existing tests failed when I started to return a valid key from a failed insert(QPixmap), so add a test that would fail. Manual conflict resolutions: - QCOMPARE_GT() -> QVERIFY( > ) - u""_s -> QStringLiteral Change-Id: I74f23d2ec4c04151f8f1266c0c503713d4642f3a Reviewed-by: Qt CI Bot Reviewed-by: Volker Hilsheimer (cherry picked from commit e409d771d922b9772a0ecb4da575c6fd6f95676f) --- .../image/qpixmapcache/tst_qpixmapcache.cpp | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/tests/auto/gui/image/qpixmapcache/tst_qpixmapcache.cpp b/tests/auto/gui/image/qpixmapcache/tst_qpixmapcache.cpp index a33cc2a3785..6dde306bbdc 100644 --- a/tests/auto/gui/image/qpixmapcache/tst_qpixmapcache.cpp +++ b/tests/auto/gui/image/qpixmapcache/tst_qpixmapcache.cpp @@ -50,6 +50,7 @@ private slots: void setCacheLimit(); void find(); void insert(); + void failedInsertReturnsInvalidKey(); void replace(); void remove(); void clear(); @@ -288,6 +289,7 @@ void tst_QPixmapCache::insert() for (int i = 0; i < numberOfKeys; ++i) { QPixmap p3(10,10); keys.append(QPixmapCache::insert(p3)); + QVERIFY(keys.back().isValid()); } num = 0; @@ -301,6 +303,32 @@ void tst_QPixmapCache::insert() QVERIFY(num <= estimatedNum); } +void tst_QPixmapCache::failedInsertReturnsInvalidKey() +{ + // + // GIVEN: a pixmap whose memory footprint exceeds the cache's limit: + // + QPixmapCache::setCacheLimit(20); + + QPixmap pm(256, 256); + pm.fill(Qt::transparent); + QVERIFY(pm.width() * pm.height() * pm.depth() / 8 + > QPixmapCache::cacheLimit() * 1024); + + // + // WHEN: trying to add this pixmap to the cache + // + const auto success = QPixmapCache::insert(QStringLiteral("foo"), pm); // QString API + { QPixmap r; QVERIFY(!QPixmapCache::find(QStringLiteral("foo"), &r)); } + const auto key = QPixmapCache::insert(pm); // "int" API + + // + // THEN: failure is reported to the user + // + QVERIFY(!key.isValid()); // "int" API + QVERIFY(!success); // QString API +} + void tst_QPixmapCache::replace() { //The int part of the API From 07776612c85a5e782d79fea7ef080ce60734edd2 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Wed, 7 Jun 2023 17:34:59 +0200 Subject: [PATCH 015/151] tst_QPixmapCache: QVERIFY a failed replace() Between the find() == 0 obfuscation (since fixed) and this unchecked replace(), it took me way too much time to figure out what was going on: the key passed has been invalidated by the setCacheLimit(0). Now that we QVERIFY that the replace() _fails_, it's much easier to backtrack and figure out why it does so and why, consequently, the following find() is also expected to fail. As a drive-by, reorder two lines so the grouping becomes clearer (blocks now both headed by setCacheLimit()). Change-Id: I434b65fc13c3fed6512036efeb98d738eeb2a13d Reviewed-by: Volker Hilsheimer (cherry picked from commit 0e96dd3464bc2e03d66ebb574a7a5352942ffdb2) Reviewed-by: Qt Cherry-pick Bot --- tests/auto/gui/image/qpixmapcache/tst_qpixmapcache.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/auto/gui/image/qpixmapcache/tst_qpixmapcache.cpp b/tests/auto/gui/image/qpixmapcache/tst_qpixmapcache.cpp index 6dde306bbdc..b5602192707 100644 --- a/tests/auto/gui/image/qpixmapcache/tst_qpixmapcache.cpp +++ b/tests/auto/gui/image/qpixmapcache/tst_qpixmapcache.cpp @@ -131,9 +131,9 @@ void tst_QPixmapCache::setCacheLimit() QPixmapCache::setCacheLimit(0); QVERIFY(!QPixmapCache::find(key, p1)); - p1 = new QPixmap(2, 3); QPixmapCache::setCacheLimit(1000); - QPixmapCache::replace(key, *p1); + p1 = new QPixmap(2, 3); + QVERIFY(!QPixmapCache::replace(key, *p1)); QVERIFY(!QPixmapCache::find(key, p1)); delete p1; From f1f5c5ce2815d12f1ed966d50a4fca7dc6cca02b Mon Sep 17 00:00:00 2001 From: Amir Masoud Abdol Date: Fri, 9 Jun 2023 10:33:38 +0200 Subject: [PATCH 016/151] Fix the issue with setting the QT_BUILDING_QT `TYPE` argument is not a thing, and if it is there, QT_BUILDING_QT is set to `TRUE;CACHE;TYPE;STRING;When this is present and set to true, it signals that we are building Qt from source.` instead of `TRUE`. Change-Id: I24784e9aead4929d408d06bce72d3f33ee21eb63 Reviewed-by: Alexandru Croitor (cherry picked from commit 5d12d9846a9436b4ef4e1f8ac42d081d60568ecf) Reviewed-by: Qt Cherry-pick Bot --- cmake/QtSetup.cmake | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmake/QtSetup.cmake b/cmake/QtSetup.cmake index a8cbbd13869..34137b65702 100644 --- a/cmake/QtSetup.cmake +++ b/cmake/QtSetup.cmake @@ -2,8 +2,8 @@ # Set the QT_IS_BUILDING_QT variable so we can verify whether we are building # Qt from source -set(QT_BUILDING_QT TRUE CACHE - TYPE STRING "When this is present and set to true, it signals that we are building Qt from source.") +set(QT_BUILDING_QT TRUE CACHE BOOL + "When this is present and set to true, it signals that we are building Qt from source.") # Pre-calculate the developer_build feature if it's set by the user via INPUT_developer_build if(NOT FEATURE_developer_build AND INPUT_developer_build From 3edc726cd075d383c96e925fa5b64f82ae5d7ba1 Mon Sep 17 00:00:00 2001 From: Heikki Halmet Date: Fri, 9 Jun 2023 11:57:26 +0000 Subject: [PATCH 017/151] Add feature to disable building tests IFW requires static build of Qt which does not build tests on all configurations. This allows building modules without them building tests. Previously IFW used 5.15 repos, those build tests in test workitem, not running into the issue. This is only relevant if the tested repo i.e IFW implements it's own test instructions. Change-Id: I1e03f3b577d7be314f92ed3989e5f6daf2a46da1 Reviewed-by: Toni Saario (cherry picked from commit 409aa8d097a424c6281653d8c4dc3bc1c46054ed) Reviewed-by: Qt Cherry-pick Bot --- .../cmake_build_and_upload_test_artifacts_host.yaml | 11 ++++++++--- .../cmake_build_and_upload_test_artifacts_target.yaml | 11 ++++++++--- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/coin/instructions/cmake_build_and_upload_test_artifacts_host.yaml b/coin/instructions/cmake_build_and_upload_test_artifacts_host.yaml index 3592ac42702..bc16368fc2d 100644 --- a/coin/instructions/cmake_build_and_upload_test_artifacts_host.yaml +++ b/coin/instructions/cmake_build_and_upload_test_artifacts_host.yaml @@ -13,6 +13,11 @@ instructions: variableValue: "{{.Env.COMMON_TEST_CMAKE_ARGS}}" - !include "{{qt/qtbase}}/cmake_build_and_upload_test_artifacts.yaml" disable_if: - condition: property - property: features - contains_value: DisableTests + condition: or + conditions: + - condition: property + property: features + contains_value: DisableTests + - condition: property + property: features + contains_value: DoNotBuildTests diff --git a/coin/instructions/cmake_build_and_upload_test_artifacts_target.yaml b/coin/instructions/cmake_build_and_upload_test_artifacts_target.yaml index 8c3dfe14e13..73386681953 100644 --- a/coin/instructions/cmake_build_and_upload_test_artifacts_target.yaml +++ b/coin/instructions/cmake_build_and_upload_test_artifacts_target.yaml @@ -24,6 +24,11 @@ instructions: variableValue: "{{.Env.COMMON_TARGET_TEST_CMAKE_ARGS}}" - !include "{{qt/qtbase}}/cmake_build_and_upload_test_artifacts.yaml" disable_if: - condition: property - property: features - contains_value: DisableTests + condition: or + conditions: + - condition: property + property: features + contains_value: DisableTests + - condition: property + property: features + contains_value: DoNotBuildTests From be8f2e43116a2edfae709e2c99009c3bad26f872 Mon Sep 17 00:00:00 2001 From: Amir Masoud Abdol Date: Mon, 12 Jun 2023 10:37:01 +0200 Subject: [PATCH 018/151] Silence a warning in EGL check There is a chance that an unused variable warning will be treated as an error, and in that case, this check will fail, and as a result FindEGL will fail. Fixes: QTBUG-114431 Change-Id: Iaac49589144dbe4172ec58c6705a9f899c25f01f Reviewed-by: Alexey Edelev (cherry picked from commit 14b01b0aadfac07e2a87cea4af0b09b874ffa100) Reviewed-by: Qt Cherry-pick Bot --- cmake/3rdparty/extra-cmake-modules/find-modules/FindEGL.cmake | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cmake/3rdparty/extra-cmake-modules/find-modules/FindEGL.cmake b/cmake/3rdparty/extra-cmake-modules/find-modules/FindEGL.cmake index 0733f1f702c..9ac8e2fa0cf 100644 --- a/cmake/3rdparty/extra-cmake-modules/find-modules/FindEGL.cmake +++ b/cmake/3rdparty/extra-cmake-modules/find-modules/FindEGL.cmake @@ -128,7 +128,8 @@ check_cxx_source_compiles(" #include int main(int, char **) { - EGLint x = 0; EGLDisplay dpy = 0; EGLContext ctx = 0; + [[maybe_unused]] EGLint x = 0; + EGLDisplay dpy = 0; EGLContext ctx = 0; eglDestroyContext(dpy, ctx); }" HAVE_EGL) From 8af1698891a7e57a068dc4c41e142fd22655aff4 Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Fri, 9 Jun 2023 12:27:03 +0200 Subject: [PATCH 019/151] doc: Remove bogus step in font resolution algorithm This is a left-over from when setFamilies() and setFamily() were setting two different properties, for compatibility reasons. There is no longer a special step for the singular family, and the sentence is also a bit obfuscated, so we just remove it. Change-Id: Ia3c244d41f550a5062de8de63053770258dcacba Reviewed-by: Andy Shaw (cherry picked from commit 0ed324314bf151894be9bdd8272adbbc63c2b0ee) Reviewed-by: Qt Cherry-pick Bot --- src/gui/text/qfont.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/gui/text/qfont.cpp b/src/gui/text/qfont.cpp index e57e4bf327b..bc95ba260b1 100644 --- a/src/gui/text/qfont.cpp +++ b/src/gui/text/qfont.cpp @@ -494,8 +494,6 @@ QFontEngineData::~QFontEngineData() The font matching algorithm works as follows: \list 1 \li The specified font families (set by setFamilies()) are searched for. - \li If not found, then if set the specified font family exists and can be used to represent - the writing system in use, it will be selected. \li If not, a replacement font that supports the writing system is selected. The font matching algorithm will try to find the best match for all the properties set in the QFont. How this is From b7c3eabdb8380be2a80ae4c688dfc743e7cebca1 Mon Sep 17 00:00:00 2001 From: Fabian Kosmale Date: Tue, 18 Apr 2023 08:54:36 +0200 Subject: [PATCH 020/151] Avoid capturing same property twice Avoid capturing the same property multiple times in a binding by storing them in the BindingEvaluationState. We store them in a QVarLengthArray array, as the number of properties involved in a binding is expected to be rather low, so a linear scan is fine. Avoiding double capture is a good idea in general, as we would otherwise needlessly reevaluate bindings multiple times, and also needlessly allocate memory for further observers, instead of using a binding's inline observer array. Even more importantantly, our notification code makes assumptions that notify will visit bindings only exactly once. Not upholding that invariant leads to memory corruption and subsequent crashes, as observers allocated by the binding would get freed, even though we would still access them later. Fixes: QTBUG-112822 Change-Id: Icdc1f43fe554df6fa69e881872b2c429d5fa0bbc Reviewed-by: Ulf Hermann (cherry picked from commit cb30e45b9a800c6ad9cdfb446a20b6a6e8efbe71) Reviewed-by: Qt Cherry-pick Bot --- src/corelib/kernel/qproperty.cpp | 5 +++++ src/corelib/kernel/qproperty_p.h | 1 + .../corelib/kernel/qproperty/tst_qproperty.cpp | 17 +++++++++++++++++ 3 files changed, 23 insertions(+) diff --git a/src/corelib/kernel/qproperty.cpp b/src/corelib/kernel/qproperty.cpp index ea7635a58f2..1080079dcfb 100644 --- a/src/corelib/kernel/qproperty.cpp +++ b/src/corelib/kernel/qproperty.cpp @@ -566,6 +566,11 @@ void QPropertyBindingData::registerWithCurrentlyEvaluatingBinding_helper(Binding { QPropertyBindingDataPointer d{this}; + if (currentState->alreadyCaptureProperties.contains(this)) + return; + else + currentState->alreadyCaptureProperties.push_back(this); + QPropertyObserverPointer dependencyObserver = currentState->binding->allocateDependencyObserver(); Q_ASSERT(QPropertyObserver::ObserverNotifiesBinding == 0); dependencyObserver.setBindingToNotify_unsafe(currentState->binding); diff --git a/src/corelib/kernel/qproperty_p.h b/src/corelib/kernel/qproperty_p.h index 43bd81061dd..b850fa88326 100644 --- a/src/corelib/kernel/qproperty_p.h +++ b/src/corelib/kernel/qproperty_p.h @@ -144,6 +144,7 @@ struct BindingEvaluationState QPropertyBindingPrivate *binding; BindingEvaluationState *previousState = nullptr; BindingEvaluationState **currentState = nullptr; + QVarLengthArray alreadyCaptureProperties; }; /*! diff --git a/tests/auto/corelib/kernel/qproperty/tst_qproperty.cpp b/tests/auto/corelib/kernel/qproperty/tst_qproperty.cpp index 8d6781fa2d1..63cf9c28174 100644 --- a/tests/auto/corelib/kernel/qproperty/tst_qproperty.cpp +++ b/tests/auto/corelib/kernel/qproperty/tst_qproperty.cpp @@ -99,6 +99,7 @@ private slots: void metaProperty(); void modifyObserverListWhileIterating(); + void noDoubleCapture(); void compatPropertyNoDobuleNotification(); void compatPropertySignals(); @@ -1491,6 +1492,22 @@ void tst_QProperty::modifyObserverListWhileIterating() } } +void tst_QProperty::noDoubleCapture() +{ + QProperty size; + size = 3; + QProperty max; + max.setBinding([&size]() -> int { + // each loop run attempts to capture size + for (int i = 0; i < size; ++i) {} + return size.value(); + }); + auto bindingPriv = QPropertyBindingPrivate::get(max.binding()); + QCOMPARE(bindingPriv->dependencyObserverCount, 1); + size = 4; // should not crash + QCOMPARE(max.value(), 4); +} + class CompatPropertyTester : public QObject { Q_OBJECT From 04d1d544cd82fa59bd39262e23751c178b59ef04 Mon Sep 17 00:00:00 2001 From: Tarja Sundqvist Date: Wed, 14 Jun 2023 13:48:05 +0300 Subject: [PATCH 021/151] Bump version to 6.2.10 Change-Id: I836c953185a24eddb4e952bde61f4c23f23841d5 Reviewed-by: Tarja Sundqvist --- .cmake.conf | 2 +- .qmake.conf | 2 +- src/plugins/sqldrivers/.cmake.conf | 2 +- tests/auto/cmake/mockplugins/.cmake.conf | 2 +- tests/auto/cmake/test_static_resources/.cmake.conf | 2 +- util/cmake/pro2cmake.py | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.cmake.conf b/.cmake.conf index 4c6b48a8d37..f42a19e28be 100644 --- a/.cmake.conf +++ b/.cmake.conf @@ -1,4 +1,4 @@ -set(QT_REPO_MODULE_VERSION "6.2.9") +set(QT_REPO_MODULE_VERSION "6.2.10") set(QT_REPO_MODULE_PRERELEASE_VERSION_SEGMENT "") # Minimum requirement for building Qt diff --git a/.qmake.conf b/.qmake.conf index b3d558e4d2c..b4b94869c03 100644 --- a/.qmake.conf +++ b/.qmake.conf @@ -6,4 +6,4 @@ DEFINES += QT_NO_JAVA_STYLE_ITERATORS QT_SOURCE_TREE = $$PWD QT_BUILD_TREE = $$shadowed($$PWD) -MODULE_VERSION = 6.2.9 +MODULE_VERSION = 6.2.10 diff --git a/src/plugins/sqldrivers/.cmake.conf b/src/plugins/sqldrivers/.cmake.conf index 0c21440f994..8f8ece9189b 100644 --- a/src/plugins/sqldrivers/.cmake.conf +++ b/src/plugins/sqldrivers/.cmake.conf @@ -1 +1 @@ -set(QT_REPO_MODULE_VERSION "6.2.9") +set(QT_REPO_MODULE_VERSION "6.2.10") diff --git a/tests/auto/cmake/mockplugins/.cmake.conf b/tests/auto/cmake/mockplugins/.cmake.conf index 0c21440f994..8f8ece9189b 100644 --- a/tests/auto/cmake/mockplugins/.cmake.conf +++ b/tests/auto/cmake/mockplugins/.cmake.conf @@ -1 +1 @@ -set(QT_REPO_MODULE_VERSION "6.2.9") +set(QT_REPO_MODULE_VERSION "6.2.10") diff --git a/tests/auto/cmake/test_static_resources/.cmake.conf b/tests/auto/cmake/test_static_resources/.cmake.conf index 0c21440f994..8f8ece9189b 100644 --- a/tests/auto/cmake/test_static_resources/.cmake.conf +++ b/tests/auto/cmake/test_static_resources/.cmake.conf @@ -1 +1 @@ -set(QT_REPO_MODULE_VERSION "6.2.9") +set(QT_REPO_MODULE_VERSION "6.2.10") diff --git a/util/cmake/pro2cmake.py b/util/cmake/pro2cmake.py index 901bba1d759..40bb44ce45d 100755 --- a/util/cmake/pro2cmake.py +++ b/util/cmake/pro2cmake.py @@ -4423,7 +4423,7 @@ def create_top_level_cmake_conf(): conf_file_name = ".cmake.conf" try: with open(conf_file_name, "x") as file: - file.write('set(QT_REPO_MODULE_VERSION "6.2.9")\n') + file.write('set(QT_REPO_MODULE_VERSION "6.2.10")\n') except FileExistsError: pass From 4195ec9ae52412c70c4291c03e855287d0b73620 Mon Sep 17 00:00:00 2001 From: Bartlomiej Moskal Date: Tue, 30 May 2023 14:17:19 +0200 Subject: [PATCH 022/151] Android: Restore the default QSettings path to the .config directory After 140ca89a3c2b8d78889d27217f977cd4de10041b commit, the path of the QSettings default file location changed. That caused the problem with updating the app (old settings file is not used anymore). That is why we should still use old (.config) directory for QSettings file if the file exists. Fixes: QTBUG-109405 Fixes: QTBUG-109369 Change-Id: I8ce53e0a80e4c2d16802b27b000ab3fbed198628 Reviewed-by: Assam Boudjelthia (cherry picked from commit beaaa0bf02fee696b03f2839bea8e0e6bc685a62) --- src/corelib/io/qsettings.cpp | 40 +++++++++++++++++++++++++----------- 1 file changed, 28 insertions(+), 12 deletions(-) diff --git a/src/corelib/io/qsettings.cpp b/src/corelib/io/qsettings.cpp index df254946e7a..0fd3ee0a6b7 100644 --- a/src/corelib/io/qsettings.cpp +++ b/src/corelib/io/qsettings.cpp @@ -963,26 +963,43 @@ static inline int pathHashKey(QSettings::Format format, QSettings::Scope scope) } #ifndef Q_OS_WIN -static QString make_user_path() +static constexpr QChar sep = QLatin1Char('/'); + +#if !defined(QSETTINGS_USE_QSTANDARDPATHS) || defined(Q_OS_ANDROID) +static QString make_user_path_without_qstandard_paths() { - static constexpr QChar sep = QLatin1Char('/'); -#ifndef QSETTINGS_USE_QSTANDARDPATHS - // Non XDG platforms (OS X, iOS, Android...) have used this code path erroneously - // for some time now. Moving away from that would require migrating existing settings. QByteArray env = qgetenv("XDG_CONFIG_HOME"); if (env.isEmpty()) { return QDir::homePath() + QLatin1String("/.config/"); } else if (env.startsWith('/')) { return QFile::decodeName(env) + sep; - } else { - return QDir::homePath() + sep + QFile::decodeName(env) + sep; } + + return QDir::homePath() + sep + QFile::decodeName(env) + sep; +} +#endif // !QSETTINGS_USE_QSTANDARDPATHS || Q_OS_ANDROID + +static QString make_user_path() +{ +#ifndef QSETTINGS_USE_QSTANDARDPATHS + // Non XDG platforms (OS X, iOS, Android...) have used this code path erroneously + // for some time now. Moving away from that would require migrating existing settings. + // The migration has already been done for Android. + return make_user_path_without_qstandard_paths(); #else - // When using a proper XDG platform, use QStandardPaths rather than the above hand-written code; - // it makes the use of test mode from unit tests possible. + +#ifdef Q_OS_ANDROID + // If an old settings path exists, use it instead of creating a new one + QString ret = make_user_path_without_qstandard_paths(); + if (QFile(ret).exists()) + return ret; +#endif // Q_OS_ANDROID + + // When using a proper XDG platform or Android platform, use QStandardPaths rather than the + // above hand-written code. It makes the use of test mode from unit tests possible. // Ideally all platforms should use this, but see above for the migration issue. return QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation) + sep; -#endif +#endif // !QSETTINGS_USE_QSTANDARDPATHS } #endif // !Q_OS_WIN @@ -1351,8 +1368,7 @@ void QConfFileSettingsPrivate::syncConfFile(QConfFile *confFile) // On android and if it is a content URL put the lock file in a // writable location to prevent permissions issues and invalid paths. if (confFile->name.startsWith(QLatin1String("content:"))) - lockFileName = QStandardPaths::writableLocation(QStandardPaths::CacheLocation) - + QFileInfo(lockFileName).fileName(); + lockFileName = make_user_path() + QFileInfo(lockFileName).fileName(); # endif /* Use a lockfile in order to protect us against other QSettings instances From bcde7eeb01b922b2037bde75ef71dcf24222080f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A5rten=20Nordheim?= Date: Wed, 14 Jun 2023 09:23:42 +0200 Subject: [PATCH 023/151] Update public suffix list Task-number: QTBUG-114548 Change-Id: I81277a4bd440fd0245a84953cd0417c09dfb4132 Reviewed-by: Timur Pocheptsov --- src/network/kernel/qt_attribution.json | 2 +- src/network/kernel/qurltlds_p.h | 27264 +++++++++++------------ 2 files changed, 12898 insertions(+), 14368 deletions(-) diff --git a/src/network/kernel/qt_attribution.json b/src/network/kernel/qt_attribution.json index 75739acd172..17a7699c71e 100644 --- a/src/network/kernel/qt_attribution.json +++ b/src/network/kernel/qt_attribution.json @@ -20,7 +20,7 @@ supported by Qt (by the QNetworkCookieJar class).", "Homepage": "Consult https://github.com/publicsuffix/list for the sha1 but download from ...", "Homepage": "http://publicsuffix.org/", - "Version": "a304485800b4b6b796fcccbb3be1585f189ee038, fetched on 2023-05-02", + "Version": "c72a917ddc5adecd6b28c45d8db6d5eb8bd838d3, fetched on 2023-06-14", "License": "Mozilla Public License 2.0", "LicenseFile": "PSL-LICENSE.txt", "LicenseId": "MPL-2.0", diff --git a/src/network/kernel/qurltlds_p.h b/src/network/kernel/qurltlds_p.h index 3d133123caa..15365fe0bbd 100644 --- a/src/network/kernel/qurltlds_p.h +++ b/src/network/kernel/qurltlds_p.h @@ -61,14748 +61,13278 @@ QT_BEGIN_NAMESPACE // for instructions see the program at // util/publicSuffix/ -static const quint16 tldCount = 9021; +static const quint16 tldCount = 9024; // After the tldCount "real" entries in tldIndices, include a final entry // that records the sum of the lengths of all the chunks, i.e. the index // just past the end of tldChunks. static constexpr quint32 tldIndices[tldCount + 1] = { 0, -21, -28, -40, -74, -74, -81, -88, -105, -160, -167, -188, -195, -195, -199, -216, -223, -223, -223, -227, -234, -248, -263, -294, -322, -362, -362, -369, -369, -398, -412, -428, -451, -492, -499, -499, -499, -506, -513, -558, -567, -584, -584, -584, -591, -630, -630, -630, -644, -672, -704, -704, -721, -746, -784, -811, -837, -837, -851, -868, -888, -931, -953, -960, -967, -967, -1006, -1036, -1036, -1036, -1085, -1105, -1121, -1138, -1145, -1173, -1182, -1195, -1219, -1219, -1219, -1237, -1241, -1252, -1252, -1252, -1274, -1316, -1324, -1340, -1347, -1368, -1380, -1420, +0, +4, +10, +36, +68, +87, +94, +131, +139, +143, +143, +143, +164, +164, +164, +213, +284, +284, +301, +307, +328, +352, +352, +352, +376, +376, +376, +376, +376, +455, +455, +466, +466, +466, +466, +488, +516, +516, +516, +539, +545, +545, +545, +545, +556, +556, +556, +610, +697, +703, +703, +710, +741, +754, +754, +754, +754, +754, +754, +754, +754, +760, +760, +760, +760, +760, +760, +776, +785, +791, +791, +817, +821, +821, +821, +821, +832, +832, +832, +905, +1137, +1143, +1153, +1153, +1153, +1172, +1172, +1179, +1179, +1179, +1179, +1179, +1179, +1179, +1188, +1188, +1188, +1188, +1199, +1209, +1256, +1301, +1301, +1301, +1301, +1301, +1301, +1301, +1311, +1311, +1311, +1353, +1413, +1413, +1413, +1413, +1413, +1422, +1433, +1433, +1433, +1433, 1442, -1455, -1494, -1516, -1516, -1526, -1526, -1565, -1565, -1579, -1625, -1647, -1654, -1654, -1694, -1694, -1729, -1759, +1442, +1442, +1442, +1442, +1451, +1451, +1451, +1451, +1461, +1467, +1467, +1480, +1491, +1491, +1491, +1501, +1501, +1501, +1501, +1506, +1540, +1702, +1702, +1702, +1702, +1702, +1702, +1702, +1702, +1718, +1735, +1735, +1735, +1735, +1755, +1755, +1770, +1770, 1774, -1808, -1821, -1828, +1774, +1815, 1858, -1881, -1881, -1888, -1901, -1916, -1933, -1933, -1956, -1999, -2018, -2042, -2077, -2084, -2091, -2091, -2091, -2091, -2104, -2118, -2126, -2142, -2172, -2172, -2224, -2235, -2245, -2288, -2295, -2327, -2327, -2337, -2364, -2392, -2399, -2439, -2452, -2452, -2467, -2474, -2492, -2499, -2499, -2499, -2538, -2538, -2553, +1858, +1858, +1873, +1873, +1873, +1887, +1887, +1899, +1899, +1899, +1917, +2044, +2044, +2054, +2054, +2102, +2102, +2113, +2113, +2113, +2113, +2113, +2113, +2113, +2149, +2168, +2168, +2168, +2168, +2176, +2191, +2241, +2248, +2248, +2253, +2253, +2257, +2257, +2262, +2272, +2272, +2272, +2332, +2488, +2501, +2517, +2531, +2531, +2541, +2541, +2541, +2541, +2541, +2541, +2541, +2541, 2573, -2573, -2573, -2579, +2578, +2578, +2578, 2590, 2590, -2601, -2629, -2645, -2673, -2673, -2673, -2673, -2684, -2698, -2698, -2735, -2756, -2763, -2810, -2810, -2835, -2850, -2857, -2864, -2886, -2893, -2904, -2911, -2911, -2926, -2939, -2970, -2977, -2984, -2996, -2996, -3003, -3010, -3015, -3035, -3042, +2600, +2619, +2635, +2635, +2652, +2652, +2652, +2652, +2659, +2659, +2659, +2659, +2685, +2765, +2765, +2765, +2769, +2783, +2792, +2792, +2792, +2792, +2799, +2799, +2821, +2821, +2877, +2884, +2884, +2884, +2884, +2884, +2899, +2927, +2964, +2968, +2981, +2992, +2999, +3006, +3006, +3006, +3006, +3006, 3049, -3065, -3137, -3137, -3161, -3168, -3182, -3182, -3200, -3236, -3266, -3307, -3331, -3363, -3380, -3400, -3427, -3427, -3437, -3437, -3451, -3481, -3481, -3520, -3552, -3571, -3571, -3578, -3626, -3626, -3659, -3659, -3685, -3723, -3723, -3730, -3730, -3740, -3760, -3767, -3767, -3786, -3786, -3793, -3804, -3820, -3827, -3827, -3852, -3859, -3866, -3874, -3881, -3894, -3894, -3901, -3927, -3961, -3981, -3990, -4010, -4022, -4032, -4039, -4058, -4080, -4098, -4102, -4102, -4102, -4102, -4120, -4120, -4126, -4142, -4151, -4151, -4151, -4151, -4151, -4166, -4176, -4198, -4207, -4233, -4233, -4233, -4240, -4252, -4259, -4273, -4292, -4292, -4306, -4334, -4346, -4346, -4346, -4366, -4366, +3170, +3170, +3194, +3194, +3194, +3194, +3194, +3194, +3194, +3202, +3207, +3216, +3216, +3230, +3235, +3235, +3235, +3235, +3235, +3235, +3269, +3269, +3269, +3269, +3269, +3288, +3288, +3288, +3314, +3314, +3314, +3343, +3545, +3545, +3555, +3569, +3569, +3620, +3620, +3620, +3620, +3620, +3620, +3620, +3620, +3637, +3668, +3690, +3690, +3690, +3690, +3700, +3744, +3744, +3744, +3764, +3764, +3768, +3775, +3784, +3800, +3813, +3813, +3877, +3940, +3940, +3947, +3947, +3947, +3947, +3947, +3947, +3947, +3947, +3947, +3947, +3947, +4038, +4038, +4038, +4038, +4047, +4055, +4075, +4086, +4095, +4095, +4095, +4095, +4095, +4116, +4116, +4127, +4127, +4127, +4167, +4351, +4357, +4357, +4363, +4377, +4394, +4394, +4394, +4394, 4405, -4447, -4447, -4464, -4464, -4483, -4490, -4490, -4490, -4499, -4506, -4538, -4545, -4551, -4563, -4587, -4594, -4601, -4629, -4636, -4643, -4651, -4687, -4699, -4748, -4768, -4768, -4768, -4768, -4775, -4784, -4784, -4828, -4828, -4832, -4837, -4837, -4875, -4885, -4908, -4908, -4908, -4918, -4932, -4964, -4964, -4974, -4992, -4999, -4999, -5010, -5010, -5028, -5028, -5028, -5065, -5065, -5070, -5076, -5106, -5106, +4405, +4412, +4433, +4488, +4515, +4515, +4515, +4515, +4521, +4531, +4580, +4613, +4613, +4623, +4641, +4648, +4648, +4648, +4662, +4672, +4672, +4715, +4831, +4831, +4845, +4857, +4857, +4857, +4857, +4861, +4861, +4861, +4861, +4861, +4861, +4876, +4882, +4882, +4882, +4882, +4890, +4896, +4906, +4906, +4906, +4976, +4976, +4976, +4976, +4986, +4986, +4986, +4986, +5017, +5087, +5087, +5087, +5087, +5095, +5102, +5102, +5102, +5102, 5124, -5130, -5175, -5175, -5175, -5175, -5175, -5175, -5182, -5191, -5209, -5218, -5218, -5266, -5266, -5274, -5281, -5281, -5304, -5304, -5304, -5313, -5324, -5334, -5358, -5363, -5379, -5404, -5420, -5448, -5457, -5467, -5467, -5474, -5507, -5517, -5529, -5548, -5591, -5591, -5608, -5608, -5622, -5633, -5657, -5657, -5675, -5685, -5699, -5704, +5124, +5124, +5124, +5148, +5158, +5158, +5158, +5165, +5165, +5165, +5214, +5214, +5229, +5234, +5240, +5240, +5240, +5250, +5261, +5261, +5261, +5308, +5438, +5438, +5471, +5471, +5471, +5478, +5489, +5497, +5497, +5497, +5497, +5497, +5497, +5553, +5553, +5572, +5580, +5587, +5587, +5587, +5587, +5594, +5601, +5611, +5611, +5611, +5611, +5611, +5618, +5618, +5618, +5643, +5707, +5720, 5749, -5783, +5749, +5765, +5769, +5773, +5780, +5780, +5787, +5787, +5787, +5787, +5799, +5799, +5799, +5799, 5799, 5799, 5805, -5805, -5825, -5841, -5851, -5860, -5860, -5865, -5902, -5902, -5931, -5944, -5950, -5950, -5950, -5950, -5950, -5950, -5958, -5974, -5983, -6014, -6079, -6089, -6089, -6134, -6143, -6143, -6143, -6143, -6155, -6155, -6155, -6155, -6166, -6183, -6219, -6235, -6244, -6249, -6249, -6255, -6259, -6259, -6259, -6259, -6259, -6259, -6275, -6291, -6291, -6291, -6300, -6300, -6313, -6332, -6349, -6349, -6349, -6356, -6356, -6374, -6374, -6374, -6395, -6395, -6395, -6407, -6407, -6411, -6430, -6447, -6454, -6473, -6473, -6480, -6480, -6480, -6487, -6487, -6497, -6526, -6535, -6535, -6542, -6542, -6594, -6594, -6604, -6611, -6625, -6642, -6668, -6756, -6762, -6762, -6769, -6776, -6807, -6819, -6834, -6841, -6848, -6870, -6886, -6886, -6911, -6934, -6941, -6953, -6953, -6981, -6994, -7001, -7018, -7048, -7060, -7074, -7081, -7168, -7172, -7182, -7182, -7189, -7189, -7196, -7203, -7210, -7210, -7224, -7241, -7241, -7261, -7268, -7295, -7302, -7302, -7323, -7335, -7369, -7384, -7391, -7391, -7408, +5849, +5849, +5857, +5885, +5885, +5885, +5885, +5885, +5904, +5904, +5904, +5937, +6095, +6118, +6152, +6152, +6159, +6169, +6169, +6177, +6177, +6185, +6185, +6200, +6200, +6264, +6278, +6278, +6278, +6278, +6278, +6299, +6314, +6314, +6314, +6328, +6328, +6343, +6343, +6343, +6343, +6343, +6343, +6404, +6498, +6504, +6504, +6504, +6511, +6511, +6511, +6511, +6511, +6519, +6527, +6527, +6554, +6579, +6579, +6588, +6588, +6588, +6588, +6588, +6617, +6646, +6646, +6659, +6659, +6659, +6659, +6669, +6680, +6680, +6687, +6752, +6840, +6840, +6856, +6872, +6872, +6872, +6872, +6872, +6872, +6872, +6872, +6872, +6872, +6993, +6993, +6993, +6993, +6993, +7005, +7041, +7064, +7114, +7114, +7126, +7126, +7126, +7126, +7126, +7126, +7126, +7126, +7148, +7277, +7294, +7294, +7300, +7300, +7316, +7316, +7316, +7316, +7316, +7316, +7316, +7316, +7362, +7362, +7372, +7372, +7372, +7372, +7382, 7415, 7415, -7459, -7459, -7459, -7459, -7459, -7459, -7468, -7484, -7484, -7511, -7518, -7530, -7530, -7540, -7587, -7605, -7644, -7644, -7644, -7651, -7659, -7659, -7675, -7684, -7684, -7684, -7709, -7722, -7722, -7736, -7760, -7845, -7852, -7852, -7881, -7881, +7415, +7433, +7433, +7442, +7442, +7442, +7442, +7442, +7442, +7470, +7498, +7498, +7508, +7508, +7524, +7524, +7524, +7524, +7524, +7524, +7524, +7524, +7524, +7603, +7603, +7603, +7603, +7603, +7611, +7621, +7662, +7671, +7671, +7671, +7671, +7671, +7692, +7692, +7701, +7701, +7701, +7733, +7836, +7842, +7842, +7842, +7842, +7842, +7842, +7842, +7842, +7842, +7842, +7842, +7850, +7884, 7888, -7933, -7949, -7968, -7989, -7995, -8014, -8046, -8046, -8058, -8068, -8087, -8096, -8103, -8120, -8154, -8161, -8183, -8204, -8209, -8209, -8228, -8254, -8265, -8265, -8276, -8276, -8311, -8355, -8379, -8388, -8388, -8415, -8428, -8428, -8443, -8461, -8501, -8526, -8547, -8556, -8556, +7894, +7894, +7894, +7899, +7899, +7954, +7964, +7964, +7988, +7988, +8007, +8007, +8007, +8019, +8019, +8019, +8085, +8226, +8232, +8253, +8253, +8253, +8253, +8253, +8253, +8253, +8253, +8253, +8253, +8253, +8293, +8293, +8298, +8298, +8309, +8309, +8356, +8392, +8392, +8392, +8392, +8392, +8401, +8401, +8401, +8401, +8401, +8401, +8411, +8571, 8576, -8576, -8576, -8616, -8631, -8631, -8650, -8672, -8683, -8690, -8698, -8708, -8737, -8758, -8769, -8788, -8807, -8848, -8877, -8890, -8890, -8897, -8904, -8910, -8917, -8944, -8973, -8996, -8996, -8996, -8996, -9003, -9044, -9051, -9058, -9065, -9065, -9077, -9106, -9127, -9144, -9154, -9191, -9216, -9230, -9257, -9274, -9281, -9281, -9288, -9288, -9305, -9351, -9378, -9385, -9392, -9392, -9412, -9438, -9445, -9482, -9488, -9528, -9542, -9549, +8583, +8583, +8602, +8612, +8612, +8612, +8612, +8612, +8612, +8624, +8624, +8649, +8649, +8655, +8655, +8660, +8660, +8664, +8689, +8718, +8718, +8718, +8718, +8730, +8730, +8730, +8730, +8730, +8730, +8749, +8797, +8797, +8819, +8819, +8819, +8824, +8824, +8834, +8834, +8834, +8834, +8834, +8834, +8892, +8919, +8937, +8937, +8937, +8937, +8937, +8953, +8976, +8976, +8986, +8986, +9006, +9028, +9028, +9064, +9064, +9064, +9095, +9178, +9190, +9208, +9208, +9208, +9208, +9208, +9208, +9208, +9208, +9208, +9208, +9208, +9293, +9331, +9343, +9343, +9343, +9343, +9388, +9440, +9440, +9440, +9465, +9465, +9465, +9465, +9465, +9465, +9465, +9465, +9523, 9563, -9570, -9586, -9614, -9623, -9623, -9632, -9632, -9646, -9676, -9696, -9696, -9696, -9696, -9714, -9728, -9757, -9772, -9789, -9789, -9837, -9854, -9894, -9894, -9918, -9918, -9918, -9942, -9961, -9977, -10010, -10017, -10017, -10017, -10051, +9569, +9579, +9579, +9579, +9579, +9579, +9579, +9579, +9592, +9606, +9606, +9606, +9637, +9649, +9654, +9654, +9654, +9654, +9662, +9686, +9699, +9699, +9699, +9699, +9699, +9711, +9711, +9734, +9734, +9734, +9758, +9975, +9988, +9988, +9988, +9988, +9988, +9988, +9988, +9988, +9992, +9992, +9992, +9992, +10018, +10018, +10018, +10018, +10018, +10018, +10038, +10038, +10052, +10052, +10052, 10058, -10087, -10094, -10111, -10111, -10169, -10189, -10251, -10279, -10314, -10324, -10341, -10369, -10376, -10386, -10386, -10420, -10420, -10420, -10452, -10462, -10475, -10475, -10475, -10491, -10491, -10514, -10532, -10532, -10544, -10551, -10551, -10551, -10569, -10612, -10637, -10637, -10655, -10662, -10709, -10732, -10767, -10786, -10802, -10813, -10834, -10834, -10852, -10895, -10908, -10915, -10922, -10977, -11000, -11000, -11007, -11036, -11036, -11080, +10058, +10058, +10058, +10058, +10058, +10058, +10180, +10295, +10295, +10295, +10295, +10295, +10295, +10295, +10295, +10295, +10295, +10295, +10295, +10304, +10351, +10359, +10363, +10363, +10363, +10363, +10363, +10465, +10474, +10479, +10479, +10483, +10483, +10483, +10483, +10508, +10508, +10508, +10520, +10689, +10689, +10689, +10697, +10697, +10707, +10707, +10707, +10707, +10707, +10707, +10707, +10711, +10711, +10723, +10730, +10734, +10734, +10741, +10757, +10803, +10803, +10803, +10816, +10830, +10845, +10853, +10853, +10864, +10864, +10864, +10941, +11070, +11070, +11070, +11070, +11070, 11095, -11108, -11115, -11134, -11156, -11174, -11216, -11216, -11230, -11230, -11253, -11271, -11271, -11293, -11293, -11293, -11373, -11384, -11384, -11461, -11461, -11461, -11476, -11486, -11497, -11515, -11533, -11553, -11560, -11567, -11574, -11591, -11591, -11591, -11598, -11611, -11623, -11652, -11675, -11682, -11692, -11692, -11700, -11710, -11710, -11720, -11743, -11764, -11775, -11775, -11781, -11794, -11814, -11832, -11847, -11847, -11885, -11894, -11914, -11936, -11943, +11095, +11100, +11100, +11100, +11100, +11119, +11119, +11157, +11157, +11164, +11164, +11164, +11164, +11173, +11173, +11183, +11183, +11193, +11193, +11199, +11199, +11199, +11199, +11199, +11203, +11210, +11347, +11351, +11362, +11362, +11369, +11392, +11392, +11392, +11392, +11392, +11392, +11392, +11392, +11410, +11425, +11425, +11425, +11425, +11425, +11431, +11478, +11496, +11496, +11496, +11496, +11496, +11496, +11496, +11505, +11505, +11505, +11545, +11633, +11633, +11672, +11678, +11686, +11686, +11686, +11686, +11686, +11686, +11686, +11686, +11686, +11711, +11711, +11711, +11711, +11711, +11711, +11721, +11767, +11774, +11774, +11774, +11774, +11774, +11774, +11774, +11774, +11774, +11774, +11820, +11903, +11903, +11903, +11916, 11951, -11958, -11958, -11958, -11966, -11966, -11966, -11988, -12012, -12012, -12012, -12012, -12012, -12037, +11961, +11961, +11961, +11974, +11978, +11978, +11978, +11978, +11996, +12003, +12015, +12015, +12015, +12029, +12034, 12062, -12090, -12101, -12108, -12129, -12135, -12135, -12155, -12164, -12182, -12191, -12199, -12208, -12243, -12248, -12255, -12255, -12268, -12289, -12308, -12326, -12330, -12337, -12337, -12337, -12373, -12381, -12388, -12388, -12397, -12397, -12397, -12397, -12397, -12397, -12412, -12426, -12431, -12431, -12431, -12499, -12504, -12504, -12504, -12504, -12523, -12523, -12523, -12523, -12545, -12551, -12551, -12570, -12586, -12628, -12628, -12628, -12628, -12644, -12648, -12648, -12648, -12658, -12658, -12702, -12734, -12734, -12765, -12777, -12777, -12777, -12777, -12833, -12833, -12833, -12852, -12852, -12859, -12879, -12905, -12905, -12918, -12928, -12943, -12943, -12967, -12967, -12967, -12971, -12977, -12977, -13013, -13052, -13059, -13065, -13076, +12062, +12062, +12083, +12083, +12083, +12083, +12083, +12111, +12111, +12111, +12141, +12301, +12301, +12313, +12313, +12313, +12319, +12319, +12319, +12319, +12319, +12319, +12319, +12319, +12319, +12319, +12319, +12319, +12319, +12319, +12334, +12360, +12370, +12370, +12378, +12378, +12378, +12378, +12385, +12399, +12399, +12399, +12478, +12703, +12703, +12732, +12746, +12746, +12746, +12746, +12746, +12746, +12746, +12746, +12746, +12746, +12764, +12764, +12768, +12768, +12775, +12775, +12775, +12831, +12862, +12869, +12869, +12873, +12880, +12890, +12890, +12890, +12890, +12890, +12931, +13019, +13019, +13036, +13036, +13041, +13041, +13041, +13041, +13041, +13053, +13053, +13053, +13053, +13068, +13068, +13087, +13091, +13091, +13091, 13101, -13113, -13113, -13113, -13127, -13166, -13194, -13194, -13213, -13228, -13250, -13250, -13250, -13256, -13287, -13287, -13287, -13287, -13287, -13302, -13350, -13369, -13375, -13375, -13391, -13397, -13403, -13443, -13443, -13465, -13471, -13481, -13481, -13481, -13481, -13481, -13481, -13481, -13487, -13493, -13493, -13493, -13513, -13534, -13548, -13552, -13556, -13566, -13576, -13581, -13581, -13611, -13642, -13642, -13642, -13642, -13652, -13669, -13702, -13702, -13737, -13746, -13767, -13785, -13785, -13811, -13831, -13850, -13850, -13850, -13873, -13888, -13888, -13888, -13908, -13914, -13927, -13938, -13966, -13984, -13984, -13984, -13984, -13990, -13990, -13990, -13990, -14007, -14030, -14030, -14030, -14057, -14064, -14064, -14064, -14064, -14095, -14118, -14165, +13118, +13118, +13122, +13130, +13130, +13135, +13135, +13142, +13152, +13152, +13152, +13180, +13221, +13221, +13221, +13221, +13221, +13221, +13221, +13221, +13221, +13226, +13226, +13226, +13226, +13244, +13244, +13266, +13266, +13266, +13278, +13278, +13327, +13352, +13362, +13382, +13382, +13382, +13382, +13382, +13394, +13394, +13394, +13415, +13596, +13596, +13605, +13605, +13615, +13615, +13615, +13615, +13615, +13615, +13615, +13615, +13623, +13645, +13651, +13651, +13651, +13651, +13651, +13651, +13694, +13694, +13694, +13694, +13694, +13694, +13701, +13701, +13713, +13713, +13713, +13713, +13814, +13814, +13821, +13821, +13821, +13821, +13821, +13832, +13832, +13832, +13832, +13832, +13839, +13866, +13866, +13866, +13872, +13872, +13872, +13900, +13973, +14012, +14012, +14017, +14017, +14017, +14017, +14023, +14034, +14034, +14034, +14078, +14139, +14145, +14145, +14145, +14145, +14145, +14145, +14145, +14145, +14154, +14154, 14175, -14190, -14196, -14205, -14242, -14242, -14284, -14299, +14175, +14197, +14197, +14197, +14197, +14197, +14197, +14207, +14207, +14207, +14207, +14216, +14227, +14227, +14227, +14227, +14227, +14227, +14227, +14249, 14305, 14305, -14310, -14310, -14343, -14362, -14368, -14397, -14397, -14412, -14431, -14431, -14489, -14495, -14501, -14507, -14515, -14515, -14515, +14305, +14316, +14316, +14330, +14330, +14330, +14330, +14338, +14338, +14338, +14338, +14390, +14390, +14414, +14414, +14421, +14421, +14436, +14461, +14486, +14498, +14510, +14510, +14510, +14510, +14510, +14521, +14521, 14521, -14538, -14564, -14570, -14598, -14598, 14605, -14605, -14624, -14624, -14624, -14624, -14624, -14624, -14630, -14640, -14654, -14659, -14679, -14692, -14713, -14713, -14723, -14741, -14741, -14757, +14720, +14720, +14759, 14770, -14816, -14847, -14897, -14908, -14924, -14957, -14963, -14980, -15005, -15044, -15075, -15087, -15087, -15087, -15092, -15098, -15098, -15121, -15121, -15121, -15144, -15181, -15187, -15196, -15208, -15208, -15220, -15234, -15268, -15281, -15281, -15281, -15281, -15281, -15285, -15326, -15332, -15351, -15351, -15357, -15385, -15385, -15402, -15412, -15458, -15474, -15499, -15529, -15541, +14770, +14810, +14810, +14810, +14810, +14817, +14817, +14817, +14817, +14917, +14923, +14936, +14936, +14936, +14947, +14956, +14960, +14965, +14975, +14975, +14975, +14975, +14975, +14989, +14998, +14998, +14998, +15034, +15129, +15141, +15151, +15151, +15151, +15163, +15163, +15173, +15173, +15173, +15173, +15173, +15173, +15217, +15217, +15224, +15224, +15224, +15229, +15241, +15241, +15246, +15255, +15271, +15271, +15271, +15271, +15271, +15271, +15271, +15271, +15379, +15452, +15452, +15459, +15459, +15483, +15483, +15483, +15489, +15507, +15507, +15507, +15507, +15516, +15516, +15528, +15547, +15554, +15554, +15554, +15554, 15566, -15572, -15572, -15612, -15636, -15657, -15657, -15657, -15680, -15680, -15680, -15680, -15686, -15706, -15706, -15745, -15763, -15777, -15798, -15806, -15818, -15818, -15839, -15862, -15878, -15890, -15902, -15913, -15913, -15937, -15943, -15968, -16006, -16006, -16006, -16024, -16024, -16024, -16034, -16034, -16034, -16081, -16101, -16101, -16101, -16114, -16124, -16124, -16124, -16136, -16172, -16172, -16180, +15574, +15574, +15595, +15595, +15595, +15595, +15595, +15606, +15606, +15606, +15674, +15819, +15843, +15843, +15843, +15849, +15873, +15873, +15873, +15888, +15888, +15888, +15888, +15888, +15907, +15920, +15940, +15940, +15940, +15950, +15950, +15966, +15966, +15981, +15981, +15981, +15996, +15996, +15996, +16001, +16005, +16005, +16065, +16165, +16186, +16201, +16201, +16201, 16205, 16205, 16205, -16212, -16224, -16231, -16231, -16231, -16231, -16277, -16277, -16283, -16306, -16306, -16331, -16338, -16358, -16391, -16410, -16410, -16422, -16451, -16451, -16451, -16484, -16489, -16489, -16489, -16541, -16554, -16554, -16568, -16595, -16601, -16613, -16639, -16655, -16661, -16677, -16697, -16697, -16703, -16727, -16745, -16745, -16753, -16779, -16779, -16779, -16806, -16819, -16849, -16863, -16869, -16869, -16900, -16906, -16919, -16946, -16957, -16963, -17037, -17043, -17057, +16205, +16205, +16205, +16211, +16211, +16211, +16211, +16223, +16223, +16234, +16234, +16243, +16257, +16275, +16275, +16285, +16285, +16285, +16285, +16285, +16308, +16308, +16308, +16330, +16374, +16374, +16374, +16380, +16380, +16387, +16387, +16387, +16405, +16405, +16405, +16405, +16405, +16420, +16420, +16420, +16425, +16425, +16425, +16425, +16472, +16496, +16496, +16501, +16501, +16501, +16501, +16501, +16501, +16505, +16505, +16551, +16658, +16658, +16658, +16658, +16658, +16663, +16663, +16663, +16663, +16663, +16663, +16663, +16663, +16713, +16730, +16730, +16730, +16730, +16739, +16739, +16739, +16739, +16739, +16739, +16744, +16744, +16744, +16744, +16754, +16754, +16754, +16769, +16866, +16888, +16888, +16894, +16923, +16961, +16975, +16982, +16989, +16989, +16989, +16989, +16989, +17015, +17015, +17015, +17015, +17015, +17015, +17046, 17063, -17063, -17069, -17082, -17119, -17119, -17145, -17163, -17163, -17181, -17196, -17196, -17196, -17205, -17248, -17258, -17273, -17279, -17279, +17084, +17084, +17091, +17091, +17091, +17091, +17091, +17110, +17110, +17110, +17148, +17268, +17268, 17289, -17308, -17345, -17366, -17366, -17396, -17396, -17426, -17436, -17436, -17436, -17443, -17443, -17443, -17474, -17474, -17499, -17514, -17533, -17556, -17556, -17568, -17585, +17307, +17313, +17318, +17318, +17318, +17318, +17318, +17318, +17318, +17318, +17373, +17373, +17381, +17381, +17381, +17390, +17390, +17420, +17468, +17468, +17489, +17489, +17489, +17489, +17489, +17494, +17494, +17494, +17520, +17536, +17569, +17579, 17597, -17607, -17613, -17662, -17676, -17676, -17676, -17694, -17708, -17708, -17735, -17735, -17741, -17760, -17768, -17778, -17778, -17778, -17793, -17819, -17866, -17866, -17866, -17866, -17866, -17883, -17883, -17883, -17889, -17889, -17895, -17908, -17920, -17926, -17926, -17968, -17985, -17985, -17985, -17985, +17636, +17650, +17653, +17663, +17663, +17666, +17666, +17666, +17684, +17714, +17719, +17722, +17722, +17728, +17734, +17787, +17824, +17861, +17864, +17894, +17900, +17903, +17909, +17913, +17935, +17938, +17941, 18008, -18039, -18045, -18090, -18090, -18090, 18101, -18119, -18119, -18149, -18149, -18163, -18185, -18220, -18247, -18267, -18306, -18306, -18306, -18306, -18315, -18315, -18330, -18330, -18330, -18344, -18358, -18358, -18370, -18377, -18397, -18397, -18397, -18403, -18438, -18452, -18452, -18452, -18452, -18472, -18472, -18490, -18490, -18497, -18503, -18511, -18535, -18544, -18544, -18544, -18550, -18550, -18586, -18593, +18104, +18117, +18123, +18160, +18168, +18174, +18180, +18183, +18189, +18192, +18192, +18202, +18237, +18240, +18243, +18243, +18243, +18246, +18255, +18291, +18297, +18300, +18313, +18316, +18319, +18325, +18338, +18356, +18359, +18359, +18432, +18555, +18561, +18561, +18564, +18564, +18567, +18567, +18570, +18570, +18570, +18573, +18573, +18573, +18599, +18599, 18611, 18611, 18611, -18621, -18628, +18611, +18624, +18639, 18653, -18663, -18663, -18663, -18680, -18680, -18693, -18699, -18699, -18711, -18749, -18755, -18755, -18755, -18755, -18785, -18790, -18805, -18805, -18825, -18836, -18836, -18836, -18853, -18853, -18862, -18862, -18879, -18910, +18662, +18708, +18714, +18717, +18720, +18720, +18720, +18723, +18723, +18770, +18905, +18908, 18925, -18947, -18947, -18947, -18947, -18947, -18947, -18953, -18960, -18978, -19008, -19008, -19008, -19008, -19042, -19042, -19042, +18925, +18928, +18962, +18965, +18977, +18980, +18988, +18988, +18988, +18991, 19058, +19061, +19061, 19064, -19064, -19087, -19087, -19087, -19100, -19159, -19159, -19159, -19182, -19226, -19226, -19226, -19293, -19311, -19311, -19339, -19339, -19350, -19356, -19387, -19395, -19399, -19399, -19433, -19467, -19476, -19520, -19520, -19540, -19540, -19540, -19540, -19546, -19564, -19574, -19574, -19595, -19617, -19634, -19684, -19697, -19707, -19707, -19707, -19717, -19717, -19728, -19728, -19741, -19758, -19785, -19785, -19843, -19849, -19849, -19869, -19877, -19883, -19900, -19908, -19908, -19908, -19926, -19937, -19937, -19962, -19962, -19974, -19987, -19993, -20029, -20029, -20029, -20049, -20059, -20076, -20095, -20099, +19067, +19070, +19083, +19142, +19153, +19153, +19166, +19166, +19176, +19176, +19179, +19188, +19191, +19201, +19221, +19343, +19343, +19346, +19365, +19371, +19384, +19406, +19413, +19413, +19420, +19420, +19420, +19430, +19516, +19535, +19550, +19550, +19570, +19587, +19590, +19629, +19655, +19655, +19655, +19662, +19679, +19693, +19703, +19703, +19710, +19722, +19833, +19910, +19917, +19924, +19931, +19938, +19946, +19946, +19956, +19956, +19966, +19973, +19973, +19973, +20094, +20104, +20111, 20121, -20134, -20179, -20208, -20208, -20208, -20221, -20221, -20221, -20240, -20247, -20264, -20296, -20311, -20331, -20341, -20341, -20341, -20396, -20413, -20444, -20444, -20459, -20473, -20501, -20501, -20501, -20515, -20524, -20531, -20561, -20561, -20577, -20577, -20588, +20124, +20130, +20143, +20206, +20226, +20233, +20283, +20283, +20302, +20305, +20308, +20321, +20328, +20328, +20361, +20512, +20529, +20532, +20552, +20558, +20571, +20574, +20584, +20587, +20590, +20597, +20615, +20618, +20618, +20632, 20644, -20644, -20695, -20695, -20695, -20695, +20657, +20663, +20675, +20688, +20711, +20717, 20723, -20741, -20741, -20756, +20729, +20732, +20738, +20759, 20764, -20764, -20782, -20782, -20792, -20803, -20835, -20904, -20904, -20914, -20914, -20924, -20924, -20933, -20933, -20933, -20954, -20962, -20962, -20962, -20998, -20998, -21008, -21014, -21014, -21033, -21045, -21067, -21067, -21067, -21067, -21088, -21100, -21107, -21120, -21130, -21130, -21130, -21145, -21155, -21221, -21221, -21221, -21237, -21255, -21274, -21274, -21293, -21311, -21347, -21350, -21381, -21417, -21426, -21446, -21457, -21473, -21476, -21476, -21542, -21560, -21566, -21598, -21601, +20794, +20801, +20801, +20825, +20955, +20966, +20969, +20980, +20980, +21010, +21010, +21025, +21032, +21039, +21042, +21042, +21073, +21083, +21090, +21090, +21097, +21109, +21122, +21132, +21167, +21177, +21180, +21180, +21183, +21190, +21190, +21209, +21226, +21229, +21239, +21248, +21369, +21372, +21375, +21378, +21388, +21403, +21403, +21406, +21406, +21409, +21409, +21409, +21416, +21423, +21430, +21430, +21441, +21448, +21455, +21492, +21514, +21537, +21537, +21544, +21544, +21544, +21548, +21548, +21562, +21581, +21581, 21604, -21610, -21622, -21667, +21694, +21707, +21710, +21716, 21719, -21722, -21748, -21756, -21799, -21802, -21805, -21826, -21855, -21864, -21867, -21873, -21883, -21883, -21953, -21972, -21975, -21995, -22018, +21746, +21746, +21759, +21762, +21772, +21775, +21778, +21781, +21819, +21836, +21839, +21846, +21853, +21869, +21888, +21928, +21952, +21958, +21982, +21988, +22002, +22015, 22037, -22040, -22063, -22080, -22083, -22083, -22083, -22107, -22122, -22122, -22128, -22131, -22160, -22163, -22173, -22194, -22197, -22216, -22238, +22052, +22055, +22058, +22072, +22228, 22238, 22263, -22283, -22283, -22289, -22308, -22350, -22353, -22360, -22383, -22393, -22403, -22436, -22452, -22478, -22506, -22513, -22529, -22529, -22558, -22565, -22575, -22578, -22590, -22596, -22619, -22626, -22629, -22660, -22667, -22687, -22690, -22690, -22731, -22754, -22766, -22780, -22800, -22808, -22811, +22270, +22273, +22299, +22309, +22322, +22335, +22348, +22351, +22361, +22368, +22386, +22405, +22412, +22412, +22422, +22422, +22441, +22507, +22530, +22537, +22564, +22571, +22599, +22609, +22609, +22609, +22609, +22612, +22686, +22787, +22787, +22807, +22807, +22807, 22822, -22831, +22825, +22825, +22825, 22834, -22849, 22856, -22860, -22875, -22885, -22888, -22914, -22955, -22980, -22990, -22993, -23019, -23029, -23029, -23057, -23075, -23090, -23097, -23100, -23110, -23117, -23143, -23186, -23193, -23203, -23245, -23245, -23258, -23274, -23274, -23290, -23297, -23297, +22856, +22856, +22909, +22923, +22923, +22923, +22930, +22930, +22942, +22942, +22974, +22981, +22981, +22988, +22988, +22988, +22995, +23002, +23002, +23009, +23067, +23210, +23233, +23252, +23259, +23266, +23286, +23286, +23292, +23292, +23299, 23314, -23314, -23345, -23348, -23372, -23396, +23332, +23332, 23409, -23430, -23454, -23468, -23471, -23474, -23474, -23510, -23542, -23542, -23578, -23585, -23585, -23585, -23611, -23630, -23656, -23667, -23667, -23696, -23696, -23706, -23713, -23742, -23749, -23771, -23785, -23818, -23818, -23828, -23831, -23859, -23862, -23875, -23881, -23903, -23903, -23926, -23976, -24004, -24004, -24015, -24028, -24031, -24038, -24073, -24095, -24119, -24160, -24179, -24198, -24204, -24210, -24237, -24240, -24265, -24268, -24281, -24293, -24309, +23420, +23420, +23420, +23420, +23434, +23463, +23485, +23493, +23509, +23550, +23554, +23554, +23554, +23554, +23554, +23567, +23567, +23634, +23801, +23808, +23825, +23839, +23854, +23891, +23891, +23908, +23915, +23922, +23922, +23922, +23929, +24005, +24027, +24046, +24046, +24046, +24046, +24097, +24142, +24155, +24162, +24172, +24172, +24186, +24208, +24208, +24208, +24215, +24222, +24251, +24300, +24311, +24318, 24325, 24332, -24344, -24354, -24357, -24363, -24414, -24438, -24475, -24497, -24518, -24553, -24565, -24586, -24589, -24589, -24592, -24617, -24617, -24620, -24658, -24658, -24661, -24661, -24661, -24735, -24735, -24735, +24341, +24341, +24361, +24361, +24361, +24367, +24397, +24404, +24439, +24446, +24455, +24461, +24461, +24461, +24479, +24479, +24486, +24486, +24491, +24499, +24513, +24529, +24529, +24529, +24529, +24536, +24564, +24736, 24742, -24762, -24793, -24793, -24816, -24819, -24826, -24843, -24843, +24742, +24750, +24750, +24757, +24757, +24757, +24757, +24757, +24764, +24764, +24764, +24799, +24807, +24807, +24807, +24807, +24815, +24830, +24855, 24863, -24875, -24882, -24915, -24949, -24972, -24972, -24993, -25027, -25027, -25079, -25101, -25104, -25124, -25144, -25164, -25190, -25193, -25250, -25253, -25291, -25297, -25307, -25353, -25356, -25356, -25368, -25368, -25368, -25377, -25377, -25377, -25407, -25407, -25407, -25419, -25422, -25431, -25444, -25469, -25490, -25504, -25552, -25552, -25572, -25572, -25575, -25592, -25595, -25607, -25617, -25620, -25626, -25653, -25659, -25671, -25688, -25741, -25751, -25754, -25757, -25760, -25763, -25785, -25799, -25828, -25849, -25855, -25868, -25881, -25891, -25897, -25907, -25913, -25927, -25930, -25983, -26001, -26021, -26040, -26055, -26079, -26157, -26160, -26180, -26183, -26189, -26189, -26201, -26222, +24863, +24877, +24877, +24877, +24893, +24893, +24911, +24911, +24911, +24945, +25049, +25059, +25059, +25068, +25081, +25088, +25088, +25088, +25088, +25088, +25088, +25088, +25088, +25110, +25122, +25130, +25130, +25152, +25152, +25152, +25202, +25211, +25211, +25235, +25235, +25241, +25241, +25241, +25266, +25273, +25273, +25296, +25395, +25395, +25402, +25402, +25402, +25425, +25425, +25432, +25432, +25432, +25432, +25432, +25432, +25457, +25463, +25474, +25474, +25474, +25474, +25485, +25532, +25532, +25532, +25542, +25542, +25542, +25542, +25542, +25554, +25554, +25558, +25616, +25717, +25723, +25723, +25723, +25723, +25723, +25723, +25734, +25743, +25743, +25743, +25743, +25748, +25787, +25787, +25787, +25787, +25787, +25787, +25794, +25845, +25845, +25860, +25885, +25885, +25885, +25898, +25898, +25898, +25898, +25898, +25922, +26200, +26200, +26207, +26213, +26213, +26232, +26232, +26232, +26232, +26244, 26251, 26251, 26251, -26251, -26251, -26251, -26287, -26287, -26311, -26311, -26348, -26353, +26299, +26299, +26299, +26299, +26299, +26299, +26322, +26339, +26368, +26368, 26387, 26387, -26403, -26406, -26406, -26450, -26466, -26487, -26502, -26502, -26552, -26552, -26588, -26624, -26639, -26649, -26659, -26684, -26715, -26746, -26751, -26751, -26773, -26799, -26799, -26799, -26799, -26799, -26811, -26821, -26860, -26881, -26893, -26902, -26941, -26948, -26955, -26968, -26978, -27015, -27043, -27068, -27068, -27068, -27075, -27100, -27112, -27141, -27141, -27159, -27159, -27166, -27188, -27188, -27188, -27194, -27204, -27235, -27247, -27247, -27258, -27281, -27281, -27310, -27310, -27310, -27310, -27317, -27349, -27368, -27393, -27399, -27399, -27451, -27455, -27455, -27461, -27467, -27486, -27498, -27501, -27501, -27523, -27523, -27544, -27551, +26387, +26387, +26387, +26399, +26399, +26404, +26437, +26506, +26516, +26516, +26538, +26538, +26538, +26538, +26538, +26538, +26538, +26548, +26553, +26553, +26614, +26630, +26630, +26630, +26630, +26630, +26637, +26687, +26706, +26706, +26706, +26713, +26713, +26713, +26713, +26713, +26713, +26713, +26757, +26912, +26912, +26912, +26917, +26934, +26944, +26944, +26944, +26944, +26944, +26944, +26944, +26944, +26997, +26997, +26997, +26997, +26997, +26997, +27006, +27006, +27014, +27014, +27021, +27021, +27021, +27021, +27021, +27021, +27021, +27036, +27036, +27151, +27151, +27156, +27168, +27168, +27182, +27182, +27182, +27182, +27182, +27182, +27182, +27182, +27239, +27239, +27239, +27239, +27239, +27239, +27239, +27322, +27322, +27322, +27322, +27322, +27322, +27322, +27322, +27322, +27334, +27342, +27398, +27517, +27522, +27530, +27530, +27538, 27557, -27564, -27574, -27574, -27574, -27596, -27596, -27606, -27606, -27606, -27606, -27643, -27643, -27649, -27684, -27691, -27700, -27700, -27716, -27723, -27723, -27748, -27748, -27748, -27748, -27773, -27773, -27773, -27787, -27798, -27820, -27820, -27820, -27820, -27827, -27827, -27827, -27839, -27855, -27855, -27861, -27865, -27894, -27894, -27917, -27929, -27954, -27961, -27961, -27968, -27984, -27984, -28007, -28007, -28007, -28014, -28029, -28036, -28046, -28063, -28075, -28084, -28093, -28093, -28093, -28124, -28136, -28136, -28177, -28186, -28199, -28213, -28219, -28219, -28235, -28251, -28259, -28281, -28281, -28281, -28294, -28294, -28313, -28326, -28326, -28333, -28333, -28343, -28343, -28378, +27557, +27557, +27557, +27565, +27573, +27573, +27573, +27614, +27620, +27620, +27620, +27620, +27633, +27661, +27746, +27746, +27746, +27746, +27746, +27746, +27746, +27757, +27757, +27757, +27766, +27795, +27882, +27882, +27882, +27882, +27890, +27890, +27898, +27898, +27898, +27904, +27904, +27904, +27904, +28070, +28077, +28077, +28077, +28077, +28083, +28103, +28145, +28170, +28170, +28170, +28176, +28176, +28176, +28184, +28214, +28214, +28214, +28269, +28380, +28380, +28395, +28395, 28395, 28407, -28419, -28419, -28441, -28448, -28468, -28490, -28498, -28498, -28498, -28511, -28517, -28524, -28582, -28582, -28582, -28589, -28589, -28609, -28616, -28645, -28645, -28645, -28677, -28694, -28694, -28694, -28703, -28725, -28725, -28743, -28743, -28743, -28749, -28749, -28769, -28775, -28791, -28791, -28800, -28800, -28814, -28821, -28821, -28827, -28841, -28841, -28856, -28872, -28897, -28897, -28897, -28897, -28940, -28976, -29003, -29003, -29003, -29013, -29013, -29039, -29044, -29051, -29075, -29126, -29151, -29151, -29158, -29158, -29170, -29191, -29215, -29229, +28407, +28407, +28407, +28407, +28407, +28407, +28411, +28478, +28478, +28478, +28478, +28486, +28486, +28504, +28554, +28599, +28615, +28615, +28615, +28630, +28630, +28630, +28655, +28655, +28655, +28698, +28828, +28828, +28836, +28836, +28836, +28836, +28836, +28836, +28836, +28836, +28836, +28843, +28843, +28889, +28901, +28911, +28915, +28927, +28927, +28936, +28990, +28990, +28990, +28995, +28995, +28995, +28995, +28995, +28995, +28995, +28995, +29040, +29202, +29217, +29217, +29225, 29241, -29241, -29266, -29278, -29307, -29307, +29256, +29261, +29261, +29261, +29261, +29261, +29261, +29272, +29316, 29323, -29335, -29335, -29335, -29335, +29323, +29333, +29333, 29345, -29374, -29406, -29418, -29428, -29428, -29428, -29448, -29448, -29448, -29473, -29532, -29538, -29549, -29549, -29549, -29561, -29561, -29561, -29585, -29585, -29618, -29632, -29649, +29364, +29390, +29415, +29427, +29446, +29446, +29446, +29446, +29446, +29459, +29459, +29459, +29495, +29616, +29616, +29626, +29635, 29655, -29655, -29660, -29660, -29660, -29660, -29681, -29694, -29706, -29706, -29729, -29740, -29740, -29740, -29759, -29778, -29824, -29824, -29849, -29870, -29889, -29912, -29912, -29921, -29925, -29925, -29940, -29971, -29971, -29971, -29971, +29663, +29663, +29663, +29663, +29671, +29671, +29671, +29696, +29719, +29723, +29723, +29723, +29723, +29723, +29723, +29735, +29748, +29748, +29756, +29756, +29761, +29761, +29771, +29771, +29771, +29771, +29789, +29975, +29975, 29988, -29988, -29988, -29988, -29988, -29988, -29988, -30002, -30002, -30002, +29996, +29996, +30001, +30001, +30001, +30001, 30011, -30023, -30035, -30061, -30061, -30092, -30092, -30120, -30127, -30127, -30132, -30132, -30132, -30142, -30154, +30011, +30011, +30011, +30074, +30081, +30081, +30081, +30081, +30081, +30107, +30148, +30148, +30148, 30160, -30173, -30185, -30207, -30216, -30216, -30216, -30216, -30233, -30242, -30259, -30275, -30290, -30290, -30290, -30290, -30290, -30316, -30335, -30395, -30395, -30405, -30427, -30427, -30435, -30435, -30435, -30435, -30435, -30435, -30459, -30476, -30483, -30483, -30483, -30483, -30483, -30504, -30522, -30522, -30538, -30573, -30573, -30573, -30573, -30573, -30573, -30579, -30591, -30614, -30623, -30628, -30628, -30638, -30654, +30160, +30160, +30160, +30160, +30160, +30160, +30160, +30160, +30235, +30235, +30235, +30235, +30235, +30246, +30246, +30246, +30246, +30251, +30251, +30251, +30268, +30331, +30347, +30363, +30374, +30374, +30374, +30374, +30378, +30400, +30400, +30421, +30421, +30428, +30441, +30441, +30464, +30464, +30464, +30497, +30588, +30588, +30588, +30588, +30608, +30621, +30621, +30621, +30621, +30621, +30621, +30621, +30626, +30694, +30694, +30694, 30699, -30699, -30730, -30730, -30730, -30752, -30785, -30793, -30793, -30793, -30808, -30861, -30873, -30873, -30899, -30907, -30907, -30907, -30919, -30919, -30939, -30939, -30944, -30944, -30965, -30985, -30993, -31011, +30707, +30711, +30727, +30763, +30800, +30800, +30800, +30800, +30800, +30800, +30807, +30816, +30816, +30816, +30828, +30956, +30972, +30972, +30983, +30983, +30983, +30983, +30983, +30983, +30999, +30999, +30999, 31019, -31019, -31019, -31036, -31048, -31048, -31081, -31108, -31108, -31108, -31124, -31131, -31167, -31208, -31219, -31229, -31239, -31245, -31245, -31245, -31255, -31262, -31283, -31283, -31283, -31283, -31283, -31297, -31297, -31309, -31328, -31328, -31366, -31386, -31404, -31404, -31420, -31436, -31475, -31489, -31489, -31523, -31523, -31543, -31543, -31555, -31583, +31034, +31034, +31034, +31034, +31034, +31043, +31043, +31077, +31096, +31105, +31105, +31105, +31111, +31111, +31111, +31111, +31111, +31111, +31123, +31292, +31299, +31318, +31318, +31318, +31341, +31341, +31341, +31347, +31351, +31351, +31351, +31351, +31382, +31382, +31382, +31382, +31382, +31382, +31391, +31391, +31397, +31414, +31428, +31428, +31428, +31428, +31428, +31440, +31440, +31450, +31491, 31605, -31629, -31644, -31644, -31644, -31665, -31675, -31710, -31729, -31749, -31761, -31761, -31775, -31804, -31804, -31830, -31830, -31859, -31871, -31897, -31910, -31910, -31922, -31957, -31980, -31990, -32038, -32094, -32094, -32112, -32135, -32135, -32135, -32146, -32181, -32181, -32227, +31605, +31616, +31625, +31643, +31652, +31652, +31652, +31659, +31671, +31671, +31671, +31696, +31771, +31771, +31805, +31805, +31809, +31809, +31823, +31866, +31866, +31875, +31875, +31875, +31875, +31875, +31875, +31905, +31905, +31905, +31918, +32101, +32101, +32101, +32101, +32105, +32105, +32105, +32105, +32105, +32105, +32105, +32105, +32105, +32178, +32178, +32178, +32178, +32188, +32194, +32200, +32247, +32247, +32247, +32247, +32247, +32247, +32247, +32247, +32247, 32255, -32277, -32296, -32308, -32320, -32320, -32324, -32328, -32328, -32358, -32373, -32397, -32409, -32421, -32421, -32442, -32442, -32478, -32490, -32497, -32502, -32517, -32517, -32579, -32600, -32619, -32619, +32259, +32303, +32448, +32462, +32476, +32480, +32480, +32494, +32494, +32494, +32494, +32500, +32500, +32500, +32500, +32539, +32539, +32547, +32547, +32547, +32547, +32565, +32592, +32603, +32603, +32618, +32623, 32634, -32652, -32683, -32720, -32740, -32747, -32747, -32758, -32758, -32794, -32826, -32838, -32865, -32885, -32901, -32905, -32905, -32919, -32919, -32919, -32931, -32954, -32986, -33024, -33046, -33079, -33079, -33079, -33079, -33079, -33079, -33090, -33090, -33141, -33149, -33174, -33174, -33186, -33202, -33202, -33230, -33251, -33261, -33274, -33300, +32634, +32634, +32649, +32649, +32657, +32696, +32872, +32872, +32872, +32872, +32872, +32872, +32887, +32887, +32887, +32887, +32887, +32887, +32887, +32938, +32938, +32942, +32942, +32942, +32942, +32942, +32942, +32950, +32950, +32962, +32962, +32962, +32962, +32966, +32978, +32978, +32978, +33018, +33190, +33190, +33198, +33198, +33210, +33216, +33216, +33216, +33216, +33216, +33216, +33216, +33226, +33243, +33243, +33243, +33243, +33243, +33250, +33250, +33296, +33296, +33296, +33303, +33303, +33303, 33318, -33323, -33360, -33360, -33405, -33452, -33452, -33452, -33452, -33480, -33480, -33510, -33531, -33531, -33531, -33531, -33531, -33531, -33531, -33538, -33560, -33560, -33567, -33580, -33580, -33595, -33649, -33661, -33673, -33673, -33719, -33719, -33756, -33756, -33778, -33812, -33845, -33858, -33872, -33872, -33872, -33872, -33898, -33898, -33898, -33931, -33931, -33939, -33939, -33939, -34008, -34042, -34042, -34081, -34088, -34088, -34088, -34094, -34105, -34143, -34150, -34150, -34150, -34166, -34189, -34203, -34222, -34233, -34257, -34263, -34279, -34279, -34293, -34313, -34321, -34321, -34329, -34329, -34347, -34377, -34385, -34385, +33318, +33318, +33318, +33318, +33331, +33501, +33501, +33508, +33508, +33508, +33508, +33515, +33515, +33515, +33515, +33515, +33515, +33515, +33534, +33540, +33540, +33540, +33540, +33553, +33553, +33579, +33599, +33599, +33620, +33620, +33620, +33620, +33620, +33627, +33627, +33627, +33664, +33889, +33903, +33916, +33916, +33916, +33926, +33926, +33926, +33926, +33933, +33940, +33940, +33948, +33967, +33978, +33984, +33984, +33984, +33984, +33996, +34031, +34031, +34031, +34048, +34048, +34055, +34062, +34062, +34072, +34072, +34072, +34098, +34239, +34239, +34251, +34251, +34251, +34251, +34251, +34251, +34251, +34251, +34251, +34251, +34269, +34306, +34312, +34312, +34312, +34312, +34312, +34336, +34359, +34359, +34359, +34363, +34363, +34363, +34371, +34371, +34371, +34371, +34371, 34407, -34420, -34420, -34439, -34439, -34439, -34450, -34458, -34467, -34467, -34490, -34520, -34539, -34556, -34560, -34560, -34587, -34587, -34630, -34630, -34630, -34652, -34652, -34660, -34684, -34724, +34513, +34513, +34513, +34513, +34534, +34546, +34546, +34546, +34559, +34559, +34559, +34559, +34559, +34594, +34604, +34604, +34604, +34608, +34614, +34651, +34680, +34691, +34691, +34701, +34701, +34705, +34705, +34721, 34734, -34758, -34758, -34772, -34772, -34776, -34776, -34798, -34798, -34798, -34798, -34798, -34798, -34815, -34815, -34826, -34826, -34857, -34857, -34857, -34857, -34865, -34865, -34896, -34912, -34963, -34971, -34971, -34990, +34734, +34734, +34777, +34866, +34866, +34885, +34885, +34885, +34920, +34920, +34924, +34924, +34924, +34931, +34931, +34931, +34953, +34968, +34968, +34968, +34968, +34974, +34993, 35012, 35012, -35035, -35062, -35062, -35095, -35104, -35144, -35166, -35166, -35187, -35187, -35187, -35187, -35203, -35203, -35224, -35224, -35228, -35228, -35228, -35255, -35268, -35273, -35300, -35306, -35306, -35317, -35317, -35344, -35392, -35392, -35392, -35411, -35420, -35435, -35435, -35471, -35489, -35493, -35493, -35512, -35518, -35518, -35536, -35536, -35536, -35564, -35581, -35581, -35581, -35581, -35606, -35606, -35610, -35627, -35627, -35641, -35641, -35641, -35641, -35647, -35647, -35647, -35647, -35647, -35659, -35659, -35659, -35669, -35695, -35731, -35731, -35755, -35760, -35772, -35772, -35772, -35772, -35772, -35787, -35787, -35808, -35808, -35821, -35838, -35867, -35867, -35872, -35872, -35904, -35923, -35928, -35928, -35928, -35928, -35944, -35955, -35955, -35959, -35971, -35971, -35971, -35975, +35012, +35045, +35045, +35045, +35066, +35066, +35081, +35081, +35081, +35146, +35334, +35334, +35334, +35334, +35338, +35338, +35338, +35338, +35345, +35359, +35359, +35359, +35359, +35410, +35410, +35410, +35410, +35415, +35415, +35433, +35483, +35483, +35483, +35500, +35500, +35500, +35500, +35500, +35511, +35511, +35511, +35525, +35682, +35682, +35682, +35682, +35706, +35706, +35706, +35706, +35706, +35724, +35724, +35724, +35724, +35740, +35740, +35740, +35740, +35750, +35750, +35750, +35750, +35773, +35773, +35773, +35773, +35790, +35790, +35790, +35830, +35830, +35830, +35853, +35949, +35960, +35960, +35964, +35964, +35964, +35969, +35969, +35969, +35969, 35979, -35993, -35993, -36026, -36026, -36026, -36038, -36038, -36038, -36054, -36101, -36133, -36157, -36157, -36175, -36194, -36194, -36198, -36236, -36236, -36267, -36276, -36276, -36276, -36302, -36306, -36315, -36332, -36342, -36342, -36352, -36352, -36379, -36379, -36379, -36379, -36379, -36386, -36386, -36386, -36399, -36414, -36430, -36430, -36444, -36444, -36460, -36477, -36491, -36524, -36554, -36571, -36582, -36601, -36601, -36601, -36605, -36623, -36644, -36654, -36654, -36671, -36671, -36671, -36671, -36671, -36671, -36681, -36692, -36692, -36692, -36707, -36707, -36724, -36724, -36736, -36736, -36747, -36757, -36757, -36776, -36776, -36796, -36796, -36809, -36809, -36847, -36847, -36881, -36907, -36913, -36913, -36913, -36926, -36945, -36959, -36959, -36959, -36987, -36987, -36987, -36999, -37016, -37039, -37039, -37077, -37077, -37103, -37136, -37157, -37190, -37200, -37218, -37218, -37218, -37218, -37224, -37224, +35988, +35988, +35988, +35988, +36007, +36007, +36007, +36007, +36017, +36047, +36058, +36058, +36070, +36070, +36070, +36070, +36070, +36070, +36070, +36070, +36113, +36250, +36258, +36268, +36268, +36268, +36274, +36274, +36290, +36290, +36290, +36290, +36290, +36290, +36360, +36387, +36387, +36387, +36387, +36387, +36396, +36443, +36443, +36443, +36459, +36459, +36459, +36459, +36459, +36471, +36471, +36471, +36534, +36642, +36655, +36655, +36655, +36673, +36684, +36684, +36684, +36684, +36684, +36684, +36684, +36684, +36839, +36844, +36844, +36844, +36844, +36853, +36859, +36919, +36952, +36952, +36956, +36956, +36956, +36956, +36956, +36982, +36982, +36982, +36994, 37251, -37258, -37273, -37273, -37286, -37294, -37294, -37305, -37305, -37305, -37305, -37319, -37319, -37319, -37337, -37356, -37356, -37356, -37356, -37356, -37356, -37356, -37369, -37369, -37380, -37380, -37393, -37408, +37251, +37251, +37257, +37257, +37269, +37269, +37269, +37269, +37269, +37269, +37269, +37269, +37324, +37342, +37360, +37365, +37370, +37378, +37386, +37412, 37423, 37423, -37423, -37423, -37423, -37441, -37453, -37458, -37474, -37474, -37487, -37487, -37501, -37501, -37501, -37522, -37522, -37522, -37522, -37535, -37542, -37561, -37561, -37561, -37561, -37574, -37590, -37590, -37621, -37621, -37642, -37649, -37649, -37649, -37653, -37679, -37679, -37698, -37717, -37717, -37717, -37735, -37757, -37809, -37832, -37840, -37840, -37840, -37840, -37856, -37878, -37892, -37938, -37938, -37947, -37957, -37964, -37964, -37987, -38028, -38043, -38062, -38062, -38077, -38087, -38143, -38143, -38143, -38186, -38186, -38186, -38215, -38224, -38224, -38224, -38224, -38224, -38224, -38253, -38253, -38253, -38253, -38257, -38313, -38348, -38381, +37428, +37428, +37428, +37428, +37428, +37455, +37455, +37455, +37482, +37618, +37618, +37637, +37637, +37659, +37670, +37670, +37670, +37670, +37670, +37670, +37682, +37682, +37744, +37752, +37758, +37766, +37766, +37766, +37766, +37851, +37876, +37876, +37895, +37895, +37918, +37918, +37918, +37918, +37918, +37918, +37968, +38046, +38055, +38055, +38055, +38073, +38092, +38092, +38092, +38092, +38098, +38098, +38098, +38113, +38208, +38208, +38208, +38208, +38214, +38230, +38239, +38254, +38254, +38254, +38264, +38264, +38264, +38264, +38264, +38264, +38264, +38264, +38299, +38350, +38350, +38360, +38360, +38376, 38396, 38396, 38396, 38396, -38420, -38440, -38461, -38461, -38461, -38461, -38461, -38461, -38461, -38480, -38493, -38511, -38511, -38511, -38511, -38531, -38539, -38539, -38548, -38560, -38560, -38564, -38583, -38583, -38599, -38624, -38642, -38642, -38642, -38642, -38652, -38668, -38668, -38684, -38692, -38692, -38692, -38692, -38692, -38692, -38698, -38698, -38704, -38730, -38738, -38738, -38763, -38763, -38763, -38763, -38781, -38781, -38781, -38802, -38802, -38802, -38802, -38831, -38831, -38836, -38852, -38865, -38911, -38925, -38942, -38958, -38958, -38971, -38971, -38977, -39012, -39019, -39025, -39025, -39047, -39047, -39057, -39093, -39118, -39118, -39118, -39128, -39128, -39128, -39156, -39166, -39166, -39176, -39194, +38403, +38403, +38403, +38403, +38439, +38439, +38445, +38445, +38445, +38445, +38445, +38521, +38521, +38521, +38534, +38538, +38538, +38538, +38538, +38557, +38557, +38557, +38656, +38707, +38707, +38707, +38707, +38716, +38725, +38725, +38736, +38743, +38743, +38743, +38743, +38743, +38743, +38756, +38779, +38779, +38779, +38779, +38789, +38812, +38823, +38823, +38845, +38845, +38845, +38845, +38868, +38878, +38878, +38878, +38935, +39026, +39038, +39038, +39038, +39048, +39048, +39048, +39048, +39048, +39048, +39056, +39056, +39056, +39109, +39113, +39140, +39152, +39152, +39152, +39172, +39184, +39184, +39184, 39204, -39232, -39276, -39276, -39276, -39305, -39305, -39305, -39317, -39346, -39366, -39366, -39366, -39378, -39378, -39378, -39395, +39214, +39214, +39214, +39219, +39228, +39239, +39239, +39260, +39396, +39402, +39402, +39402, +39408, +39414, +39414, +39414, +39414, +39420, +39420, +39420, 39427, -39434, -39470, -39470, -39470, -39470, -39470, -39476, -39476, -39476, -39476, -39504, -39551, -39561, -39561, -39590, -39598, -39598, -39598, -39610, -39616, -39616, -39631, -39631, -39631, -39652, -39657, -39664, -39678, -39678, -39695, -39695, -39695, -39695, -39701, -39701, -39752, -39774, -39774, -39781, -39781, -39791, -39810, -39821, -39836, -39836, -39856, -39886, -39886, -39901, -39910, -39917, -39917, -39929, -39929, -39929, -39939, -39953, -39953, -39953, -39957, -39964, -39981, -39981, -39993, -39993, -40000, -40004, -40014, -40014, -40014, -40014, -40014, -40014, -40014, -40014, -40014, -40014, -40014, -40037, -40037, -40044, -40067, -40089, -40102, -40102, -40106, -40112, -40112, -40112, -40139, -40149, -40149, -40187, -40187, -40198, -40219, -40219, -40237, -40244, -40268, -40304, -40320, -40336, -40350, -40350, -40350, -40358, -40367, -40367, -40376, -40376, -40390, -40390, -40409, -40409, -40428, -40454, -40462, -40469, -40469, -40479, -40484, -40484, +39439, +39439, +39451, +39451, +39451, +39457, +39498, +39535, +39549, +39549, +39549, +39549, +39549, +39549, +39554, +39564, +39564, +39586, +39662, +39766, +39766, +39766, +39776, +39776, +39776, +39776, +39776, +39790, +39790, +39790, +39790, +39790, +39847, +39847, +39853, +39853, +39864, +39864, +39878, +39884, +39897, +39897, +39919, +39919, +39919, +39919, +39919, +39927, +39927, +39927, +39963, +40050, +40076, +40076, +40076, +40095, +40095, +40095, +40095, +40095, +40101, +40101, +40101, +40101, +40101, +40101, +40101, +40101, +40101, +40107, +40123, +40170, +40191, +40191, +40217, +40217, +40217, +40217, +40224, +40243, +40243, +40243, +40309, +40380, +40380, +40380, +40380, +40380, +40389, +40389, +40402, +40415, +40415, +40415, +40415, +40415, +40493, +40500, +40507, +40519, 40526, -40535, -40557, -40583, -40587, -40587, -40620, -40639, -40644, -40644, -40644, -40644, -40644, -40644, -40644, -40644, -40663, -40663, -40677, -40677, -40677, -40677, -40677, -40697, -40715, -40715, -40734, -40734, -40734, -40734, -40734, -40734, -40734, -40734, -40734, -40741, -40751, -40751, -40780, -40780, -40793, -40815, -40824, -40824, -40848, -40865, -40893, -40897, -40918, -40966, -40966, -40966, -40966, -40966, -40966, -40966, -40989, -40989, -41002, -41024, -41030, -41054, -41054, +40534, +40540, +40540, +40545, +40545, +40545, +40551, +40566, +40566, +40566, +40566, +40566, +40566, +40604, +40687, +40687, +40687, +40687, +40687, +40691, +40691, +40691, +40691, +40691, +40691, +40691, +40691, +40703, +40703, +40719, +40719, +40719, +40719, +40748, +40813, +40837, +40837, +40837, +40843, +40849, +40849, +40849, +40849, +40849, +40849, +40926, +41021, +41021, +41035, +41035, +41044, +41044, +41044, +41050, +41050, 41058, 41071, -41071, -41091, -41095, -41095, -41095, -41095, -41117, -41140, -41140, -41156, -41156, -41161, -41192, -41205, -41233, -41233, -41251, -41251, -41251, -41251, -41251, -41288, -41314, -41333, -41333, -41333, -41349, -41379, -41407, -41426, -41439, -41457, -41457, -41457, -41482, -41482, -41493, -41500, -41531, -41542, -41542, -41550, -41550, -41550, -41577, -41577, -41606, -41625, -41642, -41701, -41728, -41753, +41083, +41096, +41158, +41158, +41158, +41158, +41158, +41158, +41164, +41220, +41228, +41228, +41253, +41253, +41260, +41260, +41260, +41268, +41268, +41268, +41295, +41418, +41441, +41451, +41455, +41463, +41472, +41472, +41472, +41472, +41472, +41487, +41487, +41487, +41533, +41533, +41533, +41533, +41533, +41533, +41551, +41572, +41572, +41572, +41572, +41595, +41595, +41595, +41600, +41628, +41628, +41628, +41639, +41664, +41664, +41681, +41681, +41681, +41681, +41681, +41681, +41681, +41681, +41681, +41681, +41681, +41696, +41702, +41714, +41714, +41714, +41714, +41714, +41755, +41755, +41755, +41755, +41755, +41755, +41755, +41755, +41778, +41778, 41793, -41809, -41814, -41814, -41818, -41850, -41867, -41867, -41892, -41904, -41904, -41904, +41826, +41901, +41901, +41908, +41908, +41916, 41937, -41937, -41953, -41953, -41953, -41953, -41996, -42006, -42015, -42015, -42032, -42032, -42032, -42032, -42042, -42067, -42067, -42101, -42101, -42129, -42129, -42129, -42129, -42136, -42145, -42145, -42145, -42155, -42179, -42210, -42217, -42234, -42249, -42266, -42278, -42278, -42278, -42298, -42298, -42298, -42308, -42308, -42314, -42314, -42328, -42338, -42349, -42356, -42362, -42376, -42383, -42446, -42446, -42446, -42473, -42473, -42473, -42485, -42503, -42503, -42543, -42578, +41952, +41958, +41958, +41958, +41958, +41958, +41958, +41998, +41998, +42018, +42018, +42026, +42026, +42026, +42046, +42046, +42046, +42074, +42074, +42080, +42089, +42096, +42107, +42107, +42107, +42140, +42235, +42235, +42242, +42242, +42242, +42242, +42242, +42248, +42248, +42258, +42264, +42271, +42271, +42354, +42360, +42360, +42360, +42366, +42366, +42372, +42378, +42397, +42397, +42402, +42402, +42402, +42410, +42410, +42419, +42419, +42419, +42461, +42590, +42590, 42617, 42617, -42617, -42631, -42631, -42638, -42638, -42638, -42659, -42686, -42686, -42686, -42701, -42708, -42708, -42727, -42727, -42727, -42742, -42742, +42633, +42633, +42633, +42633, +42633, +42633, +42633, +42633, +42633, +42646, +42646, +42646, +42646, +42657, +42657, +42682, +42719, +42719, +42719, +42733, +42733, +42733, +42733, +42733, +42733, +42733, +42739, 42770, -42770, -42777, -42777, -42809, -42820, -42820, -42820, -42820, -42820, -42835, -42881, -42881, -42881, -42889, -42900, -42918, -42933, -42951, -42978, -43005, -43005, -43005, -43050, -43050, -43059, -43082, -43082, -43146, -43146, -43175, -43175, -43175, -43184, -43184, -43204, -43204, -43204, -43204, -43222, -43231, -43237, -43237, -43246, -43246, -43276, -43309, -43315, -43334, -43334, -43340, -43347, -43368, -43377, -43390, -43394, -43425, -43425, -43425, -43442, -43442, -43462, -43462, -43492, -43517, -43517, -43517, -43554, -43554, -43578, -43578, -43591, -43606, -43606, -43606, -43631, -43652, -43652, -43660, -43660, -43690, -43690, -43716, -43716, -43716, -43750, -43758, -43775, -43800, -43832, -43836, -43836, -43850, -43861, -43861, -43861, -43861, -43883, -43883, -43889, -43895, -43895, -43905, -43905, -43958, -43996, -44008, -44008, -44024, -44057, -44085, -44090, -44090, -44100, -44100, -44100, -44106, -44106, -44121, -44138, +42913, +42919, +42934, +42934, +42934, +42948, +42948, +42948, +42948, +42948, +42948, +42948, +42948, +42963, +42975, +42982, +42982, +42982, +42982, +42992, +43062, +43085, +43085, +43103, +43103, +43103, +43103, +43103, +43103, +43103, +43103, +43158, +43257, +43271, +43284, +43292, +43292, +43301, +43301, +43301, +43301, +43306, +43314, +43314, +43314, +43362, +43362, +43395, +43395, +43405, +43412, +43420, +43479, +43479, +43479, +43502, +43502, +43502, +43502, +43502, +43502, +43502, +43502, +43514, +43600, +43628, +43638, +43644, +43648, +43648, +43653, +43659, +43659, +43659, +43659, +43659, +43659, +43770, +43780, +43796, +43796, +43802, +43802, +43802, +43808, +43808, +43808, +43813, +43813, +43821, +43821, +43821, +43821, +43821, +43821, +43865, +44009, +44027, +44034, +44034, +44034, +44041, +44041, +44041, +44052, +44052, +44052, +44052, +44052, +44077, +44077, +44077, +44077, +44077, +44077, +44086, +44096, +44096, +44096, +44111, +44111, +44125, +44125, +44125, 44154, -44185, -44227, -44231, -44231, -44231, -44231, -44231, -44262, -44289, -44302, -44302, -44326, -44356, -44385, -44385, -44407, -44414, -44414, -44431, -44447, -44465, -44484, -44501, -44525, -44532, -44544, -44553, -44559, -44575, -44575, -44575, -44575, -44575, -44585, -44598, -44614, -44627, -44647, -44667, -44667, -44686, -44702, -44702, -44702, -44702, -44709, -44709, -44709, -44709, -44719, -44719, -44719, -44766, -44830, -44830, -44843, -44843, -44851, -44851, -44858, +44154, +44154, +44187, +44250, +44256, +44272, +44278, +44278, +44278, +44278, +44278, +44278, +44278, +44278, +44278, +44282, +44338, +44359, +44374, +44384, +44384, +44384, +44400, +44418, +44432, +44432, +44432, +44432, +44452, +44452, +44452, +44452, +44452, +44452, +44495, +44678, +44678, +44698, +44698, +44698, +44710, +44710, +44710, +44710, +44717, +44717, +44717, +44717, +44753, +44753, +44753, +44753, +44753, +44753, +44753, +44822, +44846, +44846, +44857, +44857, 44866, 44866, -44872, -44872, -44907, -44907, -44920, -44920, -44933, -44947, -44957, -44971, -44971, -44978, -44978, -44999, -44999, -45033, -45059, -45065, -45084, -45116, -45136, -45145, -45207, -45207, -45207, -45207, -45207, -45207, -45217, -45217, -45245, -45259, -45259, -45259, -45259, -45267, -45274, -45274, -45301, -45301, -45352, -45392, -45392, -45422, -45422, -45422, -45422, -45422, -45435, -45435, -45448, -45486, -45486, -45520, -45534, -45534, -45545, -45545, -45551, -45569, +44866, +44878, +44878, +44878, +44878, +44986, +44992, +45003, +45003, +45011, +45011, +45011, +45011, +45011, +45011, +45011, +45011, +45031, +45131, +45137, +45137, +45137, +45147, +45155, +45155, +45183, +45183, +45198, +45208, +45215, +45224, +45231, +45236, +45236, +45236, +45236, +45271, +45379, +45379, +45398, +45398, +45414, +45419, +45419, +45425, +45432, +45432, +45432, +45432, +45432, +45487, +45493, +45493, +45493, +45505, +45505, +45505, +45535, +45558, +45558, 45586, -45594, -45594, -45594, -45594, -45594, -45627, -45646, -45656, -45656, -45656, -45656, -45677, -45677, -45677, -45688, -45716, -45724, -45724, -45743, -45743, -45758, -45769, -45780, -45796, -45816, -45852, -45860, -45869, -45880, -45880, -45888, -45915, -45915, -45915, -45915, -45915, -45933, -45954, -45959, -45981, -45994, -46008, -46032, -46032, -46040, -46052, -46052, -46061, -46081, -46081, -46081, -46081, -46081, -46081, -46088, -46107, -46118, -46145, -46181, -46189, -46208, -46223, -46240, -46257, -46257, -46287, -46306, -46336, -46336, -46336, -46345, -46345, -46345, -46355, -46355, -46376, -46387, +45586, +45593, +45593, +45593, +45593, +45593, +45593, +45643, +45784, +45784, +45799, +45811, +45811, +45824, +45824, +45824, +45824, +45824, +45824, +45824, +45824, +45883, +45890, +45902, +45906, +45919, +45925, +45939, +46016, +46064, +46064, +46064, +46064, +46077, +46086, +46086, +46101, +46101, +46101, +46144, +46290, +46294, +46308, +46317, +46317, +46329, +46329, +46329, +46329, +46342, +46342, +46342, +46362, +46400, 46412, -46453, -46478, -46509, -46509, -46530, -46552, -46581, -46592, -46641, -46668, -46686, -46746, -46746, -46746, -46764, -46772, -46772, -46780, -46812, -46812, -46812, -46835, -46850, -46866, -46866, -46866, -46870, -46870, +46432, +46432, +46439, +46439, +46459, +46512, +46521, +46521, +46521, +46521, +46521, +46521, +46521, +46546, +46546, +46546, +46565, +46684, +46711, +46711, +46711, +46719, +46719, +46725, +46725, +46725, +46738, +46738, +46769, +46775, +46811, +46815, +46815, +46815, +46815, +46815, +46823, +46847, +46861, +46861, +46881, +46885, +46885, +46898, +46898, 46908, 46908, 46908, -46921, -46921, -46921, -46921, -46953, -46957, -46957, -46957, -46970, -46970, -46994, -46994, -47006, -47028, -47028, -47062, -47080, -47104, -47142, -47160, -47190, -47209, -47215, -47236, -47254, -47295, -47310, -47346, -47354, -47354, -47354, -47367, -47380, -47380, -47380, -47403, -47403, -47403, -47425, -47453, -47462, -47484, -47503, -47551, -47573, -47593, -47617, -47617, -47617, -47617, -47636, -47699, -47699, -47762, -47762, -47790, -47811, -47820, -47846, -47846, -47883, -47883, -47893, -47893, -47893, -47893, -47909, -47935, -47947, -47954, -47958, -47962, -48019, -48019, -48019, -48028, -48035, -48041, -48051, -48051, -48057, -48068, -48087, -48099, -48126, -48126, -48126, -48126, -48126, -48126, -48153, -48169, -48179, -48179, -48184, -48194, -48225, -48225, -48225, -48225, -48255, -48255, -48255, -48265, -48265, -48302, -48331, -48357, -48357, -48376, -48387, -48415, -48415, -48427, -48427, -48442, -48442, -48442, -48442, -48460, -48489, -48505, -48520, -48520, -48550, -48550, -48550, -48561, +46954, +47024, +47030, +47041, +47041, +47041, +47050, +47050, +47066, +47066, +47066, +47066, +47066, +47072, +47134, +47157, +47164, +47164, +47164, +47164, +47173, +47223, +47232, +47232, +47232, +47237, +47237, +47237, +47247, +47271, +47271, +47271, +47280, +47415, +47415, +47415, +47415, +47427, +47443, +47443, +47443, +47443, +47443, +47451, +47451, +47451, +47520, +47520, +47532, +47532, +47532, +47532, +47542, +47632, +47632, +47632, +47651, +47651, +47651, +47651, +47651, +47659, +47659, +47659, +47706, +47776, +47782, +47799, +47799, +47806, +47827, +47827, +47827, +47834, +47838, +47838, +47838, +47838, +47924, +47924, +47924, +47924, +47924, +47924, +47934, +47988, +48007, +48007, +48026, +48033, +48037, +48046, +48046, +48072, +48072, +48072, +48104, +48181, +48195, +48205, +48205, +48205, +48205, +48205, +48220, +48220, +48220, +48230, +48230, +48230, +48287, +48287, +48287, +48287, +48287, +48287, +48313, +48313, +48325, +48325, +48332, +48332, +48337, +48337, +48344, +48344, +48344, +48344, +48409, +48559, 48573, -48604, -48610, -48624, +48616, +48629, +48639, +48639, +48639, +48639, +48639, 48644, -48653, -48653, -48653, -48653, -48653, -48663, -48675, -48731, -48742, -48742, -48757, -48762, -48769, -48787, -48794, -48794, -48794, -48815, -48815, -48815, -48845, -48845, -48845, -48845, -48845, -48845, -48865, -48865, -48889, -48898, -48912, -48927, -48927, -48981, -49001, -49001, -49052, +48644, +48644, +48644, +48718, +48726, +48726, +48726, +48735, +48746, +48764, +48772, +48786, +48804, +48826, +48826, +48830, +48830, +48842, +48842, +48852, +48859, +48903, +49022, +49022, +49036, +49036, +49036, 49058, -49079, -49115, -49115, -49121, -49121, -49142, -49142, -49153, -49179, -49179, -49179, -49222, -49272, -49279, -49279, -49279, -49279, +49058, +49058, +49058, +49058, +49067, +49067, +49067, +49139, +49152, +49152, +49152, +49152, +49152, +49183, +49228, +49237, +49237, +49237, +49241, +49249, +49249, +49249, +49253, +49253, +49253, 49287, -49305, -49305, -49305, -49351, -49361, -49370, -49370, -49378, -49378, -49378, -49382, -49382, -49406, -49424, -49424, -49455, -49471, -49502, -49502, -49506, -49506, -49526, -49526, -49545, -49563, -49642, +49494, +49494, +49511, +49519, +49548, +49548, +49548, +49548, +49555, +49559, +49559, +49559, +49559, +49559, +49581, +49581, +49581, +49596, +49596, +49609, +49609, +49629, +49629, +49629, +49629, +49629, +49629, +49633, +49654, 49659, -49663, -49667, -49688, -49700, -49726, -49739, -49739, -49755, -49771, -49782, -49811, -49811, -49819, -49843, -49843, -49843, -49851, -49864, -49864, -49882, -49882, -49882, -49911, -49933, -49933, -49976, -49992, -50003, -50011, -50011, -50011, -50011, -50058, -50064, -50083, -50114, -50114, -50131, -50131, -50154, -50207, -50207, -50215, -50215, -50232, -50236, -50252, -50252, -50252, -50252, -50257, -50275, -50293, -50293, -50307, -50336, -50336, -50336, -50336, -50336, -50336, -50336, -50389, -50425, -50452, -50478, -50521, -50521, -50548, -50586, -50586, -50593, -50601, -50640, -50672, -50672, -50691, -50746, -50746, -50746, -50768, -50773, -50773, -50773, -50791, -50791, -50801, -50816, -50828, -50836, -50861, -50861, -50877, -50877, -50902, -50910, -50910, -50910, -50927, -50949, -50968, -50986, -51002, -51002, -51031, -51031, -51041, -51041, -51041, -51041, -51047, -51064, -51072, -51072, -51072, -51072, -51072, -51072, -51088, -51107, -51107, -51107, -51107, -51112, -51130, -51130, -51130, +49659, +49686, +49790, +49802, +49802, +49809, +49809, +49855, +49855, +49855, +49855, +49855, +49855, +49855, +49859, +49859, +49859, +49859, +49859, +49871, +49880, +49880, +49920, +49920, +49920, +49928, +49928, +49928, +49928, +49928, +49939, +49939, +49939, +49969, +50135, +50144, +50152, +50152, +50173, +50183, +50183, +50183, +50183, +50189, +50189, +50189, +50189, +50211, +50227, +50270, +50284, +50284, +50284, +50284, +50358, +50369, +50369, +50385, +50385, +50385, +50385, +50395, +50395, +50395, +50395, +50458, +50503, +50508, +50527, +50534, +50550, +50557, +50564, +50571, +50571, +50578, +50578, +50578, +50585, +50625, +50631, +50651, +50651, +50658, +50678, +50678, +50723, +50735, +50735, +50743, +50750, +50750, +50764, +50764, +50764, +50771, +50778, +50827, +50915, +50931, +50944, +50951, +50966, +50997, +50997, +50997, +51012, +51019, +51026, +51026, +51026, +51144, 51151, -51198, -51214, -51238, +51193, +51193, +51193, +51193, +51193, +51218, 51251, -51277, -51308, -51325, -51325, -51329, -51337, -51371, -51371, -51386, -51404, -51404, -51404, -51430, -51430, -51442, -51442, -51458, -51458, -51516, -51534, -51595, -51606, -51615, -51615, -51647, -51675, -51689, -51689, -51722, -51722, -51729, -51735, -51735, -51735, -51742, -51742, -51752, -51771, -51791, -51815, -51815, -51815, -51830, -51865, -51865, -51865, -51886, -51921, -51921, -51939, -51939, -51948, -51948, -51954, -51954, -51961, -51961, -51970, -51989, -52024, -52024, -52030, -52030, -52030, -52030, -52052, +51251, +51289, +51289, +51296, +51296, +51296, +51326, +51333, +51333, +51389, +51461, +51461, +51461, +51468, +51468, +51468, +51468, +51484, +51484, +51484, +51491, +51491, +51491, +51629, +51629, +51629, +51629, +51635, +51635, +51645, +51674, +51683, +51683, +51683, +51683, +51683, +51690, +51690, +51690, +51697, +51697, +51704, +51853, +51853, +51879, +51893, +51893, +51909, +51909, +51916, +51926, +51926, +51926, +51926, +51933, +51976, +51983, +51983, +51994, +51999, +52006, +52006, +52053, 52060, 52060, 52060, 52060, -52060, -52060, -52060, -52079, -52086, -52086, -52138, -52138, -52188, -52198, -52198, -52198, -52198, -52198, -52202, -52218, -52233, -52252, -52252, -52261, -52261, -52273, -52273, -52288, -52293, -52324, -52340, -52340, -52392, -52392, -52392, -52399, -52423, -52423, -52471, -52489, -52489, -52489, -52489, -52489, -52489, -52505, -52512, -52531, -52563, -52567, -52582, -52604, -52604, +52067, +52067, +52074, +52083, +52083, +52090, +52090, +52152, +52178, +52178, +52185, +52199, +52199, +52199, +52199, +52199, +52199, +52199, +52199, +52213, +52278, +52291, +52291, +52291, +52298, +52305, +52318, +52381, +52395, +52395, +52428, +52428, +52428, +52428, +52428, +52437, +52437, +52437, +52484, +52585, +52585, +52599, 52608, 52608, -52629, -52664, +52616, +52625, +52638, +52645, +52652, +52652, +52652, +52652, +52665, +52678, +52678, +52678, 52685, -52695, -52695, -52695, -52695, -52695, -52735, -52763, -52763, -52775, -52775, -52782, -52782, -52804, -52804, -52804, -52804, -52804, +52692, +52699, +52778, +52785, +52785, 52811, -52829, -52842, -52863, -52863, -52863, -52883, -52883, -52922, -52944, -52944, -52953, -52953, -52953, -52983, -52983, -53004, -53013, -53013, -53013, -53013, -53045, -53061, -53066, -53066, -53072, -53076, -53076, -53091, -53091, -53091, -53103, -53112, -53138, -53138, +52811, +52818, +52825, +52832, +52832, +52832, +52832, +52860, +53022, +53037, +53057, +53064, +53064, +53087, +53094, +53121, +53121, +53140, +53140, +53147, 53154, -53201, -53228, -53228, -53228, -53244, -53244, -53266, -53271, -53271, -53279, -53299, -53312, -53319, +53196, +53202, +53209, +53209, +53215, +53215, +53234, +53259, +53276, +53290, +53322, 53336, -53389, -53398, -53398, -53398, -53423, -53433, -53445, -53445, -53465, -53465, -53465, -53492, -53497, -53525, -53563, -53563, -53583, -53588, -53588, -53588, -53588, -53588, -53598, -53598, -53627, -53651, -53651, -53658, -53672, -53679, -53708, -53708, -53708, -53715, -53715, -53715, -53715, -53715, -53721, -53736, -53764, -53764, -53764, -53764, -53764, -53764, -53783, -53783, -53805, -53815, -53815, -53815, -53829, -53829, -53843, -53843, -53843, -53854, -53864, -53871, -53878, -53911, -53946, -53964, +53350, +53357, +53357, +53357, +53357, +53357, +53412, +53620, +53620, +53637, +53650, +53675, +53693, +53693, +53693, +53693, +53693, +53700, +53700, +53700, +53707, +53730, +53730, +53730, +53747, +53747, +53747, +53771, +53778, +53778, +53778, +53785, +53785, +53785, +53800, +53807, +53807, +53814, +53824, +53952, +53965, 53972, -53972, -53972, -53989, -53993, -54039, -54051, -54065, -54072, -54095, -54095, -54114, -54114, -54121, -54130, -54141, -54141, -54162, -54185, -54185, -54193, -54204, -54204, -54204, -54216, -54216, -54216, -54216, -54227, -54233, -54245, -54252, -54260, -54260, -54266, -54286, -54312, -54319, -54319, -54330, -54330, -54346, -54346, -54356, -54356, -54356, -54356, -54391, +53979, +53986, +54010, +54023, +54023, +54023, +54037, +54037, +54037, +54044, +54061, +54061, +54085, +54085, +54096, +54096, +54118, +54147, +54147, +54147, +54152, +54152, +54152, +54152, +54152, +54152, +54152, +54152, +54188, +54366, +54384, 54398, -54403, -54411, -54426, -54426, -54426, -54449, -54460, -54492, -54492, -54498, -54533, -54564, -54564, -54609, -54631, -54663, -54663, -54663, -54663, -54677, -54677, -54709, -54709, -54760, -54767, -54777, -54777, -54781, -54808, -54808, -54835, -54856, -54873, -54888, -54902, -54927, -54939, +54405, +54418, +54425, +54425, +54439, +54446, +54455, +54455, +54455, +54462, +54547, +54547, +54562, +54562, +54562, +54562, +54569, +54576, +54576, +54576, +54576, +54583, +54590, +54597, +54607, +54628, +54635, +54642, +54729, +54878, +54885, +54910, +54910, +54924, 54947, -54977, -55031, -55047, -55047, -55075, -55085, -55115, -55134, -55146, -55183, -55206, -55206, -55206, -55206, -55206, -55227, -55227, -55242, -55242, -55242, -55252, -55263, -55288, -55294, -55294, -55301, -55308, -55314, -55386, -55403, -55403, -55423, -55432, -55443, -55443, -55443, -55448, -55458, -55458, -55458, -55478, -55499, -55518, -55522, -55538, -55551, -55551, -55551, -55551, -55551, -55580, -55602, +54947, +54954, +54954, +54954, +54960, +54983, +54983, +55040, +55040, +55050, +55050, +55057, +55064, +55083, +55181, +55195, +55195, +55207, +55207, +55221, +55228, +55228, +55228, +55228, +55235, +55286, +55463, +55463, +55477, +55492, +55517, +55524, +55524, +55524, +55524, +55524, +55524, +55524, +55528, +55576, +55576, +55590, +55590, +55590, +55598, +55605, +55605, +55605, +55605, +55605, +55605, +55605, +55605, +55612, +55612, +55612, 55618, -55636, -55662, -55667, -55667, -55676, -55676, -55697, -55729, -55740, -55786, -55786, -55798, -55817, -55835, -55854, -55854, -55854, -55854, -55903, -55916, -55927, -55939, -55953, -55960, -55966, -55980, -56004, -56004, -56029, -56046, -56063, -56063, -56063, -56063, -56063, -56129, -56129, -56138, -56152, -56194, -56194, -56239, -56239, -56246, -56246, -56277, -56284, -56284, -56330, -56330, +55637, +55782, +55782, +55800, +55810, +55810, +55832, +55832, +55832, +55832, +55855, +55855, +55855, +55855, +55869, +55869, +55869, +55869, +55876, +55876, +55882, +55937, +55937, +55937, +55958, +55958, +55958, +55972, +55981, +55981, +55988, +55988, +56047, +56195, +56195, +56195, +56195, +56211, +56247, +56247, +56247, +56259, +56259, +56265, +56265, +56265, +56285, +56285, +56285, +56285, +56285, +56285, +56312, 56347, -56372, -56385, -56465, -56465, -56477, -56483, -56490, -56514, -56520, -56520, -56543, -56543, -56543, -56543, +56361, +56361, +56361, +56361, +56366, +56366, +56366, +56376, +56376, +56376, +56396, +56513, +56527, +56533, +56533, +56533, +56540, +56540, +56540, +56540, +56540, +56540, +56540, +56540, +56556, 56568, 56568, 56568, +56568, +56580, +56590, 56601, -56616, -56653, -56661, -56673, -56708, -56708, -56732, -56749, -56749, -56749, -56782, -56798, -56798, -56798, -56812, -56817, -56817, -56872, -56891, -56903, -56903, -56917, -56917, -56917, -56917, -56917, -56927, -56950, -56972, -56991, -57009, -57009, +56631, +56631, +56646, +56646, +56678, +56678, +56678, +56690, +56690, +56690, +56748, +56823, +56838, +56838, +56838, +56838, +56843, +56857, +56857, +56857, +56857, +56857, +56864, +56870, +56925, +56925, +56932, +56932, +56932, +56932, +56948, +56985, +57004, +57021, 57031, 57031, +57031, +57038, +57038, 57049, -57059, -57059, -57077, -57091, -57098, -57098, -57119, -57119, -57130, -57130, -57137, -57156, -57156, -57156, -57156, -57156, -57179, -57179, -57179, -57190, -57201, -57226, -57242, -57269, -57289, -57289, -57289, -57312, -57312, -57344, +57049, +57049, +57099, +57217, +57217, +57227, +57227, +57227, +57248, +57248, +57252, +57252, +57266, +57266, +57266, +57279, +57279, +57283, +57283, +57287, +57287, +57287, +57293, +57317, +57317, +57317, +57341, +57341, +57341, 57352, 57352, -57367, -57367, -57367, -57367, -57367, -57386, -57419, -57419, -57428, -57437, -57449, -57457, -57476, -57476, -57483, -57483, -57490, -57490, -57490, -57534, -57534, -57551, -57567, -57567, -57598, -57605, -57612, -57612, -57680, -57680, -57680, -57680, +57352, +57352, +57352, +57385, +57510, +57525, +57525, +57533, +57533, +57543, +57550, +57550, +57556, +57556, +57556, +57564, +57564, +57588, +57616, +57616, +57616, +57616, +57616, +57616, +57632, +57641, +57641, +57668, +57668, +57668, +57679, +57679, 57701, 57701, -57712, -57718, -57761, -57776, -57785, -57812, -57812, -57812, -57821, -57821, -57836, -57870, -57870, -57870, -57870, -57870, -57870, -57880, -57891, -57891, -57922, -57922, -57948, -57948, -57948, -57948, -57948, -57948, -57976, -57982, -58020, +57701, +57728, +57848, +57848, +57858, +57858, +57858, +57866, +57866, +57866, +57866, +57866, +57866, +57866, +57866, +57931, +57931, +57960, +57960, +57960, +57981, +57994, +58012, +58049, +58049, 58054, -58066, -58080, -58091, -58100, -58100, -58100, -58113, -58113, -58136, -58160, -58167, -58174, -58184, -58193, -58199, -58199, -58221, -58221, -58240, -58240, -58250, -58258, -58258, -58265, -58285, -58285, -58292, -58297, -58297, -58318, -58318, -58328, -58365, -58372, -58372, -58388, -58399, -58414, -58414, -58428, -58436, -58442, -58442, -58442, -58453, -58453, -58453, -58478, -58519, -58519, -58519, -58519, -58519, -58519, -58546, -58582, -58582, -58582, -58582, -58592, -58592, -58620, -58646, -58671, -58671, -58671, -58682, -58682, -58694, -58741, -58768, -58786, -58786, -58786, -58786, -58837, -58866, -58866, -58866, -58872, -58872, -58872, -58872, -58879, -58900, -58900, -58925, -58925, -58925, -58936, -58940, -58940, -58967, -58982, -58989, -58996, -58996, -58996, -58996, -59003, -59003, -59003, -59003, -59003, -59003, -59003, -59013, -59029, -59029, +58054, +58054, +58054, +58054, +58077, +58084, +58084, +58120, +58219, +58225, +58242, +58242, +58273, +58273, +58273, +58273, +58281, +58286, +58286, +58291, +58298, +58341, +58341, +58358, +58358, +58358, +58358, +58373, +58397, +58415, +58415, +58437, +58437, +58437, +58437, +58447, +58457, +58457, +58457, +58494, +58631, +58631, +58657, +58664, +58673, +58673, +58688, +58688, +58688, +58688, +58688, +58698, +58698, +58713, +58728, +58737, +58737, +58737, +58761, +58785, +58831, +58842, +58842, +58858, +58858, +58865, +58865, +58870, +58870, +58870, +58870, +58933, +59039, 59048, -59048, -59059, -59075, -59082, -59082, -59082, -59088, -59096, -59096, -59121, -59144, -59181, -59181, -59181, -59209, -59242, -59242, -59242, -59258, -59258, -59268, -59277, -59277, -59277, -59277, -59312, -59312, -59312, -59330, -59330, -59343, -59378, -59395, -59414, -59424, -59447, -59447, -59466, -59485, -59504, -59508, -59527, -59527, -59527, -59539, -59539, -59555, -59561, -59561, -59561, -59561, -59582, -59594, -59594, -59594, -59594, -59594, -59594, -59601, -59601, -59601, -59601, -59616, -59642, -59649, -59715, -59715, -59715, -59715, -59715, -59715, -59715, -59731, -59741, -59768, -59768, -59768, -59768, -59768, -59786, -59786, -59794, -59794, -59794, -59794, -59799, -59809, -59809, -59809, -59814, -59814, -59814, -59836, -59852, -59887, -59887, -59895, -59911, -59921, -59935, -59950, -59965, -59965, -59978, -59978, -59995, -59995, -60012, -60012, -60012, -60017, -60028, -60028, -60073, -60089, -60101, -60137, -60137, -60148, -60193, -60206, -60206, -60221, -60231, -60246, -60268, -60286, -60316, -60357, -60372, -60378, -60384, -60384, -60391, +59065, +59071, +59071, +59071, +59071, +59071, +59071, +59071, +59071, +59071, +59071, +59112, +59119, +59131, +59131, +59131, +59131, +59131, +59200, +59205, +59205, +59205, +59205, +59205, +59205, +59205, +59205, +59205, +59212, +59245, +59264, +59278, +59278, +59278, +59278, +59278, +59287, +59287, +59294, +59294, +59294, +59294, +59294, +59345, +59345, +59357, +59357, +59357, +59357, +59357, +59365, +59375, +59375, +59388, +59388, +59405, +59405, +59405, +59405, +59410, +59410, +59480, +59595, +59595, +59609, +59609, +59609, +59609, +59609, +59609, +59621, +59621, +59621, +59629, +59629, +59684, +59684, +59691, +59691, +59691, +59691, +59701, +59714, +59755, +59755, +59780, +59780, +59780, +59780, +59780, +59780, +59780, +59780, +59805, +59890, +59890, +59904, +59904, +59904, +59904, +59904, +59904, +59904, +59920, +59920, +59920, +59920, +59925, +59941, +59966, +59966, +59966, +59973, +59973, +60003, +60003, +60003, +60049, +60062, +60069, +60076, +60076, +60100, +60100, +60108, +60123, +60254, +60260, +60274, +60282, +60293, +60299, +60299, +60299, +60299, +60299, +60299, +60299, +60299, +60323, +60323, +60323, +60335, +60349, +60349, +60359, +60398, 60410, -60430, -60443, -60443, -60448, -60460, -60460, -60460, -60521, -60521, -60521, -60521, -60554, -60572, -60594, -60600, -60607, -60607, -60607, -60623, -60638, -60654, -60671, -60699, -60699, -60729, -60729, -60740, -60747, -60747, -60756, -60756, -60756, -60775, -60793, -60793, -60810, -60810, -60810, -60810, -60810, -60822, -60835, -60835, -60853, -60897, -60918, -60939, -60962, -60962, -60962, -60985, -60985, -60990, -60990, -60997, -61028, -61039, -61054, -61054, -61063, -61073, -61073, -61084, -61090, -61113, -61113, -61120, -61129, -61129, -61129, -61129, -61160, -61175, -61180, -61180, -61180, -61195, -61202, -61202, -61221, -61237, +60424, +60429, +60429, +60429, +60429, +60436, +60436, +60436, +60436, +60477, +60562, +60562, +60562, +60562, +60562, +60566, +60576, +60576, +60576, +60576, +60576, +60576, +60576, +60606, +60606, +60620, +60636, +60642, +60660, +60673, +60713, +60713, +60713, +60727, +60727, +60727, +60727, +60727, +60738, +60738, +60738, +60768, +60799, +60812, +60838, +60838, +60838, +60838, +60838, +60838, +60843, +60843, +60843, +60843, +60843, +60866, +60866, +60866, +60866, +60876, +60876, +60884, +60903, +60936, +60943, +60947, +60947, +60947, +60947, +60957, +60980, +60980, +60980, +61042, +61127, +61127, +61127, +61144, +61144, +61144, +61154, +61154, +61154, +61154, +61154, +61163, +61163, +61179, +61179, +61179, +61188, +61196, +61203, +61213, +61257, 61264, +61271, +61271, +61271, +61271, +61271, +61271, 61284, -61314, -61325, -61358, -61377, -61400, -61414, -61414, -61430, -61430, -61430, -61439, -61458, -61463, -61463, -61463, -61501, -61501, -61519, -61526, -61535, -61535, -61535, -61560, +61284, +61284, +61386, +61490, +61490, +61500, +61500, +61515, +61515, +61515, +61515, +61521, +61521, +61521, +61521, +61521, 61571, -61571, -61591, -61591, -61623, -61623, -61635, -61667, -61667, -61677, +61602, +61602, +61602, +61602, +61602, +61639, +61665, +61665, +61669, +61679, +61679, 61684, 61684, -61701, -61708, -61708, -61723, -61749, -61795, -61835, -61835, -61841, -61841, -61861, -61877, -61891, -61912, -61924, -61937, -61937, -61937, -61937, -61937, -61969, -61969, -61969, -61976, -61976, -61990, -62006, -62013, -62013, -62029, -62081, -62081, -62106, -62106, -62106, -62106, -62126, -62126, +61692, +61704, +61704, +61704, +61704, +61911, +61911, +61921, +61927, +61933, +61933, +61933, +61933, +61933, +61948, +61958, +61958, +61958, +61998, +61998, +62018, +62027, +62027, +62038, +62054, +62077, +62105, +62105, +62130, +62130, +62130, +62130, +62130, +62130, +62130, +62130, 62145, -62145, -62157, -62184, -62200, -62218, -62218, -62218, -62218, -62229, -62229, -62244, -62251, -62251, -62251, -62267, -62277, -62282, -62282, -62282, -62289, -62300, -62328, -62328, -62328, -62352, -62352, -62352, -62352, -62383, -62383, -62383, -62390, -62390, -62390, -62399, -62399, -62399, -62409, -62432, -62432, -62432, -62444, -62457, -62490, -62495, -62495, -62505, -62505, -62505, -62505, -62523, -62523, -62567, -62577, -62577, -62592, -62601, -62645, -62645, -62661, -62666, -62666, -62666, -62666, -62677, -62677, -62677, -62677, -62677, -62677, -62677, -62682, -62682, -62682, -62700, -62762, -62781, -62788, -62788, -62788, -62788, -62828, -62828, -62828, -62828, -62828, -62838, -62860, -62860, -62860, -62884, -62884, -62884, -62902, -62907, -62918, -62947, -62959, -62959, -62966, -62991, -62991, -62997, -62997, -63015, -63015, -63025, -63036, -63036, -63057, -63067, -63067, -63067, -63089, -63107, -63118, -63118, -63160, -63172, -63204, -63214, -63229, -63299, -63305, -63317, -63324, -63345, -63377, -63387, -63419, -63419, -63419, -63431, -63441, -63457, +62332, +62341, +62365, +62372, +62387, +62396, +62396, +62396, +62415, +62424, +62424, +62424, +62431, +62471, +62488, +62488, +62488, +62496, +62496, +62496, +62496, +62496, +62496, +62496, +62496, +62496, +62502, +62502, +62502, +62502, +62502, +62538, +62660, +62672, +62672, +62672, +62694, +62709, +62709, +62709, +62709, +62709, +62709, +62709, +62709, +62746, +62750, +62750, +62750, +62756, +62756, +62765, +62786, +62793, +62793, +62798, +62798, +62798, +62798, +62798, +62823, +62823, +62823, +62833, +63039, +63039, +63068, +63068, +63068, +63097, +63097, +63097, +63097, +63097, +63097, +63097, +63097, +63119, +63125, +63133, +63133, +63133, +63133, +63133, +63152, +63191, +63191, +63191, +63191, +63191, +63191, +63196, +63196, +63196, +63206, +63236, +63362, +63362, +63370, +63370, +63370, +63370, +63370, +63370, +63370, +63370, +63370, +63370, +63370, +63459, 63466, -63473, -63473, -63487, -63487, -63487, -63512, -63521, -63534, -63534, -63534, -63548, -63601, -63601, -63601, -63621, -63651, -63707, -63707, -63716, -63722, -63722, -63722, -63768, -63797, -63816, -63829, -63829, -63852, -63881, -63895, -63912, -63936, -63936, -63964, +63466, +63466, +63466, +63466, +63494, +63513, +63532, +63532, +63542, +63542, +63542, +63542, +63552, +63575, +63575, +63575, +63632, +63755, +63769, +63788, +63788, +63809, +63809, +63809, +63809, +63809, +63818, +63818, +63818, +63818, +63929, +63929, +63929, +63929, +63929, +63929, +63954, +63954, +63954, +63954, +63961, +63961, +63961, +63961, +63961, 63968, -63975, -63984, -63984, -64000, -64034, -64039, -64039, -64039, -64039, -64039, -64039, -64071, -64087, -64107, -64124, -64157, -64157, -64170, -64170, -64170, -64177, -64177, -64177, -64177, -64200, -64200, -64223, -64223, -64242, -64270, -64277, -64296, -64304, -64304, -64318, -64318, -64336, -64336, -64336, -64336, -64336, -64346, -64346, -64346, -64346, -64352, -64372, -64382, -64382, -64382, -64382, -64392, -64392, -64419, -64428, -64428, -64433, -64433, -64433, -64465, -64465, -64465, -64465, -64465, -64486, -64493, -64522, -64522, +63968, +63968, +63986, +64097, +64103, +64103, +64103, +64122, +64122, +64122, +64122, +64122, +64122, +64122, +64122, +64122, +64238, +64244, +64259, +64259, +64259, +64259, +64259, +64276, +64276, +64284, +64295, +64295, +64295, +64295, +64295, +64295, +64295, +64295, +64348, +64523, +64523, +64530, +64530, +64536, 64542, 64542, -64548, -64548, -64575, -64575, -64581, -64581, -64593, -64622, -64628, -64649, -64680, -64697, -64697, -64697, -64708, -64736, -64736, -64759, -64774, -64779, -64791, -64791, -64816, -64816, -64832, -64832, -64832, -64832, -64839, -64839, -64852, -64873, -64873, -64873, -64883, -64889, -64902, -64902, -64902, -64902, -64934, -64934, -64934, -64952, -64952, -64952, -64952, -64965, -64965, -64965, -64965, -64977, -64989, -64989, -65007, -65007, -65013, -65030, -65048, -65048, -65048, -65048, -65048, -65048, -65048, -65059, -65059, -65059, -65059, -65076, -65076, -65088, -65088, -65099, -65099, -65123, -65128, -65165, -65178, -65188, -65210, -65220, +64542, +64542, +64542, +64552, +64552, +64552, +64552, +64558, +64571, +64571, +64571, +64577, +64586, +64597, +64606, +64606, +64633, +64633, +64633, +64633, +64633, +64640, +64640, +64640, +64648, +64750, +64760, +64760, +64766, +64766, +64766, +64766, +64766, +64766, +64766, +64766, +64766, +64766, +64781, +64781, +64781, +64781, +64781, +64781, +64781, +64790, +64790, +64790, +64806, +64806, +64813, +64813, +64813, +64813, +64813, +64813, +64920, +65086, +65086, +65103, +65111, +65119, +65163, +65163, +65163, +65163, +65163, +65163, +65163, +65163, +65228, 65234, -65275, -65294, -65304, -65304, -65329, -65346, -65367, -65367, -65377, -65403, -65409, +65234, +65234, +65234, +65234, +65234, +65245, +65258, +65258, +65258, +65258, +65263, +65302, +65302, +65302, +65302, +65309, +65320, +65432, +65432, +65444, +65451, +65451, +65458, 65465, -65487, -65508, -65520, -65555, -65583, -65583, -65609, -65615, -65615, -65623, -65623, -65632, -65651, -65651, -65651, -65651, -65669, -65669, -65698, -65698, -65703, -65703, -65715, -65737, -65789, -65789, -65798, -65798, -65836, -65859, -65875, -65875, -65875, -65897, -65942, -65942, -65962, -65962, -65962, -66044, -66044, -66053, -66053, -66064, -66064, -66071, -66071, -66085, -66101, -66101, -66115, -66121, -66121, -66156, -66164, -66184, -66190, -66190, -66209, -66209, +65465, +65469, +65469, +65469, +65469, +65476, +65557, +65557, +65557, +65557, +65564, +65578, +65585, +65605, +65630, +65637, +65653, +65660, +65660, +65671, +65671, +65671, +65678, +65685, +65713, +65847, +65847, +65854, +65861, +65895, +65895, +65895, +65895, +65895, +65902, +65909, +65909, +65916, +65923, +65930, +65944, +65944, +65944, +65944, +65973, +66009, +66016, +66016, +66029, +66036, +66056, +66056, +66056, +66056, +66063, +66063, +66070, +66201, +66201, +66201, +66208, +66208, 66230, -66236, -66236, -66236, -66272, -66272, -66297, -66323, -66344, +66230, +66243, +66243, +66243, +66256, +66256, +66256, +66291, +66291, +66291, +66291, +66291, +66291, +66317, +66345, +66345, +66345, 66363, -66378, -66378, +66369, +66369, +66376, +66376, +66393, +66393, +66393, 66414, -66420, -66420, -66420, -66420, -66420, -66420, -66420, -66434, -66477, -66477, -66490, -66505, -66513, -66529, -66529, -66536, -66548, -66557, -66592, -66626, -66634, -66641, -66641, -66641, -66647, -66647, -66668, -66668, -66668, -66668, -66686, -66711, -66733, -66746, -66763, -66763, -66771, -66788, -66818, -66818, -66818, -66818, -66826, -66835, -66872, -66888, -66888, -66897, -66897, -66945, -66950, -66960, -66960, -66960, -66960, -66960, -66960, -66967, -66993, -67002, -67002, -67027, +66530, +66530, +66530, +66538, +66545, +66571, +66571, +66571, +66578, +66585, +66585, +66608, +66622, +66655, +66662, +66669, +66669, +66676, +66683, +66692, +66820, +66831, +66831, +66831, +66831, +66838, +66838, +66845, +66845, +66845, +66852, +66861, +66972, +66972, +66972, +66972, +66983, +66990, +66990, +66990, +66990, +66990, +66990, +66990, +66997, +67031, 67044, -67044, -67050, -67067, -67103, -67129, -67129, -67138, -67138, -67138, -67138, -67158, -67158, -67176, -67176, -67176, -67188, -67225, -67244, -67252, -67277, -67286, -67326, -67340, -67353, -67361, -67361, -67371, +67063, +67063, +67070, +67084, +67118, +67183, +67183, +67183, +67183, +67183, +67183, +67183, +67192, +67192, +67192, +67192, +67230, +67375, 67384, -67409, -67409, -67409, -67409, -67416, -67416, -67456, -67470, +67401, +67401, +67401, +67408, +67408, +67415, +67415, +67422, +67422, +67438, +67438, +67467, 67474, 67474, 67481, -67496, -67496, -67496, -67515, -67523, -67543, -67566, -67576, -67576, -67576, -67576, -67594, -67605, -67605, -67605, -67609, -67609, -67609, -67625, -67625, -67625, -67632, -67632, -67632, -67640, -67640, -67640, -67662, -67674, -67686, -67686, -67695, -67712, -67750, -67750, -67750, -67787, -67802, -67808, -67818, -67818, -67864, -67878, -67878, -67878, -67878, -67898, -67898, -67915, -67960, -67960, -67960, -67983, -67998, -68014, -68014, -68014, -68026, -68053, -68053, -68053, -68053, -68062, -68062, -68079, -68093, -68109, -68109, -68109, -68134, -68150, -68176, -68176, -68213, -68277, -68277, -68295, -68321, -68321, -68321, -68321, -68341, -68358, +67488, +67495, +67530, +67578, +67578, +67578, +67592, +67592, +67599, +67606, +67634, +67654, +67654, +67654, +67702, +67754, +67761, +67768, +67810, +67817, +67824, +67831, +67838, +67838, +67845, +67845, +67852, +67859, +67871, +67882, +67909, +67909, +67909, +67922, +67948, +67967, +67984, +67991, +68023, +68023, +68030, +68037, +68037, +68044, +68044, +68044, +68064, +68114, +68120, +68147, +68147, +68188, +68188, +68188, +68188, +68188, +68188, +68188, +68188, +68199, +68297, +68297, +68305, +68305, +68305, +68305, +68320, +68353, 68366, 68366, 68373, -68395, -68395, -68403, -68403, -68403, -68442, -68442, -68442, -68442, -68478, -68491, -68491, -68502, -68502, -68515, -68515, -68515, -68515, -68515, -68527, -68531, -68553, -68567, -68567, -68605, -68623, -68623, +68380, +68400, +68409, +68416, +68423, +68423, +68430, +68455, 68642, 68649, -68654, -68695, -68707, -68707, -68715, -68738, -68744, -68764, -68794, -68794, -68810, -68816, -68829, -68839, -68847, -68860, -68871, -68871, -68882, -68889, -68901, -68901, -68917, -68922, -68963, -69007, -69019, -69019, -69019, -69030, -69036, -69073, -69080, -69102, -69102, -69115, -69115, -69146, -69146, -69146, -69146, -69146, -69146, -69146, -69160, -69176, -69194, -69202, -69209, -69216, -69238, -69262, -69262, -69262, -69262, -69262, -69291, -69298, -69314, -69335, -69348, -69359, -69359, -69359, -69359, -69400, -69400, -69400, -69420, -69451, -69462, -69462, -69462, -69462, -69468, -69468, -69480, -69501, -69513, -69530, -69541, -69549, -69549, -69549, +68666, +68673, +68680, +68680, +68680, +68680, +68680, +68687, +68698, +68698, +68706, +68753, +68753, +68753, +68757, +68757, +68767, +68798, +68911, +68928, +68928, +68928, +68936, +68947, +68947, +68947, +68947, +68947, +68959, +69006, +69243, +69256, +69290, +69304, +69316, +69328, +69328, +69342, +69349, +69356, +69356, +69356, +69363, +69440, +69440, +69457, +69457, +69457, +69457, +69464, +69488, +69500, +69500, +69500, +69519, +69526, +69551, +69558, +69565, +69572, 69579, -69596, -69596, -69605, -69605, -69617, -69639, -69653, -69666, -69666, -69666, -69666, -69666, -69666, -69666, -69676, -69703, -69710, -69767, -69786, -69786, -69816, -69816, -69844, -69881, -69898, -69908, -69908, -69915, -69930, -69930, -69930, -69957, -69957, -69970, -69993, -69993, -70022, -70022, -70030, -70045, -70070, -70122, -70122, -70122, -70122, -70131, -70131, -70131, -70141, -70169, -70191, -70208, -70220, -70220, -70220, -70220, -70250, -70273, -70300, -70300, -70300, -70304, -70319, -70319, -70325, -70338, -70338, -70338, -70359, -70369, -70376, -70376, -70402, -70430, -70430, -70447, -70447, -70508, -70515, -70536, -70543, -70543, -70543, -70568, -70586, -70599, -70615, -70615, -70633, -70633, -70684, -70696, -70707, -70716, -70716, -70724, -70724, -70724, -70735, -70772, +69608, +69789, +69796, +69803, +69803, +69817, +69829, +69829, +69836, +69836, +69836, +69836, +69850, +69850, +69885, +69885, +69885, +69885, +69892, +69902, +69909, +69954, +69973, +69980, +69985, +69985, +70005, +70027, +70027, +70035, +70044, +70051, +70107, +70192, +70192, +70211, +70223, +70251, +70284, +70284, +70296, +70303, +70315, +70315, +70345, +70345, +70408, +70420, +70420, +70420, +70429, +70429, +70436, +70448, +70486, +70486, +70486, +70486, +70486, +70486, +70486, +70486, +70486, +70486, +70513, +70632, +70632, +70632, +70632, +70632, +70639, +70639, +70663, +70663, +70670, +70670, +70670, +70670, +70690, +70690, +70690, +70690, +70697, +70714, +70737, 70780, 70780, -70802, -70845, -70845, -70861, -70877, -70904, -70904, -70923, -70923, -70949, -70949, -70949, -71001, -71029, -71029, -71029, -71029, -71029, +70789, +70789, +70801, +70832, +70832, +70842, +70864, +70871, +70871, +70947, +71036, +71036, 71043, -71051, -71057, +71043, +71043, +71043, +71043, +71050, +71050, +71050, +71050, 71065, 71065, 71065, -71071, -71071, -71090, -71100, -71116, -71127, -71140, -71140, -71165, -71165, -71165, -71165, -71171, -71182, -71190, -71200, -71200, -71206, -71231, -71231, -71231, -71238, -71266, -71266, -71273, -71273, -71290, -71296, -71296, -71301, -71315, -71333, -71362, -71382, -71409, -71424, -71436, -71436, -71436, -71454, -71469, -71469, -71469, -71469, -71490, +71070, +71070, +71070, +71079, +71079, +71089, +71134, +71160, +71160, +71160, +71160, +71160, +71160, +71160, +71185, +71192, +71192, +71192, +71251, +71263, +71263, +71263, +71275, +71275, +71275, +71283, +71283, +71283, +71283, +71295, +71295, +71312, +71325, +71325, +71325, +71325, +71325, +71337, +71366, +71391, +71391, +71391, +71391, +71391, +71391, +71391, +71415, +71415, +71415, +71470, +71500, +71500, +71500, 71506, -71506, -71537, -71545, -71558, -71599, -71620, -71645, -71667, -71685, -71685, -71685, -71698, -71698, -71716, -71723, -71734, -71740, -71740, -71740, -71759, -71759, -71841, -71841, -71841, -71848, -71876, -71876, -71883, -71883, -71929, -71929, -71951, -71951, -71951, -71951, -71965, +71521, +71531, +71531, +71531, +71531, +71531, +71531, +71531, +71531, +71613, +71613, +71635, +71635, +71635, +71656, +71656, +71714, +71714, +71714, +71714, +71714, +71726, +71726, +71726, +71749, +71749, +71749, +71792, +71949, +71949, +71959, +71959, +71983, 71995, -72026, -72026, -72026, -72066, -72085, -72090, -72118, -72118, -72158, -72158, -72158, -72164, -72164, -72181, -72181, -72219, -72235, -72235, -72247, -72293, -72304, -72326, -72336, -72380, -72380, -72395, -72445, -72495, -72511, -72526, -72536, -72536, -72536, -72558, -72579, -72579, -72598, -72604, -72615, -72615, -72615, -72615, -72632, -72665, -72665, -72687, -72727, -72737, -72744, -72744, -72744, -72791, -72810, -72817, -72817, -72866, -72916, -72916, -72928, -72939, -72958, -72971, -72982, -72992, -72992, -72999, -73028, -73043, -73056, -73056, -73085, -73085, -73100, -73147, -73147, -73147, -73165, -73173, -73173, -73180, -73204, -73204, -73210, -73235, +71995, +71995, +71995, +71995, +71995, +72007, +72031, +72058, +72058, +72058, +72058, +72058, +72058, +72068, +72115, +72115, +72115, +72133, +72133, +72145, +72145, +72145, +72145, +72145, +72145, +72208, +72353, +72353, +72365, +72365, +72365, +72365, +72365, +72365, +72365, +72365, +72365, +72365, +72365, +72376, +72387, +72393, +72393, +72393, +72405, +72425, +72425, +72436, +72436, +72436, +72436, +72436, +72436, +72448, +72467, +72467, +72467, +72496, +72691, +72703, +72715, +72715, +72715, +72739, +72739, +72746, +72776, +72776, +72776, +72787, +72787, +72873, +72885, +72891, +72891, +72903, +72912, +72920, +72948, +72966, +72966, +72993, +72993, +72993, +73005, +73005, +73005, +73005, +73005, +73052, +73199, +73230, +73240, +73240, +73240, +73240, 73252, 73252, -73278, -73290, -73290, -73308, -73329, -73338, -73350, +73264, +73264, +73264, +73264, +73276, +73340, +73340, +73354, +73354, +73354, 73360, -73366, -73401, +73369, +73389, 73401, +73413, +73413, +73413, +73413, 73425, -73425, -73425, -73441, +73444, 73454, 73454, 73454, -73454, -73454, -73467, -73478, -73478, -73478, -73497, -73506, -73528, -73528, -73528, -73557, -73557, -73557, -73557, -73583, -73583, -73583, -73608, -73616, -73624, -73624, -73630, -73640, -73693, -73693, -73693, -73702, -73766, -73807, -73807, -73807, -73807, -73807, -73822, -73828, -73837, -73837, -73862, -73874, -73874, -73874, -73874, -73874, -73881, -73881, -73881, -73910, -73945, -74040, -74040, -74040, -74057, -74077, -74094, -74129, -74129, -74129, -74129, -74144, -74144, -74144, -74144, -74144, -74161, -74181, -74203, -74203, -74203, -74203, -74224, -74224, -74224, -74224, -74240, -74240, -74250, -74250, -74250, -74250, -74250, -74250, -74250, -74250, -74250, -74250, -74257, -74319, -74337, -74362, -74362, +73472, +73629, +73629, +73629, +73629, +73650, +73665, +73665, +73665, +73665, +73665, +73665, +73665, +73665, +73699, +73699, +73699, +73699, +73699, +73699, +73705, +73735, +73776, +73791, +73791, +73791, +73791, +73791, +73791, +73801, +73801, +73801, +73877, +73987, +73987, +73999, +73999, +73999, +73999, +73999, +73999, +74004, +74012, +74012, +74012, +74020, +74076, +74076, +74076, +74076, +74076, +74085, +74136, +74157, +74157, +74157, +74183, +74183, +74183, +74183, +74183, +74183, +74183, +74183, +74212, +74307, +74307, +74328, +74345, +74345, 74369, 74369, -74390, -74409, -74409, -74433, -74433, -74433, -74433, -74463, -74491, -74491, -74491, -74491, -74491, -74491, -74500, -74500, -74530, -74548, -74548, -74548, -74570, -74580, -74597, -74597, -74597, -74615, -74615, -74615, -74615, -74634, -74661, -74661, -74681, -74681, -74681, -74681, -74697, -74697, -74697, -74697, -74711, -74717, -74741, -74751, -74751, -74816, -74816, -74868, -74868, -74874, -74889, -74889, -74889, -74889, -74908, -74914, -74914, -74914, -74931, -74931, -74942, -74951, -74982, -74982, -74989, -74999, -74999, -74999, -75004, -75004, -75019, -75019, -75068, -75068, -75084, -75115, -75155, -75168, -75181, -75187, -75187, -75219, -75249, -75249, -75249, -75256, -75276, -75315, -75315, -75315, -75315, -75356, -75356, -75377, -75377, -75377, -75384, -75403, -75415, -75435, -75503, -75523, -75537, -75554, -75560, -75580, -75580, -75580, -75580, -75580, +74369, +74369, +74369, +74369, +74369, +74388, +74441, +74441, +74441, +74441, +74448, +74455, +74455, +74479, +74479, +74479, +74479, +74479, +74479, +74486, +74497, +74507, +74507, +74507, +74598, +74710, +74710, +74724, +74724, +74745, +74745, +74745, +74745, +74752, +74759, +74759, +74759, +74766, +74781, +74794, +74810, +74810, +74810, +74810, +74820, +74879, +74879, +74879, +74879, +74879, +74886, +74886, +74893, +74905, +74912, +74912, +74958, +74992, +74992, +74992, +75016, +75016, +75021, +75021, +75028, +75028, +75028, +75028, +75028, +75028, +75063, +75072, +75072, +75072, +75072, +75079, +75093, +75150, +75150, +75150, +75150, +75150, +75150, +75163, +75163, +75176, +75176, +75176, +75247, +75442, +75442, +75442, +75442, +75453, +75465, +75465, +75465, +75472, +75472, +75472, +75472, +75472, +75518, +75524, +75524, +75534, +75534, +75534, +75534, +75562, +75562, +75562, +75576, +75576, +75584, +75584, +75584, 75591, 75591, -75608, -75608, -75643, -75655, -75661, -75666, -75666, +75598, +75619, +75673, +75673, +75673, +75673, +75680, 75695, 75695, 75695, -75715, -75715, -75715, -75715, -75726, -75783, -75815, -75815, -75881, -75881, -75881, -75881, -75881, -75906, -75906, -75906, -75928, -75938, -75938, -75938, -75938, -75938, -75948, -75948, -75948, -75948, -75961, -76043, -76064, -76064, -76074, -76074, -76074, -76093, -76110, -76110, -76123, -76134, -76134, -76134, -76134, -76134, -76143, -76143, -76162, -76162, -76162, -76189, -76189, -76189, -76208, +75695, +75695, +75695, +75695, +75695, +75730, +75737, +75759, +75759, +75766, +75766, +75789, +75801, +75814, +75835, +75835, +75835, +75835, +75835, +75852, +75863, +75863, +75863, +75897, +76065, +76071, +76078, +76086, +76086, +76091, +76091, +76098, +76098, +76109, +76109, +76109, +76109, +76188, +76188, +76188, +76188, +76188, +76195, +76216, 76228, -76238, -76238, -76238, -76264, -76296, -76302, -76351, -76363, -76376, -76389, -76408, -76408, -76445, -76445, -76454, -76460, -76460, -76460, -76465, -76482, -76482, -76482, -76482, -76501, -76512, -76512, +76252, +76252, +76252, +76260, +76260, +76267, +76267, +76267, +76267, +76267, +76342, +76392, +76392, +76392, +76392, +76392, +76392, +76399, +76406, +76406, +76406, +76406, +76432, +76446, +76484, +76484, +76484, +76484, +76484, +76484, +76494, 76518, -76552, -76601, -76618, -76637, -76637, -76637, -76669, -76669, -76686, -76692, -76712, -76729, -76749, -76749, -76778, -76794, -76820, -76832, -76837, -76837, -76837, -76837, -76837, -76851, -76851, -76851, -76869, -76908, -76918, -76939, -76939, -76976, -76994, +76531, +76543, +76555, +76565, +76579, +76591, +76591, +76591, +76591, +76591, +76628, +76730, +76730, +76746, +76746, +76746, +76746, +76746, +76746, +76752, +76752, +76772, +76772, +76772, +76797, +76804, +76804, +76804, +76804, +76804, +76804, +76825, +76843, +76843, +76875, +76882, +76882, +76882, +76882, +76889, +76889, +76889, +76912, +76992, +76999, +76999, +77004, +77013, +77013, +77013, 77013, 77021, -77030, -77030, -77030, -77030, -77049, +77028, +77028, +77028, +77028, +77040, +77040, +77040, +77040, +77067, +77074, +77074, 77080, 77080, 77080, -77106, -77114, -77132, -77132, -77132, -77132, -77132, -77142, -77142, -77174, -77201, -77201, -77217, -77223, -77223, -77223, -77235, -77235, -77235, -77235, -77235, -77245, -77268, -77268, -77268, -77283, -77296, -77296, -77296, -77319, -77347, -77347, -77347, -77354, -77366, -77400, -77400, -77410, -77425, -77442, -77463, +77087, +77087, +77095, +77104, +77104, +77112, +77112, +77112, +77163, +77291, +77291, +77291, +77291, +77304, +77318, +77318, +77325, +77332, +77332, +77332, +77332, +77339, +77359, +77359, +77371, +77371, +77378, +77384, +77394, +77445, +77455, +77455, 77479, -77504, -77536, -77536, -77543, -77543, -77543, +77479, +77486, +77493, +77493, +77506, +77513, +77513, 77549, -77549, -77549, -77555, -77588, -77593, -77613, -77638, -77638, -77638, -77638, -77638, -77656, -77656, -77656, -77656, -77693, -77704, -77704, -77716, -77724, -77724, -77724, -77724, -77784, -77784, -77796, +77647, +77647, +77668, +77668, +77668, +77677, +77677, +77684, +77684, +77684, +77691, +77709, +77709, +77725, +77725, +77725, +77725, +77725, +77725, +77732, +77782, +77809, +77809, +77816, +77816, +77823, +77823, +77823, 77834, -77855, -77869, -77905, -77917, -77917, -77933, -77933, -77950, -77950, -77961, -77970, -77970, -77970, -77970, -77970, -77970, -77970, +77834, +77834, +77880, 77988, -77993, -78004, -78014, -78014, -78031, -78031, -78031, -78049, -78049, -78049, -78064, -78080, +77997, +78006, +78015, +78024, +78046, +78046, +78046, +78046, +78046, +78053, +78053, +78053, 78099, 78099, -78108, -78118, -78125, -78125, -78125, -78125, -78159, -78159, -78159, -78191, -78204, -78229, -78229, -78242, -78242, -78242, -78253, -78253, -78253, -78253, -78253, -78262, -78282, -78318, -78332, -78362, -78395, -78416, -78465, -78465, -78483, -78483, -78533, -78533, -78614, -78649, -78677, -78730, -78760, -78767, -78791, -78791, -78791, -78791, -78791, -78797, -78803, -78803, -78803, -78808, -78821, -78831, -78831, -78838, +78124, +78124, +78124, +78124, +78124, +78124, +78160, +78160, +78160, +78160, +78160, +78160, +78160, +78183, +78183, +78183, +78208, +78325, +78338, +78350, +78357, +78357, +78364, +78371, +78378, +78378, +78385, +78385, +78385, +78392, +78476, +78487, +78487, +78494, +78508, +78522, +78548, +78618, +78625, +78639, +78653, +78660, +78667, +78681, +78681, +78681, +78695, +78702, +78747, +78839, 78844, 78851, -78885, -78913, -78959, -78959, -78959, -78979, -78979, -78979, -78979, -78999, -79011, -79011, -79011, -79011, -79011, -79024, -79043, +78858, +78872, +78884, +78884, +78896, +78896, +78910, +78917, +78917, +78917, +78996, +79003, +79010, +79010, +79010, +79010, +79049, 79060, -79060, -79060, -79060, -79060, -79066, -79066, -79087, 79106, -79123, -79132, -79132, -79151, -79190, -79190, -79190, -79206, -79206, -79211, -79211, -79274, -79274, -79274, -79309, -79318, -79318, -79318, -79318, -79318, -79355, -79355, -79355, -79360, -79360, -79377, -79388, -79388, -79388, -79388, -79388, -79412, -79433, -79433, -79433, -79433, -79477, -79477, -79477, -79487, -79529, -79529, -79529, -79572, -79584, -79584, -79621, -79661, -79676, -79706, -79706, -79706, -79706, -79706, -79719, -79726, -79731, -79731, -79731, -79738, -79738, -79738, -79738, -79738, -79754, -79754, -79761, -79761, -79789, -79811, -79811, -79811, -79832, -79832, -79847, -79847, -79847, -79847, -79853, -79874, -79874, -79874, -79879, -79879, -79905, -79922, -79922, -79933, +79113, +79120, +79120, +79127, +79127, +79137, +79169, +79176, +79176, +79218, +79314, +79328, +79328, +79335, +79335, +79342, +79342, +79349, +79349, +79356, +79363, +79363, +79363, +79378, +79378, +79387, +79387, +79392, +79406, +79425, +79509, +79516, +79516, +79516, +79516, +79524, +79531, +79531, +79531, +79538, +79549, +79626, +79678, +79678, +79708, +79708, +79708, +79723, +79723, +79723, +79730, +79737, +79737, +79757, +79764, +79822, +79841, +79841, +79855, +79855, +79862, +79888, +79943, 79959, -79994, -79994, -80003, -80040, -80040, -80074, -80074, -80083, -80091, -80091, -80103, -80119, -80138, -80138, -80138, -80148, -80148, -80194, -80208, -80208, -80224, -80235, +79959, +79971, +79971, +79978, +79978, +79992, +80006, +80013, +80020, +80052, +80140, +80140, +80172, +80172, +80189, +80206, +80206, +80206, +80206, +80206, +80206, +80206, +80213, +80220, +80227, +80234, +80234, 80241, -80252, -80260, -80269, -80283, +80241, +80248, +80271, +80271, +80271, +80288, +80288, +80288, +80288, +80288, 80299, -80325, -80340, -80347, -80356, -80374, -80392, -80408, -80425, -80444, -80444, -80452, -80474, -80492, -80507, -80515, -80515, -80525, -80542, -80542, -80542, -80552, -80583, -80592, +80299, +80299, +80326, +80420, +80428, +80445, +80445, +80445, +80464, +80464, +80471, +80471, +80483, +80483, +80483, +80483, +80543, +80571, 80599, -80599, -80618, -80640, -80655, -80674, -80690, -80703, -80726, -80726, -80738, -80750, -80750, -80756, -80777, -80777, -80777, -80777, -80794, -80794, -80815, -80845, -80874, -80882, -80888, -80894, -80894, -80894, -80894, -80911, -80911, -80911, -80911, -80929, -80957, -80992, -81011, -81011, -81011, -81011, -81018, -81018, -81027, -81034, -81034, -81034, -81055, -81055, -81055, -81087, -81108, -81126, -81126, -81126, -81138, -81147, -81186, -81224, -81224, -81232, -81244, -81249, -81256, -81266, -81266, -81277, -81323, -81323, -81341, -81382, -81382, -81382, -81382, -81388, -81388, -81388, -81420, -81420, -81433, -81433, -81447, -81459, -81459, -81470, -81476, -81494, -81513, -81521, -81521, -81526, -81526, -81526, -81553, -81553, -81553, -81575, -81575, -81575, -81575, -81591, -81591, -81612, +80606, +80619, +80626, +80633, +80659, +80707, +80707, +80714, +80721, +80735, +80742, +80749, +80792, +80792, +80801, +80822, +80994, +80994, +81001, +81001, +81001, +81001, +81008, +81015, +81015, +81022, +81022, +81029, +81036, +81036, +81057, +81064, +81064, +81071, +81071, +81078, +81144, +81163, +81177, +81200, +81215, +81229, +81241, +81241, +81258, +81258, +81258, +81294, +81395, +81395, +81402, +81402, +81423, +81438, +81438, +81444, +81444, +81451, +81451, +81451, +81451, +81486, +81492, +81505, +81505, +81512, +81519, +81529, +81605, 81627, -81627, -81627, -81627, -81627, -81627, -81641, -81650, -81650, -81682, -81682, -81693, -81706, -81752, -81775, -81797, -81803, -81803, -81803, -81812, -81826, -81826, -81826, -81826, -81826, -81826, -81836, -81848, -81848, -81848, -81873, -81911, -81919, -81919, -81919, -81931, -81938, -81951, -81958, -81965, -81990, +81634, +81653, +81666, +81666, +81666, +81680, +81687, +81687, +81687, +81697, +81773, +81780, +81787, +81794, +81801, +81816, +81816, +81816, +81816, +81823, +81823, +81823, +81823, +81872, +81872, +81872, +81872, +81872, +81872, +81890, +82000, 82007, -82029, -82052, -82059, -82087, -82108, -82119, -82127, -82158, -82199, -82217, -82217, -82235, -82248, -82248, -82255, -82288, -82302, -82315, -82320, -82351, -82358, -82365, -82365, -82384, -82391, -82398, -82413, -82413, -82413, -82420, -82420, -82427, -82446, -82453, -82463, -82463, -82470, -82499, -82507, -82541, -82541, -82541, -82541, -82554, -82603, -82620, -82627, -82634, -82634, -82642, -82642, -82649, -82659, -82666, -82666, -82691, -82691, -82698, -82698, -82757, -82757, -82764, -82772, -82780, -82825, -82844, +82007, +82012, +82012, +82012, +82012, +82012, +82022, +82022, +82022, +82078, +82190, +82197, +82204, +82211, +82218, +82237, +82237, +82244, +82251, +82251, +82251, +82251, +82258, +82301, +82317, +82324, +82324, +82324, +82324, +82331, +82370, +82380, +82387, +82387, +82393, +82400, +82407, +82414, +82448, +82455, +82462, +82492, +82583, +82590, +82605, +82605, +82648, +82648, +82648, +82662, +82662, +82662, +82662, +82662, +82662, +82662, +82705, +82718, +82718, +82732, +82732, +82773, +82805, +82812, +82823, +82835, +82835, 82849, -82855, -82855, +82856, +82861, +82861, +82861, 82868, -82889, -82916, -82916, -82923, -82930, -82939, -82939, -82939, -82962, -82982, -82989, -82989, -82989, -83009, -83009, -83015, -83015, -83015, -83025, -83032, -83042, -83067, -83077, -83084, -83103, -83110, -83110, -83145, -83158, -83158, -83189, +82907, +83026, +83026, +83037, +83045, +83052, +83064, +83064, +83064, +83071, +83071, +83071, +83071, +83071, +83131, +83131, +83139, +83139, +83139, +83139, +83146, +83187, +83187, +83187, +83187, +83187, +83187, +83187, 83195, -83212, -83218, -83230, -83230, -83247, -83254, -83254, -83272, -83279, -83308, -83324, -83366, -83401, -83408, -83421, -83421, -83436, -83436, -83448, -83495, -83502, -83509, -83509, -83509, -83509, -83525, -83525, -83542, -83564, -83591, -83634, -83650, -83650, -83657, -83675, -83702, -83724, -83731, -83755, -83755, -83790, -83790, +83195, +83195, +83195, +83252, +83303, +83310, +83345, +83352, +83357, +83364, +83379, +83387, +83387, +83387, +83394, +83415, +83415, +83451, +83459, +83459, +83459, +83465, +83475, +83475, +83506, +83516, +83516, +83534, +83534, +83534, +83534, +83534, +83534, +83541, +83541, +83625, 83812, 83812, -83812, -83818, -83818, -83825, -83853, -83860, -83895, -83916, -83924, -83924, -83949, -83956, -83956, -83976, -83976, -83983, -83991, -84033, -84040, -84046, -84059, -84096, -84103, -84131, -84150, -84161, -84168, -84187, -84187, -84194, -84220, -84227, -84227, +83819, +83826, +83826, +83826, +83826, +83826, +83826, +83826, +83826, +83826, +83826, +83879, +83879, +83879, +83879, +83879, +83879, +83879, +83898, +83898, +83898, +83898, +83898, +83898, +83898, +83898, +83908, +83908, +83908, +83941, +84175, +84197, +84197, +84203, +84203, 84232, -84251, -84251, -84272, -84279, -84286, -84305, -84305, -84325, -84332, -84339, -84364, -84371, -84381, -84404, -84411, -84420, -84439, -84446, -84462, -84481, -84481, -84488, -84495, -84502, -84518, -84532, -84539, -84568, -84581, -84594, -84625, -84644, -84654, -84654, -84660, -84666, -84673, -84689, -84689, +84232, +84232, +84232, +84232, +84232, +84239, +84239, +84260, +84270, +84270, +84270, +84270, +84270, +84297, +84303, +84303, +84303, +84303, +84303, +84316, +84316, +84316, +84328, +84328, +84328, +84394, +84463, +84471, +84478, +84483, +84483, +84483, +84483, +84483, +84483, +84483, +84483, +84483, +84483, +84550, +84556, +84556, +84556, +84556, +84556, +84556, +84577, +84592, +84592, +84592, +84592, +84592, +84592, +84592, +84606, +84606, +84606, +84628, +84683, 84695, 84695, 84695, -84695, -84715, -84731, -84731, -84744, -84751, -84773, -84773, -84816, -84851, -84872, -84888, -84894, -84901, -84923, -84933, -84950, -84950, -84950, -84963, -84977, -85014, -85021, -85021, -85021, -85056, -85069, -85076, -85083, -85117, -85117, -85140, -85164, -85171, -85171, -85171, -85171, -85171, -85171, -85178, -85189, -85196, -85196, -85225, -85225, -85237, -85237, +84719, +84730, +84730, +84730, +84730, +84730, +84730, +84730, +84730, +84759, +84759, +84759, +84759, +84759, +84776, +84782, +84800, +84842, +84842, +84842, +84842, +84847, +84847, +84847, +84847, +84847, +84847, +84913, +85032, +85038, +85057, +85065, +85082, +85097, +85097, +85097, +85097, +85097, +85097, +85097, +85116, +85184, +85207, +85207, +85207, +85212, +85212, +85231, 85244, -85244, -85260, -85270, -85287, -85287, -85301, -85326, -85365, -85383, -85390, -85397, -85411, -85418, -85450, -85479, -85517, -85524, -85524, -85580, -85580, -85587, -85594, -85601, -85629, -85646, -85682, -85682, -85712, -85719, -85719, -85751, -85758, -85758, -85765, -85791, -85818, -85818, -85825, -85832, -85846, -85869, -85876, -85883, -85889, -85896, -85896, -85905, -85938, -85954, -85954, -85968, -85985, -85985, -86007, -86034, -86073, -86094, -86094, -86109, -86116, -86165, -86172, -86186, -86198, -86198, -86212, -86238, -86238, -86238, -86238, +85263, +85263, +85263, +85263, +85263, +85275, +85275, +85275, +85275, +85275, +85297, +85420, +85434, +85444, +85444, +85444, +85444, +85444, +85444, +85444, +85444, +85444, +85444, +85444, +85490, +85490, +85490, +85490, +85490, +85490, +85500, +85539, +85564, +85564, +85574, +85574, +85574, +85581, +85581, +85581, +85581, +85581, +85621, +85717, +85717, +85738, +85738, +85752, +85768, +85768, +85768, +85784, +85784, +85784, +85807, +85807, +85819, +85837, +85837, +85837, +85837, +85837, +85847, +85858, +85858, +85858, +85858, +85858, +85858, +85868, +85868, +85899, +85899, +85899, +85977, +86115, +86128, +86128, +86128, +86128, +86128, +86136, +86148, +86159, +86159, +86159, +86159, +86159, +86159, +86159, +86159, +86159, +86164, +86173, +86173, +86229, +86237, 86245, -86257, -86273, -86273, -86295, -86295, -86302, -86309, -86327, -86327, -86344, -86375, -86395, -86395, -86416, -86451, -86451, -86470, -86470, -86483, -86483, -86490, -86490, -86509, -86509, -86509, -86520, -86536, -86536, -86565, -86593, -86593, -86614, -86614, -86614, -86629, -86629, -86629, -86638, -86657, -86657, -86657, -86657, -86681, -86681, -86681, +86279, +86279, +86279, +86279, +86279, +86287, +86287, +86287, +86343, +86571, +86571, +86588, +86588, +86600, +86610, +86610, +86610, +86610, +86620, +86620, +86620, +86620, +86683, +86689, +86689, +86689, +86689, +86689, +86689, 86694, -86694, -86712, -86718, -86718, -86742, -86763, -86775, -86796, -86811, -86820, -86846, -86846, -86884, -86884, -86884, +86713, +86713, +86725, +86725, +86725, +86725, +86725, +86734, +86734, +86734, +86734, +86878, +86878, +86878, +86878, 86895, -86902, -86929, -86929, -86929, -86939, -86955, -86970, -86982, -87002, -87020, -87080, -87080, -87080, -87080, -87080, -87080, -87080, -87080, -87080, -87104, -87104, -87111, -87121, -87121, -87144, -87144, -87176, -87195, -87222, -87257, -87257, -87267, -87274, -87274, -87279, -87318, -87359, -87359, -87375, -87375, -87394, -87416, -87444, -87444, -87444, -87454, -87454, -87454, -87454, -87485, -87485, -87492, -87511, -87522, -87538, -87571, -87587, -87587, -87601, -87621, -87621, -87621, -87653, -87665, -87665, -87665, -87689, -87698, -87734, -87734, -87734, -87741, -87756, -87774, -87786, -87794, -87794, -87811, -87811, -87831, -87831, -87831, -87831, -87846, -87846, -87846, -87846, -87855, -87855, -87861, -87861, -87871, -87871, -87880, -87880, -87896, -87896, -87902, -87902, -87902, -87902, -87923, -87945, -87945, -87962, +86908, +86908, +86908, +86908, +86908, +86908, +86908, +86908, +87075, +87081, +87096, +87096, +87096, +87096, +87116, +87146, +87156, +87156, +87156, +87156, +87156, +87156, +87156, +87170, +87186, +87186, +87228, +87406, +87420, +87442, +87442, +87442, +87442, +87442, +87442, +87442, +87442, +87442, +87456, +87456, +87514, +87520, +87545, +87545, +87545, +87545, +87545, +87591, +87597, +87597, +87614, +87614, +87614, +87630, +87630, +87641, +87641, +87641, +87651, +87715, +87715, +87715, +87715, +87715, +87715, +87725, +87725, +87725, +87725, +87725, +87725, +87725, +87761, +87768, +87775, +87775, +87775, +87775, +87775, +87792, +87792, +87792, +87792, +87792, +87792, +87792, +87792, +87802, +87802, +87802, +87865, 87971, +87977, +87977, +87977, +87977, 87986, 87986, -87986, -87986, -87986, -87986, -87999, -87999, -88037, -88054, -88082, -88092, -88106, -88148, -88156, -88156, -88156, -88164, -88164, -88181, -88203, -88229, -88246, -88246, -88263, -88263, -88316, -88316, -88316, -88323, -88341, -88341, -88347, -88352, -88352, -88359, -88366, -88366, -88388, -88409, -88444, -88450, -88455, -88455, -88455, -88455, -88465, -88465, -88465, -88471, -88471, -88480, +87994, +87994, +87994, +87994, +88028, +88028, +88041, +88041, +88041, +88041, +88041, +88065, +88075, +88104, +88114, +88130, +88142, +88142, +88159, +88177, +88177, +88183, +88183, +88183, +88210, +88375, +88387, +88387, +88392, +88392, +88407, +88413, +88413, +88413, +88413, +88413, +88413, +88413, +88413, +88420, +88441, +88441, +88447, +88454, +88470, +88483, +88490, +88490, 88499, -88538, -88538, -88538, -88538, -88556, -88568, -88568, -88575, -88575, -88583, -88596, -88603, -88621, -88621, -88657, -88669, -88676, -88697, -88697, -88697, -88729, -88729, -88729, -88729, -88754, -88754, -88773, -88809, -88818, -88818, -88827, -88888, -88888, -88901, -88901, -88901, +88499, +88505, +88505, +88505, +88516, +88516, +88516, +88608, +88756, +88764, +88771, +88783, +88803, +88817, +88817, +88817, +88829, +88829, +88829, +88829, +88829, +88863, +88863, +88863, +88863, +88863, +88874, +88893, 88906, -88926, -88926, -88940, -88948, -88959, -88959, -88959, -88965, -88999, -88999, -88999, -89020, -89020, -89028, -89037, -89054, -89061, -89061, -89075, -89075, -89075, -89075, -89109, -89109, -89126, -89126, -89151, -89151, -89164, -89164, -89164, -89164, -89170, -89195, -89220, -89220, -89220, -89227, -89236, -89243, -89243, -89243, -89243, -89243, -89254, -89264, -89288, -89299, -89314, -89314, -89314, -89330, -89350, -89350, -89361, -89397, -89415, -89427, -89435, -89441, -89459, -89465, -89465, -89470, -89489, -89489, -89489, -89489, -89503, -89526, -89548, -89548, -89566, -89566, -89571, -89588, -89588, -89599, -89608, -89608, -89608, -89619, -89672, -89702, -89702, -89702, -89727, -89784, -89784, -89790, -89790, -89790, -89790, -89800, -89800, -89813, -89840, -89855, -89855, -89885, -89885, -89895, +88906, +88916, +88916, +88916, +88916, +88916, +88916, +88944, +88944, +88944, +88963, +89112, +89124, +89124, +89124, +89124, +89137, +89137, +89143, +89143, +89143, +89143, +89143, +89143, +89187, +89194, +89200, +89200, +89200, +89206, +89212, +89263, +89275, +89275, +89285, +89285, +89307, +89313, +89313, +89313, +89313, +89319, +89383, +89477, +89483, +89483, +89483, +89483, +89499, +89499, +89521, +89521, +89527, +89527, +89527, +89533, +89563, +89563, +89563, +89563, +89563, +89597, +89625, +89681, +89704, +89704, +89704, +89704, +89704, +89717, +89723, +89723, +89723, +89723, +89752, +89892, +89892, 89908, -89942, -89952, -89967, -89985, -89994, -89994, +89925, +89954, +89954, +89954, +89954, +89954, +89970, +89970, +89977, +89977, +89977, +89977, 90005, -90011, -90035, -90035, -90051, -90051, -90051, -90051, -90051, -90070, -90070, -90070, -90070, -90078, -90078, -90078, -90086, -90097, -90097, -90105, -90105, -90122, -90137, -90189, -90189, -90199, -90235, -90241, -90241, -90241, -90248, -90265, -90296, -90296, -90296, -90319, -90348, -90348, -90355, -90373, -90373, -90410, -90410, -90468, -90484, -90507, -90507, -90517, -90517, -90541, -90572, -90572, -90572, -90601, -90616, -90709, -90723, -90761, -90781, -90781, +90005, +90005, +90022, +90034, +90068, +90101, +90101, +90101, +90101, +90101, +90108, +90108, +90108, +90108, +90108, +90174, +90342, +90342, +90352, +90352, +90352, +90352, +90352, +90358, +90358, +90383, +90383, +90383, +90389, +90456, +90456, +90463, +90463, +90463, +90463, +90500, +90500, +90512, +90519, +90519, +90519, +90525, +90525, +90525, +90537, +90537, +90545, +90568, +90748, +90748, +90748, +90748, +90754, +90777, +90777, +90777, +90777, +90777, +90777, +90777, +90783, +90789, +90795, +90808, +90808, 90815, -90822, -90842, -90873, -90873, -90899, +90821, +90827, +90861, +90867, +90881, 90906, -90934, -90941, -90941, -90948, -90948, -90958, -90981, -90988, -91015, -91021, -91047, -91075, -91082, -91103, -91114, -91123, -91123, -91123, -91182, -91210, -91223, -91223, -91239, -91239, -91239, +90906, +90917, +90925, +90925, +90925, +90925, +90925, +90945, +91131, +91131, +91155, +91155, +91163, +91169, +91169, +91169, +91169, +91169, +91169, +91169, +91169, +91209, +91209, +91209, +91209, +91209, +91215, +91221, +91243, 91254, -91267, -91287, -91307, -91334, -91334, -91367, -91406, -91417, -91424, -91431, -91457, -91457, -91473, -91480, -91480, -91487, -91487, -91519, -91538, -91548, -91548, -91548, -91555, -91562, -91562, -91562, -91581, -91599, -91614, -91640, -91640, -91640, -91647, -91665, -91665, -91672, -91690, +91254, +91270, +91270, +91270, +91270, +91270, +91312, +91346, +91346, +91407, +91498, +91515, +91515, +91527, +91527, +91541, +91541, +91547, +91547, +91553, +91553, +91571, +91587, +91618, +91625, +91625, +91625, +91631, +91631, +91638, +91680, 91697, 91697, -91697, -91715, -91715, -91761, -91804, -91811, -91820, -91831, -91838, -91838, -91845, -91858, -91882, -91882, -91901, -91901, -91946, -91953, -91960, -91969, -91969, -92006, -92030, -92076, -92082, -92101, -92108, -92108, -92108, -92108, -92115, -92122, -92207, -92227, -92247, -92264, -92282, -92291, -92291, -92291, -92313, -92337, -92351, -92358, -92358, -92373, -92388, -92395, -92404, -92404, -92435, -92442, -92442, -92453, -92472, -92472, -92478, -92487, -92507, -92521, -92531, -92531, -92531, -92570, -92592, -92592, -92592, -92599, -92599, -92625, +91725, +91725, +91731, +91737, +91737, +91770, +91778, +91778, +91814, +91942, +91950, +92007, +92007, +92050, +92077, +92077, +92077, +92077, +92077, +92083, +92083, +92083, +92123, +92129, +92129, +92129, +92151, +92151, +92151, +92225, +92255, +92263, +92287, +92287, +92295, +92295, +92302, +92332, +92332, +92338, +92346, +92428, +92439, +92447, +92447, +92447, +92464, +92471, +92477, +92477, +92477, +92477, +92477, +92477, +92513, +92529, +92541, +92541, +92541, +92548, +92554, +92621, 92632, -92632, -92664, -92715, -92741, -92750, -92776, -92792, -92799, -92806, -92818, -92818, -92826, -92843, -92843, -92865, -92891, -92898, -92908, -92924, -92936, -92948, -92983, -92983, -93048, -93056, -93056, -93056, -93063, -93097, -93123, -93138, -93138, -93158, -93165, -93174, -93180, -93187, -93195, -93231, -93243, -93250, -93257, -93270, -93284, -93310, -93329, -93343, -93343, -93368, -93368, -93368, -93368, -93407, -93407, -93407, -93454, -93465, -93465, -93465, -93500, -93500, -93508, -93517, -93517, -93517, -93530, -93546, -93546, -93562, -93580, -93587, -93603, -93603, -93603, -93610, -93643, -93643, -93660, -93660, -93660, -93678, -93685, -93701, -93726, -93726, -93726, -93733, -93740, -93763, -93787, -93787, -93787, -93787, -93787, -93794, -93813, -93813, -93835, -93843, -93843, -93843, -93860, -93889, -93934, -93956, -93980, -94015, -94022, -94056, -94073, -94083, -94101, -94114, -94114, -94120, -94133, -94140, -94147, -94172, -94188, -94234, -94241, -94276, -94299, -94337, -94354, -94360, -94360, -94360, -94373, -94373, -94416, -94440, -94479, -94479, -94479, +92639, +92661, +92661, +92668, +92675, +92675, +92675, +92675, +92675, +92681, +92824, +92824, +92853, +92859, +92873, +92882, +92882, +92888, +92888, +92894, +92894, +92902, +92902, +92976, +92982, +92994, +92994, +92994, +93000, +93000, +93006, +93045, +93045, +93045, +93051, +93064, +93076, +93099, +93121, +93127, +93127, +93175, +93373, +93379, +93389, +93408, +93421, +93426, +93426, +93432, +93432, +93432, +93445, +93459, +93459, +93459, +93459, +93471, +93471, +93482, +93482, +93511, +93582, +93620, +93630, +93667, +93667, +93673, +93692, +93692, +93702, +93702, +93702, +93723, +94042, +94042, +94067, +94067, +94067, +94090, +94090, +94090, +94090, +94090, +94098, +94098, +94105, +94157, +94163, +94163, +94163, +94163, +94169, +94181, +94193, +94193, +94193, +94193, +94193, +94209, +94216, +94216, +94232, +94232, +94232, +94264, +94378, +94396, +94402, +94409, +94436, +94444, +94451, +94451, +94451, +94451, +94458, +94458, 94501, -94524, -94534, -94559, -94578, -94578, -94585, -94603, -94610, -94646, -94672, -94684, -94708, -94714, -94745, -94768, -94797, -94811, -94837, -94887, -94911, -94926, -94952, -94971, -94978, -95005, -95014, -95041, -95041, -95048, -95101, -95108, -95115, -95122, -95136, -95150, -95174, -95174, -95195, -95218, -95218, -95235, -95274, -95281, -95281, -95301, -95322, -95329, -95343, -95343, +94507, +94527, +94527, +94532, +94545, +94583, +94602, +94626, +94640, +94640, +94640, +94647, +94654, +94681, +94681, +94690, +94703, +94717, +94748, +94938, +94938, +94945, +94961, +94982, +94993, +94993, +94999, +94999, +95013, +95020, +95020, +95020, +95020, +95033, +95040, +95040, +95040, +95046, +95065, +95077, +95095, +95102, +95134, +95134, +95134, +95134, +95140, +95140, +95147, +95147, +95165, +95203, +95223, +95240, +95272, +95272, +95285, +95285, +95292, +95292, +95292, +95299, +95299, +95299, +95327, +95327, 95350, 95350, 95350, -95357, -95378, -95378, -95385, -95392, -95399, -95424, -95424, -95424, -95424, -95443, -95463, -95477, -95477, -95477, -95484, -95499, -95510, -95539, -95571, -95578, -95583, -95590, -95630, -95630, -95630, -95637, -95667, -95687, -95707, -95730, -95730, -95730, -95756, -95756, -95776, -95776, -95776, -95792, -95806, -95824, -95824, -95843, -95850, -95860, -95860, -95860, -95860, -95860, -95880, -95880, -95901, -95913, -95928, -95938, -95938, -95950, -95972, -95985, -96000, -96007, -96037, -96037, -96044, -96065, -96077, -96077, -96077, -96077, -96084, -96084, -96084, +95364, +95381, +95476, +95487, +95494, +95530, +95536, +95566, +95572, +95572, +95572, +95579, +95579, +95683, +95834, +95849, +95872, +95885, +95912, +95929, +95929, +95945, +95957, +95975, +95981, +95981, +95988, +96063, +96078, +96078, +96085, +96091, 96104, -96128, -96138, -96160, -96167, -96176, -96191, -96191, -96198, -96230, -96237, -96247, -96247, -96283, -96283, -96295, -96322, -96355, -96355, -96372, -96404, -96423, -96423, -96423, -96423, -96457, -96469, -96476, -96476, -96483, -96500, -96534, -96541, -96548, -96574, -96581, -96601, -96601, -96601, -96601, -96601, -96611, -96611, -96635, +96120, +96142, +96164, +96164, +96164, +96164, +96171, +96171, +96185, +96192, +96192, +96199, +96245, +96443, +96443, +96456, +96456, +96463, +96474, +96474, +96474, +96474, +96474, +96474, +96474, +96474, +96544, +96551, +96551, +96551, +96558, +96558, +96572, +96612, +96622, +96622, +96637, +96637, +96637, 96644, -96669, -96703, -96703, -96703, -96709, -96737, -96737, -96737, -96764, -96783, -96783, -96790, -96810, -96810, -96828, -96853, -96860, -96860, -96882, +96644, +96660, +96660, +96660, +96694, +96866, +96866, +96883, 96889, -96908, -96921, -96937, -96937, -96978, -96985, -96985, -97016, -97074, -97113, -97113, -97141, -97141, -97172, -97188, -97207, -97219, -97226, -97233, -97288, -97336, -97343, -97388, -97423, -97445, -97457, -97464, -97469, -97494, -97506, -97506, -97562, -97603, +96906, +96930, +96930, +96943, +96948, +96955, +96955, +96962, +96962, +97006, +97019, +97019, +97026, +97033, +97040, +97080, +97118, +97135, +97135, +97177, +97183, +97190, +97231, +97238, +97263, +97263, +97263, +97297, +97360, +97382, +97403, +97429, +97442, +97465, +97472, +97485, +97485, +97492, +97498, +97511, +97518, +97539, +97546, +97560, +97560, +97570, +97577, 97610, -97637, -97644, -97651, -97665, -97675, -97713, -97732, -97737, -97756, -97775, -97775, -97798, -97804, -97829, -97850, +97722, +97734, +97741, +97803, +97810, +97824, +97831, +97831, +97842, +97842, 97862, -97910, -97921, -97955, -97975, -97975, -98000, -98036, -98044, -98044, -98051, -98051, -98073, -98073, +97916, +97986, +97986, +97993, +97993, +97993, +97999, +98006, +98006, +98021, +98027, +98027, +98027, +98027, +98065, +98065, +98074, +98074, 98093, -98110, -98110, -98116, -98116, -98116, -98132, -98139, -98164, -98180, -98187, -98224, -98224, -98231, -98242, -98253, -98277, +98105, +98115, +98181, +98211, +98218, +98218, +98225, +98225, +98225, +98232, +98248, +98248, +98255, 98308, -98330, -98348, -98348, -98378, -98378, -98401, -98419, -98435, -98435, -98461, -98461, +98433, +98453, +98481, +98488, 98502, -98509, -98509, -98529, -98529, -98540, -98571, -98571, -98577, -98590, -98590, -98590, -98600, -98627, -98627, -98627, -98642, -98652, -98673, -98680, -98687, -98701, -98717, -98724, -98724, -98743, -98750, -98797, -98821, -98821, -98856, -98881, -98913, -98936, -98936, -98936, -98944, -98951, -98951, -98951, -98976, -99022, -99029, -99042, -99079, -99140, -99147, -99170, -99202, -99221, -99277, -99284, -99316, -99322, -99329, -99329, -99329, -99355, -99383, -99400, -99419, -99442, -99454, -99472, -99492, -99492, -99501, -99518, -99518, -99525, -99525, -99550, -99550, -99550, -99550, -99571, -99571, -99601, -99601, -99613, -99639, -99649, -99649, -99660, -99660, -99660, -99682, -99699, -99717, -99717, -99753, -99753, -99753, -99776, -99789, -99836, -99836, -99852, -99864, -99934, -99966, -99973, -99988, -99992, -100012, -100055, -100064, -100064, -100082, -100082, -100099, -100105, -100105, -100105, -100139, -100147, -100183, -100197, -100197, -100211, -100211, -100218, -100235, -100265, -100265, -100265, -100304, -100321, -100321, -100341, -100372, -100405, -100422, -100465, -100515, -100525, -100546, -100546, -100559, -100567, -100585, -100594, -100594, -100608, -100627, -100636, -100649, -100666, -100673, -100673, -100673, -100673, -100712, -100734, -100734, -100757, -100761, -100774, -100842, -100856, -100879, -100888, -100888, -100900, -100900, -100934, -100934, -100934, -100934, -100949, -100949, -100957, -100984, -100984, -100992, +98502, +98502, +98507, +98507, +98514, +98514, +98526, +98526, +98588, +98604, +98612, +98612, +98618, +98618, +98640, +98667, +98667, +98667, +98684, +98684, +98684, +98697, +98697, +98705, +98718, +98718, +98769, +98903, +98910, +98924, +98955, +98967, +98974, +98974, +98987, +98987, +98987, +98987, +98994, +99001, +99026, +99033, +99040, +99040, +99040, +99040, +99055, +99105, +99129, +99136, +99136, +99136, +99152, +99159, +99159, +99168, +99175, +99175, +99187, +99361, +99385, +99402, +99402, +99440, +99440, +99440, +99453, +99453, +99453, +99453, +99453, +99459, +99494, +99494, +99494, +99494, +99494, +99510, +99517, +99564, +99593, +99593, +99593, +99593, +99600, +99600, +99600, +99610, +99610, +99617, +99647, +99763, +99763, +99769, +99769, +99783, +99806, +99806, +99806, +99806, +99806, +99806, +99806, +99806, +99846, +99846, +99860, +99860, +99860, +99860, +99887, +99923, +99935, +99935, +99935, +99941, +99941, +99947, +99964, +99991, +99991, +99991, +100006, +100083, +100093, +100112, +100112, +100127, +100141, +100141, +100154, +100154, +100154, +100160, +100179, +100179, +100216, +100216, +100216, +100216, +100229, +100233, +100245, +100280, +100291, +100291, +100301, +100301, +100301, +100301, +100301, +100301, +100308, +100308, +100398, +100479, +100486, +100486, +100486, +100486, +100486, +100486, +100493, +100493, +100501, +100501, +100501, +100516, +100516, +100516, +100541, +100541, +100541, +100557, +100572, +100589, +100599, +100599, +100599, +100599, +100599, +100617, +100617, +100617, +100617, +100628, +100680, +100816, +100823, +100823, +100827, +100827, +100827, +100827, +100831, +100831, +100831, +100831, +100849, +100849, +100849, +100849, +100860, +100860, +100860, +100882, +100903, +100925, +100935, +100935, +100991, +100991, +100998, +100998, +100998, 101002, 101002, -101018, -101018, -101018, -101049, -101057, -101068, -101068, -101084, -101103, -101103, -101103, -101103, -101103, -101109, -101116, -101116, -101116, -101128, -101138, -101138, -101146, -101146, -101178, -101184, -101220, -101232, +101002, +101047, +101144, +101162, +101209, +101218, +101218, +101218, +101218, +101218, +101218, +101218, +101218, +101218, +101218, +101227, +101233, 101239, -101265, -101265, -101273, -101273, -101273, -101280, -101293, -101301, -101309, -101320, -101320, -101320, -101330, -101362, -101362, -101392, -101414, -101414, -101451, -101451, -101451, -101468, -101522, -101532, -101532, -101549, -101549, -101559, -101559, +101239, +101239, +101247, +101263, +101305, +101343, +101357, +101367, +101367, +101367, +101367, +101367, +101387, +101387, +101387, +101398, +101487, +101487, +101487, +101487, +101487, +101501, +101501, +101510, +101510, +101510, +101510, +101510, +101510, +101568, +101574, +101574, +101574, +101574, +101574, 101596, -101604, -101610, -101623, -101648, -101648, +101614, +101631, +101631, +101631, +101631, +101647, +101647, +101647, +101656, 101663, -101696, -101696, -101696, -101703, -101722, -101739, -101739, -101762, -101762, -101773, -101795, -101795, -101795, -101841, -101859, -101902, -101902, +101663, +101733, +101905, +101905, 101921, -101947, -101947, -101947, -101947, +101931, +101931, +101949, +101949, +101949, 101956, -101970, -101970, -101970, -101980, -101980, -102000, -102013, -102020, -102032, -102050, -102082, -102091, -102106, -102106, -102153, -102175, -102193, -102200, -102210, -102230, -102230, -102230, -102230, -102289, -102331, -102366, -102377, -102377, -102377, -102394, -102410, -102440, -102440, -102447, -102458, -102465, -102498, -102498, -102498, -102537, -102551, -102551, -102558, -102581, -102587, -102587, -102602, -102622, -102622, -102660, -102686, -102693, -102700, -102707, -102707, -102721, -102743, -102757, -102785, -102822, -102861, -102881, -102891, -102919, -102973, -102973, -102985, -102985, -103001, -103001, -103001, -103044, -103062, -103062, -103071, -103071, -103071, -103089, -103093, -103093, -103093, -103093, -103103, -103103, -103110, -103110, -103110, -103110, -103110, -103123, +101956, +101956, +101963, +101963, +102015, +102015, +102015, +102015, +102015, +102015, +102025, +102073, +102073, +102073, +102090, +102090, +102090, +102090, +102100, +102100, +102100, +102100, +102166, +102295, +102295, +102295, +102315, +102357, +102373, +102373, +102390, +102390, +102390, +102399, +102399, +102399, +102399, +102399, +102419, +102419, +102419, +102419, +102453, +102515, +102549, +102549, +102591, +102591, +102620, +102620, +102620, +102643, +102643, +102643, +102687, +102773, +102795, +102802, +102802, +102802, +102813, +102813, +102813, +102829, +102829, +102833, +102833, +102837, +102849, +102849, +102864, +102864, +102871, +102871, +102871, +102901, +102965, +102965, +102965, +102965, +102965, +102965, +102981, +102999, +102999, +102999, +103012, +103087, +103094, 103130, -103153, -103153, -103170, -103170, -103202, -103220, -103235, -103242, -103264, -103280, -103300, -103300, -103306, +103146, +103156, +103156, +103156, +103156, +103156, +103156, +103156, +103156, +103156, +103207, +103207, +103207, +103207, +103207, +103211, +103245, +103297, +103304, +103304, +103309, +103309, +103309, 103330, 103330, 103330, 103330, -103340, -103369, -103383, -103403, -103410, -103471, -103479, -103496, -103517, -103539, -103539, -103585, -103614, -103614, -103632, -103672, -103692, -103692, -103729, -103729, -103752, -103777, -103794, -103814, -103831, -103831, -103858, -103858, -103900, -103900, -103909, -103927, -103939, -103939, -103939, -103939, -103953, -103960, -103967, -103967, -103992, -104004, -104004, -104004, -104030, +103330, +103379, +103529, +103529, +103599, +103599, +103628, +103640, +103640, +103644, +103644, +103654, +103654, +103654, +103654, +103671, +103675, +103681, +103681, +103681, +103690, +103702, +103702, +103734, +103734, +103755, +103755, +103755, +103755, +103768, +103805, +103812, +103812, +103850, +103879, +103915, +103915, +103915, +103942, +103942, +103942, +103964, +103964, +103964, +103970, +103976, +103976, +104027, +104034, +104034, +104034, +104034, 104041, -104053, -104060, -104060, -104086, -104110, -104128, -104135, -104155, -104166, -104166, -104172, -104204, -104204, -104204, -104204, -104241, -104257, -104257, -104257, -104275, -104294, -104315, -104333, -104333, -104368, -104394, -104394, -104394, -104401, -104447, -104455, -104470, -104486, -104486, -104511, -104511, -104536, -104548, -104548, -104570, -104570, -104570, -104595, -104631, -104641, -104663, -104679, -104697, +104056, +104083, +104098, +104106, +104123, +104123, +104123, +104123, +104123, +104133, +104133, +104133, +104213, +104386, +104398, +104410, +104429, +104429, +104451, +104451, +104451, +104451, +104451, +104451, +104451, +104451, +104515, +104515, +104515, +104515, +104519, +104519, +104552, +104568, +104587, +104597, +104597, +104597, +104606, +104606, +104606, +104617, +104617, +104617, +104665, 104717, 104717, -104732, -104740, -104757, -104764, -104788, -104805, -104809, -104837, -104849, -104886, -104886, -104886, -104886, -104886, -104903, -104903, -104903, -104907, -104917, -104917, -104917, -104917, -104917, -104944, -104944, -104953, -104953, -104953, -104963, -104963, -104972, -104994, -104994, -104994, -104994, -104994, -104994, -105025, +104727, +104742, +104746, +104753, +104753, +104753, +104753, +104771, +104771, +104780, +104780, +104835, +104835, +104845, +104845, +104852, +104852, +104860, +104881, +104881, +104881, +104897, +104897, +104897, +104901, +104901, +104922, +104922, +104922, +104971, +104981, +104981, +104998, +104998, +104998, +105009, +105009, +105009, +105009, +105017, +105026, +105026, 105044, -105044, -105044, -105049, -105049, -105071, -105071, -105071, -105089, -105096, -105103, -105142, -105142, -105142, -105142, -105142, -105142, -105142, -105162, -105187, -105206, -105216, -105269, -105269, -105289, -105289, -105289, -105335, -105347, -105374, -105386, -105386, -105386, -105397, -105407, -105423, -105423, -105437, -105437, -105449, -105470, -105478, -105489, -105489, -105489, -105509, -105509, -105529, -105529, -105529, -105541, -105555, -105560, -105560, -105575, -105575, -105575, -105586, -105586, -105592, -105592, -105592, -105592, -105607, -105607, -105622, -105622, -105622, -105650, -105660, +105093, +105093, +105107, +105107, +105133, +105133, +105133, +105155, +105166, +105183, +105195, +105201, +105201, +105201, +105211, +105221, +105221, +105221, +105221, +105370, +105370, +105370, +105370, +105390, +105400, +105400, +105400, +105400, +105400, +105400, +105400, +105400, +105431, +105431, +105431, +105431, +105431, +105438, +105442, +105442, +105454, +105454, +105458, +105458, +105458, +105458, +105458, +105458, +105458, +105458, +105497, +105662, +105662, 105676, -105702, -105712, -105729, -105746, -105755, -105777, -105777, -105794, -105794, -105798, -105827, -105827, -105827, -105839, -105844, -105844, -105844, -105868, -105868, -105888, -105888, -105888, -105922, -105945, -105945, -105955, -105955, -105986, -105986, -106005, -106005, -106012, -106026, -106030, -106034, -106054, -106061, -106061, -106065, -106069, -106084, -106095, -106095, -106101, -106123, -106144, -106144, -106154, -106154, -106173, -106173, -106246, -106246, -106246, -106277, -106317, -106333, -106373, -106386, +105676, +105676, +105701, +105701, +105701, +105701, +105701, +105701, +105701, +105701, +105742, +105748, +105752, +105766, +105766, +105766, +105775, +105779, +105779, +105779, +105796, +105806, +105806, +105806, +105816, +105825, +105825, +105825, +105835, +106032, +106032, +106050, +106050, +106055, +106055, +106055, +106055, +106055, +106055, +106070, +106078, +106082, +106086, +106086, +106106, +106106, +106116, +106120, +106131, +106146, +106168, +106168, +106168, +106168, +106174, +106174, +106183, +106183, +106183, +106187, +106256, +106368, +106381, +106401, 106405, -106458, -106489, -106489, -106489, -106497, -106515, -106522, -106522, -106522, -106530, -106538, -106560, -106582, -106582, -106627, -106627, -106627, -106634, -106643, -106643, -106654, -106669, -106669, -106669, -106682, -106691, -106691, -106691, -106698, -106698, -106707, -106707 +106405, +106426, +106426, +106426, +106426, +106426, +106426, +106426, +106426, +106459, +106459, +106459, +106459, +106466, +106472, +106481, +106494, +106501, +106501, +106501, +106501, +106501, +106501, +106501, +106523, +106523, +106523, +106593, +106646, +106652, +106673, +106673, +106673, +106680, +106680, +106680, +106680, +106680, +106680, +106699, +106699, +106742, +106742, +106762 }; static const quint16 tldChunkCount = 2; static const char * const tldData[tldChunkCount] = { -"lib.sc.us\0ladesk.com\0" -"web.ve\0" -"trader.aero\0" -"\xd1\x83\xd0\xba\xd1\x80\0from-wa.com\0arkhangelsk.su\0" -"net.ac\0" -"arq.br\0" -"net.ae\0bg.eu.org\0" -"maintenance.aero\0net.af\0kyowa.hokkaido.jp\0ceo\0noop.app\0" -"net.ag\0" -"cfa\0is-a-blogger.com\0" -"net.ai\0" -"cfd\0" -"net.al\0poznan.pl\0" -"net.am\0" +"cfa\0" +"poker\0" +"al.us\0k12.fl.us\0k12.mo.us\0" +"pu.it\0verona.it\0cfd\0from-la.net\0" +"tec.ve\0murmansk.su\0" +"per.nf\0" +"6.bg\0is-found.org\0eu.org\0httpbin.org\0" +"rexroth\0" "buy\0" -"net.ba\0" -"net.ar\0net.bb\0" -"davvenjarga.no\0" -"kitagawa.kochi.jp\0walbrzych.pl\0" -"net.au\0sa.it\0ikeda.osaka.jp\0" -"s3-website-ap-southeast-1.amazonaws.com\0" -"net.bh\0" -"net.az\0net.bj\0tvedestrand.no\0" -"ikeda.gifu.jp\0" -"shinto.gunma.jp\0" -"net.bm\0g\xc3\xa1\xc5\x8bgaviika.no\0" -"net.bn\0kagoshima.kagoshima.jp\0capitalone\0" -"net.bo\0" -"net.br\0" -"net.bs\0" -"net.bt\0health-carereform.com\0myspreadshop.es\0" -"aland.fi\0" -"sakahogi.gifu.jp\0" -"net.ci\0" -"net.bz\0haga.tochigi.jp\0myspreadshop.fi\0" -"net.cm\0giving\0" -"pp.az\0net.cn\0tele.amune.org\0" -"net.co\0sango.nara.jp\0siellak.no\0" -"hanno.saitama.jp\0" -"hasuda.saitama.jp\0\xe4\xbf\xa1\xe6\x81\xaf\0" -"gyeongbuk.kr\0cc.wv.us\0myspreadshop.fr\0" -"etne.no\0club.tw\0consulting\0" -"net.cu\0*.builder.code.com\0" -"net.cw\0jp.net\0" -"miyoshi.aichi.jp\0" -"net.cy\0hita.oita.jp\0" -"arezzo.it\0hashbang.sh\0firewall-gateway.com\0" -"rn.gov.br\0x.se\0web.za\0" -"abbvie\0" -"net.dm\0" -"net.do\0assn.lk\0game-host.org\0oxa.cloud\0" -"shopselect.net\0filegear-sg.me\0" -"net.ec\0nichinan.tottori.jp\0is-a-photographer.com\0" -"oshino.yamanashi.jp\0" -"oizumi.gunma.jp\0" -"echizen.fukui.jp\0" -"net.eg\0" -"erotika.hu\0ae.org\0vivian.jp\0" -"deta.dev\0" -"net.dz\0fm.it\0" -"london\0is-into-cars.com\0" -"jan-mayen.no\0kred\0" -"bzh\0" -"golffan.us\0" -"6.bg\0matsudo.chiba.jp\0" -"aerodrome.aero\0net.et\0site.tb-hosting.com\0" -"oslo.no\0" -"myspreadshop.ie\0" -"report\0" -"nakayama.yamagata.jp\0" -"notaires.km\0" -"net.fj\0download\0daynight.jp\0sinaapp.com\0" -"ro.gov.br\0aarp\0george\0" -"suedtirol.it\0" -"net.fm\0okinoshima.shimane.jp\0sytes.net\0" -"takanezawa.tochigi.jp\0" -"lib.ri.us\0" -"bmd.br\0naples.it\0asahikawa.hokkaido.jp\0" -"pyatigorsk.ru\0" -"net.ge\0homeunix.com\0hr.eu.org\0myspreadshop.at\0" -"pe.ca\0myspreadshop.be\0" -"net.gg\0" -"gokase.miyazaki.jp\0mond.jp\0servemp3.com\0" -"flight.aero\0lom.it\0hino.tottori.jp\0" -"net.gl\0takayama.gunma.jp\0m.se\0" -"photos\0weather\0" -"net.gn\0akaiwa.okayama.jp\0r\xc3\xa5""de.no\0" -"\xe9\xa6\x99\xe6\xa0\xbc\xe9\x87\x8c\xe6\x8b\x89\0" -"net.gp\0" -"fuefuki.yamanashi.jp\0belau.pw\0" -"net.gr\0myspreadshop.ca\0" -"net.gt\0" -"net.gu\0er.in\0" -"chofu.tokyo.jp\0" -"otsuchi.iwate.jp\0" -"net.gy\0myspreadshop.ch\0" -"higashiyoshino.nara.jp\0s3.fr-par.scw.cloud\0" -"net.hk\0moskenes.no\0" -"nannestad.no\0vinnica.ua\0" -"tohnosho.chiba.jp\0shibuya.tokyo.jp\0" -"net.hn\0" -"qcx.io\0" -"neat-url.com\0" -"net.ht\0net.id\0" -"hosting\0" -"myspreadshop.de\0" -"pharmaciens.km\0dattolocal.com\0" -"logistics.aero\0motoyama.kochi.jp\0tozawa.yamagata.jp\0" -"caserta.it\0" -"lowicz.pl\0" -"net.il\0namegata.ibaraki.jp\0myspreadshop.dk\0" -"net.im\0" -"net.in\0rollag.no\0us.platform.sh\0" -"veneto.it\0" -"net.iq\0andebu.no\0lib.pr.us\0" -"net.ir\0mutual\0azerbaijan.su\0" -"net.is\0" -"vfs.cloud9.ap-northeast-2.amazonaws.com\0" -"net.je\0fm.no\0" -"app.br\0samsung\0" -"co.krd\0" -"akishima.tokyo.jp\0" -"sex.hu\0" -"b.se\0eu-central-1.elasticbeanstalk.com\0" -"net.jo\0support\0" -"s3.nl-ams.scw.cloud\0" -"shoes\0" -"com\0eu.int\0" -"poltava.ua\0" -"jampa.br\0net.kg\0contractors\0" -"cq.cn\0cpa\0trust\0" -"yamatotakada.nara.jp\0net.ki\0" -"sand\xc3\xb8y.no\0" -"net.kn\0rar.ve\0" -"s3.dualstack.us-east-2.amazonaws.com\0" -"\xd8\xa7\xdb\x8c\xd8\xb1\xd8\xa7\xd9\x86.ir\0net.la\0" -"net.lb\0" -"net.lc\0s3-website-ap-northeast-1.amazonaws.com\0" -"imabari.ehime.jp\0origins\0" -"lom.no\0hitachi\0" -"net.kw\0" -"berlin\0" -"tsuno.kochi.jp\0net.ky\0" -"net.kz\0" -"net.lk\0dad\0" -"nsn.us\0" -"aus.basketball\0" -"t\xc3\xb8nsberg.no\0" -"homebuilt.aero\0nanto.toyama.jp\0" -"net.ma\0" -"net.lr\0" -"net.ls\0pics\0" -"net.me\0" -"net.lv\0" -"\xd0\xb1\xd0\xb3\0" -"karuizawa.nagano.jp\0" -"net.ly\0" -"vda.it\0" -"net.mk\0volda.no\0" -"assabu.hokkaido.jp\0kitamoto.saitama.jp\0net.ml\0stuff-4-sale.us\0ownip.net\0" -"chippubetsu.hokkaido.jp\0" -"net.mo\0" -"day\0homegoods\0" -"eero-stage.online\0" -"kounosu.saitama.jp\0net.ms\0nikita.jp\0" -"net.mt\0is-a-cubicle-slave.com\0" -"mamurogawa.yamagata.jp\0net.mu\0gitpage.si\0" -"net.mv\0net.nf\0half.host\0" -"kawanishi.nara.jp\0net.mw\0net.ng\0" -"ba.gov.br\0net.mx\0" -"pe.it\0net.my\0net.ni\0" -"net.mz\0crs\0noticeable.news\0" -"caxias.br\0" -"keymachine.de\0" -"tobetsu.hokkaido.jp\0homesense\0" -"nishinoomote.kagoshima.jp\0servebbs.net\0" -"kaita.hiroshima.jp\0net.nr\0pizza\0" -"hidaka.wakayama.jp\0" -"app.gp\0" -"nantan.kyoto.jp\0ap-south-1.elasticbeanstalk.com\0" -"takatsuki.osaka.jp\0\xe5\x80\x8b\xe4\xba\xba.\xe9\xa6\x99\xe6\xb8\xaf\0" -"sakata.yamagata.jp\0net.nz\0" -"shikatsu.aichi.jp\0yonabaru.okinawa.jp\0" -"net.om\0" -"k12.mt.us\0" -"aoki.nagano.jp\0able\0" -"net.pa\0" -"fukuchi.fukuoka.jp\0" -"net.pe\0" -"sassari.it\0" -"pe.kr\0lib.dc.us\0" -"net.ph\0" -"miyazaki.miyazaki.jp\0dds\0" -"net.pk\0" -"net.pl\0" -"berg.no\0" -"net.pn\0" -"\xd8\xa7\xd9\x84\xd9\x85\xd8\xba\xd8\xb1\xd8\xa8\0" -"net.qa\0" -"yoshimi.saitama.jp\0net.pr\0" -"net.ps\0n4t.co\0outsystemscloud.com\0" -"net.pt\0sakura.ne.jp\0" -"gs.st.no\0" -"mie.jp\0flatanger.no\0" -"londrina.br\0" -"\xe5\xb1\xb1\xe5\x8f\xa3.jp\0" -"net.py\0" -"raffleentry.org.uk\0" -"obanazawa.yamagata.jp\0" -"kashihara.nara.jp\0" -"dev\0" -"press.aero\0sex.pl\0" -"locus\0" -"cesena-forli.it\0" -"180r.com\0" -"handa.aichi.jp\0" -"se.gov.br\0" -"kurobe.toyama.jp\0cern\0" -"shopping\0" -"sandnessjoen.no\0evenes.no\0" -"net.sa\0" -"net.sb\0\xd0\xb5\xd1\x8e\0" -"net.sc\0" -"h\xc3\xa5.no\0net.sd\0" -"salangen.no\0net.ru\0" -"net.rw\0net.sg\0" -"nishiizu.shizuoka.jp\0net.sh\0" -"eu.ngrok.io\0" -"aparecida.br\0net.sl\0" -"showa.gunma.jp\0noboribetsu.hokkaido.jp\0" -"net.so\0vfs.cloud9.us-east-1.amazonaws.com\0" -"myhome-server.de\0" -"net.ss\0dhl\0grocery\0" -"net.st\0" -"bargains\0" -"net.th\0" -"industria.bo\0pp.se\0net.sy\0pp.ru\0" -"net.tj\0" -"no.it\0" -"ngrok.pizza\0" -"miyota.nagano.jp\0net.tm\0" -"net.tn\0" -"net.to\0" -"barlettatraniandria.it\0news\0" -"net.ua\0" -"net.tr\0" -"mine.nu\0" -"net.tt\0privatizehealthinsurance.net\0" -"karasjok.no\0" -"omachi.saga.jp\0nesoddtangen.no\0eidfjord.no\0watch\0" -"net.tw\0ddnsfree.com\0" -"net.uk\0" -"luroy.no\0" -"grosseto.it\0fuettertdasnetz.de\0sells-it.net\0" -"diy\0" -"next\0" -"itoman.okinawa.jp\0net.vc\0ui.nabu.casa\0" -"mutual.ar\0" -"lib.mn.us\0net.ve\0pp.ua\0" -"am.gov.br\0" -"net.uy\0net.vi\0" -"net.uz\0is-a-caterer.com\0""64-b.it\0" -"ddns5.com\0" -"iwata.shizuoka.jp\0" -"net.vn\0" -"chowder.jp\0" -"friuli-vgiulia.it\0" -"szex.hu\0net.vu\0myactivedirectory.com\0" -"ping\0" -"ln.cn\0" -"banamex\0custom.metacentrum.cz\0" -"pink\0\xd0\xbc\xd0\xbe\xd1\x81\xd0\xba\xd0\xb2\xd0\xb0\0" -"mt.it\0" -"vall\xc3\xa9""e-aoste.it\0masuda.shimane.jp\0elblag.pl\0" -"net.ws\0" -"agric.za\0" -"flog.br\0sa.gov.pl\0" -"vadso.no\0" -"esan.hokkaido.jp\0us-west-1.elasticbeanstalk.com\0" -"neustar\0" -"viajes\0" -"saltdal.no\0mydrobo.com\0" -"asnes.no\0" -"mantova.it\0" -"k12.ky.us\0" -"algard.no\0namsskogan.no\0" -"town\0" -"net.ye\0deloitte\0" -"takahama.fukui.jp\0now.sh\0" -"taishi.hyogo.jp\0" -"bib.br\0nishigo.fukushima.jp\0" -"bardu.no\0" -"lib.ar.us\0" -"sydney\0" -"skj\xc3\xa5k.no\0\xe0\xb9\x80\xe0\xb8\x99\xe0\xb9\x87\xe0\xb8\x95.\xe0\xb9\x84\xe0\xb8\x97\xe0\xb8\xa2\0" -"\xe5\xb3\xb6\xe6\xa0\xb9.jp\0" -"design.aero\0" -"kasaoka.okayama.jp\0" -"ravenna.it\0hatsukaichi.hiroshima.jp\0net.za\0" -"toyama.toyama.jp\0" -"vlog.br\0aetna\0" -"foundation\0" -"bulsan-s\xc3\xbc""dtirol.it\0dnp\0" -"bibai.hokkaido.jp\0" -"firestone\0" -"research.aero\0" -"gmbh\0" -"mi.it\0br\xc3\xb8nn\xc3\xb8y.no\0\xe0\xa4\xad\xe0\xa4\xbe\xe0\xa4\xb0\xe0\xa4\xa4\xe0\xa4\xae\xe0\xa5\x8d\0net.zm\0" -"yukuhashi.fukuoka.jp\0dog\0kuron.jp\0" -"shoo.okayama.jp\0" -"ap.it\0" -"gotemba.shizuoka.jp\0" -"asahi.toyama.jp\0" -"il.eu.org\0" -"assur.bj\0" -"buzz\0" -"toys\0from-ak.com\0fi.cloudplatform.fi\0" -"\xe5\xae\xae\xe5\xb4\x8e.jp\0\xd8\xa7\xd9\x84\xd8\xac\xd8\xb2\xd8\xa7\xd8\xa6\xd8\xb1\0dot\0" -"xs4all.space\0" -"wa.au\0" -"goip.de\0" -"lcube-server.de\0" -"pharmacy\0" -"minokamo.gifu.jp\0kr\xc3\xa5""anghke.no\0" -"exchange.aero\0crotone.it\0mashiko.tochigi.jp\0lib.md.us\0pagexl.com\0" -"ap.gov.br\0" -"mobi.gp\0nonoichi.ishikawa.jp\0taira.toyama.jp\0" -"lesja.no\0" -"troandin.no\0" -"sn\xc3\xa5""ase.no\0" -"guovdageaidnu.no\0" -"sor-varanger.no\0hu.eu.org\0ie.eu.org\0" -"mitaka.tokyo.jp\0" -"sampa.br\0" -"\xd1\x80\xd1\x84\0" -"jx.cn\0" -"eat\0" -"*.developer.app\0" -"ap.gov.pl\0nikon\0" -"other.nf\0" -"cloudns.asia\0" -"kamikoani.akita.jp\0" -"nagiso.nagano.jp\0" -"reg.dk\0" -"yawara.ibaraki.jp\0" -"tsu.mie.jp\0lardal.no\0" -"sandcats.io\0" -"eco\0" -"cloudfunctions.net\0" -"lib.la.us\0estate\0" -"dni.us\0" -"kawanishi.hyogo.jp\0" -"edu.ac\0" -"edu.af\0" -"teramo.it\0" -"kongsvinger.no\0herokussl.com\0" -"hlx.live\0" -"edu.al\0" -"trentinosued-tirol.it\0b\xc3\xa5tsfjord.no\0washtenaw.mi.us\0" -"secaas.hk\0" -"edu.ba\0" -"edu.ar\0edu.bb\0" -"edu\0ama.aichi.jp\0" -"dtv\0ma.leg.br\0*.dweb.link\0" -"ambulance.aero\0edu.au\0musashimurayama.tokyo.jp\0ostrowiec.pl\0filegear-jp.me\0arvo.network\0" -"lc.it\0" -"edu.bh\0" -"edu.bi\0" -"edu.az\0edu.bj\0asaka.saitama.jp\0" -"ugim.gov.pl\0" -"iida.nagano.jp\0" -"edu.bm\0" -"edu.bn\0" -"edu.bo\0iwate.iwate.jp\0" -"ohda.shimane.jp\0" -"edu.br\0ikeda.hokkaido.jp\0" -"edu.bs\0valleedaoste.it\0" -"edu.bt\0" -"notaires.fr\0" -"leangaviika.no\0svn-repos.de\0" -"u2.xnbay.com\0" -"edu.ci\0" -"edu.bz\0in-vpn.de\0" -"buyshop.jp\0*.vultrobjects.com\0" -"aeroport.fr\0" -"basilicata.it\0" -"edu.cn\0" -"edu.co\0furudono.fukushima.jp\0koshigaya.saitama.jp\0""123website.nl\0affinitylottery.org.uk\0" -"dvr\0" -"recife.br\0" -"tjmaxx\0" -"edu.cu\0" -"edu.cv\0" -"edu.cw\0" -"international\0" -"pagefrontapp.com\0" -"matsukawa.nagano.jp\0" -"edu.dm\0" -"sowa.ibaraki.jp\0tysv\xc3\xa6r.no\0" -"edu.do\0" -"matsushima.miyagi.jp\0" -"mt.us\0nd.us\0" -"edu.ec\0anan.nagano.jp\0*.rss.my.id\0" -"oe.yamagata.jp\0" -"edu.ee\0" -"edu.eg\0cog.mi.us\0" -"airtel\0" -"edu.dz\0andriabarlettatrani.it\0likes-pie.com\0" -"radom.pl\0" -"wakasa.fukui.jp\0" -"edu.es\0lanbib.se\0gdynia.pl\0" -"edu.et\0" -"sauherad.no\0" -"\xe7\xb6\xb2\xe7\xbb\x9c.hk\0" -"kouhoku.saga.jp\0mi.th\0industries\0""123website.lu\0" -"bar.pro\0k12.tx.us\0" -"warmia.pl\0eastasia.azurestaticapps.net\0" -"edu.fm\0" -"schmidt\0" -"vestre-toten.no\0" -"andoy.no\0" -"edu.gd\0azumino.nagano.jp\0" -"edu.ge\0gifts\0" -"stada\0fool.jp\0" -"edu.gh\0ogose.saitama.jp\0" -"edu.gi\0yashiro.hyogo.jp\0kunohe.iwate.jp\0circle\0vfs.cloud9.ca-central-1.amazonaws.com\0" -"broker\0" -"edu.gl\0fukushima.hokkaido.jp\0" -"edu.gn\0" -"is-very-bad.org\0j.scaleforce.com.cy\0*.s5y.io\0" -"edu.gp\0ddns.net\0" -"numata.hokkaido.jp\0" -"edu.gr\0ravpage.co.il\0" -"mi.us\0" -"edu.gt\0chungbuk.kr\0" -"edu.gu\0naha.okinawa.jp\0donna.no\0" -"telebit.app\0" -"lerdal.no\0" -"edu.gy\0from-ri.com\0" -"resto.bj\0" -"edu.hk\0" -"eco.bj\0gr.eu.org\0" -"ntr.br\0kawaba.gunma.jp\0boehringer\0" -"edu.hn\0" -"community\0framer.wiki\0" -"nakadomari.aomori.jp\0" -"v.bg\0" -"higashi.fukuoka.jp\0" -"eco.br\0edu.ht\0chicappa.jp\0" -"bielawa.pl\0" -"theshop.jp\0" -"cn-northwest-1.eb.amazonaws.com.cn\0" -"toyosato.shiga.jp\0""123minsida.se\0ivory.ne.jp\0" -"pub.instances.scw.cloud\0" -"wlocl.pl\0" -"edu.in\0k12.il.us\0lib.vi.us\0" -"gildeskal.no\0" -"edu.iq\0pupu.jp\0" -"nanae.hokkaido.jp\0" -"edu.is\0miyazu.kyoto.jp\0hamatama.saga.jp\0" -"edu.it\0is-into-games.com\0" -"iwakuni.yamaguchi.jp\0" -"cc.or.us\0" -"shimosuwa.nagano.jp\0" -"s3.dualstack.ca-central-1.amazonaws.com\0" -"!www.ck\0cya.gg\0" -"izumiotsu.osaka.jp\0" -"uk.in\0edu.jo\0ilawa.pl\0" -"empresa.bo\0" -"nsw.au\0" -"pila.pl\0" -"krakow.pl\0" -"gs.nl.no\0edgekey-staging.net\0" -"hl.cn\0wpdevcloud.com\0" -"gangwon.kr\0" -"ishikawa.jp\0edu.kg\0" -"gjemnes.no\0politie\0" -"geo.br\0macapa.br\0kasugai.aichi.jp\0edu.ki\0" -"\xc3\xb8yer.no\0carrd.co\0barsy.info\0" -"supabase.net\0" -"edu.km\0" -"edu.kn\0" -"epson\0" -"edu.kp\0" -"ichiba.tokushima.jp\0edu.la\0" -"k.bg\0edu.lb\0authgearapps.com\0" -"edu.lc\0qualifioapp.com\0" -"edu.kw\0" -"s3-website.us-east-2.amazonaws.com\0uk.kg\0" -"edu.ky\0" -"edu.kz\0" -"edu.lk\0" -"levanger.no\0" -"hirono.fukushima.jp\0rivne.ua\0" -"odate.akita.jp\0vf.no\0" -"map.fastlylb.net\0" -"khplay.nl\0" -"edu.lr\0\xd8\xa7\xd9\x8a\xd8\xb1\xd8\xa7\xd9\x86\0travelersinsurance\0" -"edu.ls\0ks.ua\0from-nm.com\0" -"moonscale.net\0" -"togitsu.nagasaki.jp\0edu.me\0" -"edu.lv\0bamble.no\0" -"edu.mg\0" -"edu.ly\0" -"edu.mk\0jondal.no\0" -"shakotan.hokkaido.jp\0edu.ml\0is-very-sweet.org\0" -"osakikamijima.hiroshima.jp\0" -"edu.mn\0" -"edu.mo\0" -"sekd1.beebyteapp.io\0" -"koori.fukushima.jp\0bib.ve\0" -"edu.ms\0" -"economia.bo\0sannohe.aomori.jp\0edu.mt\0" -"ks.us\0" -"ha.cn\0tp.it\0kurashiki.okayama.jp\0edu.mv\0" -"edu.mw\0edu.ng\0" -"edu.mx\0" -"edu.my\0edu.ni\0" -"edu.mz\0" -"paas.beebyte.io\0" -"kitahata.saga.jp\0fan\0school\0" -"grainger\0" -"olawa.pl\0" -"\xd0\xba\xd0\xbe\xd0\xbc.\xd1\x80\xd1\x83\xd1\x81\0" -"edu.nr\0independent-inquest.uk\0" -"kamikawa.saitama.jp\0" -"citadel\0jambyl.su\0" -"123website.be\0" -"*.beget.app\0azure-mobile.net\0" -"roan.no\0tsk.tr\0" -"dynamic-dns.info\0" -"okawa.kochi.jp\0edu.om\0clinic\0dyndns-at-home.com\0" -"tokai.ibaraki.jp\0" -"isshiki.aichi.jp\0sogndal.no\0from-la.net\0" -"okazaki.aichi.jp\0edu.pa\0" -"shimoichi.nara.jp\0kh.ua\0" -"chungnam.kr\0edu.pe\0" -"edu.pf\0saarland\0" -"otaru.hokkaido.jp\0even\xc3\xa1\xc5\xa1\xc5\xa1i.no\0" -"edu.ph\0" -"meiwa.mie.jp\0edu.pk\0""123website.ch\0" -"edu.pl\0" -"\xe7\xa6\x8f\xe5\xb3\xb6.jp\0dyndns.dappnode.io\0" -"edu.pn\0" -"pordenone.it\0esq\0" -"civilaviation.aero\0tecnologia.bo\0shikama.miyagi.jp\0edu.qa\0" -"edu.pr\0wa.us\0target\0" -"mukawa.hokkaido.jp\0edu.ps\0ap-northeast-1.elasticbeanstalk.com\0" -"edu.pt\0k8s.pl-waw.scw.cloud\0" -"maringa.br\0matsuno.ehime.jp\0x0.com\0" -"odessa.ua\0" -"te.it\0biev\xc3\xa1t.no\0" -"iwamizawa.hokkaido.jp\0xerox\0" -"edu.py\0" -"fjaler.no\0" -"ogori.fukuoka.jp\0nanjo.okinawa.jp\0" -"\xe0\xae\x87\xe0\xae\xa8\xe0\xaf\x8d\xe0\xae\xa4\xe0\xae\xbf\xe0\xae\xaf\xe0\xae\xbe\0richardli\0" -"landrover\0" -"chernihiv.ua\0" -"ureshino.mie.jp\0" -"gonna.jp\0lolitapunk.jp\0" -"toride.ibaraki.jp\0" -"is-lost.org\0" -"sakura\0" -"cloudycluster.net\0" -"shintomi.miyazaki.jp\0lexus\0groks-this.info\0" -"kuromatsunai.hokkaido.jp\0" -"edu.sa\0eus\0villas\0" -"edu.sb\0" -"joyo.kyoto.jp\0matsubara.osaka.jp\0edu.rs\0edu.sc\0" -"bearalv\xc3\xa1hki.no\0edu.sd\0" -"plo.ps\0mobi.tt\0\xe0\xb2\xad\xe0\xb2\xbe\xe0\xb2\xb0\xe0\xb2\xa4\0edu.ru\0" -"kawagoe.saitama.jp\0" -"skjak.no\0edu.sg\0" -"wif.gov.pl\0" -"takko.aomori.jp\0chat\0" -"malvik.no\0mobi.tz\0" -"trentinoa-adige.it\0bando.ibaraki.jp\0edu.sl\0" -"sarpsborg.no\0" -"edu.sn\0" -"edu.so\0" -"ooshika.nagano.jp\0amsterdam\0onavstack.net\0dscloud.mobi\0" -"stalowa-wola.pl\0\xe4\xbc\x81\xe4\xb8\x9a\0" -"edu.ss\0" -"\xe6\xbb\x8b\xe8\xb3\x80.jp\0edu.st\0lovesick.jp\0" -"yono.saitama.jp\0edu.sv\0it1.jenv-aruba.cloud\0" -"sabae.fukui.jp\0" -"khakassia.su\0" -"edu.sy\0" -"edu.tj\0uk0.bigv.io\0" -"lomza.pl\0servebbs.org\0" -"sites.static.land\0" -"edu.tm\0vfs.cloud9.ap-east-1.amazonaws.com\0" -"edu.to\0boy.jp\0" -"navigation.aero\0edu.ua\0" -"edu.tr\0nalchik.ru\0" -"edu.tt\0linkyard.cloud\0" -"groundhandling.aero\0edu.tw\0*.dev.adobeaemcloud.com\0dyndns-wiki.com\0rackmaze.com\0" -"square7.de\0" -"\xd7\x9e\xd7\x9e\xd7\xa9\xd7\x9c.\xd7\x99\xd7\xa9\xd7\xa8\xd7\x90\xd7\x9c\0kawaue.gifu.jp\0s3.dualstack.ap-northeast-1.amazonaws.com\0" -"nord-aurdal.no\0" -"\xe7\xbb\x84\xe7\xbb\x87.hk\0" -"komforb.se\0" -"is-a-democrat.com\0" -"takasago.hyogo.jp\0" -"masoy.no\0nalchik.su\0" -"edu.vc\0" -"emr.it\0" -"edu.ve\0" -"hl.no\0draydns.de\0" -"edu.uy\0" -"myeffect.net\0" -"navuotna.no\0" -"uonuma.niigata.jp\0no-ip.info\0" -"servers.run\0plesk.page\0" -"edu.vn\0" -"us.eu.org\0" -"tula.su\0" -"fit\0ro.im\0" -"wnext.app\0" -"edu.vu\0forgot.his.name\0" -"is-not-certified.com\0" -"belluno.it\0" -"ro.it\0" -"hornindal.no\0" -"togakushi.nagano.jp\0" -"ichikawa.chiba.jp\0" -"tajimi.gifu.jp\0" -"ando.nara.jp\0kuki.saitama.jp\0loten.no\0" -"curv.dev\0" -"mishima.shizuoka.jp\0" -"mobi.na\0swiebodzin.pl\0" -"edu.ws\0" -"booking\0" -"imamat\0" -"mobi.ng\0" -"lavagis.no\0square7.ch\0" -"green\0abkhazia.su\0""0e.vc\0" -"shibukawa.gunma.jp\0x0.to\0" -"kainan.tokushima.jp\0weir\0" -"wa.edu.au\0unusualperson.com\0" -"001www.com\0" -"edu.ye\0" -"kuriyama.hokkaido.jp\0" -"ha.no\0" -"inashiki.ibaraki.jp\0" -"software\0" -"tamano.okayama.jp\0" -"uri.arpa\0" -"drud.io\0" -"abudhabi\0" -"vfs.cloud9.us-east-2.amazonaws.com\0" -"lego\0" -"edu.za\0" -"ome.tokyo.jp\0" -"kaneyama.yamagata.jp\0" -"naoshima.kagawa.jp\0" -"takaoka.toyama.jp\0" -"fly\0" -"\xd5\xb0\xd5\xa1\xd5\xb5\0" -"ikeda.nagano.jp\0vegarshei.no\0lefrak\0" -"kill.jp\0" -"edu.zm\0" -"modum.no\0" -"bc.platform.sh\0" -"pvt.k12.ma.us\0" -"4.bg\0" -"liguria.it\0notogawa.shiga.jp\0ny-2.paas.massivegrid.net\0mazeplay.com\0" -"v.ua\0" -"java\0mo-siemens.io\0" -"bolzano.it\0\xd8\xa7\xdb\x8c\xd8\xb1\xd8\xa7\xd9\x86\0" -"te.ua\0" -"bmoattachments.org\0" -"dyndns-work.com\0" -"kitakata.fukushima.jp\0n\xc3\xa6r\xc3\xb8y.no\0cc.wi.us\0" -"cloudaccess.net\0" -"foo\0" -"k.se\0play\0" -"soja.okayama.jp\0zgora.pl\0solar\0scrapping.cc\0" -"graphox.us\0doomdns.org\0""4lima.de\0" -"himeji.hyogo.jp\0aga.niigata.jp\0" -"mobi.ke\0fox\0" -"friulivenezia-giulia.it\0amakusa.kumamoto.jp\0skiptvet.no\0" -"yamato.kanagawa.jp\0" -"ar.com\0" -"hatogaya.saitama.jp\0" -"bukhara.su\0collegefan.org\0" -"co.ae\0jaguar\0" -"mg.leg.br\0" -"co.ag\0hurum.no\0" -"gs.svalbard.no\0hotel.tz\0" -"gal\0" -"co.am\0" -"co.ao\0inazawa.aichi.jp\0bjerkreim.no\0" -"vibovalentia.it\0tsukui.kanagawa.jp\0gap\0" -"emerck\0" -"co.bb\0" -"swidnik.pl\0" -"co.at\0v\xc3\xa5g\xc3\xa5.no\0""4lima.at\0" -"for-the.biz\0" -"keliweb.cloud\0" -"co.bi\0suginami.tokyo.jp\0gay\0jc.neen.it\0" -"co.bj\0tarui.gifu.jp\0leclerc\0" -"amusement.aero\0frl\0" -"discordsez.com\0" -"hichiso.gifu.jp\0co.bn\0" -"co.ca\0" -"it1.eur.aruba.jenv-aruba.cloud\0" -"co.bw\0penza.su\0" -"*.nagoya.jp\0misato.wakayama.jp\0theater\0""4lima.ch\0" -"co.ci\0\xe0\xac\xad\xe0\xac\xbe\xe0\xac\xb0\xe0\xac\xa4\0" -"nx.cn\0" -"co.cl\0ybo.trade\0" -"co.cm\0" -"pn.it\0" -"flakstad.no\0vuelos\0est-mon-blogueur.com\0" -"jelastic.tsukaeru.net\0" -"co.cr\0" -"financial\0" -"co.cz\0" -"co.dk\0" -"airtraffic.aero\0gdn\0" -"trentins\xc3\xbc""d-tirol.it\0" -"\xc3\xa1laheadju.no\0" -"gea\0" -"ftr\0" -"\xe5\x8d\x83\xe8\x91\x89.jp\0" -"k12.ok.us\0" -"nico\0" -"ohkura.yamagata.jp\0properties\0" -"hayashima.okayama.jp\0lib.pa.us\0" -"twmail.cc\0" -"iizuna.nagano.jp\0" -"\xe5\xb2\xa1\xe5\xb1\xb1.jp\0krym.ua\0\xd8\xa7\xd9\x84\xd9\x8a\xd9\x85\xd9\x86\0fun\0" -"fukuchiyama.kyoto.jp\0g\xc3\xa1ivuotna.no\0" -"rauma.no\0" -"ishikari.hokkaido.jp\0" -"\xe1\x83\x92\xe1\x83\x94\0uber.space\0" -"us.com\0pythonanywhere.com\0" -"oshima.yamaguchi.jp\0" -"izumi.kagoshima.jp\0" -"gs.tm.no\0vindafjord.no\0" -"nm.cn\0hyogo.jp\0" -"ichinomiya.aichi.jp\0" -"pc.it\0" -"alaheadju.no\0" -"debian.net\0" -"ichikawamisato.yamanashi.jp\0" -"cz.it\0dyn-ip24.de\0" -"co.gg\0" -"unnan.shimane.jp\0" -"co.gl\0\xd8\xa7\xd9\x84\xd8\xb3\xd8\xb9\xd9\x88\xd8\xaf\xdb\x8c\xd8\xa9\0" -"\xe0\xaa\xad\xe0\xaa\xbe\xe0\xaa\xb0\xe0\xaa\xa4\0*.transurl.be\0" -"realty\0" -"*.yokohama.jp\0shingo.aomori.jp\0" -"akamaiedge-staging.net\0" -"genoa.it\0iizuka.fukuoka.jp\0bandai.fukushima.jp\0" -"v\xc3\xa5gan.no\0" -"translate.goog\0" -"co.gy\0" -"hotel.lk\0" -"profesional.bo\0yk.ca\0hostyhosting.io\0" -"shishikui.tokushima.jp\0cc.tx.us\0lib.de.us\0" -"ikawa.akita.jp\0" -"nb.ca\0" -"gold\0" -"aure.no\0mazowsze.pl\0golf\0drud.us\0" -"co.id\0l-o-g-i-n.de\0" -"co.hu\0" -"sarufutsu.hokkaido.jp\0select\0" -"americanfamily\0" -"fyi\0room\0gotdns.ch\0" -"\xe9\xab\x98\xe7\x9f\xa5.jp\0higashihiroshima.hiroshima.jp\0joetsu.niigata.jp\0" -"co.il\0" -"co.im\0" -"co.in\0" -"desa.id\0" -"co.ir\0" -"takagi.nagano.jp\0" -"co.it\0kushima.miyazaki.jp\0" -"co.je\0" -"shintoku.hokkaido.jp\0juegos\0" -"etc.br\0" -"\xc3\xa5lg\xc3\xa5rd.no\0\xe5\xb9\xbf\xe4\xb8\x9c\0" -"co.jp\0" -"ce.gov.br\0" -"easypanel.app\0" -"aero\0" -"uchihara.ibaraki.jp\0" -"soc.dz\0co.ke\0" -"drammen.no\0k12.me.us\0" -"sicily.it\0" -"yakage.okayama.jp\0" -"reggioemilia.it\0" -"kv\xc3\xa6""fjord.no\0" -"friuli-v-giulia.it\0kakuda.miyagi.jp\0snoasa.no\0" -"tokamachi.niigata.jp\0fr.eu.org\0" -"s3-fips-us-gov-west-1.amazonaws.com\0*.transurl.eu\0" -"askvoll.no\0" -"nikaho.akita.jp\0" -"co.kr\0cc.id.us\0serveexchange.com\0" -"co.lc\0" -"campinas.br\0goog\0" -"\xe0\xa8\xad\xe0\xa8\xbe\xe0\xa8\xb0\xe0\xa8\xa4\0gle\0jele.io\0" -"fukuyama.hiroshima.jp\0r\xc3\xa1hkker\xc3\xa1vju.no\0" -"bungotakada.oita.jp\0ostroda.pl\0" -"from-in.com\0" -"nike\0" -"nowtv\0" -"yuza.yamagata.jp\0ninja\0" -"kaizuka.osaka.jp\0co.ma\0" -"fet.no\0s3-ca-central-1.amazonaws.com\0" -"co.ls\0" -"hotel.hu\0" -"bt.it\0co.me\0" -"co.mg\0pc.pl\0" -"frenchkiss.jp\0" -"ac.ae\0sicilia.it\0agano.niigata.jp\0" -"vevelstad.no\0" -"gmo\0" -"sakyo.kyoto.jp\0filegear-gb.me\0telebit.io\0" -"co.na\0" -"izumisano.osaka.jp\0" -"smile\0" -"co.mu\0lelux.site\0dyn-vpn.de\0" -"co.mw\0kharkiv.ua\0" -"ac.at\0gmx\0" -"ac.be\0konan.aichi.jp\0nayoro.hokkaido.jp\0co.ni\0" -"co.mz\0\xe5\xa4\xa9\xe4\xb8\xbb\xe6\x95\x99\0" -"mito.ibaraki.jp\0nesna.no\0" -"co.nl\0myphotos.cc\0ybo.science\0" -"from-ct.com\0" -"presse.km\0vossevangen.no\0" -"co.no\0" -"messina.it\0\xc3\xa5krehamn.no\0nysa.pl\0flights\0" -"sorocaba.br\0jessheim.no\0" -"cc.hi.us\0my-vigor.de\0" -"matsumoto.kagoshima.jp\0" -"co.nz\0" -"onred.one\0spdns.org\0" -"ac.ci\0tsuno.miyazaki.jp\0gs.rl.no\0co.om\0" -"tonaki.okinawa.jp\0" -"miyagi.jp\0goo\0" -"kl\xc3\xa6""bu.no\0gop\0\xeb\x8b\xb7\xec\xbb\xb4\0" -"dentist\0" -"ac.cn\0quest\0" -"parachuting.aero\0got\0" -"kamifurano.hokkaido.jp\0" -"ac.cr\0gov\0bi.it\0" -"brasilia.me\0" -"uzhgorod.ua\0" -"vicenza.it\0" -"gausdal.no\0\xe0\xa6\xad\xe0\xa6\xbe\xe0\xa6\xb0\xe0\xa6\xa4\0" -"co.pl\0" -"ac.cy\0presse.ml\0marriott\0" -"minakami.gunma.jp\0kita.kyoto.jp\0co.pn\0" -"setagaya.tokyo.jp\0" -"bitter.jp\0" -"fuel.aero\0altoadige.it\0toyokawa.aichi.jp\0co.pw\0" -"kagamino.okayama.jp\0" -"ouda.nara.jp\0" -"lib.nm.us\0" -"redumbrella\0" -"trentinoaltoadige.it\0kerrylogistics\0" -"taxi.br\0" -"andria-barletta-trani.it\0" -"soc.lk\0" -"tech.orange\0" -"rep.br\0" -"austevoll.no\0nordkapp.no\0kids.us\0bounceme.net\0" -"ac.fj\0" -"ostroleka.pl\0hbo\0co.ro\0" -"paris\0here-for-more.info\0" -"kosher\0" -"co.rs\0airkitapps.eu\0" -"miyawaka.fukuoka.jp\0mayfirst.org\0" -"is-a-therapist.com\0" -"an.it\0co.rw\0" -"fr-par-1.baremetal.scw.cloud\0" -"far.br\0\xd7\x99\xd7\xa9\xd7\xa8\xd7\x90\xd7\x9c\0miyake.nara.jp\0" -"plus\0" -"ryokami.saitama.jp\0shopitsite.com\0thingdustdata.com\0" -"mo-i-rana.no\0" -"ac.gn\0moss.no\0" -"inagi.tokyo.jp\0*.stolos.io\0" -"co.st\0" -"enterprises\0" -"platterp.us\0*.transurl.nl\0" -"yandexcloud.net\0" -"co.th\0" -"instantcloud.cn\0" -"co.sz\0co.tj\0juniper\0" -"actor\0" -"mr.no\0vanylven.no\0co.tm\0" -"fujimi.saitama.jp\0" -"gifu.jp\0" -"slg.br\0\xe0\xa4\xad\xe0\xa4\xbe\xe0\xa4\xb0\xe0\xa4\xa4\0co.ua\0" -"osakasayama.osaka.jp\0co.tt\0" -"app.lmpm.com\0" -"\xd8\xa7\xd9\x84\xd8\xb3\xd8\xb9\xd9\x88\xd8\xaf\xdb\x8c\xdb\x83\0broke-it.net\0" -"co.ug\0abogado\0" -"ac.id\0" -"la-spezia.it\0engerdal.no\0co.tz\0" -"co.uk\0" -"sosnowiec.pl\0" -"tenkawa.nara.jp\0folldal.no\0" -"dvrdns.org\0" -"oh.us\0" -"ac.il\0uchinada.ishikawa.jp\0today\0dyn.home-webserver.de\0serveminecraft.net\0" -"ac.im\0" -"ac.in\0mypi.co\0" -"co.us\0" -"co.ve\0" -"ac.ir\0chrome\0" -"mugi.tokushima.jp\0mikawa.yamagata.jp\0" -"museum\0zgorzelec.pl\0co.vi\0" -"oppegard.no\0co.uz\0" -"*.webpaas.ovh.net\0" -"kiyama.saga.jp\0" -"clan.rip\0" -"komae.tokyo.jp\0s3-external-1.amazonaws.com\0" -"narvik.no\0" -"filegear-ie.me\0" -"ac.jp\0" -"k12.ut.us\0" -"friulive-giulia.it\0" -"psse.gov.pl\0jelastic.regruhosting.ru\0" -"kanie.aichi.jp\0ac.ke\0" -"catering.aero\0theatre\0mcpe.me\0" -"koga.ibaraki.jp\0localzone.xyz\0" -"lib.ks.us\0" -"off.ai\0" -"*.compute.estate\0typedream.app\0" -"aikawa.kanagawa.jp\0ac.kr\0" -"lgbt\0icurus.jp\0" -"arakawa.saitama.jp\0" -"izumizaki.fukushima.jp\0" -"from-ks.com\0" -"monzaebrianza.it\0" -"kvalsund.no\0" -"\xe7\xb5\x84\xe7\xb9\x94.tw\0" -"ac.lk\0" -"valle-d-aosta.it\0nishihara.okinawa.jp\0nm.us\0citi\0" -"nabari.mie.jp\0" -"nanyo.yamagata.jp\0" -"ac.ma\0x443.pw\0" -"sakegawa.yamagata.jp\0ac.ls\0" -"ac.me\0" -"tsuwano.shimane.jp\0" -"country\0" -"\xe5\xba\x83\xe5\xb3\xb6.jp\0" -"shopware.store\0" -"tokashiki.okinawa.jp\0city\0" -"\xd8\xaa\xd9\x88\xd9\x86\xd8\xb3\0co.za\0mc.eu.org\0ch.trendhosting.cloud\0" -"hiv\0codespot.com\0" -"ac.mu\0" -"ac.mw\0" -"\xd8\xa7\xd9\x84\xd8\xa7\xd8\xb1\xd8\xaf\xd9\x86\0" -"ac.ni\0co.zm\0" -"ac.mz\0" -"narashino.chiba.jp\0*.ocp.customer-oci.com\0" -"clicketcloud.com\0" -"itau\0git-pages.rit.edu\0" -"chihayaakasaka.osaka.jp\0rep.kp\0" -"co.zw\0" -"buzen.fukuoka.jp\0westus2.azurestaticapps.net\0" -"abruzzo.it\0" -"homeoffice.gov.uk\0" -"noda.chiba.jp\0ac.nz\0ybo.faith\0" -"snowflake.app\0" -"from-ca.com\0lt.eu.org\0" -"agematsu.nagano.jp\0m\xc3\xa1latvuopmi.no\0" -"maebashi.gunma.jp\0hacca.jp\0" -"otari.nagano.jp\0hkt\0" -"dellogliastra.it\0ac.pa\0ent.platform.sh\0" -"stcgroup\0" -"uozu.toyama.jp\0" -"servegame.com\0" -"tuxfamily.org\0" -"barsy.co.uk\0" -"bet.ar\0" -"wajiki.tokushima.jp\0" -"ac.pr\0" -"\xd7\xa6\xd7\x94\xd7\x9c.\xd7\x99\xd7\xa9\xd7\xa8\xd7\x90\xd7\x9c\0s\xc3\xb8r-varanger.no\0" -"!city.kobe.jp\0" -"loppa.no\0podhale.pl\0" -"kamagaya.chiba.jp\0" -"teo.br\0" -"parts\0" -"finance\0" -"zushi.kanagawa.jp\0tunes\0" -"bar1.net\0" -"party\0" -"mod.gi\0munakata.fukuoka.jp\0helsinki\0" -"gratis\0" -"hagi.yamaguchi.jp\0" -"tromso.no\0" -"moo.jp\0" -"from-tn.com\0rackmaze.net\0" -"go.gov.br\0" -"eiheiji.fukui.jp\0" -"construction\0" -"ac.rs\0" -"ac.se\0ac.ru\0" -"shimoji.okinawa.jp\0tottori.tottori.jp\0" -"ac.rw\0" -"is-an-actor.com\0mytabit.co.il\0" -"t.bg\0" -"drobak.no\0safe\0" -"minami.tokushima.jp\0" -"hot\0studio\0" -"zachpomor.pl\0how\0" -"rieti.it\0" -"is-a-student.com\0" -"arida.wakayama.jp\0ac.th\0pya.jp\0" -"kawai.iwate.jp\0" -"uw.gov.pl\0ac.sz\0ac.tj\0" -"tc.br\0" +"media.pl\0witd.gov.pl\0" +"b\xc3\xa1l\xc3\xa1t.no\0marker.no\0naamesjevuemie.no\0verran.no\0" +"ise.mie.jp\0chijiwa.nagasaki.jp\0tamano.okayama.jp\0hizen.saga.jp\0flop.jp\0" +"fnd.br\0se.gov.br\0" +"in.rs\0" +"whm.nl-ams.scw.cloud\0" +"hotel.hu\0b.se\0nohost.me\0" +"\xd0\xb4\xd0\xb5\xd1\x82\xd0\xb8\0bc.platform.sh\0" +"s3-ap-northeast-2.amazonaws.com\0siiites.com\0cloudflare-ipfs.com\0app.render.com\0" +"lolipop.io\0" +"graphics\0pics\0watches\0" +"abruzzo.it\0mantova.it\0build\0" +"isa-geek.org\0at.eu.org\0" +"in.th\0" +"rzeszow.pl\0" +"research.aero\0alvdal.no\0hjartdal.no\0voss.no\0voagat.no\0" +"\xe9\xa6\x99\xe5\xb7\x9d.jp\0shimofusa.chiba.jp\0ikeda.hokkaido.jp\0kanonji.kagawa.jp\0pigboat.jp\0opal.ne.jp\0" +"in.ua\0" "drr.ac\0" -"ecommerce-shop.pl\0" -"ide.kyoto.jp\0yoita.niigata.jp\0" -"perugia.it\0soeda.fukuoka.jp\0ac.ug\0" -"ac.tz\0*.lcl.dev\0" -"ac.uk\0" -"j\xc3\xb8lster.no\0nhlfan.net\0" -"gz.cn\0e12.ve\0" -"sakuragawa.ibaraki.jp\0s3.dualstack.sa-east-1.amazonaws.com\0" -"soka.saitama.jp\0kinder\0" -"okagaki.fukuoka.jp\0miniserver.com\0srht.site\0" -"*.kitakyushu.jp\0nakatombetsu.hokkaido.jp\0latino\0instances.spawn.cc\0" -"ikoma.nara.jp\0ibm\0" -"ikusaka.nagano.jp\0trysil.no\0" -"i.bg\0baidu\0" -"ac.vn\0" -"us-east-2.elasticbeanstalk.com\0" -"sblo.jp\0" -"ice\0" -"yoshioka.gunma.jp\0campaign.gov.uk\0" -"app.banzaicloud.io\0*.paywhirl.com\0" -"kapsi.fi\0" -"aip.ee\0hyuga.miyazaki.jp\0monash\0from-pr.com\0" -"tabuse.yamaguchi.jp\0" -"tmall\0" -"pippu.hokkaido.jp\0" -"latina.it\0" -"training\0williamhill\0" -"ginoza.okinawa.jp\0icu\0" -"suifu.ibaraki.jp\0" -"manno.kagawa.jp\0geisei.kochi.jp\0misaki.okayama.jp\0" -"in-butter.de\0" -"cranky.jp\0" -"r\xc3\xa1isa.no\0" -"associates\0" -"go.ci\0cam.it\0" -"sh.cn\0okinawa.jp\0" -"s3.us-east-2.amazonaws.com\0" -"andriatranibarletta.it\0otaki.chiba.jp\0yoka.hyogo.jp\0la.us\0" -"tn.it\0" -"taiki.mie.jp\0\xe5\x9c\xa8\xe7\xba\xbf\0" -"flop.jp\0" -"go.cr\0" -"vestre-slidre.no\0" -"caravan\0" -"kurume.fukuoka.jp\0" -"r\xc3\xb8yken.no\0" -"emp.br\0udono.mie.jp\0sale\0" -"kerryhotels\0" -"l\xc3\xb8""dingen.no\0" -"ac.za\0" -"shimokitayama.nara.jp\0aktyubinsk.su\0" -"balsan-suedtirol.it\0" -"presse.ci\0" -"wellbeingzone.eu\0" -"yurihonjo.akita.jp\0" -"ifm\0" -"lind\xc3\xa5s.no\0apartments\0" -"hair\0jpn.org\0" -"insurance.aero\0*.cloud.metacentrum.cz\0ts.net\0" -"minamiminowa.nagano.jp\0ac.zm\0" -"tr\xc3\xb8gstad.no\0" -"\xe5\x85\xac\xe5\x8f\xb8.cn\0cc.nj.us\0" -"\xe5\xa8\xb1\xe4\xb9\x90\0" -"nakano.nagano.jp\0" -"s3-ap-southeast-1.amazonaws.com\0" -"cc.ca.us\0ac.zw\0" -"mods.jp\0httpbin.org\0" -"museum.tt\0" -"kannami.shizuoka.jp\0ovre-eiker.no\0weeklylottery.org.uk\0" -"stuff-4-sale.org\0" -"mincom.tn\0endoftheinternet.org\0" -"\xe5\x85\xac\xe5\x8f\xb8.hk\0tube\0" -"mircloud.host\0" -"gd.cn\0ss.it\0nogi.tochigi.jp\0" -"is-a-guru.com\0" -"\xd0\xb4\xd0\xb5\xd1\x82\xd0\xb8\0" -"kindle\0" -"s3.eu-central-1.amazonaws.com\0" -"*.alces.network\0" +"functions.fnc.fr-par.scw.cloud\0" +"abbvie\0tushu\0" +"amfam\0" +"in.us\0k12.va.us\0" +"bar1.net\0" +"nt.au\0" +"genting\0ae.org\0ybo.review\0" +"bzh\0" +"cistron.nl\0" +"dyr\xc3\xb8y.no\0hyllestad.no\0melhus.no\0somna.no\0m\xc3\xa1tta-v\xc3\xa1rjjat.no\0v-info.info\0" +"akita.akita.jp\0nikaho.akita.jp\0yukuhashi.fukuoka.jp\0annaka.gunma.jp\0aibetsu.hokkaido.jp\0pippu.hokkaido.jp\0tomakomai.hokkaido.jp\0urakawa.hokkaido.jp\0natori.miyagi.jp\0tawaramoto.nara.jp\0uruma.okinawa.jp\0nanbu.tottori.jp\0typedream.app\0" +"nt.ca\0" +"am.gov.br\0" +"travelersinsurance\0" +"per.sg\0" +"verisign\0" +"jeonbuk.kr\0" +"lib.ok.us\0" +"pesarourbino.it\0blackbaudcdn.net\0homelinux.net\0" +"able\0*.compute.estate\0exnet.su\0mein-iserv.de\0" +"sa.gov.pl\0" +"gjovik.no\0mel\xc3\xb8y.no\0sk\xc3\xa5nland.no\0acct.pro\0" +"noheji.aomori.jp\0shisui.chiba.jp\0ginan.gifu.jp\0hiji.oita.jp\0" +"clinique\0" +"\xd8\xa7\xd9\x8a\xd8\xb1\xd8\xa7\xd9\x86\0" +"\xd8\xa8\xd8\xa7\xd8\xb1\xd8\xaa\0" +"bradesco\0" +"k12.mi.us\0" +"fr.it\0" +"autocode.dev\0" +"in-vpn.org\0" +"\xe4\xba\x9a\xe9\xa9\xac\xe9\x80\x8a\0" +"cern\0" +"fedje.no\0gratangen.no\0rennesoy.no\0" +"saitama.jp\0\xe6\x84\x9b\xe5\xaa\x9b.jp\0anjo.aichi.jp\0kasugai.aichi.jp\0shinto.gunma.jp\0mombetsu.hokkaido.jp\0shoo.okayama.jp\0kimino.wakayama.jp\0mikawa.yamagata.jp\0boy.jp\0candypop.jp\0" +"alp1.ae.flow.ch\0" +"grocery\0property\0" +"com\0qualifioapp.com\0" +"basicserver.io\0" +"cpa\0" +"lib.mt.us\0lib.nd.us\0lib.wi.us\0glass\0news\0" +"trentinosudtirol.it\0akamaiedge-staging.net\0" +"collegefan.org\0" +"restaurant.bj\0" +"umig.gov.pl\0" +"sande.vestfold.no\0" +"\xe6\xb2\x96\xe7\xb8\x84.jp\0chikuzen.fukuoka.jp\0kaho.fukuoka.jp\0hiratsuka.kanagawa.jp\0gushikami.okinawa.jp\0misato.shimane.jp\0aizumi.tokushima.jp\0" +"ap.gov.br\0" +"coop.ht\0dad\0next\0it1.eur.aruba.jenv-aruba.cloud\0" +"\xd8\xa7\xdb\x8c\xd8\xb1\xd8\xa7\xd9\x86\0" +"vfs.cloud9.me-south-1.amazonaws.com\0" +"coop.in\0*.code.run\0" +"coop.ar\0" +"k12.ca.us\0\xd0\xb1\xd0\xb3\0" +"lazio.it\0taa.it\0fg.it\0napoli.it\0*.hosting.ovh.net\0" +"bib.ve\0" +"ping\0" +"day\0" +"pink\0" +"ap.gov.pl\0" +"accident-prevention.aero\0\xc3\xa5mli.no\0fusa.no\0siljan.no\0eng.pro\0" +"akita.jp\0shiso.hyogo.jp\0naka.ibaraki.jp\0tonosho.kagawa.jp\0tatsuno.nagano.jp\0ishigaki.okinawa.jp\0hirakata.osaka.jp\0ina.saitama.jp\0shibuya.tokyo.jp\0cranky.jp\0" +"cloudns.asia\0" +"coop.br\0gouv.fr\0" +"crs\0passagens\0" +"iopsys.se\0" +"fastvps-server.com\0servep2p.com\0" +"town\0" +"redumbrella\0" +"lib.ma.us\0" +"toscana.it\0contact\0" +"opensocial.site\0" +"is-very-good.org\0" +"gon.pk\0" +"recreation.aero\0utsira.no\0" +"moriyoshi.akita.jp\0honai.ehime.jp\0nahari.kochi.jp\0hikari.yamaguchi.jp\0pecori.jp\0" +"dds\0" +"gouv.ht\0my.id\0" +"video.hu\0" +"plc.ly\0" +"independent-review.uk\0" +"ltd.co.im\0isa-geek.com\0sells-for-less.com\0impertrix.com\0" +"olayan\0" +"fresenius\0toys\0" +"laspezia.it\0vv.it\0dynv6.net\0" +"dyn.cosidns.de\0kalmykia.su\0dd-dns.de\0" +"dev\0" +"is-saved.org\0" +"gmbh\0mc.ax\0" +"shouji\0" +"pro.az\0" +"group.aero\0nt.no\0fjaler.no\0hattfjelldal.no\0" +"takko.aomori.jp\0ayase.kanagawa.jp\0kuwana.mie.jp\0taiwa.miyagi.jp\0kitaura.miyazaki.jp\0hamatama.saga.jp\0mishima.shizuoka.jp\0" +"med.br\0pro.br\0pa.leg.br\0" +"gouv.ci\0" +"buzz\0" +"*.sch.uk\0" +"onfabrica.com\0" +"\xd0\xb5\xd1\x8e\0" +"trentinos\xc3\xbc""d-tirol.it\0myfritz.net\0" +"pro.cy\0lamborghini\0" +"szczytno.pl\0dhl\0krakow.pl\0" +"rana.no\0med.pro\0\xe0\xb6\xbd\xe0\xb6\x82\xe0\xb6\x9a\xe0\xb7\x8f\0" +"yotsukaido.chiba.jp\0katsuyama.fukui.jp\0kurogi.fukuoka.jp\0sakuragawa.ibaraki.jp\0takahagi.ibaraki.jp\0tsuchiura.ibaraki.jp\0kitakata.miyazaki.jp\0bizen.okayama.jp\0aisho.shiga.jp\0mitou.yamaguchi.jp\0digick.jp\0" +"pb.leg.br\0" +"med.ec\0pro.ec\0" +"med.ee\0localhost.daplie.me\0merseine.nu\0kalmykia.ru\0" +"wphostedmail.com\0" +"s3.cn-north-1.amazonaws.com.cn\0" +"\xe6\x94\xbf\xe5\xba\x9c.\xe9\xa6\x99\xe6\xb8\xaf\0mypi.co\0" +"k12.as.us\0" +"mn.it\0tranibarlettaandria.it\0alwaysdata.net\0" +"au.eu.org\0be.eu.org\0" +"diy\0" +"pro.fj\0" +"softbank\0" +"jelenia-gora.pl\0" +"\xd0\xbe\xd0\xbd\xd0\xbb\xd0\xb0\xd0\xb9\xd0\xbd\0" +"gs.hm.no\0kopervik.no\0bajddar.no\0sande.m\xc3\xb8re-og-romsdal.no\0nt.ro\0" +"nango.fukushima.jp\0jinsekikogen.hiroshima.jp\0obama.nagasaki.jp\0" +"mus.br\0" +"s3-website-us-west-1.amazonaws.com\0discourse.team\0freebox-os.com\0freemyip.com\0pixolino.com\0" +"agric.za\0" +"monster\0" +"lib.tx.us\0tec.mi.us\0" +"homeip.net\0" +"woodside\0" +"upaas.kazteleport.kz\0" +"oke.gov.pl\0" +"hobol.no\0holmestrand.no\0kristiansund.no\0" +"rokunohe.aomori.jp\0minamiboso.chiba.jp\0kumano.hiroshima.jp\0mihara.hiroshima.jp\0miyazu.kyoto.jp\0minamiminowa.nagano.jp\0tenkawa.nara.jp\0warabi.saitama.jp\0matsue.shimane.jp\0girlfriend.jp\0" +"od.ua\0" +"deals\0" +"pro.ht\0med.ht\0" +"hlx.page\0i234.me\0" +"gitpage.si\0" +"plc.uk\0" +"airtel\0international\0" +"vfs.cloud9.eu-west-1.amazonaws.com\0outsystemscloud.com\0" +"pro.in\0up.in\0nissan\0nyc.mn\0" +"weber\0" +"k12.az.us\0" +"friulivenezia-giulia.it\0bozen-suedtirol.it\0mc.it\0" +"lasalle\0melbourne\0schulserver.de\0" +"bg.eu.org\0" +"*.bzz.dapps.earth\0" +"nissay\0" +"swiebodzin.pl\0" +"statefarm\0" +"lenvik.no\0skien.no\0skjerv\xc3\xb8y.no\0sokndal.no\0" +"namie.fukushima.jp\0kuromatsunai.hokkaido.jp\0okoppe.hokkaido.jp\0sakuho.nagano.jp\0unzen.nagasaki.jp\0dnp\0frenchkiss.jp\0" +"slz.br\0prd.fr\0" +"official.ec\0" +"dog\0" +"dattolocal.com\0" +"tj.cn\0" +"juniper\0" +"works\0" +"dot\0world\0" +"homeftp.org\0fedorainfracloud.org\0app.os.fedoraproject.org\0now-dns.org\0" +"\xe6\x95\x8e\xe8\x82\xb2.hk\0" +"akrehamn.no\0harstad.no\0law.pro\0" +"kujukuri.chiba.jp\0sannan.hyogo.jp\0yawara.ibaraki.jp\0shimoichi.nara.jp\0" +"aero.tt\0" +"chrome\0" +"med.ly\0americanfamily\0" +"plc.co.im\0jdevcloud.com\0" +"\xe5\x85\xac\xe5\x8f\xb8.cn\0" +"pro.na\0" +"sicilia.it\0veneto.it\0bulsan.it\0lecce.it\0\xd1\x80\xd1\x84\0eat\0" +"aero.mv\0pro.mv\0" +"v.bg\0" +"be.ax\0" +"\xe5\x85\xac\xe5\x8f\xb8.hk\0" +"wif.gov.pl\0" +"fl\xc3\xa5.no\0klabu.no\0mandal.no\0molde.no\0siellak.no\0" +"biratori.hokkaido.jp\0moseushi.hokkaido.jp\0okawa.kochi.jp\0ujitawara.kyoto.jp\0gokase.miyazaki.jp\0onna.okinawa.jp\0velvet.jp\0noop.app\0" +"des.br\0asso.fr\0simplesite.com.br\0" +"nov.ru\0" +"\xd8\xa7\xd9\x84\xd9\x8a\xd9\x85\xd9\x86\0" +"coop.rw\0" +"prd.km\0medecin.km\0med.om\0pro.om\0from-in.com\0from-ks.com\0" +"eco\0shiftcrypto.io\0" +"asso.gp\0" +"med.pa\0" +"nov.su\0" +"red.sv\0" +"hr.eu.org\0" +"med.pl\0" +"exchange.aero\0sk\xc3\xa1nit.no\0" +"yoro.gifu.jp\0uda.nara.jp\0sanjo.niigata.jp\0tokorozawa.saitama.jp\0" +"vinnytsia.ua\0" +"experts-comptables.fr\0pro.pr\0" +"asso.ht\0coop.tt\0" +"edu\0" +"dtv\0" +"prd.mg\0" +"uwu.ai\0" +"bplaced.com\0" +"mn.us\0" +"bergamo.it\0west1-us.cloudjiffy.net\0ddns.net\0" +"coop.mv\0" +"k.bg\0coop.mw\0altervista.org\0" +"kepno.pl\0lublin.pl\0" +"mosjoen.no\0austrheim.no\0dyroy.no\0" +"tsumagoi.gunma.jp\0nishitosa.kochi.jp\0miyazaki.miyazaki.jp\0kouhoku.saga.jp\0misasa.tottori.jp\0taira.toyama.jp\0hagi.yamaguchi.jp\0user.aseinet.ne.jp\0netgamers.jp\0" +"med.sa\0\xd1\x81\xd0\xbe\xd1\x87\xd0\xb8.\xd1\x80\xd1\x83\xd1\x81\0" +"huissier-justice.fr\0dvr\0pi.leg.br\0" +"med.sd\0" +"jogasz.hu\0" +"x443.pw\0" +"asso.ci\0" +"service.gov.uk\0" +"kr.com\0dnsalias.com\0is-a-republican.com\0appspot.com\0reservd.com\0" +"sd.cn\0gouv.sn\0" +"autos\0webspace.rocks\0" +"cloudjiffy.net\0" +"homelinux.org\0" +"pharmacy\0be.gy\0" +"sld.do\0aurskog-h\xc3\xb8land.no\0meloy.no\0barrell-of-knowledge.info\0" +"koga.fukuoka.jp\0iitate.fukushima.jp\0yawata.kyoto.jp\0kawanehon.shizuoka.jp\0yoshida.shizuoka.jp\0" +"cv.ua\0" +"pro.tt\0" +"coop.py\0" +"asso.dz\0" +"\xd7\x9e\xd7\x9e\xd7\xa9\xd7\x9c.\xd7\x99\xd7\xa9\xd7\xa8\xd7\x90\xd7\x9c\0social\0" +"getmyip.com\0familyds.com\0" +"dedyn.io\0" +"friuliveneziagiulia.it\0so.it\0" +"nsw.edu.au\0hs.zone\0in-vpn.de\0" +"hepforge.org\0" +"\xe4\xb8\xaa\xe4\xba\xba.hk\0" +"gorlice.pl\0" +"pro.vn\0" +"airline.aero\0namsos.no\0rollag.no\0ralingen.no\0stavanger.no\0vik.no\0" +"matsumoto.kagoshima.jp\0zamami.okinawa.jp\0namegawa.saitama.jp\0ujiie.tochigi.jp\0matrix.jp\0" +"anani.br\0rio.br\0" +"shop.brendly.rs\0" +"coop.km\0s3-us-east-2.amazonaws.com\0ap-northeast-2.elasticbeanstalk.com\0fastly-terrarium.com\0forgeblocks.com\0serveirc.com\0" +"chungnam.kr\0" +"cc.fl.us\0cc.ny.us\0cc.wv.us\0services\0" +"homedepot\0isa-geek.net\0" +"latrobe\0abkhazia.su\0iservschule.de\0synology-ds.de\0" +"dnsdojo.org\0" +"bolivia.bo\0midsund.no\0" +"toyota.aichi.jp\0oketo.hokkaido.jp\0shizukuishi.iwate.jp\0shintomi.miyazaki.jp\0kokonoe.oita.jp\0neyagawa.osaka.jp\0shimane.shimane.jp\0" +"ck.ua\0donetsk.ua\0" +"boats\0" +"forgot.his.name\0" +"stream\0is-a-cpa.com\0oncilla.mythic-beasts.com\0" +"gitlab.io\0" +"k12.ga.us\0" +"carbonia-iglesias.it\0chat\0market\0" +"is-very-sweet.org\0" +"attorney\0" +"br\xc3\xb8nn\xc3\xb8ysund.no\0tysv\xc3\xa6r.no\0" +"yamanashi.jp\0motosu.gifu.jp\0" +"pe.leg.br\0" +"elementor.cloud\0" +"gouv.km\0appspaceusercontent.com\0ar.com\0gentapps.com\0fentiger.mythic-beasts.com\0" +"neustar\0" +"lib.il.us\0" +"bozen.it\0comcast\0mircloud.host\0hicam.net\0" +"navoi.su\0" +"\xe4\xbc\x81\xe4\xb8\x9a\0localzone.xyz\0" +"zagan.pl\0" +"batsfjord.no\0ris\xc3\xb8r.no\0tjome.no\0" +"inzai.chiba.jp\0sanda.hyogo.jp\0shiwa.iwate.jp\0ohda.shimane.jp\0iwakuni.yamaguchi.jp\0wnext.app\0weblike.jp\0" +"km.ua\0" +"gouv.ml\0" +"mazeplay.com\0beta.bounty-full.com\0" +"fan\0" +"gv.ao\0" +"weir\0" +"gv.at\0andriatranibarletta.it\0ri.it\0vanguard\0in-vpn.net\0" +"grozny.su\0" +"marketing\0rsc.cdn77.org\0" +"demo.datacenter.fi\0" +"pinb.gov.pl\0" +"kviteseid.no\0namsskogan.no\0narvik.no\0r\xc3\xb8st.no\0vindafjord.no\0ikano\0" +"\xe5\xae\xae\xe5\x9f\x8e.jp\0numata.gunma.jp\0yabu.hyogo.jp\0tokai.ibaraki.jp\0hasama.oita.jp\0mibu.tochigi.jp\0mitaka.tokyo.jp\0arida.wakayama.jp\0kahoku.yamagata.jp\0" +"qc.ca\0" +"jdf.br\0sjc.br\0vet.br\0" +"cloudcontrolapp.com\0is-a-bookkeeper.com\0" +"lego\0" +"sld.pa\0esq\0" +"cc.ms.us\0cc.nc.us\0lib.hi.us\0\xe3\x83\x95\xe3\x82\xa1\xe3\x83\x83\xe3\x82\xb7\xe3\x83\xa7\xe3\x83\xb3\0" +"valle-aosta.it\0bolzano-altoadige.it\0" +"abudhabi\0" +"skanit.no\0" +"inazawa.aichi.jp\0abira.hokkaido.jp\0omitama.ibaraki.jp\0shibata.miyagi.jp\0matsumoto.nagano.jp\0soja.okayama.jp\0shimotsuke.tochigi.jp\0kita.tokyo.jp\0fashionstore.jp\0" +"v.ua\0" +"tel.tr\0" +"es-1.axarnet.cloud\0" +"grozny.ru\0" +"adimo.co.uk\0" +"servepics.com\0pagexl.com\0" +"tokyo\0" +"java\0" +"eus\0" +"como.it\0*.ex.ortsinfo.at\0" +"asso.re\0\xd5\xb0\xd5\xa1\xd5\xb5\0test-iserv.de\0" +"play\0iki.fi\0" +"tananger.no\0ski.no\0" +"yokoshibahikari.chiba.jp\0kawachinagano.osaka.jp\0" +"floripa.br\0medecin.fr\0" +"k.se\0" +"\xe5\x95\x86\xe6\xa5\xad.tw\0" +"*.devcdnaccesso.com\0s3-website.ca-central-1.amazonaws.com\0" +"*.compute.amazonaws.com.cn\0" +"cisco\0musician.io\0" +"forli-cesena.it\0" +"catholic.edu.au\0google\0" +"il.eu.org\0" +"j.scaleforce.com.cy\0" +"custom.metacentrum.cz\0" +"oow.gov.pl\0rzgw.gov.pl\0ostrowiec.pl\0" +"midtre-gauldal.no\0vegarshei.no\0" +"osakikamijima.hiroshima.jp\0kanoya.kagoshima.jp\0ogawa.saitama.jp\0framer.app\0noor.jp\0" +"mykolaiv.ua\0" +"port.fr\0pr.leg.br\0" +"appspacehosted.com\0builtwithdark.com\0*.digitaloceanspaces.com\0js.wpenginepowered.com\0" +"bihar.in\0capetown\0construction\0xihuan\0" +"au.ngrok.io\0" +"asso.nc\0sd.us\0k12.ne.us\0k12.vt.us\0golffan.us\0" +"cam.it\0iglesias-carbonia.it\0fit\0jls-sto2.elastx.net\0" +"4.bg\0hu.eu.org\0ie.eu.org\0" +"gs.bu.no\0osoyro.no\0aurskog-holand.no\0skodje.no\0vaapste.no\0" +"okayama.jp\0joyo.kyoto.jp\0ama.shimane.jp\0" +"amica\0" +"ce.gov.br\0" +"a\xc3\xa9roport.ci\0" +"parliament.nz\0" +"eu-west-3.elasticbeanstalk.com\0" +"xj.cn\0crown\0" +"nico\0" +"staples\0" +"bplaced.net\0homeftp.net\0" +"svn-repos.de\0" +"cloudns.biz\0" +"baseball\0nz.basketball\0" +"tromsa.no\0ullensaker.no\0" +"chosei.chiba.jp\0sodegaura.chiba.jp\0rikubetsu.hokkaido.jp\0kakuda.miyagi.jp\0shichikashuku.miyagi.jp\0iijima.nagano.jp\0hirado.nagasaki.jp\0okayama.okayama.jp\0kamimine.saga.jp\0saitama.saitama.jp\0ichikawamisato.yamanashi.jp\0" +"framer.media\0" +"fly\0" +"*.compute-1.amazonaws.com\0" +"il.us\0ri.us\0reviews\0" +"dyn-berlin.de\0" +"eu.ax\0" +"ambulance.aero\0patria.bo\0gs.st.no\0j\xc3\xb8rpeland.no\0and\xc3\xb8y.no\0hoylandet.no\0osteroy.no\0r\xc3\xb8yken.no\0tingvoll.no\0dielddanuorri.no\0" +"\xe5\xb2\x90\xe9\x98\x9c.jp\0tako.chiba.jp\0naganohara.gunma.jp\0otofuke.hokkaido.jp\0akune.kagoshima.jp\0sakyo.kyoto.jp\0kusatsu.shiga.jp\0" +"hospital\0" +"asso.km\0room\0from-ar.com\0playstation-cloud.com\0" +"yamaxun\0" +"foo\0" +"biella.it\0gold\0\xeb\x8b\xb7\xec\xbb\xb4\0buyshouses.net\0map.fastlylb.net\0iliadboxos.it\0""2.azurestaticapps.net\0pcloud.host\0" +"sochi.su\0" +"golf\0" +"fox\0" +"grajewo.pl\0malopolska.pl\0" +"k\xc3\xa5""fjord.no\0" +"fukui.jp\0ogata.akita.jp\0hanamigawa.chiba.jp\0okawa.fukuoka.jp\0tachiarai.fukuoka.jp\0aoki.nagano.jp\0naha.okinawa.jp\0settsu.osaka.jp\0fujimino.saitama.jp\0hokuto.yamanashi.jp\0" +"asso.mc\0" +"reklam.hu\0" +"gal\0" +"business.in\0" +"hzc.io\0" +"gap\0" +"bet.ar\0" +"ia.us\0k12.ct.us\0" +"alessandria.it\0isernia.it\0jls-sto3.elastx.net\0" +"blogsite.org\0" +"*.dapps.earth\0" +"ekloges.cy\0gay\0" +"test.tj\0" +"frl\0\xe5\xb9\xbf\xe4\xb8\x9c\0" +"aero\0aircraft.aero\0magazine.aero\0web.bo\0kvinnherad.no\0davvesiida.no\0vardo.no\0" +"higashi.fukushima.jp\0sanuki.kagawa.jp\0meiwa.mie.jp\0ishinomaki.miyagi.jp\0iiyama.nagano.jp\0shimosuwa.nagano.jp\0fukumitsu.toyama.jp\0" +"finance\0nike\0magnet.page\0" +"goog\0" +"j.layershift.co.uk\0" +"betainabox.com\0*.stg-builder.code.com\0" +"web.co\0" +"cc.az.us\0" +"dynvpn.de\0" +"gr.eu.org\0" +"praxi\0" +"gdn\0" +"web.do\0" +"komaki.aichi.jp\0okazaki.aichi.jp\0suzu.ishikawa.jp\0kitagawa.miyazaki.jp\0sakurai.nara.jp\0nagi.okayama.jp\0ome.tokyo.jp\0namerikawa.toyama.jp\0" +"gea\0" +"kep.tr\0ftr\0" +"\xe1\x83\x92\xe1\x83\x94\0" +"test.ru\0filegear-de.me\0" +"us-4.evennode.com\0" +"fun\0immobilien\0" +"gv.vc\0" +"fe.it\0fermo.it\0la-spezia.it\0akamai-staging.net\0" +"online\0obninsk.su\0" +"tychy.pl\0" +"fuoisku.no\0fitjar.no\0gol.no\0lavangen.no\0" +"kochi.jp\0wakkanai.hokkaido.jp\0nakamura.kochi.jp\0chikuhoku.nagano.jp\0shiraoka.saitama.jp\0" +"not.br\0users.scale.virtualcloud.com.br\0" +"ox.rs\0" +"schmidt\0" +"dynalias.com\0from-ca.com\0" +"lib.ut.us\0" +"trani-andria-barletta.it\0barefoot\0dnsdojo.net\0" +"web.gu\0" +"fredrikstad.no\0leirfjord.no\0\xc3\xb8ystre-slidre.no\0" +"mashike.hokkaido.jp\0toyo.kochi.jp\0nagasu.kumamoto.jp\0muika.niigata.jp\0taku.saga.jp\0" +"ftpaccess.cc\0" +"web.id\0museum.tt\0uk.primetel.cloud\0" +"casino.hu\0" +"\xd8\xa7\xd8\xb1\xd8\xa7\xd9\x85\xd9\x83\xd9\x88\0" +"fyi\0" +"us-3.evennode.com\0" +"web.in\0" +"uk0.bigv.io\0" +"wolterskluwer\0" +"plus\0" +"vt.it\0global.ssl.fastly.net\0" +"dvrdns.org\0spdns.org\0" +"konsulat.gov.pl\0wiih.gov.pl\0" +"amot.no\0giske.no\0s\xc3\xb8r-odal.no\0" +"\xe5\xae\xae\xe5\xb4\x8e.jp\0kariya.aichi.jp\0togo.aichi.jp\0godo.gifu.jp\0hida.gifu.jp\0asaminami.hiroshima.jp\0fuchu.hiroshima.jp\0shingu.hyogo.jp\0sakaki.nagano.jp\0kounosu.saitama.jp\0" +"saogonca.br\0" +"horse\0" +"user.party.eus\0" +"b.ssl.fastly.net\0ibxos.it\0" +"gle\0trade\0" +"wedding\0" +"web.lk\0" +"kobierzyce.pl\0" +"pueblo.bo\0alstahaug.no\0frana.no\0gjerstad.no\0kristiansand.no\0loabat.no\0risor.no\0" +"wakasa.fukui.jp\0nishi.fukuoka.jp\0nishinomiya.hyogo.jp\0hitachiomiya.ibaraki.jp\0kiso.nagano.jp\0minamiaiki.nagano.jp\0shinanomachi.nagano.jp\0usa.oita.jp\0hatoyama.saitama.jp\0edogawa.tokyo.jp\0koto.tokyo.jp\0minato.tokyo.jp\0deta.app\0" +"\xe0\xb8\xad\xe0\xb8\x87\xe0\xb8\x84\xe0\xb9\x8c\xe0\xb8\x81\xe0\xb8\xa3.\xe0\xb9\x84\xe0\xb8\x97\xe0\xb8\xa2\0" +"citic\0base.ec\0" +"us-2.evennode.com\0" +"gmo\0" +"nis.za\0" +"trentino-s\xc3\xbc""d-tirol.it\0alto-adige.it\0ogliastra.it\0vi.it\0" +"redstone\0bukhara.su\0dyn-vpn.de\0" +"web.nf\0" +"gmx\0" +"web.ni\0" +"no-ip.biz\0" +"amusement.aero\0samnanger.no\0trondheim.no\0" +"yuki.ibaraki.jp\0higashitsuno.kochi.jp\0atami.shizuoka.jp\0shizuoka.shizuoka.jp\0lovepop.jp\0" +"go.gov.br\0qsl.br\0" +"lgbt\0" +"gucci\0rugby\0" +"googlecode.com\0" +"goo\0resindevice.io\0" +"gop\0" +"lib.ky.us\0" +"got\0vps-host.net\0" +"gov\0" +"samsung\0" +"citi\0" +"web.pk\0" +"uw.gov.pl\0" +"gangaviika.no\0karasjohka.no\0" +"tamba.hyogo.jp\0kitanakagusuku.okinawa.jp\0" +"city\0" +"us-1.evennode.com\0" +"cloud-fr1.unispace.io\0" +"blockbuster\0" +"ct.it\0rimini.it\0sassari.it\0edu.scot\0soc.srcf.net\0" +"e12.ve\0itau\0krasnodar.su\0" +"museum.mv\0" +"museum.mw\0us.eu.org\0" +"swidnica.pl\0" +"museum.no\0fla.no\0hbo\0" +"higashiura.aichi.jp\0kamioka.akita.jp\0nagara.chiba.jp\0nogata.fukuoka.jp\0hitachi.ibaraki.jp\0kaga.ishikawa.jp\0misugi.mie.jp\0otaki.nagano.jp\0takatori.nara.jp\0asahi.yamagata.jp\0penne.jp\0" +"fbxos.fr\0" +"goldpoint\0" +"de.cool\0" +"museum.om\0dsmynas.com\0" +"sx.cn\0" +"prato.it\0reggio-calabria.it\0redirectme.net\0" +"web.tj\0" +"stargard.pl\0" +"toho.fukuoka.jp\0kimobetsu.hokkaido.jp\0kanzaki.saga.jp\0ogose.saitama.jp\0koto.shiga.jp\0inami.toyama.jp\0" +"web.tr\0" +"\xd9\x87\xd9\x85\xd8\xb1\xd8\xa7\xd9\x87\0" +"global\0" +"s3-eu-west-1.amazonaws.com\0" +"group\0" +"vt.us\0k12.ak.us\0minisite.ms\0" +"trentino-suedtirol.it\0cesena-forl\xc3\xac.it\0ci.it\0parma.it\0ts.it\0krellian.net\0" +"vic.gov.au\0web.ve\0safe\0*.cloudera.site\0" +"t.bg\0" +"ubank\0" +"wkz.gov.pl\0" +"union.aero\0politica.bo\0\xc3\xa5snes.no\0stordal.no\0" +"yurihonjo.akita.jp\0kumejima.okinawa.jp\0higashiosaka.osaka.jp\0" +"bc.ca\0" +"\xd9\x85\xd9\x88\xd9\x82\xd8\xb9\0" +"independent-panel.uk\0" +"ass.km\0veterinaire.km\0" +"lib.az.us\0" +"tunk.org\0" "hra.health\0" -"toei.aichi.jp\0toba.mie.jp\0itoigawa.niigata.jp\0institute\0" -"tsugaru.aomori.jp\0choyo.kumamoto.jp\0mitsue.nara.jp\0" -"hokuryu.hokkaido.jp\0""32-b.it\0" -"erimo.hokkaido.jp\0" -"des.br\0rome.it\0" -"surgery\0" -"nagai.yamagata.jp\0" -"myftp.org\0" -"vic.gov.au\0" -"olecko.pl\0mk.eu.org\0halfmoon.jp\0" -"minamioguni.kumamoto.jp\0nishi.osaka.jp\0funahashi.toyama.jp\0gaular.no\0" -"lib.gu.us\0" -"lunner.no\0" -"cc.mo.us\0" -"go.id\0ngrok-free.dev\0" -"lincoln\0" -"samukawa.kanagawa.jp\0webspace.rocks\0" -"hisamitsu\0" -"ut.us\0" -"homesecuritypc.com\0" -"brindisi.it\0" -"3.azurestaticapps.net\0" -"extraspace\0giize.com\0" -"fi.cr\0go.it\0" -"suzuki\0" -"randaberg.no\0" -"b-data.io\0" -"freebox-os.com\0" -"\xe7\xb5\x84\xe7\xb9\x94.hk\0" -"sardinia.it\0trentin-sudtirol.it\0fujishiro.ibaraki.jp\0blogspot.com\0" -"freedesktop.org\0" -"sardegna.it\0go.jp\0" -"sarl\0dynathome.net\0" -"ac\0yoshino.nara.jp\0" -"ad\0is-a-nurse.com\0" -"ae\0go.ke\0kraanghke.no\0encoreapi.com\0" +"egersund.no\0recht.pro\0" +"sakura.chiba.jp\0nagaokakyo.kyoto.jp\0mochizuki.nagano.jp\0" +"apartments\0" +"aip.ee\0fie.ee\0" +"chintai\0" +"is-into-cartoons.com\0teaches-yoga.com\0freeboxos.com\0" +"\xe7\xb6\xb2\xe7\xb5\xa1.\xe9\xa6\x99\xe6\xb8\xaf\0apigee.io\0" +"web.za\0" +"vi.us\0pictures\0" +"bn.it\0enna.it\0nextdirect\0" +"karaganda.su\0mordovia.su\0" +"hiv\0fly.dev\0" +"i.bg\0dating\0" +"swidnik.pl\0" +"air-traffic-control.aero\0andoy.no\0etne.no\0fosnes.no\0fr\xc3\xb8ya.no\0granvin.no\0ibestad.no\0" +"isshiki.aichi.jp\0togitsu.nagasaki.jp\0kashiwara.osaka.jp\0hikimi.shimane.jp\0nagai.yamagata.jp\0lolitapunk.jp\0upper.jp\0" +"def.br\0ong.br\0veterinaire.fr\0ms.leg.br\0" +"tatamotors\0" +"games.hu\0chase\0lease\0showtime\0lohmus.me\0" +"luxury\0" +"webview-assets.cloud9.eu-north-1.amazonaws.com\0discordsays.com\0is-a-student.com\0is-an-anarchist.com\0" +"ah.cn\0" +"apps.lair.io\0" +"jeonnam.kr\0" +"cc.or.us\0" +"hkt\0" +"sale\0" +"iserv.dev\0" +"idv.hk\0inc.hk\0" +"targi.pl\0" +"passenger-association.aero\0donna.no\0" +"niigata.jp\0*.kawasaki.jp\0!city.nagoya.jp\0yamatsuri.fukushima.jp\0kusu.oita.jp\0mima.tokushima.jp\0" +"uzhgorod.ua\0" +"mt.leg.br\0" +"mordovia.ru\0" +"\xe7\xb6\xb2\xe8\xb7\xaf.tw\0" +"s3.eu-west-3.amazonaws.com\0streamlitapp.com\0" +"\xe5\x9c\xa8\xe7\xba\xbf\0" +"hair\0" +"ct.us\0ma.us\0" +"tube\0" +"store.nf\0" +"cable-modem.org\0" +"gs.nl.no\0gausdal.no\0hoyanger.no\0navuotna.no\0g\xc3\xa1ivuotna.no\0meland.no\0nesset.no\0vanylven.no\0v\xc3\xa5g\xc3\xa5.no\0aaa.pro\0" +"fukuchi.fukuoka.jp\0miasa.nagano.jp\0minamimaki.nagano.jp\0otaki.saitama.jp\0" +"odo.br\0" +"pub.instances.scw.cloud\0" +"jp.kg\0" +"appengine.flow.ch\0" +"memorial\0" +"calvinklein\0" +"app.banzaicloud.io\0" +"\xe5\xa8\xb1\xe4\xb9\x90\0" +"hot\0blog.gt\0" +"goip.de\0" +"how\0is-very-nice.org\0" +"podhale.pl\0" +"bronnoysund.no\0forde.no\0kv\xc3\xa6""fjord.no\0loppa.no\0sarpsborg.no\0trana.no\0" +"*.kobe.jp\0saigawa.fukuoka.jp\0kui.hiroshima.jp\0sugito.saitama.jp\0fujinomiya.shizuoka.jp\0moka.tochigi.jp\0higashiyamato.tokyo.jp\0tateyama.toyama.jp\0" +"dnepropetrovsk.ua\0kv.ua\0" +"jp.md\0" +"*.vps.myjino.ru\0ddns.me\0" +"eu.platform.sh\0" +"dyndns-at-work.com\0" +"5g.in\0hs.run\0" +"firewalledreplit.co\0" +"landrover\0" +"ascolipiceno.it\0" +"\xd8\xa7\xd9\x84\xd8\xa8\xd8\xad\xd8\xb1\xd9\x8a\xd9\x86\0" +"gub.uy\0bentley\0" +"sarl\0" +"ibm\0" +"blog.bo\0krokstadelva.no\0hole.no\0h\xc3\xa6gebostad.no\0lillesand.no\0" +"yame.fukuoka.jp\0tonaki.okinawa.jp\0itano.tokushima.jp\0sakaiminato.tottori.jp\0gobo.wakayama.jp\0skr.jp\0" +"rovno.ua\0zhytomyr.ua\0" +"blog.br\0eng.br\0" +"ice\0" +"click\0" +"*.stolos.io\0" +"cuisinella\0" +"cc.wi.us\0" +"campobasso.it\0" +"icu\0aktyubinsk.su\0" +"fr.eu.org\0" +"um.gov.pl\0walbrzych.pl\0" +"show.aero\0skiptvet.no\0" +"ikeda.fukui.jp\0kuju.oita.jp\0kadoma.osaka.jp\0" +"music\0" +"coffee\0" +"linkyard-cloud.ch\0" +"amscompute.com\0" +"jeep\0" +"sardegna.it\0rg.it\0blogspot.co.at\0meinforum.net\0" +"wa.edu.au\0store.ve\0save\0" +"i.ng\0" +"ifm\0" +"vgs.no\0ah.no\0flatanger.no\0halden.no\0tysvar.no\0" +"*.yokohama.jp\0kumano.mie.jp\0furukawa.miyagi.jp\0shiojiri.nagano.jp\0kashiba.nara.jp\0hinode.tokyo.jp\0gonna.jp\0" +"t.se\0" +"is-a-rockstar.com\0lon.wafaicloud.com\0servemp3.com\0" +"yn.cn\0foundation\0" +"ulsan.kr\0" +"i.ph\0" +"us.gov.pl\0" +"beiarn.no\0saxo\0" +"anamizu.ishikawa.jp\0miura.kanagawa.jp\0tomi.nagano.jp\0hamamatsu.shizuoka.jp\0morimachi.shizuoka.jp\0" +"khmelnytskyi.ua\0sm.ua\0" +"tools\0" +"fr-par-1.baremetal.scw.cloud\0" +"erotika.hu\0kommunalforbund.se\0na4u.ru\0" +"on-the-web.tv\0" +"idv.tw\0" +"\xd8\xb9\xd8\xb1\xd8\xa8\0" +"ktistory.com\0appchizi.com\0" +"as.us\0k12.oh.us\0dst.mi.us\0haus\0" +"vibo-valentia.it\0" +"tas.au\0dnsupdater.de\0" +"\xe5\x81\xa5\xe5\xba\xb7\0" +"slupsk.pl\0demon.nl\0" +"workinggroup.aero\0tran\xc3\xb8y.no\0store.ro\0" +"isumi.chiba.jp\0takata.fukuoka.jp\0matsukawa.nagano.jp\0nagawa.nagano.jp\0matsubara.osaka.jp\0omaezaki.shizuoka.jp\0pinoko.jp\0" +"cim.br\0""123siteweb.fr\0" +"tickets\0travelers\0" +"jetzt\0" +"i.se\0" +"from-mi.com\0theworkpc.com\0servehttp.com\0skygearapp.com\0" +"2038.io\0" +"discover\0" +"store.st\0firewall-gateway.net\0" +"bplaced.de\0in-berlin.de\0synology-diskstation.de\0" +"endoftheinternet.org\0" +"pohl\0" +"flekkefjord.no\0\xc3\xb8rland.no\0" +"sowa.ibaraki.jp\0" +"sb.ua\0ui.nabu.casa\0\xd0\xbc\xd1\x81\xd0\xba.\xd1\x80\xd1\x83\xd1\x81\0" +"macapa.br\0" +"ac\0game-server.cc\0" +"ad\0hyatt\0blogspot.co.id\0linkyard.cloud\0" +"ae\0ravendb.me\0" "af\0" -"ag\0nara.jp\0futaba.fukushima.jp\0" -"vfs.cloud9.ap-south-1.amazonaws.com\0" -"ai\0rehab\0" -"wpenginepowered.com\0" -"r\xc3\xa5holt.no\0" -"al\0servebbs.com\0" -"am\0" -"ao\0miyako.iwate.jp\0kodaira.tokyo.jp\0trycloudflare.com\0wpmucdn.com\0" -"static-access.net\0" +"ag\0eun.eg\0" +"ai\0" +"al\0blogspot.co.il\0" +"am\0s3-us-west-2.amazonaws.com\0" +"wien\0" +"ao\0" "aq\0ba\0" -"ar\0bb\0go.kr\0cc.md.us\0cistron.nl\0" -"as\0" -"at\0" -"au\0be\0" -"bf\0cc.ak.us\0" -"aw\0bg\0skanland.no\0es.eu.org\0fedorapeople.org\0" -"ax\0bh\0chonan.chiba.jp\0shika.ishikawa.jp\0from-ar.com\0" +"ar\0bb\0" +"as\0k12.ms.us\0k12.nc.us\0\xe8\x87\xba\xe7\x81\xa3\0enterprises\0hermes\0inc\0" +"at\0imperia.it\0traniandriabarletta.it\0" +"au\0wa.gov.au\0be\0drive\0virtualuser.de\0" +"bf\0" +"aw\0bg\0""2.bg\0ing\0readmyblog.org\0" +"ax\0bh\0" "bi\0" -"az\0bj\0lu.eu.org\0me.eu.org\0" -"from.hr\0" -"midori.gunma.jp\0bievat.no\0inc\0homelink.one\0" +"az\0bj\0" +"ink\0" +"kmpsp.gov.pl\0lomza.pl\0" "bm\0" "bn\0" -"bo\0shiroishi.saga.jp\0" -"ing\0is-a-personaltrainer.com\0" -"ca\0rm.it\0" -"br\0" +"entertainment.aero\0trader.aero\0bo\0gs.tm.no\0kvitsoy.no\0\xc3\xb8ygarden.no\0" +"naie.hokkaido.jp\0shiraoi.hokkaido.jp\0taishi.hyogo.jp\0minamiuonuma.niigata.jp\0ito.shizuoka.jp\0" +"ca\0" +"br\0ac.leg.br\0" "bs\0cc\0" -"bt\0cd\0ink\0" -"bv\0cf\0webview-assets.cloud9.ap-southeast-1.amazonaws.com\0definima.net\0" -"bw\0cg\0edgestack.me\0" +"bt\0cd\0int\0nodes.k8s.fr-par.scw.cloud\0" +"blog.vu\0" +"bv\0cf\0" +"bw\0cg\0" "ch\0" -"by\0ci\0selje.no\0jeep\0" -"bz\0i.ng\0bo.telemark.no\0" -"rokunohe.aomori.jp\0" -"cl\0" -"cm\0int\0monzabrianza.it\0" -"cn\0kicks-ass.net\0" +"by\0ci\0" +"bz\0" +"cl\0\xe5\x98\x89\xe9\x87\x8c\0" +"cm\0sa.com\0dyndns-office.com\0it.com\0" +"cn\0" "co\0" -"cr\0fnc.fr-par.scw.cloud\0" -"weatherchannel\0" +"cr\0" +"cc.tx.us\0" +"trentinoalto-adige.it\0kicks-ass.net\0" "cu\0de\0" "cv\0" -"cw\0\xe5\xa4\xa7\xe5\x88\x86.jp\0ashiya.hyogo.jp\0" +"cw\0ddnss.org\0" "cx\0" -"cy\0ass.km\0" -"cz\0dj\0save\0lv.eu.org\0" -"dk\0" -"nagasu.kumamoto.jp\0" -"dm\0ondigitalocean.app\0" -"do\0akashi.hyogo.jp\0ie.ua\0" -"demo.datadetect.com\0" -"email\0" -"ec\0ven.it\0cc.ky.us\0" -"mil.ac\0kamitsue.oita.jp\0yasugi.shimane.jp\0" +"cy\0" +"cz\0dj\0" +"dk\0\xe7\xb5\x84\xe7\xbb\x87.hk\0" +"przeworsk.pl\0lidl\0" +"dm\0" +"do\0folkebibl.no\0skedsmokorset.no\0os.hedmark.no\0\xc3\xb8yer.no\0oystre-slidre.no\0" +"\xe5\x92\x8c\xe6\xad\x8c\xe5\xb1\xb1.jp\0iwamizawa.hokkaido.jp\0obira.hokkaido.jp\0nomi.ishikawa.jp\0ebina.kanagawa.jp\0chizu.tottori.jp\0unazuki.toyama.jp\0" +"zt.ua\0" +"ec\0" "ee\0" -"mil.ae\0" -"eg\0t.se\0\xd9\xbe\xd8\xa7\xd9\x83\xd8\xb3\xd8\xaa\xd8\xa7\xd9\x86\0" -"museum.mv\0" -"museum.mw\0" -"dz\0obama.nagasaki.jp\0podlasie.pl\0" -"i.ph\0beskidy.pl\0" -"\xe5\x81\xa5\xe5\xba\xb7\0dynamisches-dns.de\0" -"mil.al\0tn.us\0primetel.cloud\0" -"living\0" -"psi.br\0no-ip.ca\0" -"museum.no\0prequalifyme.today\0" -"mil.ba\0" -"mil.ar\0es\0" -"et\0" -"eu\0aukra.no\0" -"fi.it\0" -"higashinaruse.akita.jp\0" -"\xd8\xb9\xd8\xb1\xd8\xa8\0" -"fi\0" -"fj\0koryo.nara.jp\0sor-aurdal.no\0" -"mil.az\0" -"*.hosting.myjino.ru\0" -"fm\0" -"2.bg\0fo\0aki.kochi.jp\0museum.om\0travel.pl\0" -"mil.bo\0\xd1\x81\xd0\xbe\xd1\x87\xd0\xb8.\xd1\x80\xd1\x83\xd1\x81\0" -"ga\0etisalat\0" -"fr\0gb\0auto.pl\0" -"mil.br\0thruhere.net\0" -"gd\0saxo\0" -"ge\0" -"gf\0noho.st\0" -"gg\0go.pw\0" -"gh\0" -"gi\0haus\0eu.org\0" -"mil.by\0" -"jcb\0" -"gl\0from-ne.com\0" -"mil.cl\0gm\0" -"gn\0" -"mil.cn\0yachimata.chiba.jp\0" -"mil.co\0gp\0miharu.fukushima.jp\0university\0" -"gq\0shirataka.yamagata.jp\0" -"gr\0locker\0" -"gs\0" -"gt\0sk\xc3\xa1nit.no\0szczytno.pl\0" -"gu\0\xc3\xa5l.no\0" -"gw\0shinshinotsu.hokkaido.jp\0" -"i.se\0hepforge.org\0" -"gy\0stripper.jp\0" -"mil.cy\0" -"hk\0" -"ntdll.top\0" -"hm\0ist\0" -"transporte.bo\0hn\0gs.va.no\0" -"uki.kumamoto.jp\0her\xc3\xb8y.m\xc3\xb8re-og-romsdal.no\0" -"mil.do\0" -"beardu.no\0" -"cargo.aero\0hr\0grane.no\0verm\xc3\xb6gensberatung\0" -"mil.ec\0ht\0id\0" -"hu\0ie\0\xc3\xa5rdal.no\0" -"en.it\0um.gov.pl\0" -"mil.eg\0" -"yura.wakayama.jp\0" -"il\0suita.osaka.jp\0stavanger.no\0" -"im\0" -"in\0moseushi.hokkaido.jp\0" -"io\0nikko.tochigi.jp\0itv\0" -"\xe5\x8c\x97\xe6\xb5\xb7\xe9\x81\x93.jp\0" -"iq\0schulplattform.de\0" -"ir\0sunagawa.hokkaido.jp\0" -"is\0budejju.no\0" -"it\0" -"je\0" -"toyohashi.aichi.jp\0nagawa.nagano.jp\0" -"int.ar\0salvador.br\0gop.pk\0go.th\0" -"ikeda.fukui.jp\0seika.kyoto.jp\0go.tj\0" -"mil.fj\0" -"pohl\0fedorainfracloud.org\0" -"jo\0khmelnytskyi.ua\0" -"int.az\0jp\0knowsitall.info\0" -"realestate\0" -"taiwa.miyagi.jp\0kppsp.gov.pl\0" -"int.bo\0ke\0" -"mil.ge\0" -"\xe6\x84\x9b\xe5\xaa\x9b.jp\0kg\0travel.tt\0go.ug\0" -"r2.dev\0" -"mil.gh\0internet.in\0ki\0" -"sund.no\0go.tz\0" -"of.by\0\xd0\xbe\xd0\xb1\xd1\x80.\xd1\x81\xd1\x80\xd0\xb1\0t3l3p0rt.net\0" -"km\0\xe5\x98\x89\xe9\x87\x8c\0" -"kn\0" -"int.ci\0miyoshi.hiroshima.jp\0" -"kp\0" -"la\0fr\xc3\xa6na.no\0" -"kr\0lb\0" -"fujiidera.osaka.jp\0lc\0" -"int.co\0mil.gt\0hdfcbank\0" -"\xd9\xbe\xd8\xa7\xda\xa9\xd8\xb3\xd8\xaa\xd8\xa7\xd9\x86\0*.ocs.customer-oci.com\0from-mi.com\0" -"balsan.it\0kw\0kuleuven.cloud\0" -"ky\0li\0wien\0" -"kz\0kr.eu.org\0" -"lk\0" -"int.cv\0" -"game-server.cc\0is-a-republican.com\0" -"cremona.it\0vologda.su\0" -"mil.hn\0omuta.fukuoka.jp\0" -"yoshida.saitama.jp\0vision\0googleapis.com\0" -"sakura.chiba.jp\0ma\0" -"kiyose.tokyo.jp\0lr\0" -"ls\0mc\0" -"lt\0md\0" -"mil.id\0lu\0me\0accesscam.org\0" -"lv\0" -"mg\0us.gov.pl\0from-ga.com\0" -"mh\0" -"ly\0jele.host\0" -"augustow.pl\0" -"hida.gifu.jp\0mk\0" -"ml\0porsgrunn.no\0" -"\xe8\x87\xba\xe7\x81\xa3\0" -"mn\0forde.no\0" -"mil.in\0mo\0" -"mp\0" -"mq\0na\0" -"mil.iq\0makurazaki.kagoshima.jp\0mr\0vang.no\0cc.va.us\0" -"misato.shimane.jp\0ms\0nc\0" -"mt\0deatnu.no\0wielun.pl\0servehttp.com\0" -"asahi.nagano.jp\0mu\0ne\0" -"mv\0nf\0bo.nordland.no\0" -"itano.tokushima.jp\0mw\0ng\0fi.eu.org\0" -"mx\0jio\0lidl\0" -"umi.fukuoka.jp\0my\0ni\0" -"mz\0" -"nl\0" -"laz.it\0naamesjevuemie.no\0" -"no\0" -"mil.jo\0anamizu.ishikawa.jp\0medecin.km\0" -"nr\0" -"idf.il\0pa.it\0nu\0s3-website-ap-southeast-2.amazonaws.com\0cloudapps.digital\0" -"mil.kg\0" -"otsuki.yamanashi.jp\0" -"sch.ae\0matsuura.nagasaki.jp\0nz\0" -"traniandriabarletta.it\0" -"om\0" -"mil.km\0" -"karumai.iwate.jp\0" -"pa\0life\0chillout.jp\0" -"cagliari.it\0" -"mil.kr\0" -"tenri.nara.jp\0nakijin.okinawa.jp\0" -"pe\0westeurope.azurestaticapps.net\0" -"pf\0*.azurecontainer.io\0" -"ph\0jaworzno.pl\0xy.ax\0" -"tadotsu.kagawa.jp\0store.nf\0\xe5\x95\x86\xe5\x9f\x8e\0" -"towada.aomori.jp\0mil.kz\0malatvuopmi.no\0pk\0k12.nh.us\0" -"bjarkoy.no\0pl\0oldnavy\0" -"pm\0" -"yorii.saitama.jp\0pn\0" -"yamagata.ibaraki.jp\0" -"hakusan.ishikawa.jp\0" -"avellino.it\0qa\0barsy.menu\0" -"pr\0" -"ono.fukushima.jp\0urakawa.hokkaido.jp\0ps\0kropyvnytskyi.ua\0" -"pt\0" -"bergen.no\0jll\0website.yandexcloud.net\0" -"mp.br\0" -"mil.lv\0pw\0" -"mashiki.kumamoto.jp\0tateyama.toyama.jp\0mil.mg\0" -"py\0" -"cloudns.biz\0" -"media.hu\0" -"schools.nsw.edu.au\0ise.mie.jp\0" -"int.in\0wiki\0" -"re\0" -"broadway\0" -"mil.mv\0of.je\0" -"nogata.fukuoka.jp\0mil.ng\0" -"\xe6\x95\x99\xe8\x82\xb2.hk\0int.is\0jmp\0" -"mil.my\0mil.ni\0" -"mil.mz\0dattoweb.com\0from-sd.com\0*.migration.run\0" -"akabira.hokkaido.jp\0" -"ro\0" -"wa.gov.au\0mil.no\0" -"sa\0" -"sb\0vanguard\0" -"rs\0sc\0jnj\0" -"sd\0" -"ru\0se\0" -"\xe7\xb6\xb2\xe8\xb7\xaf.tw\0makeup\0matrix.jp\0" -"rw\0sg\0" -"sh\0hospital\0" -"nose.osaka.jp\0si\0" -"lindas.no\0sj\0is-an-anarchist.com\0royal-commission.uk\0" -"mil.nz\0sk\0" -"sl\0" -"sm\0" -"sn\0" -"so\0" -"akrehamn.no\0lib.ny.us\0" -"capital\0vegas\0" -"okutama.tokyo.jp\0sr\0hippy.jp\0" -"ogata.akita.jp\0ss\0tc\0" -"st\0td\0" -"su\0yodobashi\0" -"mil.pe\0sv\0tf\0" -"int.la\0tg\0" -"sx\0th\0" -"mil.ph\0sy\0" -"sz\0tj\0" -"norddal.no\0tk\0" -"tl\0" -"\xe7\xa7\x8b\xe7\x94\xb0.jp\0mutsu.aomori.jp\0mil.pl\0pomorskie.pl\0tm\0jot\0" -"seiyo.ehime.jp\0tn\0" -"to\0eu.encoway.cloud\0" -"romsa.no\0porn\0wine\0" -"int.lk\0ua\0like\0" -"baidar.no\0mil.qa\0tr\0joy\0" -"\xd9\x85\xd9\x84\xd9\x8a\xd8\xb3\xd9\x8a\xd8\xa7\0webview-assets.cloud9.ap-northeast-1.amazonaws.com\0kawaiishop.jp\0" -"tt\0" -"matsuda.kanagawa.jp\0" -"tv\0" -"tw\0ug\0" -"pruszkow.pl\0" -"mil.py\0tz\0restaurant\0" -"br.it\0cb.it\0uk\0auspost\0edeka\0" -"aridagawa.wakayama.jp\0va\0co.network\0" -"us\0vc\0demo.jelastic.com\0" -"ve\0toyota\0*.compute.amazonaws.com.cn\0" -"post\0" -"misato.miyagi.jp\0vg\0iliadboxos.it\0" -"k12.wy.us\0uy\0vi\0" -"uz\0" -"umbria.it\0ginan.gifu.jp\0int.mv\0mjondalen.no\0" -"int.mw\0fidelity\0" -"hinohara.tokyo.jp\0vn\0" -"int.ni\0from.tv\0" -"tosashimizu.kochi.jp\0wakuya.miyagi.jp\0of.no\0pl.ua\0" -"lecce.it\0kiyosu.aichi.jp\0malbork.pl\0" -"\xe5\xb1\xb1\xe6\xa2\xa8.jp\0overhalla.no\0ddnslive.com\0" -"vu\0from-nh.com\0" -"wf\0mil.ru\0" -"gjovik.no\0" -"keisen.fukuoka.jp\0mil.rw\0" -"campinagrande.br\0sch.id\0mil.sh\0" -"simplesite.gr\0official.academy\0" -"limo\0" -"shinichi.hiroshima.jp\0" -"nosegawa.nara.jp\0airforce\0" -"ws\0\xda\x80\xd8\xa7\xd8\xb1\xd8\xaa\0" -"skanit.no\0" -"nagano.nagano.jp\0swinoujscie.pl\0mil.st\0" -"takanabe.miyazaki.jp\0" -"sch.ir\0link\0" -"store.ve\0" -"nagi.okayama.jp\0kudamatsu.yamaguchi.jp\0" -"mil.sy\0" -"mil.tj\0" -"fnd.br\0bg.it\0" -"nagano.jp\0" -"oyamazaki.kyoto.jp\0iveland.no\0mil.tm\0" -"kakamigahara.gifu.jp\0""4u.com\0" -"kasuga.fukuoka.jp\0mil.to\0" -"mil.tr\0" -"sch.jo\0accountants\0mango\0" -"media.pl\0ye\0" -"\xe0\xb8\xa3\xe0\xb8\xb1\xe0\xb8\x90\xe0\xb8\x9a\xe0\xb8\xb2\xe0\xb8\xa5.\xe0\xb9\x84\xe0\xb8\x97\xe0\xb8\xa2\0" -"\xc3\xa5""fjord.no\0mil.tw\0" -"int.pt\0" -"flekkefjord.no\0mil.tz\0" -"homes\0" -"pa.leg.br\0" -"l\xc3\xb8ten.no\0whm.nl-ams.scw.cloud\0" -"fyresdal.no\0" -"avocats.bj\0" -"mil.vc\0yt\0\xd0\xbe\xd0\xbd\xd0\xbb\xd0\xb0\xd0\xb9\xd0\xbd\0" -"mil.ve\0cx.ua\0forgeblocks.com\0" -"mil.uy\0" -"tagawa.fukuoka.jp\0se.net\0ru.net\0" -"otake.hiroshima.jp\0" -"zm\0nflfan.org\0pubtls.org\0" -"gripe\0" -"sch.lk\0intuit\0does-it.net\0cust.testing.thingdust.io\0" -"kfh\0" -"me.in\0" -"pa.us\0" -"okegawa.saitama.jp\0" -"r\xc3\xb8mskog.no\0" -"zw\0" -"lu.it\0me.it\0\xe4\xba\x9a\xe9\xa9\xac\xe9\x80\x8a\0" -"educator.aero\0int.ru\0" -"abr.it\0" -"al.it\0" -"sch.ly\0" -"pb.leg.br\0" -"surnadal.no\0pulawy.pl\0" -"utsira.no\0" -"experts-comptables.fr\0canva-apps.com\0" -"me.ke\0" -"shibecha.hokkaido.jp\0gildesk\xc3\xa5l.no\0" -"sch.ng\0" -"lutsk.ua\0" -"dyndns.ddnss.de\0" -"int.tj\0" -"hirono.iwate.jp\0store.ro\0" -"oseto.nagasaki.jp\0mil.ye\0" -"kv\xc3\xa6nangen.no\0" -"int.tt\0kia\0" -"ota.tokyo.jp\0cc.ga.us\0" -"rec.br\0" -"mil.za\0club\0" -"elementor.cloud\0" -"nv.us\0" -"kim\0" -"yawatahama.ehime.jp\0store.st\0" -"tsushima.aichi.jp\0scot\0" -"wskr.gov.pl\0" -"sar.it\0int.ve\0boxfuse.io\0" -"rec.co\0" -"mil.zm\0" -"honjyo.akita.jp\0" -"lodingen.no\0nesseby.no\0" -"int.vn\0" -"stor-elvdal.no\0" -"sch.qa\0" -"puglia.it\0" -"mil.zw\0fairwinds\0" -"myfritz.net\0" -"smola.no\0" -"zarow.pl\0" -"shinjo.nara.jp\0minato.osaka.jp\0" -"from-va.com\0" -"travel.in\0badaddja.no\0live\0kicks-ass.org\0" -"computer\0" -"storfjord.no\0" -"simplesite.pl\0" -"phone\0" -"in-the-band.net\0" -"al.no\0lib.al.us\0" -"amot.no\0" -"kawamata.fukushima.jp\0" -"*.advisor.ws\0" -"mutsuzawa.chiba.jp\0" -"tatar\0in.net\0" -"ltd.cy\0" -"ic.gov.pl\0" -"ballooning.aero\0sch.sa\0edgeapp.net\0" -"gru.br\0barcelona\0" -"blogspot.vn\0" -"engineering\0" -"restaurant.bj\0jobs.tt\0" -"vic.au\0" -"is-a-bookkeeper.com\0" -"matsubushi.saitama.jp\0" -"aca.pro\0" -"onrender.com\0" -"ws.na\0" -"sch.so\0" -"medecin.fr\0padua.it\0sakai.osaka.jp\0sakaiminato.tottori.jp\0" -"sch.ss\0" -"nagaokakyo.kyoto.jp\0" -"sch.tf\0" -"tas.edu.au\0dyndns-office.com\0" -"shiroi.chiba.jp\0earth\0online.th\0" -"schule\0jele.club\0" -"fedje.no\0" -"games.hu\0trondheim.no\0" -"dyndns-server.com\0" -"aa.no\0" -"securitytactics.com\0" -"reise\0" -"vefsn.no\0voting\0" -"shiga.jp\0" -"barsy.support\0" -"ltd.gi\0" -"tw.cn\0" -"gangaviika.no\0" -"ami.ibaraki.jp\0" -"microlight.aero\0" -"\xe5\x85\xb5\xe5\xba\xab.jp\0tamba.hyogo.jp\0" -"chirurgiens-dentistes.fr\0sagae.yamagata.jp\0" -"cesenaforli.it\0gushikami.okinawa.jp\0" -"blogspot.re\0ciscofreak.com\0" -"vads\xc3\xb8.no\0" -"me.so\0\xe0\xa6\xad\xe0\xa6\xbe\xe0\xa7\xb0\xe0\xa6\xa4\0ltd.hk\0" -"rsvp\0" -"hockey\0" -"yugawa.fukushima.jp\0kpn\0" -"!city.yokohama.jp\0nichinan.miyazaki.jp\0me.ss\0me.tc\0" -"\xe5\x8f\xb0\xe6\xb9\xbe\0yahoo\0blogspot.ro\0" -"sch.wf\0" -"blogspot.rs\0" -"asakawa.fukushima.jp\0" -"blogspot.ru\0blogspot.se\0" -"saga.jp\0space\0" -"blogspot.sg\0" -"serveftp.net\0blogspot.si\0" -"now-dns.net\0" -"ujiie.tochigi.jp\0blogspot.sk\0" -"barsycenter.com\0" -"blogspot.sn\0" -"patria.bo\0" -"omotego.fukushima.jp\0krd\0lat\0" -"takahagi.ibaraki.jp\0blogspot.td\0" -"me.tz\0photo\0" -"me.uk\0law\0" -"kibichuo.okayama.jp\0" -"ayagawa.kagawa.jp\0taipei\0" -"tone.ibaraki.jp\0\xd8\xa8\xd9\x8a\xd8\xaa\xd9\x83\0githubusercontent.com\0ravendb.run\0" -"me.us\0" -"vb.it\0hdfc\0" -"al.us\0honda\0" -"\xd7\x90\xd7\xa7\xd7\x93\xd7\x9e\xd7\x99\xd7\x94.\xd7\x99\xd7\xa9\xd7\xa8\xd7\x90\xd7\x9c\0" -"blogspot.tw\0blogspot.ug\0ngrok.io\0" -"dyndns-ip.com\0" -"impertrixcdn.com\0" -"faith\0" -"r.bg\0" -"betainabox.com\0me.vu\0" -"godo.gifu.jp\0" -"blogspot.mr\0" -"benevento.it\0vestby.no\0" -"barsy.club\0" -"sch.zm\0blogspot.mx\0" -"rec.nf\0blogspot.my\0" -"hakuba.nagano.jp\0nishikawa.yamagata.jp\0ltd.lk\0" -"blogspot.nl\0myiphost.com\0" -"wakayama.wakayama.jp\0" -"haboro.hokkaido.jp\0" -"blogspot.no\0goupile.fr\0" -"\xd8\xb9\xd8\xb1\xd8\xa7\xd9\x82\0" -"lds\0" -"ngrok-free.app\0" -"yamagata.jp\0cc.de.us\0pi.leg.br\0" -"forl\xc3\xac-cesena.it\0" -"gx.cn\0film.hu\0" -"bradesco\0" -"\xc3\xa5lesund.no\0" -"blogspot.pe\0" -"kvafjord.no\0sanofi\0ltd.ng\0" -"kembuchi.hokkaido.jp\0sadist.jp\0" -"lillehammer.no\0vps.mcdir.ru\0" -"hk.org\0" -"g.bg\0" -"es.gov.br\0" -"blogspot.qa\0" -"amfam\0" -"tosu.saga.jp\0" -"blogspot.pt\0" -"tra.kp\0discourse.team\0" -"edu.scot\0" -"build\0rocky.page\0" -"store.bb\0" -"tydal.no\0nyan.to\0" -"sannan.hyogo.jp\0" -"lib.ia.us\0fage\0" -"software.aero\0blogspot.is\0" -"lancia\0blogspot.it\0" -"inatsuki.fukuoka.jp\0akamaized-staging.net\0sellsyourhome.org\0" -"\xe7\xae\x87\xe4\xba\xba.hk\0" -"tokuyama.yamaguchi.jp\0" -"arts.co\0" -"pokrovsk.su\0blogspot.jp\0" -"nanbu.tottori.jp\0" -"rec.ro\0" -"biratori.hokkaido.jp\0" -"miura.kanagawa.jp\0" -"stufftoread.com\0" -"jevnaker.no\0seljord.no\0dnsdojo.org\0" -"in.na\0" -"blogspot.kr\0" -"kuchinotsu.nagasaki.jp\0" -"store.dk\0" -"fail\0" -"\xe5\xa5\x88\xe8\x89\xaf.jp\0" -"ozu.kumamoto.jp\0" -"\xe5\x92\x8c\xe6\xad\x8c\xe5\xb1\xb1.jp\0in.ni\0pors\xc3\xa1\xc5\x8bgu.no\0blogspot.li\0" -"office-on-the.net\0co.financial\0" -"kagawa.jp\0from-vt.com\0" -"tawaramoto.nara.jp\0taifun-dns.de\0" -"hamburg\0" -"hs.kr\0cc.nh.us\0" -"servegame.org\0framer.website\0blogspot.lt\0blogspot.md\0" -"blogspot.lu\0" -"kristiansand.no\0tr\xc3\xa6na.no\0" -"publ.pt\0" -"blogspot.mk\0" -"dating\0dnsalias.net\0" -"seat\0" -"ogi.saga.jp\0\xd8\xa8\xd8\xa7\xd8\xb1\xd8\xaa\0" -"ta.it\0gen.mi.us\0llc\0" -"mex.com\0" -"takata.fukuoka.jp\0" -"lacaixa\0" -"rec.ve\0mypsx.net\0" -"blogspot.fi\0" -"sub.jp\0njs.jelastic.vps-host.net\0" -"satsumasendai.kagoshima.jp\0" -"llp\0poivron.org\0" -"ltd.ua\0" -"akdn\0us-east-1.elasticbeanstalk.com\0" -"\xe0\xb8\x98\xe0\xb8\xb8\xe0\xb8\xa3\xe0\xb8\x81\xe0\xb8\xb4\xe0\xb8\x88.\xe0\xb9\x84\xe0\xb8\x97\xe0\xb8\xa2\0blogspot.fr\0" -"potenza.it\0" -"*.user.fm\0" -"pe.leg.br\0" -"radio\0" -"furniture\0" -"ltd.uk\0" -"higashi.fukushima.jp\0" -"parliament.nz\0" -"blogspot.gr\0" -"friuli-vegiulia.it\0" -"*.compute-1.amazonaws.com\0ap.ngrok.io\0" -"skien.no\0gotdns.org\0" -"!city.kawasaki.jp\0" -"minami.kyoto.jp\0" -"valled-aosta.it\0" -"s3-us-east-2.amazonaws.com\0blogspot.hk\0" -"mymediapc.net\0" -"githubpreview.dev\0messwithdns.com\0" -"itayanagi.aomori.jp\0" -"blogspot.hr\0" -"seto.aichi.jp\0prof.pr\0in.rs\0" -"edgesuite-staging.net\0" -"blogspot.hu\0blogspot.ie\0" -"seek\0hungry.jp\0" -"firewall-gateway.net\0" -"\xe6\x94\xbf\xe5\xba\x9c.hk\0" -"lol\0mypep.link\0myspreadshop.com.au\0" -"fans\0kasserver.com\0" -"bulsan.it\0finnoy.no\0" -"blogspot.in\0" -"sandefjord.no\0" -"cesena-forl\xc3\xac.it\0blogspot.ba\0" -"kitahiroshima.hokkaido.jp\0" -"iijima.nagano.jp\0blogspot.be\0" -"netlify.app\0" -"def.br\0voyage\0blogspot.bg\0" -"log.br\0in.th\0" -"blogspot.bj\0" -"show.aero\0cim.br\0lpl\0*.triton.zone\0" -"wiw.gov.pl\0pcloud.host\0" -"k12.fl.us\0" -"rankoshi.hokkaido.jp\0joboji.iwate.jp\0tatamotors\0" -"leasing.aero\0obira.hokkaido.jp\0takino.hyogo.jp\0graphics\0" -"in.ua\0blogspot.ca\0" -"misugi.mie.jp\0sogne.no\0" -"cosenza.it\0" -"yatsushiro.kumamoto.jp\0blogspot.cf\0" -"takaharu.miyazaki.jp\0blogsite.xyz\0blogspot.ch\0" -"eastus2.azurestaticapps.net\0" -"chigasaki.kanagawa.jp\0" -"kotoura.tottori.jp\0" -"blogspot.cl\0" -"pisz.pl\0man\0" -"map\0" -"mba\0" -"ora.gunma.jp\0itako.ibaraki.jp\0" -"in.us\0cleaning\0" -"yamanakako.yamanashi.jp\0" -"blogspot.de\0" -"blogspot.cv\0" -"scientist.aero\0fr.it\0" -"matsushige.tokushima.jp\0blogspot.cz\0" -"blogspot.dk\0" -"coffee\0" -"ruhr\0" -"withgoogle.com\0" -"motegi.tochigi.jp\0arts.ve\0s3-website.ap-south-1.amazonaws.com\0" -"kumamoto.kumamoto.jp\0" -"shiogama.miyagi.jp\0" -"heguri.nara.jp\0" -"nakama.fukuoka.jp\0" -"farm\0\xd9\x87\xd9\x85\xd8\xb1\xd8\xa7\xd9\x87\0cloudjiffy.net\0" -"ookuwa.nagano.jp\0ngo.lk\0onporter.run\0" -"oz.au\0toyo.kochi.jp\0" -"\xe6\x9b\xb8\xe7\xb1\x8d\0" -"twmail.net\0" -"vfs.cloud9.eu-north-1.amazonaws.com\0" -"bozen-suedtirol.it\0sf.no\0kaufen\0" -"mydatto.com\0" -"akagi.shimane.jp\0jp.eu.org\0" -"shiwa.iwate.jp\0guge\0" -"alp1.ae.flow.ch\0" -"ltd\0" -"ullensvang.no\0" -"saogonca.br\0" -"pagespeedmobilizer.com\0" -"\xe6\xa0\x83\xe6\x9c\xa8.jp\0r.se\0publishproxy.com\0" -"hitachi.ibaraki.jp\0ibaraki.ibaraki.jp\0" -"global.ssl.fastly.net\0" -"fast\0s3-website.nl-ams.scw.cloud\0" -"med\0ngo.ng\0" -"in-addr.arpa\0samegawa.fukushima.jp\0yoga\0logoip.com\0" -"corsica\0" -"higashiyodogawa.osaka.jp\0" -"fg.it\0glass\0" -"\xe7\xbd\x91\xe5\x9d\x80\0ibxos.it\0" -"urn.arpa\0pueblo.bo\0akita.jp\0" -"nishi.fukuoka.jp\0men\0" -"\xe7\x86\x8a\xe6\x9c\xac.jp\0" -"iyo.ehime.jp\0" -"ric.jelastic.vps-host.net\0" -"shari.hokkaido.jp\0" -"0.bg\0" -"kofu.yamanashi.jp\0demo.datacenter.fi\0" -"shirosato.ibaraki.jp\0iiyama.nagano.jp\0bharti\0" -"hidaka.saitama.jp\0readthedocs.io\0k8s.scw.cloud\0" -"paas.hosted-by-previder.com\0" -"bronnoy.no\0beta.tailscale.net\0" -"kamikawa.hokkaido.jp\0" -"ngo.ph\0" -"blogspot.ae\0pr.leg.br\0" -"seg.br\0" -"audnedaln.no\0" -"arts.ro\0rogers\0" -"shirakawa.gifu.jp\0g.se\0\xd8\xa7\xd9\x84\xd8\xa8\xd8\xad\xd8\xb1\xd9\x8a\xd9\x86\0edgecompute.app\0" -"blogspot.al\0" -"blogspot.am\0" -"tsukigata.hokkaido.jp\0oiso.kanagawa.jp\0\xeb\x8b\xb7\xeb\x84\xb7\0" -"poker\0cn-north-1.eb.amazonaws.com.cn\0" -"fylkesbibl.no\0fl\xc3\xa5.no\0" -"isumi.chiba.jp\0*.sensiosite.cloud\0" -"karasuyama.tochigi.jp\0\xd8\xb3\xd9\x88\xd8\xaf\xd8\xa7\xd9\x86\0" -"pu.it\0\xe5\xa4\xa7\xe6\x8b\xbf\0" -"kamo.kyoto.jp\0" -"krasnik.pl\0dnsupdate.info\0" -"yonaguni.okinawa.jp\0netgamers.jp\0" -"pioneer\0" -"mihama.chiba.jp\0s3-website-us-east-1.amazonaws.com\0lpusercontent.com\0" -"kushimoto.wakayama.jp\0fireweb.app\0" -"pesaro-urbino.it\0tabayama.yamanashi.jp\0" -"travel\0" -"nt.au\0" -"mil\0gon.pk\0" -"taki.mie.jp\0kawatana.nagasaki.jp\0help\0" -"uk.net\0" -"rv.ua\0k12.ca.us\0" -"seranishi.hiroshima.jp\0" -"1337.pictures\0" -"mit\0s3.teckids.org\0" -"syno-ds.de\0" -"valle-aosta.it\0deno.dev\0" -"nt.ca\0" -"adachi.tokyo.jp\0" -"framer.photos\0" -"kumagaya.saitama.jp\0" -"chintai\0" -"gallery\0" -"is-an-actress.com\0" -"yamaga.kumamoto.jp\0mitsubishi\0" -"arts.nf\0" -"lolipop.io\0hasura.app\0" -"ringerike.no\0" -"\xe7\xbd\x91\xe7\xab\x99\0parallel.jp\0" -"\xc3\xa5seral.no\0" -"hyundai\0" -"partners\0" -"flesberg.no\0akadns.net\0" -"hamada.shimane.jp\0websozai.jp\0" -"saigawa.fukuoka.jp\0" -"is-an-artist.com\0" -"mlb\0" -"passenger-association.aero\0" -"yuasa.wakayama.jp\0www.ro\0community-pro.net\0" -"fbxos.fr\0mongolian.jp\0" -"okinawa\0" -"jolster.no\0dlugoleka.pl\0" -"prod\0chirurgiens-dentistes-en-france.fr\0" -"k12.mo.us\0" -"tochigi.tochigi.jp\0prof\0" -"mma\0dnsup.net\0" -"mls\0" -"alpha-myqnapcloud.com\0" -"inagawa.hyogo.jp\0" -"skierva.no\0" -"niimi.okayama.jp\0deals\0systems\0" -"rana.no\0" -"huissier-justice.fr\0int.eu.org\0" -"olbia-tempio.it\0" -"accident-investigation.aero\0higashiizu.shizuoka.jp\0" -"voss.no\0" -"okayama.okayama.jp\0" -"tarumizu.kagoshima.jp\0" -"higashiyamato.tokyo.jp\0" -"s3-sa-east-1.amazonaws.com\0" -"\xe6\x95\x8e\xe8\x82\xb2.hk\0trentino-s\xc3\xbc""d-tirol.it\0" -"capetown\0" -"tahara.aichi.jp\0tynset.no\0here\0ventures\0" -"tomioka.gunma.jp\0erni\0" -"lierne.no\0\xe5\x8f\xb0\xe7\x81\xa3\0moe\0" -"moi\0from-ny.net\0" -"shimodate.ibaraki.jp\0" -"mom\0" -"urasoe.okinawa.jp\0under.jp\0" -"akamaihd.net\0" -"guru\0" -"r\xc3\xb8st.no\0k12.as.us\0upli.io\0" -"be.ax\0" -"qld.au\0mov\0" -"\xe4\xbd\x90\xe8\xb3\x80.jp\0toshima.tokyo.jp\0" -"agro.bj\0\xe5\xb1\xb1\xe5\xbd\xa2.jp\0certmgr.org\0*.bzz.dapps.earth\0" -"akamai-staging.net\0" -"gmina.pl\0" -"agro.bo\0ngo.za\0" -"takayama.gifu.jp\0*.usercontent.goog\0" -"torahime.shiga.jp\0" -"nab\0" -"hongo.hiroshima.jp\0" -"tushu\0" -"motobu.okinawa.jp\0" -"s3.ap-south-1.amazonaws.com\0" -"uruma.okinawa.jp\0" -"minamifurano.hokkaido.jp\0" -"nba\0" -"yamagata.gifu.jp\0" -"\xd0\xbc\xd0\xb8\xd1\x80.\xd1\x80\xd1\x83\xd1\x81\0" -"5g.in\0" -"siiites.com\0" -"k12.mi.us\0" -"shimada.shizuoka.jp\0mc.ax\0" -"appengine.flow.ch\0own.pm\0qbuser.com\0" -"k12.az.us\0lib.ok.us\0msd\0" -"sexy\0" -"omniwe.site\0" -"res.aero\0my.id\0" -"k8s.nl-ams.scw.cloud\0" -"mintere.site\0" -"tabitorder.co.il\0" -"sula.no\0recht.pro\0protection\0" -"cool\0" -"torino.it\0utashinai.hokkaido.jp\0" -"bihoro.hokkaido.jp\0" -"coop\0" -"annaka.gunma.jp\0" -"troitsk.su\0" -"mtn\0" -"naustdal.no\0" -"mtr\0" -"nec\0" -"co.technology\0" -"hashima.gifu.jp\0merckmsd\0o0o0.jp\0" -"dnsdojo.net\0" -"perspecta.cloud\0" -"saikai.nagasaki.jp\0d\xc3\xb8nna.no\0ally\0serveftp.org\0" -"rawa-maz.pl\0conn.uk\0now-dns.org\0" -"hagebostad.no\0myftp.biz\0" -"futsu.nagasaki.jp\0" -"yamagata.nagano.jp\0" -"net\0" -"nt.no\0lib.mt.us\0lib.nd.us\0autos\0be.gy\0" -"ancona.it\0murata.miyagi.jp\0new\0" -"attorney\0" -"caracal.mythic-beasts.com\0" -"nfl\0" -"cc.gu.us\0" -"skedsmokorset.no\0" -"\xe5\x9f\xbc\xe7\x8e\x89.jp\0" -"github.io\0" -"brescia.it\0claims\0uh-oh.jp\0" -"\xe6\x94\xbf\xe5\x8a\xa1\0" -"austrheim.no\0" -"mn.it\0odesa.ua\0" -"s\xc3\xb8ndre-land.no\0" -"casino.hu\0ngo\0" -"obuse.nagano.jp\0" -"solutions\0lab.ms\0" -"chernovtsy.ua\0" -"swatch\0independent-commission.uk\0" -"nahari.kochi.jp\0\xd0\xbe\xd1\x80\xd0\xb3.\xd1\x81\xd1\x80\xd0\xb1\0" -"ponpes.id\0mormon\0" -"mmafan.biz\0" -"akune.kagoshima.jp\0" -"nhk\0" -"builtwithdark.com\0" -"carbonia-iglesias.it\0" -"lur\xc3\xb8y.no\0" -"is-very-evil.org\0" -"lib.ma.us\0" -"h\xc3\xa1""bmer.no\0" -"cv.ua\0cc.sc.us\0" -"uk.reclaim.cloud\0" -"rendalen.no\0" -"lebesby.no\0" -"is.eu.org\0" -"j.layershift.co.uk\0" -"nt.ro\0myasustor.com\0" -"alstahaug.no\0" -"shirakawa.fukushima.jp\0damnserver.com\0" -"horokanai.hokkaido.jp\0from-ma.com\0" -"koshu.yamanashi.jp\0ing.pa\0" -"mc.it\0" -"gehirn.ne.jp\0" -"marumori.miyagi.jp\0" -"*.gateway.dev\0" -"yakumo.shimane.jp\0dd-dns.de\0" -"mo\xc3\xa5reke.no\0" -"kurotaki.nara.jp\0" -"glogow.pl\0yolasite.com\0" -"yusuhara.kochi.jp\0kamisato.saitama.jp\0" -"kitanakagusuku.okinawa.jp\0" -"oji.nara.jp\0k12.va.us\0barsy.mobi\0" -"us.ngrok.io\0panel.gg\0" -"boats\0dreamhosters.com\0it.eu.org\0" -"peewee.jp\0" -"seirou.niigata.jp\0" -"od.ua\0" -"songdalen.no\0sakuratan.com\0" -"tkmaxx\0" -"orsta.no\0ck.ua\0" -"seki.gifu.jp\0" -"bodo.no\0" -"obninsk.su\0" -"canva-apps.cn\0" -"router.management\0" -"catania.it\0rentals\0" -"bialystok.pl\0" -"kwp.gov.pl\0" -"oita.oita.jp\0" -"toga.toyama.jp\0" -"himi.toyama.jp\0" -"onagawa.miyagi.jp\0" -"from-wv.com\0" -"amex\0" -"alstom\0dedyn.io\0" -"ringsaker.no\0" -"movimiento.bo\0" -"ma.gov.br\0prudential\0" -"langev\xc3\xa5g.no\0" -"vxl.sh\0" -"aogashima.tokyo.jp\0" -"shoparena.pl\0" -"midori.chiba.jp\0" -"dnsalias.org\0in.eu.org\0run.app\0" -"uji.kyoto.jp\0med.pro\0" -"rel.ht\0" -"now\0" -"kawagoe.mie.jp\0daejeon.kr\0" -"sodegaura.chiba.jp\0" -"vv.it\0kongsberg.no\0" -"fujisato.akita.jp\0" -"aseral.no\0parasite.jp\0" -"gosen.niigata.jp\0mitou.yamaguchi.jp\0*.r.appspot.com\0" -"makinohara.shizuoka.jp\0" -"fly.dev\0" -"b\xc3\xa1hcavuotna.no\0" -"s\xc3\xbc""dtirol.it\0selbu.no\0" -"l\xc3\xb8renskog.no\0" -"santoandre.br\0balsan-s\xc3\xbc""dtirol.it\0bloxcms.com\0" -"pavia.it\0" -"no-ip.org\0" -"cat.ax\0" -"aeroclub.aero\0hlx.page\0" -"takikawa.hokkaido.jp\0x.mythic-beasts.com\0" -"creditcard\0nra\0" -"eidsvoll.no\0\xe5\x85\xab\xe5\x8d\xa6\0" -"taito.tokyo.jp\0" -"lib.wi.us\0" -"matera.it\0uwajima.ehime.jp\0aibetsu.hokkaido.jp\0ericsson\0" -"tsukumi.oita.jp\0abeno.osaka.jp\0obi\0web.app\0" -"toyone.aichi.jp\0myfast.space\0" -"cc.pr.us\0" -"okinawa.okinawa.jp\0gitapp.si\0" -"nrw\0" -"ueda.nagano.jp\0sande.m\xc3\xb8re-og-romsdal.no\0knx-server.net\0" -"kawahara.tottori.jp\0bir.ru\0nyaa.am\0" -"yamato.fukushima.jp\0ota.gunma.jp\0" -"gs.ol.no\0mn.us\0" -"minamiuonuma.niigata.jp\0" -"hachinohe.aomori.jp\0" -"beta.bounty-full.com\0" -"ginowan.okinawa.jp\0" -"poniatowa.pl\0" -"shinjuku.tokyo.jp\0" -"iglesiascarbonia.it\0" -"time.no\0" -"monza.it\0" -"freeddns.us\0" -"ntt\0" -"kazimierz-dolny.pl\0" -"doesntexist.com\0" -"shinyoshitomi.fukuoka.jp\0" -"revista.bo\0\xe5\x85\xac\xe7\x9b\x8a\0" -"maceio.br\0" -"laakesvuemie.no\0" -"okaya.nagano.jp\0" -"govt.nz\0" -"up.in\0" -"tj.cn\0" -"barrell-of-knowledge.info\0" -"agro.pl\0" -"oguni.kumamoto.jp\0br.com\0" -"abira.hokkaido.jp\0" -"tachiarai.fukuoka.jp\0" -"izumi.osaka.jp\0lifeinsurance\0" -"p.bg\0" -"forl\xc3\xac""cesena.it\0" -"rel.pl\0cisco\0" -"nachikatsuura.wakayama.jp\0jls-sto1.elastx.net\0" -"brumunddal.no\0" -"gv.ao\0twmail.org\0" -"happou.akita.jp\0" -"applinzi.com\0" -"gv.at\0" -"yokoze.saitama.jp\0iide.yamagata.jp\0" -"direct\0" -"amica\0" -"kaminokawa.tochigi.jp\0" -"ragusa.it\0" -"carboniaiglesias.it\0and\xc3\xb8y.no\0weber\0" -"air-traffic-control.aero\0" -"lpages.co\0" -"cc.dc.us\0nyc\0clerkstage.app\0" -"wegrow.pl\0" -"ms.leg.br\0" -"public-inquiry.uk\0" -"bedzin.pl\0" -"yamagata.yamagata.jp\0\xe8\xb4\xad\xe7\x89\xa9\0" -"ivgu.no\0ap-northeast-3.elasticbeanstalk.com\0" -"boleslawiec.pl\0nog.community\0" -"academia.bo\0" -"mikasa.hokkaido.jp\0co.events\0" -"shikaoi.hokkaido.jp\0" -"homeftp.org\0" -"chiyoda.tokyo.jp\0" -"wazuka.kyoto.jp\0bostik\0dyn53.io\0" -"eng.br\0" -"e.bg\0palermo.it\0toyota.yamaguchi.jp\0" -"ikano\0" -"ssl.origin.cdn77-secure.org\0" -"gamagori.aichi.jp\0meldal.no\0cloudsite.builders\0" -"mt.leg.br\0" -"forum.hu\0k12.ga.us\0lib.tx.us\0" -"toshiba\0" -"km.ua\0works\0" -"world\0" -"schulserver.de\0" -"shobara.hiroshima.jp\0" -"shaw\0" -"\xe5\x85\xac\xe5\x8f\xb8\0" -"\xd0\xbe\xd1\x80\xd0\xb3.\xd1\x80\xd1\x83\xd1\x81\0" -"crown\0georgia.su\0" -"sd.cn\0" -"webview-assets.cloud9.ap-northeast-3.amazonaws.com\0" -"hiratsuka.kanagawa.jp\0" -"fla.no\0" -"\xe5\x80\x8b\xe4\xba\xba.hk\0" -"its.me\0scrysec.com\0" -"gj\xc3\xb8vik.no\0" -"alwaysdata.net\0" -"hokuto.yamanashi.jp\0" -"b\xc3\xa1l\xc3\xa1t.no\0east-kazakhstan.su\0" -"sue.fukuoka.jp\0" -"floro.no\0" -"google\0" -"photography\0" -"s\xc3\xb8mna.no\0" -"konskowola.pl\0" -"one\0" -"nic.in\0" -"ong\0mydobiss.com\0" -"enscaled.sg\0" -"\xe8\x81\x94\xe9\x80\x9a\0" -"onl\0" -"lib.il.us\0" -"schaeffler\0tashkent.su\0" -"fie.ee\0" -"*.dev-builder.code.com\0" -"likescandy.com\0shw.io\0" -"h\xc3\xb8nefoss.no\0" -"ooo\0" -"so.it\0" -"lon-1.paas.massivegrid.net\0" -"crimea.ua\0" -"chuo.chiba.jp\0daiwa.hiroshima.jp\0zara\0" -"in-vpn.org\0" -"tsushima.nagasaki.jp\0" -"tsumagoi.gunma.jp\0" -"boston\0" -"synology-diskstation.de\0" -"dazaifu.fukuoka.jp\0urawa.saitama.jp\0" -"misato.akita.jp\0" -"fashionstore.jp\0" -"usuki.oita.jp\0" -"roma.it\0" -"mcdir.me\0" -"tksat.bo\0" -"campobasso.it\0" -"leikanger.no\0eu.ax\0" -"hadano.kanagawa.jp\0" -"muroto.kochi.jp\0lib.hi.us\0" -"windows\0" -"art.br\0" -"tysnes.no\0" -"hgtv\0" -"s3.dualstack.ap-southeast-1.amazonaws.com\0" -"cc.ar.us\0" -"kisarazu.chiba.jp\0org\0" -"vallee-aoste.it\0directory\0" -"pay\0" -"izena.okinawa.jp\0krokstadelva.no\0" -"kuroiso.tochigi.jp\0" -"shia\0" -"uchinomi.kagawa.jp\0" -"kami.kochi.jp\0" -"lugansk.ua\0pstmn.io\0" -"art.do\0technology\0" -"kumenan.okayama.jp\0" -"art.dz\0" -"webhop.me\0" -"novara.it\0safety\0forumz.info\0" -"siteleaf.net\0" -"is-a-conservative.com\0" -"cc.wy.us\0" -"qc.ca\0kaszuby.pl\0yandex\0" -"oarai.ibaraki.jp\0" -"kerryproperties\0from-ok.com\0" -"ott\0" -"kozagawa.wakayama.jp\0" -"wloclawek.pl\0vfs.cloud9.eu-west-3.amazonaws.com\0" -"kaminoyama.yamagata.jp\0" -"dynalias.com\0" -"nakagusuku.okinawa.jp\0" -"il.us\0" -"ri.it\0anan.tokushima.jp\0" -"pet\0" -"\xd8\xa7\xd9\x85\xd8\xa7\xd8\xb1\xd8\xa7\xd8\xaa\0" -"minobu.yamanashi.jp\0" -"ovh\0" -"rag-cloud.hosteur.com\0" -"rikuzentakata.iwate.jp\0" -"9.bg\0indie.porn\0" -"loan\0" -"balat.no\0sorum.no\0*.sys.qcx.io\0" -"ballangen.no\0" -"kasuya.fukuoka.jp\0homedepot\0" -"oguni.yamagata.jp\0" -"hasvik.no\0s3.eu-west-3.amazonaws.com\0" -"babia-gora.pl\0murmansk.su\0" -"moriyoshi.akita.jp\0" -"clickrising.net\0" -"naturbruksgymn.se\0selfip.info\0" -"art.ht\0miyoshi.tokushima.jp\0" -"iwaki.fukushima.jp\0" -"milan.it\0phd\0" -"\xc3\xa5s.no\0cuisinella\0" -"p.se\0data\0\xd9\x83\xd8\xa7\xd8\xab\xd9\x88\xd9\x84\xd9\x8a\xd9\x83\0" -"troms\xc3\xb8.no\0" -"de.com\0" -"kazo.saitama.jp\0date\0microsoft\0" -"muos\xc3\xa1t.no\0" -"riik.ee\0" -"ina.nagano.jp\0nic.tj\0ia.us\0" -"higashimurayama.tokyo.jp\0pid\0" -"tsubame.niigata.jp\0" -"kameoka.kyoto.jp\0" -"trentinsud-tirol.it\0fe.it\0kirovograd.ua\0is-a-anarchist.com\0" -"tempio-olbia.it\0psp.gov.pl\0" -"higashiagatsuma.gunma.jp\0" -"soo.kagoshima.jp\0watches\0\xd8\xa7\xd8\xaa\xd8\xb5\xd8\xa7\xd9\x84\xd8\xa7\xd8\xaa\0" -"izu.shizuoka.jp\0" -"shop\0" -"pin\0" -"harima.hyogo.jp\0sandvikcoromant\0" -"cloudaccess.host\0" -"kuzumaki.iwate.jp\0tattoo\0" -"nhs.uk\0show\0" -"wios.gov.pl\0pages.torproject.net\0" -"ann-arbor.mi.us\0" -"ochi.kochi.jp\0sweetpepper.org\0boyfriend.jp\0" -"k12.ct.us\0" -"yombo.me\0" -"kusatsu.gunma.jp\0" -"mg.gov.br\0" -"jelenia-gora.pl\0mcdir.ru\0" -"hiji.oita.jp\0gloppen.no\0byen.site\0" -"minamiechizen.fukui.jp\0e.se\0" -"gol.no\0" -"redstone\0" -"pt.eu.org\0" -"kamiamakusa.kumamoto.jp\0" -"caltanissetta.it\0geek.nz\0gv.vc\0" -"energy\0" -"a.ssl.fastly.net\0" -"ryuoh.shiga.jp\0" -"workisboring.com\0" -"stjordal.no\0" -"localhost.daplie.me\0" -"kurgan.su\0" -"citic\0" -"wolterskluwer\0" -"ac.leg.br\0" -"kragero.no\0" -"chanel\0" -"tokyo\0" -"hjelmeland.no\0" -"madrid\0" -"journal.aero\0vfs.cloud9.ap-southeast-2.amazonaws.com\0no-ip.net\0" -"toyoake.aichi.jp\0tranoy.no\0" -"oristano.it\0" -"verm\xc3\xb6gensberater\0" -"politica.bo\0karasjohka.no\0worse-than.tv\0" -"pnc\0s3.cn-north-1.amazonaws.com.cn\0" -"air-surveillance.aero\0ofunato.iwate.jp\0" -"oyodo.nara.jp\0" -"nic.za\0" -"deporte.bo\0fr\xc3\xb8ya.no\0" -"mosj\xc3\xb8""en.no\0tselinograd.su\0" -"gs.tr.no\0sd.us\0" -"eun.eg\0" -"hapmir.no\0guardian\0" -"blogspot.co.at\0" -"kumamoto.jp\0chuo.fukuoka.jp\0" -"art.pl\0" -"repbody.aero\0kainan.wakayama.jp\0" -"alesund.no\0" -"minoh.osaka.jp\0" -"ishikawa.okinawa.jp\0bitbridge.net\0ashgabad.su\0" -"tiffany\0" -"kafjord.no\0" -"hirakata.osaka.jp\0" -"kiryu.gunma.jp\0" -"is-a-designer.com\0" -"seiro.niigata.jp\0k12.ne.us\0" -"act.au\0meraker.no\0rygge.no\0" -"unazuki.toyama.jp\0s3-us-west-2.amazonaws.com\0" -"rovno.ua\0" -"\xe0\xb8\x97\xe0\xb8\xab\xe0\xb8\xb2\xe0\xb8\xa3.\xe0\xb9\x84\xe0\xb8\x97\xe0\xb8\xa2\0" -"friulivgiulia.it\0saroma.hokkaido.jp\0daito.osaka.jp\0scholarships\0" -"aircraft.aero\0bahcavuotna.no\0" -"vardo.no\0" -"hatoyama.saitama.jp\0" -"friuliv-giulia.it\0" -"rulez.jp\0" -"ri.us\0" -"frana.no\0" -"chiryu.aichi.jp\0ullensaker.no\0" -"\xe9\x95\xb7\xe5\xb4\x8e.jp\0miyakonojo.miyazaki.jp\0" -"horse\0" -"katashina.gunma.jp\0" -"ct.it\0" -"coupon\0" -"kobierzyce.pl\0art.sn\0" -"\xc3\xa5mot.no\0" -"fukushima.jp\0" -"pro\0" -"yamanobe.yamagata.jp\0*.otap.co\0" -"otaki.saitama.jp\0" -"yokawa.hyogo.jp\0pru\0" -"gotsu.shimane.jp\0familyds.com\0" -"pages.it.hs-heilbronn.de\0" -"calabria.it\0hamatonbetsu.hokkaido.jp\0" -"barclaycard\0awsmppl.com\0" -"wodzislaw.pl\0" -"rahkkeravju.no\0" -"london.cloudapps.digital\0" -"toon.ehime.jp\0no.com\0" -"cricket\0" -"medio-campidano.it\0kvitsoy.no\0" -"bc.ca\0jls-sto3.elastx.net\0" -"ulsan.kr\0work\0knightpoint.systems\0" -"college\0" -"kashiwa.chiba.jp\0" -"barletta-trani-andria.it\0" -"kutchan.hokkaido.jp\0is-gone.com\0" -"pub\0" -"sayo.hyogo.jp\0" -"tickets.io\0" -"kawai.nara.jp\0compare\0" -"ci.it\0" -"gucci\0" -"\xe7\xb5\x84\xe7\xbb\x87.hk\0" -"tomika.gifu.jp\0tsuru.yamanashi.jp\0dyndns-at-work.com\0" -"shiriuchi.hokkaido.jp\0ditchyourip.com\0" -"homeftp.net\0" -"blogspot.com.cy\0" -"massacarrara.it\0noshiro.akita.jp\0" -"rennes\xc3\xb8y.no\0blogspot.co.id\0" -"silk\0" -"police.uk\0" -"praxi\0" -"blogspot.co.il\0" -"uryu.hokkaido.jp\0" -"blogspot.com.ee\0" -"global\0from-mt.com\0from-nd.com\0" -"forgot.her.name\0velvet.jp\0blogspot.com.eg\0" -"pwc\0" -"ibigawa.gifu.jp\0shiftcrypto.io\0" -"whoswho\0is-a-bulls-fan.com\0" -"przeworsk.pl\0" -"nishiawakura.okayama.jp\0" -"barefoot\0sina\0blogspot.com.ar\0" -"gentlentapis.com\0cutegirl.jp\0" -"xj.cn\0blogspot.com.au\0" -"ote.bj\0" -"b\xc3\xa1hccavuotna.no\0" -"\xe5\xb2\xa9\xe6\x89\x8b.jp\0ox.rs\0" -"taiki.hokkaido.jp\0" -"moriguchi.osaka.jp\0" -"koza.wakayama.jp\0" -"ah.cn\0tomisato.chiba.jp\0" -"\xe5\x95\x86\xe5\xba\x97\0" -"babymilk.jp\0" -"\xd9\x85\xd9\x88\xd9\x82\xd8\xb9\0" -"bn.it\0" -"blogspot.com.br\0" -"statefarm\0" -"oga.akita.jp\0" -"blogspot.com.by\0" -"mytuleap.com\0" -"from-or.com\0""2038.io\0" -"\xd8\xb3\xd9\x88\xd8\xb1\xd9\x8a\xd8\xa7\0repl.run\0" -"\xd8\xb3\xd9\x88\xd8\xb1\xd9\x8a\xd8\xa9\0base.ec\0" -"blogspot.com.co\0" -"udi.br\0" -"k12.ak.us\0" -"cahcesuolo.no\0consulado.st\0*.elb.amazonaws.com\0" -"watari.miyagi.jp\0leczna.pl\0k8s.fr-par.scw.cloud\0lima-city.rocks\0" -"*.sapporo.jp\0" -"oita.jp\0" -"abc.br\0" -"company\0" -"chase\0" -"s3-website-us-west-2.amazonaws.com\0" -"serveftp.com\0" -"fastvps.host\0" -"ueno.gunma.jp\0" -"pepper.jp\0" -"gs.fm.no\0love\0" -"\xe7\xbd\x91\xe7\xbb\x9c\0" -"sos.pl\0events\0but.jp\0" -"neyagawa.osaka.jp\0blogspot.com.es\0" -"asso.fr\0kurate.fukuoka.jp\0" -"group\0" -"*.quipelements.com\0" -"yamada.iwate.jp\0nakano.tokyo.jp\0" -"shiroishi.miyagi.jp\0" -"lucca.it\0" -"nagatoro.saitama.jp\0l\xc3\xa1hppi.no\0us-west-2.elasticbeanstalk.com\0" -"k12.vt.us\0" -"asso.gp\0kushiro.hokkaido.jp\0" -"vaporcloud.io\0" -"schwarz\0" -"the.br\0" -"ikaruga.nara.jp\0gniezno.pl\0" -"trentinos\xc3\xbc""dtirol.it\0isehara.kanagawa.jp\0lib.az.us\0" -"s3-website.ap-northeast-2.amazonaws.com\0" -"sakae.chiba.jp\0asago.hyogo.jp\0" -"spydeberg.no\0" -"asso.ht\0site\0" -"catanzaro.it\0divtasvuodna.no\0radio.am\0" -"owariasahi.aichi.jp\0girlfriend.jp\0" -"codeberg.page\0" -"dnshome.de\0" -"ct.us\0" -"hachioji.tokyo.jp\0" -"giehtavuoatna.no\0" -"info.gu\0" -"setouchi.okayama.jp\0schoolbus.jp\0" -"sells-for-less.com\0" -"al.leg.br\0" -"radio.br\0candypop.jp\0" -"v\xc3\xa6r\xc3\xb8y.no\0" -"info.ht\0scalebook.scw.cloud\0" -"info.hu\0" -"jed.wafaicloud.com\0" -"point2this.com\0" -"*.0emm.com\0" -"ybo.review\0" -"toyono.osaka.jp\0" -"murakami.niigata.jp\0" -"info.in\0msk.ru\0independent-panel.uk\0" -"asso.ci\0" -"holdings\0" -"dyndns1.de\0" -"flap.id\0" -"info.et\0g\xc3\xbcnstigliefern.de\0" -"seihi.nagasaki.jp\0" -"info.fj\0kinghost.net\0" -"dclk\0" -"cust.dev.thingdust.io\0" -"saga.saga.jp\0" -"msk.su\0iki.fi\0" -"dyndns.info\0dynserv.org\0" -"kaas.gg\0" -"katowice.pl\0" -"baseball\0" -"firewalledreplit.co\0" -"lib.ee\0" -"pages.wiardweb.com\0" -"mlbfan.org\0" -"satosho.okayama.jp\0mycd.eu\0" -"yamanashi.yamanashi.jp\0lima-city.de\0" -"asso.dz\0" -"kawazu.shizuoka.jp\0" -"easypanel.host\0" -"sakaki.nagano.jp\0" -"blackbaudcdn.net\0" -"kr\xc3\xb8""dsherad.no\0blogspot.co.uk\0" -"prato.it\0aejrie.no\0" -"motosu.gifu.jp\0\xe9\x80\x9a\xe8\xb2\xa9\0info.cx\0" -"radio.fm\0" -"lib.ky.us\0" -"minamiawaji.hyogo.jp\0" -"management\0" -"trento.it\0ah.no\0bar2.net\0" -"info.ec\0yotsukaido.chiba.jp\0mediatech.by\0" -"dyroy.no\0\xe5\x95\x86\xe6\xa5\xad.tw\0click\0" -"meiwa.gunma.jp\0sells-for-u.com\0" -"ip6.arpa\0usa.oita.jp\0" -"trade\0blogspot.com.mt\0" -"tsuruta.aomori.jp\0jeonnam.kr\0" -"edu.eu.org\0" -"fredrikstad.no\0*.ex.futurecms.at\0blogspot.com.ng\0" -"fitness\0adobeio-static.net\0" -"trafficplex.cloud\0" -"iwakura.aichi.jp\0shinagawa.tokyo.jp\0in-vpn.net\0lima-city.at\0" -"vt.it\0c.cdn77.org\0" -"info.bb\0" -"info.at\0" -"workinggroup.aero\0info.au\0rugby\0" -"js.wpenginepowered.com\0" -"mail-box.ne.jp\0" -"info.az\0info.bj\0" -"red\0" -"hanggliding.aero\0info.bo\0steinkjer.no\0" -"lima-city.ch\0" -"aizubange.fukushima.jp\0grong.no\0" -"ren\0" -"inabe.mie.jp\0" -"kin.okinawa.jp\0trana.no\0" -"kirkenes.no\0" -"info.co\0snillfjord.no\0" -"kuwana.mie.jp\0\xe6\x96\xb0\xe9\x97\xbb\0autocode.dev\0" -"scrapper-site.net\0" -"sebastopol.ua\0on-web.fr\0" -"vfs.cloud9.eu-central-1.amazonaws.com\0" -"soma.fukushima.jp\0" -"koto.shiga.jp\0blogspot.com.tr\0" -"kommunalforbund.se\0" -"lease\0" -"ishinomaki.miyagi.jp\0" -"a.prod.fastly.net\0" -"shiranuka.hokkaido.jp\0*.customer-oci.com\0" -"ainan.ehime.jp\0" -"narita.chiba.jp\0rishiri.hokkaido.jp\0" -"noor.jp\0" -"for-some.biz\0" -"vi.it\0bip.sh\0" -"ibara.okayama.jp\0as.us\0" -"nozawaonsen.nagano.jp\0" -"chizu.tottori.jp\0ringebu.no\0" -"bytom.pl\0" -"user.party.eus\0col.ng\0" -"jogasz.hu\0hemne.no\0" -"showa.fukushima.jp\0dnipropetrovsk.ua\0framer.app\0" -"e164.arpa\0potager.org\0" -"y.bg\0map.fastly.net\0" -"turin.it\0blogspot.co.ke\0" -"saitama.saitama.jp\0" -"miyama.fukuoka.jp\0s3-us-gov-west-1.amazonaws.com\0nsupdate.info\0" -"biei.hokkaido.jp\0iwanuma.miyagi.jp\0yonago.tottori.jp\0is.gov.pl\0" -"fujikawa.yamanashi.jp\0jp.kg\0" -"bozen.it\0dagestan.ru\0" -"salat.no\0" -"ogawa.nagano.jp\0lib.ut.us\0" -"championship.aero\0leksvik.no\0singles\0" -"mypets.ws\0" -"is-a-player.com\0" -"minamiizu.shizuoka.jp\0ril\0" -"nerdpol.ovh\0" -"jdf.br\0" -"rio\0" -"rip\0" -"tokigawa.saitama.jp\0minami-alps.yamanashi.jp\0dagestan.su\0" -"tokke.no\0" -"durban\0" -"sx.cn\0" -"tj\xc3\xb8me.no\0" -"ma.us\0" -"karacol.su\0" -"amagasaki.hyogo.jp\0" -"konyvelo.hu\0" -"mydissent.net\0hzc.io\0jp.md\0" -"ohira.tochigi.jp\0\xe0\xb9\x84\xe0\xb8\x97\xe0\xb8\xa2\0" -"komaki.aichi.jp\0" -"fauske.no\0" -"n.bg\0" -"reklam.hu\0" -"oumu.hokkaido.jp\0j\xc3\xb8rpeland.no\0" -"city.hu\0!city.sapporo.jp\0baby\0" -"powiat.pl\0" -"nisshin.aichi.jp\0yoshida.shizuoka.jp\0" -"equipment.aero\0anjo.aichi.jp\0" -"cyon.link\0blogspot.com.uy\0" -"es-1.axarnet.cloud\0" -"sondrio.it\0" -"vald-aosta.it\0kv.ua\0tank.jp\0" -"edgekey.net\0" -"blogspot.co.nz\0" -"wolomin.pl\0walter\0" -"miho.ibaraki.jp\0tjeldsund.no\0" -"\xc4\x8d\xc3\xa1hcesuolo.no\0" -"shiso.hyogo.jp\0" -"misasa.tottori.jp\0kvits\xc3\xb8y.no\0" -"dedibox.fr\0" -"from-ky.com\0" -"fussa.tokyo.jp\0mozilla-iot.org\0" -"ts.it\0" -"wzmiuw.gov.pl\0" -"chikuhoku.nagano.jp\0" -"fjell.no\0" -"iris.arpa\0" -"mydatto.net\0" -"hazu.aichi.jp\0akkeshi.hokkaido.jp\0b\xc3\xb8.nordland.no\0ubank\0" -"lyngdal.no\0" -"c.bg\0*.stg.dev\0" -"maif\0" -"fin.ci\0" -"unzen.nagasaki.jp\0" -"gub.uy\0" -"targi.pl\0nikolaev.ua\0" -"kamitonda.wakayama.jp\0asso.re\0" -"imakane.hokkaido.jp\0" -"instance.datadetect.com\0" -"itigo.jp\0" -"mokuren.ne.jp\0" -"land-4-sale.us\0" -"parma.it\0fujikawaguchiko.yamanashi.jp\0*.vps.myjino.ru\0" -"is-a-linux-user.org\0" -"nore-og-uvdal.no\0gallup\0nodes.k8s.pl-waw.scw.cloud\0" -"drive\0" -"fin.ec\0fuso.aichi.jp\0" -"friuli-venezia-giulia.it\0cloudns.eu\0" -"vt.us\0" -"cust.retrosnub.co.uk\0" -"bergamo.it\0" -"yaizu.shizuoka.jp\0info.ve\0" -"shichinohe.aomori.jp\0osoyro.no\0sorreisa.no\0" -"oi.kanagawa.jp\0kamiichi.toyama.jp\0is-a-soxfan.org\0" -"ath.cx\0" -"info.vn\0" -"tsunan.niigata.jp\0" -"gifu.gifu.jp\0toyooka.hyogo.jp\0yahaba.iwate.jp\0" -"milano.it\0" -"allstate\0" -"jur.pro\0" -"sap\0" -"hammarfeasta.no\0godaddy\0" -"engineer.aero\0sas\0" -"haugesund.no\0szkola.pl\0rexroth\0" -"aya.miyazaki.jp\0" -"sekikawa.niigata.jp\0volkswagen\0" -"sbi\0" -"*.linodeobjects.com\0" -"reggio-calabria.it\0" -"cc.mt.us\0cc.nd.us\0" -"coop.ht\0tanagura.fukushima.jp\0kamakura.kanagawa.jp\0haibara.shizuoka.jp\0amli.no\0" -"asso.nc\0ghost.io\0" -"sca\0" -"scb\0" -"niihama.ehime.jp\0sbs\0" -"glug.org.uk\0" -"info.tn\0ilovecollege.info\0" -"webthings.io\0" -"vi.us\0fnwk.site\0" -"coop.in\0info.tr\0" -"music\0skin\0" -"f\xc3\xb8rde.no\0info.tt\0pgafan.net\0" -"coop.ar\0" -"cloudns.in\0myddns.rocks\0" -"info.tz\0" -"cherkassy.ua\0" -"jetzt\0static.land\0" -"beppu.oita.jp\0bronnoysund.no\0" -"sukagawa.fukushima.jp\0" -"appspaceusercontent.com\0hosting-cluster.nl\0" -"chosei.chiba.jp\0" -"africa.com\0" -"coop.br\0" -"kikonai.hokkaido.jp\0yasuda.kochi.jp\0pointto.us\0" -"hyatt\0" -"contact\0cloudns.cc\0" -"tachikawa.tokyo.jp\0shacknet.nu\0" -"info.ro\0forte.id\0" -"delhi.in\0academy\0es.ax\0" -"amami.kagoshima.jp\0kautokeino.no\0d.gv.vc\0from-dc.com\0" -"info.sd\0" -"hachijo.tokyo.jp\0" -"run\0" -"cc.mi.us\0xii.jp\0" -"deal\0" -"mielec.pl\0sandvik\0" -"archi\0lubartow.pl\0" -"sew\0\xe0\xa4\x95\xe0\xa5\x89\xe0\xa4\xae\0" -"muroran.hokkaido.jp\0band\0sex\0" -"tas.gov.au\0bank\0browsersafetymark.io\0opensocial.site\0" -"ap-southeast-2.elasticbeanstalk.com\0" -"abu.yamaguchi.jp\0zapto.org\0" -"\xd8\xa7\xd9\x8a\xd8\xb1\xd8\xa7\xd9\x86.ir\0info.pk\0sfr\0" -"hirata.fukushima.jp\0info.pl\0blogspot.co.za\0" -"fukushima.fukushima.jp\0rwe\0" -"s3-website.eu-central-1.amazonaws.com\0" -"agency\0" -"info.pr\0" -"niikappu.hokkaido.jp\0ichikawa.hyogo.jp\0" -"users.scale.virtualcloud.com.br\0" -"is-an-engineer.com\0" -"semboku.akita.jp\0rikubetsu.hokkaido.jp\0aogaki.hyogo.jp\0" -"langevag.no\0grozny.su\0" -"c.la\0" -"abarth\0cocotte.jp\0" -"panasonic\0" -"info.na\0\xd9\x82\xd8\xb7\xd8\xb1\0" -"motorcycles\0" -"asso.km\0" -"ozu.ehime.jp\0oygarden.no\0" -"info.mv\0info.nf\0" -"hiranai.aomori.jp\0us.org\0" -"info.ni\0" -"omigawa.chiba.jp\0" -"y.se\0android\0cheap.jp\0" -"hasami.nagasaki.jp\0" -"arab\0blogsite.org\0" -"diskstation.org\0" -"sykkylven.no\0info.nr\0sumy.ua\0" -"pecori.jp\0" -"rg.it\0" -"asso.mc\0volyn.ua\0" -"kilo.jp\0" -"meguro.tokyo.jp\0" -"info.la\0cloud66.ws\0" -"7.bg\0" -"iwade.wakayama.jp\0" -"hakodate.hokkaido.jp\0" -"yabuki.fukushima.jp\0sakuho.nagano.jp\0grozny.ru\0" -"ownprovider.com\0" -"friuli-veneziagiulia.it\0" -"loginline.io\0" -"fuji.shizuoka.jp\0lukow.pl\0" -"moroyama.saitama.jp\0torsken.no\0" -"muika.niigata.jp\0" -"ski\0" -"info.ls\0" -"eu.meteorapp.com\0pro.typeform.com\0" -"bookonline.app\0" -"u.channelsdvr.net\0" -"cc.ks.us\0hermes\0pl.eu.org\0" -"jobs\0waw.pl\0" -"n.se\0cloud.goog\0" -"kita.tokyo.jp\0cymru\0fh-muenster.io\0tcp4.me\0operaunite.com\0" -"katsuura.chiba.jp\0" -"evje-og-hornnes.no\0sky\0s3.dualstack.ap-south-1.amazonaws.com\0" -"uzs.gov.pl\0" -"gs.vf.no\0" -"psc.br\0heroy.more-og-romsdal.no\0" -"takamatsu.kagawa.jp\0rade.no\0" -"isteingeek.de\0" -"ogasawara.tokyo.jp\0fhs.no\0hs.run\0" -"webcam\0" -"fc.it\0" -"ras.ru\0" -"watson.jp\0" -"mimata.miyazaki.jp\0" -"yoshinogari.saga.jp\0" -"sado.niigata.jp\0info.ke\0" -"filegear-de.me\0" -"info.ki\0r.cdn77.net\0dattorelay.com\0" -"is-an-accountant.com\0" -"nakatsugawa.gifu.jp\0*.moonscale.io\0" -"tomobe.ibaraki.jp\0" -"exnet.su\0" -"sm.ua\0" -"nom.ad\0" -"cc.wa.us\0" -"nom.ag\0zakopane.pl\0" -"belem.br\0idv.hk\0reserve-online.net\0" -"es.kr\0" -"isa.kagoshima.jp\0c.se\0" -"markets\0" -"shibata.niigata.jp\0" -"fin.tn\0" -"kariya.aichi.jp\0yokote.akita.jp\0spa\0\xe0\xa4\xb8\xe0\xa4\x82\xe0\xa4\x97\xe0\xa4\xa0\xe0\xa4\xa8\0" -"holtalen.no\0dielddanuorri.no\0cloudns.us\0fldrv.com\0" -"senasa.ar\0" -"soy\0" -"venice.it\0tools\0" -"geekgalaxy.com\0" -"takatsuki.shiga.jp\0" -"osaka.jp\0" -"nowaruda.pl\0" -"accountant\0tab\0" -"dell\0" -"architectes.bj\0\xd8\xa8\xd8\xa7\xd8\xb2\xd8\xa7\xd8\xb1\0zero\0" -"otaki.nagano.jp\0" -"nom.co\0trentin-s\xc3\xbc""d-tirol.it\0k12.oh.us\0\xe3\x82\xa2\xe3\x83\x9e\xe3\x82\xbe\xe3\x83\xb3\0" -"ryukyu\0" -"sb.ua\0dopaas.com\0gda.pl\0" -"khmelnitskiy.ua\0s3-ap-northeast-1.amazonaws.com\0" -"uk.primetel.cloud\0" -"is-a-lawyer.com\0" -"adm.br\0" -"m\xc3\xa1tta-v\xc3\xa1rjjat.no\0" -"consulting.aero\0muosat.no\0house\0" -"tax\0" -"bearalvahki.no\0" -"carrara-massa.it\0xbox\0" -"srl\0" -"karatsu.saga.jp\0fiat\0" -"friulivegiulia.it\0kr.com\0jele.site\0" -"miyashiro.saitama.jp\0" -"\xe0\xba\xa5\xe0\xba\xb2\xe0\xba\xa7\0" -"foz.br\0nishiaizu.fukushima.jp\0sp.leg.br\0" -"kinokawa.wakayama.jp\0\xd2\x9b\xd0\xb0\xd0\xb7\0" -"tci\0wroc.pl\0" -"nom.es\0" -"stargard.pl\0""1kapp.com\0" -"\xd0\xb1\xd0\xb5\xd0\xbb\0" -"stc\0meteorapp.com\0" -"ddnsgeek.com\0" -"takamori.kumamoto.jp\0" -"k12.ms.us\0k12.nc.us\0" -"nom.fr\0piacenza.it\0calvinklein\0network\0" -"taiji.wakayama.jp\0tdk\0" -"terni.it\0" -"ternopil.ua\0folionetwork.site\0" -"student.aero\0coop.rw\0" -"busan.kr\0" -"hjartdal.no\0istanbul\0vpndns.net\0" -"gs.jan-mayen.no\0" -"fido\0" -"yn.cn\0" -"tel\0" -"\xd8\xa7\xd9\x84\xd8\xb9\xd9\x84\xd9\x8a\xd8\xa7\xd9\x86\0" -"protonet.io\0" -"gs.hl.no\0" -"commune.am\0buyshouses.net\0" -"pesarourbino.it\0" -"webview-assets.cloud9.eu-south-1.amazonaws.com\0" -"cr.it\0izumozaki.niigata.jp\0" -"!city.nagoya.jp\0" -"independent-review.uk\0" -"army\0" -"coop.tt\0" -"niyodogawa.kochi.jp\0" -"folkebibl.no\0" -"flickr\0" -"gonohe.aomori.jp\0" -"minowa.nagano.jp\0vacations\0adobeaemcloud.net\0undo.jp\0" -"opole.pl\0" -"ip.linodeusercontent.com\0" -"k12.nj.us\0" -"upow.gov.pl\0" -"naganohara.gunma.jp\0" -"os.hordaland.no\0en-root.fr\0" -"desi\0" -"cuiaba.br\0coop.mv\0horten.no\0" -"hannan.osaka.jp\0coop.mw\0myshopify.com\0" -"onna.okinawa.jp\0thd\0" -"arpa\0" -"\xe7\xa6\x8f\xe5\xb2\xa1.jp\0" -"forsale\0whm.fr-par.scw.cloud\0" -"trentinostirol.it\0store\0" -"moscow\0" -"h\xc3\xb8ylandet.no\0" -"ppg.br\0" -"\xe0\xb8\xad\xe0\xb8\x87\xe0\xb8\x84\xe0\xb9\x8c\xe0\xb8\x81\xe0\xb8\xa3.\xe0\xb9\x84\xe0\xb8\x97\xe0\xb8\xa2\0" -"nom.km\0" -"cheap\0" -"servequake.com\0" -"balena-devices.com\0sopot.pl\0" -"shimamoto.osaka.jp\0" -"\xe3\x82\xb9\xe3\x83\x88\xe3\x82\xa2\0syncloud.it\0" -"dynv6.net\0" -"aioi.hyogo.jp\0" -"tama.tokyo.jp\0" -"gs.oslo.no\0" -"lib.mo.us\0" -"nom.mg\0" -"inc.hk\0" -"vennesla.no\0saves-the-whales.com\0" -"kanazawa.ishikawa.jp\0hiphop\0\xe7\xbd\x91\xe5\xba\x97\0" -"atami.shizuoka.jp\0" -"coop.py\0" -"gives\0cloudns.pw\0" -"tjx\0" -"izumo.shimane.jp\0pages.dev\0is-a-socialist.com\0" -"nagasaki.jp\0" -"nom.nc\0search\0" -"idv.tw\0" -"anpachi.gifu.jp\0tienda\0" -"averoy.no\0*.sch.uk\0" -"nom.ni\0" -"hobol.no\0" -"homeip.net\0" -"kanzaki.saga.jp\0asda\0" -"qld.edu.au\0winb.gov.pl\0" -"temasek\0" -"bl.it\0arte\0" -"casacam.net\0" -"gujarat.in\0" -"ne.jp\0" -"aarborte.no\0" -"sec.ps\0" -"info.zm\0" -"ne.ke\0" -"film\0hobby-site.com\0" -"isen.kagoshima.jp\0coop.km\0" -"nom.pa\0" -"stordal.no\0" -"nom.pe\0engineer\0" -"lib.nh.us\0" -"shingu.wakayama.jp\0ne.kr\0lib.as.us\0" -"nom.pl\0" -"bbva\0" -"comcast\0" -"123webseite.de\0" -"pol.dz\0americanexpress\0" -"opal.ne.jp\0" -"minamiyamashiro.kyoto.jp\0\xe3\x82\xb3\xe3\x83\xa0\0" -"miami\0" -"s3-website.eu-west-3.amazonaws.com\0" -"salud.bo\0is-a-geek.com\0crap.jp\0" -"kristiansund.no\0dyndns.tv\0myspreadshop.co.uk\0" -"poa.br\0olbiatempio.it\0" -"pa.gov.br\0trentino-suedtirol.it\0" -"yasu.shiga.jp\0" -"aq.it\0ba.it\0toyoura.hokkaido.jp\0" -"\xd1\x83\xd0\xbf\xd1\x80.\xd1\x81\xd1\x80\xd0\xb1\0s3.dualstack.eu-west-3.amazonaws.com\0" -"nom.re\0" -"al.eu.org\0" -"top\0" -"gaivuotna.no\0chernivtsi.ua\0" -"\xe9\x9d\x92\xe6\xa3\xae.jp\0tatsuno.hyogo.jp\0" -"kunitomi.miyazaki.jp\0" -"hiraya.nagano.jp\0" -"123webseite.at\0" -"med.br\0nom.ro\0" -"awsglobalaccelerator.com\0" -"dsmynas.org\0" -"xfinity\0" -"*.cryptonomic.net\0from-ut.com\0" -"samnanger.no\0zt.ua\0education\0akamaiorigin-staging.net\0" -"maserati\0supply\0" -"airport.aero\0faststacks.net\0" -"lib.me.us\0" -"kiwa.mie.jp\0*.diher.solutions\0" -"yakumo.hokkaido.jp\0" -"blogdns.org\0" -"pb.gov.br\0funagata.yamagata.jp\0cr.ua\0" -"asia\0usr.cloud.muni.cz\0" -"trentin-sud-tirol.it\0" -"is-a-green.com\0" -"dyndns.ws\0" -"ufcfan.org\0" -"saobernardo.br\0no.eu.org\0" -"ok.us\0" -"pol.ht\0" -"nom.tm\0" -"press\0" -"lo.it\0honjo.saitama.jp\0webview-assets.cloud9.ca-central-1.amazonaws.com\0" -"med.ec\0\xe7\xbe\xa4\xe9\xa6\xac.jp\0" -"med.ee\0*.firenet.ch\0" -"hopto.me\0" -"gliwice.pl\0" -"fire\0" -"barsy.net\0" -"ubs\0\xe5\x98\x89\xe9\x87\x8c\xe5\xa4\xa7\xe9\x85\x92\xe5\xba\x97\0" -"sth.ac.at\0bryansk.su\0" -"aichi.jp\0egoism.jp\0" -"trv\0" -"backplaneapp.io\0" -"ne.pw\0url.tw\0" -"nom.ve\0playstation-cloud.com\0" -"aisai.aichi.jp\0kep.tr\0" -"katori.chiba.jp\0" -"is-a-musician.com\0" -"kitashiobara.fukushima.jp\0" -"fish\0" -"radoy.no\0" -"higashiyama.kyoto.jp\0" -"ariake.saga.jp\0koya.wakayama.jp\0" -"trapani.it\0" -"nishiokoppe.hokkaido.jp\0kobayashi.miyazaki.jp\0" -"eero.online\0" -"shiojiri.nagano.jp\0" -"pinoko.jp\0omg.lol\0" -"leirfjord.no\0lotte\0" -"trentino-s-tirol.it\0como.it\0minamata.kumamoto.jp\0" -"s\xc3\xb8rreisa.no\0" -"enebakk.no\0" -"from-tx.com\0" -"kota.aichi.jp\0" -"res.in\0" -"lotto\0" -"\xc3\xa5snes.no\0tui\0" -"hoteles\0bounty-full.com\0" -"space-to-rent.com\0gsj.bz\0" -"*.svc.firenet.ch\0" -"urbino-pesaro.it\0" -"tako.chiba.jp\0niki.hokkaido.jp\0yamatokoriyama.nara.jp\0nissedal.no\0" -"giske.no\0" -"mangyshlak.su\0" -"stokke.no\0jp.ngrok.io\0hotelwithflight.com\0" -"med.ht\0niigata.jp\0fukui.fukui.jp\0*.on-k3s.io\0" -"secure\0" -"yachts\0*.code.run\0sumomo.ne.jp\0" -"physio\0" -"daisen.akita.jp\0valer.hedmark.no\0readymade.jp\0" -"gobo.wakayama.jp\0" -"tvs\0vs.mythic-beasts.com\0" -"sellfy.store\0" -"tsuyama.okayama.jp\0bananarepublic\0webview-assets.cloud9.us-east-1.amazonaws.com\0" -"\xd0\xbe\xd0\xb4.\xd1\x81\xd1\x80\xd0\xb1\0" -"ne.ug\0" -"nom.za\0" -"creditunion\0from-nv.com\0" -"ne.tz\0" -"boldlygoingnowhere.org\0" -"fuchu.tokyo.jp\0nz.eu.org\0" -"ne.us\0fentiger.mythic-beasts.com\0" -"vr.it\0frontier\0" -"taishin.fukushima.jp\0discordsays.com\0" -"trading\0" -"orkanger.no\0" -"ggf.br\0valer.ostfold.no\0armenia.su\0" -"podzone.net\0ipifony.net\0" -"natori.miyagi.jp\0" -"koobin.events\0eating-organic.net\0" -"ascolipiceno.it\0" -"servebeer.com\0" -"ltda\0" -"zao.miyagi.jp\0slask.pl\0lanxess\0west1-us.cloudjiffy.net\0" -"\xe4\xba\xac\xe9\x83\xbd.jp\0roros.no\0" -"doomdns.com\0" -"is-a-geek.org\0" -"fosnes.no\0" -"kira.aichi.jp\0halsa.no\0" -"vaksdal.no\0immobilien\0" -"takashima.shiga.jp\0" -"*.platformsh.site\0" -"asahi.mie.jp\0commbank\0" -"himeshima.oita.jp\0" -"lebork.pl\0" -"hakui.ishikawa.jp\0" -"saiki.oita.jp\0" -"\xd9\x83\xd9\x88\xd9\x85\0" -"med.ly\0nz.basketball\0" -"fukuoka.jp\0" -"cn.com\0" -"sdn.gov.pl\0careers\0" -"h\xc3\xb8yanger.no\0logoip.de\0" -"tourism.tn\0" -"hidora.com\0" -"mayfirst.info\0su.paba.se\0" -"doesntexist.org\0" -"s3-eu-west-1.amazonaws.com\0" -"is-with-theband.com\0" -"w.bg\0jprs\0isa-geek.org\0" -"ciencia.bo\0balsfjord.no\0genting\0" -"hosp.uk\0" -"\xc3\xb8vre-eiker.no\0" -"bindal.no\0sanok.pl\0" -"val-d-aosta.it\0midtre-gauldal.no\0" -"democrat\0" -"lenug.su\0" -"med.om\0sncf\0" -"cruises\0" -"matsuyama.ehime.jp\0" -"med.pa\0" -"aramco\0" -"toyota.aichi.jp\0oto.fukuoka.jp\0andasuolo.no\0" -"kai.yamanashi.jp\0" -"numata.gunma.jp\0" -"spjelkavik.no\0ca.reclaim.cloud\0" -"med.pl\0" -"pol.tr\0" -"nakagyo.kyoto.jp\0omihachiman.shiga.jp\0hamamatsu.shizuoka.jp\0digital\0" -"tome.miyagi.jp\0dabur\0" -"m\xc3\xa5s\xc3\xb8y.no\0" -"is.it\0" -"maibara.shiga.jp\0privatelink.snowflake.app\0" -"saijo.ehime.jp\0" -"risor.no\0" -"kisosaki.mie.jp\0uno\0\xe6\x8b\x9b\xe8\x81\x98\0" -"perso.ht\0" -"l.bg\0pi.gov.br\0" -"tateshina.nagano.jp\0littlestar.jp\0" -"barsy.pro\0" -"uol\0gr.com\0" -"miyama.mie.jp\0machida.tokyo.jp\0" -"galsa.no\0woltlab-demo.com\0" -"onion\0med.sa\0handcrafted.jp\0" -"sk.ca\0" -"bod\xc3\xb8.no\0notteroy.no\0virtualserver.io\0" -"tanohata.iwate.jp\0med.sd\0cc.oh.us\0" -"principe.st\0" -"aknoluokta.no\0" -"cieszyn.pl\0" -"cc.co.us\0" -"hiroshima.jp\0" -"*.oci.customer-oci.com\0" -"mizumaki.fukuoka.jp\0ups\0" -"tennis\0" -"pvh.br\0" -"to.leg.br\0" -"gs.mr.no\0" -"hb.cn\0" -"vagan.no\0dyn.ddnss.de\0" -"sumoto.kumamoto.jp\0" -"barsy.pub\0" -"arna.no\0" -"it.com\0" -"odawara.kanagawa.jp\0" -"rocher\0" -"a.bg\0" -"issmarterthanyou.com\0" -"nohost.me\0" -"\xd7\x99\xd7\xa9\xd7\x95\xd7\x91.\xd7\x99\xd7\xa9\xd7\xa8\xd7\x90\xd7\x9c\0inuyama.aichi.jp\0" -"za.com\0" -"mizuho.tokyo.jp\0" -"net.eu.org\0" -"abiko.chiba.jp\0" -"freesite.host\0" -"16-b.it\0" -"gg.ax\0" -"froland.no\0" -"pilot.aero\0chuo.tokyo.jp\0" -"minato.tokyo.jp\0cc.nm.us\0market\0gov.scot\0" -"trentinoalto-adige.it\0vana\0" -"\xe6\x88\x91\xe7\x88\xb1\xe4\xbd\xa0\0sg-1.paas.massivegrid.net\0" -"ltd.co.im\0" -"saitama.jp\0yamada.toyama.jp\0" -"higashisumiyoshi.osaka.jp\0" -"sv.it\0rybnik.pl\0navoi.su\0" -"bolivia.bo\0" -"from-sc.com\0" -"s3-eu-central-1.amazonaws.com\0flynnhosting.net\0" -"krasnodar.su\0hasura-app.io\0" -"shinjo.okayama.jp\0" -"tsukuba.ibaraki.jp\0is-a-liberal.com\0*.uberspace.de\0" -"mihama.fukui.jp\0for-our.info\0" -"weibo\0" -"dev.br\0" -"kamikitayama.nara.jp\0" -"fuoisku.no\0farmers\0toray\0" -"kharkov.ua\0" -"vet\0" -"koka.shiga.jp\0nordreisa.no\0" -"srv.br\0reviews\0" -"\xd9\x85\xd8\xb5\xd8\xb1\0" -"review\0" -"agr.br\0" -"pe.gov.br\0" -"shop.brendly.rs\0" -"shinshiro.aichi.jp\0" -"tourism.pl\0" -"kamo.niigata.jp\0" -"sic.it\0" -"gr.it\0" -"myds.me\0" -"christmas\0cookingchannel\0" -"*.stg-builder.code.com\0" -"s3.dualstack.us-east-1.amazonaws.com\0" -"s3-website.fr-par.scw.cloud\0" -"is-a-nascarfan.com\0loginline.dev\0" -"gr.jp\0myvnc.com\0" -"toyama.jp\0" -"valle.no\0" -"nord-odal.no\0diskussionsbereich.de\0" -"ozora.hokkaido.jp\0" -"gyeongnam.kr\0" -"tourism.bj\0kakinoki.shimane.jp\0vig\0" -"goiania.br\0hm.no\0" -"lilly\0isa-geek.com\0" -"\xe9\x9d\x99\xe5\xb2\xa1.jp\0" -"fusa.no\0dnsiskinky.com\0" -"trentino-aadige.it\0" -"vin\0skygearapp.com\0" -"adobeioruntime.net\0" -"vip\0" -"kitaakita.akita.jp\0" -"siracusa.it\0" -"is-a-knight.org\0" -"ua.rs\0" -"kawaguchi.saitama.jp\0" -"raindrop.jp\0" -"boo.jp\0" -"hasama.oita.jp\0" -"kitakata.miyazaki.jp\0meet\0" -"mus.br\0" -"trentin-suedtirol.it\0leitungsen.de\0cust.prod.thingdust.io\0""12hp.de\0" -"government.aero\0" -"mt.eu.org\0" -"sa.ngrok.io\0basicserver.io\0" -"hanamaki.iwate.jp\0" -"fishing\0" -"audi\0" -"pa.gov.pl\0" -"w.se\0" -"tondabayashi.osaka.jp\0" -"hinode.tokyo.jp\0" -"kitagata.saga.jp\0nagahama.shiga.jp\0" -"12hp.at\0" -"phx.enscaled.us\0" -"hemnes.no\0" -"hizen.saga.jp\0" -"re.it\0discover\0" -"watarai.mie.jp\0" -"toki.gifu.jp\0" -"oystre-slidre.no\0" -"arai.shizuoka.jp\0" -"beer\0" -"finn\xc3\xb8y.no\0" -"5.bg\0kiho.mie.jp\0mysecuritycamera.net\0ynh.fr\0" -"inami.toyama.jp\0" -"*.on-rio.io\0" -"hashikami.aomori.jp\0netbank\0""12hp.ch\0" -"aremark.no\0" -"chichibu.saitama.jp\0barrel-of-knowledge.info\0" -"council.aero\0" -"mitake.gifu.jp\0" -"barsy.org\0" -"cooperativa.bo\0" -"nakatane.kagoshima.jp\0" -"eidskog.no\0bel.tr\0" -"obu.aichi.jp\0suzaka.nagano.jp\0" -"*.kawasaki.jp\0ravendb.cloud\0tempurl.host\0" -"otoyo.kochi.jp\0" -"re.kr\0" -"coach\0" -"k12.ec\0" -"cc.la.us\0sakura.tv\0" -"fukumitsu.toyama.jp\0" -"togliatti.su\0" -"l.se\0" -"nittedal.no\0" -"chikushino.fukuoka.jp\0""611.to\0dyndns-pics.com\0azimuth.network\0" -"bulsan-suedtirol.it\0lolipopmc.jp\0" -"*.in.futurecms.at\0" -"matsuzaki.shizuoka.jp\0" -"pz.it\0" -"\xe6\x89\x8b\xe6\x9c\xba\0" -"wake.okayama.jp\0" -"s\xc3\xb8r-aurdal.no\0" -"itcouldbewor.se\0" -"pr.gov.br\0\xe7\x82\xb9\xe7\x9c\x8b\0" -"takaishi.osaka.jp\0flor\xc3\xb8.no\0" -"*.bd\0kustanai.ru\0freemyip.com\0" -"in-dsl.org\0" -"hu.com\0" -"perso.sn\0" -"family\0definima.io\0" -"sasayama.hyogo.jp\0" -"foggia.it\0gos.pk\0" -"kustanai.su\0" -"meme\0deci.jp\0" -"inami.wakayama.jp\0" -"togane.chiba.jp\0lib.fl.us\0is-into-anime.com\0" -"perso.tn\0from-mo.com\0" -"takahata.yamagata.jp\0" -"*.ck\0kamaishi.iwate.jp\0" -"adv.br\0sohu\0mywire.org\0" -"a.se\0" -"datsun\0" -"eu-west-1.elasticbeanstalk.com\0" -"\xc3\xb8ksnes.no\0" -"api.stdlib.com\0" -"angry.jp\0" -"ruovat.no\0" -"boomla.net\0" -"po.it\0" -"osaka\0b.ssl.fastly.net\0" -"nissan\0" -"snasa.no\0" -"k12.il\0skjervoy.no\0dsmynas.net\0" -"sanda.hyogo.jp\0" -"menu\0" -"wafflecell.com\0" -"nissay\0" -"hughes\0podzone.org\0" -"nishio.aichi.jp\0" -"forlicesena.it\0blogdns.net\0" -"kumano.hiroshima.jp\0" -"\xe9\xa6\x99\xe5\xb7\x9d.jp\0otofuke.hokkaido.jp\0" -"loginto.me\0" -"gujo.gifu.jp\0k12.nv.us\0dnsfor.me\0" -"*.er\0hammerfest.no\0" -"ogimi.okinawa.jp\0legal\0" -"is-a-geek.net\0" -"is-a-hunter.com\0" -"cc.ut.us\0" -"yamashina.kyoto.jp\0" -"*.fk\0" -"tamamura.gunma.jp\0my.eu.org\0my-wan.de\0" -"chikuma.nagano.jp\0" -"viking\0" -"kyoto.jp\0" -"iwanai.hokkaido.jp\0guide\0" -"eurovision\0" -"shimizu.hokkaido.jp\0" -"tatebayashi.gunma.jp\0dyndns.biz\0" -"ot.it\0pd.it\0" -"shimabara.nagasaki.jp\0mimoza.jp\0" -"utazas.hu\0" -"doctor\0" -"cs.keliweb.cloud\0" -"pub.sa\0" -"airkitapps.com\0" -"toyotsu.fukuoka.jp\0taobao\0" -"vallee-d-aoste.it\0uppo.gov.pl\0dubai\0passagens\0" -"rost.no\0credit\0customer.speedpartner.de\0" -"6g.in\0" -"sobetsu.hokkaido.jp\0" -"internet-dns.de\0" -"tobe.ehime.jp\0" -"ryugasaki.ibaraki.jp\0" -"joburg\0song\0" -"tokushima.jp\0" -"val-daosta.it\0endofinternet.net\0" -"church\0" -"pharmacien.fr\0" -"kozaki.chiba.jp\0" -"crd.co\0" -"yuki.ibaraki.jp\0" -"wanouchi.gifu.jp\0vfs.cloud9.eu-west-2.amazonaws.com\0" -"sony\0cloudcontrolapp.com\0" -"kikuchi.kumamoto.jp\0" -"chikuho.fukuoka.jp\0" -"filegear.me\0" -"sagamihara.kanagawa.jp\0win\0" -"fl.us\0hopto.org\0" -"bj.cn\0*.jm\0dev.vu\0" -"istmein.de\0" -"valledaosta.it\0" -"casino\0" -"news.hu\0vega.no\0" -"*.kh\0diet\0" -"flir\0" -"oracle\0" -"grajewo.pl\0" -"cloud.interhostsolutions.be\0" -"beauty\0at-band-camp.net\0" -"nishihara.kumamoto.jp\0sochi.su\0" -"sel.no\0" -"cc.tn.us\0" -"nl.eu.org\0" -"\xe9\xb9\xbf\xe5\x85\x90\xe5\xb3\xb6.jp\0kalisz.pl\0" -"verbania.it\0" -"lillesand.no\0" -"friuli-ve-giulia.it\0money\0unicom\0" -"best\0" -"luster.no\0" -"airbus\0q-a.eu.org\0" -"forli-cesena.it\0hitachinaka.ibaraki.jp\0*.mm\0" -"insurance\0" -"\xe6\x96\xb0\xe6\xbd\x9f.jp\0auto\0" -"klabu.no\0" -"ce.it\0obama.fukui.jp\0wme\0freetls.fastly.net\0" -"cesenaforl\xc3\xac.it\0" -"luxe\0" -"dscloud.me\0" -"*.np\0" -"kure.hiroshima.jp\0" -"sakai.ibaraki.jp\0yamanouchi.nagano.jp\0forsand.no\0fastvps.site\0" -"sekigahara.gifu.jp\0" -"adv.mz\0" -"vfs.cloud9.ap-northeast-1.amazonaws.com\0" -"clerk.app\0" -"vao.it\0kanra.gunma.jp\0" -"federation.aero\0hs.zone\0" -"tsuiki.fukuoka.jp\0" -"*.pg\0" -"livorno.it\0" -"onomichi.hiroshima.jp\0k12.tr\0" -"babyblue.jp\0" -"per.la\0" -"from-md.com\0isa-geek.net\0" -"ms.it\0" -"wakasa.tottori.jp\0" -"nombre.bo\0" -"wow\0gb.net\0" -"sveio.no\0getmyip.com\0" -"napoli.it\0" -"trentin-sued-tirol.it\0" -"po.gov.pl\0bentley\0" -"fuossko.no\0" -"\xe0\xa4\xad\xe0\xa4\xbe\xe0\xa4\xb0\xe0\xa5\x8b\xe0\xa4\xa4\0host\0lighting\0from-fl.com\0" -"broker.aero\0" -"sande.vestfold.no\0k12.vi\0rgr.jp\0" -"k12.wa.us\0" -"chtr.k12.ma.us\0" -"group.aero\0showa.yamanashi.jp\0vfs.cloud9.ap-southeast-1.amazonaws.com\0" -"gallo\0" -"from-az.net\0" -"nov.ru\0" -"kakegawa.shizuoka.jp\0" -"itakura.gunma.jp\0nordre-land.no\0" -"lib.nj.us\0" -"s3-ap-northeast-2.amazonaws.com\0" -"ms.kr\0bu.no\0" -"ng.eu.org\0" -"conference.aero\0" -"kochi.jp\0" -"per.nf\0" -"tosa.kochi.jp\0" -"nov.su\0barsyonline.co.uk\0" -"ddnss.de\0" -"amazon\0sucks\0" -"muko.kyoto.jp\0" -"hemsedal.no\0inderoy.no\0svelvik.no\0canon\0framer.media\0" -"cloudcontrolled.com\0" -"shiraoi.hokkaido.jp\0df.leg.br\0" -"nakagawa.tokushima.jp\0k\xc3\xa1r\xc3\xa1\xc5\xa1johka.no\0paroch.k12.ma.us\0" -"nuoro.it\0" -"ao.it\0" -"shizuoka.shizuoka.jp\0royrvik.no\0webhosting.be\0" -"id.forgerock.io\0tlon.network\0" -"nango.fukushima.jp\0" -"r\xc3\xa6lingen.no\0" -"opoczno.pl\0balashov.su\0" -"starostwo.gov.pl\0from-wy.com\0" -"\xe7\xb6\xb2\xe7\xb5\xa1.\xe9\xa6\x99\xe6\xb8\xaf\0" -"daigo.ibaraki.jp\0" -"yanagawa.fukuoka.jp\0wtc\0" -"gunma.jp\0shimane.shimane.jp\0" -"wtf\0" -"olayan\0" -"samsclub\0" -"toda.saitama.jp\0" -"shingu.hyogo.jp\0azurewebsites.net\0" -"cyou\0" -"kyotango.kyoto.jp\0kilatiron.com\0" -"vard\xc3\xb8.no\0total\0" -"azurestaticapps.net\0" -"sanuki.kagawa.jp\0" -"gojome.akita.jp\0""123hjemmeside.no\0" -"joinville.br\0" -"repair\0" -"semine.miyagi.jp\0ny.us\0" -"kawaminami.miyazaki.jp\0" -"u2-local.xnbay.com\0" -"reservd.disrec.thingdust.io\0" -"\xe6\x85\x88\xe5\x96\x84\0" -"kimino.wakayama.jp\0" -"neko.am\0" -"cdn-edges.net\0" -"tokoname.aichi.jp\0" -"\xe6\xb7\xa1\xe9\xa9\xac\xe9\x94\xa1\0" -"ad.jp\0" -"per.sg\0\xe0\xb6\xbd\xe0\xb6\x82\xe0\xb6\x9a\xe0\xb7\x8f\0" -"rj.leg.br\0" -"lib.wy.us\0" -"onga.fukuoka.jp\0selfip.net\0" -"ehime.jp\0" -"dish\0" -"holmestrand.no\0lib.ak.us\0nyc.mn\0" -"kitagawa.miyazaki.jp\0" -"est.pr\0" -"campidano-medio.it\0karmoy.no\0" -"nakagawa.fukuoka.jp\0" -"rocks\0" -"edgesuite.net\0shiftedit.io\0" -"jl.cn\0" -"blackfriday\0" -"app.os.stg.fedoraproject.org\0" -"kr.it\0" -"ninomiya.kanagawa.jp\0" -"namie.fukushima.jp\0mints.ne.jp\0" -"divttasvuotna.no\0" -"viterbo.it\0" -"kokubunji.tokyo.jp\0\xc3\xa5mli.no\0" -"esashi.hokkaido.jp\0xin\0" -"honai.ehime.jp\0" -"spot\0" -"agents.aero\0" -"etnedal.no\0bialowieza.pl\0" -"carraramassa.it\0" -"g12.br\0" -"trd.br\0games\0" -"mysecuritycamera.org\0" -"modena.it\0" -"nc.tr\0" -"yufu.oita.jp\0" -"shirahama.wakayama.jp\0base.shop\0" -"gjerstad.no\0prime\0" -"valdaosta.it\0" -"riopreto.br\0" -"ms.us\0nc.us\0" -"campidanomedio.it\0" -"az.us\0" -"ube.yamaguchi.jp\0" -"staging.onred.one\0" -"sunndal.no\0" -"togura.nagano.jp\0" -"from-pa.com\0" -"in-dsl.net\0" -"nishinoshima.shimane.jp\0" -"kddi\0" -"gloomy.jp\0customer.mythic-beasts.com\0" -"whitesnow.jp\0" -"no-ip.biz\0" -"skaun.no\0crafting.xyz\0" -"lohmus.me\0" -"herokuapp.com\0" -"minamiboso.chiba.jp\0kawakita.ishikawa.jp\0" -"numazu.shizuoka.jp\0" -"*.kobe.jp\0" -"hokuto.hokkaido.jp\0kg.kr\0" -"tsuruga.fukui.jp\0" -"gratangen.no\0lasalle\0" -"skodje.no\0" -"florence.it\0small-web.org\0" -"bible\0" -"ogliastra.it\0iwi.nz\0fra1-de.cloudjiffy.net\0appchizi.com\0" -"kaneyama.fukushima.jp\0" -"*.spectrum.myjino.ru\0" -"mytabit.com\0", - -"s3-website.eu-west-2.amazonaws.com\0" -"shingu.fukuoka.jp\0accenture\0" -"gs.of.no\0""123hjemmeside.dk\0" -"ve.it\0" -"wedding\0" -"meloy.no\0" -"kitami.hokkaido.jp\0" -"naka.hiroshima.jp\0" -"wanggou\0is-a-hard-worker.com\0" -"u.bg\0" -"piemonte.it\0" -"ecn.br\0kyowa.akita.jp\0" -"ashiya.fukuoka.jp\0\xe0\xae\x9a\xe0\xae\xbf\xe0\xae\x99\xe0\xaf\x8d\xe0\xae\x95\xe0\xae\xaa\xe0\xaf\x8d\xe0\xae\xaa\xe0\xaf\x82\xe0\xae\xb0\xe0\xaf\x8d\0" -"yokohama\0" -"asaminami.hiroshima.jp\0omi.niigata.jp\0" -"kawachinagano.osaka.jp\0" -"rindal.no\0nexus\0" -"kazuno.akita.jp\0azure\0" -"mombetsu.hokkaido.jp\0mw.gov.pl\0my-gateway.de\0" -"fujimino.saitama.jp\0" -"kamisunagawa.hokkaido.jp\0webview-assets.cloud9.eu-north-1.amazonaws.com\0cafjs.com\0" -"cc.pa.us\0" -"l\xc3\xa6rdal.no\0" -"hol.no\0" -"kumano.mie.jp\0" -"oyabe.toyama.jp\0" -"adult\0domains\0" -"wv.us\0" -"fujiyoshida.yamanashi.jp\0dojin.com\0" -"law.pro\0" -"trentins\xc3\xbc""dtirol.it\0" -"hk.cn\0" -"takasu.hokkaido.jp\0" -"rimini.it\0bajddar.no\0" -"rodeo\0" -"vfs.cloud9.me-south-1.amazonaws.com\0" -"priv.instances.scw.cloud\0" -"author.aero\0realestate.pl\0" -"authgear-staging.com\0" -"j.bg\0loginline.app\0" -"amscompute.com\0" -"ms.gov.br\0otsuki.kochi.jp\0travelers\0" -"to.gt\0" -"os.hedmark.no\0" -"tamatsukuri.ibaraki.jp\0quebec\0in-berlin.de\0" -"ktistory.com\0" -"tokai.aichi.jp\0" -"eng.pro\0" -"\xe6\x9d\xb1\xe4\xba\xac.jp\0kr.ua\0" -"ato.br\0" -"gjerdrum.no\0" -"cc.nv.us\0" -"name.hr\0oirm.gov.pl\0simplesite.com\0" -"urausu.hokkaido.jp\0better-than.tv\0" -"hangout\0" -"umb.it\0" -"delta\0" -"nakagawa.hokkaido.jp\0" -"kujukuri.chiba.jp\0" -"mt.gov.br\0haram.no\0cloud\0" -"to.it\0kyiv.ua\0bona.jp\0" -"drangedal.no\0" -"aguni.okinawa.jp\0" -"name.et\0" -"mitoyo.kagawa.jp\0" -"tottori.jp\0kayabe.hokkaido.jp\0" -"name.fj\0" -"lazio.it\0" -"iitate.fukushima.jp\0yuu.yamaguchi.jp\0" -"kagami.kochi.jp\0" -"froya.no\0" -"consultant.aero\0ohtawara.tochigi.jp\0wmcloud.org\0" -"talk\0" -"orskog.no\0" -"leg.br\0" -"kotohira.kagawa.jp\0luxury\0" -"ipiranga\0" -"observer\0home.dyndns.org\0" -"paragliding.aero\0" -"sener\0" -"rr.leg.br\0rdv.to\0" -"\xc3\xb8ystre-slidre.no\0sirdal.no\0vaga.no\0" -"fujioka.gunma.jp\0perma.jp\0" -"girly.jp\0" -"fujieda.shizuoka.jp\0" -"venezia.it\0soccer\0" -"sor-fron.no\0" -"trentinos\xc3\xbc""d-tirol.it\0dattolocal.net\0" -"versicherung\0to.md\0" -"zuerich\0" -"trani-barletta-andria.it\0" -"fukui.jp\0" -"paas.massivegrid.com\0reserve-online.com\0" -"masfjorden.no\0" -"karaganda.su\0" -"name.eg\0" -"\xe8\x8c\xa8\xe5\x9f\x8e.jp\0" -"tara.saga.jp\0" -"drayddns.com\0nfshost.com\0" -"gen.in\0" -"rs.leg.br\0sc.leg.br\0homesecuritymac.com\0" -"mj\xc3\xb8ndalen.no\0" -"xxx\0" -"det.br\0" -"plc.ly\0winners\0" -"\xe0\xae\x87\xe0\xae\xb2\xe0\xae\x99\xe0\xaf\x8d\xe0\xae\x95\xe0\xaf\x88\0" -"name.az\0" -"laspezia.it\0lund.no\0" -"tozsde.hu\0feste-ip.net\0" -"lyngen.no\0" -"kasama.ibaraki.jp\0" -"dr\xc3\xb8""bak.no\0" -"xyz\0" -"money.bj\0lk3.ru\0" -"tos.it\0" -"auction\0" -"1.azurestaticapps.net\0" -"fj.cn\0si.it\0" -"hoplix.shop\0" -"gs.aa.no\0" -"ibaraki.osaka.jp\0" -"inder\xc3\xb8y.no\0marker.no\0\xe0\xb4\xad\xe0\xb4\xbe\xe0\xb4\xb0\xe0\xb4\xa4\xe0\xb4\x82\0" -"s3.dualstack.eu-west-1.amazonaws.com\0" -"virtualuser.de\0" -"study\0" -"lenvik.no\0" -"shimotsuma.ibaraki.jp\0us-east-1.amazonaws.com\0" -"iamallama.com\0" -"hoyanger.no\0walmart\0" -"servesarcasm.com\0" -"sugito.saitama.jp\0ardal.no\0endofinternet.org\0" -"bizen.okayama.jp\0place\0" -"h\xc3\xa6gebostad.no\0" -"st.no\0lib.sd.us\0" -"kalmykia.su\0" -"valleaosta.it\0soundcast.me\0" -"cc.me.us\0" -"maizuru.kyoto.jp\0" -"hb.cldmail.ru\0" -"cc.al.us\0gen.ng\0" -"shimonoseki.yamaguchi.jp\0" -"iki.nagasaki.jp\0" -"fr-1.paas.massivegrid.net\0" -"qh.cn\0trentinsudtirol.it\0swidnica.pl\0" -"kasamatsu.gifu.jp\0toyotomi.hokkaido.jp\0jelastic.saveincloud.net\0" -"v\xc3\xa5ler.hedmark.no\0" -"rn.it\0est-a-la-masion.com\0" -"ge.it\0rsc.cdn77.org\0" -"kui.hiroshima.jp\0" -"de.cool\0" -"gen.nz\0" -"ashibetsu.hokkaido.jp\0" -"latrobe\0" -"business.in\0niiza.saitama.jp\0rn.leg.br\0" -"ed.ao\0afjord.no\0melbourne\0ngrok.app\0" -"skjerv\xc3\xb8y.no\0" -"harstad.no\0" -"\xe3\x82\xaf\xe3\x83\xa9\xe3\x82\xa6\xe3\x83\x89\0" -"kalmykia.ru\0" -"you\0" -"zp.gov.pl\0if.ua\0sharp\0" -"servepics.com\0" -"shinonsen.hyogo.jp\0leirvik.no\0agakhan\0" -"opencraft.hosting\0" -"vip.jelastic.cloud\0" -"2ix.at\0" -"u.se\0" -"ferrari\0kyoto\0*.dapps.earth\0jellybean.jp\0" -"investments\0" -"kiwi.nz\0" -"ino.kochi.jp\0\xe4\xb8\xad\xe6\x96\x87\xe7\xbd\x91\0" -"ed.ci\0" -"stj\xc3\xb8rdalshalsen.no\0" -"ro.leg.br\0firewall-gateway.de\0" -"oguchi.aichi.jp\0" -"rc.it\0" -"uk.oxa.cloud\0" -"biella.it\0" -"conf.au\0" -"ed.cr\0plc.uk\0" -"hamaroy.no\0" -"memset.net\0" -"2ix.ch\0" -"unj\xc3\xa1rga.no\0" -"hamura.tokyo.jp\0" -"taxi\0" -"3.bg\0alto-adige.it\0codes\0is-a-techie.com\0" -"pb.ao\0shioya.tochigi.jp\0is-a-landscaper.com\0" -"ralingen.no\0" -"vestnes.no\0" -"or.at\0" -"\xe3\x82\xbb\xe3\x83\xbc\xe3\x83\xab\0nodes.k8s.nl-ams.scw.cloud\0" -"2ix.de\0" -"medicina.bo\0k12.or.us\0" -"or.bi\0bnr.la\0" -"murayama.yamagata.jp\0k12.co.us\0" -"kita.osaka.jp\0" -"fuchu.toyama.jp\0" -"tagami.niigata.jp\0" -"alibaba\0" -"nis.za\0" -"pro.az\0" -"wakayama.jp\0shangrila\0" -"or.ci\0linkyard-cloud.ch\0" -"yamatsuri.fukushima.jp\0globo\0" -"pro.br\0" -"gen.tr\0is-by.us\0" -"shizukuishi.iwate.jp\0" -"or.cr\0alipay\0" -"act.edu.au\0" -"itabashi.tokyo.jp\0mytis.ru\0user.srcf.net\0" -"komatsu.ishikawa.jp\0" -"not.br\0minamisanriku.miyagi.jp\0" -"erotica.hu\0" -"og.ao\0" -"tingvoll.no\0" -"furubira.hokkaido.jp\0" -"adimo.co.uk\0" -"kitagata.gifu.jp\0" -"pro.cy\0yun\0" -"muni.il\0" -"nt.edu.au\0aoste.it\0vpnplus.to\0" -"lubin.pl\0name.vn\0" -"agrar.hu\0" -"skierv\xc3\xa1.no\0" -"pro.ec\0quicksytes.com\0" -"omasvuotna.no\0" -"tours\0\xe4\xbd\x9b\xe5\xb1\xb1\0" -"ac.gov.br\0" -"myamaze.net\0loginline.site\0" -"\xe6\x94\xbf\xe5\xba\x9c\0" -"minamiashigara.kanagawa.jp\0kamiizumi.saitama.jp\0softbank\0" -"nanbu.yamanashi.jp\0" -"us-4.evennode.com\0now-dns.top\0" -"b\xc3\xb8.telemark.no\0mer\xc3\xa5ker.no\0" -"bas.it\0bestbuy\0fashion\0streamlit.app\0" -"wphostedmail.com\0" -"\xe5\xbe\xb3\xe5\xb3\xb6.jp\0" -"chu.jp\0" -"pro.fj\0name.tj\0" -"s3-eu-west-3.amazonaws.com\0" -"\xe3\x82\xb0\xe3\x83\xbc\xe3\x82\xb0\xe3\x83\xab\0" -"lynx.mythic-beasts.com\0" -"trentinosud-tirol.it\0name.tr\0" -"name.tt\0" -"schokokeks.net\0" -"ed.jp\0otama.fukushima.jp\0" -"\xe0\xb8\x84\xe0\xb8\xad\xe0\xb8\xa1\0s3.dualstack.ap-northeast-2.amazonaws.com\0" -"cnpy.gdn\0" -"ba.leg.br\0" -"s3-ap-south-1.amazonaws.com\0" -"tomigusuku.okinawa.jp\0" -"kasahara.gifu.jp\0" -"tananger.no\0" -"nl.ca\0vikna.no\0on-aptible.com\0" -"or.id\0kawakami.nara.jp\0" -"elk.pl\0dev-myqnapcloud.com\0" -"zip\0" -"123kotisivu.fi\0" -"nl.ci\0" -"turystyka.pl\0" -"kikugawa.shizuoka.jp\0" -"pdns.page\0" -"pro.ht\0" -"mihama.wakayama.jp\0center\0" -"or.it\0cloud-fr1.unispace.io\0" -"shirako.chiba.jp\0" -"marshalls\0webview-assets.cloud9.ap-southeast-2.amazonaws.com\0" -"degree\0" -"kiyokawa.kanagawa.jp\0" -"pro.in\0" -"trani-andria-barletta.it\0" -"us-3.evennode.com\0" -"prd.fr\0or.jp\0" -"withyoutube.com\0" -"maniwa.okayama.jp\0" -"mihara.hiroshima.jp\0or.ke\0cust.disrec.thingdust.io\0" -"dray-dns.de\0" -"selfip.org\0" -"bomlo.no\0" -"name.pm\0" -"tran\xc3\xb8y.no\0" -"name.qa\0reservd.testing.thingdust.io\0" -"name.pr\0" -"trentino-altoadige.it\0" -"fukusaki.hyogo.jp\0or.kr\0lib.ct.us\0builders\0" -"sakae.nagano.jp\0" -"storebase.store\0" -"kurogi.fukuoka.jp\0cc.in.us\0" -"askim.no\0vagsoy.no\0" -"s3.isk01.sakurastorage.jp\0" -"xz.cn\0webview-assets.cloud9.us-west-2.amazonaws.com\0" -"name.na\0m\xc4\x81ori.nz\0se.leg.br\0" -"cn.in\0name.mv\0" -"name.ng\0" -"og.it\0" -"name.my\0" -"cn.it\0" -"furukawa.miyagi.jp\0" -"gov.nc.tr\0" -"niteroi.br\0ollo\0" -"farsund.no\0" -"yamanashi.jp\0" -"or.na\0v\xc3\xa5ler.\xc3\xb8stfold.no\0" -"or.mu\0" -"namaste.jp\0" -"i234.me\0" -"hsbc\0icbc\0" -"ed.pw\0" -"sci.eg\0est-le-patron.com\0" -"pro.na\0" -"lib.nv.us\0us-2.evennode.com\0" -"\xe5\x95\x86\xe6\xa0\x87\0" -"pro.mv\0lib.ca.us\0" -"cc.hn\0" -"food\0" -"lebtimnetz.de\0" -"sakura.tochigi.jp\0" -"jcloud-ver-jpc.ik-server.com\0" -"am.br\0otsu.shiga.jp\0" -"kunigami.okinawa.jp\0prd.km\0" -"resindevice.io\0" -"wedeploy.sh\0" -"matsue.shimane.jp\0" -"gs.sf.no\0lipsy\0" -"matsumae.hokkaido.jp\0" -"tajiri.osaka.jp\0" -"yoro.gifu.jp\0name.mk\0digick.jp\0" -"port.fr\0" -"bs.it\0pro.om\0" -"noda.iwate.jp\0arakawa.tokyo.jp\0am.leg.br\0" -"iglesias-carbonia.it\0" -"ohi.fukui.jp\0limanowa.pl\0" -"maori.nz\0expert\0sport\0" -"trentinoaadige.it\0" -"ddnsking.com\0" -"tonosho.kagawa.jp\0" -"prd.mg\0" -"r\xc3\xb8""d\xc3\xb8y.no\0" -"or.pw\0" -"unjarga.no\0beep.pl\0" -"name.jo\0her\xc3\xb8y.nordland.no\0pomorze.pl\0k12.la.us\0id.firewalledreplit.co\0bss.design\0" -"pro.pr\0" -"bolt.hu\0lib.ms.us\0lib.nc.us\0" -"bhz.br\0" -"higashishirakawa.gifu.jp\0conf.se\0leadpages.co\0" -"ford\0us.reclaim.cloud\0" -"ab.ca\0hole.no\0" -"tsuga.tochigi.jp\0sk\xc3\xa5nland.no\0" -"noheji.aomori.jp\0taka.hyogo.jp\0" -"utsunomiya.tochigi.jp\0us-1.evennode.com\0" -"kaisei.kanagawa.jp\0" -"bike\0" -"bahccavuotna.no\0official.ec\0" -"mini\0s3-website-sa-east-1.amazonaws.com\0" -"na.it\0" -"association.aero\0" -"tatsuno.nagano.jp\0prochowice.pl\0sling\0" -"cable-modem.org\0" -"from-ia.com\0" -"nakamichi.yamanashi.jp\0mint\0is-a-rockstar.com\0" -"gjesdal.no\0" -"kawanabe.kagoshima.jp\0" -"fbx-os.fr\0" -"floripa.br\0mihama.mie.jp\0kunitachi.tokyo.jp\0" -"jotelulu.cloud\0" -"taketa.oita.jp\0shunan.yamaguchi.jp\0eu.platform.sh\0" -"andria-trani-barletta.it\0pistoia.it\0cc.na\0leka.no\0" -"or.th\0ngrok.dev\0" -"dyn.cosidns.de\0" -"\xe6\x84\x9b\xe7\x9f\xa5.jp\0" -"trentino-sud-tirol.it\0" -"horonobe.hokkaido.jp\0" -"kumakogen.ehime.jp\0" -"nl.no\0" -"loab\xc3\xa1t.no\0" -"asahi.ibaraki.jp\0" -"democracia.bo\0vinnytsia.ua\0or.ug\0" -"kihoku.ehime.jp\0skype\0" -"tgory.pl\0or.tz\0ddnss.org\0*.futurecms.at\0" -"health.nz\0" -"virgin\0" -"wajima.ishikawa.jp\0achi.nagano.jp\0lplfinancial\0" -"hakone.kanagawa.jp\0" -"pro.tt\0" -"warabi.saitama.jp\0kosuge.yamanashi.jp\0or.us\0bing\0" -"hiroo.hokkaido.jp\0kochi.kochi.jp\0komoro.nagano.jp\0" -"am.in\0swiss\0" -"wroclaw.pl\0" -"shonai.yamagata.jp\0" -"cloudns.club\0" -"saotome.st\0" -"ap.leg.br\0" -"eid.no\0" -"balsan-sudtirol.it\0bloomberg\0" -"myfirewall.org\0" -"v\xc3\xa1rgg\xc3\xa1t.no\0" -"nakamura.kochi.jp\0gotdns.com\0" -"iservschule.de\0" -"kanagawa.jp\0is-a-chef.org\0townnews-staging.com\0" -"moriyama.shiga.jp\0" -"staples\0" -"pro.vn\0" -"cards\0dh.bytemark.co.uk\0" -"zp.ua\0" -"omura.nagasaki.jp\0online\0" -"her.jp\0xnbay.com\0" -"onjuku.chiba.jp\0lib.mi.us\0" -"egersund.no\0" -"miyako.fukuoka.jp\0" -"cn.ua\0cloudfront.net\0" -"natal.br\0" -"evenassi.no\0" -"al.gov.br\0" -"vodka\0" -"vfs.cloud9.eu-west-1.amazonaws.com\0" -"osasco.br\0tamaki.mie.jp\0" -"my-firewall.org\0" -"berlev\xc3\xa5g.no\0" -"familyds.net\0" -"dnsking.ch\0" -"2-d.jp\0wedeploy.me\0" -"tokyo.jp\0" -"kawanehon.shizuoka.jp\0" -"shimane.jp\0kumatori.osaka.jp\0" +"eg\0" +"dz\0" "is-a-financialadvisor.com\0" -"sphinx.mythic-beasts.com\0" -"netflix\0" -"tinn.no\0" -"cn.vu\0" -"k12.vi.us\0" -"warszawa.pl\0s3-website-eu-west-1.amazonaws.com\0us.ax\0" -"boutique\0" -"nishikatsura.yamanashi.jp\0zhytomyr.ua\0oncilla.mythic-beasts.com\0" -"bsb.br\0aizumi.tokushima.jp\0xen.prgmr.com\0" -"star\0tr.eu.org\0" -"cc.ua\0" -"showtime\0" -"ogaki.gifu.jp\0steigen.no\0" -"witd.gov.pl\0" -"maison\0" -"nirasaki.yamanashi.jp\0\xd7\xa7\xd7\x95\xd7\x9d\0" -"yame.fukuoka.jp\0hiraizumi.iwate.jp\0" -"sasaguri.fukuoka.jp\0sano.tochigi.jp\0conf.lv\0webview-assets.cloud9.ap-northeast-2.amazonaws.com\0" -"streamlitapp.com\0" -"vercelli.it\0yamaxun\0" -"user.webaccel.jp\0" -"tsuchiura.ibaraki.jp\0is-a-chef.com\0" -"health.vn\0qpon\0" -"johana.toyama.jp\0" -"kitaura.miyazaki.jp\0" -"arendal.no\0fakefur.jp\0" -"kitadaito.okinawa.jp\0" -"yawata.kyoto.jp\0" -"lib.vt.us\0" -"aju.br\0" -"trentino-s\xc3\xbc""dtirol.it\0marnardal.no\0aivencloud.com\0supabase.in\0" -"zamami.okinawa.jp\0" -"alta.no\0mattel\0gdansk.pl\0" -"lig.it\0" -"nakanoto.ishikawa.jp\0" -"certification.aero\0" -"lancaster\0onthewifi.com\0" -"tainai.niigata.jp\0grimstad.no\0" -"iwatsuki.saitama.jp\0charity\0" -"catering\0" -"fortal.br\0nanporo.hokkaido.jp\0" -"dnepropetrovsk.ua\0" -"alpha.bounty-full.com\0" -"molise.it\0" -"yokkaichi.mie.jp\0" -"osen.no\0cyon.site\0" -"fastvps-server.com\0" -"id.au\0nishikata.tochigi.jp\0" -"k12.id.us\0lib.va.us\0" -"lv.ua\0lifestyle\0" -"arita.saga.jp\0" -"iz.hr\0" -"askoy.no\0readmyblog.org\0" -"dyr\xc3\xb8y.no\0" -"trentinosuedtirol.it\0kadena.okinawa.jp\0uy.com\0jelastic.dogado.eu\0" -"kiso.nagano.jp\0haebaru.okinawa.jp\0myforum.community\0" -"us.in\0" -"net-freaks.com\0" -"gs.nt.no\0olkusz.pl\0" -"vc.it\0" -"is-a-painter.com\0" -"ekloges.cy\0" -"kutno.pl\0" -"trainer.aero\0tm.cy\0kopervik.no\0" -"odo.br\0" -"\xe5\xaf\x8c\xe5\xb1\xb1.jp\0" -"s.bg\0" -"ju.mp\0mcpre.ru\0" -"lombardia.it\0on-the-web.tv\0eu.pythonanywhere.com\0" -"chieti.it\0us.kg\0" -"altervista.org\0voorloper.cloud\0" -"mat.br\0fujinomiya.shizuoka.jp\0dst.mi.us\0" -"\xe7\xbb\x84\xe7\xbb\x87\xe6\x9c\xba\xe6\x9e\x84\0" -"\xe3\x83\x9d\xe3\x82\xa4\xe3\x83\xb3\xe3\x83\x88\0" -"tm.dz\0" -"rishirifuji.hokkaido.jp\0lviv.ua\0" -"hamar.no\0couchpotatofries.org\0" -"tec.br\0" -"okuizumo.shimane.jp\0" -"stockholm\0\xd8\xa7\xd8\xb1\xd8\xa7\xd9\x85\xd9\x83\xd9\x88\0mymailer.com.tw\0" -"shisui.chiba.jp\0pixolino.com\0supabase.co\0" -"tsubetsu.hokkaido.jp\0" -"\xe8\xb0\xb7\xe6\xad\x8c\0" -"chikugo.fukuoka.jp\0" -"b\xc3\xa1id\xc3\xa1r.no\0" -"avoues.fr\0genova.it\0" -"kagamiishi.fukushima.jp\0kashiba.nara.jp\0higashimatsuyama.saitama.jp\0" -"isahaya.nagasaki.jp\0" -"io.in\0philips\0" -"tm.fr\0pescara.it\0" -"hi.cn\0" -"kanegasaki.iwate.jp\0" -"okayama.jp\0" -"iheya.okinawa.jp\0" -"accident-prevention.aero\0marketing\0" -"wedeploy.io\0" -"us.na\0" -"h.bg\0" -"playstation\0fantasyleague.cc\0" -"nagareyama.chiba.jp\0" -"vlaanderen\0" -"yamada.fukuoka.jp\0hanyu.saitama.jp\0myqnapcloud.com\0io.kg\0" -"fastly-terrarium.com\0vercel.app\0" -"date.fukushima.jp\0takahashi.okayama.jp\0s3.eu-west-2.amazonaws.com\0" -"audible\0j.scaleforce.net\0" -"tm.hu\0mibu.tochigi.jp\0" -"meland.no\0" -"orkdal.no\0" -"cal.it\0wi.us\0" -"webview-assets.cloud9.sa-east-1.amazonaws.com\0ap-northeast-2.elasticbeanstalk.com\0" -"honbetsu.hokkaido.jp\0" -"edugit.io\0" -"id.ir\0bydgoszcz.pl\0" -"try-snowplow.com\0" -"co.education\0" -"pup.gov.pl\0" -"video.hu\0" -"katsuyama.fukui.jp\0" -"kvam.no\0ivano-frankivsk.ua\0" -"geometre-expert.fr\0" -"fvg.it\0s\xc3\xb8r-fron.no\0" -"\xe7\xa6\x8f\xe4\xba\x95.jp\0" -"red.sv\0ryd.wafaicloud.com\0" -"ninohe.iwate.jp\0tm.km\0nesset.no\0" -"vn.ua\0" -"hikari.yamaguchi.jp\0nl-ams-1.baremetal.scw.cloud\0" -"v-info.info\0" -"is-saved.org\0" -"vps-host.net\0" -"musashino.tokyo.jp\0" -"naruto.tokushima.jp\0granvin.no\0gmail\0" -"herad.no\0" -"gc.ca\0" -"team\0" -"urayasu.chiba.jp\0" -"is-a-candidate.org\0" -"natural.bo\0" -"tm.mc\0" -"shizuoka.jp\0ishikawa.fukushima.jp\0" -"sr.it\0umig.gov.pl\0sa-east-1.elasticbeanstalk.com\0" -"ascoli-piceno.it\0" -"tm.mg\0fastlylb.net\0" -"ong.br\0chikujo.fukuoka.jp\0id.lv\0" -"*.northflank.app\0" -"id.ly\0" -"takarazuka.hyogo.jp\0" -"morioka.iwate.jp\0" -"nagato.yamaguchi.jp\0" -"trentinos-tirol.it\0hareid.no\0" -"pantheonsite.io\0" -"usui.fukuoka.jp\0dynvpn.de\0" -"from-al.com\0" -"tech\0" -"balestrand.no\0" -"takahama.aichi.jp\0" -"tm.no\0mortgage\0from-ms.com\0from-nc.com\0" -"uk.eu.org\0" -"game\0dyndns-free.com\0" -"ishigaki.okinawa.jp\0kamimine.saga.jp\0" -"yahiko.niigata.jp\0" -"bjark\xc3\xb8y.no\0caa.li\0" -"bokn.no\0" -"cc.mn.us\0" -"members.linode.com\0" -"functions.fnc.fr-par.scw.cloud\0" -"miyoshi.saitama.jp\0cbg.ru\0" -"qoto.io\0" -"kariwa.niigata.jp\0" -"zapto.xyz\0" -"nyuzen.toyama.jp\0usercontent.jp\0" -"lon-2.paas.massivegrid.net\0" -"webredirect.org\0" -"tm.pl\0" -"pinb.gov.pl\0" -"oppdal.no\0" -"shinanomachi.nagano.jp\0" -"emergency.aero\0" -"yao.osaka.jp\0" -"sanagochi.tokushima.jp\0" -"furano.hokkaido.jp\0thick.jp\0" -"tmp.br\0" -"eidsberg.no\0" -"kumejima.okinawa.jp\0dontexist.net\0" -"lib.ga.us\0" -"simple-url.com\0" -"myoko.niigata.jp\0" -"takazaki.miyazaki.jp\0" -"nes.akershus.no\0" -"hattfjelldal.no\0konin.pl\0" -"tateyama.chiba.jp\0test-iserv.de\0" -"\xe7\xa7\xbb\xe5\x8a\xa8\0" -"tm.ro\0" -"tx.us\0" -"*.sendai.jp\0republican\0ybo.party\0" -"ieee\0" -"tm.se\0novecore.site\0" -"nakasatsunai.hokkaido.jp\0" -"simplesite.com.br\0" -"tadaoka.osaka.jp\0\xd1\x81\xd0\xb0\xd0\xbc\xd0\xb0\xd1\x80\xd0\xb0.\xd1\x80\xd1\x83\xd1\x81\0" -"g\xc3\xa1ls\xc3\xa1.no\0" -"s\xc3\xb8rfold.no\0" -"kitchen\0" -"ibaraki.jp\0s\xc3\xa1l\xc3\xa1t.no\0ny-1.paas.massivegrid.net\0musician.io\0" -"webhop.info\0" -"yasuoka.nagano.jp\0*.magentosite.cloud\0" -"kunneppu.hokkaido.jp\0" -"is-a-chef.net\0" -"oirase.aomori.jp\0sauda.no\0k12.pa.us\0" -"coolblog.jp\0" -"mobara.chiba.jp\0" -"vall\xc3\xa9""edaoste.it\0" -"selfip.biz\0" -"plumbing\0" -"adobeaemcloud.com\0" -"s.se\0" -"api.gov.uk\0" -"sm\xc3\xb8la.no\0" -"kusatsu.shiga.jp\0" -"yashio.saitama.jp\0" -"id.us\0uni5.net\0" -"ra.it\0\xe6\x96\xb0\xe5\x8a\xa0\xe5\x9d\xa1\0" -"nishiarita.saga.jp\0" -"udine.it\0" -"sandoy.no\0" -"atm.pl\0" -"aid.pl\0free\0mock.pstmn.io\0repl.co\0" -"mykolaiv.ua\0tuleap-partners.com\0" -"1.bg\0limited\0" -"feira.br\0servehumour.com\0" -"smushcdn.com\0" -"midsund.no\0" -"upper.jp\0" -"hirokawa.fukuoka.jp\0" -"obihiro.hokkaido.jp\0rl.no\0k12.de.us\0" -"bieszczady.pl\0" -"eaton.mi.us\0florist\0lublin.pl\0" -"iruma.saitama.jp\0gotpantheon.com\0" -"*.kunden.ortsinfo.at\0" -"wassamu.hokkaido.jp\0sumita.iwate.jp\0chernigov.ua\0" -"yuzawa.niigata.jp\0" -"\xc3\xb8rland.no\0\xd8\xa8\xda\xbe\xd8\xa7\xd8\xb1\xd8\xaa\0s3-website.pl-waw.scw.cloud\0" -"entertainment.aero\0aomori.aomori.jp\0kawajima.saitama.jp\0matta-varjjat.no\0tuva.su\0" -"rio.br\0tranibarlettaandria.it\0h.se\0" -"chikusei.ibaraki.jp\0hiho.jp\0" -"\xe0\xb8\xa8\xe0\xb8\xb6\xe0\xb8\x81\xe0\xb8\xa9\xe0\xb8\xb2.\xe0\xb9\x84\xe0\xb8\x97\xe0\xb8\xa2\0cloud.jelastic.open.tim.it\0" -"centralus.azurestaticapps.net\0" -"shouji\0" -"chiyoda.gunma.jp\0tec.ve\0" -"hi.us\0" -"pv.it\0" -"docs\0" -"cloudns.info\0" -"9guacu.br\0" -"health\0" -"tm.za\0" -"camera\0" -"yabu.hyogo.jp\0webhop.biz\0chips.jp\0" -"trieste.it\0noto.ishikawa.jp\0" -"kawakami.nagano.jp\0omi.nagano.jp\0kvinesdal.no\0" -"\xe3\x81\xbf\xe3\x82\x93\xe3\x81\xaa\0glitch.me\0" -"ibestad.no\0cityeats\0" -"lavangen.no\0" -"cloudapp.net\0" -"appspacehosted.com\0" -"sandnes.no\0shell\0" -"nu.ca\0" -"abashiri.hokkaido.jp\0" -"aurskog-h\xc3\xb8land.no\0" -"miyada.nagano.jp\0" -"brand.se\0" -"shinjo.yamagata.jp\0" -"fukagawa.hokkaido.jp\0ushiku.ibaraki.jp\0" -"translated.page\0" -"gbiz\0" -"dr.in\0h\xc3\xa1pmir.no\0webview-assets.cloud9.eu-west-3.amazonaws.com\0" -"lakas.hu\0ohira.miyagi.jp\0s\xc3\xb8gne.no\0" -"memorial\0" -"s3.dualstack.eu-west-2.amazonaws.com\0" -"surf\0" -"kijo.miyazaki.jp\0" -"salerno.it\0" -"nishitosa.kochi.jp\0zone\0" -"shikokuchuo.ehime.jp\0" -"urbinopesaro.it\0higashimatsushima.miyagi.jp\0" -"lib.or.us\0" -"yatomi.aichi.jp\0tomari.hokkaido.jp\0\xd0\xba\xd0\xbe\xd0\xbc\0" -"tsurugashima.saitama.jp\0nishiazai.shiga.jp\0" -"chimkent.su\0" -"rovigo.it\0komvux.se\0is-a-patsfan.org\0" -"s3.dualstack.eu-central-1.amazonaws.com\0" -"beagleboard.io\0" -"shikabe.hokkaido.jp\0stange.no\0" -"familyds.org\0" -"norton\0" -"kids\0" -"taa.it\0" -"\xc3\xb8rsta.no\0fh.se\0" -"fot.br\0" -"tur.ar\0gyeonggi.kr\0capoo.jp\0" -"a\xc3\xa9roport.ci\0tunk.org\0" -"kadogawa.miyazaki.jp\0" -"sondre-land.no\0" -"dr.na\0" -"pymnt.uk\0dscloud.biz\0" -"teva\0" -"tur.br\0daegu.kr\0k12.nm.us\0" -"nanmoku.gunma.jp\0" -"legnica.pl\0" -"dynalias.net\0gentapps.com\0" -"direct.quickconnect.cn\0reservd.com\0" -"stord.no\0" -"chijiwa.nagasaki.jp\0ojiya.niigata.jp\0" -"isesaki.gunma.jp\0nankoku.kochi.jp\0" -"cc.il.us\0" -"monster\0" -"hokkaido.jp\0" -"dyndns-mail.com\0" -"sigdal.no\0spdns.eu\0" -"ce.leg.br\0" -"ferrero\0cdn.prod.atlassian-dev.net\0selfip.com\0" -"mo.cn\0lier.no\0" -"kosaka.akita.jp\0" -"varggat.no\0" -"nu.it\0" -"grondar.za\0" -"bauhaus\0" -"delivery\0" -"cl.it\0frei.no\0" -"kyonan.chiba.jp\0" -"media\0greater.jp\0penne.jp\0" -"asuke.aichi.jp\0" -"esp.br\0" -"kepno.pl\0" -"oketo.hokkaido.jp\0" -"moriya.ibaraki.jp\0" -"\xd0\xba\xd1\x80\xd1\x8b\xd0\xbc.\xd1\x80\xd1\x83\xd1\x81\0" -"ogawa.saitama.jp\0" -"trentino-stirol.it\0" -"komatsu\0" -"shimokawa.hokkaido.jp\0" -"tamayu.shimane.jp\0" -"frogn.no\0style\0" -"guitars\0" -"k12.md.us\0" -"tomiya.miyagi.jp\0" -"lib.oh.us\0" -"kashima.ibaraki.jp\0rzgw.gov.pl\0" -"lecco.it\0" -"\xe4\xb8\xad\xe4\xbf\xa1\0" -"ebetsu.hokkaido.jp\0" -"morotsuka.miyazaki.jp\0" -"googlecode.com\0" -"cc.ia.us\0in-brb.de\0" -"barsyonline.com\0" -"is-slick.com\0" -"imb.br\0yazu.tottori.jp\0" -"hokksund.no\0" -"md.ci\0irish\0" -"nokia\0" -"trentinsued-tirol.it\0" -"ca.in\0jele.cloud\0" -"*.user.localcert.dev\0" -"s3.ca-central-1.amazonaws.com\0" -"yoshikawa.saitama.jp\0clubmed\0" -"holy.jp\0" -"ca.it\0" -"xx.gl\0" -"is-a-teacher.com\0" -"ichihara.chiba.jp\0" -"trentinosudtirol.it\0gran.no\0" -"jozi.biz\0*.nodebalancer.linode.com\0" -"aaa.pro\0*.tst.site\0" -"coz.br\0" -"demon.nl\0" -"alsace\0" -"lib.ne.us\0editorx.io\0" -"jls-sto2.elastx.net\0""123miweb.es\0" -"services.aero\0slz.br\0" -"dr.tr\0from-mn.com\0" -"indigena.bo\0" -"discount\0" -"kvinnherad.no\0app.os.fedoraproject.org\0" -"yachiyo.ibaraki.jp\0hlx3.page\0spdns.de\0" -"kiev.ua\0" -"sor-odal.no\0" -"open\0" -"dealer\0" -"gamvik.no\0" -"ravendb.me\0" -"webview-assets.cloud9.eu-west-2.amazonaws.com\0" -"blog\0\xe9\x9b\xbb\xe8\xa8\x8a\xe7\x9b\x88\xe7\xa7\x91\0" -"production.aero\0mo.it\0tanabe.wakayama.jp\0" -"av.it\0" -"lorenskog.no\0enterprisecloud.nu\0" -"apps.lair.io\0" -"togo.aichi.jp\0" -"backdrop.jp\0" -"kommune.no\0" -"salon\0" -"ca.na\0is-leet.com\0" -"ichikai.tochigi.jp\0" -"enna.it\0" -"visa\0" -"kokonoe.oita.jp\0mragowo.pl\0" -"nakaniikawa.toyama.jp\0" -"cc.sd.us\0vp4.me\0" -"etajima.hiroshima.jp\0" -"redirectme.net\0" -"suzuka.mie.jp\0" -"realm.cz\0" -"friuliveneziagiulia.it\0tychy.pl\0" -"aver\xc3\xb8y.no\0" -"charter.aero\0" -"webview-assets.cloud9.ap-east-1.amazonaws.com\0" -"kusu.oita.jp\0hob\xc3\xb8l.no\0" -"trading.aero\0iobb.net\0" -"lt.it\0" -"\xd8\xb4\xd8\xa8\xd9\x83\xd8\xa9\0" -"namdalseid.no\0" -"\xe5\xb2\x90\xe9\x98\x9c.jp\0" -"safety.aero\0" -"vix.br\0aurskog-holand.no\0" -"chikuzen.fukuoka.jp\0otobe.hokkaido.jp\0" -"fujitsu\0" -"org.ac\0viva\0" -"cnt.br\0" -"org.ae\0promo\0" -"org.af\0" +"eu.ngrok.io\0" +"es\0k12.nj.us\0" +"et\0verbania.it\0" +"eu\0life\0store\0" +"deta.dev\0" +"joburg\0mc.eu.org\0app.os.stg.fedoraproject.org\0" +"es.ax\0" +"fi\0" +"fj\0" +"fm\0" +"fo\0lavagis.no\0mer\xc3\xa5ker.no\0\xc3\xb8ksnes.no\0s\xc3\xb8rum.no\0" +"ishikawa.jp\0mihama.aichi.jp\0shibetsu.hokkaido.jp\0noda.iwate.jp\0matsuura.nagasaki.jp\0kurobe.toyama.jp\0yura.wakayama.jp\0iide.yamagata.jp\0" +"ga\0" +"leg.br\0fr\0gb\0jcb\0" +"gd\0" +"ge\0pyatigorsk.ru\0myjino.ru\0lk3.ru\0" +"gf\0" +"gg\0panel.gg\0" +"gh\0" +"gi\0wiki\0" +"gl\0" +"gm\0s3.dualstack.eu-west-3.amazonaws.com\0s3-sa-east-1.amazonaws.com\0" +"gn\0" +"gp\0" +"gq\0" +"gr\0" +"gs\0lib.mo.us\0" +"gt\0gorizia.it\0siena.it\0ist\0fastlylb.net\0jc.neen.it\0""64-b.it\0" +"gu\0forsale\0" +"gw\0lt.eu.org\0" +"gy\0energy\0" +"hk\0" +"zgora.pl\0" +"hm\0" +"hn\0\xe5\x95\x86\xe5\x9f\x8e\0" +"stat.no\0moskenes.no\0" +"chiryu.aichi.jp\0iwakura.aichi.jp\0kusatsu.gunma.jp\0ichikawa.hyogo.jp\0wakuya.miyagi.jp\0tsuwano.shimane.jp\0yasugi.shimane.jp\0" +"hr\0" +"org.ac\0myphotos.cc\0" +"ht\0id\0" +"org.ae\0hu\0ie\0" +"org.af\0\xd8\xb3\xd9\x88\xd8\xaf\xd8\xa7\xd9\x86\0itv\0" "org.ag\0" -"zaporizhzhia.ua\0business\0" -"org.ai\0iopsys.se\0" -"tamakawa.fukushima.jp\0" -"express.aero\0\xe6\xb2\x96\xe7\xb8\x84.jp\0" -"org.al\0" -"org.am\0birkenes.no\0verisign\0" -"cc.ri.us\0synology.me\0" -"pigboat.jp\0" -"test.tj\0" -"org.ba\0ujitawara.kyoto.jp\0vivo\0" -"org.ar\0org.bb\0aso.kumamoto.jp\0vercel.dev\0" -"sayama.saitama.jp\0" -"org.au\0skoczow.pl\0" -"kani.gifu.jp\0" +"org.ai\0" +"org.al\0il\0" +"org.am\0im\0s3.dualstack.ap-southeast-2.amazonaws.com\0ddnsgeek.com\0mysecuritycamera.com\0" +"in\0development.run\0" +"io\0sandcats.io\0" +"iris.arpa\0org.ba\0iq\0" +"org.ar\0org.bb\0ir\0" +"is\0" +"it\0pug.it\0firenze.it\0*.cryptonomic.net\0" +"org.au\0je\0wine\0cloudns.eu\0" "org.bh\0" -"org.bi\0aisho.shiga.jp\0karelia.su\0" +"org.bi\0yodobashi\0" "org.az\0org.bj\0" -"gliding.aero\0" -"blue\0" -"org.bm\0js.cn\0reggiocalabria.it\0" -"org.bn\0" -"org.bo\0" -"li.it\0nara.nara.jp\0" +"secaas.hk\0" +"org.bm\0" +"org.bn\0porn\0" +"org.bo\0jo\0fylkesbibl.no\0jorpeland.no\0elverum.no\0jondal.no\0r\xc3\xa1isa.no\0sogndal.no\0suldal.no\0varggat.no\0vpnplus.to\0" +"jp\0kazuno.akita.jp\0utashinai.hokkaido.jp\0sado.niigata.jp\0kakinoki.shimane.jp\0" +"otsuka\0" "org.br\0" "org.bs\0" -"org.bt\0realtor\0" -"org.bw\0" -"org.ci\0" -"org.bz\0\xd0\xb0\xd0\xba.\xd1\x81\xd1\x80\xd0\xb1\0" -"sld.do\0" -"beiarn.no\0" -"org.cn\0" -"org.co\0is-an-entertainer.com\0" -"ddns.me\0" -"nord-fron.no\0is-a-libertarian.com\0" -"org.cu\0beats\0" -"org.cv\0hikone.shiga.jp\0hino.tokyo.jp\0tonkotsu.jp\0" -"org.cw\0loabat.no\0" -"\xe4\xb8\x96\xe7\x95\x8c\0" -"org.cy\0" -"test.ru\0" +"org.bt\0" +"ke\0like\0" +"org.bw\0kg\0" +"org.ci\0ki\0" +"org.bz\0" +"km\0s3-website-ap-southeast-1.amazonaws.com\0eu-west-2.elasticbeanstalk.com\0doesntexist.com\0from-oh.com\0homesecuritypc.com\0" +"org.cn\0kn\0" +"org.co\0" +"kp\0hiphop\0" +"la\0" +"kr\0lb\0" +"lc\0lib.nh.us\0" +"altoadige.it\0bologna.it\0ragusa.it\0post\0website.yandexcloud.net\0" +"org.cu\0l-o-g-i-n.de\0" +"org.cv\0" +"org.cw\0kw\0poivron.org\0is-lost.org\0misconfused.org\0" +"org.cy\0ky\0li\0archi\0" +"kz\0" +"lk\0" +"homesklep.pl\0" "org.dm\0" -"kirara.st\0" -"org.do\0" -"rag-cloud-ch.hosteur.com\0" -"org.ec\0" -"org.ee\0rebun.hokkaido.jp\0ca-central-1.elasticbeanstalk.com\0" -"org.eg\0" -"shop.ht\0" -"shop.hu\0" -"org.dz\0oishida.yamagata.jp\0co.com\0seidat.net\0" -"kishiwada.osaka.jp\0" -"kiwi\0" -"nj.us\0" -"blogsyte.com\0" -"kuju.oita.jp\0stat.no\0" -"ca.us\0jcloud.ik-server.com\0" -"org.es\0" -"org.et\0" -"*.nom.br\0" -"direct.quickconnect.to\0" -"wellbeingzone.co.uk\0" -"org.fj\0" -"org.fm\0batsfjord.no\0" -"tv.bb\0" -"oksnes.no\0" -"otsuka\0" -"k12.tn.us\0" -"org.ge\0ayase.kanagawa.jp\0" -"\xc3\xa1lt\xc3\xa1.no\0" -"org.gg\0" -"org.gh\0\xce\xb5\xce\xbb\0insure\0" +"org.do\0lur\xc3\xb8y.no\0divtasvuodna.no\0" +"seranishi.hiroshima.jp\0sarufutsu.hokkaido.jp\0minamiashigara.kanagawa.jp\0iwanuma.miyagi.jp\0yasuoka.nagano.jp\0koka.shiga.jp\0adachi.tokyo.jp\0ota.tokyo.jp\0" +"ma\0sevastopol.ua\0" +"lr\0" +"org.ec\0ls\0mc\0events\0" +"lt\0md\0" +"org.ee\0lu\0me\0" +"lv\0" +"org.eg\0mg\0" +"mh\0" +"ly\0" +"org.dz\0" +"mk\0blogspot.co.uk\0" +"ml\0" +"mn\0cloudns.in\0" +"mo\0jio\0limo\0" +"mp\0kuokgroup\0" +"mq\0na\0" +"store.bb\0mr\0" +"org.es\0ms\0nc\0" +"org.et\0vda.it\0fc.it\0mt\0" +"mu\0ne\0" +"mv\0nf\0" +"mw\0ng\0" +"mx\0" +"my\0ni\0" +"org.fj\0mz\0webhop.biz\0" +"link\0" +"nl\0nieruchomosci.pl\0poznan.pl\0" +"org.fm\0" +"no\0gs.rl.no\0hokksund.no\0" +"toyotsu.fukuoka.jp\0hokuto.hokkaido.jp\0hara.nagano.jp\0ookuwa.nagano.jp\0itabashi.tokyo.jp\0meguro.tokyo.jp\0abu.yamaguchi.jp\0verse.jp\0" +"lugansk.ua\0" +"nr\0" +"cloudns.cc\0" +"org.ge\0szex.hu\0nu\0cymru\0house\0" +"org.gg\0blog.kg\0" +"org.gh\0" "org.gi\0" -"kosai.shizuoka.jp\0traeumtgerade.de\0" -"tv.bo\0org.gl\0" -"org.gn\0stranda.no\0kmpsp.gov.pl\0" -"tv.br\0" -"org.gp\0rad\xc3\xb8y.no\0" -"av.tr\0" -"org.gr\0\xce\xb5\xcf\x85\0" -"crew.aero\0org.gt\0" -"org.gu\0" -"hitra.no\0heavy.jp\0" -"qsl.br\0" -"club.aero\0org.gy\0ena.gifu.jp\0" -"imizu.toyama.jp\0" -"org.hk\0sakurai.nara.jp\0user.aseinet.ne.jp\0" -"minamitane.kagoshima.jp\0nextdirect\0" -"social\0" -"org.hn\0mo.us\0" -"service.gov.uk\0" -"cechire.com\0" -"webview-assets.cloud9.af-south-1.amazonaws.com\0" -"org.ht\0" -"org.hu\0" -"development.run\0" -"oyama.tochigi.jp\0" -"org.il\0akita.akita.jp\0" -"org.im\0kasukabe.saitama.jp\0" -"org.in\0kawanishi.yamagata.jp\0*.on-acorn.io\0" -"nagara.chiba.jp\0" +"nz\0" +"org.gl\0\xd7\x90\xd7\xa7\xd7\x93\xd7\x9e\xd7\x99\xd7\x94.\xd7\x99\xd7\xa9\xd7\xa8\xd7\x90\xd7\x9c\0" +"om\0uk.com\0" +"org.gn\0" +"org.gp\0" +"ip6.arpa\0pa\0" +"org.gr\0es.kr\0" +"lib.me.us\0" +"org.gt\0direct\0pages.torproject.net\0" +"org.gu\0pe\0" +"pf\0" +"ph\0" +"org.gy\0" +"org.hk\0pk\0store.dk\0" +"pl\0ic.gov.pl\0jll\0" +"pm\0" +"org.hn\0pn\0" +"volda.no\0" +"midori.gunma.jp\0miyoshi.hiroshima.jp\0nakagawa.hokkaido.jp\0hakui.ishikawa.jp\0takahata.yamagata.jp\0cutegirl.jp\0ivory.ne.jp\0" +"qa\0" +"pr\0" +"ps\0" +"org.ht\0pt\0" +"org.hu\0film.hu\0" +"pw\0" +"py\0" +"org.il\0" +"org.im\0" +"org.in\0" +"gallup\0jmp\0" "org.iq\0" -"org.ir\0lug.org.uk\0" -"org.is\0*.landing.myjino.ru\0" -"\xe4\xb8\x89\xe9\x87\x8d.jp\0squares.net\0" -"org.je\0" -"dontexist.org\0go.leg.br\0" -"kasai.hyogo.jp\0shimoda.shizuoka.jp\0" -"monzaedellabrianza.it\0" -"lt.ua\0" -"org.jo\0" -"jor.br\0mol.it\0serveblog.net\0" -"sjc.br\0" -"taketomi.okinawa.jp\0b\xc3\xa5""d\xc3\xa5""ddj\xc3\xa5.no\0" -"takinoue.hokkaido.jp\0" -"intl.tn\0" -"mitane.akita.jp\0tolga.no\0" -"org.kg\0" -"org.ki\0vestvagoy.no\0" -"eek.jp\0" -"recipes\0" -"takayama.nagano.jp\0org.km\0*.statics.cloud\0" -"org.kn\0" -"md.us\0" -"va.it\0org.kp\0" -"org.la\0\xe7\xb5\x84\xe7\xb9\x94.\xe9\xa6\x99\xe6\xb8\xaf\0firebaseapp.com\0" -"org.lb\0" -"org.lc\0ak.us\0*.lclstage.dev\0" -"sasebo.nagasaki.jp\0" -"agdenes.no\0" -"\xed\x95\x9c\xea\xb5\xad\0" -"org.kw\0from-hi.com\0" -"org.ky\0" -"kinko.kagoshima.jp\0org.kz\0" -"org.lk\0" -"q.bg\0" -"toyako.hokkaido.jp\0" -"fujisawa.kanagawa.jp\0" -"org.ma\0" -"org.lr\0" -"org.ls\0in.ngrok.io\0" -"org.me\0temp-dns.com\0" -"org.lv\0" -"org.mg\0" -"shinkamigoto.nagasaki.jp\0" -"org.ly\0" -"k12.gu.us\0" -"vall\xc3\xa9""eaoste.it\0org.mk\0" +"org.ir\0" +"org.is\0claims\0viajes\0lima-city.rocks\0" +"cuneo.it\0vr.it\0pictet\0" +"org.je\0re\0lima-city.de\0" +"racing\0" +"jnj\0" +"realestate.pl\0" +"\xe0\xa4\xad\xe0\xa4\xbe\xe0\xa4\xb0\xe0\xa4\xa4\xe0\xa4\xae\xe0\xa5\x8d\0" +"student.aero\0org.jo\0ro\0" +"ne.jp\0inuyama.aichi.jp\0fukushima.fukushima.jp\0minamitane.kagoshima.jp\0karuizawa.nagano.jp\0" +"sa\0crimea.ua\0" +"sb\0" +"rs\0sc\0" +"sd\0" +"ne.ke\0ru\0se\0blogspot.co.ke\0" +"org.kg\0rw\0sg\0" +"sh\0" +"org.ki\0si\0" +"sj\0" +"sk\0" +"sl\0" +"org.km\0sm\0cf-ipfs.com\0is-uberleet.com\0" +"org.kn\0sn\0norton\0" +"so\0" +"org.kp\0" +"org.la\0" +"ne.kr\0org.lb\0sr\0" +"org.lc\0ss\0tc\0press\0" +"siracusa.it\0st\0td\0jot\0scot\0lima-city.at\0" +"su\0mel.cloudlets.com.au\0" +"sv\0tf\0" +"org.kw\0tg\0toolforge.org\0" +"sx\0th\0" +"org.ky\0sy\0joy\0" +"org.kz\0sz\0tj\0" +"org.lk\0tk\0*.dweb.link\0" +"wsse.gov.pl\0tl\0" +"tm\0" +"tn\0" +"fetsund.no\0to\0" +"hashikami.aomori.jp\0shiranuka.hokkaido.jp\0yamakita.kanagawa.jp\0kumamoto.kumamoto.jp\0ando.nara.jp\0ikoma.nara.jp\0suita.osaka.jp\0nakaniikawa.toyama.jp\0kilo.jp\0" +"org.ma\0ua\0" +"org.lr\0tr\0club\0al.leg.br\0" +"org.ls\0" +"tt\0" +"org.me\0enterprisecloud.nu\0" +"org.lv\0tv\0" +"org.mg\0tw\0ug\0" +"lima-city.ch\0" +"org.ly\0miami\0" +"tz\0" +"org.mk\0uk\0" "org.ml\0" -"adult.ht\0" -"org.mn\0\xd0\xbc\xd0\xba\xd0\xb4\0page\0" +"isa-hockeynut.com\0" +"internet.in\0org.mn\0" "org.mo\0" -"mihama.aichi.jp\0" -"org.na\0rennesoy.no\0" -"org.ms\0" -"org.mt\0" -"org.mu\0" -"org.mv\0cc.ct.us\0" -"org.mw\0org.ng\0" +"org.na\0va\0" +"org.ms\0us\0ok.us\0vc\0" +"catania.it\0reggioemilia.it\0org.mt\0cloudaccess.host\0*.futurecms.at\0" +"conf.au\0org.mu\0ve\0live\0" +"org.mv\0" +"org.mw\0org.ng\0vg\0mk.eu.org\0" "org.mx\0" -"aostavalley.it\0org.my\0org.ni\0" -"tv.im\0org.mz\0" -"zlg.br\0tv.in\0" -"mifune.kumamoto.jp\0rhcloud.com\0" -"ingatlan.hu\0sld.pa\0" -"\xe5\xae\xae\xe5\x9f\x8e.jp\0" -"ky.us\0" -"tv.it\0" -"org.nr\0" -"bato.tochigi.jp\0" -"im.it\0" -"bosch\0homelinux.com\0" -"caa.aero\0org.nz\0" -"serveirc.com\0" -"org.om\0" -"f.bg\0plurinacional.bo\0" -"\xe9\xb3\xa5\xe5\x8f\x96.jp\0kunisaki.oita.jp\0shiftcrypto.dev\0" -"org.pa\0for-more.biz\0elementor.cool\0" -"larvik.no\0heteml.net\0" -"choshi.chiba.jp\0" -"tv.kg\0" -"org.pe\0" -"yaotsu.gifu.jp\0org.pf\0" -"k12.sc.us\0" -"marche.it\0org.ph\0" -"va.no\0org.pk\0" -"ski.no\0org.pl\0" -"hurdal.no\0romskog.no\0activetrail.biz\0" +"org.my\0org.ni\0uy\0vi\0bestbuy\0" +"org.mz\0uz\0" +"vn\0" +"stjordalshalsen.no\0agdenes.no\0evje-og-hornnes.no\0gildeskal.no\0grimstad.no\0" +"kitagata.gifu.jp\0wanouchi.gifu.jp\0suzaka.nagano.jp\0ariake.saga.jp\0tsuruoka.yamagata.jp\0snowflake.app\0" +"chambagri.fr\0org.nr\0" +"vu\0kustanai.ru\0" +"wf\0" +"delivery\0" +"org.nz\0blogspot.co.nz\0" +"org.om\0firebaseapp.com\0ryd.wafaicloud.com\0ladesk.com\0" +"canva-apps.cn\0" +"org.pa\0" +"cc.id.us\0ws\0" +"org.pe\0khakassia.su\0kustanai.su\0" +"org.pf\0" +"org.ph\0" +"org.pk\0" +"org.pl\0" "org.pn\0" -"bjugn.no\0org.qa\0paas.datacenter.fi\0" -"org.pr\0koeln\0" +"software.aero\0enebakk.no\0rade.no\0torsken.no\0mayfirst.info\0" +"misato.akita.jp\0misawa.aomori.jp\0shimizu.hokkaido.jp\0ami.ibaraki.jp\0seihi.nagasaki.jp\0gose.nara.jp\0kurotaki.nara.jp\0katano.osaka.jp\0nobushi.jp\0" +"org.qa\0\xd0\xba\xd1\x80\xd1\x8b\xd0\xbc.\xd1\x80\xd1\x83\xd1\x81\0" +"sorocaba.br\0org.pr\0" "org.ps\0" "org.pt\0" -"naie.hokkaido.jp\0myspreadshop.com\0" -"contagem.br\0sorfold.no\0" -"magazine.aero\0savona.it\0" +"city.hu\0ye\0mytis.ru\0" +"ne.pw\0" "org.py\0" -"hotels\0" -"stavern.no\0" -"\xe6\x9c\xba\xe6\x9e\x84\0" -"manaus.br\0lon.wafaicloud.com\0" -"cherkasy.ua\0" -"\xd0\xbc\xd0\xbe\xd0\xbd\0" -"journalist.aero\0" -"ris\xc3\xb8r.no\0" -"verona.it\0\xe5\xbe\xae\xe5\x8d\x9a\0" -"akamaized.net\0" -"kahoku.ishikawa.jp\0tv.na\0" -"futtsu.chiba.jp\0org.ro\0platter-app.dev\0" -"kitakami.iwate.jp\0" +"\xd8\xa7\xd8\xaa\xd8\xb5\xd8\xa7\xd9\x84\xd8\xa7\xd8\xaa\0" +"dh.bytemark.co.uk\0" +"webview-assets.cloud9.af-south-1.amazonaws.com\0net-freaks.com\0shopitsite.com\0" +"gujarat.in\0" +"\xd8\xa7\xd9\x8a\xd8\xb1\xd8\xa7\xd9\x86.ir\0" +"gives\0cloudns.us\0co.business\0" +"abr.it\0cr.it\0lo.it\0yt\0" +"info.gu\0" +"platter-app.dev\0" +"mywire.org\0es.eu.org\0lu.eu.org\0me.eu.org\0" +"kfh\0" +"zm\0stockholm\0" +"arna.no\0vossevangen.no\0nesseby.no\0sor-varanger.no\0tranoy.no\0org.ro\0" +"yokote.akita.jp\0tanagura.fukushima.jp\0ashoro.hokkaido.jp\0ina.ibaraki.jp\0utazu.kagawa.jp\0kamiamakusa.kumamoto.jp\0heguri.nara.jp\0taketomi.okinawa.jp\0chofu.tokyo.jp\0rsvp\0" "org.sa\0" -"org.sb\0" +"es.gov.br\0org.sb\0" "org.rs\0org.sc\0" -"org.sd\0" -"tarama.okinawa.jp\0org.se\0org.ru\0" -"healthcare\0eu-4.evennode.com\0" -"org.rw\0org.sg\0storage.yandexcloud.net\0" +"info.ht\0org.sd\0" +"info.hu\0priv.hu\0org.se\0spb.ru\0org.ru\0" +"org.rw\0org.sg\0zw\0" "org.sh\0" -"webview-assets.cloud9.eu-central-1.amazonaws.com\0nid.io\0" +"fin.ci\0" "org.sl\0" -"pictet\0" -"org.sn\0" -"yamakita.kanagawa.jp\0org.so\0" -"read\0from-nj.com\0" -"tobishima.aichi.jp\0framercanvas.com\0" -"org.ss\0global.prod.fastly.net\0" -"org.st\0" -"atsugi.kanagawa.jp\0org.sv\0movie\0" -"mar.it\0" -"org.sy\0" -"org.sz\0org.tj\0kikirara.jp\0" -"toya.hokkaido.jp\0floppy.jp\0" +"webview-assets.cloud9.ap-southeast-2.amazonaws.com\0mytuleap.com\0pleskns.com\0" +"info.in\0org.sn\0maison\0" +"org.so\0*.on-k3s.io\0" +"org.ss\0cc.hi.us\0lib.as.us\0land-4-sale.us\0mypets.ws\0" +"info.et\0trentinoa-adige.it\0caserta.it\0org.st\0" +"lotte\0spb.su\0" +"org.sv\0" +"lv.eu.org\0" +"org.sy\0bharti\0" +"info.fj\0org.sz\0org.tj\0" "org.tm\0" "org.tn\0" -"org.to\0stream\0" -"onza.mythic-beasts.com\0" -"org.ua\0" +"s\xc3\xb8ndre-land.no\0org.to\0lotto\0" +"uwajima.ehime.jp\0bando.ibaraki.jp\0ritto.shiga.jp\0" +"org.ua\0kia\0" "org.tr\0" -"sp.it\0" +"fin.ec\0" "org.tt\0" -"gs.ah.no\0" -"fst.br\0org.tw\0org.ug\0pussycat.jp\0" -"*.cloudera.site\0" -"wales\0edu.krd\0" -"miasta.pl\0org.uk\0" -"higashiosaka.osaka.jp\0" -"alt.za\0c66.me\0is-a-cpa.com\0" -"tokushima.tokushima.jp\0nes.buskerud.no\0" -"is-into-cartoons.com\0" -"akamaiedge.net\0" -"org.vc\0" -"otoineppu.hokkaido.jp\0mazury.pl\0onflashdrive.app\0" +"mcpre.ru\0" +"org.tw\0ne.ug\0org.ug\0" +"ne.tz\0" +"org.uk\0affinitylottery.org.uk\0" +"mattel\0" +"kim\0us-west-1.elasticbeanstalk.com\0" +"\xe5\x8f\xb0\xe6\xb9\xbe\0" +"ngrok.io\0" +"cheap\0" +"ne.us\0org.vc\0hdfc\0" "org.ve\0" -"tarnobrzeg.pl\0" -"sdscloud.pl\0" +"r.bg\0" +"info.cx\0" "org.uy\0org.vi\0" -"funabashi.chiba.jp\0org.uz\0" +"resto.bj\0org.uz\0" "org.vn\0" -"dsmynas.com\0" -"cuneo.it\0\xe9\xa3\x9f\xe5\x93\x81\0" -"engine.aero\0goldpoint\0" -"gob.ar\0" +"snaase.no\0stjordal.no\0weibo\0" +"yamaguchi.jp\0sakae.chiba.jp\0aizumisato.fukushima.jp\0matsumae.hokkaido.jp\0marugame.kagawa.jp\0bungoono.oita.jp\0okutama.tokyo.jp\0tachikawa.tokyo.jp\0onflashdrive.app\0hungry.jp\0" +"sk.ca\0" +"info.ec\0" "org.vu\0" -"eu-3.evennode.com\0" -"yasaka.nagano.jp\0" -"lucania.it\0cc.as.us\0boutir.com\0" -"chitose.hokkaido.jp\0" -"trentino-sudtirol.it\0" -"kaga.ishikawa.jp\0fukaya.saitama.jp\0" -"embaixada.st\0va.us\0" -"gob.bo\0tv.sd\0" -"org.ws\0" -"\xe3\x83\x95\xe3\x82\xa1\xe3\x83\x83\xe3\x82\xb7\xe3\x83\xa7\xe3\x83\xb3\0" -"oum.gov.pl\0" -"misaki.osaka.jp\0" -"fr-par-2.baremetal.scw.cloud\0" -"mochizuki.nagano.jp\0shop.th\0" -"gob.cl\0*.telebit.xyz\0" -"hobby-site.org\0" -"jgora.pl\0" -"wiih.gov.pl\0org.ye\0" -"gorizia.it\0dynalias.org\0" -"ismaili\0pars\0" -"hofu.yamaguchi.jp\0" -"tv.tr\0" -"gob.do\0org.za\0frontdoor\0" -"kamoenai.hokkaido.jp\0" -"porsangu.no\0" -"brother\0tires\0org.yt\0" -"gob.ec\0game.tw\0" -"cc.ma.us\0" -"tv.tz\0*.devcdnaccesso.com\0" -"jab.br\0vaapste.no\0sko.gov.pl\0\xd8\xb9\xd9\x85\xd8\xa7\xd9\x86\0" -"catfood.jp\0" +"gsj.bz\0" +"ru.com\0from-nm.com\0fastly-edge.com\0" +"auction\0" +"info.bb\0" +"org.ws\0singles\0" +"lucca.it\0info.at\0priv.at\0" +"info.au\0" +"kicks-ass.org\0" +"info.az\0info.bj\0" +"wiw.gov.pl\0gda.pl\0" +"dgca.aero\0navigation.aero\0info.bo\0" +"fukushima.jp\0konan.aichi.jp\0samegawa.fukushima.jp\0toya.hokkaido.jp\0tochio.niigata.jp\0tottori.tottori.jp\0" +"\xd1\x8f.\xd1\x80\xd1\x83\xd1\x81\0" +"builders\0" +"uk.oxa.cloud\0" +"org.ye\0" +"githubusercontent.com\0" +"creditunion\0" +"info.co\0" +"org.za\0blogspot.co.za\0" +"bl.it\0sv.it\0*.webpaas.ovh.net\0supabase.net\0org.yt\0" +"4lima.de\0" +"g.bg\0bmoattachments.org\0" +"toray\0" +"stalowa-wola.pl\0turek.pl\0" "org.zm\0" -"is-very-good.org\0ee.eu.org\0" -"ro.eu.org\0" -"\xc3\xa1k\xc5\x8boluokta.no\0" -"office\0shop.ro\0" -"sunnyday.jp\0" -"gob.es\0homeunix.net\0" -"eu-2.evennode.com\0" -"koganei.tokyo.jp\0org.zw\0ap-southeast-1.elasticbeanstalk.com\0" -"trogstad.no\0from-il.com\0" -"pug.it\0" -"halden.no\0" -"hoylandet.no\0kozow.com\0" -"alessandria.it\0comsec\0fresenius\0" -"tado.mie.jp\0author\0" -"ogawa.ibaraki.jp\0mus.mi.us\0" -"chita.aichi.jp\0north-kazakhstan.su\0" -"myjino.ru\0" -"tel.tr\0" -"mobi\0" -"vestv\xc3\xa5g\xc3\xb8y.no\0shop.pl\0reit\0mycloud.by\0" -"trentin-s\xc3\xbc""dtirol.it\0higashiura.aichi.jp\0" -"lea\xc5\x8bgaviika.no\0" -"\xe6\xb8\xb8\xe6\x88\x8f\0bluebite.io\0" -"modelling.aero\0gob.gt\0" -"musica.ar\0hikawa.shimane.jp\0" -"alvdal.no\0" -"eu-west-3.elasticbeanstalk.com\0" -"gob.hn\0" -"nakagawa.nagano.jp\0" -"isernia.it\0" -"kaho.fukuoka.jp\0" -"musica.bo\0abbott\0daemon.panel.gg\0" -"barsy.me\0za.net\0" -"moda\0property\0" -"ens.tn\0git-repos.de\0" -"isa-hockeynut.com\0dyn-berlin.de\0" -"co.business\0" -"hitachiomiya.ibaraki.jp\0" -"security\0" -"si.eu.org\0s3.isk02.sakurastorage.jp\0" -"emb.kw\0" -"senseering.net\0" -"eu-1.evennode.com\0" -"appspot.com\0" -"na4u.ru\0" -"misawa.aomori.jp\0" -"hisayama.fukuoka.jp\0" -"k12.dc.us\0tiaa\0" -"cc.vt.us\0" -"on.ca\0" +"transporte.bo\0lesja.no\0" +"kawakita.ishikawa.jp\0hanamaki.iwate.jp\0oi.kanagawa.jp\0tado.mie.jp\0haga.tochigi.jp\0machida.tokyo.jp\0" +"mat.br\0" +"suli.hu\0lanbib.se\0fage\0" +"org.zw\0" +"sphinx.mythic-beasts.com\0" +"onion\0" +"utwente.io\0" +"industries\0" +"trentinosued-tirol.it\0dev.static.land\0""4lima.at\0" +"kr.eu.org\0" +"limanowa.pl\0" +"kpn\0" +"floro.no\0jessheim.no\0habmer.no\0r\xc3\xb8""d\xc3\xb8y.no\0\xc4\x8d\xc3\xa1hcesuolo.no\0" +"ikata.ehime.jp\0toyako.hokkaido.jp\0oguni.kumamoto.jp\0kainan.wakayama.jp\0uenohara.yamanashi.jp\0sblo.jp\0" +"cr.ua\0" +"cloudns.pw\0" +"4lima.ch\0" +"fail\0" +"dyndns-wiki.com\0onza.mythic-beasts.com\0" +"hughes\0" +"aq.it\0ba.it\0krd\0lat\0seat\0onavstack.net\0does-it.net\0" +"*.stgstage.dev\0" +"law\0gotdns.org\0fi.eu.org\0" +"for-some.biz\0" +"klepp.no\0\xc3\xb8vre-eiker.no\0" +"aomori.jp\0\xe5\xbe\xb3\xe5\xb3\xb6.jp\0gonohe.aomori.jp\0saijo.ehime.jp\0iwaki.fukushima.jp\0ora.gunma.jp\0sunagawa.hokkaido.jp\0kamaishi.iwate.jp\0amami.kagoshima.jp\0nakagyo.kyoto.jp\0kaizuka.osaka.jp\0kita.osaka.jp\0kazo.saitama.jp\0gamo.shiga.jp\0tabuse.yamaguchi.jp\0chuo.yamanashi.jp\0holy.jp\0pussycat.jp\0" +"foz.br\0" +"ua.rs\0" +"conf.se\0prvcy.page\0" +"photography\0" +"iwi.nz\0" +"hu.com\0hobby-site.com\0loseyourip.com\0qbuser.com\0" +"vuelos\0noticeable.news\0" +"pesaro-urbino.it\0" +"east-kazakhstan.su\0termez.su\0" +"verm\xc3\xb6gensberatung\0" +"mazowsze.pl\0" +"akdn\0" +"luroy.no\0nordkapp.no\0sortland.no\0" +"kitami.hokkaido.jp\0yamamoto.miyagi.jp\0kawagoe.saitama.jp\0halfmoon.jp\0" +"odessa.ua\0" +"lds\0*.diher.solutions\0" +"allfinanz\0" +"seek\0" +"aivencloud.com\0is-an-engineer.com\0pagefrontapp.com\0""1kapp.com\0" +"guardian\0reisen\0" +"villas\0" +"lig.it\0is.it\0trani-barletta-andria.it\0syncloud.it\0" +"wanggou\0lelux.site\0" +"cat.ax\0" +"fhs.no\0karasjok.no\0barrel-of-knowledge.info\0" +"!city.sendai.jp\0oamishirasato.chiba.jp\0masaki.ehime.jp\0toon.ehime.jp\0otoineppu.hokkaido.jp\0ninohe.iwate.jp\0minoh.osaka.jp\0yonago.tottori.jp\0uozu.toyama.jp\0" +"fans\0" +"eu.encoway.cloud\0" "marine.ru\0" -"yalta.ua\0" -"ferrara.it\0f.se\0" -"dance\0" -"mysecuritycamera.com\0" -"takehara.hiroshima.jp\0" -"myshopblocks.com\0" -"jpmorgan\0" -"pt.it\0iwate.jp\0" -"porsanger.no\0" -"yokosuka.kanagawa.jp\0takatori.nara.jp\0" -"rent\0lugs.org.uk\0" -"uda.nara.jp\0virtual-user.de\0" -"s\xc3\xa1lat.no\0" -"davvesiida.no\0" -"dep.no\0platform0.app\0mel.cloudlets.com.au\0" -"jewelry\0" -"lodi.it\0" -"*.ex.ortsinfo.at\0" -"tomakomai.hokkaido.jp\0" -"jinsekikogen.hiroshima.jp\0" -"fhv.se\0k12.ny.us\0" -"aosta.it\0hotmail\0" -"omaezaki.shizuoka.jp\0kolobrzeg.pl\0dynu.net\0sk.eu.org\0" -"jus.br\0" -"cc.vi.us\0pictures\0" -"ns.ca\0" -"bofa\0" -"gob.mx\0" -"gob.ni\0" -"miasa.nagano.jp\0tirol\0" -"tysvar.no\0eurodir.ru\0" -"groks-the.info\0lovepop.jp\0barsy.ro\0" -"forex\0" -"fund\0" -"suldal.no\0" -"pi.it\0" -"dovre.no\0" -"writesthisblog.com\0" -"ama.shimane.jp\0*.compute.amazonaws.com\0" -"minami.fukuoka.jp\0" -"futbol\0gent\0" -"gob.pa\0" -"jpn.com\0" -"eigersund.no\0" -"gob.pe\0" -"kamisu.ibaraki.jp\0" -"nemuro.hokkaido.jp\0fujimi.nagano.jp\0" -"*.build.run\0" -"cri.br\0" -"gob.pk\0science\0de.gt\0" -"kyotamba.kyoto.jp\0homelinux.net\0" -"sp.gov.br\0ritto.shiga.jp\0" -"lib.co.us\0blush.jp\0" -"shijonawate.osaka.jp\0staba.jp\0oy.lc\0" -"varoy.no\0" -"flier.jp\0" -"fujisawa.iwate.jp\0s\xc3\xb8rum.no\0barsy.uk\0smartlabeling.scw.cloud\0" -"inf.br\0za.bz\0" -"rest\0" -"ru.eu.org\0se.eu.org\0" -"mein-iserv.de\0" -"firm.ht\0" -"*.awdev.ca\0" -"ga.us\0" -"shimotsuke.tochigi.jp\0blogdns.com\0" -"jeonbuk.kr\0zombie.jp\0" -"firm.in\0" -"co.place\0" -"inf.cu\0secret.jp\0" -"eti.br\0" -"\xe5\x85\xac\xe5\x8f\xb8.\xe9\xa6\x99\xe6\xb8\xaf\0" -"naka.ibaraki.jp\0home-webserver.de\0" -"ukiha.fukuoka.jp\0" -"piedmont.it\0bitbucket.io\0" -"oppeg\xc3\xa5rd.no\0" -"audio\0" -"ocelot.mythic-beasts.com\0" -"sande.more-og-romsdal.no\0" -"eu.com\0" -"sejny.pl\0" -"gob.sv\0" -"basketball\0" -"so.gov.pl\0" -"firm.co\0dyndns-blog.com\0" -"gleeze.com\0" -"oharu.aichi.jp\0" -"ito.shizuoka.jp\0" -"lindesnes.no\0js.org\0" -"kherson.ua\0" -"vfs.cloud9.af-south-1.amazonaws.com\0" -"kamijima.ehime.jp\0" -"cloudns.pro\0" -"firm.dk\0" -"de.ls\0" -"tysfjord.no\0de.md\0" -"bz.it\0" -"pccw\0" -"okoppe.hokkaido.jp\0" -"\xd0\xbc\xd1\x81\xd0\xba.\xd1\x80\xd1\x83\xd1\x81\0" -"suzu.ishikawa.jp\0e4.cz\0" -"gob.ve\0synology-ds.de\0" -"toyonaka.osaka.jp\0" -"bond\0" -"sandnessj\xc3\xb8""en.no\0" -"klodzko.pl\0" -"firmdale\0" -"storj.farm\0" -"trentino-alto-adige.it\0higashine.yamagata.jp\0blog.gt\0" -"higashiizumo.shimane.jp\0seven\0" -"monza-e-della-brianza.it\0" -"moareke.no\0webview-assets.cloud9.us-east-2.amazonaws.com\0" -"mb.ca\0" -"cn.eu.org\0" -"servep2p.com\0" -"n\xc3\xa1vuotna.no\0ostrowwlkp.pl\0" -"melhus.no\0book\0" -"genkai.saga.jp\0cologne\0hu.net\0" -"voagat.no\0" -"remotewd.com\0" -"hirogawa.wakayama.jp\0supersale.jp\0" -"lima.zone\0" -"saku.nagano.jp\0" -"hirara.okinawa.jp\0" -"raisa.no\0" -"bologna.it\0" -"bo.it\0" -"devices.resinstaging.io\0" -"konsulat.gov.pl\0" -"yusui.kagoshima.jp\0" -"jeez.jp\0" -"blog.bo\0" -"adygeya.su\0" -"blog.br\0" -"monza-brianza.it\0" -"for-better.biz\0" -"anani.br\0hidaka.hokkaido.jp\0takamori.nagano.jp\0moto\0" -"\xe7\x9f\xb3\xe5\xb7\x9d.jp\0" -"minano.saitama.jp\0wien.funkfeuer.at\0" -"dp.ua\0" -"design\0" -"akamaiorigin.net\0" -"kosei.shiga.jp\0oshima.tokyo.jp\0" -"com.ac\0chino.nagano.jp\0" -"nedre-eiker.no\0goodyear\0tips\0" -"com.af\0" -"com.ag\0vic.edu.au\0" -"com.ai\0tuscany.it\0shimofusa.chiba.jp\0" -"katsuragi.wakayama.jp\0mediatech.dev\0""2.azurestaticapps.net\0" -"com.al\0football\0" -"com.am\0aero.tt\0organic\0" -"school.na\0" -"com.ba\0edogawa.tokyo.jp\0" -"com.ar\0com.bb\0at.it\0rennebu.no\0" -"com.au\0morimachi.shizuoka.jp\0" -"loseyourip.com\0" -"com.aw\0koga.fukuoka.jp\0inawashiro.fukushima.jp\0yamazoe.nara.jp\0fujikawa.shizuoka.jp\0stryn.no\0" -"com.bh\0inf.mk\0" -"com.bi\0kimobetsu.hokkaido.jp\0encr.app\0" -"com.az\0com.bj\0mx.na\0" -"chiba.jp\0molde.no\0\xe0\xb0\xad\xe0\xb0\xbe\xe0\xb0\xb0\xe0\xb0\xa4\xe0\xb1\x8d\0" -"com.bm\0" -"com.bn\0\xd8\xa7\xd8\xa8\xd9\x88\xd8\xb8\xd8\xa8\xd9\x8a\0" -"com.bo\0kasuga.hyogo.jp\0aero.mv\0" -"adygeya.ru\0read-books.org\0" -"com.br\0" -"com.bs\0bolzano-altoadige.it\0" -"com.bt\0" -"cri.nz\0" -"school.nz\0" -"com.by\0com.ci\0bykle.no\0" -"com.bz\0" -"*.backyards.banzaicloud.io\0" -"we.bs\0" -"com.cm\0bifuka.hokkaido.jp\0" -"com.cn\0yugawara.kanagawa.jp\0" -"com.co\0" -"suwalki.pl\0cy.eu.org\0" -"media.aero\0" -"services\0" -"com.cu\0\xe0\xa6\xac\xe0\xa6\xbe\xe0\xa6\x82\xe0\xa6\xb2\xe0\xa6\xbe\0bplaced.com\0com.de\0is-certified.com\0" -"com.cv\0elasticbeanstalk.com\0" -"com.cw\0forum\0" -"com.cy\0barsy.bg\0" -"ina.ibaraki.jp\0" -"com.dm\0ai.in\0" -"sevastopol.ua\0de.us\0" -"com.do\0mb.it\0\xd0\xbe\xd1\x80\xd0\xb3\0" -"sanjo.niigata.jp\0sr.gov.pl\0" -"dell-ogliastra.it\0rissa.no\0at.md\0" -"com.ec\0nasu.tochigi.jp\0\xe9\xa6\x99\xe6\xb8\xaf\0barsy.ca\0" -"loisirs.bj\0" -"com.ee\0" -"\xe9\xa4\x90\xe5\x8e\x85\0" -"com.eg\0rzeszow.pl\0firm.ve\0" -"moka.tochigi.jp\0" -"com.dz\0" -"racing\0" -"ulvik.no\0productions\0id.repl.co\0" -"tenei.fukushima.jp\0" -"cz.eu.org\0" -"com.es\0" -"com.et\0" -"sa.edu.au\0barsy.de\0" -"takasaki.gunma.jp\0" -"rs.webaccel.jp\0" -"com.fj\0bulsan-sudtirol.it\0" -"com.fm\0" -"katagami.akita.jp\0" -"zappos\0" -"ichinohe.iwate.jp\0" -"com.fr\0" -"com.ge\0utwente.io\0" -"webview-assets.cloud9.us-west-1.amazonaws.com\0" -"com.gh\0\xc3\xb8rskog.no\0messerli.app\0minisite.ms\0" -"com.gi\0" -"naroy.no\0" -"bplaced.de\0" -"com.gl\0" -"com.gn\0" -"control.aero\0" -"com.gp\0law.za\0dk.eu.org\0" -"com.gr\0bridgestone\0" -"com.gt\0hachirogata.akita.jp\0nomi.ishikawa.jp\0" -"com.gu\0" -"sa.com\0" -"barsy.eu\0" -"com.gy\0jorpeland.no\0orland.no\0condos\0" -"homeunix.org\0camdvr.org\0" -"com.hk\0aosta-valley.it\0*.elb.amazonaws.com.cn\0" -"lg.jp\0" -"bozen-s\xc3\xbc""dtirol.it\0" -"com.hn\0" -"com.hr\0" -"fed.us\0" -"cng.br\0com.ht\0eniwa.hokkaido.jp\0higashikagura.hokkaido.jp\0higashichichibu.saitama.jp\0" -"s3.pl-waw.scw.cloud\0" -"\xe7\xbb\x84\xe7\xb9\x94.hk\0k12.in.us\0" -"community-pro.de\0" -"dyndns-remote.com\0" -"press.cy\0" -"isla.pr\0\xd0\xb1\xd0\xb8\xd0\xb7.\xd1\x80\xd1\x83\xd1\x81\0" -"com.im\0emiliaromagna.it\0" -"com.in\0inf.ua\0" -"com.io\0" -"com.iq\0firm.ro\0" -"*.database.run\0" -"com.is\0" -"asker.no\0" -"\xe7\xa5\x9e\xe5\xa5\x88\xe5\xb7\x9d.jp\0habikino.osaka.jp\0" -"cci.fr\0" -"slattum.no\0" -"marugame.kagawa.jp\0" -"nh.us\0" -"exchange\0" -"shiraoka.saitama.jp\0" -"com.jo\0abo.pa\0" -"ug.gov.pl\0" -"shimamaki.hokkaido.jp\0bd.se\0""123sait.ru\0" -"sn\xc3\xa5sa.no\0cloudns.org\0" -"com.kg\0" -"vall\xc3\xa9""e-d-aoste.it\0com.ki\0" -"za.org\0" -"shiiba.miyazaki.jp\0dnsalias.com\0" -"higashikawa.hokkaido.jp\0ichinoseki.iwate.jp\0com.km\0" -"clinique\0service.gov.scot\0" -"naklo.pl\0" -"com.kp\0de.eu.org\0barsy.in\0" -"com.la\0barsy.io\0" -"com.lb\0" -"com.lc\0" -"ggee\0orange\0" -"blog.vu\0" -"com.kw\0k12.ia.us\0" -"com.ky\0orangecloud.tn\0" -"fuchu.hiroshima.jp\0com.kz\0" -"com.lk\0" -"\xe7\xbd\x91\xe7\xb5\xa1.hk\0" -"123paginaweb.pt\0" -"from-wi.com\0" -"asso.eu.org\0" -"vfs.cloud9.us-west-2.amazonaws.com\0" -"com.lr\0s3-website.ca-central-1.amazonaws.com\0cloudflare-ipfs.com\0" -"shiksha\0" -"com.lv\0" -"com.mg\0karm\xc3\xb8y.no\0catholic\0uwu.ai\0" -"kumiyama.kyoto.jp\0firm.nf\0" -"com.ly\0firm.ng\0" -"com.mk\0bashkiria.ru\0" -"com.ml\0" -"somna.no\0" -"ricoh\0" -"com.mo\0" -"website\0" -"firenze.it\0sakado.saitama.jp\0com.na\0" +"pharmaciens.km\0de.com\0mydatto.com\0pages.wiardweb.com\0" +"cc.nj.us\0" +"info.ve\0" +"\xeb\x8b\xb7\xeb\x84\xb7\0" +"fin.tn\0info.vn\0" +"nayoro.hokkaido.jp\0anan.nagano.jp\0yaese.okinawa.jp\0takashima.shiga.jp\0kanuma.tochigi.jp\0mashiko.tochigi.jp\0pupu.jp\0" +"ruhr\0" +"investments\0" +"123minsida.se\0" +"s3-website-ap-northeast-1.amazonaws.com\0is-a-painter.com\0" +"re.it\0a.prod.fastly.net\0heteml.net\0eating-organic.net\0privatizehealthinsurance.net\0" +"farm\0\xe6\x9b\xb8\xe7\xb1\x8d\0" +"info.tn\0" +"gs.va.no\0mosj\xc3\xb8""en.no\0h\xc3\xa1pmir.no\0tvedestrand.no\0vadso.no\0" +"sumita.iwate.jp\0nakijin.okinawa.jp\0oyabe.toyama.jp\0kudoyama.wakayama.jp\0murayama.yamagata.jp\0\xe7\xbd\x91\xe5\x9d\x80\0kuron.jp\0watson.jp\0" +"yoga\0" +"info.tr\0" +"info.tt\0" +"forum.hu\0r.se\0guge\0" +"hyundai\0" +"info.tz\0" +"gr.com\0dyndns-work.com\0is-into-games.com\0" +"hb.cn\0" +"re.kr\0flickr\0" +"cc.mo.us\0chtr.k12.ma.us\0llc\0" +"andriabarlettatrani.it\0suedtirol.it\0fast\0office-on-the.net\0""32-b.it\0community-pro.net\0" +"co.network\0" +"cnpy.gdn\0" +"l\xc3\xa6rdal.no\0tromso.no\0info.ro\0" +"\xe9\xb9\xbf\xe5\x85\x90\xe5\xb3\xb6.jp\0kimitsu.chiba.jp\0kyonan.chiba.jp\0koga.ibaraki.jp\0takahashi.okayama.jp\0llp\0" +"info.sd\0" +"conf.lv\0" +"lilly\0" +"vfs.cloud9.ap-northeast-3.amazonaws.com\0webview-assets.cloud9.me-south-1.amazonaws.com\0awsglobalaccelerator.com\0x.mythic-beasts.com\0stufftoread.com\0unusualperson.com\0" +"durban\0" +"dabur\0" +"k12.nv.us\0k12.wa.us\0" +"pz.it\0cdn.prod.atlassian-dev.net\0bar2.net\0" +"pages.it.hs-heilbronn.de\0" +"gg.ax\0" +"info.pk\0" +"info.pl\0priv.pl\0zpisdn.gov.pl\0" +"h\xc3\xb8ylandet.no\0songdalen.no\0svelvik.no\0matta-varjjat.no\0" +"oharu.aichi.jp\0uchiko.ehime.jp\0okuma.fukushima.jp\0shiriuchi.hokkaido.jp\0karatsu.saga.jp\0hino.tokyo.jp\0girly.jp\0" +"ggf.br\0info.pr\0" +"g.se\0office\0" +"lol\0" +"br.com\0from-pr.com\0jcloud-ver-jpc.ik-server.com\0jed.wafaicloud.com\0" +"info.na\0" +"cc.md.us\0cc.va.us\0" +"akadns.net\0servebbs.net\0seidat.net\0senseering.net\0" +"fujitsu\0myspreadshop.com.au\0community-pro.de\0" +"info.mv\0info.nf\0" +"info.ni\0\xe7\xbd\x91\xe7\xab\x99\0" +"zachpomor.pl\0lpl\0beep.pl\0" +"priv.no\0b\xc3\xa1hccavuotna.no\0eidskog.no\0\xe5\xa4\xa7\xe6\x8b\xbf\0" +"aioi.hyogo.jp\0uki.kumamoto.jp\0agano.niigata.jp\0miyashiro.saitama.jp\0hikawa.shimane.jp\0kotoura.tottori.jp\0minobu.yamanashi.jp\0help\0" +"info.nr\0" +"bostik\0" +"s3-eu-west-3.amazonaws.com\0*.customer-oci.com\0" +"caravan\0man\0" +"*.otap.co\0" +"map\0" +"info.la\0mba\0" +"supplies\0" +"pmn.it\0gr.it\0milan.it\0po.it\0ny-1.paas.massivegrid.net\0" +"0.bg\0" +"hm.no\0berlev\xc3\xa5g.no\0os.hordaland.no\0sirdal.no\0" +"gr.jp\0munakata.fukuoka.jp\0hongo.hiroshima.jp\0shimamaki.hokkaido.jp\0nosegawa.nara.jp\0koshigaya.saitama.jp\0kumagaya.saitama.jp\0wakasa.tottori.jp\0hidaka.wakayama.jp\0" +"ipiranga\0osaka\0" +"info.ls\0" +"accountant\0prod\0" +"priv.me\0bir.ru\0" +"prof\0" +"\xd7\x99\xd7\xa9\xd7\xa8\xd7\x90\xd7\x9c\0" +"from-ma.com\0is-gone.com\0site.tb-hosting.com\0" +"coupon\0" +"ntdll.top\0" +"gyeonggi.kr\0" +"cc.ky.us\0lib.wy.us\0" +"trentino-s\xc3\xbc""dtirol.it\0ltd\0" +"azerbaijan.su\0karelia.su\0" +"workers.dev\0" +"pubtls.org\0jpn.org\0" +"wodzislaw.pl\0" +"bievat.no\0davvenj\xc3\xa1rga.no\0tj\xc3\xb8me.no\0" +"tsugaru.aomori.jp\0miyawaka.fukuoka.jp\0shinichi.hiroshima.jp\0ayabe.kyoto.jp\0chino.nagano.jp\0otsuki.yamanashi.jp\0\xe6\x88\x91\xe7\x88\xb1\xe4\xbd\xa0\0" +"sp.leg.br\0" +"cityeats\0" +"med\0walmart\0flap.id\0" +"info.ke\0" +"info.ki\0" +"london.cloudapps.digital\0" +"*.ocp.customer-oci.com\0" +"men\0" +"ot.it\0pd.it\0" +"here\0komatsu\0" +"booking\0" +"erni\0" +"\xe5\x80\x8b\xe4\xba\xba.hk\0" +"ardal.no\0sorum.no\0" +"\xe8\x8c\xa8\xe5\x9f\x8e.jp\0midori.chiba.jp\0hirata.fukushima.jp\0gifu.gifu.jp\0ichinoseki.iwate.jp\0geisei.kochi.jp\0kami.kochi.jp\0nagahama.shiga.jp\0toga.toyama.jp\0tokuyama.yamaguchi.jp\0narusawa.yamanashi.jp\0" +"joinville.br\0" +"markets\0" +"guru\0" +"ybo.party\0" +"vfs.cloud9.eu-north-1.amazonaws.com\0from-dc.com\0is-a-llama.com\0" +"boston\0" +"cc.ca.us\0lib.fl.us\0\xe5\x8f\xb0\xe7\x81\xa3\0" +"barletta-trani-andria.it\0yandexcloud.net\0" +"potager.org\0" +"\xe4\xbd\x90\xe8\xb3\x80.jp\0kunimi.fukushima.jp\0uchihara.ibaraki.jp\0ozu.kumamoto.jp\0punyu.jp\0" +"eurodir.ru\0" +"sexy\0" +"mil\0chanel\0legal\0" +"myiphost.com\0myactivedirectory.com\0operaunite.com\0temp-dns.com\0" +"instantcloud.cn\0" +"nid.io\0dyn53.io\0" +"barsy.shop\0" +"mit\0" +"istmein.de\0barsy.site\0" +"hamburg\0mayfirst.org\0" +"sydney\0" +"\xd8\xa7\xd8\xa8\xd9\x88\xd8\xb8\xd8\xa8\xd9\x8a\0" +"kwp.gov.pl\0wuoz.gov.pl\0" +"journal.aero\0mosvik.no\0vard\xc3\xb8.no\0" +"!city.yokohama.jp\0dazaifu.fukuoka.jp\0nichinan.miyazaki.jp\0fukudomi.saga.jp\0izu.shizuoka.jp\0" +"*.magentosite.cloud\0" +"myfast.space\0" +"cool\0" +"dyndns-remote.com\0withyoutube.com\0postman-echo.com\0myshopblocks.com\0" +"coop\0" +"toshiba\0" +"mlb\0" +"lib.nj.us\0sucks\0" +"reggiocalabria.it\0cloudycluster.net\0" +"hisamitsu\0dyn.ddnss.de\0my-gateway.de\0" +"gos.pk\0" +"radom.pl\0" +"kvafjord.no\0" +"tokoname.aichi.jp\0mito.ibaraki.jp\0isen.kagoshima.jp\0miyada.nagano.jp\0toda.saitama.jp\0sumida.tokyo.jp\0shinjo.yamagata.jp\0mond.jp\0" +"\xd0\xb0\xd0\xba.\xd1\x81\xd1\x80\xd0\xb1\0mma\0" +"k12.ec\0mls\0" +"ally\0university\0" +"total\0ravpage.co.il\0" +"apps.fbsbx.com\0" +"seoul.kr\0" +"mol.it\0frosinone.it\0serveblog.net\0" +"dynamisches-dns.de\0" +"other.nf\0" +"money\0" "b\xc3\xa1jddar.no\0" -"com.ms\0" -"com.mt\0" -"com.mu\0at.vg\0" -"com.mv\0com.nf\0" -"campania.it\0com.mw\0com.ng\0" -"com.mx\0magnet.page\0" -"com.my\0com.ni\0" -"z.bg\0bashkiria.su\0skr.jp\0" -"pmn.it\0kawasaki.miyagi.jp\0hyllestad.no\0" -"tonami.toyama.jp\0com.nr\0servecounterstrike.com\0" -"mosjoen.no\0" -"kamioka.akita.jp\0shibata.miyagi.jp\0" -"sola.no\0" -"sport.hu\0" -"ine.kyoto.jp\0" -"bryne.no\0com.om\0" -"settsu.osaka.jp\0" -"heroy.nordland.no\0" -"com.pa\0" -"recreation.aero\0" -"com.pe\0" -"kami.miyagi.jp\0com.pf\0lezajsk.pl\0" -"africa.bj\0com.ph\0" -"fetsund.no\0com.pk\0" -"com.pl\0" -"!city.sendai.jp\0" -"osteroy.no\0dontexist.com\0" -"com.qa\0" -"com.pr\0" -"com.ps\0channelsdvr.net\0" -"com.pt\0deno-staging.dev\0" -"com.py\0" -"yomitan.okinawa.jp\0" -"o.bg\0\xd8\xa7\xd9\x84\xd8\xb3\xd8\xb9\xd9\x88\xd8\xaf\xd9\x8a\xd9\x87\0" -"tana.no\0" -"vibo-valentia.it\0" -"ayabe.kyoto.jp\0cleverapps.io\0" -"koriyama.fukushima.jp\0slupsk.pl\0diadem.cloud\0" -"fermo.it\0mino.gifu.jp\0" -"koge.tottori.jp\0cooking\0" -"massa-carrara.it\0com.re\0appudo.net\0" -"dental\0" -"ebino.miyazaki.jp\0starachowice.pl\0" -"kimitsu.chiba.jp\0" -"lib.tn.us\0" -"namikata.ehime.jp\0" -"is-found.org\0" -"lg.ua\0" -"bremanger.no\0" -"com.ro\0" -"fam.pk\0" -"com.sa\0cc.ok.us\0bar0.net\0" -"econo.bj\0com.sb\0" -"sumoto.hyogo.jp\0gorlice.pl\0com.sc\0wixsite.com\0" -"com.sd\0" -"hof.no\0com.se\0homelinux.org\0com.ru\0" -"higashikurume.tokyo.jp\0" -"shonai.fukuoka.jp\0com.sg\0ftpaccess.cc\0" -"com.sh\0es.leg.br\0" -"tt.im\0" -"sn.cn\0com.sl\0" -"com.sn\0\xd8\xa7\xd9\x84\xd8\xb3\xd8\xb9\xd9\x88\xd8\xaf\xd9\x8a\xd8\xa9\0*.on-rancher.cloud\0" -"yachiyo.chiba.jp\0com.so\0" -"he.cn\0ud.it\0sklep.pl\0youtube\0ca.eu.org\0" -"honjo.akita.jp\0com.ss\0" -"com.st\0is-uberleet.com\0" -"mel\xc3\xb8y.no\0" -"hakata.fukuoka.jp\0com.sv\0" -"yamamoto.miyagi.jp\0" -"com.sy\0" -"olsztyn.pl\0com.tj\0" -"vik.no\0" -"enf.br\0konan.shiga.jp\0flowers\0we.tc\0" -"d.bg\0com.tm\0g.vbrplsbx.io\0" -"com.tn\0cafe\0" -"com.to\0postman-echo.com\0" -"rs.ba\0" -"snaase.no\0com.ua\0dnsupdater.de\0" -"gov.ac\0gulen.no\0com.tr\0" -"nieruchomosci.pl\0dvrcam.info\0" -"gov.ae\0com.tt\0" -"gov.af\0suli.hu\0avocat.pro\0" -"to.gov.br\0izunokuni.shizuoka.jp\0gsm.pl\0cupcake.is\0" -"verran.no\0com.tw\0com.ug\0" -"vipsinaapp.com\0" -"lel.br\0loginline.services\0" -"komagane.nagano.jp\0" -"gov.al\0" -"*.owo.codes\0app.render.com\0" +"\xe5\x8c\x97\xe6\xb5\xb7\xe9\x81\x93.jp\0ota.gunma.jp\0chippubetsu.hokkaido.jp\0date.hokkaido.jp\0tone.ibaraki.jp\0yamada.iwate.jp\0goto.nagasaki.jp\0moriguchi.osaka.jp\0yaizu.shizuoka.jp\0deca.jp\0run.app\0" +"\xe6\x94\xbf\xe5\x8a\xa1\0" +"feira.br\0ma.gov.br\0" +"moe\0orange\0filegear.me\0" +"coach\0" +"moi\0" +"presse.km\0alstom\0mom\0fldrv.com\0" +"cc.ak.us\0" +"guide\0" +"\xd9\x81\xd9\x84\xd8\xb3\xd8\xb7\xd9\x8a\xd9\x86\0mov\0" +"accesscam.org\0" +"griw.gov.pl\0" +"mincom.tn\0" +"flesberg.no\0kongsberg.no\0lund.no\0roan.no\0" +"namikata.ehime.jp\0ukiha.fukuoka.jp\0tatebayashi.gunma.jp\0kushiro.hokkaido.jp\0azumino.nagano.jp\0haibara.shizuoka.jp\0" +"tsk.tr\0nab\0" "diamonds\0" -"ina.saitama.jp\0honefoss.no\0" +"router.management\0" +"sport.hu\0" +"tjmaxx\0" +"framer.wiki\0" +"k12.il\0presse.ml\0hotmail\0" +"webview-assets.cloud9.ap-northeast-2.amazonaws.com\0instance.datadetect.com\0" +"id.firewalledreplit.co\0tickets.io\0" +"nba\0" +"pvt.k12.ma.us\0" +"medio-campidano.it\0ms.it\0static-access.net\0" +"curv.dev\0" +"kazimierz-dolny.pl\0kaszuby.pl\0" +"trading.aero\0" +"!city.kitakyushu.jp\0oguchi.aichi.jp\0hachirogata.akita.jp\0takahama.fukui.jp\0kasahara.gifu.jp\0kiryu.gunma.jp\0takazaki.miyazaki.jp\0himeshima.oita.jp\0izumisano.osaka.jp\0cocotte.jp\0rdy.jp\0" +"msd\0" +"s3-website-eu-west-1.amazonaws.com\0us.com\0simple-url.com\0barsycenter.com\0" +"\xe6\xb7\xa1\xe9\xa9\xac\xe9\x94\xa1\0" +"ms.kr\0" +"rocks\0" +"trentinsuedtirol.it\0umbria.it\0monza-brianza.it\0" +"info.zm\0" +"mtn\0" +"caa.aero\0deporte.bo\0hurum.no\0davvenjarga.no\0" +"kyoto.jp\0miyoshi.aichi.jp\0kure.hiroshima.jp\0chikusei.ibaraki.jp\0fudai.iwate.jp\0ogawara.miyagi.jp\0hasuda.saitama.jp\0hino.tottori.jp\0platform0.app\0" +"\xd1\x81\xd0\xbf\xd0\xb1.\xd1\x80\xd1\x83\xd1\x81\0" +"maceio.br\0mtr\0" +"nec\0" +"pri.ee\0sex.hu\0" +"dubai\0" +"is-an-entertainer.com\0is-certified.com\0" +"repl.co\0" +"fl.us\0ny.us\0wv.us\0" +"ve.it\0net\0service.gov.scot\0" +"*.tst.site\0" +"\xd8\xb3\xd9\x88\xd8\xb1\xd9\x8a\xd8\xa7\0new\0" +"amex\0" +"\xd8\xb3\xd9\x88\xd8\xb1\xd9\x8a\xd8\xa9\0" +"gniezno.pl\0nfl\0" +"lincoln\0" +"ballangen.no\0hareid.no\0hol.no\0nesna.no\0" +"yachiyo.chiba.jp\0kawamata.fukushima.jp\0shari.hokkaido.jp\0shimodate.ibaraki.jp\0komatsu.ishikawa.jp\0kameyama.mie.jp\0higashikurume.tokyo.jp\0yamada.toyama.jp\0hashimoto.wakayama.jp\0" +"\xd8\xa7\xd9\x84\xd8\xb9\xd9\x84\xd9\x8a\xd8\xa7\xd9\x86\0" +"s3-ca-central-1.amazonaws.com\0qc.com\0kilatiron.com\0" +"ngo\0" +"audible\0" +"certmgr.org\0" +"nhk\0" +"katowice.pl\0" +"flight.aero\0wiki.bo\0orland.no\0sigdal.no\0" +"ehime.jp\0\xe7\x9f\xb3\xe5\xb7\x9d.jp\0tamatsukuri.ibaraki.jp\0soo.kagoshima.jp\0takagi.nagano.jp\0ibaraki.osaka.jp\0misaki.osaka.jp\0izunokuni.shizuoka.jp\0shimoda.shizuoka.jp\0miyoshi.tokushima.jp\0" +"wiki.br\0" +"*.rss.my.id\0" +"prime\0" +"financial\0" +"dreamhosters.com\0" +"pfizer\0" +"trentino-sud-tirol.it\0sondrio.it\0homeunix.net\0" +"col.ng\0" +"architectes.bj\0" +"for-our.info\0" +"chuo.chiba.jp\0ichihara.chiba.jp\0minakami.gunma.jp\0tsubata.ishikawa.jp\0tadotsu.kagawa.jp\0minamiyamashiro.kyoto.jp\0sayama.saitama.jp\0yasu.shiga.jp\0sagae.yamagata.jp\0but.jp\0" +"art.br\0" +"\xe5\x85\xab\xe5\x8d\xa6\0" +"from-ga.com\0x0.com\0" +"bj.cn\0" +"gyeongnam.kr\0" +"iglesiascarbonia.it\0to.gt\0" +"north-kazakhstan.su\0" +"consulting\0jp.eu.org\0" +"sex.pl\0" +"art.do\0\xc3\xa5krehamn.no\0hamaroy.no\0gallo\0" +"*.nagoya.jp\0buzen.fukuoka.jp\0soma.fukushima.jp\0naka.hiroshima.jp\0embetsu.hokkaido.jp\0joso.ibaraki.jp\0kunisaki.oita.jp\0kasaoka.okayama.jp\0tokashiki.okinawa.jp\0gotsu.shimane.jp\0chiyoda.tokyo.jp\0namaste.jp\0secret.jp\0sunnyday.jp\0" +"sebastopol.ua\0" +"k12.tr\0nc.tr\0" +"pdns.page\0" +"\xe8\xb4\xad\xe7\x89\xa9\0" +"art.dz\0" +"capital\0" +"is-a-therapist.com\0" +"eurovision\0" +"rodeo\0" +"ms.us\0nc.us\0" +"ce.it\0kr.it\0to.it\0flynnhosting.net\0" +"p.bg\0wmflabs.org\0" +"k12.vi\0" +"\xe5\x85\xac\xe7\x9b\x8a\0" +"wegrow.pl\0" +"balat.no\0s\xc3\xb8r-varanger.no\0" +"ochi.kochi.jp\0ikusaka.nagano.jp\0fukaya.saitama.jp\0yoshimi.saitama.jp\0okinoshima.shimane.jp\0higashimurayama.tokyo.jp\0musashimurayama.tokyo.jp\0" +"aeroport.fr\0" +"cloudapps.digital\0" +"s3.dualstack.eu-west-1.amazonaws.com\0" +"jl.cn\0" +"lib.sd.us\0framer.photos\0" +"barlettatraniandria.it\0" +"now\0" +"univ.bj\0" +"namdalseid.no\0randaberg.no\0romsa.no\0" +"akashi.hyogo.jp\0ono.hyogo.jp\0morotsuka.miyazaki.jp\0niigata.niigata.jp\0satte.saitama.jp\0musashino.tokyo.jp\0" +"art.ht\0android\0to.md\0" +"ybo.science\0" +"*.firenet.ch\0" +"balena-devices.com\0ownprovider.com\0" +"education\0" +"nra\0" +"sener\0" +"nexus\0loginline.services\0""123miweb.es\0" +"nordeste-idc.saveincloud.net\0" +"tas.edu.au\0" +"e.bg\0shaw\0" +"obi\0" +"*.alces.network\0" +"kwpsp.gov.pl\0" +"bu.no\0lindas.no\0oygarden.no\0s\xc3\xb8r-aurdal.no\0" +"hiranai.aomori.jp\0katsuura.chiba.jp\0fukagawa.hokkaido.jp\0aso.kumamoto.jp\0oshima.tokyo.jp\0" +"natal.br\0to.leg.br\0" +"glitch.me\0jelastic.regruhosting.ru\0" +"nrw\0" +"\xe8\x81\x94\xe9\x80\x9a\0" +"from-ne.com\0myvnc.com\0" +"canon\0jpmorgan\0" +"kg.kr\0" +"cc.ga.us\0lib.ak.us\0" +"campidano-medio.it\0" +"catering\0servebbs.org\0int.eu.org\0" +"africa.bj\0avocats.bj\0" +"boleslawiec.pl\0" +"accident-investigation.aero\0krager\xc3\xb8.no\0lea\xc5\x8bgaviika.no\0sauda.no\0" +"hokkaido.jp\0tokai.aichi.jp\0maebashi.gunma.jp\0tsurugi.ishikawa.jp\0kisosaki.mie.jp\0marumori.miyagi.jp\0kitagata.saga.jp\0ogi.saga.jp\0matsubushi.saitama.jp\0yamanakako.yamanashi.jp\0messerli.app\0" +"ntt\0" +"\xe5\x85\xac\xe5\x8f\xb8\0" +"jewelry\0study\0" +"elasticbeanstalk.com\0*.cns.joyent.com\0app.lmpm.com\0" +"zara\0" +"games\0motorcycles\0" +"ao.it\0balsan-s\xc3\xbc""dtirol.it\0si.it\0adobeaemcloud.net\0" +"\xd8\xa7\xd9\x84\xd8\xb3\xd8\xb9\xd9\x88\xd8\xaf\xd9\x8a\xd9\x87\0" +"psp.gov.pl\0" +"st.no\0amli.no\0" +"\xe6\xa0\x83\xe6\x9c\xa8.jp\0yokaichiba.chiba.jp\0nakatsugawa.gifu.jp\0yamagata.ibaraki.jp\0kizu.kyoto.jp\0iizuna.nagano.jp\0kouzushima.tokyo.jp\0hirogawa.wakayama.jp\0handcrafted.jp\0" +"report\0cs.keliweb.cloud\0" +"presse.ci\0xfinity\0" +"dyndns-pics.com\0" +"school.na\0" +"mycd.eu\0tselinograd.su\0" +"\xd8\xa7\xd9\x84\xd8\xb3\xd8\xb9\xd9\x88\xd8\xaf\xd9\x8a\xd8\xa9\0" +"babia-gora.pl\0ustka.pl\0warmia.pl\0art.pl\0" +"hitra.no\0""611.to\0oya.to\0" +"\xe7\x86\x8a\xe6\x9c\xac.jp\0onjuku.chiba.jp\0asakawa.fukushima.jp\0tsubetsu.hokkaido.jp\0kyotanabe.kyoto.jp\0uh-oh.jp\0" +"kr.ua\0shia\0" +"nyc\0" +"hgtv\0" +"school.nz\0" +"lundbeck\0" +"dyndns.dappnode.io\0" +"k12.or.us\0" +"mar.it\0rn.it\0target\0sytes.net\0" +"adygeya.su\0" +"asso.eu.org\0" +"academia.bo\0haram.no\0hornindal.no\0orsta.no\0" +"ad.jp\0tobe.ehime.jp\0inashiki.ibaraki.jp\0kashima.saga.jp\0hidaka.saitama.jp\0fuji.shizuoka.jp\0oguni.yamagata.jp\0sharp\0babymilk.jp\0icurus.jp\0" +"lviv.ua\0" +"mg.gov.br\0" +"place\0" +"daemon.panel.gg\0" +"webview-assets.cloud9.ca-central-1.amazonaws.com\0paas.massivegrid.com\0" +"qh.cn\0hk.cn\0post.in\0art.sn\0" +"cc.nh.us\0" +"trentin-s\xc3\xbc""d-tirol.it\0embaixada.st\0ipifony.net\0" +"webredirect.org\0" +"rawa-maz.pl\0" +"noticias.bo\0\xc3\xa5""fjord.no\0orskog.no\0r\xc3\xb8ros.no\0sor-fron.no\0jur.pro\0" +"!city.kawasaki.jp\0mitoyo.kagawa.jp\0motoyama.kochi.jp\0yoshinogari.saga.jp\0nakagawa.tokushima.jp\0gehirn.ne.jp\0" +"chernihiv.ua\0" +"support\0oxa.cloud\0" +"adygeya.ru\0" +"s3.dualstack.ap-northeast-1.amazonaws.com\0s3-us-gov-west-1.amazonaws.com\0s3-website-us-east-1.amazonaws.com\0cloudcontrolled.com\0xen.prgmr.com\0rackmaze.com\0" +"loan\0" +"computer\0" +"az.us\0" +"campidanomedio.it\0carraramassa.it\0genova.it\0latina.it\0rc.it\0" +"one\0bryansk.su\0*.platformsh.site\0" +"ong\0" +"klodzko.pl\0ostroda.pl\0onl\0" +"troandin.no\0" +"aizuwakamatsu.fukushima.jp\0higashikagura.hokkaido.jp\0awaji.hyogo.jp\0fujishiro.ibaraki.jp\0tosashimizu.kochi.jp\0umaji.kochi.jp\0choyo.kumamoto.jp\0otari.nagano.jp\0toyono.osaka.jp\0honjo.saitama.jp\0sakura.tochigi.jp\0takaoka.toyama.jp\0ube.yamaguchi.jp\0websozai.jp\0" +"tours\0" +"pvt.ge\0p.se\0" +"is-a-cubicle-slave.com\0is-a-doctor.com\0platter-app.com\0" +"xz.cn\0playstation\0" +"ooo\0cleverapps.io\0" +"shop\0" +"data\0" +"theater\0" +"fitness\0" +"s\xc3\xbc""dtirol.it\0familyds.net\0" +"bible\0date\0" +"show\0" +"ostroleka.pl\0""123website.nl\0" +"gs.oslo.no\0m\xc3\xa1latvuopmi.no\0" +"\xe5\xa4\xa7\xe5\x88\x86.jp\0matsuda.kanagawa.jp\0yokosuka.kanagawa.jp\0shiroishi.miyagi.jp\0ishikawa.okinawa.jp\0chuo.osaka.jp\0aridagawa.wakayama.jp\0cheap.jp\0" +"geometre-expert.fr\0" +"de.trendhosting.cloud\0" +"loginto.me\0" +"barsy.co.uk\0" +"us-east-2.elasticbeanstalk.com\0servebeer.com\0authgearapps.com\0" +"univ.sn\0" +"pb.ao\0" +"mobi.gp\0" +"or.at\0trentino-alto-adige.it\0gb.net\0*.kunden.ortsinfo.at\0iobb.net\0reserve-online.net\0" +"rar.ve\0azure\0vladimir.su\0" +"9.bg\0org\0is.eu.org\0" +"or.bi\0pay\0dscloud.mobi\0" +"ballooning.aero\0nombre.bo\0fyresdal.no\0sauherad.no\0" +"\xe6\x84\x9b\xe7\x9f\xa5.jp\0yachimata.chiba.jp\0hokuryu.hokkaido.jp\0asago.hyogo.jp\0sango.nara.jp\0" +"lutsk.ua\0" +"trafficplex.cloud\0" +"e.se\0""123website.lu\0" +"or.ci\0" +"cookingchannel\0" +"s3.eu-central-1.amazonaws.com\0is-a-democrat.com\0ip.linodeusercontent.com\0health-carereform.com\0" +"delta\0" +"or.cr\0\xe3\x82\xb9\xe3\x83\x88\xe3\x82\xa2\0" +"cc.de.us\0" +"valledaosta.it\0" +"it.eu.org\0" +"divttasvuotna.no\0kyoto\0dvrcam.info\0" +"imari.saga.jp\0mugi.tokushima.jp\0kokubunji.tokyo.jp\0" +"osasco.br\0" +"adult\0cloud\0ott\0" +"storage\0vladimir.ru\0" +"family\0" +"vfs.cloud9.eu-south-1.amazonaws.com\0" +"og.ao\0" +"liguria.it\0valle-daosta.it\0ven.it\0etisalat\0pet\0dynathome.net\0schokokeks.net\0" +"homeunix.org\0" +"ovh\0" +"mielno.pl\0sanok.pl\0" +"stathelle.no\0gulen.no\0k\xc3\xa1r\xc3\xa1\xc5\xa1johka.no\0n\xc3\xa6r\xc3\xb8y.no\0n\xc3\xb8tter\xc3\xb8y.no\0ruovat.no\0sande.more-og-romsdal.no\0" +"\xe5\xa4\xa7\xe9\x98\xaa.jp\0umi.fukuoka.jp\0oarai.ibaraki.jp\0staba.jp\0" +"forte.id\0" +"mcdir.me\0" +"cloud.goog\0" +"bip.sh\0" +"fj.cn\0vision\0" +"bitbucket.io\0edugit.io\0" +"lib.nv.us\0" +"rome.it\0phd\0twmail.net\0" +"draydns.de\0" +"blogdns.org\0in.eu.org\0" +"\xe6\x94\xbf\xe5\xba\x9c.hk\0tlon.network\0" +"lowicz.pl\0" +"equipment.aero\0scientist.aero\0m\xc3\xa5s\xc3\xb8y.no\0nes.akershus.no\0" +"\xe4\xb8\x89\xe9\x87\x8d.jp\0kira.aichi.jp\0itayanagi.aomori.jp\0narashino.chiba.jp\0misato.saitama.jp\0peewee.jp\0" +"if.ua\0zp.ua\0" +"or.id\0pid\0" +"kiwi.nz\0" +"space-to-rent.com\0lpusercontent.com\0pro.typeform.com\0" +"pin\0" +"*.backyards.banzaicloud.io\0" +"hoplix.shop\0" +"k12.co.us\0k12.vi.us\0" +"ge.it\0or.it\0" +"is-a-celticsfan.org\0" +"online.th\0" +"work\0" +"sejny.pl\0" +"storj.farm\0" +"aremark.no\0ask\xc3\xb8y.no\0" +"or.jp\0okinawa.jp\0\xe5\xa5\x88\xe8\x89\xaf.jp\0\xe5\xb1\xb1\xe6\xa2\xa8.jp\0yamatotakada.nara.jp\0kishiwada.osaka.jp\0sanagochi.tokushima.jp\0fuchu.tokyo.jp\0kinokawa.wakayama.jp\0" +"nl.ca\0" +"sport\0" +"or.ke\0" +"nl.ci\0" +"school\0" +"from-ky.com\0" +"protonet.io\0" +"or.kr\0" +"lib.ms.us\0lib.nc.us\0lib.vt.us\0cloud66.ws\0" +"friuli-vgiulia.it\0serveminecraft.net\0" +"123website.be\0" +"silk\0" +"elblag.pl\0" +"\xe0\xae\x87\xe0\xae\xa8\xe0\xaf\x8d\xe0\xae\xa4\xe0\xae\xbf\xe0\xae\xaf\xe0\xae\xbe\0" +"aeroclub.aero\0repbody.aero\0aurland.no\0hagebostad.no\0ringsaker.no\0s\xc3\xa1l\xc3\xa1t.no\0" +"kanagawa.jp\0nara.jp\0saga.jp\0ozu.ehime.jp\0hichiso.gifu.jp\0shiroishi.saga.jp\0sakado.saitama.jp\0bambina.jp\0" +"co.events\0" +"123website.ch\0" +"vfs.cloud9.ap-northeast-2.amazonaws.com\0try-snowplow.com\0" +"ed.ao\0" +"or.na\0sina\0" +"k12.la.us\0pnc\0" +"og.it\0" +"act.au\0or.mu\0" +"sling\0doesntexist.org\0" +"lapy.pl\0" +"andebu.no\0frei.no\0unj\xc3\xa1rga.no\0globo\0" +"noshiro.akita.jp\0chikugo.fukuoka.jp\0ibara.okayama.jp\0kodaira.tokyo.jp\0nyuzen.toyama.jp\0" +"vodka\0\xd1\x81\xd0\xb0\xd0\xbc\xd0\xb0\xd1\x80\xd0\xb0.\xd1\x80\xd1\x83\xd1\x81\0" +"vip.jelastic.cloud\0" +"ed.ci\0" +"ed.cr\0" +"lib.va.us\0swiss\0" +"forl\xc3\xac-cesena.it\0centralus.azurestaticapps.net\0" +"skype\0framer.website\0" +"trading\0opencraft.hosting\0" +"reg.dk\0" +"ugim.gov.pl\0\xe7\xbd\x91\xe7\xbb\x9c\0" +"agents.aero\0catering.aero\0democracia.bo\0rodoy.no\0salat.no\0tana.no\0" +"kamikawa.hokkaido.jp\0kanegasaki.iwate.jp\0shinagawa.tokyo.jp\0fakefur.jp\0" +"mcdir.ru\0" +"or.pw\0\xe5\x95\x86\xe5\xba\x97\0" +"\xd8\xa7\xd9\x84\xd9\x85\xd8\xba\xd8\xb1\xd8\xa8\0" +"webview-assets.cloud9.eu-west-3.amazonaws.com\0is-a-techie.com\0barsyonline.com\0" +"gen.in\0" +"qcx.io\0" +"now-dns.top\0" +"sakura\0" +"realtor\0" +"codes\0" +"love\0" +"us.ax\0" +"123kotisivu.fi\0" +"b\xc3\xb8.nordland.no\0etnedal.no\0pro\0www.ro\0" +"odawara.kanagawa.jp\0nobeoka.miyazaki.jp\0okuizumo.shimane.jp\0nakamichi.yamanashi.jp\0" +"pru\0" +"from-ri.com\0" +"hostyhosting.io\0" +"cc.sc.us\0lib.ct.us\0lib.mi.us\0" +"t3l3p0rt.net\0broke-it.net\0podzone.net\0lon-1.paas.massivegrid.net\0" +"site\0theatre\0dyndns1.de\0" +"or.th\0" +"lipsy\0" +"brumunddal.no\0b\xc3\xa5""d\xc3\xa5""ddj\xc3\xa5.no\0drangedal.no\0lahppi.no\0l\xc3\xb8renskog.no\0seljord.no\0" +"\xe6\xbb\x8b\xe8\xb3\x80.jp\0kiyosato.hokkaido.jp\0otoyo.kochi.jp\0suzuka.mie.jp\0konan.shiga.jp\0shimizu.shizuoka.jp\0" +"pub\0df.leg.br\0" +"discount\0" +"or.ug\0" +"oldnavy\0" +"soc.dz\0or.tz\0" +"lugs.org.uk\0" +"lplfinancial\0" +"doomdns.com\0is-a-geek.com\0ddnsfree.com\0yali.mythic-beasts.com\0" +"or.us\0" +"brescia.it\0monza.it\0na.it\0rieti.it\0venice.it\0nhlfan.net\0" +"website\0" +"voting\0webhop.org\0gen.ng\0" +"\xe9\x80\x9a\xe8\xb2\xa9\0" +"nysa.pl\0" +"nl.no\0muosat.no\0meraker.no\0" +"ed.jp\0ebetsu.hokkaido.jp\0taiki.hokkaido.jp\0katsuragi.nara.jp\0shimokitayama.nara.jp\0arakawa.saitama.jp\0wakayama.wakayama.jp\0" +"ternopil.ua\0*.awdev.ca\0" +"\xe0\xb9\x84\xe0\xb8\x97\xe0\xb8\xa2\0" +"pwc\0" +"mobi.tt\0" +"co.place\0" +"gen.nz\0mobi.tz\0" +"from-mo.com\0from-nh.com\0from-wi.com\0xnbay.com\0" +"lib.ca.us\0recipes\0" +"trentin-s\xc3\xbc""dtirol.it\0" +"\xe0\xa4\xb8\xe0\xa4\x82\xe0\xa4\x97\xe0\xa4\xa0\xe0\xa4\xa8\0ath.cx\0" +"dclk\0" +"is.gov.pl\0ecommerce-shop.pl\0" +"barsy.info\0" +"*.northflank.app\0jeez.jp\0" +"est.pr\0rj.leg.br\0" +"canva-apps.com\0" +"us.in\0" +"us.ngrok.io\0" +"caltanissetta.it\0ravenna.it\0vc.it\0ts.net\0" +"warszawa.pl\0wroclaw.pl\0" +"orangecloud.tn\0" +"askim.no\0moareke.no\0nannestad.no\0" +"taka.hyogo.jp\0yachiyo.ibaraki.jp\0fukuchiyama.kyoto.jp\0kita.kyoto.jp\0her.jp\0" +"abc.br\0" +"jobs.tt\0" +"*.spectrum.myjino.ru\0" +"better-than.tv\0" +"us.kg\0" +"s3-website-ap-southeast-2.amazonaws.com\0" +"*.azurecontainer.io\0" +"mobi.na\0" +"bulsan-suedtirol.it\0" +"mobi.ng\0plumbing\0in-dsl.org\0" +"tm.cy\0" +"jozi.biz\0" +"soc.lk\0" +"malbork.pl\0" +"federation.aero\0salud.bo\0moss.no\0" +"shibukawa.gunma.jp\0shikabe.hokkaido.jp\0hitachiota.ibaraki.jp\0hiraizumi.iwate.jp\0sakai.osaka.jp\0" +"gen.tr\0" +"ed.pw\0" +"community\0" +"tm.dz\0" +"\xe6\x96\xb0\xe9\x97\xbb\0" +"s3.dualstack.us-east-2.amazonaws.com\0webview-assets.cloud9.eu-west-2.amazonaws.com\0" +"cn.in\0" +"us.na\0" +"wi.us\0" +"cn.it\0" +"vic.au\0service.one\0" +"y.bg\0" +"agro.bj\0" +"czest.pl\0" +"media.aero\0agro.bo\0unjarga.no\0sorreisa.no\0" +"rishiri.hokkaido.jp\0ine.kyoto.jp\0miyama.mie.jp\0isahaya.nagasaki.jp\0iwatsuki.saitama.jp\0bato.tochigi.jp\0kai.yamanashi.jp\0under.jp\0" +"dev.br\0jor.br\0teo.br\0tm.fr\0" +"123paginaweb.pt\0" +"u2.xnbay.com\0" +"\xd8\xa8\xd8\xa7\xd8\xb2\xd8\xa7\xd8\xb1\0" +"cc.gu.us\0cc.pr.us\0photos\0" +"vallee-d-aoste.it\0select\0myfast.host\0" +"is-a-geek.org\0" +"cc.hn\0" +"b\xc3\xb8.telemark.no\0malatvuopmi.no\0" +"\xe9\x95\xb7\xe5\xb4\x8e.jp\0oirase.aomori.jp\0ainan.ehime.jp\0otsuchi.iwate.jp\0isa.kagoshima.jp\0oita.oita.jp\0omachi.saga.jp\0tochigi.tochigi.jp\0oshino.yamanashi.jp\0" +"vn.ua\0" +"saobernardo.br\0" +"tm.hu\0mobi.ke\0" +"dyn-o-saur.com\0" +"servers.run\0" +"studio\0" +"k12.id.us\0" +"bs.it\0grosseto.it\0akamaiorigin-staging.net\0mydatto.net\0faststacks.net\0" +"tas.gov.au\0pokrovsk.su\0" +"n.bg\0\xd9\x85\xd9\x84\xd9\x8a\xd8\xb3\xd9\x8a\xd8\xa7\0" +"gs.ol.no\0bygland.no\0oksnes.no\0ringerike.no\0s\xc3\xb8rfold.no\0" +"shitara.aichi.jp\0nakanoto.ishikawa.jp\0nishiawakura.okayama.jp\0sennan.osaka.jp\0nishikata.tochigi.jp\0" +"chernovtsy.ua\0" +"am.br\0slg.br\0" +"philips\0" +"reliance\0" +"baby\0" +"govt.nz\0" +"tm.km\0cn.com\0servegame.com\0authgear-staging.com\0" +"pantheonsite.io\0virtualserver.io\0" +"school.za\0" +"doctor\0" +"leclerc\0" +"saarland\0map.fastly.net\0""3.azurestaticapps.net\0rackmaze.net\0" +"pt.eu.org\0familyds.org\0" +"honefoss.no\0" +"kagoshima.jp\0\xe9\x9d\x99\xe5\xb2\xa1.jp\0aisai.aichi.jp\0erimo.hokkaido.jp\0kashima.ibaraki.jp\0greater.jp\0" +"lv.ua\0zaporizhzhe.ua\0nagoya\0" +"on-web.fr\0" +"tm.mc\0" +"red\0" +"maif\0" +"tm.mg\0" +"s3-ap-southeast-2.amazonaws.com\0vfs.cloud9.ap-south-1.amazonaws.com\0eu-4.evennode.com\0ocelot.mythic-beasts.com\0" +"6g.in\0ren\0" +"paas.beebyte.io\0" +"cc.na\0" +"sr.it\0" +"c.bg\0" +"ismaili\0" +"tm.no\0askoy.no\0evenes.no\0here-for-more.info\0" +"higashi.fukuoka.jp\0kani.gifu.jp\0hatsukaichi.hiroshima.jp\0higashikagawa.kagawa.jp\0nozawaonsen.nagano.jp\0sekikawa.niigata.jp\0nishiizu.shizuoka.jp\0" +"ab.ca\0zhitomir.ua\0" +"imb.br\0" +"voyage\0" +"dnsking.ch\0" +"from-tn.com\0smushcdn.com\0" +"cc.wy.us\0" +"half.host\0" +"s3.teckids.org\0" +"co.technology\0" +"tm.pl\0uzs.gov.pl\0williamhill\0" +"flor\xc3\xb8.no\0raholt.no\0storfjord.no\0" +"itakura.gunma.jp\0shibecha.hokkaido.jp\0omi.niigata.jp\0sadist.jp\0" +"cn.ua\0" +"iz.hr\0rr.leg.br\0" +"cards\0" +"ril\0" +"servebbs.com\0eu-3.evennode.com\0wpmucdn.com\0blogsyte.com\0" +"am.in\0skin\0\xe0\xa4\x95\xe0\xa5\x89\xe0\xa4\xae\0" +"rio\0id.repl.co\0" +"rip\0ju.mp\0" +"tx.us\0k12.pa.us\0" +"trentinostirol.it\0" +"id.au\0cologne\0" +"fi.cloudplatform.fi\0" +"halsa.no\0nordreisa.no\0sondre-land.no\0tm.ro\0" +"kamogawa.chiba.jp\0narita.chiba.jp\0obama.fukui.jp\0hirokawa.fukuoka.jp\0inatsuki.fukuoka.jp\0fukushima.hokkaido.jp\0tsukuba.ibaraki.jp\0urasoe.okinawa.jp\0tamayu.shimane.jp\0yuu.yamaguchi.jp\0" +"rs.leg.br\0sc.leg.br\0" +"tm.se\0cn.vu\0" +"suzuki\0" +"ap-northeast-1.elasticbeanstalk.com\0" +"friulive-giulia.it\0trentino-sudtirol.it\0blogdns.net\0futuremailing.at\0" +"mobile\0wellbeingzone.eu\0" +"twmail.org\0" +"broadway\0" +"jaworzno.pl\0" +"kagamiishi.fukushima.jp\0kawaba.gunma.jp\0kahoku.ishikawa.jp\0yugawara.kanagawa.jp\0asahi.nagano.jp\0mints.ne.jp\0" +"cc.ua\0" +"goiania.br\0" +"clubmed\0" +"deal\0elementor.cool\0" +"webview-assets.cloud9.eu-south-1.amazonaws.com\0is-a-hard-worker.com\0eu-2.evennode.com\0sakuratan.com\0" +"io.in\0" +"\xe4\xb8\xad\xe6\x96\x87\xe7\xbd\x91\0" +"jeju.kr\0" +"forl\xc3\xac""cesena.it\0band\0""2ix.at\0" +"*.lclstage.dev\0" +"\xe0\xba\xa5\xe0\xba\xb2\xe0\xba\xa7\0" +"yandex\0" +"press.cy\0" +"nowruz\0" +"bank\0" +"cargo.aero\0gjemnes.no\0s\xc3\xb8rreisa.no\0" +"yoichi.hokkaido.jp\0zentsuji.kagawa.jp\0fujisawa.kanagawa.jp\0minami.kyoto.jp\0ogawa.nagano.jp\0arai.shizuoka.jp\0" +"contagem.br\0jus.br\0" +"perspecta.cloud\0" +"y.se\0" +"io.kg\0" +"2ix.ch\0" +"s3.dualstack.eu-west-2.amazonaws.com\0trycloudflare.com\0" +"hi.cn\0" +"\xd9\x82\xd8\xb7\xd8\xb1\0c.la\0" +"vicenza.it\0freetls.fastly.net\0" +"storebase.store\0""2ix.de\0" +"is-a-knight.org\0podzone.org\0" +"agency\0" +"civilaviation.aero\0br\xc3\xb8nn\xc3\xb8y.no\0galsa.no\0roros.no\0" +"fujisato.akita.jp\0kamishihoro.hokkaido.jp\0kamisunagawa.hokkaido.jp\0ozora.hokkaido.jp\0onagawa.miyagi.jp\0kamitonda.wakayama.jp\0edgecompute.app\0" +"arab\0rn.leg.br\0" +"accountants\0" +"soundcast.me\0" +"is-a-personaltrainer.com\0eu-1.evennode.com\0servehumour.com\0" +"datsun\0" +"ap.ngrok.io\0" +"sap\0" +"law.za\0tm.za\0" +"id.ir\0" +"gen.mi.us\0sas\0" +"valleedaoste.it\0andria-barletta-trani.it\0ra.it\0dnsalias.net\0azure-mobile.net\0" +"insure\0eero-stage.online\0tuva.su\0""123webseite.de\0" +"aland.fi\0sbi\0" +"assur.bj\0" +"aus.basketball\0" +"rl.no\0trogstad.no\0vads\xc3\xb8.no\0dnsupdate.info\0" +"ibaraki.jp\0urausu.hokkaido.jp\0muko.kyoto.jp\0matsushima.miyagi.jp\0asaka.saitama.jp\0nagatoro.saitama.jp\0yokoze.saitama.jp\0chuo.tokyo.jp\0lovesick.jp\0" +"sca\0" +"scb\0ro.leg.br\0" +"jobs\0sbs\0" +"n.se\0dev.vu\0" +"mediatech.by\0" +"\xd7\x99\xd7\xa9\xd7\x95\xd7\x91.\xd7\x99\xd7\xa9\xd7\xa8\xd7\x90\xd7\x9c\0" +"vfs.cloud9.ca-central-1.amazonaws.com\0" +"supabase.in\0" +"sekd1.beebyteapp.io\0" +"toyota\0" +"lib.ga.us\0lib.or.us\0" +"emiliaromagna.it\0akamaihd-staging.net\0""123webseite.at\0" +"allstate\0" +"agro.pl\0czeladz.pl\0shell\0" +"saltdal.no\0abogado\0" +"ama.aichi.jp\0ichikawa.chiba.jp\0ogori.fukuoka.jp\0ebino.miyazaki.jp\0ouchi.saga.jp\0tendo.yamagata.jp\0babyblue.jp\0chips.jp\0" +"kharkiv.ua\0khmelnitskiy.ua\0" +"desa.id\0" +"id.lv\0" +"id.ly\0realty\0" +"lug.org.uk\0wellbeingzone.co.uk\0" +"gmail\0" +"dyndns-home.com\0securitytactics.com\0" +"run\0" +"courses\0" +"pv.it\0credit\0vpndns.net\0" +"mangyshlak.su\0" +"7.bg\0sew\0edu.eu.org\0" +"sex\0" +"crafting.xyz\0" +"miasta.pl\0" +"gs.tr.no\0hurdal.no\0aejrie.no\0salangen.no\0zero\0" +"yoshikawa.saitama.jp\0matsushige.tokushima.jp\0nanto.toyama.jp\0hacca.jp\0" +"gc.ca\0" +"ecn.br\0sfr\0" +"c.se\0rwe\0" +"mymailer.com.tw\0" +"xx.gl\0" +"webview-assets.cloud9.us-east-1.amazonaws.com\0sells-for-u.com\0" +"direct.quickconnect.cn\0" +"crd.co\0" +"cc.dc.us\0" +"trentino-s-tirol.it\0trentinsudtirol.it\0in-dsl.net\0" +"penza.su\0" +"xbox\0" +"\xe7\xbd\x91\xe7\xb5\xa1.hk\0" +"dell\0hosting-cluster.nl\0" +"rissa.no\0" +"mitane.akita.jp\0shiroi.chiba.jp\0date.fukushima.jp\0iki.nagasaki.jp\0iheya.okinawa.jp\0motobu.okinawa.jp\0daito.osaka.jp\0shingu.wakayama.jp\0" +"vapor.cloud\0" +"itcouldbewor.se\0" +"schwarz\0" +"s3-website.ap-northeast-2.amazonaws.com\0dyndns-server.com\0hidora.com\0" +"supabase.co\0" +"k12.nm.us\0" +"piemonte.it\0trentinsued-tirol.it\0padua.it\0trapani.it\0webhop.net\0sg-1.paas.massivegrid.net\0" +"cooking\0nflfan.org\0" +"wroc.pl\0" +"berlevag.no\0kl\xc3\xa6""bu.no\0levanger.no\0rakkestad.no\0" +"iwate.jp\0katori.chiba.jp\0asahi.mie.jp\0kashihara.nara.jp\0kawaiishop.jp\0" +"nu.ca\0" +"lel.br\0ba.leg.br\0" +"expert\0" +"bashkiria.ru\0myds.me\0" +"vxl.sh\0" +"ski\0" +"us-gov-west-1.elasticbeanstalk.com\0is-a-socialist.com\0likes-pie.com\0demo.jelastic.com\0" +"lib.oh.us\0" +"puglia.it\0trentins\xc3\xbc""d-tirol.it\0is-a-geek.net\0gov.scot\0" +"style\0bashkiria.su\0" +"\xd9\x85\xd9\x88\xd8\xb1\xd9\x8a\xd8\xaa\xd8\xa7\xd9\x86\xd9\x8a\xd8\xa7\0" +"health\0" +"sky\0" +"econo.bj\0" +"dlugoleka.pl\0sosnowiec.pl\0" +"sola.no\0troms\xc3\xb8.no\0vang.no\0fido\0" +"chitose.hokkaido.jp\0yahiko.niigata.jp\0kitamoto.saitama.jp\0ondigitalocean.app\0" +"\xd0\xbe\xd1\x80\xd0\xb3.\xd1\x81\xd1\x80\xd0\xb1\0" +"avocat.fr\0" +"game.tw\0\xd2\x9b\xd0\xb0\xd0\xb7\0" +"m\xc4\x81ori.nz\0" +"us-east-1.elasticbeanstalk.com\0serveexchange.com\0qa2.com\0" +"id.us\0k12.de.us\0k12.md.us\0" +"tashkent.su\0" +"js.org\0" +"army\0" +"\xd0\xb1\xd0\xb5\xd0\xbb\0" +"evenassi.no\0giehtavuoatna.no\0marnardal.no\0overhalla.no\0skj\xc3\xa5k.no\0" +"kumakogen.ehime.jp\0shikokuchuo.ehime.jp\0yamato.fukushima.jp\0iwaizumi.iwate.jp\0shinjo.okayama.jp\0nasu.tochigi.jp\0kitayama.wakayama.jp\0hiho.jp\0thick.jp\0" +"\xd0\xb1\xd0\xb8\xd0\xb7.\xd1\x80\xd1\x83\xd1\x81\0" +"adm.br\0pa.gov.br\0rep.br\0samsclub\0se.leg.br\0" +"\xe3\x82\xa2\xe3\x83\x9e\xe3\x82\xbe\xe3\x83\xb3\0" +"equipment\0" +"desi\0" +"s3-website-us-west-2.amazonaws.com\0from-al.com\0from-or.com\0is-a-nurse.com\0" +"kitchen\0" +"arpa\0spa\0" +"boehringer\0" +"lib.ne.us\0systems\0" +"dentist\0" +"isteingeek.de\0" +"githubpreview.dev\0" +"\xe7\xbd\x91\xe5\xba\x97\0tele.amune.org\0" +"soy\0" +"foodnetwork\0" +"*.user.fm\0" +"nat.tn\0" +"works.aero\0b\xc3\xb8mlo.no\0leangaviika.no\0odda.no\0" +"choshi.chiba.jp\0fujisawa.iwate.jp\0rifu.miyagi.jp\0watari.miyagi.jp\0mitsue.nara.jp\0hikone.shiga.jp\0nishikawa.yamagata.jp\0" +"pb.gov.br\0tab\0" +"press.se\0vps.mcdir.ru\0" +"maori.nz\0" +"s3.dualstack.ap-south-1.amazonaws.com\0cloud.nospamproxy.com\0mytabit.com\0" +"co.education\0" +"nsn.us\0hi.us\0k12.tn.us\0bauhaus\0" +"fvg.it\0marche.it\0cremona.it\0laquila.it\0nu.it\0" +"software\0" +"tax\0" +"holiday\0" +"srl\0" +"kvanangen.no\0sor-odal.no\0valle.no\0" +"\xe5\xba\x83\xe5\xb3\xb6.jp\0!city.kobe.jp\0kitashiobara.fukushima.jp\0gujo.gifu.jp\0ikeda.gifu.jp\0tomika.gifu.jp\0morioka.iwate.jp\0tsukumi.oita.jp\0takaishi.osaka.jp\0kosai.shizuoka.jp\0imizu.toyama.jp\0mamurogawa.yamagata.jp\0boo.jp\0" +"jab.br\0am.leg.br\0" +"coupons\0" +"nl-ams-1.baremetal.scw.cloud\0" +"church\0" +"tci\0" +"\xe7\xbd\x91\xe7\xbb\x9c.cn\0mo.cn\0salon\0" +"\xe6\x96\xb0\xe5\x8a\xa0\xe5\x9d\xa1\0asda\0" +"cc.ar.us\0stc\0" +"arte\0*.uberspace.de\0" +"tdk\0" +"elk.pl\0tarnobrzeg.pl\0" +"film\0" +"control.aero\0hammerfest.no\0" +"semboku.akita.jp\0fukuyama.hiroshima.jp\0shiogama.miyagi.jp\0tagajo.miyagi.jp\0kitadaito.okinawa.jp\0mods.jp\0" +"media\0nokia\0" +"plo.ps\0" +"brand.se\0translated.page\0daplie.me\0dscloud.me\0" +"tel\0" +"bbva\0natura\0" +"engineer\0" +"aquila.it\0akamaized.net\0clickrising.net\0" +"hosting\0" +"sdn.gov.pl\0" +"emergency.aero\0gs.svalbard.no\0" +"\xe9\xb3\xa5\xe5\x8f\x96.jp\0obihiro.hokkaido.jp\0ino.kochi.jp\0yatsushiro.kumamoto.jp\0yasaka.nagano.jp\0fujiidera.osaka.jp\0habikino.osaka.jp\0yakumo.shimane.jp\0taito.tokyo.jp\0whitesnow.jp\0" +"press.ma\0" +"isla.pr\0" +"whm.fr-par.scw.cloud\0" +"dnsfor.me\0" +"md.ci\0" +"is-a-conservative.com\0" +"\xe0\xa6\xac\xe0\xa6\xbe\xe0\xa6\x82\xe0\xa6\xb2\xe0\xa6\xbe\0" +"aramco\0lpages.co\0cust.testing.thingdust.io\0" +"rep.kp\0tra.kp\0" +"trentinos-tirol.it\0trentinosud-tirol.it\0thd\0\xe7\xbb\x84\xe7\xbb\x87\xe6\x9c\xba\xe6\x9e\x84\0futurehosting.at\0" +"realestate\0" +"my-firewall.org\0" +"\xe7\xbd\x91\xe7\xbb\x9c.hk\0" +"airtraffic.aero\0indigena.bo\0porsangu.no\0direct.quickconnect.to\0" +"kawaue.gifu.jp\0nago.okinawa.jp\0otsu.shiga.jp\0" +"asia\0" +"*.nom.br\0ap.leg.br\0" +"net.ac\0" +"voorloper.cloud\0" +"net.ae\0" +"net.af\0" +"net.ag\0" +"net.ai\0" +"net.al\0" +"net.am\0amsterdam\0*.ocs.customer-oci.com\0" +"dr.in\0" +"promo\0g.vbrplsbx.io\0" +"net.ba\0" +"net.ar\0net.bb\0tv.bb\0" +"mo.it\0monzaedellabrianza.it\0reggio-emilia.it\0" +"net.au\0fire\0" +"fishing\0" +"net.bh\0" +"net.az\0net.bj\0" +"net.bm\0" +"net.bn\0" +"engineer.aero\0net.bo\0tv.bo\0\xc3\xa1laheadju.no\0cpa.pro\0" +"gifu.jp\0uto.kumamoto.jp\0inabe.mie.jp\0achi.nagano.jp\0izumo.shimane.jp\0\xe3\x82\xb3\xe3\x83\xa0\0topaz.ne.jp\0" +"krym.ua\0avianca\0" +"net.br\0tv.br\0" +"net.bs\0" +"net.bt\0publ.pt\0" +"fh.se\0boutique\0site.transip.me\0" +"fish\0irish\0tjx\0" +"net.ci\0" +"net.bz\0" +"net.cm\0*.dev.adobeaemcloud.com\0webview-assets.cloud9.ap-east-1.amazonaws.com\0is-an-actor.com\0rag-cloud-ch.hosteur.com\0" +"net.cn\0" +"net.co\0browsersafetymark.io\0mock.pstmn.io\0" +"genoa.it\0vibovalentia.it\0" +"net.cu\0deloitte\0myhome-server.de\0" +"net.cw\0go.dyndns.org\0stuff-4-sale.org\0" +"net.cy\0" +"psse.gov.pl\0ilawa.pl\0sopot.pl\0" +"net.dm\0" +"net.do\0alaheadju.no\0folldal.no\0hemsedal.no\0lorenskog.no\0" +"noda.chiba.jp\0ooshika.nagano.jp\0yonezawa.yamagata.jp\0koshu.yamanashi.jp\0" +"net.ec\0" +"net.eg\0belau.pw\0" +"net.dz\0" +"kasserver.com\0s3.ap-south-1.amazonaws.com\0s3.eu-west-2.amazonaws.com\0s3.dualstack.sa-east-1.amazonaws.com\0is-a-blogger.com\0quicksytes.com\0" +"dr.na\0" +"k12.sc.us\0" +"net.et\0lt.it\0va.it\0varese.it\0" +"firmdale\0" +"net.fj\0" +"net.fm\0" +"casino\0" +"shimane.jp\0mutsuzawa.chiba.jp\0arao.kumamoto.jp\0takayama.nagano.jp\0saikai.nagasaki.jp\0akishima.tokyo.jp\0tabayama.yamanashi.jp\0raindrop.jp\0stripper.jp\0" +"g12.br\0pi.gov.br\0greta.fr\0" +"koobin.events\0" +"net.ge\0hopto.me\0" +"net.gg\0" +"gotdns.ch\0" +"net.gl\0" +"from-wa.com\0is-into-anime.com\0remotewd.com\0" +"net.gn\0" +"net.gp\0top\0" +"ltda\0" +"net.gr\0" +"net.gt\0livorno.it\0monzabrianza.it\0bounceme.net\0" +"net.gu\0" +"net.gy\0" +"net.hk\0" +"olawa.pl\0" +"net.hn\0" +"mizusawa.iwate.jp\0hyuga.miyazaki.jp\0tonami.toyama.jp\0blush.jp\0" +"\xd0\xbe\xd0\xb4.\xd1\x81\xd1\x80\xd0\xb1\0\xd0\xbe\xd1\x80\xd0\xb3.\xd1\x80\xd1\x83\xd1\x81\0" +"hotels\0" +"net.ht\0net.id\0" +"net.il\0mutual\0" +"net.im\0tv.im\0us-east-1.amazonaws.com\0miniserver.com\0ddnsking.com\0" +"net.in\0tv.in\0" +"net.iq\0" +"net.ir\0" +"net.is\0nj.us\0" +"cl.it\0li.it\0tv.it\0uk.net\0debian.net\0dynalias.net\0moonscale.net\0" +"net.je\0\xd9\x83\xd9\x88\xd9\x85\0" +"w.bg\0ssl.origin.cdn77-secure.org\0" +"lubin.pl\0" +"leasing.aero\0net.jo\0va.no\0horten.no\0sorfold.no\0" +"asuke.aichi.jp\0abiko.chiba.jp\0okaya.nagano.jp\0sasebo.nagasaki.jp\0kadena.okinawa.jp\0yashio.saitama.jp\0" +"det.br\0inf.br\0" +"jprs\0ubs\0" +"politie\0" +"sncf\0trv\0" +"net.kg\0tv.kg\0" +"now.sh\0" +"net.ki\0" +"homeunix.com\0" +"js.cn\0net.kn\0" +"net.la\0" +"net.lb\0" +"net.lc\0" +"myamaze.net\0casacam.net\0kirara.st\0atl.jelastic.vps-host.net\0beta.tailscale.net\0" +"inf.cu\0" +"net.kw\0shopping\0pl.eu.org\0" +"net.ky\0" +"net.kz\0" +"net.lk\0" +"b\xc3\xa5tsfjord.no\0sor-aurdal.no\0" +"kawara.fukuoka.jp\0onomichi.hiroshima.jp\0takikawa.hokkaido.jp\0kawagoe.mie.jp\0higashiyodogawa.osaka.jp\0saga.saga.jp\0tosu.saga.jp\0obanazawa.yamagata.jp\0jellybean.jp\0" +"net.ma\0okinawa\0" +"net.lr\0bel.tr\0dr.tr\0" +"net.ls\0" +"sch.ae\0net.me\0barsy.me\0" +"net.lv\0" +"*.usercontent.goog\0kaas.gg\0" +"net.ly\0surgery\0tui\0" +"net.mk\0" +"net.ml\0" +"is-with-theband.com\0eu.pythonanywhere.com\0" +"ca.in\0" +"net.mo\0" +"tv.na\0" +"net.ms\0mo.us\0wales\0" +"ca.it\0net.mt\0from-ny.net\0" +"net.mu\0furniture\0" +"net.mv\0net.nf\0" +"l.bg\0net.mw\0net.ng\0dnsalias.org\0" +"net.mx\0\xe6\x8b\x9b\xe8\x81\x98\0" +"net.my\0net.ni\0" +"net.mz\0" +"gs.fm.no\0drammen.no\0eid.no\0her\xc3\xb8y.nordland.no\0ulvik.no\0" +"gamagori.aichi.jp\0toei.aichi.jp\0asahi.chiba.jp\0urayasu.chiba.jp\0kihoku.ehime.jp\0rankoshi.hokkaido.jp\0harima.hyogo.jp\0kotohira.kagawa.jp\0wazuka.kyoto.jp\0aguni.okinawa.jp\0sakura.ne.jp\0s3.isk02.sakurastorage.jp\0" +"pe.gov.br\0net.nr\0" +"catholic\0tvs\0" +"priv.instances.scw.cloud\0" +"git-pages.rit.edu\0" +"net.nz\0" +"net.om\0" +"*.elb.amazonaws.com.cn\0" +"net.pa\0shangrila\0" +"creditcard\0akamaihd.net\0" +"net.pe\0" +"net.ph\0" +"net.pk\0network\0" +"net.pl\0" +"net.pn\0" +"idrett.no\0" +"teshikaga.hokkaido.jp\0karumai.iwate.jp\0komoro.nagano.jp\0yakage.okayama.jp\0kasukabe.saitama.jp\0kosei.shiga.jp\0aogashima.tokyo.jp\0" +"net.qa\0lt.ua\0" +"net.pr\0" +"net.ps\0" +"net.pt\0" +"ingatlan.hu\0synology.me\0" +"\xd8\xa7\xd9\x84\xd8\xa7\xd8\xb1\xd8\xaf\xd9\x86\0" +"net.py\0taipei\0" +"travel\0" +"woltlab-demo.com\0" +"devices.resinstaging.io\0" +"ca.na\0vana\0" +"md.us\0va.us\0k12.gu.us\0" +"av.it\0carrara-massa.it\0sp.it\0" +"a.bg\0" +"b\xc3\xa1hcavuotna.no\0romskog.no\0barsy.ro\0" +"nagasaki.jp\0horonobe.hokkaido.jp\0kasumigaura.ibaraki.jp\0yoita.niigata.jp\0hayashima.okayama.jp\0tajiri.osaka.jp\0notogawa.shiga.jp\0ohira.tochigi.jp\0asahi.toyama.jp\0koza.wakayama.jp\0" +"net.sa\0poltava.ua\0" +"ntr.br\0net.sb\0" +"net.sc\0" +"net.sd\0tv.sd\0" +"net.ru\0" +"net.rw\0net.sg\0" +"net.sh\0" +"\xd8\xb4\xd8\xa8\xd9\x83\xd8\xa9\0" +"net.sl\0" +"s3-fips-us-gov-west-1.amazonaws.com\0point2this.com\0simplesite.com\0reserve-online.com\0" +"net.so\0qoto.io\0" +"net.ss\0" +"net.st\0" +"net.th\0" +"net.sy\0" +"net.tj\0" +"\xe3\x82\xbb\xe3\x83\xbc\xe3\x83\xab\0" +"pa.gov.pl\0bielawa.pl\0" +"net.tm\0" +"net.tn\0" +"kafjord.no\0lierne.no\0nissedal.no\0skierva.no\0skanland.no\0v\xc3\xa5gs\xc3\xb8y.no\0net.to\0webhop.info\0" +"tsuruta.aomori.jp\0tajimi.gifu.jp\0matsusaka.mie.jp\0kunitomi.miyazaki.jp\0tsushima.nagasaki.jp\0kawanishi.nara.jp\0showa.yamanashi.jp\0capoo.jp\0hasura.app\0" +"net.ua\0" +"riopreto.br\0net.tr\0tv.tr\0" +"sch.id\0net.tt\0" +"brasilia.me\0su.paba.se\0" +"net.tw\0" +"tv.tz\0" +"inf.mk\0net.uk\0barsy.uk\0" +"commune.am\0s3-website.ap-south-1.amazonaws.com\0cafjs.com\0" +"github.io\0" +"\xd9\x85\xd8\xb5\xd8\xb1\0" +"sch.ir\0" +"ky.us\0net.vc\0tires\0" +"lombardia.it\0vall\xc3\xa9""edaoste.it\0benevento.it\0savona.it\0from-az.net\0barsy.net\0cloudapp.net\0mypsx.net\0" +"nsw.au\0net.ve\0" +"engineering\0" +"net.uy\0net.vi\0" +"net.uz\0" +"net.vn\0" +"educator.aero\0paragliding.aero\0sch.jo\0smola.no\0uno\0" +"\xe7\xa7\x8b\xe7\x94\xb0.jp\0sakai.fukui.jp\0bihoro.hokkaido.jp\0takasu.hokkaido.jp\0kanazawa.ishikawa.jp\0hioki.kagoshima.jp\0izumi.osaka.jp\0takanezawa.tochigi.jp\0angry.jp\0pya.jp\0sub.jp\0mokuren.ne.jp\0" +"agr.br\0fot.br\0" +"bananarepublic\0" +"adult.ht\0sandvikcoromant\0" +"net.vu\0" +"uol\0" +"vfs.cloud9.ap-east-1.amazonaws.com\0applinzi.com\0" +"hasura-app.io\0" +"weather\0" +"net.ws\0" +"sch.lk\0" +"koeln\0" +"pilot.aero\0time.no\0" +"tokushima.jp\0kota.aichi.jp\0takayama.gunma.jp\0takehara.hiroshima.jp\0toyotomi.hokkaido.jp\0yahaba.iwate.jp\0osaki.miyagi.jp\0minami-alps.yamanashi.jp\0" +"pr.gov.br\0free.hr\0" +"beats\0ups\0" +"net.ye\0movie\0yombo.me\0" +"sch.ly\0beauty\0fidelity\0" +"onthewifi.com\0" +"net.za\0" +"ca.us\0" +"sth.ac.at\0aoste.it\0im.it\0meet\0se.net\0selfip.net\0ru.net\0" +"sch.ng\0servegame.org\0" +"*.telebit.xyz\0" +"hdfcbank\0" +"net.zm\0" +"gs.vf.no\0sandnessj\xc3\xb8""en.no\0lebesby.no\0porsanger.no\0varoy.no\0" +"daisen.akita.jp\0tomioka.gunma.jp\0goshiki.hyogo.jp\0noto.ishikawa.jp\0atsugi.kanagawa.jp\0kawaminami.miyazaki.jp\0arita.saga.jp\0tama.tokyo.jp\0catfood.jp\0" +"\xe0\xa4\xad\xe0\xa4\xbe\xe0\xa4\xb0\xe0\xa5\x8b\xe0\xa4\xa4\0" +"w.se\0*.landing.myjino.ru\0rocky.page\0" +"hashbang.sh\0" +"za.bz\0" +"est-a-la-masion.com\0" +"cc.mt.us\0cc.nd.us\0cc.wa.us\0" +"trentinosuedtirol.it\0cdn-edges.net\0" +"webhosting.be\0" +"audi\0" +"gdansk.pl\0" +"baidar.no\0l\xc3\xb8ten.no\0" +"miyazaki.jp\0aizubange.fukushima.jp\0nishimera.miyazaki.jp\0wada.nagano.jp\0nara.nara.jp\0shibata.niigata.jp\0lolipopmc.jp\0" +"sch.qa\0inf.ua\0" +"av.tr\0" +"degree\0" +"dyndns-blog.com\0" +"*.build.run\0" +"beer\0lawyer\0" +"k12.ny.us\0" +"sar.it\0vet\0" +"in-brb.de\0firewall-gateway.de\0" +"myfirewall.org\0" +"h\xc3\xa4kkinen.fi\0prequalifyme.today\0" +"wskr.gov.pl\0" +"bjarkoy.no\0bodo.no\0\xc3\xb8stre-toten.no\0s\xc3\xb8gne.no\0vestvagoy.no\0" +"horokanai.hokkaido.jp\0shakotan.hokkaido.jp\0yaita.tochigi.jp\0mail-box.ne.jp\0" +"sch.sa\0kiev.ua\0" +"l.se\0" +"worse-than.tv\0" +"\xe7\x82\xb9\xe7\x9c\x8b\0" +"tirol\0" +"from-md.com\0giize.com\0logoip.com\0stackhero-network.com\0" +"sch.so\0" +"sch.ss\0cc.mi.us\0" +"trentino-stirol.it\0mediocampidano.it\0" +"schule\0dyn-ip24.de\0" +"*.lcl.dev\0sch.tf\0" +"al.eu.org\0" +"\xe6\x89\x8b\xe6\x9c\xba\0" +"pomorze.pl\0" +"movimiento.bo\0\xc3\xa5lg\xc3\xa5rd.no\0bearalv\xc3\xa1hki.no\0sund.no\0" +"kamifurano.hokkaido.jp\0kitagawa.kochi.jp\0higashiyama.kyoto.jp\0miyakonojo.miyazaki.jp\0nagiso.nagano.jp\0mizuho.tokyo.jp\0" +"avoues.fr\0" +"meme\0sohu\0barsy.menu\0" +"vig\0" +"nog.community\0" +"co.financial\0" +"vin\0" +"vip\0" +"ak.us\0" +"palermo.it\0pt.it\0hu.net\0" +"5.bg\0no.eu.org\0barsy.bg\0" +"dyndns.biz\0" +"\xc3\xa5lesund.no\0vaksdal.no\0barsy.pro\0" +"mie.jp\0abashiri.hokkaido.jp\0hakodate.hokkaido.jp\0ryugasaki.ibaraki.jp\0oshu.iwate.jp\0kin.okinawa.jp\0ichikai.tochigi.jp\0xii.jp\0" +"on.ca\0barsy.ca\0" +"frogans\0" +"a.se\0menu\0" +"sch.wf\0" +"bosch\0" +"!www.ck\0" +"from-mt.com\0from-nd.com\0" +"\xe7\xb6\xb2\xe7\xb5\xa1.cn\0london\0republican\0" +"vall\xc3\xa9""eaoste.it\0" +"barsy.de\0" +"camdvr.org\0mozilla-iot.org\0" +"mmafan.biz\0" +"sklep.pl\0shoparena.pl\0" +"\xc3\xa5seral.no\0bahccavuotna.no\0" +"kutchan.hokkaido.jp\0miho.ibaraki.jp\0hakusan.ishikawa.jp\0otsuki.kochi.jp\0tosa.kochi.jp\0tamaki.mie.jp\0kagamino.okayama.jp\0" +"barsy.pub\0" +"mine.nu\0" +"vfs.cloud9.us-west-2.amazonaws.com\0mydobiss.com\0myspreadshop.com\0" +"reservd.testing.thingdust.io\0" +"gob.ar\0\xd8\xa7\xdb\x8c\xd8\xb1\xd8\xa7\xd9\x86.ir\0" +"myddns.rocks\0" +"*.bd\0lom.it\0pi.it\0" +"cloud.interhostsolutions.be\0barsy.eu\0" +"song\0" +"oschr.gov.pl\0leczna.pl\0" +"sch.zm\0" +"gob.bo\0inder\xc3\xb8y.no\0modum.no\0aca.pro\0" +"miyagi.jp\0nakagawa.fukuoka.jp\0nakama.fukuoka.jp\0sasayama.hyogo.jp\0nantan.kyoto.jp\0hanyu.saitama.jp\0" +"ns.ca\0" +"adv.br\0morena.br\0" +"uk.reclaim.cloud\0k8s.scw.cloud\0" +"zuerich\0" +"sony\0" +"*.ck\0" +"gob.cl\0" +"from-sd.com\0is-a-guru.com\0clicketcloud.com\0" +"stage.nodeart.io\0" +"cc.ks.us\0oy.lc\0" +"roma.it\0in-the-band.net\0" +"staging.onred.one\0" +"c.cdn77.org\0nz.eu.org\0" +"\xe7\xb6\xb2\xe7\xb5\xa1.hk\0" +"po.gov.pl\0" +"aerodrome.aero\0profesional.bo\0gob.do\0" +"kamikoani.akita.jp\0bifuka.hokkaido.jp\0koshimizu.hokkaido.jp\0nakagawa.nagano.jp\0yorii.saitama.jp\0minamiizu.shizuoka.jp\0susono.shizuoka.jp\0" +"\xe0\xb8\xa8\xe0\xb8\xb6\xe0\xb8\x81\xe0\xb8\xa9\xe0\xb8\xb2.\xe0\xb9\x84\xe0\xb8\x97\xe0\xb8\xa2\0" +"gob.ec\0" +"merckmsd\0" +"\xd9\xbe\xd8\xa7\xda\xa9\xd8\xb3\xd8\xaa\xd8\xa7\xd9\x86\0" +"police.uk\0" +"discordsez.com\0" +"seven\0barsy.in\0" +"barsy.io\0" +"*.er\0flir\0simplesite.gr\0" +"gob.es\0k12.dc.us\0airbus\0" +"campania.it\0cesenaforli.it\0diet\0freesite.host\0" +"healthcare\0" +"sweetpepper.org\0" +"sanofi\0" +"*.fk\0" +"b\xc3\xa6rum.no\0lom.no\0naroy.no\0royrvik.no\0r\xc3\xa5""de.no\0valer.hedmark.no\0" +"otake.hiroshima.jp\0shinonsen.hyogo.jp\0obuse.nagano.jp\0kawatana.nagasaki.jp\0nasushiobara.tochigi.jp\0chu.jp\0" +"rivne.ua\0" +"esp.br\0ce.leg.br\0" +"we.bs\0" +"from-ok.com\0likescandy.com\0encoreapi.com\0" +"amazon\0" +"*.on-rio.io\0" +"gob.gt\0trentinoaltoadige.it\0ferrara.it\0piacenza.it\0\xe0\xb2\xad\xe0\xb2\xbe\xe0\xb2\xb0\xe0\xb2\xa4\0best\0" +"luxe\0" +"gob.hn\0" +"nesodden.no\0auto\0groks-this.info\0" +"iwanai.hokkaido.jp\0" +"\xd1\x83\xd0\xbf\xd1\x80.\xd1\x81\xd1\x80\xd0\xb1\0" +"\xd8\xb9\xd9\x85\xd8\xa7\xd9\x86\0" +"tkmaxx\0" +"dyndns-free.com\0est-le-patron.com\0gentlentapis.com\0" +"jp.ngrok.io\0" +"edu.krd\0" +"institute\0" +"dynalias.org\0" +"\xd8\xa7\xd9\x84\xd8\xb3\xd8\xb9\xd9\x88\xd8\xaf\xdb\x8c\xd8\xa9\0" +"*.jm\0" +"groundhandling.aero\0lillehammer.no\0nittedal.no\0ostre-toten.no\0nyan.to\0" +"kumamoto.jp\0eiheiji.fukui.jp\0soeda.fukuoka.jp\0ushiku.ibaraki.jp\0zao.miyagi.jp\0omura.nagasaki.jp\0okinawa.okinawa.jp\0" +"psi.br\0rec.br\0" +"*.kh\0swatch\0" +"sandvik\0" +"s3-website.eu-west-3.amazonaws.com\0homesecuritymac.com\0" +"rec.co\0" +"lib.co.us\0" +"florist\0host\0" +"accenture\0ddnss.de\0dray-dns.de\0my-wan.de\0" +"net.eu.org\0small-web.org\0" +"government.aero\0vikna.no\0" +"tottori.jp\0okagaki.fukuoka.jp\0saka.hiroshima.jp\0nishiarita.saga.jp\0taiji.wakayama.jp\0" +"santoandre.br\0" +"charity\0godaddy\0" +"*.mm\0" +"win\0ravendb.run\0" +"cust.disrec.thingdust.io\0" +"center\0" +"naples.it\0edgekey-staging.net\0" +"hobby-site.org\0barsy.org\0couchpotatofries.org\0" +"gob.mx\0forex\0" +"gob.ni\0" +"adv.mz\0" +"pr.gov.pl\0simplesite.pl\0" +"intl.tn\0" +"bahcavuotna.no\0" +"yamada.fukuoka.jp\0amakusa.kumamoto.jp\0seiro.niigata.jp\0satosho.okayama.jp\0soka.saitama.jp\0higashiizu.shizuoka.jp\0*.np\0mongolian.jp\0" +"mb.ca\0" +"ato.br\0fst.br\0" +"domains\0" +"management\0" +"dance\0" +"za.com\0eu.meteorapp.com\0" +"olayangroup\0" +"gob.pa\0bnr.la\0" +"lib.tn.us\0" +"j.scaleforce.net\0jelastic.tsukaeru.net\0" +"gob.pe\0cyou\0" +"*.webhare.dev\0" +"*.pg\0" +"gob.pk\0" +"gj\xc3\xb8vik.no\0aarborte.no\0rygge.no\0tydal.no\0" +"\xe7\xa6\x8f\xe5\xb3\xb6.jp\0minamiechizen.fukui.jp\0chikujo.fukuoka.jp\0murata.miyagi.jp\0yazu.tottori.jp\0" +"wme\0" +"\xe9\xa3\x9e\xe5\x88\xa9\xe6\xb5\xa6\0" +"cechire.com\0is-a-musician.com\0" +"\xe7\xb5\x84\xe7\xb9\x94.\xe9\xa6\x99\xe6\xb8\xaf\0" +"discourse.group\0" +"mx.na\0" +"verm\xc3\xb6gensberater\0" +"isa.us\0ga.us\0" +"trentino-altoadige.it\0potenza.it\0\xe6\x85\x88\xe5\x96\x84\0" +"game-host.org\0" +"kartuzy.pl\0" +"arte.bo\0gs.hl.no\0l\xc3\xb8""dingen.no\0" +"sakai.ibaraki.jp\0tenri.nara.jp\0" +"\xe9\x9b\xbb\xe8\xa8\x8a\xe7\x9b\x88\xe7\xa7\x91\0" +"seg.br\0prof.pr\0barsy.club\0" +"dish\0" +"pagespeedmobilizer.com\0" +"e164.arpa\0" +"noip.us\0" +"pisa.it\0spot\0de.gt\0" +"qld.edu.au\0capitalone\0ivanovo.su\0" +"gob.sv\0" +"wow\0" +"\xe7\xb6\xb2\xe7\xbb\x9c.hk\0" +"mw.gov.pl\0bialystok.pl\0" +"author.aero\0aseral.no\0aknoluokta.no\0hjelmeland.no\0j\xc3\xb8lster.no\0" +"hashima.gifu.jp\0tarui.gifu.jp\0tainai.niigata.jp\0fujieda.shizuoka.jp\0oyama.tochigi.jp\0" +"vacations\0yachts\0" +"dyndns.tv\0" +"pymnt.uk\0" +"messwithdns.com\0" +"stcgroup\0" +"alibaba\0" +"walter\0" +"k12.in.us\0" +"dell-ogliastra.it\0lecco.it\0mb.it\0venezia.it\0" +"gob.ve\0" +"rec.nf\0" +"zgorzelec.pl\0" +"consulting.aero\0maintenance.aero\0press.aero\0barum.no\0hof.no\0nord-aurdal.no\0steinkjer.no\0nsupdate.info\0" +"furubira.hokkaido.jp\0muroran.hokkaido.jp\0kinko.kagoshima.jp\0takamori.nagano.jp\0yao.osaka.jp\0parasite.jp\0" +"ms.gov.br\0" +"kuleuven.cloud\0" +"ricoh\0" +"adobeaemcloud.com\0ap-south-1.elasticbeanstalk.com\0" +"cn-north-1.eb.amazonaws.com.cn\0" +"\xd8\xa7\xd9\x84\xd8\xb3\xd8\xb9\xd9\x88\xd8\xaf\xdb\x8c\xdb\x83\0wtc\0dyndns.ws\0we.tc\0" +"cosenza.it\0knx-server.net\0" +"wtf\0" +"mt.eu.org\0" +"kddi\0" +"netbank\0" +"sdscloud.pl\0" +"hiroshima.jp\0toyoake.aichi.jp\0mizunami.gifu.jp\0higashikawa.hokkaido.jp\0nakatombetsu.hokkaido.jp\0ako.hyogo.jp\0shimotsuma.ibaraki.jp\0kuchinotsu.nagasaki.jp\0yamazoe.nara.jp\0tagami.niigata.jp\0shimamoto.osaka.jp\0" +"mt.gov.br\0" +"de.ls\0" +"de.md\0" +"off.ai\0tiffany\0" +"health.nz\0" +"tt.im\0ca-central-1.elasticbeanstalk.com\0" +"\xe6\x95\x99\xe8\x82\xb2.\xe9\xa6\x99\xe6\xb8\xaf\0audio\0" +"clan.rip\0" +"schaeffler\0" +"nh.us\0k12.ia.us\0" +"bz.it\0ud.it\0memset.net\0" +"traeumtgerade.de\0vologda.su\0" +"u.bg\0cleaning\0selfip.org\0" +"berg.no\0rec.ro\0" +"lg.jp\0osaka.jp\0noboribetsu.hokkaido.jp\0iwama.ibaraki.jp\0ofunato.iwate.jp\0toba.mie.jp\0yoshino.nara.jp\0higashimatsuyama.saitama.jp\0kamiizumi.saitama.jp\0yuasa.wakayama.jp\0tozawa.yamagata.jp\0" +"volyn.ua\0" +"ind.br\0go.leg.br\0ynh.fr\0" +"rogers\0" +"jotelulu.cloud\0" +"parti.se\0" +"\xe0\xae\x87\xe0\xae\xb2\xe0\xae\x99\xe0\xaf\x8d\xe0\xae\x95\xe0\xaf\x88\0" +"helsinki\0" +"futbol\0" +"vfs.cloud9.ap-southeast-2.amazonaws.com\0" +"sn.cn\0vlaanderen\0" +"athleta\0" +"e4.cz\0" +"kirkenes.no\0audnedaln.no\0\xc3\xb8rskog.no\0" +"ohi.fukui.jp\0minamifurano.hokkaido.jp\0oiso.kanagawa.jp\0kagami.kochi.jp\0kami.miyagi.jp\0numazu.shizuoka.jp\0nikko.tochigi.jp\0" +"dp.ua\0uz.ua\0" +"ch.trendhosting.cloud\0" +"filegear-jp.me\0" +"forum\0us-west-2.elasticbeanstalk.com\0" +"xin\0" +"rs.ba\0" +"holdings\0" +"bo.it\0olbiatempio.it\0" +"rec.ve\0" +"j.bg\0" +"wzmiuw.gov.pl\0wolomin.pl\0" +"verdal.no\0" +"kamagaya.chiba.jp\0higashishirakawa.gifu.jp\0otobe.hokkaido.jp\0kunohe.iwate.jp\0tateshina.nagano.jp\0misaki.okayama.jp\0haebaru.okinawa.jp\0matsuzaki.shizuoka.jp\0ichiba.tokushima.jp\0kofu.yamanashi.jp\0kikirara.jp\0" +"\xe0\xb8\xa3\xe0\xb8\xb1\xe0\xb8\x90\xe0\xb8\x9a\xe0\xb8\xb2\xe0\xb8\xa5.\xe0\xb9\x84\xe0\xb8\x97\xe0\xb8\xa2\0" +"news.hu\0noip.me\0xs4all.space\0" +"awsmppl.com\0dynns.com\0" +"sc.cn\0" +"upli.io\0" +"ind.gt\0calabria.it\0" +"lebtimnetz.de\0shopware.store\0srht.site\0" +"talk\0" +"health.vn\0" +"dovre.no\0h\xc3\xa1""bmer.no\0vagsoy.no\0" +"chiba.jp\0yawatahama.ehime.jp\0ueno.gunma.jp\0miyako.iwate.jp\0hidaka.kochi.jp\0oji.nara.jp\0setagaya.tokyo.jp\0kaneyama.yamagata.jp\0" +"taxi.br\0" +"webcam\0webview-assets.cloud9.us-west-2.amazonaws.com\0ap-southeast-2.elasticbeanstalk.com\0" +"ind.in\0" +"de.us\0k12.pr.us\0*.owo.codes\0" +"at.it\0sells-it.net\0" +"firestone\0spdns.eu\0" +"my.eu.org\0" +"statebank\0" +"kppsp.gov.pl\0zp.gov.pl\0" +"leirvik.no\0alta.no\0b\xc3\xa1id\xc3\xa1r.no\0kv\xc3\xa6nangen.no\0lodingen.no\0" +"omuta.fukuoka.jp\0onojo.fukuoka.jp\0seki.gifu.jp\0tanabe.kyoto.jp\0nabari.mie.jp\0saku.nagano.jp\0minami.tokushima.jp\0chowder.jp\0" +"chernivtsi.ua\0" +"bsb.br\0ribeirao.br\0" +"k8s.pl-waw.scw.cloud\0" +"security\0" +"s3.ap-northeast-2.amazonaws.com\0s3.dualstack.eu-central-1.amazonaws.com\0from-mn.com\0is-a-green.com\0scrysec.com\0" +"cc.oh.us\0washtenaw.mi.us\0" +"ind.kw\0" +"waw.pl\0" +"oppdal.no\0osen.no\0" +"mizumaki.fukuoka.jp\0ono.fukushima.jp\0kanra.gunma.jp\0kamisu.ibaraki.jp\0oyamazaki.kyoto.jp\0hayakawa.yamanashi.jp\0" +"lg.ua\0" +"tn.oxa.cloud\0at.md\0" +"s3-eu-west-2.amazonaws.com\0webview-assets.cloud9.eu-west-1.amazonaws.com\0lynx.mythic-beasts.com\0dev-myqnapcloud.com\0" +"ai.in\0" +"beagleboard.io\0" +"bas.it\0novara.it\0" +"nome.cv\0" +"q-a.eu.org\0" +"industria.bo\0gs.mr.no\0grong.no\0narviika.no\0stange.no\0" +"ichinomiya.chiba.jp\0tsuruga.fukui.jp\0oki.fukuoka.jp\0izumizaki.fukushima.jp\0yoshioka.gunma.jp\0akkeshi.hokkaido.jp\0nagaoka.niigata.jp\0johana.toyama.jp\0nishikatsura.yamanashi.jp\0" +"bhz.br\0" +"smart\0" +"sc.ke\0" +"\xe3\x81\xbf\xe3\x82\x93\xe3\x81\xaa\0" +"zj.cn\0" +"loginline.io\0" +"sc.kr\0" +"cc.nm.us\0" +"saotome.st\0" +"spdns.de\0" +"is-a-patsfan.org\0nl.eu.org\0" +"gsm.pl\0" +"oyer.no\0" +"hekinan.aichi.jp\0kasuya.fukuoka.jp\0sumoto.hyogo.jp\0minamiise.mie.jp\0kamitsue.oita.jp\0toyama.toyama.jp\0" +"\xe0\xb8\x84\xe0\xb8\xad\xe0\xb8\xa1\0" +"sc.ls\0" +"vipsinaapp.com\0" +"dynu.net\0" +"is-a-soxfan.org\0" +"alipay\0" +"mjondalen.no\0\xc3\xa5l.no\0asker.no\0fauske.no\0flakstad.no\0hamar.no\0lyngen.no\0norddal.no\0porsgrunn.no\0sykkylven.no\0" +"\xe5\xb2\xa1\xe5\xb1\xb1.jp\0gojome.akita.jp\0yashiro.hyogo.jp\0hakone.kanagawa.jp\0kikuchi.kumamoto.jp\0chikuma.nagano.jp\0yamanouchi.nagano.jp\0kyuragi.saga.jp\0koya.wakayama.jp\0coolblog.jp\0" +"ac.gov.br\0udi.br\0" +"careers\0" +"shop.ht\0" +"shop.hu\0bd.se\0fhv.se\0naturbruksgymn.se\0u.se\0" +"is-a-caterer.com\0*.nodebalancer.linode.com\0dnsiskinky.com\0hk.com\0" +"he.cn\0" +"appudo.net\0" +"my-router.de\0" +"taxi\0" +"activetrail.biz\0*.cloud.metacentrum.cz\0" +"ind.tn\0" +"g\xc3\xa1ls\xc3\xa1.no\0" +"keisen.fukuoka.jp\0sera.hiroshima.jp\0takarazuka.hyogo.jp\0tanohata.iwate.jp\0samukawa.kanagawa.jp\0myoko.niigata.jp\0" +"boavista.br\0" +"gov.ac\0" +"gov.ae\0" +"gov.af\0" +"xxx\0" +"gov.al\0", + +"museum\0s3.dualstack.ap-southeast-1.amazonaws.com\0s3-ap-southeast-1.amazonaws.com\0" "gov.ba\0" -"gov.ar\0gov.bb\0mashike.hokkaido.jp\0is-a-bruinsfan.org\0" +"gov.ar\0gov.bb\0" "gov.as\0" -"com.vc\0" -"gov.au\0" -"gov.bf\0com.ve\0" -"go.dyndns.org\0" -"gov.bh\0shiki.saitama.jp\0" -"gov.az\0com.uy\0com.vi\0" -"sayama.osaka.jp\0com.uz\0" -"gov.bm\0siljan.no\0" -"gov.bn\0sc.cn\0kakogawa.hyogo.jp\0courses\0" -"com.vn\0" -"asakuchi.okayama.jp\0" -"gov.br\0\xe6\x95\x99\xe8\x82\xb2.\xe9\xa6\x99\xe6\xb8\xaf\0" +"jp.net\0fastvps.host\0" +"gov.au\0youtube\0logoip.de\0" +"gov.bf\0" +"ng.eu.org\0at.vg\0" +"gov.bh\0" +"gov.az\0xyz\0" +"gov.bm\0" +"gov.bn\0" +"bjerkreim.no\0sogne.no\0volvo\0" +"honjyo.akita.jp\0sosa.chiba.jp\0ishikawa.fukushima.jp\0takasago.hyogo.jp\0kochi.kochi.jp\0kushima.miyazaki.jp\0iida.nagano.jp\0""2-d.jp\0eek.jp\0" +"gov.br\0" "gov.bs\0" -"gov.bt\0gov.cd\0" -"com.vu\0" +"gov.bt\0gov.cd\0scalebook.scw.cloud\0" "gov.by\0" -"gov.bz\0travelchannel\0" +"gov.bz\0" "gov.cl\0" "gov.cm\0" "gov.cn\0" -"gov.co\0tohma.hokkaido.jp\0" -"czest.pl\0ooguy.com\0" -"vet.br\0com.ws\0fedex\0" -"asn.au\0gov.cu\0" +"gov.co\0n4t.co\0" +"cc.ut.us\0knightpoint.systems\0" +"carboniaiglesias.it\0urbinopesaro.it\0" +"gov.cu\0" +"versicherung\0" "gov.cx\0" -"gov.cy\0blog.kg\0" -"taranto.it\0" -"uchiko.ehime.jp\0stj\xc3\xb8rdal.no\0" -"arte.bo\0hikimi.shimane.jp\0uz.ua\0" +"gov.cy\0\xe3\x82\xaf\xe3\x83\xa9\xe3\x82\xa6\xe3\x83\x89\0" "gov.dm\0" -"name\0" "gov.do\0" -"vfs.cloud9.ap-northeast-3.amazonaws.com\0" +"takamori.kumamoto.jp\0tokamachi.niigata.jp\0uonuma.niigata.jp\0hita.oita.jp\0tadaoka.osaka.jp\0kaminokawa.tochigi.jp\0mihama.wakayama.jp\0" "gov.ec\0" -"shimogo.fukushima.jp\0cc.ne.us\0" -"gov.ee\0polkowice.pl\0" -"ako.hyogo.jp\0com.ye\0" -"gov.eg\0site.transip.me\0" -"gov.dz\0kahoku.yamagata.jp\0" -"est-a-la-maison.com\0" -"kyuragi.saga.jp\0" -"freeboxos.com\0" -"cd.eu.org\0free.hr\0" -"hirosaki.aomori.jp\0" -"gov.et\0" -"\xe9\x95\xb7\xe9\x87\x8e.jp\0" -"gov.fj\0cloud66.zone\0" -"akamaihd-staging.net\0" -"bplaced.net\0" -"priv.hu\0com.zm\0" -"dynns.com\0" -"ribeirao.br\0" -"koshimizu.hokkaido.jp\0" -"freeddns.org\0" -"gov.gd\0main.jp\0" -"gov.ge\0" -"jeju.kr\0br\xc3\xb8nn\xc3\xb8ysund.no\0call\0" +"gov.ee\0filegear-au.me\0" +"gov.eg\0sc.ug\0" +"gov.dz\0sc.tz\0" +"s3-website-sa-east-1.amazonaws.com\0" +"sc.us\0k12.mn.us\0k12.wi.us\0" +"gov.et\0cal.it\0asti.it\0pr.it\0" +"3.bg\0freeddns.org\0" +"fedex\0" +"gov.fj\0" +"wielun.pl\0\xe6\x94\xbf\xe5\xba\x9c\0" +"slattum.no\0solund.no\0" +"nakanojo.gunma.jp\0minamiawaji.hyogo.jp\0tome.miyagi.jp\0kobayashi.miyazaki.jp\0yuzawa.niigata.jp\0utsunomiya.tochigi.jp\0" +"guitars\0" +"gov.gd\0" +"gov.ge\0tozsde.hu\0mortgage\0" "gov.gh\0" -"gov.gi\0jelastic.team\0" -"r\xc3\xb8yrvik.no\0" +"gov.gi\0" +"independent-inquest.uk\0" +"travelchannel\0" +"saves-the-whales.com\0orsites.com\0" "gov.gn\0" -"trentino-a-adige.it\0" -"gov.gr\0tagajo.miyagi.jp\0" -"equipment\0" -"de.trendhosting.cloud\0" -"gov.gu\0" -"press.se\0" -"\xe6\x97\xb6\xe5\xb0\x9a\0noip.us\0" +"tattoo\0" +"\xe4\xbd\x9b\xe5\xb1\xb1\0" +"gov.gr\0" +"cc.co.us\0" +"friuli-ve-giulia.it\0trentin-sudtirol.it\0trentino.it\0agrigento.it\0feste-ip.net\0dnsup.net\0njs.jelastic.vps-host.net\0user.srcf.net\0" +"gov.gu\0you\0" "gov.gy\0" -"aquila.it\0hekinan.aichi.jp\0camp\0" "gov.hk\0" -"b\xc3\xb8mlo.no\0" -"rotorcraft.aero\0tsubata.ishikawa.jp\0" -"v\xc3\xa5gs\xc3\xb8y.no\0" -"stjordalshalsen.no\0ciao.jp\0" -"kashima.saga.jp\0akiruno.tokyo.jp\0" -"ogano.saitama.jp\0" -"gov.ie\0saka.hiroshima.jp\0pfizer\0" -"hioki.kagoshima.jp\0" -"inzai.chiba.jp\0doshi.yamanashi.jp\0" -"wmflabs.org\0" +"ens.tn\0" +"tokke.no\0" +"kosaka.akita.jp\0etajima.hiroshima.jp\0esan.hokkaido.jp\0mitsuke.niigata.jp\0yonabaru.okinawa.jp\0nanyo.yamagata.jp\0" +"jele.cloud\0" +"gov.ie\0" "gov.il\0" -"gov.in\0" -"teaches-yoga.com\0" -"hirado.nagasaki.jp\0torproject.net\0" +"on-aptible.com\0is-a-nascarfan.com\0" +"gov.in\0pg.in\0" +"shw.io\0sa.ngrok.io\0" "gov.iq\0" -"gov.ir\0" -"gov.is\0shimonita.gunma.jp\0" -"gov.it\0" -"tas.au\0sc.ke\0hk.com\0" -"k12.pr.us\0" -"garden\0futuremailing.at\0" -"barum.no\0" -"komono.mie.jp\0modalen.no\0" -"gov.jo\0s3-us-west-1.amazonaws.com\0" -"sc.kr\0" -"nago.okinawa.jp\0zhitomir.ua\0" -"smart\0upaas.kazteleport.kz\0" -"gov.kg\0au.ngrok.io\0" +"gov.ir\0dealer\0" +"gov.is\0k12.ma.us\0paroch.k12.ma.us\0" +"gov.it\0trentinoaadige.it\0pg.it\0hangout\0ny-2.paas.massivegrid.net\0" +"commbank\0" +"res.aero\0gov.jo\0bindal.no\0gjerdrum.no\0" +"*.sendai.jp\0ashiya.hyogo.jp\0higashi.okinawa.jp\0okegawa.saitama.jp\0toyosato.shiga.jp\0iwafune.tochigi.jp\0heavy.jp\0itigo.jp\0littlestar.jp\0zombie.jp\0" +"odesa.ua\0" +"9guacu.br\0eti.br\0" +"cbg.ru\0" +"gov.kg\0" "gov.ki\0" -"z.se\0apps.fbsbx.com\0" -"airkitapps-au.com\0" -"gov.km\0aquarelle\0priv.at\0" +"campaign.gov.uk\0" +"gov.km\0meteorapp.com\0nyaa.am\0" "gov.kn\0" -"awaji.hyogo.jp\0gov.kp\0" +"gov.kp\0" "gov.la\0" -"gov.lb\0m\xc3\xa5lselv.no\0" -"gov.lc\0sc.ls\0" -"discourse.group\0" -"yonezawa.yamagata.jp\0nesodden.no\0cpa.pro\0" -"gov.kw\0" -"imperia.it\0is-a-celticsfan.org\0" -"aizumisato.fukushima.jp\0gov.kz\0sortland.no\0vladikavkaz.ru\0" -"tsuruoka.yamagata.jp\0gov.lk\0ivanovo.su\0" -"catholic.edu.au\0krager\xc3\xb8.no\0" -"care\0from-co.net\0onfabrica.com\0" -"masaki.ehime.jp\0" -"gov.ma\0olayangroup\0" -"8.bg\0gov.lr\0" -"gov.ls\0" +"gov.lb\0" +"gov.lc\0cc.la.us\0cc.tn.us\0lib.wa.us\0" +"andria-trani-barletta.it\0\xe0\xac\xad\xe0\xac\xbe\xe0\xac\xb0\xe0\xac\xa4\0jele.host\0" +"emb.kw\0gov.kw\0" +"caa.li\0" +"gov.kz\0" +"gov.lk\0assn.lk\0\xe3\x82\xb0\xe3\x83\xbc\xe3\x82\xb0\xe3\x83\xab\0" +"pulawy.pl\0khplay.nl\0" +"empresa.bo\0dr\xc3\xb8""bak.no\0notodden.no\0selje.no\0ollo\0" +"katagami.akita.jp\0kawai.iwate.jp\0shonai.yamagata.jp\0" +"gov.ma\0" +"gov.lr\0" +"gov.ls\0contractors\0panasonic\0scholarships\0" "gov.lt\0" -"teshikaga.hokkaido.jp\0gov.me\0krodsherad.no\0tonsberg.no\0" -"frosinone.it\0yatsuka.shimane.jp\0gov.lv\0mckinsey\0" +"gov.me\0" +"gov.lv\0" "gov.mg\0" -"hitachiota.ibaraki.jp\0parti.se\0nh-serv.co.uk\0" -"gov.ly\0impertrix.com\0""123siteweb.fr\0" -"vladikavkaz.su\0csx.cc\0" -"gov.mk\0casa\0" +"gov.ly\0" +"gov.mk\0" "gov.ml\0" -"cars\0" -"gov.mn\0piw.gov.pl\0dupont\0" -"gov.mo\0case\0" -"sosa.chiba.jp\0okuma.fukushima.jp\0orx.biz\0""3utilities.com\0" -"ashikaga.tochigi.jp\0press.ma\0gov.mr\0cash\0" -"gov.ms\0" -"aizuwakamatsu.fukushima.jp\0" -"gov.mu\0" +"mydrobo.com\0" +"gov.mn\0yun\0" +"gov.mo\0video\0mo-siemens.io\0" +"gov.mr\0lamer\0" +"gov.ms\0barclays\0hsbc\0icbc\0" +"bulsan-sudtirol.it\0" +"gov.mu\0ybo.trade\0" "gov.mv\0" -"gov.mw\0gov.ng\0" -"mielno.pl\0" -"iwafune.tochigi.jp\0gov.my\0griw.gov.pl\0" -"gov.mz\0szczecin.pl\0" -"o.se\0" -"lombardy.it\0gov.nl\0" -"yamato.kumamoto.jp\0" -"union.aero\0square7.net\0" -"dy.fi\0" -"chambagri.fr\0pleskns.com\0" -"rodoy.no\0gov.nr\0navy\0" -"boavista.br\0" -"iwama.ibaraki.jp\0reisen\0\xd1\x8f.\xd1\x80\xd1\x83\xd1\x81\0mein-vigor.de\0" -"akamai.net\0" -"omachi.nagano.jp\0asn.lv\0analytics\0" -"yokaichiba.chiba.jp\0" -"joso.ibaraki.jp\0\xd1\x81\xd0\xb0\xd0\xb9\xd1\x82\0" -"cloud.fedoraproject.org\0topaz.ne.jp\0" -"coupons\0" -"gov.om\0" -"frosta.no\0merseine.nu\0" -"fukuroi.shizuoka.jp\0" -"onojo.fukuoka.jp\0" -"apple\0" -"kadoma.osaka.jp\0" +"gov.mw\0gov.ng\0us.org\0mlbfan.org\0" +"gov.my\0" +"gov.mz\0" +"gov.nl\0" +"iveland.no\0skaun.no\0" +"itako.ibaraki.jp\0iruma.saitama.jp\0koge.tottori.jp\0" +"nf.ca\0" +"coz.br\0gov.nr\0cloudns.club\0" +"nome.pt\0food\0s3-website.nl-ams.scw.cloud\0" +"prudential\0" +"gov.om\0s3.us-east-2.amazonaws.com\0webview-assets.cloud9.eu-central-1.amazonaws.com\0eu.com\0neko.am\0" +"jele.io\0" +"kerrylogistics\0" +"bozen-s\xc3\xbc""dtirol.it\0edgesuite.net\0" +"in-butter.de\0" +"\xe5\x95\x86\xe6\xa0\x87\0" "gov.ph\0" -"*.digitaloceanspaces.com\0" -"sumida.tokyo.jp\0" +"mckinsey\0barsy.mobi\0" +"realm.cz\0" "gov.pk\0" -"goto.nagasaki.jp\0gov.pl\0pimienta.org\0" +"gov.pl\0" "gov.pn\0" -"kartuzy.pl\0" -"dyndns.org\0" -"gov.qa\0\xe9\x9b\x86\xe5\x9b\xa2\0daplie.me\0" -"gov.pr\0progressive\0from-de.com\0" -"kanan.osaka.jp\0gov.ps\0" -"sokndal.no\0gov.pt\0" -"omitama.ibaraki.jp\0prvcy.page\0" -"donetsk.ua\0dnsdojo.com\0" -"laquila.it\0gov.py\0" -"zagan.pl\0nagoya\0" -"minamiaiki.nagano.jp\0d.se\0" -"nagasaki.nagasaki.jp\0shimizu.shizuoka.jp\0" -"\xe5\xae\xb6\xe9\x9b\xbb\0" -"gyokuto.kumamoto.jp\0" -"toscana.it\0" -"avocat.fr\0yanaizu.fukushima.jp\0" -"gu.us\0" -"pr.it\0dunlop\0" -"a.run.app\0" -"bihar.in\0kamikawa.hyogo.jp\0" -"tempioolbia.it\0" -"saloon.jp\0" -"mandal.no\0wsa.gov.pl\0" -"gov.sa\0" -"gov.sb\0" +"plurinacional.bo\0sula.no\0" +"inawashiro.fukushima.jp\0mishima.fukushima.jp\0atsuma.hokkaido.jp\0takino.hyogo.jp\0toyooka.hyogo.jp\0ureshino.mie.jp\0shinkamigoto.nagasaki.jp\0kumatori.osaka.jp\0kakegawa.shizuoka.jp\0gloomy.jp\0" +"gov.qa\0" +"al.gov.br\0gov.pr\0" +"gov.ps\0" +"gov.pt\0" +"gov.py\0" +"\xd8\xa8\xda\xbe\xd8\xa7\xd8\xb1\xd8\xaa\0" +"omg.lol\0" +"radio.am\0is-a-photographer.com\0gotpantheon.com\0" +"zip\0" +"musica.ar\0" +"gu.us\0pr.us\0k12.ks.us\0ventures\0" +"valled-aosta.it\0balsan-sudtirol.it\0dellogliastra.it\0massa-carrara.it\0ford\0dattolocal.net\0storage.yandexcloud.net\0" +"qld.au\0in-dsl.de\0" +"shop.th\0" +"mini\0dy.fi\0" +"blogspot.vn\0" +"musica.bo\0ol.no\0aver\xc3\xb8y.no\0gaular.no\0vestby.no\0" +"kuroishi.aomori.jp\0kisarazu.chiba.jp\0sasaguri.fukuoka.jp\0tenei.fukushima.jp\0ena.gifu.jp\0asahikawa.hokkaido.jp\0nakano.nagano.jp\0nakagusuku.okinawa.jp\0ogimi.okinawa.jp\0shiki.saitama.jp\0fuefuki.yamanashi.jp\0*.beget.app\0moo.jp\0streamlit.app\0" +"gov.sa\0omega\0" +"radio.br\0the.br\0gov.sb\0en-root.fr\0" "gov.rs\0gov.sc\0" -"gov.sd\0feedback\0" -"gov.ru\0" -"gov.rw\0gov.sg\0rich\0" +"gov.sd\0mint\0" +"bike\0gov.ru\0" +"gov.rw\0gov.sg\0" "gov.sh\0" -"s3.ap-northeast-2.amazonaws.com\0qc.com\0noip.me\0" -"kamishihoro.hokkaido.jp\0" -"gok.pk\0gov.sl\0lamer\0dyndns-web.com\0" -"barsy.online\0orsites.com\0" -"kanoya.kagoshima.jp\0\xd0\xbf\xd1\x80.\xd1\x81\xd1\x80\xd0\xb1\0" -"\xc3\xb8stre-toten.no\0gov.so\0" -"deca.jp\0" +"mod.gi\0" +"gov.sl\0" +"airkitapps.com\0s3-website.eu-central-1.amazonaws.com\0dattoweb.com\0gotdns.com\0" +"gov.so\0b-data.io\0" "gov.ss\0" -"valleeaoste.it\0varese.it\0" -"pri.ee\0tendo.yamagata.jp\0sc.ug\0is-a-llama.com\0" -"gov.sx\0" -"gov.sy\0black\0" -"kisofukushima.nagano.jp\0gov.tj\0sc.tz\0" -"kashiwara.osaka.jp\0s3.dualstack.ap-southeast-2.amazonaws.com\0" +"turin.it\0shopselect.net\0" +"my-vigor.de\0" +"gov.sx\0nerdpol.ovh\0" +"gov.sy\0" +"gov.tj\0usr.cloud.muni.cz\0" +"gok.pk\0" "gov.tl\0" -"tanabe.kyoto.jp\0gov.tm\0" -"mizusawa.iwate.jp\0gov.tn\0\xd1\x80\xd1\x83\xd1\x81\0" -"gov.to\0mircloud.us\0" -"zj.cn\0zentsuji.kagawa.jp\0eu-west-2.elasticbeanstalk.com\0" +"gov.tm\0" +"gov.tn\0" +"ovre-eiker.no\0gov.to\0shop.ro\0" +"yaotsu.gifu.jp\0kembuchi.hokkaido.jp\0amagasaki.hyogo.jp\0mihara.kochi.jp\0kijo.miyazaki.jp\0kibichuo.okayama.jp\0akagi.shimane.jp\0suginami.tokyo.jp\0nichinan.tottori.jp\0iwade.wakayama.jp\0" "gov.ua\0" -"pg.in\0atsuma.hokkaido.jp\0gov.tr\0" -"sc.us\0" -"gov.tt\0" -"gov.tw\0isa.us\0no-ip.co.uk\0" -"pg.it\0hayakawa.yamanashi.jp\0" -"minamiise.mie.jp\0" -"nagaoka.niigata.jp\0" -"gov.uk\0barclays\0mobile\0" -"oster\xc3\xb8y.no\0" -"iwaizumi.iwate.jp\0" -"ru.com\0paris.eu.org\0" -"greta.fr\0" -"okawa.fukuoka.jp\0" +"gov.tr\0" +"rel.ht\0gov.tt\0" +"tech.orange\0" +"gov.tw\0" +"gov.uk\0lefrak\0" +"vfs.cloud9.us-west-1.amazonaws.com\0" +"camera\0" +"senasa.ar\0" "gov.vc\0" -"tochio.niigata.jp\0gov.ve\0" -"kitayama.wakayama.jp\0" -"sennan.osaka.jp\0gamo.shiga.jp\0" -"*.frusky.de\0" -"tjome.no\0k12.mn.us\0gov.vn\0" -"jcloud.kz\0" -"webhop.org\0" -"mima.tokushima.jp\0aaa\0" -"date.hokkaido.jp\0" -"berlevag.no\0volvo\0" -"nf.ca\0post.in\0pisa.it\0kizu.kyoto.jp\0" -"ono.hyogo.jp\0alfaromeo\0" -"freeboxos.fr\0" -"ind.br\0kanonji.kagawa.jp\0hashimoto.wakayama.jp\0" -"susaki.kochi.jp\0" -"service.one\0" -"yokoshibahikari.chiba.jp\0saito.miyazaki.jp\0fitjar.no\0stage.nodeart.io\0" -"mizunami.gifu.jp\0dyn-o-saur.com\0" +"matera.it\0vs.it\0square7.net\0ham-radio-op.net\0" +"gov.ve\0blogspot.re\0" +"r2.dev\0" +"bing\0" +"cipriani\0mitsubishi\0" +"loisirs.bj\0selfip.biz\0" +"shop.pl\0" +"radio.fm\0" +"gov.vn\0" +"tecnologia.bo\0r\xc3\xa1hkker\xc3\xa1vju.no\0oppeg\xc3\xa5rd.no\0blogspot.ro\0" +"\xe5\xb2\xa9\xe6\x89\x8b.jp\0nishiaizu.fukushima.jp\0niimi.okayama.jp\0maibara.shiga.jp\0moriyama.shiga.jp\0" +"cnt.br\0curitiba.br\0" +"blogspot.rs\0" +"s3-website.pl-waw.scw.cloud\0" +"agrar.hu\0blogspot.ru\0blogspot.se\0" +"blogspot.sg\0" +"monash\0" +"blogspot.si\0" +"public-inquiry.uk\0blogspot.sk\0" +"vfs.cloud9.sa-east-1.amazonaws.com\0bounty-full.com\0wixsite.com\0" +"blogspot.sn\0" +"urn.arpa\0" "gov.ws\0" -"palmas.br\0dvag\0" -"abb\0" -"kameyama.mie.jp\0abc\0" -"cs.in\0namegawa.saitama.jp\0is-very-nice.org\0" -"gs.hm.no\0" -"mediocampidano.it\0" -"myspreadshop.net\0" -"cs.it\0" -"shibetsu.hokkaido.jp\0taku.saga.jp\0" -"avianca\0" -"bozen-sudtirol.it\0flt.cloud.muni.cz\0" -"santamaria.br\0" -"biz.bb\0gov.ye\0" -"biz.at\0" -"*.cns.joyent.com\0" -"freebox-os.fr\0platter-app.com\0" -"oamishirasato.chiba.jp\0uto.kumamoto.jp\0" -"biz.az\0\xe5\xa4\xa7\xe9\x98\xaa.jp\0" -"plc.co.im\0k12.ma.us\0" -"wakkanai.hokkaido.jp\0school.za\0" -"tono.iwate.jp\0gov.za\0mircloud.ru\0" -"riobranco.br\0aco\0" -"treviso.it\0kanna.gunma.jp\0bbs.tr\0k12.ar.us\0" -"aerobatic.aero\0nerima.tokyo.jp\0gift\0toolforge.org\0" -"tranby.no\0" -"mishima.fukushima.jp\0" -"hostedpi.com\0" -"oyer.no\0" -"gouv.fr\0namsos.no\0" -"punyu.jp\0" -"gov.zm\0fem.jp\0" -"kuroishi.aomori.jp\0" -"deta.app\0" -"homesklep.pl\0" -"goshiki.hyogo.jp\0" -"oya.to\0" -"ads\0vfs.cloud9.sa-east-1.amazonaws.com\0" -"suwa.nagano.jp\0gov.zw\0" -"tomi.nagano.jp\0express\0" -"aeg\0" -"\xd9\x81\xd9\x84\xd8\xb3\xd8\xb7\xd9\x8a\xd9\x86\0" -"biz.cy\0minamidaito.okinawa.jp\0kanuma.tochigi.jp\0blockbuster\0oops.jp\0" -"veg\xc3\xa5rshei.no\0" -"ch.it\0biz.dk\0iserv.dev\0" -"siena.it\0" -"from-id.com\0" -"ebiz.tw\0pgfog.com\0dev.static.land\0" -"\xd0\xba\xd0\xb0\xd1\x82\xd0\xbe\xd0\xbb\xd0\xb8\xd0\xba\0" -"univ.bj\0" -"bingo\0vote\0fastly-edge.com\0" -"gouv.ht\0" -"raholt.no\0" -"ind.gt\0afl\0cbre\0" -"asahi.chiba.jp\0is-a-doctor.com\0" -"lomo.jp\0" -"ol.no\0voto\0" -"bio.br\0lundbeck\0" -"biz.et\0trentino.it\0" -"omega\0" -"biz.fj\0" -"miyazaki.jp\0" -"ch.eu.org\0" -"frogans\0" -"nasushiobara.tochigi.jp\0priv.pl\0" -"pr.us\0" -"vfs.cloud9.eu-south-1.amazonaws.com\0" -"cf-ipfs.com\0" -"ind.in\0" -"soni.nara.jp\0stathelle.no\0" -"lapy.pl\0" -"biz.gl\0" -"h\xc3\xa4kkinen.fi\0" -"gouv.ci\0" -"nome.cv\0" -"aurland.no\0" -"hicam.net\0" -"matsumoto.nagano.jp\0gets-it.net\0" -"toho.fukuoka.jp\0cdn77-ssl.net\0" -"aig\0ravendb.community\0" -"tec.mi.us\0nodes.k8s.fr-par.scw.cloud\0" -"matsusaka.mie.jp\0" -"africa\0webview-assets.cloud9.me-south-1.amazonaws.com\0" -"k12.ks.us\0" -"omiya.saitama.jp\0" -"k12.al.us\0" -"biz.id\0exposed\0stackhero-network.com\0" -"priv.no\0" -"dn.ua\0" -"airline.aero\0" -"reservd.dev.thingdust.io\0" -"skydiving.aero\0" -"bungoono.oita.jp\0\xd1\x81\xd1\x80\xd0\xb1\0infiniti\0" -"biz.in\0" -"ind.kw\0from-me.org\0" -"shitara.aichi.jp\0" -"yali.mythic-beasts.com\0" -"malselv.no\0" -"narusawa.yamanashi.jp\0" -"higashi.okinawa.jp\0idrett.no\0anquan\0apigee.io\0" -"nanao.ishikawa.jp\0" -"shima.mie.jp\0verdal.no\0video\0jdevcloud.com\0" -"ashoro.hokkaido.jp\0" -"ar.it\0n\xc3\xa5\xc3\xa5mesjevuemie.no\0" -"reliance\0" -"sakuraweb.com\0" -"lahppi.no\0" -"higashiomi.shiga.jp\0" -"krellian.net\0" -"biz.ki\0" -"mordovia.su\0" -"priv.me\0k12.wi.us\0" -"higashitsuno.kochi.jp\0hvaler.no\0" -"ustka.pl\0" -"sakai.fukui.jp\0" -"webview-assets.cloud9.ap-south-1.amazonaws.com\0" -"df.gov.br\0duckdns.org\0" -"gose.nara.jp\0imdb\0" -"bayern\0" -"habmer.no\0" -"ezproxy.kuleuven.be\0" -"minamimaki.nagano.jp\0incheon.kr\0ostre-toten.no\0workers.dev\0" -"mihara.kochi.jp\0yaese.okinawa.jp\0clothing\0" -"niigata.niigata.jp\0dyndns-home.com\0" -"barsy.shop\0" -"arao.kumamoto.jp\0" -"utazu.kagawa.jp\0" -"\xe7\xbd\x91\xe7\xbb\x9c.cn\0kunimi.fukushima.jp\0" -"biz.ls\0" -"barsy.site\0" -"spb.ru\0" -"static.observableusercontent.com\0" -"sukumo.kochi.jp\0strand.no\0dc.us\0daa.jp\0" -"\xe6\x94\xbf\xe5\xba\x9c.\xe9\xa6\x99\xe6\xb8\xaf\0" -"\xe6\xbe\xb3\xe9\x96\x80\0" -"n\xc3\xb8tter\xc3\xb8y.no\0cipriani\0" -"ag.it\0" -"veterinaire.km\0" -"hanamigawa.chiba.jp\0" -"ikata.ehime.jp\0independent-inquiry.uk\0" -"atl.jelastic.vps-host.net\0" -"spb.su\0" -"biz.mv\0" -"biz.mw\0" -"biz.my\0biz.ni\0" -"anz\0mordovia.ru\0ch.tc\0" -"imari.saga.jp\0" -"emilia-romagna.it\0aol\0loans\0" -"macerata.it\0kviteseid.no\0unicloud.pl\0" -"wada.nagano.jp\0ouchi.saga.jp\0at.eu.org\0" -"kouzushima.tokyo.jp\0" -"in-dsl.de\0" -"termez.su\0servehalflife.com\0" -"curitiba.br\0biz.nr\0us-gov-west-1.elasticbeanstalk.com\0" -"noticias.bo\0" -"myspreadshop.nl\0" -"kuji.iwate.jp\0\xc3\xb8ygarden.no\0myspreadshop.no\0" -"\xe9\xa3\x9e\xe5\x88\xa9\xe6\xb5\xa6\0qa2.com\0" -"cc.fl.us\0" -"nakai.kanagawa.jp\0" -"app\0" -"rj.gov.br\0" -"\xe4\xb8\xad\xe5\x9b\xbd\0" -"le.it\0biz.pk\0" -"biz.pl\0" -"trentino-sued-tirol.it\0" -"bci.dnstrace.pro\0" -"kudoyama.wakayama.jp\0os\xc3\xb8yro.no\0" -"web.bo\0biz.pr\0bar\0" -"bbc\0bnpparibas\0" -"\xe4\xb8\xad\xe5\x9c\x8b\0" -"veterinaire.fr\0lawyer\0" -"myspreadshop.pl\0" -"tickets\0vladimir.su\0" -"it.ao\0" -"kitaaiki.nagano.jp\0kpmg\0" -"\xe7\xbd\x91\xe7\xbb\x9c.hk\0" -"nakanojo.gunma.jp\0weblike.jp\0" -"koto.tokyo.jp\0" -"lib.wa.us\0gitlab.io\0" -"web.co\0" -"miki.hyogo.jp\0holt\xc3\xa5len.no\0klepp.no\0kwpsp.gov.pl\0homedns.org\0" -"art\0bbt\0" -"zama.kanagawa.jp\0" -"ind.tn\0*.webhare.dev\0" -"h\xc3\xa1mm\xc3\xa1rfeasta.no\0bcg\0" -"kasumigaura.ibaraki.jp\0svalbard.no\0bambina.jp\0" -"nordeste-idc.saveincloud.net\0" -"kawara.fukuoka.jp\0" -"athleta\0s3-ap-southeast-2.amazonaws.com\0" -"bcn\0myspreadshop.it\0" -"rifu.miyagi.jp\0nishimera.miyazaki.jp\0" -"web.do\0osaki.miyagi.jp\0" -"hara.nagano.jp\0solund.no\0" -"satte.saitama.jp\0" -"dgca.aero\0versus.jp\0" +"blogspot.td\0" +"apple\0kaluga.su\0diskussionsbereich.de\0" +"gs.jan-mayen.no\0r\xc3\xa5holt.no\0" +"oita.jp\0odate.akita.jp\0tohnosho.chiba.jp\0sabae.fukui.jp\0saito.miyazaki.jp\0fujimi.nagano.jp\0soni.nara.jp\0bookonline.app\0" +"gov.ye\0" +"blogspot.tw\0blogspot.ug\0" +"safety\0" +"*.linodeobjects.com\0" +"gov.za\0" +"star\0blogspot.mr\0" +"fed.us\0wy.us\0k12.ar.us\0" +"westeurope.azurestaticapps.net\0static.land\0" +"deno.dev\0" +"blogspot.mx\0" +"blogspot.my\0paas.datacenter.fi\0" +"cyon.link\0" +"glogow.pl\0blogspot.nl\0" +"gov.zm\0" +"algard.no\0asnes.no\0aukra.no\0stranda.no\0stryn.no\0vestre-toten.no\0blogspot.no\0" +"\xe9\xab\x98\xe7\x9f\xa5.jp\0showa.fukushima.jp\0kitakami.iwate.jp\0kunigami.okinawa.jp\0kushimoto.wakayama.jp\0" +"aju.br\0" +"gov.zw\0" +"black\0feedback\0" +"qpon\0" +"uri.arpa\0" +"cog.mi.us\0" +"trentino-aadige.it\0\xe0\xaa\xad\xe0\xaa\xbe\xe0\xaa\xb0\xe0\xaa\xa4\0serveftp.net\0" +"leitungsen.de\0blogspot.pe\0" +"rel.pl\0sos.pl\0cieszyn.pl\0" +"\xd7\xa7\xd7\x95\xd7\x9d\0" +"yugawa.fukushima.jp\0naoshima.kagawa.jp\0higashiomi.shiga.jp\0" +"blogspot.qa\0" +"blogspot.pt\0" +"club.tw\0" +"no-ip.co.uk\0" "s3.amazonaws.com\0" -"works.aero\0\xe7\xb6\xb2\xe7\xb5\xa1.cn\0vs.it\0" -"sera.hiroshima.jp\0shichikashuku.miyagi.jp\0" -"woodside\0" -"*.hosting.ovh.net\0" -"spacekit.io\0" -"theworkpc.com\0" -"biz.ss\0" -"\xe6\xbe\xb3\xe9\x97\xa8\0" -"fudai.iwate.jp\0statebank\0" -"vladimir.ru\0" -"nishiwaki.hyogo.jp\0biz.tj\0" -"karpacz.pl\0" -"k\xc3\xa5""fjord.no\0" -"rdy.jp\0" -"komatsushima.tokushima.jp\0" -"\xe4\xb8\xaa\xe4\xba\xba.hk\0\xd1\x81\xd0\xbf\xd0\xb1.\xd1\x80\xd1\x83\xd1\x81\0" -"ketrzyn.pl\0biz.ua\0" -"biz.tr\0" -"nobeoka.miyazaki.jp\0" -"biz.tt\0bet\0" -"mk.ua\0" -"fukudomi.saga.jp\0zaporizhzhe.ua\0" -"uenohara.yamanashi.jp\0diskstation.me\0" -"davvenj\xc3\xa1rga.no\0" -"immo\0soc.srcf.net\0" -"susono.shizuoka.jp\0" -"kiyosato.hokkaido.jp\0" -"asahi.yamagata.jp\0" -"s3-website-us-west-1.amazonaws.com\0" -"czeladz.pl\0""123homepage.it\0" -"web.gu\0" -"webview-assets.cloud9.eu-west-1.amazonaws.com\0" -"univ.sn\0" -"diskstation.eu\0" -"aomori.jp\0ar.us\0" -"mosvik.no\0odda.no\0biz.vn\0" -"nat.tn\0vm.bytemark.co.uk\0" -"2000.hu\0axa\0" -"b\xc3\xa6rum.no\0grue.no\0aws\0" -"x.bg\0yamaguchi.jp\0biz.wf\0" -"nsw.edu.au\0web.id\0ebina.kanagawa.jp\0" -"morena.br\0" -"tokorozawa.saitama.jp\0" -"valle-daosta.it\0" -"katsuragi.nara.jp\0" -"wiki.bo\0myfast.host\0" -"umaji.kochi.jp\0" -"wiki.br\0" -"yaita.tochigi.jp\0" -"web.in\0" -"higashikagawa.kagawa.jp\0" -"seoul.kr\0gouv.sn\0" -"bid\0" -"\xe7\xb6\xb2\xe7\xb5\xa1.hk\0misato.saitama.jp\0" -"urown.cloud\0" -"embetsu.hokkaido.jp\0lib.in.us\0nowruz\0" -"futurehosting.at\0" -"bio\0" -"nyanta.jp\0" -"kouyama.kagoshima.jp\0wy.us\0" -"copro.uk\0" -"biz\0hn.cn\0" -"acct.pro\0" -"gs.bu.no\0kvanangen.no\0" -"oki.fukuoka.jp\0hidaka.kochi.jp\0" -"\xd9\x85\xd9\x88\xd8\xb1\xd9\x8a\xd8\xaa\xd8\xa7\xd9\x86\xd9\x8a\xd8\xa7\0" -"m.bg\0" -"ecologia.bo\0hadsel.no\0" -"ranzan.saitama.jp\0" -"biz.zm\0" -"web.lk\0" -"elverum.no\0malopolska.pl\0meinforum.net\0" -"guam.gu\0vapor.cloud\0" -"sakawa.kochi.jp\0supplies\0" +"cs.in\0garden\0" +"blogspot.is\0" +"cs.it\0pistoia.it\0blogspot.it\0" +"customer.speedpartner.de\0" +"pup.gov.pl\0pomorskie.pl\0" +"\xc3\xa1lt\xc3\xa1.no\0gildesk\xc3\xa5l.no\0vestnes.no\0v\xc3\xa6r\xc3\xb8y.no\0vagan.no\0" +"shonai.fukuoka.jp\0blogspot.jp\0" +"loans\0" +"*.banzai.cloud\0" +"homesense\0" +"s3-website.eu-west-2.amazonaws.com\0co.com\0from-fl.com\0from-pa.com\0is-a-player.com\0" +"cust.dev.thingdust.io\0" +"observer\0blogspot.kr\0" +"bozen-sudtirol.it\0r.cdn77.net\0pgafan.net\0myspreadshop.net\0" +"blogspot.li\0" +"wios.gov.pl\0legnica.pl\0" +"championship.aero\0forsand.no\0cahcesuolo.no\0" +"\xe5\x85\xb5\xe5\xba\xab.jp\0shinshiro.aichi.jp\0echizen.fukui.jp\0nakatane.kagoshima.jp\0ina.nagano.jp\0chichibu.saitama.jp\0urawa.saitama.jp\0yamagata.yamagata.jp\0user.webaccel.jp\0" +"jele.club\0" +"blogspot.lt\0blogspot.md\0" +"blogspot.lu\0" +"blogspot.mk\0" +"\xe8\xb0\xb7\xe6\xad\x8c\0tabitorder.co.il\0" +"publishproxy.com\0pgfog.com\0" +"k12.al.us\0" +"ch.it\0le.it\0tr.it\0eastasia.azurestaticapps.net\0" +"s.bg\0paris.eu.org\0" +"blogspot.fi\0" +"safety.aero\0aure.no\0fr\xc3\xa6na.no\0hasvik.no\0gaivuotna.no\0rad\xc3\xb8y.no\0" +"koori.fukushima.jp\0oizumi.gunma.jp\0kitahiroshima.hokkaido.jp\0ide.kyoto.jp\0togakushi.nagano.jp\0oseto.nagasaki.jp\0tarama.okinawa.jp\0ikeda.osaka.jp\0" +"blogspot.fr\0" +"selfip.com\0" +"protection\0" +"bingo\0" +"blogspot.gr\0" +"lib.in.us\0lib.sc.us\0" +"karacol.su\0" +"blogspot.hk\0" +"atm.pl\0lubartow.pl\0" +"bryne.no\0orkdal.no\0strand.no\0" +"chonan.chiba.jp\0kozaki.chiba.jp\0koriyama.fukushima.jp\0yusui.kagoshima.jp\0agematsu.nagano.jp\0hirara.okinawa.jp\0chihayaakasaka.osaka.jp\0kamikawa.saitama.jp\0ranzan.saitama.jp\0kaminoyama.yamagata.jp\0" +"dn.ua\0mk.ua\0" +"blogspot.hr\0" +"blogspot.hu\0blogspot.ie\0" +"url.tw\0" +"\xe3\x83\x9d\xe3\x82\xa4\xe3\x83\xb3\xe3\x83\x88\0*.svc.firenet.ch\0" +"api.gov.uk\0" +"webview-assets.cloud9.ap-south-1.amazonaws.com\0wpdevcloud.com\0ddns5.com\0herokussl.com\0" +"blogspot.in\0" +"it.ao\0" +"blogspot.ba\0" +"busan.kr\0" +"windows\0" +"westus2.azurestaticapps.net\0" +"sa.au\0blogspot.be\0" +"h.bg\0blogspot.bg\0zapto.org\0" +"blogspot.bj\0" +"ciencia.bo\0tr.no\0gs.of.no\0rauma.no\0vennesla.no\0" +"mukawa.hokkaido.jp\0rishirifuji.hokkaido.jp\0hadano.kanagawa.jp\0komono.mie.jp\0joetsu.niigata.jp\0takatsuki.osaka.jp\0genkai.saga.jp\0kuroiso.tochigi.jp\0" +"ivano-frankivsk.ua\0blogspot.ca\0" +"es.leg.br\0" +"blogspot.cf\0" +"blogspot.ch\0" +"blogspot.cl\0" +"ap-northeast-3.elasticbeanstalk.com\0from-va.com\0*.r.appspot.com\0" +"\xe5\x85\xac\xe5\x8f\xb8.\xe9\xa6\x99\xe6\xb8\xaf\0" +"sa.cr\0" +"cc.pa.us\0" +"trentinsud-tirol.it\0" +"blogspot.de\0" +"blogspot.cv\0" +"blogspot.cz\0" +"fam.pk\0blogspot.dk\0" +"kalisz.pl\0" +"snoasa.no\0vega.no\0" +"*.sapporo.jp\0owariasahi.aichi.jp\0matsuyama.ehime.jp\0itoman.okinawa.jp\0kanan.osaka.jp\0takatsuki.shiga.jp\0inami.wakayama.jp\0oishida.yamagata.jp\0rs.webaccel.jp\0" +"it1.jenv-aruba.cloud\0" +"diskstation.me\0" +"team\0iamallama.com\0withgoogle.com\0" +"dc.us\0" +"ar.it\0forlicesena.it\0terni.it\0" +"barsy.online\0diskstation.eu\0homelink.one\0" +"ngrok-free.dev\0" +"lebork.pl\0" +"andasuolo.no\0gjesdal.no\0jevnaker.no\0lardal.no\0stord.no\0surnadal.no\0sveio.no\0" +"kurate.fukuoka.jp\0hanawa.fukushima.jp\0haboro.hokkaido.jp\0kyotamba.kyoto.jp\0ogano.saitama.jp\0torahime.shiga.jp\0" +"salvador.br\0" +"tech\0" +"country\0" +"muni.il\0" +"vfs.cloud9.us-east-1.amazonaws.com\0townnews-staging.com\0" +"frontier\0" +"cc.nv.us\0lib.id.us\0lib.ri.us\0stuff-4-sale.us\0ch.tc\0" +"\xe0\xa8\xad\xe0\xa8\xbe\xe0\xa8\xb0\xe0\xa8\xa4\0""16-b.it\0" +"freedesktop.org\0myftp.org\0" +"eidsberg.no\0""123hjemmeside.no\0" +"yakumo.hokkaido.jp\0maniwa.okayama.jp\0nishiazai.shiga.jp\0anan.tokushima.jp\0nakayama.yamagata.jp\0" +"barueri.br\0fbx-os.fr\0" +"mil.ac\0homegoods\0" +"mil.ae\0game\0blogspot.ae\0" +"mil.al\0blogspot.al\0" +"s3-us-west-1.amazonaws.com\0blogspot.am\0jelastic.team\0" +"mil.ba\0" +"mil.ar\0" +"lombardy.it\0ag.it\0sa.it\0" +"mil.az\0" +"mypep.link\0" +"mazury.pl\0" +"insurance.aero\0rotorcraft.aero\0mil.bo\0dep.no\0averoy.no\0budejju.no\0bo.telemark.no\0meldal.no\0" +"miyama.fukuoka.jp\0chiyoda.gunma.jp\0taki.mie.jp\0nagano.nagano.jp\0motegi.tochigi.jp\0hofu.yamaguchi.jp\0daynight.jp\0" +"enf.br\0mil.br\0" +"k8s.fr-par.scw.cloud\0" +"\xe7\xa7\xbb\xe5\x8a\xa8\0" +"mil.by\0" +"mil.cl\0" +"damnserver.com\0" +"mil.cn\0hn.cn\0" +"mil.co\0*.s5y.io\0" +"lib.pr.us\0" +"friulivgiulia.it\0lucania.it\0val-daosta.it\0monzaebrianza.it\0" +"mil.cy\0" +"grp.lk\0" +"nowaruda.pl\0" +"own.pm\0" +"mil.do\0even\xc3\xa1\xc5\xa1\xc5\xa1i.no\0loab\xc3\xa1t.no\0cloudns.info\0" +"kawai.nara.jp\0gotemba.shizuoka.jp\0" +"mil.ec\0comsec\0marshalls\0" +"ieee\0" +"mil.eg\0" +"blogdns.com\0*.dev-builder.code.com\0" +"repl.run\0" +"kosher\0" +"1337.pictures\0" +"aosta.it\0bari.it\0cagliari.it\0rovigo.it\0sites.static.land\0" +"pp.az\0mil.fj\0" +"kolobrzeg.pl\0" +"svalbard.no\0alesund.no\0heroy.more-og-romsdal.no\0lerdal.no\0nord-odal.no\0" +"shikatsu.aichi.jp\0tahara.aichi.jp\0mitake.gifu.jp\0ishikari.hokkaido.jp\0kamigori.hyogo.jp\0taiki.mie.jp\0tsubame.niigata.jp\0omihachiman.shiga.jp\0hinohara.tokyo.jp\0koganei.tokyo.jp\0kunitachi.tokyo.jp\0" +"restaurant\0" +"mil.ge\0s.se\0" +"mil.gh\0" +"from-ia.com\0issmarterthanyou.com\0neat-url.com\0" +"gs.cn\0" +"base.shop\0" +"mil.gt\0valleeaoste.it\0trust\0" +"is-a-chef.org\0" +"hitachi\0" +"aid.pl\0" +"mil.hn\0" +"jolster.no\0stokke.no\0" +"kamijima.ehime.jp\0ouda.nara.jp\0chicappa.jp\0vercel.app\0" +"mil.id\0" +"free\0hlx3.page\0" +"vfs.cloud9.eu-west-3.amazonaws.com\0" +"mil.in\0" +"boxfuse.io\0editorx.io\0" +"mil.iq\0" +"ar.us\0associates\0shoes\0" +"squares.net\0" +"togliatti.su\0" +"*.user.localcert.dev\0" +"123hjemmeside.dk\0" +"opoczno.pl\0" +"mil.jo\0bod\xc3\xb8.no\0heroy.nordland.no\0" +"sannohe.aomori.jp\0furano.hokkaido.jp\0itami.hyogo.jp\0kasuga.hyogo.jp\0namegata.ibaraki.jp\0kuzumaki.iwate.jp\0zushi.kanagawa.jp\0nagasaki.nagasaki.jp\0kashiwazaki.niigata.jp\0" +"pe.ca\0" +"cri.br\0" +"flowers\0" +"h.se\0" +"mil.kg\0" +"mycloud.by\0" +"mil.km\0s3-eu-central-1.amazonaws.com\0myasustor.com\0from-nv.com\0is-a-lawyer.com\0" +"mil.kr\0" +"cc.me.us\0docs\0juegos\0" +"sardinia.it\0" +"nt.edu.au\0mein-vigor.de\0" +"netflix\0" +"mil.kz\0" +"journalist.aero\0jan-mayen.no\0bjugn.no\0kvalsund.no\0sunndal.no\0ullensvang.no\0" +"ono.fukui.jp\0eniwa.hokkaido.jp\0tomari.hokkaido.jp\0" +"mil.lv\0" +"mil.mg\0" +"independent-commission.uk\0" +"digital\0final\0" +"dnsdojo.com\0is-a-chef.com\0nfshost.com\0" +"k12.mt.us\0" +"basilicata.it\0torino.it\0" +"zone\0""12hp.de\0" +"mil.mv\0surf\0" +"1.bg\0mil.ng\0" +"ybo.faith\0" +"mil.my\0mil.ni\0" +"mil.mz\0gbiz\0" +"mil.no\0bergen.no\0malvik.no\0sm\xc3\xb8la.no\0" +"\xe5\xaf\x8c\xe5\xb1\xb1.jp\0handa.aichi.jp\0kasamatsu.gifu.jp\0mino.gifu.jp\0ikeda.nagano.jp\0kawakami.nara.jp\0boyfriend.jp\0" +"fm.br\0fortal.br\0" +"watch\0" +"mil.nz\0\xd8\xa7\xd9\x85\xd8\xa7\xd8\xb1\xd8\xa7\xd8\xaa\0" +"from-wv.com\0onrender.com\0" +"design\0" +"\xe0\xa6\xad\xe0\xa6\xbe\xe0\xa6\xb0\xe0\xa6\xa4\0""12hp.at\0" +"act.edu.au\0mil.pe\0" +"bloomberg\0tr.eu.org\0wmcloud.org\0" +"mil.ph\0" +"mil.pl\0" +"karlsoy.no\0cloudns.pro\0" +"\xe4\xba\xac\xe9\x83\xbd.jp\0iyo.ehime.jp\0sukagawa.fukushima.jp\0mifune.kumamoto.jp\0kanmaki.nara.jp\0" +"mil.qa\0" +"kids\0" +"perso.ht\0" +"12hp.ch\0" +"mil.py\0" +"sinaapp.com\0" +"lacaixa\0pizza\0shiksha\0teva\0" +"locker\0" +"pe.it\0" +"viking\0" +"ferrari\0" +"money.bj\0" +"pila.pl\0" +"homebuilt.aero\0larvik.no\0radoy.no\0rindal.no\0latino\0" +"fukui.fukui.jp\0minami.fukuoka.jp\0miyako.fukuoka.jp\0takanabe.miyazaki.jp\0shinjo.nara.jp\0taishi.osaka.jp\0toyonaka.osaka.jp\0fem.jp\0" +"diadem.cloud\0" +"alsace\0mil.ru\0" +"mil.rw\0" +"mil.sh\0" +"\xd0\xba\xd0\xbe\xd0\xbc\0" +"tuleap-partners.com\0" +"bluebite.io\0" +"tienda\0" +"pe.kr\0" +"lib.mn.us\0" +"vald-aosta.it\0tempioolbia.it\0mil.st\0akamaiedge.net\0" +"onred.one\0" +"serveftp.org\0ufcfan.org\0" +"mil.sy\0" +"mil.tj\0" +"turystyka.pl\0" +"mil.tm\0" +"fuel.aero\0drobak.no\0masoy.no\0mil.to\0" +"tochigi.jp\0miharu.fukushima.jp\0manno.kagawa.jp\0higashimatsushima.miyagi.jp\0abeno.osaka.jp\0main.jp\0" +"mil.tr\0freebox-os.fr\0" +"lakas.hu\0" +"mil.tw\0" +"mil.tz\0" +"vm.bytemark.co.uk\0" +"dyndns-mail.com\0" +"mil.vc\0" +"fm.it\0edgekey.net\0global.prod.fastly.net\0bar0.net\0" +"wa.au\0mil.ve\0keymachine.de\0" +"living\0" +"mil.uy\0" +"ketrzyn.pl\0" +"airport.aero\0gs.sf.no\0h\xc3\xa5.no\0bci.dnstrace.pro\0" +"hazu.aichi.jp\0shingo.aomori.jp\0sakahogi.gifu.jp\0inagawa.hyogo.jp\0shika.ishikawa.jp\0toshima.tokyo.jp\0ciao.jp\0" +"yalta.ua\0" +"\xd1\x81\xd0\xb0\xd0\xb9\xd1\x82\0" +"bargains\0" +"download\0" +"komvux.se\0pp.se\0pp.ru\0" +"cri.nz\0" +"webview-assets.cloud9.sa-east-1.amazonaws.com\0" +"backplaneapp.io\0pstmn.io\0" +"folionetwork.site\0home-webserver.de\0" +"basketball\0unicloud.pl\0" +"rost.no\0valer.ostfold.no\0" +"hirosaki.aomori.jp\0mutsu.aomori.jp\0nonoichi.ishikawa.jp\0kisofukushima.nagano.jp\0shimoji.okinawa.jp\0iwata.shizuoka.jp\0" +"\xe4\xb8\xad\xe4\xbf\xa1\0pp.ua\0" +"campinas.br\0" +"com.ac\0" +"mil.ye\0" +"com.af\0" +"com.ag\0" +"com.ai\0" +"com.al\0" +"com.am\0sa-east-1.elasticbeanstalk.com\0est-mon-blogueur.com\0ooguy.com\0servequake.com\0" +"er.in\0open\0" +"makeup\0" +"com.ba\0mil.za\0" +"com.ar\0com.bb\0" +"k12.ky.us\0k12.tx.us\0locus\0" +"vallee-aoste.it\0macerata.it\0monza-e-della-brianza.it\0no.it\0taranto.it\0" +"com.au\0" +"loginline.dev\0" +"com.aw\0giving\0" +"com.bh\0" +"com.bi\0" +"com.az\0com.bj\0" +"com.bm\0mil.zm\0" +"com.bn\0" +"com.bo\0fm.no\0gs.aa.no\0bremanger.no\0tr\xc3\xa6na.no\0" +"tateyama.chiba.jp\0tsukiyono.gunma.jp\0kayabe.hokkaido.jp\0izumi.kagoshima.jp\0semine.miyagi.jp\0" +"visa\0" +"com.br\0" +"com.bs\0" +"com.bt\0dupont\0" +"shacknet.nu\0" +"mil.zw\0blog\0" +"com.by\0com.ci\0" +"com.bz\0" +"com.cm\0webview-assets.cloud9.ap-southeast-1.amazonaws.com\0is-an-accountant.com\0" +"com.cn\0" +"com.co\0" +"cc.al.us\0lib.dc.us\0lib.md.us\0lib.vi.us\0" +"belluno.it\0" +"com.cu\0com.de\0schulplattform.de\0taifun-dns.de\0" +"com.cv\0" +"com.cw\0" +"com.cy\0" +"\xe7\xbb\x84\xe7\xb9\x94.hk\0" +"auto.pl\0travel.pl\0ostrowwlkp.pl\0" +"com.dm\0" +"tksat.bo\0com.do\0spydeberg.no\0stj\xc3\xb8rdal.no\0" +"nishigo.fukushima.jp\0hamatonbetsu.hokkaido.jp\0aikawa.kanagawa.jp\0miyake.nara.jp\0nakano.tokyo.jp\0" +"\xd0\xba\xd0\xbe\xd0\xbc.\xd1\x80\xd1\x83\xd1\x81\0" +"com.ec\0" +"com.ee\0" +"com.eg\0" +"supply\0" +"com.dz\0" +"*.paywhirl.com\0" +"carrd.co\0" +"viva\0" +"jaguar\0kinder\0" +"com.es\0mircloud.us\0" +"com.et\0friuli-venezia-giulia.it\0mt.it\0imamat\0dontexist.net\0from-co.net\0siteleaf.net\0" +"ryukyu\0" +"academy\0" +"com.fj\0" +"com.fm\0" +"indie.porn\0" +"trainer.aero\0cooperativa.bo\0bardu.no\0haugesund.no\0snasa.no\0tr\xc3\xb8gstad.no\0vivo\0" +"\xe6\x96\xb0\xe6\xbd\x9f.jp\0otaki.chiba.jp\0togura.nagano.jp\0nikita.jp\0" +"com.fr\0\xe0\xb8\x97\xe0\xb8\xab\xe0\xb8\xb2\xe0\xb8\xa3.\xe0\xb9\x84\xe0\xb8\x97\xe0\xb8\xa2\0" +"com.ge\0""2000.hu\0" +"com.gh\0" +"com.gi\0" +"royal-commission.uk\0" +"com.gl\0" +"notaires.km\0from-de.com\0from-vt.com\0rag-cloud.hosteur.com\0" +"cq.cn\0ln.cn\0com.gn\0" +"com.gp\0dunlop\0" +"com.gr\0" +"cc.in.us\0lib.la.us\0condos\0" +"com.gt\0lodi.it\0\xe0\xa4\xad\xe0\xa4\xbe\xe0\xa4\xb0\xe0\xa4\xa4\0lon-2.paas.massivegrid.net\0" +"com.gu\0hlx.live\0" +"cloudns.org\0" +"com.gy\0" +"com.hk\0ngo.lk\0" +"konskowola.pl\0" +"\xed\x95\x9c\xea\xb5\xad\0" +"com.hn\0" +"nesoddtangen.no\0\xc3\xa1k\xc5\x8boluokta.no\0" +"kiyosu.aichi.jp\0nagareyama.chiba.jp\0shirakawa.gifu.jp\0himeji.hyogo.jp\0seirou.niigata.jp\0" +"chirurgiens-dentistes.fr\0com.hr\0" +"com.ht\0travel.tt\0" +"konyvelo.hu\0blue\0" +"dental\0" +"com.im\0" +"com.in\0" +"com.io\0" +"com.iq\0" +"com.is\0" +"mi.it\0urbino-pesaro.it\0" +"uk.eu.org\0ngo.ng\0" +"suwalki.pl\0" +"com.jo\0bjark\xc3\xb8y.no\0whoswho\0" +"yabuki.fukushima.jp\0shimonita.gunma.jp\0shima.mie.jp\0murakami.niigata.jp\0tomigusuku.okinawa.jp\0" +"kyiv.ua\0" +"caxias.br\0cng.br\0" +"george\0mircloud.ru\0" +"com.kg\0" +"com.ki\0kiwi\0" +"com.km\0airkitapps-au.com\0vfs.cloud9.us-east-2.amazonaws.com\0" +"perso.sn\0nikon\0onporter.run\0" +"reservd.disrec.thingdust.io\0" +"com.kp\0" +"com.la\0stada\0" +"com.lb\0" +"com.lc\0" +"avellino.it\0is-a-chef.net\0" +"kindle\0internet-dns.de\0chimkent.su\0git-repos.de\0" +"com.kw\0" +"ngo.ph\0" +"ltd.cy\0com.ky\0" +"com.kz\0" +"com.lk\0" +"augustow.pl\0swinoujscie.pl\0tgory.pl\0\xe4\xb8\x96\xe7\x95\x8c\0" +"perso.tn\0" +"afjord.no\0skedsmo.no\0" +"\xe7\xa5\x9e\xe5\xa5\x88\xe5\xb7\x9d.jp\0\xe7\xa6\x8f\xe4\xba\x95.jp\0oto.fukuoka.jp\0bandai.fukushima.jp\0isesaki.gunma.jp\0meiwa.gunma.jp\0tobetsu.hokkaido.jp\0tsukui.kanagawa.jp\0setouchi.okayama.jp\0minamidaito.okinawa.jp\0" +"com.lr\0" +"com.lv\0" +"com.mg\0" +"com.ly\0" +"com.mk\0" +"com.ml\0" +"uk.in\0*.database.run\0" +"com.mo\0" +"com.na\0" +"com.ms\0" +"val-d-aosta.it\0vao.it\0bolzano.it\0com.mt\0akamai.net\0""123homepage.it\0" +"com.mu\0bridgestone\0" +"com.mv\0com.nf\0" +"com.mw\0com.ng\0lighting\0" +"com.mx\0banamex\0" +"com.my\0com.ni\0" +"for-the.biz\0" +"starostwo.gov.pl\0" +"certification.aero\0vf.no\0sand\xc3\xb8y.no\0" +"uryu.hokkaido.jp\0kamo.kyoto.jp\0kamikitayama.nara.jp\0aga.niigata.jp\0higashiizumo.shimane.jp\0egoism.jp\0" +"com.nr\0" +"k8s.nl-ams.scw.cloud\0" +"vladikavkaz.ru\0" +"uk.kg\0" +"ltd.gi\0" +"com.om\0unicom\0jcloud.ik-server.com\0" +"jx.cn\0" +"leadpages.co\0" +"com.pa\0" +"author\0" +"lib.ar.us\0" +"trentin-sued-tirol.it\0trentinos\xc3\xbc""dtirol.it\0vall\xc3\xa9""e-d-aoste.it\0cdn77-ssl.net\0" +"com.pe\0vladikavkaz.su\0" +"com.pf\0" +"is-a-bruinsfan.org\0" +"com.ph\0xerox\0" +"com.pk\0ltd.hk\0" +"com.pl\0" +"\xc3\xb8rsta.no\0" +"kitakata.fukushima.jp\0sano.tochigi.jp\0shishikui.tokushima.jp\0ngrok-free.app\0" +"com.qa\0" +"com.pr\0" +"com.ps\0" +"com.pt\0" +"filegear-gb.me\0" +"com.py\0" +"is-a-landscaper.com\0gleeze.com\0thingdustdata.com\0" +"mt.us\0nd.us\0wa.us\0" +"friuliv-giulia.it\0laz.it\0lc.it\0tp.it\0trento.it\0scrapper-site.net\0wien.funkfeuer.at\0*.ex.futurecms.at\0uni5.net\0" +"com.re\0" +"q.bg\0" +"rybnik.pl\0" +"bykle.no\0gran.no\0leksvik.no\0sandnes.no\0trysil.no\0com.ro\0" +"tsushima.aichi.jp\0kashiwa.chiba.jp\0yoka.hyogo.jp\0omachi.nagano.jp\0minano.saitama.jp\0kawahara.tottori.jp\0fool.jp\0" +"com.sa\0" +"com.sb\0" +"com.sc\0" +"com.sd\0" +"page\0com.se\0com.ru\0" +"com.sg\0" +"com.sh\0" +"com.sl\0" +"from-ak.com\0*.builder.code.com\0bloxcms.com\0" +"com.sn\0ericsson\0" +"com.so\0" +"com.ss\0" +"vercelli.it\0com.st\0principe.st\0auspost\0" +"aquarelle\0" +"com.sv\0" +"mi.th\0" +"com.sy\0" +"com.tj\0" +"ltd.lk\0" +"oum.gov.pl\0sko.gov.pl\0upow.gov.pl\0" +"com.tm\0" +"com.tn\0" +"club.aero\0nord-fron.no\0com.to\0" +"happou.akita.jp\0miki.hyogo.jp\0nishiwaki.hyogo.jp\0kitaaiki.nagano.jp\0makinohara.shizuoka.jp\0" +"com.ua\0" +"from.hr\0com.tr\0" +"firm.ht\0com.tt\0s3-website.fr-par.scw.cloud\0" +"com.tw\0com.ug\0" +"firm.in\0cn-northwest-1.eb.amazonaws.com.cn\0" +"shiftedit.io\0" +"alt.za\0ngo.za\0" +"mi.us\0k12.il.us\0com.vc\0tennis\0graphox.us\0" +"te.it\0teramo.it\0channelsdvr.net\0" +"com.ve\0" +"vercel.dev\0" +"f.bg\0ltd.ng\0" +"com.uy\0com.vi\0" +"com.uz\0" +"\xce\xb5\xce\xbb\0" +"com.vn\0" +"gs.nt.no\0kr\xc3\xb8""dsherad.no\0stor-elvdal.no\0" +"\xe7\xbe\xa4\xe9\xa6\xac.jp\0omigawa.chiba.jp\0tomiya.miyagi.jp\0gosen.niigata.jp\0niiza.saitama.jp\0bunkyo.tokyo.jp\0fujiyoshida.yamanashi.jp\0" +"dedibox.fr\0" +"farmers\0" +"\xd0\xbc\xd0\xba\xd0\xb4\0" +"com.vu\0\xce\xb5\xcf\x85\0" +"search\0" +"africa.com\0is-a-anarchist.com\0is-slick.com\0workisboring.com\0" +"firm.co\0" +"com.ws\0" +"trentins\xc3\xbc""dtirol.it\0\xe6\x9c\xba\xe6\x9e\x84\0mymediapc.net\0" +"firm.dk\0" +"bomlo.no\0froya.no\0nes.buskerud.no\0s\xc3\xa1lat.no\0tjeldsund.no\0" +"shizuoka.jp\0tsuyama.okayama.jp\0nagato.yamaguchi.jp\0" +"\xe9\xa3\x9f\xe5\x93\x81\0" +"chirurgiens-dentistes-en-france.fr\0" +"sec.ps\0" +"read\0" +"com.ye\0" +"\xd9\xbe\xd8\xa7\xd9\x83\xd8\xb3\xd8\xaa\xd8\xa7\xd9\x86\0" +"ebiz.tw\0" +"\xe5\xbe\xae\xe5\x8d\x9a\0" +"weeklylottery.org.uk\0" +"vfs.cloud9.af-south-1.amazonaws.com\0" +"agakhan\0" +"aetna\0" +"mutual.ar\0" +"ap.it\0oristano.it\0pordenone.it\0" +"lifestyle\0" +"sellsyourhome.org\0" +"com.zm\0" +"gamvik.no\0gloppen.no\0guovdageaidnu.no\0lindesnes.no\0nedre-eiker.no\0v\xc3\xa5gan.no\0bar.pro\0" +"nisshin.aichi.jp\0chikushino.fukuoka.jp\0kaneyama.fukushima.jp\0ogaki.gifu.jp\0assabu.hokkaido.jp\0imakane.hokkaido.jp\0kawakami.nagano.jp\0fujimi.saitama.jp\0nogi.tochigi.jp\0katsushika.tokyo.jp\0" +"cci.fr\0" +"csx.cc\0" +"\xd0\xbc\xd0\xbe\xd0\xbd\0webview-assets.cloud9.us-east-2.amazonaws.com\0" +"friuli-v-giulia.it\0" +"powiat.pl\0" +"frosta.no\0vestre-slidre.no\0x0.to\0" +"shichinohe.aomori.jp\0onga.fukuoka.jp\0akabira.hokkaido.jp\0shimokawa.hokkaido.jp\0hirono.iwate.jp\0yusuhara.kochi.jp\0minamisanriku.miyagi.jp\0asakuchi.okayama.jp\0higashisumiyoshi.osaka.jp\0komae.tokyo.jp\0fuchu.toyama.jp\0backdrop.jp\0o0o0.jp\0" +"ks.ua\0ltd.ua\0no-ip.ca\0" +"gifts\0" +"codeberg.page\0filegear-ie.me\0" +"ltd.uk\0" +"ro.im\0wafflecell.com\0" +"travel.in\0" +"ks.us\0eaton.mi.us\0is-by.us\0" +"ro.it\0" +"\xe9\xa6\x99\xe6\xa0\xbc\xe9\x87\x8c\xe6\x8b\x89\0" +"winb.gov.pl\0" +"\xc3\xa5mot.no\0\xc3\xa5s.no\0inderoy.no\0kvinesdal.no\0r\xc3\xb8yrvik.no\0sandefjord.no\0" +"towada.aomori.jp\0kakamigahara.gifu.jp\0beppu.oita.jp\0hanno.saitama.jp\0" +"sumy.ua\0" +"srv.br\0" +"pars\0" +"vfs.cloud9.ap-southeast-1.amazonaws.com\0dyndns-web.com\0from-tx.com\0" +"hl.cn\0" +"trentin-sud-tirol.it\0" +"arkhangelsk.su\0" +"bieszczady.pl\0" +"economia.bo\0hadsel.no\0" +"omiya.saitama.jp\0ryokami.saitama.jp\0nanbu.yamanashi.jp\0" +"kh.ua\0te.ua\0" +"smartlabeling.scw.cloud\0" +"komforb.se\0" +"dyndns-ip.com\0""3utilities.com\0" +"incheon.kr\0solar\0" +"lexus\0" +"reit\0thruhere.net\0" +"firm.ve\0secure\0fastvps.site\0*.transurl.be\0" +"mobi\0" +"engine.aero\0kommune.no\0mo-i-rana.no\0arendal.no\0notteroy.no\0\xe6\xb8\xb8\xe6\x88\x8f\0" +"kurume.fukuoka.jp\0nanporo.hokkaido.jp\0saroma.hokkaido.jp\0maizuru.kyoto.jp\0udono.mie.jp\0ohira.miyagi.jp\0wake.okayama.jp\0" +"yk.ca\0" +"zlg.br\0notaires.fr\0" +"organic\0" +"ca.reclaim.cloud\0" +"riik.ee\0ras.ru\0" "northwesternmutual\0" -"kaluga.su\0" -"ono.fukui.jp\0kyotanabe.kyoto.jp\0namerikawa.toyama.jp\0" -"qld.gov.au\0cc.ny.us\0" -"!city.kitakyushu.jp\0ask\xc3\xb8y.no\0myspreadshop.se\0" -"from-oh.com\0" -"owani.aomori.jp\0gwangju.kr\0" -"wuoz.gov.pl\0" -"tochigi.jp\0" -"tromsa.no\0" -"katano.osaka.jp\0" -"web.nf\0natura\0" -"gs.cn\0tr.it\0" -"oshu.iwate.jp\0web.ni\0" -"nome.pt\0" -"barueri.br\0" -"grp.lk\0s\xc3\xb8r-odal.no\0" -"bunkyo.tokyo.jp\0bms\0" -"foodnetwork\0" -"sa.gov.au\0bmw\0" -"b.bg\0" -"pvt.ge\0mail.pl\0" -"bygland.no\0" -"sa.au\0" -"b.br\0kuokgroup\0" -"itami.hyogo.jp\0" -"trentinsuedtirol.it\0holiday\0" -"lib.id.us\0" -"taishi.osaka.jp\0" -"\xe0\xa4\xa8\xe0\xa5\x87\xe0\xa4\x9f\0misconfused.org\0" -"royken.no\0" -"agrigento.it\0bom\0" -"padova.it\0web.pk\0" -"info\0boo\0" -"narviika.no\0r\xc3\xb8ros.no\0" -"ham-radio-op.net\0" -"bot\0" -"chuo.osaka.jp\0*.stgstage.dev\0" -"box\0storage\0" -"wang\0" -"sa.cr\0chuo.yamanashi.jp\0" -"katsushika.tokyo.jp\0" -"nishinomiya.hyogo.jp\0my-router.de\0" -"gouv.km\0mup.gov.pl\0cab\0" -"rr.gov.br\0" -"ichinomiya.chiba.jp\0nobushi.jp\0" -"yoichi.hokkaido.jp\0" +"vfs.cloud9.eu-central-1.amazonaws.com\0dyndns-at-home.com\0dopaas.com\0" +"ha.cn\0epson\0bss.design\0" +"moda\0" +"cc.mn.us\0lib.pa.us\0" +"tempurl.host\0" +"schools.nsw.edu.au\0" +"dscloud.biz\0" +"balsfjord.no\0selbu.no\0" +"chuo.fukuoka.jp\0tomobe.ibaraki.jp\0watarai.mie.jp\0tara.saga.jp\0ogasawara.tokyo.jp\0shirataka.yamagata.jp\0floppy.jp\0nyanta.jp\0" +"tiaa\0yokohama\0" +"sp.gov.br\0" +"webview-assets.cloud9.us-west-1.amazonaws.com\0" +"k12.ok.us\0" +"edgesuite-staging.net\0at-band-camp.net\0" +"square7.de\0*.transurl.eu\0" +"hopto.org\0" +"ote.bj\0" +"tranby.no\0askvoll.no\0karm\xc3\xb8y.no\0firm.ro\0" +"\xe5\xb1\xb1\xe5\xbd\xa2.jp\0mihama.chiba.jp\0oumu.hokkaido.jp\0sayo.hyogo.jp\0takaharu.miyazaki.jp\0pepper.jp\0bona.jp\0" +"log.br\0santamaria.br\0" +"marriott\0rent\0" +"f.se\0uber.space\0" +"ent.platform.sh\0" +"independent-inquiry.uk\0" +"from-hi.com\0" +"mormon\0volkswagen\0" +"analytics\0" +"pescara.it\0" +"jcloud.kz\0" +"gmina.pl\0so.gov.pl\0zakopane.pl\0" +"badaddja.no\0h\xc3\xa1mm\xc3\xa1rfeasta.no\0kautokeino.no\0skierv\xc3\xa1.no\0deatnu.no\0tonsberg.no\0" +"higashinaruse.akita.jp\0joboji.iwate.jp\0shikama.miyagi.jp\0miyota.nagano.jp\0ryuoh.shiga.jp\0kainan.tokushima.jp\0tanabe.wakayama.jp\0clerk.app\0" +"chernigov.ua\0" +"from.tv\0" +"enscaled.sg\0" +"square7.ch\0" +"bofa\0" +"grainger\0" +"molise.it\0umb.it\0pn.it\0fund\0eastus2.azurestaticapps.net\0" +"tula.su\0" +"firm.nf\0" +"dontexist.org\0firm.ng\0dsmynas.org\0" +"mail.pl\0" +"hl.no\0her\xc3\xb8y.m\xc3\xb8re-og-romsdal.no\0rennes\xc3\xb8y.no\0sandoy.no\0" +"fukusaki.hyogo.jp\0niyodogawa.kochi.jp\0hakuba.nagano.jp\0shimabara.nagasaki.jp\0yufu.oita.jp\0tondabayashi.osaka.jp\0higashichichibu.saitama.jp\0nishinoshima.shimane.jp\0kudamatsu.yamaguchi.jp\0fujikawa.yamanashi.jp\0mimoza.jp\0saloon.jp\0" +"campinagrande.br\0" +"eu.int\0gent\0" +"webhop.me\0" +"gitapp.si\0" +"s3-external-1.amazonaws.com\0drayddns.com\0alpha-myqnapcloud.com\0" +"nx.cn\0" +"rest\0" +"jelastic.dogado.eu\0" +"homedns.org\0" +"konin.pl\0" +"obu.aichi.jp\0aomori.aomori.jp\0sue.fukuoka.jp\0taishin.fukushima.jp\0tarumizu.kagoshima.jp\0nishihara.okinawa.jp\0osakasayama.osaka.jp\0loginline.app\0" +"abbott\0microsoft\0" +"edgestack.me\0" +"s3-website.us-east-2.amazonaws.com\0webview-assets.cloud9.ap-northeast-1.amazonaws.com\0eu-central-1.elasticbeanstalk.com\0ddnslive.com\0ditchyourip.com\0servehalflife.com\0" +"green\0" +"readthedocs.io\0" +"k12.me.us\0k12.ut.us\0" +"sic.it\0vall\xc3\xa9""e-aoste.it\0pc.it\0" +"lima.zone\0" +"*.transurl.nl\0" +"\xe0\xb0\xad\xe0\xb0\xbe\xe0\xb0\xb0\xe0\xb0\xa4\xe0\xb1\x8d\0" +"ha.no\0skjak.no\0tynset.no\0dynamic-dns.info\0" +"seto.aichi.jp\0honjo.akita.jp\0nishiokoppe.hokkaido.jp\0numata.hokkaido.jp\0ichinohe.iwate.jp\0kawanabe.kagoshima.jp\0yokkaichi.mie.jp\0shiiba.miyazaki.jp\0ojiya.niigata.jp\0readymade.jp\0" +"kirovograd.ua\0" +"geo.br\0trd.br\0name.hr\0" +"nh-serv.co.uk\0" +"eu-west-1.elasticbeanstalk.com\0customer.mythic-beasts.com\0" +"nm.cn\0" +"reservd.dev.thingdust.io\0" +"name.et\0azurewebsites.net\0azurestaticapps.net\0" +"smile\0" +"pccw\0duckdns.org\0" +"name.fj\0orx.biz\0" +"oia.gov.pl\0" +"d\xc3\xb8nna.no\0" +"yamatokoriyama.nara.jp\0shimada.shizuoka.jp\0sakegawa.yamagata.jp\0" +"sakura.tv\0" +"*.oci.customer-oci.com\0serveftp.com\0" +"nic.in\0" +"taobao\0" +"florence.it\0bond\0" +"sr.gov.pl\0" +"austevoll.no\0n\xc3\xa5\xc3\xa5mesjevuemie.no\0rendalen.no\0v\xc3\xa5ler.hedmark.no\0" +"fukuoka.jp\0anpachi.gifu.jp\0tsunan.niigata.jp\0shijonawate.osaka.jp\0kamiichi.toyama.jp\0yamanobe.yamagata.jp\0" +"nb.ca\0" +"exchange\0" +"name.eg\0" +"book\0temasek\0cust.retrosnub.co.uk\0" +"blogspot.com\0" +"daejeon.kr\0gyeongbuk.kr\0" +"lib.nm.us\0" +"trentino-sued-tirol.it\0quest\0" +"jambyl.su\0" +"shiftcrypto.dev\0" +"dynserv.org\0" +"official.academy\0" +"name.az\0myftp.biz\0" +"pc.pl\0" +"broker.aero\0f\xc3\xb8rde.no\0moto\0" +"toyokawa.aichi.jp\0yanaizu.fukushima.jp\0higashiagatsuma.gunma.jp\0wajima.ishikawa.jp\0satsumasendai.kagoshima.jp\0zama.kanagawa.jp\0izumiotsu.osaka.jp\0yatsuka.shimane.jp\0" +"nikolaev.ua\0" +"tips\0" +"filegear-sg.me\0" +"nowtv\0" +"res.in\0" +"\xe9\xa6\x99\xe6\xb8\xaf\0*.on-acorn.io\0" +"ninja\0" +"rocher\0" +"americanexpress\0" +"definima.net\0" +"\xe9\xa4\x90\xe5\x8e\x85\0" +"clothing\0" +"today\0" +"olsztyn.pl\0" +"express.aero\0microlight.aero\0\xc3\xa5rdal.no\0balestrand.no\0kr\xc3\xa5""anghke.no\0hemne.no\0knowsitall.info\0" +"nishio.aichi.jp\0shimogo.fukushima.jp\0tsu.mie.jp\0kariwa.niigata.jp\0taketa.oita.jp\0nanjo.okinawa.jp\0tsurugashima.saitama.jp\0misato.wakayama.jp\0daa.jp\0" +"corsica\0" +"psc.br\0" +"kerryhotels\0" +"s3.fr-par.scw.cloud\0" +"hb.cldmail.ru\0" +"wedeploy.sh\0" +"*.0emm.com\0servecounterstrike.com\0" +"gangwon.kr\0" +"cc.sd.us\0lib.de.us\0" +"\xe0\xa6\xad\xe0\xa6\xbe\xe0\xa7\xb0\xe0\xa6\xa4\0" +"*.stg.dev\0" +"ug.gov.pl\0kutno.pl\0naklo.pl\0" +"l\xc3\xa1hppi.no\0ivgu.no\0" +"aichi.jp\0toyone.aichi.jp\0nishinoomote.kagoshima.jp\0susaki.kochi.jp\0tsuno.miyazaki.jp\0tokigawa.saitama.jp\0lomo.jp\0ngrok.app\0s3.isk01.sakurastorage.jp\0" +"\xd0\xbf\xd1\x80.\xd1\x81\xd1\x80\xd0\xb1\0" +"co.ae\0c66.me\0" +"co.ag\0" +"co.am\0is-a-bulls-fan.com\0members.linode.com\0" +"virgin\0" +"co.ao\0" +"co.bb\0" +"paris\0" +"co.at\0aostavalley.it\0brindisi.it\0endofinternet.net\0" +"ashgabad.su\0" +"no-ip.org\0" +"co.bi\0blogspot.com.cy\0" +"co.bj\0" +"co.bn\0" +"parachuting.aero\0oster\xc3\xb8y.no\0snillfjord.no\0v\xc3\xa1rgg\xc3\xa1t.no\0ferrero\0" +"matsudo.chiba.jp\0daiwa.hiroshima.jp\0biei.hokkaido.jp\0kyotango.kyoto.jp\0nose.osaka.jp\0perma.jp\0" +"co.ca\0" +"blogspot.com.ee\0" +"co.bw\0blogspot.com.eg\0" +"co.ci\0" +"co.cl\0" +"co.cm\0*.compute.amazonaws.com\0" +"co.cr\0chungbuk.kr\0blogspot.com.ar\0" +"cc.il.us\0cc.ri.us\0lib.ks.us\0" +"friuli-veneziagiulia.it\0trentin-suedtirol.it\0perugia.it\0" +"estate\0blogspot.com.au\0" +"nic.tj\0co.cz\0" +"co.dk\0" +"hanggliding.aero\0m\xc3\xa5lselv.no\0" +"shingu.fukuoka.jp\0takayama.gifu.jp\0hidaka.hokkaido.jp\0kamakura.kanagawa.jp\0ninomiya.kanagawa.jp\0kurashiki.okayama.jp\0kiyama.saga.jp\0kill.jp\0" +"blogspot.com.br\0" +"fairwinds\0\xd0\xbe\xd1\x80\xd0\xb3\0" +"fr-par-2.baremetal.scw.cloud\0" +"blogspot.com.by\0" +"nhs.uk\0" +"blogspot.com.co\0in.ngrok.io\0" +"int.ar\0lancaster\0" +"oh.us\0tunes\0" +"valle-d-aosta.it\0cz.it\0viterbo.it\0" +"asn.au\0fnwk.site\0lcube-server.de\0" +"int.az\0" +"consultant.aero\0int.bo\0mr.no\0eidsvoll.no\0leikanger.no\0forumz.info\0" +"shirako.chiba.jp\0ashiya.fukuoka.jp\0shobara.hiroshima.jp\0kasama.ibaraki.jp\0uchinada.ishikawa.jp\0ikaruga.nara.jp\0fukuroi.shizuoka.jp\0fussa.tokyo.jp\0easypanel.app\0web.app\0" +"ma.leg.br\0" +"co.gg\0" +"int.ci\0myforum.community\0" +"co.gl\0" +"from-ms.com\0from-nc.com\0codespot.com\0""001www.com\0*.vultrobjects.com\0" +"int.co\0" +"cc.ia.us\0blogspot.com.es\0platterp.us\0" +"omniwe.site\0" +"int.cv\0" +"co.gy\0" +"szczecin.pl\0" +"name.vn\0" +"kragero.no\0oppegard.no\0" +"nagano.jp\0tokyo.jp\0kikonai.hokkaido.jp\0chigasaki.kanagawa.jp\0muroto.kochi.jp\0sayama.osaka.jp\0kawaguchi.saitama.jp\0masuda.shimane.jp\0komatsushima.tokushima.jp\0sumomo.ne.jp\0rulez.jp\0" +"co.id\0" +"co.hu\0ggee\0wedeploy.me\0" +"co.il\0" +"co.im\0" +"co.in\0" +"*.sys.qcx.io\0" +"nic.za\0" +"co.ir\0" +"nm.us\0" +"tos.it\0co.it\0cricket\0myeffect.net\0" +"co.je\0" +"mediatech.dev\0" +"z.bg\0ee.eu.org\0ro.eu.org\0" +"technology\0" +"name.tj\0" +"bamble.no\0karmoy.no\0" +"co.jp\0!city.sapporo.jp\0kanie.aichi.jp\0mihama.fukui.jp\0yamagata.gifu.jp\0nanao.ishikawa.jp\0aki.kochi.jp\0mimata.miyazaki.jp\0minato.osaka.jp\0wajiki.tokushima.jp\0fujikawaguchiko.yamanashi.jp\0" +"to.gov.br\0tc.br\0name.tr\0" +"name.tt\0" +"co.ke\0" +"no.com\0from-sc.com\0vs.mythic-beasts.com\0" +"co.kr\0" +"co.lc\0" +"akamaized-staging.net\0" +"troitsk.su\0" +"is-very-bad.org\0" +"uppo.gov.pl\0bialowieza.pl\0tmall\0gdynia.pl\0" +"\xe0\xae\x9a\xe0\xae\xbf\xe0\xae\x99\xe0\xaf\x8d\xe0\xae\x95\xe0\xae\xaa\xe0\xaf\x8d\xe0\xae\xaa\xe0\xaf\x82\xe0\xae\xb0\xe0\xaf\x8d\0" +"council.aero\0ecologia.bo\0langev\xc3\xa5g.no\0biev\xc3\xa1t.no\0dyndns.info\0" +"ibaraki.ibaraki.jp\0rikuzentakata.iwate.jp\0kaisei.kanagawa.jp\0hachioji.tokyo.jp\0netlify.app\0" +"co.ma\0kherson.ua\0" +"co.ls\0parts\0" +"bolt.hu\0co.me\0" +"co.mg\0" +"party\0" +"homeoffice.gov.uk\0" +"channel\0citadel\0" +"is-a-teacher.com\0sakuraweb.com\0" +"int.in\0" +"co.na\0" +"int.is\0" +"bt.it\0tn.it\0torproject.net\0noho.st\0za.net\0" +"co.mu\0dnshome.de\0" +"o.bg\0co.mw\0review\0si.eu.org\0" +"co.ni\0" +"co.mz\0" +"mragowo.pl\0starachowice.pl\0co.nl\0" +"name.pm\0" +"mo\xc3\xa5reke.no\0modalen.no\0sel.no\0co.no\0" +"chita.aichi.jp\0kyowa.akita.jp\0fujioka.gunma.jp\0kakogawa.hyogo.jp\0higashiyoshino.nara.jp\0itoigawa.niigata.jp\0ashikaga.tochigi.jp\0" +"name.qa\0" +"flog.br\0niteroi.br\0ppg.br\0name.pr\0\xe0\xb9\x80\xe0\xb8\x99\xe0\xb9\x87\xe0\xb8\x95.\xe0\xb9\x84\xe0\xb8\x97\xe0\xb8\xa2\0" +"limited\0*.statics.cloud\0*.on-rancher.cloud\0" +"cruise\0*.hosting.myjino.ru\0" +"co.nz\0" +"co.om\0is-leet.com\0alpha.bounty-full.com\0" +"sh.cn\0" +"int.la\0name.na\0abo.pa\0" +"balsan-suedtirol.it\0olbia-tempio.it\0blogspot.com.mt\0""1.azurestaticapps.net\0" +"dyndns.ddnss.de\0*.triton.zone\0" +"name.mv\0" +"name.ng\0blogspot.com.ng\0" +"name.my\0" +"int.lk\0" +"bydgoszcz.pl\0co.pl\0gliwice.pl\0" +"co.pn\0" +"tinn.no\0" +"shirakawa.fukushima.jp\0izumozaki.niigata.jp\0karasuyama.tochigi.jp\0kiyose.tokyo.jp\0" +"kharkov.ua\0" +"vlog.br\0" +"ac.ae\0erotica.hu\0" +"asn.lv\0" +"co.pw\0" +"writesthisblog.com\0impertrixcdn.com\0" +"*.migration.run\0" +"definima.io\0" +"biz.bb\0" +"ut.us\0" +"ac.at\0bi.it\0cesena-forli.it\0ss.it\0treviso.it\0easypanel.host\0biz.at\0" +"ac.be\0cafe\0" +"int.mv\0" +"d.bg\0int.mw\0sk.eu.org\0" +"int.ni\0" +"biz.az\0" +"co.ro\0" +"*.kitakyushu.jp\0nakai.kanagawa.jp\0kiwa.mie.jp\0izena.okinawa.jp\0fujikawa.shizuoka.jp\0kannami.shizuoka.jp\0akiruno.tokyo.jp\0nirasaki.yamanashi.jp\0" +"riobranco.br\0blogspot.com.tr\0" +"co.rs\0" +"ravendb.cloud\0" +"airforce\0" +"co.rw\0" +"ac.ci\0" +"name.mk\0" +"uy.com\0from-il.com\0is-not-certified.com\0ciscofreak.com\0u2-local.xnbay.com\0" +"ac.cn\0" +"spacekit.io\0" +"ac.cr\0" +"co.st\0" +"guam.gu\0dyn.home-webserver.de\0lenug.su\0" +"co.th\0" +"ac.cy\0biz.cy\0" +"co.sz\0co.tj\0" +"biz.dk\0azimuth.network\0" +"piw.gov.pl\0lezajsk.pl\0" +"co.tm\0" +"aerobatic.aero\0name.jo\0tysfjord.no\0vevelstad.no\0" +"kagawa.jp\0nakadomari.aomori.jp\0hakata.fukuoka.jp\0usui.fukuoka.jp\0yasuda.kochi.jp\0minowa.nagano.jp\0yamagata.nagano.jp\0oyodo.nara.jp\0kumenan.okayama.jp\0yoshida.saitama.jp\0kikugawa.shizuoka.jp\0undo.jp\0" +"co.ua\0" +"recife.br\0" +"cloudsite.builders\0" +"int.pt\0co.tt\0" +"name\0" +"co.ug\0" +"pol.dz\0co.tz\0" +"co.uk\0conn.uk\0" +"wedeploy.io\0" +"grondar.za\0" +"co.us\0gratis\0phx.enscaled.us\0" +"biz.et\0an.it\0ancona.it\0arezzo.it\0milano.it\0pavia.it\0intuit\0dsmynas.net\0" +"co.ve\0progressive\0ezproxy.kuleuven.be\0" +"ngrok.dev\0" +"ru.eu.org\0se.eu.org\0fedorapeople.org\0" +"co.vi\0" +"ac.fj\0biz.fj\0co.uz\0" +"bedzin.pl\0" +"engerdal.no\0raisa.no\0" +"hyogo.jp\0ichinomiya.aichi.jp\0togane.chiba.jp\0honbetsu.hokkaido.jp\0kamoenai.hokkaido.jp\0niikappu.hokkaido.jp\0ayagawa.kagawa.jp\0minamioguni.kumamoto.jp\0usuki.oita.jp\0yonaguni.okinawa.jp\0kuki.saitama.jp\0naruto.tokushima.jp\0nerima.tokyo.jp\0funahashi.toyama.jp\0shunan.yamaguchi.jp\0toyota.yamaguchi.jp\0buyshop.jp\0tonkotsu.jp\0" +"bio.br\0poa.br\0goupile.fr\0" +"int.ru\0mcpe.me\0tcp4.me\0" +"geek.nz\0" +"biz.gl\0" +"s3-ap-northeast-1.amazonaws.com\0hotelwithflight.com\0" +"ac.gn\0" +"actor\0" +"freeddns.us\0" +"piedmont.it\0" +"blogspot.com.uy\0" +"int.tj\0" +"wsa.gov.pl\0call\0" +"flora.no\0malselv.no\0selfip.info\0" +"\xe9\x95\xb7\xe9\x87\x8e.jp\0tobishima.aichi.jp\0toyohashi.aichi.jp\0kunneppu.hokkaido.jp\0kasai.hyogo.jp\0shinjuku.tokyo.jp\0chillout.jp\0" +"dnipropetrovsk.ua\0" +"rehab\0" +"edu.ac\0" +"pol.ht\0ac.id\0biz.id\0int.tt\0" +"science\0" +"edu.af\0" +"\xe6\x97\xb6\xe5\xb0\x9a\0" +"edu.al\0ac.il\0idf.il\0istanbul\0mytabit.co.il\0" +"ac.im\0" +"ac.in\0biz.in\0kaufen\0" +"camp\0" +"edu.ba\0co.za\0" +"edu.ar\0edu.bb\0ac.ir\0brother\0frontdoor\0" +"la.us\0tn.us\0lab.ms\0" +"friulivegiulia.it\0rm.it\0" +"edu.au\0int.ve\0" +"edu.bh\0" +"edu.bi\0" +"edu.az\0edu.bj\0for-more.biz\0" +"football\0" +"edu.bm\0co.zm\0" +"edu.bn\0int.vn\0" +"services.aero\0edu.bo\0hemnes.no\0" +"ac.jp\0\xe5\xb3\xb6\xe6\xa0\xb9.jp\0mobara.chiba.jp\0shinyoshitomi.fukuoka.jp\0aogaki.hyogo.jp\0minamata.kumamoto.jp\0suwa.nagano.jp\0hatogaya.saitama.jp\0miyoshi.saitama.jp\0hachijo.tokyo.jp\0oe.yamagata.jp\0a.run.app\0" +"edu.br\0" +"edu.bs\0\xd8\xaa\xd9\x88\xd9\x86\xd8\xb3\0" +"edu.bt\0keliweb.cloud\0" +"ac.ke\0z.se\0" +"co.zw\0" +"edu.ci\0biz.ki\0" +"edu.bz\0" +"edu.cn\0gz.cn\0" +"edu.co\0" +"ac.kr\0" +"cc.vt.us\0lib.gu.us\0" +"edgeapp.net\0" +"edu.cu\0georgia.su\0" +"edu.cv\0" +"edu.cw\0cn.eu.org\0read-books.org\0" +"ac.lk\0" +"edu.dm\0" +"edu.do\0steigen.no\0" +"sobetsu.hokkaido.jp\0tohma.hokkaido.jp\0" +"ac.ma\0\xd0\xbe\xd0\xb1\xd1\x80.\xd1\x81\xd1\x80\xd0\xb1\0" +"bbs.tr\0gov.nc.tr\0" +"edu.ec\0ac.ls\0biz.ls\0productions\0" +"edu.ee\0ac.me\0" +"edu.eg\0" +"edu.dz\0" +"hostedpi.com\0geekgalaxy.com\0" +"cust.prod.thingdust.io\0" +"soccer\0\xe9\x9b\x86\xe5\x9b\xa2\0" +"edu.es\0k12.wy.us\0" +"edu.et\0valdaosta.it\0u.channelsdvr.net\0cloud.jelastic.open.tim.it\0jls-sto1.elastx.net\0no-ip.net\0" +"ac.mu\0care\0" +"biz.mv\0" +"ac.mw\0biz.mw\0dyndns.org\0from-me.org\0" +"xy.ax\0" +"biz.my\0ac.ni\0biz.ni\0\xe5\xa4\xa9\xe4\xb8\xbb\xe6\x95\x99\0" +"ac.mz\0" +"edu.fm\0" +"charter.aero\0conference.aero\0hapmir.no\0hvaler.no\0lunner.no\0masfjorden.no\0laakesvuemie.no\0vestv\xc3\xa5g\xc3\xb8y.no\0" +"takahama.aichi.jp\0futtsu.chiba.jp\0ashibetsu.hokkaido.jp\0nakasatsunai.hokkaido.jp\0yamashina.kyoto.jp\0hiraya.nagano.jp\0tokushima.tokushima.jp\0theshop.jp\0" +"casa\0pramerica\0" +"jampa.br\0pvh.br\0biz.nr\0" +"cars\0rentals\0" +"edu.gd\0s3.nl-ams.scw.cloud\0" +"edu.ge\0o.se\0case\0" +"\xe5\x98\x89\xe9\x87\x8c\xe5\xa4\xa7\xe9\x85\x92\xe5\xba\x97\0" +"edu.gh\0cash\0" +"go.ci\0edu.gi\0navy\0" +"ac.nz\0" +"edu.gl\0" +"s3-ap-south-1.amazonaws.com\0static.observableusercontent.com\0myshopify.com\0" +"edu.gn\0fashion\0" +"edu.gp\0" +"ac.pa\0" +"go.cr\0edu.gr\0" +"cc.vi.us\0zappos\0" +"edu.gt\0cloudfront.net\0" +"edu.gu\0loginline.site\0" +"edu.gy\0" +"edu.hk\0biz.pk\0" +"biz.pl\0" +"edu.hn\0" +"oslo.no\0eigersund.no\0nore-og-uvdal.no\0vaga.no\0" +"funabashi.chiba.jp\0chikuho.fukuoka.jp\0tagawa.fukuoka.jp\0furudono.fukushima.jp\0moriya.ibaraki.jp\0sagamihara.kanagawa.jp\0yamaga.kumamoto.jp\0akaiwa.okayama.jp\0kawanishi.yamagata.jp\0oshima.yamaguchi.jp\0" +"biz.pr\0ac.pr\0" +"edu.ht\0" +"extraspace\0" +"*.elb.amazonaws.com\0is-into-cars.com\0wpenginepowered.com\0yolasite.com\0" +"edu.in\0" +"edu.iq\0" +"edu.is\0dni.us\0" +"edu.it\0emr.it\0in.net\0cloudfunctions.net\0" +"byen.site\0" +"8.bg\0cy.eu.org\0" +"eco.bj\0" +"myspreadshop.nl\0" +"edu.jo\0stavern.no\0myspreadshop.no\0" +"iizuka.fukuoka.jp\0hirono.fukushima.jp\0katashina.gunma.jp\0kaita.hiroshima.jp\0bibai.hokkaido.jp\0otaru.hokkaido.jp\0sukumo.kochi.jp\0uji.kyoto.jp\0yono.saitama.jp\0himi.toyama.jp\0" +"eco.br\0mg.leg.br\0" +"ac.rs\0" +"us.reclaim.cloud\0" +"ac.se\0d.se\0ac.ru\0msk.ru\0" +"edu.kg\0ac.rw\0" +"rich\0" +"edu.ki\0" +"\xe5\xae\xb6\xe9\x9b\xbb\0" +"edu.km\0is-a-libertarian.com\0myqnapcloud.com\0" +"gd.cn\0edu.kn\0" +"edu.kp\0" +"edu.la\0" +"edu.lb\0" +"edu.lc\0biz.ss\0kids.us\0cc.ct.us\0cc.ma.us\0" +"jelastic.saveincloud.net\0kinghost.net\0" +"kurgan.su\0msk.su\0" +"edu.kw\0training\0cz.eu.org\0diskstation.org\0" +"ac.th\0" +"edu.ky\0" +"edu.kz\0ac.sz\0ac.tj\0biz.tj\0for-better.biz\0" +"edu.lk\0" +"jgora.pl\0myspreadshop.pl\0" +"production.aero\0beardu.no\0lier.no\0" +"\xe5\x9f\xbc\xe7\x8e\x89.jp\0kanna.gunma.jp\0hamura.tokyo.jp\0katsuragi.wakayama.jp\0" +"\xd8\xa7\xd9\x84\xd8\xac\xd8\xb2\xd8\xa7\xd8\xa6\xd8\xb1\0biz.ua\0" +"edu.lr\0biz.tr\0pol.tr\0" +"edu.ls\0instances.spawn.cc\0" +"go.id\0biz.tt\0" +"edu.me\0baidu\0insurance\0" +"edu.lv\0" +"edu.mg\0ac.ug\0" +"edu.ly\0" +"ac.tz\0" +"edu.mk\0ac.uk\0" +"edu.ml\0" +"firewall-gateway.com\0" +"edu.mn\0" +"edu.mo\0physio\0" +"barcelona\0" "career\0" -"bari.it\0final\0" +"edu.ms\0k12.nh.us\0mus.mi.us\0vegas\0" +"cesenaforl\xc3\xac.it\0go.it\0edu.mt\0adobeio-static.net\0*.in.futurecms.at\0fra1-de.cloudjiffy.net\0co.krd\0myspreadshop.it\0" +"*.frusky.de\0" +"edu.mv\0" +"edu.mw\0edu.ng\0endofinternet.org\0is-a-linux-user.org\0dk.eu.org\0" +"edu.mx\0" +"edu.my\0edu.ni\0" +"edu.mz\0" +"skoczow.pl\0" +"ac.vn\0biz.vn\0bayern\0" +"r\xc3\xb8mskog.no\0skjervoy.no\0sn\xc3\xa5""ase.no\0s\xc3\xb8mna.no\0vefsn.no\0" +"go.jp\0niihama.ehime.jp\0nanae.hokkaido.jp\0bitter.jp\0rgr.jp\0telebit.app\0" +"edu.nr\0" +"go.ke\0" +"biz.wf\0" +"us.platform.sh\0" +"of.by\0" +"edu.om\0dontexist.com\0is-an-artist.com\0" +"ghost.io\0" +"edu.pa\0ngrok.pizza\0" +"fi.cr\0go.kr\0" +"lib.ny.us\0" +"aosta-valley.it\0trentino-a-adige.it\0nuoro.it\0mysecuritycamera.net\0" +"edu.pe\0cloud66.zone\0jele.site\0" +"edu.pf\0" +"edu.ph\0" +"edu.pk\0" +"edu.pl\0opole.pl\0" +"edu.pn\0" +"design.aero\0bo.nordland.no\0hammarfeasta.no\0royken.no\0" +"\xe9\x9d\x92\xe6\xa3\xae.jp\0hiroo.hokkaido.jp\0shinshinotsu.hokkaido.jp\0toyoura.hokkaido.jp\0daigo.ibaraki.jp\0ogawa.ibaraki.jp\0hamada.shimane.jp\0" +"edu.qa\0\xd1\x80\xd1\x83\xd1\x81\0ie.ua\0" +"cuiaba.br\0maringa.br\0edu.pr\0" +"edu.ps\0" +"edu.pt\0madrid\0" +"dvag\0" +"edu.py\0" +"glug.org.uk\0" +"s3.dualstack.ap-northeast-2.amazonaws.com\0mex.com\0rhcloud.com\0" +"delhi.in\0anquan\0" +"drud.io\0" +"ac.za\0" +"properties\0pointto.us\0" +"messina.it\0pa.it\0ownip.net\0" +"de.eu.org\0za.org\0" +"blogsite.xyz\0" +"pisz.pl\0" +"ac.zm\0biz.zm\0" +"orkanger.no\0bokn.no\0fet.no\0finn\xc3\xb8y.no\0h\xc3\xb8yanger.no\0" +"matsuno.ehime.jp\0tsuiki.fukuoka.jp\0mikasa.hokkaido.jp\0kagoshima.kagoshima.jp\0funagata.yamagata.jp\0yamanashi.yamanashi.jp\0\xd0\xbc\xd0\xbe\xd1\x81\xd0\xba\xd0\xb2\xd0\xb0\0" +"edu.sa\0" +"etc.br\0edu.sb\0" +"edu.rs\0edu.sc\0fantasyleague.cc\0" +"edu.sd\0gift\0" +"edu.ru\0" +"edu.sg\0ac.zw\0" +"emerck\0" +"edu.sl\0" +"is-a-designer.com\0""4u.com\0" +"edu.sn\0" +"edu.so\0" +"edu.ss\0express\0" +"padova.it\0trieste.it\0udine.it\0edu.st\0wpmudev.host\0" +"vote\0g\xc3\xbcnstigliefern.de\0" +"edu.sv\0" +"edu.sy\0kapsi.fi\0" +"edu.tj\0" +"zarow.pl\0" +"edu.tm\0" +"edu.to\0voto\0" +"hachinohe.aomori.jp\0owani.aomori.jp\0tamakawa.fukushima.jp\0takasaki.gunma.jp\0nemuro.hokkaido.jp\0asahi.ibaraki.jp\0isehara.kanagawa.jp\0kamisato.saitama.jp\0supersale.jp\0hippy.jp\0" +"edu.ua\0kropyvnytskyi.ua\0" +"df.gov.br\0edu.tr\0" +"edu.tt\0*.sensiosite.cloud\0urown.cloud\0" +"go.pw\0edu.tw\0" +"email\0" +"vfs.cloud9.eu-west-2.amazonaws.com\0" +"goodyear\0repair\0" +"edu.vc\0" +"catanzaro.it\0fi.it\0tempio-olbia.it\0barclaycard\0" +"edu.ve\0cbre\0of.je\0syno-ds.de\0" +"edu.uy\0" +"mielec.pl\0" +"edu.vn\0" +"gs.ah.no\0grane.no\0holtalen.no\0" +"wakayama.jp\0kitaakita.akita.jp\0otama.fukushima.jp\0niki.hokkaido.jp\0kiho.mie.jp\0saiki.oita.jp\0nishi.osaka.jp\0deci.jp\0" +"mp.br\0" +"barsy.support\0" +"edu.vu\0myspreadshop.se\0" +"s3.dualstack.ca-central-1.amazonaws.com\0" +"\xe5\x80\x8b\xe4\xba\xba.\xe9\xa6\x99\xe6\xb8\xaf\0" +"cc.as.us\0edu.ws\0bnpparibas\0" +"sicily.it\0ric.jelastic.vps-host.net\0" +"balashov.su\0" +"go.th\0" +"go.tj\0" +"\xe6\x95\x99\xe8\x82\xb2.hk\0gop.pk\0" +"prochowice.pl\0poniatowa.pl\0" +"bearalvahki.no\0" +"yamagata.jp\0kyowa.hokkaido.jp\0kouyama.kagoshima.jp\0kumiyama.kyoto.jp\0tank.jp\0" +"pl.ua\0aaa\0" +"rj.gov.br\0sampa.br\0" +"nom.ad\0exposed\0" +"edu.ye\0vp4.me\0" +"nom.ag\0go.ug\0" +"go.tz\0" +"myspreadshop.co.uk\0" +"s3.dualstack.us-east-1.amazonaws.com\0" +"ws.na\0edu.za\0" +"abb\0" +"abc\0d.gv.vc\0" +"bulsan-s\xc3\xbc""dtirol.it\0en.it\0democrat\0" +"armenia.su\0" +"ca.eu.org\0" +"edu.zm\0" +"of.no\0kraanghke.no\0krodsherad.no\0rahkkeravju.no\0kvits\xc3\xb8y.no\0naustdal.no\0ilovecollege.info\0" +"takinoue.hokkaido.jp\0shirosato.ibaraki.jp\0gyokuto.kumamoto.jp\0ohkura.yamagata.jp\0" +"africa\0" +"cya.gg\0" +"gallery\0" +"weatherchannel\0" +"arts.co\0nom.co\0aco\0yahoo\0" +"gwangju.kr\0imdb\0" +"\xd9\x83\xd8\xa7\xd8\xab\xd9\x88\xd9\x84\xd9\x8a\xd9\x83\0" +"a.ssl.fastly.net\0" +"cyon.site\0" +"flt.cloud.muni.cz\0" +"tourism.tn\0" +"association.aero\0revista.bo\0os\xc3\xb8yro.no\0s\xc3\xb8r-fron.no\0" +"hisayama.fukuoka.jp\0sekigahara.gifu.jp\0hitachinaka.ibaraki.jp\0aya.miyazaki.jp\0hasami.nagasaki.jp\0kitahata.saga.jp\0\xe6\xbe\xb3\xe9\x96\x80\0clerkstage.app\0" +"\xd1\x81\xd1\x80\xd0\xb1\0" +"ads\0" +"aeg\0" +"barsyonline.co.uk\0" +"telebit.io\0" +"\xe0\xb4\xad\xe0\xb4\xbe\xe0\xb4\xb0\xe0\xb4\xa4\xe0\xb4\x82\0tatar\0" +"nom.es\0pa.us\0drud.us\0" +"chieti.it\0gets-it.net\0" +"sa.edu.au\0" +"boldlygoingnowhere.org\0is-a-candidate.org\0tuxfamily.org\0" +"hockey\0" +"afl\0" +"air-surveillance.aero\0modelling.aero\0grue.no\0" +"fuso.aichi.jp\0futaba.fukushima.jp\0minokamo.gifu.jp\0kawajima.saitama.jp\0nachikatsuura.wakayama.jp\0" +"pub.sa\0vinnica.ua\0" +"belem.br\0bmd.br\0far.br\0palmas.br\0vix.br\0nom.fr\0" +"brussels\0" +"180r.com\0" +"tw.cn\0" +"mango\0" +"pioneer\0" +"kerryproperties\0" +"emilia-romagna.it\0valleaosta.it\0modena.it\0" +"qld.gov.au\0airkitapps.eu\0sellfy.store\0" +"*.gateway.dev\0" +"cd.eu.org\0" +"slask.pl\0krasnik.pl\0" +"rennebu.no\0" +"kasuga.fukuoka.jp\0yokawa.hyogo.jp\0suifu.ibaraki.jp\0yamato.kanagawa.jp\0doshi.yamanashi.jp\0" +"lifeinsurance\0" +"aig\0kpmg\0" +"vfs.cloud9.ap-northeast-1.amazonaws.com\0jpn.com\0kozow.com\0" +"me.in\0" +"nv.us\0myspreadshop.es\0" +"lu.it\0me.it\0vb.it\0" +"vic.edu.au\0phone\0" +"myspreadshop.fi\0" +"lukow.pl\0" +"\xe4\xb8\xad\xe5\x9b\xbd\0" +"stj\xc3\xb8rdalshalsen.no\0holt\xc3\xa5len.no\0kongsvinger.no\0ringebu.no\0no-ip.info\0" +"toyama.jp\0nanmoku.gunma.jp\0shikaoi.hokkaido.jp\0tsukigata.hokkaido.jp\0kawanishi.hyogo.jp\0sakawa.kochi.jp\0yamato.kumamoto.jp\0komagane.nagano.jp\0tsuga.tochigi.jp\0schoolbus.jp\0" +"myspreadshop.fr\0" +"twmail.cc\0" +"me.ke\0reise\0space\0" +"\xe6\xbe\xb3\xe9\x97\xa8\0" +"\xe4\xb8\xad\xe5\x9c\x8b\0" +"nom.km\0s3.ca-central-1.amazonaws.com\0googleapis.com\0" +"christmas\0" +"ascoli-piceno.it\0akamaiorigin.net\0mydissent.net\0" +"is-very-evil.org\0" +"\xe7\xbb\x84\xe7\xbb\x87.hk\0" +"langevag.no\0eidfjord.no\0t\xc3\xb8nsberg.no\0veg\xc3\xa5rshei.no\0groks-the.info\0" +"kamikawa.hyogo.jp\0toride.ibaraki.jp\0misato.miyagi.jp\0sakae.nagano.jp\0bungotakada.oita.jp\0yomitan.okinawa.jp\0kozagawa.wakayama.jp\0" +"quebec\0scrapping.cc\0" +"primetel.cloud\0nodes.k8s.pl-waw.scw.cloud\0" +"myspreadshop.ie\0" +"nom.mg\0\xe7\xb5\x84\xe7\xb9\x94.tw\0" +"\xda\x80\xd8\xa7\xd8\xb1\xd8\xaa\0" +"immo\0fh-muenster.io\0" +"nom.nc\0homes\0lanxess\0*.advisor.ws\0" +"massacarrara.it\0salerno.it\0adobeioruntime.net\0myspreadshop.at\0" +"sa.gov.au\0arts.ve\0myspreadshop.be\0" +"x.bg\0pimienta.org\0cloud.fedoraproject.org\0" +"nom.ni\0blackfriday\0richardli\0" +"mup.gov.pl\0pruszkow.pl\0" +"sandnessjoen.no\0n\xc3\xa1vuotna.no\0nordre-land.no\0" +"seiyo.ehime.jp\0shirahama.wakayama.jp\0higashine.yamagata.jp\0usercontent.jp\0parallel.jp\0" +"edeka\0myspreadshop.ca\0" +"arq.br\0" +"plesk.page\0" +"myspreadshop.ch\0" +"anz\0" +"aol\0" +"from-ut.com\0" +"*.moonscale.io\0" +"nom.pa\0" +"friuli-vegiulia.it\0tuscany.it\0" +"nom.pe\0gripe\0g\xc3\xbcnstigbestellen.de\0novecore.site\0myspreadshop.de\0" +"myspreadshop.dk\0" +"nom.pl\0tourism.pl\0" +"photo\0rdv.to\0" +"iwate.iwate.jp\0kiyokawa.kanagawa.jp\0moroyama.saitama.jp\0inagi.tokyo.jp\0app\0" +"\xec\x82\xbc\xec\x84\xb1\0" +"aparecida.br\0rr.gov.br\0freeboxos.fr\0" +"origins\0winners\0" +"ponpes.id\0" +"webview-assets.cloud9.ap-northeast-3.amazonaws.com\0" +"bar\0" +"ann-arbor.mi.us\0bbc\0cruises\0""0e.vc\0" +"br.it\0cb.it\0bitbridge.net\0fr-1.paas.massivegrid.net\0" +"nom.re\0" +"m.bg\0" +"tourism.bj\0zapto.xyz\0" +"froland.no\0r\xc3\xa6lingen.no\0arts.ro\0nom.ro\0\xe0\xa4\xa8\xe0\xa5\x87\xe0\xa4\x9f\0" +"toki.gifu.jp\0esashi.hokkaido.jp\0kuriyama.hokkaido.jp\0kadogawa.miyazaki.jp\0ueda.nagano.jp\0sakata.yamagata.jp\0*.developer.app\0privatelink.snowflake.app\0" +"rs.gov.br\0sc.gov.br\0gru.br\0tec.br\0tmp.br\0\xe0\xb8\x98\xe0\xb8\xb8\xe0\xb8\xa3\xe0\xb8\x81\xe0\xb8\xb4\xe0\xb8\x88.\xe0\xb9\x84\xe0\xb8\x97\xe0\xb8\xa2\0" +"art\0bbt\0fnc.fr-par.scw.cloud\0" +"dagestan.ru\0" +"bcg\0" +"directory\0" +"servesarcasm.com\0" +"bcn\0" +"me.so\0" +"daegu.kr\0" +"me.ss\0me.tc\0" +"circle\0dagestan.su\0mintere.site\0" +"mysecuritycamera.org\0" +"arvo.network\0" +"oirm.gov.pl\0podlasie.pl\0wloclawek.pl\0" +"nom.tm\0" +"natural.bo\0fjell.no\0frogn.no\0loten.no\0" +"tsuno.kochi.jp\0koryo.nara.jp\0" +"zaporizhzhia.ua\0cx.ua\0\xd0\xbc\xd0\xb8\xd1\x80.\xd1\x80\xd1\x83\xd1\x81\0" +"nodes.k8s.nl-ams.scw.cloud\0" +"sci.eg\0translate.goog\0" +"me.tz\0" +"me.uk\0" +"demo.datadetect.com\0homelinux.com\0framercanvas.com\0" +"berlin\0" +"tur.ar\0" +"me.us\0business\0" +"bg.it\0ta.it\0bet\0boomla.net\0" +"nom.ve\0compare\0" +"arts.nf\0" +"b.bg\0wang\0hk.org\0" +"szkola.pl\0" +"crew.aero\0info\0herad.no\0bronnoy.no\0finnoy.no\0lind\xc3\xa5s.no\0pors\xc3\xa1\xc5\x8bgu.no\0sn\xc3\xa5sa.no\0" +"gunma.jp\0yatomi.aichi.jp\0tomisato.chiba.jp\0tatsuno.hyogo.jp\0uchinomi.kagawa.jp\0nankoku.kochi.jp\0nishihara.kumamoto.jp\0mihama.mie.jp\0hannan.osaka.jp\0shimonoseki.yamaguchi.jp\0" +"cherkasy.ua\0" +"b.br\0tur.br\0" +"partners\0solutions\0" +"fhsk.se\0college\0me.vu\0" +"from-ct.com\0from-nj.com\0herokuapp.com\0caracal.mythic-beasts.com\0" +"axa\0" +"cc.ok.us\0lib.al.us\0lib.ia.us\0aws\0" +"cloudaccess.net\0" +"fuettertdasnetz.de\0" +"pages.dev\0" +"infiniti\0" +"beskidy.pl\0" +"birkenes.no\0leka.no\0tolga.no\0v\xc3\xa5ler.\xc3\xb8stfold.no\0" +"shiga.jp\0oga.akita.jp\0ibigawa.gifu.jp\0omi.nagano.jp\0" +"rn.gov.br\0" +"clinic\0flights\0" +"bid\0" +"lib.ee\0" +"ravendb.community\0" +"copro.uk\0" +"ap-southeast-1.elasticbeanstalk.com\0pythonanywhere.com\0" +"bio\0radio\0" +"nom.za\0" +"hoteles\0" +"al.it\0balsan.it\0land\0" +"home.dyndns.org\0" +"biz\0" +"karpacz.pl\0olkusz.pl\0" +"gliding.aero\0skydiving.aero\0fuossko.no\0luster.no\0" +"\xe6\x9d\xb1\xe4\xba\xac.jp\0" +"app.br\0ro.gov.br\0" +"nalchik.ru\0" +"company\0" +"hotel.tz\0" +"\xd7\xa6\xd7\x94\xd7\x9c.\xd7\x99\xd7\xa9\xd7\xa8\xd7\x90\xd7\x9c\0" +"est-a-la-maison.com\0from-id.com\0is-a-liberal.com\0" +"vaporcloud.io\0" +"in-addr.arpa\0ing.pa\0honda\0" +"foggia.it\0now-dns.net\0" +"nalchik.su\0" +"deno-staging.dev\0" +"doomdns.org\0" +"earth\0" +"\xe7\xae\x87\xe4\xba\xba.hk\0" +"olecko.pl\0" +"\xe5\x8d\x83\xe8\x91\x89.jp\0imabari.ehime.jp\0rebun.hokkaido.jp\0tono.iwate.jp\0futsu.nagasaki.jp\0kamo.niigata.jp\0ginowan.okinawa.jp\0yuza.yamagata.jp\0fireweb.app\0oops.jp\0" +"s3.pl-waw.scw.cloud\0" +"utazas.hu\0" +"is-a-hunter.com\0api.stdlib.com\0" +"broker\0" +"bms\0" +"eero.online\0" +"bmw\0" +"sf.no\0al.no\0g\xc3\xa1\xc5\x8bgaviika.no\0muos\xc3\xa1t.no\0" +"\xe5\xb1\xb1\xe5\x8f\xa3.jp\0ikawa.akita.jp\0shintoku.hokkaido.jp\0wassamu.hokkaido.jp\0kuji.iwate.jp\0sumoto.kumamoto.jp\0shioya.tochigi.jp\0kosuge.yamanashi.jp\0versus.jp\0vivian.jp\0crap.jp\0" +"bib.br\0emp.br\0" +"media.hu\0x.se\0""123sait.ru\0" +"bom\0is-an-actress.com\0*.quipelements.com\0" +"gx.cn\0" +"boo\0" +"\xd1\x83\xd0\xba\xd1\x80\0app.gp\0" +"cc.ne.us\0" +"bot\0" +"moscow\0ch.eu.org\0" +"box\0faith\0" +"\xe7\xb5\x84\xe7\xb9\x94.hk\0" +"bytom.pl\0" +"hob\xc3\xb8l.no\0" +"yanagawa.fukuoka.jp\0showa.gunma.jp\0makurazaki.kagoshima.jp\0mashiki.kumamoto.jp\0kameoka.kyoto.jp\0kawasaki.miyagi.jp\0unnan.shimane.jp\0kawazu.shizuoka.jp\0ohtawara.tochigi.jp\0arakawa.tokyo.jp\0encr.app\0" +"pharmacien.fr\0cab\0" +"kred\0" +"\xd0\xba\xd0\xb0\xd1\x82\xd0\xbe\xd0\xbb\xd0\xb8\xd0\xba\0" +"hosp.uk\0" "cal\0" "cam\0" -"au.eu.org\0be.eu.org\0" -"\xec\x82\xbc\xec\x84\xb1\0" -"cba\0" +"\xe4\xbf\xa1\xe6\x81\xaf\0webthings.io\0" +"in.na\0cba\0" "car\0" -"*.banzai.cloud\0" -"cat\0cruise\0" -"tr.no\0" -"notodden.no\0pramerica\0" -"g\xc3\xbcnstigbestellen.de\0" -"allfinanz\0" -"tsukiyono.gunma.jp\0" -"kanmaki.nara.jp\0cc.ms.us\0cc.nc.us\0cbn\0vfs.cloud9.us-west-1.amazonaws.com\0" -"fm.br\0reggio-emilia.it\0gouv.ml\0" -"tsurugi.ishikawa.jp\0skedsmo.no\0cc.az.us\0" -"cbs\0lamborghini\0" -"rs.gov.br\0sc.gov.br\0hanawa.fukushima.jp\0" -"kagoshima.jp\0" -"mitsuke.niigata.jp\0" -"ogawara.miyagi.jp\0kashiwazaki.niigata.jp\0land\0uk.com\0" -"kamogawa.chiba.jp\0rakkestad.no\0" -"fhsk.se\0" -"kamigori.hyogo.jp\0" -"web.tj\0" -"asti.it\0" -"channel\0" -"verse.jp\0tn.oxa.cloud\0" -"cloud.nospamproxy.com\0" -"karlsoy.no\0web.tr\0s3-eu-west-2.amazonaws.com\0" -"vgs.no\0" -"flora.no\0" -"webhop.net\0" -"filegear-au.me\0" -"wpmudev.host\0" -"brussels\0" -"xihuan\0" -"turek.pl\0" +"cupcake.is\0" +"cat\0crotone.it\0" +"oz.au\0virtual-user.de\0" +"in.ni\0" +"hotel.lk\0" +"cbn\0" +"aa.no\0mj\xc3\xb8ndalen.no\0spjelkavik.no\0lyngdal.no\0omasvuotna.no\0tysnes.no\0" +"omotego.fukushima.jp\0tamamura.gunma.jp\0higashihiroshima.hiroshima.jp\0takamatsu.kagawa.jp\0ginoza.okinawa.jp\0aarp\0" +"cherkassy.ua\0" +"ba.gov.br\0manaus.br\0" +"cbs\0" +"m.se\0forgot.her.name\0" +"boutir.com\0from-wy.com\0dojin.com\0" +"per.la\0" +"hs.kr\0" +"\xd8\xa8\xd9\x8a\xd8\xaa\xd9\x83\0" +"consulado.st\0" +"oracle\0" +"polkowice.pl\0wlocl.pl\0" +"logistics.aero\0medicina.bo\0h\xc3\xb8nefoss.no\0farsund.no\0kvam.no\0avocat.pro\0" +"\xe7\xa6\x8f\xe5\xb2\xa1.jp\0seika.kyoto.jp\0tsuru.yamanashi.jp\0flier.jp\0" +"rv.ua\0" +"londrina.br\0\xd8\xb9\xd8\xb1\xd8\xa7\xd9\x82\0" +"its.me\0" +"raffleentry.org.uk\0" +"dattorelay.com\0paas.hosted-by-previder.com\0" +"ceo\0id.forgerock.io\0" }; -static constexpr quint32 tldChunks[tldChunkCount] = {65520, 106707}; +static constexpr quint32 tldChunks[tldChunkCount] = {65476, 106762}; QT_END_NAMESPACE From aece9fab015260e359cadf849f3f6c8488d0d990 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Tue, 13 Jun 2023 11:37:13 +0200 Subject: [PATCH 024/151] RIP QBasicMutexLocker This was used as a work-around for Q5MutexLocker's UB downcasting QBasicMutex to QMutex, and for some unspecified performance improvements. Now that Q6MutexLocker is a template, the two are almost token-by-token identical, so we can remove this work-around and use QMutexLocker directly. Partially reverts aea500d5d76864bb1a3918e338ca6806e1766e41. Change-Id: I57ef5c53999869aa3454fbbaad884c1d18591b2a Reviewed-by: Fabian Kosmale Reviewed-by: Thiago Macieira (cherry picked from commit 8d39b2165596f0aaae0e5841eb4c849cf4ee1bb0) Reviewed-by: Qt Cherry-pick Bot --- src/corelib/kernel/qobject.cpp | 24 ++++++++--------- src/corelib/thread/qorderedmutexlocker_p.h | 31 ---------------------- 2 files changed, 12 insertions(+), 43 deletions(-) diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp index b62dda6cfd0..1a6896ea227 100644 --- a/src/corelib/kernel/qobject.cpp +++ b/src/corelib/kernel/qobject.cpp @@ -261,7 +261,7 @@ bool QObjectPrivate::isSender(const QObject *receiver, const char *signal) const ConnectionData *cd = connections.loadRelaxed(); if (signal_index < 0 || !cd) return false; - QBasicMutexLocker locker(signalSlotLock(q)); + QMutexLocker locker(signalSlotLock(q)); if (signal_index < cd->signalVectorCount()) { const QObjectPrivate::Connection *c = cd->signalVector.loadRelaxed()->at(signal_index).first.loadRelaxed(); @@ -301,7 +301,7 @@ QObjectList QObjectPrivate::senderList() const QObjectList returnValue; ConnectionData *cd = connections.loadRelaxed(); if (cd) { - QBasicMutexLocker locker(signalSlotLock(q_func())); + QMutexLocker locker(signalSlotLock(q_func())); for (Connection *c = cd->senders; c; c = c->next) returnValue << c->sender; } @@ -1046,7 +1046,7 @@ QObject::~QObject() } QBasicMutex *signalSlotMutex = signalSlotLock(this); - QBasicMutexLocker locker(signalSlotMutex); + QMutexLocker locker(signalSlotMutex); // disconnect all receivers int receiverCount = cd->signalVectorCount(); @@ -1379,7 +1379,7 @@ bool QObject::event(QEvent *e) QAbstractMetaCallEvent *mce = static_cast(e); if (!d_func()->connections.loadRelaxed()) { - QBasicMutexLocker locker(signalSlotLock(this)); + QMutexLocker locker(signalSlotLock(this)); d_func()->ensureConnectionData(); } QObjectPrivate::Sender sender(this, const_cast(mce->sender()), mce->signalId()); @@ -2491,7 +2491,7 @@ QObject *QObject::sender() const { Q_D(const QObject); - QBasicMutexLocker locker(signalSlotLock(this)); + QMutexLocker locker(signalSlotLock(this)); QObjectPrivate::ConnectionData *cd = d->connections.loadRelaxed(); if (!cd || !cd->currentSender) return nullptr; @@ -2533,7 +2533,7 @@ int QObject::senderSignalIndex() const { Q_D(const QObject); - QBasicMutexLocker locker(signalSlotLock(this)); + QMutexLocker locker(signalSlotLock(this)); QObjectPrivate::ConnectionData *cd = d->connections.loadRelaxed(); if (!cd || !cd->currentSender) return -1; @@ -2598,7 +2598,7 @@ int QObject::receivers(const char *signal) const } QObjectPrivate::ConnectionData *cd = d->connections.loadRelaxed(); - QBasicMutexLocker locker(signalSlotLock(this)); + QMutexLocker locker(signalSlotLock(this)); if (cd && signal_index < cd->signalVectorCount()) { const QObjectPrivate::Connection *c = cd->signalVector.loadRelaxed()->at(signal_index).first.loadRelaxed(); while (c) { @@ -2645,7 +2645,7 @@ bool QObject::isSignalConnected(const QMetaMethod &signal) const signalIndex += QMetaObjectPrivate::signalOffset(signal.mobj); - QBasicMutexLocker locker(signalSlotLock(this)); + QMutexLocker locker(signalSlotLock(this)); return d->isSignalConnected(signalIndex, true); } @@ -3559,7 +3559,7 @@ bool QMetaObjectPrivate::disconnect(const QObject *sender, QObject *s = const_cast(sender); QBasicMutex *senderMutex = signalSlotLock(sender); - QBasicMutexLocker locker(senderMutex); + QMutexLocker locker(senderMutex); QObjectPrivate::ConnectionData *scd = QObjectPrivate::get(s)->connections.loadRelaxed(); if (!scd) @@ -3786,7 +3786,7 @@ static void queued_activate(QObject *sender, int signal, QObjectPrivate::Connect while (argumentTypes[nargs - 1]) ++nargs; - QBasicMutexLocker locker(signalSlotLock(c->receiver.loadRelaxed())); + QMutexLocker locker(signalSlotLock(c->receiver.loadRelaxed())); QObject *receiver = c->receiver.loadRelaxed(); if (!receiver) { // the connection has been disconnected before we got the lock @@ -3927,7 +3927,7 @@ void doActivate(QObject *sender, int signal_index, void **argv) QSemaphore semaphore; { - QBasicMutexLocker locker(signalSlotLock(receiver)); + QMutexLocker locker(signalSlotLock(receiver)); if (!c->isSingleShot && !c->receiver.loadAcquire()) continue; QMetaCallEvent *ev = c->isSlotObject ? @@ -4253,7 +4253,7 @@ void QObject::dumpObjectInfo() const objectName().isEmpty() ? "unnamed" : objectName().toLocal8Bit().data()); Q_D(const QObject); - QBasicMutexLocker locker(signalSlotLock(this)); + QMutexLocker locker(signalSlotLock(this)); // first, look for connections where this object is the sender qDebug(" SIGNALS OUT"); diff --git a/src/corelib/thread/qorderedmutexlocker_p.h b/src/corelib/thread/qorderedmutexlocker_p.h index 6ba3750fc72..6fb19e9a481 100644 --- a/src/corelib/thread/qorderedmutexlocker_p.h +++ b/src/corelib/thread/qorderedmutexlocker_p.h @@ -152,35 +152,6 @@ private: bool locked; }; -class QBasicMutexLocker -{ -public: - inline explicit QBasicMutexLocker(QBasicMutex *m) QT_MUTEX_LOCK_NOEXCEPT - : m(m), isLocked(true) - { - m->lock(); - } - inline ~QBasicMutexLocker() { if (isLocked) unlock(); } - - inline void unlock() noexcept - { - isLocked = false; - m->unlock(); - } - - inline void relock() QT_MUTEX_LOCK_NOEXCEPT - { - isLocked = true; - m->lock(); - } - -private: - Q_DISABLE_COPY(QBasicMutexLocker) - - QBasicMutex *m; - bool isLocked; -}; - #else class QOrderedMutexLocker @@ -199,8 +170,6 @@ public: static bool relock(QBasicMutex *, QBasicMutex *) { return false; } }; -using QBasicMutexLocker = QMutexLocker; - #endif From e08c4ba0f136627935f2f32ccbb8572b5e620e03 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Tue, 13 Jun 2023 11:10:25 +0200 Subject: [PATCH 025/151] tst_QProperty: fix -Wsign-compare Amends cb30e45b9a800c6ad9cdfb446a20b6a6e8efbe71. Change-Id: I53c32a44c642a931038c7c95de903eafc0d0f6b9 Reviewed-by: Fabian Kosmale (cherry picked from commit 0ffb5c79db977c8dc892be6f4651d57ad5a5ed0e) Reviewed-by: Ulf Hermann --- tests/auto/corelib/kernel/qproperty/tst_qproperty.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/auto/corelib/kernel/qproperty/tst_qproperty.cpp b/tests/auto/corelib/kernel/qproperty/tst_qproperty.cpp index 63cf9c28174..b8041238450 100644 --- a/tests/auto/corelib/kernel/qproperty/tst_qproperty.cpp +++ b/tests/auto/corelib/kernel/qproperty/tst_qproperty.cpp @@ -1503,7 +1503,7 @@ void tst_QProperty::noDoubleCapture() return size.value(); }); auto bindingPriv = QPropertyBindingPrivate::get(max.binding()); - QCOMPARE(bindingPriv->dependencyObserverCount, 1); + QCOMPARE(bindingPriv->dependencyObserverCount, 1U); size = 4; // should not crash QCOMPARE(max.value(), 4); } From 6a549625eade31350d6dd83123c40e41fbb6792f Mon Sep 17 00:00:00 2001 From: Dennis Oberst Date: Wed, 14 Jun 2023 18:31:40 +0200 Subject: [PATCH 026/151] QFuture: mention the work-stealing algorithm in the docs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A number of users have explored the behavior and complained about it. Lets add a \note explaining this. The function in charge is QThreadPool::stealAndRunRunnable(QRunnable *), which is a private function, exclusively used by: QFutureInterfaceBase::waitForResult() QFutureInterfaceBase::waitForFinished() also update the documentation to reflect these changes accordingly. Fixes: QTBUG-112351 Change-Id: I839858cb449063d8af9bef64d2f35a6816a419b0 Reviewed-by: Ivan Solovev Reviewed-by: Mårten Nordheim (cherry picked from commit 0235de994be7e04aca3456f1260b18313dd45b74) Reviewed-by: Qt Cherry-pick Bot --- src/concurrent/qtconcurrentrun.cpp | 5 ++--- src/corelib/thread/qfuture.qdoc | 9 +++++++-- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/concurrent/qtconcurrentrun.cpp b/src/concurrent/qtconcurrentrun.cpp index 2b63a80bde2..696e857a59a 100644 --- a/src/concurrent/qtconcurrentrun.cpp +++ b/src/concurrent/qtconcurrentrun.cpp @@ -296,9 +296,8 @@ \since 5.4 \fn QFuture QtConcurrent::run(QThreadPool *pool, Function function, ...); - Runs \a function in a separate thread. The thread is taken from the - QThreadPool \a pool. Note that \a function may not run immediately; \a function - will only be run once a thread becomes available. + Schedules \a function on \a pool. Note that \a function may not run + immediately; \a function will only be run once a thread becomes available. \include qtconcurrentrun.cpp run-description */ diff --git a/src/corelib/thread/qfuture.qdoc b/src/corelib/thread/qfuture.qdoc index f49c9462e8e..834ec402304 100644 --- a/src/corelib/thread/qfuture.qdoc +++ b/src/corelib/thread/qfuture.qdoc @@ -142,6 +142,12 @@ be created using convenience functions QtFuture::makeReadyFuture and QtFuture::makeExceptionalFuture. + \note Some APIs (see \l {QFuture::then()} or various QtConcurrent method + overloads) allow scheduling the computation to a specific thread pool. + However, QFuture implements a work-stealing algorithm to prevent deadlocks + and optimize thread usage. As a result, computations can be executed + directly in the thread which requests the QFuture's result. + \note To start a computation and store results in a QFuture, use QPromise or one of the APIs in the \l {Qt Concurrent} framework. @@ -1153,8 +1159,7 @@ Attaches a continuation to this future, allowing to chain multiple asynchronous computations if desired. When the asynchronous computation represented by this - future finishes, \a function will be invoked in a separate thread taken from the - QThreadPool \a pool. + future finishes, \a function will be scheduled on \a pool. \sa onFailed(), onCanceled() */ From a6afb92c5e3ea31bbd2ae64abead2f34f77a2663 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Tue, 13 Jun 2023 15:30:55 +0200 Subject: [PATCH 027/151] tst_qmenu: fix -Wsuggest-override ... and fix placement of {. Amends f0049873d2ce0742a2df7ce265db70ca8baa8442. Change-Id: I2479087005d350a23e45eda126a89e0be91c0701 Reviewed-by: Axel Spoerl (cherry picked from commit c41e03008aff89af5e63177970cc0333260f89e9) Reviewed-by: Qt Cherry-pick Bot --- tests/auto/widgets/widgets/qmenu/tst_qmenu.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/auto/widgets/widgets/qmenu/tst_qmenu.cpp b/tests/auto/widgets/widgets/qmenu/tst_qmenu.cpp index 48a5593e95c..fb899901f60 100644 --- a/tests/auto/widgets/widgets/qmenu/tst_qmenu.cpp +++ b/tests/auto/widgets/widgets/qmenu/tst_qmenu.cpp @@ -2019,7 +2019,8 @@ void tst_QMenu::nestedTearOffDetached() public: QMenu *tornOffMenu = nullptr; protected: - bool eventFilter(QObject *receiver, QEvent *event) { + bool eventFilter(QObject *receiver, QEvent *event) override + { if (event->type() == QEvent::Show && receiver->inherits("QTornOffMenu")) tornOffMenu = qobject_cast(receiver); return QObject::eventFilter(receiver, event); From d89a086cb42b643733a0d4a7ffb897af4b449b01 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Mon, 12 Jun 2023 12:20:34 +0200 Subject: [PATCH 028/151] QPixmapCache: simplify remove(QString) The previous code used `cacheKey` as the name of an iterator, which made the code hard to understand. Instead of renaming that to the more idiomatic `it`, use QHash::take() to get an actual `cacheKey` back, and then delegate to QPMCache::remove(QPixmapCache::Key) for the actual removal. Task-number: QTBUG-112200 Change-Id: I9311c19f12a05cad694702672f17ae19ba339b04 Reviewed-by: Volker Hilsheimer (cherry picked from commit c2bcba93a67ed980021304c3bbca5556b4cc3add) Reviewed-by: Qt Cherry-pick Bot --- src/gui/image/qpixmapcache.cpp | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/src/gui/image/qpixmapcache.cpp b/src/gui/image/qpixmapcache.cpp index 3afa9401d4c..de5245d11bc 100644 --- a/src/gui/image/qpixmapcache.cpp +++ b/src/gui/image/qpixmapcache.cpp @@ -406,13 +406,8 @@ bool QPMCache::replace(const QPixmapCache::Key &key, const QPixmap &pixmap, int bool QPMCache::remove(const QString &key) { - auto cacheKey = cacheKeys.constFind(key); - //The key was not in the cache - if (cacheKey == cacheKeys.constEnd()) - return false; - const bool result = QCache::remove(cacheKey.value()); - cacheKeys.erase(cacheKey); - return result; + const auto cacheKey = cacheKeys.take(key); + return cacheKey.isValid() && remove(cacheKey); } bool QPMCache::remove(const QPixmapCache::Key &key) From 51b32b312985cfa4ddaf25d8249f69ed941263d9 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Mon, 5 Jun 2023 15:49:57 +0200 Subject: [PATCH 029/151] QPixmapCache: DRY insert() Implement insert(QString, QPixmap) in terms of insert(QPixmap) to avoid duplicating code and to separate concerns: insert(QString, QPixmap) is now only dealing with the cacheKeys, insert(QPixmap) is only concerned with the Key-based lookup. Task-number: QTBUG-112200 Change-Id: I30394da43a5e93b7bd41ef9ce9c7aea044523c30 Reviewed-by: Volker Hilsheimer (cherry picked from commit aa8e8e94b99dfff8613bcbcc8ac6de5d0d8bcb12) Reviewed-by: Qt Cherry-pick Bot --- src/gui/image/qpixmapcache.cpp | 23 +++++++---------------- 1 file changed, 7 insertions(+), 16 deletions(-) diff --git a/src/gui/image/qpixmapcache.cpp b/src/gui/image/qpixmapcache.cpp index de5245d11bc..de6b99c0675 100644 --- a/src/gui/image/qpixmapcache.cpp +++ b/src/gui/image/qpixmapcache.cpp @@ -351,25 +351,16 @@ QPixmap *QPMCache::object(const QPixmapCache::Key &key) const bool QPMCache::insert(const QString& key, const QPixmap &pixmap, int cost) { - QPixmapCache::Key &cacheKey = cacheKeys[key]; //If for the same key we add already a pixmap we should delete it - if (cacheKey.d) - QCache::remove(cacheKey); + remove(key); - //we create a new key the old one has been removed - cacheKey = createKey(); - - bool success = QCache::insert(cacheKey, new QPixmapCacheEntry(cacheKey, pixmap), cost); - if (success) { - if (!theid) { - theid = startTimer(flush_time); - t = false; - } - } else { - //Insertion failed we released the new allocated key - cacheKeys.remove(key); + // this will create a new key; the old one has been removed + auto k = insert(pixmap, cost); + if (k.isValid()) { + cacheKeys[key] = std::move(k); + return true; } - return success; + return false; } QPixmapCache::Key QPMCache::insert(const QPixmap &pixmap, int cost) From 39290247be2652c6ae1557d6d3d683acd693910e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A5rten=20Nordheim?= Date: Fri, 2 Jun 2023 19:01:09 +0200 Subject: [PATCH 030/151] QStringView: size is encoded with code units not code points Code points is what you get when surrogate pairs have been joined Change-Id: I86c4131de5782ce1e6342217947a603ca16bb521 Reviewed-by: Giuseppe D'Angelo Reviewed-by: Thiago Macieira (cherry picked from commit 054a64ce67421b213df73a9bcfda3fa6e9c6e64f) Reviewed-by: Qt Cherry-pick Bot --- src/corelib/text/qstringview.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/corelib/text/qstringview.cpp b/src/corelib/text/qstringview.cpp index c7c8a5f6797..13043dd719b 100644 --- a/src/corelib/text/qstringview.cpp +++ b/src/corelib/text/qstringview.cpp @@ -515,7 +515,7 @@ QT_BEGIN_NAMESPACE /*! \fn qsizetype QStringView::size() const - Returns the size of this string view, in UTF-16 code points (that is, + Returns the size of this string view, in UTF-16 code units (that is, surrogate pairs count as two for the purposes of this function, the same as in QString). From 6fb561ab836e2ddf1fa745e4ef6222e458383d58 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A5rten=20Nordheim?= Date: Mon, 6 Mar 2023 16:23:23 +0100 Subject: [PATCH 031/151] Http2: Don't skip checking flag for trailing HEADERS frame if PRIORITY MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If the trailing frame just had PRIORITY we would early-return, though this meant we didn't check if the frame had the END_STREAM flag set, leading some requests to certain servers to hang. Fixes: QTBUG-111417 Change-Id: Iac174dc5aeca30d5d19fae35f303983de9841847 Reviewed-by: Timur Pocheptsov Reviewed-by: Konrad Kujawa (cherry picked from commit 7822b89aef30404164bc6f6f790d0cc563e10cbf) Reviewed-by: Qt CI Bot Reviewed-by: Mårten Nordheim --- src/network/access/qhttp2protocolhandler.cpp | 18 +++++----- tests/auto/network/access/http2/http2srv.cpp | 22 ++++++++++-- tests/auto/network/access/http2/http2srv.h | 4 +++ tests/auto/network/access/http2/tst_http2.cpp | 35 +++++++++++++++++++ 4 files changed, 67 insertions(+), 12 deletions(-) diff --git a/src/network/access/qhttp2protocolhandler.cpp b/src/network/access/qhttp2protocolhandler.cpp index f369133b8b5..2cfc8f85e4b 100644 --- a/src/network/access/qhttp2protocolhandler.cpp +++ b/src/network/access/qhttp2protocolhandler.cpp @@ -1001,7 +1001,12 @@ void QHttp2ProtocolHandler::handleContinuedHEADERS() } std::vector hpackBlock(assemble_hpack_block(continuedFrames)); - if (!hpackBlock.size()) { + const bool hasHeaderFields = !hpackBlock.empty(); + if (hasHeaderFields) { + HPack::BitIStream inputStream{&hpackBlock[0], &hpackBlock[0] + hpackBlock.size()}; + if (!decoder.decodeHeaderFields(inputStream)) + return connectionError(COMPRESSION_ERROR, "HPACK decompression failed"); + } else if (firstFrameType == FrameType::PUSH_PROMISE) { // It could be a PRIORITY sent in HEADERS - already handled by this // point in handleHEADERS. If it was PUSH_PROMISE (HTTP/2 8.2.1): // "The header fields in PUSH_PROMISE and any subsequent CONTINUATION @@ -1010,21 +1015,16 @@ void QHttp2ProtocolHandler::handleContinuedHEADERS() // not include a complete and valid set of header fields or the :method // pseudo-header field identifies a method that is not safe, it MUST // respond with a stream error (Section 5.4.2) of type PROTOCOL_ERROR." - if (firstFrameType == FrameType::PUSH_PROMISE) - resetPromisedStream(continuedFrames[0], Http2::PROTOCOL_ERROR); - + resetPromisedStream(continuedFrames[0], Http2::PROTOCOL_ERROR); return; } - HPack::BitIStream inputStream{&hpackBlock[0], &hpackBlock[0] + hpackBlock.size()}; - if (!decoder.decodeHeaderFields(inputStream)) - return connectionError(COMPRESSION_ERROR, "HPACK decompression failed"); - switch (firstFrameType) { case FrameType::HEADERS: if (activeStreams.contains(streamID)) { Stream &stream = activeStreams[streamID]; - updateStream(stream, decoder.decodedHeader()); + if (hasHeaderFields) + updateStream(stream, decoder.decodedHeader()); // Needs to resend the request; we should finish and delete the current stream const bool needResend = stream.request().d->needResendWithCredentials; // No DATA frames. Or needs to resend. diff --git a/tests/auto/network/access/http2/http2srv.cpp b/tests/auto/network/access/http2/http2srv.cpp index 450544893e4..9e19b76a9dc 100644 --- a/tests/auto/network/access/http2/http2srv.cpp +++ b/tests/auto/network/access/http2/http2srv.cpp @@ -136,6 +136,11 @@ void Http2Server::setRedirect(const QByteArray &url, int count) redirectCount = count; } +void Http2Server::setSendTrailingHEADERS(bool enable) +{ + sendTrailingHEADERS = enable; +} + void Http2Server::emulateGOAWAY(int timeout) { Q_ASSERT(timeout >= 0); @@ -273,9 +278,20 @@ void Http2Server::sendDATA(quint32 streamID, quint32 windowSize) return; if (last) { - writer.start(FrameType::DATA, FrameFlag::END_STREAM, streamID); - writer.setPayloadSize(0); - writer.write(*socket); + if (sendTrailingHEADERS) { + writer.start(FrameType::HEADERS, + FrameFlag::PRIORITY | FrameFlag::END_HEADERS | FrameFlag::END_STREAM, streamID); + const quint32 maxFrameSize(clientSetting(Settings::MAX_FRAME_SIZE_ID, + Http2::maxPayloadSize)); + // 5 bytes for PRIORITY data: + writer.append(quint32(0)); // streamID 0 (32-bit) + writer.append(quint8(0)); // + weight 0 (8-bit) + writer.writeHEADERS(*socket, maxFrameSize); + } else { + writer.start(FrameType::DATA, FrameFlag::END_STREAM, streamID); + writer.setPayloadSize(0); + writer.write(*socket); + } suspendedStreams.erase(it); activeRequests.erase(streamID); diff --git a/tests/auto/network/access/http2/http2srv.h b/tests/auto/network/access/http2/http2srv.h index 73d195bd06e..7c8810003c0 100644 --- a/tests/auto/network/access/http2/http2srv.h +++ b/tests/auto/network/access/http2/http2srv.h @@ -93,6 +93,8 @@ public: // Set the redirect URL and count. The server will return a redirect response with the url // 'count' amount of times void setRedirect(const QByteArray &redirectUrl, int count); + // Send a trailing HEADERS frame with PRIORITY and END_STREAM flag + void setSendTrailingHEADERS(bool enable); void emulateGOAWAY(int timeout); void redirectOpenStream(quint16 targetPort); @@ -228,6 +230,8 @@ private: QByteArray redirectUrl; int redirectCount = 0; + + bool sendTrailingHEADERS = false; protected slots: void ignoreErrorSlot(); }; diff --git a/tests/auto/network/access/http2/tst_http2.cpp b/tests/auto/network/access/http2/tst_http2.cpp index 189df08ecf9..e712b00a6e2 100644 --- a/tests/auto/network/access/http2/tst_http2.cpp +++ b/tests/auto/network/access/http2/tst_http2.cpp @@ -116,6 +116,8 @@ private slots: void redirect_data(); void redirect(); + void trailingHEADERS(); + protected slots: // Slots to listen to our in-process server: void serverStarted(quint16 port); @@ -1150,6 +1152,39 @@ void tst_Http2::redirect() QTRY_VERIFY(serverGotSettingsACK); } +void tst_Http2::trailingHEADERS() +{ + clearHTTP2State(); + serverPort = 0; + + ServerPtr targetServer(newServer(defaultServerSettings, defaultConnectionType())); + targetServer->setSendTrailingHEADERS(true); + + QMetaObject::invokeMethod(targetServer.data(), "startServer", Qt::QueuedConnection); + runEventLoop(); + + QVERIFY(serverPort != 0); + + nRequests = 1; + + const auto url = requestUrl(defaultConnectionType()); + QNetworkRequest request(url); + + std::unique_ptr reply{ manager->get(request) }; + connect(reply.get(), &QNetworkReply::finished, this, &tst_Http2::replyFinished); + + // Since we're using self-signed certificates, ignore SSL errors: + reply->ignoreSslErrors(); + + runEventLoop(); + STOP_ON_FAILURE + + QCOMPARE(nRequests, 0); + + QCOMPARE(reply->error(), QNetworkReply::NoError); + QTRY_VERIFY(serverGotSettingsACK); +} + void tst_Http2::serverStarted(quint16 port) { serverPort = port; From e4579edb165ebb2d284ab504d07401b61c2c5ba1 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Wed, 21 Jun 2023 10:38:00 +0200 Subject: [PATCH 032/151] QFutureSynchronizer: fix aliasing problem in setFuture() When setFuture() was handed an element of m_futures, it would hold the reference to past the clear(), which invalidates said reference. Fix by taking the future by value instead of by cref. While append() is not affected, as QList::append() already guards against aliasing, do the same change there, both for consistency as well as to optimize the common case of passing rvalues. It also means we can use the rvalue overload of QList::append(), skipping the alias analysis in the lvalue QList::append(). [ChangeLog][QtConcurrent][QFutureSynchronizer] Fixed a crash in setFuture() if the argument was already a member of QFutureSynchronizer::futures(). Manual conflict resolutions: - makeReadyValueFuture() didn't exist in Qt 6.2, use makeReadyFuture() Change-Id: Ic0b212b9f265a746df9a6beb6272a5415d131442 Reviewed-by: Fabian Kosmale Reviewed-by: Qt CI Bot (cherry picked from commit e8dcbaaaf61ee2164db61e70a5d61d7a5b849371) --- src/corelib/thread/qfuturesynchronizer.h | 12 +++++----- src/corelib/thread/qfuturesynchronizer.qdoc | 6 ++--- .../tst_qfuturesynchronizer.cpp | 23 +++++++++++++++++++ 3 files changed, 32 insertions(+), 9 deletions(-) diff --git a/src/corelib/thread/qfuturesynchronizer.h b/src/corelib/thread/qfuturesynchronizer.h index 1605b34bb3c..db2e3a0035c 100644 --- a/src/corelib/thread/qfuturesynchronizer.h +++ b/src/corelib/thread/qfuturesynchronizer.h @@ -54,21 +54,21 @@ class QFutureSynchronizer public: QFutureSynchronizer() : m_cancelOnWait(false) { } - explicit QFutureSynchronizer(const QFuture &future) + explicit QFutureSynchronizer(QFuture future) : m_cancelOnWait(false) - { addFuture(future); } + { addFuture(std::move(future)); } ~QFutureSynchronizer() { waitForFinished(); } - void setFuture(const QFuture &future) + void setFuture(QFuture future) { waitForFinished(); m_futures.clear(); - addFuture(future); + addFuture(std::move(future)); } - void addFuture(const QFuture &future) + void addFuture(QFuture future) { - m_futures.append(future); + m_futures.append(std::move(future)); } void waitForFinished() diff --git a/src/corelib/thread/qfuturesynchronizer.qdoc b/src/corelib/thread/qfuturesynchronizer.qdoc index 67dafb039e6..ab37f6734e3 100644 --- a/src/corelib/thread/qfuturesynchronizer.qdoc +++ b/src/corelib/thread/qfuturesynchronizer.qdoc @@ -62,7 +62,7 @@ */ /*! - \fn template QFutureSynchronizer::QFutureSynchronizer(const QFuture &future) + \fn template QFutureSynchronizer::QFutureSynchronizer(QFuture future) Constructs a QFutureSynchronizer and begins watching \a future by calling addFuture(). @@ -80,7 +80,7 @@ */ /*! - \fn template void QFutureSynchronizer::setFuture(const QFuture &future) + \fn template void QFutureSynchronizer::setFuture(QFuture future) Sets \a future to be the only future managed by this QFutureSynchronizer. This is a convenience function that calls waitForFinished(), @@ -90,7 +90,7 @@ */ /*! - \fn template void QFutureSynchronizer::addFuture(const QFuture &future) + \fn template void QFutureSynchronizer::addFuture(QFuture future) Adds \a future to the list of managed futures. diff --git a/tests/auto/corelib/thread/qfuturesynchronizer/tst_qfuturesynchronizer.cpp b/tests/auto/corelib/thread/qfuturesynchronizer/tst_qfuturesynchronizer.cpp index ab42bdf3412..28f5aeeae11 100644 --- a/tests/auto/corelib/thread/qfuturesynchronizer/tst_qfuturesynchronizer.cpp +++ b/tests/auto/corelib/thread/qfuturesynchronizer/tst_qfuturesynchronizer.cpp @@ -38,6 +38,7 @@ class tst_QFutureSynchronizer : public QObject private Q_SLOTS: void construction(); + void setFutureAliasingExistingMember(); void addFuture(); void cancelOnWait(); void clearFutures(); @@ -58,6 +59,28 @@ void tst_QFutureSynchronizer::construction() QCOMPARE(synchronizerWithFuture.futures().size(), 1); } +void tst_QFutureSynchronizer::setFutureAliasingExistingMember() +{ + // + // GIVEN: a QFutureSynchronizer with one QFuture: + // + QFutureSynchronizer synchronizer(QtFuture::makeReadyFuture(42)); + + // + // WHEN: calling setFuture() with an alias of the QFuture already in `synchronizer`: + // + for (int i = 0; i < 2; ++i) { + const auto &f = synchronizer.futures().constFirst(); + synchronizer.setFuture(f); + } + + // + // THEN: it didn't crash + // + QCOMPARE(synchronizer.futures().size(), 1); + QCOMPARE(synchronizer.futures().constFirst().result(), 42); +} + void tst_QFutureSynchronizer::addFuture() { QFutureSynchronizer synchronizer; From 6210c7c81ca65be7879fa7cdc2fceb60e5afa32c Mon Sep 17 00:00:00 2001 From: Venugopal Shivashankar Date: Tue, 13 Jun 2023 12:54:57 +0200 Subject: [PATCH 033/151] Doc: Mark QRasterPaintEngine as \internal Most of the QWS (Qt Windowing System) classes from the Qt 4 times are cleaned up in Qt 6. Any existing QWS API documentation should be marked \internal. Task-number: QTBUG-35605 Change-Id: I24201406114feaf8af21403b09375a2ee9a4709e Reviewed-by: Laszlo Agocs (cherry picked from commit 4af07d6e54091e7a9e413b92b943eee41cb67bb8) Reviewed-by: Qt Cherry-pick Bot --- src/gui/painting/qpaintengine_raster.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/gui/painting/qpaintengine_raster.cpp b/src/gui/painting/qpaintengine_raster.cpp index 913176f2b46..444032dac78 100644 --- a/src/gui/painting/qpaintengine_raster.cpp +++ b/src/gui/painting/qpaintengine_raster.cpp @@ -277,8 +277,7 @@ QRasterPaintEnginePrivate::QRasterPaintEnginePrivate() : /*! \class QRasterPaintEngine - \preliminary - \ingroup qws + \internal \inmodule QtGui \since 4.2 From 4d5db7770670e34375e7173005bbb90b33943632 Mon Sep 17 00:00:00 2001 From: Topi Reinio Date: Wed, 14 Dec 2022 12:09:57 +0000 Subject: [PATCH 034/151] Doc: Clarify that the rich text engine has limited support for HTML tags MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes: QTBUG-108482 Change-Id: I10983c5737b8c4453e79467e5a41fd6dfe11069f Reviewed-by: Tor Arne Vestbø (cherry picked from commit 577174d505deb16cb5aca835d34e5280a61e9cfe) Reviewed-by: Qt Cherry-pick Bot --- src/gui/doc/src/richtext.qdoc | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/gui/doc/src/richtext.qdoc b/src/gui/doc/src/richtext.qdoc index 4114067c66c..6cc43bb5402 100644 --- a/src/gui/doc/src/richtext.qdoc +++ b/src/gui/doc/src/richtext.qdoc @@ -863,7 +863,11 @@ \section1 Supported Tags The following table lists the HTML tags supported by Qt's - \l{Rich Text Processing}{rich text} engine: + \l{Rich Text Processing}{rich text} engine. + + \note The functionality implemented for tags listed below is a subset of + the full HTML 4 specification. Not all attributes are supported, + see comments for each tag. \table 70% \header \li Tag From 041b8f37263d28c6421e464976186fd231b9e2cb Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Thu, 15 Jun 2023 11:37:46 -0700 Subject: [PATCH 035/151] QMetaContainer: add missing #include For std::iterator_traits, tags, std::advance, std::distance, etc. Fixes: QTBUG-114583 Change-Id: I443cf0c8a76243eead33fffd1768e904ae823f75 Reviewed-by: Fabian Kosmale Reviewed-by: Marc Mutz (cherry picked from commit 003c29511de5979fba526acd62f2a4c7c356b982) Reviewed-by: Qt Cherry-pick Bot --- src/corelib/kernel/qmetacontainer.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/corelib/kernel/qmetacontainer.h b/src/corelib/kernel/qmetacontainer.h index 48ad22d113c..f2e32924d4e 100644 --- a/src/corelib/kernel/qmetacontainer.h +++ b/src/corelib/kernel/qmetacontainer.h @@ -44,6 +44,8 @@ #include #include +#include + QT_BEGIN_NAMESPACE class QMetaType; From 9acce353e47510c2fda6987f417687ebb33bf99e Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Tue, 27 Jun 2023 09:14:09 +0200 Subject: [PATCH 036/151] tst_QFutureSynchronizer: describe how setFutureAliasingExistingMember() works MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit So no-one 'fixes' the test by pinning synchronizer.futures() into a named variable or collapsing the two lines into one. Both would break the premiss of the test. Amends e8dcbaaaf61ee2164db61e70a5d61d7a5b849371. Change-Id: I7a98c382a7db0bf3ff369dcaf61af0942796d6a3 Reviewed-by: Thiago Macieira Reviewed-by: Mårten Nordheim (cherry picked from commit 70a7a695fdbaccd042aa4371cbb231ced2d9b499) Reviewed-by: Qt Cherry-pick Bot --- .../thread/qfuturesynchronizer/tst_qfuturesynchronizer.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tests/auto/corelib/thread/qfuturesynchronizer/tst_qfuturesynchronizer.cpp b/tests/auto/corelib/thread/qfuturesynchronizer/tst_qfuturesynchronizer.cpp index 28f5aeeae11..0e63bc40288 100644 --- a/tests/auto/corelib/thread/qfuturesynchronizer/tst_qfuturesynchronizer.cpp +++ b/tests/auto/corelib/thread/qfuturesynchronizer/tst_qfuturesynchronizer.cpp @@ -70,6 +70,11 @@ void tst_QFutureSynchronizer::setFutureAliasingExistingMember() // WHEN: calling setFuture() with an alias of the QFuture already in `synchronizer`: // for (int i = 0; i < 2; ++i) { + // The next line triggers -Wdangling-reference, but it's a FP because + // of implicit sharing. We cannot keep a copy of synchronizer.futures() + // around to avoid the warning, as the extra copy would cause a detach() + // of m_futures inside setFuture() with the consequence that `f` no longer + // aliases an element in m_futures, which is the goal of this test. const auto &f = synchronizer.futures().constFirst(); synchronizer.setFuture(f); } From 5b47d294cfb817f8daa3cf054f738727c499fea5 Mon Sep 17 00:00:00 2001 From: Ahmad Samir Date: Wed, 12 Apr 2023 13:10:26 +0200 Subject: [PATCH 037/151] QXmlStreamReader: change fastScanName() to take a Value* For easier debugging, e.g. to print out value.len and value.prefix. Change-Id: Ib0eed38772f899502962f578775d34ea2744fdde Reviewed-by: Marc Mutz (cherry picked from commit 1a423ce4372d18a779f3c0d746d5283d9a425839) Reviewed-by: Qt Cherry-pick Bot --- src/corelib/serialization/qxmlstream.cpp | 16 ++++++++-------- src/corelib/serialization/qxmlstream.g | 3 ++- src/corelib/serialization/qxmlstream_p.h | 2 +- src/corelib/serialization/qxmlstreamparser_p.h | 3 ++- 4 files changed, 13 insertions(+), 11 deletions(-) diff --git a/src/corelib/serialization/qxmlstream.cpp b/src/corelib/serialization/qxmlstream.cpp index c7226969cc1..72c33584a98 100644 --- a/src/corelib/serialization/qxmlstream.cpp +++ b/src/corelib/serialization/qxmlstream.cpp @@ -1292,7 +1292,7 @@ inline qsizetype QXmlStreamReaderPrivate::fastScanContentCharList() return n; } -inline qsizetype QXmlStreamReaderPrivate::fastScanName(qint16 *prefix) +inline qsizetype QXmlStreamReaderPrivate::fastScanName(Value *val) { qsizetype n = 0; uint c; @@ -1329,16 +1329,16 @@ inline qsizetype QXmlStreamReaderPrivate::fastScanName(qint16 *prefix) case '+': case '*': putChar(c); - if (prefix && *prefix == n+1) { - *prefix = 0; + if (val && val->prefix == n + 1) { + val->prefix = 0; putChar(':'); --n; } return n; case ':': - if (prefix) { - if (*prefix == 0) { - *prefix = qint16(n + 2); + if (val) { + if (val->prefix == 0) { + val->prefix = qint16(n + 2); } else { // only one colon allowed according to the namespace spec. putChar(c); return n; @@ -1354,8 +1354,8 @@ inline qsizetype QXmlStreamReaderPrivate::fastScanName(qint16 *prefix) } } - if (prefix) - *prefix = 0; + if (val) + val->prefix = 0; qsizetype pos = textBuffer.size() - n; putString(textBuffer, pos); textBuffer.resize(pos); diff --git a/src/corelib/serialization/qxmlstream.g b/src/corelib/serialization/qxmlstream.g index 66b8b7dcdab..81ca36688cd 100644 --- a/src/corelib/serialization/qxmlstream.g +++ b/src/corelib/serialization/qxmlstream.g @@ -1489,7 +1489,8 @@ space_opt ::= space; qname ::= LETTER; /. case $rule_number: { - sym(1).len += fastScanName(&sym(1).prefix); + Value &val = sym(1); + val.len += fastScanName(&val); if (atEnd) { resume($rule_number); return false; diff --git a/src/corelib/serialization/qxmlstream_p.h b/src/corelib/serialization/qxmlstream_p.h index 543fe3ca436..8f64130d2f9 100644 --- a/src/corelib/serialization/qxmlstream_p.h +++ b/src/corelib/serialization/qxmlstream_p.h @@ -504,7 +504,7 @@ public: qsizetype fastScanLiteralContent(); qsizetype fastScanSpace(); qsizetype fastScanContentCharList(); - qsizetype fastScanName(qint16 *prefix = nullptr); + qsizetype fastScanName(Value *val = nullptr); inline qsizetype fastScanNMTOKEN(); diff --git a/src/corelib/serialization/qxmlstreamparser_p.h b/src/corelib/serialization/qxmlstreamparser_p.h index d91850fae3a..17558aae641 100644 --- a/src/corelib/serialization/qxmlstreamparser_p.h +++ b/src/corelib/serialization/qxmlstreamparser_p.h @@ -981,7 +981,8 @@ bool QXmlStreamReaderPrivate::parse() break; case 262: { - sym(1).len += fastScanName(&sym(1).prefix); + Value &val = sym(1); + val.len += fastScanName(&val); if (atEnd) { resume(262); return false; From df51e40952ff675abf8bf1925b3082a876336a01 Mon Sep 17 00:00:00 2001 From: Ahmad Samir Date: Thu, 22 Jun 2023 15:56:07 +0300 Subject: [PATCH 038/151] QXmlStreamReader: make fastScanName() indicate parsing status to callers This fixes a crash while parsing an XML file with garbage data, the file starts with '<' then garbage data: - The loop in the parse() keeps iterating until it hits "case 262:", which calls fastScanName() - fastScanName() iterates over the text buffer scanning for the attribute name (e.g. "xml:lang"), until it finds ':' - Consider a Value val, fastScanName() is called on it, it would set val.prefix to a number > val.len, then it would hit the 4096 condition and return (returned 0, now it returns the equivalent of std::null_opt), which means that val.len doesn't get modified, making it smaller than val.prefix - The code would try constructing an XmlStringRef with negative length, which would hit an assert in one of QStringView's constructors Add an assert to the XmlStringRef constructor. Add unittest based on the file from the bug report. Later on I will replace FastScanNameResult with std::optional (std::optional is C++17, which isn't required by Qt 5.15, and we want to backport this fix). Credit to OSS-Fuzz. Manual conflict resolutions: - Dropped (unneeded) _ba UDLs, which don't exist in 6.2 Fixes: QTBUG-109781 Fixes: QTBUG-114829 Change-Id: I455a5eeb47870c2ac9ffd0cbcdcd99c1ae2dd374 Reviewed-by: Allan Sandfeld Jensen (cherry picked from commit 6326bec46a618c72feba4a2bb994c4d475050aed) Reviewed-by: Qt CI Bot Reviewed-by: Volker Hilsheimer --- src/corelib/serialization/qxmlstream.cpp | 23 ++++++++--- src/corelib/serialization/qxmlstream.g | 12 +++++- src/corelib/serialization/qxmlstream_p.h | 14 ++++++- .../serialization/qxmlstreamparser_p.h | 12 +++++- .../qxmlstream/tst_qxmlstream.cpp | 39 +++++++++++++++++++ 5 files changed, 88 insertions(+), 12 deletions(-) diff --git a/src/corelib/serialization/qxmlstream.cpp b/src/corelib/serialization/qxmlstream.cpp index 72c33584a98..598b9f0428f 100644 --- a/src/corelib/serialization/qxmlstream.cpp +++ b/src/corelib/serialization/qxmlstream.cpp @@ -1292,7 +1292,9 @@ inline qsizetype QXmlStreamReaderPrivate::fastScanContentCharList() return n; } -inline qsizetype QXmlStreamReaderPrivate::fastScanName(Value *val) +// Fast scan an XML attribute name (e.g. "xml:lang"). +inline QXmlStreamReaderPrivate::FastScanNameResult +QXmlStreamReaderPrivate::fastScanName(Value *val) { qsizetype n = 0; uint c; @@ -1300,7 +1302,8 @@ inline qsizetype QXmlStreamReaderPrivate::fastScanName(Value *val) if (n >= 4096) { // This is too long to be a sensible name, and // can exhaust memory, or the range of decltype(*prefix) - return 0; + raiseNamePrefixTooLongError(); + return {}; } switch (c) { case '\n': @@ -1334,18 +1337,18 @@ inline qsizetype QXmlStreamReaderPrivate::fastScanName(Value *val) putChar(':'); --n; } - return n; + return FastScanNameResult(n); case ':': if (val) { if (val->prefix == 0) { val->prefix = qint16(n + 2); } else { // only one colon allowed according to the namespace spec. putChar(c); - return n; + return FastScanNameResult(n); } } else { putChar(c); - return n; + return FastScanNameResult(n); } Q_FALLTHROUGH(); default: @@ -1359,7 +1362,7 @@ inline qsizetype QXmlStreamReaderPrivate::fastScanName(Value *val) qsizetype pos = textBuffer.size() - n; putString(textBuffer, pos); textBuffer.resize(pos); - return 0; + return FastScanNameResult(0); } enum NameChar { NameBeginning, NameNotBeginning, NotName }; @@ -1839,6 +1842,14 @@ void QXmlStreamReaderPrivate::raiseWellFormedError(const QString &message) raiseError(QXmlStreamReader::NotWellFormedError, message); } +void QXmlStreamReaderPrivate::raiseNamePrefixTooLongError() +{ + // TODO: add a ImplementationLimitsExceededError and use it instead + raiseError(QXmlStreamReader::NotWellFormedError, + QXmlStream::tr("Length of XML attribute name exceeds implemnetation limits (4KiB " + "characters).")); +} + void QXmlStreamReaderPrivate::parseError() { diff --git a/src/corelib/serialization/qxmlstream.g b/src/corelib/serialization/qxmlstream.g index 81ca36688cd..1b5a682b36a 100644 --- a/src/corelib/serialization/qxmlstream.g +++ b/src/corelib/serialization/qxmlstream.g @@ -1490,7 +1490,11 @@ qname ::= LETTER; /. case $rule_number: { Value &val = sym(1); - val.len += fastScanName(&val); + if (auto res = fastScanName(&val)) + val.len += *res; + else + return false; + if (atEnd) { resume($rule_number); return false; @@ -1501,7 +1505,11 @@ qname ::= LETTER; name ::= LETTER; /. case $rule_number: - sym(1).len += fastScanName(); + if (auto res = fastScanName()) + sym(1).len += *res; + else + return false; + if (atEnd) { resume($rule_number); return false; diff --git a/src/corelib/serialization/qxmlstream_p.h b/src/corelib/serialization/qxmlstream_p.h index 8f64130d2f9..a277753f188 100644 --- a/src/corelib/serialization/qxmlstream_p.h +++ b/src/corelib/serialization/qxmlstream_p.h @@ -71,7 +71,7 @@ public: constexpr XmlStringRef() = default; constexpr inline XmlStringRef(const QString *string, qsizetype pos, qsizetype length) - : m_string(string), m_pos(pos), m_size(length) + : m_string(string), m_pos(pos), m_size((Q_ASSERT(length >= 0), length)) { } XmlStringRef(const QString *string) @@ -504,7 +504,16 @@ public: qsizetype fastScanLiteralContent(); qsizetype fastScanSpace(); qsizetype fastScanContentCharList(); - qsizetype fastScanName(Value *val = nullptr); + + struct FastScanNameResult { + FastScanNameResult() : ok(false) {} + explicit FastScanNameResult(qsizetype len) : addToLen(len), ok(true) { } + operator bool() { return ok; } + qsizetype operator*() { Q_ASSERT(ok); return addToLen; } + qsizetype addToLen; + bool ok; + }; + FastScanNameResult fastScanName(Value *val = nullptr); inline qsizetype fastScanNMTOKEN(); @@ -513,6 +522,7 @@ public: void raiseError(QXmlStreamReader::Error error, const QString& message = QString()); void raiseWellFormedError(const QString &message); + void raiseNamePrefixTooLongError(); QXmlStreamEntityResolver *entityResolver; diff --git a/src/corelib/serialization/qxmlstreamparser_p.h b/src/corelib/serialization/qxmlstreamparser_p.h index 17558aae641..d67d71ca01d 100644 --- a/src/corelib/serialization/qxmlstreamparser_p.h +++ b/src/corelib/serialization/qxmlstreamparser_p.h @@ -982,7 +982,11 @@ bool QXmlStreamReaderPrivate::parse() case 262: { Value &val = sym(1); - val.len += fastScanName(&val); + if (auto res = fastScanName(&val)) + val.len += *res; + else + return false; + if (atEnd) { resume(262); return false; @@ -990,7 +994,11 @@ bool QXmlStreamReaderPrivate::parse() } break; case 263: - sym(1).len += fastScanName(); + if (auto res = fastScanName()) + sym(1).len += *res; + else + return false; + if (atEnd) { resume(263); return false; diff --git a/tests/auto/corelib/serialization/qxmlstream/tst_qxmlstream.cpp b/tests/auto/corelib/serialization/qxmlstream/tst_qxmlstream.cpp index 47eb3084e97..8327f03cd58 100644 --- a/tests/auto/corelib/serialization/qxmlstream/tst_qxmlstream.cpp +++ b/tests/auto/corelib/serialization/qxmlstream/tst_qxmlstream.cpp @@ -606,6 +606,8 @@ private slots: void readBack() const; void roundTrip() const; void roundTrip_data() const; + void test_fastScanName_data() const; + void test_fastScanName() const; void entityExpansionLimit() const; @@ -1779,5 +1781,42 @@ void tst_QXmlStream::roundTrip() const QCOMPARE(out, in); } +void tst_QXmlStream::test_fastScanName_data() const +{ + QTest::addColumn("data"); + QTest::addColumn("errorType"); + + // 4096 is the limit in QXmlStreamReaderPrivate::fastScanName() + + QByteArray arr = " Date: Tue, 27 Jun 2023 18:22:16 +0200 Subject: [PATCH 039/151] CoreText: Handle failure to find matching theme font descriptors CTFontDescriptorCreateMatchingFontDescriptors has been observed to return nullptr, so we need to handle that explicitly. Fixes: QTBUG-113698 Change-Id: Ic9fa574c14068fcae98fe8e6ceddd8a4f7008210 Reviewed-by: Volker Hilsheimer (cherry picked from commit 9526a7693604c5513a08a4ab08c0c691c3003f39) Reviewed-by: Qt Cherry-pick Bot --- src/gui/text/coretext/qcoretextfontdatabase.mm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/text/coretext/qcoretextfontdatabase.mm b/src/gui/text/coretext/qcoretextfontdatabase.mm index a290a45b45b..c17f408230b 100644 --- a/src/gui/text/coretext/qcoretextfontdatabase.mm +++ b/src/gui/text/coretext/qcoretextfontdatabase.mm @@ -929,7 +929,7 @@ void QCoreTextFontDatabase::populateThemeFonts() auto addFontVariants = [&](CTFontDescriptorRef descriptor) { QCFType matchingDescriptors = CTFontDescriptorCreateMatchingFontDescriptors(descriptor, nullptr); - const int matchingDescriptorsCount = CFArrayGetCount(matchingDescriptors); + const int matchingDescriptorsCount = matchingDescriptors ? CFArrayGetCount(matchingDescriptors) : 0; qCDebug(lcQpaFonts) << "Enumerating font variants based on" << id(descriptor) << "resulted in" << matchingDescriptorsCount << "matching descriptors" << matchingDescriptors.as(); From 83330aea2918c0d5602ce4a03ed8a517ee06257e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Thu, 29 Jun 2023 15:42:36 +0200 Subject: [PATCH 040/151] macOS: Enable dirs in file dialogs, also when treating bundles as dirs In our NSOpenSavePanelDelegate we respond to panel:shouldEnableURL: with YES if it's a directory or symlink to a directory, which matches the native behavior. But the panel has a special flag to treat bundles as directories instead of files. We were checking this flag, but ignoring the case where it was actually set (which it normally is not), and as a result would go on to filter directory names as well. We now handle both cases, and only call [NSWorkspace isFilePackageAtPath:] if needed (when the treatsFilePackagesAsDirectories flag is not set). Change-Id: I2b9a16ff99b4b643389acc042c032813f432ac59 Reviewed-by: Volker Hilsheimer (cherry picked from commit 8fbce6b4a04ba9712e45340afc9b52fe2966f125) Reviewed-by: Qt Cherry-pick Bot --- src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm b/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm index 49eed150d33..97edf60f6b7 100644 --- a/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm +++ b/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm @@ -253,10 +253,9 @@ typedef QSharedPointer SharedPointerFileDialogOptions; NSString *fileType = fileAttrs.fileType; bool isDir = [fileType isEqualToString:NSFileTypeDirectory]; if (isDir) { - if (!m_panel.treatsFilePackagesAsDirectories) { - if ([NSWorkspace.sharedWorkspace isFilePackageAtPath:filename] == NO) - return YES; - } + bool treatBundlesAsFiles = !m_panel.treatsFilePackagesAsDirectories; + if (!(treatBundlesAsFiles && [NSWorkspace.sharedWorkspace isFilePackageAtPath:filename])) + return YES; } // Treat symbolic links and aliases to directories like directories From f0ae06aa1eb238e5cc0f4167c100b7a0213a589a Mon Sep 17 00:00:00 2001 From: Ievgenii Meshcheriakov Date: Fri, 30 Jun 2023 15:58:04 +0200 Subject: [PATCH 041/151] Fix invalid closing XML tag Change-Id: I1785fe855f69d7dc7d043b235ed4f3b99a6057fc Reviewed-by: Friedemann Kleint (cherry picked from commit 77a4ff4036330ea445b0dab8132cf143533106a7) Reviewed-by: Qt Cherry-pick Bot --- src/gui/accessible/linux/dbusxml/Socket.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/accessible/linux/dbusxml/Socket.xml b/src/gui/accessible/linux/dbusxml/Socket.xml index 75ec99f9945..f9ac76d2c88 100644 --- a/src/gui/accessible/linux/dbusxml/Socket.xml +++ b/src/gui/accessible/linux/dbusxml/Socket.xml @@ -17,7 +17,7 @@ - + From d06debf2248cebe9ce58694382600e80d9cd4734 Mon Sep 17 00:00:00 2001 From: Axel Spoerl Date: Wed, 10 May 2023 10:14:20 +0200 Subject: [PATCH 042/151] Implement QWidgetPrivate::focusObject() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit QWidgetPrivate::focusObject() always returns nullptr. That has lead to mismatches between QGuiApplication::focusObject() and QApplication::focusWidget(), when a widget got focus by the window system (e.g. mouse click). This patch implements QWidgetPrivate::focusObject. It returns the current widget, if it doesn't have a focus proxy. If it has a focus proxy, it resolves the proxy chain and returns the deepest focus proxy. (Note: It does not return QWidget::focusWidget(), because the focus widget might not yet have been set, when the method is called). Fixes: QTBUG-92464 Fixes: QTBUG-108522 Done-With: Liang Qi Change-Id: Icf01e8ac4fc5f722fbf8e0ca5a562617ae9ae8f2 Reviewed-by: Volker Hilsheimer Reviewed-by: Tor Arne Vestbø Reviewed-by: Liang Qi (cherry picked from commit f83ea896227dfb37281ca18cdebbd072df3b1da7) Reviewed-by: Qt CI Bot --- src/widgets/kernel/qwidget.cpp | 7 +++++++ src/widgets/kernel/qwidget_p.h | 2 +- tests/auto/widgets/util/qcompleter/tst_qcompleter.cpp | 1 + 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/widgets/kernel/qwidget.cpp b/src/widgets/kernel/qwidget.cpp index 54d61495067..324fa7ceced 100644 --- a/src/widgets/kernel/qwidget.cpp +++ b/src/widgets/kernel/qwidget.cpp @@ -6709,6 +6709,13 @@ QWidget *QWidget::focusWidget() const return const_cast(d_func()->focus_child); } +QObject *QWidgetPrivate::focusObject() +{ + Q_Q(QWidget); + QWidget *proxy = deepestFocusProxy(); + return proxy ? proxy : q; +} + /*! Returns the next widget in this widget's focus chain. diff --git a/src/widgets/kernel/qwidget_p.h b/src/widgets/kernel/qwidget_p.h index 19986d1d6d7..8d3cb0ecaa4 100644 --- a/src/widgets/kernel/qwidget_p.h +++ b/src/widgets/kernel/qwidget_p.h @@ -619,7 +619,7 @@ public: QOpenGLContext *shareContext() const; - virtual QObject *focusObject() { return nullptr; } + virtual QObject *focusObject(); #ifndef QT_NO_OPENGL virtual GLuint textureId() const { return 0; } diff --git a/tests/auto/widgets/util/qcompleter/tst_qcompleter.cpp b/tests/auto/widgets/util/qcompleter/tst_qcompleter.cpp index 18dc855cf95..3336bfa8a84 100644 --- a/tests/auto/widgets/util/qcompleter/tst_qcompleter.cpp +++ b/tests/auto/widgets/util/qcompleter/tst_qcompleter.cpp @@ -1710,6 +1710,7 @@ void tst_QCompleter::QTBUG_14292_filesystem() QTRY_VERIFY(comp.popup()->isVisible()); QCOMPARE(comp.popup()->model()->rowCount(), 2); QApplication::processEvents(); + QCOMPARE(qApp->focusObject(), &edit); // for QTBUG_108522 QTest::keyClick(&edit, 'h'); QCOMPARE(comp.popup()->model()->rowCount(), 2); QTest::keyClick(&edit, 'e'); From 2aebbfc9f2a22fa01dd3c7ddc3626f3350b1f665 Mon Sep 17 00:00:00 2001 From: Inho Lee Date: Fri, 30 Jun 2023 09:50:36 +0200 Subject: [PATCH 043/151] QXkbCommon::isLatin1 : Add a lower bound of Latin1 The range of the Latin1 key is from 0x20 to 0xff in both xkb_keysym and Qt::Key. Task-number: QTBUG-113387 Task-number: QTBUG-74479 Change-Id: I2eaba3129bead9526910f716c211f637804ab592 Reviewed-by: Eskil Abrahamsen Blomfeldt (cherry picked from commit 1652687d34d8e663c53c456b45cf0040570d870d) Reviewed-by: Qt Cherry-pick Bot --- src/gui/platform/unix/qxkbcommon_p.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/platform/unix/qxkbcommon_p.h b/src/gui/platform/unix/qxkbcommon_p.h index 76d95e99254..f99b6459d02 100644 --- a/src/gui/platform/unix/qxkbcommon_p.h +++ b/src/gui/platform/unix/qxkbcommon_p.h @@ -95,7 +95,7 @@ public: static xkb_keysym_t lookupLatinKeysym(xkb_state *state, xkb_keycode_t keycode); static bool isLatin1(xkb_keysym_t sym) { - return sym <= 0xff; + return sym >= 0x20 && sym <= 0xff; } static bool isKeypad(xkb_keysym_t sym) { return sym >= XKB_KEY_KP_Space && sym <= XKB_KEY_KP_9; From 2a47a92734baebf79858c167805b793cc972e09a Mon Sep 17 00:00:00 2001 From: Eirik Aavitsland Date: Fri, 30 Jun 2023 15:57:12 +0200 Subject: [PATCH 044/151] Update bundled libpng to version 1.6.40 [ChangeLog][Third-Party Code] libpng was updated to version 1.6.40 Change-Id: Id10d61fc4c3b8cccdcca9042097d4dc470aa0067 Reviewed-by: Eskil Abrahamsen Blomfeldt Reviewed-by: Qt CI Bot (cherry picked from commit 8aa0d71d06fc1673d90bddecc15c8c7917a39c32) Reviewed-by: Eirik Aavitsland --- src/3rdparty/libpng/ANNOUNCE | 30 ++--- src/3rdparty/libpng/CHANGES | 20 ++- src/3rdparty/libpng/LICENSE | 4 +- src/3rdparty/libpng/README | 162 ++++++++++++------------ src/3rdparty/libpng/libpng-manual.txt | 6 +- src/3rdparty/libpng/png.c | 8 +- src/3rdparty/libpng/png.h | 22 ++-- src/3rdparty/libpng/pngconf.h | 2 +- src/3rdparty/libpng/pngget.c | 13 +- src/3rdparty/libpng/pnglibconf.h | 4 +- src/3rdparty/libpng/pngpriv.h | 6 +- src/3rdparty/libpng/pngset.c | 62 ++++----- src/3rdparty/libpng/pngwrite.c | 10 +- src/3rdparty/libpng/qt_attribution.json | 7 +- 14 files changed, 181 insertions(+), 175 deletions(-) diff --git a/src/3rdparty/libpng/ANNOUNCE b/src/3rdparty/libpng/ANNOUNCE index 5675b973ab2..404cbb0de9a 100644 --- a/src/3rdparty/libpng/ANNOUNCE +++ b/src/3rdparty/libpng/ANNOUNCE @@ -1,5 +1,5 @@ -libpng 1.6.39 - November 20, 2022 -================================= +libpng 1.6.40 - June 21, 2023 +============================= This is a public release of libpng, intended for use in production code. @@ -9,13 +9,13 @@ Files available for download Source files with LF line endings (for Unix/Linux): - * libpng-1.6.39.tar.xz (LZMA-compressed, recommended) - * libpng-1.6.39.tar.gz + * libpng-1.6.40.tar.xz (LZMA-compressed, recommended) + * libpng-1.6.40.tar.gz Source files with CRLF line endings (for Windows): - * lpng1639.7z (LZMA-compressed, recommended) - * lpng1639.zip + * lpng1640.7z (LZMA-compressed, recommended) + * lpng1640.zip Other information: @@ -25,19 +25,15 @@ Other information: * TRADEMARK.md -Changes from version 1.6.38 to version 1.6.39 +Changes from version 1.6.39 to version 1.6.40 --------------------------------------------- - * Changed the error handler of oversized chunks (i.e. larger than - PNG_USER_CHUNK_MALLOC_MAX) from png_chunk_error to png_benign_error. - * Fixed a buffer overflow error in contrib/tools/pngfix. - * Fixed a memory leak (CVE-2019-6129) in contrib/tools/pngcp. - * Disabled the ARM Neon optimizations by default in the CMake file, - following the default behavior of the configure script. - * Allowed configure.ac to work with the trunk version of autoconf. - * Removed the support for "install" targets from the legacy makefiles; - removed the obsolete makefile.cegcc. - * Cleaned up the code and updated the internal documentation. + * Fixed the eXIf chunk multiplicity checks. + * Fixed a memory leak in pCAL processing. + * Corrected the validity report about tRNS inside png_get_valid(). + * Fixed various build issues on *BSD, Mac and Windows. + * Updated the configurations and the scripts for continuous integration. + * Cleaned up the code, the build scripts, and the documentation. Send comments/corrections/commendations to png-mng-implement at lists.sf.net. diff --git a/src/3rdparty/libpng/CHANGES b/src/3rdparty/libpng/CHANGES index 366e0f6a7be..2d8c585c0e7 100644 --- a/src/3rdparty/libpng/CHANGES +++ b/src/3rdparty/libpng/CHANGES @@ -204,7 +204,7 @@ Version 0.97 [January, 1998] Added simple sRGB support (Glenn R-P) Easier conditional compiling, e.g., define PNG_READ/WRITE_NOT_FULLY_SUPPORTED; - all configurable options can be selected from command-line instead + all configurable options can be selected from command line instead of having to edit pngconf.h (Glenn R-P) Fixed memory leak in pngwrite.c (free info_ptr->text) (Glenn R-P) Added more conditions for png_do_background, to avoid changing @@ -942,7 +942,7 @@ Version 1.0.8 [July 24, 2000] Version 1.0.9beta1 [November 10, 2000] Fixed typo in scripts/makefile.hpux Updated makevms.com in scripts and contrib/* and contrib/* (Martin Zinser) - Fixed seqence-point bug in contrib/pngminus/png2pnm (Martin Zinser) + Fixed sequence-point bug in contrib/pngminus/png2pnm (Martin Zinser) Changed "cdrom.com" in documentation to "libpng.org" Revised pnggccrd.c to get it all working, and updated makefile.gcmmx (Greg). Changed type of "params" from voidp to png_voidp in png_read|write_png(). @@ -2295,7 +2295,7 @@ Version 1.4.0beta58 [May 14, 2009] Clarified usage of sig_bit versus sig_bit_p in example.c (Vincent Torri) Version 1.4.0beta59 [May 15, 2009] - Reformated sources in libpng style (3-space indentation, comment format) + Reformatted sources in libpng style (3-space indentation, comment format) Fixed typo in libpng docs (PNG_FILTER_AVE should be PNG_FILTER_AVG) Added sections about the git repository and our coding style to the documentation @@ -2661,7 +2661,7 @@ Version 1.4.1beta06 [January 28, 2010] Version 1.4.1beta07 [February 6, 2010] Folded some long lines in the source files. - Added defineable PNG_USER_CHUNK_CACHE_MAX, PNG_USER_CHUNK_MALLOC_MAX, + Added definable PNG_USER_CHUNK_CACHE_MAX, PNG_USER_CHUNK_MALLOC_MAX, and a PNG_USER_LIMITS_SUPPORTED flag. Eliminated use of png_ptr->irowbytes and reused the slot in png_ptr as png_ptr->png_user_chunk_malloc_max. @@ -3919,7 +3919,7 @@ Version 1.6.0beta08 [February 1, 2012] version checking to configure.ac Improved pngstest speed by not doing redundant tests and add const to the background parameter of png_image_finish_read. The --background - option is now done automagically only when required, so that commandline + option is now done automagically only when required, so that command-line option no longer exists. Cleaned up pngpriv.h to consistently declare all functions and data. Also eliminated PNG_CONST_DATA, which is apparently not needed but we @@ -5927,7 +5927,7 @@ Version 1.6.32beta03 [August 2, 2017] (Bug report from the OSS-fuzz project). Version 1.6.32beta04 [August 2, 2017] - Replaced local eXIf_buf with info_ptr-eXIf_buf in png_handle_eXIf(). + Replaced local eXIf_buf with info_ptr->eXIf_buf in png_handle_eXIf(). Update libpng.3 and libpng-manual.txt about eXIf functions. Version 1.6.32beta05 [August 2, 2017] @@ -6121,6 +6121,14 @@ Version 1.6.39 [November 20, 2022] removed the obsolete makefile.cegcc. Cleaned up the code and updated the internal documentation. +Version 1.6.40 [June 21, 2023] + Fixed the eXIf chunk multiplicity checks. + Fixed a memory leak in pCAL processing. + Corrected the validity report about tRNS inside png_get_valid(). + Fixed various build issues on *BSD, Mac and Windows. + Updated the configurations and the scripts for continuous integration. + Cleaned up the code, the build scripts, and the documentation. + Send comments/corrections/commendations to png-mng-implement at lists.sf.net. Subscription is required; visit https://lists.sourceforge.net/lists/listinfo/png-mng-implement diff --git a/src/3rdparty/libpng/LICENSE b/src/3rdparty/libpng/LICENSE index c8ad24eecf7..086d1c2fda6 100644 --- a/src/3rdparty/libpng/LICENSE +++ b/src/3rdparty/libpng/LICENSE @@ -4,8 +4,8 @@ COPYRIGHT NOTICE, DISCLAIMER, and LICENSE PNG Reference Library License version 2 --------------------------------------- - * Copyright (c) 1995-2022 The PNG Reference Library Authors. - * Copyright (c) 2018-2022 Cosmin Truta. + * Copyright (c) 1995-2023 The PNG Reference Library Authors. + * Copyright (c) 2018-2023 Cosmin Truta. * Copyright (c) 2000-2002, 2004, 2006-2018 Glenn Randers-Pehrson. * Copyright (c) 1996-1997 Andreas Dilger. * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc. diff --git a/src/3rdparty/libpng/README b/src/3rdparty/libpng/README index 097a3c21841..dedd2c1639e 100644 --- a/src/3rdparty/libpng/README +++ b/src/3rdparty/libpng/README @@ -1,57 +1,88 @@ -README for libpng version 1.6.39 +README for libpng version 1.6.40 ================================ -See the note about version numbers near the top of png.h. -See INSTALL for instructions on how to install libpng. +See the note about version numbers near the top of `png.h`. +See `INSTALL` for instructions on how to install libpng. -Libpng comes in several distribution formats. Get libpng-*.tar.gz or -libpng-*.tar.xz if you want UNIX-style line endings in the text files, -or lpng*.7z or lpng*.zip if you want DOS-style line endings. +Libpng comes in several distribution formats. Get `libpng-*.tar.gz` +or `libpng-*.tar.xz` if you want UNIX-style line endings in the text +files, or `lpng*.7z` or `lpng*.zip` if you want DOS-style line endings. -Version 0.89 was the first official release of libpng. Don't let the -fact that it's the first release fool you. The libpng library has been -in extensive use and testing since mid-1995. By late 1997 it had -finally gotten to the stage where there hadn't been significant -changes to the API in some time, and people have a bad feeling about -libraries with versions < 1.0. Version 1.0.0 was released in -March 1998. +For a detailed description on using libpng, read `libpng-manual.txt`. +For examples of libpng in a program, see `example.c` and `pngtest.c`. +For usage information and restrictions (what little they are) on libpng, +see `png.h`. For a description on using zlib (the compression library +used by libpng) and zlib's restrictions, see `zlib.h`. -**** -Note that some of the changes to the png_info structure render this +You should use zlib 1.0.4 or later to run this, but it _may_ work with +versions as old as zlib 0.95. Even so, there are bugs in older zlib +versions which can cause the output of invalid compression streams for +some images. + +You should also note that zlib is a compression library that is useful +for more things than just PNG files. You can use zlib as a drop-in +replacement for `fread()` and `fwrite()`, if you are so inclined. + +zlib should be available at the same place that libpng is, or at +https://zlib.net . + +You may also want a copy of the PNG specification. It is available +as an RFC, a W3C Recommendation, and an ISO/IEC Standard. You can find +these at http://www.libpng.org/pub/png/pngdocs.html . + +This code is currently being archived at https://libpng.sourceforge.io +in the download area, and at http://libpng.download/src . + +This release, based in a large way on Glenn's, Guy's and Andreas' +earlier work, was created and will be supported by myself and the PNG +development group. + +Send comments, corrections and commendations to `png-mng-implement` +at `lists.sourceforge.net`. (Subscription is required; visit +https://lists.sourceforge.net/lists/listinfo/png-mng-implement +to subscribe.) + +Send general questions about the PNG specification to `png-mng-misc` +at `lists.sourceforge.net`. (Subscription is required; visit +https://lists.sourceforge.net/lists/listinfo/png-mng-misc +to subscribe.) + +Historical notes +---------------- + +The libpng library has been in extensive use and testing since mid-1995. +Version 0.89, published a year later, was the first official release. +By late 1997, it had finally gotten to the stage where there hadn't +been significant changes to the API in some time, and people have a bad +feeling about libraries with versions below 1.0. Version 1.0.0 was +released in March 1998. + +Note that some of the changes to the `png_info` structure render this version of the library binary incompatible with libpng-0.89 or earlier versions if you are using a shared library. The type of the -"filler" parameter for png_set_filler() has changed from png_byte to -png_uint_32, which will affect shared-library applications that use -this function. +`filler` parameter for `png_set_filler()` has changed from `png_byte` +to `png_uint_32`, which will affect shared-library applications that +use this function. -To avoid problems with changes to the internals of the png info_struct, +To avoid problems with changes to the internals of the `info_struct`, new APIs have been made available in 0.95 to avoid direct application -access to info_ptr. These functions are the png_set_ and -png_get_ functions. These functions should be used when -accessing/storing the info_struct data, rather than manipulating it +access to `info_ptr`. These functions are the `png_set_` and +`png_get_` functions. These functions should be used when +accessing/storing the `info_struct` data, rather than manipulating it directly, to avoid such problems in the future. It is important to note that the APIs did not make current programs that access the info struct directly incompatible with the new library, through libpng-1.2.x. In libpng-1.4.x, which was meant to -be a transitional release, members of the png_struct and the -info_struct can still be accessed, but the compiler will issue a +be a transitional release, members of the `png_struct` and the +`info_struct` can still be accessed, but the compiler will issue a warning about deprecated usage. Since libpng-1.5.0, direct access to these structs is not allowed, and the definitions of the structs -reside in private pngstruct.h and pnginfo.h header files that are not -accessible to applications. It is strongly suggested that new -programs use the new APIs (as shown in example.c and pngtest.c), and -older programs be converted to the new format, to facilitate upgrades -in the future. -**** - -Additions since 0.90 include the ability to compile libpng as a -Windows DLL, and new APIs for accessing data in the info struct. -Experimental functions include the ability to set weighting and cost -factors for row filter selection, direct reads of integers from buffers -on big-endian processors that support misaligned data access, faster -methods of doing alpha composition, and more accurate 16->8 bit color -conversion. +reside in private `pngstruct.h` and `pnginfo.h` header files that are +not accessible to applications. It is strongly suggested that new +programs use the new APIs (as shown in `example.c` and `pngtest.c`), +and older programs be converted to the new format, to facilitate +upgrades in the future. The additions since 0.89 include the ability to read from a PNG stream which has had some (or all) of the signature bytes read by the calling @@ -61,50 +92,17 @@ the library action on the detection of chunk CRC errors. It is possible to set different actions based on whether the CRC error occurred in a critical or an ancillary chunk. -For a detailed description on using libpng, read libpng-manual.txt. -For examples of libpng in a program, see example.c and pngtest.c. For -usage information and restrictions (what little they are) on libpng, -see png.h. For a description on using zlib (the compression library -used by libpng) and zlib's restrictions, see zlib.h +The additions since 0.90 include the ability to compile libpng as a +Windows DLL, and new APIs for accessing data in the `info_struct`. +Experimental functions included the ability to set weighting and cost +factors for row filter selection, direct reads of integers from buffers +on big-endian processors that support misaligned data access, faster +methods of doing alpha composition, and more accurate 16-to-8 bit color +conversion. Some of these experimental functions, such as the weighted +filter heuristics, have since been removed. -I have included a general makefile, as well as several machine and -compiler specific ones, but you may have to modify one for your own -needs. - -You should use zlib 1.0.4 or later to run this, but it MAY work with -versions as old as zlib 0.95. Even so, there are bugs in older zlib -versions which can cause the output of invalid compression streams for -some images. - -You should also note that zlib is a compression library that is useful -for more things than just PNG files. You can use zlib as a drop-in -replacement for fread() and fwrite(), if you are so inclined. - -zlib should be available at the same place that libpng is, or at -https://zlib.net. - -You may also want a copy of the PNG specification. It is available -as an RFC, a W3C Recommendation, and an ISO/IEC Standard. You can find -these at http://www.libpng.org/pub/png/pngdocs.html . - -This code is currently being archived at libpng.sourceforge.io in the -[DOWNLOAD] area, and at http://libpng.download/src . - -This release, based in a large way on Glenn's, Guy's and Andreas' -earlier work, was created and will be supported by myself and the PNG -development group. - -Send comments/corrections/commendations to png-mng-implement at -lists.sourceforge.net (subscription required; visit -https://lists.sourceforge.net/lists/listinfo/png-mng-implement -to subscribe). - -Send general questions about the PNG specification to png-mng-misc -at lists.sourceforge.net (subscription required; visit -https://lists.sourceforge.net/lists/listinfo/png-mng-misc to -subscribe). - -Files in this distribution: +Files included in this distribution +----------------------------------- ANNOUNCE => Announcement of this version, with recent changes AUTHORS => List of contributing authors @@ -153,7 +151,7 @@ Files in this distribution: arm-neon/ => Optimized code for the ARM-NEON platform mips-msa/ => Optimized code for the MIPS-MSA platform powerpc-vsx/ => Optimized code for the POWERPC-VSX platform - examples/ => Example programs + examples/ => Examples of libpng usage gregbook/ => Source code for PNG reading and writing, from "PNG: The Definitive Guide" by Greg Roelofs, O'Reilly, 1999 diff --git a/src/3rdparty/libpng/libpng-manual.txt b/src/3rdparty/libpng/libpng-manual.txt index d8567961691..67b50788266 100644 --- a/src/3rdparty/libpng/libpng-manual.txt +++ b/src/3rdparty/libpng/libpng-manual.txt @@ -1,6 +1,6 @@ libpng-manual.txt - A description on how to use and modify libpng - Copyright (c) 2018-2022 Cosmin Truta + Copyright (c) 2018-2023 Cosmin Truta Copyright (c) 1998-2018 Glenn Randers-Pehrson This document is released under the libpng license. @@ -9,9 +9,9 @@ libpng-manual.txt - A description on how to use and modify libpng Based on: - libpng version 1.6.36, December 2018, through 1.6.39 - November 2022 + libpng version 1.6.36, December 2018, through 1.6.40 - June 2023 Updated and distributed by Cosmin Truta - Copyright (c) 2018-2022 Cosmin Truta + Copyright (c) 2018-2023 Cosmin Truta libpng versions 0.97, January 1998, through 1.6.35 - July 2018 Updated and distributed by Glenn Randers-Pehrson diff --git a/src/3rdparty/libpng/png.c b/src/3rdparty/libpng/png.c index 4f3e8bbd31f..d6471b06ccd 100644 --- a/src/3rdparty/libpng/png.c +++ b/src/3rdparty/libpng/png.c @@ -1,7 +1,7 @@ /* png.c - location for general purpose libpng functions * - * Copyright (c) 2018-2022 Cosmin Truta + * Copyright (c) 2018-2023 Cosmin Truta * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson * Copyright (c) 1996-1997 Andreas Dilger * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc. @@ -14,7 +14,7 @@ #include "pngpriv.h" /* Generate a compiler error if there is an old png.h in the search path. */ -typedef png_libpng_version_1_6_39 Your_png_h_is_not_version_1_6_39; +typedef png_libpng_version_1_6_40 Your_png_h_is_not_version_1_6_40; #ifdef __GNUC__ /* The version tests may need to be added to, but the problem warning has @@ -815,8 +815,8 @@ png_get_copyright(png_const_structrp png_ptr) return PNG_STRING_COPYRIGHT #else return PNG_STRING_NEWLINE \ - "libpng version 1.6.39" PNG_STRING_NEWLINE \ - "Copyright (c) 2018-2022 Cosmin Truta" PNG_STRING_NEWLINE \ + "libpng version 1.6.40" PNG_STRING_NEWLINE \ + "Copyright (c) 2018-2023 Cosmin Truta" PNG_STRING_NEWLINE \ "Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson" \ PNG_STRING_NEWLINE \ "Copyright (c) 1996-1997 Andreas Dilger" PNG_STRING_NEWLINE \ diff --git a/src/3rdparty/libpng/png.h b/src/3rdparty/libpng/png.h index f109cdf3365..cfc4841099d 100644 --- a/src/3rdparty/libpng/png.h +++ b/src/3rdparty/libpng/png.h @@ -1,9 +1,9 @@ /* png.h - header file for PNG reference library * - * libpng version 1.6.39 - November 20, 2022 + * libpng version 1.6.40 * - * Copyright (c) 2018-2022 Cosmin Truta + * Copyright (c) 2018-2023 Cosmin Truta * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson * Copyright (c) 1996-1997 Andreas Dilger * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc. @@ -15,7 +15,7 @@ * libpng versions 0.89, June 1996, through 0.96, May 1997: Andreas Dilger * libpng versions 0.97, January 1998, through 1.6.35, July 2018: * Glenn Randers-Pehrson - * libpng versions 1.6.36, December 2018, through 1.6.39, November 2022: + * libpng versions 1.6.36, December 2018, through 1.6.40, June 2023: * Cosmin Truta * See also "Contributing Authors", below. */ @@ -27,8 +27,8 @@ * PNG Reference Library License version 2 * --------------------------------------- * - * * Copyright (c) 1995-2022 The PNG Reference Library Authors. - * * Copyright (c) 2018-2022 Cosmin Truta. + * * Copyright (c) 1995-2023 The PNG Reference Library Authors. + * * Copyright (c) 2018-2023 Cosmin Truta. * * Copyright (c) 2000-2002, 2004, 2006-2018 Glenn Randers-Pehrson. * * Copyright (c) 1996-1997 Andreas Dilger. * * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc. @@ -239,7 +239,7 @@ * ... * 1.5.30 15 10530 15.so.15.30[.0] * ... - * 1.6.39 16 10639 16.so.16.39[.0] + * 1.6.40 16 10640 16.so.16.40[.0] * * Henceforth the source version will match the shared-library major and * minor numbers; the shared-library major version number will be used for @@ -278,8 +278,8 @@ */ /* Version information for png.h - this should match the version in png.c */ -#define PNG_LIBPNG_VER_STRING "1.6.39" -#define PNG_HEADER_VERSION_STRING " libpng version 1.6.39 - November 20, 2022\n" +#define PNG_LIBPNG_VER_STRING "1.6.40" +#define PNG_HEADER_VERSION_STRING " libpng version 1.6.40 - June 21, 2023\n" #define PNG_LIBPNG_VER_SONUM 16 #define PNG_LIBPNG_VER_DLLNUM 16 @@ -287,7 +287,7 @@ /* These should match the first 3 components of PNG_LIBPNG_VER_STRING: */ #define PNG_LIBPNG_VER_MAJOR 1 #define PNG_LIBPNG_VER_MINOR 6 -#define PNG_LIBPNG_VER_RELEASE 39 +#define PNG_LIBPNG_VER_RELEASE 40 /* This should be zero for a public release, or non-zero for a * development version. [Deprecated] @@ -318,7 +318,7 @@ * From version 1.0.1 it is: * XXYYZZ, where XX=major, YY=minor, ZZ=release */ -#define PNG_LIBPNG_VER 10639 /* 1.6.39 */ +#define PNG_LIBPNG_VER 10640 /* 1.6.40 */ /* Library configuration: these options cannot be changed after * the library has been built. @@ -428,7 +428,7 @@ extern "C" { /* This triggers a compiler error in png.c, if png.c and png.h * do not agree upon the version number. */ -typedef char* png_libpng_version_1_6_39; +typedef char* png_libpng_version_1_6_40; /* Basic control structions. Read libpng-manual.txt or libpng.3 for more info. * diff --git a/src/3rdparty/libpng/pngconf.h b/src/3rdparty/libpng/pngconf.h index fcb4b430698..6671e3c3356 100644 --- a/src/3rdparty/libpng/pngconf.h +++ b/src/3rdparty/libpng/pngconf.h @@ -1,7 +1,7 @@ /* pngconf.h - machine-configurable file for libpng * - * libpng version 1.6.39 + * libpng version 1.6.40 * * Copyright (c) 2018-2022 Cosmin Truta * Copyright (c) 1998-2002,2004,2006-2016,2018 Glenn Randers-Pehrson diff --git a/src/3rdparty/libpng/pngget.c b/src/3rdparty/libpng/pngget.c index e44933c0d2c..1490a032e1a 100644 --- a/src/3rdparty/libpng/pngget.c +++ b/src/3rdparty/libpng/pngget.c @@ -1,7 +1,7 @@ /* pngget.c - retrieval of values from info struct * - * Copyright (c) 2018 Cosmin Truta + * Copyright (c) 2018-2023 Cosmin Truta * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson * Copyright (c) 1996-1997 Andreas Dilger * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc. @@ -21,7 +21,18 @@ png_get_valid(png_const_structrp png_ptr, png_const_inforp info_ptr, png_uint_32 flag) { if (png_ptr != NULL && info_ptr != NULL) + { +#ifdef PNG_READ_tRNS_SUPPORTED + /* png_handle_PLTE() may have canceled a valid tRNS chunk but left the + * 'valid' flag for the detection of duplicate chunks. Do not report a + * valid tRNS chunk in this case. + */ + if (flag == PNG_INFO_tRNS && png_ptr->num_trans == 0) + return(0); +#endif + return(info_ptr->valid & flag); + } return(0); } diff --git a/src/3rdparty/libpng/pnglibconf.h b/src/3rdparty/libpng/pnglibconf.h index e5948c8ce19..c7033ae176f 100644 --- a/src/3rdparty/libpng/pnglibconf.h +++ b/src/3rdparty/libpng/pnglibconf.h @@ -1,8 +1,8 @@ /* pnglibconf.h - library build configuration */ -/* libpng version 1.6.39 */ +/* libpng version 1.6.40 */ -/* Copyright (c) 2018-2022 Cosmin Truta */ +/* Copyright (c) 2018-2023 Cosmin Truta */ /* Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson */ /* This code is released under the libpng license. */ diff --git a/src/3rdparty/libpng/pngpriv.h b/src/3rdparty/libpng/pngpriv.h index b8a73b685df..7c19373f0b8 100644 --- a/src/3rdparty/libpng/pngpriv.h +++ b/src/3rdparty/libpng/pngpriv.h @@ -1,7 +1,7 @@ /* pngpriv.h - private declarations for use inside libpng * - * Copyright (c) 2018-2022 Cosmin Truta + * Copyright (c) 2018-2023 Cosmin Truta * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson * Copyright (c) 1996-1997 Andreas Dilger * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc. @@ -626,7 +626,7 @@ #define PNG_BACKGROUND_IS_GRAY 0x800U #define PNG_HAVE_PNG_SIGNATURE 0x1000U #define PNG_HAVE_CHUNK_AFTER_IDAT 0x2000U /* Have another chunk after IDAT */ - /* 0x4000U (unused) */ +#define PNG_WROTE_eXIf 0x4000U #define PNG_IS_READ_STRUCT 0x8000U /* Else is a write struct */ /* Flags for the transformations the PNG library does on the image data */ @@ -1910,7 +1910,7 @@ PNG_INTERNAL_FUNCTION(void,png_ascii_from_fixed,(png_const_structrp png_ptr, */ #define PNG_FP_INVALID 512 /* Available for callers as a distinct value */ -/* Result codes for the parser (boolean - true meants ok, false means +/* Result codes for the parser (boolean - true means ok, false means * not ok yet.) */ #define PNG_FP_MAYBE 0 /* The number may be valid in the future */ diff --git a/src/3rdparty/libpng/pngset.c b/src/3rdparty/libpng/pngset.c index 8c372cf4150..3fc31feb0cb 100644 --- a/src/3rdparty/libpng/pngset.c +++ b/src/3rdparty/libpng/pngset.c @@ -1,7 +1,7 @@ /* pngset.c - storage of image information into info struct * - * Copyright (c) 2018-2022 Cosmin Truta + * Copyright (c) 2018-2023 Cosmin Truta * Copyright (c) 1998-2018 Glenn Randers-Pehrson * Copyright (c) 1996-1997 Andreas Dilger * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc. @@ -137,46 +137,40 @@ png_set_cHRM_XYZ(png_const_structrp png_ptr, png_inforp info_ptr, double red_X, #ifdef PNG_eXIf_SUPPORTED void PNGAPI png_set_eXIf(png_const_structrp png_ptr, png_inforp info_ptr, - png_bytep eXIf_buf) + png_bytep exif) { png_warning(png_ptr, "png_set_eXIf does not work; use png_set_eXIf_1"); PNG_UNUSED(info_ptr) - PNG_UNUSED(eXIf_buf) + PNG_UNUSED(exif) } void PNGAPI png_set_eXIf_1(png_const_structrp png_ptr, png_inforp info_ptr, - png_uint_32 num_exif, png_bytep eXIf_buf) + png_uint_32 num_exif, png_bytep exif) { - int i; + png_bytep new_exif; png_debug1(1, "in %s storage function", "eXIf"); - if (png_ptr == NULL || info_ptr == NULL) + if (png_ptr == NULL || info_ptr == NULL || + (png_ptr->mode & PNG_WROTE_eXIf) != 0) return; - if (info_ptr->exif) - { - png_free(png_ptr, info_ptr->exif); - info_ptr->exif = NULL; - } + new_exif = png_voidcast(png_bytep, png_malloc_warn(png_ptr, num_exif)); - info_ptr->num_exif = num_exif; - - info_ptr->exif = png_voidcast(png_bytep, png_malloc_warn(png_ptr, - info_ptr->num_exif)); - - if (info_ptr->exif == NULL) + if (new_exif == NULL) { png_warning(png_ptr, "Insufficient memory for eXIf chunk data"); return; } + memcpy(new_exif, exif, (size_t)num_exif); + + png_free_data(png_ptr, info_ptr, PNG_FREE_EXIF, 0); + + info_ptr->num_exif = num_exif; + info_ptr->exif = new_exif; info_ptr->free_me |= PNG_FREE_EXIF; - - for (i = 0; i < (int) info_ptr->num_exif; i++) - info_ptr->exif[i] = eXIf_buf[i]; - info_ptr->valid |= PNG_INFO_eXIf; } #endif /* eXIf */ @@ -237,15 +231,13 @@ png_set_hIST(png_const_structrp png_ptr, png_inforp info_ptr, if (info_ptr->hist == NULL) { png_warning(png_ptr, "Insufficient memory for hIST chunk data"); - return; } - info_ptr->free_me |= PNG_FREE_HIST; - for (i = 0; i < info_ptr->num_palette; i++) info_ptr->hist[i] = hist[i]; + info_ptr->free_me |= PNG_FREE_HIST; info_ptr->valid |= PNG_INFO_hIST; } #endif @@ -367,6 +359,8 @@ png_set_pCAL(png_const_structrp png_ptr, png_inforp info_ptr, memcpy(info_ptr->pcal_purpose, purpose, length); + info_ptr->free_me |= PNG_FREE_PCAL; + png_debug(3, "storing X0, X1, type, and nparams in info"); info_ptr->pcal_X0 = X0; info_ptr->pcal_X1 = X1; @@ -383,7 +377,6 @@ png_set_pCAL(png_const_structrp png_ptr, png_inforp info_ptr, if (info_ptr->pcal_units == NULL) { png_warning(png_ptr, "Insufficient memory for pCAL units"); - return; } @@ -395,7 +388,6 @@ png_set_pCAL(png_const_structrp png_ptr, png_inforp info_ptr, if (info_ptr->pcal_params == NULL) { png_warning(png_ptr, "Insufficient memory for pCAL params"); - return; } @@ -413,7 +405,6 @@ png_set_pCAL(png_const_structrp png_ptr, png_inforp info_ptr, if (info_ptr->pcal_params[i] == NULL) { png_warning(png_ptr, "Insufficient memory for pCAL parameter"); - return; } @@ -421,7 +412,6 @@ png_set_pCAL(png_const_structrp png_ptr, png_inforp info_ptr, } info_ptr->valid |= PNG_INFO_pCAL; - info_ptr->free_me |= PNG_FREE_PCAL; } #endif @@ -478,18 +468,17 @@ png_set_sCAL_s(png_const_structrp png_ptr, png_inforp info_ptr, if (info_ptr->scal_s_height == NULL) { - png_free (png_ptr, info_ptr->scal_s_width); + png_free(png_ptr, info_ptr->scal_s_width); info_ptr->scal_s_width = NULL; png_warning(png_ptr, "Memory allocation failed while processing sCAL"); - return; } memcpy(info_ptr->scal_s_height, sheight, lengthh); - info_ptr->valid |= PNG_INFO_sCAL; info_ptr->free_me |= PNG_FREE_SCAL; + info_ptr->valid |= PNG_INFO_sCAL; } # ifdef PNG_FLOATING_POINT_SUPPORTED @@ -625,11 +614,10 @@ png_set_PLTE(png_structrp png_ptr, png_inforp info_ptr, if (num_palette > 0) memcpy(png_ptr->palette, palette, (unsigned int)num_palette * (sizeof (png_color))); + info_ptr->palette = png_ptr->palette; info_ptr->num_palette = png_ptr->num_palette = (png_uint_16)num_palette; - info_ptr->free_me |= PNG_FREE_PLTE; - info_ptr->valid |= PNG_INFO_PLTE; } @@ -1020,8 +1008,8 @@ png_set_tRNS(png_structrp png_ptr, png_inforp info_ptr, png_malloc(png_ptr, PNG_MAX_PALETTE_LENGTH)); memcpy(info_ptr->trans_alpha, trans_alpha, (size_t)num_trans); - info_ptr->valid |= PNG_INFO_tRNS; info_ptr->free_me |= PNG_FREE_TRNS; + info_ptr->valid |= PNG_INFO_tRNS; } png_ptr->trans_alpha = info_ptr->trans_alpha; } @@ -1054,8 +1042,8 @@ png_set_tRNS(png_structrp png_ptr, png_inforp info_ptr, if (num_trans != 0) { - info_ptr->valid |= PNG_INFO_tRNS; info_ptr->free_me |= PNG_FREE_TRNS; + info_ptr->valid |= PNG_INFO_tRNS; } } #endif @@ -1089,11 +1077,11 @@ png_set_sPLT(png_const_structrp png_ptr, { /* Out of memory or too many chunks */ png_chunk_report(png_ptr, "too many sPLT chunks", PNG_CHUNK_WRITE_ERROR); - return; } png_free(png_ptr, info_ptr->splt_palettes); + info_ptr->splt_palettes = np; info_ptr->free_me |= PNG_FREE_SPLT; @@ -1247,11 +1235,11 @@ png_set_unknown_chunks(png_const_structrp png_ptr, { png_chunk_report(png_ptr, "too many unknown chunks", PNG_CHUNK_WRITE_ERROR); - return; } png_free(png_ptr, info_ptr->unknown_chunks); + info_ptr->unknown_chunks = np; /* safe because it is initialized */ info_ptr->free_me |= PNG_FREE_UNKN; diff --git a/src/3rdparty/libpng/pngwrite.c b/src/3rdparty/libpng/pngwrite.c index 4e58d776a96..32f4bfbe7df 100644 --- a/src/3rdparty/libpng/pngwrite.c +++ b/src/3rdparty/libpng/pngwrite.c @@ -1,7 +1,7 @@ /* pngwrite.c - general routines to write a PNG file * - * Copyright (c) 2018-2022 Cosmin Truta + * Copyright (c) 2018-2023 Cosmin Truta * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson * Copyright (c) 1996-1997 Andreas Dilger * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc. @@ -239,7 +239,10 @@ png_write_info(png_structrp png_ptr, png_const_inforp info_ptr) #ifdef PNG_WRITE_eXIf_SUPPORTED if ((info_ptr->valid & PNG_INFO_eXIf) != 0) + { png_write_eXIf(png_ptr, info_ptr->exif, info_ptr->num_exif); + png_ptr->mode |= PNG_WROTE_eXIf; + } #endif #ifdef PNG_WRITE_hIST_SUPPORTED @@ -439,8 +442,9 @@ png_write_end(png_structrp png_ptr, png_inforp info_ptr) #endif #ifdef PNG_WRITE_eXIf_SUPPORTED - if ((info_ptr->valid & PNG_INFO_eXIf) != 0) - png_write_eXIf(png_ptr, info_ptr->exif, info_ptr->num_exif); + if ((info_ptr->valid & PNG_INFO_eXIf) != 0 && + (png_ptr->mode & PNG_WROTE_eXIf) == 0) + png_write_eXIf(png_ptr, info_ptr->exif, info_ptr->num_exif); #endif #ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED diff --git a/src/3rdparty/libpng/qt_attribution.json b/src/3rdparty/libpng/qt_attribution.json index 2c51a056850..cf5aae3824d 100644 --- a/src/3rdparty/libpng/qt_attribution.json +++ b/src/3rdparty/libpng/qt_attribution.json @@ -6,12 +6,13 @@ "Description": "libpng is the official PNG reference library.", "Homepage": "http://www.libpng.org/pub/png/libpng.html", - "Version": "1.6.39", + "Version": "1.6.40", + "DownloadLocation": "https://download.sourceforge.net/libpng/libpng-1.6.40.tar.xz", "License": "libpng License and PNG Reference Library version 2", "LicenseId": "Libpng AND libpng-2.0", "LicenseFile": "LICENSE", - "Copyright": "Copyright (c) 1995-2022 The PNG Reference Library Authors -Copyright (c) 2000-2022 Cosmin Truta + "Copyright": "Copyright (c) 1995-2023 The PNG Reference Library Authors +Copyright (c) 2000-2023 Cosmin Truta Copyright (c) 1998-2018 Glenn Randers-Pehrson Copyright (c) 1996-1997 Andreas Dilger Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc. From 87d46ab304e3498dd0c89fce1279cf0d3960867d Mon Sep 17 00:00:00 2001 From: Volker Hilsheimer Date: Tue, 4 Jul 2023 18:47:26 +0200 Subject: [PATCH 045/151] QVariant: always compare floating point with double precision When Qt is configured with `-qreal float`, then we should still compare QVariants containing floating point values with the full precision of the stored type, and not cast to qreal (ie. float). Cast all floating point types up to double, which is the highest- precision floating point type we support in Qt. This might have a small performance impact when compiling with `-qreal float`, if the FPU does not perform well with double-precision floating point values. We don't test any `-qreal float` configurations in CI, so not adding a unit test for this. Cherry-pick conflict resolution: adapt patch to explicit boolean out-parameter for "ok", instead of relying on std::optional. Fixes: QTBUG-114991 Change-Id: I198ec2c39913b501ef2fe99ae3048b160baa1fd8 Reviewed-by: Thiago Macieira (cherry picked from commit 1fe60cbcc3c476f5f4bc4bce49d4e73d99c49d3d) Reviewed-by: Tuukka Kettunen --- src/corelib/kernel/qvariant.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/corelib/kernel/qvariant.cpp b/src/corelib/kernel/qvariant.cpp index 8981521640f..60be6369244 100644 --- a/src/corelib/kernel/qvariant.cpp +++ b/src/corelib/kernel/qvariant.cpp @@ -217,22 +217,22 @@ static qlonglong qConvertToNumber(const QVariant::Private *d, bool *ok, bool all return Q_INT64_C(0); } -static qreal qConvertToRealNumber(const QVariant::Private *d, bool *ok) +static double qConvertToRealNumber(const QVariant::Private *d, bool *ok) { *ok = true; switch (uint(d->typeId())) { case QMetaType::QString: return d->get().toDouble(ok); case QMetaType::Double: - return qreal(d->get()); + return d->get(); case QMetaType::Float: - return qreal(d->get()); + return double(d->get()); case QMetaType::ULongLong: case QMetaType::UInt: case QMetaType::UChar: case QMetaType::UShort: case QMetaType::ULong: - return qreal(qMetaTypeUNumber(d)); + return double(qMetaTypeUNumber(d)); #ifndef QT_BOOTSTRAPPED case QMetaType::QCborValue: return d->get().toDouble(); @@ -241,7 +241,7 @@ static qreal qConvertToRealNumber(const QVariant::Private *d, bool *ok) #endif default: // includes enum conversion as well as invalid types - return qreal(qConvertToNumber(d, ok)); + return double(qConvertToNumber(d, ok)); } } @@ -2339,12 +2339,12 @@ static bool numericEquals(const QVariant::Private *d1, const QVariant::Private * if (promotedType != QMetaType::QReal) return integralEquals(promotedType, d1, d2); - // qreal comparisons + // floating point comparison bool ok; - qreal r1 = qConvertToRealNumber(d1, &ok); + const double r1 = qConvertToRealNumber(d1, &ok); if (!ok) return false; - qreal r2 = qConvertToRealNumber(d2, &ok); + const double r2 = qConvertToRealNumber(d2, &ok); if (!ok) return false; if (r1 == r2) From 3981f5e2081acffd2ef8237bc881bed26bacadbe Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Wed, 5 Jul 2023 07:42:19 +0200 Subject: [PATCH 046/151] QLogging: DRY isFatal(QtMsgType) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Extract Method on the count-down algorithm of fatalCriticals and fatalWarnings, so we don't have the repeat the calculation and the comment. Task-number: QTBUG-115062 Change-Id: I4bcbc2f5a21b999e7f301085581677b437a889e9 Reviewed-by: David Faure Reviewed-by: Kai Köhne (cherry picked from commit 3ffc1f9775cde1369ebdfcfa91ec18c393c24260) Reviewed-by: Qt Cherry-pick Bot --- src/corelib/global/qlogging.cpp | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/corelib/global/qlogging.cpp b/src/corelib/global/qlogging.cpp index 6cab994a77b..d01461ebf3b 100644 --- a/src/corelib/global/qlogging.cpp +++ b/src/corelib/global/qlogging.cpp @@ -190,6 +190,13 @@ static int checked_var_value(const char *varname) return ok ? value : 1; } +static bool is_fatal_count_down(QAtomicInt &n) +{ + // it's fatal if the current value is exactly 1, + // otherwise decrement if it's non-zero + return n.loadRelaxed() && n.fetchAndAddRelaxed(-1) == 1; +} + static bool isFatal(QtMsgType msgType) { if (msgType == QtFatalMsg) @@ -197,18 +204,12 @@ static bool isFatal(QtMsgType msgType) if (msgType == QtCriticalMsg) { static QAtomicInt fatalCriticals = checked_var_value("QT_FATAL_CRITICALS"); - - // it's fatal if the current value is exactly 1, - // otherwise decrement if it's non-zero - return fatalCriticals.loadRelaxed() && fatalCriticals.fetchAndAddRelaxed(-1) == 1; + return is_fatal_count_down(fatalCriticals); } if (msgType == QtWarningMsg || msgType == QtCriticalMsg) { static QAtomicInt fatalWarnings = checked_var_value("QT_FATAL_WARNINGS"); - - // it's fatal if the current value is exactly 1, - // otherwise decrement if it's non-zero - return fatalWarnings.loadRelaxed() && fatalWarnings.fetchAndAddRelaxed(-1) == 1; + return is_fatal_count_down(fatalWarnings); } return false; From 053ba85d3f2c229289bc882f5fe28b121c06d680 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Mon, 3 Jul 2023 18:39:01 +0200 Subject: [PATCH 047/151] QOpenGLFunctions: fix -Wunused-private-field (Clang 15) I see this with -unity-build -unity-build-batch-size 32, but I don't know whether it's unity-build or just Clang 15, so also pick to 6.2. The issue exists in 5.15, too, presumably, but I have no desire to find a non-C++17 fix. It appears the generator (glgen) is out-of-sync with the state of its supposed output as of at least 18aae36a90c0753f1b1e615ba8437d8ebd1bd2fb, so don't try to update the generator (I failed to find where these fields originate from, anyway). Task-number: QTBUG-115031 Change-Id: Ia27620b8f8034c3e8eff383abb849e6ce93dce8a Reviewed-by: Qt CI Bot Reviewed-by: Volker Hilsheimer (cherry picked from commit 4443d392e4f234a5315cfd773559af936cb62ddb) Reviewed-by: Qt Cherry-pick Bot --- src/opengl/qopenglfunctions_2_0.cpp | 1 - src/opengl/qopenglfunctions_2_0.h | 2 +- src/opengl/qopenglfunctions_2_1.cpp | 1 - src/opengl/qopenglfunctions_2_1.h | 2 +- src/opengl/qopenglfunctions_3_0.cpp | 2 -- src/opengl/qopenglfunctions_3_0.h | 4 ++-- src/opengl/qopenglfunctions_3_2_compatibility.cpp | 2 -- src/opengl/qopenglfunctions_3_2_compatibility.h | 4 ++-- src/opengl/qopenglfunctions_3_3_compatibility.cpp | 1 - src/opengl/qopenglfunctions_3_3_compatibility.h | 2 +- src/opengl/qopenglfunctions_4_0_compatibility.cpp | 1 - src/opengl/qopenglfunctions_4_0_compatibility.h | 2 +- src/opengl/qopenglfunctions_4_1_compatibility.cpp | 1 - src/opengl/qopenglfunctions_4_1_compatibility.h | 2 +- src/opengl/qopenglfunctions_4_2_compatibility.cpp | 1 - src/opengl/qopenglfunctions_4_2_compatibility.h | 2 +- src/opengl/qopenglfunctions_4_3_compatibility.cpp | 1 - src/opengl/qopenglfunctions_4_3_compatibility.h | 2 +- 18 files changed, 11 insertions(+), 22 deletions(-) diff --git a/src/opengl/qopenglfunctions_2_0.cpp b/src/opengl/qopenglfunctions_2_0.cpp index 23ea5c28f32..ea66b016492 100644 --- a/src/opengl/qopenglfunctions_2_0.cpp +++ b/src/opengl/qopenglfunctions_2_0.cpp @@ -79,7 +79,6 @@ QOpenGLFunctions_2_0::QOpenGLFunctions_2_0() , d_1_2_Deprecated(nullptr) , d_1_3_Deprecated(nullptr) , d_1_4_Deprecated(nullptr) - , m_reserved_2_0_Deprecated(nullptr) { } diff --git a/src/opengl/qopenglfunctions_2_0.h b/src/opengl/qopenglfunctions_2_0.h index d88f0f57495..28a530edafb 100644 --- a/src/opengl/qopenglfunctions_2_0.h +++ b/src/opengl/qopenglfunctions_2_0.h @@ -691,7 +691,7 @@ private: QOpenGLFunctions_1_2_DeprecatedBackend* d_1_2_Deprecated; QOpenGLFunctions_1_3_DeprecatedBackend* d_1_3_Deprecated; QOpenGLFunctions_1_4_DeprecatedBackend* d_1_4_Deprecated; - void *m_reserved_2_0_Deprecated; // To maintain BC + Q_DECL_UNUSED_MEMBER void *m_reserved_2_0_Deprecated = nullptr; // To maintain BC }; // OpenGL 1.0 core functions diff --git a/src/opengl/qopenglfunctions_2_1.cpp b/src/opengl/qopenglfunctions_2_1.cpp index 9c98b28b815..6d22bdf7cb2 100644 --- a/src/opengl/qopenglfunctions_2_1.cpp +++ b/src/opengl/qopenglfunctions_2_1.cpp @@ -80,7 +80,6 @@ QOpenGLFunctions_2_1::QOpenGLFunctions_2_1() , d_1_2_Deprecated(nullptr) , d_1_3_Deprecated(nullptr) , d_1_4_Deprecated(nullptr) - , m_reserved_2_0_Deprecated(nullptr) { } diff --git a/src/opengl/qopenglfunctions_2_1.h b/src/opengl/qopenglfunctions_2_1.h index 348ae3635ab..224c19b4385 100644 --- a/src/opengl/qopenglfunctions_2_1.h +++ b/src/opengl/qopenglfunctions_2_1.h @@ -702,7 +702,7 @@ private: QOpenGLFunctions_1_2_DeprecatedBackend* d_1_2_Deprecated; QOpenGLFunctions_1_3_DeprecatedBackend* d_1_3_Deprecated; QOpenGLFunctions_1_4_DeprecatedBackend* d_1_4_Deprecated; - void *m_reserved_2_0_Deprecated; // To maintain BC + Q_DECL_UNUSED_MEMBER void *m_reserved_2_0_Deprecated = nullptr; // To maintain BC }; // OpenGL 1.0 core functions diff --git a/src/opengl/qopenglfunctions_3_0.cpp b/src/opengl/qopenglfunctions_3_0.cpp index d12f1f5ba33..2cab7681913 100644 --- a/src/opengl/qopenglfunctions_3_0.cpp +++ b/src/opengl/qopenglfunctions_3_0.cpp @@ -81,8 +81,6 @@ QOpenGLFunctions_3_0::QOpenGLFunctions_3_0() , d_1_2_Deprecated(nullptr) , d_1_3_Deprecated(nullptr) , d_1_4_Deprecated(nullptr) - , m_reserved_2_0_Deprecated(nullptr) - , m_reserved_3_0_Deprecated(nullptr) { } diff --git a/src/opengl/qopenglfunctions_3_0.h b/src/opengl/qopenglfunctions_3_0.h index 4b0e77cb14a..dc4e3f022ec 100644 --- a/src/opengl/qopenglfunctions_3_0.h +++ b/src/opengl/qopenglfunctions_3_0.h @@ -791,8 +791,8 @@ private: QOpenGLFunctions_1_2_DeprecatedBackend* d_1_2_Deprecated; QOpenGLFunctions_1_3_DeprecatedBackend* d_1_3_Deprecated; QOpenGLFunctions_1_4_DeprecatedBackend* d_1_4_Deprecated; - void *m_reserved_2_0_Deprecated; // To maintain BC - void *m_reserved_3_0_Deprecated; // To maintain BC + Q_DECL_UNUSED_MEMBER void *m_reserved_2_0_Deprecated = nullptr; // To maintain BC + Q_DECL_UNUSED_MEMBER void *m_reserved_3_0_Deprecated = nullptr; // To maintain BC }; // OpenGL 1.0 core functions diff --git a/src/opengl/qopenglfunctions_3_2_compatibility.cpp b/src/opengl/qopenglfunctions_3_2_compatibility.cpp index 59e0bd007a0..f6e413f6fc0 100644 --- a/src/opengl/qopenglfunctions_3_2_compatibility.cpp +++ b/src/opengl/qopenglfunctions_3_2_compatibility.cpp @@ -83,8 +83,6 @@ QOpenGLFunctions_3_2_Compatibility::QOpenGLFunctions_3_2_Compatibility() , d_1_2_Deprecated(nullptr) , d_1_3_Deprecated(nullptr) , d_1_4_Deprecated(nullptr) - , m_reserved_2_0_Deprecated(nullptr) - , m_reserved_3_0_Deprecated(nullptr) { } diff --git a/src/opengl/qopenglfunctions_3_2_compatibility.h b/src/opengl/qopenglfunctions_3_2_compatibility.h index 03e7c2b3061..84dda24acb0 100644 --- a/src/opengl/qopenglfunctions_3_2_compatibility.h +++ b/src/opengl/qopenglfunctions_3_2_compatibility.h @@ -832,8 +832,8 @@ private: QOpenGLFunctions_1_2_DeprecatedBackend* d_1_2_Deprecated; QOpenGLFunctions_1_3_DeprecatedBackend* d_1_3_Deprecated; QOpenGLFunctions_1_4_DeprecatedBackend* d_1_4_Deprecated; - void *m_reserved_2_0_Deprecated; // To maintain BC - void *m_reserved_3_0_Deprecated; // To maintain BC + Q_DECL_UNUSED_MEMBER void *m_reserved_2_0_Deprecated = nullptr; // To maintain BC + Q_DECL_UNUSED_MEMBER void *m_reserved_3_0_Deprecated = nullptr; // To maintain BC }; // OpenGL 1.0 core functions diff --git a/src/opengl/qopenglfunctions_3_3_compatibility.cpp b/src/opengl/qopenglfunctions_3_3_compatibility.cpp index d04aecb64e1..d0b584f8660 100644 --- a/src/opengl/qopenglfunctions_3_3_compatibility.cpp +++ b/src/opengl/qopenglfunctions_3_3_compatibility.cpp @@ -84,7 +84,6 @@ QOpenGLFunctions_3_3_Compatibility::QOpenGLFunctions_3_3_Compatibility() , d_1_2_Deprecated(nullptr) , d_1_3_Deprecated(nullptr) , d_1_4_Deprecated(nullptr) - , m_reserved_2_0_Deprecated(nullptr) , d_3_3_Deprecated(nullptr) { } diff --git a/src/opengl/qopenglfunctions_3_3_compatibility.h b/src/opengl/qopenglfunctions_3_3_compatibility.h index 4e538411843..32d85dd87dd 100644 --- a/src/opengl/qopenglfunctions_3_3_compatibility.h +++ b/src/opengl/qopenglfunctions_3_3_compatibility.h @@ -895,7 +895,7 @@ private: QOpenGLFunctions_1_2_DeprecatedBackend* d_1_2_Deprecated; QOpenGLFunctions_1_3_DeprecatedBackend* d_1_3_Deprecated; QOpenGLFunctions_1_4_DeprecatedBackend* d_1_4_Deprecated; - void *m_reserved_2_0_Deprecated; // To maintain BC + Q_DECL_UNUSED_MEMBER void *m_reserved_2_0_Deprecated = nullptr; // To maintain BC QOpenGLFunctions_3_3_DeprecatedBackend* d_3_3_Deprecated; }; diff --git a/src/opengl/qopenglfunctions_4_0_compatibility.cpp b/src/opengl/qopenglfunctions_4_0_compatibility.cpp index 4d7393929be..6db5e6fa9cd 100644 --- a/src/opengl/qopenglfunctions_4_0_compatibility.cpp +++ b/src/opengl/qopenglfunctions_4_0_compatibility.cpp @@ -85,7 +85,6 @@ QOpenGLFunctions_4_0_Compatibility::QOpenGLFunctions_4_0_Compatibility() , d_1_2_Deprecated(nullptr) , d_1_3_Deprecated(nullptr) , d_1_4_Deprecated(nullptr) - , m_reserved_2_0_Deprecated(nullptr) , d_3_3_Deprecated(nullptr) { } diff --git a/src/opengl/qopenglfunctions_4_0_compatibility.h b/src/opengl/qopenglfunctions_4_0_compatibility.h index 5d904a69b3a..b3c65f6ad94 100644 --- a/src/opengl/qopenglfunctions_4_0_compatibility.h +++ b/src/opengl/qopenglfunctions_4_0_compatibility.h @@ -946,7 +946,7 @@ private: QOpenGLFunctions_1_2_DeprecatedBackend* d_1_2_Deprecated; QOpenGLFunctions_1_3_DeprecatedBackend* d_1_3_Deprecated; QOpenGLFunctions_1_4_DeprecatedBackend* d_1_4_Deprecated; - void *m_reserved_2_0_Deprecated; // To maintain BC + Q_DECL_UNUSED_MEMBER void *m_reserved_2_0_Deprecated = nullptr; // To maintain BC QOpenGLFunctions_3_3_DeprecatedBackend* d_3_3_Deprecated; }; diff --git a/src/opengl/qopenglfunctions_4_1_compatibility.cpp b/src/opengl/qopenglfunctions_4_1_compatibility.cpp index 9df70dcfca8..0a84c73a32c 100644 --- a/src/opengl/qopenglfunctions_4_1_compatibility.cpp +++ b/src/opengl/qopenglfunctions_4_1_compatibility.cpp @@ -86,7 +86,6 @@ QOpenGLFunctions_4_1_Compatibility::QOpenGLFunctions_4_1_Compatibility() , d_1_2_Deprecated(nullptr) , d_1_3_Deprecated(nullptr) , d_1_4_Deprecated(nullptr) - , m_reserved_2_0_Deprecated(nullptr) , d_3_3_Deprecated(nullptr) { } diff --git a/src/opengl/qopenglfunctions_4_1_compatibility.h b/src/opengl/qopenglfunctions_4_1_compatibility.h index 8f96cfb4fcd..e6ae6d9d1fa 100644 --- a/src/opengl/qopenglfunctions_4_1_compatibility.h +++ b/src/opengl/qopenglfunctions_4_1_compatibility.h @@ -1039,7 +1039,7 @@ private: QOpenGLFunctions_1_2_DeprecatedBackend* d_1_2_Deprecated; QOpenGLFunctions_1_3_DeprecatedBackend* d_1_3_Deprecated; QOpenGLFunctions_1_4_DeprecatedBackend* d_1_4_Deprecated; - void *m_reserved_2_0_Deprecated; // To maintain BC + Q_DECL_UNUSED_MEMBER void *m_reserved_2_0_Deprecated = nullptr; // To maintain BC QOpenGLFunctions_3_3_DeprecatedBackend* d_3_3_Deprecated; }; diff --git a/src/opengl/qopenglfunctions_4_2_compatibility.cpp b/src/opengl/qopenglfunctions_4_2_compatibility.cpp index 30b0758cfc5..2dcf29e81df 100644 --- a/src/opengl/qopenglfunctions_4_2_compatibility.cpp +++ b/src/opengl/qopenglfunctions_4_2_compatibility.cpp @@ -87,7 +87,6 @@ QOpenGLFunctions_4_2_Compatibility::QOpenGLFunctions_4_2_Compatibility() , d_1_2_Deprecated(nullptr) , d_1_3_Deprecated(nullptr) , d_1_4_Deprecated(nullptr) - , m_reserved_2_0_Deprecated(nullptr) , d_3_3_Deprecated(nullptr) { } diff --git a/src/opengl/qopenglfunctions_4_2_compatibility.h b/src/opengl/qopenglfunctions_4_2_compatibility.h index 382b551e31a..96946e7c212 100644 --- a/src/opengl/qopenglfunctions_4_2_compatibility.h +++ b/src/opengl/qopenglfunctions_4_2_compatibility.h @@ -1062,7 +1062,7 @@ private: QOpenGLFunctions_1_2_DeprecatedBackend* d_1_2_Deprecated; QOpenGLFunctions_1_3_DeprecatedBackend* d_1_3_Deprecated; QOpenGLFunctions_1_4_DeprecatedBackend* d_1_4_Deprecated; - void *m_reserved_2_0_Deprecated; // To maintain BC + Q_DECL_UNUSED_MEMBER void *m_reserved_2_0_Deprecated = nullptr; // To maintain BC QOpenGLFunctions_3_3_DeprecatedBackend* d_3_3_Deprecated; }; diff --git a/src/opengl/qopenglfunctions_4_3_compatibility.cpp b/src/opengl/qopenglfunctions_4_3_compatibility.cpp index fe1de7a6300..1b8cd5e1147 100644 --- a/src/opengl/qopenglfunctions_4_3_compatibility.cpp +++ b/src/opengl/qopenglfunctions_4_3_compatibility.cpp @@ -88,7 +88,6 @@ QOpenGLFunctions_4_3_Compatibility::QOpenGLFunctions_4_3_Compatibility() , d_1_2_Deprecated(nullptr) , d_1_3_Deprecated(nullptr) , d_1_4_Deprecated(nullptr) - , m_reserved_2_0_Deprecated(nullptr) , d_3_3_Deprecated(nullptr) { } diff --git a/src/opengl/qopenglfunctions_4_3_compatibility.h b/src/opengl/qopenglfunctions_4_3_compatibility.h index 52030c1e6c3..1014c2c165e 100644 --- a/src/opengl/qopenglfunctions_4_3_compatibility.h +++ b/src/opengl/qopenglfunctions_4_3_compatibility.h @@ -1100,7 +1100,7 @@ private: QOpenGLFunctions_1_2_DeprecatedBackend* d_1_2_Deprecated; QOpenGLFunctions_1_3_DeprecatedBackend* d_1_3_Deprecated; QOpenGLFunctions_1_4_DeprecatedBackend* d_1_4_Deprecated; - void *m_reserved_2_0_Deprecated; // To maintain BC + Q_DECL_UNUSED_MEMBER void *m_reserved_2_0_Deprecated = nullptr; // To maintain BC QOpenGLFunctions_3_3_DeprecatedBackend* d_3_3_Deprecated; }; From c62c6399176d9c1b0d0c528a564cbad4e504bfb0 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Wed, 5 Jul 2023 08:36:06 +0200 Subject: [PATCH 048/151] Make sure we don't count down past 0 QT_FATAL_CRITICALS MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The old code first checked for == 0, then, if false, executed a fetchAndAdd(-1), both with relaxed memory ordering. This can lead to executions that, counter to what the code comment states, can count down past 0: // T1 T2 loadRelaxed() // true loadRelaxed() // true fetchAndAddRelaxed(-1) // e.g. 1 → 0 fetchAndAddRelaxed(-1) // 0 → -1 while fatality is detected exactly once, this execution doesn't stop at 0 and causes further calls to isFatal() to count down further, with the (very) remote spectre of underflow past INT_MIN. Fix by using a CAS loop instead, so each count-down uses only one step, not two, which therefore can no longer interleave. Fixes: QTBUG-115062 Change-Id: If77b906c94cb4b9fa91bfad84fe63bc8d9103b0a Reviewed-by: Qt CI Bot Reviewed-by: Thiago Macieira (cherry picked from commit b933a5668cc5647d26378f8a9a52901d0497585d) Reviewed-by: Qt Cherry-pick Bot --- src/corelib/global/qlogging.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/corelib/global/qlogging.cpp b/src/corelib/global/qlogging.cpp index d01461ebf3b..b5f79e51b3c 100644 --- a/src/corelib/global/qlogging.cpp +++ b/src/corelib/global/qlogging.cpp @@ -194,7 +194,11 @@ static bool is_fatal_count_down(QAtomicInt &n) { // it's fatal if the current value is exactly 1, // otherwise decrement if it's non-zero - return n.loadRelaxed() && n.fetchAndAddRelaxed(-1) == 1; + + int v = n.loadRelaxed(); + while (v != 0 && !n.testAndSetRelaxed(v, v - 1, v)) + ; + return v == 1; // we exited the loop, so either v == 0 or CAS succeeded to set n from v to v-1 } static bool isFatal(QtMsgType msgType) From fe82d78ce36d692b37fef3f0e608e082baa3eff7 Mon Sep 17 00:00:00 2001 From: Giuseppe D'Angelo Date: Fri, 7 Jul 2023 16:47:08 +0200 Subject: [PATCH 049/151] qtpaths: generate proper JSON The "manual" generation left a trailing comma in the object definition. This is illegal, as per RFC 8259: object = begin-object [ member *( value-separator member ) ] end-object Hence, the resulting JSON does not get accepted by any parser. Let's just not do that and use QJsonDocument. Change-Id: I882486e55f66c52d142638f37584088091bbc123 Fixes: QTBUG-115124 Reviewed-by: Alexandru Croitor Reviewed-by: Alexey Edelev (cherry picked from commit 04f2acf93ad28848808822c9a8e0479509ec5555) Reviewed-by: Qt Cherry-pick Bot --- qmake/propertyprinter.cpp | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/qmake/propertyprinter.cpp b/qmake/propertyprinter.cpp index b57a01c7ab1..3953ae65d50 100644 --- a/qmake/propertyprinter.cpp +++ b/qmake/propertyprinter.cpp @@ -41,6 +41,10 @@ #include +#include +#include +#include + QT_BEGIN_NAMESPACE void qmakePropertyPrinter(const QList> &values) @@ -58,11 +62,12 @@ void qmakePropertyPrinter(const QList> &values) void jsonPropertyPrinter(const QList> &values) { - std::cout << "{\n"; - for (const auto &val : values) { - std::cout << "\"" << qPrintable(val.first) << "\":\"" << qPrintable(val.second) << "\",\n"; - } - std::cout << "}\n"; + QJsonObject object; + for (const auto &val : values) + object.insert(val.first, val.second); + + QJsonDocument document(object); + std::cout << document.toJson().constData(); } QT_END_NAMESPACE From 3eb7fafaf4250f81670ae616432eddb99c9fdb3c Mon Sep 17 00:00:00 2001 From: Mitch Curtis Date: Mon, 26 Jun 2023 15:49:12 +0800 Subject: [PATCH 050/151] Doc: state blacklist condition requirement explicitly Each line with a test function must be followed by a line describing the conditions for ignoring that test function. From what I can see, this wasn't explicitly stated anywhere. Fixes: QTBUG-114825 Change-Id: I1941d6c9a6d56a8374a0c5a99c538cf1eaebd544 Reviewed-by: Edward Welbourne (cherry picked from commit 6b6678bc88e1b53f055b3a7cb8cd30da8ac0e248) Reviewed-by: Qt Cherry-pick Bot --- src/testlib/qtestblacklist.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/testlib/qtestblacklist.cpp b/src/testlib/qtestblacklist.cpp index 845c7abe687..07be132335d 100644 --- a/src/testlib/qtestblacklist.cpp +++ b/src/testlib/qtestblacklist.cpp @@ -78,7 +78,8 @@ QT_BEGIN_NAMESPACE data row's name coincides with that of a local data row, some unintended matches may result; try to keep your data-row tags distinct.) - Subsequent lines give conditions for ignoring this test. + Subsequent lines give conditions for ignoring this test. You need at least + one or the group has no effect. # See qtbase/src/testlib/qtestblacklist.cpp for format # Test doesn't work on QNX at all From 7d5a61eb281f11c5aa80787a3f872786635edeef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Morten=20S=C3=B8rvig?= Date: Wed, 21 Jun 2023 14:48:49 +0200 Subject: [PATCH 051/151] QWizard: Support fractional DPR on Windows MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We were storing the DPR as int; change to qreal. Task-number: QTBUG-114175 Change-Id: I7dc7df82f584cddbbb3f690f1df74e7a30369ab2 Reviewed-by: Tor Arne Vestbø (cherry picked from commit c0e48ed645f68e714e982064540d710676a0738b) Reviewed-by: Morten Johan Sørvig --- src/widgets/dialogs/qwizard_win.cpp | 4 ++-- src/widgets/dialogs/qwizard_win_p.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/widgets/dialogs/qwizard_win.cpp b/src/widgets/dialogs/qwizard_win.cpp index bad692bd940..9c022f98680 100644 --- a/src/widgets/dialogs/qwizard_win.cpp +++ b/src/widgets/dialogs/qwizard_win.cpp @@ -69,7 +69,7 @@ Q_DECLARE_METATYPE(QMargins) QT_BEGIN_NAMESPACE int QVistaHelper::instanceCount = 0; -int QVistaHelper::m_devicePixelRatio = 1; +qreal QVistaHelper::m_devicePixelRatio = 1.0; QVistaHelper::VistaState QVistaHelper::cachedVistaState = QVistaHelper::Dirty; /****************************************************************************** @@ -119,7 +119,7 @@ void QVistaBackButton::paintEvent(QPaintEvent *) RECT clipRect; int xoffset = origin.x() + QWidget::mapToParent(r.topLeft()).x() - 1; int yoffset = origin.y() + QWidget::mapToParent(r.topLeft()).y() - 1; - const int dpr = devicePixelRatio(); + const qreal dpr = devicePixelRatio(); const QRect rDp = QRect(r.topLeft() * dpr, r.size() * dpr); const int xoffsetDp = xoffset * dpr; const int yoffsetDp = yoffset * dpr; diff --git a/src/widgets/dialogs/qwizard_win_p.h b/src/widgets/dialogs/qwizard_win_p.h index 284f1b3d25c..bc124b2e4c4 100644 --- a/src/widgets/dialogs/qwizard_win_p.h +++ b/src/widgets/dialogs/qwizard_win_p.h @@ -152,7 +152,7 @@ private: int titleBarOffset; // Extra spacing above the text int iconSpacing; // Space between button and icon - static int m_devicePixelRatio; + static qreal m_devicePixelRatio; }; From 6c4fc23b942683e42d573356308b696e4f51479c Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Mon, 5 Jun 2023 07:38:55 +0200 Subject: [PATCH 052/151] tst_QScopeGuard: test if and how guard in optional<> works It's a bit cumbersome, but works, in principle, using CTAD. Task-number: QTBUG-114200 Change-Id: Ib7354180e870a695a978edabf684aedfcf9d9ecc Reviewed-by: Jarek Kobus (cherry picked from commit b08ddd2c4ecedccd0bc08e9f2390a7b86ed861f4) Reviewed-by: Qt Cherry-pick Bot --- .../tools/qscopeguard/tst_qscopeguard.cpp | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/tests/auto/corelib/tools/qscopeguard/tst_qscopeguard.cpp b/tests/auto/corelib/tools/qscopeguard/tst_qscopeguard.cpp index 21567137fd6..9584e9178f8 100644 --- a/tests/auto/corelib/tools/qscopeguard/tst_qscopeguard.cpp +++ b/tests/auto/corelib/tools/qscopeguard/tst_qscopeguard.cpp @@ -30,6 +30,8 @@ #include #include +#include + /*! \class tst_QScopeGuard \internal @@ -45,6 +47,7 @@ private Q_SLOTS: void construction(); void constructionFromLvalue(); void constructionFromRvalue(); + void optionalGuard(); void leavingScope(); void exceptions(); }; @@ -154,6 +157,24 @@ void tst_QScopeGuard::constructionFromRvalue() #endif } +void tst_QScopeGuard::optionalGuard() +{ + int i = 0; + auto lambda = [&] { ++i; }; + std::optional sg = false ? std::optional{qScopeGuard(lambda)} : std::nullopt; + QVERIFY(!sg); + QCOMPARE(i, 0); + sg.emplace(qScopeGuard(lambda)); + QVERIFY(sg); + sg->dismiss(); + sg.reset(); + QCOMPARE(i, 0); + sg.emplace(qScopeGuard(lambda)); + QCOMPARE(i, 0); + sg.reset(); + QCOMPARE(i, 1); +} + void tst_QScopeGuard::leavingScope() { auto cleanup = qScopeGuard([] { s_globalState++; QCOMPARE(s_globalState, 3); }); From 425b2523785ea0e1c178ce613ca130a914f394b6 Mon Sep 17 00:00:00 2001 From: Bartlomiej Moskal Date: Tue, 27 Jun 2023 09:14:57 +0200 Subject: [PATCH 053/151] Android: Fix for checking clipboard text mime type Different mime types are widely used on mobile devices. For example all text copied from gmail is copied as text/html type. After 2937cf91c74b6562bf56e8872dfd2bfaafebb3cc commit there is a regression that makes it impossible to paste any text different than "text/plain". To fix it, any "text/*" mime type should be treat as it contains a text (not only "text/plain"). That will allow to paste different text mime types. During this work also tst_qclipboard testset was turned on for Android and new test (getTextFromHTMLMimeType) was added. Fixes: QTBUG-113461 Change-Id: I3ef9476b8facdc3b61f144bd55222898390127c9 Reviewed-by: Assam Boudjelthia (cherry picked from commit fdccb66a4e9a8b22c881c4775895b7af174b0b24) --- .../platforms/android/androidjniclipboard.cpp | 10 ++++----- tests/auto/gui/kernel/CMakeLists.txt | 2 +- .../auto/gui/kernel/qclipboard/test/BLACKLIST | 5 +++++ .../gui/kernel/qclipboard/tst_qclipboard.cpp | 21 ++++++++++++++++++- 4 files changed, 31 insertions(+), 7 deletions(-) create mode 100644 tests/auto/gui/kernel/qclipboard/test/BLACKLIST diff --git a/src/plugins/platforms/android/androidjniclipboard.cpp b/src/plugins/platforms/android/androidjniclipboard.cpp index f1f370948a5..6ca1bc1b1ab 100644 --- a/src/plugins/platforms/android/androidjniclipboard.cpp +++ b/src/plugins/platforms/android/androidjniclipboard.cpp @@ -79,16 +79,16 @@ namespace QtAndroidClipboard "(Ljava/lang/String;)V", QJniObject::fromString(u.toEncoded()).object()); } - } else if (data->hasText()) { // hasText || hasUrls, so the order matter here. - QJniObject::callStaticMethod(applicationClass(), - "setClipboardText", "(Ljava/lang/String;)V", - QJniObject::fromString(data->text()).object()); - } else if (data->hasHtml()) { + } else if (data->hasHtml()) { // html can contain text QJniObject::callStaticMethod(applicationClass(), "setClipboardHtml", "(Ljava/lang/String;Ljava/lang/String;)V", QJniObject::fromString(data->text()).object(), QJniObject::fromString(data->html()).object()); + } else if (data->hasText()) { // hasText must be the last (the order matter here) + QJniObject::callStaticMethod(applicationClass(), + "setClipboardText", "(Ljava/lang/String;)V", + QJniObject::fromString(data->text()).object()); } } diff --git a/tests/auto/gui/kernel/CMakeLists.txt b/tests/auto/gui/kernel/CMakeLists.txt index 7ff4e402802..0e1c86aad48 100644 --- a/tests/auto/gui/kernel/CMakeLists.txt +++ b/tests/auto/gui/kernel/CMakeLists.txt @@ -26,7 +26,7 @@ add_subdirectory(qguiapplication) add_subdirectory(qpixelformat) add_subdirectory(qrasterwindow) add_subdirectory(qaddpostroutine) -if(NOT ANDROID AND NOT UIKIT) +if(NOT UIKIT) add_subdirectory(qclipboard) endif() if(TARGET Qt::Network) diff --git a/tests/auto/gui/kernel/qclipboard/test/BLACKLIST b/tests/auto/gui/kernel/qclipboard/test/BLACKLIST new file mode 100644 index 00000000000..3ca7791b371 --- /dev/null +++ b/tests/auto/gui/kernel/qclipboard/test/BLACKLIST @@ -0,0 +1,5 @@ +# QTBUG-87429 +[testSignals] +android +[setMimeData] +android diff --git a/tests/auto/gui/kernel/qclipboard/tst_qclipboard.cpp b/tests/auto/gui/kernel/qclipboard/tst_qclipboard.cpp index 42af0dea2c6..3f6fe3ad832 100644 --- a/tests/auto/gui/kernel/qclipboard/tst_qclipboard.cpp +++ b/tests/auto/gui/kernel/qclipboard/tst_qclipboard.cpp @@ -66,6 +66,7 @@ private slots: void testSignals(); void setMimeData(); void clearBeforeSetText(); + void getTextFromHTMLMimeType(); # ifdef Q_OS_WIN void testWindowsMimeRegisterType(); void testWindowsMime_data(); @@ -86,7 +87,7 @@ void tst_QClipboard::initTestCase() #if QT_CONFIG(clipboard) void tst_QClipboard::init() { -#if QT_CONFIG(process) +#if QT_CONFIG(process) && !defined(Q_OS_ANDROID) const QString testdataDir = QFileInfo(QFINDTESTDATA("copier")).absolutePath(); QVERIFY2(QDir::setCurrent(testdataDir), qPrintable("Could not chdir to " + testdataDir)); #endif @@ -449,6 +450,24 @@ void tst_QClipboard::clearBeforeSetText() QCOMPARE(QGuiApplication::clipboard()->text(), text); } +void tst_QClipboard::getTextFromHTMLMimeType() +{ + QClipboard * clipboard = QGuiApplication::clipboard(); + QMimeData * mimeData = new QMimeData(); + const QString testString("TEST"); + const QString htmlString(QLatin1String("") + testString + QLatin1String("")); + + mimeData->setText(testString); + mimeData->setHtml(htmlString); + clipboard->setMimeData(mimeData); + + QCOMPARE(clipboard->text(), testString); + QVERIFY(clipboard->mimeData()->hasText()); + QVERIFY(clipboard->mimeData()->hasHtml()); + QCOMPARE(clipboard->mimeData()->text(), testString); + QCOMPARE(clipboard->mimeData()->html(), htmlString); +} + # ifdef Q_OS_WIN using QWindowsMime = QNativeInterface::Private::QWindowsMime; From 7f7287ab5502106b2842d0587a9d909590f35d1c Mon Sep 17 00:00:00 2001 From: Axel Spoerl Date: Fri, 30 Jun 2023 12:43:59 +0200 Subject: [PATCH 054/151] QXmlStreamReader: Raise error on unexpected tokens MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit QXmlStreamReader accepted multiple DOCTYPE elements, containing DTD fragments in the XML prolog, and in the XML body. Well-formed but invalid XML files - with multiple DTD fragments in prolog and body, combined with recursive entity expansions - have caused infinite loops in QXmlStreamReader. This patch implements a token check in QXmlStreamReader. A stream is allowed to start with an XML prolog. StartDocument and DOCTYPE elements are only allowed in this prolog, which may also contain ProcessingInstruction and Comment elements. As soon as anything else is seen, the prolog ends. After that, the prolog-specific elements are treated as unexpected. Furthermore, the prolog can contain at most one DOCTYPE element. Update the documentation to reflect the new behavior. Add an autotest that checks the new error cases are correctly detected, and no error is raised for legitimate input. The original OSS-Fuzz files (see bug reports) are not included in this patch for file size reasons. They have been tested manually. Each of them has more than one DOCTYPE element, causing infinite loops in recursive entity expansions. The newly implemented functionality detects those invalid DTD fragments. By raising an error, it aborts stream reading before an infinite loop occurs. Thanks to OSS-Fuzz for finding this. Fixes: QTBUG-92113 Fixes: QTBUG-95188 Change-Id: I0a082b9188b2eee50b396c4d5b1c9e1fd237bbdd Reviewed-by: Volker Hilsheimer (cherry picked from commit c4301be7d5f94852e1b17f2c2989d5ca807855d4) Reviewed-by: Mårten Nordheim --- src/corelib/serialization/qxmlstream.cpp | 142 +++++++++++++++++- src/corelib/serialization/qxmlstream_p.h | 11 ++ .../qxmlstream/tokenError/dtdInBody.xml | 20 +++ .../qxmlstream/tokenError/multipleDtd.xml | 20 +++ .../qxmlstream/tokenError/wellFormed.xml | 15 ++ .../qxmlstream/tst_qxmlstream.cpp | 39 +++++ 6 files changed, 239 insertions(+), 8 deletions(-) create mode 100644 tests/auto/corelib/serialization/qxmlstream/tokenError/dtdInBody.xml create mode 100644 tests/auto/corelib/serialization/qxmlstream/tokenError/multipleDtd.xml create mode 100644 tests/auto/corelib/serialization/qxmlstream/tokenError/wellFormed.xml diff --git a/src/corelib/serialization/qxmlstream.cpp b/src/corelib/serialization/qxmlstream.cpp index 598b9f0428f..885354ff792 100644 --- a/src/corelib/serialization/qxmlstream.cpp +++ b/src/corelib/serialization/qxmlstream.cpp @@ -174,7 +174,7 @@ void reversed(const Range &&) = delete; addData() or by waiting for it to arrive on the device(). \value UnexpectedElementError The parser encountered an element - that was different to those it expected. + or token that was different to those it expected. */ @@ -309,13 +309,34 @@ QXmlStreamEntityResolver *QXmlStreamReader::entityResolver() const QXmlStreamReader is a well-formed XML 1.0 parser that does \e not include external parsed entities. As long as no error occurs, the - application code can thus be assured that the data provided by the - stream reader satisfies the W3C's criteria for well-formed XML. For - example, you can be certain that all tags are indeed nested and - closed properly, that references to internal entities have been - replaced with the correct replacement text, and that attributes have - been normalized or added according to the internal subset of the - DTD. + application code can thus be assured, that + \list + \li the data provided by the stream reader satisfies the W3C's + criteria for well-formed XML, + \li tokens are provided in a valid order. + \endlist + + Unless QXmlStreamReader raises an error, it guarantees the following: + \list + \li All tags are nested and closed properly. + \li References to internal entities have been replaced with the + correct replacement text. + \li Attributes have been normalized or added according to the + internal subset of the \l DTD. + \li Tokens of type \l StartDocument happen before all others, + aside from comments and processing instructions. + \li At most one DOCTYPE element (a token of type \l DTD) is present. + \li If present, the DOCTYPE appears before all other elements, + aside from StartDocument, comments and processing instructions. + \endlist + + In particular, once any token of type \l StartElement, \l EndElement, + \l Characters, \l EntityReference or \l EndDocument is seen, no + tokens of type StartDocument or DTD will be seen. If one is present in + the input stream, out of order, an error is raised. + + \note The token types \l Comment and \l ProcessingInstruction may appear + anywhere in the stream. If an error occurs while parsing, atEnd() and hasError() return true, and error() returns the error that occurred. The functions @@ -618,6 +639,7 @@ QXmlStreamReader::TokenType QXmlStreamReader::readNext() d->token = -1; return readNext(); } + d->checkToken(); return d->type; } @@ -737,6 +759,13 @@ static const short QXmlStreamReader_tokenTypeString_indices[] = { 0, 8, 16, 30, 42, 55, 66, 77, 85, 89, 105, 0 }; +static const char QXmlStreamReader_XmlContextString[] = + "Prolog\0" + "Body\0"; + +static const short QXmlStreamReader_XmlContextString_indices[] = { + 0, 7 +}; /*! \property QXmlStreamReader::namespaceProcessing @@ -773,6 +802,16 @@ QString QXmlStreamReader::tokenString() const QXmlStreamReader_tokenTypeString_indices[d->type]); } +/*! + \internal + \return \param ctxt (Prolog/Body) as a string. + */ +QString contextString(QXmlStreamReaderPrivate::XmlContext ctxt) +{ + return QLatin1String(QXmlStreamReader_XmlContextString + + QXmlStreamReader_XmlContextString_indices[static_cast(ctxt)]); +} + #endif // QT_NO_XMLSTREAMREADER QXmlStreamPrivateTagStack::QXmlStreamPrivateTagStack() @@ -860,6 +899,8 @@ void QXmlStreamReaderPrivate::init() type = QXmlStreamReader::NoToken; error = QXmlStreamReader::NoError; + currentContext = XmlContext::Prolog; + foundDTD = false; } /* @@ -3769,6 +3810,91 @@ void QXmlStreamWriter::writeCurrentToken(const QXmlStreamReader &reader) } } +static constexpr bool isTokenAllowedInContext(QXmlStreamReader::TokenType type, + QXmlStreamReaderPrivate::XmlContext loc) +{ + switch (type) { + case QXmlStreamReader::StartDocument: + case QXmlStreamReader::DTD: + return loc == QXmlStreamReaderPrivate::XmlContext::Prolog; + + case QXmlStreamReader::StartElement: + case QXmlStreamReader::EndElement: + case QXmlStreamReader::Characters: + case QXmlStreamReader::EntityReference: + case QXmlStreamReader::EndDocument: + return loc == QXmlStreamReaderPrivate::XmlContext::Body; + + case QXmlStreamReader::Comment: + case QXmlStreamReader::ProcessingInstruction: + return true; + + case QXmlStreamReader::NoToken: + case QXmlStreamReader::Invalid: + return false; + } + return false; +} + +/*! + \internal + \brief QXmlStreamReader::isValidToken + \return \c true if \param type is a valid token type. + \return \c false if \param type is an unexpected token, + which indicates a non-well-formed or invalid XML stream. + */ +bool QXmlStreamReaderPrivate::isValidToken(QXmlStreamReader::TokenType type) +{ + // Don't change currentContext, if Invalid or NoToken occur in the prolog + if (type == QXmlStreamReader::Invalid || type == QXmlStreamReader::NoToken) + return false; + + // If a token type gets rejected in the body, there is no recovery + const bool result = isTokenAllowedInContext(type, currentContext); + if (result || currentContext == XmlContext::Body) + return result; + + // First non-Prolog token observed => switch context to body and check again. + currentContext = XmlContext::Body; + return isTokenAllowedInContext(type, currentContext); +} + +/*! + \internal + Checks token type and raises an error, if it is invalid + in the current context (prolog/body). + */ +void QXmlStreamReaderPrivate::checkToken() +{ + Q_Q(QXmlStreamReader); + + // The token type must be consumed, to keep track if the body has been reached. + const XmlContext context = currentContext; + const bool ok = isValidToken(type); + + // Do nothing if an error has been raised already (going along with an unexpected token) + if (error != QXmlStreamReader::Error::NoError) + return; + + if (!ok) { + raiseError(QXmlStreamReader::UnexpectedElementError, + QLatin1String("Unexpected token type %1 in %2.") + .arg(q->tokenString(), contextString(context))); + return; + } + + if (type != QXmlStreamReader::DTD) + return; + + // Raise error on multiple DTD tokens + if (foundDTD) { + raiseError(QXmlStreamReader::UnexpectedElementError, + QLatin1String("Found second DTD token in %1.").arg(contextString(context))); + } else { + foundDTD = true; + } +} + /*! \fn bool QXmlStreamAttributes::hasAttribute(const QString &qualifiedName) const \since 4.5 diff --git a/src/corelib/serialization/qxmlstream_p.h b/src/corelib/serialization/qxmlstream_p.h index a277753f188..c33f1cd44f9 100644 --- a/src/corelib/serialization/qxmlstream_p.h +++ b/src/corelib/serialization/qxmlstream_p.h @@ -302,6 +302,17 @@ public: QStringDecoder decoder; bool atEnd; + enum class XmlContext + { + Prolog, + Body, + }; + + XmlContext currentContext = XmlContext::Prolog; + bool foundDTD = false; + bool isValidToken(QXmlStreamReader::TokenType type); + void checkToken(); + /*! \sa setType() */ diff --git a/tests/auto/corelib/serialization/qxmlstream/tokenError/dtdInBody.xml b/tests/auto/corelib/serialization/qxmlstream/tokenError/dtdInBody.xml new file mode 100644 index 00000000000..1c3ca4e2711 --- /dev/null +++ b/tests/auto/corelib/serialization/qxmlstream/tokenError/dtdInBody.xml @@ -0,0 +1,20 @@ + + + + + + + + +]> + + + tst_QXmlStream + + + + + ]> + diff --git a/tests/auto/corelib/serialization/qxmlstream/tokenError/multipleDtd.xml b/tests/auto/corelib/serialization/qxmlstream/tokenError/multipleDtd.xml new file mode 100644 index 00000000000..cd398c0f9fd --- /dev/null +++ b/tests/auto/corelib/serialization/qxmlstream/tokenError/multipleDtd.xml @@ -0,0 +1,20 @@ + + + + + + + + +]> + + + +]> + + + tst_QXmlStream + + diff --git a/tests/auto/corelib/serialization/qxmlstream/tokenError/wellFormed.xml b/tests/auto/corelib/serialization/qxmlstream/tokenError/wellFormed.xml new file mode 100644 index 00000000000..1b61a3f0622 --- /dev/null +++ b/tests/auto/corelib/serialization/qxmlstream/tokenError/wellFormed.xml @@ -0,0 +1,15 @@ + + + + + + + + +]> + + + tst_QXmlStream + + diff --git a/tests/auto/corelib/serialization/qxmlstream/tst_qxmlstream.cpp b/tests/auto/corelib/serialization/qxmlstream/tst_qxmlstream.cpp index 8327f03cd58..2da9ad949b1 100644 --- a/tests/auto/corelib/serialization/qxmlstream/tst_qxmlstream.cpp +++ b/tests/auto/corelib/serialization/qxmlstream/tst_qxmlstream.cpp @@ -611,6 +611,9 @@ private slots: void entityExpansionLimit() const; + void tokenErrorHandling_data() const; + void tokenErrorHandling() const; + private: static QByteArray readFile(const QString &filename); @@ -1818,5 +1821,41 @@ void tst_QXmlStream::test_fastScanName() const QCOMPARE(reader.error(), errorType); } +void tst_QXmlStream::tokenErrorHandling_data() const +{ + QTest::addColumn("fileName"); + QTest::addColumn("expectedError"); + QTest::addColumn("errorKeyWord"); + + constexpr auto invalid = QXmlStreamReader::Error::UnexpectedElementError; + constexpr auto valid = QXmlStreamReader::Error::NoError; + QTest::newRow("DtdInBody") << "dtdInBody.xml" << invalid << "DTD"; + QTest::newRow("multipleDTD") << "multipleDtd.xml" << invalid << "second DTD"; + QTest::newRow("wellFormed") << "wellFormed.xml" << valid << ""; +} + +void tst_QXmlStream::tokenErrorHandling() const +{ + QFETCH(const QString, fileName); + QFETCH(const QXmlStreamReader::Error, expectedError); + QFETCH(const QString, errorKeyWord); + + const QDir dir(QFINDTESTDATA("tokenError")); + QFile file(dir.absoluteFilePath(fileName)); + + // Cross-compiling: File will be on host only + if (!file.exists()) + QSKIP("Testfile not found."); + + file.open(QIODevice::ReadOnly); + QXmlStreamReader reader(&file); + while (!reader.atEnd()) + reader.readNext(); + + QCOMPARE(reader.error(), expectedError); + if (expectedError != QXmlStreamReader::Error::NoError) + QVERIFY(reader.errorString().contains(errorKeyWord)); +} + #include "tst_qxmlstream.moc" // vim: et:ts=4:sw=4:sts=4 From 26940b125979f35a5a605e93ecdc5ca5a041d758 Mon Sep 17 00:00:00 2001 From: Axel Spoerl Date: Tue, 11 Jul 2023 13:51:44 +0200 Subject: [PATCH 055/151] tst_QXmlStream::tokenErrorHandling() - register test directory in CMake MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Register the directory tokenError in the build system to expose it to embedded devices / for cross compiling. Do not fail the test function, when a test file isn't found. The tested functionality is platform independent and will be tested on other platforms. Task-number: QTBUG-92113 Task-number: QTBUG-95188 Change-Id: I885d8fdfbbf8ec60e6326bfd871fa85a4390247d Reviewed-by: Jan Arve Sæther (cherry picked from commit b476570932dcfc1b32e8405bcdd219c2dcc421f7) Reviewed-by: Qt CI Bot --- .../auto/corelib/serialization/qxmlstream/CMakeLists.txt | 8 +++++++- .../corelib/serialization/qxmlstream/tst_qxmlstream.cpp | 5 +++-- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/tests/auto/corelib/serialization/qxmlstream/CMakeLists.txt b/tests/auto/corelib/serialization/qxmlstream/CMakeLists.txt index f132bd86b14..548c912975d 100644 --- a/tests/auto/corelib/serialization/qxmlstream/CMakeLists.txt +++ b/tests/auto/corelib/serialization/qxmlstream/CMakeLists.txt @@ -9,11 +9,17 @@ file(GLOB_RECURSE test_data RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} data/* XML-Test-Suite/*) +file(GLOB_RECURSE tokenError + RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} + tokenError/* XML-token-error/*) + qt_internal_add_test(tst_qxmlstream SOURCES tst_qxmlstream.cpp LIBRARIES Qt::Network Qt::GuiPrivate - TESTDATA ${test_data} + TESTDATA + ${test_data} + ${tokenError} ) diff --git a/tests/auto/corelib/serialization/qxmlstream/tst_qxmlstream.cpp b/tests/auto/corelib/serialization/qxmlstream/tst_qxmlstream.cpp index 2da9ad949b1..e06e66ed566 100644 --- a/tests/auto/corelib/serialization/qxmlstream/tst_qxmlstream.cpp +++ b/tests/auto/corelib/serialization/qxmlstream/tst_qxmlstream.cpp @@ -1843,9 +1843,10 @@ void tst_QXmlStream::tokenErrorHandling() const const QDir dir(QFINDTESTDATA("tokenError")); QFile file(dir.absoluteFilePath(fileName)); - // Cross-compiling: File will be on host only + // Cross-compiling: Files may not be found when running test standalone + // QSKIP in that case, because the tested functionality is platform independent. if (!file.exists()) - QSKIP("Testfile not found."); + QSKIP(QObject::tr("Testfile %1 not found.").arg(fileName).toUtf8().constData()); file.open(QIODevice::ReadOnly); QXmlStreamReader reader(&file); From 00712c7771900334f9f58ae95e5d23705c72d4a4 Mon Sep 17 00:00:00 2001 From: Alexandru Croitor Date: Wed, 12 Jul 2023 11:13:14 +0200 Subject: [PATCH 056/151] moc: Store errno after fopen call To avoid QFile::encodeName() potentially overriding the value. Task-number: QTBUG-101926 Change-Id: Ie751df877d6624238ded344474b5eccc324ec541 Reviewed-by: Fabian Kosmale (cherry picked from commit dd1b7b5539d6aecdd5f8342ef0fa260e40f5c483) Reviewed-by: Qt Cherry-pick Bot --- src/tools/moc/main.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/tools/moc/main.cpp b/src/tools/moc/main.cpp index 97be0f6548a..3afc947d2fa 100644 --- a/src/tools/moc/main.cpp +++ b/src/tools/moc/main.cpp @@ -556,9 +556,12 @@ int runMoc(int argc, char **argv) f = fopen(QFile::encodeName(jsonOutputFileName).constData(), "w"); if (!f) #endif + { + const auto fopen_errno = errno; fprintf(stderr, "moc: Cannot create JSON output file %s. %s\n", QFile::encodeName(jsonOutputFileName).constData(), - strerror(errno)); + strerror(fopen_errno)); + } jsonOutput.reset(f); } } else { // use stdout @@ -603,9 +606,12 @@ int runMoc(int argc, char **argv) depFileHandleRaw = fopen(QFile::encodeName(depOutputFileName).constData(), "w"); if (!depFileHandleRaw) #endif + { + const auto fopen_errno = errno; fprintf(stderr, "moc: Cannot create dep output file '%s'. %s\n", QFile::encodeName(depOutputFileName).constData(), - strerror(errno)); + strerror(fopen_errno)); + } depFileHandle.reset(depFileHandleRaw); if (!depFileHandle.isNull()) { From 3d0ef9b4f4710fc64892bdcf03d7271e0e02ef05 Mon Sep 17 00:00:00 2001 From: Alexandru Croitor Date: Wed, 12 Jul 2023 10:31:04 +0200 Subject: [PATCH 057/151] moc: Print sterror(errno) when moc can't write the output file Also prepend a "Error:" label to all strrerror handling locations, to make it clear where the error starts. Task-number: QTBUG-101926 Change-Id: I1a781b4c5716636eff4d47a6c8554dcbd51d2697 Reviewed-by: Fabian Kosmale (cherry picked from commit 3ba3f322b6b1781cfc1a64be8240b1ae74c36840) Reviewed-by: Qt Cherry-pick Bot --- src/tools/moc/main.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/tools/moc/main.cpp b/src/tools/moc/main.cpp index 3afc947d2fa..09c1c0ec534 100644 --- a/src/tools/moc/main.cpp +++ b/src/tools/moc/main.cpp @@ -543,7 +543,10 @@ int runMoc(int argc, char **argv) if (!out) #endif { - fprintf(stderr, "moc: Cannot create %s\n", QFile::encodeName(output).constData()); + const auto fopen_errno = errno; + fprintf(stderr, "moc: Cannot create %s. Error: %s\n", + QFile::encodeName(output).constData(), + strerror(fopen_errno)); return 1; } @@ -558,7 +561,7 @@ int runMoc(int argc, char **argv) #endif { const auto fopen_errno = errno; - fprintf(stderr, "moc: Cannot create JSON output file %s. %s\n", + fprintf(stderr, "moc: Cannot create JSON output file %s. Error: %s\n", QFile::encodeName(jsonOutputFileName).constData(), strerror(fopen_errno)); } @@ -608,7 +611,7 @@ int runMoc(int argc, char **argv) #endif { const auto fopen_errno = errno; - fprintf(stderr, "moc: Cannot create dep output file '%s'. %s\n", + fprintf(stderr, "moc: Cannot create dep output file '%s'. Error: %s\n", QFile::encodeName(depOutputFileName).constData(), strerror(fopen_errno)); } From 563eaed396f76df56417ec1dba5fbcf440900df6 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Fri, 14 Jul 2023 11:48:06 +0200 Subject: [PATCH 058/151] tst_QParallelAnimationGroup: fix memleak MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Setting the parent of a QObject to nullptr means the ex-parent no longer owns and deletes the object as its child, leaking it. Fix by creating a scope-guard to defer deletion until the tests have run. This is simpler than the alternatives: Putting it into unique_ptr would require a new variable name, or a larger refactoring of the function, because the `test` variable is being re-used for many different objects in the course of the function, most of which should not be deleted. Using QAutoPointer would drag in QtWidgetsPrivate, and the class is probably not available in all active branches. Finally, deleteLater() would require reliably returning to the event loop, which may not happen if the test is run in isolation. Bug exists since the dawn of the public history, and QScopeGuard is available in all active branches. Change-Id: Ib4fcb44b0b68d4ccbcf5af144a18ffb378a72213 Reviewed-by: Mårten Nordheim Reviewed-by: Ivan Solovev (cherry picked from commit e667624371613fad17b09d106e2eb80d581e0e0f) Reviewed-by: Qt Cherry-pick Bot --- .../qparallelanimationgroup/tst_qparallelanimationgroup.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/auto/corelib/animation/qparallelanimationgroup/tst_qparallelanimationgroup.cpp b/tests/auto/corelib/animation/qparallelanimationgroup/tst_qparallelanimationgroup.cpp index 6cf7e5cb948..5711ddf819e 100644 --- a/tests/auto/corelib/animation/qparallelanimationgroup/tst_qparallelanimationgroup.cpp +++ b/tests/auto/corelib/animation/qparallelanimationgroup/tst_qparallelanimationgroup.cpp @@ -32,6 +32,7 @@ #include #include +#include Q_DECLARE_METATYPE(QAbstractAnimation::State) @@ -953,6 +954,7 @@ void tst_QParallelAnimationGroup::autoAdd() test = static_cast(group.animationAt(0)); test->setParent(0); // remove the last one (with duration = 250) + const auto deleteParentlessObject = qScopeGuard([test] { delete test; }); QCOMPARE(test->group(), static_cast(0)); QCOMPARE(group.duration(), 0); } From 2fc24a907556780cb04c313e9479232f13e70683 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Fri, 14 Jul 2023 11:48:06 +0200 Subject: [PATCH 059/151] tst_QNetworkCookieJar: fix memleak MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit QTest::toString() returns a new[]'ed char array, which needs to be manually deleted and QVERIFY2() doesn't take ownership of its second argument. Fix by wrapping in unique_ptr(...).get(). Bug exists since the dawn of the public history. Change-Id: I19ec09f46ec0ce5eacf1437f62dc625bc9343831 Reviewed-by: Mårten Nordheim (cherry picked from commit d3c08df330f615dc3a248fd0c346a5c1ad6e1c38) Reviewed-by: Qt Cherry-pick Bot --- .../access/qnetworkcookiejar/tst_qnetworkcookiejar.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/auto/network/access/qnetworkcookiejar/tst_qnetworkcookiejar.cpp b/tests/auto/network/access/qnetworkcookiejar/tst_qnetworkcookiejar.cpp index a4e756a1da0..9c8e2e56870 100644 --- a/tests/auto/network/access/qnetworkcookiejar/tst_qnetworkcookiejar.cpp +++ b/tests/auto/network/access/qnetworkcookiejar/tst_qnetworkcookiejar.cpp @@ -40,6 +40,8 @@ #include "private/qurltlds_p.h" #endif +#include + class tst_QNetworkCookieJar: public QObject { Q_OBJECT @@ -255,7 +257,7 @@ void tst_QNetworkCookieJar::setCookiesFromUrl() QVERIFY2(result.contains(cookie), cookie.toRawForm()); result.removeAll(cookie); } - QVERIFY2(result.isEmpty(), QTest::toString(result)); + QVERIFY2(result.isEmpty(), std::unique_ptr(QTest::toString(result)).get()); } void tst_QNetworkCookieJar::cookiesForUrl_data() From c30b074b673e8fb41681176d8a404fb65cc77359 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Fri, 14 Jul 2023 14:35:46 +0200 Subject: [PATCH 060/151] tst_QTcpSocket: fix mem-leak earlyConstructedSockets is a QObject, but had no parent and was never deleted, leaking all the data is holds. Fix by giving it a parent. The code predates the begin of the public history. Change-Id: Ibc5688afd6111e84f591c37e39b6bb618d76c47a Reviewed-by: Ivan Solovev Reviewed-by: Thiago Macieira (cherry picked from commit 8cb542c2d430ffc5a6d63c404c7e700132e6364a) Reviewed-by: Qt Cherry-pick Bot --- tests/auto/network/socket/qtcpsocket/tst_qtcpsocket.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/auto/network/socket/qtcpsocket/tst_qtcpsocket.cpp b/tests/auto/network/socket/qtcpsocket/tst_qtcpsocket.cpp index 005fa165c1d..70767ecb213 100644 --- a/tests/auto/network/socket/qtcpsocket/tst_qtcpsocket.cpp +++ b/tests/auto/network/socket/qtcpsocket/tst_qtcpsocket.cpp @@ -312,7 +312,7 @@ tst_QTcpSocket::tst_QTcpSocket() tmpSocket = 0; //This code relates to the socketsConstructedBeforeEventLoop test case - earlyConstructedSockets = new SocketPair; + earlyConstructedSockets = new SocketPair(this); QVERIFY(earlyConstructedSockets->create()); earlyBytesWrittenCount = 0; earlyReadyReadCount = 0; From ea77cd036942c7e5d10862aad7c8737e633ce5e9 Mon Sep 17 00:00:00 2001 From: Edward Welbourne Date: Fri, 24 Mar 2023 14:21:12 +0100 Subject: [PATCH 061/151] tst_QDateTime: Remove two duplicate test cases Change-Id: I36541b5c6f7c35deee9678e2f736e1db9f36039f Reviewed-by: Jason McDonald (cherry picked from commit a076fdfec60c4b82ac7c5f4eff128ff1a0615a18) Reviewed-by: Edward Welbourne --- tests/auto/corelib/time/qdatetime/tst_qdatetime.cpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/tests/auto/corelib/time/qdatetime/tst_qdatetime.cpp b/tests/auto/corelib/time/qdatetime/tst_qdatetime.cpp index af54b5d8194..12521cd1992 100644 --- a/tests/auto/corelib/time/qdatetime/tst_qdatetime.cpp +++ b/tests/auto/corelib/time/qdatetime/tst_qdatetime.cpp @@ -2634,8 +2634,6 @@ void tst_QDateTime::fromStringDateFormat_data() << Qt::RFC2822Date << QDateTime(QDate(1987, 2, 13), QTime(14, 24, 51), Qt::UTC); QTest::newRow("RFC 850 and 1036 +0000") << QString::fromLatin1("Thu Jan 01 00:12:34 1970 +0000") << Qt::RFC2822Date << QDateTime(QDate(1970, 1, 1), QTime(0, 12, 34), Qt::UTC); - QTest::newRow("RFC 850 and 1036 +0000") << QString::fromLatin1("Thu Jan 01 00:12:34 1970 +0000") - << Qt::RFC2822Date << QDateTime(QDate(1970, 1, 1), QTime(0, 12, 34), Qt::UTC); // No timezone assume UTC QTest::newRow("RFC 850 and 1036 no timezone") << QString::fromLatin1("Thu Jan 01 00:12:34 1970") << Qt::RFC2822Date << QDateTime(QDate(1970, 1, 1), QTime(0, 12, 34), Qt::UTC); @@ -2767,9 +2765,6 @@ void tst_QDateTime::fromStringStringFormat_data() QTest::newRow("offset-from-utc:3-digit-with-colon") << QString("2008-10-13 -4:30 11.50") << QString("yyyy-MM-dd t hh.mm") << QDateTime(QDate(2008, 10, 13), QTime(11, 50), Qt::OffsetFromUTC, -16200); - QTest::newRow("offset-from-utc:merged-with-time") - << QString("2008-10-13 UTC+010011.50") << QString("yyyy-MM-dd thh.mm") - << QDateTime(QDate(2008, 10, 13), QTime(11, 50), Qt::OffsetFromUTC, 3600); QTest::newRow("offset-from-utc:with-colon-merged-with-time") << QString("2008-10-13 UTC+01:0011.50") << QString("yyyy-MM-dd thh.mm") << QDateTime(QDate(2008, 10, 13), QTime(11, 50), Qt::OffsetFromUTC, 3600); From e307f57e9daddb218e638061b94fff5506ef5004 Mon Sep 17 00:00:00 2001 From: Axel Spoerl Date: Thu, 13 Jul 2023 15:48:46 +0200 Subject: [PATCH 062/151] QWidget: Don't re-use backing store on Android MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit QWidget re-uses backing stores created in QWidgetPrivate::create(). The Android platform plugin creates a new platform window, when a widget becomes a toplevel window. When it is hidden, the platform window is deleted. The link between QAndroidPlatformWindow and its backing store is made in the constructor of QAndroidPlatformBackingstore. When a new QAndroidPlatformWindow is constructed and the backing store is re-used, there is no more link between platform window and platform backing store. This has lead to screen assets not being painted, when shown more than once. This patch forces QWidgetPrivate::create() to construct a new backing store on Android. This way, toplevel windows always have a backing store associated with it. It adds an assertion to QAndroidPlatformScreen::addWindow(). That will make e.g. tst_QWidget::visible() crash without the fix. Fixes: QTBUG-97482 Change-Id: Ib1b172068b03549df161ab93ac24a273221d5423 Reviewed-by: Jan Arve Sæther (cherry picked from commit dbb072eb2838a04e89e34dad686394a496d5de87) Reviewed-by: Qt CI Bot --- src/plugins/platforms/android/qandroidplatformscreen.cpp | 3 ++- src/widgets/kernel/qwidget.cpp | 7 ++++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/plugins/platforms/android/qandroidplatformscreen.cpp b/src/plugins/platforms/android/qandroidplatformscreen.cpp index 1b3086483f3..bbd44bac69e 100644 --- a/src/plugins/platforms/android/qandroidplatformscreen.cpp +++ b/src/plugins/platforms/android/qandroidplatformscreen.cpp @@ -79,7 +79,7 @@ public: } private: - QTime m_timer; + QElapsedTimer m_timer; QString m_msg; }; @@ -188,6 +188,7 @@ bool QAndroidPlatformScreen::event(QEvent *event) void QAndroidPlatformScreen::addWindow(QAndroidPlatformWindow *window) { + Q_ASSERT(window->backingStore()); if (window->parent() && window->isRaster()) return; diff --git a/src/widgets/kernel/qwidget.cpp b/src/widgets/kernel/qwidget.cpp index 324fa7ceced..510ed44a53b 100644 --- a/src/widgets/kernel/qwidget.cpp +++ b/src/widgets/kernel/qwidget.cpp @@ -1327,8 +1327,13 @@ void QWidgetPrivate::create() } #endif + // Android doesn't allow to re-use the backing store. + // => force creation of a new one. +#ifdef Q_OS_ANDROID + QBackingStore *store = nullptr; +#else QBackingStore *store = q->backingStore(); - +#endif if (!store) { if (q->windowType() != Qt::Desktop) { if (q->isWindow()) From 7bcaf5190b1c7288cb7095ecd6890db51b0b7153 Mon Sep 17 00:00:00 2001 From: Edward Welbourne Date: Fri, 24 Mar 2023 15:09:48 +0100 Subject: [PATCH 063/151] Correct time zone in tst_QDateTimeEdit::stepIntoDSTGap() Given that QDTE only supports local time and UTC, using Europe/Oslo as zone was disconnected from reality, especially as various QDateTime()s were constructed using local time. Use the system zone. Change-Id: I95b3a6a6acf9ffc2b8c7f05d3dd9440ff173abfe Reviewed-by: Volker Hilsheimer (cherry picked from commit 919d2e0c5a844da1ca87b554fb7b8060a520e640) Reviewed-by: Qt Cherry-pick Bot --- tests/auto/widgets/widgets/qdatetimeedit/tst_qdatetimeedit.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/auto/widgets/widgets/qdatetimeedit/tst_qdatetimeedit.cpp b/tests/auto/widgets/widgets/qdatetimeedit/tst_qdatetimeedit.cpp index 5f003928c00..ef395db56c5 100644 --- a/tests/auto/widgets/widgets/qdatetimeedit/tst_qdatetimeedit.cpp +++ b/tests/auto/widgets/widgets/qdatetimeedit/tst_qdatetimeedit.cpp @@ -4738,7 +4738,7 @@ void tst_QDateTimeEdit::stepIntoDSTGap_data() QTest::addColumn("steps"); QTest::addColumn("end"); - const QTimeZone timeZone = QTimeZone("Europe/Oslo"); + const QTimeZone timeZone = QTimeZone::systemTimeZone(); if (!timeZone.hasDaylightTime()) QSKIP("This test needs to run in a timezone that observes DST!"); From 7fb98f796f0f03622e028fd85c3a761f7cb1a508 Mon Sep 17 00:00:00 2001 From: Edward Welbourne Date: Fri, 24 Mar 2023 13:22:10 +0100 Subject: [PATCH 064/151] Improve QTimeZone's documentation about territories MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Clarify that a zone whose territory() is AnyTerritory may simply not have a known association, or cover several territories. Added more \sa links to territory(), where relevant. Fix some surviving uses of country for territory. Split some long lines. Change-Id: I9196f785afed9bc185a459608c5d9361127401cb Reviewed-by: Thiago Macieira (cherry picked from commit 455abef6c659b370bb84dbc686373f830198a330) Reviewed-by: Mårten Nordheim --- src/corelib/time/qtimezone.cpp | 44 +++++++++++++++++++++------------- 1 file changed, 28 insertions(+), 16 deletions(-) diff --git a/src/corelib/time/qtimezone.cpp b/src/corelib/time/qtimezone.cpp index 6c088a80487..17e15ce5878 100644 --- a/src/corelib/time/qtimezone.cpp +++ b/src/corelib/time/qtimezone.cpp @@ -383,6 +383,8 @@ QTimeZone::QTimeZone(int offsetSeconds) If the custom time zone does not have a specific territory then set it to the default value of QLocale::AnyTerritory. + + \sa id(), offsetFromUtc(), displayName(), abbreviation(), territory(), comment() */ QTimeZone::QTimeZone(const QByteArray &ianaId, int offsetSeconds, const QString &name, @@ -494,6 +496,14 @@ QByteArray QTimeZone::id() const \since 6.2 Returns the territory for the time zone. + + A return of \l {QLocale::}{AnyTerritory} means the zone has no known + territorial association. In some cases this may be because the zone has no + associated territory - for example, UTC - or because the zone is used in + several territories - for example, CET. In other cases, the QTimeZone + backend may not know which territory the zone is associated with - for + example, because it is not the primary zone of the territory in which it is + used. */ QLocale::Territory QTimeZone::territory() const { @@ -863,12 +873,12 @@ QList QTimeZone::availableTimeZoneIds() /*! Returns a list of all available IANA time zone IDs for a given \a territory. - As a special case, a \a territory of Qt::AnyTerritory returns those time zones - that do not have any territory related to them, such as UTC. If you require - a list of all time zone IDs for all countries then use the standard - availableTimeZoneIds() method. + As a special case, a \a territory of \l {QLocale::}{AnyTerritory} selects + those time zones that have no kown territorial association, such as UTC. If + you require a list of all time zone IDs for all territories then use the + standard availableTimeZoneIds() method. - \sa isTimeZoneIdAvailable() + \sa isTimeZoneIdAvailable(), territory() */ QList QTimeZone::availableTimeZoneIds(QLocale::Territory territory) @@ -905,9 +915,9 @@ QByteArray QTimeZone::ianaIdToWindowsId(const QByteArray &ianaId) Returns the default IANA ID for a given \a windowsId. Because a Windows ID can cover several IANA IDs in several different - countries, this function returns the most frequently used IANA ID with no - regard for the country and should thus be used with care. It is usually - best to request the default for a specific country. + territories, this function returns the most frequently used IANA ID with no + regard for the territory and should thus be used with care. It is usually + best to request the default for a specific territory. \sa ianaIdToWindowsId(), windowsIdToIanaIds() */ @@ -923,13 +933,14 @@ QByteArray QTimeZone::windowsIdToDefaultIanaId(const QByteArray &windowsId) Because a Windows ID can cover several IANA IDs within a given territory, the most frequently used IANA ID in that territory is returned. - As a special case, QLocale::AnyTerritory returns the default of those IANA IDs - that do not have any specific territory. + As a special case, \l{QLocale::}{AnyTerritory} returns the default of those + IANA IDs that have no known territorial association. - \sa ianaIdToWindowsId(), windowsIdToIanaIds() + \sa ianaIdToWindowsId(), windowsIdToIanaIds(), territory() */ -QByteArray QTimeZone::windowsIdToDefaultIanaId(const QByteArray &windowsId, QLocale::Territory territory) +QByteArray QTimeZone::windowsIdToDefaultIanaId(const QByteArray &windowsId, + QLocale::Territory territory) { return QTimeZonePrivate::windowsIdToDefaultIanaId(windowsId, territory); } @@ -950,16 +961,17 @@ QList QTimeZone::windowsIdToIanaIds(const QByteArray &windowsId) /*! Returns all the IANA IDs for a given \a windowsId and \a territory. - As a special case QLocale::AnyTerritory returns those IANA IDs that do - not have any specific territory. + As a special case, \l{QLocale::}{AnyTerritory} selects those IANA IDs that + have no known territorial association. The returned list is in order of frequency of usage, i.e. larger zones within a territory are listed first. - \sa ianaIdToWindowsId(), windowsIdToDefaultIanaId() + \sa ianaIdToWindowsId(), windowsIdToDefaultIanaId(), territory() */ -QList QTimeZone::windowsIdToIanaIds(const QByteArray &windowsId, QLocale::Territory territory) +QList QTimeZone::windowsIdToIanaIds(const QByteArray &windowsId, + QLocale::Territory territory) { return QTimeZonePrivate::windowsIdToIanaIds(windowsId, territory); } From cb326c9dc6e4cb235082d76fe2a72ae128574435 Mon Sep 17 00:00:00 2001 From: Ievgenii Meshcheriakov Date: Thu, 27 Apr 2023 16:29:01 +0200 Subject: [PATCH 065/151] QDBusServer: Fix potential crash when private pointer is null Check that the private pointer is not null before attempting to dereference it. This can happen, for example, when a QDBusServer instance was constructed with an empty string as address. Attempting to destroy an object constructed this way was causing a segmentation fault on Linux. Add a test case that attempts to construct a QDBusServer object with an empty string as address to check that this does not cause a segmentation fault anymore. Change-Id: I5fe63134026e2a9f509b61d452285891b1ec624d Reviewed-by: Thiago Macieira (cherry picked from commit 90d3c5b95145c1fa326d1d6d9fa5bcd7b3dedc4c) Reviewed-by: Qt CI Bot Reviewed-by: Edward Welbourne --- src/dbus/qdbusserver.cpp | 33 +++++++++++++------ .../qdbusconnection/tst_qdbusconnection.cpp | 5 +++ .../qdbusconnection/tst_qdbusconnection.h | 2 ++ 3 files changed, 30 insertions(+), 10 deletions(-) diff --git a/src/dbus/qdbusserver.cpp b/src/dbus/qdbusserver.cpp index 0c7b4e9ad46..922ac37e573 100644 --- a/src/dbus/qdbusserver.cpp +++ b/src/dbus/qdbusserver.cpp @@ -75,6 +75,8 @@ QDBusServer::QDBusServer(const QString &address, QObject *parent) return; emit instance->serverRequested(address, this); + Q_ASSERT(d != nullptr); + QObject::connect(d, SIGNAL(newServerConnection(QDBusConnectionPrivate*)), this, SLOT(_q_newConnection(QDBusConnectionPrivate*)), Qt::QueuedConnection); } @@ -102,6 +104,8 @@ QDBusServer::QDBusServer(QObject *parent) return; emit instance->serverRequested(address, this); + Q_ASSERT(d != nullptr); + QObject::connect(d, SIGNAL(newServerConnection(QDBusConnectionPrivate*)), this, SLOT(_q_newConnection(QDBusConnectionPrivate*)), Qt::QueuedConnection); } @@ -111,17 +115,20 @@ QDBusServer::QDBusServer(QObject *parent) */ QDBusServer::~QDBusServer() { - QMutex *managerMutex = nullptr; - if (QDBusConnectionManager::instance()) - managerMutex = &QDBusConnectionManager::instance()->mutex; - QMutexLocker locker(managerMutex); + if (!d) + return; + + auto manager = QDBusConnectionManager::instance(); + if (!manager) + return; + + QMutexLocker locker(&manager->mutex); QWriteLocker writeLocker(&d->lock); - if (QDBusConnectionManager::instance()) { - for (const QString &name : qAsConst(d->serverConnectionNames)) - QDBusConnectionManager::instance()->removeConnection(name); - d->serverConnectionNames.clear(); - locker.unlock(); - } + for (const QString &name : std::as_const(d->serverConnectionNames)) + manager->removeConnection(name); + d->serverConnectionNames.clear(); + locker.unlock(); + d->serverObject = nullptr; d->ref.storeRelaxed(0); d->deleteLater(); @@ -174,6 +181,9 @@ QString QDBusServer::address() const */ void QDBusServer::setAnonymousAuthenticationAllowed(bool value) { + if (!d) + return; + d->anonymousAuthenticationAllowed = value; } @@ -186,6 +196,9 @@ void QDBusServer::setAnonymousAuthenticationAllowed(bool value) */ bool QDBusServer::isAnonymousAuthenticationAllowed() const { + if (!d) + return false; + return d->anonymousAuthenticationAllowed; } diff --git a/tests/auto/dbus/qdbusconnection/tst_qdbusconnection.cpp b/tests/auto/dbus/qdbusconnection/tst_qdbusconnection.cpp index cd6288ee34c..310a79ca082 100644 --- a/tests/auto/dbus/qdbusconnection/tst_qdbusconnection.cpp +++ b/tests/auto/dbus/qdbusconnection/tst_qdbusconnection.cpp @@ -1437,6 +1437,11 @@ void tst_QDBusConnection::pendingCallWhenDisconnected() #endif } +void tst_QDBusConnection::emptyServerAddress() +{ + QDBusServer server({}, nullptr); +} + QString MyObject::path; QString MyObjectWithoutInterface::path; QString MyObjectWithoutInterface::interface; diff --git a/tests/auto/dbus/qdbusconnection/tst_qdbusconnection.h b/tests/auto/dbus/qdbusconnection/tst_qdbusconnection.h index a2e80149bc4..9624071c84d 100644 --- a/tests/auto/dbus/qdbusconnection/tst_qdbusconnection.h +++ b/tests/auto/dbus/qdbusconnection/tst_qdbusconnection.h @@ -140,6 +140,8 @@ private slots: void callVirtualObjectLocal(); void pendingCallWhenDisconnected(); + void emptyServerAddress(); + public: QString serviceName() const { return "org.qtproject.Qt.Autotests.QDBusConnection"; } bool callMethod(const QDBusConnection &conn, const QString &path); From 40377fcd9a49b9beb37bb8fbf27b735ca179fba8 Mon Sep 17 00:00:00 2001 From: Edward Welbourne Date: Wed, 3 May 2023 13:14:16 +0200 Subject: [PATCH 066/151] Return TZ time-zone backend's tranCache() as a const reference Assorted code was iterating from tranCache().cbegin() to tranCache().cend(), and getting away with it because CoW means tranCache()'s two distinct returns were referencing the same pimpl, but let's make tranCache() return a const ref so that these calls are all accessing the same object (and we get complaints if we do anything non-const with it via this method). Axivion-Id: qt_qtbase_dev_linux:SV1685 Change-Id: If43ccf37c2b27837e5462cb4a0eeb07f0045cbfe Reviewed-by: Marc Mutz (cherry picked from commit 77d0f3753643fa818c4bef7542f7e5d97812252c) Reviewed-by: Qt Cherry-pick Bot --- src/corelib/time/qtimezoneprivate_p.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/corelib/time/qtimezoneprivate_p.h b/src/corelib/time/qtimezoneprivate_p.h index 527b4df1f15..0015f208b18 100644 --- a/src/corelib/time/qtimezoneprivate_p.h +++ b/src/corelib/time/qtimezoneprivate_p.h @@ -362,7 +362,7 @@ private: mutable QExplicitlySharedDataPointer m_icu; #endif QTzTimeZoneCacheEntry cached_data; - QList tranCache() const { return cached_data.m_tranTimes; } + const QList &tranCache() const { return cached_data.m_tranTimes; } }; #endif // Q_OS_UNIX From c6e2b4834ee047af2271b3519e86a84567e490b0 Mon Sep 17 00:00:00 2001 From: Ahmad Samir Date: Sun, 29 Jan 2023 21:04:52 +0200 Subject: [PATCH 067/151] QStandardPaths/Unix: minor cleanup - Better readability by returning early - Make a QRegularExpression static const so that the regex pattern is compiled only once Change-Id: Ic0d6bd4b068624c4ff60c6e71d09f20393adaa64 Reviewed-by: Thiago Macieira (cherry picked from commit 482a75fef9643220366029862dbf636a88bccb82) Reviewed-by: Daniel Smith (cherry picked from commit f4eacea72bd1e248faa40d15a77c8f49a6b4d81f) Reviewed-by: Edward Welbourne --- src/corelib/io/qstandardpaths_unix.cpp | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/corelib/io/qstandardpaths_unix.cpp b/src/corelib/io/qstandardpaths_unix.cpp index 83e2f036b87..7f93b864352 100644 --- a/src/corelib/io/qstandardpaths_unix.cpp +++ b/src/corelib/io/qstandardpaths_unix.cpp @@ -210,13 +210,14 @@ QString QStandardPaths::writableLocation(StandardLocation type) case CacheLocation: case GenericCacheLocation: { + if (isTestModeEnabled()) + return QDir::homePath() + QLatin1String("/.qttest/cache"); + // http://standards.freedesktop.org/basedir-spec/basedir-spec-0.6.html QString xdgCacheHome = QFile::decodeName(qgetenv("XDG_CACHE_HOME")); if (!xdgCacheHome.startsWith(u'/')) xdgCacheHome.clear(); // spec says relative paths should be ignored - if (isTestModeEnabled()) - xdgCacheHome = QDir::homePath() + QLatin1String("/.qttest/cache"); if (xdgCacheHome.isEmpty()) xdgCacheHome = QDir::homePath() + QLatin1String("/.cache"); if (type == QStandardPaths::CacheLocation) @@ -227,12 +228,12 @@ QString QStandardPaths::writableLocation(StandardLocation type) case AppLocalDataLocation: case GenericDataLocation: { + if (isTestModeEnabled()) + return QDir::homePath() + QLatin1String("/.qttest/share"); QString xdgDataHome = QFile::decodeName(qgetenv("XDG_DATA_HOME")); if (!xdgDataHome.startsWith(u'/')) xdgDataHome.clear(); // spec says relative paths should be ignored - if (isTestModeEnabled()) - xdgDataHome = QDir::homePath() + QLatin1String("/.qttest/share"); if (xdgDataHome.isEmpty()) xdgDataHome = QDir::homePath() + QLatin1String("/.local/share"); if (type == AppDataLocation || type == AppLocalDataLocation) @@ -243,13 +244,14 @@ QString QStandardPaths::writableLocation(StandardLocation type) case GenericConfigLocation: case AppConfigLocation: { + if (isTestModeEnabled()) + return QDir::homePath() + QLatin1String("/.qttest/config"); + // http://standards.freedesktop.org/basedir-spec/latest/ QString xdgConfigHome = QFile::decodeName(qgetenv("XDG_CONFIG_HOME")); if (!xdgConfigHome.startsWith(u'/')) xdgConfigHome.clear(); // spec says relative paths should be ignored - if (isTestModeEnabled()) - xdgConfigHome = QDir::homePath() + QLatin1String("/.qttest/config"); if (xdgConfigHome.isEmpty()) xdgConfigHome = QDir::homePath() + QLatin1String("/.config"); if (type == AppConfigLocation) @@ -298,7 +300,7 @@ QString QStandardPaths::writableLocation(StandardLocation type) if (!key.isEmpty() && !isTestModeEnabled() && file.open(QIODevice::ReadOnly)) { QTextStream stream(&file); // Only look for lines like: XDG_DESKTOP_DIR="$HOME/Desktop" - QRegularExpression exp(QLatin1String("^XDG_(.*)_DIR=(.*)$")); + static const QRegularExpression exp(QLatin1String("^XDG_(.*)_DIR=(.*)$")); QString result; while (!stream.atEnd()) { const QString &line = stream.readLine(); From 4160354f9abf92cd01f9197751019a70faee689b Mon Sep 17 00:00:00 2001 From: Ahmad Samir Date: Thu, 20 Apr 2023 12:26:24 +0200 Subject: [PATCH 068/151] QStandardPaths/Unix: restore org and app names in unittests Some unittests set a custom Organization and Application names and then clears them. Instead used init() method to "reset" those two names to the original values before each unittest is run. Change-Id: I359f3911dd50a2aecfd8dde22e2d591adc6e224e Reviewed-by: David Faure (cherry picked from commit e320280f6183cea519b213d2fd35146db920b29b) Reviewed-by: Edward Welbourne --- .../io/qstandardpaths/tst_qstandardpaths.cpp | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/tests/auto/corelib/io/qstandardpaths/tst_qstandardpaths.cpp b/tests/auto/corelib/io/qstandardpaths/tst_qstandardpaths.cpp index 16e86c03340..2c160924789 100644 --- a/tests/auto/corelib/io/qstandardpaths/tst_qstandardpaths.cpp +++ b/tests/auto/corelib/io/qstandardpaths/tst_qstandardpaths.cpp @@ -59,6 +59,7 @@ class tst_qstandardpaths : public QObject private slots: void initTestCase(); void dump(); + void init(); void testDefaultLocations(); void testCustomLocations(); void enableTestMode(); @@ -163,6 +164,16 @@ void tst_qstandardpaths::dump() } } +void tst_qstandardpaths::init() +{ + // Some unittests set a custom org/app names, restore the original ones + // before each unittest is run + static const QString org = QCoreApplication::organizationName(); + static const QString app = QCoreApplication::applicationName(); + QCoreApplication::setOrganizationName(org); + QCoreApplication::setApplicationName(app); +} + void tst_qstandardpaths::testDefaultLocations() { #ifdef Q_XDG_PLATFORM @@ -331,10 +342,6 @@ void tst_qstandardpaths::testDataLocation() QCOMPARE(appDataDirs.at(1), QString::fromLatin1("/usr/local/share/Qt/QtTest")); QCOMPARE(appDataDirs.at(2), QString::fromLatin1("/usr/share/Qt/QtTest")); #endif - - // reset for other tests - QCoreApplication::setOrganizationName(QString()); - QCoreApplication::setApplicationName(QString()); } void tst_qstandardpaths::testAppConfigLocation() @@ -348,9 +355,6 @@ void tst_qstandardpaths::testAppConfigLocation() QCOMPARE(QStandardPaths::writableLocation(QStandardPaths::AppConfigLocation), base + "/Qt/tst_qstandardpaths"); QCoreApplication::setApplicationName("QtTest"); QCOMPARE(QStandardPaths::writableLocation(QStandardPaths::AppConfigLocation), base + "/Qt/QtTest"); - // reset for other tests - QCoreApplication::setOrganizationName(QString()); - QCoreApplication::setApplicationName(QString()); #endif } From 2ee41cffecde5dc467de63e3b6bcf38e358c88c8 Mon Sep 17 00:00:00 2001 From: Ahmad Samir Date: Thu, 20 Apr 2023 13:22:13 +0200 Subject: [PATCH 069/151] QStandardPaths/Unix: fix writableLocation() when test mode is enabled In commit 482a75fef9643 the code was changed to return early, but that missed appending the organization and app names while test mode is enabled. Issue spotted by Edward. Change-Id: Ifd220f8990874a173413dcf71d105c04b605c800 Reviewed-by: David Faure (cherry picked from commit a7555c33060a2f5e9d0d0f2220286c38f31d436f) Reviewed-by: Qt CI Bot Reviewed-by: Edward Welbourne --- src/corelib/io/qstandardpaths_unix.cpp | 57 ++++++++------- .../io/qstandardpaths/tst_qstandardpaths.cpp | 69 ++++++++++++++++++- 2 files changed, 98 insertions(+), 28 deletions(-) diff --git a/src/corelib/io/qstandardpaths_unix.cpp b/src/corelib/io/qstandardpaths_unix.cpp index 7f93b864352..fe4972145b4 100644 --- a/src/corelib/io/qstandardpaths_unix.cpp +++ b/src/corelib/io/qstandardpaths_unix.cpp @@ -210,16 +210,18 @@ QString QStandardPaths::writableLocation(StandardLocation type) case CacheLocation: case GenericCacheLocation: { - if (isTestModeEnabled()) - return QDir::homePath() + QLatin1String("/.qttest/cache"); + QString xdgCacheHome; + if (isTestModeEnabled()) { + xdgCacheHome = QDir::homePath() + QLatin1String("/.qttest/cache"); + } else { + // http://standards.freedesktop.org/basedir-spec/basedir-spec-0.6.html + xdgCacheHome = QFile::decodeName(qgetenv("XDG_CACHE_HOME")); + if (!xdgCacheHome.startsWith(u'/')) + xdgCacheHome.clear(); // spec says relative paths should be ignored - // http://standards.freedesktop.org/basedir-spec/basedir-spec-0.6.html - QString xdgCacheHome = QFile::decodeName(qgetenv("XDG_CACHE_HOME")); - if (!xdgCacheHome.startsWith(u'/')) - xdgCacheHome.clear(); // spec says relative paths should be ignored - - if (xdgCacheHome.isEmpty()) - xdgCacheHome = QDir::homePath() + QLatin1String("/.cache"); + if (xdgCacheHome.isEmpty()) + xdgCacheHome = QDir::homePath() + QLatin1String("/.cache"); + } if (type == QStandardPaths::CacheLocation) appendOrganizationAndApp(xdgCacheHome); return xdgCacheHome; @@ -228,14 +230,17 @@ QString QStandardPaths::writableLocation(StandardLocation type) case AppLocalDataLocation: case GenericDataLocation: { - if (isTestModeEnabled()) - return QDir::homePath() + QLatin1String("/.qttest/share"); - QString xdgDataHome = QFile::decodeName(qgetenv("XDG_DATA_HOME")); - if (!xdgDataHome.startsWith(u'/')) - xdgDataHome.clear(); // spec says relative paths should be ignored + QString xdgDataHome; + if (isTestModeEnabled()) { + xdgDataHome = QDir::homePath() + QLatin1String("/.qttest/share"); + } else { + xdgDataHome = QFile::decodeName(qgetenv("XDG_DATA_HOME")); + if (!xdgDataHome.startsWith(u'/')) + xdgDataHome.clear(); // spec says relative paths should be ignored - if (xdgDataHome.isEmpty()) - xdgDataHome = QDir::homePath() + QLatin1String("/.local/share"); + if (xdgDataHome.isEmpty()) + xdgDataHome = QDir::homePath() + QLatin1String("/.local/share"); + } if (type == AppDataLocation || type == AppLocalDataLocation) appendOrganizationAndApp(xdgDataHome); return xdgDataHome; @@ -244,16 +249,18 @@ QString QStandardPaths::writableLocation(StandardLocation type) case GenericConfigLocation: case AppConfigLocation: { - if (isTestModeEnabled()) - return QDir::homePath() + QLatin1String("/.qttest/config"); + QString xdgConfigHome; + if (isTestModeEnabled()) { + xdgConfigHome = QDir::homePath() + QLatin1String("/.qttest/config"); + } else { + // http://standards.freedesktop.org/basedir-spec/latest/ + xdgConfigHome = QFile::decodeName(qgetenv("XDG_CONFIG_HOME")); + if (!xdgConfigHome.startsWith(u'/')) + xdgConfigHome.clear(); // spec says relative paths should be ignored - // http://standards.freedesktop.org/basedir-spec/latest/ - QString xdgConfigHome = QFile::decodeName(qgetenv("XDG_CONFIG_HOME")); - if (!xdgConfigHome.startsWith(u'/')) - xdgConfigHome.clear(); // spec says relative paths should be ignored - - if (xdgConfigHome.isEmpty()) - xdgConfigHome = QDir::homePath() + QLatin1String("/.config"); + if (xdgConfigHome.isEmpty()) + xdgConfigHome = QDir::homePath() + QLatin1String("/.config"); + } if (type == AppConfigLocation) appendOrganizationAndApp(xdgConfigHome); return xdgConfigHome; diff --git a/tests/auto/corelib/io/qstandardpaths/tst_qstandardpaths.cpp b/tests/auto/corelib/io/qstandardpaths/tst_qstandardpaths.cpp index 2c160924789..2956251c6c9 100644 --- a/tests/auto/corelib/io/qstandardpaths/tst_qstandardpaths.cpp +++ b/tests/auto/corelib/io/qstandardpaths/tst_qstandardpaths.cpp @@ -52,6 +52,41 @@ // Update this when adding new enum values; update enumNames too static const int MaxStandardLocation = QStandardPaths::AppConfigLocation; +static QString genericCacheLoc() +{ + return QStandardPaths::writableLocation(QStandardPaths::GenericCacheLocation); +} +static QString cacheLoc() +{ + return QStandardPaths::writableLocation(QStandardPaths::CacheLocation); +} + +static QString genericDataLoc() +{ + return QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation); +} +static QString appDataLoc() +{ + return QStandardPaths::writableLocation(QStandardPaths::AppDataLocation); +} +static QString appLocalDataLoc() +{ + return QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation); +} + +static QString genericConfigLoc() +{ + return QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation); +} +static QString configLoc() +{ + return QStandardPaths::writableLocation(QStandardPaths::ConfigLocation); +} +static QString appConfigLoc() +{ + return QStandardPaths::writableLocation(QStandardPaths::AppConfigLocation); +} + class tst_qstandardpaths : public QObject { Q_OBJECT @@ -244,24 +279,52 @@ void tst_qstandardpaths::enableTestMode() setCustomLocations(); // for the global config dir const QString qttestDir = QDir::homePath() + QLatin1String("/.qttest"); - // ConfigLocation + // *Config*Location const QString configDir = qttestDir + QLatin1String("/config"); QCOMPARE(QStandardPaths::writableLocation(QStandardPaths::ConfigLocation), configDir); QCOMPARE(QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation), configDir); const QStringList confDirs = QStandardPaths::standardLocations(QStandardPaths::ConfigLocation); QCOMPARE(confDirs, QStringList() << configDir << m_globalConfigDir); + // AppConfigLocation should be "GenericConfigLocation/organization-name/app-name" + QCOMPARE(appConfigLoc(), configDir + QLatin1String("/tst_qstandardpaths")); - // GenericDataLocation + // *Data*Location const QString dataDir = qttestDir + QLatin1String("/share"); QCOMPARE(QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation), dataDir); const QStringList gdDirs = QStandardPaths::standardLocations(QStandardPaths::GenericDataLocation); QCOMPARE(gdDirs, QStringList() << dataDir << m_globalAppDir); + // AppDataLocation/AppLocalDataLocation should be + // "GenericDataLocation/organization-name/app-name" + QCOMPARE(appDataLoc(), dataDir + QLatin1String("/tst_qstandardpaths")); + QCOMPARE(appLocalDataLoc(), dataDir + QLatin1String("/tst_qstandardpaths")); - // GenericCacheLocation + // *CacheLocation const QString cacheDir = qttestDir + QLatin1String("/cache"); QCOMPARE(QStandardPaths::writableLocation(QStandardPaths::GenericCacheLocation), cacheDir); const QStringList cacheDirs = QStandardPaths::standardLocations(QStandardPaths::GenericCacheLocation); QCOMPARE(cacheDirs, QStringList() << cacheDir); + // CacheLocation should be "GenericCacheLocation/organization-name/app-name" + QCOMPARE(cacheLoc(), cacheDir + QLatin1String("/tst_qstandardpaths")); + + QCoreApplication::setOrganizationName("Qt"); + QCOMPARE(appConfigLoc(), configDir + QLatin1String("/Qt/tst_qstandardpaths")); + QCOMPARE(appDataLoc(), dataDir + QLatin1String("/Qt/tst_qstandardpaths")); + QCOMPARE(appLocalDataLoc(), dataDir + QLatin1String("/Qt/tst_qstandardpaths")); + QCOMPARE(cacheLoc(), cacheDir + QLatin1String("/Qt/tst_qstandardpaths")); + QCOMPARE(cacheLoc(), cacheDir + QLatin1String("/Qt/tst_qstandardpaths")); + + QCoreApplication::setApplicationName("QtTest"); + QCOMPARE(appConfigLoc(), configDir + QLatin1String("/Qt/QtTest")); + QCOMPARE(appDataLoc(), dataDir + QLatin1String("/Qt/QtTest")); + QCOMPARE(appLocalDataLoc(), dataDir + QLatin1String("/Qt/QtTest")); + QCoreApplication::setApplicationName("QtTest"); + QCOMPARE(cacheLoc(), cacheDir + QLatin1String("/Qt/QtTest")); + + // Check these are unaffected by org/app names + QCOMPARE(genericConfigLoc(), configDir); + QCOMPARE(configLoc(), configDir); + QCOMPARE(genericDataLoc(), dataDir); + QCOMPARE(genericCacheLoc(), cacheDir); #endif // On all platforms, we want to ensure that the writableLocation is different in test mode and real mode. From c136a840af31ad252d59ffeb1881c22b336c375c Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Fri, 14 Jul 2023 17:20:06 +0200 Subject: [PATCH 070/151] tst_QSortFilterProxyModel: fix mem-leaks tst_QSortFilterProxyModel::doubleProxySelectionSetSourceModel() leaked _everything_, driving asan nuts. Allocate objects on the stack instead; now it's asan-clean. Change-Id: I721e797e02b1daec9e2b5e3d4ef612a42b2e3492 Reviewed-by: Ivan Solovev (cherry picked from commit 9f8449a054a165ae560c91d3e31409bc293df80d) Reviewed-by: David Faure --- .../tst_qsortfilterproxymodel.cpp | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/tests/auto/corelib/itemmodels/qsortfilterproxymodel_common/tst_qsortfilterproxymodel.cpp b/tests/auto/corelib/itemmodels/qsortfilterproxymodel_common/tst_qsortfilterproxymodel.cpp index 535bd0db2b3..cd276fffc69 100644 --- a/tests/auto/corelib/itemmodels/qsortfilterproxymodel_common/tst_qsortfilterproxymodel.cpp +++ b/tests/auto/corelib/itemmodels/qsortfilterproxymodel_common/tst_qsortfilterproxymodel.cpp @@ -3264,36 +3264,36 @@ void tst_QSortFilterProxyModel::removeRowsRecursive() void tst_QSortFilterProxyModel::doubleProxySelectionSetSourceModel() { - QStandardItemModel *model1 = new QStandardItemModel; - QStandardItem *parentItem = model1->invisibleRootItem(); + QStandardItemModel model1; + QStandardItem *parentItem = model1.invisibleRootItem(); for (int i = 0; i < 4; ++i) { QStandardItem *item = new QStandardItem(QLatin1String("model1 item ") + QString::number(i)); parentItem->appendRow(item); parentItem = item; } - QStandardItemModel *model2 = new QStandardItemModel; - QStandardItem *parentItem2 = model2->invisibleRootItem(); + QStandardItemModel model2; + QStandardItem *parentItem2 = model2.invisibleRootItem(); for (int i = 0; i < 4; ++i) { QStandardItem *item = new QStandardItem(QLatin1String("model2 item ") + QString::number(i)); parentItem2->appendRow(item); parentItem2 = item; } - QSortFilterProxyModel *toggleProxy = new QSortFilterProxyModel; - toggleProxy->setSourceModel(model1); + QSortFilterProxyModel toggleProxy; + toggleProxy.setSourceModel(&model1); - QSortFilterProxyModel *proxyModel = new QSortFilterProxyModel; - proxyModel->setSourceModel(toggleProxy); + QSortFilterProxyModel proxyModel; + proxyModel.setSourceModel(&toggleProxy); - QModelIndex mi = proxyModel->index(0, 0, proxyModel->index(0, 0, proxyModel->index(0, 0))); - QItemSelectionModel ism(proxyModel); + QModelIndex mi = proxyModel.index(0, 0, proxyModel.index(0, 0, proxyModel.index(0, 0))); + QItemSelectionModel ism(&proxyModel); ism.select(mi, QItemSelectionModel::Select); QModelIndexList mil = ism.selectedIndexes(); QCOMPARE(mil.count(), 1); QCOMPARE(mil.first(), mi); - toggleProxy->setSourceModel(model2); + toggleProxy.setSourceModel(&model2); // No crash, it's good news! QVERIFY(ism.selection().isEmpty()); } From 1bd76f8fa02fed3b6477be2d4f870d4b8e924673 Mon Sep 17 00:00:00 2001 From: Axel Spoerl Date: Fri, 14 Jul 2023 13:53:11 +0200 Subject: [PATCH 071/151] tst_QXmlStream: Fix CMakeLists.txt MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove non existing path from GLOB_RECURSE statement. Change-Id: Ie122bd062acf8cc26f2ddead808c101af4da9573 Reviewed-by: Jan Arve Sæther (cherry picked from commit bc9ad7db6b6a6121919a7c2400f8a11e2a29dda4) Reviewed-by: Qt Cherry-pick Bot --- tests/auto/corelib/serialization/qxmlstream/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/auto/corelib/serialization/qxmlstream/CMakeLists.txt b/tests/auto/corelib/serialization/qxmlstream/CMakeLists.txt index 548c912975d..b9b78742254 100644 --- a/tests/auto/corelib/serialization/qxmlstream/CMakeLists.txt +++ b/tests/auto/corelib/serialization/qxmlstream/CMakeLists.txt @@ -11,7 +11,7 @@ file(GLOB_RECURSE test_data file(GLOB_RECURSE tokenError RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} - tokenError/* XML-token-error/*) + tokenError/*) qt_internal_add_test(tst_qxmlstream SOURCES From 2e7196ae2b457dc4308ebad8f31400443e425d2c Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Fri, 14 Jul 2023 20:00:13 +0200 Subject: [PATCH 072/151] tst_QAbstractItemModelTester: fix mem-leak QThreeWidgetItems that have been removed from their parents (or the widget) must be deleted manually. The treeWidgetModel() test forgot that, driving asan nuts. Code predates the beginning of the public history, so picking to all active branches. Change-Id: I139549b0bd8baf4abfb90f926f6290119471046f Reviewed-by: Ivan Solovev (cherry picked from commit 51edc438dd88d3260b6d824a95d4b4782c59fb03) Reviewed-by: Qt Cherry-pick Bot --- .../qabstractitemmodeltester/tst_qabstractitemmodeltester.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/auto/testlib/qabstractitemmodeltester/tst_qabstractitemmodeltester.cpp b/tests/auto/testlib/qabstractitemmodeltester/tst_qabstractitemmodeltester.cpp index e8f8d0c390e..457e2530fea 100644 --- a/tests/auto/testlib/qabstractitemmodeltester/tst_qabstractitemmodeltester.cpp +++ b/tests/auto/testlib/qabstractitemmodeltester/tst_qabstractitemmodeltester.cpp @@ -79,6 +79,7 @@ void tst_QAbstractItemModelTester::treeWidgetModel() new QTreeWidgetItem(root, QStringList(QString::number(i))); QTreeWidgetItem *remove = root->child(2); root->removeChild(remove); + delete remove; QTreeWidgetItem *parent = new QTreeWidgetItem(&widget, QStringList("parent")); new QTreeWidgetItem(parent, QStringList("child")); parent->setHidden(true); From 94f30113ce35dc9414dcb9786ea07596907664ef Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Fri, 14 Jul 2023 21:14:39 +0200 Subject: [PATCH 073/151] tst_QNetworkDiskCache: fix mem-leak MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A caller of Q(Abstract)NetworkDiskCache::data() is supposed to delete the returned value, and this caller forgot. Do it now; better late than never. Amends feb1afc78290433b0c22b1b3f6d65542eeb5b957. Change-Id: I1b27663df9ad49e0203172265d224fdb6ec06646 Reviewed-by: Mårten Nordheim (cherry picked from commit bad3b8f78b9eddb9dd5c08d96f9ee8137d98c19e) Reviewed-by: Qt Cherry-pick Bot --- .../network/access/qnetworkdiskcache/tst_qnetworkdiskcache.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/auto/network/access/qnetworkdiskcache/tst_qnetworkdiskcache.cpp b/tests/auto/network/access/qnetworkdiskcache/tst_qnetworkdiskcache.cpp index 006a529c6d0..b60ab35c78a 100644 --- a/tests/auto/network/access/qnetworkdiskcache/tst_qnetworkdiskcache.cpp +++ b/tests/auto/network/access/qnetworkdiskcache/tst_qnetworkdiskcache.cpp @@ -682,6 +682,7 @@ void tst_QNetworkDiskCache::streamVersion() QIODevice *dataDevice = cache.data(url); QVERIFY(dataDevice != 0); QByteArray cachedData = dataDevice->readAll(); + delete dataDevice; QCOMPARE(cachedData, data); } } From c336a57b2699001d2fe6faeec0dfe170bda72201 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Fri, 14 Jul 2023 21:51:41 +0200 Subject: [PATCH 074/151] QSslDiffieHellmanParameters: fix mem-leak MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Says ASAN: Direct leak of 524 byte(s) in 1 object(s) allocated from: #0 0x7f708f0a67cf in __interceptor_malloc ../../../../gcc/libsanitizer/asan/asan_malloc_linux.cpp:145 #1 0x7f707d94bf9e in CRYPTO_malloc crypto/mem.c:196 #2 0x7f707d7bd248 in asn1_item_flags_i2d crypto/asn1/tasn_enc.c:65 #3 0x7f707d7bd1b7 in ASN1_item_i2d crypto/asn1/tasn_enc.c:45 #4 0x7f707d85b7be in i2d_DHparams crypto/dh/dh_asn1.c:54 #5 0x7f7075a82223 in q_i2d_DHparams(dh_st*, unsigned char**) qsslsocket_openssl_symbols.cpp:435 #6 0x7f7075a82223 in QTlsBackendOpenSSL::dhParametersFromPem(QByteArray const&, QByteArray*) const qssldiffiehellmanparameters_openssl.cpp:139 #7 0x7f708ca9b588 in QSslDiffieHellmanParametersPrivate::initFromPem(QByteArray const&) qssldiffiehellmanparameters.cpp:285 #8 0x7f708ca9b588 in QSslDiffieHellmanParameters::fromEncoded(QByteArray const&, QSsl::EncodingFormat) qssldiffiehellmanparameters.cpp:94 #9 0x55fd8a545ebe in tst_QSslDiffieHellmanParameters::constructionPEM() tst_qssldiffiehellmanparameters.cpp:98 [...] The pointer returned in the out-parameter of a i2d_DHparams() call is supposed to be OPENSSL_free()ed by the user (this is not at all obvious from the docs¹, but an SO answer² indicates that's how it should be (as well as asan stopping from complaining with this patch applied)). ¹ https://www.openssl.org/docs/man3.1/man3/i2d_DHparams.html ² https://stackoverflow.com/a/53563669. Amends 2cf63c71ebe139890526057dcc51b24ea6df6c30. [ChangeLog][QtNetwork][SSL] Fixed a memory leak in parsing of PEM-encoded Diffie-Hellman parameters. Change-Id: I9ed4a26c4676db1c0d54a1945a4fb5014ce568cd Reviewed-by: Mårten Nordheim Reviewed-by: Timur Pocheptsov (cherry picked from commit 676087ef1f7cc885d51256ec30e242d972dccb65) Reviewed-by: Qt Cherry-pick Bot --- src/plugins/tls/openssl/qssldiffiehellmanparameters_openssl.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/plugins/tls/openssl/qssldiffiehellmanparameters_openssl.cpp b/src/plugins/tls/openssl/qssldiffiehellmanparameters_openssl.cpp index 89a24481383..d745afb80f5 100644 --- a/src/plugins/tls/openssl/qssldiffiehellmanparameters_openssl.cpp +++ b/src/plugins/tls/openssl/qssldiffiehellmanparameters_openssl.cpp @@ -173,6 +173,7 @@ int QTlsBackendOpenSSL::dhParametersFromPem(const QByteArray &pem, QByteArray *d if (isSafeDH(dh)) { char *buf = nullptr; const int len = q_i2d_DHparams(dh, reinterpret_cast(&buf)); + const auto freeBuf = qScopeGuard([&] { q_OPENSSL_free(buf); }); if (len > 0) *data = QByteArray(buf, len); else From d6a81eb0cf1a837ef3ed693daccba72c511d5d2c Mon Sep 17 00:00:00 2001 From: Mitch Curtis Date: Fri, 14 Jul 2023 15:37:27 +0800 Subject: [PATCH 075/151] Doc: explain how to create a QToolBar Surprisingly, this wasn't mentioned in the detailed description at all. Users would need to click on the link for the example in the "See also" section and then read through it to find any mention of how tool bars are created. Change-Id: I9db23b475009072f34defab38b6d6200a45f2f35 Reviewed-by: Volker Hilsheimer (cherry picked from commit 14d10c632bad3346d404271535e6225d226afaa5) Reviewed-by: Qt Cherry-pick Bot --- src/widgets/widgets/qtoolbar.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/widgets/widgets/qtoolbar.cpp b/src/widgets/widgets/qtoolbar.cpp index 8f3bf907312..71403d37623 100644 --- a/src/widgets/widgets/qtoolbar.cpp +++ b/src/widgets/widgets/qtoolbar.cpp @@ -388,6 +388,10 @@ void QToolBarPrivate::plug(const QRect &r) \ingroup mainwindow-classes \inmodule QtWidgets + A toolbar is typically created by calling + \l QMainWindow::addToolBar(const QString &title), but it can also + be added as the first widget in a QVBoxLayout, for example. + Toolbar buttons are added by adding \e actions, using addAction() or insertAction(). Groups of buttons can be separated using addSeparator() or insertSeparator(). If a toolbar button is not From b606f514b0200a8541faba821e7df4499ee1fde4 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Sat, 15 Jul 2023 23:02:34 +0200 Subject: [PATCH 076/151] tst_QHostInfo: fix mem-leaks in threadSafetyAsynchronousAPI() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Allocate participating threads and objects on the stack, not the heap. As a drive-by, port from QList to C arrays (never use a dynamically-sized container for statically-sized data™). Code predates the public history, all active branches are affected. Change-Id: If8def658c1c7b505074938d637e78ad2d1f9fd57 Reviewed-by: Mårten Nordheim (cherry picked from commit 69d767bec265587a5645a08f14bb7e7540f01867) Reviewed-by: Marc Mutz Reviewed-by: Volker Hilsheimer --- .../kernel/qhostinfo/tst_qhostinfo.cpp | 23 ++++++++----------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/tests/auto/network/kernel/qhostinfo/tst_qhostinfo.cpp b/tests/auto/network/kernel/qhostinfo/tst_qhostinfo.cpp index 5118584b5ee..37c258627a6 100644 --- a/tests/auto/network/kernel/qhostinfo/tst_qhostinfo.cpp +++ b/tests/auto/network/kernel/qhostinfo/tst_qhostinfo.cpp @@ -71,7 +71,6 @@ #define TEST_DOMAIN ".test.qt-project.org" - class tst_QHostInfo : public QObject { Q_OBJECT @@ -579,24 +578,22 @@ void tst_QHostInfo::threadSafetyAsynchronousAPI() { const int nattempts = 10; const int lookupsperthread = 10; - QList threads; - QList receivers; + QThread threads[nattempts]; + LookupReceiver receivers[nattempts]; for (int i = 0; i < nattempts; ++i) { - QThread* thread = new QThread; - LookupReceiver* receiver = new LookupReceiver; + QThread *thread = &threads[i]; + LookupReceiver *receiver = &receivers[i]; receiver->numrequests = lookupsperthread; - receivers.append(receiver); receiver->moveToThread(thread); connect(thread, SIGNAL(started()), receiver, SLOT(start())); thread->start(); - threads.append(thread); } - for (int k = threads.count() - 1; k >= 0; --k) - QVERIFY(threads.at(k)->wait(60000)); - foreach (LookupReceiver* receiver, receivers) { - QCOMPARE(receiver->result.error(), QHostInfo::NoError); - QCOMPARE(receiver->result.addresses().at(0).toString(), QString("192.0.2.1")); - QCOMPARE(receiver->numrequests, 0); + for (int k = nattempts - 1; k >= 0; --k) + QVERIFY(threads[k].wait(60000)); + for (LookupReceiver &receiver : receivers) { + QCOMPARE(receiver.result.error(), QHostInfo::NoError); + QCOMPARE(receiver.result.addresses().at(0).toString(), QString("192.0.2.1")); + QCOMPARE(receiver.numrequests, 0); } } From 88a1d27928ee4f11cb373476c30221c619be7a8a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A5rten=20Nordheim?= Date: Tue, 18 Jul 2023 09:14:05 +0200 Subject: [PATCH 077/151] QHostInfo: fix leaking slot object We were not ref'ing or deref'ing the slot object in the various places that owned it. So, if, in the end, the QHostInfoResult object didn't call the slot we would leak the slot object. Fixes: QTBUG-115263 Change-Id: I45f43756c7589470045d97b59257ccfd85a325b7 Reviewed-by: Marc Mutz Reviewed-by: Volker Hilsheimer (cherry picked from commit 061ab84e98a3457c361287084e0c1e9a396ab197) Reviewed-by: Qt Cherry-pick Bot --- src/network/kernel/qhostinfo.cpp | 1 - src/network/kernel/qhostinfo_p.h | 8 ++++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/network/kernel/qhostinfo.cpp b/src/network/kernel/qhostinfo.cpp index cf5dde25d40..5b99ea87f66 100644 --- a/src/network/kernel/qhostinfo.cpp +++ b/src/network/kernel/qhostinfo.cpp @@ -182,7 +182,6 @@ bool QHostInfoResult::event(QEvent *event) // we didn't have a context object, or it's still alive if (!withContextObject || receiver) slotObj->call(const_cast(receiver.data()), args); - slotObj->destroyIfLastRef(); deleteLater(); return true; diff --git a/src/network/kernel/qhostinfo_p.h b/src/network/kernel/qhostinfo_p.h index 260d27dffaa..cd1268d973c 100644 --- a/src/network/kernel/qhostinfo_p.h +++ b/src/network/kernel/qhostinfo_p.h @@ -89,6 +89,12 @@ public: moveToThread(receiver->thread()); } + ~QHostInfoResult() + { + if (slotObj) + slotObj->destroyIfLastRef(); + } + void postResultsReady(const QHostInfo &info); Q_SIGNALS: @@ -102,6 +108,8 @@ private: : receiver(other->receiver), slotObj(other->slotObj), withContextObject(other->withContextObject) { + if (slotObj) + slotObj->ref(); // cleanup if the application terminates before results are delivered connect(QCoreApplication::instance(), &QCoreApplication::aboutToQuit, this, &QObject::deleteLater); From 9c81f551b9769728df020005cd165d2afecf22c8 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Mon, 17 Jul 2023 17:40:31 +0200 Subject: [PATCH 078/151] tst_QSortFilterProxyModel: fix mem-leaks II: sortStable() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Like in 9f8449a054a165ae560c91d3e31409bc293df80d, for doubleProxySelectionSetSourceModel(), the sortStable() test also leaked _everything_. Fix in the same way, by allocating model and view on the stack intead of the heap. With this patch, tst_QSortFilterProxyModel is now asan-, but not ubsan-clean (and, because of https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110704, asan still reports a leak in cp-demangle.c, which should be™ gone once we fix the rest of QTBUG-99563). Task-number: QTBUG-115264 Change-Id: Ic0e833d7336435e324457f9d9667ee8573a7dafc Reviewed-by: Ivan Solovev (cherry picked from commit 65647d54b9fddb0b0e3238024d79e12e4bf53295) --- .../tst_qsortfilterproxymodel.cpp | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/tests/auto/corelib/itemmodels/qsortfilterproxymodel_common/tst_qsortfilterproxymodel.cpp b/tests/auto/corelib/itemmodels/qsortfilterproxymodel_common/tst_qsortfilterproxymodel.cpp index cd276fffc69..6f3bef62aa1 100644 --- a/tests/auto/corelib/itemmodels/qsortfilterproxymodel_common/tst_qsortfilterproxymodel.cpp +++ b/tests/auto/corelib/itemmodels/qsortfilterproxymodel_common/tst_qsortfilterproxymodel.cpp @@ -2835,7 +2835,7 @@ void tst_QSortFilterProxyModel::sortColumnTracking2() void tst_QSortFilterProxyModel::sortStable() { - QStandardItemModel* model = new QStandardItemModel(5, 2); + QStandardItemModel model(5, 2); for (int r = 0; r < 5; r++) { const QString prefix = QLatin1String("Row:") + QString::number(r) + QLatin1String(", Column:"); for (int c = 0; c < 2; c++) { @@ -2844,24 +2844,24 @@ void tst_QSortFilterProxyModel::sortStable() QStandardItem* child = new QStandardItem(QLatin1String("Item ") + QString::number(i)); item->appendRow( child ); } - model->setItem(r, c, item); + model.setItem(r, c, item); } } - model->setHorizontalHeaderItem( 0, new QStandardItem( "Name" )); - model->setHorizontalHeaderItem( 1, new QStandardItem( "Value" )); + model.setHorizontalHeaderItem( 0, new QStandardItem( "Name" )); + model.setHorizontalHeaderItem( 1, new QStandardItem( "Value" )); - QSortFilterProxyModel *filterModel = new QSortFilterProxyModel(model); - filterModel->setSourceModel(model); + QSortFilterProxyModel *filterModel = new QSortFilterProxyModel(&model); + filterModel->setSourceModel(&model); - QTreeView *view = new QTreeView; - view->setModel(filterModel); + QTreeView view; + view.setModel(filterModel); QModelIndex firstRoot = filterModel->index(0,0); - view->expand(firstRoot); - view->setSortingEnabled(true); + view.expand(firstRoot); + view.setSortingEnabled(true); - view->model()->sort(1, Qt::DescendingOrder); + view.model()->sort(1, Qt::DescendingOrder); QVariant lastItemData =filterModel->index(2,0, firstRoot).data(); - view->model()->sort(1, Qt::DescendingOrder); + view.model()->sort(1, Qt::DescendingOrder); QCOMPARE(lastItemData, filterModel->index(2,0, firstRoot).data()); } From 7bc99703dfeb8deb7a78187e7cefbc696badb34f Mon Sep 17 00:00:00 2001 From: Edward Welbourne Date: Mon, 22 Jun 2020 18:34:45 +0200 Subject: [PATCH 079/151] Simplify (and fix) initialization of a list of time-zones Looping over the entries had a typo in it and was quite unnecessary, as it just made a fresh copy of a list we already had. Change-Id: I0f3023b06163e5854d425d816e465785cda5fc91 Reviewed-by: Marc Mutz (cherry picked from commit 07e4015687c52ded043345605b7c9426f1424c77) Reviewed-by: Mate Barany --- tests/benchmarks/corelib/time/qtimezone/main.cpp | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/tests/benchmarks/corelib/time/qtimezone/main.cpp b/tests/benchmarks/corelib/time/qtimezone/main.cpp index ffdc57da347..d9d722c498d 100644 --- a/tests/benchmarks/corelib/time/qtimezone/main.cpp +++ b/tests/benchmarks/corelib/time/qtimezone/main.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2022 The Qt Company Ltd. +** Copyright (C) 2023 The Qt Company Ltd. ** Copyright (C) 2019 Crimson AS ** Copyright (C) 2018 Klaralvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author David Faure ** Contact: https://www.qt.io/licensing/ @@ -55,11 +55,7 @@ private Q_SLOTS: static QList enoughZones() { #ifdef EXHAUSTIVE - auto available = QTimeZone::availableTimeZoneIds(); - QList result; - result.reserve(available.size() + 1); - for (conat auto &name : available) - result << name; + QList result = QTimeZone::availableTimeZoneIds(); #else QList result { QByteArray("UTC"), From 5ec8aa323574c54f1778273a89c391f689ac2896 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Thu, 13 Jul 2023 10:23:59 +0200 Subject: [PATCH 080/151] tst_QFuture: fix UB (call of member function on wrong object) By the time QObject::destroyed() is emitted from ~QObject(), sender no longer is-a SenderObject, only a QObject, so calling a SenderObject member function on it is UB. Says UBSan: tst_qfuture.cpp:3854:84: runtime error: member call on address 0x60200000e550 which does not point to an object of type 'SenderObject' 0x60200000e550: note: object is of type 'QObject' 00 00 00 00 e8 3f 96 c9 51 7f 00 00 80 3e 00 00 c0 60 00 00 02 11 00 00 08 00 00 00 16 00 00 72 ^~~~~~~~~~~~~~~~~~~~~~~ vptr for 'QObject' Fix by removing the QObject::connect(). This, of course, breaks the test's WHEN, but I don't see how to keep that WHEN without the UB. At least the THEN part is not invalidated, and there doesn't appear to be another test that tests that destroying objects before signal emission results in a cancelled future. Amends 612f6999c81a500a024f128bdf739342d659754a. Change-Id: I38ca4611c071e8fd200393b600210e36d4030bc6 Reviewed-by: Ivan Solovev (cherry picked from commit 4b0261fed08dc766a7eeeb1e41121f8634e9b8cb) Reviewed-by: Qt Cherry-pick Bot --- tests/auto/corelib/thread/qfuture/tst_qfuture.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/auto/corelib/thread/qfuture/tst_qfuture.cpp b/tests/auto/corelib/thread/qfuture/tst_qfuture.cpp index acaecd56fc9..52671dfb9de 100644 --- a/tests/auto/corelib/thread/qfuture/tst_qfuture.cpp +++ b/tests/auto/corelib/thread/qfuture/tst_qfuture.cpp @@ -3724,8 +3724,6 @@ void tst_QFuture::signalConnect() QSignalSpy spy(sender, &QObject::destroyed); sender->deleteLater(); - // emit the signal when sender is being destroyed - QObject::connect(sender, &QObject::destroyed, [sender] { sender->emitIntArg(42); }); spy.wait(); QVERIFY(future.isCanceled()); From 30b79055c5e35949b8774f94163e2fd6d02e0e3a Mon Sep 17 00:00:00 2001 From: Edward Welbourne Date: Thu, 13 Jul 2023 14:43:55 +0200 Subject: [PATCH 081/151] Check QDT's local time abbreviation as well as the qTzName()s Since QDateTime uses some fall-backs if qTzName() doesn't give it something useful (as happens on MS-Win when local time is UTC), QDateTimeParser should check the result of those fall-backs as well as the qTzName()s when checking for local-time as zone. In 6.2, startsWithLocalTimeZone() is a member function of QDTP, implemented in qdatetime.cpp, to share qt_tzname(), before the latter was converted to qTzName(). The initialization of QDTP::scanString()'s usedDateTime also works differently, as it predates the lightweight QTimeZone revolution. Change-Id: Ic809b7e44cd0c83fb076b24c27547268345fa379 Reviewed-by: Konrad Kujawa Reviewed-by: Edward Welbourne (cherry picked from commit c888e3922d73df791f0f31553536abf03b241a65) --- src/corelib/time/qdatetime.cpp | 9 +++++++-- src/corelib/time/qdatetimeparser.cpp | 18 ++++++++---------- src/corelib/time/qdatetimeparser_p.h | 2 +- 3 files changed, 16 insertions(+), 13 deletions(-) diff --git a/src/corelib/time/qdatetime.cpp b/src/corelib/time/qdatetime.cpp index 4b3126e50b3..cfd5b1de6bf 100644 --- a/src/corelib/time/qdatetime.cpp +++ b/src/corelib/time/qdatetime.cpp @@ -2373,17 +2373,22 @@ static QString qt_tzname(QDateTimePrivate::DaylightStatus daylightStatus) \internal Implemented here to share qt_tzname() */ -int QDateTimeParser::startsWithLocalTimeZone(QStringView name) +int QDateTimeParser::startsWithLocalTimeZone(QStringView name, const QDateTime &when) { QDateTimePrivate::DaylightStatus zones[2] = { QDateTimePrivate::StandardTime, QDateTimePrivate::DaylightTime }; + // On MS-Win, at least when system zone is UTC, the tzname[]s may be empty. for (const auto z : zones) { QString zone(qt_tzname(z)); - if (name.startsWith(zone)) + if (!zone.isEmpty() && name.startsWith(zone)) return zone.size(); } + // Mimic what QLocale::toString() would have used, to ensure round-trips work: + const QString local = QDateTime(when.date(), when.time()).timeZoneAbbreviation(); + if (name.startsWith(local)) + return local.size(); return 0; } #endif // datetimeparser diff --git a/src/corelib/time/qdatetimeparser.cpp b/src/corelib/time/qdatetimeparser.cpp index 9cd34e7d242..8e377caeb63 100644 --- a/src/corelib/time/qdatetimeparser.cpp +++ b/src/corelib/time/qdatetimeparser.cpp @@ -1186,19 +1186,17 @@ QDateTimeParser::scanString(const QDateTime &defaultValue, bool fixup) const sectionNodes[index].pos = pos; int *current = nullptr; const SectionNode sn = sectionNodes.at(index); - ParsedSection sect; - - { + const QDateTime usedDateTime = ([=]() { const QDate date = actualDate(isSet, calendar, year, year2digits, month, day, dayofweek); const QTime time = actualTime(isSet, hour, hour12, ampm, minute, second, msec); - sect = parseSection( #if QT_CONFIG(timezone) - tspec == Qt::TimeZone ? QDateTime(date, time, timeZone) : + if (tspec == Qt::TimeZone) + return QDateTime(date, time, timeZone); #endif - QDateTime(date, time, tspec, zoneOffset), - index, pos); - } + return QDateTime(date, time, tspec, zoneOffset); + })(); + ParsedSection sect = parseSection(usedDateTime, index, pos); QDTPDEBUG << "sectionValue" << sn.name() << m_text << "pos" << pos << "used" << sect.used << stateName(sect.state); @@ -1240,7 +1238,7 @@ QDateTimeParser::scanString(const QDateTime &defaultValue, bool fixup) const timeZone = QTimeZone(zoneName.toLatin1()); tspec = timeZone.isValid() ? Qt::TimeZone - : (Q_ASSERT(startsWithLocalTimeZone(zoneName)), Qt::LocalTime); + : (Q_ASSERT(startsWithLocalTimeZone(zoneName, usedDateTime)), Qt::LocalTime); #else tspec = Qt::LocalTime; #endif @@ -1747,7 +1745,7 @@ QDateTimeParser::ParsedSection QDateTimeParser::findUtcOffset(QStringView str) c QDateTimeParser::ParsedSection QDateTimeParser::findTimeZoneName(QStringView str, const QDateTime &when) const { - const int systemLength = startsWithLocalTimeZone(str); + const int systemLength = startsWithLocalTimeZone(str, when); #if QT_CONFIG(timezone) // Collect up plausibly-valid characters; let QTimeZone work out what's // truly valid. diff --git a/src/corelib/time/qdatetimeparser_p.h b/src/corelib/time/qdatetimeparser_p.h index 7bb1aa01191..47d54772c2a 100644 --- a/src/corelib/time/qdatetimeparser_p.h +++ b/src/corelib/time/qdatetimeparser_p.h @@ -219,7 +219,7 @@ private: ParsedSection findTimeZone(QStringView str, const QDateTime &when, int maxVal, int minVal) const; // Implemented in qdatetime.cpp: - static int startsWithLocalTimeZone(const QStringView name); + static int startsWithLocalTimeZone(const QStringView name, const QDateTime &when); enum AmPmFinder { Neither = -1, From 5eff1c1cc2463b8fbb6a5e0a01ae54e105c178d1 Mon Sep 17 00:00:00 2001 From: Edward Welbourne Date: Wed, 19 Jul 2023 10:58:24 +0200 Subject: [PATCH 082/151] Update system collator when system local is default and updates Amends commit 94de5f9b25e1816039885c765e2a5b312f7daa7e so that every change to the default locale is reflected in an update to the default collator used by QString::localeAwareCompare(). Although the change to the system locale does update the QLocaleData object shared by all system locale objects, the possible change to its collator() may imply the default collator needs an update; and the collator backend's init() may use the language, script and territory that's changed in setting up the revised collator, even if the QLocale instance referenced has the same QLocaleData. In 6.5, the Q_CONSTINIT qualifier isn't in use for the existing declarations, so leave it out; and leave a Q_GLOBAL_STATIC_WITH_ARGS(), adjacent to a moved declaration, as such. Change-Id: I957486c03c3d779fc9a2f0b889346ec13b1af868 Reviewed-by: Thiago Macieira Reviewed-by: Qt CI Bot (cherry picked from commit df736da245bf1ea04fadffa1f5d35c37252930a4) Reviewed-by: Edward Welbourne --- src/corelib/text/qlocale.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/corelib/text/qlocale.cpp b/src/corelib/text/qlocale.cpp index 450a7807f6b..669db20ca91 100644 --- a/src/corelib/text/qlocale.cpp +++ b/src/corelib/text/qlocale.cpp @@ -630,6 +630,7 @@ qsizetype qt_repeatCount(QStringView s) } static const QLocaleData *default_data = nullptr; +QBasicAtomicInt QLocalePrivate::s_generation = Q_BASIC_ATOMIC_INITIALIZER(0); static const QLocaleData *const c_data = locale_data; static QLocalePrivate *c_private() @@ -713,6 +714,10 @@ static void updateSystemPrivate() systemLocaleData.m_script_id = res.toInt(); // Should we replace Any values based on likely sub-tags ? + + // If system locale is default locale, update the default collator's generation: + if (default_data == &systemLocaleData) + QLocalePrivate::s_generation.fetchAndAddRelaxed(1); } #endif // !QT_NO_SYSTEMLOCALE @@ -786,7 +791,6 @@ QDataStream &operator>>(QDataStream &ds, QLocale &l) static const int locale_data_size = sizeof(locale_data)/sizeof(QLocaleData) - 1; -QBasicAtomicInt QLocalePrivate::s_generation = Q_BASIC_ATOMIC_INITIALIZER(0); Q_GLOBAL_STATIC_WITH_ARGS(QSharedDataPointer, defaultLocalePrivate, (new QLocalePrivate(defaultData(), defaultIndex()))) From 4d3542ac95a4996b36cb28e0d601d5c15a77ca33 Mon Sep 17 00:00:00 2001 From: Giuseppe D'Angelo Date: Mon, 24 Jul 2023 18:29:37 +0200 Subject: [PATCH 083/151] QSet: document removeIf The docs were never added (unlike the docs for erase_if). Change-Id: I7857c5eded68791ddfc4e6ce42a60d5736f5a438 Fixes: QTBUG-115473 Reviewed-by: Thiago Macieira (cherry picked from commit 76e650045e342c977042195059a6eedd7809a260) Reviewed-by: Qt Cherry-pick Bot --- src/corelib/tools/qset.qdoc | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/corelib/tools/qset.qdoc b/src/corelib/tools/qset.qdoc index 137aa615027..1e19ed25ea7 100644 --- a/src/corelib/tools/qset.qdoc +++ b/src/corelib/tools/qset.qdoc @@ -910,3 +910,12 @@ from the set \a set. Returns the number of elements removed, if any. */ + +/*! \fn template template qsizetype QSet::removeIf(Predicate pred) + \relates QSet + \since 6.1 + + Removes all elements for which the predicate \a pred returns true + from the set \a set. Returns the number of elements removed, if + any. +*/ From 27b1b8614fa850bba8053e48be3160054d7b3528 Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Mon, 3 Jul 2023 15:36:07 +0200 Subject: [PATCH 084/151] rhi: metal: Fix external MTLDevice import Fixes: QTBUG-115002 Change-Id: I57c12685f8451420c30c65a1a25064607b52e31c Reviewed-by: Qt CI Bot Reviewed-by: Andy Nichols (cherry picked from commit e090853ad598aa4f39304d69ec29b80fc3fceb62) Reviewed-by: Qt Cherry-pick Bot --- src/gui/rhi/qrhimetal.mm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/rhi/qrhimetal.mm b/src/gui/rhi/qrhimetal.mm index 2a2cad1670a..105764a05b4 100644 --- a/src/gui/rhi/qrhimetal.mm +++ b/src/gui/rhi/qrhimetal.mm @@ -337,7 +337,7 @@ QRhiMetal::QRhiMetal(QRhiMetalInitParams *params, QRhiMetalNativeHandles *import importedDevice = importDevice != nullptr; if (importedDevice) { - if (d->dev) { + if (importDevice->dev) { d->dev = (id) importDevice->dev; importedCmdQueue = importDevice->cmdQueue != nullptr; if (importedCmdQueue) From 3a1a6b034de92fc26319fd80a6853e75838fc416 Mon Sep 17 00:00:00 2001 From: Edward Welbourne Date: Tue, 6 Jun 2023 17:11:23 +0200 Subject: [PATCH 085/151] Fix what we can of macOS's divergence for pre-1900 dates MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The system locale backend on macOS uses system APIs to format dates and times in localized ways. Those system APIs appear to know more about time zones than the time_t functions (which artificially cut off before 1900) are willing to tell us. As a result, QDateTime is left to guess the offsets in use before 1900 but the locale-formatting takes a correct offset into account, which can lead to QDateTime and the locale-aware APIs using different offsets. This is further compounded by the system APIs taking into account the calendar transition from Julian to Gregorian. We can't do much about the latter. Previously we were formatting dates by passing the start of the day to the system APIs (which take a date-time, albeit using a "Date" name for the type), along with a date-format that ignores the time of day. For dates before 1900, if the system APIs know the offset in use was less than that in use in the early 1900s, QDateTime (using the latter) gets the start of the day slightly earlier than where the system APIs know it is, so the day before is the date at that time. Use noon on the day in question to avoid this problem, at least for zones that didn't do whole day offset-shifts (crossing the date line) before 1900. Document the problem and the limited extent to which we can solve it. 6.2 back-port simply replaces (invalid, but tolerated) QTime() with QTime(12, 0) to achieve the same effect. Task-number: QTBUG-54955 Change-Id: I5be1bfdb3013433ee248846533ef73af39f173f5 Reviewed-by: Tor Arne Vestbø (cherry picked from commit 9155a07667a3e3e7ac59382a59ba615d7211a322) --- src/corelib/text/qlocale_mac.mm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/corelib/text/qlocale_mac.mm b/src/corelib/text/qlocale_mac.mm index a963e86fb0a..d795d108063 100644 --- a/src/corelib/text/qlocale_mac.mm +++ b/src/corelib/text/qlocale_mac.mm @@ -150,7 +150,7 @@ static QVariant macDayName(int day, QSystemLocale::QueryType type) static QVariant macDateToString(QDate date, bool short_format) { - QCFType myDate = QDateTime(date, QTime()).toCFDate(); + QCFType myDate = QDateTime(date, QTime(12, 0)).toCFDate(); QCFType mylocale = CFLocaleCopyCurrent(); CFDateFormatterStyle style = short_format ? kCFDateFormatterShortStyle : kCFDateFormatterLongStyle; QCFType myFormatter From 7076e8e9f49757b609bc9281095c3d2cfba3e250 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Fri, 30 Jun 2023 07:59:51 +0200 Subject: [PATCH 086/151] Fix typo in QXmlStreamReader error message MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Amends 6326bec46a618c72feba4a2bb994c4d475050aed. Task-number: QTBUG-109781 Task-number: QTBUG-114829 Change-Id: Ib5189dc908cd61c6c6fa23024776a4a5baa75ca5 Reviewed-by: Robert Löhning (cherry picked from commit bdc8dc51380d2ce4580e6b84e3286ec6f1866156) Reviewed-by: Qt Cherry-pick Bot --- src/corelib/serialization/qxmlstream.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/corelib/serialization/qxmlstream.cpp b/src/corelib/serialization/qxmlstream.cpp index 885354ff792..e77f544ceb2 100644 --- a/src/corelib/serialization/qxmlstream.cpp +++ b/src/corelib/serialization/qxmlstream.cpp @@ -1887,7 +1887,7 @@ void QXmlStreamReaderPrivate::raiseNamePrefixTooLongError() { // TODO: add a ImplementationLimitsExceededError and use it instead raiseError(QXmlStreamReader::NotWellFormedError, - QXmlStream::tr("Length of XML attribute name exceeds implemnetation limits (4KiB " + QXmlStream::tr("Length of XML attribute name exceeds implementation limits (4KiB " "characters).")); } From 66a0d3a03ce1123d381abf915fb01fc7c1627976 Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Thu, 27 Jul 2023 12:35:57 +0200 Subject: [PATCH 087/151] doc: Fix QVulkanFunctions code snippet Showing code that cannot possibly compile is bad practice. (vkAllocateCommandBuffers is in QVulkanDeviceFunctions, not QVulkanFunctions) Rather use a member function that is actually in QVulkanFunctions. Change-Id: I3063a8a229152144ce866e915eb4c14ecc58e9ce Reviewed-by: Laszlo Agocs (cherry picked from commit e8e9c287ec6a086a96b36e692ab6d5ed11b64951) Reviewed-by: Qt Cherry-pick Bot --- .../snippets/code/src_gui_vulkan_qvulkanfunctions.cpp | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/gui/doc/snippets/code/src_gui_vulkan_qvulkanfunctions.cpp b/src/gui/doc/snippets/code/src_gui_vulkan_qvulkanfunctions.cpp index df084185812..9c1b1c2fede 100644 --- a/src/gui/doc/snippets/code/src_gui_vulkan_qvulkanfunctions.cpp +++ b/src/gui/doc/snippets/code/src_gui_vulkan_qvulkanfunctions.cpp @@ -55,20 +55,18 @@ namespace src_gui_vulkan_qvulkanfunctions { struct Window { - void render(); + void init(); QVulkanInstance *vulkanInstance() { return nullptr; } }; -VkDevice_T *device = nullptr; -VkCommandBufferAllocateInfo cmdBufInfo; -VkCommandBuffer cmdBuf; //! [0] -void Window::render() +void Window::init() { QVulkanInstance *inst = vulkanInstance(); QVulkanFunctions *f = inst->functions(); // ... - VkResult err = f->vkAllocateCommandBuffers(device, &cmdBufInfo, &cmdBuf); + uint32_t count = 0; + VkResult err = f->vkEnumeratePhysicalDevices(inst->vkInstance(), &count, nullptr); // ... } //! [0] From 7ed48038c56643b6d82e67300c1930f944614105 Mon Sep 17 00:00:00 2001 From: Amir Masoud Abdol Date: Thu, 20 Jul 2023 09:59:29 +0200 Subject: [PATCH 088/151] Fix the project name Fixes: QTBUG-115327 Change-Id: I77fc3a98d1658609caa9618430f6e6823b8e1bb5 Reviewed-by: Alexey Edelev (cherry picked from commit 95ed8d1fd9ccc5270b825550085c3a3df2830d5c) Reviewed-by: Qt Cherry-pick Bot --- examples/widgets/tools/echoplugin/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/widgets/tools/echoplugin/CMakeLists.txt b/examples/widgets/tools/echoplugin/CMakeLists.txt index 69bb6e981af..8c5d38056d3 100644 --- a/examples/widgets/tools/echoplugin/CMakeLists.txt +++ b/examples/widgets/tools/echoplugin/CMakeLists.txt @@ -1,5 +1,5 @@ cmake_minimum_required(VERSION 3.16) -project(plugandpaint LANGUAGES CXX) +project(echoplugin LANGUAGES CXX) set(CMAKE_AUTOMOC ON) From 725c77420b799994a0b6a6897a873911d4b5e835 Mon Sep 17 00:00:00 2001 From: Liang Qi Date: Mon, 31 Jul 2023 05:35:11 +0200 Subject: [PATCH 089/151] xcb: guard a pointer before usage in QXcbAtom::initializeAllAtoms(). See also the example in https://manpages.debian.org/testing/libxcb-doc/xcb_intern_atom_reply.3.en.html Fixes: QTBUG-115599 Change-Id: I6590fe1aa11deec7fef7ce6d8f5c49a71d636648 Reviewed-by: Axel Spoerl (cherry picked from commit 552e3b9b78c136aebedf0a591af04661f0dedbbf) Reviewed-by: Qt Cherry-pick Bot --- src/plugins/platforms/xcb/qxcbatom.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/plugins/platforms/xcb/qxcbatom.cpp b/src/plugins/platforms/xcb/qxcbatom.cpp index 58c6713909e..62a459fb071 100644 --- a/src/plugins/platforms/xcb/qxcbatom.cpp +++ b/src/plugins/platforms/xcb/qxcbatom.cpp @@ -272,8 +272,10 @@ void QXcbAtom::initializeAllAtoms(xcb_connection_t *connection) { for (i = 0; i < QXcbAtom::NAtoms; ++i) { xcb_intern_atom_reply_t *reply = xcb_intern_atom_reply(connection, cookies[i], nullptr); - m_allAtoms[i] = reply->atom; - free(reply); + if (reply) { + m_allAtoms[i] = reply->atom; + free(reply); + } } } From f35ae5526d57af48a6c31926b4d6bd23d2cc1740 Mon Sep 17 00:00:00 2001 From: Edward Welbourne Date: Thu, 15 Jun 2023 13:45:58 +0200 Subject: [PATCH 090/151] QDTP: match local-time by preference to its zone When parsing a string whose time-zone part matches local time's name, use local time in preference to the QTimeZone with that name. The case is ambiguous, and the bug was already fixed (by something else) in dev, but this caused a failure in 6.2 through 6.5; and using local time is more natural to QDateTime in any case. The fix incidentally makes the the logic of the zone-resolution code more straightforward and a closer match to how findTimeZone() found the match. The issue was hidden from 6.6 by a change [*] to the handling of POSIX rules, that lead to plain abbreviations such as CEST and BST - for which the IANA DB has no entry - no longer being considered "valid" zones, despite being technically valid POSIX zone descriptors (effectively as aliases for UTC). [*] commit 41c561ddde6210651c60c0789d592f79d7b3e4d5 As 6.2 predates the lightweight QTimeZone revolution, QDTP::scanString() has a tspec variable that must be set where dev simply set a time zone. The test code also can't use qTzName(), as it wasn't yet moved from qt_tzname() in QDT.cpp, so fall back on a more brutal way to get local time's abbreviation. Likewise, the modified test can't use QTimeZone::LocalTime. Fixes: QTBUG-114575 Change-Id: I4369901afd26961d038e382f4c4a7beb83659ad7 Reviewed-by: Konrad Kujawa Reviewed-by: Qt CI Bot Reviewed-by: Thiago Macieira (cherry picked from commit ca6a0fd63fdd5209f2cc1ff59e6b31c0bed14597) --- src/corelib/time/qdatetimeparser.cpp | 14 ++++---- .../corelib/time/qdatetime/tst_qdatetime.cpp | 10 ++++-- .../qdatetimeparser/tst_qdatetimeparser.cpp | 32 +++++++++++++++++++ 3 files changed, 47 insertions(+), 9 deletions(-) diff --git a/src/corelib/time/qdatetimeparser.cpp b/src/corelib/time/qdatetimeparser.cpp index 8e377caeb63..989ee63c471 100644 --- a/src/corelib/time/qdatetimeparser.cpp +++ b/src/corelib/time/qdatetimeparser.cpp @@ -1233,15 +1233,15 @@ QDateTimeParser::scanString(const QDateTime &defaultValue, bool fixup) const if (isUtc || isUtcOffset) { tspec = sect.value ? Qt::OffsetFromUTC : Qt::UTC; - } else { #if QT_CONFIG(timezone) - timeZone = QTimeZone(zoneName.toLatin1()); - tspec = timeZone.isValid() - ? Qt::TimeZone - : (Q_ASSERT(startsWithLocalTimeZone(zoneName, usedDateTime)), Qt::LocalTime); -#else - tspec = Qt::LocalTime; + } else if (startsWithLocalTimeZone(zoneName, usedDateTime) != sect.used) { + QTimeZone namedZone = QTimeZone(zoneName.toLatin1()); + Q_ASSERT(namedZone.isValid()); + timeZone = namedZone; + tspec = Qt::TimeZone; #endif + } else { + tspec = Qt::LocalTime; } } break; diff --git a/tests/auto/corelib/time/qdatetime/tst_qdatetime.cpp b/tests/auto/corelib/time/qdatetime/tst_qdatetime.cpp index 12521cd1992..af423893d90 100644 --- a/tests/auto/corelib/time/qdatetime/tst_qdatetime.cpp +++ b/tests/auto/corelib/time/qdatetime/tst_qdatetime.cpp @@ -2933,9 +2933,15 @@ void tst_QDateTime::fromStringStringFormat_localTimeZone_data() } QTimeZone gmt("GMT"); if (gmt.isValid()) { - QTest::newRow("local-timezone-with-offset:GMT") << QByteArrayLiteral("GMT") + const bool fullyLocal = ([]() { + TimeZoneRollback useZone("GMT"); + return QDateTime::currentDateTime().timeZoneAbbreviation() == QStringLiteral("GMT"); + })(); + QTest::newRow("local-timezone-with-offset:GMT") + << QByteArrayLiteral("GMT") << QString("2008-10-13 GMT 11.50") << QString("yyyy-MM-dd t hh.mm") - << QDateTime(QDate(2008, 10, 13), QTime(11, 50), gmt); + << (fullyLocal ? QDateTime(QDate(2008, 10, 13), QTime(11, 50)) + : QDateTime(QDate(2008, 10, 13), QTime(11, 50), gmt)); } QTimeZone helsinki("Europe/Helsinki"); if (helsinki.isValid()) { diff --git a/tests/auto/corelib/time/qdatetimeparser/tst_qdatetimeparser.cpp b/tests/auto/corelib/time/qdatetimeparser/tst_qdatetimeparser.cpp index 98dd36bc32d..9f28a03ac51 100644 --- a/tests/auto/corelib/time/qdatetimeparser/tst_qdatetimeparser.cpp +++ b/tests/auto/corelib/time/qdatetimeparser/tst_qdatetimeparser.cpp @@ -71,6 +71,7 @@ class tst_QDateTimeParser : public QObject Q_OBJECT private Q_SLOTS: + void reparse(); void parseSection_data(); void parseSection(); @@ -78,6 +79,37 @@ private Q_SLOTS: void intermediateYear(); }; +void tst_QDateTimeParser::reparse() +{ + const QDateTime when = QDate(2023, 6, 15).startOfDay(); + // QTBUG-114575: 6.2 through 6.5 got back a bogus Qt::TimeZone (with zero offset): + const Qt::TimeSpec spec = ([](QStringView name) { + // When local time is UTC or a fixed offset from it, the parser prefers + // to interpret a UTC or offset suffix as such, rather than as local + // time (thereby avoiding DST-ness checks). We have to match that here. + if (name == QLatin1String("UTC")) + return Qt::UTC; + if (name.startsWith(u'+') || name.startsWith(u'-')) { + if (std::all_of(name.begin() + 1, name.end(), [](QChar ch) { return ch == u'0'; })) + return Qt::UTC; + if (std::all_of(name.begin() + 1, name.end(), [](QChar ch) { return ch.isDigit(); })) + return Qt::OffsetFromUTC; + // Potential hh:mm offset ? Not yet seen as local tzname[] entry. + } + return Qt::LocalTime; + })(when.timeZoneAbbreviation()); + + const QStringView format = u"dd/MM/yyyy HH:mm t"; + QDateTimeParser who(QMetaType::QDateTime, QDateTimeParser::DateTimeEdit); + QVERIFY(who.parseFormat(format)); + const auto state = who.parse(when.toString(format), -1, when, false); + QCOMPARE(state.state, QDateTimeParser::Acceptable); + QVERIFY(!state.conflicts); + QCOMPARE(state.padded, 0); + QCOMPARE(state.value.timeSpec(), spec); + QCOMPARE(state.value, when); +} + void tst_QDateTimeParser::parseSection_data() { QTest::addColumn("format"); From c6e2686555ba46ddd5c39f5a14a6d5188a423af3 Mon Sep 17 00:00:00 2001 From: Axel Spoerl Date: Mon, 31 Jul 2023 15:31:36 +0200 Subject: [PATCH 091/151] Remove assertion in QAndroidPlatformScreen::addWindow() QAndroidPlatformScreen::addWindow() asserted the existence of a backing store, when a window is added. But QQuickWindow neither needs nor has a backing store. This patch removes the assertion, which was introduced in dbb072eb2838a04e89e34dad686394a496d5de87 Task-number: QTBUG-97482 Change-Id: Ifb43f83d39e16b972754e86d0ff9633f58dac3f8 Reviewed-by: Shawn Rutledge (cherry picked from commit 9a39ad8dfb4e6d1a179bd0fa38026886f8f7cb8e) Reviewed-by: Qt Cherry-pick Bot --- src/plugins/platforms/android/qandroidplatformscreen.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/plugins/platforms/android/qandroidplatformscreen.cpp b/src/plugins/platforms/android/qandroidplatformscreen.cpp index bbd44bac69e..1d4caa491d8 100644 --- a/src/plugins/platforms/android/qandroidplatformscreen.cpp +++ b/src/plugins/platforms/android/qandroidplatformscreen.cpp @@ -188,7 +188,6 @@ bool QAndroidPlatformScreen::event(QEvent *event) void QAndroidPlatformScreen::addWindow(QAndroidPlatformWindow *window) { - Q_ASSERT(window->backingStore()); if (window->parent() && window->isRaster()) return; From 68d02a4239cb37bd391be0b510122688abc6af91 Mon Sep 17 00:00:00 2001 From: Axel Spoerl Date: Fri, 4 Aug 2023 07:35:31 +0200 Subject: [PATCH 092/151] Fix link to platform window in QAndroidPlatformBackingStore::flush() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Android QPA implementation requires a 1:1 link between a platform window and a platform backing store, to correctly flush a backing store to the screen. QAndroidPlatformBackingStore has a bool member m_backingStoreSet, to remember if this link exists. It defaults to false and is set to true, when setBackingStore() is called in the constructor. It falsely remains true, when a platform window is deleted, e.g. because a QWindow has been hidden. When the QWindow is shown again, a new Android platform window is created. With m_backingStoreSet still being true, this new platform window will never be associated with a backing store. As a consequence, it will never be displayed on the screen. The 1:1 relationship of an Android platform window and an Android backing store is neither ideal, nor in line with other QPA layers (e.g. XCB). Changing the Android QPA implementation is complex and a short term fix is necessary. This patch removes the member m_backingStoreSet. Instead of it, QAndroidPlatformBackingStore::flush() directly checks, if the platform window corresponding to the QWindow argument is associated to a backing store. If that is not the case, setBackingStore() is called. QTBUG-97482 has been fixed with another approach, which this patch reverts. The following commits are effectively reverted by this patch: 9a39ad8dfb4e6d1a179bd0fa38026886f8f7cb8e f91588923b1e7b68f1bd79b38af44d024df85996 a4ca9e80658bca7dad1529f03c1b59173a6ecf62 dbb072eb2838a04e89e34dad686394a496d5de87 959a8b3967ac3b6315f5b458628ec5661dfc367e Fixes: QTBUG-97482 Change-Id: Ic4344f8df2e954c057dd2705340f11dfd2d4c6fe Reviewed-by: Tor Arne Vestbø (cherry picked from commit 86fe84f5f7fd9a55e0f26a9572996caf443ff834) Reviewed-by: Qt CI Bot --- .../platforms/android/qandroidplatformbackingstore.cpp | 6 +++--- .../platforms/android/qandroidplatformbackingstore.h | 1 - src/plugins/platforms/android/qandroidplatformscreen.cpp | 2 +- src/widgets/kernel/qwidget.cpp | 6 ------ 4 files changed, 4 insertions(+), 11 deletions(-) diff --git a/src/plugins/platforms/android/qandroidplatformbackingstore.cpp b/src/plugins/platforms/android/qandroidplatformbackingstore.cpp index 420c96a89f7..e4645a367e4 100644 --- a/src/plugins/platforms/android/qandroidplatformbackingstore.cpp +++ b/src/plugins/platforms/android/qandroidplatformbackingstore.cpp @@ -61,10 +61,11 @@ void QAndroidPlatformBackingStore::flush(QWindow *window, const QRegion ®ion, { Q_UNUSED(offset); - if (!m_backingStoreSet) + auto *platformWindow = static_cast(window->handle()); + if (!platformWindow->backingStore()) setBackingStore(window); - (static_cast(window->handle()))->repaint(region); + platformWindow->repaint(region); } void QAndroidPlatformBackingStore::resize(const QSize &size, const QRegion &staticContents) @@ -79,7 +80,6 @@ void QAndroidPlatformBackingStore::setBackingStore(QWindow *window) { if (window->surfaceType() == QSurface::RasterSurface || window->surfaceType() == QSurface::RasterGLSurface) { (static_cast(window->handle()))->setBackingStore(this); - m_backingStoreSet = true; } else { qWarning("QAndroidPlatformBackingStore does not support OpenGL-only windows."); } diff --git a/src/plugins/platforms/android/qandroidplatformbackingstore.h b/src/plugins/platforms/android/qandroidplatformbackingstore.h index d5fc6828d2e..638be610966 100644 --- a/src/plugins/platforms/android/qandroidplatformbackingstore.h +++ b/src/plugins/platforms/android/qandroidplatformbackingstore.h @@ -57,7 +57,6 @@ public: void setBackingStore(QWindow *window); protected: QImage m_image; - bool m_backingStoreSet = false; }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/android/qandroidplatformscreen.cpp b/src/plugins/platforms/android/qandroidplatformscreen.cpp index 1d4caa491d8..1b3086483f3 100644 --- a/src/plugins/platforms/android/qandroidplatformscreen.cpp +++ b/src/plugins/platforms/android/qandroidplatformscreen.cpp @@ -79,7 +79,7 @@ public: } private: - QElapsedTimer m_timer; + QTime m_timer; QString m_msg; }; diff --git a/src/widgets/kernel/qwidget.cpp b/src/widgets/kernel/qwidget.cpp index 510ed44a53b..c24022bce81 100644 --- a/src/widgets/kernel/qwidget.cpp +++ b/src/widgets/kernel/qwidget.cpp @@ -1327,13 +1327,7 @@ void QWidgetPrivate::create() } #endif - // Android doesn't allow to re-use the backing store. - // => force creation of a new one. -#ifdef Q_OS_ANDROID - QBackingStore *store = nullptr; -#else QBackingStore *store = q->backingStore(); -#endif if (!store) { if (q->windowType() != Qt::Desktop) { if (q->isWindow()) From 613477d82dab93ebb79c1184ff7b906493ca265f Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Fri, 21 Jul 2023 23:03:29 +0200 Subject: [PATCH 093/151] QDateTimeParser: unbreak C++20 build (implicit capture of *this by [=]) Use [&] instead and remove overparenthefication as a drive-by. Amends c888e3922d73df791f0f31553536abf03b241a65. Change-Id: Ic7930d5011c247122a1b3396ea0d6a9a2d6107de Reviewed-by: Giuseppe D'Angelo (cherry picked from commit 19c70f40d257d528df65fac44eb847676425d03f) Reviewed-by: Edward Welbourne Reviewed-by: Konrad Kujawa --- src/corelib/time/qdatetimeparser.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/corelib/time/qdatetimeparser.cpp b/src/corelib/time/qdatetimeparser.cpp index 989ee63c471..bc6f13e7af4 100644 --- a/src/corelib/time/qdatetimeparser.cpp +++ b/src/corelib/time/qdatetimeparser.cpp @@ -1186,7 +1186,7 @@ QDateTimeParser::scanString(const QDateTime &defaultValue, bool fixup) const sectionNodes[index].pos = pos; int *current = nullptr; const SectionNode sn = sectionNodes.at(index); - const QDateTime usedDateTime = ([=]() { + const QDateTime usedDateTime = [&] { const QDate date = actualDate(isSet, calendar, year, year2digits, month, day, dayofweek); const QTime time = actualTime(isSet, hour, hour12, ampm, minute, second, msec); @@ -1195,7 +1195,7 @@ QDateTimeParser::scanString(const QDateTime &defaultValue, bool fixup) const return QDateTime(date, time, timeZone); #endif return QDateTime(date, time, tspec, zoneOffset); - })(); + }(); ParsedSection sect = parseSection(usedDateTime, index, pos); QDTPDEBUG << "sectionValue" << sn.name() << m_text From a219503f17ee03573a1243f28b06fc06edf11340 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Thu, 27 Jul 2023 19:52:24 +0200 Subject: [PATCH 094/151] [docs] Link from QtConcurent::run() to QThreadPool::start(Callable&&) The latter is a better choice if you don't need the result QFuture. Describe the QThreadPool::start() overload in prose, since the signature changed in 6.6 from std::function to Callable auto&&. The chosen wording is compatible with both. Fixes: QTBUG-111875 Change-Id: I9f67c2f7e4b221602bf1c35b72e5d38898a4f0c9 Reviewed-by: Leena Miettinen Reviewed-by: Ivan Solovev Reviewed-by: Qt CI Bot (cherry picked from commit 47a0282707d6a0d12f6f584c81a982632d09cfb7) Reviewed-by: Qt Cherry-pick Bot --- src/concurrent/qtconcurrentrun.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/concurrent/qtconcurrentrun.cpp b/src/concurrent/qtconcurrentrun.cpp index 696e857a59a..7ae5124ddef 100644 --- a/src/concurrent/qtconcurrentrun.cpp +++ b/src/concurrent/qtconcurrentrun.cpp @@ -116,6 +116,10 @@ \snippet code/src_concurrent_qtconcurrentrun.cpp 2 + If you don't need the result (for example, because the function returns + \c{void}), using the QThreadPool::start() overload taking a function object + is more efficient. + As documented above, passing arguments is done like this: \snippet code/src_concurrent_qtconcurrentrun.cpp 3 @@ -288,7 +292,7 @@ running task, fetching multiple results from the called \a function or monitoring progress reported by the \a function. - \sa {Concurrent Run (basic mode)}, {Concurrent Run With Promise} + \sa {Concurrent Run (basic mode)}, {Concurrent Run With Promise}, QThreadPool::start() //! [run-description] */ From ad472257f38c18f4ea3ace5672c74a816fa47377 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Fri, 21 Jul 2023 11:12:50 +0200 Subject: [PATCH 095/151] QHostInfo: fix remaining slotObj leaks We failed to delete the slot object when lookUpHost() was called in these (exceptional) circumstances: - on a thread with no event dispatcher - after application shut-down, when the QHostInfoLookupManager Q_APPLICATION_STATIC was destroyed already Fix by adding the missing destroyIfLastRef() calls into these code paths, too. Amends ad5eb297e179a164e297a7c2eb3b9674a1196605. This would be so much easier if we had SlotObjUniquePtr... Task-number: QTBUG-115263 Change-Id: Ief8bf125bc196742c0ce59c1fd87ab93242fc0da Reviewed-by: Ivan Solovev Reviewed-by: Qt CI Bot (cherry picked from commit 693c9e6b1b2f160862a7490af78072a244fa5b9f) Reviewed-by: Qt Cherry-pick Bot --- src/network/kernel/qhostinfo.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/network/kernel/qhostinfo.cpp b/src/network/kernel/qhostinfo.cpp index 5b99ea87f66..19cfec0c43b 100644 --- a/src/network/kernel/qhostinfo.cpp +++ b/src/network/kernel/qhostinfo.cpp @@ -795,6 +795,8 @@ int QHostInfo::lookupHostImpl(const QString &name, if (!QAbstractEventDispatcher::instance(QThread::currentThread())) { qWarning("QHostInfo::lookupHost() called with no event dispatcher"); + if (slotObj) + slotObj->destroyIfLastRef(); return -1; } @@ -841,6 +843,8 @@ int QHostInfo::lookupHostImpl(const QString &name, QObject::connect(&runnable->resultEmitter, SIGNAL(resultsReady(QHostInfo)), receiver, member, Qt::QueuedConnection); manager->scheduleLookup(runnable); + } else if (slotObj) { + slotObj->destroyIfLastRef(); } return id; } From 7880d7e6b516fbb3991147c29059d4abfa3d4f0c Mon Sep 17 00:00:00 2001 From: Axel Spoerl Date: Fri, 4 Aug 2023 05:56:11 +0000 Subject: [PATCH 096/151] Revert "Remove assertion in QAndroidPlatformScreen::addWindow()" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit c6e2686555ba46ddd5c39f5a14a6d5188a423af3. Reason for revert: QTBUG-97482 fixed in Android QPA Layer Change-Id: Id65f64488dda4c80bc152f866a0fb5eaa0337e52 Reviewed-by: Tor Arne Vestbø --- src/plugins/platforms/android/qandroidplatformscreen.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/plugins/platforms/android/qandroidplatformscreen.cpp b/src/plugins/platforms/android/qandroidplatformscreen.cpp index 1b3086483f3..4414d0280df 100644 --- a/src/plugins/platforms/android/qandroidplatformscreen.cpp +++ b/src/plugins/platforms/android/qandroidplatformscreen.cpp @@ -188,6 +188,7 @@ bool QAndroidPlatformScreen::event(QEvent *event) void QAndroidPlatformScreen::addWindow(QAndroidPlatformWindow *window) { + Q_ASSERT(window->backingStore()); if (window->parent() && window->isRaster()) return; From 7f9c184b88bb5e8893aea8263ba4aab9eeffcdaf Mon Sep 17 00:00:00 2001 From: Axel Spoerl Date: Fri, 4 Aug 2023 05:57:14 +0000 Subject: [PATCH 097/151] Revert "QWidget: Don't re-use backing store on Android" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit e307f57e9daddb218e638061b94fff5506ef5004. Reason for revert: QTBUG-97482 fixed in Android QPA layer Change-Id: I4ec8750137c98b7bac977a2c5f8b78516a219554 Reviewed-by: Tor Arne Vestbø --- src/plugins/platforms/android/qandroidplatformscreen.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/plugins/platforms/android/qandroidplatformscreen.cpp b/src/plugins/platforms/android/qandroidplatformscreen.cpp index 4414d0280df..1b3086483f3 100644 --- a/src/plugins/platforms/android/qandroidplatformscreen.cpp +++ b/src/plugins/platforms/android/qandroidplatformscreen.cpp @@ -188,7 +188,6 @@ bool QAndroidPlatformScreen::event(QEvent *event) void QAndroidPlatformScreen::addWindow(QAndroidPlatformWindow *window) { - Q_ASSERT(window->backingStore()); if (window->parent() && window->isRaster()) return; From 9ab5e499e9f4bb8b4bb5e9d693e9eb0e4a3ceb45 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Fri, 4 Aug 2023 23:51:48 +0200 Subject: [PATCH 098/151] tst_QMainWindow: for UB (use of reserved names) Identifiers matching _[A-Z_].* are reserved for use by the C++ implementation. Replace the __ prefix of variable names with _v_, making them non-reserved. Change-Id: I35127d7473678e2efd93a4b21847db562c53abd2 Reviewed-by: Richard Moe Gustavsen (cherry picked from commit 8de746a96c4f83093d1bd50dc1bc3c68148097ac) Reviewed-by: Qt Cherry-pick Bot --- .../widgets/qmainwindow/tst_qmainwindow.cpp | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/tests/auto/widgets/widgets/qmainwindow/tst_qmainwindow.cpp b/tests/auto/widgets/widgets/qmainwindow/tst_qmainwindow.cpp index 8ced7bd106e..b0dcc8b125d 100644 --- a/tests/auto/widgets/widgets/qmainwindow/tst_qmainwindow.cpp +++ b/tests/auto/widgets/widgets/qmainwindow/tst_qmainwindow.cpp @@ -1614,17 +1614,17 @@ QMap dockWidgetGeometries(QMainWindow *mw) #define COMPARE_DOCK_WIDGET_GEOS(_oldGeos, _newGeos) \ { \ - QMap __oldGeos = _oldGeos; \ - QMap __newGeos = _newGeos; \ - QCOMPARE(__newGeos.keys(), __oldGeos.keys()); \ - QStringList __keys = __newGeos.keys(); \ - foreach (const QString &key, __keys) { \ - QRect __r1 = __oldGeos[key]; \ - QRect __r2 = __newGeos[key]; \ - if (__r1 != __r2) \ - qWarning() << key << __r1 << __r2; \ + QMap _v_oldGeos = _oldGeos; \ + QMap _v_newGeos = _newGeos; \ + QCOMPARE(_v_newGeos.keys(), _v_oldGeos.keys()); \ + QStringList _v_keys = _v_newGeos.keys(); \ + foreach (const QString &key, _v_keys) { \ + QRect _v_r1 = _v_oldGeos[key]; \ + QRect _v_r2 = _v_newGeos[key]; \ + if (_v_r1 != _v_r2) \ + qWarning() << key << _v_r1 << _v_r2; \ } \ - QCOMPARE(__newGeos, __oldGeos); \ + QCOMPARE(_v_newGeos, _v_oldGeos); \ } #ifdef QT_BUILD_INTERNAL From a7de27056f0b08f46d6680c2a0cc9cd721faf591 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Tue, 8 Aug 2023 20:06:24 +0200 Subject: [PATCH 099/151] tst_QImageReader: fix missing checks for "newly"-added ImageOptions The following commits neglected to amend tst_QImageReader::supportsOption() with the ImageOption enumerators they added to QImageIOHandler: - c0ba249a48fd85ee8e047ff47448a4ed32d6cd91 - 163af2cf53d3441b453744b99254c07a175af5de - ba323b04cd78fb43e9e63b891e973d24b08250af Fix first and foremost by adding the missing ImageOption::ImageFormat to the list of PNG-supported formats (which, curiously enough, predates the public history and therefore the above three commits), and second, by rewriting the whole test function to enable -Wswitch, so further additions are less likely to be forgotten. Change-Id: I102121b2c8a9067864b8ade2ebe2650be6fb6010 Reviewed-by: Fabian Kosmale Reviewed-by: Ivan Komissarov (cherry picked from commit 679bb388f09ca09f29ad23d22f9b381bf4f6eea0) Reviewed-by: Qt Cherry-pick Bot --- .../image/qimagereader/tst_qimagereader.cpp | 72 +++++++++++-------- 1 file changed, 43 insertions(+), 29 deletions(-) diff --git a/tests/auto/gui/image/qimagereader/tst_qimagereader.cpp b/tests/auto/gui/image/qimagereader/tst_qimagereader.cpp index d9dac9e7a5b..f5185dad11a 100644 --- a/tests/auto/gui/image/qimagereader/tst_qimagereader.cpp +++ b/tests/auto/gui/image/qimagereader/tst_qimagereader.cpp @@ -37,6 +37,7 @@ #include #include #include +#include #include #include #include @@ -1619,43 +1620,56 @@ void tst_QImageReader::supportsOption_data() QTest::addColumn("options"); QTest::newRow("png") << QString("black.png") - << (QIntList() << QImageIOHandler::Gamma - << QImageIOHandler::Description - << QImageIOHandler::Quality - << QImageIOHandler::CompressionRatio - << QImageIOHandler::Size - << QImageIOHandler::ScaledSize); + << QIntList{ + QImageIOHandler::Gamma, + QImageIOHandler::Description, + QImageIOHandler::Quality, + QImageIOHandler::CompressionRatio, + QImageIOHandler::Size, + QImageIOHandler::ScaledSize, + QImageIOHandler::ImageFormat, + }; } void tst_QImageReader::supportsOption() { QFETCH(QString, fileName); - QFETCH(QIntList, options); - - QSet allOptions; - allOptions << QImageIOHandler::Size - << QImageIOHandler::ClipRect - << QImageIOHandler::Description - << QImageIOHandler::ScaledClipRect - << QImageIOHandler::ScaledSize - << QImageIOHandler::CompressionRatio - << QImageIOHandler::Gamma - << QImageIOHandler::Quality - << QImageIOHandler::Name - << QImageIOHandler::SubType - << QImageIOHandler::IncrementalReading - << QImageIOHandler::Endianness - << QImageIOHandler::Animation - << QImageIOHandler::BackgroundColor; + QFETCH(const QIntList, options); QImageReader reader(prefix + fileName); - for (int i = 0; i < options.size(); ++i) { - QVERIFY(reader.supportsOption(QImageIOHandler::ImageOption(options.at(i)))); - allOptions.remove(QImageIOHandler::ImageOption(options.at(i))); - } - foreach (QImageIOHandler::ImageOption option, allOptions) - QVERIFY(!reader.supportsOption(option)); + for (int i = 0; ; ++i) { + // this switch ensures the compiler warns when we miss an enumerator [-Wswitch] + // do _not_ add a default case! + switch (const auto o = QImageIOHandler::ImageOption(i)) { + case QImageIOHandler::Size: + case QImageIOHandler::ClipRect: + case QImageIOHandler::Description: + case QImageIOHandler::ScaledClipRect: + case QImageIOHandler::ScaledSize: + case QImageIOHandler::CompressionRatio: + case QImageIOHandler::Gamma: + case QImageIOHandler::Quality: + case QImageIOHandler::Name: + case QImageIOHandler::SubType: + case QImageIOHandler::IncrementalReading: + case QImageIOHandler::Endianness: + case QImageIOHandler::Animation: + case QImageIOHandler::BackgroundColor: + case QImageIOHandler::ImageFormat: + case QImageIOHandler::SupportedSubTypes: + case QImageIOHandler::OptimizedWrite: + case QImageIOHandler::ProgressiveScanWrite: + case QImageIOHandler::ImageTransformation: + { + auto printOnFailure = qScopeGuard([&] { qDebug("failed at %d", i); }); + QCOMPARE(reader.supportsOption(o), options.contains(i)); + printOnFailure.dismiss(); + continue; // ... as long as `i` represents a valid ImageOption value + } + } + break; // ... once `i` no longer represents a valid ImageOption value + } } void tst_QImageReader::autoDetectImageFormat() From 11af8ebb47604c845011684cc88c1fa09fc16115 Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Mon, 3 Jul 2023 08:18:06 +0200 Subject: [PATCH 100/151] doc: Make docs for ElideNone a bit more precise MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ElideNone was originally introduced as a way of modifying behavior of specific widgets, such as QTabBar. The text would previously always be a elided and an ellipsis character would be added somewhere to indicate this to the user. Given that context, it makes sense that the documentation says the effect of ElideNone is that ellipsis does not appear in the text, since the text would still be elided if it were too long, given that the painter would draw it clipped to the widget. When QFontMetrics::elidedText() was introduced later, this became more confusing. In the context of this function, you would expect the text to be returned truncated to the width but without the ellipsis character. Instead it just returns the full string. Since this has been the effect of ElideNone since the start and multiple places use it as a way of disabling the truncation of the string, we simply update the documentation to make this more clear. Fixes: QTBUG-40315 Change-Id: If037430da6260020b1d99be7bd43e622f8afa844 Reviewed-by: Tor Arne Vestbø (cherry picked from commit e7507d6cb706d28954343723438c4fc7d6fe5ba4) Reviewed-by: Qt Cherry-pick Bot --- src/corelib/global/qnamespace.qdoc | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/corelib/global/qnamespace.qdoc b/src/corelib/global/qnamespace.qdoc index 873a4c91ee0..d7debe972a2 100644 --- a/src/corelib/global/qnamespace.qdoc +++ b/src/corelib/global/qnamespace.qdoc @@ -2865,7 +2865,10 @@ \value ElideLeft The ellipsis should appear at the beginning of the text. \value ElideRight The ellipsis should appear at the end of the text. \value ElideMiddle The ellipsis should appear in the middle of the text. - \value ElideNone Ellipsis should NOT appear in the text. + \value ElideNone Ellipsis should NOT appear in the text. When passed to functions such as + QFontMetrics::elidedText(), this will cause the full string to return unless + the text contains multi-length variants. Elision in this case must be done + by clipping to the component width. Qt::ElideMiddle is normally the most appropriate choice for URLs (e.g., "\l{http://bugreports.qt.io/browse/QTWEBSITE-13}{http://bugreports.qt.../QTWEBSITE-13/}"), From 2530c3ff028712928517a0ff2133902022f76867 Mon Sep 17 00:00:00 2001 From: Alexey Edelev Date: Wed, 9 Aug 2023 12:38:45 +0200 Subject: [PATCH 101/151] Fix typo in QUntypedPropertyBinding docs Change-Id: Id279760a40be56bea6456e57404348bd2619f64b Reviewed-by: Fabian Kosmale (cherry picked from commit 91f5f44b1344fb64891c364a23e6aff2e5283e5a) Reviewed-by: Qt Cherry-pick Bot --- src/corelib/kernel/qproperty.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/corelib/kernel/qproperty.cpp b/src/corelib/kernel/qproperty.cpp index 1080079dcfb..21abdda84ea 100644 --- a/src/corelib/kernel/qproperty.cpp +++ b/src/corelib/kernel/qproperty.cpp @@ -421,7 +421,7 @@ QPropertyBindingError QUntypedPropertyBinding::error() const /*! Returns the meta-type of the binding. - If the QUntypedProperyBinding is null, an invalid QMetaType is returned. + If the QUntypedPropertyBinding is null, an invalid QMetaType is returned. */ QMetaType QUntypedPropertyBinding::valueMetaType() const { From 05596463b1a95c13fe83c72151d6b66f1f484072 Mon Sep 17 00:00:00 2001 From: Alexey Edelev Date: Wed, 9 Aug 2023 12:41:15 +0200 Subject: [PATCH 102/151] Fix typo in core animation docs Change-Id: I9fdab0e3969a4d89695c70c4e44a8018a141c6bb Reviewed-by: Fabian Kosmale (cherry picked from commit 4f686b7b78552282e47fce7640f0154efe091077) Reviewed-by: Qt Cherry-pick Bot --- src/corelib/doc/src/animation.qdoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/corelib/doc/src/animation.qdoc b/src/corelib/doc/src/animation.qdoc index ceef6efc451..4d2d036d298 100644 --- a/src/corelib/doc/src/animation.qdoc +++ b/src/corelib/doc/src/animation.qdoc @@ -246,7 +246,7 @@ A QPropertyAnimation should always have a parent that controls its lifespan. A typical application may include several animations that are grouped, where the animation group takes ownership of those animations. - An independent QProperyAnimation must be explicitly assigned a parent to + An independent QPropertyAnimation must be explicitly assigned a parent to control its lifespan. In the following example, you can see that an independent QPropertyAnimation has the QApplication instance as its parent: From 5ed7eb0d724f4ec52f9dd3056934de95cc83da23 Mon Sep 17 00:00:00 2001 From: Axel Spoerl Date: Thu, 27 Jul 2023 12:01:34 +0200 Subject: [PATCH 103/151] QColorDialog: Ignore mouse move events when no mouse button is pressed mouseMoveEvent overrides in QColorLuminancePicker and QColorPicker have triggered value changes unconditionally. This happened under the assumption that the widget attribute WA_Hover is not set (which is the default behavior). In that case, mouseMoveEvents are only delivered if a button is pressed. If WA_Hover is set - e.g. by applying a style sheet - mouseMoveEvents get delivered also when no button is pressed. This leads to faulty behavior: The color and the luminance change, whenever the mouse is moved into the respective widget. Color/luminance are changed to the value representing the edge on which the mouse has left the area. This patch changes both mouseMoveEvent overrides. They return early to avoid hovering changing the colors of the luminance/color picker, but ignore() the event in case anything behind the picker needs hover. Since this is a purely graphical effect, an autotest was not added. Fixes: QTBUG-115516 Change-Id: I000d113a1c81c46799cbb5197bf9acb3849e7d3b Reviewed-by: Shawn Rutledge (cherry picked from commit a2ec43b8ebcbf8462928800a7db4f6af7e482b18) Reviewed-by: Qt Cherry-pick Bot --- src/widgets/dialogs/qcolordialog.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/widgets/dialogs/qcolordialog.cpp b/src/widgets/dialogs/qcolordialog.cpp index 6150401c20f..d88628769a1 100644 --- a/src/widgets/dialogs/qcolordialog.cpp +++ b/src/widgets/dialogs/qcolordialog.cpp @@ -797,6 +797,10 @@ QColorLuminancePicker::~QColorLuminancePicker() void QColorLuminancePicker::mouseMoveEvent(QMouseEvent *m) { + if (m->buttons() == Qt::NoButton) { + m->ignore(); + return; + } setVal(y2val(m->position().toPoint().y())); } void QColorLuminancePicker::mousePressEvent(QMouseEvent *m) @@ -931,6 +935,10 @@ void QColorPicker::setCol(int h, int s) void QColorPicker::mouseMoveEvent(QMouseEvent *m) { QPoint p = m->position().toPoint() - contentsRect().topLeft(); + if (m->buttons() == Qt::NoButton) { + m->ignore(); + return; + } setCol(p); emit newCol(hue, sat); } From 3fec5b5be296d8efc242410b5fbe3af78fa1c8ea Mon Sep 17 00:00:00 2001 From: Axel Spoerl Date: Fri, 11 Aug 2023 08:48:33 +0200 Subject: [PATCH 104/151] Improve diagnostic output in tst_QDockWidget::floatingTabs() Use QTRY_COMPARE instead of QTRY_VERIFY. Task-number: QTBUG-115058 Change-Id: I2bfb7c54476e8fdd4f34c74888f56a6f7942a7ee Reviewed-by: Santhosh Kumar (cherry picked from commit 814b7fd3a82725a958af76282fcf56561bc92d42) Reviewed-by: Qt Cherry-pick Bot --- tests/auto/widgets/widgets/qdockwidget/tst_qdockwidget.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/auto/widgets/widgets/qdockwidget/tst_qdockwidget.cpp b/tests/auto/widgets/widgets/qdockwidget/tst_qdockwidget.cpp index c6ac5eb104c..9c09d0d4336 100644 --- a/tests/auto/widgets/widgets/qdockwidget/tst_qdockwidget.cpp +++ b/tests/auto/widgets/widgets/qdockwidget/tst_qdockwidget.cpp @@ -1442,10 +1442,10 @@ void tst_QDockWidget::floatingTabs() qCDebug(lcTestDockWidget) << "Checking path consistency" << layout->layoutState.indexOf(d1) << layout->layoutState.indexOf(d2); // Path1 must be identical - QTRY_VERIFY(path1 == layout->layoutState.indexOf(d1)); + QTRY_COMPARE(path1, layout->layoutState.indexOf(d1)); // d1 must have a gap item due to size change - QTRY_VERIFY(layout->layoutState.indexOf(d2) == QList() << path2 << 0); + QTRY_COMPARE(layout->layoutState.indexOf(d2), QList() << path2 << 0); #else QSKIP("test requires -developer-build option"); #endif // QT_BUILD_INTERNAL From af43fa46d3bcea04a3ad0323e6fc9908fa626aea Mon Sep 17 00:00:00 2001 From: Axel Spoerl Date: Fri, 11 Aug 2023 18:20:28 +0200 Subject: [PATCH 105/151] Harden QMenuPrivate::hideMenu() against menu argument becoming stale MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit QMenuPrivate::hideMenu() hides a menu and reposts events in case a new action has become the active one. For that purpose, it waits 20ms and 60ms for visual effects to be rendered. If the last action has been triggered, the menu's deleteLater slot has been called before hideMenu(). In that case, it gets deleted while events are processed during the waiting periods. Subsequently, menu becomes stale. This patch replaces the QMenu * argument with a QPointer. Early returns are inserted after waiting. QSignalBlocker is replaced by manual signal blocking, to prevent the signal blocker from recovering the state of a stale object, when it goes out of scope. An auto test is not added: The error scenario occurs, when a menu is triggered by keyboard input, while a mouse event is sent to the main window from outside the menu. Such a test scenario is complex to match and exposed to flakiness. Fixes: QTBUG-115597 Change-Id: I4f937fe66fb1b5cf78ebee70fd0006712172cb12 Reviewed-by: Tor Arne Vestbø (cherry picked from commit e66cbdf68455263aa6b77d4ea9a4e621837dbad3) Reviewed-by: Qt Cherry-pick Bot --- src/widgets/widgets/qmenu.cpp | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/src/widgets/widgets/qmenu.cpp b/src/widgets/widgets/qmenu.cpp index ba93f53aecc..6ee5f92586c 100644 --- a/src/widgets/widgets/qmenu.cpp +++ b/src/widgets/widgets/qmenu.cpp @@ -605,10 +605,16 @@ void QMenuPrivate::hideMenu(QMenu *menu) }; #if QT_CONFIG(effects) - QSignalBlocker blocker(menu); + // If deleteLater has been called and the event loop spins, while waiting + // for visual effects to happen, menu might become stale. + // To prevent a QSignalBlocker from restoring a stale object, block and restore signals manually. + QPointer stillAlive(menu); + const bool signalsBlocked = menu->signalsBlocked(); + menu->blockSignals(true); + aboutToHide = true; // Flash item which is about to trigger (if any). - if (menu->style()->styleHint(QStyle::SH_Menu_FlashTriggeredItem) + if (menu && menu->style()->styleHint(QStyle::SH_Menu_FlashTriggeredItem) && currentAction && currentAction == actionAboutToTrigger && menu->actions().contains(currentAction)) { QEventLoop eventLoop; @@ -619,6 +625,9 @@ void QMenuPrivate::hideMenu(QMenu *menu) QTimer::singleShot(60, &eventLoop, SLOT(quit())); eventLoop.exec(); + if (!stillAlive) + return; + // Select and wait 20 ms. menu->setActiveAction(activeAction); QTimer::singleShot(20, &eventLoop, SLOT(quit())); @@ -626,10 +635,16 @@ void QMenuPrivate::hideMenu(QMenu *menu) } aboutToHide = false; - blocker.unblock(); + + if (stillAlive) + menu->blockSignals(signalsBlocked); + else + return; + #endif // QT_CONFIG(effects) if (activeMenu == menu) activeMenu = nullptr; + menu->d_func()->causedPopup.action = nullptr; menu->close(); menu->d_func()->causedPopup.widget = nullptr; From c89afcc399b99825182183ff6b20b2585fbf2e52 Mon Sep 17 00:00:00 2001 From: Eirik Aavitsland Date: Mon, 14 Aug 2023 09:36:50 +0200 Subject: [PATCH 106/151] Avoid compiler warning Under some configure options, gcc13 emits an intractable warning on this line. This patch works around it. Fixes: QTBUG-115809 Change-Id: Ib63f2ad81ebdb1f609a7f42c25119c5ae29f08bb Reviewed-by: Paul Olav Tvete (cherry picked from commit f8f23c43feb2fb233a8f047cd1b82259498d9aeb) Reviewed-by: Qt Cherry-pick Bot --- src/gui/painting/qpathclipper.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/gui/painting/qpathclipper.cpp b/src/gui/painting/qpathclipper.cpp index 21cd1cdd1ed..302468ed846 100644 --- a/src/gui/painting/qpathclipper.cpp +++ b/src/gui/painting/qpathclipper.cpp @@ -685,7 +685,8 @@ int QKdPointTree::build(int begin, int end, int depth) } } - qSwap(m_nodes.at(last), m_nodes.at(begin)); + if (last != begin) + qSwap(m_nodes.at(last), m_nodes.at(begin)); if (last > begin) m_nodes.at(last).left = &m_nodes.at(build(begin, last, depth + 1)); From 7c701000087574ba4bbdddb9d7a198beef587ac5 Mon Sep 17 00:00:00 2001 From: Edward Welbourne Date: Thu, 10 Aug 2023 11:48:05 +0200 Subject: [PATCH 107/151] Clear the _X version of alongside the enum deprecator When QT_NO_DEPRECATED_WARNINGS is defined, we undefine Q_DECL_ENUMERATOR_DEPRECATED as it's used raw (rather than via an intermediary or version-variant). The same is true of its _X() variant, so do the same for this - which involves redefining it to a still function-like macro, so that its parameter gets ignored. This amends commit 59b03992ab332a320ac7cff7c5b099b2c30e14b2 (and shall get conflicts on older branches, before the defines in question moved to qtdeprecationmarkers.h in 6.5). Change-Id: If85c135cddbb33e93cb90f400af123c74e0298ac Reviewed-by: Ivan Solovev (cherry picked from commit ffaa1281d492d9ab1b0301944c12301dacff55cb) --- src/corelib/global/qglobal.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/corelib/global/qglobal.h b/src/corelib/global/qglobal.h index e123f411f84..cee2c70e967 100644 --- a/src/corelib/global/qglobal.h +++ b/src/corelib/global/qglobal.h @@ -321,6 +321,8 @@ typedef double qreal; # define QT_DEPRECATED_CONSTRUCTOR # undef Q_DECL_ENUMERATOR_DEPRECATED # define Q_DECL_ENUMERATOR_DEPRECATED +# undef Q_DECL_ENUMERATOR_DEPRECATED_X +# define Q_DECL_ENUMERATOR_DEPRECATED_X(ignored) #endif #ifndef QT_DEPRECATED_WARNINGS_SINCE From 813d989ad10bdce9dbd20ed5dcbd7cb634bc30b2 Mon Sep 17 00:00:00 2001 From: Assam Boudjelthia Date: Fri, 11 Aug 2023 01:42:35 +0300 Subject: [PATCH 108/151] Android: fix content URI handling for non-ascii file names Pass an encoded URI string before parsing them through the Android APIs. Fixes: QTBUG-114435 Change-Id: I65131799fad81bfe7490d663d3b7996c94d37f0b Reviewed-by: Ville Voutilainen (cherry picked from commit ea75e34d6968bb59624874411e793c95b26d0dbe) --- .../platforms/android/androidcontentfileengine.cpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/plugins/platforms/android/androidcontentfileengine.cpp b/src/plugins/platforms/android/androidcontentfileengine.cpp index 1ca774091b4..728ecc49003 100644 --- a/src/plugins/platforms/android/androidcontentfileengine.cpp +++ b/src/plugins/platforms/android/androidcontentfileengine.cpp @@ -624,7 +624,8 @@ QJniObject parseUri(const QString &uri) DocumentFilePtr DocumentFile::parseFromAnyUri(const QString &fileName) { - const QJniObject uri = parseUri(fileName); + const QString encodedUri = QUrl(fileName).toEncoded(); + const QJniObject uri = parseUri(encodedUri); if (DocumentsContract::isDocumentUri(uri)) return fromSingleUri(uri); @@ -632,17 +633,17 @@ DocumentFilePtr DocumentFile::parseFromAnyUri(const QString &fileName) const QString documentType = QLatin1String("/document/"); const QString treeType = QLatin1String("/tree/"); - const int treeIndex = fileName.indexOf(treeType); - const int documentIndex = fileName.indexOf(documentType); - const int index = fileName.lastIndexOf(QLatin1Char('/')); + const int treeIndex = encodedUri.indexOf(treeType); + const int documentIndex = encodedUri.indexOf(documentType); + const int index = encodedUri.lastIndexOf(QUrl::toPercentEncoding(QLatin1String("/"))); if (index <= treeIndex + treeType.size() || index <= documentIndex + documentType.size()) return fromTreeUri(uri); - const QString parentUrl = fileName.left(index); + const QString parentUrl = encodedUri.left(index); DocumentFilePtr parentDocFile = fromTreeUri(parseUri(parentUrl)); - const QString baseName = fileName.mid(index); + const QString baseName = encodedUri.mid(index); const QString fileUrl = parentUrl + QUrl::toPercentEncoding(baseName); DocumentFilePtr docFile = std::make_shared(parseUri(fileUrl)); From 4b2538966521c881194da1175ffd3eef3aed88e6 Mon Sep 17 00:00:00 2001 From: Andreas Eliasson Date: Tue, 15 Aug 2023 11:13:26 +0200 Subject: [PATCH 109/151] Doc: Remove references to non-existing current() method There seems to be no current() method. Replace with the vkInstance method. Fixes: QTBUG-115853 Change-Id: Ifc0f741186092862b498fe4be2d39076b92fa725 Reviewed-by: Laszlo Agocs (cherry picked from commit 50bce440277d4383dcf3a055cb9b5d513735bcbc) Reviewed-by: Qt Cherry-pick Bot --- src/gui/vulkan/qvulkaninstance.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/gui/vulkan/qvulkaninstance.cpp b/src/gui/vulkan/qvulkaninstance.cpp index 3c5f34f5c60..e861e843e72 100644 --- a/src/gui/vulkan/qvulkaninstance.cpp +++ b/src/gui/vulkan/qvulkaninstance.cpp @@ -306,7 +306,8 @@ QVulkanInstance::QVulkanInstance() /*! Destructor. - \note current() will return \nullptr once the instance is destroyed. + \note \l {QVulkanInstance::}{vkInstance()} will return \nullptr once the + instance is destroyed. */ QVulkanInstance::~QVulkanInstance() { @@ -593,8 +594,8 @@ void QVulkanInstance::setApiVersion(const QVersionNumber &vulkanVersion) \return true if successful, false on error or when Vulkan is not supported. - When successful, the pointer to this QVulkanInstance is retrievable via the - static function current(). + When successful, the pointer to this QVulkanInstance is retrievable via + \l {QVulkanInstance::}{vkInstance()}. The Vulkan instance and library is available as long as this QVulkanInstance exists, or until destroy() is called. From 4d30a3922bc8ee3c58d2611dabbefe0a5395316d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Arve=20S=C3=A6ther?= Date: Wed, 16 Aug 2023 09:51:52 +0200 Subject: [PATCH 110/151] Revert "Windows QPA: Add support to UiaRaiseNotificationEvent()" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 566def740ec58e842e6bb37177f80e20aebaa245. The fix had some unwanted side-effects when the QAccessibleValueChangeEvent carried a value of type string. Only QComboBox uses QAccessibleValueChangeEvent in such a way. The consequence of the reverted patch was that it broke QComboBox so that the screen reader would read aloud the value change event regardless of the visibility or focus state of the QComboBox. (Thus, if you e.g. changed the QComboBox::currentIndex on a *hidden* combo box, the screen reader would still read aloud the event) This is also the root cause of what is described in QTBUG-93763. Also, due to the usage of NotificationProcessing_ImportantMostRecent the screen reader would treat it as such an important event that it would abort whatever it was currently speaking. In addition, the reverted change didn't fix any bugs and it failed to implement the suggested behavior in a correct way (as was described in QTBUG-75003 - albeit properly described after the change was merged). QTBUG-75003 has already been reopened due to this, and the change can therefore be reverted quite risk-free. Task-number: QTBUG-75003 Task-number: QTBUG-93763 Change-Id: Ib91872adc563c31534fe2b30fd9c447bfcca6b40 Reviewed-by: Tor Arne Vestbø (cherry picked from commit 193fb8bb68e35f6ad25a7d62a6e321bd41ecf688) Reviewed-by: Qt Cherry-pick Bot --- .../windows/apisupport/qwindowsuiawrapper.cpp | 10 +------ .../windows/apisupport/qwindowsuiawrapper_p.h | 3 --- .../windows/apisupport/uiatypes_p.h | 16 ------------ .../uiautomation/qwindowsuiamainprovider.cpp | 26 ++++--------------- 4 files changed, 6 insertions(+), 49 deletions(-) diff --git a/src/gui/accessible/windows/apisupport/qwindowsuiawrapper.cpp b/src/gui/accessible/windows/apisupport/qwindowsuiawrapper.cpp index c357fa117cc..8a84175e3cb 100644 --- a/src/gui/accessible/windows/apisupport/qwindowsuiawrapper.cpp +++ b/src/gui/accessible/windows/apisupport/qwindowsuiawrapper.cpp @@ -53,7 +53,6 @@ QWindowsUiaWrapper::QWindowsUiaWrapper() m_pUiaHostProviderFromHwnd = reinterpret_cast(uiaLib.resolve("UiaHostProviderFromHwnd")); m_pUiaRaiseAutomationPropertyChangedEvent = reinterpret_cast(uiaLib.resolve("UiaRaiseAutomationPropertyChangedEvent")); m_pUiaRaiseAutomationEvent = reinterpret_cast(uiaLib.resolve("UiaRaiseAutomationEvent")); - m_pUiaRaiseNotificationEvent = reinterpret_cast(uiaLib.resolve("UiaRaiseNotificationEvent")); m_pUiaClientsAreListening = reinterpret_cast(uiaLib.resolve("UiaClientsAreListening")); } } @@ -69,7 +68,7 @@ QWindowsUiaWrapper *QWindowsUiaWrapper::instance() return &wrapper; } -// True if most symbols resolved (UiaRaiseNotificationEvent is optional). +// True if all symbols resolved. BOOL QWindowsUiaWrapper::ready() { return m_pUiaReturnRawElementProvider @@ -114,12 +113,5 @@ HRESULT QWindowsUiaWrapper::raiseAutomationEvent(IRawElementProviderSimple *pPro return m_pUiaRaiseAutomationEvent(pProvider, id); } -HRESULT QWindowsUiaWrapper::raiseNotificationEvent(IRawElementProviderSimple *provider, NotificationKind notificationKind, NotificationProcessing notificationProcessing, BSTR displayString, BSTR activityId) -{ - if (!m_pUiaRaiseNotificationEvent) - return UIA_E_NOTSUPPORTED; - return m_pUiaRaiseNotificationEvent(provider, notificationKind, notificationProcessing, displayString, activityId); -} - QT_END_NAMESPACE diff --git a/src/gui/accessible/windows/apisupport/qwindowsuiawrapper_p.h b/src/gui/accessible/windows/apisupport/qwindowsuiawrapper_p.h index ef5c62af74c..388979cf704 100644 --- a/src/gui/accessible/windows/apisupport/qwindowsuiawrapper_p.h +++ b/src/gui/accessible/windows/apisupport/qwindowsuiawrapper_p.h @@ -80,20 +80,17 @@ public: HRESULT hostProviderFromHwnd(HWND hwnd, IRawElementProviderSimple **ppProvider); HRESULT raiseAutomationPropertyChangedEvent(IRawElementProviderSimple *pProvider, PROPERTYID id, VARIANT oldValue, VARIANT newValue); HRESULT raiseAutomationEvent(IRawElementProviderSimple *pProvider, EVENTID id); - HRESULT raiseNotificationEvent(IRawElementProviderSimple *provider, NotificationKind notificationKind, NotificationProcessing notificationProcessing, BSTR displayString, BSTR activityId); private: typedef LRESULT (WINAPI *PtrUiaReturnRawElementProvider)(HWND, WPARAM, LPARAM, IRawElementProviderSimple *); typedef HRESULT (WINAPI *PtrUiaHostProviderFromHwnd)(HWND, IRawElementProviderSimple **); typedef HRESULT (WINAPI *PtrUiaRaiseAutomationPropertyChangedEvent)(IRawElementProviderSimple *, PROPERTYID, VARIANT, VARIANT); typedef HRESULT (WINAPI *PtrUiaRaiseAutomationEvent)(IRawElementProviderSimple *, EVENTID); - typedef HRESULT (WINAPI *PtrUiaRaiseNotificationEvent)(IRawElementProviderSimple *, NotificationKind, NotificationProcessing, BSTR, BSTR); typedef BOOL (WINAPI *PtrUiaClientsAreListening)(); PtrUiaReturnRawElementProvider m_pUiaReturnRawElementProvider = nullptr; PtrUiaHostProviderFromHwnd m_pUiaHostProviderFromHwnd = nullptr; PtrUiaRaiseAutomationPropertyChangedEvent m_pUiaRaiseAutomationPropertyChangedEvent = nullptr; PtrUiaRaiseAutomationEvent m_pUiaRaiseAutomationEvent = nullptr; - PtrUiaRaiseNotificationEvent m_pUiaRaiseNotificationEvent = nullptr; PtrUiaClientsAreListening m_pUiaClientsAreListening = nullptr; }; diff --git a/src/gui/accessible/windows/apisupport/uiatypes_p.h b/src/gui/accessible/windows/apisupport/uiatypes_p.h index 0f09e7c6f5b..a8feb756377 100644 --- a/src/gui/accessible/windows/apisupport/uiatypes_p.h +++ b/src/gui/accessible/windows/apisupport/uiatypes_p.h @@ -162,22 +162,6 @@ enum ExpandCollapseState { ExpandCollapseState_LeafNode = 3 }; -enum NotificationKind { - NotificationKind_ItemAdded = 0, - NotificationKind_ItemRemoved = 1, - NotificationKind_ActionCompleted = 2, - NotificationKind_ActionAborted = 3, - NotificationKind_Other = 4 -}; - -enum NotificationProcessing { - NotificationProcessing_ImportantAll = 0, - NotificationProcessing_ImportantMostRecent = 1, - NotificationProcessing_All = 2, - NotificationProcessing_MostRecent = 3, - NotificationProcessing_CurrentThenMostRecent = 4 -}; - struct UiaRect { double left; double top; diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp b/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp index 352d7edd886..d5be2c910c7 100644 --- a/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp +++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp @@ -177,27 +177,11 @@ void QWindowsUiaMainProvider::notifyValueChange(QAccessibleValueChangeEvent *eve } if (event->value().typeId() == QMetaType::QString) { if (QWindowsUiaMainProvider *provider = providerForAccessible(accessible)) { - - // Tries to notify the change using UiaRaiseNotificationEvent(), which is only available on - // Windows 10 version 1709 or newer. Otherwise uses UiaRaiseAutomationPropertyChangedEvent(). - - BSTR displayString = bStrFromQString(event->value().toString()); - BSTR activityId = bStrFromQString(QString()); - - HRESULT hr = QWindowsUiaWrapper::instance()->raiseNotificationEvent(provider, NotificationKind_Other, - NotificationProcessing_ImportantMostRecent, - displayString, activityId); - - ::SysFreeString(displayString); - ::SysFreeString(activityId); - - if (hr == static_cast(UIA_E_NOTSUPPORTED)) { - VARIANT oldVal, newVal; - clearVariant(&oldVal); - setVariantString(event->value().toString(), &newVal); - QWindowsUiaWrapper::instance()->raiseAutomationPropertyChangedEvent(provider, UIA_ValueValuePropertyId, oldVal, newVal); - ::SysFreeString(newVal.bstrVal); - } + // Notifies changes in string values. + VARIANT oldVal, newVal; + clearVariant(&oldVal); + setVariantString(event->value().toString(), &newVal); + QWindowsUiaWrapper::instance()->raiseAutomationPropertyChangedEvent(provider, UIA_ValueValuePropertyId, oldVal, newVal); } } else if (QAccessibleValueInterface *valueInterface = accessible->valueInterface()) { if (QWindowsUiaMainProvider *provider = providerForAccessible(accessible)) { From 0d4adaa776660fdb3b088a702a7f3e1979143673 Mon Sep 17 00:00:00 2001 From: Mitch Curtis Date: Fri, 11 Aug 2023 16:22:56 +0800 Subject: [PATCH 111/151] Improve Qt Test documentation regarding skipping/expecting failures - Mention QEXPECT_FAIL on the best practices page. - Link to the best practices page from "Chapter 6: Skipping Tests with QSKIP". - Add some more links. Change-Id: I0c9e0adb9fe500791dad44869434cf6ecdcf51a1 Reviewed-by: Edward Welbourne (cherry picked from commit 5de991059e1590b0f40b73b5929953c3a6754478) --- .../doc/src/qttest-best-practices.qdoc | 19 ++++++++++++------- src/testlib/doc/src/qttestlib-manual.qdoc | 6 ++++-- 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/src/testlib/doc/src/qttest-best-practices.qdoc b/src/testlib/doc/src/qttest-best-practices.qdoc index 71fe1991c75..b4a2c375815 100644 --- a/src/testlib/doc/src/qttest-best-practices.qdoc +++ b/src/testlib/doc/src/qttest-best-practices.qdoc @@ -200,14 +200,19 @@ \section2 Select Appropriate Mechanisms to Exclude Tests It is important to select the appropriate mechanism to exclude inapplicable - tests: \l QSKIP(), using conditional statements to exclude parts of a test - function, or not building the test for a particular platform. + tests. - Use QSKIP() to handle cases where a whole test function is found at run-time - to be inapplicable in the current test environment. When just a part of a - test function is to be skipped, a conditional statement can be used, - optionally with a \c qDebug() call to report the reason for skipping the - inapplicable part. + Use \l QSKIP() to handle cases where a whole test function is found at + run-time to be inapplicable in the current test environment. When just a + part of a test function is to be skipped, a conditional statement can be + used, optionally with a \c qDebug() call to report the reason for skipping + the inapplicable part. + + When there are known test failures that should eventually be fixed, + \l QEXPECT_FAIL is recommended, as it supports running the rest of the + test, when possible. It also verifies that the issue still exists, and + lets the code's maintainer know if they unwittingly fix it, a benefit + which is gained even when using the \l {QTest::}{Abort} flag. Test functions or data rows of a data-driven test can be limited to particular platforms, or to particular features being enabled using diff --git a/src/testlib/doc/src/qttestlib-manual.qdoc b/src/testlib/doc/src/qttestlib-manual.qdoc index c1d3bc147a5..f8d55b21399 100644 --- a/src/testlib/doc/src/qttestlib-manual.qdoc +++ b/src/testlib/doc/src/qttestlib-manual.qdoc @@ -986,7 +986,7 @@ \section2 Using QSKIP(\a description) in a test function - If the QSKIP() macro is called from a test function, it stops + If the \l QSKIP() macro is called from a test function, it stops the execution of the test without adding a failure to the test log. It can be used to skip tests that are certain to fail. The text in the QSKIP \a description parameter is appended to the test log, @@ -994,7 +994,7 @@ QSKIP can be used to skip testing when the implementation is not yet complete or not supported on a certain platform. When there are known - failures, it is recommended to use QEXPECT_FAIL, so that the test is + failures, it is recommended to use \l QEXPECT_FAIL, so that the test is always completely executed. Example of QSKIP in a test function: @@ -1019,4 +1019,6 @@ If called from \c initTestCase() or \c initTestCase_data(), the QSKIP() macro will skip all test and _data functions. + + \sa {Select Appropriate Mechanisms to Exclude Tests} */ From 058526690de0ebd4d87af0da85ec4589f2bcd3d8 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Tue, 15 Aug 2023 11:40:35 +0200 Subject: [PATCH 112/151] tst_QHashFunctions: use actual seed in consistent() test function We were only ever testing with a 0 seed, even though the function was called for all QFETCH_GLOBAL seeds. Add the seed. Amends 5e93361888e3d2b03e7b6da19517b44e0239fb47. Change-Id: I3c78714ad6fb3f94233789dd2c8884d9b157fa76 Reviewed-by: Thiago Macieira (cherry picked from commit fa522eb8becba3243aae8bee191f6f60672434f2) Reviewed-by: Qt Cherry-pick Bot --- tests/auto/corelib/tools/qhashfunctions/tst_qhashfunctions.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/auto/corelib/tools/qhashfunctions/tst_qhashfunctions.cpp b/tests/auto/corelib/tools/qhashfunctions/tst_qhashfunctions.cpp index 3281c4cefd5..63807cad106 100644 --- a/tests/auto/corelib/tools/qhashfunctions/tst_qhashfunctions.cpp +++ b/tests/auto/corelib/tools/qhashfunctions/tst_qhashfunctions.cpp @@ -84,7 +84,7 @@ void tst_QHashFunctions::consistent() { // QString-like const QString s = QStringLiteral("abcdefghijklmnopqrstuvxyz").repeated(16); - QCOMPARE(qHash(s), qHash(QStringView(s))); + QCOMPARE(qHash(s, seed), qHash(QStringView(s), seed)); } void tst_QHashFunctions::initTestCase() From 267dca3a518e8f442ed4595780a482e2df749993 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Str=C3=B8mme?= Date: Thu, 3 Aug 2023 11:07:36 +0200 Subject: [PATCH 113/151] Update to Freetype 2.13.1 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The build fix applied to the 2.13.0 update has also been applied to this update. This cherry-pick also includes the follow-up patch: 11321384d9393c27ad218971d0fdf3c735a05dee Fixes: QTBUG-115340 Change-Id: I970b560948af3472b222690019a85a79c537b7d9 Reviewed-by: Eskil Abrahamsen Blomfeldt (cherry picked from commit 0bdd01b7f7c248543c3cd44509d79011f7babd8a) Reviewed-by: Christian Strømme --- src/3rdparty/freetype/README | 8 +- src/3rdparty/freetype/docs/CHANGES | 50 +- src/3rdparty/freetype/docs/DEBUG | 6 +- .../include/freetype/config/ftoption.h | 47 +- .../include/freetype/config/ftstdlib.h | 14 +- .../freetype/include/freetype/freetype.h | 565 +++++++++++++----- .../freetype/include/freetype/ftcache.h | 74 +-- .../freetype/include/freetype/ftchapters.h | 23 +- .../freetype/include/freetype/ftdriver.h | 11 +- .../freetype/include/freetype/ftimage.h | 10 +- .../freetype/include/freetype/ftlogging.h | 2 +- src/3rdparty/freetype/include/freetype/ftmm.h | 57 +- .../freetype/include/freetype/ftoutln.h | 2 +- .../freetype/include/freetype/ftrender.h | 2 +- .../freetype/include/freetype/ftsynth.h | 12 + .../freetype/include/freetype/ftsystem.h | 16 +- .../freetype/internal/compiler-macros.h | 7 +- .../include/freetype/internal/ftdrv.h | 1 + .../include/freetype/internal/ftmmtypes.h | 20 +- .../freetype/internal/services/svmetric.h | 10 +- .../include/freetype/internal/services/svmm.h | 109 ++-- .../freetype/internal/services/svpscmap.h | 2 +- .../include/freetype/internal/t1types.h | 26 +- .../include/freetype/internal/tttypes.h | 122 ++-- src/3rdparty/freetype/qt_attribution.json | 4 +- src/3rdparty/freetype/src/autofit/afblue.dat | 2 +- src/3rdparty/freetype/src/autofit/afcjk.c | 56 +- src/3rdparty/freetype/src/autofit/afcjk.h | 20 +- src/3rdparty/freetype/src/autofit/afglobal.c | 5 +- src/3rdparty/freetype/src/autofit/afglobal.h | 2 +- src/3rdparty/freetype/src/autofit/afhints.c | 58 +- src/3rdparty/freetype/src/autofit/afindic.c | 32 +- src/3rdparty/freetype/src/autofit/aflatin.c | 49 +- src/3rdparty/freetype/src/autofit/aflatin.h | 4 +- src/3rdparty/freetype/src/autofit/afloader.c | 6 +- src/3rdparty/freetype/src/autofit/afmodule.c | 37 +- src/3rdparty/freetype/src/autofit/afshaper.c | 6 +- src/3rdparty/freetype/src/autofit/ft-hb.c | 2 +- src/3rdparty/freetype/src/base/ftbbox.c | 42 +- src/3rdparty/freetype/src/base/ftcalc.c | 4 +- src/3rdparty/freetype/src/base/ftdbgmem.c | 2 +- src/3rdparty/freetype/src/base/ftmac.c | 2 +- src/3rdparty/freetype/src/base/ftmm.c | 146 ++++- src/3rdparty/freetype/src/base/ftobjs.c | 23 +- src/3rdparty/freetype/src/base/ftoutln.c | 52 +- src/3rdparty/freetype/src/base/ftstroke.c | 21 +- src/3rdparty/freetype/src/base/ftsynth.c | 20 +- src/3rdparty/freetype/src/base/ftsystem.c | 9 +- src/3rdparty/freetype/src/base/ftver.rc | 4 +- src/3rdparty/freetype/src/bdf/bdf.h | 4 - src/3rdparty/freetype/src/bdf/bdfdrivr.c | 116 ++-- src/3rdparty/freetype/src/bdf/bdflib.c | 67 ++- src/3rdparty/freetype/src/bzip2/ftbzip2.c | 19 +- src/3rdparty/freetype/src/cache/ftcbasic.c | 8 +- src/3rdparty/freetype/src/cache/ftccache.c | 125 ++-- src/3rdparty/freetype/src/cache/ftccache.h | 17 +- src/3rdparty/freetype/src/cache/ftcglyph.c | 46 +- src/3rdparty/freetype/src/cache/ftcglyph.h | 15 +- src/3rdparty/freetype/src/cache/ftcmanag.c | 42 +- src/3rdparty/freetype/src/cache/ftcmru.c | 30 +- src/3rdparty/freetype/src/cache/ftcsbits.c | 17 +- src/3rdparty/freetype/src/cache/ftcsbits.h | 11 - src/3rdparty/freetype/src/cff/cffcmap.c | 107 ++-- src/3rdparty/freetype/src/cff/cffdrivr.c | 443 ++++++++------ src/3rdparty/freetype/src/cff/cffgload.c | 6 +- src/3rdparty/freetype/src/cff/cffload.c | 31 +- src/3rdparty/freetype/src/cff/cffload.h | 4 +- src/3rdparty/freetype/src/cff/cffobjs.c | 24 +- src/3rdparty/freetype/src/cff/cffparse.c | 228 ++----- src/3rdparty/freetype/src/cff/cffparse.h | 9 - src/3rdparty/freetype/src/cid/cidgload.c | 141 ++++- src/3rdparty/freetype/src/cid/cidgload.h | 8 + src/3rdparty/freetype/src/cid/cidload.c | 51 +- src/3rdparty/freetype/src/cid/cidobjs.c | 14 +- src/3rdparty/freetype/src/cid/cidparse.c | 18 +- src/3rdparty/freetype/src/cid/cidriver.c | 93 +-- src/3rdparty/freetype/src/dlg/dlgwrap.c | 2 +- src/3rdparty/freetype/src/gxvalid/gxvfgen.c | 3 +- .../freetype/src/gzip/README.freetype | 2 +- src/3rdparty/freetype/src/gzip/ftgzip.c | 5 +- src/3rdparty/freetype/src/gzip/rules.mk | 1 - src/3rdparty/freetype/src/pcf/pcfdrivr.c | 122 ++-- src/3rdparty/freetype/src/pfr/pfrcmap.c | 48 +- src/3rdparty/freetype/src/pfr/pfrdrivr.c | 26 +- src/3rdparty/freetype/src/pfr/pfrgload.c | 3 +- src/3rdparty/freetype/src/pfr/pfrload.c | 60 +- src/3rdparty/freetype/src/pfr/pfrobjs.c | 6 +- src/3rdparty/freetype/src/psaux/afmparse.c | 2 +- src/3rdparty/freetype/src/psaux/t1cmap.c | 141 +++-- src/3rdparty/freetype/src/pshinter/pshalgo.c | 2 +- src/3rdparty/freetype/src/pshinter/pshmod.c | 9 +- src/3rdparty/freetype/src/pshinter/pshrec.c | 63 +- src/3rdparty/freetype/src/psnames/psmodule.c | 42 +- src/3rdparty/freetype/src/raster/ftraster.c | 44 +- src/3rdparty/freetype/src/raster/ftrend1.c | 21 +- src/3rdparty/freetype/src/sdf/ftbsdf.c | 7 +- src/3rdparty/freetype/src/sdf/ftsdf.c | 21 +- src/3rdparty/freetype/src/sdf/ftsdfrend.c | 35 +- src/3rdparty/freetype/src/sfnt/pngshim.c | 7 +- src/3rdparty/freetype/src/sfnt/sfdriver.c | 143 +++-- src/3rdparty/freetype/src/sfnt/sfobjs.c | 30 +- src/3rdparty/freetype/src/sfnt/sfwoff.c | 2 +- src/3rdparty/freetype/src/sfnt/sfwoff2.c | 2 +- src/3rdparty/freetype/src/sfnt/ttbdf.c | 13 +- src/3rdparty/freetype/src/sfnt/ttbdf.h | 2 +- src/3rdparty/freetype/src/sfnt/ttcmap.c | 547 ++++++++--------- src/3rdparty/freetype/src/sfnt/ttcolr.c | 6 +- src/3rdparty/freetype/src/sfnt/ttcpal.c | 2 +- src/3rdparty/freetype/src/sfnt/ttload.c | 7 + src/3rdparty/freetype/src/sfnt/ttmtx.c | 2 +- src/3rdparty/freetype/src/sfnt/ttpost.c | 288 ++++----- src/3rdparty/freetype/src/sfnt/ttsbit.c | 2 +- src/3rdparty/freetype/src/sfnt/ttsvg.c | 2 +- src/3rdparty/freetype/src/sfnt/woff2tags.c | 2 +- src/3rdparty/freetype/src/smooth/ftgrays.c | 49 +- src/3rdparty/freetype/src/smooth/ftsmooth.c | 22 +- src/3rdparty/freetype/src/svg/ftsvg.c | 45 +- src/3rdparty/freetype/src/tools/apinames.c | 44 +- .../freetype/src/tools/ftrandom/ftrandom.c | 2 +- .../freetype/src/tools/vms_shorten_symbol.c | 250 ++++++++ src/3rdparty/freetype/src/truetype/ttdriver.c | 158 ++--- src/3rdparty/freetype/src/truetype/ttgload.c | 276 ++++----- src/3rdparty/freetype/src/truetype/ttgxvar.c | 518 +++++++++------- src/3rdparty/freetype/src/truetype/ttgxvar.h | 40 +- src/3rdparty/freetype/src/truetype/ttinterp.c | 145 ++--- src/3rdparty/freetype/src/truetype/ttinterp.h | 10 +- src/3rdparty/freetype/src/truetype/ttobjs.c | 85 +-- src/3rdparty/freetype/src/truetype/ttobjs.h | 6 +- src/3rdparty/freetype/src/truetype/ttpload.c | 37 +- src/3rdparty/freetype/src/truetype/ttpload.h | 6 +- src/3rdparty/freetype/src/truetype/ttsubpix.c | 2 +- src/3rdparty/freetype/src/type1/t1afm.c | 4 +- src/3rdparty/freetype/src/type1/t1driver.c | 93 +-- src/3rdparty/freetype/src/type1/t1load.c | 256 ++++---- src/3rdparty/freetype/src/type1/t1load.h | 22 +- src/3rdparty/freetype/src/type1/t1objs.c | 8 +- src/3rdparty/freetype/src/type42/t42drivr.c | 43 +- src/3rdparty/freetype/src/type42/t42parse.c | 92 +-- src/3rdparty/freetype/src/winfonts/winfnt.c | 40 +- 139 files changed, 4191 insertions(+), 3282 deletions(-) create mode 100644 src/3rdparty/freetype/src/tools/vms_shorten_symbol.c diff --git a/src/3rdparty/freetype/README b/src/3rdparty/freetype/README index 327b94d8e55..eb48e7e1848 100644 --- a/src/3rdparty/freetype/README +++ b/src/3rdparty/freetype/README @@ -1,4 +1,4 @@ -FreeType 2.13.0 +FreeType 2.13.1 =============== Homepage: https://www.freetype.org @@ -32,9 +32,9 @@ sites. Go to and download one of the following files. - freetype-doc-2.13.0.tar.xz - freetype-doc-2.13.0.tar.gz - ftdoc2130.zip + freetype-doc-2.13.1.tar.xz + freetype-doc-2.13.1.tar.gz + ftdoc2131.zip To view the documentation online, go to diff --git a/src/3rdparty/freetype/docs/CHANGES b/src/3rdparty/freetype/docs/CHANGES index 3c6a8774b12..b6ad1ce5df8 100644 --- a/src/3rdparty/freetype/docs/CHANGES +++ b/src/3rdparty/freetype/docs/CHANGES @@ -1,3 +1,43 @@ +CHANGES BETWEEN 2.13.0 and 2.13.1 (2023-Jun-24) + + I. MISCELLANEOUS + + - New function `FT_Get_Default_Named_Instance` to get the index of + the default named instance of an OpenType Variation Font. + + - A new load flag `FT_LOAD_NO_SVG` to make FreeType ignore glyphs in + an 'SVG ' table. + + - New function `FT_GlyphSlot_AdjustWeight` to adjust the glyph + weight either horizontally or vertically. This is part of the + `ftsynth.h` header file, which is still considered to be in alpha + stage. + + - TrueType interpreter version 38 (also known as 'Infinality') has + been deactivated; the value of `TT_INTERPRETER_VERSION_38` is now + the same as `TT_INTERPRETER_VERSION_40`. + + - Updated OpenVMS support. + + - The base API documentation has been modularized for easier + handling. + + - Switching named instances on and off in Variation Fonts was buggy + if the design coordinates didn't change. + + - `ftbench` has a new command-line option `-a` to apply design + coordinates. + + - `ftview` can now flip SVG rendering on and off using the 'Z' key. + + - In `ftmulti` it is now possible to toggle the fill rule and + overlap flag used for rendering glyphs using the 'F3' and 'F4' + keys, respectively. Toggling the anti-aliased mode has been + changed to the 'TAB' key. + + +====================================================================== + CHANGES BETWEEN 2.12.1 and 2.13.0 (2023-Feb-09) I. IMPORTANT CHANGES @@ -12,7 +52,7 @@ CHANGES BETWEEN 2.12.1 and 2.13.0 (2023-Feb-09) https://learn.microsoft.com/en-us/typography/opentype/spec/colr - III. MISCELLANEOUS + II. MISCELLANEOUS - For OpenType Variable Fonts, `avar` table format 2.0 is now supported. The code was contributed by Behdad Esfahbod. @@ -75,6 +115,10 @@ CHANGES BETWEEN 2.12.1 and 2.13.0 (2023-Feb-09) af_debug_hints_ ``` + - The internal zlib library was updated to version 1.2.13. Note, + however, that FreeType is *not* affected by CVE-2022-37434 since + it doesn't use the `inflateGetHeader` function. + ====================================================================== @@ -2420,7 +2464,7 @@ CHANGES BETWEEN 2.3.8 and 2.3.7 is provided for x86 and ARM. See FT_CONFIG_OPTION_INLINE_MULFIX and FT_CONFIG_OPTION_NO_ASSEMBLER (in ftoption.h) for more. - - The handling of `tricky' fonts (this is, fonts which don't work + - The handling of `tricky' fonts (that is, fonts which don't work with the autohinter, needing the font format's hinting engine) has been generalized and changed slightly: @@ -2877,7 +2921,7 @@ CHANGES BETWEEN 2.2 and 2.1.10 II. IMPORTANT CHANGES - - Version 2.2 no longer exposes its internals, this is, the header + - Version 2.2 no longer exposes its internals, that is, the header files located in the `include/freetype/internal' directory of the source package are not copied anymore by the `make install' command. Consequently, a number of rogue clients which directly diff --git a/src/3rdparty/freetype/docs/DEBUG b/src/3rdparty/freetype/docs/DEBUG index 4a5ac3a40c6..7398df69b12 100644 --- a/src/3rdparty/freetype/docs/DEBUG +++ b/src/3rdparty/freetype/docs/DEBUG @@ -270,12 +270,12 @@ to access them. `FT2_DEBUG' environment variable. Use this function to override the value with `level'. Use value `NULL' to disable tracing. - FT_Trace_Set_Default_Level(): + FT_Trace_Set_Default_Level( void ) Reset the tracing levels to the default value, i.e., the value of the `FT2_DEBUG' environment variable or no tracing if not set. - FT_Set_Log_Handler( ft_custom_log_handler handler ): + FT_Set_Log_Handler( ft_custom_log_handler handler ) Use `handler' as a custom handler for formatting tracing and error messages. The `ft_custom_log_handler' typedef has the following @@ -290,7 +290,7 @@ to access them. first argument of `FT_TRACE' or `FT_ERROR', and `args' holds the remaining arguments. - FT_Set_Default_Log_Handler(): + FT_Set_Default_Log_Handler( void ) Reset the log handler to the default version. diff --git a/src/3rdparty/freetype/include/freetype/config/ftoption.h b/src/3rdparty/freetype/include/freetype/config/ftoption.h index 9e03e1783be..1976b33af95 100644 --- a/src/3rdparty/freetype/include/freetype/config/ftoption.h +++ b/src/3rdparty/freetype/include/freetype/config/ftoption.h @@ -661,36 +661,12 @@ FT_BEGIN_HEADER * not) instructions in a certain way so that all TrueType fonts look like * they do in a Windows ClearType (DirectWrite) environment. See [1] for a * technical overview on what this means. See `ttinterp.h` for more - * details on the LEAN option. + * details on this option. * - * There are three possible values. - * - * Value 1: - * This value is associated with the 'Infinality' moniker, contributed by - * an individual nicknamed Infinality with the goal of making TrueType - * fonts render better than on Windows. A high amount of configurability - * and flexibility, down to rules for single glyphs in fonts, but also - * very slow. Its experimental and slow nature and the original - * developer losing interest meant that this option was never enabled in - * default builds. - * - * The corresponding interpreter version is v38. - * - * Value 2: - * The new default mode for the TrueType driver. The Infinality code - * base was stripped to the bare minimum and all configurability removed - * in the name of speed and simplicity. The configurability was mainly - * aimed at legacy fonts like 'Arial', 'Times New Roman', or 'Courier'. - * Legacy fonts are fonts that modify vertical stems to achieve clean - * black-and-white bitmaps. The new mode focuses on applying a minimal - * set of rules to all fonts indiscriminately so that modern and web - * fonts render well while legacy fonts render okay. - * - * The corresponding interpreter version is v40. - * - * Value 3: - * Compile both, making both v38 and v40 available (the latter is the - * default). + * The new default mode focuses on applying a minimal set of rules to all + * fonts indiscriminately so that modern and web fonts render well while + * legacy fonts render okay. The corresponding interpreter version is v40. + * The so-called Infinality mode (v38) is no longer available in FreeType. * * By undefining these, you get rendering behavior like on Windows without * ClearType, i.e., Windows XP without ClearType enabled and Win9x @@ -705,9 +681,7 @@ FT_BEGIN_HEADER * [1] * https://www.microsoft.com/typography/cleartype/truetypecleartype.aspx */ -/* #define TT_CONFIG_OPTION_SUBPIXEL_HINTING 1 */ -#define TT_CONFIG_OPTION_SUBPIXEL_HINTING 2 -/* #define TT_CONFIG_OPTION_SUBPIXEL_HINTING ( 1 | 2 ) */ +#define TT_CONFIG_OPTION_SUBPIXEL_HINTING /************************************************************************** @@ -977,21 +951,14 @@ FT_BEGIN_HEADER /* - * The next three macros are defined if native TrueType hinting is + * The next two macros are defined if native TrueType hinting is * requested by the definitions above. Don't change this. */ #ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER #define TT_USE_BYTECODE_INTERPRETER - #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING -#if TT_CONFIG_OPTION_SUBPIXEL_HINTING & 1 -#define TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY -#endif - -#if TT_CONFIG_OPTION_SUBPIXEL_HINTING & 2 #define TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL #endif -#endif #endif diff --git a/src/3rdparty/freetype/include/freetype/config/ftstdlib.h b/src/3rdparty/freetype/include/freetype/config/ftstdlib.h index 3c9d2ae59a4..f65148a902e 100644 --- a/src/3rdparty/freetype/include/freetype/config/ftstdlib.h +++ b/src/3rdparty/freetype/include/freetype/config/ftstdlib.h @@ -111,13 +111,13 @@ #include -#define FT_FILE FILE -#define ft_fclose fclose -#define ft_fopen fopen -#define ft_fread fread -#define ft_fseek fseek -#define ft_ftell ftell -#define ft_sprintf sprintf +#define FT_FILE FILE +#define ft_fclose fclose +#define ft_fopen fopen +#define ft_fread fread +#define ft_fseek fseek +#define ft_ftell ftell +#define ft_snprintf snprintf /************************************************************************** diff --git a/src/3rdparty/freetype/include/freetype/freetype.h b/src/3rdparty/freetype/include/freetype/freetype.h index efff74fe399..4a074a4449b 100644 --- a/src/3rdparty/freetype/include/freetype/freetype.h +++ b/src/3rdparty/freetype/include/freetype/freetype.h @@ -102,61 +102,25 @@ FT_BEGIN_HEADER */ - - /*************************************************************************/ - /*************************************************************************/ - /* */ - /* B A S I C T Y P E S */ - /* */ - /*************************************************************************/ - /*************************************************************************/ - - /************************************************************************** * * @section: - * base_interface + * font_testing_macros * * @title: - * Base Interface + * Font Testing Macros * * @abstract: - * The FreeType~2 base font interface. + * Macros to test various properties of fonts. * * @description: - * This section describes the most important public high-level API - * functions of FreeType~2. + * Macros to test the most important font properties. + * + * It is recommended to use these high-level macros instead of directly + * testing the corresponding flags, which are scattered over various + * structures. * * @order: - * FT_Library - * FT_Face - * FT_Size - * FT_GlyphSlot - * FT_CharMap - * FT_Encoding - * FT_ENC_TAG - * - * FT_FaceRec - * - * FT_FACE_FLAG_SCALABLE - * FT_FACE_FLAG_FIXED_SIZES - * FT_FACE_FLAG_FIXED_WIDTH - * FT_FACE_FLAG_HORIZONTAL - * FT_FACE_FLAG_VERTICAL - * FT_FACE_FLAG_COLOR - * FT_FACE_FLAG_SFNT - * FT_FACE_FLAG_CID_KEYED - * FT_FACE_FLAG_TRICKY - * FT_FACE_FLAG_KERNING - * FT_FACE_FLAG_MULTIPLE_MASTERS - * FT_FACE_FLAG_VARIATION - * FT_FACE_FLAG_GLYPH_NAMES - * FT_FACE_FLAG_EXTERNAL_STREAM - * FT_FACE_FLAG_HINTER - * FT_FACE_FLAG_SVG - * FT_FACE_FLAG_SBIX - * FT_FACE_FLAG_SBIX_OVERLAY - * * FT_HAS_HORIZONTAL * FT_HAS_VERTICAL * FT_HAS_KERNING @@ -176,21 +140,59 @@ FT_BEGIN_HEADER * FT_IS_NAMED_INSTANCE * FT_IS_VARIATION * - * FT_STYLE_FLAG_BOLD - * FT_STYLE_FLAG_ITALIC + */ + + + /************************************************************************** * - * FT_SizeRec - * FT_Size_Metrics + * @section: + * library_setup * - * FT_GlyphSlotRec - * FT_Glyph_Metrics - * FT_SubGlyph + * @title: + * Library Setup * - * FT_Bitmap_Size + * @abstract: + * Functions to start and end the usage of the FreeType library. * + * @description: + * Functions to start and end the usage of the FreeType library. + * + * Note that @FT_Library_Version and @FREETYPE_XXX are of limited use + * because even a new release of FreeType with only documentation + * changes increases the version number. + * + * @order: + * FT_Library * FT_Init_FreeType * FT_Done_FreeType * + * FT_Library_Version + * FREETYPE_XXX + * + */ + + + /************************************************************************** + * + * @section: + * face_creation + * + * @title: + * Face Creation + * + * @abstract: + * Functions to manage fonts. + * + * @description: + * The functions and structures collected in this section operate on + * fonts globally. + * + * @order: + * FT_Face + * FT_FaceRec + * FT_FACE_FLAG_XXX + * FT_STYLE_FLAG_XXX + * * FT_New_Face * FT_Done_Face * FT_Reference_Face @@ -198,10 +200,36 @@ FT_BEGIN_HEADER * FT_Face_Properties * FT_Open_Face * FT_Open_Args + * FT_OPEN_XXX * FT_Parameter * FT_Attach_File * FT_Attach_Stream * + */ + + + /************************************************************************** + * + * @section: + * sizing_and_scaling + * + * @title: + * Sizing and Scaling + * + * @abstract: + * Functions to manage font sizes. + * + * @description: + * The functions and structures collected in this section are related to + * selecting and manipulating the size of a font globally. + * + * @order: + * FT_Size + * FT_SizeRec + * FT_Size_Metrics + * + * FT_Bitmap_Size + * * FT_Set_Char_Size * FT_Set_Pixel_Sizes * FT_Request_Size @@ -209,44 +237,37 @@ FT_BEGIN_HEADER * FT_Size_Request_Type * FT_Size_RequestRec * FT_Size_Request + * * FT_Set_Transform * FT_Get_Transform + * + */ + + + /************************************************************************** + * + * @section: + * glyph_retrieval + * + * @title: + * Glyph Retrieval + * + * @abstract: + * Functions to manage glyphs. + * + * @description: + * The functions and structures collected in this section operate on + * single glyphs, of which @FT_Load_Glyph is most important. + * + * @order: + * FT_GlyphSlot + * FT_GlyphSlotRec + * FT_Glyph_Metrics + * * FT_Load_Glyph - * FT_Get_Char_Index - * FT_Get_First_Char - * FT_Get_Next_Char - * FT_Load_Char - * - * FT_OPEN_MEMORY - * FT_OPEN_STREAM - * FT_OPEN_PATHNAME - * FT_OPEN_DRIVER - * FT_OPEN_PARAMS - * - * FT_LOAD_DEFAULT - * FT_LOAD_RENDER - * FT_LOAD_MONOCHROME - * FT_LOAD_LINEAR_DESIGN - * FT_LOAD_NO_SCALE - * FT_LOAD_NO_HINTING - * FT_LOAD_NO_BITMAP - * FT_LOAD_SBITS_ONLY - * FT_LOAD_NO_AUTOHINT - * FT_LOAD_COLOR - * - * FT_LOAD_VERTICAL_LAYOUT - * FT_LOAD_IGNORE_TRANSFORM - * FT_LOAD_FORCE_AUTOHINT - * FT_LOAD_NO_RECURSE - * FT_LOAD_PEDANTIC - * - * FT_LOAD_TARGET_NORMAL - * FT_LOAD_TARGET_LIGHT - * FT_LOAD_TARGET_MONO - * FT_LOAD_TARGET_LCD - * FT_LOAD_TARGET_LCD_V - * + * FT_LOAD_XXX * FT_LOAD_TARGET_MODE + * FT_LOAD_TARGET_XXX * * FT_Render_Glyph * FT_Render_Mode @@ -254,34 +275,121 @@ FT_BEGIN_HEADER * FT_Kerning_Mode * FT_Get_Track_Kerning * + */ + + + /************************************************************************** + * + * @section: + * character_mapping + * + * @title: + * Character Mapping + * + * @abstract: + * Functions to manage character-to-glyph maps. + * + * @description: + * This section holds functions and structures that are related to + * mapping character input codes to glyph indices. + * + * Note that for many scripts the simplistic approach used by FreeType + * of mapping a single character to a single glyph is not valid or + * possible! In general, a higher-level library like HarfBuzz or ICU + * should be used for handling text strings. + * + * @order: + * FT_CharMap * FT_CharMapRec + * FT_Encoding + * FT_ENC_TAG + * * FT_Select_Charmap * FT_Set_Charmap * FT_Get_Charmap_Index * + * FT_Get_Char_Index + * FT_Get_First_Char + * FT_Get_Next_Char + * FT_Load_Char + * + */ + + + /************************************************************************** + * + * @section: + * information_retrieval + * + * @title: + * Information Retrieval + * + * @abstract: + * Functions to retrieve font and glyph information. + * + * @description: + * Functions to retrieve font and glyph information. Only some very + * basic data is covered; see also the chapter on the format-specific + * API for more. + * + * + * @order: * FT_Get_Name_Index * FT_Get_Glyph_Name * FT_Get_Postscript_Name * FT_Get_FSType_Flags + * FT_FSTYPE_XXX * FT_Get_SubGlyph_Info + * FT_SUBGLYPH_FLAG_XXX * + */ + + + /************************************************************************** + * + * @section: + * other_api_data + * + * @title: + * Other API Data + * + * @abstract: + * Other structures, enumerations, and macros. + * + * @description: + * Other structures, enumerations, and macros. Deprecated functions are + * also listed here. + * + * @order: * FT_Face_Internal * FT_Size_Internal * FT_Slot_Internal * - * FT_FACE_FLAG_XXX - * FT_STYLE_FLAG_XXX - * FT_OPEN_XXX - * FT_LOAD_XXX - * FT_LOAD_TARGET_XXX - * FT_SUBGLYPH_FLAG_XXX - * FT_FSTYPE_XXX + * FT_SubGlyph * * FT_HAS_FAST_GLYPHS + * FT_Face_CheckTrueTypePatents + * FT_Face_SetUnpatentedHinting * */ + /*************************************************************************/ + /*************************************************************************/ + /* */ + /* B A S I C T Y P E S */ + /* */ + /*************************************************************************/ + /*************************************************************************/ + + + /************************************************************************** + * + * @section: + * glyph_retrieval + * + */ + /************************************************************************** * * @struct: @@ -349,6 +457,13 @@ FT_BEGIN_HEADER } FT_Glyph_Metrics; + /************************************************************************** + * + * @section: + * sizing_and_scaling + * + */ + /************************************************************************** * * @struct: @@ -409,6 +524,13 @@ FT_BEGIN_HEADER /*************************************************************************/ /*************************************************************************/ + /************************************************************************** + * + * @section: + * library_setup + * + */ + /************************************************************************** * * @type: @@ -483,7 +605,7 @@ FT_BEGIN_HEADER /************************************************************************** * * @section: - * base_interface + * face_creation * */ @@ -519,6 +641,13 @@ FT_BEGIN_HEADER typedef struct FT_FaceRec_* FT_Face; + /************************************************************************** + * + * @section: + * sizing_and_scaling + * + */ + /************************************************************************** * * @type: @@ -551,6 +680,13 @@ FT_BEGIN_HEADER typedef struct FT_SizeRec_* FT_Size; + /************************************************************************** + * + * @section: + * glyph_retrieval + * + */ + /************************************************************************** * * @type: @@ -570,6 +706,13 @@ FT_BEGIN_HEADER typedef struct FT_GlyphSlotRec_* FT_GlyphSlot; + /************************************************************************** + * + * @section: + * character_mapping + * + */ + /************************************************************************** * * @type: @@ -877,6 +1020,13 @@ FT_BEGIN_HEADER /*************************************************************************/ + /************************************************************************** + * + * @section: + * other_api_data + * + */ + /************************************************************************** * * @type: @@ -892,6 +1042,13 @@ FT_BEGIN_HEADER typedef struct FT_Face_InternalRec_* FT_Face_Internal; + /************************************************************************** + * + * @section: + * face_creation + * + */ + /************************************************************************** * * @struct: @@ -918,7 +1075,7 @@ FT_BEGIN_HEADER * If we have the third named instance of face~4, say, `face_index` is * set to 0x00030004. * - * Bit 31 is always zero (this is, `face_index` is always a positive + * Bit 31 is always zero (that is, `face_index` is always a positive * value). * * [Since 2.9] Changing the design coordinates with @@ -936,7 +1093,7 @@ FT_BEGIN_HEADER * * [Since 2.6.1] Bits 16-30 hold the number of named instances * available for the current face if we have a GX or OpenType variation - * (sub)font. Bit 31 is always zero (this is, `style_flags` is always + * (sub)font. Bit 31 is always zero (that is, `style_flags` is always * a positive value). Note that a variation font has always at least * one named instance, namely the default instance. * @@ -1002,7 +1159,7 @@ FT_BEGIN_HEADER * Note that the bounding box might be off by (at least) one pixel for * hinted fonts. See @FT_Size_Metrics for further discussion. * - * Note that the bounding box does not vary in OpenType variable fonts + * Note that the bounding box does not vary in OpenType variation fonts * and should only be used in relation to the default instance. * * units_per_EM :: @@ -1090,9 +1247,9 @@ FT_BEGIN_HEADER FT_Generic generic; - /*# The following member variables (down to `underline_thickness`) */ - /*# are only relevant to scalable outlines; cf. @FT_Bitmap_Size */ - /*# for bitmap fonts. */ + /* The following member variables (down to `underline_thickness`) */ + /* are only relevant to scalable outlines; cf. @FT_Bitmap_Size */ + /* for bitmap fonts. */ FT_BBox bbox; FT_UShort units_per_EM; @@ -1110,7 +1267,7 @@ FT_BEGIN_HEADER FT_Size size; FT_CharMap charmap; - /*@private begin */ + /* private fields, internal to FreeType */ FT_Driver driver; FT_Memory memory; @@ -1123,8 +1280,6 @@ FT_BEGIN_HEADER FT_Face_Internal internal; - /*@private end */ - } FT_FaceRec; @@ -1207,13 +1362,13 @@ FT_BEGIN_HEADER * successfully; in all other cases you get an * `FT_Err_Invalid_Argument` error. * - * Note that CID-keyed fonts that are in an SFNT wrapper (this is, all + * Note that CID-keyed fonts that are in an SFNT wrapper (that is, all * OpenType/CFF fonts) don't have this flag set since the glyphs are * accessed in the normal way (using contiguous indices); the * 'CID-ness' isn't visible to the application. * * FT_FACE_FLAG_TRICKY :: - * The face is 'tricky', this is, it always needs the font format's + * The face is 'tricky', that is, it always needs the font format's * native hinting engine to get a reasonable result. A typical example * is the old Chinese font `mingli.ttf` (but not `mingliu.ttc`) that * uses TrueType bytecode instructions to move and scale all of its @@ -1235,8 +1390,8 @@ FT_BEGIN_HEADER * FT_FACE_FLAG_VARIATION :: * [Since 2.9] Set if the current face (or named instance) has been * altered with @FT_Set_MM_Design_Coordinates, - * @FT_Set_Var_Design_Coordinates, or @FT_Set_Var_Blend_Coordinates. - * This flag is unset by a call to @FT_Set_Named_Instance. + * @FT_Set_Var_Design_Coordinates, @FT_Set_Var_Blend_Coordinates, or + * @FT_Set_MM_WeightVector to select a non-default instance. * * FT_FACE_FLAG_SVG :: * [Since 2.12] The face has an 'SVG~' OpenType table. @@ -1272,6 +1427,13 @@ FT_BEGIN_HEADER #define FT_FACE_FLAG_SBIX_OVERLAY ( 1L << 18 ) + /************************************************************************** + * + * @section: + * font_testing_macros + * + */ + /************************************************************************** * * @macro: @@ -1381,6 +1543,13 @@ FT_BEGIN_HEADER ( !!( (face)->face_flags & FT_FACE_FLAG_FIXED_SIZES ) ) + /************************************************************************** + * + * @section: + * other_api_data + * + */ + /************************************************************************** * * @macro: @@ -1393,6 +1562,13 @@ FT_BEGIN_HEADER #define FT_HAS_FAST_GLYPHS( face ) 0 + /************************************************************************** + * + * @section: + * font_testing_macros + * + */ + /************************************************************************** * * @macro: @@ -1451,8 +1627,8 @@ FT_BEGIN_HEADER * * @description: * A macro that returns true whenever a face object has been altered by - * @FT_Set_MM_Design_Coordinates, @FT_Set_Var_Design_Coordinates, or - * @FT_Set_Var_Blend_Coordinates. + * @FT_Set_MM_Design_Coordinates, @FT_Set_Var_Design_Coordinates, + * @FT_Set_Var_Blend_Coordinates, or @FT_Set_MM_WeightVector. * * @since: * 2.9 @@ -1628,6 +1804,13 @@ FT_BEGIN_HEADER ( !!( (face)->face_flags & FT_FACE_FLAG_SBIX_OVERLAY ) ) + /************************************************************************** + * + * @section: + * face_creation + * + */ + /************************************************************************** * * @enum: @@ -1654,6 +1837,13 @@ FT_BEGIN_HEADER #define FT_STYLE_FLAG_BOLD ( 1 << 1 ) + /************************************************************************** + * + * @section: + * other_api_data + * + */ + /************************************************************************** * * @type: @@ -1666,6 +1856,13 @@ FT_BEGIN_HEADER typedef struct FT_Size_InternalRec_* FT_Size_Internal; + /************************************************************************** + * + * @section: + * sizing_and_scaling + * + */ + /************************************************************************** * * @struct: @@ -1817,6 +2014,13 @@ FT_BEGIN_HEADER } FT_SizeRec; + /************************************************************************** + * + * @section: + * other_api_data + * + */ + /************************************************************************** * * @struct: @@ -1848,6 +2052,13 @@ FT_BEGIN_HEADER typedef struct FT_Slot_InternalRec_* FT_Slot_Internal; + /************************************************************************** + * + * @section: + * glyph_retrieval + * + */ + /************************************************************************** * * @struct: @@ -2092,6 +2303,13 @@ FT_BEGIN_HEADER /*************************************************************************/ + /************************************************************************** + * + * @section: + * library_setup + * + */ + /************************************************************************** * * @function: @@ -2149,6 +2367,13 @@ FT_BEGIN_HEADER FT_Done_FreeType( FT_Library library ); + /************************************************************************** + * + * @section: + * face_creation + * + */ + /************************************************************************** * * @enum: @@ -2451,7 +2676,7 @@ FT_BEGIN_HEADER * Each new face object created with this function also owns a default * @FT_Size object, accessible as `face->size`. * - * One @FT_Library instance can have multiple face objects, this is, + * One @FT_Library instance can have multiple face objects, that is, * @FT_Open_Face and its siblings can be called multiple times using the * same `library` argument. * @@ -2650,6 +2875,13 @@ FT_BEGIN_HEADER FT_Done_Face( FT_Face face ); + /************************************************************************** + * + * @section: + * sizing_and_scaling + * + */ + /************************************************************************** * * @function: @@ -2679,7 +2911,7 @@ FT_BEGIN_HEADER * silently uses outlines if there is no bitmap for a given glyph index. * * For GX and OpenType variation fonts, a bitmap strike makes sense only - * if the default instance is active (this is, no glyph variation takes + * if the default instance is active (that is, no glyph variation takes * place); otherwise, FreeType simply ignores bitmap strikes. The same * is true for all named instances that are different from the default * instance. @@ -2942,6 +3174,13 @@ FT_BEGIN_HEADER FT_UInt pixel_height ); + /************************************************************************** + * + * @section: + * glyph_retrieval + * + */ + /************************************************************************** * * @function: @@ -2976,7 +3215,7 @@ FT_BEGIN_HEADER * glyph may be transformed. See @FT_Set_Transform for the details. * * For subsetted CID-keyed fonts, `FT_Err_Invalid_Argument` is returned - * for invalid CID values (this is, for CID values that don't have a + * for invalid CID values (that is, for CID values that don't have a * corresponding glyph in the font). See the discussion of the * @FT_FACE_FLAG_CID_KEYED flag for more details. * @@ -2990,6 +3229,13 @@ FT_BEGIN_HEADER FT_Int32 load_flags ); + /************************************************************************** + * + * @section: + * character_mapping + * + */ + /************************************************************************** * * @function: @@ -3033,6 +3279,13 @@ FT_BEGIN_HEADER FT_Int32 load_flags ); + /************************************************************************** + * + * @section: + * glyph_retrieval + * + */ + /************************************************************************** * * @enum: @@ -3172,10 +3425,11 @@ FT_BEGIN_HEADER * * [Since 2.12] If the glyph index maps to an entry in the face's * 'SVG~' table, load the associated SVG document from this table and - * set the `format` field of @FT_GlyphSlotRec to @FT_GLYPH_FORMAT_SVG. - * Note that FreeType itself can't render SVG documents; however, the - * library provides hooks to seamlessly integrate an external renderer. - * See sections @ot_svg_driver and @svg_fonts for more. + * set the `format` field of @FT_GlyphSlotRec to @FT_GLYPH_FORMAT_SVG + * ([since 2.13.1] provided @FT_LOAD_NO_SVG is not set). Note that + * FreeType itself can't render SVG documents; however, the library + * provides hooks to seamlessly integrate an external renderer. See + * sections @ot_svg_driver and @svg_fonts for more. * * [Since 2.10, experimental] If the glyph index maps to an entry in * the face's 'COLR' table with a 'CPAL' palette table (as defined in @@ -3189,6 +3443,9 @@ FT_BEGIN_HEADER * @FT_Palette_Select instead of setting @FT_LOAD_COLOR for rendering * so that the client application can handle blending by itself. * + * FT_LOAD_NO_SVG :: + * [Since 2.13.1] Ignore SVG glyph data when loading. + * * FT_LOAD_COMPUTE_METRICS :: * [Since 2.6.1] Compute glyph metrics from the glyph data, without the * use of bundled metrics tables (for example, the 'hdmx' table in @@ -3254,6 +3511,7 @@ FT_BEGIN_HEADER #define FT_LOAD_COLOR ( 1L << 20 ) #define FT_LOAD_COMPUTE_METRICS ( 1L << 21 ) #define FT_LOAD_BITMAP_METRICS_ONLY ( 1L << 22 ) +#define FT_LOAD_NO_SVG ( 1L << 24 ) /* */ @@ -3372,6 +3630,13 @@ FT_BEGIN_HEADER FT_STATIC_CAST( FT_Render_Mode, ( (x) >> 16 ) & 15 ) + /************************************************************************** + * + * @section: + * sizing_and_scaling + * + */ + /************************************************************************** * * @function: @@ -3447,6 +3712,13 @@ FT_BEGIN_HEADER FT_Vector* delta ); + /************************************************************************** + * + * @section: + * glyph_retrieval + * + */ + /************************************************************************** * * @enum: @@ -3841,6 +4113,13 @@ FT_BEGIN_HEADER FT_Fixed* akerning ); + /************************************************************************** + * + * @section: + * character_mapping + * + */ + /************************************************************************** * * @function: @@ -4057,6 +4336,13 @@ FT_BEGIN_HEADER FT_UInt *agindex ); + /************************************************************************** + * + * @section: + * face_creation + * + */ + /************************************************************************** * * @function: @@ -4155,6 +4441,13 @@ FT_BEGIN_HEADER FT_Parameter* properties ); + /************************************************************************** + * + * @section: + * information_retrieval + * + */ + /************************************************************************** * * @function: @@ -4266,9 +4559,10 @@ FT_BEGIN_HEADER * * [Since 2.9] Special PostScript names for named instances are only * returned if the named instance is set with @FT_Set_Named_Instance (and - * the font has corresponding entries in its 'fvar' table). If - * @FT_IS_VARIATION returns true, the algorithmically derived PostScript - * name is provided, not looking up special entries for named instances. + * the font has corresponding entries in its 'fvar' table or is the + * default named instance). If @FT_IS_VARIATION returns true, the + * algorithmically derived PostScript name is provided, not looking up + * special entries for named instances. */ FT_EXPORT( const char* ) FT_Get_Postscript_Name( FT_Face face ); @@ -4900,32 +5194,10 @@ FT_BEGIN_HEADER /************************************************************************** * * @section: - * version - * - * @title: - * FreeType Version - * - * @abstract: - * Functions and macros related to FreeType versions. - * - * @description: - * Note that those functions and macros are of limited use because even a - * new release of FreeType with only documentation changes increases the - * version number. - * - * @order: - * FT_Library_Version - * - * FREETYPE_MAJOR - * FREETYPE_MINOR - * FREETYPE_PATCH - * - * FT_Face_CheckTrueTypePatents - * FT_Face_SetUnpatentedHinting + * library_setup * */ - /************************************************************************** * * @enum: @@ -4950,7 +5222,7 @@ FT_BEGIN_HEADER */ #define FREETYPE_MAJOR 2 #define FREETYPE_MINOR 13 -#define FREETYPE_PATCH 0 +#define FREETYPE_PATCH 1 /************************************************************************** @@ -4992,6 +5264,13 @@ FT_BEGIN_HEADER FT_Int *apatch ); + /************************************************************************** + * + * @section: + * other_api_data + * + */ + /************************************************************************** * * @function: diff --git a/src/3rdparty/freetype/include/freetype/ftcache.h b/src/3rdparty/freetype/include/freetype/ftcache.h index c76869545a7..a2072e26b82 100644 --- a/src/3rdparty/freetype/include/freetype/ftcache.h +++ b/src/3rdparty/freetype/include/freetype/ftcache.h @@ -43,61 +43,61 @@ FT_BEGIN_HEADER * objects, as well as caching information like character maps and glyph * images while limiting their maximum memory usage. * - * Note that all types and functions begin with the `FTC_` prefix. + * Note that all types and functions begin with the `FTC_` prefix rather + * than the usual `FT_` prefix in the rest of FreeType. * - * The cache is highly portable and thus doesn't know anything about the - * fonts installed on your system, or how to access them. This implies - * the following scheme: + * The cache is highly portable and, thus, doesn't know anything about + * the fonts installed on your system, or how to access them. Therefore, + * it requires the following. * - * First, available or installed font faces are uniquely identified by - * @FTC_FaceID values, provided to the cache by the client. Note that - * the cache only stores and compares these values, and doesn't try to - * interpret them in any way. + * * @FTC_FaceID, an arbitrary non-zero value that uniquely identifies + * available or installed font faces, has to be provided to the + * cache by the client. Note that the cache only stores and compares + * these values and doesn't try to interpret them in any way, but they + * have to be persistent on the client side. * - * Second, the cache calls, only when needed, a client-provided function - * to convert an @FTC_FaceID into a new @FT_Face object. The latter is - * then completely managed by the cache, including its termination - * through @FT_Done_Face. To monitor termination of face objects, the - * finalizer callback in the `generic` field of the @FT_Face object can - * be used, which might also be used to store the @FTC_FaceID of the - * face. + * * @FTC_Face_Requester, a method to convert an @FTC_FaceID into a new + * @FT_Face object when necessary, has to be provided to the cache by + * the client. The @FT_Face object is completely managed by the cache, + * including its termination through @FT_Done_Face. To monitor + * termination of face objects, the finalizer callback in the `generic` + * field of the @FT_Face object can be used, which might also be used + * to store the @FTC_FaceID of the face. * - * Clients are free to map face IDs to anything else. The most simple - * usage is to associate them to a (pathname,face_index) pair that is - * used to call @FT_New_Face. However, more complex schemes are also - * possible. + * Clients are free to map face IDs to anything useful. The most simple + * usage is, for example, to associate them to a `{pathname,face_index}` + * pair that is then used by @FTC_Face_Requester to call @FT_New_Face. + * However, more complex schemes are also possible. * * Note that for the cache to work correctly, the face ID values must be * **persistent**, which means that the contents they point to should not * change at runtime, or that their value should not become invalid. - * * If this is unavoidable (e.g., when a font is uninstalled at runtime), - * you should call @FTC_Manager_RemoveFaceID as soon as possible, to let + * you should call @FTC_Manager_RemoveFaceID as soon as possible to let * the cache get rid of any references to the old @FTC_FaceID it may keep * internally. Failure to do so will lead to incorrect behaviour or even - * crashes. + * crashes in @FTC_Face_Requester. * * To use the cache, start with calling @FTC_Manager_New to create a new * @FTC_Manager object, which models a single cache instance. You can * then look up @FT_Face and @FT_Size objects with - * @FTC_Manager_LookupFace and @FTC_Manager_LookupSize, respectively. + * @FTC_Manager_LookupFace and @FTC_Manager_LookupSize, respectively, and + * use them in any FreeType work stream. You can also cache other + * FreeType objects as follows. * - * If you want to use the charmap caching, call @FTC_CMapCache_New, then - * later use @FTC_CMapCache_Lookup to perform the equivalent of - * @FT_Get_Char_Index, only much faster. + * * If you want to use the charmap caching, call @FTC_CMapCache_New, + * then later use @FTC_CMapCache_Lookup to perform the equivalent of + * @FT_Get_Char_Index, only much faster. * - * If you want to use the @FT_Glyph caching, call @FTC_ImageCache_New, - * then later use @FTC_ImageCache_Lookup to retrieve the corresponding - * @FT_Glyph objects from the cache. - * - * If you need lots of small bitmaps, it is much more memory efficient to - * call @FTC_SBitCache_New followed by @FTC_SBitCache_Lookup. This - * returns @FTC_SBitRec structures, which are used to store small bitmaps - * directly. (A small bitmap is one whose metrics and dimensions all fit - * into 8-bit integers). - * - * We hope to also provide a kerning cache in the near future. + * * If you want to use the @FT_Glyph caching, call @FTC_ImageCache_New, + * then later use @FTC_ImageCache_Lookup to retrieve the corresponding + * @FT_Glyph objects from the cache. * + * * If you need lots of small bitmaps, it is much more memory-efficient + * to call @FTC_SBitCache_New followed by @FTC_SBitCache_Lookup. This + * returns @FTC_SBitRec structures, which are used to store small + * bitmaps directly. (A small bitmap is one whose metrics and + * dimensions all fit into 8-bit integers). * * @order: * FTC_Manager diff --git a/src/3rdparty/freetype/include/freetype/ftchapters.h b/src/3rdparty/freetype/include/freetype/ftchapters.h index 6a9733ad7c1..7566fbd10f8 100644 --- a/src/3rdparty/freetype/include/freetype/ftchapters.h +++ b/src/3rdparty/freetype/include/freetype/ftchapters.h @@ -31,9 +31,28 @@ * Core API * * @sections: - * version * basic_types - * base_interface + * library_setup + * face_creation + * font_testing_macros + * sizing_and_scaling + * glyph_retrieval + * character_mapping + * information_retrieval + * other_api_data + * + */ + + + /************************************************************************** + * + * @chapter: + * extended_api + * + * @title: + * Extended API + * + * @sections: * glyph_variants * color_management * layer_management diff --git a/src/3rdparty/freetype/include/freetype/ftdriver.h b/src/3rdparty/freetype/include/freetype/ftdriver.h index f90946fd17d..7af7465bc76 100644 --- a/src/3rdparty/freetype/include/freetype/ftdriver.h +++ b/src/3rdparty/freetype/include/freetype/ftdriver.h @@ -134,7 +134,7 @@ FT_BEGIN_HEADER * each being rounded to the nearest pixel edge, taking care of overshoot * suppression at small sizes, stem darkening, and scaling. * - * Hstems (this is, hint values defined in the font to help align + * Hstems (that is, hint values defined in the font to help align * horizontal features) that fall within a blue zone are said to be * 'captured' and are aligned to that zone. Uncaptured stems are moved * in one of four ways, top edge up or down, bottom edge up or down. @@ -446,7 +446,7 @@ FT_BEGIN_HEADER * at smaller sizes. * * For the auto-hinter, stem-darkening is experimental currently and thus - * switched off by default (this is, `no-stem-darkening` is set to TRUE + * switched off by default (that is, `no-stem-darkening` is set to TRUE * by default). Total consistency with the CFF driver is not achieved * right now because the emboldening method differs and glyphs must be * scaled down on the Y-axis to keep outline points inside their @@ -651,11 +651,8 @@ FT_BEGIN_HEADER * Windows~98; only grayscale and B/W rasterizing is supported. * * TT_INTERPRETER_VERSION_38 :: - * Version~38 corresponds to MS rasterizer v.1.9; it is roughly - * equivalent to the hinting provided by DirectWrite ClearType (as can - * be found, for example, in the Internet Explorer~9 running on - * Windows~7). It is used in FreeType to select the 'Infinality' - * subpixel hinting code. The code may be removed in a future version. + * Version~38 is the same Version~40. The original 'Infinality' code is + * no longer available. * * TT_INTERPRETER_VERSION_40 :: * Version~40 corresponds to MS rasterizer v.2.1; it is roughly diff --git a/src/3rdparty/freetype/include/freetype/ftimage.h b/src/3rdparty/freetype/include/freetype/ftimage.h index 2e8e6734cc0..6baa812560e 100644 --- a/src/3rdparty/freetype/include/freetype/ftimage.h +++ b/src/3rdparty/freetype/include/freetype/ftimage.h @@ -19,7 +19,7 @@ /************************************************************************** * * Note: A 'raster' is simply a scan-line converter, used to render - * FT_Outlines into FT_Bitmaps. + * `FT_Outline`s into `FT_Bitmap`s. * */ @@ -256,6 +256,12 @@ FT_BEGIN_HEADER * palette :: * A typeless pointer to the bitmap palette; this field is intended for * paletted pixel modes. Not used currently. + * + * @note: + * `width` and `rows` refer to the *physical* size of the bitmap, not the + * *logical* one. For example, if @FT_Pixel_Mode is set to + * `FT_PIXEL_MODE_LCD`, the logical width is a just a third of the + * physical one. */ typedef struct FT_Bitmap_ { @@ -856,7 +862,7 @@ FT_BEGIN_HEADER * @FT_SpanFunc that takes the y~coordinate of the span as a parameter. * * The anti-aliased rasterizer produces coverage values from 0 to 255, - * this is, from completely transparent to completely opaque. + * that is, from completely transparent to completely opaque. */ typedef struct FT_Span_ { diff --git a/src/3rdparty/freetype/include/freetype/ftlogging.h b/src/3rdparty/freetype/include/freetype/ftlogging.h index 2246dc83651..53b8b896427 100644 --- a/src/3rdparty/freetype/include/freetype/ftlogging.h +++ b/src/3rdparty/freetype/include/freetype/ftlogging.h @@ -62,7 +62,7 @@ FT_BEGIN_HEADER * component. * * ``` - * FT_Trace_Set_Level( "any:7 memory:0 ); + * FT_Trace_Set_Level( "any:7 memory:0" ); * ``` * * @note: diff --git a/src/3rdparty/freetype/include/freetype/ftmm.h b/src/3rdparty/freetype/include/freetype/ftmm.h index e381ef3d30a..d145128a9bc 100644 --- a/src/3rdparty/freetype/include/freetype/ftmm.h +++ b/src/3rdparty/freetype/include/freetype/ftmm.h @@ -153,7 +153,7 @@ FT_BEGIN_HEADER * @note: * The fields `minimum`, `def`, and `maximum` are 16.16 fractional values * for TrueType GX and OpenType variation fonts. For Adobe MM fonts, the - * values are integers. + * values are whole numbers (i.e., the fractional part is zero). */ typedef struct FT_Var_Axis_ { @@ -399,8 +399,8 @@ FT_BEGIN_HEADER * * @note: * The design coordinates are 16.16 fractional values for TrueType GX and - * OpenType variation fonts. For Adobe MM fonts, the values are - * integers. + * OpenType variation fonts. For Adobe MM fonts, the values are supposed + * to be whole numbers (i.e., the fractional part is zero). * * [Since 2.8.1] To reset all axes to the default values, call the * function with `num_coords` set to zero and `coords` set to `NULL`. @@ -446,8 +446,8 @@ FT_BEGIN_HEADER * * @note: * The design coordinates are 16.16 fractional values for TrueType GX and - * OpenType variation fonts. For Adobe MM fonts, the values are - * integers. + * OpenType variation fonts. For Adobe MM fonts, the values are whole + * numbers (i.e., the fractional part is zero). * * @since: * 2.7.1 @@ -602,10 +602,12 @@ FT_BEGIN_HEADER * * @note: * Adobe Multiple Master fonts limit the number of designs, and thus the - * length of the weight vector to~16. + * length of the weight vector to 16~elements. * - * If `len` is zero and `weightvector` is `NULL`, the weight vector array - * is reset to the default values. + * If `len` is larger than zero, this function sets the + * @FT_FACE_FLAG_VARIATION bit in @FT_Face's `face_flags` field (i.e., + * @FT_IS_VARIATION will return true). If `len` is zero, this bit flag + * is unset and the weight vector array is reset to the default values. * * The Adobe documentation also states that the values in the * WeightVector array must total 1.0 +/-~0.001. In practice this does @@ -753,6 +755,45 @@ FT_BEGIN_HEADER FT_Set_Named_Instance( FT_Face face, FT_UInt instance_index ); + + /************************************************************************** + * + * @function: + * FT_Get_Default_Named_Instance + * + * @description: + * Retrieve the index of the default named instance, to be used with + * @FT_Set_Named_Instance. + * + * The default instance of a variation font is that instance for which + * the nth axis coordinate is equal to `axis[n].def` (as specified in the + * @FT_MM_Var structure), with~n covering all axes. + * + * FreeType synthesizes a named instance for the default instance if the + * font does not contain such an entry. + * + * @input: + * face :: + * A handle to the source face. + * + * @output: + * instance_index :: + * The index of the default named instance. + * + * @return: + * FreeType error code. 0~means success. + * + * @note: + * For Adobe MM fonts (which don't have named instances) this function + * always returns zero for `instance_index`. + * + * @since: + * 2.13.1 + */ + FT_EXPORT( FT_Error ) + FT_Get_Default_Named_Instance( FT_Face face, + FT_UInt *instance_index ); + /* */ diff --git a/src/3rdparty/freetype/include/freetype/ftoutln.h b/src/3rdparty/freetype/include/freetype/ftoutln.h index 54434b25f6f..f9329ca40c9 100644 --- a/src/3rdparty/freetype/include/freetype/ftoutln.h +++ b/src/3rdparty/freetype/include/freetype/ftoutln.h @@ -118,7 +118,7 @@ FT_BEGIN_HEADER * attachement. * * Similarly, the function returns success for an empty outline also - * (doing nothing, this is, not calling any emitter); if necessary, you + * (doing nothing, that is, not calling any emitter); if necessary, you * should filter this out, too. */ FT_EXPORT( FT_Error ) diff --git a/src/3rdparty/freetype/include/freetype/ftrender.h b/src/3rdparty/freetype/include/freetype/ftrender.h index a8576dab002..0b6fad32e84 100644 --- a/src/3rdparty/freetype/include/freetype/ftrender.h +++ b/src/3rdparty/freetype/include/freetype/ftrender.h @@ -158,7 +158,7 @@ FT_BEGIN_HEADER FT_Renderer_GetCBoxFunc get_glyph_cbox; FT_Renderer_SetModeFunc set_mode; - FT_Raster_Funcs* raster_class; + const FT_Raster_Funcs* raster_class; } FT_Renderer_Class; diff --git a/src/3rdparty/freetype/include/freetype/ftsynth.h b/src/3rdparty/freetype/include/freetype/ftsynth.h index 5d196976572..af90967dda0 100644 --- a/src/3rdparty/freetype/include/freetype/ftsynth.h +++ b/src/3rdparty/freetype/include/freetype/ftsynth.h @@ -68,6 +68,18 @@ FT_BEGIN_HEADER FT_EXPORT( void ) FT_GlyphSlot_Embolden( FT_GlyphSlot slot ); + /* Precisely adjust the glyph weight either horizontally or vertically. */ + /* The `xdelta` and `ydelta` values are fractions of the face Em size */ + /* (in fixed-point format). Considering that a regular face would have */ + /* stem widths on the order of 0.1 Em, a delta of 0.05 (0x0CCC) should */ + /* be very noticeable. To increase or decrease the weight, use positive */ + /* or negative values, respectively. */ + FT_EXPORT( void ) + FT_GlyphSlot_AdjustWeight( FT_GlyphSlot slot, + FT_Fixed xdelta, + FT_Fixed ydelta ); + + /* Slant an outline glyph to the right by about 12 degrees. */ FT_EXPORT( void ) FT_GlyphSlot_Oblique( FT_GlyphSlot slot ); diff --git a/src/3rdparty/freetype/include/freetype/ftsystem.h b/src/3rdparty/freetype/include/freetype/ftsystem.h index a995b078de5..3a08f4912c9 100644 --- a/src/3rdparty/freetype/include/freetype/ftsystem.h +++ b/src/3rdparty/freetype/include/freetype/ftsystem.h @@ -229,8 +229,7 @@ FT_BEGIN_HEADER * A handle to the source stream. * * offset :: - * The offset from the start of the stream to seek to if this is a seek - * operation (see note). + * The offset from the start of the stream to seek to. * * buffer :: * The address of the read buffer. @@ -239,16 +238,9 @@ FT_BEGIN_HEADER * The number of bytes to read from the stream. * * @return: - * The number of bytes effectively read by the stream. - * - * @note: - * This function performs a seek *or* a read operation depending on the - * argument values. If `count` is zero, the operation is a seek to - * `offset` bytes. If `count` is >~0, the operation is a read of `count` - * bytes from the current position in the stream, and the `offset` value - * should be ignored. - * - * For seek operations, a non-zero return value indicates an error. + * If count >~0, return the number of bytes effectively read by the + * stream (after seeking to `offset`). If count ==~0, return the status + * of the seek operation (non-zero indicates an error). * */ typedef unsigned long diff --git a/src/3rdparty/freetype/include/freetype/internal/compiler-macros.h b/src/3rdparty/freetype/include/freetype/internal/compiler-macros.h index 7883317fed9..6f67650979e 100644 --- a/src/3rdparty/freetype/include/freetype/internal/compiler-macros.h +++ b/src/3rdparty/freetype/include/freetype/internal/compiler-macros.h @@ -41,8 +41,11 @@ FT_BEGIN_HEADER # if ( defined( __STDC_VERSION__ ) && __STDC_VERSION__ > 201710L ) || \ ( defined( __cplusplus ) && __cplusplus > 201402L ) # define FALL_THROUGH [[__fallthrough__]] -# elif ( defined( __GNUC__ ) && __GNUC__ >= 7 ) || \ - ( defined( __clang__ ) && __clang_major__ >= 10 ) +# elif ( defined( __GNUC__ ) && __GNUC__ >= 7 ) || \ + ( defined( __clang__ ) && \ + ( defined( __apple_build_version__ ) \ + ? __apple_build_version__ >= 12000000 \ + : __clang_major__ >= 10 ) ) # define FALL_THROUGH __attribute__(( __fallthrough__ )) # else # define FALL_THROUGH ( (void)0 ) diff --git a/src/3rdparty/freetype/include/freetype/internal/ftdrv.h b/src/3rdparty/freetype/include/freetype/internal/ftdrv.h index f78912ca0c7..9001c07ad0b 100644 --- a/src/3rdparty/freetype/include/freetype/internal/ftdrv.h +++ b/src/3rdparty/freetype/include/freetype/internal/ftdrv.h @@ -157,6 +157,7 @@ FT_BEGIN_HEADER * A handle to a function used to select a new fixed size. It is used * only if @FT_FACE_FLAG_FIXED_SIZES is set. Can be set to 0 if the * scaling done in the base layer suffices. + * * @note: * Most function pointers, with the exception of `load_glyph`, can be set * to 0 to indicate a default behaviour. diff --git a/src/3rdparty/freetype/include/freetype/internal/ftmmtypes.h b/src/3rdparty/freetype/include/freetype/internal/ftmmtypes.h index b7c66c35def..c4b21d6144e 100644 --- a/src/3rdparty/freetype/include/freetype/internal/ftmmtypes.h +++ b/src/3rdparty/freetype/include/freetype/internal/ftmmtypes.h @@ -28,13 +28,19 @@ FT_BEGIN_HEADER typedef struct GX_ItemVarDataRec_ { - FT_UInt itemCount; /* number of delta sets per item */ - FT_UInt regionIdxCount; /* number of region indices */ - FT_UInt* regionIndices; /* array of `regionCount' indices; */ - /* these index `varRegionList' */ - FT_ItemVarDelta* deltaSet; /* array of `itemCount' deltas */ - /* use `innerIndex' for this array */ - + FT_UInt itemCount; /* Number of delta sets per item. */ + FT_UInt regionIdxCount; /* Number of region indices. */ + FT_UInt* regionIndices; /* Array of `regionCount` indices; */ + /* these index `varRegionList`. */ + FT_Byte* deltaSet; /* Array of `itemCount` deltas; */ + /* use `innerIndex` for this array. */ + FT_UShort wordDeltaCount; /* Number of the first 32-bit ints */ + /* or 16-bit ints of `deltaSet` */ + /* depending on `longWords`. */ + FT_Bool longWords; /* If true, `deltaSet` is a 32-bit */ + /* array followed by a 16-bit */ + /* array, otherwise a 16-bit array */ + /* followed by an 8-bit array. */ } GX_ItemVarDataRec, *GX_ItemVarData; diff --git a/src/3rdparty/freetype/include/freetype/internal/services/svmetric.h b/src/3rdparty/freetype/include/freetype/internal/services/svmetric.h index e588ea4872a..167617ebb3d 100644 --- a/src/3rdparty/freetype/include/freetype/internal/services/svmetric.h +++ b/src/3rdparty/freetype/include/freetype/internal/services/svmetric.h @@ -77,6 +77,9 @@ FT_BEGIN_HEADER typedef void (*FT_Metrics_Adjust_Func)( FT_Face face ); + typedef FT_Error + (*FT_Size_Reset_Func)( FT_Size size ); + FT_DEFINE_SERVICE( MetricsVariations ) { @@ -90,6 +93,7 @@ FT_BEGIN_HEADER FT_VOrg_Adjust_Func vorg_adjust; FT_Metrics_Adjust_Func metrics_adjust; + FT_Size_Reset_Func size_reset; }; @@ -101,7 +105,8 @@ FT_BEGIN_HEADER tsb_adjust_, \ bsb_adjust_, \ vorg_adjust_, \ - metrics_adjust_ ) \ + metrics_adjust_, \ + size_reset_ ) \ static const FT_Service_MetricsVariationsRec class_ = \ { \ hadvance_adjust_, \ @@ -111,7 +116,8 @@ FT_BEGIN_HEADER tsb_adjust_, \ bsb_adjust_, \ vorg_adjust_, \ - metrics_adjust_ \ + metrics_adjust_, \ + size_reset_ \ }; /* */ diff --git a/src/3rdparty/freetype/include/freetype/internal/services/svmm.h b/src/3rdparty/freetype/include/freetype/internal/services/svmm.h index d94204232e1..7e76ab8324e 100644 --- a/src/3rdparty/freetype/include/freetype/internal/services/svmm.h +++ b/src/3rdparty/freetype/include/freetype/internal/services/svmm.h @@ -60,9 +60,9 @@ FT_BEGIN_HEADER /* use return value -1 to indicate that the new coordinates */ /* are equal to the current ones; no changes are thus needed */ typedef FT_Error - (*FT_Set_MM_Blend_Func)( FT_Face face, - FT_UInt num_coords, - FT_Long* coords ); + (*FT_Set_MM_Blend_Func)( FT_Face face, + FT_UInt num_coords, + FT_Fixed* coords ); typedef FT_Error (*FT_Get_Var_Design_Func)( FT_Face face, @@ -70,13 +70,17 @@ FT_BEGIN_HEADER FT_Fixed* coords ); typedef FT_Error - (*FT_Set_Instance_Func)( FT_Face face, - FT_UInt instance_index ); + (*FT_Set_Named_Instance_Func)( FT_Face face, + FT_UInt instance_index ); typedef FT_Error - (*FT_Get_MM_Blend_Func)( FT_Face face, - FT_UInt num_coords, - FT_Long* coords ); + (*FT_Get_Default_Named_Instance_Func)( FT_Face face, + FT_UInt *instance_index ); + + typedef FT_Error + (*FT_Get_MM_Blend_Func)( FT_Face face, + FT_UInt num_coords, + FT_Fixed* coords ); typedef FT_Error (*FT_Get_Var_Blend_Func)( FT_Face face, @@ -86,7 +90,7 @@ FT_BEGIN_HEADER FT_MM_Var* *mm_var ); typedef void - (*FT_Done_Blend_Func)( FT_Face ); + (*FT_Done_Blend_Func)( FT_Face face ); typedef FT_Error (*FT_Set_MM_WeightVector_Func)( FT_Face face, @@ -98,6 +102,9 @@ FT_BEGIN_HEADER FT_UInt* len, FT_Fixed* weight_vector ); + typedef void + (*FT_Construct_PS_Name_Func)( FT_Face face ); + typedef FT_Error (*FT_Var_Load_Delta_Set_Idx_Map_Func)( FT_Face face, FT_ULong offset, @@ -134,11 +141,13 @@ FT_BEGIN_HEADER FT_Get_MM_Var_Func get_mm_var; FT_Set_Var_Design_Func set_var_design; FT_Get_Var_Design_Func get_var_design; - FT_Set_Instance_Func set_instance; + FT_Set_Named_Instance_Func set_named_instance; + FT_Get_Default_Named_Instance_Func get_default_named_instance; FT_Set_MM_WeightVector_Func set_mm_weightvector; FT_Get_MM_WeightVector_Func get_mm_weightvector; /* for internal use; only needed for code sharing between modules */ + FT_Construct_PS_Name_Func construct_ps_name; FT_Var_Load_Delta_Set_Idx_Map_Func load_delta_set_idx_map; FT_Var_Load_Item_Var_Store_Func load_item_var_store; FT_Var_Get_Item_Delta_Func get_item_delta; @@ -149,43 +158,49 @@ FT_BEGIN_HEADER }; -#define FT_DEFINE_SERVICE_MULTIMASTERSREC( class_, \ - get_mm_, \ - set_mm_design_, \ - set_mm_blend_, \ - get_mm_blend_, \ - get_mm_var_, \ - set_var_design_, \ - get_var_design_, \ - set_instance_, \ - set_weightvector_, \ - get_weightvector_, \ - load_delta_set_idx_map_, \ - load_item_var_store_, \ - get_item_delta_, \ - done_item_var_store_, \ - done_delta_set_idx_map_, \ - get_var_blend_, \ - done_blend_ ) \ - static const FT_Service_MultiMastersRec class_ = \ - { \ - get_mm_, \ - set_mm_design_, \ - set_mm_blend_, \ - get_mm_blend_, \ - get_mm_var_, \ - set_var_design_, \ - get_var_design_, \ - set_instance_, \ - set_weightvector_, \ - get_weightvector_, \ - load_delta_set_idx_map_, \ - load_item_var_store_, \ - get_item_delta_, \ - done_item_var_store_, \ - done_delta_set_idx_map_, \ - get_var_blend_, \ - done_blend_ \ +#define FT_DEFINE_SERVICE_MULTIMASTERSREC( class_, \ + get_mm_, \ + set_mm_design_, \ + set_mm_blend_, \ + get_mm_blend_, \ + get_mm_var_, \ + set_var_design_, \ + get_var_design_, \ + set_named_instance_, \ + get_default_named_instance_, \ + set_mm_weightvector_, \ + get_mm_weightvector_, \ + \ + construct_ps_name_, \ + load_delta_set_idx_map_, \ + load_item_var_store_, \ + get_item_delta_, \ + done_item_var_store_, \ + done_delta_set_idx_map_, \ + get_var_blend_, \ + done_blend_ ) \ + static const FT_Service_MultiMastersRec class_ = \ + { \ + get_mm_, \ + set_mm_design_, \ + set_mm_blend_, \ + get_mm_blend_, \ + get_mm_var_, \ + set_var_design_, \ + get_var_design_, \ + set_named_instance_, \ + get_default_named_instance_, \ + set_mm_weightvector_, \ + get_mm_weightvector_, \ + \ + construct_ps_name_, \ + load_delta_set_idx_map_, \ + load_item_var_store_, \ + get_item_delta_, \ + done_item_var_store_, \ + done_delta_set_idx_map_, \ + get_var_blend_, \ + done_blend_ \ }; /* */ diff --git a/src/3rdparty/freetype/include/freetype/internal/services/svpscmap.h b/src/3rdparty/freetype/include/freetype/internal/services/svpscmap.h index fd99d857e47..6e599f3aabe 100644 --- a/src/3rdparty/freetype/include/freetype/internal/services/svpscmap.h +++ b/src/3rdparty/freetype/include/freetype/internal/services/svpscmap.h @@ -97,7 +97,7 @@ FT_BEGIN_HEADER (*PS_Unicodes_CharIndexFunc)( PS_Unicodes unicodes, FT_UInt32 unicode ); - typedef FT_UInt32 + typedef FT_UInt (*PS_Unicodes_CharNextFunc)( PS_Unicodes unicodes, FT_UInt32 *unicode ); diff --git a/src/3rdparty/freetype/include/freetype/internal/t1types.h b/src/3rdparty/freetype/include/freetype/internal/t1types.h index 5a105c58795..b9c94398fd1 100644 --- a/src/3rdparty/freetype/include/freetype/internal/t1types.h +++ b/src/3rdparty/freetype/include/freetype/internal/t1types.h @@ -201,30 +201,30 @@ FT_BEGIN_HEADER typedef struct T1_FaceRec_ { - FT_FaceRec root; - T1_FontRec type1; - const void* psnames; - const void* psaux; - const void* afm_data; - FT_CharMapRec charmaprecs[2]; - FT_CharMap charmaps[2]; + FT_FaceRec root; + T1_FontRec type1; + const void* psnames; + const void* psaux; + const void* afm_data; + FT_CharMapRec charmaprecs[2]; + FT_CharMap charmaps[2]; /* support for Multiple Masters fonts */ - PS_Blend blend; + PS_Blend blend; /* undocumented, optional: indices of subroutines that express */ /* the NormalizeDesignVector and the ConvertDesignVector procedure, */ /* respectively, as Type 2 charstrings; -1 if keywords not present */ - FT_Int ndv_idx; - FT_Int cdv_idx; + FT_Int ndv_idx; + FT_Int cdv_idx; /* undocumented, optional: has the same meaning as len_buildchar */ /* for Type 2 fonts; manipulated by othersubrs 19, 24, and 25 */ - FT_UInt len_buildchar; - FT_Long* buildchar; + FT_UInt len_buildchar; + FT_Long* buildchar; /* since version 2.1 - interface to PostScript hinter */ - const void* pshinter; + const void* pshinter; } T1_FaceRec; diff --git a/src/3rdparty/freetype/include/freetype/internal/tttypes.h b/src/3rdparty/freetype/include/freetype/internal/tttypes.h index 3b521924ca5..984121a0e48 100644 --- a/src/3rdparty/freetype/include/freetype/internal/tttypes.h +++ b/src/3rdparty/freetype/include/freetype/internal/tttypes.h @@ -779,13 +779,15 @@ FT_BEGIN_HEADER /************************************************************************** * * @struct: - * TT_Post_20Rec + * TT_Post_NamesRec * * @description: - * Postscript names sub-table, format 2.0. Stores the PS name of each - * glyph in the font face. + * Postscript names table, either format 2.0 or 2.5. * * @fields: + * loaded :: + * A flag to indicate whether the PS names are loaded. + * * num_glyphs :: * The number of named glyphs in the table. * @@ -798,68 +800,13 @@ FT_BEGIN_HEADER * glyph_names :: * The PS names not in Mac Encoding. */ - typedef struct TT_Post_20Rec_ + typedef struct TT_Post_NamesRec_ { + FT_Bool loaded; FT_UShort num_glyphs; FT_UShort num_names; FT_UShort* glyph_indices; - FT_Char** glyph_names; - - } TT_Post_20Rec, *TT_Post_20; - - - /************************************************************************** - * - * @struct: - * TT_Post_25Rec - * - * @description: - * Postscript names sub-table, format 2.5. Stores the PS name of each - * glyph in the font face. - * - * @fields: - * num_glyphs :: - * The number of glyphs in the table. - * - * offsets :: - * An array of signed offsets in a normal Mac Postscript name encoding. - */ - typedef struct TT_Post_25_ - { - FT_UShort num_glyphs; - FT_Char* offsets; - - } TT_Post_25Rec, *TT_Post_25; - - - /************************************************************************** - * - * @struct: - * TT_Post_NamesRec - * - * @description: - * Postscript names table, either format 2.0 or 2.5. - * - * @fields: - * loaded :: - * A flag to indicate whether the PS names are loaded. - * - * format_20 :: - * The sub-table used for format 2.0. - * - * format_25 :: - * The sub-table used for format 2.5. - */ - typedef struct TT_Post_NamesRec_ - { - FT_Bool loaded; - - union - { - TT_Post_20Rec format_20; - TT_Post_25Rec format_25; - - } names; + FT_Byte** glyph_names; } TT_Post_NamesRec, *TT_Post_Names; @@ -1253,12 +1200,16 @@ FT_BEGIN_HEADER * mm :: * A pointer to the Multiple Masters service. * - * var :: - * A pointer to the Metrics Variations service. + * tt_var :: + * A pointer to the Metrics Variations service for the "truetype" + * driver. * - * hdmx :: - * The face's horizontal device metrics ('hdmx' table). This table is - * optional in TrueType/OpenType fonts. + * face_var :: + * A pointer to the Metrics Variations service for this `TT_Face`'s + * driver. + * + * psaux :: + * A pointer to the PostScript Auxiliary service. * * gasp :: * The grid-fitting and scaling properties table ('gasp'). This table @@ -1364,6 +1315,12 @@ FT_BEGIN_HEADER * var_postscript_prefix_len :: * The length of the `var_postscript_prefix` string. * + * var_default_named_instance :: + * The index of the default named instance. + * + * non_var_style_name :: + * The non-variation style name, used as a backup. + * * horz_metrics_size :: * The size of the 'hmtx' table. * @@ -1410,14 +1367,6 @@ FT_BEGIN_HEADER * A mapping between the strike indices exposed by the API and the * indices used in the font's sbit table. * - * cpal :: - * A pointer to data related to the 'CPAL' table. `NULL` if the table - * is not available. - * - * colr :: - * A pointer to data related to the 'COLR' table. `NULL` if the table - * is not available. - * * kern_table :: * A pointer to the 'kern' table. * @@ -1458,6 +1407,18 @@ FT_BEGIN_HEADER * * ebdt_size :: * The size of the sbit data table. + * + * cpal :: + * A pointer to data related to the 'CPAL' table. `NULL` if the table + * is not available. + * + * colr :: + * A pointer to data related to the 'COLR' table. `NULL` if the table + * is not available. + * + * svg :: + * A pointer to data related to the 'SVG' table. `NULL` if the table + * is not available. */ typedef struct TT_FaceRec_ { @@ -1508,8 +1469,14 @@ FT_BEGIN_HEADER void* mm; /* a typeless pointer to the FT_Service_MetricsVariationsRec table */ - /* used to handle the HVAR, VVAR, and MVAR OpenType tables */ - void* var; + /* used to handle the HVAR, VVAR, and MVAR OpenType tables by the */ + /* "truetype" driver */ + void* tt_var; + + /* a typeless pointer to the FT_Service_MetricsVariationsRec table */ + /* used to handle the HVAR, VVAR, and MVAR OpenType tables by this */ + /* TT_Face's driver */ + void* face_var; /* since 2.13.1 */ #endif /* a typeless pointer to the PostScript Aux service */ @@ -1591,6 +1558,9 @@ FT_BEGIN_HEADER const char* var_postscript_prefix; /* since 2.7.2 */ FT_UInt var_postscript_prefix_len; /* since 2.7.2 */ + FT_UInt var_default_named_instance; /* since 2.13.1 */ + + const char* non_var_style_name; /* since 2.13.1 */ #endif /* since version 2.2 */ diff --git a/src/3rdparty/freetype/qt_attribution.json b/src/3rdparty/freetype/qt_attribution.json index abfc43aaf1f..31328c7b31c 100644 --- a/src/3rdparty/freetype/qt_attribution.json +++ b/src/3rdparty/freetype/qt_attribution.json @@ -7,8 +7,8 @@ "Description": "FreeType is a freely available software library to render fonts.", "Homepage": "http://www.freetype.org", - "Version": "2.13.0", - + "Version": "2.13.1", + "License": "Freetype Project License or GNU General Public License v2.0 only", "LicenseId": "FTL OR GPL-2.0", "LicenseFile": "LICENSE.txt", diff --git a/src/3rdparty/freetype/src/autofit/afblue.dat b/src/3rdparty/freetype/src/autofit/afblue.dat index b7efe8be6ce..8299baa2591 100644 --- a/src/3rdparty/freetype/src/autofit/afblue.dat +++ b/src/3rdparty/freetype/src/autofit/afblue.dat @@ -89,7 +89,7 @@ AF_BLUE_STRING_ENUM AF_BLUE_STRINGS_ARRAY AF_BLUE_STRING_MAX_LEN: "ت ث ط ظ ك" // We don't necessarily have access to medial forms via Unicode in case // Arabic presentational forms are missing. The only character that is - // guaranteed to have the same vertical position with joining (this is, + // guaranteed to have the same vertical position with joining (that is, // non-isolated) forms is U+0640, ARABIC TATWEEL, which must join both // round and flat curves. AF_BLUE_STRING_ARABIC_JOIN diff --git a/src/3rdparty/freetype/src/autofit/afcjk.c b/src/3rdparty/freetype/src/autofit/afcjk.c index 5daefff359c..af775b190c0 100644 --- a/src/3rdparty/freetype/src/autofit/afcjk.c +++ b/src/3rdparty/freetype/src/autofit/afcjk.c @@ -417,16 +417,14 @@ { FT_Int nn; - FT_Int first = 0; - FT_Int last = -1; + FT_Int pp, first, last; - for ( nn = 0; nn < outline.n_contours; first = last + 1, nn++ ) + last = -1; + for ( nn = 0; nn < outline.n_contours; nn++ ) { - FT_Int pp; - - - last = outline.contours[nn]; + first = last + 1; + last = outline.contours[nn]; /* Avoid single-point contours since they are never rasterized. */ /* In some fonts, they correspond to mark attachment points */ @@ -569,8 +567,8 @@ af_cjk_metrics_check_digits( AF_CJKMetrics metrics, FT_Face face ) { - FT_Bool started = 0, same_width = 1; - FT_Fixed advance = 0, old_advance = 0; + FT_Bool started = 0, same_width = 1; + FT_Long advance = 0, old_advance = 0; /* If HarfBuzz is not available, we need a pointer to a single */ /* unsigned long value. */ @@ -635,10 +633,11 @@ /* Initialize global metrics. */ FT_LOCAL_DEF( FT_Error ) - af_cjk_metrics_init( AF_CJKMetrics metrics, - FT_Face face ) + af_cjk_metrics_init( AF_StyleMetrics metrics_, /* AF_CJKMetrics */ + FT_Face face ) { - FT_CharMap oldmap = face->charmap; + AF_CJKMetrics metrics = (AF_CJKMetrics)metrics_; + FT_CharMap oldmap = face->charmap; metrics->units_per_em = face->units_per_EM; @@ -756,9 +755,12 @@ /* Scale global values in both directions. */ FT_LOCAL_DEF( void ) - af_cjk_metrics_scale( AF_CJKMetrics metrics, - AF_Scaler scaler ) + af_cjk_metrics_scale( AF_StyleMetrics metrics_, /* AF_CJKMetrics */ + AF_Scaler scaler ) { + AF_CJKMetrics metrics = (AF_CJKMetrics)metrics_; + + /* we copy the whole structure since the x and y scaling values */ /* are not modified, contrary to e.g. the `latin' auto-hinter */ metrics->root.scaler = *scaler; @@ -771,11 +773,14 @@ /* Extract standard_width from writing system/script specific */ /* metrics class. */ - FT_LOCAL_DEF( void ) - af_cjk_get_standard_widths( AF_CJKMetrics metrics, - FT_Pos* stdHW, - FT_Pos* stdVW ) + FT_CALLBACK_DEF( void ) + af_cjk_get_standard_widths( AF_StyleMetrics metrics_, /* AF_CJKMetrics */ + FT_Pos* stdHW, + FT_Pos* stdVW ) { + AF_CJKMetrics metrics = (AF_CJKMetrics)metrics_; + + if ( stdHW ) *stdHW = metrics->axis[AF_DIMENSION_VERT].standard_width; @@ -1376,9 +1381,10 @@ /* Initalize hinting engine. */ FT_LOCAL_DEF( FT_Error ) - af_cjk_hints_init( AF_GlyphHints hints, - AF_CJKMetrics metrics ) + af_cjk_hints_init( AF_GlyphHints hints, + AF_StyleMetrics metrics_ ) /* AF_CJKMetrics */ { + AF_CJKMetrics metrics = (AF_CJKMetrics)metrics_; FT_Render_Mode mode; FT_UInt32 scaler_flags, other_flags; @@ -2268,11 +2274,13 @@ /* Apply the complete hinting algorithm to a CJK glyph. */ FT_LOCAL_DEF( FT_Error ) - af_cjk_hints_apply( FT_UInt glyph_index, - AF_GlyphHints hints, - FT_Outline* outline, - AF_CJKMetrics metrics ) + af_cjk_hints_apply( FT_UInt glyph_index, + AF_GlyphHints hints, + FT_Outline* outline, + AF_StyleMetrics metrics_ ) /* AF_CJKMetrics */ { + AF_CJKMetrics metrics = (AF_CJKMetrics)metrics_; + FT_Error error; int dim; diff --git a/src/3rdparty/freetype/src/autofit/afcjk.h b/src/3rdparty/freetype/src/autofit/afcjk.h index bd7b81b3e24..f380ef6e032 100644 --- a/src/3rdparty/freetype/src/autofit/afcjk.h +++ b/src/3rdparty/freetype/src/autofit/afcjk.h @@ -103,22 +103,22 @@ FT_BEGIN_HEADER #ifdef AF_CONFIG_OPTION_CJK FT_LOCAL( FT_Error ) - af_cjk_metrics_init( AF_CJKMetrics metrics, - FT_Face face ); + af_cjk_metrics_init( AF_StyleMetrics metrics, + FT_Face face ); FT_LOCAL( void ) - af_cjk_metrics_scale( AF_CJKMetrics metrics, - AF_Scaler scaler ); + af_cjk_metrics_scale( AF_StyleMetrics metrics, + AF_Scaler scaler ); FT_LOCAL( FT_Error ) - af_cjk_hints_init( AF_GlyphHints hints, - AF_CJKMetrics metrics ); + af_cjk_hints_init( AF_GlyphHints hints, + AF_StyleMetrics metrics ); FT_LOCAL( FT_Error ) - af_cjk_hints_apply( FT_UInt glyph_index, - AF_GlyphHints hints, - FT_Outline* outline, - AF_CJKMetrics metrics ); + af_cjk_hints_apply( FT_UInt glyph_index, + AF_GlyphHints hints, + FT_Outline* outline, + AF_StyleMetrics metrics ); /* shared; called from afindic.c */ FT_LOCAL( void ) diff --git a/src/3rdparty/freetype/src/autofit/afglobal.c b/src/3rdparty/freetype/src/autofit/afglobal.c index ede27eb1660..b1957570f03 100644 --- a/src/3rdparty/freetype/src/autofit/afglobal.c +++ b/src/3rdparty/freetype/src/autofit/afglobal.c @@ -376,8 +376,11 @@ FT_LOCAL_DEF( void ) - af_face_globals_free( AF_FaceGlobals globals ) + af_face_globals_free( void* globals_ ) { + AF_FaceGlobals globals = (AF_FaceGlobals)globals_; + + if ( globals ) { FT_Memory memory = globals->face->memory; diff --git a/src/3rdparty/freetype/src/autofit/afglobal.h b/src/3rdparty/freetype/src/autofit/afglobal.h index 83a7c2ff15b..66170e419dd 100644 --- a/src/3rdparty/freetype/src/autofit/afglobal.h +++ b/src/3rdparty/freetype/src/autofit/afglobal.h @@ -156,7 +156,7 @@ FT_BEGIN_HEADER AF_StyleMetrics *ametrics ); FT_LOCAL( void ) - af_face_globals_free( AF_FaceGlobals globals ); + af_face_globals_free( void* globals ); FT_LOCAL( FT_Bool ) af_face_globals_is_digit( AF_FaceGlobals globals, diff --git a/src/3rdparty/freetype/src/autofit/afhints.c b/src/3rdparty/freetype/src/autofit/afhints.c index 6515af9f04e..e4a378fbf74 100644 --- a/src/3rdparty/freetype/src/autofit/afhints.c +++ b/src/3rdparty/freetype/src/autofit/afhints.c @@ -320,8 +320,9 @@ static char* - af_print_idx( char* p, - int idx ) + af_print_idx( char* p, + size_t n, + int idx ) { if ( idx == -1 ) { @@ -330,7 +331,7 @@ p[2] = '\0'; } else - ft_sprintf( p, "%d", idx ); + ft_snprintf( p, n, "%d", idx ); return p; } @@ -457,12 +458,12 @@ " %5d %5d %7.2f %7.2f %7.2f %7.2f" " %5s %5s %5s %5s\n", point_idx, - af_print_idx( buf1, + af_print_idx( buf1, 16, af_get_edge_index( hints, segment_idx_1, 1 ) ), - af_print_idx( buf2, segment_idx_1 ), - af_print_idx( buf3, + af_print_idx( buf2, 16, segment_idx_1 ), + af_print_idx( buf3, 16, af_get_edge_index( hints, segment_idx_0, 0 ) ), - af_print_idx( buf4, segment_idx_0 ), + af_print_idx( buf4, 16, segment_idx_0 ), ( point->flags & AF_FLAG_NEAR ) ? " near " : ( point->flags & AF_FLAG_WEAK_INTERPOLATION ) @@ -476,18 +477,22 @@ (double)point->x / 64, (double)point->y / 64, - af_print_idx( buf5, af_get_strong_edge_index( hints, - point->before, - 1 ) ), - af_print_idx( buf6, af_get_strong_edge_index( hints, - point->after, - 1 ) ), - af_print_idx( buf7, af_get_strong_edge_index( hints, - point->before, - 0 ) ), - af_print_idx( buf8, af_get_strong_edge_index( hints, - point->after, - 0 ) ) )); + af_print_idx( buf5, 16, + af_get_strong_edge_index( hints, + point->before, + 1 ) ), + af_print_idx( buf6, 16, + af_get_strong_edge_index( hints, + point->after, + 1 ) ), + af_print_idx( buf7, 16, + af_get_strong_edge_index( hints, + point->before, + 0 ) ), + af_print_idx( buf8, 16, + af_get_strong_edge_index( hints, + point->after, + 0 ) ) )); } AF_DUMP(( "\n" )); } @@ -574,9 +579,12 @@ AF_INDEX_NUM( seg->first, points ), AF_INDEX_NUM( seg->last, points ), - af_print_idx( buf1, AF_INDEX_NUM( seg->link, segments ) ), - af_print_idx( buf2, AF_INDEX_NUM( seg->serif, segments ) ), - af_print_idx( buf3, AF_INDEX_NUM( seg->edge, edges ) ), + af_print_idx( buf1, 16, + AF_INDEX_NUM( seg->link, segments ) ), + af_print_idx( buf2, 16, + AF_INDEX_NUM( seg->serif, segments ) ), + af_print_idx( buf3, 16, + AF_INDEX_NUM( seg->edge, edges ) ), seg->height, seg->height - ( seg->max_coord - seg->min_coord ), @@ -716,8 +724,10 @@ AF_INDEX_NUM( edge, edges ), (double)(int)edge->opos / 64, af_dir_str( (AF_Direction)edge->dir ), - af_print_idx( buf1, AF_INDEX_NUM( edge->link, edges ) ), - af_print_idx( buf2, AF_INDEX_NUM( edge->serif, edges ) ), + af_print_idx( buf1, 16, + AF_INDEX_NUM( edge->link, edges ) ), + af_print_idx( buf2, 16, + AF_INDEX_NUM( edge->serif, edges ) ), edge->blue_edge ? 'y' : 'n', (double)edge->opos / 64, diff --git a/src/3rdparty/freetype/src/autofit/afindic.c b/src/3rdparty/freetype/src/autofit/afindic.c index 289a09d71d8..7fb12c63d5a 100644 --- a/src/3rdparty/freetype/src/autofit/afindic.c +++ b/src/3rdparty/freetype/src/autofit/afindic.c @@ -28,9 +28,12 @@ static FT_Error - af_indic_metrics_init( AF_CJKMetrics metrics, - FT_Face face ) + af_indic_metrics_init( AF_StyleMetrics metrics_, /* AF_CJKMetrics */ + FT_Face face ) { + AF_CJKMetrics metrics = (AF_CJKMetrics)metrics_; + + /* skip blue zone init in CJK routines */ FT_CharMap oldmap = face->charmap; @@ -55,8 +58,8 @@ static void - af_indic_metrics_scale( AF_CJKMetrics metrics, - AF_Scaler scaler ) + af_indic_metrics_scale( AF_StyleMetrics metrics, + AF_Scaler scaler ) { /* use CJK routines */ af_cjk_metrics_scale( metrics, scaler ); @@ -64,8 +67,8 @@ static FT_Error - af_indic_hints_init( AF_GlyphHints hints, - AF_CJKMetrics metrics ) + af_indic_hints_init( AF_GlyphHints hints, + AF_StyleMetrics metrics ) { /* use CJK routines */ return af_cjk_hints_init( hints, metrics ); @@ -73,10 +76,10 @@ static FT_Error - af_indic_hints_apply( FT_UInt glyph_index, - AF_GlyphHints hints, - FT_Outline* outline, - AF_CJKMetrics metrics ) + af_indic_hints_apply( FT_UInt glyph_index, + AF_GlyphHints hints, + FT_Outline* outline, + AF_StyleMetrics metrics ) { /* use CJK routines */ return af_cjk_hints_apply( glyph_index, hints, outline, metrics ); @@ -87,10 +90,13 @@ /* metrics class. */ static void - af_indic_get_standard_widths( AF_CJKMetrics metrics, - FT_Pos* stdHW, - FT_Pos* stdVW ) + af_indic_get_standard_widths( AF_StyleMetrics metrics_, /* AF_CJKMetrics */ + FT_Pos* stdHW, + FT_Pos* stdVW ) { + AF_CJKMetrics metrics = (AF_CJKMetrics)metrics_; + + if ( stdHW ) *stdHW = metrics->axis[AF_DIMENSION_VERT].standard_width; diff --git a/src/3rdparty/freetype/src/autofit/aflatin.c b/src/3rdparty/freetype/src/autofit/aflatin.c index 4b3c59b3c31..46c6e450a85 100644 --- a/src/3rdparty/freetype/src/autofit/aflatin.c +++ b/src/3rdparty/freetype/src/autofit/aflatin.c @@ -496,23 +496,20 @@ /* now compute min or max point indices and coordinates */ points = outline.points; best_point = -1; + best_contour_first = -1; + best_contour_last = -1; best_y = 0; /* make compiler happy */ - best_contour_first = 0; /* ditto */ - best_contour_last = 0; /* ditto */ { FT_Int nn; - FT_Int first = 0; - FT_Int last = -1; + FT_Int pp, first, last; - for ( nn = 0; nn < outline.n_contours; first = last + 1, nn++ ) + last = -1; + for ( nn = 0; nn < outline.n_contours; nn++ ) { - FT_Int old_best_point = best_point; - FT_Int pp; - - - last = outline.contours[nn]; + first = last + 1; + last = outline.contours[nn]; /* Avoid single-point contours since they are never */ /* rasterized. In some fonts, they correspond to mark */ @@ -551,7 +548,7 @@ } } - if ( best_point != old_best_point ) + if ( best_point > best_contour_last ) { best_contour_first = first; best_contour_last = last; @@ -1068,8 +1065,8 @@ af_latin_metrics_check_digits( AF_LatinMetrics metrics, FT_Face face ) { - FT_Bool started = 0, same_width = 1; - FT_Fixed advance = 0, old_advance = 0; + FT_Bool started = 0, same_width = 1; + FT_Long advance = 0, old_advance = 0; /* If HarfBuzz is not available, we need a pointer to a single */ /* unsigned long value. */ @@ -1134,9 +1131,11 @@ /* Initialize global metrics. */ FT_LOCAL_DEF( FT_Error ) - af_latin_metrics_init( AF_LatinMetrics metrics, + af_latin_metrics_init( AF_StyleMetrics metrics_, /* AF_LatinMetrics */ FT_Face face ) { + AF_LatinMetrics metrics = (AF_LatinMetrics)metrics_; + FT_Error error = FT_Err_Ok; FT_CharMap oldmap = face->charmap; @@ -1489,9 +1488,12 @@ /* Scale global values in both directions. */ FT_LOCAL_DEF( void ) - af_latin_metrics_scale( AF_LatinMetrics metrics, + af_latin_metrics_scale( AF_StyleMetrics metrics_, /* AF_LatinMetrics */ AF_Scaler scaler ) { + AF_LatinMetrics metrics = (AF_LatinMetrics)metrics_; + + metrics->root.scaler.render_mode = scaler->render_mode; metrics->root.scaler.face = scaler->face; metrics->root.scaler.flags = scaler->flags; @@ -1504,11 +1506,14 @@ /* Extract standard_width from writing system/script specific */ /* metrics class. */ - FT_LOCAL_DEF( void ) - af_latin_get_standard_widths( AF_LatinMetrics metrics, + FT_CALLBACK_DEF( void ) + af_latin_get_standard_widths( AF_StyleMetrics metrics_, /* AF_LatinMetrics */ FT_Pos* stdHW, FT_Pos* stdVW ) { + AF_LatinMetrics metrics = (AF_LatinMetrics)metrics_; + + if ( stdHW ) *stdHW = metrics->axis[AF_DIMENSION_VERT].standard_width; @@ -2041,7 +2046,7 @@ max = seg2->max_coord; /* compute maximum coordinate difference of the two segments */ - /* (this is, how much they overlap) */ + /* (that is, how much they overlap) */ len = max - min; if ( len >= len_threshold ) { @@ -2610,8 +2615,10 @@ static FT_Error af_latin_hints_init( AF_GlyphHints hints, - AF_LatinMetrics metrics ) + AF_StyleMetrics metrics_ ) /* AF_LatinMetrics */ { + AF_LatinMetrics metrics = (AF_LatinMetrics)metrics_; + FT_Render_Mode mode; FT_UInt32 scaler_flags, other_flags; FT_Face face = metrics->root.scaler.face; @@ -3547,8 +3554,10 @@ af_latin_hints_apply( FT_UInt glyph_index, AF_GlyphHints hints, FT_Outline* outline, - AF_LatinMetrics metrics ) + AF_StyleMetrics metrics_ ) /* AF_LatinMetrics */ { + AF_LatinMetrics metrics = (AF_LatinMetrics)metrics_; + FT_Error error; int dim; diff --git a/src/3rdparty/freetype/src/autofit/aflatin.h b/src/3rdparty/freetype/src/autofit/aflatin.h index 3c6a7ee4f62..31aa91d3bdb 100644 --- a/src/3rdparty/freetype/src/autofit/aflatin.h +++ b/src/3rdparty/freetype/src/autofit/aflatin.h @@ -116,11 +116,11 @@ FT_BEGIN_HEADER FT_LOCAL( FT_Error ) - af_latin_metrics_init( AF_LatinMetrics metrics, + af_latin_metrics_init( AF_StyleMetrics metrics, FT_Face face ); FT_LOCAL( void ) - af_latin_metrics_scale( AF_LatinMetrics metrics, + af_latin_metrics_scale( AF_StyleMetrics metrics, AF_Scaler scaler ); FT_LOCAL( void ) diff --git a/src/3rdparty/freetype/src/autofit/afloader.c b/src/3rdparty/freetype/src/autofit/afloader.c index c8082796fe8..7c47d562af6 100644 --- a/src/3rdparty/freetype/src/autofit/afloader.c +++ b/src/3rdparty/freetype/src/autofit/afloader.c @@ -55,10 +55,8 @@ error = af_face_globals_new( face, &loader->globals, module ); if ( !error ) { - face->autohint.data = - (FT_Pointer)loader->globals; - face->autohint.finalizer = - (FT_Generic_Finalizer)af_face_globals_free; + face->autohint.data = (FT_Pointer)loader->globals; + face->autohint.finalizer = af_face_globals_free; } } diff --git a/src/3rdparty/freetype/src/autofit/afmodule.c b/src/3rdparty/freetype/src/autofit/afmodule.c index 92e5156ab2d..20a6b96bc4f 100644 --- a/src/3rdparty/freetype/src/autofit/afmodule.c +++ b/src/3rdparty/freetype/src/autofit/afmodule.c @@ -89,10 +89,8 @@ error = af_face_globals_new( face, &globals, module ); if ( !error ) { - face->autohint.data = - (FT_Pointer)globals; - face->autohint.finalizer = - (FT_Generic_Finalizer)af_face_globals_free; + face->autohint.data = (FT_Pointer)globals; + face->autohint.finalizer = af_face_globals_free; } } @@ -374,8 +372,9 @@ FT_DEFINE_SERVICE_PROPERTIESREC( af_service_properties, - (FT_Properties_SetFunc)af_property_set, /* set_property */ - (FT_Properties_GetFunc)af_property_get ) /* get_property */ + af_property_set, /* FT_Properties_SetFunc set_property */ + af_property_get /* FT_Properties_GetFunc get_property */ + ) FT_DEFINE_SERVICEDESCREC1( @@ -430,12 +429,14 @@ FT_CALLBACK_DEF( FT_Error ) - af_autofitter_load_glyph( AF_Module module, - FT_GlyphSlot slot, - FT_Size size, - FT_UInt glyph_index, - FT_Int32 load_flags ) + af_autofitter_load_glyph( FT_AutoHinter module_, + FT_GlyphSlot slot, + FT_Size size, + FT_UInt glyph_index, + FT_Int32 load_flags ) { + AF_Module module = (AF_Module)module_; + FT_Error error = FT_Err_Ok; FT_Memory memory = module->root.library->memory; @@ -499,10 +500,10 @@ FT_DEFINE_AUTOHINTER_INTERFACE( af_autofitter_interface, - NULL, /* reset_face */ - NULL, /* get_global_hints */ - NULL, /* done_global_hints */ - (FT_AutoHinter_GlyphLoadFunc)af_autofitter_load_glyph /* load_glyph */ + NULL, /* FT_AutoHinter_GlobalResetFunc reset_face */ + NULL, /* FT_AutoHinter_GlobalGetFunc get_global_hints */ + NULL, /* FT_AutoHinter_GlobalDoneFunc done_global_hints */ + af_autofitter_load_glyph /* FT_AutoHinter_GlyphLoadFunc load_glyph */ ) FT_DEFINE_MODULE( @@ -517,9 +518,9 @@ (const void*)&af_autofitter_interface, - (FT_Module_Constructor)af_autofitter_init, /* module_init */ - (FT_Module_Destructor) af_autofitter_done, /* module_done */ - (FT_Module_Requester) af_get_interface /* get_interface */ + af_autofitter_init, /* FT_Module_Constructor module_init */ + af_autofitter_done, /* FT_Module_Destructor module_done */ + af_get_interface /* FT_Module_Requester get_interface */ ) diff --git a/src/3rdparty/freetype/src/autofit/afshaper.c b/src/3rdparty/freetype/src/autofit/afshaper.c index 1b8b870e89d..abc6f1d292d 100644 --- a/src/3rdparty/freetype/src/autofit/afshaper.c +++ b/src/3rdparty/freetype/src/autofit/afshaper.c @@ -258,7 +258,7 @@ /* * We now check whether we can construct blue zones, using glyphs * covered by the feature only. In case there is not a single zone - * (this is, not a single character is covered), we skip this coverage. + * (that is, not a single character is covered), we skip this coverage. * */ if ( style_class->coverage != AF_COVERAGE_DEFAULT ) @@ -313,9 +313,9 @@ * hinted and usually rendered glyph. * * Consider the superscript feature of font `pala.ttf': Some of the - * glyphs are `real', this is, they have a zero vertical offset, but + * glyphs are `real', that is, they have a zero vertical offset, but * most of them are small caps glyphs shifted up to the superscript - * position (this is, the `sups' feature is present in both the GSUB and + * position (that is, the `sups' feature is present in both the GSUB and * GPOS tables). The code for blue zones computation actually uses a * feature's y offset so that the `real' glyphs get correct hints. But * later on it is impossible to decide whether a glyph index belongs to, diff --git a/src/3rdparty/freetype/src/autofit/ft-hb.c b/src/3rdparty/freetype/src/autofit/ft-hb.c index 09a8401c4a8..71aee045503 100644 --- a/src/3rdparty/freetype/src/autofit/ft-hb.c +++ b/src/3rdparty/freetype/src/autofit/ft-hb.c @@ -108,7 +108,7 @@ hb_ft_font_create_ (FT_Face ft_face, #else /* !FT_CONFIG_OPTION_USE_HARFBUZZ */ /* ANSI C doesn't like empty source files */ -typedef int _ft_hb_dummy; +typedef int ft_hb_dummy_; #endif /* !FT_CONFIG_OPTION_USE_HARFBUZZ */ diff --git a/src/3rdparty/freetype/src/base/ftbbox.c b/src/3rdparty/freetype/src/base/ftbbox.c index 7dd71882ea5..385fea40401 100644 --- a/src/3rdparty/freetype/src/base/ftbbox.c +++ b/src/3rdparty/freetype/src/base/ftbbox.c @@ -82,10 +82,13 @@ * @Return: * Always 0. Needed for the interface only. */ - static int - BBox_Move_To( FT_Vector* to, - TBBox_Rec* user ) + FT_CALLBACK_DEF( int ) + BBox_Move_To( const FT_Vector* to, + void* user_ ) { + TBBox_Rec* user = (TBBox_Rec*)user_; + + FT_UPDATE_BBOX( to, user->bbox ); user->last = *to; @@ -116,10 +119,13 @@ * @Return: * Always 0. Needed for the interface only. */ - static int - BBox_Line_To( FT_Vector* to, - TBBox_Rec* user ) + FT_CALLBACK_DEF( int ) + BBox_Line_To( const FT_Vector* to, + void* user_ ) { + TBBox_Rec* user = (TBBox_Rec*)user_; + + user->last = *to; return 0; @@ -205,11 +211,14 @@ * In the case of a non-monotonous arc, we compute directly the * extremum coordinates, as it is sufficiently fast. */ - static int - BBox_Conic_To( FT_Vector* control, - FT_Vector* to, - TBBox_Rec* user ) + FT_CALLBACK_DEF( int ) + BBox_Conic_To( const FT_Vector* control, + const FT_Vector* to, + void* user_ ) { + TBBox_Rec* user = (TBBox_Rec*)user_; + + /* in case `to' is implicit and not included in bbox yet */ FT_UPDATE_BBOX( to, user->bbox ); @@ -410,12 +419,15 @@ * In the case of a non-monotonous arc, we don't compute directly * extremum coordinates, we subdivide instead. */ - static int - BBox_Cubic_To( FT_Vector* control1, - FT_Vector* control2, - FT_Vector* to, - TBBox_Rec* user ) + FT_CALLBACK_DEF( int ) + BBox_Cubic_To( const FT_Vector* control1, + const FT_Vector* control2, + const FT_Vector* to, + void* user_ ) { + TBBox_Rec* user = (TBBox_Rec*)user_; + + /* We don't need to check `to' since it is always an on-point, */ /* thus within the bbox. Only segments with an off-point outside */ /* the bbox can possibly reach new extreme values. */ diff --git a/src/3rdparty/freetype/src/base/ftcalc.c b/src/3rdparty/freetype/src/base/ftcalc.c index 13e74f3353b..442b08ddf9d 100644 --- a/src/3rdparty/freetype/src/base/ftcalc.c +++ b/src/3rdparty/freetype/src/base/ftcalc.c @@ -1061,7 +1061,7 @@ /* */ /* This approach has the advantage that the angle between */ /* `in' and `out' is not checked. In case one of the two */ - /* vectors is `dominant', this is, much larger than the */ + /* vectors is `dominant', that is, much larger than the */ /* other vector, we thus always have a flat corner. */ /* */ /* hypotenuse */ @@ -1103,7 +1103,7 @@ for ( i = 0; i < count; ++i ) temp += (FT_Int64)s[i] * f[i]; - return ( temp + 0x8000 ) >> 16; + return (FT_Int32)( ( temp + 0x8000 ) >> 16 ); #else temp.hi = 0; temp.lo = 0; diff --git a/src/3rdparty/freetype/src/base/ftdbgmem.c b/src/3rdparty/freetype/src/base/ftdbgmem.c index 6730c4c8d38..8fab50dd017 100644 --- a/src/3rdparty/freetype/src/base/ftdbgmem.c +++ b/src/3rdparty/freetype/src/base/ftdbgmem.c @@ -963,7 +963,7 @@ #else /* !FT_DEBUG_MEMORY */ /* ANSI C doesn't like empty source files */ - typedef int _debug_mem_dummy; + typedef int debug_mem_dummy_; #endif /* !FT_DEBUG_MEMORY */ diff --git a/src/3rdparty/freetype/src/base/ftmac.c b/src/3rdparty/freetype/src/base/ftmac.c index de34e834f25..492d0553845 100644 --- a/src/3rdparty/freetype/src/base/ftmac.c +++ b/src/3rdparty/freetype/src/base/ftmac.c @@ -1082,7 +1082,7 @@ #else /* !FT_MACINTOSH */ /* ANSI C doesn't like empty source files */ - typedef int _ft_mac_dummy; + typedef int ft_mac_dummy_; #endif /* !FT_MACINTOSH */ diff --git a/src/3rdparty/freetype/src/base/ftmm.c b/src/3rdparty/freetype/src/base/ftmm.c index a2b4bd03d78..9e2dd7ee79d 100644 --- a/src/3rdparty/freetype/src/base/ftmm.c +++ b/src/3rdparty/freetype/src/base/ftmm.c @@ -185,6 +185,14 @@ error = FT_ERR( Invalid_Argument ); if ( service->set_mm_design ) error = service->set_mm_design( face, num_coords, coords ); + + if ( !error ) + { + if ( num_coords ) + face->face_flags |= FT_FACE_FLAG_VARIATION; + else + face->face_flags &= ~FT_FACE_FLAG_VARIATION; + } } /* enforce recomputation of auto-hinting data */ @@ -220,6 +228,14 @@ error = FT_ERR( Invalid_Argument ); if ( service->set_mm_weightvector ) error = service->set_mm_weightvector( face, len, weightvector ); + + if ( !error ) + { + if ( len ) + face->face_flags |= FT_FACE_FLAG_VARIATION; + else + face->face_flags &= ~FT_FACE_FLAG_VARIATION; + } } /* enforce recomputation of auto-hinting data */ @@ -283,6 +299,30 @@ if ( service_mm->set_var_design ) error = service_mm->set_var_design( face, num_coords, coords ); + if ( !error || error == -1 ) + { + FT_Bool is_variation_old = FT_IS_VARIATION( face ); + + + if ( num_coords ) + face->face_flags |= FT_FACE_FLAG_VARIATION; + else + face->face_flags &= ~FT_FACE_FLAG_VARIATION; + + if ( service_mm->construct_ps_name ) + { + if ( error == -1 ) + { + /* The PS name of a named instance and a non-named instance */ + /* usually differs, even if the axis values are identical. */ + if ( is_variation_old != FT_IS_VARIATION( face ) ) + service_mm->construct_ps_name( face ); + } + else + service_mm->construct_ps_name( face ); + } + } + /* internal error code -1 means `no change'; we can exit immediately */ if ( error == -1 ) return FT_Err_Ok; @@ -359,6 +399,30 @@ if ( service_mm->set_mm_blend ) error = service_mm->set_mm_blend( face, num_coords, coords ); + if ( !error || error == -1 ) + { + FT_Bool is_variation_old = FT_IS_VARIATION( face ); + + + if ( num_coords ) + face->face_flags |= FT_FACE_FLAG_VARIATION; + else + face->face_flags &= ~FT_FACE_FLAG_VARIATION; + + if ( service_mm->construct_ps_name ) + { + if ( error == -1 ) + { + /* The PS name of a named instance and a non-named instance */ + /* usually differs, even if the axis values are identical. */ + if ( is_variation_old != FT_IS_VARIATION( face ) ) + service_mm->construct_ps_name( face ); + } + else + service_mm->construct_ps_name( face ); + } + } + /* internal error code -1 means `no change'; we can exit immediately */ if ( error == -1 ) return FT_Err_Ok; @@ -410,6 +474,30 @@ if ( service_mm->set_mm_blend ) error = service_mm->set_mm_blend( face, num_coords, coords ); + if ( !error || error == -1 ) + { + FT_Bool is_variation_old = FT_IS_VARIATION( face ); + + + if ( num_coords ) + face->face_flags |= FT_FACE_FLAG_VARIATION; + else + face->face_flags &= ~FT_FACE_FLAG_VARIATION; + + if ( service_mm->construct_ps_name ) + { + if ( error == -1 ) + { + /* The PS name of a named instance and a non-named instance */ + /* usually differs, even if the axis values are identical. */ + if ( is_variation_old != FT_IS_VARIATION( face ) ) + service_mm->construct_ps_name( face ); + } + else + service_mm->construct_ps_name( face ); + } + } + /* internal error code -1 means `no change'; we can exit immediately */ if ( error == -1 ) return FT_Err_Ok; @@ -535,8 +623,35 @@ if ( !error ) { error = FT_ERR( Invalid_Argument ); - if ( service_mm->set_instance ) - error = service_mm->set_instance( face, instance_index ); + if ( service_mm->set_named_instance ) + error = service_mm->set_named_instance( face, instance_index ); + + if ( !error || error == -1 ) + { + FT_Bool is_variation_old = FT_IS_VARIATION( face ); + + + face->face_flags &= ~FT_FACE_FLAG_VARIATION; + face->face_index = ( instance_index << 16 ) | + ( face->face_index & 0xFFFFL ); + + if ( service_mm->construct_ps_name ) + { + if ( error == -1 ) + { + /* The PS name of a named instance and a non-named instance */ + /* usually differs, even if the axis values are identical. */ + if ( is_variation_old != FT_IS_VARIATION( face ) ) + service_mm->construct_ps_name( face ); + } + else + service_mm->construct_ps_name( face ); + } + } + + /* internal error code -1 means `no change'; we can exit immediately */ + if ( error == -1 ) + return FT_Err_Ok; } if ( !error ) @@ -554,11 +669,32 @@ face->autohint.data = NULL; } + return error; + } + + + /* documentation is in ftmm.h */ + + FT_EXPORT_DEF( FT_Error ) + FT_Get_Default_Named_Instance( FT_Face face, + FT_UInt *instance_index ) + { + FT_Error error; + + FT_Service_MultiMasters service_mm = NULL; + + + /* check of `face' delayed to `ft_face_get_mm_service' */ + + error = ft_face_get_mm_service( face, &service_mm ); if ( !error ) { - face->face_index = ( instance_index << 16 ) | - ( face->face_index & 0xFFFFL ); - face->face_flags &= ~FT_FACE_FLAG_VARIATION; + /* no error if `get_default_named_instance` is not available */ + if ( service_mm->get_default_named_instance ) + error = service_mm->get_default_named_instance( face, + instance_index ); + else + error = FT_Err_Ok; } return error; diff --git a/src/3rdparty/freetype/src/base/ftobjs.c b/src/3rdparty/freetype/src/base/ftobjs.c index ad6ef0ae168..abfa3ab0e6e 100644 --- a/src/3rdparty/freetype/src/base/ftobjs.c +++ b/src/3rdparty/freetype/src/base/ftobjs.c @@ -1019,7 +1019,8 @@ /* elegant. */ /* try to load SVG documents if available */ - if ( FT_HAS_SVG( face ) ) + if ( ( load_flags & FT_LOAD_NO_SVG ) == 0 && + FT_HAS_SVG( face ) ) { error = driver->clazz->load_glyph( slot, face->size, glyph_index, @@ -1245,9 +1246,13 @@ /* destructor for sizes list */ static void destroy_size( FT_Memory memory, - FT_Size size, - FT_Driver driver ) + void* size_, + void* driver_ ) { + FT_Size size = (FT_Size)size_; + FT_Driver driver = (FT_Driver)driver_; + + /* finalize client-specific data */ if ( size->generic.finalizer ) size->generic.finalizer( size ); @@ -1293,10 +1298,12 @@ /* destructor for faces list */ static void destroy_face( FT_Memory memory, - FT_Face face, - FT_Driver driver ) + void* face_, + void* driver_ ) { - FT_Driver_Class clazz = driver->clazz; + FT_Face face = (FT_Face)face_; + FT_Driver driver = (FT_Driver)driver_; + FT_Driver_Class clazz = driver->clazz; /* discard auto-hinting data */ @@ -1310,7 +1317,7 @@ /* discard all sizes for this face */ FT_List_Finalize( &face->sizes_list, - (FT_List_Destructor)destroy_size, + destroy_size, memory, driver ); face->size = NULL; @@ -1346,7 +1353,7 @@ Destroy_Driver( FT_Driver driver ) { FT_List_Finalize( &driver->faces_list, - (FT_List_Destructor)destroy_face, + destroy_face, driver->root.memory, driver ); } diff --git a/src/3rdparty/freetype/src/base/ftoutln.c b/src/3rdparty/freetype/src/base/ftoutln.c index 30ff21ff39e..134f39d2b1f 100644 --- a/src/3rdparty/freetype/src/base/ftoutln.c +++ b/src/3rdparty/freetype/src/base/ftoutln.c @@ -58,7 +58,9 @@ FT_Error error; FT_Int n; /* index of contour in outline */ - FT_UInt first; /* index of first point in contour */ + FT_Int first; /* index of first point in contour */ + FT_Int last; /* index of last point in contour */ + FT_Int tag; /* current point's state */ FT_Int shift; @@ -73,18 +75,17 @@ shift = func_interface->shift; delta = func_interface->delta; - first = 0; + last = -1; for ( n = 0; n < outline->n_contours; n++ ) { - FT_Int last; /* index of last point in contour */ + FT_TRACE5(( "FT_Outline_Decompose: Contour %d\n", n )); - - FT_TRACE5(( "FT_Outline_Decompose: Outline %d\n", n )); - - last = outline->contours[n]; - if ( last < 0 ) + first = last + 1; + last = outline->contours[n]; + if ( last < first ) goto Invalid_Outline; + limit = outline->points + last; v_start = outline->points[first]; @@ -282,8 +283,6 @@ Close: if ( error ) goto Exit; - - first = (FT_UInt)last + 1; } FT_TRACE5(( "FT_Outline_Decompose: Done\n" )); @@ -368,7 +367,7 @@ if ( n_points <= 0 || n_contours <= 0 ) goto Bad; - end0 = end = -1; + end0 = -1; for ( n = 0; n < n_contours; n++ ) { end = outline->contours[n]; @@ -380,7 +379,7 @@ end0 = end; } - if ( end != n_points - 1 ) + if ( end0 != n_points - 1 ) goto Bad; /* XXX: check the tags array */ @@ -388,7 +387,7 @@ } Bad: - return FT_THROW( Invalid_Argument ); + return FT_THROW( Invalid_Outline ); } @@ -550,10 +549,12 @@ if ( !outline ) return; - first = 0; - + last = -1; for ( n = 0; n < outline->n_contours; n++ ) { + /* keep the first contour point as is and swap points around it */ + /* to guarantee that the cubic arches stay valid after reverse */ + first = last + 2; last = outline->contours[n]; /* reverse point table */ @@ -591,8 +592,6 @@ q--; } } - - first = last + 1; } outline->flags ^= FT_OUTLINE_REVERSE_FILL; @@ -941,7 +940,7 @@ points = outline->points; - first = 0; + last = -1; for ( c = 0; c < outline->n_contours; c++ ) { FT_Vector in, out, anchor, shift; @@ -949,8 +948,9 @@ FT_Int i, j, k; - l_in = 0; - last = outline->contours[c]; + first = last + 1; + last = outline->contours[c]; + l_in = 0; /* pacify compiler */ in.x = in.y = anchor.x = anchor.y = 0; @@ -1037,8 +1037,6 @@ in = out; l_in = l_out; } - - first = last + 1; } return FT_Err_Ok; @@ -1054,7 +1052,7 @@ FT_Int xshift, yshift; FT_Vector* points; FT_Vector v_prev, v_cur; - FT_Int c, n, first; + FT_Int c, n, first, last; FT_Pos area = 0; @@ -1086,11 +1084,11 @@ points = outline->points; - first = 0; + last = -1; for ( c = 0; c < outline->n_contours; c++ ) { - FT_Int last = outline->contours[c]; - + first = last + 1; + last = outline->contours[c]; v_prev.x = points[last].x >> xshift; v_prev.y = points[last].y >> yshift; @@ -1106,8 +1104,6 @@ v_prev = v_cur; } - - first = last + 1; } if ( area > 0 ) diff --git a/src/3rdparty/freetype/src/base/ftstroke.c b/src/3rdparty/freetype/src/base/ftstroke.c index db358e772ed..92f1e43080f 100644 --- a/src/3rdparty/freetype/src/base/ftstroke.c +++ b/src/3rdparty/freetype/src/base/ftstroke.c @@ -2055,7 +2055,9 @@ FT_Error error; FT_Int n; /* index of contour in outline */ - FT_UInt first; /* index of first point in contour */ + FT_Int first; /* index of first point in contour */ + FT_Int last; /* index of last point in contour */ + FT_Int tag; /* current point's state */ @@ -2067,22 +2069,17 @@ FT_Stroker_Rewind( stroker ); - first = 0; - + last = -1; for ( n = 0; n < outline->n_contours; n++ ) { - FT_UInt last; /* index of last point in contour */ - - - last = (FT_UInt)outline->contours[n]; - limit = outline->points + last; + first = last + 1; + last = outline->contours[n]; /* skip empty points; we don't stroke these */ if ( last <= first ) - { - first = last + 1; continue; - } + + limit = outline->points + last; v_start = outline->points[first]; v_last = outline->points[last]; @@ -2231,8 +2228,6 @@ if ( error ) goto Exit; } - - first = last + 1; } return FT_Err_Ok; diff --git a/src/3rdparty/freetype/src/base/ftsynth.c b/src/3rdparty/freetype/src/base/ftsynth.c index 6ec25e13e47..f32edd3388b 100644 --- a/src/3rdparty/freetype/src/base/ftsynth.c +++ b/src/3rdparty/freetype/src/base/ftsynth.c @@ -97,9 +97,18 @@ FT_EXPORT_DEF( void ) FT_GlyphSlot_Embolden( FT_GlyphSlot slot ) + { + FT_GlyphSlot_AdjustWeight( slot, 0x0AAA, 0x0AAA ); + } + + + FT_EXPORT_DEF( void ) + FT_GlyphSlot_AdjustWeight( FT_GlyphSlot slot, + FT_Fixed xdelta, + FT_Fixed ydelta ) { FT_Library library; - FT_Face face; + FT_Size size; FT_Error error; FT_Pos xstr, ystr; @@ -108,16 +117,15 @@ return; library = slot->library; - face = slot->face; + size = slot->face->size; if ( slot->format != FT_GLYPH_FORMAT_OUTLINE && slot->format != FT_GLYPH_FORMAT_BITMAP ) return; - /* some reasonable strength */ - xstr = FT_MulFix( face->units_per_EM, - face->size->metrics.y_scale ) / 24; - ystr = xstr; + /* express deltas in pixels in 26.6 format */ + xstr = (FT_Pos)size->metrics.x_ppem * xdelta / 1024; + ystr = (FT_Pos)size->metrics.y_ppem * ydelta / 1024; if ( slot->format == FT_GLYPH_FORMAT_OUTLINE ) FT_Outline_EmboldenXY( &slot->outline, xstr, ystr ); diff --git a/src/3rdparty/freetype/src/base/ftsystem.c b/src/3rdparty/freetype/src/base/ftsystem.c index fcd289d19f4..61c99e36357 100644 --- a/src/3rdparty/freetype/src/base/ftsystem.c +++ b/src/3rdparty/freetype/src/base/ftsystem.c @@ -206,7 +206,7 @@ * The number of bytes to read from the stream. * * @Return: - * The number of bytes actually read. If `count' is zero (this is, + * The number of bytes actually read. If `count' is zero (that is, * the function is used for seeking), a non-zero return value * indicates an error. */ @@ -219,7 +219,7 @@ FT_FILE* file; - if ( !count && offset > stream->size ) + if ( offset > stream->size && !count ) return 1; file = STREAM_FILE( stream ); @@ -227,6 +227,11 @@ if ( stream->pos != offset ) ft_fseek( file, (long)offset, SEEK_SET ); + /* Avoid calling `fread` with `buffer=NULL` and `count=0`, */ + /* which is undefined behaviour. */ + if ( !count ) + return 0; + return (unsigned long)ft_fread( buffer, 1, count, file ); } diff --git a/src/3rdparty/freetype/src/base/ftver.rc b/src/3rdparty/freetype/src/base/ftver.rc index f113cb892bb..c7155d53d77 100644 --- a/src/3rdparty/freetype/src/base/ftver.rc +++ b/src/3rdparty/freetype/src/base/ftver.rc @@ -18,8 +18,8 @@ #include -#define FT_VERSION 2,13,0,0 -#define FT_VERSION_STR "2.13.0" +#define FT_VERSION 2,13,1,0 +#define FT_VERSION_STR "2.13.1" VS_VERSION_INFO VERSIONINFO FILEVERSION FT_VERSION diff --git a/src/3rdparty/freetype/src/bdf/bdf.h b/src/3rdparty/freetype/src/bdf/bdf.h index 5acbd5f2f94..e2cb52c10a4 100644 --- a/src/3rdparty/freetype/src/bdf/bdf.h +++ b/src/3rdparty/freetype/src/bdf/bdf.h @@ -239,10 +239,6 @@ FT_BEGIN_HEADER FT_LOCAL( void ) bdf_free_font( bdf_font_t* font ); - FT_LOCAL( bdf_property_t * ) - bdf_get_property( char* name, - bdf_font_t* font ); - FT_LOCAL( bdf_property_t * ) bdf_get_font_property( bdf_font_t* font, const char* name ); diff --git a/src/3rdparty/freetype/src/bdf/bdfdrivr.c b/src/3rdparty/freetype/src/bdf/bdfdrivr.c index d7e8e0efc5e..e02a1609306 100644 --- a/src/3rdparty/freetype/src/bdf/bdfdrivr.c +++ b/src/3rdparty/freetype/src/bdf/bdfdrivr.c @@ -311,9 +311,9 @@ THE SOFTWARE. FT_CALLBACK_DEF( void ) - BDF_Face_Done( FT_Face bdfface ) /* BDF_Face */ + BDF_Face_Done( FT_Face face ) /* BDF_Face */ { - BDF_Face face = (BDF_Face)bdfface; + BDF_Face bdfface = (BDF_Face)face; FT_Memory memory; @@ -322,31 +322,31 @@ THE SOFTWARE. memory = FT_FACE_MEMORY( face ); - bdf_free_font( face->bdffont ); + bdf_free_font( bdfface->bdffont ); - FT_FREE( face->en_table ); + FT_FREE( bdfface->en_table ); - FT_FREE( face->charset_encoding ); - FT_FREE( face->charset_registry ); - FT_FREE( bdfface->family_name ); - FT_FREE( bdfface->style_name ); + FT_FREE( bdfface->charset_encoding ); + FT_FREE( bdfface->charset_registry ); + FT_FREE( face->family_name ); + FT_FREE( face->style_name ); - FT_FREE( bdfface->available_sizes ); + FT_FREE( face->available_sizes ); - FT_FREE( face->bdffont ); + FT_FREE( bdfface->bdffont ); } FT_CALLBACK_DEF( FT_Error ) BDF_Face_Init( FT_Stream stream, - FT_Face bdfface, /* BDF_Face */ + FT_Face face, /* BDF_Face */ FT_Int face_index, FT_Int num_params, FT_Parameter* params ) { - FT_Error error = FT_Err_Ok; - BDF_Face face = (BDF_Face)bdfface; - FT_Memory memory = FT_FACE_MEMORY( face ); + FT_Error error = FT_Err_Ok; + BDF_Face bdfface = (BDF_Face)face; + FT_Memory memory = FT_FACE_MEMORY( face ); bdf_font_t* font = NULL; bdf_options_t options; @@ -375,7 +375,7 @@ THE SOFTWARE. goto Exit; /* we have a bdf font: let's construct the face object */ - face->bdffont = font; + bdfface->bdffont = font; /* BDF cannot have multiple faces in a single font file. * XXX: non-zero face_index is already invalid argument, but @@ -386,7 +386,7 @@ THE SOFTWARE. if ( face_index > 0 && ( face_index & 0xFFFF ) > 0 ) { FT_ERROR(( "BDF_Face_Init: invalid face index\n" )); - BDF_Face_Done( bdfface ); + BDF_Face_Done( face ); return FT_THROW( Invalid_Argument ); } @@ -401,18 +401,18 @@ THE SOFTWARE. font->unencoded_size, font->unencoded_used )); - bdfface->num_faces = 1; - bdfface->face_index = 0; + face->num_faces = 1; + face->face_index = 0; - bdfface->face_flags |= FT_FACE_FLAG_FIXED_SIZES | - FT_FACE_FLAG_HORIZONTAL; + face->face_flags |= FT_FACE_FLAG_FIXED_SIZES | + FT_FACE_FLAG_HORIZONTAL; prop = bdf_get_font_property( font, "SPACING" ); if ( prop && prop->format == BDF_ATOM && prop->value.atom && ( *(prop->value.atom) == 'M' || *(prop->value.atom) == 'm' || *(prop->value.atom) == 'C' || *(prop->value.atom) == 'c' ) ) - bdfface->face_flags |= FT_FACE_FLAG_FIXED_WIDTH; + face->face_flags |= FT_FACE_FLAG_FIXED_WIDTH; /* FZ XXX: TO DO: FT_FACE_FLAGS_VERTICAL */ /* FZ XXX: I need a font to implement this */ @@ -420,26 +420,27 @@ THE SOFTWARE. prop = bdf_get_font_property( font, "FAMILY_NAME" ); if ( prop && prop->value.atom ) { - if ( FT_STRDUP( bdfface->family_name, prop->value.atom ) ) + if ( FT_STRDUP( face->family_name, prop->value.atom ) ) goto Exit; } else - bdfface->family_name = NULL; + face->family_name = NULL; - if ( FT_SET_ERROR( bdf_interpret_style( face ) ) ) + if ( FT_SET_ERROR( bdf_interpret_style( bdfface ) ) ) goto Exit; /* the number of glyphs (with one slot for the undefined glyph */ /* at position 0 and all unencoded glyphs) */ - bdfface->num_glyphs = (FT_Long)( font->glyphs_size + 1 ); + face->num_glyphs = (FT_Long)( font->glyphs_size + 1 ); - bdfface->num_fixed_sizes = 1; - if ( FT_NEW( bdfface->available_sizes ) ) + face->num_fixed_sizes = 1; + if ( FT_NEW( face->available_sizes ) ) goto Exit; { - FT_Bitmap_Size* bsize = bdfface->available_sizes; - FT_Short resolution_x = 0, resolution_y = 0; + FT_Bitmap_Size* bsize = face->available_sizes; + FT_Short resolution_x = 0; + FT_Short resolution_y = 0; long value; @@ -598,20 +599,20 @@ THE SOFTWARE. unsigned long n; - if ( FT_QNEW_ARRAY( face->en_table, font->glyphs_size ) ) + if ( FT_QNEW_ARRAY( bdfface->en_table, font->glyphs_size ) ) goto Exit; - face->default_glyph = 0; + bdfface->default_glyph = 0; for ( n = 0; n < font->glyphs_size; n++ ) { - (face->en_table[n]).enc = cur[n].encoding; + (bdfface->en_table[n]).enc = cur[n].encoding; FT_TRACE4(( " idx %ld, val 0x%lX\n", n, cur[n].encoding )); - (face->en_table[n]).glyph = (FT_UShort)n; + (bdfface->en_table[n]).glyph = (FT_UShort)n; if ( cur[n].encoding == font->default_char ) { if ( n < FT_UINT_MAX ) - face->default_glyph = (FT_UInt)n; + bdfface->default_glyph = (FT_UInt)n; else FT_TRACE1(( "BDF_Face_Init:" " idx %ld is too large for this system\n", n )); @@ -639,27 +640,27 @@ THE SOFTWARE. const char* s; - if ( FT_STRDUP( face->charset_encoding, + if ( FT_STRDUP( bdfface->charset_encoding, charset_encoding->value.atom ) || - FT_STRDUP( face->charset_registry, + FT_STRDUP( bdfface->charset_registry, charset_registry->value.atom ) ) goto Exit; /* Uh, oh, compare first letters manually to avoid dependency */ /* on locales. */ - s = face->charset_registry; + s = bdfface->charset_registry; if ( ( s[0] == 'i' || s[0] == 'I' ) && ( s[1] == 's' || s[1] == 'S' ) && ( s[2] == 'o' || s[2] == 'O' ) ) { s += 3; - if ( !ft_strcmp( s, "10646" ) || - ( !ft_strcmp( s, "8859" ) && - !ft_strcmp( face->charset_encoding, "1" ) ) ) + if ( !ft_strcmp( s, "10646" ) || + ( !ft_strcmp( s, "8859" ) && + !ft_strcmp( bdfface->charset_encoding, "1" ) ) ) unicode_charmap = 1; /* another name for ASCII */ - else if ( !ft_strcmp( s, "646.1991" ) && - !ft_strcmp( face->charset_encoding, "IRV" ) ) + else if ( !ft_strcmp( s, "646.1991" ) && + !ft_strcmp( bdfface->charset_encoding, "IRV" ) ) unicode_charmap = 1; } @@ -667,7 +668,7 @@ THE SOFTWARE. FT_CharMapRec charmap; - charmap.face = FT_FACE( face ); + charmap.face = face; charmap.encoding = FT_ENCODING_NONE; /* initial platform/encoding should indicate unset status? */ charmap.platform_id = TT_PLATFORM_APPLE_UNICODE; @@ -693,7 +694,7 @@ THE SOFTWARE. FT_CharMapRec charmap; - charmap.face = FT_FACE( face ); + charmap.face = face; charmap.encoding = FT_ENCODING_ADOBE_STANDARD; charmap.platform_id = TT_PLATFORM_ADOBE; charmap.encoding_id = TT_ADOBE_ID_STANDARD; @@ -701,8 +702,8 @@ THE SOFTWARE. error = FT_CMap_New( &bdf_cmap_class, NULL, &charmap, NULL ); /* Select default charmap */ - if ( bdfface->num_charmaps ) - bdfface->charmap = bdfface->charmaps[0]; + if ( face->num_charmaps ) + face->charmap = face->charmaps[0]; } } } @@ -711,7 +712,7 @@ THE SOFTWARE. return error; Fail: - BDF_Face_Done( bdfface ); + BDF_Face_Done( face ); return FT_THROW( Unknown_File_Format ); } @@ -868,17 +869,18 @@ THE SOFTWARE. * */ - static FT_Error - bdf_get_bdf_property( BDF_Face face, + FT_CALLBACK_DEF( FT_Error ) + bdf_get_bdf_property( FT_Face face, /* BDF_Face */ const char* prop_name, BDF_PropertyRec *aproperty ) { + BDF_Face bdfface = (BDF_Face)face; bdf_property_t* prop; - FT_ASSERT( face && face->bdffont ); + FT_ASSERT( bdfface && bdfface->bdffont ); - prop = bdf_get_font_property( face->bdffont, prop_name ); + prop = bdf_get_font_property( bdfface->bdffont, prop_name ); if ( prop ) { switch ( prop->format ) @@ -921,13 +923,16 @@ THE SOFTWARE. } - static FT_Error - bdf_get_charset_id( BDF_Face face, + FT_CALLBACK_DEF( FT_Error ) + bdf_get_charset_id( FT_Face face, /* BDF_Face */ const char* *acharset_encoding, const char* *acharset_registry ) { - *acharset_encoding = face->charset_encoding; - *acharset_registry = face->charset_registry; + BDF_Face bdfface = (BDF_Face)face; + + + *acharset_encoding = bdfface->charset_encoding; + *acharset_registry = bdfface->charset_registry; return 0; } @@ -964,7 +969,6 @@ THE SOFTWARE. } - FT_CALLBACK_TABLE_DEF const FT_Driver_ClassRec bdf_driver_class = { diff --git a/src/3rdparty/freetype/src/bdf/bdflib.c b/src/3rdparty/freetype/src/bdf/bdflib.c index 2224698fc00..0fa7e0a8c5f 100644 --- a/src/3rdparty/freetype/src/bdf/bdflib.c +++ b/src/3rdparty/freetype/src/bdf/bdflib.c @@ -51,6 +51,9 @@ #define FT_COMPONENT bdflib +#define BUFSIZE 128 + + /************************************************************************** * * Default BDF font options. @@ -378,7 +381,7 @@ *alen = 0; if ( list == NULL || list->used == 0 ) - return 0; + return NULL; dp = list->field[0]; for ( i = j = 0; i < list->used; i++ ) @@ -887,18 +890,18 @@ } - FT_LOCAL_DEF( bdf_property_t* ) - bdf_get_property( char* name, + static bdf_property_t* + bdf_get_property( const char* name, bdf_font_t* font ) { size_t* propid; if ( name == NULL || *name == 0 ) - return 0; + return NULL; if ( ( propid = ft_hash_str_lookup( name, &(font->proptbl) ) ) == NULL ) - return 0; + return NULL; if ( *propid >= num_bdf_properties_ ) return font->user_props + ( *propid - num_bdf_properties_ ); @@ -944,7 +947,7 @@ static FT_Error bdf_add_comment_( bdf_font_t* font, - char* comment, + const char* comment, unsigned long len ) { char* cp; @@ -1053,27 +1056,24 @@ bdf_property_t* p; - *name = sp = ep = line; + sp = ep = line; while ( *ep && *ep != ' ' && *ep != '\t' ) ep++; - hold = -1; - if ( *ep ) - { - hold = *ep; - *ep = 0; - } + hold = *ep; + *ep = '\0'; p = bdf_get_property( sp, font ); - /* Restore the character that was saved before any return can happen. */ - if ( hold != -1 ) - *ep = (char)hold; - /* If the property exists and is not an atom, just return here. */ if ( p && p->format != BDF_ATOM ) + { + *ep = (char)hold; /* Undo NUL-termination. */ return 0; + } + + *name = sp; /* The property is an atom. Trim all leading and trailing whitespace */ /* and double quotes for the atom value. */ @@ -1081,25 +1081,26 @@ ep = line + linelen; /* Trim the leading whitespace if it exists. */ - if ( *sp ) - *sp++ = 0; - while ( *sp && - ( *sp == ' ' || *sp == '\t' ) ) - sp++; + if ( sp < ep ) + do + sp++; + while ( *sp == ' ' || *sp == '\t' ); /* Trim the leading double quote if it exists. */ if ( *sp == '"' ) sp++; + *value = sp; /* Trim the trailing whitespace if it exists. */ - while ( ep > sp && - ( *( ep - 1 ) == ' ' || *( ep - 1 ) == '\t' ) ) - *--ep = 0; + if ( sp < ep ) + do + *ep-- = '\0'; + while ( *ep == ' ' || *ep == '\t' ); /* Trim the trailing double quote if it exists. */ - if ( ep > sp && *( ep - 1 ) == '"' ) - *--ep = 0; + if ( *ep == '"' ) + *ep = '\0'; return 1; } @@ -1775,7 +1776,7 @@ bdf_parse_t_* p; char* name; char* value; - char nbuf[128]; + char nbuf[BUFSIZE]; FT_Error error = FT_Err_Ok; FT_UNUSED( lineno ); @@ -1796,7 +1797,7 @@ if ( bdf_get_font_property( p->font, "FONT_ASCENT" ) == 0 ) { p->font->font_ascent = p->font->bbx.ascent; - ft_sprintf( nbuf, "%hd", p->font->bbx.ascent ); + ft_snprintf( nbuf, BUFSIZE, "%hd", p->font->bbx.ascent ); error = bdf_add_property_( p->font, "FONT_ASCENT", nbuf, lineno ); if ( error ) @@ -1808,7 +1809,7 @@ if ( bdf_get_font_property( p->font, "FONT_DESCENT" ) == 0 ) { p->font->font_descent = p->font->bbx.descent; - ft_sprintf( nbuf, "%hd", p->font->bbx.descent ); + ft_snprintf( nbuf, BUFSIZE, "%hd", p->font->bbx.descent ); error = bdf_add_property_( p->font, "FONT_DESCENT", nbuf, lineno ); if ( error ) @@ -2116,7 +2117,7 @@ /* Check for the CHARS field -- font properties are optional */ if ( _bdf_strncmp( line, "CHARS", 5 ) == 0 ) { - char nbuf[128]; + char nbuf[BUFSIZE]; if ( !( p->flags & BDF_FONT_BBX_ ) ) @@ -2130,7 +2131,7 @@ /* Add the two standard X11 properties which are required */ /* for compiling fonts. */ p->font->font_ascent = p->font->bbx.ascent; - ft_sprintf( nbuf, "%hd", p->font->bbx.ascent ); + ft_snprintf( nbuf, BUFSIZE, "%hd", p->font->bbx.ascent ); error = bdf_add_property_( p->font, "FONT_ASCENT", nbuf, lineno ); if ( error ) @@ -2138,7 +2139,7 @@ FT_TRACE2(( "bdf_parse_properties_: " ACMSG1, p->font->bbx.ascent )); p->font->font_descent = p->font->bbx.descent; - ft_sprintf( nbuf, "%hd", p->font->bbx.descent ); + ft_snprintf( nbuf, BUFSIZE, "%hd", p->font->bbx.descent ); error = bdf_add_property_( p->font, "FONT_DESCENT", nbuf, lineno ); if ( error ) diff --git a/src/3rdparty/freetype/src/bzip2/ftbzip2.c b/src/3rdparty/freetype/src/bzip2/ftbzip2.c index 6cf10678b7f..ad342bd0115 100644 --- a/src/3rdparty/freetype/src/bzip2/ftbzip2.c +++ b/src/3rdparty/freetype/src/bzip2/ftbzip2.c @@ -62,10 +62,12 @@ static void* - ft_bzip2_alloc( FT_Memory memory, - int items, - int size ) + ft_bzip2_alloc( void* memory_, /* FT_Memory */ + int items, + int size ) { + FT_Memory memory = (FT_Memory)memory_; + FT_ULong sz = (FT_ULong)size * (FT_ULong)items; FT_Error error; FT_Pointer p = NULL; @@ -77,9 +79,12 @@ static void - ft_bzip2_free( FT_Memory memory, - void* address ) + ft_bzip2_free( void* memory_, /* FT_Memory */ + void* address ) { + FT_Memory memory = (FT_Memory)memory_; + + FT_MEM_FREE( address ); } @@ -170,8 +175,8 @@ } /* initialize bzlib */ - bzstream->bzalloc = (alloc_func)ft_bzip2_alloc; - bzstream->bzfree = (free_func) ft_bzip2_free; + bzstream->bzalloc = ft_bzip2_alloc; + bzstream->bzfree = ft_bzip2_free; bzstream->opaque = zip->memory; bzstream->avail_in = 0; diff --git a/src/3rdparty/freetype/src/cache/ftcbasic.c b/src/3rdparty/freetype/src/cache/ftcbasic.c index 4c6d41b2cd7..24a56c8d26a 100644 --- a/src/3rdparty/freetype/src/cache/ftcbasic.c +++ b/src/3rdparty/freetype/src/cache/ftcbasic.c @@ -337,7 +337,7 @@ #if 1 /* inlining is about 50% faster! */ FTC_GCACHE_LOOKUP_CMP( cache, ftc_basic_family_compare, - FTC_GNode_Compare, + ftc_gnode_compare, hash, gindex, &query, node, @@ -411,7 +411,7 @@ FTC_GCACHE_LOOKUP_CMP( cache, ftc_basic_family_compare, - FTC_GNode_Compare, + ftc_gnode_compare, hash, gindex, &query, node, @@ -537,7 +537,7 @@ #if 1 /* inlining is about 50% faster! */ FTC_GCACHE_LOOKUP_CMP( cache, ftc_basic_family_compare, - FTC_SNode_Compare, + ftc_snode_compare, hash, gindex, &query, node, @@ -613,7 +613,7 @@ FTC_GCACHE_LOOKUP_CMP( cache, ftc_basic_family_compare, - FTC_SNode_Compare, + ftc_snode_compare, hash, gindex, &query, node, diff --git a/src/3rdparty/freetype/src/cache/ftccache.c b/src/3rdparty/freetype/src/cache/ftccache.c index d54e68ca9a2..e0698557b70 100644 --- a/src/3rdparty/freetype/src/cache/ftccache.c +++ b/src/3rdparty/freetype/src/cache/ftccache.c @@ -94,8 +94,8 @@ idx = hash & cache->mask; - if ( idx < cache->p ) - idx = hash & ( 2 * cache->mask + 1 ); + if ( idx >= cache->p ) + idx = hash & ( cache->mask >> 1 ); return cache->buckets + idx; } @@ -113,9 +113,9 @@ for (;;) { FTC_Node node, *pnode; - FT_UFast p = cache->p; - FT_UFast mask = cache->mask; - FT_UFast count = mask + p + 1; /* number of buckets */ + FT_UFast p = cache->p; + FT_UFast size = cache->mask + 1; /* available size */ + FT_UFast half = size >> 1; /* do we need to expand the buckets array? */ @@ -127,20 +127,22 @@ /* try to expand the buckets array _before_ splitting * the bucket lists */ - if ( p >= mask ) + if ( p == size ) { FT_Memory memory = cache->memory; FT_Error error; /* if we can't expand the array, leave immediately */ - if ( FT_RENEW_ARRAY( cache->buckets, - ( mask + 1 ) * 2, ( mask + 1 ) * 4 ) ) + if ( FT_QRENEW_ARRAY( cache->buckets, size, size * 2 ) ) break; + + cache->mask = 2 * size - 1; + half = size; } - /* split a single bucket */ - pnode = cache->buckets + p; + /* the bucket to split */ + pnode = cache->buckets + p - half; for (;;) { @@ -148,7 +150,7 @@ if ( !node ) break; - if ( node->hash & ( mask + 1 ) ) + if ( node->hash & half ) { *pnode = node->link; node->link = new_list; @@ -158,56 +160,50 @@ pnode = &node->link; } - cache->buckets[p + mask + 1] = new_list; + cache->buckets[p] = new_list; cache->slack += FTC_HASH_MAX_LOAD; + cache->p = p + 1; - if ( p >= mask ) - { - cache->mask = 2 * mask + 1; - cache->p = 0; - } - else - cache->p = p + 1; + FT_TRACE2(( "ftc_cache_resize: cache %u increased to %u hashes\n", + cache->index, cache->p )); } /* do we need to shrink the buckets array? */ - else if ( cache->slack > (FT_Long)count * FTC_HASH_SUB_LOAD ) + else if ( cache->slack > (FT_Long)p * FTC_HASH_SUB_LOAD ) { - FT_UFast old_index = p + mask; - FTC_Node* pold; + FTC_Node old_list = cache->buckets[--p]; - if ( old_index + 1 <= FTC_HASH_INITIAL_SIZE ) + if ( p < FTC_HASH_INITIAL_SIZE ) break; - if ( p == 0 ) + if ( p == half ) { FT_Memory memory = cache->memory; FT_Error error; /* if we can't shrink the array, leave immediately */ - if ( FT_QRENEW_ARRAY( cache->buckets, - ( mask + 1 ) * 2, mask + 1 ) ) + if ( FT_QRENEW_ARRAY( cache->buckets, size, half ) ) break; - cache->mask >>= 1; - p = cache->mask; + cache->mask = half - 1; } - else - p--; - pnode = cache->buckets + p; + /* the bucket to merge */ + pnode = cache->buckets + p - half; + while ( *pnode ) pnode = &(*pnode)->link; - pold = cache->buckets + old_index; - *pnode = *pold; - *pold = NULL; + *pnode = old_list; cache->slack -= FTC_HASH_MAX_LOAD; cache->p = p; + + FT_TRACE2(( "ftc_cache_resize: cache %u decreased to %u hashes\n", + cache->index, cache->p )); } /* otherwise, the hash table is balanced */ @@ -239,7 +235,7 @@ if ( node == node0 ) break; - pnode = &(*pnode)->link; + pnode = &node->link; } *pnode = node0->link; @@ -322,13 +318,6 @@ /*************************************************************************/ - FT_LOCAL_DEF( FT_Error ) - FTC_Cache_Init( FTC_Cache cache ) - { - return ftc_cache_init( cache ); - } - - FT_LOCAL_DEF( FT_Error ) ftc_cache_init( FTC_Cache cache ) { @@ -336,27 +325,35 @@ FT_Error error; - cache->p = 0; + cache->p = FTC_HASH_INITIAL_SIZE; cache->mask = FTC_HASH_INITIAL_SIZE - 1; cache->slack = FTC_HASH_INITIAL_SIZE * FTC_HASH_MAX_LOAD; - FT_MEM_NEW_ARRAY( cache->buckets, FTC_HASH_INITIAL_SIZE * 2 ); + FT_MEM_NEW_ARRAY( cache->buckets, FTC_HASH_INITIAL_SIZE ); return error; } - static void - FTC_Cache_Clear( FTC_Cache cache ) + FT_LOCAL_DEF( FT_Error ) + FTC_Cache_Init( FTC_Cache cache ) { - if ( cache && cache->buckets ) + return ftc_cache_init( cache ); + } + + + FT_LOCAL_DEF( void ) + ftc_cache_done( FTC_Cache cache ) + { + FT_Memory memory = cache->memory; + + + if ( cache->buckets ) { FTC_Manager manager = cache->manager; + FT_UFast count = cache->p; FT_UFast i; - FT_UFast count; - count = cache->p + cache->mask + 1; - for ( i = 0; i < count; i++ ) { FTC_Node node = cache->buckets[i], next; @@ -376,30 +373,14 @@ cache->clazz.node_free( node, cache ); node = next; } - cache->buckets[i] = NULL; } - ftc_cache_resize( cache ); } - } + FT_FREE( cache->buckets ); - FT_LOCAL_DEF( void ) - ftc_cache_done( FTC_Cache cache ) - { - if ( cache->memory ) - { - FT_Memory memory = cache->memory; - - - FTC_Cache_Clear( cache ); - - FT_FREE( cache->buckets ); - cache->mask = 0; - cache->p = 0; - cache->slack = 0; - - cache->memory = NULL; - } + cache->p = 0; + cache->mask = 0; + cache->slack = 0; } @@ -562,12 +543,12 @@ FTC_Cache_RemoveFaceID( FTC_Cache cache, FTC_FaceID face_id ) { - FT_UFast i, count; FTC_Manager manager = cache->manager; FTC_Node frees = NULL; + FT_UFast count = cache->p; + FT_UFast i; - count = cache->p + cache->mask + 1; for ( i = 0; i < count; i++ ) { FTC_Node* pnode = cache->buckets + i; diff --git a/src/3rdparty/freetype/src/cache/ftccache.h b/src/3rdparty/freetype/src/cache/ftccache.h index 23bcb658586..850d2554b54 100644 --- a/src/3rdparty/freetype/src/cache/ftccache.h +++ b/src/3rdparty/freetype/src/cache/ftccache.h @@ -72,11 +72,12 @@ FT_BEGIN_HEADER #define FTC_NODE_NEXT( x ) FTC_NODE( (x)->mru.next ) #define FTC_NODE_PREV( x ) FTC_NODE( (x)->mru.prev ) + /* address the hash table entries */ #ifdef FTC_INLINE -#define FTC_NODE_TOP_FOR_HASH( cache, hash ) \ - ( ( cache )->buckets + \ - ( ( ( ( hash ) & ( cache )->mask ) < ( cache )->p ) \ - ? ( ( hash ) & ( ( cache )->mask * 2 + 1 ) ) \ +#define FTC_NODE_TOP_FOR_HASH( cache, hash ) \ + ( ( cache )->buckets + \ + ( ( ( ( hash ) & ( cache )->mask ) >= ( cache )->p ) \ + ? ( ( hash ) & ( ( cache )->mask >> 1 ) ) \ : ( ( hash ) & ( cache )->mask ) ) ) #else FT_LOCAL( FTC_Node* ) @@ -139,11 +140,13 @@ FT_BEGIN_HEADER } FTC_CacheClassRec; - /* each cache really implements a dynamic hash table to manage its nodes */ + /* each cache really implements a hash table to manage its nodes */ + /* the number of the table entries (buckets) can change dynamically */ + /* each bucket contains a linked lists of nodes for a given hash */ typedef struct FTC_CacheRec_ { - FT_UFast p; - FT_UFast mask; + FT_UFast p; /* hash table counter */ + FT_UFast mask; /* hash table index range */ FT_Long slack; FTC_Node* buckets; diff --git a/src/3rdparty/freetype/src/cache/ftcglyph.c b/src/3rdparty/freetype/src/cache/ftcglyph.c index b3fb2f219c4..d344733f37c 100644 --- a/src/3rdparty/freetype/src/cache/ftcglyph.c +++ b/src/3rdparty/freetype/src/cache/ftcglyph.c @@ -79,20 +79,6 @@ } -#ifdef FTC_INLINE - - FT_LOCAL_DEF( FT_Bool ) - FTC_GNode_Compare( FTC_GNode gnode, - FTC_GQuery gquery, - FTC_Cache cache, - FT_Bool* list_changed ) - { - return ftc_gnode_compare( FTC_NODE( gnode ), gquery, - cache, list_changed ); - } - -#endif - /*************************************************************************/ /*************************************************************************/ /***** *****/ @@ -115,22 +101,22 @@ FT_LOCAL_DEF( FT_Error ) - ftc_gcache_init( FTC_Cache ftccache ) + ftc_gcache_init( FTC_Cache cache ) { - FTC_GCache cache = (FTC_GCache)ftccache; + FTC_GCache gcache = (FTC_GCache)cache; FT_Error error; - error = FTC_Cache_Init( FTC_CACHE( cache ) ); + error = FTC_Cache_Init( cache ); if ( !error ) { - FTC_GCacheClass clazz = (FTC_GCacheClass)FTC_CACHE( cache )->org_class; + FTC_GCacheClass clazz = (FTC_GCacheClass)cache->org_class; - FTC_MruList_Init( &cache->families, + FTC_MruList_Init( &gcache->families, clazz->family_class, 0, /* no maximum here! */ cache, - FTC_CACHE( cache )->memory ); + cache->memory ); } return error; @@ -140,31 +126,31 @@ #if 0 FT_LOCAL_DEF( FT_Error ) - FTC_GCache_Init( FTC_GCache cache ) + FTC_GCache_Init( FTC_GCache gcache ) { - return ftc_gcache_init( FTC_CACHE( cache ) ); + return ftc_gcache_init( FTC_CACHE( gcache ) ); } #endif /* 0 */ FT_LOCAL_DEF( void ) - ftc_gcache_done( FTC_Cache ftccache ) + ftc_gcache_done( FTC_Cache cache ) { - FTC_GCache cache = (FTC_GCache)ftccache; + FTC_GCache gcache = (FTC_GCache)cache; - FTC_Cache_Done( (FTC_Cache)cache ); - FTC_MruList_Done( &cache->families ); + FTC_Cache_Done( cache ); + FTC_MruList_Done( &gcache->families ); } #if 0 FT_LOCAL_DEF( void ) - FTC_GCache_Done( FTC_GCache cache ) + FTC_GCache_Done( FTC_GCache gcache ) { - ftc_gcache_done( FTC_CACHE( cache ) ); + ftc_gcache_done( FTC_CACHE( gcache ) ); } #endif /* 0 */ @@ -183,7 +169,7 @@ #ifndef FTC_INLINE FT_LOCAL_DEF( FT_Error ) - FTC_GCache_Lookup( FTC_GCache cache, + FTC_GCache_Lookup( FTC_GCache gcache, FT_Offset hash, FT_UInt gindex, FTC_GQuery query, @@ -204,7 +190,7 @@ /* out-of-memory condition occurs during glyph node initialization. */ family->num_nodes++; - error = FTC_Cache_Lookup( FTC_CACHE( cache ), hash, query, anode ); + error = FTC_Cache_Lookup( FTC_CACHE( gcache ), hash, query, anode ); if ( --family->num_nodes == 0 ) FTC_FAMILY_FREE( family, cache ); diff --git a/src/3rdparty/freetype/src/cache/ftcglyph.h b/src/3rdparty/freetype/src/cache/ftcglyph.h index 728d4db1d61..0181e98166e 100644 --- a/src/3rdparty/freetype/src/cache/ftcglyph.h +++ b/src/3rdparty/freetype/src/cache/ftcglyph.h @@ -58,7 +58,7 @@ * - FTC_GNode sub-class, e.g. MyNode, with relevant methods: * my_node_new (must call FTC_GNode_Init) * my_node_free (must call FTC_GNode_Done) - * my_node_compare (must call FTC_GNode_Compare) + * my_node_compare (must call ftc_gnode_compare) * my_node_remove_faceid (must call ftc_gnode_unselect in case * of match) * @@ -179,19 +179,6 @@ FT_BEGIN_HEADER FT_UInt gindex, /* glyph index for node */ FTC_Family family ); -#ifdef FTC_INLINE - - /* returns TRUE iff the query's glyph index correspond to the node; */ - /* this assumes that the `family' and `hash' fields of the query are */ - /* already correctly set */ - FT_LOCAL( FT_Bool ) - FTC_GNode_Compare( FTC_GNode gnode, - FTC_GQuery gquery, - FTC_Cache cache, - FT_Bool* list_changed ); - -#endif - /* call this function to clear a node's family -- this is necessary */ /* to implement the `node_remove_faceid' cache method correctly */ FT_LOCAL( void ) diff --git a/src/3rdparty/freetype/src/cache/ftcmanag.c b/src/3rdparty/freetype/src/cache/ftcmanag.c index 6c84339100b..94f8469c92b 100644 --- a/src/3rdparty/freetype/src/cache/ftcmanag.c +++ b/src/3rdparty/freetype/src/cache/ftcmanag.c @@ -426,7 +426,7 @@ memory = manager->memory; /* now discard all caches */ - for (idx = manager->num_caches; idx-- > 0; ) + for ( idx = manager->num_caches; idx-- > 0; ) { FTC_Cache cache = manager->caches[idx]; @@ -537,7 +537,7 @@ FT_LOCAL_DEF( void ) FTC_Manager_Compress( FTC_Manager manager ) { - FTC_Node node, first; + FTC_Node node, prev, first; if ( !manager ) @@ -557,20 +557,16 @@ return; /* go to last node -- it's a circular list */ - node = FTC_NODE_PREV( first ); + prev = FTC_NODE_PREV( first ); do { - FTC_Node prev; - - - prev = ( node == first ) ? NULL : FTC_NODE_PREV( node ); + node = prev; + prev = FTC_NODE_PREV( node ); if ( node->ref_count <= 0 ) ftc_node_destroy( node, manager ); - node = prev; - - } while ( node && manager->cur_weight > manager->max_weight ); + } while ( node != first && manager->cur_weight > manager->max_weight ); } @@ -633,20 +629,20 @@ FT_UInt count ) { FTC_Node first = manager->nodes_list; - FTC_Node node; - FT_UInt result; + FTC_Node prev, node; + FT_UInt result = 0; /* try to remove `count' nodes from the list */ - if ( !first ) /* empty list! */ - return 0; + if ( !first || !count ) + return result; - /* go to last node - it's a circular list */ - node = FTC_NODE_PREV(first); - for ( result = 0; result < count; ) + /* go to last node -- it's a circular list */ + prev = FTC_NODE_PREV( first ); + do { - FTC_Node prev = FTC_NODE_PREV( node ); - + node = prev; + prev = FTC_NODE_PREV( node ); /* don't touch locked nodes */ if ( node->ref_count <= 0 ) @@ -654,13 +650,9 @@ ftc_node_destroy( node, manager ); result++; } + } while ( node != first && result < count ); - if ( node == first ) - break; - - node = prev; - } - return result; + return result; } diff --git a/src/3rdparty/freetype/src/cache/ftcmru.c b/src/3rdparty/freetype/src/cache/ftcmru.c index 67227033e79..ad10a06bc46 100644 --- a/src/3rdparty/freetype/src/cache/ftcmru.c +++ b/src/3rdparty/freetype/src/cache/ftcmru.c @@ -329,29 +329,23 @@ FTC_MruNode_CompareFunc selection, FT_Pointer key ) { - FTC_MruNode first, node, next; + FTC_MruNode first = list->nodes; + FTC_MruNode prev, node; - first = list->nodes; - while ( first && ( !selection || selection( first, key ) ) ) + if ( !first || !selection ) + return; + + prev = first->prev; + do { - FTC_MruList_Remove( list, first ); - first = list->nodes; - } + node = prev; + prev = node->prev; - if ( first ) - { - node = first->next; - while ( node != first ) - { - next = node->next; + if ( selection( node, key ) ) + FTC_MruList_Remove( list, node ); - if ( selection( node, key ) ) - FTC_MruList_Remove( list, node ); - - node = next; - } - } + } while ( node != first ); } diff --git a/src/3rdparty/freetype/src/cache/ftcsbits.c b/src/3rdparty/freetype/src/cache/ftcsbits.c index ee9dab26323..9929a0bcc3c 100644 --- a/src/3rdparty/freetype/src/cache/ftcsbits.c +++ b/src/3rdparty/freetype/src/cache/ftcsbits.c @@ -342,7 +342,7 @@ FT_Bool result; - if (list_changed) + if ( list_changed ) *list_changed = FALSE; result = FT_BOOL( gnode->family == gquery->family && gindex - gnode->gindex < snode->count ); @@ -411,19 +411,4 @@ return result; } - -#ifdef FTC_INLINE - - FT_LOCAL_DEF( FT_Bool ) - FTC_SNode_Compare( FTC_SNode snode, - FTC_GQuery gquery, - FTC_Cache cache, - FT_Bool* list_changed ) - { - return ftc_snode_compare( FTC_NODE( snode ), gquery, - cache, list_changed ); - } - -#endif - /* END */ diff --git a/src/3rdparty/freetype/src/cache/ftcsbits.h b/src/3rdparty/freetype/src/cache/ftcsbits.h index 3473923f038..e833cb5c30c 100644 --- a/src/3rdparty/freetype/src/cache/ftcsbits.h +++ b/src/3rdparty/freetype/src/cache/ftcsbits.h @@ -81,17 +81,6 @@ FT_BEGIN_HEADER FTC_SNode_Weight( FTC_SNode inode ); #endif - -#ifdef FTC_INLINE - - FT_LOCAL( FT_Bool ) - FTC_SNode_Compare( FTC_SNode snode, - FTC_GQuery gquery, - FTC_Cache cache, - FT_Bool* list_changed); - -#endif - /* */ FT_END_HEADER diff --git a/src/3rdparty/freetype/src/cff/cffcmap.c b/src/3rdparty/freetype/src/cff/cffcmap.c index 6ed31432227..10d287bc81f 100644 --- a/src/3rdparty/freetype/src/cff/cffcmap.c +++ b/src/3rdparty/freetype/src/cff/cffcmap.c @@ -32,9 +32,10 @@ /*************************************************************************/ FT_CALLBACK_DEF( FT_Error ) - cff_cmap_encoding_init( CFF_CMapStd cmap, - FT_Pointer pointer ) + cff_cmap_encoding_init( FT_CMap cmap, + FT_Pointer pointer ) { + CFF_CMapStd cffcmap = (CFF_CMapStd)cmap; TT_Face face = (TT_Face)FT_CMAP_FACE( cmap ); CFF_Font cff = (CFF_Font)face->extra.data; CFF_Encoding encoding = &cff->encoding; @@ -42,63 +43,56 @@ FT_UNUSED( pointer ); - cmap->gids = encoding->codes; + cffcmap->gids = encoding->codes; return 0; } FT_CALLBACK_DEF( void ) - cff_cmap_encoding_done( CFF_CMapStd cmap ) + cff_cmap_encoding_done( FT_CMap cmap ) { - cmap->gids = NULL; + CFF_CMapStd cffcmap = (CFF_CMapStd)cmap; + + + cffcmap->gids = NULL; } FT_CALLBACK_DEF( FT_UInt ) - cff_cmap_encoding_char_index( CFF_CMapStd cmap, - FT_UInt32 char_code ) + cff_cmap_encoding_char_index( FT_CMap cmap, + FT_UInt32 char_code ) { - FT_UInt result = 0; + CFF_CMapStd cffcmap = (CFF_CMapStd)cmap; + FT_UInt result = 0; if ( char_code < 256 ) - result = cmap->gids[char_code]; + result = cffcmap->gids[char_code]; return result; } - FT_CALLBACK_DEF( FT_UInt32 ) - cff_cmap_encoding_char_next( CFF_CMapStd cmap, - FT_UInt32 *pchar_code ) + FT_CALLBACK_DEF( FT_UInt ) + cff_cmap_encoding_char_next( FT_CMap cmap, + FT_UInt32 *pchar_code ) { - FT_UInt result = 0; - FT_UInt32 char_code = *pchar_code; + CFF_CMapStd cffcmap = (CFF_CMapStd)cmap; + FT_UInt result = 0; + FT_UInt32 char_code = *pchar_code; - *pchar_code = 0; - - if ( char_code < 255 ) + while ( char_code < 255 ) { - FT_UInt code = (FT_UInt)( char_code + 1 ); - - - for (;;) + result = cffcmap->gids[++char_code]; + if ( result ) { - if ( code >= 256 ) - break; - - result = cmap->gids[code]; - if ( result != 0 ) - { - *pchar_code = code; - break; - } - - code++; + *pchar_code = char_code; + break; } } + return result; } @@ -130,9 +124,10 @@ /*************************************************************************/ FT_CALLBACK_DEF( const char* ) - cff_sid_to_glyph_name( TT_Face face, + cff_sid_to_glyph_name( void* face_, /* TT_Face */ FT_UInt idx ) { + TT_Face face = (TT_Face)face_; CFF_Font cff = (CFF_Font)face->extra.data; CFF_Charset charset = &cff->charset; FT_UInt sid = charset->sids[idx]; @@ -143,14 +138,15 @@ FT_CALLBACK_DEF( FT_Error ) - cff_cmap_unicode_init( PS_Unicodes unicodes, + cff_cmap_unicode_init( FT_CMap cmap, /* PS_Unicodes */ FT_Pointer pointer ) { - TT_Face face = (TT_Face)FT_CMAP_FACE( unicodes ); - FT_Memory memory = FT_FACE_MEMORY( face ); - CFF_Font cff = (CFF_Font)face->extra.data; - CFF_Charset charset = &cff->charset; - FT_Service_PsCMaps psnames = (FT_Service_PsCMaps)cff->psnames; + PS_Unicodes unicodes = (PS_Unicodes)cmap; + TT_Face face = (TT_Face)FT_CMAP_FACE( cmap ); + FT_Memory memory = FT_FACE_MEMORY( face ); + CFF_Font cff = (CFF_Font)face->extra.data; + CFF_Charset charset = &cff->charset; + FT_Service_PsCMaps psnames = (FT_Service_PsCMaps)cff->psnames; FT_UNUSED( pointer ); @@ -166,17 +162,18 @@ return psnames->unicodes_init( memory, unicodes, cff->num_glyphs, - (PS_GetGlyphNameFunc)&cff_sid_to_glyph_name, + &cff_sid_to_glyph_name, (PS_FreeGlyphNameFunc)NULL, (FT_Pointer)face ); } FT_CALLBACK_DEF( void ) - cff_cmap_unicode_done( PS_Unicodes unicodes ) + cff_cmap_unicode_done( FT_CMap cmap ) /* PS_Unicodes */ { - FT_Face face = FT_CMAP_FACE( unicodes ); - FT_Memory memory = FT_FACE_MEMORY( face ); + PS_Unicodes unicodes = (PS_Unicodes)cmap; + FT_Face face = FT_CMAP_FACE( cmap ); + FT_Memory memory = FT_FACE_MEMORY( face ); FT_FREE( unicodes->maps ); @@ -185,25 +182,27 @@ FT_CALLBACK_DEF( FT_UInt ) - cff_cmap_unicode_char_index( PS_Unicodes unicodes, - FT_UInt32 char_code ) + cff_cmap_unicode_char_index( FT_CMap cmap, /* PS_Unicodes */ + FT_UInt32 char_code ) { - TT_Face face = (TT_Face)FT_CMAP_FACE( unicodes ); - CFF_Font cff = (CFF_Font)face->extra.data; - FT_Service_PsCMaps psnames = (FT_Service_PsCMaps)cff->psnames; + PS_Unicodes unicodes = (PS_Unicodes)cmap; + TT_Face face = (TT_Face)FT_CMAP_FACE( cmap ); + CFF_Font cff = (CFF_Font)face->extra.data; + FT_Service_PsCMaps psnames = (FT_Service_PsCMaps)cff->psnames; return psnames->unicodes_char_index( unicodes, char_code ); } - FT_CALLBACK_DEF( FT_UInt32 ) - cff_cmap_unicode_char_next( PS_Unicodes unicodes, - FT_UInt32 *pchar_code ) + FT_CALLBACK_DEF( FT_UInt ) + cff_cmap_unicode_char_next( FT_CMap cmap, /* PS_Unicodes */ + FT_UInt32 *pchar_code ) { - TT_Face face = (TT_Face)FT_CMAP_FACE( unicodes ); - CFF_Font cff = (CFF_Font)face->extra.data; - FT_Service_PsCMaps psnames = (FT_Service_PsCMaps)cff->psnames; + PS_Unicodes unicodes = (PS_Unicodes)cmap; + TT_Face face = (TT_Face)FT_CMAP_FACE( cmap ); + CFF_Font cff = (CFF_Font)face->extra.data; + FT_Service_PsCMaps psnames = (FT_Service_PsCMaps)cff->psnames; return psnames->unicodes_char_next( unicodes, pchar_code ); diff --git a/src/3rdparty/freetype/src/cff/cffdrivr.c b/src/3rdparty/freetype/src/cff/cffdrivr.c index 4e2e0e00deb..9898d625ca4 100644 --- a/src/3rdparty/freetype/src/cff/cffdrivr.c +++ b/src/3rdparty/freetype/src/cff/cffdrivr.c @@ -108,20 +108,20 @@ * They can be implemented by format-specific interfaces. */ FT_CALLBACK_DEF( FT_Error ) - cff_get_kerning( FT_Face ttface, /* TT_Face */ + cff_get_kerning( FT_Face face, /* CFF_Face */ FT_UInt left_glyph, FT_UInt right_glyph, FT_Vector* kerning ) { - TT_Face face = (TT_Face)ttface; - SFNT_Service sfnt = (SFNT_Service)face->sfnt; + CFF_Face cffface = (CFF_Face)face; + SFNT_Service sfnt = (SFNT_Service)cffface->sfnt; kerning->x = 0; kerning->y = 0; if ( sfnt ) - kerning->x = sfnt->get_kerning( face, left_glyph, right_glyph ); + kerning->x = sfnt->get_kerning( cffface, left_glyph, right_glyph ); return FT_Err_Ok; } @@ -158,23 +158,23 @@ * FreeType error code. 0 means success. */ FT_CALLBACK_DEF( FT_Error ) - cff_glyph_load( FT_GlyphSlot cffslot, /* CFF_GlyphSlot */ - FT_Size cffsize, /* CFF_Size */ + cff_glyph_load( FT_GlyphSlot slot, /* CFF_GlyphSlot */ + FT_Size size, /* CFF_Size */ FT_UInt glyph_index, FT_Int32 load_flags ) { FT_Error error; - CFF_GlyphSlot slot = (CFF_GlyphSlot)cffslot; - CFF_Size size = (CFF_Size)cffsize; + CFF_GlyphSlot cffslot = (CFF_GlyphSlot)slot; + CFF_Size cffsize = (CFF_Size)size; - if ( !slot ) + if ( !cffslot ) return FT_THROW( Invalid_Slot_Handle ); FT_TRACE1(( "cff_glyph_load: glyph index %d\n", glyph_index )); /* check whether we want a scaled outline or bitmap */ - if ( !size ) + if ( !cffsize ) load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING; /* reset the size object if necessary */ @@ -184,12 +184,12 @@ if ( size ) { /* these two objects must have the same parent */ - if ( cffsize->face != cffslot->face ) + if ( size->face != slot->face ) return FT_THROW( Invalid_Face_Handle ); } /* now load the glyph outline if necessary */ - error = cff_slot_load( slot, size, glyph_index, load_flags ); + error = cff_slot_load( cffslot, cffsize, glyph_index, load_flags ); /* force drop-out mode to 2 - irrelevant now */ /* slot->outline.dropout_mode = 2; */ @@ -216,7 +216,7 @@ /* it is no longer necessary that those values are identical to */ /* the values in the `CFF' table */ - TT_Face ttface = (TT_Face)face; + CFF_Face cffface = (CFF_Face)face; FT_Short dummy; @@ -225,7 +225,7 @@ #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT /* no fast retrieval for blended MM fonts without VVAR table */ if ( ( FT_IS_NAMED_INSTANCE( face ) || FT_IS_VARIATION( face ) ) && - !( ttface->variation_support & TT_FACE_FLAG_VAR_VADVANCE ) ) + !( cffface->variation_support & TT_FACE_FLAG_VAR_VADVANCE ) ) return FT_THROW( Unimplemented_Feature ); #endif @@ -233,7 +233,7 @@ /* otherwise we extract the info from the CFF glyphstrings */ /* (instead of synthesizing a global value using the `OS/2' */ /* table) */ - if ( !ttface->vertical_info ) + if ( !cffface->vertical_info ) goto Missing_Table; for ( nn = 0; nn < count; nn++ ) @@ -241,11 +241,11 @@ FT_UShort ah; - ( (SFNT_Service)ttface->sfnt )->get_metrics( ttface, - 1, - start + nn, - &dummy, - &ah ); + ( (SFNT_Service)cffface->sfnt )->get_metrics( cffface, + 1, + start + nn, + &dummy, + &ah ); FT_TRACE5(( " idx %d: advance height %d font unit%s\n", start + nn, @@ -259,12 +259,12 @@ #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT /* no fast retrieval for blended MM fonts without HVAR table */ if ( ( FT_IS_NAMED_INSTANCE( face ) || FT_IS_VARIATION( face ) ) && - !( ttface->variation_support & TT_FACE_FLAG_VAR_HADVANCE ) ) + !( cffface->variation_support & TT_FACE_FLAG_VAR_HADVANCE ) ) return FT_THROW( Unimplemented_Feature ); #endif /* check whether we have data from the `hmtx' table at all */ - if ( !ttface->horizontal.number_Of_HMetrics ) + if ( !cffface->horizontal.number_Of_HMetrics ) goto Missing_Table; for ( nn = 0; nn < count; nn++ ) @@ -272,11 +272,11 @@ FT_UShort aw; - ( (SFNT_Service)ttface->sfnt )->get_metrics( ttface, - 0, - start + nn, - &dummy, - &aw ); + ( (SFNT_Service)cffface->sfnt )->get_metrics( cffface, + 0, + start + nn, + &dummy, + &aw ); FT_TRACE5(( " idx %d: advance width %d font unit%s\n", start + nn, @@ -312,13 +312,14 @@ * */ - static FT_Error - cff_get_glyph_name( CFF_Face face, + FT_CALLBACK_DEF( FT_Error ) + cff_get_glyph_name( FT_Face face, /* CFF_Face */ FT_UInt glyph_index, FT_Pointer buffer, FT_UInt buffer_max ) { - CFF_Font font = (CFF_Font)face->extra.data; + CFF_Face cffface = (CFF_Face)face; + CFF_Font font = (CFF_Font)cffface->extra.data; FT_String* gname; FT_UShort sid; FT_Error error; @@ -338,10 +339,7 @@ if ( service && service->get_name ) - return service->get_name( FT_FACE( face ), - glyph_index, - buffer, - buffer_max ); + return service->get_name( face, glyph_index, buffer, buffer_max ); else { FT_ERROR(( "cff_get_glyph_name:" @@ -366,7 +364,7 @@ /* first, locate the sid in the charset table */ sid = font->charset.sids[glyph_index]; - /* now, lookup the name itself */ + /* now, look up the name itself */ gname = cff_index_get_sid_string( font, sid ); if ( gname ) @@ -379,21 +377,19 @@ } - static FT_UInt - cff_get_name_index( CFF_Face face, + FT_CALLBACK_DEF( FT_UInt ) + cff_get_name_index( FT_Face face, /* CFF_Face */ const FT_String* glyph_name ) { - CFF_Font cff; - CFF_Charset charset; + CFF_Face cffface = (CFF_Face)face; + CFF_Font cff = (CFF_Font)cffface->extra.data; + CFF_Charset charset = &cff->charset; FT_Service_PsCMaps psnames; FT_String* name; FT_UShort sid; FT_UInt i; - cff = (CFF_FontRec *)face->extra.data; - charset = &cff->charset; - /* CFF2 table does not have glyph names; */ /* we need to use `post' table method */ if ( cff->version_major == 2 ) @@ -408,7 +404,7 @@ if ( service && service->name_index ) - return service->name_index( FT_FACE( face ), glyph_name ); + return service->name_index( face, glyph_name ); else { FT_ERROR(( "cff_get_name_index:" @@ -446,8 +442,8 @@ FT_DEFINE_SERVICE_GLYPHDICTREC( cff_service_glyph_dict, - (FT_GlyphDict_GetNameFunc) cff_get_glyph_name, /* get_name */ - (FT_GlyphDict_NameIndexFunc)cff_get_name_index /* name_index */ + cff_get_glyph_name, /* FT_GlyphDict_GetNameFunc get_name */ + cff_get_name_index /* FT_GlyphDict_NameIndexFunc name_index */ ) @@ -456,25 +452,32 @@ * */ - static FT_Int + FT_CALLBACK_DEF( FT_Int ) cff_ps_has_glyph_names( FT_Face face ) { return ( face->face_flags & FT_FACE_FLAG_GLYPH_NAMES ) > 0; } - static FT_Error - cff_ps_get_font_info( CFF_Face face, + FT_CALLBACK_DEF( FT_Error ) + cff_ps_get_font_info( FT_Face face, /* CFF_Face */ PS_FontInfoRec* afont_info ) { - CFF_Font cff = (CFF_Font)face->extra.data; - FT_Error error = FT_Err_Ok; + CFF_Face cffface = (CFF_Face)face; + CFF_Font cff = (CFF_Font)cffface->extra.data; + FT_Error error = FT_Err_Ok; + if ( cffface->is_cff2 ) + { + error = FT_THROW( Invalid_Argument ); + goto Fail; + } + if ( cff && !cff->font_info ) { CFF_FontRecDict dict = &cff->top_font.font_dict; - FT_Memory memory = face->root.memory; + FT_Memory memory = FT_FACE_MEMORY( face ); PS_FontInfoRec* font_info = NULL; @@ -507,18 +510,19 @@ } - static FT_Error - cff_ps_get_font_extra( CFF_Face face, + FT_CALLBACK_DEF( FT_Error ) + cff_ps_get_font_extra( FT_Face face, /* CFF_Face */ PS_FontExtraRec* afont_extra ) { - CFF_Font cff = (CFF_Font)face->extra.data; - FT_Error error = FT_Err_Ok; + CFF_Face cffface = (CFF_Face)face; + CFF_Font cff = (CFF_Font)cffface->extra.data; + FT_Error error = FT_Err_Ok; if ( cff && !cff->font_extra ) { CFF_FontRecDict dict = &cff->top_font.font_dict; - FT_Memory memory = face->root.memory; + FT_Memory memory = FT_FACE_MEMORY( face ); PS_FontExtraRec* font_extra = NULL; FT_String* embedded_postscript; @@ -588,13 +592,13 @@ FT_DEFINE_SERVICE_PSINFOREC( cff_service_ps_info, - (PS_GetFontInfoFunc) cff_ps_get_font_info, /* ps_get_font_info */ - (PS_GetFontExtraFunc) cff_ps_get_font_extra, /* ps_get_font_extra */ - (PS_HasGlyphNamesFunc) cff_ps_has_glyph_names, /* ps_has_glyph_names */ + cff_ps_get_font_info, /* PS_GetFontInfoFunc ps_get_font_info */ + cff_ps_get_font_extra, /* PS_GetFontExtraFunc ps_get_font_extra */ + cff_ps_has_glyph_names, /* PS_HasGlyphNamesFunc ps_has_glyph_names */ /* unsupported with CFF fonts */ - (PS_GetFontPrivateFunc)NULL, /* ps_get_font_private */ + NULL, /* PS_GetFontPrivateFunc ps_get_font_private */ /* not implemented */ - (PS_GetFontValueFunc) NULL /* ps_get_font_value */ + NULL /* PS_GetFontValueFunc ps_get_font_value */ ) @@ -603,17 +607,18 @@ * */ - static const char* - cff_get_ps_name( CFF_Face face ) + FT_CALLBACK_DEF( const char* ) + cff_get_ps_name( FT_Face face ) /* CFF_Face */ { - CFF_Font cff = (CFF_Font)face->extra.data; - SFNT_Service sfnt = (SFNT_Service)face->sfnt; + CFF_Face cffface = (CFF_Face)face; + CFF_Font cff = (CFF_Font)cffface->extra.data; + SFNT_Service sfnt = (SFNT_Service)cffface->sfnt; /* following the OpenType specification 1.7, we return the name stored */ /* in the `name' table for a CFF wrapped into an SFNT container */ - if ( FT_IS_SFNT( FT_FACE( face ) ) && sfnt ) + if ( FT_IS_SFNT( face ) && sfnt ) { FT_Library library = FT_FACE_LIBRARY( face ); FT_Module sfnt_module = FT_Get_Module( library, "sfnt" ); @@ -625,17 +630,17 @@ if ( service && service->get_ps_font_name ) - return service->get_ps_font_name( FT_FACE( face ) ); + return service->get_ps_font_name( face ); } - return (const char*)cff->font_name; + return cff ? (const char*)cff->font_name : NULL; } FT_DEFINE_SERVICE_PSFONTNAMEREC( cff_service_ps_name, - (FT_PsName_GetFunc)cff_get_ps_name /* get_ps_font_name */ + cff_get_ps_name /* FT_PsName_GetFunc get_ps_font_name */ ) @@ -649,7 +654,7 @@ * Otherwise call the service function in the sfnt module. * */ - static FT_Error + FT_CALLBACK_DEF( FT_Error ) cff_get_cmap_info( FT_CharMap charmap, TT_CMapInfo *cmap_info ) { @@ -683,7 +688,7 @@ FT_DEFINE_SERVICE_TTCMAPSREC( cff_service_get_cmap_info, - (TT_CMap_Info_GetFunc)cff_get_cmap_info /* get_cmap_info */ + cff_get_cmap_info /* TT_CMap_Info_GetFunc get_cmap_info */ ) @@ -691,14 +696,15 @@ * CID INFO SERVICE * */ - static FT_Error - cff_get_ros( CFF_Face face, + FT_CALLBACK_DEF( FT_Error ) + cff_get_ros( FT_Face face, /* FT_Face */ const char* *registry, const char* *ordering, FT_Int *supplement ) { - FT_Error error = FT_Err_Ok; - CFF_Font cff = (CFF_Font)face->extra.data; + FT_Error error = FT_Err_Ok; + CFF_Face cffface = (CFF_Face)face; + CFF_Font cff = (CFF_Font)cffface->extra.data; if ( cff ) @@ -748,12 +754,13 @@ } - static FT_Error - cff_get_is_cid( CFF_Face face, + FT_CALLBACK_DEF( FT_Error ) + cff_get_is_cid( FT_Face face, /* CFF_Face */ FT_Bool *is_cid ) { - FT_Error error = FT_Err_Ok; - CFF_Font cff = (CFF_Font)face->extra.data; + FT_Error error = FT_Err_Ok; + CFF_Face cffface = (CFF_Face)face; + CFF_Font cff = (CFF_Font)cffface->extra.data; *is_cid = 0; @@ -771,17 +778,16 @@ } - static FT_Error - cff_get_cid_from_glyph_index( CFF_Face face, + FT_CALLBACK_DEF( FT_Error ) + cff_get_cid_from_glyph_index( FT_Face face, /* CFF_Face */ FT_UInt glyph_index, FT_UInt *cid ) { - FT_Error error = FT_Err_Ok; - CFF_Font cff; + FT_Error error = FT_Err_Ok; + CFF_Face cffface = (CFF_Face)face; + CFF_Font cff = (CFF_Font)cffface->extra.data; - cff = (CFF_Font)face->extra.data; - if ( cff ) { FT_UInt c; @@ -814,12 +820,12 @@ FT_DEFINE_SERVICE_CIDREC( cff_service_cid_info, - (FT_CID_GetRegistryOrderingSupplementFunc) - cff_get_ros, /* get_ros */ - (FT_CID_GetIsInternallyCIDKeyedFunc) - cff_get_is_cid, /* get_is_cid */ - (FT_CID_GetCIDFromGlyphIndexFunc) - cff_get_cid_from_glyph_index /* get_cid_from_glyph_index */ + cff_get_ros, + /* FT_CID_GetRegistryOrderingSupplementFunc get_ros */ + cff_get_is_cid, + /* FT_CID_GetIsInternallyCIDKeyedFunc get_is_cid */ + cff_get_cid_from_glyph_index + /* FT_CID_GetCIDFromGlyphIndexFunc get_cid_from_glyph_index */ ) @@ -831,9 +837,9 @@ FT_DEFINE_SERVICE_PROPERTIESREC( cff_service_properties, - (FT_Properties_SetFunc)ps_property_set, /* set_property */ - (FT_Properties_GetFunc)ps_property_get ) /* get_property */ - + ps_property_set, /* FT_Properties_SetFunc set_property */ + ps_property_get /* FT_Properties_GetFunc get_property */ + ) #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT @@ -842,160 +848,195 @@ * */ - static FT_Error - cff_set_mm_blend( CFF_Face face, + FT_CALLBACK_DEF( FT_Error ) + cff_set_mm_blend( FT_Face face, /* CFF_Face */ FT_UInt num_coords, FT_Fixed* coords ) { - FT_Service_MultiMasters mm = (FT_Service_MultiMasters)face->mm; + CFF_Face cffface = (CFF_Face)face; + FT_Service_MultiMasters mm = (FT_Service_MultiMasters)cffface->mm; - return mm->set_mm_blend( FT_FACE( face ), num_coords, coords ); + return mm->set_mm_blend( face, num_coords, coords ); } - static FT_Error - cff_get_mm_blend( CFF_Face face, + FT_CALLBACK_DEF( FT_Error ) + cff_get_mm_blend( FT_Face face, /* CFF_Face */ FT_UInt num_coords, FT_Fixed* coords ) { - FT_Service_MultiMasters mm = (FT_Service_MultiMasters)face->mm; + CFF_Face cffface = (CFF_Face)face; + FT_Service_MultiMasters mm = (FT_Service_MultiMasters)cffface->mm; - return mm->get_mm_blend( FT_FACE( face ), num_coords, coords ); + return mm->get_mm_blend( face, num_coords, coords ); } - static FT_Error - cff_set_mm_weightvector( CFF_Face face, + FT_CALLBACK_DEF( FT_Error ) + cff_set_mm_weightvector( FT_Face face, /* CFF_Face */ FT_UInt len, FT_Fixed* weightvector ) { - FT_Service_MultiMasters mm = (FT_Service_MultiMasters)face->mm; + CFF_Face cffface = (CFF_Face)face; + FT_Service_MultiMasters mm = (FT_Service_MultiMasters)cffface->mm; - return mm->set_mm_weightvector( FT_FACE( face ), len, weightvector ); + return mm->set_mm_weightvector( face, len, weightvector ); } - static FT_Error - cff_get_mm_weightvector( CFF_Face face, + FT_CALLBACK_DEF( FT_Error ) + cff_get_mm_weightvector( FT_Face face, /* CFF_Face */ FT_UInt* len, FT_Fixed* weightvector ) { - FT_Service_MultiMasters mm = (FT_Service_MultiMasters)face->mm; + CFF_Face cffface = (CFF_Face)face; + FT_Service_MultiMasters mm = (FT_Service_MultiMasters)cffface->mm; - return mm->get_mm_weightvector( FT_FACE( face ), len, weightvector ); + return mm->get_mm_weightvector( face, len, weightvector ); } - static FT_Error - cff_get_mm_var( CFF_Face face, + FT_CALLBACK_DEF( void ) + cff_construct_ps_name( FT_Face face ) /* CFF_Face */ + { + CFF_Face cffface = (CFF_Face)face; + FT_Service_MultiMasters mm = (FT_Service_MultiMasters)cffface->mm; + + + mm->construct_ps_name( face ); + } + + + FT_CALLBACK_DEF( FT_Error ) + cff_get_mm_var( FT_Face face, /* CFF_Face */ FT_MM_Var* *master ) { - FT_Service_MultiMasters mm = (FT_Service_MultiMasters)face->mm; + CFF_Face cffface = (CFF_Face)face; + FT_Service_MultiMasters mm = (FT_Service_MultiMasters)cffface->mm; - return mm->get_mm_var( FT_FACE( face ), master ); + return mm->get_mm_var( face, master ); } - static FT_Error - cff_set_var_design( CFF_Face face, + FT_CALLBACK_DEF( FT_Error ) + cff_set_var_design( FT_Face face, /* CFF_Face */ FT_UInt num_coords, FT_Fixed* coords ) { - FT_Service_MultiMasters mm = (FT_Service_MultiMasters)face->mm; + CFF_Face cffface = (CFF_Face)face; + FT_Service_MultiMasters mm = (FT_Service_MultiMasters)cffface->mm; - return mm->set_var_design( FT_FACE( face ), num_coords, coords ); + return mm->set_var_design( face, num_coords, coords ); } - static FT_Error - cff_get_var_design( CFF_Face face, + FT_CALLBACK_DEF( FT_Error ) + cff_get_var_design( FT_Face face, /* CFF_Face */ FT_UInt num_coords, FT_Fixed* coords ) { - FT_Service_MultiMasters mm = (FT_Service_MultiMasters)face->mm; + CFF_Face cffface = (CFF_Face)face; + FT_Service_MultiMasters mm = (FT_Service_MultiMasters)cffface->mm; - return mm->get_var_design( FT_FACE( face ), num_coords, coords ); + return mm->get_var_design( face, num_coords, coords ); } - static FT_Error - cff_set_instance( CFF_Face face, - FT_UInt instance_index ) + FT_CALLBACK_DEF( FT_Error ) + cff_set_named_instance( FT_Face face, /* CFF_Face */ + FT_UInt instance_index ) { - FT_Service_MultiMasters mm = (FT_Service_MultiMasters)face->mm; + CFF_Face cffface = (CFF_Face)face; + FT_Service_MultiMasters mm = (FT_Service_MultiMasters)cffface->mm; - return mm->set_instance( FT_FACE( face ), instance_index ); + return mm->set_named_instance( face, instance_index ); } - static FT_Error - cff_load_item_variation_store( CFF_Face face, + FT_CALLBACK_DEF( FT_Error ) + cff_get_default_named_instance( FT_Face face, /* CFF_Face */ + FT_UInt *instance_index ) + { + CFF_Face cffface = (CFF_Face)face; + FT_Service_MultiMasters mm = (FT_Service_MultiMasters)cffface->mm; + + + return mm->get_default_named_instance( face, instance_index ); + } + + + FT_CALLBACK_DEF( FT_Error ) + cff_load_item_variation_store( FT_Face face, /* CFF_Face */ FT_ULong offset, GX_ItemVarStore itemStore ) { - FT_Service_MultiMasters mm = (FT_Service_MultiMasters)face->mm; + CFF_Face cffface = (CFF_Face)face; + FT_Service_MultiMasters mm = (FT_Service_MultiMasters)cffface->mm; - return mm->load_item_var_store( FT_FACE(face), offset, itemStore ); + return mm->load_item_var_store( face, offset, itemStore ); } - static FT_Error - cff_load_delta_set_index_mapping( CFF_Face face, + FT_CALLBACK_DEF( FT_Error ) + cff_load_delta_set_index_mapping( FT_Face face, /* CFF_Face */ FT_ULong offset, GX_DeltaSetIdxMap map, GX_ItemVarStore itemStore, FT_ULong table_len ) { - FT_Service_MultiMasters mm = (FT_Service_MultiMasters)face->mm; + CFF_Face cffface = (CFF_Face)face; + FT_Service_MultiMasters mm = (FT_Service_MultiMasters)cffface->mm; - return mm->load_delta_set_idx_map( FT_FACE( face ), offset, map, + return mm->load_delta_set_idx_map( face, offset, map, itemStore, table_len ); } - static FT_Int - cff_get_item_delta( CFF_Face face, + FT_CALLBACK_DEF( FT_Int ) + cff_get_item_delta( FT_Face face, /* CFF_Face */ GX_ItemVarStore itemStore, FT_UInt outerIndex, FT_UInt innerIndex ) { - FT_Service_MultiMasters mm = (FT_Service_MultiMasters)face->mm; + CFF_Face cffface = (CFF_Face)face; + FT_Service_MultiMasters mm = (FT_Service_MultiMasters)cffface->mm; - return mm->get_item_delta( FT_FACE( face ), itemStore, - outerIndex, innerIndex ); + return mm->get_item_delta( face, itemStore, outerIndex, innerIndex ); } - static void - cff_done_item_variation_store( CFF_Face face, + FT_CALLBACK_DEF( void ) + cff_done_item_variation_store( FT_Face face, /* CFF_Face */ GX_ItemVarStore itemStore ) { - FT_Service_MultiMasters mm = (FT_Service_MultiMasters)face->mm; + CFF_Face cffface = (CFF_Face)face; + FT_Service_MultiMasters mm = (FT_Service_MultiMasters)cffface->mm; - mm->done_item_var_store( FT_FACE( face ), itemStore ); + mm->done_item_var_store( face, itemStore ); } - static void - cff_done_delta_set_index_map( CFF_Face face, + FT_CALLBACK_DEF( void ) + cff_done_delta_set_index_map( FT_Face face, /* CFF_Face */ GX_DeltaSetIdxMap deltaSetIdxMap ) { - FT_Service_MultiMasters mm = (FT_Service_MultiMasters)face->mm; + CFF_Face cffface = (CFF_Face)face; + FT_Service_MultiMasters mm = (FT_Service_MultiMasters)cffface->mm; - mm->done_delta_set_idx_map( FT_FACE ( face ), deltaSetIdxMap ); + mm->done_delta_set_idx_map( face, deltaSetIdxMap ); } @@ -1003,36 +1044,35 @@ FT_DEFINE_SERVICE_MULTIMASTERSREC( cff_service_multi_masters, - (FT_Get_MM_Func) NULL, /* get_mm */ - (FT_Set_MM_Design_Func) NULL, /* set_mm_design */ - (FT_Set_MM_Blend_Func) cff_set_mm_blend, /* set_mm_blend */ - (FT_Get_MM_Blend_Func) cff_get_mm_blend, /* get_mm_blend */ - (FT_Get_MM_Var_Func) cff_get_mm_var, /* get_mm_var */ - (FT_Set_Var_Design_Func)cff_set_var_design, /* set_var_design */ - (FT_Get_Var_Design_Func)cff_get_var_design, /* get_var_design */ - (FT_Set_Instance_Func) cff_set_instance, /* set_instance */ - (FT_Set_MM_WeightVector_Func) - cff_set_mm_weightvector, - /* set_mm_weightvector */ - (FT_Get_MM_WeightVector_Func) - cff_get_mm_weightvector, - /* get_mm_weightvector */ - (FT_Var_Load_Delta_Set_Idx_Map_Func) - cff_load_delta_set_index_mapping, - /* load_delta_set_idx_map */ - (FT_Var_Load_Item_Var_Store_Func) - cff_load_item_variation_store, - /* load_item_variation_store */ - (FT_Var_Get_Item_Delta_Func) - cff_get_item_delta, /* get_item_delta */ - (FT_Var_Done_Item_Var_Store_Func) - cff_done_item_variation_store, - /* done_item_variation_store */ - (FT_Var_Done_Delta_Set_Idx_Map_Func) - cff_done_delta_set_index_map, - /* done_delta_set_index_map */ - (FT_Get_Var_Blend_Func) cff_get_var_blend, /* get_var_blend */ - (FT_Done_Blend_Func) cff_done_blend /* done_blend */ + NULL, /* FT_Get_MM_Func get_mm */ + NULL, /* FT_Set_MM_Design_Func set_mm_design */ + cff_set_mm_blend, /* FT_Set_MM_Blend_Func set_mm_blend */ + cff_get_mm_blend, /* FT_Get_MM_Blend_Func get_mm_blend */ + cff_get_mm_var, /* FT_Get_MM_Var_Func get_mm_var */ + cff_set_var_design, /* FT_Set_Var_Design_Func set_var_design */ + cff_get_var_design, /* FT_Get_Var_Design_Func get_var_design */ + cff_set_named_instance, + /* FT_Set_Named_Instance_Func set_named_instance */ + cff_get_default_named_instance, + /* FT_Get_Default_Named_Instance_Func get_default_named_instance */ + cff_set_mm_weightvector, + /* FT_Set_MM_WeightVector_Func set_mm_weightvector */ + cff_get_mm_weightvector, + /* FT_Get_MM_WeightVector_Func get_mm_weightvector */ + cff_construct_ps_name, + /* FT_Construct_PS_Name_Func construct_ps_name */ + cff_load_delta_set_index_mapping, + /* FT_Var_Load_Delta_Set_Idx_Map_Func load_delta_set_idx_map */ + cff_load_item_variation_store, + /* FT_Var_Load_Item_Var_Store_Func load_item_variation_store */ + cff_get_item_delta, + /* FT_Var_Get_Item_Delta_Func get_item_delta */ + cff_done_item_variation_store, + /* FT_Var_Done_Item_Var_Store_Func done_item_variation_store */ + cff_done_delta_set_index_map, + /* FT_Var_Done_Delta_Set_Idx_Map_Func done_delta_set_index_map */ + cff_get_var_blend, /* FT_Get_Var_Blend_Func get_var_blend */ + cff_done_blend /* FT_Done_Blend_Func done_blend */ ) @@ -1041,41 +1081,46 @@ * */ - static FT_Error - cff_hadvance_adjust( CFF_Face face, + FT_CALLBACK_DEF( FT_Error ) + cff_hadvance_adjust( FT_Face face, /* CFF_Face */ FT_UInt gindex, FT_Int *avalue ) { - FT_Service_MetricsVariations var = (FT_Service_MetricsVariations)face->var; + CFF_Face cffface = (CFF_Face)face; + FT_Service_MetricsVariations + var = (FT_Service_MetricsVariations)cffface->tt_var; - return var->hadvance_adjust( FT_FACE( face ), gindex, avalue ); + return var->hadvance_adjust( face, gindex, avalue ); } - static void - cff_metrics_adjust( CFF_Face face ) + FT_CALLBACK_DEF( void ) + cff_metrics_adjust( FT_Face face ) /* CFF_Face */ { - FT_Service_MetricsVariations var = (FT_Service_MetricsVariations)face->var; + CFF_Face cffface = (CFF_Face)face; + FT_Service_MetricsVariations + var = (FT_Service_MetricsVariations)cffface->tt_var; - var->metrics_adjust( FT_FACE( face ) ); + var->metrics_adjust( face ); } FT_DEFINE_SERVICE_METRICSVARIATIONSREC( cff_service_metrics_variations, - (FT_HAdvance_Adjust_Func)cff_hadvance_adjust, /* hadvance_adjust */ - (FT_LSB_Adjust_Func) NULL, /* lsb_adjust */ - (FT_RSB_Adjust_Func) NULL, /* rsb_adjust */ + cff_hadvance_adjust, /* FT_HAdvance_Adjust_Func hadvance_adjust */ + NULL, /* FT_LSB_Adjust_Func lsb_adjust */ + NULL, /* FT_RSB_Adjust_Func rsb_adjust */ - (FT_VAdvance_Adjust_Func)NULL, /* vadvance_adjust */ - (FT_TSB_Adjust_Func) NULL, /* tsb_adjust */ - (FT_BSB_Adjust_Func) NULL, /* bsb_adjust */ - (FT_VOrg_Adjust_Func) NULL, /* vorg_adjust */ + NULL, /* FT_VAdvance_Adjust_Func vadvance_adjust */ + NULL, /* FT_TSB_Adjust_Func tsb_adjust */ + NULL, /* FT_BSB_Adjust_Func bsb_adjust */ + NULL, /* FT_VOrg_Adjust_Func vorg_adjust */ - (FT_Metrics_Adjust_Func) cff_metrics_adjust /* metrics_adjust */ + cff_metrics_adjust, /* FT_Metrics_Adjust_Func metrics_adjust */ + NULL /* FT_Size_Reset_Func size_reset */ ) #endif @@ -1088,11 +1133,11 @@ FT_DEFINE_SERVICE_CFFLOADREC( cff_service_cff_load, - (FT_Get_Standard_Encoding_Func)cff_get_standard_encoding, - (FT_Load_Private_Dict_Func) cff_load_private_dict, - (FT_FD_Select_Get_Func) cff_fd_select_get, - (FT_Blend_Check_Vector_Func) cff_blend_check_vector, - (FT_Blend_Build_Vector_Func) cff_blend_build_vector + cff_get_standard_encoding, /* FT_Get_Standard_Encoding_Func get_standard_encoding */ + cff_load_private_dict, /* FT_Load_Private_Dict_Func load_private_dict */ + cff_fd_select_get, /* FT_FD_Select_Get_Func fd_select_get */ + cff_blend_check_vector, /* FT_Blend_Check_Vector_Func blend_check_vector */ + cff_blend_build_vector /* FT_Blend_Build_Vector_Func blend_build_vector */ ) diff --git a/src/3rdparty/freetype/src/cff/cffgload.c b/src/3rdparty/freetype/src/cff/cffgload.c index cfa0aaf2b69..c483d1d1a59 100644 --- a/src/3rdparty/freetype/src/cff/cffgload.c +++ b/src/3rdparty/freetype/src/cff/cffgload.c @@ -356,14 +356,16 @@ #ifdef FT_CONFIG_OPTION_SVG /* check for OT-SVG */ - if ( ( load_flags & FT_LOAD_COLOR ) && face->svg ) + if ( ( load_flags & FT_LOAD_NO_SVG ) == 0 && + ( load_flags & FT_LOAD_COLOR ) && + face->svg ) { /* * We load the SVG document and try to grab the advances from the * table. For the bearings we rely on the presetting hook to do that. */ - SFNT_Service sfnt = (SFNT_Service)face->sfnt; + SFNT_Service sfnt = (SFNT_Service)face->sfnt; if ( size && (size->root.metrics.x_ppem < 1 || diff --git a/src/3rdparty/freetype/src/cff/cffload.c b/src/3rdparty/freetype/src/cff/cffload.c index 4b8c6e16c58..f96002ec0b8 100644 --- a/src/3rdparty/freetype/src/cff/cffload.c +++ b/src/3rdparty/freetype/src/cff/cffload.c @@ -400,7 +400,7 @@ /* Allocate a table containing pointers to an index's elements. */ /* The `pool' argument makes this function convert the index */ - /* entries to C-style strings (this is, null-terminated). */ + /* entries to C-style strings (that is, null-terminated). */ static FT_Error cff_index_get_pointers( CFF_Index idx, FT_Byte*** table, @@ -1589,16 +1589,17 @@ #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT FT_LOCAL_DEF( FT_Error ) - cff_get_var_blend( CFF_Face face, + cff_get_var_blend( FT_Face face, /* CFF_Face */ FT_UInt *num_coords, FT_Fixed* *coords, FT_Fixed* *normalizedcoords, FT_MM_Var* *mm_var ) { - FT_Service_MultiMasters mm = (FT_Service_MultiMasters)face->mm; + CFF_Face cffface = (CFF_Face)face; + FT_Service_MultiMasters mm = (FT_Service_MultiMasters)cffface->mm; - return mm->get_var_blend( FT_FACE( face ), + return mm->get_var_blend( face, num_coords, coords, normalizedcoords, @@ -1607,13 +1608,14 @@ FT_LOCAL_DEF( void ) - cff_done_blend( CFF_Face face ) + cff_done_blend( FT_Face face ) /* CFF_Face */ { - FT_Service_MultiMasters mm = (FT_Service_MultiMasters)face->mm; + CFF_Face cffface = (CFF_Face)face; + FT_Service_MultiMasters mm = (FT_Service_MultiMasters)cffface->mm; - if (mm) - mm->done_blend( FT_FACE( face ) ); + if ( mm ) + mm->done_blend( face ); } #endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */ @@ -1650,13 +1652,6 @@ goto Exit; } - /* Zero out the code to gid/sid mappings. */ - for ( j = 0; j < 256; j++ ) - { - encoding->sids [j] = 0; - encoding->codes[j] = 0; - } - /* Note: The encoding table in a CFF font is indexed by glyph index; */ /* the first encoded glyph index is 1. Hence, we read the character */ /* code (`glyph_code') at index j and make the assignment: */ @@ -1671,6 +1666,10 @@ if ( offset > 1 ) { + /* Zero out the code to gid/sid mappings. */ + FT_ARRAY_ZERO( encoding->sids, 256 ); + FT_ARRAY_ZERO( encoding->codes, 256 ); + encoding->offset = base_offset + offset; /* we need to parse the table to determine its size */ @@ -2012,7 +2011,7 @@ /* Top and Font DICTs are not allowed to have blend operators. */ error = cff_parser_init( &parser, code, - &subfont->font_dict, + top, font->library, stackSize, 0, diff --git a/src/3rdparty/freetype/src/cff/cffload.h b/src/3rdparty/freetype/src/cff/cffload.h index 5a41cdebc8e..b5286b0c8cb 100644 --- a/src/3rdparty/freetype/src/cff/cffload.h +++ b/src/3rdparty/freetype/src/cff/cffload.h @@ -105,14 +105,14 @@ FT_BEGIN_HEADER #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT FT_LOCAL( FT_Error ) - cff_get_var_blend( CFF_Face face, + cff_get_var_blend( FT_Face face, FT_UInt *num_coords, FT_Fixed* *coords, FT_Fixed* *normalizedcoords, FT_MM_Var* *mm_var ); FT_LOCAL( void ) - cff_done_blend( CFF_Face face ); + cff_done_blend( FT_Face face ); #endif diff --git a/src/3rdparty/freetype/src/cff/cffobjs.c b/src/3rdparty/freetype/src/cff/cffobjs.c index 40cd9bf9173..6d08620c487 100644 --- a/src/3rdparty/freetype/src/cff/cffobjs.c +++ b/src/3rdparty/freetype/src/cff/cffobjs.c @@ -69,8 +69,8 @@ FT_Module module; - module = FT_Get_Module( size->root.face->driver->root.library, - "pshinter" ); + module = FT_Get_Module( font->library, "pshinter" ); + return ( module && pshinter && pshinter->get_globals_funcs ) ? pshinter->get_globals_funcs( module ) : 0; @@ -182,8 +182,7 @@ goto Exit; cff_make_private_dict( &font->top_font, &priv ); - error = funcs->create( cffsize->face->memory, &priv, - &internal->topfont ); + error = funcs->create( memory, &priv, &internal->topfont ); if ( error ) goto Exit; @@ -193,8 +192,7 @@ cff_make_private_dict( sub, &priv ); - error = funcs->create( cffsize->face->memory, &priv, - &internal->subfonts[i - 1] ); + error = funcs->create( memory, &priv, &internal->subfonts[i - 1] ); if ( error ) goto Exit; } @@ -381,8 +379,7 @@ FT_Module module; - module = FT_Get_Module( slot->face->driver->root.library, - "pshinter" ); + module = FT_Get_Module( slot->library, "pshinter" ); if ( module ) { T2_Hints_Funcs funcs; @@ -722,22 +719,15 @@ #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT { - FT_Service_MultiMasters mm = (FT_Service_MultiMasters)face->mm; - FT_Service_MetricsVariations var = (FT_Service_MetricsVariations)face->var; - FT_UInt instance_index = (FT_UInt)face_index >> 16; if ( FT_HAS_MULTIPLE_MASTERS( cffface ) && - mm && instance_index > 0 ) { - error = mm->set_instance( cffface, instance_index ); + error = FT_Set_Named_Instance( cffface, instance_index ); if ( error ) goto Exit; - - if ( var ) - var->metrics_adjust( cffface ); } } #endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */ @@ -1160,7 +1150,7 @@ } #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT - cff_done_blend( face ); + cff_done_blend( cffface ); face->blend = NULL; #endif } diff --git a/src/3rdparty/freetype/src/cff/cffparse.c b/src/3rdparty/freetype/src/cff/cffparse.c index e16206fd553..c850dfc61e1 100644 --- a/src/3rdparty/freetype/src/cff/cffparse.c +++ b/src/3rdparty/freetype/src/cff/cffparse.c @@ -63,10 +63,7 @@ /* allocate the stack buffer */ if ( FT_QNEW_ARRAY( parser->stack, stackSize ) ) - { - FT_FREE( parser->stack ); goto Exit; - } parser->stackSize = stackSize; parser->top = parser->stack; /* empty stack */ @@ -76,23 +73,6 @@ } -#ifdef CFF_CONFIG_OPTION_OLD_ENGINE - static void - finalize_t2_strings( FT_Memory memory, - void* data, - void* user ) - { - CFF_T2_String t2 = (CFF_T2_String)data; - - - FT_UNUSED( user ); - - memory->free( memory, t2->start ); - memory->free( memory, data ); - } -#endif /* CFF_CONFIG_OPTION_OLD_ENGINE */ - - FT_LOCAL_DEF( void ) cff_parser_done( CFF_Parser parser ) { @@ -102,63 +82,19 @@ FT_FREE( parser->stack ); #ifdef CFF_CONFIG_OPTION_OLD_ENGINE - FT_List_Finalize( &parser->t2_strings, - finalize_t2_strings, - memory, - NULL ); + FT_List_Finalize( &parser->t2_strings, NULL, memory, NULL ); #endif } - /* Assuming `first >= last'. */ - - static FT_Error - cff_parser_within_limits( CFF_Parser parser, - FT_Byte* first, - FT_Byte* last ) - { -#ifndef CFF_CONFIG_OPTION_OLD_ENGINE - - /* Fast path for regular FreeType builds with the "new" engine; */ - /* `first >= parser->start' can be assumed. */ - - FT_UNUSED( first ); - - return last < parser->limit ? FT_Err_Ok : FT_THROW( Invalid_Argument ); - -#else /* CFF_CONFIG_OPTION_OLD_ENGINE */ - - FT_ListNode node; - - - if ( first >= parser->start && - last < parser->limit ) - return FT_Err_Ok; - - node = parser->t2_strings.head; - - while ( node ) - { - CFF_T2_String t2 = (CFF_T2_String)node->data; - - - if ( first >= t2->start && - last < t2->limit ) - return FT_Err_Ok; - - node = node->next; - } - - return FT_THROW( Invalid_Argument ); - -#endif /* CFF_CONFIG_OPTION_OLD_ENGINE */ - } - + /* The parser limit checks in the next two functions are supposed */ + /* to detect the immediate crossing of the stream boundary. They */ + /* shall not be triggered from the distant t2_strings buffers. */ /* read an integer */ static FT_Long - cff_parse_integer( CFF_Parser parser, - FT_Byte* start ) + cff_parse_integer( FT_Byte* start, + FT_Byte* limit ) { FT_Byte* p = start; FT_Int v = *p++; @@ -167,14 +103,14 @@ if ( v == 28 ) { - if ( cff_parser_within_limits( parser, p, p + 1 ) ) + if ( p + 2 > limit && limit >= p ) goto Bad; val = (FT_Short)( ( (FT_UShort)p[0] << 8 ) | p[1] ); } else if ( v == 29 ) { - if ( cff_parser_within_limits( parser, p, p + 3 ) ) + if ( p + 4 > limit && limit >= p ) goto Bad; val = (FT_Long)( ( (FT_ULong)p[0] << 24 ) | @@ -188,14 +124,14 @@ } else if ( v < 251 ) { - if ( cff_parser_within_limits( parser, p, p ) ) + if ( p + 1 > limit && limit >= p ) goto Bad; val = ( v - 247 ) * 256 + p[0] + 108; } else { - if ( cff_parser_within_limits( parser, p, p ) ) + if ( p + 1 > limit && limit >= p ) goto Bad; val = -( v - 251 ) * 256 - p[0] - 108; @@ -244,10 +180,10 @@ /* read a real */ static FT_Fixed - cff_parse_real( CFF_Parser parser, - FT_Byte* start, - FT_Long power_ten, - FT_Long* scaling ) + cff_parse_real( FT_Byte* start, + FT_Byte* limit, + FT_Long power_ten, + FT_Long* scaling ) { FT_Byte* p = start; FT_Int nib; @@ -282,7 +218,7 @@ p++; /* Make sure we don't read past the end. */ - if ( cff_parser_within_limits( parser, p, p ) ) + if ( p + 1 > limit && limit >= p ) goto Bad; } @@ -319,7 +255,7 @@ p++; /* Make sure we don't read past the end. */ - if ( cff_parser_within_limits( parser, p, p ) ) + if ( p + 1 > limit && limit >= p ) goto Bad; } @@ -358,7 +294,7 @@ p++; /* Make sure we don't read past the end. */ - if ( cff_parser_within_limits( parser, p, p ) ) + if ( p + 1 > limit && limit >= p ) goto Bad; } @@ -525,7 +461,7 @@ if ( **d == 30 ) { /* binary-coded decimal is truncated to integer */ - return cff_parse_real( parser, *d, 0, NULL ) >> 16; + return cff_parse_real( *d, parser->limit, 0, NULL ) >> 16; } else if ( **d == 255 ) @@ -551,7 +487,7 @@ } else - return cff_parse_integer( parser, *d ); + return cff_parse_integer( *d, parser->limit ); } @@ -562,10 +498,10 @@ FT_Long scaling ) { if ( **d == 30 ) - return cff_parse_real( parser, *d, scaling, NULL ); + return cff_parse_real( *d, parser->limit, scaling, NULL ); else { - FT_Long val = cff_parse_integer( parser, *d ); + FT_Long val = cff_parse_integer( *d, parser->limit ); if ( scaling ) @@ -630,14 +566,14 @@ FT_ASSERT( scaling ); if ( **d == 30 ) - return cff_parse_real( parser, *d, 0, scaling ); + return cff_parse_real( *d, parser->limit, 0, scaling ); else { FT_Long number; FT_Int integer_length; - number = cff_parse_integer( parser, d[0] ); + number = cff_parse_integer( *d, parser->limit ); if ( number > 0x7FFFL ) { @@ -686,7 +622,7 @@ dict->has_font_matrix = TRUE; - /* We expect a well-formed font matrix, this is, the matrix elements */ + /* We expect a well-formed font matrix, that is, the matrix elements */ /* `xx' and `yy' are of approximately the same magnitude. To avoid */ /* loss of precision, we use the magnitude of the largest matrix */ /* element to scale all other elements. The scaling factor is then */ @@ -1264,11 +1200,8 @@ FT_Byte* charstring_base; FT_ULong charstring_len; - FT_Fixed* stack; - FT_ListNode node; - CFF_T2_String t2; - FT_Fixed t2_size; - FT_Byte* q; + FT_Fixed* stack; + FT_Byte* q = NULL; charstring_base = ++p; @@ -1309,39 +1242,18 @@ /* Now copy the stack data in the temporary decoder object, */ /* converting it back to charstring number representations */ /* (this is ugly, I know). */ + /* The maximum required size is 5 bytes per stack element. */ + if ( FT_QALLOC( q, (FT_Long)( 2 * sizeof ( FT_ListNode ) ) + + 5 * ( decoder.top - decoder.stack ) ) ) + goto Exit; - node = (FT_ListNode)memory->alloc( memory, - sizeof ( FT_ListNodeRec ) ); - if ( !node ) - goto Out_Of_Memory_Error; + FT_List_Add( &parser->t2_strings, (FT_ListNode)q ); - FT_List_Add( &parser->t2_strings, node ); + q += 2 * sizeof ( FT_ListNode ); - t2 = (CFF_T2_String)memory->alloc( memory, - sizeof ( CFF_T2_StringRec ) ); - if ( !t2 ) - goto Out_Of_Memory_Error; - - node->data = t2; - - /* `5' is the conservative upper bound of required bytes per stack */ - /* element. */ - - t2_size = 5 * ( decoder.top - decoder.stack ); - - q = (FT_Byte*)memory->alloc( memory, t2_size ); - if ( !q ) - goto Out_Of_Memory_Error; - - t2->start = q; - t2->limit = q + t2_size; - - stack = decoder.stack; - - while ( stack < decoder.top ) + for ( stack = decoder.stack; stack < decoder.top; stack++ ) { - FT_ULong num; - FT_Bool neg; + FT_Long num = *stack; if ( (FT_UInt)( parser->top - parser->stack ) >= parser->stackSize ) @@ -1349,69 +1261,37 @@ *parser->top++ = q; - if ( *stack < 0 ) - { - num = (FT_ULong)NEG_LONG( *stack ); - neg = 1; - } - else - { - num = (FT_ULong)*stack; - neg = 0; - } - if ( num & 0xFFFFU ) { - if ( neg ) - num = (FT_ULong)-num; - *q++ = 255; - *q++ = ( num & 0xFF000000U ) >> 24; - *q++ = ( num & 0x00FF0000U ) >> 16; - *q++ = ( num & 0x0000FF00U ) >> 8; - *q++ = num & 0x000000FFU; + *q++ = (FT_Byte)( ( num >> 24 ) & 0xFF ); + *q++ = (FT_Byte)( ( num >> 16 ) & 0xFF ); + *q++ = (FT_Byte)( ( num >> 8 ) & 0xFF ); + *q++ = (FT_Byte)( ( num ) & 0xFF ); } else { num >>= 16; - if ( neg ) + if ( -107 <= num && num <= 107 ) + *q++ = (FT_Byte)( num + 139 ); + else if ( 108 <= num && num <= 1131 ) { - if ( num <= 107 ) - *q++ = (FT_Byte)( 139 - num ); - else if ( num <= 1131 ) - { - *q++ = (FT_Byte)( ( ( num - 108 ) >> 8 ) + 251 ); - *q++ = (FT_Byte)( ( num - 108 ) & 0xFF ); - } - else - { - num = (FT_ULong)-num; - - *q++ = 28; - *q++ = (FT_Byte)( num >> 8 ); - *q++ = (FT_Byte)( num & 0xFF ); - } + *q++ = (FT_Byte)( ( ( num - 108 ) >> 8 ) + 247 ); + *q++ = (FT_Byte)( ( num - 108 ) & 0xFF ); + } + else if ( -1131 <= num && num <= -108 ) + { + *q++ = (FT_Byte)( ( ( -num - 108 ) >> 8 ) + 251 ); + *q++ = (FT_Byte)( ( -num - 108) & 0xFF ); } else { - if ( num <= 107 ) - *q++ = (FT_Byte)( num + 139 ); - else if ( num <= 1131 ) - { - *q++ = (FT_Byte)( ( ( num - 108 ) >> 8 ) + 247 ); - *q++ = (FT_Byte)( ( num - 108 ) & 0xFF ); - } - else - { - *q++ = 28; - *q++ = (FT_Byte)( num >> 8 ); - *q++ = (FT_Byte)( num & 0xFF ); - } + *q++ = 28; + *q++ = (FT_Byte)( num >> 8 ); + *q++ = (FT_Byte)( num & 0xFF ); } } - - stack++; } } #endif /* CFF_CONFIG_OPTION_OLD_ENGINE */ @@ -1598,12 +1478,6 @@ Exit: return error; -#ifdef CFF_CONFIG_OPTION_OLD_ENGINE - Out_Of_Memory_Error: - error = FT_THROW( Out_Of_Memory ); - goto Exit; -#endif - Stack_Overflow: error = FT_THROW( Invalid_Argument ); goto Exit; diff --git a/src/3rdparty/freetype/src/cff/cffparse.h b/src/3rdparty/freetype/src/cff/cffparse.h index 58d59fa4ac5..b6378a8e8d6 100644 --- a/src/3rdparty/freetype/src/cff/cffparse.h +++ b/src/3rdparty/freetype/src/cff/cffparse.h @@ -133,15 +133,6 @@ FT_BEGIN_HEADER FT_END_HEADER -#ifdef CFF_CONFIG_OPTION_OLD_ENGINE - typedef struct CFF_T2_String_ - { - FT_Byte* start; - FT_Byte* limit; - - } CFF_T2_StringRec, *CFF_T2_String; -#endif /* CFF_CONFIG_OPTION_OLD_ENGINE */ - #endif /* CFFPARSE_H_ */ diff --git a/src/3rdparty/freetype/src/cid/cidgload.c b/src/3rdparty/freetype/src/cid/cidgload.c index ba4b7565d54..eaca765ad06 100644 --- a/src/3rdparty/freetype/src/cid/cidgload.c +++ b/src/3rdparty/freetype/src/cid/cidgload.c @@ -40,6 +40,117 @@ #define FT_COMPONENT cidgload + /* + * A helper function to compute FD number (`fd_select`), the offset to the + * head of the glyph data (`off1`), and the offset to the and of the glyph + * data (`off2`). + * + * The number how many times `cid_get_offset` is invoked can be controlled + * by the number of non-NULL arguments. If `fd_select` is non-NULL but + * `off1` and `off2` are NULL, `cid_get_offset` is invoked only for + * `fd_select`; `off1` and `off2` are not validated. + * + */ + FT_LOCAL_DEF( FT_Error ) + cid_compute_fd_and_offsets( CID_Face face, + FT_UInt glyph_index, + FT_ULong* fd_select_p, + FT_ULong* off1_p, + FT_ULong* off2_p ) + { + FT_Error error = FT_Err_Ok; + + CID_FaceInfo cid = &face->cid; + FT_Stream stream = face->cid_stream; + FT_UInt entry_len = cid->fd_bytes + cid->gd_bytes; + + FT_Byte* p; + FT_Bool need_frame_exit = 0; + FT_ULong fd_select, off1, off2; + + + /* For ordinary fonts, read the CID font dictionary index */ + /* and charstring offset from the CIDMap. */ + + if ( FT_STREAM_SEEK( cid->data_offset + cid->cidmap_offset + + glyph_index * entry_len ) || + FT_FRAME_ENTER( 2 * entry_len ) ) + goto Exit; + + need_frame_exit = 1; + + p = (FT_Byte*)stream->cursor; + fd_select = cid_get_offset( &p, cid->fd_bytes ); + off1 = cid_get_offset( &p, cid->gd_bytes ); + + p += cid->fd_bytes; + off2 = cid_get_offset( &p, cid->gd_bytes ); + + if ( fd_select_p ) + *fd_select_p = fd_select; + if ( off1_p ) + *off1_p = off1; + if ( off2_p ) + *off2_p = off2; + + if ( fd_select >= cid->num_dicts ) + { + /* + * fd_select == 0xFF is often used to indicate that the CID + * has no charstring to be rendered, similar to GID = 0xFFFF + * in TrueType fonts. + */ + if ( ( cid->fd_bytes == 1 && fd_select == 0xFFU ) || + ( cid->fd_bytes == 2 && fd_select == 0xFFFFU ) ) + { + FT_TRACE1(( "cid_load_glyph: fail for glyph index %d:\n", + glyph_index )); + FT_TRACE1(( " FD number %ld is the maximum\n", + fd_select )); + FT_TRACE1(( " integer fitting into %d byte%s\n", + cid->fd_bytes, cid->fd_bytes == 1 ? "" : "s" )); + } + else + { + FT_TRACE0(( "cid_load_glyph: fail for glyph index %d:\n", + glyph_index )); + FT_TRACE0(( " FD number %ld is larger\n", + fd_select )); + FT_TRACE0(( " than number of dictionaries (%d)\n", + cid->num_dicts )); + } + + error = FT_THROW( Invalid_Offset ); + goto Exit; + } + else if ( off2 > stream->size ) + { + FT_TRACE0(( "cid_load_glyph: fail for glyph index %d:\n", + glyph_index )); + FT_TRACE0(( " end of the glyph data\n" )); + FT_TRACE0(( " is beyond the data stream\n" )); + + error = FT_THROW( Invalid_Offset ); + goto Exit; + } + else if ( off1 > off2 ) + { + FT_TRACE0(( "cid_load_glyph: fail for glyph index %d:\n", + glyph_index )); + FT_TRACE0(( " the end position of glyph data\n" )); + FT_TRACE0(( " is set before the start position\n" )); + + error = FT_THROW( Invalid_Offset ); + } + + Exit: + if ( need_frame_exit ) + FT_FRAME_EXIT(); + + return error; + } + + FT_CALLBACK_DEF( FT_Error ) cid_load_glyph( T1_Decoder decoder, FT_UInt glyph_index ) @@ -97,35 +208,15 @@ else #endif /* FT_CONFIG_OPTION_INCREMENTAL */ - - /* For ordinary fonts read the CID font dictionary index */ - /* and charstring offset from the CIDMap. */ { - FT_UInt entry_len = cid->fd_bytes + cid->gd_bytes; FT_ULong off1, off2; - if ( FT_STREAM_SEEK( cid->data_offset + cid->cidmap_offset + - glyph_index * entry_len ) || - FT_FRAME_ENTER( 2 * entry_len ) ) + error = cid_compute_fd_and_offsets( face, glyph_index, + &fd_select, &off1, &off2 ); + if ( error ) goto Exit; - p = (FT_Byte*)stream->cursor; - fd_select = cid_get_offset( &p, cid->fd_bytes ); - off1 = cid_get_offset( &p, cid->gd_bytes ); - p += cid->fd_bytes; - off2 = cid_get_offset( &p, cid->gd_bytes ); - FT_FRAME_EXIT(); - - if ( fd_select >= cid->num_dicts || - off2 > stream->size || - off1 > off2 ) - { - FT_TRACE0(( "cid_load_glyph: invalid glyph stream offsets\n" )); - error = FT_THROW( Invalid_Offset ); - goto Exit; - } - glyph_length = off2 - off1; if ( glyph_length == 0 || @@ -161,7 +252,9 @@ cs_offset = decoder->lenIV >= 0 ? (FT_UInt)decoder->lenIV : 0; if ( cs_offset > glyph_length ) { - FT_TRACE0(( "cid_load_glyph: invalid glyph stream offsets\n" )); + FT_TRACE0(( "cid_load_glyph: fail for glyph_index=%d, " + "offset to the charstring is beyond glyph length\n", + glyph_index )); error = FT_THROW( Invalid_Offset ); goto Exit; } diff --git a/src/3rdparty/freetype/src/cid/cidgload.h b/src/3rdparty/freetype/src/cid/cidgload.h index 97954d418ff..edd6229234c 100644 --- a/src/3rdparty/freetype/src/cid/cidgload.h +++ b/src/3rdparty/freetype/src/cid/cidgload.h @@ -42,6 +42,14 @@ FT_BEGIN_HEADER FT_Int32 load_flags ); + FT_LOCAL( FT_Error ) + cid_compute_fd_and_offsets( CID_Face face, + FT_UInt glyph_index, + FT_ULong* fd_select_p, + FT_ULong* off1_p, + FT_ULong* off2_p ); + + FT_END_HEADER #endif /* CIDGLOAD_H_ */ diff --git a/src/3rdparty/freetype/src/cid/cidload.c b/src/3rdparty/freetype/src/cid/cidload.c index 26daa5da7f6..a7da8ea39d5 100644 --- a/src/3rdparty/freetype/src/cid/cidload.c +++ b/src/3rdparty/freetype/src/cid/cidload.c @@ -155,23 +155,24 @@ FT_CALLBACK_DEF( void ) - cid_parse_font_matrix( CID_Face face, - CID_Parser* parser ) + cid_parse_font_matrix( FT_Face face, /* CID_Face */ + void* parser_ ) { + CID_Face cidface = (CID_Face)face; + CID_Parser* parser = (CID_Parser*)parser_; CID_FaceDict dict; - FT_Face root = (FT_Face)&face->root; FT_Fixed temp[6]; FT_Fixed temp_scale; - if ( parser->num_dict < face->cid.num_dicts ) + if ( parser->num_dict < cidface->cid.num_dicts ) { FT_Matrix* matrix; FT_Vector* offset; FT_Int result; - dict = face->cid.font_dicts + parser->num_dict; + dict = cidface->cid.font_dicts + parser->num_dict; matrix = &dict->font_matrix; offset = &dict->font_offset; @@ -204,7 +205,7 @@ if ( temp_scale != 0x10000L ) { /* set units per EM based on FontMatrix values */ - root->units_per_EM = (FT_UShort)FT_DivFix( 1000, temp_scale ); + face->units_per_EM = (FT_UShort)FT_DivFix( 1000, temp_scale ); temp[0] = FT_DivFix( temp[0], temp_scale ); temp[1] = FT_DivFix( temp[1], temp_scale ); @@ -237,13 +238,15 @@ FT_CALLBACK_DEF( void ) - parse_fd_array( CID_Face face, - CID_Parser* parser ) + parse_fd_array( FT_Face face, /* CID_Face */ + void* parser_ ) { - CID_FaceInfo cid = &face->cid; - FT_Memory memory = face->root.memory; - FT_Stream stream = parser->stream; - FT_Error error = FT_Err_Ok; + CID_Face cidface = (CID_Face)face; + CID_Parser* parser = (CID_Parser*)parser_; + CID_FaceInfo cid = &cidface->cid; + FT_Memory memory = FT_FACE_MEMORY( face ); + FT_Stream stream = parser->stream; + FT_Error error = FT_Err_Ok; FT_Long num_dicts, max_dicts; @@ -313,18 +316,20 @@ /* By mistake, `expansion_factor' appears both in PS_PrivateRec */ /* and CID_FaceDictRec (both are public header files and can't */ - /* changed). We simply copy the value. */ + /* be thus changed). We simply copy the value. */ FT_CALLBACK_DEF( void ) - parse_expansion_factor( CID_Face face, - CID_Parser* parser ) + parse_expansion_factor( FT_Face face, /* CID_Face */ + void* parser_ ) { + CID_Face cidface = (CID_Face)face; + CID_Parser* parser = (CID_Parser*)parser_; CID_FaceDict dict; - if ( parser->num_dict < face->cid.num_dicts ) + if ( parser->num_dict < cidface->cid.num_dicts ) { - dict = face->cid.font_dicts + parser->num_dict; + dict = cidface->cid.font_dicts + parser->num_dict; dict->expansion_factor = cid_parser_to_fixed( parser, 0 ); dict->private_dict.expansion_factor = dict->expansion_factor; @@ -341,11 +346,15 @@ /* to catch it for producing better trace output. */ FT_CALLBACK_DEF( void ) - parse_font_name( CID_Face face, - CID_Parser* parser ) + parse_font_name( FT_Face face, /* CID_Face */ + void* parser_ ) { #ifdef FT_DEBUG_LEVEL_TRACE - if ( parser->num_dict < face->cid.num_dicts ) + CID_Face cidface = (CID_Face)face; + CID_Parser* parser = (CID_Parser*)parser_; + + + if ( parser->num_dict < cidface->cid.num_dicts ) { T1_TokenRec token; FT_UInt len; @@ -361,7 +370,7 @@ } #else FT_UNUSED( face ); - FT_UNUSED( parser ); + FT_UNUSED( parser_ ); #endif return; diff --git a/src/3rdparty/freetype/src/cid/cidobjs.c b/src/3rdparty/freetype/src/cid/cidobjs.c index 06b2139a93d..f698a419289 100644 --- a/src/3rdparty/freetype/src/cid/cidobjs.c +++ b/src/3rdparty/freetype/src/cid/cidobjs.c @@ -69,8 +69,7 @@ FT_Module module; - module = FT_Get_Module( slot->face->driver->root.library, - "pshinter" ); + module = FT_Get_Module( slot->library, "pshinter" ); if ( module ) { T1_Hints_Funcs funcs; @@ -268,7 +267,8 @@ * * @Input: * stream :: - * The source font stream. + * Dummy argument for compatibility with the `FT_Face_InitFunc` API. + * Ignored. The stream should be passed through `face->root.stream`. * * face_index :: * The index of the font face in the resource. @@ -375,6 +375,14 @@ if ( info->is_fixed_pitch ) cidface->face_flags |= FT_FACE_FLAG_FIXED_WIDTH; + /* + * For the sfnt-wrapped CID fonts for MacOS, currently, + * its `cmap' tables are ignored, and the content in + * its `CID ' table is treated the same as naked CID-keyed + * font. See ft_lookup_PS_in_sfnt_stream(). + */ + cidface->face_flags |= FT_FACE_FLAG_CID_KEYED; + /* XXX: TODO: add kerning with .afm support */ /* get style name -- be careful, some broken fonts only */ diff --git a/src/3rdparty/freetype/src/cid/cidparse.c b/src/3rdparty/freetype/src/cid/cidparse.c index 16889db9b6f..171a886215a 100644 --- a/src/3rdparty/freetype/src/cid/cidparse.c +++ b/src/3rdparty/freetype/src/cid/cidparse.c @@ -214,18 +214,24 @@ cur <= limit - STARTDATA_LEN && ft_strncmp( (char*)cur, STARTDATA, STARTDATA_LEN ) == 0 ) { - if ( ft_strncmp( (char*)arg1, "(Hex)", 5 ) == 0 ) + T1_TokenRec type_token; + FT_Long binary_length; + + + parser->root.cursor = arg1; + cid_parser_to_token( parser, &type_token ); + if ( type_token.limit - type_token.start == 5 && + ft_memcmp( (char*)type_token.start, "(Hex)", 5 ) == 0 ) { - FT_Long tmp = ft_strtol( (const char *)arg2, NULL, 10 ); - - - if ( tmp < 0 ) + parser->root.cursor = arg2; + binary_length = cid_parser_to_int( parser ); + if ( binary_length < 0 ) { FT_ERROR(( "cid_parser_new: invalid length of hex data\n" )); error = FT_THROW( Invalid_File_Format ); } else - parser->binary_length = (FT_ULong)tmp; + parser->binary_length = (FT_ULong)binary_length; } goto Exit; diff --git a/src/3rdparty/freetype/src/cid/cidriver.c b/src/3rdparty/freetype/src/cid/cidriver.c index f7499237d73..99e7b118395 100644 --- a/src/3rdparty/freetype/src/cid/cidriver.c +++ b/src/3rdparty/freetype/src/cid/cidriver.c @@ -48,10 +48,11 @@ * */ - static const char* - cid_get_postscript_name( CID_Face face ) + FT_CALLBACK_DEF( const char* ) + cid_get_postscript_name( FT_Face face ) /* CID_Face */ { - const char* result = face->cid.cid_font_name; + CID_Face cidface = (CID_Face)face; + const char* result = cidface->cid.cid_font_name; if ( result && result[0] == '/' ) @@ -72,34 +73,36 @@ * */ - static FT_Error - cid_ps_get_font_info( FT_Face face, + FT_CALLBACK_DEF( FT_Error ) + cid_ps_get_font_info( FT_Face face, /* CID_Face */ PS_FontInfoRec* afont_info ) { - *afont_info = ((CID_Face)face)->cid.font_info; + *afont_info = ( (CID_Face)face )->cid.font_info; return FT_Err_Ok; } - static FT_Error - cid_ps_get_font_extra( FT_Face face, - PS_FontExtraRec* afont_extra ) + + FT_CALLBACK_DEF( FT_Error ) + cid_ps_get_font_extra( FT_Face face, /* CID_Face */ + PS_FontExtraRec* afont_extra ) { - *afont_extra = ((CID_Face)face)->font_extra; + *afont_extra = ( (CID_Face)face )->font_extra; return FT_Err_Ok; } + static const FT_Service_PsInfoRec cid_service_ps_info = { - (PS_GetFontInfoFunc) cid_ps_get_font_info, /* ps_get_font_info */ - (PS_GetFontExtraFunc) cid_ps_get_font_extra, /* ps_get_font_extra */ + cid_ps_get_font_info, /* PS_GetFontInfoFunc ps_get_font_info */ + cid_ps_get_font_extra, /* PS_GetFontExtraFunc ps_get_font_extra */ /* unsupported with CID fonts */ - (PS_HasGlyphNamesFunc) NULL, /* ps_has_glyph_names */ + NULL, /* PS_HasGlyphNamesFunc ps_has_glyph_names */ /* unsupported */ - (PS_GetFontPrivateFunc)NULL, /* ps_get_font_private */ + NULL, /* PS_GetFontPrivateFunc ps_get_font_private */ /* not implemented */ - (PS_GetFontValueFunc) NULL /* ps_get_font_value */ + NULL /* PS_GetFontValueFunc ps_get_font_value */ }; @@ -107,13 +110,14 @@ * CID INFO SERVICE * */ - static FT_Error - cid_get_ros( CID_Face face, + FT_CALLBACK_DEF( FT_Error ) + cid_get_ros( FT_Face face, /* CID_Face */ const char* *registry, const char* *ordering, FT_Int *supplement ) { - CID_FaceInfo cid = &face->cid; + CID_Face cidface = (CID_Face)face; + CID_FaceInfo cid = &cidface->cid; if ( registry ) @@ -129,32 +133,48 @@ } - static FT_Error - cid_get_is_cid( CID_Face face, + FT_CALLBACK_DEF( FT_Error ) + cid_get_is_cid( FT_Face face, /* CID_Face */ FT_Bool *is_cid ) { FT_Error error = FT_Err_Ok; FT_UNUSED( face ); + /* + * XXX: If the ROS is Adobe-Identity-H or -V, + * the font has no reliable information about + * its glyph collection. Should we not set + * *is_cid in such cases? + */ if ( is_cid ) - *is_cid = 1; /* cid driver is only used for CID keyed fonts */ + *is_cid = 1; return error; } - static FT_Error - cid_get_cid_from_glyph_index( CID_Face face, + FT_CALLBACK_DEF( FT_Error ) + cid_get_cid_from_glyph_index( FT_Face face, /* CID_Face */ FT_UInt glyph_index, FT_UInt *cid ) { - FT_Error error = FT_Err_Ok; - FT_UNUSED( face ); + FT_Error error = FT_Err_Ok; + CID_Face cidface = (CID_Face)face; - if ( cid ) - *cid = glyph_index; /* identity mapping */ + /* + * Currently, FreeType does not support incrementally-defined, CID-keyed + * fonts that store the glyph description data in a `/GlyphDirectory` + * array or dictionary. Fonts loaded by the incremental loading feature + * are thus not handled here. + */ + error = cid_compute_fd_and_offsets( cidface, glyph_index, + NULL, NULL, NULL ); + if ( error ) + *cid = 0; + else + *cid = glyph_index; return error; } @@ -162,12 +182,12 @@ static const FT_Service_CIDRec cid_service_cid_info = { - (FT_CID_GetRegistryOrderingSupplementFunc) - cid_get_ros, /* get_ros */ - (FT_CID_GetIsInternallyCIDKeyedFunc) - cid_get_is_cid, /* get_is_cid */ - (FT_CID_GetCIDFromGlyphIndexFunc) - cid_get_cid_from_glyph_index /* get_cid_from_glyph_index */ + cid_get_ros, + /* FT_CID_GetRegistryOrderingSupplementFunc get_ros */ + cid_get_is_cid, + /* FT_CID_GetIsInternallyCIDKeyedFunc get_is_cid */ + cid_get_cid_from_glyph_index + /* FT_CID_GetCIDFromGlyphIndexFunc get_cid_from_glyph_index */ }; @@ -179,9 +199,9 @@ FT_DEFINE_SERVICE_PROPERTIESREC( cid_service_properties, - (FT_Properties_SetFunc)ps_property_set, /* set_property */ - (FT_Properties_GetFunc)ps_property_get ) /* get_property */ - + ps_property_set, /* FT_Properties_SetFunc set_property */ + ps_property_get /* FT_Properties_GetFunc get_property */ + ) /* * SERVICE LIST @@ -209,7 +229,6 @@ } - FT_CALLBACK_TABLE_DEF const FT_Driver_ClassRec t1cid_driver_class = { diff --git a/src/3rdparty/freetype/src/dlg/dlgwrap.c b/src/3rdparty/freetype/src/dlg/dlgwrap.c index 271241f0a86..e9dc3410a4d 100644 --- a/src/3rdparty/freetype/src/dlg/dlgwrap.c +++ b/src/3rdparty/freetype/src/dlg/dlgwrap.c @@ -25,7 +25,7 @@ #include "dlg.c" #else /* ANSI C doesn't like empty source files */ - typedef int _dlg_dummy; + typedef int dlg_dummy_; #endif diff --git a/src/3rdparty/freetype/src/gxvalid/gxvfgen.c b/src/3rdparty/freetype/src/gxvalid/gxvfgen.c index 1153542286a..cf98bb36c38 100644 --- a/src/3rdparty/freetype/src/gxvalid/gxvfgen.c +++ b/src/3rdparty/freetype/src/gxvalid/gxvfgen.c @@ -97,7 +97,8 @@ #define EMPTYFEAT {0, 0, {NULL}} - static GX_Feature_RegistryRec featreg_table[] = { + static GX_Feature_RegistryRec featreg_table[] = + { { /* 0 */ "All Typographic Features", 0, diff --git a/src/3rdparty/freetype/src/gzip/README.freetype b/src/3rdparty/freetype/src/gzip/README.freetype index e0c8ced180a..76298b06b59 100644 --- a/src/3rdparty/freetype/src/gzip/README.freetype +++ b/src/3rdparty/freetype/src/gzip/README.freetype @@ -1,7 +1,7 @@ Name: zlib Short Name: zlib URL: http://zlib.net/ -Version: 1.2.12 +Version: 1.2.13 License: see `zlib.h` Description: diff --git a/src/3rdparty/freetype/src/gzip/ftgzip.c b/src/3rdparty/freetype/src/gzip/ftgzip.c index 48da6ff9c7c..ca6a2aabe6d 100644 --- a/src/3rdparty/freetype/src/gzip/ftgzip.c +++ b/src/3rdparty/freetype/src/gzip/ftgzip.c @@ -70,10 +70,9 @@ /* so that configuration with `FT_CONFIG_OPTION_SYSTEM_ZLIB' might */ /* include the wrong `zconf.h' file, leading to errors. */ -#if defined( __GNUC__ ) || defined( __clang__ ) #define ZEXPORT -#define ZEXTERN static -#endif + /* prevent zlib functions from being visible outside their object files */ +#define ZEXTERN static #define HAVE_MEMCPY 1 #define Z_SOLO 1 diff --git a/src/3rdparty/freetype/src/gzip/rules.mk b/src/3rdparty/freetype/src/gzip/rules.mk index 6feb6f51ce7..050e14705c0 100644 --- a/src/3rdparty/freetype/src/gzip/rules.mk +++ b/src/3rdparty/freetype/src/gzip/rules.mk @@ -43,7 +43,6 @@ GZIP_DRV_SRCS := $(GZIP_DIR)/adler32.c \ $(GZIP_DIR)/crc32.c \ $(GZIP_DIR)/crc32.h \ $(GZIP_DIR)/ftzconf.h \ - $(GZIP_DIR)/infback.c \ $(GZIP_DIR)/inffast.c \ $(GZIP_DIR)/inffast.h \ $(GZIP_DIR)/inffixed.h \ diff --git a/src/3rdparty/freetype/src/pcf/pcfdrivr.c b/src/3rdparty/freetype/src/pcf/pcfdrivr.c index bfa6eacca4c..f1dba024042 100644 --- a/src/3rdparty/freetype/src/pcf/pcfdrivr.c +++ b/src/3rdparty/freetype/src/pcf/pcfdrivr.c @@ -75,36 +75,36 @@ THE SOFTWARE. FT_CALLBACK_DEF( FT_Error ) - pcf_cmap_init( FT_CMap pcfcmap, /* PCF_CMap */ + pcf_cmap_init( FT_CMap cmap, /* PCF_CMap */ FT_Pointer init_data ) { - PCF_CMap cmap = (PCF_CMap)pcfcmap; - PCF_Face face = (PCF_Face)FT_CMAP_FACE( pcfcmap ); + PCF_CMap pcfcmap = (PCF_CMap)cmap; + PCF_Face face = (PCF_Face)FT_CMAP_FACE( cmap ); FT_UNUSED( init_data ); - cmap->enc = &face->enc; + pcfcmap->enc = &face->enc; return FT_Err_Ok; } FT_CALLBACK_DEF( void ) - pcf_cmap_done( FT_CMap pcfcmap ) /* PCF_CMap */ + pcf_cmap_done( FT_CMap cmap ) /* PCF_CMap */ { - PCF_CMap cmap = (PCF_CMap)pcfcmap; + PCF_CMap pcfcmap = (PCF_CMap)cmap; - cmap->enc = NULL; + pcfcmap->enc = NULL; } FT_CALLBACK_DEF( FT_UInt ) - pcf_cmap_char_index( FT_CMap pcfcmap, /* PCF_CMap */ + pcf_cmap_char_index( FT_CMap cmap, /* PCF_CMap */ FT_UInt32 charcode ) { - PCF_Enc enc = ( (PCF_CMap)pcfcmap )->enc; + PCF_Enc enc = ( (PCF_CMap)cmap )->enc; FT_UInt32 i = ( charcode >> 8 ) - enc->firstRow; FT_UInt32 j = ( charcode & 0xFF ) - enc->firstCol; @@ -121,10 +121,10 @@ THE SOFTWARE. FT_CALLBACK_DEF( FT_UInt ) - pcf_cmap_char_next( FT_CMap pcfcmap, /* PCF_CMap */ + pcf_cmap_char_next( FT_CMap cmap, /* PCF_CMap */ FT_UInt32 *acharcode ) { - PCF_Enc enc = ( (PCF_CMap)pcfcmap )->enc; + PCF_Enc enc = ( (PCF_CMap)cmap )->enc; FT_UInt32 charcode = *acharcode + 1; FT_UInt32 i = ( charcode >> 8 ) - enc->firstRow; @@ -170,9 +170,9 @@ THE SOFTWARE. FT_CALLBACK_DEF( void ) - PCF_Face_Done( FT_Face pcfface ) /* PCF_Face */ + PCF_Face_Done( FT_Face face ) /* PCF_Face */ { - PCF_Face face = (PCF_Face)pcfface; + PCF_Face pcfface = (PCF_Face)face; FT_Memory memory; @@ -181,18 +181,18 @@ THE SOFTWARE. memory = FT_FACE_MEMORY( face ); - FT_FREE( face->metrics ); - FT_FREE( face->enc.offset ); + FT_FREE( pcfface->metrics ); + FT_FREE( pcfface->enc.offset ); /* free properties */ - if ( face->properties ) + if ( pcfface->properties ) { FT_Int i; - for ( i = 0; i < face->nprops; i++ ) + for ( i = 0; i < pcfface->nprops; i++ ) { - PCF_Property prop = &face->properties[i]; + PCF_Property prop = &pcfface->properties[i]; if ( prop ) @@ -203,33 +203,33 @@ THE SOFTWARE. } } - FT_FREE( face->properties ); + FT_FREE( pcfface->properties ); } - FT_FREE( face->toc.tables ); - FT_FREE( pcfface->family_name ); - FT_FREE( pcfface->style_name ); - FT_FREE( pcfface->available_sizes ); - FT_FREE( face->charset_encoding ); - FT_FREE( face->charset_registry ); + FT_FREE( pcfface->toc.tables ); + FT_FREE( face->family_name ); + FT_FREE( face->style_name ); + FT_FREE( face->available_sizes ); + FT_FREE( pcfface->charset_encoding ); + FT_FREE( pcfface->charset_registry ); /* close compressed stream if any */ - if ( pcfface->stream == &face->comp_stream ) + if ( face->stream == &pcfface->comp_stream ) { - FT_Stream_Close( &face->comp_stream ); - pcfface->stream = face->comp_source; + FT_Stream_Close( &pcfface->comp_stream ); + face->stream = pcfface->comp_source; } } FT_CALLBACK_DEF( FT_Error ) PCF_Face_Init( FT_Stream stream, - FT_Face pcfface, /* PCF_Face */ + FT_Face face, /* PCF_Face */ FT_Int face_index, FT_Int num_params, FT_Parameter* params ) { - PCF_Face face = (PCF_Face)pcfface; + PCF_Face pcfface = (PCF_Face)face; FT_Error error; FT_UNUSED( num_params ); @@ -238,10 +238,10 @@ THE SOFTWARE. FT_TRACE2(( "PCF driver\n" )); - error = pcf_load_font( stream, face, face_index ); + error = pcf_load_font( stream, pcfface, face_index ); if ( error ) { - PCF_Face_Done( pcfface ); + PCF_Face_Done( face ); #if defined( FT_CONFIG_OPTION_USE_ZLIB ) || \ defined( FT_CONFIG_OPTION_USE_LZW ) || \ @@ -254,7 +254,7 @@ THE SOFTWARE. /* this didn't work, try gzip support! */ FT_TRACE2(( " ... try gzip stream\n" )); - error2 = FT_Stream_OpenGzip( &face->comp_stream, stream ); + error2 = FT_Stream_OpenGzip( &pcfface->comp_stream, stream ); if ( FT_ERR_EQ( error2, Unimplemented_Feature ) ) goto Fail; @@ -270,7 +270,7 @@ THE SOFTWARE. /* this didn't work, try LZW support! */ FT_TRACE2(( " ... try LZW stream\n" )); - error3 = FT_Stream_OpenLZW( &face->comp_stream, stream ); + error3 = FT_Stream_OpenLZW( &pcfface->comp_stream, stream ); if ( FT_ERR_EQ( error3, Unimplemented_Feature ) ) goto Fail; @@ -286,7 +286,7 @@ THE SOFTWARE. /* this didn't work, try Bzip2 support! */ FT_TRACE2(( " ... try Bzip2 stream\n" )); - error4 = FT_Stream_OpenBzip2( &face->comp_stream, stream ); + error4 = FT_Stream_OpenBzip2( &pcfface->comp_stream, stream ); if ( FT_ERR_EQ( error4, Unimplemented_Feature ) ) goto Fail; @@ -297,12 +297,12 @@ THE SOFTWARE. if ( error ) goto Fail; - face->comp_source = stream; - pcfface->stream = &face->comp_stream; + pcfface->comp_source = stream; + face->stream = &pcfface->comp_stream; - stream = pcfface->stream; + stream = face->stream; - error = pcf_load_font( stream, face, face_index ); + error = pcf_load_font( stream, pcfface, face_index ); if ( error ) goto Fail; @@ -326,14 +326,14 @@ THE SOFTWARE. else if ( face_index > 0 && ( face_index & 0xFFFF ) > 0 ) { FT_ERROR(( "PCF_Face_Init: invalid face index\n" )); - PCF_Face_Done( pcfface ); + PCF_Face_Done( face ); return FT_THROW( Invalid_Argument ); } /* set up charmap */ { - FT_String *charset_registry = face->charset_registry; - FT_String *charset_encoding = face->charset_encoding; + FT_String *charset_registry = pcfface->charset_registry; + FT_String *charset_encoding = pcfface->charset_encoding; FT_Bool unicode_charmap = 0; @@ -349,13 +349,13 @@ THE SOFTWARE. ( s[2] == 'o' || s[2] == 'O' ) ) { s += 3; - if ( !ft_strcmp( s, "10646" ) || - ( !ft_strcmp( s, "8859" ) && - !ft_strcmp( face->charset_encoding, "1" ) ) ) + if ( !ft_strcmp( s, "10646" ) || + ( !ft_strcmp( s, "8859" ) && + !ft_strcmp( pcfface->charset_encoding, "1" ) ) ) unicode_charmap = 1; /* another name for ASCII */ - else if ( !ft_strcmp( s, "646.1991" ) && - !ft_strcmp( face->charset_encoding, "IRV" ) ) + else if ( !ft_strcmp( s, "646.1991" ) && + !ft_strcmp( pcfface->charset_encoding, "IRV" ) ) unicode_charmap = 1; } } @@ -364,7 +364,7 @@ THE SOFTWARE. FT_CharMapRec charmap; - charmap.face = FT_FACE( face ); + charmap.face = face; charmap.encoding = FT_ENCODING_NONE; /* initial platform/encoding should indicate unset status? */ charmap.platform_id = TT_PLATFORM_APPLE_UNICODE; @@ -386,7 +386,7 @@ THE SOFTWARE. Fail: FT_TRACE2(( " not a PCF file\n" )); - PCF_Face_Done( pcfface ); + PCF_Face_Done( face ); error = FT_THROW( Unknown_File_Format ); /* error */ goto Exit; } @@ -569,15 +569,16 @@ THE SOFTWARE. * */ - static FT_Error - pcf_get_bdf_property( PCF_Face face, + FT_CALLBACK_DEF( FT_Error ) + pcf_get_bdf_property( FT_Face face, /* PCF_Face */ const char* prop_name, BDF_PropertyRec *aproperty ) { + PCF_Face pcfface = (PCF_Face)face; PCF_Property prop; - prop = pcf_find_property( face, prop_name ); + prop = pcf_find_property( pcfface, prop_name ); if ( prop ) { if ( prop->isString ) @@ -611,13 +612,16 @@ THE SOFTWARE. } - static FT_Error - pcf_get_charset_id( PCF_Face face, + FT_CALLBACK_DEF( FT_Error ) + pcf_get_charset_id( FT_Face face, /* PCF_Face */ const char* *acharset_encoding, const char* *acharset_registry ) { - *acharset_encoding = face->charset_encoding; - *acharset_registry = face->charset_registry; + PCF_Face pcfface = (PCF_Face)face; + + + *acharset_encoding = pcfface->charset_encoding; + *acharset_registry = pcfface->charset_registry; return FT_Err_Ok; } @@ -634,7 +638,7 @@ THE SOFTWARE. * PROPERTY SERVICE * */ - static FT_Error + FT_CALLBACK_DEF( FT_Error ) pcf_property_set( FT_Module module, /* PCF_Driver */ const char* property_name, const void* value, @@ -695,10 +699,10 @@ THE SOFTWARE. } - static FT_Error + FT_CALLBACK_DEF( FT_Error ) pcf_property_get( FT_Module module, /* PCF_Driver */ const char* property_name, - const void* value ) + void* value ) { #ifdef PCF_CONFIG_OPTION_LONG_FAMILY_NAMES diff --git a/src/3rdparty/freetype/src/pfr/pfrcmap.c b/src/3rdparty/freetype/src/pfr/pfrcmap.c index 312a9ffe174..08fe41d54eb 100644 --- a/src/3rdparty/freetype/src/pfr/pfrcmap.c +++ b/src/3rdparty/freetype/src/pfr/pfrcmap.c @@ -24,17 +24,18 @@ FT_CALLBACK_DEF( FT_Error ) - pfr_cmap_init( PFR_CMap cmap, + pfr_cmap_init( FT_CMap cmap, /* PFR_CMap */ FT_Pointer pointer ) { - FT_Error error = FT_Err_Ok; - PFR_Face face = (PFR_Face)FT_CMAP_FACE( cmap ); + PFR_CMap pfrcmap = (PFR_CMap)cmap; + FT_Error error = FT_Err_Ok; + PFR_Face face = (PFR_Face)FT_CMAP_FACE( cmap ); FT_UNUSED( pointer ); - cmap->num_chars = face->phy_font.num_chars; - cmap->chars = face->phy_font.chars; + pfrcmap->num_chars = face->phy_font.num_chars; + pfrcmap->chars = face->phy_font.chars; /* just for safety, check that the character entries are correctly */ /* sorted in increasing character code order */ @@ -42,9 +43,9 @@ FT_UInt n; - for ( n = 1; n < cmap->num_chars; n++ ) + for ( n = 1; n < pfrcmap->num_chars; n++ ) { - if ( cmap->chars[n - 1].char_code >= cmap->chars[n].char_code ) + if ( pfrcmap->chars[n - 1].char_code >= pfrcmap->chars[n].char_code ) { error = FT_THROW( Invalid_Table ); goto Exit; @@ -58,26 +59,30 @@ FT_CALLBACK_DEF( void ) - pfr_cmap_done( PFR_CMap cmap ) + pfr_cmap_done( FT_CMap cmap ) /* PFR_CMap */ { - cmap->chars = NULL; - cmap->num_chars = 0; + PFR_CMap pfrcmap = (PFR_CMap)cmap; + + + pfrcmap->chars = NULL; + pfrcmap->num_chars = 0; } FT_CALLBACK_DEF( FT_UInt ) - pfr_cmap_char_index( PFR_CMap cmap, + pfr_cmap_char_index( FT_CMap cmap, /* PFR_CMap */ FT_UInt32 char_code ) { - FT_UInt min = 0; - FT_UInt max = cmap->num_chars; - FT_UInt mid = min + ( max - min ) / 2; + PFR_CMap pfrcmap = (PFR_CMap)cmap; + FT_UInt min = 0; + FT_UInt max = pfrcmap->num_chars; + FT_UInt mid = min + ( max - min ) / 2; PFR_Char gchar; while ( min < max ) { - gchar = cmap->chars + mid; + gchar = pfrcmap->chars + mid; if ( gchar->char_code == char_code ) return mid + 1; @@ -96,10 +101,11 @@ } - FT_CALLBACK_DEF( FT_UInt32 ) - pfr_cmap_char_next( PFR_CMap cmap, + FT_CALLBACK_DEF( FT_UInt ) + pfr_cmap_char_next( FT_CMap cmap, /* PFR_CMap */ FT_UInt32 *pchar_code ) { + PFR_CMap pfrcmap = (PFR_CMap)cmap; FT_UInt result = 0; FT_UInt32 char_code = *pchar_code + 1; @@ -107,14 +113,14 @@ Restart: { FT_UInt min = 0; - FT_UInt max = cmap->num_chars; + FT_UInt max = pfrcmap->num_chars; FT_UInt mid = min + ( max - min ) / 2; PFR_Char gchar; while ( min < max ) { - gchar = cmap->chars + mid; + gchar = pfrcmap->chars + mid; if ( gchar->char_code == char_code ) { @@ -143,9 +149,9 @@ /* we didn't find it, but we have a pair just above it */ char_code = 0; - if ( min < cmap->num_chars ) + if ( min < pfrcmap->num_chars ) { - gchar = cmap->chars + min; + gchar = pfrcmap->chars + min; result = min; if ( result != 0 ) { diff --git a/src/3rdparty/freetype/src/pfr/pfrdrivr.c b/src/3rdparty/freetype/src/pfr/pfrdrivr.c index 78c6c6882cd..0048f52411c 100644 --- a/src/3rdparty/freetype/src/pfr/pfrdrivr.c +++ b/src/3rdparty/freetype/src/pfr/pfrdrivr.c @@ -27,16 +27,16 @@ FT_CALLBACK_DEF( FT_Error ) - pfr_get_kerning( FT_Face pfrface, /* PFR_Face */ + pfr_get_kerning( FT_Face face, /* PFR_Face */ FT_UInt left, FT_UInt right, FT_Vector *avector ) { - PFR_Face face = (PFR_Face)pfrface; - PFR_PhyFont phys = &face->phy_font; + PFR_Face pfrface = (PFR_Face)face; + PFR_PhyFont phys = &pfrface->phy_font; - (void)pfr_face_get_kerning( pfrface, left, right, avector ); + (void)pfr_face_get_kerning( face, left, right, avector ); /* convert from metrics to outline units when necessary */ if ( phys->outline_resolution != phys->metrics_resolution ) @@ -62,12 +62,12 @@ */ FT_CALLBACK_DEF( FT_Error ) - pfr_get_advance( FT_Face pfrface, /* PFR_Face */ + pfr_get_advance( FT_Face face, /* PFR_Face */ FT_UInt gindex, FT_Pos *anadvance ) { - PFR_Face face = (PFR_Face)pfrface; - FT_Error error = FT_ERR( Invalid_Argument ); + PFR_Face pfrface = (PFR_Face)face; + FT_Error error = FT_ERR( Invalid_Argument ); *anadvance = 0; @@ -77,9 +77,9 @@ gindex--; - if ( face ) + if ( pfrface ) { - PFR_PhyFont phys = &face->phy_font; + PFR_PhyFont phys = &pfrface->phy_font; if ( gindex < phys->num_chars ) @@ -95,16 +95,16 @@ FT_CALLBACK_DEF( FT_Error ) - pfr_get_metrics( FT_Face pfrface, /* PFR_Face */ + pfr_get_metrics( FT_Face face, /* PFR_Face */ FT_UInt *anoutline_resolution, FT_UInt *ametrics_resolution, FT_Fixed *ametrics_x_scale, FT_Fixed *ametrics_y_scale ) { - PFR_Face face = (PFR_Face)pfrface; - PFR_PhyFont phys = &face->phy_font; + PFR_Face pfrface = (PFR_Face)face; + PFR_PhyFont phys = &pfrface->phy_font; FT_Fixed x_scale, y_scale; - FT_Size size = face->root.size; + FT_Size size = pfrface->root.size; if ( anoutline_resolution ) diff --git a/src/3rdparty/freetype/src/pfr/pfrgload.c b/src/3rdparty/freetype/src/pfr/pfrgload.c index 14f2ec37780..48cf27ec809 100644 --- a/src/3rdparty/freetype/src/pfr/pfrgload.c +++ b/src/3rdparty/freetype/src/pfr/pfrgload.c @@ -560,8 +560,7 @@ FT_Byte* limit ) { FT_Error error = FT_Err_Ok; - FT_GlyphLoader loader = glyph->loader; - FT_Memory memory = loader->memory; + FT_Memory memory = glyph->loader->memory; PFR_SubGlyph subglyph; FT_UInt flags, i, count, org_count; FT_Int x_pos, y_pos; diff --git a/src/3rdparty/freetype/src/pfr/pfrload.c b/src/3rdparty/freetype/src/pfr/pfrload.c index de85ee6aadc..856a5942f5b 100644 --- a/src/3rdparty/freetype/src/pfr/pfrload.c +++ b/src/3rdparty/freetype/src/pfr/pfrload.c @@ -449,15 +449,16 @@ /* load bitmap strikes lists */ FT_CALLBACK_DEF( FT_Error ) - pfr_extra_item_load_bitmap_info( FT_Byte* p, - FT_Byte* limit, - PFR_PhyFont phy_font ) + pfr_extra_item_load_bitmap_info( FT_Byte* p, + FT_Byte* limit, + void* phy_font_ ) { - FT_Memory memory = phy_font->memory; - PFR_Strike strike; - FT_UInt flags0; - FT_UInt n, count, size1; - FT_Error error = FT_Err_Ok; + PFR_PhyFont phy_font = (PFR_PhyFont)phy_font_; + FT_Memory memory = phy_font->memory; + PFR_Strike strike; + FT_UInt flags0; + FT_UInt n, count, size1; + FT_Error error = FT_Err_Ok; PFR_CHECK( 5 ); @@ -549,13 +550,14 @@ * family. */ FT_CALLBACK_DEF( FT_Error ) - pfr_extra_item_load_font_id( FT_Byte* p, - FT_Byte* limit, - PFR_PhyFont phy_font ) + pfr_extra_item_load_font_id( FT_Byte* p, + FT_Byte* limit, + void* phy_font_ ) { - FT_Error error = FT_Err_Ok; - FT_Memory memory = phy_font->memory; - FT_UInt len = (FT_UInt)( limit - p ); + PFR_PhyFont phy_font = (PFR_PhyFont)phy_font_; + FT_Error error = FT_Err_Ok; + FT_Memory memory = phy_font->memory; + FT_UInt len = (FT_UInt)( limit - p ); if ( phy_font->font_id ) @@ -575,14 +577,15 @@ /* load stem snap tables */ FT_CALLBACK_DEF( FT_Error ) - pfr_extra_item_load_stem_snaps( FT_Byte* p, - FT_Byte* limit, - PFR_PhyFont phy_font ) + pfr_extra_item_load_stem_snaps( FT_Byte* p, + FT_Byte* limit, + void* phy_font_ ) { - FT_UInt count, num_vert, num_horz; - FT_Int* snaps = NULL; - FT_Error error = FT_Err_Ok; - FT_Memory memory = phy_font->memory; + PFR_PhyFont phy_font = (PFR_PhyFont)phy_font_; + FT_UInt count, num_vert, num_horz; + FT_Int* snaps = NULL; + FT_Error error = FT_Err_Ok; + FT_Memory memory = phy_font->memory; if ( phy_font->vertical.stem_snaps ) @@ -619,10 +622,11 @@ /* load kerning pair data */ FT_CALLBACK_DEF( FT_Error ) - pfr_extra_item_load_kerning_pairs( FT_Byte* p, - FT_Byte* limit, - PFR_PhyFont phy_font ) + pfr_extra_item_load_kerning_pairs( FT_Byte* p, + FT_Byte* limit, + void* phy_font_ ) { + PFR_PhyFont phy_font = (PFR_PhyFont)phy_font_; PFR_KernItem item = NULL; FT_Error error = FT_Err_Ok; FT_Memory memory = phy_font->memory; @@ -715,10 +719,10 @@ static const PFR_ExtraItemRec pfr_phy_font_extra_items[] = { - { 1, (PFR_ExtraItem_ParseFunc)pfr_extra_item_load_bitmap_info }, - { 2, (PFR_ExtraItem_ParseFunc)pfr_extra_item_load_font_id }, - { 3, (PFR_ExtraItem_ParseFunc)pfr_extra_item_load_stem_snaps }, - { 4, (PFR_ExtraItem_ParseFunc)pfr_extra_item_load_kerning_pairs }, + { 1, pfr_extra_item_load_bitmap_info }, + { 2, pfr_extra_item_load_font_id }, + { 3, pfr_extra_item_load_stem_snaps }, + { 4, pfr_extra_item_load_kerning_pairs }, { 0, NULL } }; diff --git a/src/3rdparty/freetype/src/pfr/pfrobjs.c b/src/3rdparty/freetype/src/pfr/pfrobjs.c index 3db8f0a060e..8ef17c66360 100644 --- a/src/3rdparty/freetype/src/pfr/pfrobjs.c +++ b/src/3rdparty/freetype/src/pfr/pfrobjs.c @@ -50,14 +50,14 @@ if ( !face ) return; - memory = pfrface->driver->root.memory; + memory = pfrface->memory; /* we don't want dangling pointers */ pfrface->family_name = NULL; pfrface->style_name = NULL; /* finalize the physical font record */ - pfr_phy_font_done( &face->phy_font, FT_FACE_MEMORY( face ) ); + pfr_phy_font_done( &face->phy_font, memory ); /* no need to finalize the logical font or the header */ FT_FREE( pfrface->available_sizes ); @@ -214,7 +214,7 @@ FT_UInt n, count = phy_font->num_strikes; FT_Bitmap_Size* size; PFR_Strike strike; - FT_Memory memory = pfrface->stream->memory; + FT_Memory memory = pfrface->memory; if ( FT_QNEW_ARRAY( pfrface->available_sizes, count ) ) diff --git a/src/3rdparty/freetype/src/psaux/afmparse.c b/src/3rdparty/freetype/src/psaux/afmparse.c index 68f95698e65..db08941def7 100644 --- a/src/3rdparty/freetype/src/psaux/afmparse.c +++ b/src/3rdparty/freetype/src/psaux/afmparse.c @@ -1086,7 +1086,7 @@ #else /* T1_CONFIG_OPTION_NO_AFM */ /* ANSI C doesn't like empty source files */ - typedef int _afm_parse_dummy; + typedef int afm_parse_dummy_; #endif /* T1_CONFIG_OPTION_NO_AFM */ diff --git a/src/3rdparty/freetype/src/psaux/t1cmap.c b/src/3rdparty/freetype/src/psaux/t1cmap.c index bf0a393b456..c4bcf599ea3 100644 --- a/src/3rdparty/freetype/src/psaux/t1cmap.c +++ b/src/3rdparty/freetype/src/psaux/t1cmap.c @@ -50,8 +50,11 @@ FT_CALLBACK_DEF( void ) - t1_cmap_std_done( T1_CMapStd cmap ) + t1_cmap_std_done( FT_CMap cmap_ ) /* T1_CMapStd */ { + T1_CMapStd cmap = (T1_CMapStd)cmap_; + + cmap->num_glyphs = 0; cmap->glyph_names = NULL; cmap->sid_to_string = NULL; @@ -60,10 +63,11 @@ FT_CALLBACK_DEF( FT_UInt ) - t1_cmap_std_char_index( T1_CMapStd cmap, - FT_UInt32 char_code ) + t1_cmap_std_char_index( FT_CMap cmap, /* T1_CMapStd */ + FT_UInt32 char_code ) { - FT_UInt result = 0; + T1_CMapStd t1cmap = (T1_CMapStd)cmap; + FT_UInt result = 0; if ( char_code < 256 ) @@ -73,13 +77,13 @@ /* convert character code to Adobe SID string */ - code = cmap->code_to_sid[char_code]; - glyph_name = cmap->sid_to_string( code ); + code = t1cmap->code_to_sid[char_code]; + glyph_name = t1cmap->sid_to_string( code ); /* look for the corresponding glyph name */ - for ( n = 0; n < cmap->num_glyphs; n++ ) + for ( n = 0; n < t1cmap->num_glyphs; n++ ) { - const char* gname = cmap->glyph_names[n]; + const char* gname = t1cmap->glyph_names[n]; if ( gname && gname[0] == glyph_name[0] && @@ -95,9 +99,9 @@ } - FT_CALLBACK_DEF( FT_UInt32 ) - t1_cmap_std_char_next( T1_CMapStd cmap, - FT_UInt32 *pchar_code ) + FT_CALLBACK_DEF( FT_UInt ) + t1_cmap_std_char_next( FT_CMap cmap, + FT_UInt32 *pchar_code ) { FT_UInt result = 0; FT_UInt32 char_code = *pchar_code + 1; @@ -120,13 +124,14 @@ FT_CALLBACK_DEF( FT_Error ) - t1_cmap_standard_init( T1_CMapStd cmap, + t1_cmap_standard_init( FT_CMap cmap, /* T1_CMapStd */ FT_Pointer pointer ) { + T1_CMapStd t1cmap = (T1_CMapStd)cmap; FT_UNUSED( pointer ); - t1_cmap_std_init( cmap, 0 ); + t1_cmap_std_init( t1cmap, 0 ); return 0; } @@ -150,13 +155,14 @@ FT_CALLBACK_DEF( FT_Error ) - t1_cmap_expert_init( T1_CMapStd cmap, + t1_cmap_expert_init( FT_CMap cmap, /* T1_CMapStd */ FT_Pointer pointer ) { + T1_CMapStd t1cmap = (T1_CMapStd)cmap; FT_UNUSED( pointer ); - t1_cmap_std_init( cmap, 1 ); + t1_cmap_std_init( t1cmap, 1 ); return 0; } @@ -188,20 +194,21 @@ FT_CALLBACK_DEF( FT_Error ) - t1_cmap_custom_init( T1_CMapCustom cmap, - FT_Pointer pointer ) + t1_cmap_custom_init( FT_CMap cmap, /* T1_CMapCustom */ + FT_Pointer pointer ) { - T1_Face face = (T1_Face)FT_CMAP_FACE( cmap ); - T1_Encoding encoding = &face->type1.encoding; + T1_CMapCustom t1cmap = (T1_CMapCustom)cmap; + T1_Face face = (T1_Face)FT_CMAP_FACE( cmap ); + T1_Encoding encoding = &face->type1.encoding; FT_UNUSED( pointer ); - cmap->first = (FT_UInt)encoding->code_first; - cmap->count = (FT_UInt)encoding->code_last - cmap->first; - cmap->indices = encoding->char_index; + t1cmap->first = (FT_UInt)encoding->code_first; + t1cmap->count = (FT_UInt)encoding->code_last - t1cmap->first; + t1cmap->indices = encoding->char_index; - FT_ASSERT( cmap->indices ); + FT_ASSERT( t1cmap->indices ); FT_ASSERT( encoding->code_first <= encoding->code_last ); return 0; @@ -209,45 +216,50 @@ FT_CALLBACK_DEF( void ) - t1_cmap_custom_done( T1_CMapCustom cmap ) + t1_cmap_custom_done( FT_CMap cmap ) /* T1_CMapCustom */ { - cmap->indices = NULL; - cmap->first = 0; - cmap->count = 0; + T1_CMapCustom t1cmap = (T1_CMapCustom)cmap; + + + t1cmap->indices = NULL; + t1cmap->first = 0; + t1cmap->count = 0; } FT_CALLBACK_DEF( FT_UInt ) - t1_cmap_custom_char_index( T1_CMapCustom cmap, - FT_UInt32 char_code ) + t1_cmap_custom_char_index( FT_CMap cmap, /* T1_CMapCustom */ + FT_UInt32 char_code ) { - FT_UInt result = 0; + T1_CMapCustom t1cmap = (T1_CMapCustom)cmap; + FT_UInt result = 0; - if ( ( char_code >= cmap->first ) && - ( char_code < ( cmap->first + cmap->count ) ) ) - result = cmap->indices[char_code]; + if ( char_code >= t1cmap->first && + char_code < ( t1cmap->first + t1cmap->count ) ) + result = t1cmap->indices[char_code]; return result; } - FT_CALLBACK_DEF( FT_UInt32 ) - t1_cmap_custom_char_next( T1_CMapCustom cmap, - FT_UInt32 *pchar_code ) + FT_CALLBACK_DEF( FT_UInt ) + t1_cmap_custom_char_next( FT_CMap cmap, /* T1_CMapCustom */ + FT_UInt32 *pchar_code ) { - FT_UInt result = 0; - FT_UInt32 char_code = *pchar_code; + T1_CMapCustom t1cmap = (T1_CMapCustom)cmap; + FT_UInt result = 0; + FT_UInt32 char_code = *pchar_code; char_code++; - if ( char_code < cmap->first ) - char_code = cmap->first; + if ( char_code < t1cmap->first ) + char_code = t1cmap->first; - for ( ; char_code < ( cmap->first + cmap->count ); char_code++ ) + for ( ; char_code < ( t1cmap->first + t1cmap->count ); char_code++ ) { - result = cmap->indices[char_code]; + result = t1cmap->indices[char_code]; if ( result != 0 ) goto Exit; } @@ -287,20 +299,24 @@ /*************************************************************************/ FT_CALLBACK_DEF( const char * ) - psaux_get_glyph_name( T1_Face face, + psaux_get_glyph_name( void* face_, FT_UInt idx ) { + T1_Face face = (T1_Face)face_; + + return face->type1.glyph_names[idx]; } FT_CALLBACK_DEF( FT_Error ) - t1_cmap_unicode_init( PS_Unicodes unicodes, - FT_Pointer pointer ) + t1_cmap_unicode_init( FT_CMap cmap, /* PS_Unicodes */ + FT_Pointer pointer ) { - T1_Face face = (T1_Face)FT_CMAP_FACE( unicodes ); - FT_Memory memory = FT_FACE_MEMORY( face ); - FT_Service_PsCMaps psnames = (FT_Service_PsCMaps)face->psnames; + PS_Unicodes unicodes = (PS_Unicodes)cmap; + T1_Face face = (T1_Face)FT_CMAP_FACE( cmap ); + FT_Memory memory = FT_FACE_MEMORY( face ); + FT_Service_PsCMaps psnames = (FT_Service_PsCMaps)face->psnames; FT_UNUSED( pointer ); @@ -311,17 +327,18 @@ return psnames->unicodes_init( memory, unicodes, (FT_UInt)face->type1.num_glyphs, - (PS_GetGlyphNameFunc)&psaux_get_glyph_name, + &psaux_get_glyph_name, (PS_FreeGlyphNameFunc)NULL, (FT_Pointer)face ); } FT_CALLBACK_DEF( void ) - t1_cmap_unicode_done( PS_Unicodes unicodes ) + t1_cmap_unicode_done( FT_CMap cmap ) /* PS_Unicodes */ { - FT_Face face = FT_CMAP_FACE( unicodes ); - FT_Memory memory = FT_FACE_MEMORY( face ); + PS_Unicodes unicodes = (PS_Unicodes)cmap; + FT_Face face = FT_CMAP_FACE( cmap ); + FT_Memory memory = FT_FACE_MEMORY( face ); FT_FREE( unicodes->maps ); @@ -330,23 +347,25 @@ FT_CALLBACK_DEF( FT_UInt ) - t1_cmap_unicode_char_index( PS_Unicodes unicodes, - FT_UInt32 char_code ) + t1_cmap_unicode_char_index( FT_CMap cmap, /* PS_Unicodes */ + FT_UInt32 char_code ) { - T1_Face face = (T1_Face)FT_CMAP_FACE( unicodes ); - FT_Service_PsCMaps psnames = (FT_Service_PsCMaps)face->psnames; + PS_Unicodes unicodes = (PS_Unicodes)cmap; + T1_Face face = (T1_Face)FT_CMAP_FACE( cmap ); + FT_Service_PsCMaps psnames = (FT_Service_PsCMaps)face->psnames; return psnames->unicodes_char_index( unicodes, char_code ); } - FT_CALLBACK_DEF( FT_UInt32 ) - t1_cmap_unicode_char_next( PS_Unicodes unicodes, - FT_UInt32 *pchar_code ) + FT_CALLBACK_DEF( FT_UInt ) + t1_cmap_unicode_char_next( FT_CMap cmap, /* PS_Unicodes */ + FT_UInt32 *pchar_code ) { - T1_Face face = (T1_Face)FT_CMAP_FACE( unicodes ); - FT_Service_PsCMaps psnames = (FT_Service_PsCMaps)face->psnames; + PS_Unicodes unicodes = (PS_Unicodes)cmap; + T1_Face face = (T1_Face)FT_CMAP_FACE( cmap ); + FT_Service_PsCMaps psnames = (FT_Service_PsCMaps)face->psnames; return psnames->unicodes_char_next( unicodes, pchar_code ); diff --git a/src/3rdparty/freetype/src/pshinter/pshalgo.c b/src/3rdparty/freetype/src/pshinter/pshalgo.c index a7f321291a9..4f622e1e440 100644 --- a/src/3rdparty/freetype/src/pshinter/pshalgo.c +++ b/src/3rdparty/freetype/src/pshinter/pshalgo.c @@ -516,7 +516,7 @@ if ( !psh_hint_is_fitted( parent ) ) psh_hint_align( parent, globals, dimension, glyph ); - /* keep original relation between hints, this is, use the */ + /* keep original relation between hints, that is, use the */ /* scaled distance between the centers of the hints to */ /* compute the new position */ par_org_center = parent->org_pos + ( parent->org_len >> 1 ); diff --git a/src/3rdparty/freetype/src/pshinter/pshmod.c b/src/3rdparty/freetype/src/pshinter/pshmod.c index a12e4856601..974a99e0186 100644 --- a/src/3rdparty/freetype/src/pshinter/pshmod.c +++ b/src/3rdparty/freetype/src/pshinter/pshmod.c @@ -37,8 +37,11 @@ /* finalize module */ FT_CALLBACK_DEF( void ) - ps_hinter_done( PS_Hinter_Module module ) + ps_hinter_done( FT_Module module_ ) /* PS_Hinter_Module */ { + PS_Hinter_Module module = (PS_Hinter_Module)module_; + + module->t1_funcs.hints = NULL; module->t2_funcs.hints = NULL; @@ -48,8 +51,10 @@ /* initialize module, create hints recorder and the interface */ FT_CALLBACK_DEF( FT_Error ) - ps_hinter_init( PS_Hinter_Module module ) + ps_hinter_init( FT_Module module_ ) /* PS_Hinter_Module */ { + PS_Hinter_Module module = (PS_Hinter_Module)module_; + FT_Memory memory = module->root.memory; void* ph = &module->ps_hints; diff --git a/src/3rdparty/freetype/src/pshinter/pshrec.c b/src/3rdparty/freetype/src/pshinter/pshrec.c index 58c8cf1b486..680e6d01358 100644 --- a/src/3rdparty/freetype/src/pshinter/pshrec.c +++ b/src/3rdparty/freetype/src/pshinter/pshrec.c @@ -851,10 +851,11 @@ /* add one Type1 counter stem to the current hints table */ static void - ps_hints_t1stem3( PS_Hints hints, + ps_hints_t1stem3( T1_Hints hints_, /* PS_Hints */ FT_UInt dimension, FT_Fixed* stems ) { + PS_Hints hints = (PS_Hints)hints_; FT_Error error = FT_Err_Ok; @@ -914,9 +915,10 @@ /* reset hints (only with Type 1 hints) */ static void - ps_hints_t1reset( PS_Hints hints, + ps_hints_t1reset( T1_Hints hints_, /* PS_Hints */ FT_UInt end_point ) { + PS_Hints hints = (PS_Hints)hints_; FT_Error error = FT_Err_Ok; @@ -953,11 +955,12 @@ /* Type2 "hintmask" operator, add a new hintmask to each direction */ static void - ps_hints_t2mask( PS_Hints hints, + ps_hints_t2mask( T2_Hints hints_, /* PS_Hints */ FT_UInt end_point, FT_UInt bit_count, const FT_Byte* bytes ) { + PS_Hints hints = (PS_Hints)hints_; FT_Error error; @@ -999,10 +1002,11 @@ static void - ps_hints_t2counter( PS_Hints hints, + ps_hints_t2counter( T2_Hints hints_, /* PS_Hints */ FT_UInt bit_count, const FT_Byte* bytes ) { + PS_Hints hints = (PS_Hints)hints_; FT_Error error; @@ -1087,6 +1091,13 @@ ps_hints_open( (PS_Hints)hints, PS_HINT_TYPE_1 ); } + static FT_Error + t1_hints_close( T1_Hints hints, + FT_UInt end_point ) + { + return ps_hints_close( (PS_Hints)hints, end_point ); + } + static void t1_hints_stem( T1_Hints hints, FT_UInt dimension, @@ -1102,17 +1113,27 @@ } + static FT_Error + t1_hints_apply( T1_Hints hints, + FT_Outline* outline, + PSH_Globals globals, + FT_Render_Mode hint_mode ) + { + return ps_hints_apply( (PS_Hints)hints, outline, globals, hint_mode ); + } + + FT_LOCAL_DEF( void ) t1_hints_funcs_init( T1_Hints_FuncsRec* funcs ) { FT_ZERO( funcs ); funcs->open = (T1_Hints_OpenFunc) t1_hints_open; - funcs->close = (T1_Hints_CloseFunc) ps_hints_close; + funcs->close = (T1_Hints_CloseFunc) t1_hints_close; funcs->stem = (T1_Hints_SetStemFunc) t1_hints_stem; funcs->stem3 = (T1_Hints_SetStem3Func)ps_hints_t1stem3; funcs->reset = (T1_Hints_ResetFunc) ps_hints_t1reset; - funcs->apply = (T1_Hints_ApplyFunc) ps_hints_apply; + funcs->apply = (T1_Hints_ApplyFunc) t1_hints_apply; } @@ -1131,6 +1152,14 @@ } + static FT_Error + t2_hints_close( T2_Hints hints, + FT_UInt end_point ) + { + return ps_hints_close( (PS_Hints)hints, end_point ); + } + + static void t2_hints_stems( T2_Hints hints, FT_UInt dimension, @@ -1168,17 +1197,27 @@ } + static FT_Error + t2_hints_apply( T2_Hints hints, + FT_Outline* outline, + PSH_Globals globals, + FT_Render_Mode hint_mode ) + { + return ps_hints_apply( (PS_Hints)hints, outline, globals, hint_mode ); + } + + FT_LOCAL_DEF( void ) t2_hints_funcs_init( T2_Hints_FuncsRec* funcs ) { FT_ZERO( funcs ); - funcs->open = (T2_Hints_OpenFunc) t2_hints_open; - funcs->close = (T2_Hints_CloseFunc) ps_hints_close; - funcs->stems = (T2_Hints_StemsFunc) t2_hints_stems; - funcs->hintmask= (T2_Hints_MaskFunc) ps_hints_t2mask; - funcs->counter = (T2_Hints_CounterFunc)ps_hints_t2counter; - funcs->apply = (T2_Hints_ApplyFunc) ps_hints_apply; + funcs->open = (T2_Hints_OpenFunc) t2_hints_open; + funcs->close = (T2_Hints_CloseFunc) t2_hints_close; + funcs->stems = (T2_Hints_StemsFunc) t2_hints_stems; + funcs->hintmask = (T2_Hints_MaskFunc) ps_hints_t2mask; + funcs->counter = (T2_Hints_CounterFunc)ps_hints_t2counter; + funcs->apply = (T2_Hints_ApplyFunc) t2_hints_apply; } diff --git a/src/3rdparty/freetype/src/psnames/psmodule.c b/src/3rdparty/freetype/src/psnames/psmodule.c index db454e558eb..8203a0465d2 100644 --- a/src/3rdparty/freetype/src/psnames/psmodule.c +++ b/src/3rdparty/freetype/src/psnames/psmodule.c @@ -57,7 +57,7 @@ /* the name, as in `A.swash' or `e.final'; in this case, the */ /* VARIANT_BIT is set in the return value. */ /* */ - static FT_UInt32 + FT_CALLBACK_DEF( FT_UInt32 ) ps_unicode_value( const char* glyph_name ) { /* If the name begins with `uni', then the glyph name may be a */ @@ -309,7 +309,7 @@ /* Build a table that maps Unicode values to glyph indices. */ - static FT_Error + FT_CALLBACK_DEF( FT_Error ) ps_unicodes_init( FT_Memory memory, PS_Unicodes table, FT_UInt num_glyphs, @@ -408,7 +408,7 @@ } - static FT_UInt + FT_CALLBACK_DEF( FT_UInt ) ps_unicodes_char_index( PS_Unicodes table, FT_UInt32 unicode ) { @@ -453,7 +453,7 @@ } - static FT_UInt32 + FT_CALLBACK_DEF( FT_UInt ) ps_unicodes_char_next( PS_Unicodes table, FT_UInt32 *unicode ) { @@ -518,7 +518,7 @@ #endif /* FT_CONFIG_OPTION_ADOBE_GLYPH_LIST */ - static const char* + FT_CALLBACK_DEF( const char* ) ps_get_macintosh_name( FT_UInt name_index ) { if ( name_index >= FT_NUM_MAC_NAMES ) @@ -528,7 +528,7 @@ } - static const char* + FT_CALLBACK_DEF( const char* ) ps_get_standard_strings( FT_UInt sid ) { if ( sid >= FT_NUM_SID_NAMES ) @@ -543,13 +543,13 @@ FT_DEFINE_SERVICE_PSCMAPSREC( pscmaps_interface, - (PS_Unicode_ValueFunc) ps_unicode_value, /* unicode_value */ - (PS_Unicodes_InitFunc) ps_unicodes_init, /* unicodes_init */ - (PS_Unicodes_CharIndexFunc)ps_unicodes_char_index, /* unicodes_char_index */ - (PS_Unicodes_CharNextFunc) ps_unicodes_char_next, /* unicodes_char_next */ + ps_unicode_value, /* PS_Unicode_ValueFunc unicode_value */ + ps_unicodes_init, /* PS_Unicodes_InitFunc unicodes_init */ + ps_unicodes_char_index, /* PS_Unicodes_CharIndexFunc unicodes_char_index */ + ps_unicodes_char_next, /* PS_Unicodes_CharNextFunc unicodes_char_next */ - (PS_Macintosh_NameFunc) ps_get_macintosh_name, /* macintosh_name */ - (PS_Adobe_Std_StringsFunc) ps_get_standard_strings, /* adobe_std_strings */ + ps_get_macintosh_name, /* PS_Macintosh_NameFunc macintosh_name */ + ps_get_standard_strings, /* PS_Adobe_Std_StringsFunc adobe_std_strings */ t1_standard_encoding, /* adobe_std_encoding */ t1_expert_encoding /* adobe_expert_encoding */ @@ -560,13 +560,13 @@ FT_DEFINE_SERVICE_PSCMAPSREC( pscmaps_interface, - NULL, /* unicode_value */ - NULL, /* unicodes_init */ - NULL, /* unicodes_char_index */ - NULL, /* unicodes_char_next */ + NULL, /* PS_Unicode_ValueFunc unicode_value */ + NULL, /* PS_Unicodes_InitFunc unicodes_init */ + NULL, /* PS_Unicodes_CharIndexFunc unicodes_char_index */ + NULL, /* PS_Unicodes_CharNextFunc unicodes_char_next */ - (PS_Macintosh_NameFunc) ps_get_macintosh_name, /* macintosh_name */ - (PS_Adobe_Std_StringsFunc) ps_get_standard_strings, /* adobe_std_strings */ + ps_get_macintosh_name, /* PS_Macintosh_NameFunc macintosh_name */ + ps_get_standard_strings, /* PS_Adobe_Std_StringsFunc adobe_std_strings */ t1_standard_encoding, /* adobe_std_encoding */ t1_expert_encoding /* adobe_expert_encoding */ @@ -612,9 +612,9 @@ PUT_PS_NAMES_SERVICE( (void*)&pscmaps_interface ), /* module specific interface */ - (FT_Module_Constructor)NULL, /* module_init */ - (FT_Module_Destructor) NULL, /* module_done */ - (FT_Module_Requester) PUT_PS_NAMES_SERVICE( psnames_get_service ) /* get_interface */ + NULL, /* FT_Module_Constructor module_init */ + NULL, /* FT_Module_Destructor module_done */ + PUT_PS_NAMES_SERVICE( psnames_get_service ) /* FT_Module_Requester get_interface */ ) diff --git a/src/3rdparty/freetype/src/raster/ftraster.c b/src/3rdparty/freetype/src/raster/ftraster.c index 67cbfd5d9b7..192ca0701a2 100644 --- a/src/3rdparty/freetype/src/raster/ftraster.c +++ b/src/3rdparty/freetype/src/raster/ftraster.c @@ -1742,9 +1742,9 @@ * SUCCESS on success, FAILURE on error. */ static Bool - Decompose_Curve( RAS_ARGS UShort first, - UShort last, - Int flipped ) + Decompose_Curve( RAS_ARGS Int first, + Int last, + Int flipped ) { FT_Vector v_last; FT_Vector v_control; @@ -1969,8 +1969,8 @@ static Bool Convert_Glyph( RAS_ARGS Int flipped ) { - Int i; - UInt start; + Int i; + Int first, last; ras.fProfile = NULL; @@ -1985,8 +1985,7 @@ ras.cProfile->offset = ras.top; ras.num_Profs = 0; - start = 0; - + last = -1; for ( i = 0; i < ras.outline.n_contours; i++ ) { PProfile lastProfile; @@ -1996,12 +1995,11 @@ ras.state = Unknown_State; ras.gProfile = NULL; - if ( Decompose_Curve( RAS_VARS (UShort)start, - (UShort)ras.outline.contours[i], - flipped ) ) - return FAILURE; + first = last + 1; + last = ras.outline.contours[i]; - start = (UShort)ras.outline.contours[i] + 1; + if ( Decompose_Curve( RAS_VARS first, last, flipped ) ) + return FAILURE; /* we must now check whether the extreme arcs join or not */ if ( FRAC( ras.lastY ) == 0 && @@ -3167,9 +3165,12 @@ static int - ft_black_new( FT_Memory memory, - black_PRaster *araster ) + ft_black_new( void* memory_, /* FT_Memory */ + FT_Raster *araster_ ) /* black_PRaster */ { + FT_Memory memory = (FT_Memory)memory_; + black_PRaster *araster = (black_PRaster*)araster_; + FT_Error error; black_PRaster raster = NULL; @@ -3184,9 +3185,10 @@ static void - ft_black_done( black_PRaster raster ) + ft_black_done( FT_Raster raster_ ) /* black_PRaster */ { - FT_Memory memory = (FT_Memory)raster->memory; + black_PRaster raster = (black_PRaster)raster_; + FT_Memory memory = (FT_Memory)raster->memory; FT_FREE( raster ); @@ -3281,11 +3283,11 @@ FT_GLYPH_FORMAT_OUTLINE, - (FT_Raster_New_Func) ft_black_new, /* raster_new */ - (FT_Raster_Reset_Func) ft_black_reset, /* raster_reset */ - (FT_Raster_Set_Mode_Func)ft_black_set_mode, /* raster_set_mode */ - (FT_Raster_Render_Func) ft_black_render, /* raster_render */ - (FT_Raster_Done_Func) ft_black_done /* raster_done */ + ft_black_new, /* FT_Raster_New_Func raster_new */ + ft_black_reset, /* FT_Raster_Reset_Func raster_reset */ + ft_black_set_mode, /* FT_Raster_Set_Mode_Func raster_set_mode */ + ft_black_render, /* FT_Raster_Render_Func raster_render */ + ft_black_done /* FT_Raster_Done_Func raster_done */ ) diff --git a/src/3rdparty/freetype/src/raster/ftrend1.c b/src/3rdparty/freetype/src/raster/ftrend1.c index 0b5d8671478..6d442b1ff8c 100644 --- a/src/3rdparty/freetype/src/raster/ftrend1.c +++ b/src/3rdparty/freetype/src/raster/ftrend1.c @@ -27,8 +27,11 @@ /* initialize renderer -- init its raster */ static FT_Error - ft_raster1_init( FT_Renderer render ) + ft_raster1_init( FT_Module module ) /* FT_Renderer */ { + FT_Renderer render = (FT_Renderer)module; + + render->clazz->raster_class->raster_reset( render->raster, NULL, 0 ); return FT_Err_Ok; @@ -188,18 +191,18 @@ NULL, /* module specific interface */ - (FT_Module_Constructor)ft_raster1_init, /* module_init */ - (FT_Module_Destructor) NULL, /* module_done */ - (FT_Module_Requester) NULL, /* get_interface */ + ft_raster1_init, /* FT_Module_Constructor module_init */ + NULL, /* FT_Module_Destructor module_done */ + NULL, /* FT_Module_Requester get_interface */ FT_GLYPH_FORMAT_OUTLINE, - (FT_Renderer_RenderFunc) ft_raster1_render, /* render_glyph */ - (FT_Renderer_TransformFunc)ft_raster1_transform, /* transform_glyph */ - (FT_Renderer_GetCBoxFunc) ft_raster1_get_cbox, /* get_glyph_cbox */ - (FT_Renderer_SetModeFunc) ft_raster1_set_mode, /* set_mode */ + ft_raster1_render, /* FT_Renderer_RenderFunc render_glyph */ + ft_raster1_transform, /* FT_Renderer_TransformFunc transform_glyph */ + ft_raster1_get_cbox, /* FT_Renderer_GetCBoxFunc get_glyph_cbox */ + ft_raster1_set_mode, /* FT_Renderer_SetModeFunc set_mode */ - (FT_Raster_Funcs*)&ft_standard_raster /* raster_class */ + &ft_standard_raster /* FT_Raster_Funcs* raster_class */ ) diff --git a/src/3rdparty/freetype/src/sdf/ftbsdf.c b/src/3rdparty/freetype/src/sdf/ftbsdf.c index 901d8b7402e..e4727383390 100644 --- a/src/3rdparty/freetype/src/sdf/ftbsdf.c +++ b/src/3rdparty/freetype/src/sdf/ftbsdf.c @@ -1173,9 +1173,12 @@ /* called when adding a new module through @FT_Add_Module */ static FT_Error - bsdf_raster_new( FT_Memory memory, - BSDF_PRaster* araster ) + bsdf_raster_new( void* memory_, /* FT_Memory */ + FT_Raster* araster_ ) /* BSDF_PRaster* */ { + FT_Memory memory = (FT_Memory)memory_; + BSDF_PRaster* araster = (BSDF_PRaster*)araster_; + FT_Error error; BSDF_PRaster raster = NULL; diff --git a/src/3rdparty/freetype/src/sdf/ftsdf.c b/src/3rdparty/freetype/src/sdf/ftsdf.c index 26a6d00e4ac..bc4625d9842 100644 --- a/src/3rdparty/freetype/src/sdf/ftsdf.c +++ b/src/3rdparty/freetype/src/sdf/ftsdf.c @@ -2371,11 +2371,11 @@ * ``` * * (6) Our task is to find a value of `t` such that the above equation - * `Q(t)` becomes zero, this is, the point-to-curve vector makes + * `Q(t)` becomes zero, that is, the point-to-curve vector makes * 90~degrees with the curve. We solve this with the Newton-Raphson * method. * - * (7) We first assume an arbitary value of factor `t`, which we then + * (7) We first assume an arbitrary value of factor `t`, which we then * improve. * * ``` @@ -2684,11 +2684,11 @@ * ``` * * (6) Our task is to find a value of `t` such that the above equation - * `Q(t)` becomes zero, this is, the point-to-curve vector makes + * `Q(t)` becomes zero, that is, the point-to-curve vector makes * 90~degree with curve. We solve this with the Newton-Raphson * method. * - * (7) We first assume an arbitary value of factor `t`, which we then + * (7) We first assume an arbitrary value of factor `t`, which we then * improve. * * ``` @@ -2718,8 +2718,9 @@ FT_Error error = FT_Err_Ok; - FT_26D6_Vec aA, bB, cC, dD; /* A, B, C in the above comment */ - FT_16D16_Vec nearest_point; /* point on curve nearest to `point` */ + FT_26D6_Vec aA, bB, cC, dD; /* A, B, C, D in the above comment */ + FT_16D16_Vec nearest_point = { 0, 0 }; + /* point on curve nearest to `point` */ FT_16D16_Vec direction; /* direction of curve at `nearest_point` */ FT_26D6_Vec p0, p1, p2, p3; /* control points of a cubic curve */ @@ -3761,9 +3762,13 @@ */ static FT_Error - sdf_raster_new( FT_Memory memory, - SDF_PRaster* araster ) + sdf_raster_new( void* memory_, /* FT_Memory */ + FT_Raster* araster_ ) /* SDF_PRaster* */ { + FT_Memory memory = (FT_Memory)memory_; + SDF_PRaster* araster = (SDF_PRaster*)araster_; + + FT_Error error; SDF_PRaster raster = NULL; diff --git a/src/3rdparty/freetype/src/sdf/ftsdfrend.c b/src/3rdparty/freetype/src/sdf/ftsdfrend.c index 9ac7d6f620f..5610c119f87 100644 --- a/src/3rdparty/freetype/src/sdf/ftsdfrend.c +++ b/src/3rdparty/freetype/src/sdf/ftsdfrend.c @@ -197,10 +197,10 @@ static FT_Module_Interface - ft_sdf_requester( FT_Renderer render, + ft_sdf_requester( FT_Module module, const char* module_interface ) { - FT_UNUSED( render ); + FT_UNUSED( module ); return ft_service_list_lookup( sdf_services, module_interface ); } @@ -221,9 +221,9 @@ */ static FT_Error - ft_sdf_init( FT_Renderer render ) + ft_sdf_init( FT_Module module ) /* SDF_Renderer */ { - SDF_Renderer sdf_render = SDF_RENDERER( render ); + SDF_Renderer sdf_render = SDF_RENDERER( module ); sdf_render->spread = DEFAULT_SPREAD; @@ -236,9 +236,9 @@ static void - ft_sdf_done( FT_Renderer render ) + ft_sdf_done( FT_Module module ) { - FT_UNUSED( render ); + FT_UNUSED( module ); } @@ -300,7 +300,7 @@ /* nothing to render */ if ( !bitmap->rows || !bitmap->pitch ) - return FT_Err_Ok; + goto Exit; /* the padding will simply be equal to the `spread' */ x_pad = sdf_module->spread; @@ -508,6 +508,10 @@ goto Exit; } + /* nothing to render */ + if ( !bitmap->rows || !bitmap->pitch ) + goto Exit; + /* Do not generate SDF if the bitmap is not owned by the */ /* glyph: it might be that the source buffer is already freed. */ if ( !( slot->internal->flags & FT_GLYPH_OWN_BITMAP ) ) @@ -519,10 +523,6 @@ goto Exit; } - /* nothing to render */ - if ( !bitmap->rows || !bitmap->pitch ) - return FT_Err_Ok; - FT_Bitmap_New( &target ); /* padding will simply be equal to `spread` */ @@ -557,15 +557,14 @@ { /* the glyph is successfully converted to a SDF */ if ( slot->internal->flags & FT_GLYPH_OWN_BITMAP ) - { FT_FREE( bitmap->buffer ); - slot->internal->flags &= ~FT_GLYPH_OWN_BITMAP; - } - slot->bitmap = target; - slot->bitmap_top += y_pad; - slot->bitmap_left -= x_pad; - slot->internal->flags |= FT_GLYPH_OWN_BITMAP; + slot->bitmap = target; + slot->bitmap_top += y_pad; + slot->bitmap_left -= x_pad; + + if ( target.buffer ) + slot->internal->flags |= FT_GLYPH_OWN_BITMAP; } else if ( target.buffer ) FT_FREE( target.buffer ); diff --git a/src/3rdparty/freetype/src/sfnt/pngshim.c b/src/3rdparty/freetype/src/sfnt/pngshim.c index 423b07b02a5..33712162e00 100644 --- a/src/3rdparty/freetype/src/sfnt/pngshim.c +++ b/src/3rdparty/freetype/src/sfnt/pngshim.c @@ -406,10 +406,7 @@ switch ( color_type ) { - default: - /* Shouldn't happen, but ... */ - FALL_THROUGH; - + default: /* Shouldn't happen, but ... */ case PNG_COLOR_TYPE_RGB_ALPHA: png_set_read_user_transform_fn( png, premultiply_data ); break; @@ -457,7 +454,7 @@ #else /* !(TT_CONFIG_OPTION_EMBEDDED_BITMAPS && FT_CONFIG_OPTION_USE_PNG) */ /* ANSI C doesn't like empty source files */ - typedef int _pngshim_dummy; + typedef int pngshim_dummy_; #endif /* !(TT_CONFIG_OPTION_EMBEDDED_BITMAPS && FT_CONFIG_OPTION_USE_PNG) */ diff --git a/src/3rdparty/freetype/src/sfnt/sfdriver.c b/src/3rdparty/freetype/src/sfnt/sfdriver.c index 762883db542..0925940b03f 100644 --- a/src/3rdparty/freetype/src/sfnt/sfdriver.c +++ b/src/3rdparty/freetype/src/sfnt/sfdriver.c @@ -79,41 +79,57 @@ * */ - static void* - get_sfnt_table( TT_Face face, + FT_CALLBACK_DEF( FT_Error ) + sfnt_load_table( FT_Face face, /* TT_Face */ + FT_ULong tag, + FT_Long offset, + FT_Byte* buffer, + FT_ULong* length ) + { + TT_Face ttface = (TT_Face)face; + + + return tt_face_load_any( ttface, tag, offset, buffer, length ); + } + + + FT_CALLBACK_DEF( void* ) + get_sfnt_table( FT_Face face, /* TT_Face */ FT_Sfnt_Tag tag ) { + TT_Face ttface = (TT_Face)face; + void* table; switch ( tag ) { case FT_SFNT_HEAD: - table = &face->header; + table = &ttface->header; break; case FT_SFNT_HHEA: - table = &face->horizontal; + table = &ttface->horizontal; break; case FT_SFNT_VHEA: - table = face->vertical_info ? &face->vertical : NULL; + table = ttface->vertical_info ? &ttface->vertical : NULL; break; case FT_SFNT_OS2: - table = ( face->os2.version == 0xFFFFU ) ? NULL : &face->os2; + table = ( ttface->os2.version == 0xFFFFU ) ? NULL : &ttface->os2; break; case FT_SFNT_POST: - table = &face->postscript; + table = &ttface->postscript; break; case FT_SFNT_MAXP: - table = &face->max_profile; + table = &ttface->max_profile; break; case FT_SFNT_PCLT: - table = face->pclt.Version ? &face->pclt : NULL; + table = ttface->pclt.Version ? &ttface->pclt : NULL; break; default: @@ -124,26 +140,29 @@ } - static FT_Error - sfnt_table_info( TT_Face face, + FT_CALLBACK_DEF( FT_Error ) + sfnt_table_info( FT_Face face, /* TT_Face */ FT_UInt idx, FT_ULong *tag, FT_ULong *offset, FT_ULong *length ) { + TT_Face ttface = (TT_Face)face; + + if ( !offset || !length ) return FT_THROW( Invalid_Argument ); if ( !tag ) - *length = face->num_tables; + *length = ttface->num_tables; else { - if ( idx >= face->num_tables ) + if ( idx >= ttface->num_tables ) return FT_THROW( Table_Missing ); - *tag = face->dir_tables[idx].Tag; - *offset = face->dir_tables[idx].Offset; - *length = face->dir_tables[idx].Length; + *tag = ttface->dir_tables[idx].Tag; + *offset = ttface->dir_tables[idx].Offset; + *length = ttface->dir_tables[idx].Length; } return FT_Err_Ok; @@ -153,9 +172,9 @@ FT_DEFINE_SERVICE_SFNT_TABLEREC( sfnt_service_sfnt_table, - (FT_SFNT_TableLoadFunc)tt_face_load_any, /* load_table */ - (FT_SFNT_TableGetFunc) get_sfnt_table, /* get_table */ - (FT_SFNT_TableInfoFunc)sfnt_table_info /* table_info */ + sfnt_load_table, /* FT_SFNT_TableLoadFunc load_table */ + get_sfnt_table, /* FT_SFNT_TableGetFunc get_table */ + sfnt_table_info /* FT_SFNT_TableInfoFunc table_info */ ) @@ -166,7 +185,7 @@ * */ - static FT_Error + FT_CALLBACK_DEF( FT_Error ) sfnt_get_glyph_name( FT_Face face, FT_UInt glyph_index, FT_Pointer buffer, @@ -184,7 +203,7 @@ } - static FT_UInt + FT_CALLBACK_DEF( FT_UInt ) sfnt_get_name_index( FT_Face face, const FT_String* glyph_name ) { @@ -221,8 +240,8 @@ FT_DEFINE_SERVICE_GLYPHDICTREC( sfnt_service_glyph_dict, - (FT_GlyphDict_GetNameFunc) sfnt_get_glyph_name, /* get_name */ - (FT_GlyphDict_NameIndexFunc)sfnt_get_name_index /* name_index */ + sfnt_get_glyph_name, /* FT_GlyphDict_GetNameFunc get_name */ + sfnt_get_name_index /* FT_GlyphDict_NameIndexFunc name_index */ ) #endif /* TT_CONFIG_OPTION_POSTSCRIPT_NAMES */ @@ -523,15 +542,14 @@ FT_TRACE0(( "get_win_string:" " Character 0x%X invalid in PS name string\n", ((unsigned)p[0])*256 + (unsigned)p[1] )); - break; + continue; } } - if ( !len ) - *r = '\0'; + *r = '\0'; FT_FRAME_EXIT(); - if ( !len ) + if ( r != result ) return result; get_win_string_error: @@ -580,15 +598,14 @@ FT_TRACE0(( "get_apple_string:" " Character `%c' (0x%X) invalid in PS name string\n", *p, *p )); - break; + continue; } } - if ( !len ) - *r = '\0'; + *r = '\0'; FT_FRAME_EXIT(); - if ( !len ) + if ( r != result ) return result; get_apple_string_error: @@ -602,7 +619,7 @@ } - static FT_Bool + FT_CALLBACK_DEF( FT_Bool ) sfnt_get_name_id( TT_Face face, FT_UShort id, FT_Int *win, @@ -819,9 +836,9 @@ if ( !found ) { - /* as a last resort we try the family name; note that this is */ - /* not in the Adobe TechNote, but GX fonts (which predate the */ - /* TechNote) benefit from this behaviour */ + /* according to the 'name' documentation in the OpenType */ + /* specification the font family name is to be used if the */ + /* typographic family name is missing, so let's do that */ found = sfnt_get_name_id( face, TT_NAME_ID_FONT_FAMILY, &win, @@ -853,6 +870,10 @@ { FT_TRACE0(( "sfnt_get_var_ps_name:" " No valid PS name prefix for font instances found\n" )); + /* XXX It probably makes sense to never let this fail */ + /* since an arbitrary prefix should work, too. */ + /* On the other hand, it is very unlikely that */ + /* we ever reach this code at all. */ return NULL; } @@ -1041,47 +1062,49 @@ #endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */ - static const char* - sfnt_get_ps_name( TT_Face face ) + FT_CALLBACK_DEF( const char* ) + sfnt_get_ps_name( FT_Face face ) /* TT_Face */ { + TT_Face ttface = (TT_Face)face; + FT_Int found, win, apple; const char* result = NULL; - if ( face->postscript_name ) - return face->postscript_name; + if ( ttface->postscript_name ) + return ttface->postscript_name; #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT - if ( face->blend && - ( FT_IS_NAMED_INSTANCE( FT_FACE( face ) ) || - FT_IS_VARIATION( FT_FACE( face ) ) ) ) + if ( ttface->blend && + ( FT_IS_NAMED_INSTANCE( face ) || + FT_IS_VARIATION( face ) ) ) { - face->postscript_name = sfnt_get_var_ps_name( face ); - return face->postscript_name; + ttface->postscript_name = sfnt_get_var_ps_name( ttface ); + return ttface->postscript_name; } #endif /* scan the name table to see whether we have a Postscript name here, */ /* either in Macintosh or Windows platform encodings */ - found = sfnt_get_name_id( face, TT_NAME_ID_PS_NAME, &win, &apple ); + found = sfnt_get_name_id( ttface, TT_NAME_ID_PS_NAME, &win, &apple ); if ( !found ) return NULL; /* prefer Windows entries over Apple */ if ( win != -1 ) - result = get_win_string( face->root.memory, - face->name_table.stream, - face->name_table.names + win, + result = get_win_string( FT_FACE_MEMORY( face ), + ttface->name_table.stream, + ttface->name_table.names + win, sfnt_is_postscript, 1 ); if ( !result && apple != -1 ) - result = get_apple_string( face->root.memory, - face->name_table.stream, - face->name_table.names + apple, + result = get_apple_string( FT_FACE_MEMORY( face ), + ttface->name_table.stream, + ttface->name_table.names + apple, sfnt_is_postscript, 1 ); - face->postscript_name = result; + ttface->postscript_name = result; return result; } @@ -1090,7 +1113,7 @@ FT_DEFINE_SERVICE_PSFONTNAMEREC( sfnt_service_ps_name, - (FT_PsName_GetFunc)sfnt_get_ps_name /* get_ps_font_name */ + sfnt_get_ps_name /* FT_PsName_GetFunc get_ps_font_name */ ) @@ -1100,14 +1123,14 @@ FT_DEFINE_SERVICE_TTCMAPSREC( tt_service_get_cmap_info, - (TT_CMap_Info_GetFunc)tt_get_cmap_info /* get_cmap_info */ + tt_get_cmap_info /* TT_CMap_Info_GetFunc get_cmap_info */ ) #ifdef TT_CONFIG_OPTION_BDF static FT_Error - sfnt_get_charset_id( TT_Face face, + sfnt_get_charset_id( FT_Face face, const char* *acharset_encoding, const char* *acharset_registry ) { @@ -1145,8 +1168,8 @@ FT_DEFINE_SERVICE_BDFRec( sfnt_service_bdf, - (FT_BDF_GetCharsetIdFunc)sfnt_get_charset_id, /* get_charset_id */ - (FT_BDF_GetPropertyFunc) tt_face_find_bdf_prop /* get_property */ + sfnt_get_charset_id, /* FT_BDF_GetCharsetIdFunc get_charset_id */ + tt_face_find_bdf_prop /* FT_BDF_GetPropertyFunc get_property */ ) @@ -1337,9 +1360,9 @@ (const void*)&sfnt_interface, /* module specific interface */ - (FT_Module_Constructor)NULL, /* module_init */ - (FT_Module_Destructor) NULL, /* module_done */ - (FT_Module_Requester) sfnt_get_interface /* get_interface */ + NULL, /* FT_Module_Constructor module_init */ + NULL, /* FT_Module_Destructor module_done */ + sfnt_get_interface /* FT_Module_Requester get_interface */ ) diff --git a/src/3rdparty/freetype/src/sfnt/sfobjs.c b/src/3rdparty/freetype/src/sfnt/sfobjs.c index e018934ccaa..f5d66ef8403 100644 --- a/src/3rdparty/freetype/src/sfnt/sfobjs.c +++ b/src/3rdparty/freetype/src/sfnt/sfobjs.c @@ -534,17 +534,23 @@ 0 ); } - if ( !face->var ) + if ( !face->tt_var ) { /* we want the metrics variations interface */ /* from the `truetype' module only */ FT_Module tt_module = FT_Get_Module( library, "truetype" ); - face->var = ft_module_get_service( tt_module, - FT_SERVICE_ID_METRICS_VARIATIONS, - 0 ); + face->tt_var = ft_module_get_service( tt_module, + FT_SERVICE_ID_METRICS_VARIATIONS, + 0 ); } + + if ( !face->face_var ) + face->face_var = ft_module_get_service( + &face->root.driver->root, + FT_SERVICE_ID_METRICS_VARIATIONS, + 0 ); #endif FT_TRACE2(( "SFNT driver\n" )); @@ -692,6 +698,9 @@ instance_offset += instance_size; } + /* named instance indices start with value 1 */ + face->var_default_named_instance = i + 1; + if ( i == num_instances ) { /* no default instance in named instance table; */ @@ -1054,6 +1063,16 @@ GET_NAME( FONT_SUBFAMILY, &face->root.style_name ); } +#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT + { + FT_Memory memory = face->root.memory; + + + if ( FT_STRDUP( face->non_var_style_name, face->root.style_name ) ) + goto Exit; + } +#endif + /* now set up root fields */ { FT_Face root = &face->root; @@ -1221,7 +1240,7 @@ if ( count > 0 ) { - FT_Memory memory = face->root.stream->memory; + FT_Memory memory = face->root.memory; FT_UShort em_size = face->header.Units_Per_EM; FT_Short avgwidth = face->os2.xAvgCharWidth; FT_Size_Metrics metrics; @@ -1500,6 +1519,7 @@ #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT FT_FREE( face->var_postscript_prefix ); + FT_FREE( face->non_var_style_name ); #endif /* freeing glyph color palette data */ diff --git a/src/3rdparty/freetype/src/sfnt/sfwoff.c b/src/3rdparty/freetype/src/sfnt/sfwoff.c index 9559bf34214..7c0ce2205e6 100644 --- a/src/3rdparty/freetype/src/sfnt/sfwoff.c +++ b/src/3rdparty/freetype/src/sfnt/sfwoff.c @@ -426,7 +426,7 @@ #else /* !FT_CONFIG_OPTION_USE_ZLIB */ /* ANSI C doesn't like empty source files */ - typedef int _sfwoff_dummy; + typedef int sfwoff_dummy_; #endif /* !FT_CONFIG_OPTION_USE_ZLIB */ diff --git a/src/3rdparty/freetype/src/sfnt/sfwoff2.c b/src/3rdparty/freetype/src/sfnt/sfwoff2.c index 7a01977f866..49ad5cc8114 100644 --- a/src/3rdparty/freetype/src/sfnt/sfwoff2.c +++ b/src/3rdparty/freetype/src/sfnt/sfwoff2.c @@ -2378,7 +2378,7 @@ #else /* !FT_CONFIG_OPTION_USE_BROTLI */ /* ANSI C doesn't like empty source files */ - typedef int _sfwoff2_dummy; + typedef int sfwoff2_dummy_; #endif /* !FT_CONFIG_OPTION_USE_BROTLI */ diff --git a/src/3rdparty/freetype/src/sfnt/ttbdf.c b/src/3rdparty/freetype/src/sfnt/ttbdf.c index 118f475e7f4..536fa7467e0 100644 --- a/src/3rdparty/freetype/src/sfnt/ttbdf.c +++ b/src/3rdparty/freetype/src/sfnt/ttbdf.c @@ -136,13 +136,14 @@ FT_LOCAL_DEF( FT_Error ) - tt_face_find_bdf_prop( TT_Face face, + tt_face_find_bdf_prop( FT_Face face, /* TT_Face */ const char* property_name, BDF_PropertyRec *aprop ) { - TT_BDF bdf = &face->bdf; - FT_Size size = FT_FACE( face )->size; - FT_Error error = FT_Err_Ok; + TT_Face ttface = (TT_Face)face; + TT_BDF bdf = &ttface->bdf; + FT_Size size = FT_FACE_SIZE( face ); + FT_Error error = FT_Err_Ok; FT_Byte* p; FT_UInt count; FT_Byte* strike; @@ -153,7 +154,7 @@ if ( bdf->loaded == 0 ) { - error = tt_face_load_bdf_props( face, FT_FACE( face )->stream ); + error = tt_face_load_bdf_props( ttface, FT_FACE_STREAM( face ) ); if ( error ) goto Exit; } @@ -248,7 +249,7 @@ #else /* !TT_CONFIG_OPTION_BDF */ /* ANSI C doesn't like empty source files */ - typedef int _tt_bdf_dummy; + typedef int tt_bdf_dummy_; #endif /* !TT_CONFIG_OPTION_BDF */ diff --git a/src/3rdparty/freetype/src/sfnt/ttbdf.h b/src/3rdparty/freetype/src/sfnt/ttbdf.h index 595aeb76c2c..0d7a0aceccf 100644 --- a/src/3rdparty/freetype/src/sfnt/ttbdf.h +++ b/src/3rdparty/freetype/src/sfnt/ttbdf.h @@ -34,7 +34,7 @@ FT_BEGIN_HEADER FT_LOCAL( FT_Error ) - tt_face_find_bdf_prop( TT_Face face, + tt_face_find_bdf_prop( FT_Face face, const char* property_name, BDF_PropertyRec *aprop ); diff --git a/src/3rdparty/freetype/src/sfnt/ttcmap.c b/src/3rdparty/freetype/src/sfnt/ttcmap.c index 820cd08e6d5..9ba25dcbc13 100644 --- a/src/3rdparty/freetype/src/sfnt/ttcmap.c +++ b/src/3rdparty/freetype/src/sfnt/ttcmap.c @@ -59,10 +59,14 @@ FT_CALLBACK_DEF( FT_Error ) - tt_cmap_init( TT_CMap cmap, - FT_Byte* table ) + tt_cmap_init( FT_CMap cmap, /* TT_CMap */ + void* table_ ) { - cmap->data = table; + TT_CMap ttcmap = (TT_CMap)cmap; + FT_Byte* table = (FT_Byte*)table_; + + + ttcmap->data = table; return FT_Err_Ok; } @@ -128,21 +132,23 @@ FT_CALLBACK_DEF( FT_UInt ) - tt_cmap0_char_index( TT_CMap cmap, + tt_cmap0_char_index( FT_CMap cmap, /* TT_CMap */ FT_UInt32 char_code ) { - FT_Byte* table = cmap->data; + TT_CMap ttcmap = (TT_CMap)cmap; + FT_Byte* table = ttcmap->data; return char_code < 256 ? table[6 + char_code] : 0; } - FT_CALLBACK_DEF( FT_UInt32 ) - tt_cmap0_char_next( TT_CMap cmap, + FT_CALLBACK_DEF( FT_UInt ) + tt_cmap0_char_next( FT_CMap cmap, /* TT_CMap */ FT_UInt32 *pchar_code ) { - FT_Byte* table = cmap->data; + TT_CMap ttcmap = (TT_CMap)cmap; + FT_Byte* table = ttcmap->data; FT_UInt32 charcode = *pchar_code; FT_UInt32 result = 0; FT_UInt gindex = 0; @@ -165,10 +171,11 @@ FT_CALLBACK_DEF( FT_Error ) - tt_cmap0_get_info( TT_CMap cmap, + tt_cmap0_get_info( FT_CharMap cmap, /* TT_CMap */ TT_CMapInfo *cmap_info ) { - FT_Byte* p = cmap->data + 4; + TT_CMap ttcmap = (TT_CMap)cmap; + FT_Byte* p = ttcmap->data + 4; cmap_info->format = 0; @@ -453,10 +460,11 @@ FT_CALLBACK_DEF( FT_UInt ) - tt_cmap2_char_index( TT_CMap cmap, + tt_cmap2_char_index( FT_CMap cmap, /* TT_CMap */ FT_UInt32 char_code ) { - FT_Byte* table = cmap->data; + TT_CMap ttcmap = (TT_CMap)cmap; + FT_Byte* table = ttcmap->data; FT_UInt result = 0; FT_Byte* subheader; @@ -491,11 +499,12 @@ } - FT_CALLBACK_DEF( FT_UInt32 ) - tt_cmap2_char_next( TT_CMap cmap, + FT_CALLBACK_DEF( FT_UInt ) + tt_cmap2_char_next( FT_CMap cmap, /* TT_CMap */ FT_UInt32 *pcharcode ) { - FT_Byte* table = cmap->data; + TT_CMap ttcmap = (TT_CMap)cmap; + FT_Byte* table = ttcmap->data; FT_UInt gindex = 0; FT_UInt32 result = 0; FT_UInt32 charcode = *pcharcode + 1; @@ -579,10 +588,11 @@ FT_CALLBACK_DEF( FT_Error ) - tt_cmap2_get_info( TT_CMap cmap, + tt_cmap2_get_info( FT_CharMap cmap, /* TT_CMap */ TT_CMapInfo *cmap_info ) { - FT_Byte* p = cmap->data + 4; + TT_CMap ttcmap = (TT_CMap)cmap; + FT_Byte* p = ttcmap->data + 4; cmap_info->format = 2; @@ -706,18 +716,20 @@ FT_CALLBACK_DEF( FT_Error ) - tt_cmap4_init( TT_CMap4 cmap, - FT_Byte* table ) + tt_cmap4_init( FT_CMap cmap, /* TT_CMap4 */ + void* table_ ) { + TT_CMap4 ttcmap = (TT_CMap4)cmap; + FT_Byte* table = (FT_Byte*)table_; FT_Byte* p; - cmap->cmap.data = table; + ttcmap->cmap.data = table; - p = table + 6; - cmap->num_ranges = FT_PEEK_USHORT( p ) >> 1; - cmap->cur_charcode = (FT_UInt32)0xFFFFFFFFUL; - cmap->cur_gindex = 0; + p = table + 6; + ttcmap->num_ranges = FT_PEEK_USHORT( p ) >> 1; + ttcmap->cur_charcode = (FT_UInt32)0xFFFFFFFFUL; + ttcmap->cur_gindex = 0; return FT_Err_Ok; } @@ -755,7 +767,7 @@ cmap->cur_start == 0xFFFFU && cmap->cur_end == 0xFFFFU ) { - TT_Face face = (TT_Face)cmap->cmap.cmap.charmap.face; + TT_Face face = (TT_Face)FT_CMAP_FACE( cmap ); FT_Byte* limit = face->cmap_table + face->cmap_size; @@ -788,15 +800,12 @@ static void tt_cmap4_next( TT_CMap4 cmap ) { - TT_Face face = (TT_Face)cmap->cmap.cmap.charmap.face; + TT_Face face = (TT_Face)FT_CMAP_FACE( cmap ); FT_Byte* limit = face->cmap_table + face->cmap_size; FT_UInt charcode; - if ( cmap->cur_charcode >= 0xFFFFUL ) - goto Fail; - charcode = (FT_UInt)cmap->cur_charcode + 1; if ( charcode < cmap->cur_start ) @@ -882,7 +891,6 @@ charcode = cmap->cur_start; } - Fail: cmap->cur_charcode = (FT_UInt32)0xFFFFFFFFUL; cmap->cur_gindex = 0; } @@ -1097,32 +1105,26 @@ FT_UInt32* pcharcode, FT_Bool next ) { - TT_Face face = (TT_Face)cmap->cmap.charmap.face; + TT_Face face = (TT_Face)FT_CMAP_FACE( cmap ); FT_Byte* limit = face->cmap_table + face->cmap_size; FT_UInt num_segs2, start, end, offset; FT_Int delta; FT_UInt i, num_segs; - FT_UInt32 charcode = *pcharcode; + FT_UInt32 charcode = *pcharcode + next; FT_UInt gindex = 0; FT_Byte* p; FT_Byte* q; p = cmap->data + 6; - num_segs2 = FT_PAD_FLOOR( TT_PEEK_USHORT( p ), 2 ); - - num_segs = num_segs2 >> 1; + num_segs = TT_PEEK_USHORT( p ) >> 1; if ( !num_segs ) return 0; - if ( next ) - charcode++; - - if ( charcode > 0xFFFFU ) - return 0; + num_segs2 = num_segs << 1; /* linear search */ p = cmap->data + 14; /* ends table */ @@ -1232,37 +1234,30 @@ FT_UInt32* pcharcode, FT_Bool next ) { - TT_Face face = (TT_Face)cmap->cmap.charmap.face; + TT_Face face = (TT_Face)FT_CMAP_FACE( cmap ); FT_Byte* limit = face->cmap_table + face->cmap_size; FT_UInt num_segs2, start, end, offset; FT_Int delta; FT_UInt max, min, mid, num_segs; - FT_UInt charcode = (FT_UInt)*pcharcode; + FT_UInt charcode = (FT_UInt)*pcharcode + next; FT_UInt gindex = 0; FT_Byte* p; p = cmap->data + 6; - num_segs2 = FT_PAD_FLOOR( TT_PEEK_USHORT( p ), 2 ); + num_segs = TT_PEEK_USHORT( p ) >> 1; - if ( !num_segs2 ) + if ( !num_segs ) return 0; - num_segs = num_segs2 >> 1; - - /* make compiler happy */ - mid = num_segs; - end = 0xFFFFU; - - if ( next ) - charcode++; + num_segs2 = num_segs << 1; min = 0; max = num_segs; /* binary search */ - while ( min < max ) + do { mid = ( min + max ) >> 1; p = cmap->data + 14 + mid * 2; @@ -1445,6 +1440,7 @@ break; } } + while ( min < max ); if ( next ) { @@ -1454,12 +1450,8 @@ /* if `charcode' is not in any segment, then `mid' is */ /* the segment nearest to `charcode' */ - if ( charcode > end ) - { - mid++; - if ( mid == num_segs ) - return 0; - } + if ( charcode > end && ++mid == num_segs ) + return 0; if ( tt_cmap4_set_range( cmap4, mid ) ) { @@ -1474,7 +1466,6 @@ cmap4->cur_gindex = gindex; else { - cmap4->cur_charcode = charcode; tt_cmap4_next( cmap4 ); gindex = cmap4->cur_gindex; } @@ -1489,31 +1480,35 @@ FT_CALLBACK_DEF( FT_UInt ) - tt_cmap4_char_index( TT_CMap cmap, + tt_cmap4_char_index( FT_CMap cmap, /* TT_CMap */ FT_UInt32 char_code ) { + TT_CMap ttcmap = (TT_CMap)cmap; + + if ( char_code >= 0x10000UL ) return 0; - if ( cmap->flags & TT_CMAP_FLAG_UNSORTED ) - return tt_cmap4_char_map_linear( cmap, &char_code, 0 ); + if ( ttcmap->flags & TT_CMAP_FLAG_UNSORTED ) + return tt_cmap4_char_map_linear( ttcmap, &char_code, 0 ); else - return tt_cmap4_char_map_binary( cmap, &char_code, 0 ); + return tt_cmap4_char_map_binary( ttcmap, &char_code, 0 ); } - FT_CALLBACK_DEF( FT_UInt32 ) - tt_cmap4_char_next( TT_CMap cmap, + FT_CALLBACK_DEF( FT_UInt ) + tt_cmap4_char_next( FT_CMap cmap, /* TT_CMap */ FT_UInt32 *pchar_code ) { + TT_CMap ttcmap = (TT_CMap)cmap; FT_UInt gindex; if ( *pchar_code >= 0xFFFFU ) return 0; - if ( cmap->flags & TT_CMAP_FLAG_UNSORTED ) - gindex = tt_cmap4_char_map_linear( cmap, pchar_code, 1 ); + if ( ttcmap->flags & TT_CMAP_FLAG_UNSORTED ) + gindex = tt_cmap4_char_map_linear( ttcmap, pchar_code, 1 ); else { TT_CMap4 cmap4 = (TT_CMap4)cmap; @@ -1528,7 +1523,7 @@ *pchar_code = cmap4->cur_charcode; } else - gindex = tt_cmap4_char_map_binary( cmap, pchar_code, 1 ); + gindex = tt_cmap4_char_map_binary( ttcmap, pchar_code, 1 ); } return gindex; @@ -1536,10 +1531,11 @@ FT_CALLBACK_DEF( FT_Error ) - tt_cmap4_get_info( TT_CMap cmap, + tt_cmap4_get_info( FT_CharMap cmap, /* TT_CMap */ TT_CMapInfo *cmap_info ) { - FT_Byte* p = cmap->data + 4; + TT_CMap ttcmap = (TT_CMap)cmap; + FT_Byte* p = ttcmap->data + 4; cmap_info->format = 4; @@ -1640,10 +1636,11 @@ FT_CALLBACK_DEF( FT_UInt ) - tt_cmap6_char_index( TT_CMap cmap, + tt_cmap6_char_index( FT_CMap cmap, /* TT_CMap */ FT_UInt32 char_code ) { - FT_Byte* table = cmap->data; + TT_CMap ttcmap = (TT_CMap)cmap; + FT_Byte* table = ttcmap->data; FT_UInt result = 0; FT_Byte* p = table + 6; FT_UInt start = TT_NEXT_USHORT( p ); @@ -1661,11 +1658,12 @@ } - FT_CALLBACK_DEF( FT_UInt32 ) - tt_cmap6_char_next( TT_CMap cmap, + FT_CALLBACK_DEF( FT_UInt ) + tt_cmap6_char_next( FT_CMap cmap, /* TT_CMap */ FT_UInt32 *pchar_code ) { - FT_Byte* table = cmap->data; + TT_CMap ttcmap = (TT_CMap)cmap; + FT_Byte* table = ttcmap->data; FT_UInt32 result = 0; FT_UInt32 char_code = *pchar_code + 1; FT_UInt gindex = 0; @@ -1706,10 +1704,11 @@ FT_CALLBACK_DEF( FT_Error ) - tt_cmap6_get_info( TT_CMap cmap, + tt_cmap6_get_info( FT_CharMap cmap, /* TT_CMap */ TT_CMapInfo *cmap_info ) { - FT_Byte* p = cmap->data + 4; + TT_CMap ttcmap = (TT_CMap)cmap; + FT_Byte* p = ttcmap->data + 4; cmap_info->format = 6; @@ -1900,10 +1899,11 @@ FT_CALLBACK_DEF( FT_UInt ) - tt_cmap8_char_index( TT_CMap cmap, + tt_cmap8_char_index( FT_CMap cmap, /* TT_CMap */ FT_UInt32 char_code ) { - FT_Byte* table = cmap->data; + TT_CMap ttcmap = (TT_CMap)cmap; + FT_Byte* table = ttcmap->data; FT_UInt result = 0; FT_Byte* p = table + 8204; FT_UInt32 num_groups = TT_NEXT_ULONG( p ); @@ -1932,15 +1932,16 @@ } - FT_CALLBACK_DEF( FT_UInt32 ) - tt_cmap8_char_next( TT_CMap cmap, + FT_CALLBACK_DEF( FT_UInt ) + tt_cmap8_char_next( FT_CMap cmap, /* TT_CMap */ FT_UInt32 *pchar_code ) { - FT_Face face = cmap->cmap.charmap.face; + TT_CMap ttcmap = (TT_CMap)cmap; + FT_Face face = FT_CMAP_FACE( cmap ); FT_UInt32 result = 0; FT_UInt32 char_code; FT_UInt gindex = 0; - FT_Byte* table = cmap->data; + FT_Byte* table = ttcmap->data; FT_Byte* p = table + 8204; FT_UInt32 num_groups = TT_NEXT_ULONG( p ); FT_UInt32 start, end, start_id; @@ -2000,10 +2001,11 @@ FT_CALLBACK_DEF( FT_Error ) - tt_cmap8_get_info( TT_CMap cmap, + tt_cmap8_get_info( FT_CharMap cmap, /* TT_CMap */ TT_CMapInfo *cmap_info ) { - FT_Byte* p = cmap->data + 8; + TT_CMap ttcmap = (TT_CMap)cmap; + FT_Byte* p = ttcmap->data + 8; cmap_info->format = 8; @@ -2104,10 +2106,11 @@ FT_CALLBACK_DEF( FT_UInt ) - tt_cmap10_char_index( TT_CMap cmap, + tt_cmap10_char_index( FT_CMap cmap, /* TT_CMap */ FT_UInt32 char_code ) { - FT_Byte* table = cmap->data; + TT_CMap ttcmap = (TT_CMap)cmap; + FT_Byte* table = ttcmap->data; FT_UInt result = 0; FT_Byte* p = table + 12; FT_UInt32 start = TT_NEXT_ULONG( p ); @@ -2130,11 +2133,12 @@ } - FT_CALLBACK_DEF( FT_UInt32 ) - tt_cmap10_char_next( TT_CMap cmap, + FT_CALLBACK_DEF( FT_UInt ) + tt_cmap10_char_next( FT_CMap cmap, /* TT_CMap */ FT_UInt32 *pchar_code ) { - FT_Byte* table = cmap->data; + TT_CMap ttcmap = (TT_CMap)cmap; + FT_Byte* table = ttcmap->data; FT_UInt32 char_code; FT_UInt gindex = 0; FT_Byte* p = table + 12; @@ -2172,10 +2176,11 @@ FT_CALLBACK_DEF( FT_Error ) - tt_cmap10_get_info( TT_CMap cmap, + tt_cmap10_get_info( FT_CharMap cmap, /* TT_CMap */ TT_CMapInfo *cmap_info ) { - FT_Byte* p = cmap->data + 8; + TT_CMap ttcmap = (TT_CMap)cmap; + FT_Byte* p = ttcmap->data + 8; cmap_info->format = 10; @@ -2253,15 +2258,19 @@ FT_CALLBACK_DEF( FT_Error ) - tt_cmap12_init( TT_CMap12 cmap, - FT_Byte* table ) + tt_cmap12_init( FT_CMap cmap, /* TT_CMap12 */ + void* table_ ) { - cmap->cmap.data = table; + TT_CMap12 ttcmap = (TT_CMap12)cmap; + FT_Byte* table = (FT_Byte*)table_; - table += 12; - cmap->num_groups = FT_PEEK_ULONG( table ); - cmap->valid = 0; + ttcmap->cmap.data = table; + + table += 12; + ttcmap->num_groups = FT_PEEK_ULONG( table ); + + ttcmap->valid = 0; return FT_Err_Ok; } @@ -2331,23 +2340,21 @@ /* cmap->cur_group should be set up properly by caller */ /* */ static void - tt_cmap12_next( TT_CMap12 cmap ) + tt_cmap12_next( FT_CMap cmap ) /* TT_CMap12 */ { - FT_Face face = cmap->cmap.cmap.charmap.face; - FT_Byte* p; - FT_ULong start, end, start_id, char_code; - FT_ULong n; - FT_UInt gindex; + TT_CMap12 ttcmap = (TT_CMap12)cmap; + FT_Face face = FT_CMAP_FACE( cmap ); + FT_Byte* p; + FT_ULong start, end, start_id, char_code; + FT_ULong n; + FT_UInt gindex; - if ( cmap->cur_charcode >= 0xFFFFFFFFUL ) - goto Fail; + char_code = ttcmap->cur_charcode + 1; - char_code = cmap->cur_charcode + 1; - - for ( n = cmap->cur_group; n < cmap->num_groups; n++ ) + for ( n = ttcmap->cur_group; n < ttcmap->num_groups; n++ ) { - p = cmap->cmap.data + 16 + 12 * n; + p = ttcmap->cmap.data + 16 + 12 * n; start = TT_NEXT_ULONG( p ); end = TT_NEXT_ULONG( p ); start_id = TT_PEEK_ULONG( p ); @@ -2379,16 +2386,16 @@ if ( gindex >= (FT_UInt)face->num_glyphs ) continue; - cmap->cur_charcode = char_code; - cmap->cur_gindex = gindex; - cmap->cur_group = n; + ttcmap->cur_charcode = char_code; + ttcmap->cur_gindex = gindex; + ttcmap->cur_group = n; return; } } Fail: - cmap->valid = 0; + ttcmap->valid = 0; } @@ -2400,7 +2407,7 @@ FT_UInt gindex = 0; FT_Byte* p = cmap->data + 12; FT_UInt32 num_groups = TT_PEEK_ULONG( p ); - FT_UInt32 char_code = *pchar_code; + FT_UInt32 char_code = *pchar_code + next; FT_UInt32 start, end, start_id; FT_UInt32 max, min, mid; @@ -2408,23 +2415,11 @@ if ( !num_groups ) return 0; - /* make compiler happy */ - mid = num_groups; - end = 0xFFFFFFFFUL; - - if ( next ) - { - if ( char_code >= 0xFFFFFFFFUL ) - return 0; - - char_code++; - } - min = 0; max = num_groups; /* binary search */ - while ( min < max ) + do { mid = ( min + max ) >> 1; p = cmap->data + 16 + 12 * mid; @@ -2448,22 +2443,19 @@ break; } } + while ( min < max ); if ( next ) { - FT_Face face = cmap->cmap.charmap.face; + FT_Face face = FT_CMAP_FACE( cmap ); TT_CMap12 cmap12 = (TT_CMap12)cmap; /* if `char_code' is not in any group, then `mid' is */ /* the group nearest to `char_code' */ - if ( char_code > end ) - { - mid++; - if ( mid == num_groups ) - return 0; - } + if ( char_code > end && ++mid == num_groups ) + return 0; cmap12->valid = 1; cmap12->cur_charcode = char_code; @@ -2474,7 +2466,7 @@ if ( !gindex ) { - tt_cmap12_next( cmap12 ); + tt_cmap12_next( FT_CMAP( cmap12 ) ); if ( cmap12->valid ) gindex = cmap12->cur_gindex; @@ -2490,25 +2482,28 @@ FT_CALLBACK_DEF( FT_UInt ) - tt_cmap12_char_index( TT_CMap cmap, + tt_cmap12_char_index( FT_CMap cmap, /* TT_CMap */ FT_UInt32 char_code ) { - return tt_cmap12_char_map_binary( cmap, &char_code, 0 ); + return tt_cmap12_char_map_binary( (TT_CMap)cmap, &char_code, 0 ); } - FT_CALLBACK_DEF( FT_UInt32 ) - tt_cmap12_char_next( TT_CMap cmap, + FT_CALLBACK_DEF( FT_UInt ) + tt_cmap12_char_next( FT_CMap cmap, /* TT_CMap12 */ FT_UInt32 *pchar_code ) { TT_CMap12 cmap12 = (TT_CMap12)cmap; FT_UInt gindex; + if ( *pchar_code >= 0xFFFFFFFFUL ) + return 0; + /* no need to search */ if ( cmap12->valid && cmap12->cur_charcode == *pchar_code ) { - tt_cmap12_next( cmap12 ); + tt_cmap12_next( FT_CMAP( cmap12 ) ); if ( cmap12->valid ) { gindex = cmap12->cur_gindex; @@ -2518,17 +2513,18 @@ gindex = 0; } else - gindex = tt_cmap12_char_map_binary( cmap, pchar_code, 1 ); + gindex = tt_cmap12_char_map_binary( (TT_CMap)cmap, pchar_code, 1 ); return gindex; } FT_CALLBACK_DEF( FT_Error ) - tt_cmap12_get_info( TT_CMap cmap, + tt_cmap12_get_info( FT_CharMap cmap, /* TT_CMap */ TT_CMapInfo *cmap_info ) { - FT_Byte* p = cmap->data + 8; + TT_CMap ttcmap = (TT_CMap)cmap; + FT_Byte* p = ttcmap->data + 8; cmap_info->format = 12; @@ -2606,15 +2602,19 @@ FT_CALLBACK_DEF( FT_Error ) - tt_cmap13_init( TT_CMap13 cmap, - FT_Byte* table ) + tt_cmap13_init( FT_CMap cmap, /* TT_CMap13 */ + void* table_ ) { - cmap->cmap.data = table; + TT_CMap13 ttcmap = (TT_CMap13)cmap; + FT_Byte* table = (FT_Byte*)table_; - table += 12; - cmap->num_groups = FT_PEEK_ULONG( table ); - cmap->valid = 0; + ttcmap->cmap.data = table; + + table += 12; + ttcmap->num_groups = FT_PEEK_ULONG( table ); + + ttcmap->valid = 0; return FT_Err_Ok; } @@ -2679,23 +2679,21 @@ /* cmap->cur_group should be set up properly by caller */ /* */ static void - tt_cmap13_next( TT_CMap13 cmap ) + tt_cmap13_next( FT_CMap cmap ) /* TT_CMap13 */ { - FT_Face face = cmap->cmap.cmap.charmap.face; - FT_Byte* p; - FT_ULong start, end, glyph_id, char_code; - FT_ULong n; - FT_UInt gindex; + TT_CMap13 ttcmap = (TT_CMap13)cmap; + FT_Face face = FT_CMAP_FACE( cmap ); + FT_Byte* p; + FT_ULong start, end, glyph_id, char_code; + FT_ULong n; + FT_UInt gindex; - if ( cmap->cur_charcode >= 0xFFFFFFFFUL ) - goto Fail; + char_code = ttcmap->cur_charcode + 1; - char_code = cmap->cur_charcode + 1; - - for ( n = cmap->cur_group; n < cmap->num_groups; n++ ) + for ( n = ttcmap->cur_group; n < ttcmap->num_groups; n++ ) { - p = cmap->cmap.data + 16 + 12 * n; + p = ttcmap->cmap.data + 16 + 12 * n; start = TT_NEXT_ULONG( p ); end = TT_NEXT_ULONG( p ); glyph_id = TT_PEEK_ULONG( p ); @@ -2709,17 +2707,16 @@ if ( gindex && gindex < (FT_UInt)face->num_glyphs ) { - cmap->cur_charcode = char_code; - cmap->cur_gindex = gindex; - cmap->cur_group = n; + ttcmap->cur_charcode = char_code; + ttcmap->cur_gindex = gindex; + ttcmap->cur_group = n; return; } } } - Fail: - cmap->valid = 0; + ttcmap->valid = 0; } @@ -2731,7 +2728,7 @@ FT_UInt gindex = 0; FT_Byte* p = cmap->data + 12; FT_UInt32 num_groups = TT_PEEK_ULONG( p ); - FT_UInt32 char_code = *pchar_code; + FT_UInt32 char_code = *pchar_code + next; FT_UInt32 start, end; FT_UInt32 max, min, mid; @@ -2739,23 +2736,11 @@ if ( !num_groups ) return 0; - /* make compiler happy */ - mid = num_groups; - end = 0xFFFFFFFFUL; - - if ( next ) - { - if ( char_code >= 0xFFFFFFFFUL ) - return 0; - - char_code++; - } - min = 0; max = num_groups; /* binary search */ - while ( min < max ) + do { mid = ( min + max ) >> 1; p = cmap->data + 16 + 12 * mid; @@ -2774,6 +2759,7 @@ break; } } + while ( min < max ); if ( next ) { @@ -2784,12 +2770,8 @@ /* if `char_code' is not in any group, then `mid' is */ /* the group nearest to `char_code' */ - if ( char_code > end ) - { - mid++; - if ( mid == num_groups ) - return 0; - } + if ( char_code > end && ++mid == num_groups ) + return 0; cmap13->valid = 1; cmap13->cur_charcode = char_code; @@ -2800,7 +2782,7 @@ if ( !gindex ) { - tt_cmap13_next( cmap13 ); + tt_cmap13_next( FT_CMAP( cmap13 ) ); if ( cmap13->valid ) gindex = cmap13->cur_gindex; @@ -2816,25 +2798,28 @@ FT_CALLBACK_DEF( FT_UInt ) - tt_cmap13_char_index( TT_CMap cmap, + tt_cmap13_char_index( FT_CMap cmap, /* TT_CMap */ FT_UInt32 char_code ) { - return tt_cmap13_char_map_binary( cmap, &char_code, 0 ); + return tt_cmap13_char_map_binary( (TT_CMap)cmap, &char_code, 0 ); } - FT_CALLBACK_DEF( FT_UInt32 ) - tt_cmap13_char_next( TT_CMap cmap, + FT_CALLBACK_DEF( FT_UInt ) + tt_cmap13_char_next( FT_CMap cmap, /* TT_CMap13 */ FT_UInt32 *pchar_code ) { TT_CMap13 cmap13 = (TT_CMap13)cmap; FT_UInt gindex; + if ( *pchar_code >= 0xFFFFFFFFUL ) + return 0; + /* no need to search */ if ( cmap13->valid && cmap13->cur_charcode == *pchar_code ) { - tt_cmap13_next( cmap13 ); + tt_cmap13_next( FT_CMAP( cmap13 ) ); if ( cmap13->valid ) { gindex = cmap13->cur_gindex; @@ -2844,17 +2829,18 @@ gindex = 0; } else - gindex = tt_cmap13_char_map_binary( cmap, pchar_code, 1 ); + gindex = tt_cmap13_char_map_binary( (TT_CMap)cmap, pchar_code, 1 ); return gindex; } FT_CALLBACK_DEF( FT_Error ) - tt_cmap13_get_info( TT_CMap cmap, + tt_cmap13_get_info( FT_CharMap cmap, /* TT_CMap */ TT_CMapInfo *cmap_info ) { - FT_Byte* p = cmap->data + 8; + TT_CMap ttcmap = (TT_CMap)cmap; + FT_Byte* p = ttcmap->data + 8; cmap_info->format = 13; @@ -2969,14 +2955,15 @@ FT_CALLBACK_DEF( void ) - tt_cmap14_done( TT_CMap14 cmap ) + tt_cmap14_done( FT_CMap cmap ) /* TT_CMap14 */ { - FT_Memory memory = cmap->memory; + TT_CMap14 ttcmap = (TT_CMap14)cmap; + FT_Memory memory = ttcmap->memory; - cmap->max_results = 0; - if ( memory && cmap->results ) - FT_FREE( cmap->results ); + ttcmap->max_results = 0; + if ( memory && ttcmap->results ) + FT_FREE( ttcmap->results ); } @@ -3004,15 +2991,19 @@ FT_CALLBACK_DEF( FT_Error ) - tt_cmap14_init( TT_CMap14 cmap, - FT_Byte* table ) + tt_cmap14_init( FT_CMap cmap, /* TT_CMap14 */ + void* table_ ) { - cmap->cmap.data = table; + TT_CMap14 ttcmap = (TT_CMap14)cmap; + FT_Byte* table = (FT_Byte*)table_; - table += 6; - cmap->num_selectors = FT_PEEK_ULONG( table ); - cmap->max_results = 0; - cmap->results = NULL; + + ttcmap->cmap.data = table; + + table += 6; + ttcmap->num_selectors = FT_PEEK_ULONG( table ); + ttcmap->max_results = 0; + ttcmap->results = NULL; return FT_Err_Ok; } @@ -3142,7 +3133,7 @@ FT_CALLBACK_DEF( FT_UInt ) - tt_cmap14_char_index( TT_CMap cmap, + tt_cmap14_char_index( FT_CMap cmap, FT_UInt32 char_code ) { FT_UNUSED( cmap ); @@ -3153,8 +3144,8 @@ } - FT_CALLBACK_DEF( FT_UInt32 ) - tt_cmap14_char_next( TT_CMap cmap, + FT_CALLBACK_DEF( FT_UInt ) + tt_cmap14_char_next( FT_CMap cmap, FT_UInt32 *pchar_code ) { FT_UNUSED( cmap ); @@ -3166,7 +3157,7 @@ FT_CALLBACK_DEF( FT_Error ) - tt_cmap14_get_info( TT_CMap cmap, + tt_cmap14_get_info( FT_CharMap cmap, TT_CMapInfo *cmap_info ) { FT_UNUSED( cmap ); @@ -3280,12 +3271,16 @@ FT_CALLBACK_DEF( FT_UInt ) - tt_cmap14_char_var_index( TT_CMap cmap, - TT_CMap ucmap, + tt_cmap14_char_var_index( FT_CMap cmap, /* TT_CMap */ + FT_CMap ucmap, /* TT_CMap */ FT_UInt32 charcode, FT_UInt32 variantSelector ) { - FT_Byte* p = tt_cmap14_find_variant( cmap->data + 6, variantSelector ); + TT_CMap ttcmap = (TT_CMap)cmap; + TT_CMap ttucmap = (TT_CMap)ucmap; + + FT_Byte* p = tt_cmap14_find_variant( ttcmap->data + 6, + variantSelector ); FT_ULong defOff; FT_ULong nondefOff; @@ -3296,16 +3291,16 @@ defOff = TT_NEXT_ULONG( p ); nondefOff = TT_PEEK_ULONG( p ); - if ( defOff != 0 && - tt_cmap14_char_map_def_binary( cmap->data + defOff, charcode ) ) + if ( defOff != 0 && + tt_cmap14_char_map_def_binary( ttcmap->data + defOff, charcode ) ) { /* This is the default variant of this charcode. GID not stored */ /* here; stored in the normal Unicode charmap instead. */ - return ucmap->cmap.clazz->char_index( &ucmap->cmap, charcode ); + return ttucmap->cmap.clazz->char_index( &ttucmap->cmap, charcode ); } if ( nondefOff != 0 ) - return tt_cmap14_char_map_nondef_binary( cmap->data + nondefOff, + return tt_cmap14_char_map_nondef_binary( ttcmap->data + nondefOff, charcode ); return 0; @@ -3313,11 +3308,13 @@ FT_CALLBACK_DEF( FT_Int ) - tt_cmap14_char_var_isdefault( TT_CMap cmap, + tt_cmap14_char_var_isdefault( FT_CMap cmap, /* TT_CMap */ FT_UInt32 charcode, FT_UInt32 variantSelector ) { - FT_Byte* p = tt_cmap14_find_variant( cmap->data + 6, variantSelector ); + TT_CMap ttcmap = (TT_CMap)cmap; + FT_Byte* p = tt_cmap14_find_variant( ttcmap->data + 6, + variantSelector ); FT_ULong defOff; FT_ULong nondefOff; @@ -3328,13 +3325,13 @@ defOff = TT_NEXT_ULONG( p ); nondefOff = TT_NEXT_ULONG( p ); - if ( defOff != 0 && - tt_cmap14_char_map_def_binary( cmap->data + defOff, charcode ) ) + if ( defOff != 0 && + tt_cmap14_char_map_def_binary( ttcmap->data + defOff, charcode ) ) return 1; - if ( nondefOff != 0 && - tt_cmap14_char_map_nondef_binary( cmap->data + nondefOff, - charcode ) != 0 ) + if ( nondefOff != 0 && + tt_cmap14_char_map_nondef_binary( ttcmap->data + nondefOff, + charcode ) != 0 ) return 0; return -1; @@ -3342,12 +3339,13 @@ FT_CALLBACK_DEF( FT_UInt32* ) - tt_cmap14_variants( TT_CMap cmap, + tt_cmap14_variants( FT_CMap cmap, /* TT_CMap14 */ FT_Memory memory ) { + TT_CMap ttcmap = (TT_CMap)cmap; TT_CMap14 cmap14 = (TT_CMap14)cmap; FT_UInt32 count = cmap14->num_selectors; - FT_Byte* p = cmap->data + 10; + FT_Byte* p = ttcmap->data + 10; FT_UInt32* result; FT_UInt32 i; @@ -3368,13 +3366,14 @@ FT_CALLBACK_DEF( FT_UInt32 * ) - tt_cmap14_char_variants( TT_CMap cmap, + tt_cmap14_char_variants( FT_CMap cmap, /* TT_CMap14 */ FT_Memory memory, FT_UInt32 charCode ) { - TT_CMap14 cmap14 = (TT_CMap14) cmap; + TT_CMap ttcmap = (TT_CMap)cmap; + TT_CMap14 cmap14 = (TT_CMap14)cmap; FT_UInt32 count = cmap14->num_selectors; - FT_Byte* p = cmap->data + 10; + FT_Byte* p = ttcmap->data + 10; FT_UInt32* q; @@ -3388,12 +3387,12 @@ FT_ULong nondefOff = TT_NEXT_ULONG( p ); - if ( ( defOff != 0 && - tt_cmap14_char_map_def_binary( cmap->data + defOff, - charCode ) ) || - ( nondefOff != 0 && - tt_cmap14_char_map_nondef_binary( cmap->data + nondefOff, - charCode ) != 0 ) ) + if ( ( defOff != 0 && + tt_cmap14_char_map_def_binary( ttcmap->data + defOff, + charCode ) ) || + ( nondefOff != 0 && + tt_cmap14_char_map_nondef_binary( ttcmap->data + nondefOff, + charCode ) != 0 ) ) { q[0] = varSel; q++; @@ -3489,15 +3488,16 @@ FT_CALLBACK_DEF( FT_UInt32 * ) - tt_cmap14_variant_chars( TT_CMap cmap, + tt_cmap14_variant_chars( FT_CMap cmap, /* TT_CMap */ FT_Memory memory, FT_UInt32 variantSelector ) { - FT_Byte *p = tt_cmap14_find_variant( cmap->data + 6, - variantSelector ); - FT_Int i; - FT_ULong defOff; - FT_ULong nondefOff; + TT_CMap ttcmap = (TT_CMap)cmap; + FT_Byte *p = tt_cmap14_find_variant( ttcmap->data + 6, + variantSelector ); + FT_Int i; + FT_ULong defOff; + FT_ULong nondefOff; if ( !p ) @@ -3510,16 +3510,16 @@ return NULL; if ( defOff == 0 ) - return tt_cmap14_get_nondef_chars( cmap, cmap->data + nondefOff, + return tt_cmap14_get_nondef_chars( ttcmap, ttcmap->data + nondefOff, memory ); else if ( nondefOff == 0 ) - return tt_cmap14_get_def_chars( cmap, cmap->data + defOff, + return tt_cmap14_get_def_chars( ttcmap, ttcmap->data + defOff, memory ); else { /* Both a default and a non-default glyph set? That's probably not */ /* good font design, but the spec allows for it... */ - TT_CMap14 cmap14 = (TT_CMap14) cmap; + TT_CMap14 cmap14 = (TT_CMap14)cmap; FT_UInt32 numRanges; FT_UInt32 numMappings; FT_UInt32 duni; @@ -3531,18 +3531,18 @@ FT_UInt32 *ret; - p = cmap->data + nondefOff; - dp = cmap->data + defOff; + p = ttcmap->data + nondefOff; + dp = ttcmap->data + defOff; numMappings = (FT_UInt32)TT_NEXT_ULONG( p ); dcnt = tt_cmap14_def_char_count( dp ); numRanges = (FT_UInt32)TT_NEXT_ULONG( dp ); if ( numMappings == 0 ) - return tt_cmap14_get_def_chars( cmap, cmap->data + defOff, + return tt_cmap14_get_def_chars( ttcmap, ttcmap->data + defOff, memory ); if ( dcnt == 0 ) - return tt_cmap14_get_nondef_chars( cmap, cmap->data + nondefOff, + return tt_cmap14_get_nondef_chars( ttcmap, ttcmap->data + nondefOff, memory ); if ( tt_cmap14_ensure( cmap14, ( dcnt + numMappings + 1 ), memory ) ) @@ -3664,9 +3664,10 @@ #ifdef FT_CONFIG_OPTION_POSTSCRIPT_NAMES FT_CALLBACK_DEF( const char * ) - tt_get_glyph_name( TT_Face face, + tt_get_glyph_name( void* face_, /* TT_Face */ FT_UInt idx ) { + TT_Face face = (TT_Face)face_; FT_String* PSname = NULL; @@ -3677,12 +3678,13 @@ FT_CALLBACK_DEF( FT_Error ) - tt_cmap_unicode_init( PS_Unicodes unicodes, - FT_Pointer pointer ) + tt_cmap_unicode_init( FT_CMap cmap, /* PS_Unicodes */ + FT_Pointer pointer ) { - TT_Face face = (TT_Face)FT_CMAP_FACE( unicodes ); - FT_Memory memory = FT_FACE_MEMORY( face ); - FT_Service_PsCMaps psnames = (FT_Service_PsCMaps)face->psnames; + PS_Unicodes unicodes = (PS_Unicodes)cmap; + TT_Face face = (TT_Face)FT_CMAP_FACE( cmap ); + FT_Memory memory = FT_FACE_MEMORY( face ); + FT_Service_PsCMaps psnames = (FT_Service_PsCMaps)face->psnames; FT_UNUSED( pointer ); @@ -3693,17 +3695,18 @@ return psnames->unicodes_init( memory, unicodes, face->root.num_glyphs, - (PS_GetGlyphNameFunc)&tt_get_glyph_name, + &tt_get_glyph_name, (PS_FreeGlyphNameFunc)NULL, (FT_Pointer)face ); } FT_CALLBACK_DEF( void ) - tt_cmap_unicode_done( PS_Unicodes unicodes ) + tt_cmap_unicode_done( FT_CMap cmap ) /* PS_Unicodes */ { - FT_Face face = FT_CMAP_FACE( unicodes ); - FT_Memory memory = FT_FACE_MEMORY( face ); + PS_Unicodes unicodes = (PS_Unicodes)cmap; + FT_Face face = FT_CMAP_FACE( cmap ); + FT_Memory memory = FT_FACE_MEMORY( face ); FT_FREE( unicodes->maps ); @@ -3712,23 +3715,25 @@ FT_CALLBACK_DEF( FT_UInt ) - tt_cmap_unicode_char_index( PS_Unicodes unicodes, - FT_UInt32 char_code ) + tt_cmap_unicode_char_index( FT_CMap cmap, /* PS_Unicodes */ + FT_UInt32 char_code ) { - TT_Face face = (TT_Face)FT_CMAP_FACE( unicodes ); - FT_Service_PsCMaps psnames = (FT_Service_PsCMaps)face->psnames; + PS_Unicodes unicodes = (PS_Unicodes)cmap; + TT_Face face = (TT_Face)FT_CMAP_FACE( cmap ); + FT_Service_PsCMaps psnames = (FT_Service_PsCMaps)face->psnames; return psnames->unicodes_char_index( unicodes, char_code ); } - FT_CALLBACK_DEF( FT_UInt32 ) - tt_cmap_unicode_char_next( PS_Unicodes unicodes, - FT_UInt32 *pchar_code ) + FT_CALLBACK_DEF( FT_UInt ) + tt_cmap_unicode_char_next( FT_CMap cmap, /* PS_Unicodes */ + FT_UInt32 *pchar_code ) { - TT_Face face = (TT_Face)FT_CMAP_FACE( unicodes ); - FT_Service_PsCMaps psnames = (FT_Service_PsCMaps)face->psnames; + PS_Unicodes unicodes = (PS_Unicodes)cmap; + TT_Face face = (TT_Face)FT_CMAP_FACE( cmap ); + FT_Service_PsCMaps psnames = (FT_Service_PsCMaps)face->psnames; return psnames->unicodes_char_next( unicodes, pchar_code ); @@ -3883,7 +3888,7 @@ tt_get_cmap_info( FT_CharMap charmap, TT_CMapInfo *cmap_info ) { - FT_CMap cmap = (FT_CMap)charmap; + FT_CMap cmap = FT_CMAP( charmap ); TT_CMap_Class clazz = (TT_CMap_Class)cmap->clazz; diff --git a/src/3rdparty/freetype/src/sfnt/ttcolr.c b/src/3rdparty/freetype/src/sfnt/ttcolr.c index 5d98dcab8ff..69ccf0ee7ae 100644 --- a/src/3rdparty/freetype/src/sfnt/ttcolr.c +++ b/src/3rdparty/freetype/src/sfnt/ttcolr.c @@ -699,7 +699,7 @@ item_deltas ) ) return 0; - apaint->u.solid.color.alpha += item_deltas[0]; + apaint->u.solid.color.alpha += (FT_F2Dot14)item_deltas[0]; } #endif @@ -1646,7 +1646,7 @@ return 0; color_stop->stop_offset += F2DOT14_TO_FIXED( item_deltas[0] ); - color_stop->color.alpha += item_deltas[1]; + color_stop->color.alpha += (FT_F2Dot14)item_deltas[1]; } #else FT_UNUSED( var_index_base ); @@ -1914,7 +1914,7 @@ #else /* !TT_CONFIG_OPTION_COLOR_LAYERS */ /* ANSI C doesn't like empty source files */ - typedef int _tt_colr_dummy; + typedef int tt_colr_dummy_; #endif /* !TT_CONFIG_OPTION_COLOR_LAYERS */ diff --git a/src/3rdparty/freetype/src/sfnt/ttcpal.c b/src/3rdparty/freetype/src/sfnt/ttcpal.c index 4279bc0bd10..46ae08596f3 100644 --- a/src/3rdparty/freetype/src/sfnt/ttcpal.c +++ b/src/3rdparty/freetype/src/sfnt/ttcpal.c @@ -303,7 +303,7 @@ #else /* !TT_CONFIG_OPTION_COLOR_LAYERS */ /* ANSI C doesn't like empty source files */ - typedef int _tt_cpal_dummy; + typedef int tt_cpal_dummy_; #endif /* !TT_CONFIG_OPTION_COLOR_LAYERS */ diff --git a/src/3rdparty/freetype/src/sfnt/ttload.c b/src/3rdparty/freetype/src/sfnt/ttload.c index 14f625c8243..7b44e9cd2e7 100644 --- a/src/3rdparty/freetype/src/sfnt/ttload.c +++ b/src/3rdparty/freetype/src/sfnt/ttload.c @@ -504,6 +504,13 @@ FT_FRAME_EXIT(); + if ( !valid_entries ) + { + FT_TRACE2(( "tt_face_load_font_dir: no valid tables found\n" )); + error = FT_THROW( Unknown_File_Format ); + goto Exit; + } + FT_TRACE2(( "table directory loaded\n" )); FT_TRACE2(( "\n" )); diff --git a/src/3rdparty/freetype/src/sfnt/ttmtx.c b/src/3rdparty/freetype/src/sfnt/ttmtx.c index 5e53e6dd4a3..38ee9ae728a 100644 --- a/src/3rdparty/freetype/src/sfnt/ttmtx.c +++ b/src/3rdparty/freetype/src/sfnt/ttmtx.c @@ -239,7 +239,7 @@ #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT FT_Service_MetricsVariations var = - (FT_Service_MetricsVariations)face->var; + (FT_Service_MetricsVariations)face->tt_var; #endif diff --git a/src/3rdparty/freetype/src/sfnt/ttpost.c b/src/3rdparty/freetype/src/sfnt/ttpost.c index 0e17c6f34ae..1dfad4298bd 100644 --- a/src/3rdparty/freetype/src/sfnt/ttpost.c +++ b/src/3rdparty/freetype/src/sfnt/ttpost.c @@ -156,86 +156,66 @@ static FT_Error - load_format_20( TT_Face face, - FT_Stream stream, - FT_ULong post_len ) + load_format_20( TT_Post_Names names, + FT_Stream stream, + FT_UShort num_glyphs, + FT_ULong post_len ) { FT_Memory memory = stream->memory; FT_Error error; - FT_Int num_glyphs; - FT_UShort num_names; + FT_UShort n; + FT_UShort num_names = 0; FT_UShort* glyph_indices = NULL; - FT_Char** name_strings = NULL; - FT_Byte* strings = NULL; + FT_Byte** name_strings = NULL; + FT_Byte* q; - if ( FT_READ_USHORT( num_glyphs ) ) - goto Exit; - - /* UNDOCUMENTED! The number of glyphs in this table can be smaller */ - /* than the value in the maxp table (cf. cyberbit.ttf). */ - - /* There already exist fonts which have more than 32768 glyph names */ - /* in this table, so the test for this threshold has been dropped. */ - - if ( num_glyphs > face->max_profile.numGlyphs || - (FT_ULong)num_glyphs * 2UL > post_len - 2 ) + if ( (FT_ULong)num_glyphs * 2 > post_len ) { error = FT_THROW( Invalid_File_Format ); goto Exit; } - /* load the indices */ + /* load the indices and note their maximum */ + if ( FT_QNEW_ARRAY( glyph_indices, num_glyphs ) || + FT_FRAME_ENTER( num_glyphs * 2 ) ) + goto Fail; + + q = (FT_Byte*)stream->cursor; + + for ( n = 0; n < num_glyphs; n++ ) { - FT_Int n; + FT_UShort idx = FT_NEXT_USHORT( q ); - if ( FT_QNEW_ARRAY( glyph_indices, num_glyphs ) || - FT_FRAME_ENTER( num_glyphs * 2L ) ) - goto Fail; + if ( idx > num_names ) + num_names = idx; - for ( n = 0; n < num_glyphs; n++ ) - glyph_indices[n] = FT_GET_USHORT(); - - FT_FRAME_EXIT(); + glyph_indices[n] = idx; } - /* compute number of names stored in table */ - { - FT_Int n; + FT_FRAME_EXIT(); - - num_names = 0; - - for ( n = 0; n < num_glyphs; n++ ) - { - FT_Int idx; - - - idx = glyph_indices[n]; - if ( idx >= 258 ) - { - idx -= 257; - if ( idx > num_names ) - num_names = (FT_UShort)idx; - } - } - } + /* compute number of names stored in the table */ + num_names = num_names > 257 ? num_names - 257 : 0; /* now load the name strings */ if ( num_names ) { - FT_UShort n; FT_ULong p; + FT_Byte* strings; - post_len -= (FT_ULong)num_glyphs * 2UL + 2; + post_len -= (FT_ULong)num_glyphs * 2; - if ( FT_QALLOC( strings, post_len + 1 ) || - FT_STREAM_READ( strings, post_len ) || - FT_QNEW_ARRAY( name_strings, num_names ) ) + if ( FT_QALLOC( name_strings, num_names * sizeof ( FT_Byte* ) + + post_len + 1 ) ) + goto Fail; + + strings = (FT_Byte*)( name_strings + num_names ); + if ( FT_STREAM_READ( strings, post_len ) ) goto Fail; /* convert from Pascal- to C-strings and set pointers */ @@ -251,7 +231,7 @@ } strings[p] = 0; - name_strings[n] = (FT_Char*)strings + p + 1; + name_strings[n] = strings + p + 1; p += len + 1; } strings[post_len] = 0; @@ -259,40 +239,24 @@ /* deal with missing or insufficient string data */ if ( n < num_names ) { - if ( post_len == 0 ) - { - /* fake empty string */ - if ( FT_QREALLOC( strings, 1, 2 ) ) - goto Fail; + FT_TRACE4(( "load_format_20: %hu PostScript names are truncated\n", + num_names - n )); - post_len = 1; - strings[post_len] = 0; - } - - FT_ERROR(( "load_format_20:" - " all entries in post table are already parsed," - " using NULL names for gid %d - %d\n", - n, num_names - 1 )); for ( ; n < num_names; n++ ) - name_strings[n] = (FT_Char*)strings + post_len; + name_strings[n] = strings + post_len; } } /* all right, set table fields and exit successfully */ - { - TT_Post_20 table = &face->postscript_names.names.format_20; + names->num_glyphs = num_glyphs; + names->num_names = num_names; + names->glyph_indices = glyph_indices; + names->glyph_names = name_strings; - - table->num_glyphs = (FT_UShort)num_glyphs; - table->num_names = (FT_UShort)num_names; - table->glyph_indices = glyph_indices; - table->glyph_names = name_strings; - } return FT_Err_Ok; Fail: FT_FREE( name_strings ); - FT_FREE( strings ); FT_FREE( glyph_indices ); Exit: @@ -301,66 +265,55 @@ static FT_Error - load_format_25( TT_Face face, - FT_Stream stream, - FT_ULong post_len ) + load_format_25( TT_Post_Names names, + FT_Stream stream, + FT_UShort num_glyphs, + FT_ULong post_len ) { FT_Memory memory = stream->memory; FT_Error error; - FT_Int num_glyphs; - FT_Char* offset_table = NULL; - - FT_UNUSED( post_len ); + FT_UShort n; + FT_UShort* glyph_indices = NULL; + FT_Byte* q; - if ( FT_READ_USHORT( num_glyphs ) ) - goto Exit; - - /* check the number of glyphs */ - if ( num_glyphs > face->max_profile.numGlyphs || - num_glyphs > 258 || - num_glyphs < 1 ) + /* check the number of glyphs, including the theoretical limit */ + if ( num_glyphs > post_len || + num_glyphs > 258 + 128 ) { error = FT_THROW( Invalid_File_Format ); goto Exit; } - if ( FT_QNEW_ARRAY( offset_table, num_glyphs ) || - FT_STREAM_READ( offset_table, num_glyphs ) ) + /* load the indices and check their Mac range */ + if ( FT_QNEW_ARRAY( glyph_indices, num_glyphs ) || + FT_FRAME_ENTER( num_glyphs ) ) goto Fail; - /* now check the offset table */ + q = (FT_Byte*)stream->cursor; + + for ( n = 0; n < num_glyphs; n++ ) { - FT_Int n; + FT_Int idx = n + FT_NEXT_CHAR( q ); - for ( n = 0; n < num_glyphs; n++ ) - { - FT_Long idx = (FT_Long)n + offset_table[n]; + if ( idx < 0 || idx > 257 ) + idx = 0; - - if ( idx < 0 || idx > num_glyphs ) - { - error = FT_THROW( Invalid_File_Format ); - goto Fail; - } - } + glyph_indices[n] = (FT_UShort)idx; } + FT_FRAME_EXIT(); + /* OK, set table fields and exit successfully */ - { - TT_Post_25 table = &face->postscript_names.names.format_25; - - - table->num_glyphs = (FT_UShort)num_glyphs; - table->offsets = offset_table; - } + names->num_glyphs = num_glyphs; + names->glyph_indices = glyph_indices; return FT_Err_Ok; Fail: - FT_FREE( offset_table ); + FT_FREE( glyph_indices ); Exit: return error; @@ -370,37 +323,37 @@ static FT_Error load_post_names( TT_Face face ) { - FT_Stream stream; - FT_Error error; - FT_Fixed format; + FT_Error error = FT_Err_Ok; + FT_Stream stream = face->root.stream; + FT_Fixed format = face->postscript.FormatType; FT_ULong post_len; + FT_UShort num_glyphs; - /* get a stream for the face's resource */ - stream = face->root.stream; - /* seek to the beginning of the PS names table */ error = face->goto_table( face, TTAG_post, stream, &post_len ); if ( error ) goto Exit; - format = face->postscript.FormatType; - - /* go to beginning of subtable */ - if ( FT_STREAM_SKIP( 32 ) ) + /* UNDOCUMENTED! The number of glyphs in this table can be smaller */ + /* than the value in the maxp table (cf. cyberbit.ttf). */ + if ( post_len < 34 || + FT_STREAM_SKIP( 32 ) || + FT_READ_USHORT( num_glyphs ) || + num_glyphs > face->max_profile.numGlyphs || + num_glyphs == 0 ) goto Exit; - /* now read postscript table */ - if ( format == 0x00020000L && post_len >= 34 ) - error = load_format_20( face, stream, post_len - 32 ); - else if ( format == 0x00025000L && post_len >= 34 ) - error = load_format_25( face, stream, post_len - 32 ); - else - error = FT_THROW( Invalid_File_Format ); - - face->postscript_names.loaded = 1; + /* now read postscript names data */ + if ( format == 0x00020000L ) + error = load_format_20( &face->postscript_names, stream, + num_glyphs, post_len - 34 ); + else if ( format == 0x00025000L ) + error = load_format_25( &face->postscript_names, stream, + num_glyphs, post_len - 34 ); Exit: + face->postscript_names.loaded = 1; /* even if failed */ return error; } @@ -410,39 +363,20 @@ { FT_Memory memory = face->root.memory; TT_Post_Names names = &face->postscript_names; - FT_Fixed format; - if ( names->loaded ) + if ( names->num_glyphs ) { - format = face->postscript.FormatType; - - if ( format == 0x00020000L ) - { - TT_Post_20 table = &names->names.format_20; - - - FT_FREE( table->glyph_indices ); - table->num_glyphs = 0; - - if ( table->num_names ) - { - table->glyph_names[0]--; - FT_FREE( table->glyph_names[0] ); - - FT_FREE( table->glyph_names ); - table->num_names = 0; - } - } - else if ( format == 0x00025000L ) - { - TT_Post_25 table = &names->names.format_25; - - - FT_FREE( table->offsets ); - table->num_glyphs = 0; - } + FT_FREE( names->glyph_indices ); + names->num_glyphs = 0; } + + if ( names->num_names ) + { + FT_FREE( names->glyph_names ); + names->num_names = 0; + } + names->loaded = 0; } @@ -478,7 +412,6 @@ FT_String** PSname ) { FT_Error error; - TT_Post_Names names; FT_Fixed format; #ifdef FT_CONFIG_OPTION_POSTSCRIPT_NAMES @@ -498,8 +431,6 @@ return FT_THROW( Unimplemented_Feature ); #endif - names = &face->postscript_names; - /* `.notdef' by default */ *PSname = MAC_NAME( 0 ); @@ -510,9 +441,10 @@ if ( idx < 258 ) /* paranoid checking */ *PSname = MAC_NAME( idx ); } - else if ( format == 0x00020000L ) + else if ( format == 0x00020000L || + format == 0x00025000L ) { - TT_Post_20 table = &names->names.format_20; + TT_Post_Names names = &face->postscript_names; if ( !names->loaded ) @@ -522,43 +454,29 @@ goto End; } - if ( idx < (FT_UInt)table->num_glyphs ) + if ( idx < (FT_UInt)names->num_glyphs ) { - FT_UShort name_index = table->glyph_indices[idx]; + FT_UShort name_index = names->glyph_indices[idx]; if ( name_index < 258 ) *PSname = MAC_NAME( name_index ); - else - *PSname = (FT_String*)table->glyph_names[name_index - 258]; + else /* only for version 2.0 */ + *PSname = (FT_String*)names->glyph_names[name_index - 258]; } } - else if ( format == 0x00025000L ) - { - TT_Post_25 table = &names->names.format_25; - - - if ( !names->loaded ) - { - error = load_post_names( face ); - if ( error ) - goto End; - } - - if ( idx < (FT_UInt)table->num_glyphs ) /* paranoid checking */ - *PSname = MAC_NAME( (FT_Int)idx + table->offsets[idx] ); - } /* nothing to do for format == 0x00030000L */ End: + /* post format errors ignored */ return FT_Err_Ok; } #else /* !TT_CONFIG_OPTION_POSTSCRIPT_NAMES */ /* ANSI C doesn't like empty source files */ - typedef int _tt_post_dummy; + typedef int tt_post_dummy_; #endif /* !TT_CONFIG_OPTION_POSTSCRIPT_NAMES */ diff --git a/src/3rdparty/freetype/src/sfnt/ttsbit.c b/src/3rdparty/freetype/src/sfnt/ttsbit.c index 3c069551315..03f90a628d6 100644 --- a/src/3rdparty/freetype/src/sfnt/ttsbit.c +++ b/src/3rdparty/freetype/src/sfnt/ttsbit.c @@ -1677,7 +1677,7 @@ #else /* !TT_CONFIG_OPTION_EMBEDDED_BITMAPS */ /* ANSI C doesn't like empty source files */ - typedef int _tt_sbit_dummy; + typedef int tt_sbit_dummy_; #endif /* !TT_CONFIG_OPTION_EMBEDDED_BITMAPS */ diff --git a/src/3rdparty/freetype/src/sfnt/ttsvg.c b/src/3rdparty/freetype/src/sfnt/ttsvg.c index c1bbb66b817..4461d483b0f 100644 --- a/src/3rdparty/freetype/src/sfnt/ttsvg.c +++ b/src/3rdparty/freetype/src/sfnt/ttsvg.c @@ -405,7 +405,7 @@ #else /* !FT_CONFIG_OPTION_SVG */ /* ANSI C doesn't like empty source files */ - typedef int _tt_svg_dummy; + typedef int tt_svg_dummy_; #endif /* !FT_CONFIG_OPTION_SVG */ diff --git a/src/3rdparty/freetype/src/sfnt/woff2tags.c b/src/3rdparty/freetype/src/sfnt/woff2tags.c index 7a0a351f06c..eeedd9906be 100644 --- a/src/3rdparty/freetype/src/sfnt/woff2tags.c +++ b/src/3rdparty/freetype/src/sfnt/woff2tags.c @@ -111,7 +111,7 @@ #else /* !FT_CONFIG_OPTION_USE_BROTLI */ /* ANSI C doesn't like empty source files */ - typedef int _woff2tags_dummy; + typedef int woff2tags_dummy_; #endif /* !FT_CONFIG_OPTION_USE_BROTLI */ diff --git a/src/3rdparty/freetype/src/smooth/ftgrays.c b/src/3rdparty/freetype/src/smooth/ftgrays.c index d9f20eef131..6252df98ae6 100644 --- a/src/3rdparty/freetype/src/smooth/ftgrays.c +++ b/src/3rdparty/freetype/src/smooth/ftgrays.c @@ -1006,9 +1006,9 @@ typedef ptrdiff_t FT_PtrDist; * * For other cases, using binary splits is actually slightly faster. */ -#if defined( __SSE2__ ) || \ - defined( __x86_64__ ) || \ - defined( _M_AMD64 ) || \ +#if defined( __SSE2__ ) || \ + ( defined( __x86_64__ ) && !defined( __VMS ) ) || \ + defined( _M_AMD64 ) || \ ( defined( _M_IX86_FP ) && _M_IX86_FP >= 2 ) # define FT_SSE2 1 #else @@ -1427,8 +1427,10 @@ typedef ptrdiff_t FT_PtrDist; static int gray_move_to( const FT_Vector* to, - gray_PWorker worker ) + void* worker_ ) /* gray_PWorker */ { + gray_PWorker worker = (gray_PWorker)worker_; + TPos x, y; @@ -1446,8 +1448,11 @@ typedef ptrdiff_t FT_PtrDist; static int gray_line_to( const FT_Vector* to, - gray_PWorker worker ) + void* worker_ ) /* gray_PWorker */ { + gray_PWorker worker = (gray_PWorker)worker_; + + gray_render_line( RAS_VAR_ UPSCALE( to->x ), UPSCALE( to->y ) ); return 0; } @@ -1456,8 +1461,11 @@ typedef ptrdiff_t FT_PtrDist; static int gray_conic_to( const FT_Vector* control, const FT_Vector* to, - gray_PWorker worker ) + void* worker_ ) /* gray_PWorker */ { + gray_PWorker worker = (gray_PWorker)worker_; + + gray_render_conic( RAS_VAR_ control, to ); return 0; } @@ -1467,8 +1475,11 @@ typedef ptrdiff_t FT_PtrDist; gray_cubic_to( const FT_Vector* control1, const FT_Vector* control2, const FT_Vector* to, - gray_PWorker worker ) + void* worker_ ) /* gray_PWorker */ { + gray_PWorker worker = (gray_PWorker)worker_; + + gray_render_cubic( RAS_VAR_ control1, control2, to ); return 0; } @@ -1666,6 +1677,8 @@ typedef ptrdiff_t FT_PtrDist; int n; /* index of contour in outline */ int first; /* index of first point in contour */ + int last; /* index of last point in contour */ + char tag; /* current point's state */ int shift; @@ -1680,18 +1693,17 @@ typedef ptrdiff_t FT_PtrDist; shift = func_interface->shift; delta = func_interface->delta; - first = 0; + last = -1; for ( n = 0; n < outline->n_contours; n++ ) { - int last; /* index of last point in contour */ - - - FT_TRACE5(( "FT_Outline_Decompose: Outline %d\n", n )); + FT_TRACE5(( "FT_Outline_Decompose: Contour %d\n", n )); + first = last + 1; last = outline->contours[n]; - if ( last < 0 ) + if ( last < first ) goto Invalid_Outline; + limit = outline->points + last; v_start = outline->points[first]; @@ -1874,11 +1886,9 @@ typedef ptrdiff_t FT_PtrDist; v_start.x / 64.0, v_start.y / 64.0 )); error = func_interface->line_to( &v_start, user ); - Close: + Close: if ( error ) goto Exit; - - first = last + 1; } FT_TRACE5(( "FT_Outline_Decompose: Done\n", n )); @@ -2156,9 +2166,12 @@ typedef ptrdiff_t FT_PtrDist; #else /* !STANDALONE_ */ static int - gray_raster_new( FT_Memory memory, - gray_PRaster* araster ) + gray_raster_new( void* memory_, + FT_Raster* araster_ ) { + FT_Memory memory = (FT_Memory)memory_; + gray_PRaster* araster = (gray_PRaster*)araster_; + FT_Error error; gray_PRaster raster = NULL; diff --git a/src/3rdparty/freetype/src/smooth/ftsmooth.c b/src/3rdparty/freetype/src/smooth/ftsmooth.c index cdbc78c3e53..9b0e8886cb3 100644 --- a/src/3rdparty/freetype/src/smooth/ftsmooth.c +++ b/src/3rdparty/freetype/src/smooth/ftsmooth.c @@ -87,8 +87,10 @@ /* initialize renderer -- init its raster */ static FT_Error - ft_smooth_init( FT_Renderer render ) + ft_smooth_init( FT_Module module ) /* FT_Renderer */ { + FT_Renderer render = (FT_Renderer)module; + FT_Vector* sub = render->root.library->lcd_geometry; @@ -111,8 +113,10 @@ ft_smooth_lcd_spans( int y, int count, const FT_Span* spans, - TOrigin* target ) + void* target_ ) /* TOrigin* */ { + TOrigin* target = (TOrigin*)target_; + unsigned char* dst_line = target->origin - y * target->pitch; unsigned char* dst; unsigned short w; @@ -141,7 +145,7 @@ /* Set up direct rendering to record them on each third byte. */ params.source = outline; params.flags = FT_RASTER_FLAG_AA | FT_RASTER_FLAG_DIRECT; - params.gray_spans = (FT_SpanFunc)ft_smooth_lcd_spans; + params.gray_spans = ft_smooth_lcd_spans; params.user = ⌖ params.clip_box.xMin = 0; @@ -256,8 +260,11 @@ /* initialize renderer -- init its raster */ static FT_Error - ft_smooth_init( FT_Renderer render ) + ft_smooth_init( FT_Module module ) /* FT_Renderer */ { + FT_Renderer render = (FT_Renderer)module; + + /* set up default LCD filtering */ FT_Library_SetLcdFilter( render->root.library, FT_LCD_FILTER_DEFAULT ); @@ -340,8 +347,11 @@ ft_smooth_overlap_spans( int y, int count, const FT_Span* spans, - TOrigin* target ) + void* target_ ) { + TOrigin* target = (TOrigin*)target_; + + unsigned char* dst = target->origin - ( y / SCALE ) * target->pitch; unsigned short x; unsigned int cover, sum; @@ -386,7 +396,7 @@ /* Set up direct rendering to average oversampled spans. */ params.source = outline; params.flags = FT_RASTER_FLAG_AA | FT_RASTER_FLAG_DIRECT; - params.gray_spans = (FT_SpanFunc)ft_smooth_overlap_spans; + params.gray_spans = ft_smooth_overlap_spans; params.user = ⌖ params.clip_box.xMin = 0; diff --git a/src/3rdparty/freetype/src/svg/ftsvg.c b/src/3rdparty/freetype/src/svg/ftsvg.c index 7edb1a338e7..ba237f63809 100644 --- a/src/3rdparty/freetype/src/svg/ftsvg.c +++ b/src/3rdparty/freetype/src/svg/ftsvg.c @@ -40,26 +40,31 @@ /* ft_svg_init */ static FT_Error - ft_svg_init( SVG_Renderer svg_module ) + ft_svg_init( FT_Module module ) { + SVG_Renderer render = (SVG_Renderer)module; + FT_Error error = FT_Err_Ok; - svg_module->loaded = FALSE; - svg_module->hooks_set = FALSE; + render->loaded = FALSE; + render->hooks_set = FALSE; return error; } static void - ft_svg_done( SVG_Renderer svg_module ) + ft_svg_done( FT_Module module ) { - if ( svg_module->loaded == TRUE && - svg_module->hooks_set == TRUE ) - svg_module->hooks.free_svg( &svg_module->state ); + SVG_Renderer render = (SVG_Renderer)module; - svg_module->loaded = FALSE; + + if ( render->loaded == TRUE && + render->hooks_set == TRUE ) + render->hooks.free_svg( &render->state ); + + render->loaded = FALSE; } @@ -148,7 +153,7 @@ static const SVG_Interface svg_interface = { - (Preset_Bitmap_Func)ft_svg_preset_slot + ft_svg_preset_slot /* Preset_Bitmap_Func preset_slot */ }; @@ -203,7 +208,7 @@ static FT_Error ft_svg_property_get( FT_Module module, const char* property_name, - const void* value ) + void* value ) { FT_Error error = FT_Err_Ok; SVG_Renderer renderer = (SVG_Renderer)module; @@ -226,8 +231,8 @@ FT_DEFINE_SERVICE_PROPERTIESREC( ft_svg_service_properties, - (FT_Properties_SetFunc)ft_svg_property_set, /* set_property */ - (FT_Properties_GetFunc)ft_svg_property_get /* get_property */ + ft_svg_property_set, /* FT_Properties_SetFunc set_property */ + ft_svg_property_get /* FT_Properties_GetFunc get_property */ ) @@ -333,17 +338,17 @@ (const void*)PUT_SVG_MODULE( &svg_interface ), /* module specific interface */ - (FT_Module_Constructor)PUT_SVG_MODULE( ft_svg_init ), /* module_init */ - (FT_Module_Destructor)PUT_SVG_MODULE( ft_svg_done ), /* module_done */ - PUT_SVG_MODULE( ft_svg_get_interface ), /* get_interface */ + PUT_SVG_MODULE( ft_svg_init ), /* FT_Module_Constructor module_init */ + PUT_SVG_MODULE( ft_svg_done ), /* FT_Module_Destructor module_done */ + PUT_SVG_MODULE( ft_svg_get_interface ), /* FT_Module_Requester get_interface */ SVG_GLYPH_FORMAT, - (FT_Renderer_RenderFunc) PUT_SVG_MODULE( ft_svg_render ), /* render_glyph */ - (FT_Renderer_TransformFunc)PUT_SVG_MODULE( ft_svg_transform ), /* transform_glyph */ - NULL, /* get_glyph_cbox */ - NULL, /* set_mode */ - NULL /* raster_class */ + PUT_SVG_MODULE( ft_svg_render ), /* FT_Renderer_RenderFunc render_glyph */ + PUT_SVG_MODULE( ft_svg_transform ), /* FT_Renderer_TransformFunc transform_glyph */ + NULL, /* FT_Renderer_GetCBoxFunc get_glyph_cbox */ + NULL, /* FT_Renderer_SetModeFunc set_mode */ + NULL /* FT_Raster_Funcs* raster_class */ ) diff --git a/src/3rdparty/freetype/src/tools/apinames.c b/src/3rdparty/freetype/src/tools/apinames.c index 8a8b0822b13..dfa258fd7dd 100644 --- a/src/3rdparty/freetype/src/tools/apinames.c +++ b/src/3rdparty/freetype/src/tools/apinames.c @@ -18,11 +18,14 @@ #include #include +#include #include #include +#include "vms_shorten_symbol.c" + #define PROGRAM_NAME "apinames" -#define PROGRAM_VERSION "0.4" +#define PROGRAM_VERSION "0.5" #define LINEBUFF_SIZE 1024 @@ -41,9 +44,20 @@ typedef enum OutputFormat_ static void -panic( const char* message ) +panic( const char* fmt, + ... ) { - fprintf( stderr, "PANIC: %s\n", message ); + va_list ap; + + + fprintf( stderr, "PANIC: " ); + + va_start( ap, fmt ); + vfprintf( stderr, fmt, ap ); + va_end( ap ); + + fprintf( stderr, "\n" ); + exit(2); } @@ -202,12 +216,24 @@ names_dump( FILE* out, break; case OUTPUT_VMS_OPT: - fprintf( out, "GSMATCH=LEQUAL,2,0\n" - "CASE_SENSITIVE=YES\n" - "SYMBOL_VECTOR=(-\n" ); - for ( nn = 0; nn < num_names - 1; nn++ ) - fprintf( out, " %s=PROCEDURE,-\n", the_names[nn].name ); - fprintf( out, " %s=PROCEDURE)\n", the_names[num_names - 1].name ); + fprintf( out, "case_sensitive=YES\n" ); + + for ( nn = 0; nn < num_names; nn++ ) + { + char short_symbol[32]; + + + if ( vms_shorten_symbol( the_names[nn].name, short_symbol, 1 ) == -1 ) + panic( "could not shorten name '%s'", the_names[nn].name ); + fprintf( out, "symbol_vector = ( %s = PROCEDURE)\n", short_symbol ); + + /* Also emit a 64-bit symbol, as created by the `vms_auto64` tool. */ + /* It has the string '64__' appended to its name. */ + strcat( the_names[nn].name , "64__" ); + if ( vms_shorten_symbol( the_names[nn].name, short_symbol, 1 ) == -1 ) + panic( "could not shorten name '%s'", the_names[nn].name ); + fprintf( out, "symbol_vector = ( %s = PROCEDURE)\n", short_symbol ); + } break; diff --git a/src/3rdparty/freetype/src/tools/ftrandom/ftrandom.c b/src/3rdparty/freetype/src/tools/ftrandom/ftrandom.c index 4f912cd21d6..0ee765e528f 100644 --- a/src/3rdparty/freetype/src/tools/ftrandom/ftrandom.c +++ b/src/3rdparty/freetype/src/tools/ftrandom/ftrandom.c @@ -520,7 +520,7 @@ char buffer[1024]; - sprintf( buffer, "%s/test%d", results_dir, test_num++ ); + snprintf( buffer, 1024, "%s/test%d", results_dir, test_num++ ); if ( copyfont ( &fontlist[i], buffer ) ) { diff --git a/src/3rdparty/freetype/src/tools/vms_shorten_symbol.c b/src/3rdparty/freetype/src/tools/vms_shorten_symbol.c new file mode 100644 index 00000000000..81f2a71877f --- /dev/null +++ b/src/3rdparty/freetype/src/tools/vms_shorten_symbol.c @@ -0,0 +1,250 @@ +/* + * Copyright (c) 2010, 2017 Craig A. Berry + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +/* vms_shorten_symbol + * + * This program provides shortening of long symbols (> 31 characters) using the + * same mechanism as the OpenVMS C compiler. The basic procedure is to compute + * an AUTODIN II checksum of the entire symbol, encode the checksum in base32, + * and glue together a shortened symbol from the first 23 characters of the + * original symbol plus the encoded checksum appended. The output format is + * the same used in the name mangler database, stored by default in + * [.CXX_REPOSITORY]CXX$DEMANGLER_DB. + * + * To obtain the same result as CC/NAMES=SHORTENED, run like so: + * + * $ mcr []vms_shorten_symbol "Please_forgive_this_absurdly_long_symbol_name" + * PLEASE_FORGIVE_THIS_ABS1ARO4QU$Please_forgive_this_absurdly_long_symbol_name + * + * To obtain the same result as CC/NAMES=(SHORTENED,AS_IS), pass a non-zero + * value as the second argument, like so: + * + * $ mcr []vms_shorten_symbol "Please_forgive_this_absurdly_long_symbol_name" 1 + * Please_forgive_this_abs3rv8rnn$Please_forgive_this_absurdly_long_symbol_name + */ + +#include +#include +#include +#include + +#ifdef __VMS +#define UINT32 unsigned int +#else +#include +#define UINT32 uint32_t +#endif + +extern UINT32 crc32(const char *input_string); +extern int u32_to_base32(UINT32 input, char *output); +extern int vms_shorten_symbol(const char *symbol, char *shortened, char as_is_flag); + +/* + * This routine implements the AUTODIN II polynomial. + */ + +UINT32 +crc32(const char *input_string) +{ + +/* + * CRC code and data based partly on FreeBSD implementation, which + * notes: + * + * The crc32 functions and data was originally written by Spencer + * Garrett and was cleaned from the PostgreSQL source + * tree via the files contrib/ltree/crc32.[ch]. No license was + * included, therefore it is assumed that this code is public + * domain. Attribution still noted. + * + * (I think they mean "gleaned" not "cleaned".) + */ + + static const UINT32 autodin_ii_table[256] = { + 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, + }; + + UINT32 crc = ~0U; + char *c; + for (c = (char *)input_string; *c; ++c) + crc = (crc >> 8) ^ autodin_ii_table[(crc ^ *c) & 0xff]; + return ~crc; +} + +/* + * This is the RFC2938 variant of base32, not RFC3548, Crockford's, or + * other newer variant. It produces an 8-byte encoded character string + * (plus trailing null) from a 32-bit integer input. + */ + +int +u32_to_base32(UINT32 input, char *output) +{ + static const char base32hex_table[32] = { + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', + 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', + 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', + 'u', 'v' + }; + int i; + + /* + * Grab lowest 5 bits and look up conversion in table. Lather, rinse, + * repeat for a total of 7, 5-bit chunks to accommodate 32 bits of input. + */ + for (i = 0; i < 7; i++) { + output[6 - i] = base32hex_table[input & 0x1f]; + input >>= 5; /* position to look at next 5 */ + } + output[7] = '$'; /* It's DEC, so use '$' not '=' to pad. */ + output[8] = '\0'; + return 0; +} + +/* + * Take an input symbol name of arbitrary length and produce a symbol shortened + * to 31 characters. The shortened symbol consists of the first 23 characters + * of the original symbol plus the 8 characters of the encoded checksum. The + * third argument is a boolean indicating whether to emulate the compiler's + * /NAMES=AS_IS option. When false (the compiler's default), the shortened + * symbol will be upper cased. When the original symbol is 31 characters or + * fewer in length, no checksum will be appended and the original symbol is + * returned verbatim (though upper cased if the as_is_flag is false). + */ + +int +vms_shorten_symbol(const char *input_symbol, char *shortened, char as_is_flag) +{ + char b32str[9]; + UINT32 crc; + char *c, *symbol; + int symlen; + + symlen = strlen(input_symbol); + symbol = (char *)malloc(symlen + 1); + if (symbol == NULL) + return -1; + + strncpy(symbol, input_symbol, symlen); + symbol[symlen] = '\0'; + + if (!as_is_flag) { + for (c = symbol; *c; c++) + *c = toupper(*c); + } + + if (symlen <= 31) { + strncpy(shortened, symbol, symlen); + shortened[symlen] = '\0'; + free(symbol); + return 0; + } + + /* + * Compute the checksum on the whole symbol. + */ + + crc = crc32(symbol); + + /* The compiler does not use the inverted checksum, so we invert it + * back before encoding in base32. + */ + + if (u32_to_base32(~crc, (char *)&b32str) == -1) { + free(symbol); + return -1; + } + + if (!as_is_flag) { + for (c = (char *)&b32str; *c; c++) + *c = toupper(*c); + } + + sprintf(shortened, "%.23s%.8s", symbol, b32str); + shortened[31] = '\0'; + free(symbol); + return 0; +} + +#ifdef TEST_MAIN +int +main(int argc, char **argv) +{ + char short_symbol[32]; + char as_is_flag = 0; + + if (argc < 2) { + fprintf(stderr, "Usage: %s []\n", argv[0]); + exit(EXIT_FAILURE); + } + if (argc > 2) + as_is_flag = 1; + + if (vms_shorten_symbol(argv[1], (char *)&short_symbol, as_is_flag) == -1) { + fprintf(stderr, "Symbol shortening failed\n"); + exit(EXIT_FAILURE); + } + + printf("%s%s\n", (char *)&short_symbol, argv[1]); +} +#endif diff --git a/src/3rdparty/freetype/src/truetype/ttdriver.c b/src/3rdparty/freetype/src/truetype/ttdriver.c index 4bea63ef843..7151e820739 100644 --- a/src/3rdparty/freetype/src/truetype/ttdriver.c +++ b/src/3rdparty/freetype/src/truetype/ttdriver.c @@ -57,7 +57,7 @@ * PROPERTY SERVICE * */ - static FT_Error + FT_CALLBACK_DEF( FT_Error ) tt_property_set( FT_Module module, /* TT_Driver */ const char* property_name, const void* value, @@ -93,17 +93,27 @@ interpreter_version = *iv; } - if ( interpreter_version == TT_INTERPRETER_VERSION_35 + switch ( interpreter_version ) + { + case TT_INTERPRETER_VERSION_35: + driver->interpreter_version = TT_INTERPRETER_VERSION_35; + break; + + case TT_INTERPRETER_VERSION_38: #ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY - || interpreter_version == TT_INTERPRETER_VERSION_38 + driver->interpreter_version = TT_INTERPRETER_VERSION_38; + break; #endif + + case TT_INTERPRETER_VERSION_40: #ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL - || interpreter_version == TT_INTERPRETER_VERSION_40 + driver->interpreter_version = TT_INTERPRETER_VERSION_40; + break; #endif - ) - driver->interpreter_version = interpreter_version; - else + + default: error = FT_ERR( Unimplemented_Feature ); + } return error; } @@ -114,10 +124,10 @@ } - static FT_Error + FT_CALLBACK_DEF( FT_Error ) tt_property_get( FT_Module module, /* TT_Driver */ const char* property_name, - const void* value ) + void* value ) { FT_Error error = FT_Err_Ok; TT_Driver driver = (TT_Driver)module; @@ -144,8 +154,8 @@ FT_DEFINE_SERVICE_PROPERTIESREC( tt_service_properties, - (FT_Properties_SetFunc)tt_property_set, /* set_property */ - (FT_Properties_GetFunc)tt_property_get /* get_property */ + tt_property_set, /* FT_Properties_SetFunc set_property */ + tt_property_get /* FT_Properties_GetFunc get_property */ ) @@ -198,35 +208,35 @@ * * They can be implemented by format-specific interfaces. */ - static FT_Error - tt_get_kerning( FT_Face ttface, /* TT_Face */ + FT_CALLBACK_DEF( FT_Error ) + tt_get_kerning( FT_Face face, /* TT_Face */ FT_UInt left_glyph, FT_UInt right_glyph, FT_Vector* kerning ) { - TT_Face face = (TT_Face)ttface; - SFNT_Service sfnt = (SFNT_Service)face->sfnt; + TT_Face ttface = (TT_Face)face; + SFNT_Service sfnt = (SFNT_Service)ttface->sfnt; kerning->x = 0; kerning->y = 0; if ( sfnt ) - kerning->x = sfnt->get_kerning( face, left_glyph, right_glyph ); + kerning->x = sfnt->get_kerning( ttface, left_glyph, right_glyph ); return 0; } - static FT_Error - tt_get_advances( FT_Face ttface, + FT_CALLBACK_DEF( FT_Error ) + tt_get_advances( FT_Face face, /* TT_Face */ FT_UInt start, FT_UInt count, FT_Int32 flags, FT_Fixed *advances ) { FT_UInt nn; - TT_Face face = (TT_Face)ttface; + TT_Face ttface = (TT_Face)face; /* XXX: TODO: check for sbits */ @@ -235,8 +245,8 @@ { #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT /* no fast retrieval for blended MM fonts without VVAR table */ - if ( ( FT_IS_NAMED_INSTANCE( ttface ) || FT_IS_VARIATION( ttface ) ) && - !( face->variation_support & TT_FACE_FLAG_VAR_VADVANCE ) ) + if ( ( FT_IS_NAMED_INSTANCE( face ) || FT_IS_VARIATION( face ) ) && + !( ttface->variation_support & TT_FACE_FLAG_VAR_VADVANCE ) ) return FT_THROW( Unimplemented_Feature ); #endif @@ -247,7 +257,7 @@ /* since we don't need `tsb', we use zero for `yMax' parameter */ - TT_Get_VMetrics( face, start + nn, 0, &tsb, &ah ); + TT_Get_VMetrics( ttface, start + nn, 0, &tsb, &ah ); advances[nn] = ah; } } @@ -255,8 +265,8 @@ { #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT /* no fast retrieval for blended MM fonts without HVAR table */ - if ( ( FT_IS_NAMED_INSTANCE( ttface ) || FT_IS_VARIATION( ttface ) ) && - !( face->variation_support & TT_FACE_FLAG_VAR_HADVANCE ) ) + if ( ( FT_IS_NAMED_INSTANCE( face ) || FT_IS_VARIATION( face ) ) && + !( ttface->variation_support & TT_FACE_FLAG_VAR_HADVANCE ) ) return FT_THROW( Unimplemented_Feature ); #endif @@ -266,7 +276,7 @@ FT_UShort aw; - TT_Get_HMetrics( face, start + nn, &lsb, &aw ); + TT_Get_HMetrics( ttface, start + nn, &lsb, &aw ); advances[nn] = aw; } } @@ -290,7 +300,7 @@ #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS - static FT_Error + FT_CALLBACK_DEF( FT_Error ) tt_size_select( FT_Size size, FT_ULong strike_index ) { @@ -306,7 +316,7 @@ /* use the scaled metrics, even when tt_size_reset fails */ FT_Select_Metrics( size->face, strike_index ); - tt_size_reset( ttsize, 0 ); /* ignore return value */ + tt_size_reset( ttsize ); /* ignore return value */ } else { @@ -327,7 +337,7 @@ #endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */ - static FT_Error + FT_CALLBACK_DEF( FT_Error ) tt_size_request( FT_Size size, FT_Size_Request req ) { @@ -367,7 +377,7 @@ if ( FT_IS_SCALABLE( size->face ) ) { - error = tt_size_reset( ttsize, 0 ); + error = tt_size_reset( ttsize ); #ifdef TT_USE_BYTECODE_INTERPRETER /* for the `MPS' bytecode instruction we need the point size */ @@ -426,15 +436,15 @@ * @Return: * FreeType error code. 0 means success. */ - static FT_Error - tt_glyph_load( FT_GlyphSlot ttslot, /* TT_GlyphSlot */ - FT_Size ttsize, /* TT_Size */ + FT_CALLBACK_DEF( FT_Error ) + tt_glyph_load( FT_GlyphSlot slot, /* TT_GlyphSlot */ + FT_Size size, /* TT_Size */ FT_UInt glyph_index, FT_Int32 load_flags ) { - TT_GlyphSlot slot = (TT_GlyphSlot)ttslot; - TT_Size size = (TT_Size)ttsize; - FT_Face face = ttslot->face; + TT_GlyphSlot ttslot = (TT_GlyphSlot)slot; + TT_Size ttsize = (TT_Size)size; + FT_Face face = ttslot->face; FT_Error error; @@ -476,12 +486,12 @@ } /* use hinted metrics only if we load a glyph with hinting */ - size->metrics = ( load_flags & FT_LOAD_NO_HINTING ) - ? &ttsize->metrics - : &size->hinted_metrics; + ttsize->metrics = ( load_flags & FT_LOAD_NO_HINTING ) + ? &size->metrics + : &ttsize->hinted_metrics; /* now fill in the glyph slot with outline/bitmap/layered */ - error = TT_Load_Glyph( size, slot, glyph_index, load_flags ); + error = TT_Load_Glyph( ttsize, ttslot, glyph_index, load_flags ); /* force drop-out mode to 2 - irrelevant now */ /* slot->outline.dropout_mode = 2; */ @@ -507,49 +517,47 @@ FT_DEFINE_SERVICE_MULTIMASTERSREC( tt_service_gx_multi_masters, - (FT_Get_MM_Func) NULL, /* get_mm */ - (FT_Set_MM_Design_Func) NULL, /* set_mm_design */ - (FT_Set_MM_Blend_Func) TT_Set_MM_Blend, /* set_mm_blend */ - (FT_Get_MM_Blend_Func) TT_Get_MM_Blend, /* get_mm_blend */ - (FT_Get_MM_Var_Func) TT_Get_MM_Var, /* get_mm_var */ - (FT_Set_Var_Design_Func)TT_Set_Var_Design, /* set_var_design */ - (FT_Get_Var_Design_Func)TT_Get_Var_Design, /* get_var_design */ - (FT_Set_Instance_Func) TT_Set_Named_Instance, /* set_instance */ - (FT_Set_MM_WeightVector_Func) - NULL, /* set_mm_weightvector */ - (FT_Get_MM_WeightVector_Func) - NULL, /* get_mm_weightvector */ - (FT_Var_Load_Delta_Set_Idx_Map_Func) - tt_var_load_delta_set_index_mapping, - /* load_delta_set_idx_map */ - (FT_Var_Load_Item_Var_Store_Func) - tt_var_load_item_variation_store, - /* load_item_variation_store */ - (FT_Var_Get_Item_Delta_Func) - tt_var_get_item_delta, /* get_item_delta */ - (FT_Var_Done_Item_Var_Store_Func) - tt_var_done_item_variation_store, - /* done_item_variation_store */ - (FT_Var_Done_Delta_Set_Idx_Map_Func) - tt_var_done_delta_set_index_map, - /* done_delta_set_index_map */ - (FT_Get_Var_Blend_Func) tt_get_var_blend, /* get_var_blend */ - (FT_Done_Blend_Func) tt_done_blend /* done_blend */ + NULL, /* FT_Get_MM_Func get_mm */ + NULL, /* FT_Set_MM_Design_Func set_mm_design */ + TT_Set_MM_Blend, /* FT_Set_MM_Blend_Func set_mm_blend */ + TT_Get_MM_Blend, /* FT_Get_MM_Blend_Func get_mm_blend */ + TT_Get_MM_Var, /* FT_Get_MM_Var_Func get_mm_var */ + TT_Set_Var_Design, /* FT_Set_Var_Design_Func set_var_design */ + TT_Get_Var_Design, /* FT_Get_Var_Design_Func get_var_design */ + TT_Set_Named_Instance, /* FT_Set_Named_Instance_Func set_named_instance */ + TT_Get_Default_Named_Instance, + /* FT_Get_Default_Named_Instance_Func get_default_named_instance */ + NULL, /* FT_Set_MM_WeightVector_Func set_mm_weightvector */ + NULL, /* FT_Get_MM_WeightVector_Func get_mm_weightvector */ + + tt_construct_ps_name, /* FT_Construct_PS_Name_Func construct_ps_name */ + tt_var_load_delta_set_index_mapping, + /* FT_Var_Load_Delta_Set_Idx_Map_Func load_delta_set_idx_map */ + tt_var_load_item_variation_store, + /* FT_Var_Load_Item_Var_Store_Func load_item_variation_store */ + tt_var_get_item_delta, /* FT_Var_Get_Item_Delta_Func get_item_delta */ + tt_var_done_item_variation_store, + /* FT_Var_Done_Item_Var_Store_Func done_item_variation_store */ + tt_var_done_delta_set_index_map, + /* FT_Var_Done_Delta_Set_Idx_Map_Func done_delta_set_index_map */ + tt_get_var_blend, /* FT_Get_Var_Blend_Func get_var_blend */ + tt_done_blend /* FT_Done_Blend_Func done_blend */ ) FT_DEFINE_SERVICE_METRICSVARIATIONSREC( tt_service_metrics_variations, - (FT_HAdvance_Adjust_Func)tt_hadvance_adjust, /* hadvance_adjust */ - (FT_LSB_Adjust_Func) NULL, /* lsb_adjust */ - (FT_RSB_Adjust_Func) NULL, /* rsb_adjust */ + tt_hadvance_adjust, /* FT_HAdvance_Adjust_Func hadvance_adjust */ + NULL, /* FT_LSB_Adjust_Func lsb_adjust */ + NULL, /* FT_RSB_Adjust_Func rsb_adjust */ - (FT_VAdvance_Adjust_Func)tt_vadvance_adjust, /* vadvance_adjust */ - (FT_TSB_Adjust_Func) NULL, /* tsb_adjust */ - (FT_BSB_Adjust_Func) NULL, /* bsb_adjust */ - (FT_VOrg_Adjust_Func) NULL, /* vorg_adjust */ + tt_vadvance_adjust, /* FT_VAdvance_Adjust_Func vadvance_adjust */ + NULL, /* FT_TSB_Adjust_Func tsb_adjust */ + NULL, /* FT_BSB_Adjust_Func bsb_adjust */ + NULL, /* FT_VOrg_Adjust_Func vorg_adjust */ - (FT_Metrics_Adjust_Func) tt_apply_mvar /* metrics_adjust */ + tt_apply_mvar, /* FT_Metrics_Adjust_Func metrics_adjust */ + tt_size_reset_height /* FT_Size_Reset_Func size_reset */ ) #endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */ diff --git a/src/3rdparty/freetype/src/truetype/ttgload.c b/src/3rdparty/freetype/src/truetype/ttgload.c index d33bdad6427..5f15a7f4def 100644 --- a/src/3rdparty/freetype/src/truetype/ttgload.c +++ b/src/3rdparty/freetype/src/truetype/ttgload.c @@ -362,17 +362,16 @@ FT_Byte* p = load->cursor; FT_Byte* limit = load->limit; FT_GlyphLoader gloader = load->gloader; + FT_Outline* outline = &gloader->current.outline; FT_Int n_contours = load->n_contours; - FT_Outline* outline; - FT_UShort n_ins; FT_Int n_points; + FT_UShort n_ins; FT_Byte *flag, *flag_limit; FT_Byte c, count; FT_Vector *vec, *vec_limit; FT_Pos x, y; - FT_Short *cont, *cont_limit, prev_cont; - FT_Int xy_size = 0; + FT_Short *cont, *cont_limit, last; /* check that we can add the contours to the glyph */ @@ -380,40 +379,26 @@ if ( error ) goto Fail; + /* check space for contours array + instructions count */ + if ( n_contours >= 0xFFF || p + 2 * n_contours + 2 > limit ) + goto Invalid_Outline; + /* reading the contours' endpoints & number of points */ - cont = gloader->current.outline.contours; + cont = outline->contours; cont_limit = cont + n_contours; - /* check space for contours array + instructions count */ - if ( n_contours >= 0xFFF || p + ( n_contours + 1 ) * 2 > limit ) - goto Invalid_Outline; - - prev_cont = FT_NEXT_SHORT( p ); - - if ( n_contours > 0 ) - cont[0] = prev_cont; - - if ( prev_cont < 0 ) - goto Invalid_Outline; - - for ( cont++; cont < cont_limit; cont++ ) + last = -1; + for ( ; cont < cont_limit; cont++ ) { - cont[0] = FT_NEXT_SHORT( p ); - if ( cont[0] <= prev_cont ) - { - /* unordered contours: this is invalid */ + *cont = FT_NEXT_SHORT( p ); + + if ( *cont <= last ) goto Invalid_Outline; - } - prev_cont = cont[0]; + + last = *cont; } - n_points = 0; - if ( n_contours > 0 ) - { - n_points = cont[-1] + 1; - if ( n_points < 0 ) - goto Invalid_Outline; - } + n_points = last + 1; FT_TRACE5(( " # of points: %d\n", n_points )); @@ -422,59 +407,48 @@ if ( error ) goto Fail; - /* reading the bytecode instructions */ - load->glyph->control_len = 0; - load->glyph->control_data = NULL; - - if ( p + 2 > limit ) - goto Invalid_Outline; - + /* space checked above */ n_ins = FT_NEXT_USHORT( p ); FT_TRACE5(( " Instructions size: %u\n", n_ins )); + /* check instructions size */ + if ( p + n_ins > limit ) + { + FT_TRACE1(( "TT_Load_Simple_Glyph: excessive instruction count\n" )); + error = FT_THROW( Too_Many_Hints ); + goto Fail; + } + #ifdef TT_USE_BYTECODE_INTERPRETER if ( IS_HINTED( load->load_flags ) ) { - FT_ULong tmp; + TT_ExecContext exec = load->exec; + FT_Memory memory = exec->memory; - /* check instructions size */ - if ( ( limit - p ) < n_ins ) - { - FT_TRACE1(( "TT_Load_Simple_Glyph: instruction count mismatch\n" )); - error = FT_THROW( Too_Many_Hints ); - goto Fail; - } + if ( exec->glyphSize ) + FT_FREE( exec->glyphIns ); + exec->glyphSize = 0; /* we don't trust `maxSizeOfInstructions' in the `maxp' table */ - /* and thus update the bytecode array size by ourselves */ - - tmp = load->exec->glyphSize; - error = Update_Max( load->exec->memory, - &tmp, - sizeof ( FT_Byte ), - (void*)&load->exec->glyphIns, - n_ins ); - - load->exec->glyphSize = (FT_UInt)tmp; - if ( error ) - return error; - - load->glyph->control_len = n_ins; - load->glyph->control_data = load->exec->glyphIns; - + /* and thus allocate the bytecode array size by ourselves */ if ( n_ins ) - FT_MEM_COPY( load->exec->glyphIns, p, (FT_Long)n_ins ); + { + if ( FT_QNEW_ARRAY( exec->glyphIns, n_ins ) ) + return error; + + FT_MEM_COPY( exec->glyphIns, p, (FT_Long)n_ins ); + + exec->glyphSize = n_ins; + } } #endif /* TT_USE_BYTECODE_INTERPRETER */ p += n_ins; - outline = &gloader->current.outline; - /* reading the point tags */ flag = (FT_Byte*)outline->tags; flag_limit = flag + n_points; @@ -512,9 +486,6 @@ flag = (FT_Byte*)outline->tags; x = 0; - if ( p + xy_size > limit ) - goto Invalid_Outline; - for ( ; vec < vec_limit; vec++, flag++ ) { FT_Pos delta = 0; @@ -544,7 +515,7 @@ /* reading the Y coordinates */ - vec = gloader->current.outline.points; + vec = outline->points; vec_limit = vec + n_points; flag = (FT_Byte*)outline->tags; y = 0; @@ -836,15 +807,14 @@ TT_GlyphZone zone = &loader->zone; #ifdef TT_USE_BYTECODE_INTERPRETER - FT_Long n_ins; + TT_ExecContext exec = loader->exec; + FT_Long n_ins = exec->glyphSize; #else FT_UNUSED( is_composite ); #endif #ifdef TT_USE_BYTECODE_INTERPRETER - n_ins = loader->glyph->control_len; - /* save original point positions in `org' array */ if ( n_ins > 0 ) FT_ARRAY_COPY( zone->org, zone->cur, zone->n_points ); @@ -856,15 +826,15 @@ /* completely refer to the (already) hinted subglyphs. */ if ( is_composite ) { - loader->exec->metrics.x_scale = 1 << 16; - loader->exec->metrics.y_scale = 1 << 16; + exec->metrics.x_scale = 1 << 16; + exec->metrics.y_scale = 1 << 16; FT_ARRAY_COPY( zone->orus, zone->cur, zone->n_points ); } else { - loader->exec->metrics.x_scale = loader->size->metrics->x_scale; - loader->exec->metrics.y_scale = loader->size->metrics->y_scale; + exec->metrics.x_scale = loader->size->metrics->x_scale; + exec->metrics.y_scale = loader->size->metrics->y_scale; } #endif @@ -884,23 +854,19 @@ { FT_Error error; - FT_GlyphLoader gloader = loader->gloader; - FT_Outline current_outline = gloader->current.outline; + TT_Set_CodeRange( exec, tt_coderange_glyph, exec->glyphIns, n_ins ); - TT_Set_CodeRange( loader->exec, tt_coderange_glyph, - loader->exec->glyphIns, n_ins ); - - loader->exec->is_composite = is_composite; - loader->exec->pts = *zone; + exec->is_composite = is_composite; + exec->pts = *zone; error = TT_Run_Context( loader->exec ); - if ( error && loader->exec->pedantic_hinting ) + if ( error && exec->pedantic_hinting ) return error; /* store drop-out mode in bits 5-7; set bit 2 also as a marker */ - current_outline.tags[0] |= - ( loader->exec->GS.scan_type << 5 ) | FT_CURVE_TAG_HAS_SCANMODE; + loader->gloader->current.outline.tags[0] |= + ( exec->GS.scan_type << 5 ) | FT_CURVE_TAG_HAS_SCANMODE; } #endif @@ -910,7 +876,7 @@ /* compatibility mode, where no movement on the x axis means no reason */ /* to change bearings or advance widths. */ if ( !( driver->interpreter_version == TT_INTERPRETER_VERSION_40 && - loader->exec->backward_compatibility ) ) + exec->backward_compatibility ) ) { #endif loader->pp1 = zone->cur[zone->n_points - 4]; @@ -924,10 +890,10 @@ #ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY if ( driver->interpreter_version == TT_INTERPRETER_VERSION_38 ) { - if ( loader->exec->sph_tweak_flags & SPH_TWEAK_DEEMBOLDEN ) + if ( exec->sph_tweak_flags & SPH_TWEAK_DEEMBOLDEN ) FT_Outline_EmboldenXY( &loader->gloader->current.outline, -24, 0 ); - else if ( loader->exec->sph_tweak_flags & SPH_TWEAK_EMBOLDEN ) + else if ( exec->sph_tweak_flags & SPH_TWEAK_EMBOLDEN ) FT_Outline_EmboldenXY( &loader->gloader->current.outline, 24, 0 ); } #endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */ @@ -949,10 +915,10 @@ static FT_Error TT_Process_Simple_Glyph( TT_Loader loader ) { - FT_GlyphLoader gloader = loader->gloader; - FT_Error error = FT_Err_Ok; - FT_Outline* outline; - FT_Int n_points; + FT_Error error = FT_Err_Ok; + FT_GlyphLoader gloader = loader->gloader; + FT_Outline* outline = &gloader->current.outline; + FT_Int n_points = outline->n_points; #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT FT_Memory memory = loader->face->root.memory; @@ -960,11 +926,7 @@ #endif - outline = &gloader->current.outline; - n_points = outline->n_points; - /* set phantom points */ - outline->points[n_points ] = loader->pp1; outline->points[n_points + 1] = loader->pp2; outline->points[n_points + 2] = loader->pp3; @@ -976,7 +938,7 @@ if ( !IS_DEFAULT_INSTANCE( FT_FACE( loader->face ) ) ) { - if ( FT_NEW_ARRAY( unrounded, n_points ) ) + if ( FT_QNEW_ARRAY( unrounded, n_points ) ) goto Exit; /* Deltas apply to the unscaled data. */ @@ -1331,12 +1293,12 @@ FT_UInt start_contour ) { FT_Error error; - FT_Outline* outline; + FT_Outline* outline = &loader->gloader->base.outline; + FT_Stream stream = loader->stream; + FT_UShort n_ins; FT_UInt i; - outline = &loader->gloader->base.outline; - /* make room for phantom points */ error = FT_GLYPHLOADER_CHECK_POINTS( loader->gloader, outline->n_points + 4, @@ -1352,11 +1314,14 @@ #ifdef TT_USE_BYTECODE_INTERPRETER { - FT_Stream stream = loader->stream; - FT_UShort n_ins, max_ins; - FT_ULong tmp; + TT_ExecContext exec = loader->exec; + FT_Memory memory = exec->memory; + if ( exec->glyphSize ) + FT_FREE( exec->glyphIns ); + exec->glyphSize = 0; + /* TT_Load_Composite_Glyph only gives us the offset of instructions */ /* so we read them here */ if ( FT_STREAM_SEEK( loader->ins_pos ) || @@ -1365,39 +1330,24 @@ FT_TRACE5(( " Instructions size = %hu\n", n_ins )); - /* check it */ - max_ins = loader->face->max_profile.maxSizeOfInstructions; - if ( n_ins > max_ins ) - { - /* don't trust `maxSizeOfInstructions'; */ - /* only do a rough safety check */ - if ( n_ins > loader->byte_len ) - { - FT_TRACE1(( "TT_Process_Composite_Glyph:" - " too many instructions (%hu) for glyph with length %u\n", - n_ins, loader->byte_len )); - return FT_THROW( Too_Many_Hints ); - } - - tmp = loader->exec->glyphSize; - error = Update_Max( loader->exec->memory, - &tmp, - sizeof ( FT_Byte ), - (void*)&loader->exec->glyphIns, - n_ins ); - - loader->exec->glyphSize = (FT_UShort)tmp; - if ( error ) - return error; - } - else if ( n_ins == 0 ) + if ( !n_ins ) return FT_Err_Ok; - if ( FT_STREAM_READ( loader->exec->glyphIns, n_ins ) ) + /* don't trust `maxSizeOfInstructions'; */ + /* only do a rough safety check */ + if ( n_ins > loader->byte_len ) + { + FT_TRACE1(( "TT_Process_Composite_Glyph:" + " too many instructions (%hu) for glyph with length %u\n", + n_ins, loader->byte_len )); + return FT_THROW( Too_Many_Hints ); + } + + if ( FT_QNEW_ARRAY( exec->glyphIns, n_ins ) || + FT_STREAM_READ( exec->glyphIns, n_ins ) ) return error; - loader->glyph->control_data = loader->exec->glyphIns; - loader->glyph->control_len = n_ins; + exec->glyphSize = n_ins; } #endif @@ -1662,8 +1612,14 @@ else #endif /* FT_CONFIG_OPTION_INCREMENTAL */ + { + FT_ULong len; - offset = tt_face_get_location( face, glyph_index, &loader->byte_len ); + + offset = tt_face_get_location( FT_FACE( face ), glyph_index, &len ); + + loader->byte_len = (FT_UInt)len; + } if ( loader->byte_len > 0 ) { @@ -1889,10 +1845,7 @@ short i, limit; FT_SubGlyph subglyph; - FT_Outline outline; - FT_Vector* points = NULL; - char* tags = NULL; - short* contours = NULL; + FT_Outline outline = { 0, 0, NULL, NULL, NULL, 0 }; FT_Vector* unrounded = NULL; @@ -1900,18 +1853,14 @@ /* construct an outline structure for */ /* communication with `TT_Vary_Apply_Glyph_Deltas' */ - outline.n_contours = outline.n_points = limit; - - outline.points = NULL; - outline.tags = NULL; - outline.contours = NULL; - - if ( FT_NEW_ARRAY( points, limit + 4 ) || - FT_NEW_ARRAY( tags, limit + 4 ) || - FT_NEW_ARRAY( contours, limit + 4 ) || - FT_NEW_ARRAY( unrounded, limit + 4 ) ) + if ( FT_QNEW_ARRAY( outline.points, limit + 4 ) || + FT_QNEW_ARRAY( outline.tags, limit ) || + FT_QNEW_ARRAY( outline.contours, limit ) || + FT_QNEW_ARRAY( unrounded, limit + 4 ) ) goto Exit1; + outline.n_contours = outline.n_points = limit; + subglyph = gloader->current.subglyphs; for ( i = 0; i < limit; i++, subglyph++ ) @@ -1919,20 +1868,16 @@ /* applying deltas for anchor points doesn't make sense, */ /* but we don't have to specially check this since */ /* unused delta values are zero anyways */ - points[i].x = subglyph->arg1; - points[i].y = subglyph->arg2; - tags[i] = 1; - contours[i] = i; + outline.points[i].x = subglyph->arg1; + outline.points[i].y = subglyph->arg2; + outline.tags[i] = ON_CURVE_POINT; + outline.contours[i] = i; } - points[i++] = loader->pp1; - points[i++] = loader->pp2; - points[i++] = loader->pp3; - points[i ] = loader->pp4; - - outline.points = points; - outline.tags = tags; - outline.contours = contours; + outline.points[i++] = loader->pp1; + outline.points[i++] = loader->pp2; + outline.points[i++] = loader->pp3; + outline.points[i ] = loader->pp4; /* this call provides additional offsets */ /* for each component's translation */ @@ -1947,8 +1892,8 @@ { if ( subglyph->flags & ARGS_ARE_XY_VALUES ) { - subglyph->arg1 = (FT_Int16)points[i].x; - subglyph->arg2 = (FT_Int16)points[i].y; + subglyph->arg1 = (FT_Int16)outline.points[i].x; + subglyph->arg2 = (FT_Int16)outline.points[i].y; } } @@ -2857,7 +2802,9 @@ #ifdef FT_CONFIG_OPTION_SVG /* check for OT-SVG */ - if ( ( load_flags & FT_LOAD_COLOR ) && face->svg ) + if ( ( load_flags & FT_LOAD_NO_SVG ) == 0 && + ( load_flags & FT_LOAD_COLOR ) && + face->svg ) { SFNT_Service sfnt = (SFNT_Service)face->sfnt; @@ -2955,6 +2902,9 @@ if ( IS_HINTED( load_flags ) ) { + glyph->control_data = loader.exec->glyphIns; + glyph->control_len = loader.exec->glyphSize; + if ( loader.exec->GS.scan_control ) { /* convert scan conversion mode to FT_OUTLINE_XXX flags */ diff --git a/src/3rdparty/freetype/src/truetype/ttgxvar.c b/src/3rdparty/freetype/src/truetype/ttgxvar.c index 60a0095b6e0..8c713f1b6fe 100644 --- a/src/3rdparty/freetype/src/truetype/ttgxvar.c +++ b/src/3rdparty/freetype/src/truetype/ttgxvar.c @@ -45,6 +45,7 @@ #include #include #include +#include #include #include #include @@ -465,7 +466,7 @@ if ( store_offset ) { error = tt_var_load_item_variation_store( - face, + FT_FACE( face ), table_offset + store_offset, &table->itemStore ); if ( error ) @@ -475,7 +476,7 @@ if ( axisMap_offset ) { error = tt_var_load_delta_set_index_mapping( - face, + FT_FACE( face ), table_offset + axisMap_offset, &table->axisMap, &table->itemStore, @@ -492,10 +493,11 @@ FT_LOCAL_DEF( FT_Error ) - tt_var_load_item_variation_store( TT_Face face, + tt_var_load_item_variation_store( FT_Face face, /* TT_Face */ FT_ULong offset, GX_ItemVarStore itemStore ) { + TT_Face ttface = (TT_Face)face; FT_Stream stream = FT_FACE_STREAM( face ); FT_Memory memory = stream->memory; @@ -507,10 +509,10 @@ FT_UShort axis_count; FT_UInt region_count; - FT_UInt i, j, k; + FT_UInt i, j; FT_Bool long_words; - GX_Blend blend = face->blend; + GX_Blend blend = ttface->blend; FT_ULong* dataOffsetArray = NULL; @@ -622,6 +624,7 @@ FT_UInt item_count; FT_UInt word_delta_count; FT_UInt region_idx_count; + FT_UInt per_region_size; if ( FT_STREAM_SEEK( offset + dataOffsetArray[i] ) ) @@ -658,6 +661,8 @@ if ( FT_NEW_ARRAY( varData->regionIndices, region_idx_count ) ) goto Exit; varData->regionIdxCount = region_idx_count; + varData->wordDeltaCount = word_delta_count; + varData->longWords = long_words; for ( j = 0; j < varData->regionIdxCount; j++ ) { @@ -673,37 +678,22 @@ } } - /* Parse delta set. */ - /* */ - /* On input, deltas are (word_delta_count + region_idx_count) bytes */ - /* each if `long_words` isn't set, and twice as much otherwise. */ - /* */ - /* On output, deltas are expanded to `region_idx_count` shorts each. */ - if ( FT_NEW_ARRAY( varData->deltaSet, item_count * region_idx_count ) ) - goto Exit; - varData->itemCount = item_count; + per_region_size = word_delta_count + region_idx_count; + if ( long_words ) + per_region_size *= 2; - for ( j = 0; j < item_count * region_idx_count; ) + if ( FT_NEW_ARRAY( varData->deltaSet, per_region_size * item_count ) ) + goto Exit; + if ( FT_Stream_Read( stream, + varData->deltaSet, + per_region_size * item_count ) ) { - if ( long_words ) - { - for ( k = 0; k < word_delta_count; k++, j++ ) - if ( FT_READ_LONG( varData->deltaSet[j] ) ) - goto Exit; - for ( ; k < region_idx_count; k++, j++ ) - if ( FT_READ_SHORT( varData->deltaSet[j] ) ) - goto Exit; - } - else - { - for ( k = 0; k < word_delta_count; k++, j++ ) - if ( FT_READ_SHORT( varData->deltaSet[j] ) ) - goto Exit; - for ( ; k < region_idx_count; k++, j++ ) - if ( FT_READ_CHAR( varData->deltaSet[j] ) ) - goto Exit; - } + FT_TRACE2(( "deltaSet read failed." )); + error = FT_THROW( Invalid_Table ); + goto Exit; } + + varData->itemCount = item_count; } Exit: @@ -714,7 +704,7 @@ FT_LOCAL_DEF( FT_Error ) - tt_var_load_delta_set_index_mapping( TT_Face face, + tt_var_load_delta_set_index_mapping( FT_Face face, /* TT_Face */ FT_ULong offset, GX_DeltaSetIdxMap map, GX_ItemVarStore itemStore, @@ -941,7 +931,7 @@ } error = tt_var_load_item_variation_store( - face, + FT_FACE( face ), table_offset + store_offset, &table->itemStore ); if ( error ) @@ -950,7 +940,7 @@ if ( widthMap_offset ) { error = tt_var_load_delta_set_index_mapping( - face, + FT_FACE( face ), table_offset + widthMap_offset, &table->widthMap, &table->itemStore, @@ -992,24 +982,30 @@ FT_LOCAL_DEF( FT_ItemVarDelta ) - tt_var_get_item_delta( TT_Face face, + tt_var_get_item_delta( FT_Face face, /* TT_Face */ GX_ItemVarStore itemStore, FT_UInt outerIndex, FT_UInt innerIndex ) { + TT_Face ttface = (TT_Face)face; FT_Stream stream = FT_FACE_STREAM( face ); FT_Memory memory = stream->memory; FT_Error error = FT_Err_Ok; GX_ItemVarData varData; - FT_ItemVarDelta* deltaSet; + FT_ItemVarDelta* deltaSet = NULL; + FT_ItemVarDelta deltaSetStack[16]; + + FT_Fixed* scalars = NULL; + FT_Fixed scalarsStack[16]; FT_UInt master, j; - FT_Fixed* scalars = NULL; - FT_ItemVarDelta returnValue; + FT_ItemVarDelta returnValue = 0; + FT_UInt per_region_size; + FT_Byte* bytes; - if ( !face->blend || !face->blend->normalizedcoords ) + if ( !ttface->blend || !ttface->blend->normalizedcoords ) return 0; /* OpenType 1.8.4+: No variation data for this item */ @@ -1023,15 +1019,48 @@ if ( outerIndex >= itemStore->dataCount ) return 0; /* Out of range. */ - varData = &itemStore->varData[outerIndex]; - deltaSet = FT_OFFSET( varData->deltaSet, - varData->regionIdxCount * innerIndex ); + varData = &itemStore->varData[outerIndex]; if ( innerIndex >= varData->itemCount ) return 0; /* Out of range. */ - if ( FT_QNEW_ARRAY( scalars, varData->regionIdxCount ) ) - return 0; + if ( varData->regionIdxCount < 16 ) + { + deltaSet = deltaSetStack; + scalars = scalarsStack; + } + else + { + if ( FT_QNEW_ARRAY( deltaSet, varData->regionIdxCount ) ) + goto Exit; + if ( FT_QNEW_ARRAY( scalars, varData->regionIdxCount ) ) + goto Exit; + } + + /* Parse delta set. */ + /* */ + /* Deltas are (word_delta_count + region_idx_count) bytes each */ + /* if `longWords` isn't set, and twice as much otherwise. */ + per_region_size = varData->wordDeltaCount + varData->regionIdxCount; + if ( varData->longWords ) + per_region_size *= 2; + + bytes = varData->deltaSet + per_region_size * innerIndex; + + if ( varData->longWords ) + { + for ( master = 0; master < varData->wordDeltaCount; master++ ) + deltaSet[master] = FT_NEXT_LONG( bytes ); + for ( ; master < varData->regionIdxCount; master++ ) + deltaSet[master] = FT_NEXT_SHORT( bytes ); + } + else + { + for ( master = 0; master < varData->wordDeltaCount; master++ ) + deltaSet[master] = FT_NEXT_SHORT( bytes ); + for ( ; master < varData->regionIdxCount; master++ ) + deltaSet[master] = FT_NEXT_CHAR( bytes ); + } /* outer loop steps through master designs to be blended */ for ( master = 0; master < varData->regionIdxCount; master++ ) @@ -1060,27 +1089,27 @@ else if ( axis->peakCoord == 0 ) continue; - else if ( face->blend->normalizedcoords[j] == axis->peakCoord ) + else if ( ttface->blend->normalizedcoords[j] == axis->peakCoord ) continue; /* ignore this region if coords are out of range */ - else if ( face->blend->normalizedcoords[j] <= axis->startCoord || - face->blend->normalizedcoords[j] >= axis->endCoord ) + else if ( ttface->blend->normalizedcoords[j] <= axis->startCoord || + ttface->blend->normalizedcoords[j] >= axis->endCoord ) { scalar = 0; break; } /* cumulative product of all the axis scalars */ - else if ( face->blend->normalizedcoords[j] < axis->peakCoord ) + else if ( ttface->blend->normalizedcoords[j] < axis->peakCoord ) scalar = FT_MulDiv( scalar, - face->blend->normalizedcoords[j] - axis->startCoord, + ttface->blend->normalizedcoords[j] - axis->startCoord, axis->peakCoord - axis->startCoord ); else scalar = FT_MulDiv( scalar, - axis->endCoord - face->blend->normalizedcoords[j], + axis->endCoord - ttface->blend->normalizedcoords[j], axis->endCoord - axis->peakCoord ); } /* per-axis loop */ @@ -1106,7 +1135,11 @@ */ returnValue = FT_MulAddFix( scalars, deltaSet, varData->regionIdxCount ); - FT_FREE( scalars ); + Exit: + if ( scalars != scalarsStack ) + FT_FREE( scalars ); + if ( deltaSet != deltaSetStack ) + FT_FREE( deltaSet ); return returnValue; } @@ -1206,7 +1239,7 @@ innerIndex = gindex; } - delta = tt_var_get_item_delta( face, + delta = tt_var_get_item_delta( FT_FACE( face ), &table->itemStore, outerIndex, innerIndex ); @@ -1229,20 +1262,20 @@ FT_LOCAL_DEF( FT_Error ) - tt_hadvance_adjust( TT_Face face, + tt_hadvance_adjust( FT_Face face, /* TT_Face */ FT_UInt gindex, FT_Int *avalue ) { - return tt_hvadvance_adjust( face, gindex, avalue, 0 ); + return tt_hvadvance_adjust( (TT_Face)face, gindex, avalue, 0 ); } FT_LOCAL_DEF( FT_Error ) - tt_vadvance_adjust( TT_Face face, + tt_vadvance_adjust( FT_Face face, /* TT_Face */ FT_UInt gindex, FT_Int *avalue ) { - return tt_hvadvance_adjust( face, gindex, avalue, 1 ); + return tt_hvadvance_adjust( (TT_Face)face, gindex, avalue, 1 ); } @@ -1389,7 +1422,7 @@ records_offset = FT_STREAM_POS(); error = tt_var_load_item_variation_store( - face, + FT_FACE( face ), table_offset + store_offset, &blend->mvar_table->itemStore ); if ( error ) @@ -1462,15 +1495,14 @@ static FT_Error - tt_size_reset_iterator( FT_ListNode node, + ft_size_reset_iterator( FT_ListNode node, void* user ) { - TT_Size size = (TT_Size)node->data; - - FT_UNUSED( user ); + FT_Size size = (FT_Size)node->data; + FT_Service_MetricsVariations var = (FT_Service_MetricsVariations)user; - tt_size_reset( size, 1 ); + var->size_reset( size ); return FT_Err_Ok; } @@ -1489,16 +1521,19 @@ * The font face. */ FT_LOCAL_DEF( void ) - tt_apply_mvar( TT_Face face ) + tt_apply_mvar( FT_Face face ) /* TT_Face */ { - GX_Blend blend = face->blend; + TT_Face ttface = (TT_Face)face; + + GX_Blend blend = ttface->blend; GX_Value value, limit; + FT_Short mvar_hasc_delta = 0; FT_Short mvar_hdsc_delta = 0; FT_Short mvar_hlgp_delta = 0; - if ( !( face->variation_support & TT_FACE_FLAG_VAR_MVAR ) ) + if ( !( ttface->variation_support & TT_FACE_FLAG_VAR_MVAR ) ) return; value = blend->mvar_table->values; @@ -1506,7 +1541,7 @@ for ( ; value < limit; value++ ) { - FT_Short* p = ft_var_get_value_pointer( face, value->tag ); + FT_Short* p = ft_var_get_value_pointer( ttface, value->tag ); FT_Int delta; @@ -1543,7 +1578,8 @@ /* adjust all derived values */ { - FT_Face root = &face->root; + FT_Service_MetricsVariations var = + (FT_Service_MetricsVariations)ttface->face_var; /* * Apply the deltas of hasc, hdsc and hlgp to the FT_Face's ascender, @@ -1571,24 +1607,25 @@ * whether they were actually changed or the font had the OS/2 table's * fsSelection's bit 7 (USE_TYPO_METRICS) set. */ - FT_Short current_line_gap = root->height - root->ascender + - root->descender; + FT_Short current_line_gap = face->height - face->ascender + + face->descender; - root->ascender = root->ascender + mvar_hasc_delta; - root->descender = root->descender + mvar_hdsc_delta; - root->height = root->ascender - root->descender + + face->ascender = face->ascender + mvar_hasc_delta; + face->descender = face->descender + mvar_hdsc_delta; + face->height = face->ascender - face->descender + current_line_gap + mvar_hlgp_delta; - root->underline_position = face->postscript.underlinePosition - - face->postscript.underlineThickness / 2; - root->underline_thickness = face->postscript.underlineThickness; + face->underline_position = ttface->postscript.underlinePosition - + ttface->postscript.underlineThickness / 2; + face->underline_thickness = ttface->postscript.underlineThickness; - /* iterate over all FT_Size objects and call `tt_size_reset' */ - /* to propagate the metrics changes */ - FT_List_Iterate( &root->sizes_list, - tt_size_reset_iterator, - NULL ); + /* iterate over all FT_Size objects and call `var->size_reset' */ + /* to propagate the metrics changes */ + if ( var && var->size_reset ) + FT_List_Iterate( &face->sizes_list, + ft_size_reset_iterator, + (void*)var ); } } @@ -2099,7 +2136,7 @@ innerIndex = table->axisMap.innerIndex[idx]; } - delta = tt_var_get_item_delta( face, + delta = tt_var_get_item_delta( FT_FACE( face ), &table->itemStore, outerIndex, innerIndex ); @@ -2261,11 +2298,12 @@ * FreeType error code. 0 means success. */ FT_LOCAL_DEF( FT_Error ) - TT_Get_MM_Var( TT_Face face, + TT_Get_MM_Var( FT_Face face, /* TT_Face */ FT_MM_Var* *master ) { - FT_Stream stream = face->root.stream; - FT_Memory memory = face->root.memory; + TT_Face ttface = (TT_Face)face; + FT_Stream stream = FT_FACE_STREAM( face ); + FT_Memory memory = FT_FACE_MEMORY( face ); FT_ULong table_len; FT_Error error = FT_Err_Ok; FT_ULong fvar_start = 0; @@ -2329,19 +2367,19 @@ /* the default instance, which might be missing in the table of named */ /* instances (in 'fvar'). This value is validated in `sfobjs.c` and */ /* may be reset to 0 if consistency checks fail. */ - num_instances = (FT_UInt)face->root.style_flags >> 16; + num_instances = (FT_UInt)face->style_flags >> 16; /* read the font data and set up the internal representation */ /* if not already done */ - need_init = !face->blend; + need_init = !ttface->blend; if ( need_init ) { FT_TRACE2(( "FVAR " )); - if ( FT_SET_ERROR( face->goto_table( face, TTAG_fvar, - stream, &table_len ) ) ) + if ( FT_SET_ERROR( ttface->goto_table( ttface, TTAG_fvar, + stream, &table_len ) ) ) { FT_TRACE1(( "is missing\n" )); goto Exit; @@ -2374,14 +2412,14 @@ fvar_head.axisCount, fvar_head.axisCount == 1 ? "is" : "es" )); - if ( FT_NEW( face->blend ) ) + if ( FT_NEW( ttface->blend ) ) goto Exit; - num_axes = fvar_head.axisCount; - face->blend->num_axis = num_axes; + num_axes = fvar_head.axisCount; + ttface->blend->num_axis = num_axes; } else - num_axes = face->blend->num_axis; + num_axes = ttface->blend->num_axis; /* prepare storage area for MM data; this cannot overflow */ /* 32-bit arithmetic because of the size limits used in the */ @@ -2410,16 +2448,16 @@ if ( need_init ) { - face->blend->mmvar_len = mmvar_size + - axis_flags_size + - axis_size + - namedstyle_size + - next_coords_size + - next_name_size; + ttface->blend->mmvar_len = mmvar_size + + axis_flags_size + + axis_size + + namedstyle_size + + next_coords_size + + next_name_size; - if ( FT_ALLOC( mmvar, face->blend->mmvar_len ) ) + if ( FT_ALLOC( mmvar, ttface->blend->mmvar_len ) ) goto Exit; - face->blend->mmvar = mmvar; + ttface->blend->mmvar = mmvar; /* set up pointers and offsets into the `mmvar' array; */ /* the data gets filled in later on */ @@ -2525,27 +2563,27 @@ /* named instance coordinates are stored as design coordinates; */ /* we have to convert them to normalized coordinates also */ - if ( FT_NEW_ARRAY( face->blend->normalized_stylecoords, + if ( FT_NEW_ARRAY( ttface->blend->normalized_stylecoords, num_axes * num_instances ) ) goto Exit; - if ( fvar_head.instanceCount && !face->blend->avar_loaded ) + if ( fvar_head.instanceCount && !ttface->blend->avar_loaded ) { FT_ULong offset = FT_STREAM_POS(); - ft_var_load_avar( face ); + ft_var_load_avar( ttface ); if ( FT_STREAM_SEEK( offset ) ) goto Exit; } - FT_TRACE5(( "%d instance%s\n", + FT_TRACE5(( "%d named instance%s\n", fvar_head.instanceCount, fvar_head.instanceCount == 1 ? "" : "s" )); ns = mmvar->namedstyle; - nsc = face->blend->normalized_stylecoords; + nsc = ttface->blend->normalized_stylecoords; for ( i = 0; i < fvar_head.instanceCount; i++, ns++ ) { /* PostScript names add 2 bytes to the instance record size */ @@ -2568,7 +2606,7 @@ #ifdef FT_DEBUG_LEVEL_TRACE { - SFNT_Service sfnt = (SFNT_Service)face->sfnt; + SFNT_Service sfnt = (SFNT_Service)ttface->sfnt; FT_String* strname = NULL; FT_String* psname = NULL; @@ -2580,7 +2618,7 @@ if ( ns->strid != 0xFFFF ) { - (void)sfnt->get_name( face, + (void)sfnt->get_name( ttface, (FT_UShort)ns->strid, &strname ); if ( strname && !ft_strcmp( strname, ".notdef" ) ) @@ -2589,7 +2627,7 @@ if ( ns->psid != 0xFFFF ) { - (void)sfnt->get_name( face, + (void)sfnt->get_name( ttface, (FT_UShort)ns->psid, &psname ); if ( psname && !ft_strcmp( psname, ".notdef" ) ) @@ -2598,7 +2636,7 @@ (void)FT_STREAM_SEEK( pos ); - FT_TRACE5(( " instance %d (%s%s%s, %s%s%s)\n", + FT_TRACE5(( " named instance %d (%s%s%s, %s%s%s)\n", i, strname ? "name: `" : "", strname ? strname : "unnamed", @@ -2612,7 +2650,7 @@ } #endif /* FT_DEBUG_LEVEL_TRACE */ - ft_var_to_normalized( face, num_axes, ns->coords, nsc ); + ft_var_to_normalized( ttface, num_axes, ns->coords, nsc ); nsc += num_axes; FT_FRAME_EXIT(); @@ -2620,15 +2658,17 @@ if ( num_instances != fvar_head.instanceCount ) { - SFNT_Service sfnt = (SFNT_Service)face->sfnt; + SFNT_Service sfnt = (SFNT_Service)ttface->sfnt; FT_Int found, dummy1, dummy2; FT_UInt strid = ~0U; - /* the default instance is missing in array the */ - /* of named instances; try to synthesize an entry */ - found = sfnt->get_name_id( face, + /* The default instance is missing in array the */ + /* of named instances; try to synthesize an entry. */ + /* If this fails, `default_named_instance` remains */ + /* at value zero, which doesn't do any harm. */ + found = sfnt->get_name_id( ttface, TT_NAME_ID_TYPOGRAPHIC_SUBFAMILY, &dummy1, &dummy2 ); @@ -2636,7 +2676,7 @@ strid = TT_NAME_ID_TYPOGRAPHIC_SUBFAMILY; else { - found = sfnt->get_name_id( face, + found = sfnt->get_name_id( ttface, TT_NAME_ID_FONT_SUBFAMILY, &dummy1, &dummy2 ); @@ -2646,7 +2686,7 @@ if ( found ) { - found = sfnt->get_name_id( face, + found = sfnt->get_name_id( ttface, TT_NAME_ID_PS_NAME, &dummy1, &dummy2 ); @@ -2655,6 +2695,9 @@ FT_TRACE5(( "TT_Get_MM_Var:" " Adding default instance to named instances\n" )); + /* named instance indices start with value 1 */ + ttface->var_default_named_instance = num_instances; + ns = &mmvar->namedstyle[fvar_head.instanceCount]; ns->strid = strid; @@ -2668,7 +2711,7 @@ } } - ft_var_load_mvar( face ); + ft_var_load_mvar( ttface ); } /* fill the output array if requested */ @@ -2678,9 +2721,9 @@ FT_UInt n; - if ( FT_ALLOC( mmvar, face->blend->mmvar_len ) ) + if ( FT_ALLOC( mmvar, ttface->blend->mmvar_len ) ) goto Exit; - FT_MEM_COPY( mmvar, face->blend->mmvar, face->blend->mmvar_len ); + FT_MEM_COPY( mmvar, ttface->blend->mmvar, ttface->blend->mmvar_len ); axis_flags = (FT_UShort*)( (char*)mmvar + mmvar_size ); @@ -2756,7 +2799,7 @@ if ( !face->blend ) { - if ( FT_SET_ERROR( TT_Get_MM_Var( face, NULL ) ) ) + if ( FT_SET_ERROR( TT_Get_MM_Var( FT_FACE( face ), NULL ) ) ) goto Exit; } @@ -2841,26 +2884,29 @@ } } - if ( FT_IS_NAMED_INSTANCE( FT_FACE( face ) ) ) + if ( !have_diff ) { - FT_UInt instance_index = (FT_UInt)face->root.face_index >> 16; + if ( FT_IS_NAMED_INSTANCE( FT_FACE( face ) ) ) + { + FT_UInt instance_index = (FT_UInt)face->root.face_index >> 16; - c = blend->normalizedcoords + i; - n = blend->normalized_stylecoords + - ( instance_index - 1 ) * mmvar->num_axis + - i; + c = blend->normalizedcoords + i; + n = blend->normalized_stylecoords + + ( instance_index - 1 ) * mmvar->num_axis + + i; - for ( j = i; j < mmvar->num_axis; j++, n++, c++ ) - if ( *c != *n ) - have_diff = 1; - } - else - { - c = blend->normalizedcoords + i; - for ( j = i; j < mmvar->num_axis; j++, c++ ) - if ( *c != 0 ) - have_diff = 1; + for ( j = i; j < mmvar->num_axis; j++, n++, c++ ) + if ( *c != *n ) + have_diff = 1; + } + else + { + c = blend->normalizedcoords + i; + for ( j = i; j < mmvar->num_axis; j++, c++ ) + if ( *c != 0 ) + have_diff = 1; + } } /* return value -1 indicates `no change' */ @@ -2924,9 +2970,6 @@ } } - /* enforce recomputation of the PostScript name; */ - FT_FREE( face->postscript_name ); - Exit: return error; } @@ -2958,26 +3001,15 @@ * An array of `num_coords', each between [-1,1]. * * @Return: - * FreeType error code. 0 means success. + * FreeType error code. 0 means success, -1 means success and unchanged + * axis values. */ FT_LOCAL_DEF( FT_Error ) - TT_Set_MM_Blend( TT_Face face, + TT_Set_MM_Blend( FT_Face face, /* TT_Face */ FT_UInt num_coords, FT_Fixed* coords ) { - FT_Error error; - - - error = tt_set_mm_blend( face, num_coords, coords, 1 ); - if ( error ) - return error; - - if ( num_coords ) - face->root.face_flags |= FT_FACE_FLAG_VARIATION; - else - face->root.face_flags &= ~FT_FACE_FLAG_VARIATION; - - return FT_Err_Ok; + return tt_set_mm_blend( (TT_Face)face, num_coords, coords, 1 ); } @@ -3005,31 +3037,34 @@ * An array of `num_coords', each between [-1,1]. * * @Return: - * FreeType error code. 0 means success. + * FreeType error code. 0 means success, -1 means success and unchanged + * axis values. */ FT_LOCAL_DEF( FT_Error ) - TT_Get_MM_Blend( TT_Face face, + TT_Get_MM_Blend( FT_Face face, /* TT_Face */ FT_UInt num_coords, FT_Fixed* coords ) { + TT_Face ttface = (TT_Face)face; + FT_Error error = FT_Err_Ok; GX_Blend blend; FT_UInt i, nc; - if ( !face->blend ) + if ( !ttface->blend ) { if ( FT_SET_ERROR( TT_Get_MM_Var( face, NULL ) ) ) return error; } - blend = face->blend; + blend = ttface->blend; if ( !blend->coords ) { /* select default instance coordinates */ /* if no instance is selected yet */ - if ( FT_SET_ERROR( tt_set_mm_blend( face, 0, NULL, 1 ) ) ) + if ( FT_SET_ERROR( tt_set_mm_blend( ttface, 0, NULL, 1 ) ) ) return error; } @@ -3042,7 +3077,7 @@ nc = blend->num_axis; } - if ( face->doblend ) + if ( ttface->doblend ) { for ( i = 0; i < nc; i++ ) coords[i] = blend->normalizedcoords[i]; @@ -3089,15 +3124,16 @@ * FreeType error code. 0 means success. */ FT_LOCAL_DEF( FT_Error ) - TT_Set_Var_Design( TT_Face face, + TT_Set_Var_Design( FT_Face face, /* TT_Face */ FT_UInt num_coords, FT_Fixed* coords ) { + TT_Face ttface = (TT_Face)face; FT_Error error = FT_Err_Ok; GX_Blend blend; FT_MM_Var* mmvar; FT_UInt i; - FT_Memory memory = face->root.memory; + FT_Memory memory = FT_FACE_MEMORY( face ); FT_Fixed* c; FT_Fixed* n; @@ -3106,13 +3142,13 @@ FT_Bool have_diff = 0; - if ( !face->blend ) + if ( !ttface->blend ) { if ( FT_SET_ERROR( TT_Get_MM_Var( face, NULL ) ) ) goto Exit; } - blend = face->blend; + blend = ttface->blend; mmvar = blend->mmvar; if ( num_coords > mmvar->num_axis ) @@ -3140,13 +3176,13 @@ } } - if ( FT_IS_NAMED_INSTANCE( FT_FACE( face ) ) ) + if ( FT_IS_NAMED_INSTANCE( face ) ) { FT_UInt instance_index; FT_Var_Named_Style* named_style; - instance_index = (FT_UInt)face->root.face_index >> 16; + instance_index = (FT_UInt)face->face_index >> 16; named_style = mmvar->namedstyle + instance_index - 1; n = named_style->coords + num_coords; @@ -3183,22 +3219,17 @@ if ( FT_NEW_ARRAY( normalized, mmvar->num_axis ) ) goto Exit; - if ( !face->blend->avar_loaded ) - ft_var_load_avar( face ); + if ( !ttface->blend->avar_loaded ) + ft_var_load_avar( ttface ); FT_TRACE5(( "TT_Set_Var_Design:\n" )); FT_TRACE5(( " normalized design coordinates:\n" )); - ft_var_to_normalized( face, num_coords, blend->coords, normalized ); + ft_var_to_normalized( ttface, num_coords, blend->coords, normalized ); - error = tt_set_mm_blend( face, mmvar->num_axis, normalized, 0 ); + error = tt_set_mm_blend( ttface, mmvar->num_axis, normalized, 0 ); if ( error ) goto Exit; - if ( num_coords ) - face->root.face_flags |= FT_FACE_FLAG_VARIATION; - else - face->root.face_flags &= ~FT_FACE_FLAG_VARIATION; - Exit: FT_FREE( normalized ); return error; @@ -3231,28 +3262,29 @@ * FreeType error code. 0~means success. */ FT_LOCAL_DEF( FT_Error ) - TT_Get_Var_Design( TT_Face face, + TT_Get_Var_Design( FT_Face face, /* TT_Face */ FT_UInt num_coords, FT_Fixed* coords ) { - FT_Error error = FT_Err_Ok; + TT_Face ttface = (TT_Face)face; + FT_Error error = FT_Err_Ok; GX_Blend blend; FT_UInt i, nc; - if ( !face->blend ) + if ( !ttface->blend ) { if ( FT_SET_ERROR( TT_Get_MM_Var( face, NULL ) ) ) return error; } - blend = face->blend; + blend = ttface->blend; if ( !blend->coords ) { /* select default instance coordinates */ /* if no instance is selected yet */ - if ( FT_SET_ERROR( tt_set_mm_blend( face, 0, NULL, 1 ) ) ) + if ( FT_SET_ERROR( tt_set_mm_blend( ttface, 0, NULL, 1 ) ) ) return error; } @@ -3265,7 +3297,7 @@ nc = blend->num_axis; } - if ( face->doblend ) + if ( ttface->doblend ) { for ( i = 0; i < nc; i++ ) coords[i] = blend->coords[i]; @@ -3301,29 +3333,33 @@ * Value 0 indicates to not use an instance. * * @Return: - * FreeType error code. 0~means success. + * FreeType error code. 0~means success, -1 means success and unchanged + * axis values. */ FT_LOCAL_DEF( FT_Error ) - TT_Set_Named_Instance( TT_Face face, + TT_Set_Named_Instance( FT_Face face, /* TT_Face */ FT_UInt instance_index ) { + TT_Face ttface = (TT_Face)face; FT_Error error; GX_Blend blend; FT_MM_Var* mmvar; + FT_Memory memory = FT_FACE_MEMORY( face ); + FT_UInt num_instances; - if ( !face->blend ) + if ( !ttface->blend ) { if ( FT_SET_ERROR( TT_Get_MM_Var( face, NULL ) ) ) goto Exit; } - blend = face->blend; + blend = ttface->blend; mmvar = blend->mmvar; - num_instances = (FT_UInt)face->root.style_flags >> 16; + num_instances = (FT_UInt)face->style_flags >> 16; /* `instance_index' starts with value 1, thus `>' */ if ( instance_index > num_instances ) @@ -3334,8 +3370,7 @@ if ( instance_index > 0 ) { - FT_Memory memory = face->root.memory; - SFNT_Service sfnt = (SFNT_Service)face->sfnt; + SFNT_Service sfnt = (SFNT_Service)ttface->sfnt; FT_Var_Named_Style* named_style; FT_String* style_name; @@ -3343,40 +3378,89 @@ named_style = mmvar->namedstyle + instance_index - 1; - error = sfnt->get_name( face, + error = sfnt->get_name( ttface, (FT_UShort)named_style->strid, &style_name ); if ( error ) goto Exit; /* set (or replace) style name */ - FT_FREE( face->root.style_name ); - face->root.style_name = style_name; + FT_FREE( face->style_name ); + face->style_name = style_name; /* finally, select the named instance */ error = TT_Set_Var_Design( face, mmvar->num_axis, named_style->coords ); - if ( error ) - { - /* internal error code -1 means `no change' */ - if ( error == -1 ) - error = FT_Err_Ok; - goto Exit; - } } else + { + /* restore non-VF style name */ + FT_FREE( face->style_name ); + if ( FT_STRDUP( face->style_name, ttface->non_var_style_name ) ) + goto Exit; error = TT_Set_Var_Design( face, 0, NULL ); - - face->root.face_index = ( instance_index << 16 ) | - ( face->root.face_index & 0xFFFFL ); - face->root.face_flags &= ~FT_FACE_FLAG_VARIATION; + } Exit: return error; } + /************************************************************************** + * + * @Function: + * TT_Get_Default_Named_Instance + * + * @Description: + * Get the default named instance. + * + * @Input: + * face :: + * A handle to the source face. + * + * @Output: + * instance_index :: + * The default named instance index. + * + * @Return: + * FreeType error code. 0~means success. + */ + FT_LOCAL_DEF( FT_Error ) + TT_Get_Default_Named_Instance( FT_Face face, + FT_UInt *instance_index ) + { + TT_Face ttface = (TT_Face)face; + FT_Error error = FT_Err_Ok; + + + if ( !ttface->blend ) + { + if ( FT_SET_ERROR( TT_Get_MM_Var( face, NULL ) ) ) + goto Exit; + } + + *instance_index = ttface->var_default_named_instance; + + Exit: + return error; + } + + + /* This function triggers (lazy) recomputation of the `postscript_name` */ + /* field in `TT_Face`. */ + + FT_LOCAL_DEF( void ) + tt_construct_ps_name( FT_Face face ) + { + TT_Face ttface = (TT_Face)face; + FT_Memory memory = FT_FACE_MEMORY( face ); + + + FT_FREE( ttface->postscript_name ); + } + + /*************************************************************************/ /*************************************************************************/ /***** *****/ @@ -4409,22 +4493,25 @@ * the MM machinery in case it isn't loaded yet. */ FT_LOCAL_DEF( FT_Error ) - tt_get_var_blend( TT_Face face, + tt_get_var_blend( FT_Face face, /* TT_Face */ FT_UInt *num_coords, FT_Fixed* *coords, FT_Fixed* *normalizedcoords, FT_MM_Var* *mm_var ) { - if ( face->blend ) + TT_Face ttface = (TT_Face)face; + + + if ( ttface->blend ) { if ( num_coords ) - *num_coords = face->blend->num_axis; + *num_coords = ttface->blend->num_axis; if ( coords ) - *coords = face->blend->coords; + *coords = ttface->blend->coords; if ( normalizedcoords ) - *normalizedcoords = face->blend->normalizedcoords; + *normalizedcoords = ttface->blend->normalizedcoords; if ( mm_var ) - *mm_var = face->blend->mmvar; + *mm_var = ttface->blend->mmvar; } else { @@ -4441,7 +4528,7 @@ FT_LOCAL_DEF( void ) - tt_var_done_item_variation_store( TT_Face face, + tt_var_done_item_variation_store( FT_Face face, GX_ItemVarStore itemStore ) { FT_Memory memory = FT_FACE_MEMORY( face ); @@ -4470,7 +4557,7 @@ FT_LOCAL_DEF( void ) - tt_var_done_delta_set_index_map( TT_Face face, + tt_var_done_delta_set_index_map( FT_Face face, GX_DeltaSetIdxMap deltaSetIdxMap ) { FT_Memory memory = FT_FACE_MEMORY( face ); @@ -4490,10 +4577,11 @@ * Free the blend internal data structure. */ FT_LOCAL_DEF( void ) - tt_done_blend( TT_Face face ) + tt_done_blend( FT_Face face ) { + TT_Face ttface = (TT_Face)face; FT_Memory memory = FT_FACE_MEMORY( face ); - GX_Blend blend = face->blend; + GX_Blend blend = ttface->blend; if ( blend ) @@ -4565,7 +4653,7 @@ #else /* !TT_CONFIG_OPTION_GX_VAR_SUPPORT */ /* ANSI C doesn't like empty source files */ - typedef int _tt_gxvar_dummy; + typedef int tt_gxvar_dummy_; #endif /* !TT_CONFIG_OPTION_GX_VAR_SUPPORT */ diff --git a/src/3rdparty/freetype/src/truetype/ttgxvar.h b/src/3rdparty/freetype/src/truetype/ttgxvar.h index 4fec980dcc0..e3da6d1705c 100644 --- a/src/3rdparty/freetype/src/truetype/ttgxvar.h +++ b/src/3rdparty/freetype/src/truetype/ttgxvar.h @@ -347,33 +347,40 @@ FT_BEGIN_HEADER FT_LOCAL( FT_Error ) - TT_Set_MM_Blend( TT_Face face, + TT_Set_MM_Blend( FT_Face face, FT_UInt num_coords, FT_Fixed* coords ); FT_LOCAL( FT_Error ) - TT_Get_MM_Blend( TT_Face face, + TT_Get_MM_Blend( FT_Face face, FT_UInt num_coords, FT_Fixed* coords ); FT_LOCAL( FT_Error ) - TT_Set_Var_Design( TT_Face face, + TT_Set_Var_Design( FT_Face face, FT_UInt num_coords, FT_Fixed* coords ); FT_LOCAL( FT_Error ) - TT_Get_MM_Var( TT_Face face, + TT_Get_MM_Var( FT_Face face, FT_MM_Var* *master ); FT_LOCAL( FT_Error ) - TT_Get_Var_Design( TT_Face face, + TT_Get_Var_Design( FT_Face face, FT_UInt num_coords, FT_Fixed* coords ); FT_LOCAL( FT_Error ) - TT_Set_Named_Instance( TT_Face face, + TT_Set_Named_Instance( FT_Face face, FT_UInt instance_index ); + FT_LOCAL( FT_Error ) + TT_Get_Default_Named_Instance( FT_Face face, + FT_UInt *instance_index ); + + FT_LOCAL( void ) + tt_construct_ps_name( FT_Face face ); + FT_LOCAL( FT_Error ) tt_face_vary_cvt( TT_Face face, FT_Stream stream ); @@ -385,55 +392,54 @@ FT_BEGIN_HEADER FT_Vector* unrounded ); FT_LOCAL( FT_Error ) - tt_hadvance_adjust( TT_Face face, + tt_hadvance_adjust( FT_Face face, FT_UInt gindex, FT_Int *adelta ); FT_LOCAL( FT_Error ) - tt_vadvance_adjust( TT_Face face, + tt_vadvance_adjust( FT_Face face, FT_UInt gindex, FT_Int *adelta ); FT_LOCAL( void ) - tt_apply_mvar( TT_Face face ); - + tt_apply_mvar( FT_Face face ); FT_LOCAL( FT_Error ) - tt_var_load_item_variation_store( TT_Face face, + tt_var_load_item_variation_store( FT_Face face, FT_ULong offset, GX_ItemVarStore itemStore ); FT_LOCAL( FT_Error ) - tt_var_load_delta_set_index_mapping( TT_Face face, + tt_var_load_delta_set_index_mapping( FT_Face face, FT_ULong offset, GX_DeltaSetIdxMap map, GX_ItemVarStore itemStore, FT_ULong table_len ); FT_LOCAL( FT_ItemVarDelta ) - tt_var_get_item_delta( TT_Face face, + tt_var_get_item_delta( FT_Face face, GX_ItemVarStore itemStore, FT_UInt outerIndex, FT_UInt innerIndex ); FT_LOCAL( void ) - tt_var_done_item_variation_store( TT_Face face, + tt_var_done_item_variation_store( FT_Face face, GX_ItemVarStore itemStore ); FT_LOCAL( void ) - tt_var_done_delta_set_index_map( TT_Face face, + tt_var_done_delta_set_index_map( FT_Face face, GX_DeltaSetIdxMap deltaSetIdxMap ); FT_LOCAL( FT_Error ) - tt_get_var_blend( TT_Face face, + tt_get_var_blend( FT_Face face, FT_UInt *num_coords, FT_Fixed* *coords, FT_Fixed* *normalizedcoords, FT_MM_Var* *mm_var ); FT_LOCAL( void ) - tt_done_blend( TT_Face face ); + tt_done_blend( FT_Face face ); #endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */ diff --git a/src/3rdparty/freetype/src/truetype/ttinterp.c b/src/3rdparty/freetype/src/truetype/ttinterp.c index 4fcfaa3e430..34c3e6c92a4 100644 --- a/src/3rdparty/freetype/src/truetype/ttinterp.c +++ b/src/3rdparty/freetype/src/truetype/ttinterp.c @@ -275,57 +275,6 @@ } - /************************************************************************** - * - * @Function: - * Update_Max - * - * @Description: - * Checks the size of a buffer and reallocates it if necessary. - * - * @Input: - * memory :: - * A handle to the parent memory object. - * - * multiplier :: - * The size in bytes of each element in the buffer. - * - * new_max :: - * The new capacity (size) of the buffer. - * - * @InOut: - * size :: - * The address of the buffer's current size expressed - * in elements. - * - * buff :: - * The address of the buffer base pointer. - * - * @Return: - * FreeType error code. 0 means success. - */ - FT_LOCAL_DEF( FT_Error ) - Update_Max( FT_Memory memory, - FT_ULong* size, - FT_ULong multiplier, - void* _pbuff, - FT_ULong new_max ) - { - FT_Error error; - void** pbuff = (void**)_pbuff; - - - if ( *size < new_max ) - { - if ( FT_QREALLOC( *pbuff, *size * multiplier, new_max * multiplier ) ) - return error; - *size = new_max; - } - - return FT_Err_Ok; - } - - /************************************************************************** * * @Function: @@ -359,9 +308,9 @@ TT_Size size ) { FT_Int i; - FT_ULong tmp; TT_MaxProfile* maxp; FT_Error error; + FT_Memory memory = exec->memory; exec->face = face; @@ -406,25 +355,15 @@ /* XXX: We reserve a little more elements on the stack to deal safely */ /* with broken fonts like arialbs, courbs, timesbs, etc. */ - tmp = (FT_ULong)exec->stackSize; - error = Update_Max( exec->memory, - &tmp, - sizeof ( FT_F26Dot6 ), - (void*)&exec->stack, - maxp->maxStackElements + 32 ); - exec->stackSize = (FT_Long)tmp; - if ( error ) + if ( FT_QRENEW_ARRAY( exec->stack, + exec->stackSize, + maxp->maxStackElements + 32 ) ) return error; + exec->stackSize = maxp->maxStackElements + 32; - tmp = (FT_ULong)exec->glyphSize; - error = Update_Max( exec->memory, - &tmp, - sizeof ( FT_Byte ), - (void*)&exec->glyphIns, - maxp->maxSizeOfInstructions ); - exec->glyphSize = (FT_UInt)tmp; - if ( error ) - return error; + /* free previous glyph code range */ + FT_FREE( exec->glyphIns ); + exec->glyphSize = 0; exec->pts.n_points = 0; exec->pts.n_contours = 0; @@ -1530,14 +1469,16 @@ if ( exc->iniRange == tt_coderange_glyph && exc->cvt != exc->glyfCvt ) { - exc->error = Update_Max( exc->memory, - &exc->glyfCvtSize, - sizeof ( FT_Long ), - (void*)&exc->glyfCvt, - exc->cvtSize ); - if ( exc->error ) + FT_Memory memory = exc->memory; + FT_Error error; + + + FT_MEM_QRENEW_ARRAY( exc->glyfCvt, exc->glyfCvtSize, exc->cvtSize ); + exc->error = error; + if ( error ) return; + exc->glyfCvtSize = exc->cvtSize; FT_ARRAY_COPY( exc->glyfCvt, exc->cvt, exc->glyfCvtSize ); exc->cvt = exc->glyfCvt; } @@ -3117,18 +3058,18 @@ if ( exc->iniRange == tt_coderange_glyph && exc->storage != exc->glyfStorage ) { - FT_ULong tmp = (FT_ULong)exc->glyfStoreSize; + FT_Memory memory = exc->memory; + FT_Error error; - exc->error = Update_Max( exc->memory, - &tmp, - sizeof ( FT_Long ), - (void*)&exc->glyfStorage, - exc->storeSize ); - exc->glyfStoreSize = (FT_UShort)tmp; - if ( exc->error ) + FT_MEM_QRENEW_ARRAY( exc->glyfStorage, + exc->glyfStoreSize, + exc->storeSize ); + exc->error = error; + if ( error ) return; + exc->glyfStoreSize = exc->storeSize; FT_ARRAY_COPY( exc->glyfStorage, exc->storage, exc->glyfStoreSize ); exc->storage = exc->glyfStorage; } @@ -3606,7 +3547,8 @@ #ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY /* arguments to opcodes are skipped by `SKIP_Code' */ - FT_Byte opcode_pattern[9][12] = { + FT_Byte opcode_pattern[9][12] = + { /* #0 inline delta function 1 */ { 0x4B, /* PPEM */ @@ -7380,14 +7322,6 @@ * GETINFO[]: GET INFOrmation * Opcode range: 0x88 * Stack: uint32 --> uint32 - * - * XXX: UNDOCUMENTED: Selector bits higher than 9 are currently (May - * 2015) not documented in the OpenType specification. - * - * Selector bit 11 is incorrectly described as bit 8, while the - * real meaning of bit 8 (vertical LCD subpixels) stays - * undocumented. The same mistake can be found in Greg Hitchcock's - * whitepaper. */ static void Ins_GETINFO( TT_ExecContext exc, @@ -7446,8 +7380,6 @@ * VARIATION GLYPH * Selector Bit: 3 * Return Bit(s): 10 - * - * XXX: UNDOCUMENTED! */ if ( (args[0] & 8 ) != 0 && exc->face->blend ) K |= 1 << 10; @@ -7739,20 +7671,23 @@ /* documentation is in ttinterp.h */ FT_EXPORT_DEF( FT_Error ) - TT_RunIns( TT_ExecContext exc ) + TT_RunIns( void* exec ) { + TT_ExecContext exc = (TT_ExecContext)exec; + FT_ULong ins_counter = 0; /* executed instructions counter */ FT_ULong num_twilight_points; FT_UShort i; #ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY - FT_Byte opcode_pattern[1][2] = { - /* #8 TypeMan Talk Align */ - { - 0x06, /* SPVTL */ - 0x7D, /* RDTG */ - }, - }; + FT_Byte opcode_pattern[1][2] = + { + /* #8 TypeMan Talk Align */ + { + 0x06, /* SPVTL */ + 0x7D, /* RDTG */ + }, + }; FT_UShort opcode_patterns = 1; FT_UShort opcode_pointer[1] = { 0 }; FT_UShort opcode_size[1] = { 1 }; @@ -7906,7 +7841,7 @@ /* a variable number of arguments */ /* it is the job of the application to `activate' GX handling, */ - /* this is, calling any of the GX API functions on the current */ + /* that is, calling any of the GX API functions on the current */ /* font to select a variation instance */ if ( exc->face->blend ) exc->new_top = exc->args + exc->face->blend->num_axis; @@ -8466,7 +8401,7 @@ #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT case 0x91: /* it is the job of the application to `activate' GX handling, */ - /* this is, calling any of the GX API functions on the current */ + /* that is, calling any of the GX API functions on the current */ /* font to select a variation instance */ if ( exc->face->blend ) Ins_GETVARIATION( exc, args ); @@ -8604,7 +8539,7 @@ #else /* !TT_USE_BYTECODE_INTERPRETER */ /* ANSI C doesn't like empty source files */ - typedef int _tt_interp_dummy; + typedef int tt_interp_dummy_; #endif /* !TT_USE_BYTECODE_INTERPRETER */ diff --git a/src/3rdparty/freetype/src/truetype/ttinterp.h b/src/3rdparty/freetype/src/truetype/ttinterp.h index c54c053b29e..48d493af801 100644 --- a/src/3rdparty/freetype/src/truetype/ttinterp.h +++ b/src/3rdparty/freetype/src/truetype/ttinterp.h @@ -460,14 +460,6 @@ FT_BEGIN_HEADER FT_LOCAL( void ) TT_Clear_CodeRange( TT_ExecContext exec, FT_Int range ); - - - FT_LOCAL( FT_Error ) - Update_Max( FT_Memory memory, - FT_ULong* size, - FT_ULong multiplier, - void* _pbuff, - FT_ULong new_max ); #endif /* TT_USE_BYTECODE_INTERPRETER */ @@ -536,7 +528,7 @@ FT_BEGIN_HEADER * invoked by the TrueType debugger. */ FT_EXPORT( FT_Error ) - TT_RunIns( TT_ExecContext exec ); + TT_RunIns( void* exec ); FT_END_HEADER diff --git a/src/3rdparty/freetype/src/truetype/ttobjs.c b/src/3rdparty/freetype/src/truetype/ttobjs.c index 4a8873fd8c8..958fa54d426 100644 --- a/src/3rdparty/freetype/src/truetype/ttobjs.c +++ b/src/3rdparty/freetype/src/truetype/ttobjs.c @@ -312,7 +312,8 @@ #define TRICK_SFNT_IDS_NUM_FACES 31 static const tt_sfnt_id_rec sfnt_id[TRICK_SFNT_IDS_NUM_FACES] - [TRICK_SFNT_IDS_PER_FACE] = { + [TRICK_SFNT_IDS_PER_FACE] = + { #define TRICK_SFNT_ID_cvt 0 #define TRICK_SFNT_ID_fpgm 1 @@ -581,7 +582,7 @@ FT_Bool result = FALSE; TT_Face face = (TT_Face)ttface; - FT_UInt asize; + FT_ULong asize; FT_ULong i; FT_ULong glyph_index = 0; FT_UInt count = 0; @@ -589,7 +590,7 @@ for( i = 0; i < face->num_locations; i++ ) { - tt_face_get_location( face, i, &asize ); + tt_face_get_location( ttface, i, &asize ); if ( asize > 0 ) { count += 1; @@ -777,7 +778,6 @@ } #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT - { FT_UInt instance_index = (FT_UInt)face_index >> 16; @@ -785,14 +785,11 @@ if ( FT_HAS_MULTIPLE_MASTERS( ttface ) && instance_index > 0 ) { - error = TT_Set_Named_Instance( face, instance_index ); + error = FT_Set_Named_Instance( ttface, instance_index ); if ( error ) goto Exit; - - tt_apply_mvar( face ); } } - #endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */ /* initialize standard glyph loading routines */ @@ -858,7 +855,7 @@ face->cvt_program_size = 0; #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT - tt_done_blend( face ); + tt_done_blend( ttface ); face->blend = NULL; #endif } @@ -1338,39 +1335,29 @@ /************************************************************************** * * @Function: - * tt_size_reset + * tt_size_reset_height * * @Description: - * Reset a TrueType size when resolutions and character dimensions - * have been changed. + * Recompute a TrueType size's ascender, descender, and height + * when resolutions and character dimensions have been changed. + * Used for variation fonts as an iterator function. * * @Input: - * size :: - * A handle to the target size object. - * - * only_height :: - * Only recompute ascender, descender, and height; - * this flag is used for variation fonts where - * `tt_size_reset' is used as an iterator function. + * ft_size :: + * A handle to the target TT_Size object. This function will be called + * through a `FT_Size_Reset_Func` pointer which takes `FT_Size`. This + * function must take `FT_Size` as a result. The passed `FT_Size` is + * expected to point to a `TT_Size`. */ FT_LOCAL_DEF( FT_Error ) - tt_size_reset( TT_Size size, - FT_Bool only_height ) + tt_size_reset_height( FT_Size ft_size ) { - TT_Face face; - FT_Size_Metrics* size_metrics; - - - face = (TT_Face)size->root.face; - - /* nothing to do for CFF2 */ - if ( face->is_cff2 ) - return FT_Err_Ok; + TT_Size size = (TT_Size)ft_size; + TT_Face face = (TT_Face)size->root.face; + FT_Size_Metrics* size_metrics = &size->hinted_metrics; size->ttmetrics.valid = FALSE; - size_metrics = &size->hinted_metrics; - /* copy the result from base layer */ *size_metrics = size->root.metrics; @@ -1397,12 +1384,34 @@ size->ttmetrics.valid = TRUE; - if ( only_height ) - { - /* we must not recompute the scaling values here since */ - /* `tt_size_reset' was already called (with only_height = 0) */ - return FT_Err_Ok; - } + return FT_Err_Ok; + } + + + /************************************************************************** + * + * @Function: + * tt_size_reset + * + * @Description: + * Reset a TrueType size when resolutions and character dimensions + * have been changed. + * + * @Input: + * size :: + * A handle to the target size object. + */ + FT_LOCAL_DEF( FT_Error ) + tt_size_reset( TT_Size size ) + { + FT_Error error; + TT_Face face = (TT_Face)size->root.face; + FT_Size_Metrics* size_metrics = &size->hinted_metrics; + + + error = tt_size_reset_height( (FT_Size)size ); + if ( error ) + return error; if ( face->header.Flags & 8 ) { diff --git a/src/3rdparty/freetype/src/truetype/ttobjs.h b/src/3rdparty/freetype/src/truetype/ttobjs.h index bc6fbe7f196..d1834c046f3 100644 --- a/src/3rdparty/freetype/src/truetype/ttobjs.h +++ b/src/3rdparty/freetype/src/truetype/ttobjs.h @@ -391,8 +391,10 @@ FT_BEGIN_HEADER #endif /* TT_USE_BYTECODE_INTERPRETER */ FT_LOCAL( FT_Error ) - tt_size_reset( TT_Size size, - FT_Bool only_height ); + tt_size_reset_height( FT_Size size ); + + FT_LOCAL( FT_Error ) + tt_size_reset( TT_Size size ); /************************************************************************** diff --git a/src/3rdparty/freetype/src/truetype/ttpload.c b/src/3rdparty/freetype/src/truetype/ttpload.c index e08bf309e3c..54a64c7b462 100644 --- a/src/3rdparty/freetype/src/truetype/ttpload.c +++ b/src/3rdparty/freetype/src/truetype/ttpload.c @@ -180,10 +180,11 @@ FT_LOCAL_DEF( FT_ULong ) - tt_face_get_location( TT_Face face, - FT_UInt gindex, - FT_UInt *asize ) + tt_face_get_location( FT_Face face, /* TT_Face */ + FT_UInt gindex, + FT_ULong *asize ) { + TT_Face ttface = (TT_Face)face; FT_ULong pos1, pos2; FT_Byte* p; FT_Byte* p_limit; @@ -191,12 +192,12 @@ pos1 = pos2 = 0; - if ( gindex < face->num_locations ) + if ( gindex < ttface->num_locations ) { - if ( face->header.Index_To_Loc_Format != 0 ) + if ( ttface->header.Index_To_Loc_Format != 0 ) { - p = face->glyph_locations + gindex * 4; - p_limit = face->glyph_locations + face->num_locations * 4; + p = ttface->glyph_locations + gindex * 4; + p_limit = ttface->glyph_locations + ttface->num_locations * 4; pos1 = FT_NEXT_ULONG( p ); pos2 = pos1; @@ -206,8 +207,8 @@ } else { - p = face->glyph_locations + gindex * 2; - p_limit = face->glyph_locations + face->num_locations * 2; + p = ttface->glyph_locations + gindex * 2; + p_limit = ttface->glyph_locations + ttface->num_locations * 2; pos1 = FT_NEXT_USHORT( p ); pos2 = pos1; @@ -221,30 +222,30 @@ } /* Check broken location data. */ - if ( pos1 > face->glyf_len ) + if ( pos1 > ttface->glyf_len ) { FT_TRACE1(( "tt_face_get_location:" " too large offset (0x%08lx) found for glyph index %d,\n", pos1, gindex )); FT_TRACE1(( " " " exceeding the end of `glyf' table (0x%08lx)\n", - face->glyf_len )); + ttface->glyf_len )); *asize = 0; return 0; } - if ( pos2 > face->glyf_len ) + if ( pos2 > ttface->glyf_len ) { /* We try to sanitize the last `loca' entry. */ - if ( gindex == face->num_locations - 2 ) + if ( gindex == ttface->num_locations - 2 ) { FT_TRACE1(( "tt_face_get_location:" " too large size (%ld bytes) found for glyph index %d,\n", pos2 - pos1, gindex )); FT_TRACE1(( " " " truncating at the end of `glyf' table to %ld bytes\n", - face->glyf_len - pos1 )); - pos2 = face->glyf_len; + ttface->glyf_len - pos1 )); + pos2 = ttface->glyf_len; } else { @@ -253,7 +254,7 @@ pos2, gindex + 1 )); FT_TRACE1(( " " " exceeding the end of `glyf' table (0x%08lx)\n", - face->glyf_len )); + ttface->glyf_len )); *asize = 0; return 0; } @@ -268,9 +269,9 @@ /* We get (intentionally) a wrong, non-zero result in case the */ /* `glyf' table is missing. */ if ( pos2 >= pos1 ) - *asize = (FT_UInt)( pos2 - pos1 ); + *asize = (FT_ULong)( pos2 - pos1 ); else - *asize = (FT_UInt)( face->glyf_len - pos1 ); + *asize = (FT_ULong)( ttface->glyf_len - pos1 ); return pos1; } diff --git a/src/3rdparty/freetype/src/truetype/ttpload.h b/src/3rdparty/freetype/src/truetype/ttpload.h index 939e02fe4f1..ed229fa4616 100644 --- a/src/3rdparty/freetype/src/truetype/ttpload.h +++ b/src/3rdparty/freetype/src/truetype/ttpload.h @@ -31,9 +31,9 @@ FT_BEGIN_HEADER FT_Stream stream ); FT_LOCAL( FT_ULong ) - tt_face_get_location( TT_Face face, - FT_UInt gindex, - FT_UInt *asize ); + tt_face_get_location( FT_Face face, + FT_UInt gindex, + FT_ULong *asize ); FT_LOCAL( void ) tt_face_done_loca( TT_Face face ); diff --git a/src/3rdparty/freetype/src/truetype/ttsubpix.c b/src/3rdparty/freetype/src/truetype/ttsubpix.c index d811beef0df..aed4a1a2748 100644 --- a/src/3rdparty/freetype/src/truetype/ttsubpix.c +++ b/src/3rdparty/freetype/src/truetype/ttsubpix.c @@ -1004,7 +1004,7 @@ /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY) */ /* ANSI C doesn't like empty source files */ - typedef int _tt_subpix_dummy; + typedef int tt_subpix_dummy_; #endif /* !(TT_USE_BYTECODE_INTERPRETER && */ /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY) */ diff --git a/src/3rdparty/freetype/src/type1/t1afm.c b/src/3rdparty/freetype/src/type1/t1afm.c index 787aa92c98a..d9b9398b013 100644 --- a/src/3rdparty/freetype/src/type1/t1afm.c +++ b/src/3rdparty/freetype/src/type1/t1afm.c @@ -299,7 +299,7 @@ /* ascender and descender are optional and could both be zero */ /* check if values are meaningful before overriding defaults */ if ( fi->Ascender > fi->Descender ) - { + { /* no `U' suffix here to 0x8000! */ t1_face->ascender = (FT_Short)( ( fi->Ascender + 0x8000 ) >> 16 ); t1_face->descender = (FT_Short)( ( fi->Descender + 0x8000 ) >> 16 ); @@ -405,7 +405,7 @@ #else /* T1_CONFIG_OPTION_NO_AFM */ /* ANSI C doesn't like empty source files */ - typedef int _t1_afm_dummy; + typedef int t1_afm_dummy_; #endif /* T1_CONFIG_OPTION_NO_AFM */ diff --git a/src/3rdparty/freetype/src/type1/t1driver.c b/src/3rdparty/freetype/src/type1/t1driver.c index ded3b264e85..a4cdf372a9e 100644 --- a/src/3rdparty/freetype/src/type1/t1driver.c +++ b/src/3rdparty/freetype/src/type1/t1driver.c @@ -56,28 +56,32 @@ * */ - static FT_Error - t1_get_glyph_name( T1_Face face, + FT_CALLBACK_DEF( FT_Error ) + t1_get_glyph_name( FT_Face face, /* T1_Face */ FT_UInt glyph_index, FT_Pointer buffer, FT_UInt buffer_max ) { - FT_STRCPYN( buffer, face->type1.glyph_names[glyph_index], buffer_max ); + T1_Face t1face = (T1_Face)face; + + + FT_STRCPYN( buffer, t1face->type1.glyph_names[glyph_index], buffer_max ); return FT_Err_Ok; } - static FT_UInt - t1_get_name_index( T1_Face face, + FT_CALLBACK_DEF( FT_UInt ) + t1_get_name_index( FT_Face face, /* T1_Face */ const FT_String* glyph_name ) { - FT_Int i; + T1_Face t1face = (T1_Face)face; + FT_Int i; - for ( i = 0; i < face->type1.num_glyphs; i++ ) + for ( i = 0; i < t1face->type1.num_glyphs; i++ ) { - FT_String* gname = face->type1.glyph_names[i]; + FT_String* gname = t1face->type1.glyph_names[i]; if ( !ft_strcmp( glyph_name, gname ) ) @@ -90,8 +94,8 @@ static const FT_Service_GlyphDictRec t1_service_glyph_dict = { - (FT_GlyphDict_GetNameFunc) t1_get_glyph_name, /* get_name */ - (FT_GlyphDict_NameIndexFunc)t1_get_name_index /* name_index */ + t1_get_glyph_name, /* FT_GlyphDict_GetNameFunc get_name */ + t1_get_name_index /* FT_GlyphDict_NameIndexFunc name_index */ }; @@ -101,9 +105,12 @@ */ static const char* - t1_get_ps_name( T1_Face face ) + t1_get_ps_name( FT_Face face ) /* T1_Face */ { - return (const char*) face->type1.font_name; + T1_Face t1face = (T1_Face)face; + + + return (const char*) t1face->type1.font_name; } @@ -121,30 +128,28 @@ #ifndef T1_CONFIG_OPTION_NO_MM_SUPPORT static const FT_Service_MultiMastersRec t1_service_multi_masters = { - (FT_Get_MM_Func) T1_Get_Multi_Master, /* get_mm */ - (FT_Set_MM_Design_Func) T1_Set_MM_Design, /* set_mm_design */ - (FT_Set_MM_Blend_Func) T1_Set_MM_Blend, /* set_mm_blend */ - (FT_Get_MM_Blend_Func) T1_Get_MM_Blend, /* get_mm_blend */ - (FT_Get_MM_Var_Func) T1_Get_MM_Var, /* get_mm_var */ - (FT_Set_Var_Design_Func)T1_Set_Var_Design, /* set_var_design */ - (FT_Get_Var_Design_Func)T1_Get_Var_Design, /* get_var_design */ - (FT_Set_Instance_Func) T1_Reset_MM_Blend, /* set_instance */ - (FT_Set_MM_WeightVector_Func) - T1_Set_MM_WeightVector, /* set_mm_weightvector */ - (FT_Get_MM_WeightVector_Func) - T1_Get_MM_WeightVector, /* get_mm_weightvector */ - (FT_Var_Load_Delta_Set_Idx_Map_Func) - NULL, /* load_delta_set_idx_map */ - (FT_Var_Load_Item_Var_Store_Func) - NULL, /* load_item_variation_store */ - (FT_Var_Get_Item_Delta_Func) - NULL, /* get_item_delta */ - (FT_Var_Done_Item_Var_Store_Func) - NULL, /* done_item_variation_store */ - (FT_Var_Done_Delta_Set_Idx_Map_Func) - NULL, /* done_delta_set_index_map */ - (FT_Get_Var_Blend_Func) NULL, /* get_var_blend */ - (FT_Done_Blend_Func) T1_Done_Blend /* done_blend */ + T1_Get_Multi_Master, /* FT_Get_MM_Func get_mm */ + T1_Set_MM_Design, /* FT_Set_MM_Design_Func set_mm_design */ + T1_Set_MM_Blend, /* FT_Set_MM_Blend_Func set_mm_blend */ + T1_Get_MM_Blend, /* FT_Get_MM_Blend_Func get_mm_blend */ + T1_Get_MM_Var, /* FT_Get_MM_Var_Func get_mm_var */ + T1_Set_Var_Design, /* FT_Set_Var_Design_Func set_var_design */ + T1_Get_Var_Design, /* FT_Get_Var_Design_Func get_var_design */ + T1_Reset_MM_Blend, /* FT_Set_Named_Instance_Func set_named_instance */ + NULL, /* FT_Get_Default_Named_Instance_Func get_default_named_instance */ + T1_Set_MM_WeightVector, + /* FT_Set_MM_WeightVector_Func set_mm_weightvector */ + T1_Get_MM_WeightVector, + /* FT_Get_MM_WeightVector_Func get_mm_weightvector */ + + NULL, /* FT_Construct_PS_Name_Func construct_ps_name */ + NULL, /* FT_Var_Load_Delta_Set_Idx_Map_Func load_delta_set_idx_map */ + NULL, /* FT_Var_Load_Item_Var_Store_Func load_item_variation_store */ + NULL, /* FT_Var_Get_Item_Delta_Func get_item_delta */ + NULL, /* FT_Var_Done_Item_Var_Store_Func done_item_variation_store */ + NULL, /* FT_Var_Done_Delta_Set_Idx_Map_Func done_delta_set_index_map */ + NULL, /* FT_Get_Var_Blend_Func get_var_blend */ + T1_Done_Blend /* FT_Done_Blend_Func done_blend */ }; #endif @@ -632,11 +637,11 @@ static const FT_Service_PsInfoRec t1_service_ps_info = { - (PS_GetFontInfoFunc) t1_ps_get_font_info, /* ps_get_font_info */ - (PS_GetFontExtraFunc) t1_ps_get_font_extra, /* ps_get_font_extra */ - (PS_HasGlyphNamesFunc) t1_ps_has_glyph_names, /* ps_has_glyph_names */ - (PS_GetFontPrivateFunc)t1_ps_get_font_private, /* ps_get_font_private */ - (PS_GetFontValueFunc) t1_ps_get_font_value, /* ps_get_font_value */ + t1_ps_get_font_info, /* PS_GetFontInfoFunc ps_get_font_info */ + t1_ps_get_font_extra, /* PS_GetFontExtraFunc ps_get_font_extra */ + t1_ps_has_glyph_names, /* PS_HasGlyphNamesFunc ps_has_glyph_names */ + t1_ps_get_font_private, /* PS_GetFontPrivateFunc ps_get_font_private */ + t1_ps_get_font_value, /* PS_GetFontValueFunc ps_get_font_value */ }; @@ -656,9 +661,9 @@ FT_DEFINE_SERVICE_PROPERTIESREC( t1_service_properties, - (FT_Properties_SetFunc)ps_property_set, /* set_property */ - (FT_Properties_GetFunc)ps_property_get ) /* get_property */ - + ps_property_set, /* FT_Properties_SetFunc set_property */ + ps_property_get /* FT_Properties_GetFunc get_property */ + ) /* * SERVICE LIST diff --git a/src/3rdparty/freetype/src/type1/t1load.c b/src/3rdparty/freetype/src/type1/t1load.c index 5a1afd8d9f5..b292a3cc0ea 100644 --- a/src/3rdparty/freetype/src/type1/t1load.c +++ b/src/3rdparty/freetype/src/type1/t1load.c @@ -73,7 +73,8 @@ #ifdef FT_CONFIG_OPTION_INCREMENTAL -#define IS_INCREMENTAL FT_BOOL( face->root.internal->incremental_interface ) +#define IS_INCREMENTAL \ + FT_BOOL( FT_FACE( face )->internal->incremental_interface ) #else #define IS_INCREMENTAL 0 #endif @@ -174,10 +175,11 @@ FT_LOCAL_DEF( FT_Error ) - T1_Get_Multi_Master( T1_Face face, + T1_Get_Multi_Master( FT_Face face, /* T1_Face */ FT_Multi_Master* master ) { - PS_Blend blend = face->blend; + T1_Face t1face = (T1_Face)face; + PS_Blend blend = t1face->blend; FT_UInt n; FT_Error error; @@ -225,11 +227,12 @@ for ( j = 1; j < axismap->num_points; j++ ) { if ( ncv <= axismap->blend_points[j] ) - return INT_TO_FIXED( axismap->design_points[j - 1] ) + - ( axismap->design_points[j] - axismap->design_points[j - 1] ) * - FT_DivFix( ncv - axismap->blend_points[j - 1], - axismap->blend_points[j] - - axismap->blend_points[j - 1] ); + return INT_TO_FIXED( axismap->design_points[j - 1] + + FT_MulDiv( ncv - axismap->blend_points[j - 1], + axismap->design_points[j] - + axismap->design_points[j - 1], + axismap->blend_points[j] - + axismap->blend_points[j - 1] ) ); } return INT_TO_FIXED( axismap->design_points[axismap->num_points - 1] ); @@ -284,16 +287,17 @@ * arguments needed by the GX var distortable fonts. */ FT_LOCAL_DEF( FT_Error ) - T1_Get_MM_Var( T1_Face face, + T1_Get_MM_Var( FT_Face face, /* T1_Face */ FT_MM_Var* *master ) { - FT_Memory memory = face->root.memory; - FT_MM_Var *mmvar = NULL; + T1_Face t1face = (T1_Face)face; + FT_Memory memory = FT_FACE_MEMORY( face ); + FT_MM_Var *mmvar = NULL; FT_Multi_Master mmaster; FT_Error error; FT_UInt i; FT_Fixed axiscoords[T1_MAX_MM_AXIS]; - PS_Blend blend = face->blend; + PS_Blend blend = t1face->blend; FT_UShort* axis_flags; FT_Offset mmvar_size; @@ -319,9 +323,9 @@ sizeof ( FT_UShort ) ); axis_size = mmaster.num_axis * sizeof ( FT_Var_Axis ); - if ( FT_ALLOC( mmvar, mmvar_size + - axis_flags_size + - axis_size ) ) + if ( FT_QALLOC( mmvar, mmvar_size + + axis_flags_size + + axis_size ) ) goto Exit; mmvar->num_axis = mmaster.num_axis; @@ -332,8 +336,7 @@ /* to make `FT_Get_Var_Axis_Flags' work: the function expects that the */ /* values directly follow the data of `FT_MM_Var' */ axis_flags = (FT_UShort*)( (char*)mmvar + mmvar_size ); - for ( i = 0; i < mmaster.num_axis; i++ ) - axis_flags[i] = 0; + FT_ARRAY_ZERO( axis_flags, mmaster.num_axis ); mmvar->axis = (FT_Var_Axis*)( (char*)axis_flags + axis_flags_size ); mmvar->namedstyle = NULL; @@ -438,32 +441,21 @@ FT_LOCAL_DEF( FT_Error ) - T1_Set_MM_Blend( T1_Face face, + T1_Set_MM_Blend( FT_Face face, /* T1_Face */ FT_UInt num_coords, FT_Fixed* coords ) { - FT_Error error; - - - error = t1_set_mm_blend( face, num_coords, coords ); - if ( error ) - return error; - - if ( num_coords ) - face->root.face_flags |= FT_FACE_FLAG_VARIATION; - else - face->root.face_flags &= ~FT_FACE_FLAG_VARIATION; - - return FT_Err_Ok; + return t1_set_mm_blend( (T1_Face)face, num_coords, coords ); } FT_LOCAL_DEF( FT_Error ) - T1_Get_MM_Blend( T1_Face face, + T1_Get_MM_Blend( FT_Face face, /* T1_Face */ FT_UInt num_coords, FT_Fixed* coords ) { - PS_Blend blend = face->blend; + T1_Face t1face = (T1_Face)face; + PS_Blend blend = t1face->blend; FT_Fixed axiscoords[4]; FT_UInt i, nc; @@ -494,11 +486,12 @@ FT_LOCAL_DEF( FT_Error ) - T1_Set_MM_WeightVector( T1_Face face, + T1_Set_MM_WeightVector( FT_Face face, /* T1_Face */ FT_UInt len, FT_Fixed* weightvector ) { - PS_Blend blend = face->blend; + T1_Face t1face = (T1_Face)face; + PS_Blend blend = t1face->blend; FT_UInt i, n; @@ -522,11 +515,6 @@ for ( ; i < blend->num_designs; i++ ) blend->weight_vector[i] = (FT_Fixed)0; - - if ( len ) - face->root.face_flags |= FT_FACE_FLAG_VARIATION; - else - face->root.face_flags &= ~FT_FACE_FLAG_VARIATION; } return FT_Err_Ok; @@ -534,11 +522,12 @@ FT_LOCAL_DEF( FT_Error ) - T1_Get_MM_WeightVector( T1_Face face, + T1_Get_MM_WeightVector( FT_Face face, /* T1_Face */ FT_UInt* len, FT_Fixed* weightvector ) { - PS_Blend blend = face->blend; + T1_Face t1face = (T1_Face)face; + PS_Blend blend = t1face->blend; FT_UInt i; @@ -563,12 +552,13 @@ FT_LOCAL_DEF( FT_Error ) - T1_Set_MM_Design( T1_Face face, + T1_Set_MM_Design( FT_Face face, /* T1_Face */ FT_UInt num_coords, FT_Long* coords ) { + T1_Face t1face = (T1_Face)face; FT_Error error; - PS_Blend blend = face->blend; + PS_Blend blend = t1face->blend; FT_UInt n; FT_Fixed final_blends[T1_MAX_MM_DESIGNS]; @@ -634,15 +624,10 @@ final_blends[n] = the_blend; } - error = t1_set_mm_blend( face, blend->num_axis, final_blends ); + error = t1_set_mm_blend( t1face, blend->num_axis, final_blends ); if ( error ) return error; - if ( num_coords ) - face->root.face_flags |= FT_FACE_FLAG_VARIATION; - else - face->root.face_flags &= ~FT_FACE_FLAG_VARIATION; - return FT_Err_Ok; } @@ -650,7 +635,7 @@ /* MM fonts don't have named instances, so only the design is reset */ FT_LOCAL_DEF( FT_Error ) - T1_Reset_MM_Blend( T1_Face face, + T1_Reset_MM_Blend( FT_Face face, FT_UInt instance_index ) { FT_UNUSED( instance_index ); @@ -665,7 +650,7 @@ * arguments needed by the GX var distortable fonts. */ FT_LOCAL_DEF( FT_Error ) - T1_Set_Var_Design( T1_Face face, + T1_Set_Var_Design( FT_Face face, /* T1_Face */ FT_UInt num_coords, FT_Fixed* coords ) { @@ -684,11 +669,12 @@ FT_LOCAL_DEF( FT_Error ) - T1_Get_Var_Design( T1_Face face, + T1_Get_Var_Design( FT_Face face, /* T1_Face */ FT_UInt num_coords, FT_Fixed* coords ) { - PS_Blend blend = face->blend; + T1_Face t1face = (T1_Face)face; + PS_Blend blend = t1face->blend; FT_Fixed axiscoords[4]; FT_UInt i, nc; @@ -720,10 +706,11 @@ FT_LOCAL_DEF( void ) - T1_Done_Blend( T1_Face face ) + T1_Done_Blend( FT_Face face ) /* T1_Face */ { - FT_Memory memory = face->root.memory; - PS_Blend blend = face->blend; + T1_Face t1face = (T1_Face)face; + FT_Memory memory = FT_FACE_MEMORY( face ); + PS_Blend blend = t1face->blend; if ( blend ) @@ -768,20 +755,22 @@ dmap->num_points = 0; } - FT_FREE( face->blend ); + FT_FREE( t1face->blend ); } } static void - parse_blend_axis_types( T1_Face face, - T1_Loader loader ) + parse_blend_axis_types( FT_Face face, /* T1_Face */ + void* loader_ ) { + T1_Face t1face = (T1_Face)face; + T1_Loader loader = (T1_Loader)loader_; T1_TokenRec axis_tokens[T1_MAX_MM_AXIS]; FT_Int n, num_axis; - FT_Error error = FT_Err_Ok; + FT_Error error = FT_Err_Ok; PS_Blend blend; - FT_Memory memory; + FT_Memory memory = FT_FACE_MEMORY( face ); /* take an array of objects */ @@ -801,14 +790,13 @@ } /* allocate blend if necessary */ - error = t1_allocate_blend( face, 0, (FT_UInt)num_axis ); + error = t1_allocate_blend( t1face, 0, (FT_UInt)num_axis ); if ( error ) goto Exit; FT_TRACE4(( " [" )); - blend = face->blend; - memory = face->root.memory; + blend = t1face->blend; /* each token is an immediate containing the name of the axis */ for ( n = 0; n < num_axis; n++ ) @@ -856,14 +844,16 @@ static void - parse_blend_design_positions( T1_Face face, - T1_Loader loader ) + parse_blend_design_positions( FT_Face face, /* T1_Face */ + void* loader_ ) { + T1_Face t1face = (T1_Face)face; + T1_Loader loader = (T1_Loader)loader_; T1_TokenRec design_tokens[T1_MAX_MM_DESIGNS]; FT_Int num_designs; FT_Int num_axis = 0; /* make compiler happy */ T1_Parser parser = &loader->parser; - FT_Memory memory = face->root.memory; + FT_Memory memory = FT_FACE_MEMORY( face ); FT_Error error = FT_Err_Ok; FT_Fixed* design_pos[T1_MAX_MM_DESIGNS]; @@ -921,7 +911,7 @@ } num_axis = n_axis; - error = t1_allocate_blend( face, + error = t1_allocate_blend( t1face, (FT_UInt)num_designs, (FT_UInt)num_axis ); if ( error ) @@ -962,7 +952,7 @@ loader->parser.root.limit = old_limit; /* a valid BlendDesignPosition has been parsed */ - blend = face->blend; + blend = t1face->blend; if ( blend->design_pos[0] ) FT_FREE( blend->design_pos[0] ); @@ -980,9 +970,11 @@ static void - parse_blend_design_map( T1_Face face, - T1_Loader loader ) + parse_blend_design_map( FT_Face face, /* T1_Face */ + void* loader_ ) { + T1_Face t1face = (T1_Face)face; + T1_Loader loader = (T1_Loader)loader_; FT_Error error = FT_Err_Ok; T1_Parser parser = &loader->parser; PS_Blend blend; @@ -990,7 +982,7 @@ FT_Int n, num_axis; FT_Byte* old_cursor; FT_Byte* old_limit; - FT_Memory memory = face->root.memory; + FT_Memory memory = FT_FACE_MEMORY( face ); T1_ToTokenArray( parser, axis_tokens, @@ -1011,10 +1003,10 @@ old_cursor = parser->root.cursor; old_limit = parser->root.limit; - error = t1_allocate_blend( face, 0, (FT_UInt)num_axis ); + error = t1_allocate_blend( t1face, 0, (FT_UInt)num_axis ); if ( error ) goto Exit; - blend = face->blend; + blend = t1face->blend; FT_TRACE4(( " [" )); @@ -1089,15 +1081,17 @@ static void - parse_weight_vector( T1_Face face, - T1_Loader loader ) + parse_weight_vector( FT_Face face, /* T1_Face */ + void* loader_ ) { + T1_Face t1face = (T1_Face)face; + T1_Loader loader = (T1_Loader)loader_; T1_TokenRec design_tokens[T1_MAX_MM_DESIGNS]; FT_Int num_designs; FT_Error error = FT_Err_Ok; - FT_Memory memory = face->root.memory; + FT_Memory memory = FT_FACE_MEMORY( face ); T1_Parser parser = &loader->parser; - PS_Blend blend = face->blend; + PS_Blend blend = t1face->blend; T1_Token token; FT_Int n; FT_Byte* old_cursor; @@ -1122,10 +1116,10 @@ if ( !blend || !blend->num_designs ) { - error = t1_allocate_blend( face, (FT_UInt)num_designs, 0 ); + error = t1_allocate_blend( t1face, (FT_UInt)num_designs, 0 ); if ( error ) goto Exit; - blend = face->blend; + blend = t1face->blend; } else if ( blend->num_designs != (FT_UInt)num_designs ) { @@ -1173,11 +1167,15 @@ /* e.g., /BuildCharArray [0 0 0 0 0 0 0 0] def */ /* we're only interested in the number of array elements */ static void - parse_buildchar( T1_Face face, - T1_Loader loader ) + parse_buildchar( FT_Face face, /* T1_Face */ + void* loader_ ) { - face->len_buildchar = (FT_UInt)T1_ToFixedArray( &loader->parser, - 0, NULL, 0 ); + T1_Face t1face = (T1_Face)face; + T1_Loader loader = (T1_Loader)loader_; + + + t1face->len_buildchar = (FT_UInt)T1_ToFixedArray( &loader->parser, + 0, NULL, 0 ); #ifdef FT_DEBUG_LEVEL_TRACE { @@ -1185,7 +1183,7 @@ FT_TRACE4(( " [" )); - for ( i = 0; i < face->len_buildchar; i++ ) + for ( i = 0; i < t1face->len_buildchar; i++ ) FT_TRACE4(( " 0" )); FT_TRACE4(( "]\n" )); @@ -1335,9 +1333,10 @@ static void - parse_private( T1_Face face, - T1_Loader loader ) + parse_private( FT_Face face, + void* loader_ ) { + T1_Loader loader = (T1_Loader)loader_; FT_UNUSED( face ); loader->keywords_encountered |= T1_PRIVATE; @@ -1401,13 +1400,14 @@ /* and `/CharStrings' dictionaries. */ static void - t1_parse_font_matrix( T1_Face face, - T1_Loader loader ) + t1_parse_font_matrix( FT_Face face, /* T1_Face */ + void* loader_ ) { + T1_Face t1face = (T1_Face)face; + T1_Loader loader = (T1_Loader)loader_; T1_Parser parser = &loader->parser; - FT_Matrix* matrix = &face->type1.font_matrix; - FT_Vector* offset = &face->type1.font_offset; - FT_Face root = (FT_Face)&face->root; + FT_Matrix* matrix = &t1face->type1.font_matrix; + FT_Vector* offset = &t1face->type1.font_offset; FT_Fixed temp[6]; FT_Fixed temp_scale; FT_Int result; @@ -1443,7 +1443,7 @@ if ( temp_scale != 0x10000L ) { /* set units per EM based on FontMatrix values */ - root->units_per_EM = (FT_UShort)FT_DivFix( 1000, temp_scale ); + face->units_per_EM = (FT_UShort)FT_DivFix( 1000, temp_scale ); temp[0] = FT_DivFix( temp[0], temp_scale ); temp[1] = FT_DivFix( temp[1], temp_scale ); @@ -1471,14 +1471,16 @@ static void - parse_encoding( T1_Face face, - T1_Loader loader ) + parse_encoding( FT_Face face, /* T1_Face */ + void* loader_ ) { + T1_Face t1face = (T1_Face)face; + T1_Loader loader = (T1_Loader)loader_; T1_Parser parser = &loader->parser; FT_Byte* cur; FT_Byte* limit = parser->root.limit; - PSAux_Service psaux = (PSAux_Service)face->psaux; + PSAux_Service psaux = (PSAux_Service)t1face->psaux; T1_Skip_Spaces( parser ); @@ -1494,7 +1496,7 @@ /* and we must load it now */ if ( ft_isdigit( *cur ) || *cur == '[' ) { - T1_Encoding encode = &face->type1.encoding; + T1_Encoding encode = &t1face->type1.encoding; FT_Int count, array_size, n; PS_Table char_table = &loader->encoding_table; FT_Memory memory = parser->root.memory; @@ -1676,7 +1678,7 @@ FT_TRACE4(( "]\n" )); #endif - face->type1.encoding_type = T1_ENCODING_TYPE_ARRAY; + t1face->type1.encoding_type = T1_ENCODING_TYPE_ARRAY; parser->root.cursor = cur; } @@ -1687,21 +1689,21 @@ if ( cur + 17 < limit && ft_strncmp( (const char*)cur, "StandardEncoding", 16 ) == 0 ) { - face->type1.encoding_type = T1_ENCODING_TYPE_STANDARD; + t1face->type1.encoding_type = T1_ENCODING_TYPE_STANDARD; FT_TRACE4(( " StandardEncoding\n" )); } else if ( cur + 15 < limit && ft_strncmp( (const char*)cur, "ExpertEncoding", 14 ) == 0 ) { - face->type1.encoding_type = T1_ENCODING_TYPE_EXPERT; + t1face->type1.encoding_type = T1_ENCODING_TYPE_EXPERT; FT_TRACE4(( " ExpertEncoding\n" )); } else if ( cur + 18 < limit && ft_strncmp( (const char*)cur, "ISOLatin1Encoding", 17 ) == 0 ) { - face->type1.encoding_type = T1_ENCODING_TYPE_ISOLATIN1; + t1face->type1.encoding_type = T1_ENCODING_TYPE_ISOLATIN1; FT_TRACE4(( " ISOLatin1Encoding\n" )); } @@ -1715,9 +1717,11 @@ static void - parse_subrs( T1_Face face, - T1_Loader loader ) + parse_subrs( FT_Face face, /* T1_Face */ + void* loader_ ) { + T1_Face t1face = (T1_Face)face; + T1_Loader loader = (T1_Loader)loader_; T1_Parser parser = &loader->parser; PS_Table table = &loader->subrs; FT_Memory memory = parser->root.memory; @@ -1725,7 +1729,7 @@ FT_Int num_subrs; FT_UInt count; - PSAux_Service psaux = (PSAux_Service)face->psaux; + PSAux_Service psaux = (PSAux_Service)t1face->psaux; T1_Skip_Spaces( parser ); @@ -1857,7 +1861,7 @@ /* */ /* thanks to Tom Kacvinsky for pointing this out */ /* */ - if ( face->type1.private_dict.lenIV >= 0 ) + if ( t1face->type1.private_dict.lenIV >= 0 ) { FT_Byte* temp = NULL; @@ -1865,7 +1869,7 @@ /* some fonts define empty subr records -- this is not totally */ /* compliant to the specification (which says they should at */ /* least contain a `return'), but we support them anyway */ - if ( size < (FT_ULong)face->type1.private_dict.lenIV ) + if ( size < (FT_ULong)t1face->type1.private_dict.lenIV ) { error = FT_THROW( Invalid_File_Format ); goto Fail; @@ -1876,9 +1880,11 @@ goto Fail; FT_MEM_COPY( temp, base, size ); psaux->t1_decrypt( temp, size, 4330 ); - size -= (FT_ULong)face->type1.private_dict.lenIV; - error = T1_Add_Table( table, (FT_Int)idx, - temp + face->type1.private_dict.lenIV, size ); + size -= (FT_ULong)t1face->type1.private_dict.lenIV; + error = T1_Add_Table( table, + (FT_Int)idx, + temp + t1face->type1.private_dict.lenIV, + size ); FT_FREE( temp ); } else @@ -1910,9 +1916,11 @@ static void - parse_charstrings( T1_Face face, - T1_Loader loader ) + parse_charstrings( FT_Face face, /* T1_Face */ + void* loader_ ) { + T1_Face t1face = (T1_Face)face; + T1_Loader loader = (T1_Loader)loader_; T1_Parser parser = &loader->parser; PS_Table code_table = &loader->charstrings; PS_Table name_table = &loader->glyph_names; @@ -1920,7 +1928,7 @@ FT_Memory memory = parser->root.memory; FT_Error error; - PSAux_Service psaux = (PSAux_Service)face->psaux; + PSAux_Service psaux = (PSAux_Service)t1face->psaux; FT_Byte* cur = parser->root.cursor; FT_Byte* limit = parser->root.limit; @@ -2069,13 +2077,13 @@ notdef_found = 1; } - if ( face->type1.private_dict.lenIV >= 0 && + if ( t1face->type1.private_dict.lenIV >= 0 && n < num_glyphs + TABLE_EXTEND ) { FT_Byte* temp = NULL; - if ( size <= (FT_ULong)face->type1.private_dict.lenIV ) + if ( size <= (FT_ULong)t1face->type1.private_dict.lenIV ) { error = FT_THROW( Invalid_File_Format ); goto Fail; @@ -2086,9 +2094,11 @@ goto Fail; FT_MEM_COPY( temp, base, size ); psaux->t1_decrypt( temp, size, 4330 ); - size -= (FT_ULong)face->type1.private_dict.lenIV; - error = T1_Add_Table( code_table, n, - temp + face->type1.private_dict.lenIV, size ); + size -= (FT_ULong)t1face->type1.private_dict.lenIV; + error = T1_Add_Table( code_table, + n, + temp + t1face->type1.private_dict.lenIV, + size ); FT_FREE( temp ); } else @@ -2570,7 +2580,7 @@ { FT_ERROR(( "T1_Open_Face:" " number-of-designs != 2 ^^ number-of-axes\n" )); - T1_Done_Blend( face ); + T1_Done_Blend( FT_FACE( face ) ); } if ( face->blend && @@ -2590,15 +2600,15 @@ /* font as a normal PS font */ if ( face->blend && ( !face->blend->num_designs || !face->blend->num_axis ) ) - T1_Done_Blend( face ); + T1_Done_Blend( FT_FACE( face ) ); /* the font may have no valid WeightVector */ if ( face->blend && !face->blend->weight_vector ) - T1_Done_Blend( face ); + T1_Done_Blend( FT_FACE( face ) ); /* the font may have no valid BlendDesignPositions */ if ( face->blend && !face->blend->design_pos[0] ) - T1_Done_Blend( face ); + T1_Done_Blend( FT_FACE( face ) ); /* the font may have no valid BlendDesignMap */ if ( face->blend ) @@ -2609,7 +2619,7 @@ for ( i = 0; i < face->blend->num_axis; i++ ) if ( !face->blend->design_map[i].num_points ) { - T1_Done_Blend( face ); + T1_Done_Blend( FT_FACE( face ) ); break; } } diff --git a/src/3rdparty/freetype/src/type1/t1load.h b/src/3rdparty/freetype/src/type1/t1load.h index f8511cccf60..d8c9d2d8abe 100644 --- a/src/3rdparty/freetype/src/type1/t1load.h +++ b/src/3rdparty/freetype/src/type1/t1load.h @@ -66,52 +66,52 @@ FT_BEGIN_HEADER #ifndef T1_CONFIG_OPTION_NO_MM_SUPPORT FT_LOCAL( FT_Error ) - T1_Get_Multi_Master( T1_Face face, + T1_Get_Multi_Master( FT_Face face, FT_Multi_Master* master ); FT_LOCAL( FT_Error ) - T1_Get_MM_Var( T1_Face face, + T1_Get_MM_Var( FT_Face face, FT_MM_Var* *master ); FT_LOCAL( FT_Error ) - T1_Set_MM_Blend( T1_Face face, + T1_Set_MM_Blend( FT_Face face, FT_UInt num_coords, FT_Fixed* coords ); FT_LOCAL( FT_Error ) - T1_Get_MM_Blend( T1_Face face, + T1_Get_MM_Blend( FT_Face face, FT_UInt num_coords, FT_Fixed* coords ); FT_LOCAL( FT_Error ) - T1_Set_MM_Design( T1_Face face, + T1_Set_MM_Design( FT_Face face, FT_UInt num_coords, FT_Long* coords ); FT_LOCAL( FT_Error ) - T1_Reset_MM_Blend( T1_Face face, + T1_Reset_MM_Blend( FT_Face face, FT_UInt instance_index ); FT_LOCAL( FT_Error ) - T1_Get_Var_Design( T1_Face face, + T1_Get_Var_Design( FT_Face face, FT_UInt num_coords, FT_Fixed* coords ); FT_LOCAL( FT_Error ) - T1_Set_Var_Design( T1_Face face, + T1_Set_Var_Design( FT_Face face, FT_UInt num_coords, FT_Fixed* coords ); FT_LOCAL( void ) - T1_Done_Blend( T1_Face face ); + T1_Done_Blend( FT_Face face ); FT_LOCAL( FT_Error ) - T1_Set_MM_WeightVector( T1_Face face, + T1_Set_MM_WeightVector( FT_Face face, FT_UInt len, FT_Fixed* weightvector ); FT_LOCAL( FT_Error ) - T1_Get_MM_WeightVector( T1_Face face, + T1_Get_MM_WeightVector( FT_Face face, FT_UInt* len, FT_Fixed* weightvector ); diff --git a/src/3rdparty/freetype/src/type1/t1objs.c b/src/3rdparty/freetype/src/type1/t1objs.c index 1bb2f15f3a8..69e4fd5065e 100644 --- a/src/3rdparty/freetype/src/type1/t1objs.c +++ b/src/3rdparty/freetype/src/type1/t1objs.c @@ -167,8 +167,7 @@ FT_Module module; - module = FT_Get_Module( slot->face->driver->root.library, - "pshinter" ); + module = FT_Get_Module( slot->library, "pshinter" ); if ( module ) { T1_Hints_Funcs funcs; @@ -227,7 +226,7 @@ face->len_buildchar = 0; } - T1_Done_Blend( face ); + T1_Done_Blend( t1face ); face->blend = NULL; #endif @@ -290,7 +289,8 @@ * * @Input: * stream :: - * input stream where to load font data. + * Dummy argument for compatibility with the `FT_Face_InitFunc` API. + * Ignored. The stream should be passed through `face->root.stream`. * * face_index :: * The index of the font face in the resource. diff --git a/src/3rdparty/freetype/src/type42/t42drivr.c b/src/3rdparty/freetype/src/type42/t42drivr.c index ce1528e5db1..ee5fd44a9f9 100644 --- a/src/3rdparty/freetype/src/type42/t42drivr.c +++ b/src/3rdparty/freetype/src/type42/t42drivr.c @@ -56,33 +56,41 @@ * */ - static FT_Error - t42_get_glyph_name( T42_Face face, + FT_CALLBACK_DEF( FT_Error ) + t42_get_glyph_name( FT_Face face, /* T42_Face */ FT_UInt glyph_index, FT_Pointer buffer, FT_UInt buffer_max ) { - FT_STRCPYN( buffer, face->type1.glyph_names[glyph_index], buffer_max ); + T42_Face t42face = (T42_Face)face; + + + FT_STRCPYN( buffer, + t42face->type1.glyph_names[glyph_index], + buffer_max ); return FT_Err_Ok; } - static FT_UInt - t42_get_name_index( T42_Face face, + FT_CALLBACK_DEF( FT_UInt ) + t42_get_name_index( FT_Face face, /* T42_Face */ const FT_String* glyph_name ) { - FT_Int i; + T42_Face t42face = (T42_Face)face; + FT_Int i; - for ( i = 0; i < face->type1.num_glyphs; i++ ) + for ( i = 0; i < t42face->type1.num_glyphs; i++ ) { - FT_String* gname = face->type1.glyph_names[i]; + FT_String* gname = t42face->type1.glyph_names[i]; if ( glyph_name[0] == gname[0] && !ft_strcmp( glyph_name, gname ) ) - return (FT_UInt)ft_strtol( (const char *)face->type1.charstrings[i], - NULL, 10 ); + return (FT_UInt)ft_strtol( + (const char *)t42face->type1.charstrings[i], + NULL, + 10 ); } return 0; @@ -102,10 +110,13 @@ * */ - static const char* - t42_get_ps_font_name( T42_Face face ) + FT_CALLBACK_DEF( const char* ) + t42_get_ps_font_name( FT_Face face ) /* T42_Face */ { - return (const char*)face->type1.font_name; + T42_Face t42face = (T42_Face)face; + + + return (const char*)t42face->type1.font_name; } @@ -121,7 +132,7 @@ * */ - static FT_Error + FT_CALLBACK_DEF( FT_Error ) t42_ps_get_font_info( FT_Face face, PS_FontInfoRec* afont_info ) { @@ -131,7 +142,7 @@ } - static FT_Error + FT_CALLBACK_DEF( FT_Error ) t42_ps_get_font_extra( FT_Face face, PS_FontExtraRec* afont_extra ) { @@ -141,7 +152,7 @@ } - static FT_Int + FT_CALLBACK_DEF( FT_Int ) t42_ps_has_glyph_names( FT_Face face ) { FT_UNUSED( face ); diff --git a/src/3rdparty/freetype/src/type42/t42parse.c b/src/3rdparty/freetype/src/type42/t42parse.c index 6d765c8c10f..764bbd4c4d9 100644 --- a/src/3rdparty/freetype/src/type42/t42parse.c +++ b/src/3rdparty/freetype/src/type42/t42parse.c @@ -34,19 +34,19 @@ static void - t42_parse_font_matrix( T42_Face face, - T42_Loader loader ); + t42_parse_font_matrix( FT_Face face, + void* loader_ ); static void - t42_parse_encoding( T42_Face face, - T42_Loader loader ); + t42_parse_encoding( FT_Face face, + void* loader_ ); static void - t42_parse_charstrings( T42_Face face, - T42_Loader loader ); + t42_parse_charstrings( FT_Face face, + void* loader_ ); static void - t42_parse_sfnts( T42_Face face, - T42_Loader loader ); + t42_parse_sfnts( FT_Face face, + void* loader_ ); /* as Type42 fonts have no Private dict, */ @@ -241,12 +241,14 @@ static void - t42_parse_font_matrix( T42_Face face, - T42_Loader loader ) + t42_parse_font_matrix( FT_Face face, /* T42_Face */ + void* loader_ ) { - T42_Parser parser = &loader->parser; - FT_Matrix* matrix = &face->type1.font_matrix; - FT_Vector* offset = &face->type1.font_offset; + T42_Face t42face = (T42_Face)face; + T42_Loader loader = (T42_Loader)loader_; + T42_Parser parser = &loader->parser; + FT_Matrix* matrix = &t42face->type1.font_matrix; + FT_Vector* offset = &t42face->type1.font_offset; FT_Fixed temp[6]; FT_Fixed temp_scale; FT_Int result; @@ -299,14 +301,16 @@ static void - t42_parse_encoding( T42_Face face, - T42_Loader loader ) + t42_parse_encoding( FT_Face face, + void* loader_ ) { - T42_Parser parser = &loader->parser; + T42_Face t42face = (T42_Face)face; + T42_Loader loader = (T42_Loader)loader_; + T42_Parser parser = &loader->parser; FT_Byte* cur; - FT_Byte* limit = parser->root.limit; + FT_Byte* limit = parser->root.limit; - PSAux_Service psaux = (PSAux_Service)face->psaux; + PSAux_Service psaux = (PSAux_Service)t42face->psaux; T1_Skip_Spaces( parser ); @@ -322,7 +326,7 @@ /* and we must load it now */ if ( ft_isdigit( *cur ) || *cur == '[' ) { - T1_Encoding encode = &face->type1.encoding; + T1_Encoding encode = &t42face->type1.encoding; FT_Int count, n; PS_Table char_table = &loader->encoding_table; FT_Memory memory = parser->root.memory; @@ -493,8 +497,8 @@ T1_Skip_Spaces( parser ); } - face->type1.encoding_type = T1_ENCODING_TYPE_ARRAY; - parser->root.cursor = cur; + t42face->type1.encoding_type = T1_ENCODING_TYPE_ARRAY; + parser->root.cursor = cur; } /* Otherwise, we should have either `StandardEncoding', */ @@ -503,15 +507,15 @@ { if ( cur + 17 < limit && ft_strncmp( (const char*)cur, "StandardEncoding", 16 ) == 0 ) - face->type1.encoding_type = T1_ENCODING_TYPE_STANDARD; + t42face->type1.encoding_type = T1_ENCODING_TYPE_STANDARD; else if ( cur + 15 < limit && ft_strncmp( (const char*)cur, "ExpertEncoding", 14 ) == 0 ) - face->type1.encoding_type = T1_ENCODING_TYPE_EXPERT; + t42face->type1.encoding_type = T1_ENCODING_TYPE_EXPERT; else if ( cur + 18 < limit && ft_strncmp( (const char*)cur, "ISOLatin1Encoding", 17 ) == 0 ) - face->type1.encoding_type = T1_ENCODING_TYPE_ISOLATIN1; + t42face->type1.encoding_type = T1_ENCODING_TYPE_ISOLATIN1; else parser->root.error = FT_ERR( Ignore ); @@ -529,9 +533,11 @@ static void - t42_parse_sfnts( T42_Face face, - T42_Loader loader ) + t42_parse_sfnts( FT_Face face, + void* loader_ ) { + T42_Face t42face = (T42_Face)face; + T42_Loader loader = (T42_Loader)loader_; T42_Parser parser = &loader->parser; FT_Memory memory = parser->root.memory; FT_Byte* cur; @@ -548,8 +554,8 @@ T42_Load_Status status; /** There should only be one sfnts array, but free any previous. */ - FT_FREE( face->ttf_data ); - face->ttf_size = 0; + FT_FREE( t42face->ttf_data ); + t42face->ttf_size = 0; /* The format is */ /* */ @@ -580,7 +586,7 @@ old_string_size = 0; ttf_count = 0; ttf_reserved = 12; - if ( FT_QALLOC( face->ttf_data, ttf_reserved ) ) + if ( FT_QALLOC( t42face->ttf_data, ttf_reserved ) ) goto Fail; FT_TRACE2(( "\n" )); @@ -596,7 +602,7 @@ if ( *cur == ']' ) { parser->root.cursor++; - face->ttf_size = ttf_count; + t42face->ttf_size = ttf_count; goto Exit; } @@ -707,7 +713,7 @@ /* load offset table, 12 bytes */ if ( ttf_count < 12 ) { - face->ttf_data[ttf_count++] = string_buf[n]; + t42face->ttf_data[ttf_count++] = string_buf[n]; continue; } else @@ -715,7 +721,7 @@ FT_Long ttf_reserved_prev = ttf_reserved; - num_tables = 16 * face->ttf_data[4] + face->ttf_data[5]; + num_tables = 16 * t42face->ttf_data[4] + t42face->ttf_data[5]; status = BEFORE_TABLE_DIR; ttf_reserved = 12 + 16 * num_tables; @@ -729,7 +735,7 @@ goto Fail; } - if ( FT_QREALLOC( face->ttf_data, ttf_reserved_prev, + if ( FT_QREALLOC( t42face->ttf_data, ttf_reserved_prev, ttf_reserved ) ) goto Fail; } @@ -739,7 +745,7 @@ /* the offset table is read; read the table directory */ if ( ttf_count < ttf_reserved ) { - face->ttf_data[ttf_count++] = string_buf[n]; + t42face->ttf_data[ttf_count++] = string_buf[n]; continue; } else @@ -755,7 +761,7 @@ for ( i = 0; i < num_tables; i++ ) { - FT_Byte* p = face->ttf_data + 12 + 16 * i + 12; + FT_Byte* p = t42face->ttf_data + 12 + 16 * i + 12; len = FT_PEEK_ULONG( p ); @@ -781,7 +787,7 @@ FT_TRACE2(( " allocating %ld bytes\n", ttf_reserved )); FT_TRACE2(( "\n" )); - if ( FT_QREALLOC( face->ttf_data, ttf_reserved_prev, + if ( FT_QREALLOC( t42face->ttf_data, ttf_reserved_prev, ttf_reserved ) ) goto Fail; } @@ -795,7 +801,7 @@ error = FT_THROW( Invalid_File_Format ); goto Fail; } - face->ttf_data[ttf_count++] = string_buf[n]; + t42face->ttf_data[ttf_count++] = string_buf[n]; } } @@ -811,8 +817,8 @@ Exit: if ( parser->root.error ) { - FT_FREE( face->ttf_data ); - face->ttf_size = 0; + FT_FREE( t42face->ttf_data ); + t42face->ttf_size = 0; } if ( allocated ) FT_FREE( string_buf ); @@ -820,9 +826,11 @@ static void - t42_parse_charstrings( T42_Face face, - T42_Loader loader ) + t42_parse_charstrings( FT_Face face, /* T42_Face */ + void* loader_ ) { + T42_Face t42face = (T42_Face)face; + T42_Loader loader = (T42_Loader)loader_; T42_Parser parser = &loader->parser; PS_Table code_table = &loader->charstrings; PS_Table name_table = &loader->glyph_names; @@ -830,7 +838,7 @@ FT_Memory memory = parser->root.memory; FT_Error error; - PSAux_Service psaux = (PSAux_Service)face->psaux; + PSAux_Service psaux = (PSAux_Service)t42face->psaux; FT_Byte* cur; FT_Byte* limit = parser->root.limit; diff --git a/src/3rdparty/freetype/src/winfonts/winfnt.c b/src/3rdparty/freetype/src/winfonts/winfnt.c index fa73ae4a935..1160e4ef365 100644 --- a/src/3rdparty/freetype/src/winfonts/winfnt.c +++ b/src/3rdparty/freetype/src/winfonts/winfnt.c @@ -624,31 +624,34 @@ static FT_Error - fnt_cmap_init( FNT_CMap cmap, + fnt_cmap_init( FT_CMap cmap, /* FNT_CMap */ FT_Pointer pointer ) { - FNT_Face face = (FNT_Face)FT_CMAP_FACE( cmap ); - FNT_Font font = face->font; + FNT_CMap fntcmap = (FNT_CMap)cmap; + FNT_Face face = (FNT_Face)FT_CMAP_FACE( cmap ); + FNT_Font font = face->font; FT_UNUSED( pointer ); - cmap->first = (FT_UInt32) font->header.first_char; - cmap->count = (FT_UInt32)( font->header.last_char - cmap->first + 1 ); + fntcmap->first = (FT_UInt32)font->header.first_char; + fntcmap->count = (FT_UInt32)( font->header.last_char - + fntcmap->first + 1 ); return 0; } static FT_UInt - fnt_cmap_char_index( FNT_CMap cmap, + fnt_cmap_char_index( FT_CMap cmap, /* FNT_CMap */ FT_UInt32 char_code ) { - FT_UInt gindex = 0; + FNT_CMap fntcmap = (FNT_CMap)cmap; + FT_UInt gindex = 0; - char_code -= cmap->first; - if ( char_code < cmap->count ) + char_code -= fntcmap->first; + if ( char_code < fntcmap->count ) /* we artificially increase the glyph index; */ /* FNT_Load_Glyph reverts to the right one */ gindex = (FT_UInt)( char_code + 1 ); @@ -656,26 +659,27 @@ } - static FT_UInt32 - fnt_cmap_char_next( FNT_CMap cmap, + static FT_UInt + fnt_cmap_char_next( FT_CMap cmap, /* FNT_CMap */ FT_UInt32 *pchar_code ) { - FT_UInt gindex = 0; - FT_UInt32 result = 0; + FNT_CMap fntcmap = (FNT_CMap)cmap; + FT_UInt gindex = 0; + FT_UInt32 result = 0; FT_UInt32 char_code = *pchar_code + 1; - if ( char_code <= cmap->first ) + if ( char_code <= fntcmap->first ) { - result = cmap->first; + result = fntcmap->first; gindex = 1; } else { - char_code -= cmap->first; - if ( char_code < cmap->count ) + char_code -= fntcmap->first; + if ( char_code < fntcmap->count ) { - result = cmap->first + char_code; + result = fntcmap->first + char_code; gindex = (FT_UInt)( char_code + 1 ); } } From a9fe8dde7a2e4699537b4609692419c77da9446c Mon Sep 17 00:00:00 2001 From: Axel Spoerl Date: Thu, 10 Aug 2023 13:30:43 +0200 Subject: [PATCH 114/151] QXmlStreamReader::readNextStartElement() - return false on document end MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The method reads the next element in a loop, as long as valid elements exist. Within the loop, it returns - false if the end of an element has been reached - true if a new element has started When the document end has been reached, the loop continues, until readNext() returns Invalid. Then, PrematureEndOfDocumentError is launched. This is wrong, because reading beyond the document end is caused by a missing return condition in the loop. => Treat document end like element end and return false without reading beyond it. => Test correct behavior in tst_QXmlStream::readNextStartElement() Fixes: QTBUG-25944 Change-Id: I0160b65880756a2be541e9f55dc79557fcb1f09f Reviewed-by: Thiago Macieira (cherry picked from commit ccd8a496cf46313ea0df9fe70f4e4b57f9434b24) Reviewed-by: Qt Cherry-pick Bot --- src/corelib/serialization/qxmlstream.cpp | 2 +- .../auto/corelib/serialization/qxmlstream/tst_qxmlstream.cpp | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/corelib/serialization/qxmlstream.cpp b/src/corelib/serialization/qxmlstream.cpp index e77f544ceb2..065112e16fd 100644 --- a/src/corelib/serialization/qxmlstream.cpp +++ b/src/corelib/serialization/qxmlstream.cpp @@ -680,7 +680,7 @@ QXmlStreamReader::TokenType QXmlStreamReader::tokenType() const bool QXmlStreamReader::readNextStartElement() { while (readNext() != Invalid) { - if (isEndElement()) + if (isEndElement() || isEndDocument()) return false; else if (isStartElement()) return true; diff --git a/tests/auto/corelib/serialization/qxmlstream/tst_qxmlstream.cpp b/tests/auto/corelib/serialization/qxmlstream/tst_qxmlstream.cpp index e06e66ed566..3c24bb234b8 100644 --- a/tests/auto/corelib/serialization/qxmlstream/tst_qxmlstream.cpp +++ b/tests/auto/corelib/serialization/qxmlstream/tst_qxmlstream.cpp @@ -1145,6 +1145,10 @@ void tst_QXmlStream::readNextStartElement() const } QCOMPARE(amountOfB, 2); + + // well-formed document end follows + QVERIFY(!reader.readNextStartElement()); + QCOMPARE(reader.error(), QXmlStreamReader::NoError); } void tst_QXmlStream::readElementText() const From c8bb334332e61b6f6389d3a53f149cdb750fdcd4 Mon Sep 17 00:00:00 2001 From: Timur Pocheptsov Date: Mon, 21 Aug 2023 14:20:14 +0200 Subject: [PATCH 115/151] tst_QDtls: use DTLS v 1.0 test data conditionally MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Starting from OpenSSL v 3.1.1 DTLS 1.0 is only available, if the security level is 0, which is not the case most of the time. So we consider this version number to be a 'threshold' after which we don't test v 1.0 anymore. Task-number: QTBUG-116166 Change-Id: I9763703f36ae742e1d3c7cb17872cf8d0d82ab85 Reviewed-by: Mårten Nordheim (cherry picked from commit c1b287c531f444dfe57e6bb1353e1c517ad2d416) Reviewed-by: Timur Pocheptsov --- tests/auto/network/ssl/qdtls/tst_qdtls.cpp | 24 ++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/tests/auto/network/ssl/qdtls/tst_qdtls.cpp b/tests/auto/network/ssl/qdtls/tst_qdtls.cpp index 75d949d9578..cfdae3ebecf 100644 --- a/tests/auto/network/ssl/qdtls/tst_qdtls.cpp +++ b/tests/auto/network/ssl/qdtls/tst_qdtls.cpp @@ -604,20 +604,28 @@ void tst_QDtls::protocolVersionMatching_data() QTest::addColumn("clientProtocol"); QTest::addColumn("works"); - QTest::addRow("DtlsV1_0 <-> DtlsV1_0") << QSsl::DtlsV1_0 << QSsl::DtlsV1_0 << true; - QTest::addRow("DtlsV1_0OrLater <-> DtlsV1_0") << QSsl::DtlsV1_0OrLater << QSsl::DtlsV1_0 << true; - QTest::addRow("DtlsV1_0 <-> DtlsV1_0OrLater") << QSsl::DtlsV1_0 << QSsl::DtlsV1_0OrLater << true; - QTest::addRow("DtlsV1_0OrLater <-> DtlsV1_0OrLater") << QSsl::DtlsV1_0OrLater << QSsl::DtlsV1_0OrLater << true; + //OPENSSL_VERSION_NUMBER : + //(OPENSSL_VERSION_MAJOR<<28) | (OPENSSL_VERSION_MINOR<<20) | (OPENSSL_VERSION_PATCH<<4) + const long ossl311 = 0x30100010; + + if (QSslSocket::sslLibraryVersionNumber() < ossl311) { + QTest::addRow("DtlsV1_0 <-> DtlsV1_0") << QSsl::DtlsV1_0 << QSsl::DtlsV1_0 << true; + QTest::addRow("DtlsV1_0OrLater <-> DtlsV1_0") << QSsl::DtlsV1_0OrLater << QSsl::DtlsV1_0 << true; + QTest::addRow("DtlsV1_0 <-> DtlsV1_0OrLater") << QSsl::DtlsV1_0 << QSsl::DtlsV1_0OrLater << true; + QTest::addRow("DtlsV1_0OrLater <-> DtlsV1_0OrLater") << QSsl::DtlsV1_0OrLater << QSsl::DtlsV1_0OrLater << true; + } QTest::addRow("DtlsV1_2 <-> DtlsV1_2") << QSsl::DtlsV1_2 << QSsl::DtlsV1_2 << true; QTest::addRow("DtlsV1_2OrLater <-> DtlsV1_2") << QSsl::DtlsV1_2OrLater << QSsl::DtlsV1_2 << true; QTest::addRow("DtlsV1_2 <-> DtlsV1_2OrLater") << QSsl::DtlsV1_2 << QSsl::DtlsV1_2OrLater << true; QTest::addRow("DtlsV1_2OrLater <-> DtlsV1_2OrLater") << QSsl::DtlsV1_2OrLater << QSsl::DtlsV1_2OrLater << true; - QTest::addRow("DtlsV1_0 <-> DtlsV1_2") << QSsl::DtlsV1_0 << QSsl::DtlsV1_2 << false; - QTest::addRow("DtlsV1_0 <-> DtlsV1_2OrLater") << QSsl::DtlsV1_0 << QSsl::DtlsV1_2OrLater << false; - QTest::addRow("DtlsV1_2 <-> DtlsV1_0") << QSsl::DtlsV1_2 << QSsl::DtlsV1_0 << false; - QTest::addRow("DtlsV1_2OrLater <-> DtlsV1_0") << QSsl::DtlsV1_2OrLater << QSsl::DtlsV1_0 << false; + if (QSslSocket::sslLibraryVersionNumber() < ossl311) { + QTest::addRow("DtlsV1_0 <-> DtlsV1_2") << QSsl::DtlsV1_0 << QSsl::DtlsV1_2 << false; + QTest::addRow("DtlsV1_0 <-> DtlsV1_2OrLater") << QSsl::DtlsV1_0 << QSsl::DtlsV1_2OrLater << false; + QTest::addRow("DtlsV1_2 <-> DtlsV1_0") << QSsl::DtlsV1_2 << QSsl::DtlsV1_0 << false; + QTest::addRow("DtlsV1_2OrLater <-> DtlsV1_0") << QSsl::DtlsV1_2OrLater << QSsl::DtlsV1_0 << false; + } } void tst_QDtls::protocolVersionMatching() From e0540f768e3a68308ea7388ff9e49a844b8b08c2 Mon Sep 17 00:00:00 2001 From: Ivan Solovev Date: Mon, 21 Aug 2023 17:51:16 +0200 Subject: [PATCH 116/151] double-conversion: update to 3.3.0 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Retrieved from/changelog here: https://github.com/google/double-conversion/releases/tag/v3.3.0 Task-number: QTBUG-116236 Change-Id: Ifac887dfcb9151fe2bd8b7e3f5dfe763836a9adb Reviewed-by: Edward Welbourne Reviewed-by: Mårten Nordheim (cherry picked from commit 605412dd1996922ac1b05bfa43e47c8dc137d123) --- .../double-conversion/bignum.cc | 13 ++++----- .../double-conversion/double-to-string.cc | 9 ++++++- .../double-conversion/double-to-string.h | 27 ++++++++++++++++++- .../double-conversion/qt_attribution.json | 4 +-- 4 files changed, 43 insertions(+), 10 deletions(-) diff --git a/src/3rdparty/double-conversion/double-conversion/bignum.cc b/src/3rdparty/double-conversion/double-conversion/bignum.cc index d858c16ca00..0bcd1e0a5e1 100644 --- a/src/3rdparty/double-conversion/double-conversion/bignum.cc +++ b/src/3rdparty/double-conversion/double-conversion/bignum.cc @@ -146,7 +146,8 @@ void Bignum::AssignHexString(Vector value) { } } if (tmp > 0) { - RawBigit(used_bigits_++) = tmp; + DOUBLE_CONVERSION_ASSERT(tmp <= kBigitMask); + RawBigit(used_bigits_++) = static_cast(tmp & kBigitMask); } Clamp(); } @@ -203,7 +204,7 @@ void Bignum::AddBignum(const Bignum& other) { carry = sum >> kBigitSize; ++bigit_pos; } - used_bigits_ = (std::max)(bigit_pos, static_cast(used_bigits_)); + used_bigits_ = static_cast(std::max(bigit_pos, static_cast(used_bigits_))); DOUBLE_CONVERSION_ASSERT(IsClamped()); } @@ -239,7 +240,7 @@ void Bignum::ShiftLeft(const int shift_amount) { if (used_bigits_ == 0) { return; } - exponent_ += (shift_amount / kBigitSize); + exponent_ += static_cast(shift_amount / kBigitSize); const int local_shift = shift_amount % kBigitSize; EnsureCapacity(used_bigits_ + 1); BigitsShiftLeft(local_shift); @@ -417,7 +418,7 @@ void Bignum::Square() { DOUBLE_CONVERSION_ASSERT(accumulator == 0); // Don't forget to update the used_digits and the exponent. - used_bigits_ = product_length; + used_bigits_ = static_cast(product_length); exponent_ *= 2; Clamp(); } @@ -738,8 +739,8 @@ void Bignum::Align(const Bignum& other) { for (int i = 0; i < zero_bigits; ++i) { RawBigit(i) = 0; } - used_bigits_ += zero_bigits; - exponent_ -= zero_bigits; + used_bigits_ += static_cast(zero_bigits); + exponent_ -= static_cast(zero_bigits); DOUBLE_CONVERSION_ASSERT(used_bigits_ >= 0); DOUBLE_CONVERSION_ASSERT(exponent_ >= 0); diff --git a/src/3rdparty/double-conversion/double-conversion/double-to-string.cc b/src/3rdparty/double-conversion/double-conversion/double-to-string.cc index 9255bce1713..0ad20a1d8b6 100644 --- a/src/3rdparty/double-conversion/double-conversion/double-to-string.cc +++ b/src/3rdparty/double-conversion/double-conversion/double-to-string.cc @@ -79,7 +79,14 @@ void DoubleToStringConverter::CreateExponentialRepresentation( StringBuilder* result_builder) const { DOUBLE_CONVERSION_ASSERT(length != 0); result_builder->AddCharacter(decimal_digits[0]); - if (length != 1) { + if (length == 1) { + if ((flags_ & EMIT_TRAILING_DECIMAL_POINT_IN_EXPONENTIAL) != 0) { + result_builder->AddCharacter('.'); + if ((flags_ & EMIT_TRAILING_ZERO_AFTER_POINT_IN_EXPONENTIAL) != 0) { + result_builder->AddCharacter('0'); + } + } + } else { result_builder->AddCharacter('.'); result_builder->AddSubstring(&decimal_digits[1], length-1); } diff --git a/src/3rdparty/double-conversion/double-conversion/double-to-string.h b/src/3rdparty/double-conversion/double-conversion/double-to-string.h index 6317a08a72a..2e79525e22e 100644 --- a/src/3rdparty/double-conversion/double-conversion/double-to-string.h +++ b/src/3rdparty/double-conversion/double-conversion/double-to-string.h @@ -78,7 +78,9 @@ class DoubleToStringConverter { EMIT_TRAILING_DECIMAL_POINT = 2, EMIT_TRAILING_ZERO_AFTER_POINT = 4, UNIQUE_ZERO = 8, - NO_TRAILING_ZERO = 16 + NO_TRAILING_ZERO = 16, + EMIT_TRAILING_DECIMAL_POINT_IN_EXPONENTIAL = 32, + EMIT_TRAILING_ZERO_AFTER_POINT_IN_EXPONENTIAL = 64 }; // Flags should be a bit-or combination of the possible Flags-enum. @@ -97,6 +99,13 @@ class DoubleToStringConverter { // of the result in precision mode. Matches printf's %g. // When EMIT_TRAILING_ZERO_AFTER_POINT is also given, one trailing zero is // preserved. + // - EMIT_TRAILING_DECIMAL_POINT_IN_EXPONENTIAL: when the input number has + // exactly one significant digit and is converted into exponent form then a + // trailing decimal point is appended to the significand in shortest mode + // or in precision mode with one requested digit. + // - EMIT_TRAILING_ZERO_AFTER_POINT_IN_EXPONENTIAL: in addition to a trailing + // decimal point emits a trailing '0'-character. This flag requires the + // EMIT_TRAILING_DECIMAL_POINT_IN_EXPONENTIAL flag. // // Infinity symbol and nan_symbol provide the string representation for these // special values. If the string is NULL and the special value is encountered @@ -132,6 +141,22 @@ class DoubleToStringConverter { // ToPrecision(230.0, 2) -> "230." with EMIT_TRAILING_DECIMAL_POINT. // ToPrecision(230.0, 2) -> "2.3e2" with EMIT_TRAILING_ZERO_AFTER_POINT. // + // When converting numbers with exactly one significant digit to exponent + // form in shortest mode or in precision mode with one requested digit, the + // EMIT_TRAILING_DECIMAL_POINT and EMIT_TRAILING_ZERO_AFTER_POINT flags have + // no effect. Use the EMIT_TRAILING_DECIMAL_POINT_IN_EXPONENTIAL flag to + // append a decimal point in this case and the + // EMIT_TRAILING_ZERO_AFTER_POINT_IN_EXPONENTIAL flag to also append a + // '0'-character in this case. + // Example with decimal_in_shortest_low = 0: + // ToShortest(0.0009) -> "9e-4" + // with EMIT_TRAILING_DECIMAL_POINT_IN_EXPONENTIAL deactivated. + // ToShortest(0.0009) -> "9.e-4" + // with EMIT_TRAILING_DECIMAL_POINT_IN_EXPONENTIAL activated. + // ToShortest(0.0009) -> "9.0e-4" + // with EMIT_TRAILING_DECIMAL_POINT_IN_EXPONENTIAL activated and + // EMIT_TRAILING_ZERO_AFTER_POINT_IN_EXPONENTIAL activated. + // // The min_exponent_width is used for exponential representations. // The converter adds leading '0's to the exponent until the exponent // is at least min_exponent_width digits long. diff --git a/src/3rdparty/double-conversion/qt_attribution.json b/src/3rdparty/double-conversion/qt_attribution.json index 8ce6183e2ae..4166ccef322 100644 --- a/src/3rdparty/double-conversion/qt_attribution.json +++ b/src/3rdparty/double-conversion/qt_attribution.json @@ -5,8 +5,8 @@ "QtUsage": "Used in Qt Core. Configure with -system-doubleconversion or -no-doubleconversion to avoid.", "Homepage": "https://github.com/google/double-conversion", - "Version": "3.1.5-30-gbf46072", - "DownloadLocation": "https://github.com/google/double-conversion/commit/bf4607277fa7133825cb7899015374917cd06b8f", + "Version": "3.3.0", + "DownloadLocation": "https://github.com/google/double-conversion/releases/tag/v3.3.0", "License": "BSD 3-clause \"New\" or \"Revised\" License", "LicenseId": "BSD-3-Clause", "LicenseFile": "LICENSE", From ed0b4dc99437bd42034eb3ea1ad63a87c7449294 Mon Sep 17 00:00:00 2001 From: Eirik Aavitsland Date: Fri, 25 Aug 2023 10:45:03 +0200 Subject: [PATCH 117/151] Add wrapping build of the bundled libjpeg Similar to how it is done libpng etc. This is a backport from 6.4: it is a partial cherry-pick of be2745e4788cecb0d3122081e3328e4b66923609. This prepares for merging the update to version 3.0.0 of libjpeg-turbo, which includes significant building changes. Change-Id: I7ce0c91c673695bdbc522e125a7d425e799095fe Reviewed-by: Alexandru Croitor --- cmake/FindWrapJpeg.cmake | 11 +++ cmake/FindWrapSystemJpeg.cmake | 32 ++++++++ src/3rdparty/CMakeLists.txt | 5 ++ src/3rdparty/libjpeg/CMakeLists.txt | 74 +++++++++++++++++ src/gui/configure.cmake | 2 +- src/plugins/imageformats/jpeg/CMakeLists.txt | 86 +------------------- 6 files changed, 125 insertions(+), 85 deletions(-) create mode 100644 cmake/FindWrapJpeg.cmake create mode 100644 cmake/FindWrapSystemJpeg.cmake create mode 100644 src/3rdparty/libjpeg/CMakeLists.txt diff --git a/cmake/FindWrapJpeg.cmake b/cmake/FindWrapJpeg.cmake new file mode 100644 index 00000000000..194296e3a63 --- /dev/null +++ b/cmake/FindWrapJpeg.cmake @@ -0,0 +1,11 @@ +include(QtFindWrapHelper NO_POLICY_SCOPE) + +qt_find_package_system_or_bundled(wrap_jpeg + FRIENDLY_PACKAGE_NAME "Jpeg" + WRAP_PACKAGE_TARGET "WrapJpeg::WrapJpeg" + WRAP_PACKAGE_FOUND_VAR_NAME "WrapJpeg_FOUND" + BUNDLED_PACKAGE_NAME "BundledLibjpeg" + BUNDLED_PACKAGE_TARGET "BundledLibjpeg" + SYSTEM_PACKAGE_NAME "WrapSystemJpeg" + SYSTEM_PACKAGE_TARGET "WrapSystemJpeg::WrapSystemJpeg" +) diff --git a/cmake/FindWrapSystemJpeg.cmake b/cmake/FindWrapSystemJpeg.cmake new file mode 100644 index 00000000000..2853654ea11 --- /dev/null +++ b/cmake/FindWrapSystemJpeg.cmake @@ -0,0 +1,32 @@ +if(TARGET WrapSystemJpeg::WrapSystemJpeg) + set(WrapSystemJpeg_FOUND TRUE) + return() +endif() +set(WrapSystemJpeg_REQUIRED_VARS __jpeg_found) + +find_package(JPEG ${${CMAKE_FIND_PACKAGE_NAME}_FIND_VERSION} QUIET) + +set(__jpeg_target_name "JPEG::JPEG") +if(JPEG_FOUND AND TARGET "${__jpeg_target_name}") + set(__jpeg_found TRUE) +endif() + +if(JPEG_LIBRARIES) + list(PREPEND WrapSystemJpeg_REQUIRED_VARS JPEG_LIBRARIES) +endif() +if(JPEG_VERSION) + set(WrapSystemJpeg_VERSION "${JPEG_VERSION}") +endif() + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(WrapSystemJpeg + REQUIRED_VARS ${WrapSystemJpeg_REQUIRED_VARS} + VERSION_VAR WrapSystemJpeg_VERSION) + +if(WrapSystemJpeg_FOUND) + add_library(WrapSystemJpeg::WrapSystemJpeg INTERFACE IMPORTED) + target_link_libraries(WrapSystemJpeg::WrapSystemJpeg + INTERFACE "${__jpeg_target_name}") +endif() +unset(__jpeg_target_name) +unset(__jpeg_found) diff --git a/src/3rdparty/CMakeLists.txt b/src/3rdparty/CMakeLists.txt index 56b81bb7aff..68113d8baca 100644 --- a/src/3rdparty/CMakeLists.txt +++ b/src/3rdparty/CMakeLists.txt @@ -6,6 +6,11 @@ if(QT_FEATURE_gui AND QT_FEATURE_png AND NOT QT_FEATURE_system_png) endif() qt_install_3rdparty_library_wrap_config_extra_file(BundledLibpng) +if(QT_FEATURE_gui AND QT_FEATURE_jpeg AND NOT QT_FEATURE_system_jpeg) + add_subdirectory(libjpeg) +endif() +qt_install_3rdparty_library_wrap_config_extra_file(BundledLibjpeg) + if(QT_FEATURE_gui AND QT_FEATURE_freetype AND NOT QT_FEATURE_system_freetype) add_subdirectory(freetype) endif() diff --git a/src/3rdparty/libjpeg/CMakeLists.txt b/src/3rdparty/libjpeg/CMakeLists.txt new file mode 100644 index 00000000000..3235c57d102 --- /dev/null +++ b/src/3rdparty/libjpeg/CMakeLists.txt @@ -0,0 +1,74 @@ +qt_internal_add_3rdparty_library(BundledLibjpeg + QMAKE_LIB_NAME libjpeg + STATIC + INSTALL + SOURCES + src/jaricom.c + src/jcapimin.c + src/jcapistd.c + src/jcarith.c + src/jccoefct.c + src/jccolor.c + src/jcdctmgr.c + src/jchuff.c + src/jcinit.c + src/jcmainct.c + src/jcmarker.c + src/jcmaster.c + src/jcomapi.c + src/jcparam.c + src/jcphuff.c + src/jcprepct.c + src/jcsample.c + src/jctrans.c + src/jdapimin.c + src/jdapistd.c + src/jdarith.c + src/jdatadst.c + src/jdatasrc.c + src/jdcoefct.c + src/jdcolor.c + src/jddctmgr.c + src/jdhuff.c + src/jdinput.c + src/jdmainct.c + src/jdmarker.c + src/jdmaster.c + src/jdmerge.c + src/jdphuff.c + src/jdpostct.c + src/jdsample.c + src/jdtrans.c + src/jerror.c + src/jfdctflt.c + src/jfdctfst.c + src/jfdctint.c + src/jidctflt.c + src/jidctfst.c + src/jidctint.c + src/jidctred.c + src/jmemmgr.c + src/jmemnobs.c + src/jquant1.c + src/jquant2.c + src/jsimd_none.c + src/jutils.c + INCLUDE_DIRECTORIES + src + PUBLIC_INCLUDE_DIRECTORIES + $ +) + +qt_disable_warnings(BundledLibjpeg) +qt_set_symbol_visibility_hidden(BundledLibjpeg) + +qt_internal_extend_target(BundledLibjpeg CONDITION MSVC + DEFINES + _CRT_SECURE_NO_WARNINGS +) +if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" + OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" + OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "AppleClang") + target_compile_options(BundledLibjpeg PRIVATE "-Wno-unused-parameter") +endif() + diff --git a/src/gui/configure.cmake b/src/gui/configure.cmake index 611928d13ad..cbb3af0cf2a 100644 --- a/src/gui/configure.cmake +++ b/src/gui/configure.cmake @@ -44,7 +44,7 @@ qt_add_qmake_lib_dependency(fontconfig freetype) qt_find_package(gbm PROVIDED_TARGETS gbm::gbm MODULE_NAME gui QMAKE_LIB gbm) qt_find_package(WrapSystemHarfbuzz 2.6.0 PROVIDED_TARGETS WrapSystemHarfbuzz::WrapSystemHarfbuzz MODULE_NAME gui QMAKE_LIB harfbuzz) qt_find_package(Libinput PROVIDED_TARGETS Libinput::Libinput MODULE_NAME gui QMAKE_LIB libinput) -qt_find_package(JPEG PROVIDED_TARGETS JPEG::JPEG MODULE_NAME gui QMAKE_LIB libjpeg) +qt_find_package(WrapSystemJpeg PROVIDED_TARGETS WrapSystemJpeg::WrapSystemJpeg MODULE_NAME gui QMAKE_LIB libjpeg) qt_find_package(WrapSystemMd4c PROVIDED_TARGETS WrapSystemMd4c::WrapSystemMd4c MODULE_NAME gui QMAKE_LIB libmd4c) qt_find_package(WrapSystemPNG PROVIDED_TARGETS WrapSystemPNG::WrapSystemPNG MODULE_NAME gui QMAKE_LIB libpng) if(QT_FEATURE_system_zlib) diff --git a/src/plugins/imageformats/jpeg/CMakeLists.txt b/src/plugins/imageformats/jpeg/CMakeLists.txt index a5ce61b5a0d..bb5a78fa40c 100644 --- a/src/plugins/imageformats/jpeg/CMakeLists.txt +++ b/src/plugins/imageformats/jpeg/CMakeLists.txt @@ -1,6 +1,6 @@ # Generated from jpeg.pro. -qt_find_package(JPEG) # special case +qt_find_package(WrapJpeg PROVIDED_TARGETS WrapJpeg::WrapJpeg) ##################################################################### ## QJpegPlugin Plugin: @@ -17,6 +17,7 @@ qt_internal_add_plugin(QJpegPlugin Qt::CorePrivate Qt::Gui Qt::GuiPrivate + WrapJpeg::WrapJpeg ) # Fails to build on Windows with a static Qt, PCH enabled and @@ -25,86 +26,3 @@ qt_internal_add_plugin(QJpegPlugin if(WIN32 AND NOT BUILD_SHARED_LIBS) qt_update_ignore_pch_source(QJpegPlugin "qjpeghandler.cpp") endif() - -#### Keys ignored in scope 1:.:.:jpeg.pro:: -# OTHER_FILES = "jpeg.json" - -## Scopes: -##################################################################### - -qt_internal_extend_target(QJpegPlugin CONDITION QT_FEATURE_system_jpeg - LIBRARIES - JPEG::JPEG -) - -qt_internal_extend_target(QJpegPlugin CONDITION NOT QT_FEATURE_system_jpeg - SOURCES - ../../../3rdparty/libjpeg/src/jaricom.c - ../../../3rdparty/libjpeg/src/jcapimin.c - ../../../3rdparty/libjpeg/src/jcapistd.c - ../../../3rdparty/libjpeg/src/jcarith.c - ../../../3rdparty/libjpeg/src/jccoefct.c - ../../../3rdparty/libjpeg/src/jccolor.c - ../../../3rdparty/libjpeg/src/jcdctmgr.c - ../../../3rdparty/libjpeg/src/jchuff.c - ../../../3rdparty/libjpeg/src/jcinit.c - ../../../3rdparty/libjpeg/src/jcmainct.c - ../../../3rdparty/libjpeg/src/jcmarker.c - ../../../3rdparty/libjpeg/src/jcmaster.c - ../../../3rdparty/libjpeg/src/jcomapi.c - ../../../3rdparty/libjpeg/src/jcparam.c - ../../../3rdparty/libjpeg/src/jcphuff.c - ../../../3rdparty/libjpeg/src/jcprepct.c - ../../../3rdparty/libjpeg/src/jcsample.c - ../../../3rdparty/libjpeg/src/jctrans.c - ../../../3rdparty/libjpeg/src/jdapimin.c - ../../../3rdparty/libjpeg/src/jdapistd.c - ../../../3rdparty/libjpeg/src/jdarith.c - ../../../3rdparty/libjpeg/src/jdatadst.c - ../../../3rdparty/libjpeg/src/jdatasrc.c - ../../../3rdparty/libjpeg/src/jdcoefct.c - ../../../3rdparty/libjpeg/src/jdcolor.c - ../../../3rdparty/libjpeg/src/jddctmgr.c - ../../../3rdparty/libjpeg/src/jdhuff.c - ../../../3rdparty/libjpeg/src/jdinput.c - ../../../3rdparty/libjpeg/src/jdmainct.c - ../../../3rdparty/libjpeg/src/jdmarker.c - ../../../3rdparty/libjpeg/src/jdmaster.c - ../../../3rdparty/libjpeg/src/jdmerge.c - ../../../3rdparty/libjpeg/src/jdphuff.c - ../../../3rdparty/libjpeg/src/jdpostct.c - ../../../3rdparty/libjpeg/src/jdsample.c - ../../../3rdparty/libjpeg/src/jdtrans.c - ../../../3rdparty/libjpeg/src/jerror.c - ../../../3rdparty/libjpeg/src/jfdctflt.c - ../../../3rdparty/libjpeg/src/jfdctfst.c - ../../../3rdparty/libjpeg/src/jfdctint.c - ../../../3rdparty/libjpeg/src/jidctflt.c - ../../../3rdparty/libjpeg/src/jidctfst.c - ../../../3rdparty/libjpeg/src/jidctint.c - ../../../3rdparty/libjpeg/src/jidctred.c - ../../../3rdparty/libjpeg/src/jmemmgr.c - ../../../3rdparty/libjpeg/src/jmemnobs.c - ../../../3rdparty/libjpeg/src/jquant1.c - ../../../3rdparty/libjpeg/src/jquant2.c - ../../../3rdparty/libjpeg/src/jsimd_none.c - ../../../3rdparty/libjpeg/src/jutils.c - INCLUDE_DIRECTORIES - ../../../3rdparty/libjpeg/src -) - -# special case begin -if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" - OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" - OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "AppleClang") - target_compile_options(QJpegPlugin PRIVATE "-Wno-unused-parameter") -endif() -# special case end - -#### Keys ignored in scope 5:.:../../../3rdparty:../../../3rdparty/libjpeg.pri:GCC: -# QMAKE_CFLAGS_WARN_ON = "-Wno-unused-parameter" "-Wno-main" - -qt_internal_extend_target(QJpegPlugin CONDITION MSVC AND NOT QT_FEATURE_system_jpeg - DEFINES - _CRT_SECURE_NO_WARNINGS -) From 91942a24b4fe5387e3f929b4330ef9ba2a37c300 Mon Sep 17 00:00:00 2001 From: Eirik Aavitsland Date: Thu, 20 Jul 2023 14:31:29 +0200 Subject: [PATCH 118/151] Update bundled libjpeg-turbo to version 3.0.0 [ChangeLog][Third-Party Code] libjpeg-turbo was updated to version 3.0.0 Change-Id: I960c4bfdef268eced93317ded814e2c84befa451 Reviewed-by: Eskil Abrahamsen Blomfeldt (cherry picked from commit 3498baef76ae17b7ef8c5828de33bdbc77024e47) Reviewed-by: Eirik Aavitsland --- src/3rdparty/libjpeg/CMakeLists.txt | 148 ++-- src/3rdparty/libjpeg/COPYRIGHT.txt | 1 + .../libjpeg/import_from_libjpeg_tarball.sh | 14 +- src/3rdparty/libjpeg/qt_attribution.json | 3 +- src/3rdparty/libjpeg/src/ChangeLog.md | 222 +++++- src/3rdparty/libjpeg/src/README.ijg | 24 +- src/3rdparty/libjpeg/src/README.md | 12 +- src/3rdparty/libjpeg/src/jcapimin.c | 27 +- src/3rdparty/libjpeg/src/jcapistd.c | 53 +- src/3rdparty/libjpeg/src/jccoefct.c | 47 +- src/3rdparty/libjpeg/src/jccolext.c | 50 +- src/3rdparty/libjpeg/src/jccolor.c | 233 ++++--- src/3rdparty/libjpeg/src/jcdctmgr.c | 94 ++- src/3rdparty/libjpeg/src/jcdiffct.c | 411 +++++++++++ src/3rdparty/libjpeg/src/jchuff.c | 145 ++-- src/3rdparty/libjpeg/src/jchuff.h | 6 - src/3rdparty/libjpeg/src/jcicc.c | 105 +++ src/3rdparty/libjpeg/src/jcinit.c | 121 +++- src/3rdparty/libjpeg/src/jclhuff.c | 587 ++++++++++++++++ src/3rdparty/libjpeg/src/jclossls.c | 319 +++++++++ src/3rdparty/libjpeg/src/jcmainct.c | 45 +- src/3rdparty/libjpeg/src/jcmarker.c | 36 +- src/3rdparty/libjpeg/src/jcmaster.c | 193 +++--- src/3rdparty/libjpeg/src/jcmaster.h | 43 ++ src/3rdparty/libjpeg/src/jconfig.h | 8 +- src/3rdparty/libjpeg/src/jconfig.h.in | 47 +- src/3rdparty/libjpeg/src/jconfigint.h | 31 +- src/3rdparty/libjpeg/src/jconfigint.h.in | 29 + src/3rdparty/libjpeg/src/jcparam.c | 52 +- src/3rdparty/libjpeg/src/jcphuff.c | 16 +- src/3rdparty/libjpeg/src/jcprepct.c | 88 ++- src/3rdparty/libjpeg/src/jcsample.c | 103 +-- src/3rdparty/libjpeg/src/jctrans.c | 16 +- src/3rdparty/libjpeg/src/jdapimin.c | 9 +- src/3rdparty/libjpeg/src/jdapistd.c | 149 ++-- src/3rdparty/libjpeg/src/jdatadst.c | 10 - src/3rdparty/libjpeg/src/jdatasrc.c | 6 - src/3rdparty/libjpeg/src/jdcoefct.c | 48 +- src/3rdparty/libjpeg/src/jdcoefct.h | 5 + src/3rdparty/libjpeg/src/jdcol565.c | 62 +- src/3rdparty/libjpeg/src/jdcolext.c | 48 +- src/3rdparty/libjpeg/src/jdcolor.c | 192 ++++-- src/3rdparty/libjpeg/src/jdct.h | 135 ++-- src/3rdparty/libjpeg/src/jddctmgr.c | 61 +- src/3rdparty/libjpeg/src/jddiffct.c | 403 +++++++++++ src/3rdparty/libjpeg/src/jdhuff.c | 20 +- src/3rdparty/libjpeg/src/jdhuff.h | 7 +- src/3rdparty/libjpeg/src/jdicc.c | 167 +++++ src/3rdparty/libjpeg/src/jdinput.c | 63 +- src/3rdparty/libjpeg/src/jdlhuff.c | 302 ++++++++ src/3rdparty/libjpeg/src/jdlossls.c | 289 ++++++++ src/3rdparty/libjpeg/src/jdmainct.c | 111 +-- src/3rdparty/libjpeg/src/jdmainct.h | 15 +- src/3rdparty/libjpeg/src/jdmarker.c | 26 +- src/3rdparty/libjpeg/src/jdmaster.c | 643 +++++++++++------- src/3rdparty/libjpeg/src/jdmerge.c | 71 +- src/3rdparty/libjpeg/src/jdmerge.h | 9 +- src/3rdparty/libjpeg/src/jdmrg565.c | 43 +- src/3rdparty/libjpeg/src/jdmrgext.c | 40 +- src/3rdparty/libjpeg/src/jdphuff.c | 4 +- src/3rdparty/libjpeg/src/jdpostct.c | 109 +-- src/3rdparty/libjpeg/src/jdsample.c | 128 ++-- src/3rdparty/libjpeg/src/jdsample.h | 9 +- src/3rdparty/libjpeg/src/jdtrans.c | 12 +- src/3rdparty/libjpeg/src/jerror.h | 13 +- src/3rdparty/libjpeg/src/jfdctfst.c | 2 +- src/3rdparty/libjpeg/src/jfdctint.c | 4 +- src/3rdparty/libjpeg/src/jidctflt.c | 14 +- src/3rdparty/libjpeg/src/jidctfst.c | 18 +- src/3rdparty/libjpeg/src/jidctint.c | 136 ++-- src/3rdparty/libjpeg/src/jidctred.c | 38 +- src/3rdparty/libjpeg/src/jinclude.h | 4 +- src/3rdparty/libjpeg/src/jlossls.h | 101 +++ src/3rdparty/libjpeg/src/jmemmgr.c | 179 ++++- src/3rdparty/libjpeg/src/jmorecfg.h | 41 +- .../libjpeg/src/{jpegcomp.h => jpegapicomp.h} | 2 +- src/3rdparty/libjpeg/src/jpegint.h | 226 +++++- src/3rdparty/libjpeg/src/jpeglib.h | 149 +++- src/3rdparty/libjpeg/src/jquant1.c | 164 ++--- src/3rdparty/libjpeg/src/jquant2.c | 130 ++-- src/3rdparty/libjpeg/src/jsamplecomp.h | 336 +++++++++ src/3rdparty/libjpeg/src/jsimd.h | 4 + src/3rdparty/libjpeg/src/jsimd_none.c | 431 ------------ src/3rdparty/libjpeg/src/jutils.c | 25 +- src/3rdparty/libjpeg/src/jversion.h | 1 + 85 files changed, 6378 insertions(+), 2165 deletions(-) create mode 100644 src/3rdparty/libjpeg/src/jcdiffct.c create mode 100644 src/3rdparty/libjpeg/src/jcicc.c create mode 100644 src/3rdparty/libjpeg/src/jclhuff.c create mode 100644 src/3rdparty/libjpeg/src/jclossls.c create mode 100644 src/3rdparty/libjpeg/src/jcmaster.h create mode 100644 src/3rdparty/libjpeg/src/jddiffct.c create mode 100644 src/3rdparty/libjpeg/src/jdicc.c create mode 100644 src/3rdparty/libjpeg/src/jdlhuff.c create mode 100644 src/3rdparty/libjpeg/src/jdlossls.c create mode 100644 src/3rdparty/libjpeg/src/jlossls.h rename src/3rdparty/libjpeg/src/{jpegcomp.h => jpegapicomp.h} (98%) create mode 100644 src/3rdparty/libjpeg/src/jsamplecomp.h delete mode 100644 src/3rdparty/libjpeg/src/jsimd_none.c diff --git a/src/3rdparty/libjpeg/CMakeLists.txt b/src/3rdparty/libjpeg/CMakeLists.txt index 3235c57d102..e2ac21ca79e 100644 --- a/src/3rdparty/libjpeg/CMakeLists.txt +++ b/src/3rdparty/libjpeg/CMakeLists.txt @@ -1,58 +1,102 @@ +set(JPEG16_SOURCES + src/jcapistd.c + src/jccolor.c + src/jcdiffct.c + src/jclossls.c + src/jcmainct.c + src/jcprepct.c + src/jcsample.c + src/jdapistd.c + src/jdcolor.c + src/jddiffct.c + src/jdlossls.c + src/jdmainct.c + src/jdpostct.c + src/jdsample.c + src/jutils.c) + +set(JPEG12_SOURCES + ${JPEG16_SOURCES} + src/jccoefct.c + src/jcdctmgr.c + src/jdcoefct.c + src/jddctmgr.c + src/jdmerge.c + src/jfdctfst.c + src/jfdctint.c + src/jidctflt.c + src/jidctfst.c + src/jidctint.c + src/jidctred.c + src/jquant1.c + src/jquant2.c) + +set(JPEG_SOURCES + ${JPEG12_SOURCES} + src/jaricom.c + src/jcapimin.c + src/jcarith.c + src/jchuff.c + src/jcicc.c + src/jcinit.c + src/jclhuff.c + src/jcmarker.c + src/jcmaster.c + src/jcomapi.c + src/jcparam.c + src/jcphuff.c + src/jctrans.c + src/jdapimin.c + src/jdarith.c + src/jdatadst.c + src/jdatasrc.c + src/jdhuff.c + src/jdicc.c + src/jdinput.c + src/jdlhuff.c + src/jdmarker.c + src/jdmaster.c + src/jdphuff.c + src/jdtrans.c + src/jerror.c + src/jfdctflt.c + src/jmemmgr.c + src/jmemnobs.c) + +qt_internal_add_3rdparty_library(BundledLibjpeg16bits + STATIC + SKIP_AUTOMOC + SOURCES + ${JPEG16_SOURCES} + DEFINES + BITS_IN_JSAMPLE=16 + INCLUDE_DIRECTORIES + src + PUBLIC_INCLUDE_DIRECTORIES + $ +) + +qt_internal_add_3rdparty_library(BundledLibjpeg12bits + STATIC + SKIP_AUTOMOC + SOURCES + ${JPEG12_SOURCES} + DEFINES + BITS_IN_JSAMPLE=12 + INCLUDE_DIRECTORIES + src + PUBLIC_INCLUDE_DIRECTORIES + $ +) + qt_internal_add_3rdparty_library(BundledLibjpeg QMAKE_LIB_NAME libjpeg STATIC INSTALL SOURCES - src/jaricom.c - src/jcapimin.c - src/jcapistd.c - src/jcarith.c - src/jccoefct.c - src/jccolor.c - src/jcdctmgr.c - src/jchuff.c - src/jcinit.c - src/jcmainct.c - src/jcmarker.c - src/jcmaster.c - src/jcomapi.c - src/jcparam.c - src/jcphuff.c - src/jcprepct.c - src/jcsample.c - src/jctrans.c - src/jdapimin.c - src/jdapistd.c - src/jdarith.c - src/jdatadst.c - src/jdatasrc.c - src/jdcoefct.c - src/jdcolor.c - src/jddctmgr.c - src/jdhuff.c - src/jdinput.c - src/jdmainct.c - src/jdmarker.c - src/jdmaster.c - src/jdmerge.c - src/jdphuff.c - src/jdpostct.c - src/jdsample.c - src/jdtrans.c - src/jerror.c - src/jfdctflt.c - src/jfdctfst.c - src/jfdctint.c - src/jidctflt.c - src/jidctfst.c - src/jidctint.c - src/jidctred.c - src/jmemmgr.c - src/jmemnobs.c - src/jquant1.c - src/jquant2.c - src/jsimd_none.c - src/jutils.c + ${JPEG_SOURCES} + $ + $ INCLUDE_DIRECTORIES src PUBLIC_INCLUDE_DIRECTORIES @@ -60,7 +104,11 @@ qt_internal_add_3rdparty_library(BundledLibjpeg ) qt_disable_warnings(BundledLibjpeg) +qt_disable_warnings(BundledLibjpeg12bits) +qt_disable_warnings(BundledLibjpeg16bits) qt_set_symbol_visibility_hidden(BundledLibjpeg) +qt_set_symbol_visibility_hidden(BundledLibjpeg12bits) +qt_set_symbol_visibility_hidden(BundledLibjpeg16bits) qt_internal_extend_target(BundledLibjpeg CONDITION MSVC DEFINES diff --git a/src/3rdparty/libjpeg/COPYRIGHT.txt b/src/3rdparty/libjpeg/COPYRIGHT.txt index d75ce414586..5b6ff32c691 100644 --- a/src/3rdparty/libjpeg/COPYRIGHT.txt +++ b/src/3rdparty/libjpeg/COPYRIGHT.txt @@ -9,4 +9,5 @@ Copyright (C) 2013-2014 MIPS Technologies, Inc. Copyright (C) 2009, 2012 Pierre Ossman for Cendio AB Copyright (C) 2009-2011 Nokia Corporation and/or its subsidiary(-ies) Copyright (C) 1999-2006 MIYASAKA Masaru +Copyright (C) 1999 Ken Murchison Copyright (C) 1991-2020 Thomas G. Lane, Guido Vollbeding diff --git a/src/3rdparty/libjpeg/import_from_libjpeg_tarball.sh b/src/3rdparty/libjpeg/import_from_libjpeg_tarball.sh index 4184cc27694..de3f3091ea7 100755 --- a/src/3rdparty/libjpeg/import_from_libjpeg_tarball.sh +++ b/src/3rdparty/libjpeg/import_from_libjpeg_tarball.sh @@ -92,12 +92,17 @@ FILES=" jccolext.c jccolor.c jcdctmgr.c + jcdiffct.c jchuff.c jchuff.h + jcicc.c jcinit.c + jclhuff.c + jclossls.c jcmainct.c jcmarker.c jcmaster.c + jcmaster.h jcomapi.c jcparam.c jcphuff.c @@ -116,10 +121,15 @@ FILES=" jdcolor.c jdct.h jddctmgr.c + jddiffct.c jdhuff.c jdhuff.h + jdicc.c jdphuff.c jdinput.c + jdlhuff.c + jdlossls.c + jlossls.h jdmainct.c jdmainct.h jdmarker.c @@ -143,7 +153,7 @@ FILES=" jidctfst.c jidctint.c jinclude.h - jpegcomp.h + jpegapicomp.h jpegint.h jpeglib.h jmemmgr.c @@ -153,8 +163,8 @@ FILES=" jpeg_nbits_table.h jquant1.c jquant2.c + jsamplecomp.h jsimd.h - jsimd_none.c jsimddct.h jstdhuff.c jutils.c diff --git a/src/3rdparty/libjpeg/qt_attribution.json b/src/3rdparty/libjpeg/qt_attribution.json index c22c16ea9a6..67526d511b5 100644 --- a/src/3rdparty/libjpeg/qt_attribution.json +++ b/src/3rdparty/libjpeg/qt_attribution.json @@ -6,7 +6,8 @@ "Description": "The Independent JPEG Group's JPEG software", "Homepage": "http://libjpeg-turbo.virtualgl.org/", - "Version": "2.1.5", + "Version": "3.0.0", + "DownloadLocation": "https://sourceforge.net/projects/libjpeg-turbo/files/3.0.0/libjpeg-turbo-3.0.0.tar.gz", "License": "Independent JPEG Group License and BSD 3-Clause \"New\" or \"Revised\" License and zlib License", "LicenseId": "IJG AND BSD-3-Clause AND Zlib", "LicenseFiles": [ "LICENSE", "ijg-license.txt", "zlib-license.txt"], diff --git a/src/3rdparty/libjpeg/src/ChangeLog.md b/src/3rdparty/libjpeg/src/ChangeLog.md index a547522a15a..e12b61786ee 100644 --- a/src/3rdparty/libjpeg/src/ChangeLog.md +++ b/src/3rdparty/libjpeg/src/ChangeLog.md @@ -1,3 +1,223 @@ +3.0.0 +===== + +### Significant changes relative to 3.0 beta2: + +1. The TurboJPEG API now supports 4:4:1 (transposed 4:1:1) chrominance +subsampling, which allows losslessly transposed or rotated 4:1:1 JPEG images to +be losslessly cropped, partially decompressed, or decompressed to planar YUV +images. + +2. Fixed various segfaults and buffer overruns (CVE-2023-2804) that occurred +when attempting to decompress various specially-crafted malformed +12-bit-per-component and 16-bit-per-component lossless JPEG images using color +quantization or merged chroma upsampling/color conversion. The underlying +cause of these issues was that the color quantization and merged chroma +upsampling/color conversion algorithms were not designed with lossless +decompression in mind. Since libjpeg-turbo explicitly does not support color +conversion when compressing or decompressing lossless JPEG images, merged +chroma upsampling/color conversion never should have been enabled for such +images. Color quantization is a legacy feature that serves little or no +purpose with lossless JPEG images, so it is also now disabled when +decompressing such images. (As a result, djpeg can no longer decompress a +lossless JPEG image into a GIF image.) + +3. Fixed an oversight in 1.4 beta1[8] that caused various segfaults and buffer +overruns when attempting to decompress various specially-crafted malformed +12-bit-per-component JPEG images using djpeg with both color quantization and +RGB565 color conversion enabled. + +4. Fixed an issue whereby `jpeg_crop_scanline()` sometimes miscalculated the +downsampled width for components with 4x2 or 2x4 subsampling factors if +decompression scaling was enabled. This caused the components to be upsampled +incompletely, which caused the color converter to read from uninitialized +memory. With 12-bit data precision, this caused a buffer overrun or underrun +and subsequent segfault if the sample value read from uninitialized memory was +outside of the valid sample range. + +5. Fixed a long-standing issue whereby the `tj3Transform()` function, when used +with the `TJXOP_TRANSPOSE`, `TJXOP_TRANSVERSE`, `TJXOP_ROT90`, or +`TJXOP_ROT270` transform operation and without automatic JPEG destination +buffer (re)allocation or lossless cropping, computed the worst-case transformed +JPEG image size based on the source image dimensions rather than the +transformed image dimensions. If a calling program allocated the JPEG +destination buffer based on the transformed image dimensions, as the API +documentation instructs, and attempted to transform a specially-crafted 4:2:2, +4:4:0, 4:1:1, or 4:4:1 JPEG source image containing a large amount of metadata, +the issue caused `tj3Transform()` to overflow the JPEG destination buffer +rather than fail gracefully. The issue could be worked around by setting +`TJXOPT_COPYNONE`. Note that, irrespective of this issue, `tj3Transform()` +cannot reliably transform JPEG source images that contain a large amount of +metadata unless automatic JPEG destination buffer (re)allocation is used or +`TJXOPT_COPYNONE` is set. + +6. Fixed a regression introduced by 3.0 beta2[6] that prevented the djpeg +`-map` option from working when decompressing 12-bit-per-component lossy JPEG +images. + +7. Fixed an issue that caused the C Huffman encoder (which is not used by +default on x86 and Arm CPUs) to read from uninitialized memory when attempting +to transform a specially-crafted malformed arithmetic-coded JPEG source image +into a baseline Huffman-coded JPEG destination image. + + +2.1.91 (3.0 beta2) +================== + +### Significant changes relative to 2.1.5.1: + +1. Significantly sped up the computation of optimal Huffman tables. This +speeds up the compression of tiny images by as much as 2x and provides a +noticeable speedup for images as large as 256x256 when using optimal Huffman +tables. + +2. All deprecated fields, constructors, and methods in the TurboJPEG Java API +have been removed. + +3. Arithmetic entropy coding is now supported with 12-bit-per-component JPEG +images. + +4. Overhauled the TurboJPEG API to address long-standing limitations and to +make the API more extensible and intuitive: + + - All C function names are now prefixed with `tj3`, and all version +suffixes have been removed from the function names. Future API overhauls will +increment the prefix to `tj4`, etc., thus retaining backward API/ABI +compatibility without versioning each individual function. + - Stateless boolean flags have been replaced with stateful integer API +parameters, the values of which persist between function calls. New +functions/methods (`tj3Set()`/`TJCompressor.set()`/`TJDecompressor.set()` and +`tj3Get()`/`TJCompressor.get()`/`TJDecompressor.get()`) can be used to set and +query the value of a particular API parameter. + - The JPEG quality and subsampling are now implemented using API +parameters rather than stateless function arguments (C) or dedicated set/get +methods (Java.) + - `tj3DecompressHeader()` now stores all relevant information about the +JPEG image, including the width, height, subsampling type, entropy coding +algorithm, etc., in API parameters rather than returning that information +through pointer arguments. + - `TJFLAG_LIMITSCANS`/`TJ.FLAG_LIMITSCANS` has been reimplemented as an +API parameter (`TJPARAM_SCANLIMIT`/`TJ.PARAM_SCANLIMIT`) that allows the number +of scans to be specified. + - Optimized baseline entropy coding (the computation of optimal Huffman +tables, as opposed to using the default Huffman tables) can now be specified, +using a new API parameter (`TJPARAM_OPTIMIZE`/`TJ.PARAM_OPTIMIZE`), a new +transform option (`TJXOPT_OPTIMIZE`/`TJTransform.OPT_OPTIMIZE`), and a new +TJBench option (`-optimize`.) + - Arithmetic entropy coding can now be specified or queried, using a new +API parameter (`TJPARAM_ARITHMETIC`/`TJ.PARAM_ARITHMETIC`), a new transform +option (`TJXOPT_ARITHMETIC`/`TJTransform.OPT_ARITHMETIC`), and a new TJBench +option (`-arithmetic`.) + - The restart marker interval can now be specified, using new API +parameters (`TJPARAM_RESTARTROWS`/`TJ.PARAM_RESTARTROWS` and +`TJPARAM_RESTARTBLOCKS`/`TJ.PARAM_RESTARTBLOCKS`) and a new TJBench option +(`-restart`.) + - Pixel density can now be specified or queried, using new API parameters +(`TJPARAM_XDENSITY`/`TJ.PARAM_XDENSITY`, +`TJPARAM_YDENSITY`/`TJ.PARAM_YDENSITY`, and +`TJPARAM_DENSITYUNITS`/`TJ.PARAM_DENSITYUNITS`.) + - The accurate DCT/IDCT algorithms are now the default for both +compression and decompression, since the "fast" algorithms are considered to be +a legacy feature. (The "fast" algorithms do not pass the ISO compliance tests, +and those algorithms are not any faster than the accurate algorithms on modern +x86 CPUs.) + - All C initialization functions have been combined into a single function +(`tj3Init()`) that accepts an integer argument specifying the subsystems to +initialize. + - All C functions now use the `const` keyword for pointer arguments that +point to unmodified buffers (and for both dimensions of pointer arguments that +point to sets of unmodified buffers.) + - All C functions now use `size_t` rather than `unsigned long` to +represent buffer sizes, for compatibility with `malloc()` and to avoid +disparities in the size of `unsigned long` between LP64 (Un*x) and LLP64 +(Windows) operating systems. + - All C buffer size functions now return 0 if an error occurs, rather than +trying to awkwardly return -1 in an unsigned data type (which could easily be +misinterpreted as a very large value.) + - Decompression scaling is now enabled explicitly, using a new +function/method (`tj3SetScalingFactor()`/`TJDecompressor.setScalingFactor()`), +rather than implicitly using awkward "desired width"/"desired height" +arguments. + - Partial image decompression has been implemented, using a new +function/method (`tj3SetCroppingRegion()`/`TJDecompressor.setCroppingRegion()`) +and a new TJBench option (`-crop`.) + - The JPEG colorspace can now be specified explicitly when compressing, +using a new API parameter (`TJPARAM_COLORSPACE`/`TJ.PARAM_COLORSPACE`.) This +allows JPEG images with the RGB and CMYK colorspaces to be created. + - TJBench no longer generates error/difference images, since identical +functionality is already available in ImageMagick. + - JPEG images with unknown subsampling configurations can now be +fully decompressed into packed-pixel images or losslessly transformed (with the +exception of lossless cropping.) They cannot currently be partially +decompressed or decompressed into planar YUV images. + - `tj3Destroy()` now silently accepts a NULL handle. + - `tj3Alloc()` and `tj3Free()` now return/accept void pointers, as +`malloc()` and `free()` do. + - The C image I/O functions now accept a TurboJPEG instance handle, which +is used to transmit/receive API parameter values and to receive error +information. + +5. Added support for 8-bit-per-component, 12-bit-per-component, and +16-bit-per-component lossless JPEG images. A new libjpeg API function +(`jpeg_enable_lossless()`), TurboJPEG API parameters +(`TJPARAM_LOSSLESS`/`TJ.PARAM_LOSSLESS`, +`TJPARAM_LOSSLESSPSV`/`TJ.PARAM_LOSSLESSPSV`, and +`TJPARAM_LOSSLESSPT`/`TJ.PARAM_LOSSLESSPT`), and a cjpeg/TJBench option +(`-lossless`) can be used to create a lossless JPEG image. (Decompression of +lossless JPEG images is handled automatically.) Refer to +[libjpeg.txt](libjpeg.txt), [usage.txt](usage.txt), and the TurboJPEG API +documentation for more details. + +6. Added support for 12-bit-per-component (lossy and lossless) and +16-bit-per-component (lossless) JPEG images to the libjpeg and TurboJPEG APIs: + + - The existing `data_precision` field in `jpeg_compress_struct` and +`jpeg_decompress_struct` has been repurposed to enable the creation of +12-bit-per-component and 16-bit-per-component JPEG images or to detect whether +a 12-bit-per-component or 16-bit-per-component JPEG image is being +decompressed. + - New 12-bit-per-component and 16-bit-per-component versions of +`jpeg_write_scanlines()` and `jpeg_read_scanlines()`, as well as new +12-bit-per-component versions of `jpeg_write_raw_data()`, +`jpeg_skip_scanlines()`, `jpeg_crop_scanline()`, and `jpeg_read_raw_data()`, +provide interfaces for compressing from/decompressing to 12-bit-per-component +and 16-bit-per-component packed-pixel and planar YUV image buffers. + - New 12-bit-per-component and 16-bit-per-component compression, +decompression, and image I/O functions/methods have been added to the TurboJPEG +API, and a new API parameter (`TJPARAM_PRECISION`/`TJ.PARAM_PRECISION`) can be +used to query the data precision of a JPEG image. (YUV functions are currently +limited to 8-bit data precision but can be expanded to accommodate 12-bit data +precision in the future, if such is deemed beneficial.) + - A new cjpeg and TJBench command-line argument (`-precision`) can be used +to create a 12-bit-per-component or 16-bit-per-component JPEG image. +(Decompression and transformation of 12-bit-per-component and +16-bit-per-component JPEG images is handled automatically.) + + Refer to [libjpeg.txt](libjpeg.txt), [usage.txt](usage.txt), and the +TurboJPEG API documentation for more details. + + +2.1.5.1 +======= + +### Significant changes relative to 2.1.5: + +1. The SIMD dispatchers in libjpeg-turbo 2.1.4 and prior stored the list of +supported SIMD instruction sets in a global variable, which caused an innocuous +race condition whereby the variable could have been initialized multiple times +if `jpeg_start_*compress()` was called simultaneously in multiple threads. +libjpeg-turbo 2.1.5 included an undocumented attempt to fix this race condition +by making the SIMD support variable thread-local. However, that caused another +issue whereby, if `jpeg_start_*compress()` was called in one thread and +`jpeg_read_*()` or `jpeg_write_*()` was called in a second thread, the SIMD +support variable was never initialized in the second thread. On x86 systems, +this led the second thread to incorrectly assume that AVX2 instructions were +always available, and when it attempted to use those instructions on older x86 +CPUs that do not support them, an illegal instruction error occurred. The SIMD +dispatchers now ensure that the SIMD support variable is initialized before +dispatching based on its value. + + 2.1.5 ===== @@ -1419,7 +1639,7 @@ features (such as the colorspace extensions), but in general, it performs no faster than libjpeg v6b. 14. Added ARM 64-bit SIMD acceleration for the YCC-to-RGB color conversion -and IDCT algorithms (both are used during JPEG decompression.) For unknown +and IDCT algorithms (both are used during JPEG decompression.) For reasons (probably related to clang), this code cannot currently be compiled for iOS. diff --git a/src/3rdparty/libjpeg/src/README.ijg b/src/3rdparty/libjpeg/src/README.ijg index 9453c195010..8f3768265f6 100644 --- a/src/3rdparty/libjpeg/src/README.ijg +++ b/src/3rdparty/libjpeg/src/README.ijg @@ -43,7 +43,7 @@ User documentation: change.log Version-to-version change highlights. Programmer and internal documentation: libjpeg.txt How to use the JPEG library in your own programs. - example.txt Sample code for calling the JPEG library. + example.c Sample code for calling the JPEG library. structure.txt Overview of the JPEG library's internal structure. coderules.txt Coding style rules --- please read if you contribute code. @@ -68,17 +68,17 @@ other abrupt features may not compress well with JPEG, and a higher JPEG quality may have to be used to avoid visible compression artifacts with such images. -JPEG is lossy, meaning that the output pixels are not necessarily identical to -the input pixels. However, on photographic content and other "smooth" images, -very good compression ratios can be obtained with no visible compression -artifacts, and extremely high compression ratios are possible if you are -willing to sacrifice image quality (by reducing the "quality" setting in the -compressor.) +JPEG is normally lossy, meaning that the output pixels are not necessarily +identical to the input pixels. However, on photographic content and other +"smooth" images, very good compression ratios can be obtained with no visible +compression artifacts, and extremely high compression ratios are possible if +you are willing to sacrifice image quality (by reducing the "quality" setting +in the compressor.) -This software implements JPEG baseline, extended-sequential, and progressive -compression processes. Provision is made for supporting all variants of these -processes, although some uncommon parameter settings aren't implemented yet. -We have made no provision for supporting the hierarchical or lossless +This software implements JPEG baseline, extended-sequential, progressive, and +lossless compression processes. Provision is made for supporting all variants +of these processes, although some uncommon parameter settings aren't +implemented yet. We have made no provision for supporting the hierarchical processes defined in the standard. We provide a set of library routines for reading and writing JPEG image files, @@ -241,7 +241,7 @@ This software implements ITU T.81 | ISO/IEC 10918 with some extensions from ITU T.871 | ISO/IEC 10918-5 (JPEG File Interchange Format-- see REFERENCES). Informally, the term "JPEG image" or "JPEG file" most often refers to JFIF or a subset thereof, but there are other formats containing the name "JPEG" that -are incompatible with the DCT-based JPEG standard or with JFIF (for instance, +are incompatible with the original JPEG standard or with JFIF (for instance, JPEG 2000 and JPEG XR). This software therefore does not support these formats. Indeed, one of the original reasons for developing this free software was to help force convergence on a common, interoperable format standard for diff --git a/src/3rdparty/libjpeg/src/README.md b/src/3rdparty/libjpeg/src/README.md index 01e391ea7c0..a1eed3df3ef 100644 --- a/src/3rdparty/libjpeg/src/README.md +++ b/src/3rdparty/libjpeg/src/README.md @@ -23,6 +23,8 @@ early 2010, libjpeg-turbo spun off into an independent project, with the goal of making high-speed JPEG compression/decompression technology available to a broader range of users and developers. +More information about libjpeg-turbo can be found at +. License ======= @@ -245,16 +247,6 @@ programs that need them, without breaking ABI compatibility for programs that don't, and it allows those functions to be provided in the "official" libjpeg-turbo binaries. -Those who are concerned about maintaining strict conformance with the libjpeg -v6b or v7 API can pass an argument of `-DWITH_MEM_SRCDST=0` to `cmake` prior to -building libjpeg-turbo. This will restore the pre-1.3 behavior, in which -`jpeg_mem_src()` and `jpeg_mem_dest()` are only included when emulating the -libjpeg v8 API/ABI. - -On Un*x systems, including the in-memory source/destination managers changes -the dynamic library version from 62.2.0 to 62.3.0 if using libjpeg v6b API/ABI -emulation and from 7.2.0 to 7.3.0 if using libjpeg v7 API/ABI emulation. - Note that, on most Un*x systems, the dynamic linker will not look for a function in a library until that function is actually used. Thus, if a program is built against libjpeg-turbo 1.3+ and uses `jpeg_mem_src()` or diff --git a/src/3rdparty/libjpeg/src/jcapimin.c b/src/3rdparty/libjpeg/src/jcapimin.c index 84e7ecc9a73..cbb3d13e1ce 100644 --- a/src/3rdparty/libjpeg/src/jcapimin.c +++ b/src/3rdparty/libjpeg/src/jcapimin.c @@ -23,6 +23,7 @@ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" +#include "jcmaster.h" /* @@ -90,8 +91,18 @@ jpeg_CreateCompress(j_compress_ptr cinfo, int version, size_t structsize) cinfo->input_gamma = 1.0; /* in case application forgets */ + cinfo->data_precision = BITS_IN_JSAMPLE; + /* OK, I'm ready */ cinfo->global_state = CSTATE_START; + + /* The master struct is used to store extension parameters, so we allocate it + * here. + */ + cinfo->master = (struct jpeg_comp_master *) + (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_PERMANENT, + sizeof(my_comp_master)); + memset(cinfo->master, 0, sizeof(my_comp_master)); } @@ -183,8 +194,20 @@ jpeg_finish_compress(j_compress_ptr cinfo) /* We bypass the main controller and invoke coef controller directly; * all work is being done from the coefficient buffer. */ - if (!(*cinfo->coef->compress_data) (cinfo, (JSAMPIMAGE)NULL)) - ERREXIT(cinfo, JERR_CANT_SUSPEND); + if (cinfo->data_precision == 16) { +#ifdef C_LOSSLESS_SUPPORTED + if (!(*cinfo->coef->compress_data_16) (cinfo, (J16SAMPIMAGE)NULL)) + ERREXIT(cinfo, JERR_CANT_SUSPEND); +#else + ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision); +#endif + } else if (cinfo->data_precision == 12) { + if (!(*cinfo->coef->compress_data_12) (cinfo, (J12SAMPIMAGE)NULL)) + ERREXIT(cinfo, JERR_CANT_SUSPEND); + } else { + if (!(*cinfo->coef->compress_data) (cinfo, (JSAMPIMAGE)NULL)) + ERREXIT(cinfo, JERR_CANT_SUSPEND); + } } (*cinfo->master->finish_pass) (cinfo); } diff --git a/src/3rdparty/libjpeg/src/jcapistd.c b/src/3rdparty/libjpeg/src/jcapistd.c index aa2aad9f66c..2053028f2bf 100644 --- a/src/3rdparty/libjpeg/src/jcapistd.c +++ b/src/3rdparty/libjpeg/src/jcapistd.c @@ -1,8 +1,10 @@ /* * jcapistd.c * + * This file was part of the Independent JPEG Group's software: * Copyright (C) 1994-1996, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. + * libjpeg-turbo Modifications: + * Copyright (C) 2022, D. R. Commander. * For conditions of distribution and use, see the accompanying README.ijg * file. * @@ -18,8 +20,11 @@ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" +#include "jsamplecomp.h" +#if BITS_IN_JSAMPLE == 8 + /* * Compression initialization. * Before calling this, all parameters and a data destination must be set up. @@ -51,13 +56,15 @@ jpeg_start_compress(j_compress_ptr cinfo, boolean write_all_tables) jinit_compress_master(cinfo); /* Set up for the first pass */ (*cinfo->master->prepare_for_pass) (cinfo); - /* Ready for application to drive first pass through jpeg_write_scanlines - * or jpeg_write_raw_data. + /* Ready for application to drive first pass through _jpeg_write_scanlines + * or _jpeg_write_raw_data. */ cinfo->next_scanline = 0; cinfo->global_state = (cinfo->raw_data_in ? CSTATE_RAW_OK : CSTATE_SCANNING); } +#endif + /* * Write some scanlines of data to the JPEG compressor. @@ -67,7 +74,7 @@ jpeg_start_compress(j_compress_ptr cinfo, boolean write_all_tables) * the data destination module has requested suspension of the compressor, * or if more than image_height scanlines are passed in. * - * Note: we warn about excess calls to jpeg_write_scanlines() since + * Note: we warn about excess calls to _jpeg_write_scanlines() since * this likely signals an application programmer error. However, * excess scanlines passed in the last valid call are *silently* ignored, * so that the application need not adjust num_lines for end-of-image @@ -75,11 +82,15 @@ jpeg_start_compress(j_compress_ptr cinfo, boolean write_all_tables) */ GLOBAL(JDIMENSION) -jpeg_write_scanlines(j_compress_ptr cinfo, JSAMPARRAY scanlines, - JDIMENSION num_lines) +_jpeg_write_scanlines(j_compress_ptr cinfo, _JSAMPARRAY scanlines, + JDIMENSION num_lines) { +#if BITS_IN_JSAMPLE != 16 || defined(C_LOSSLESS_SUPPORTED) JDIMENSION row_ctr, rows_left; + if (cinfo->data_precision != BITS_IN_JSAMPLE) + ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision); + if (cinfo->global_state != CSTATE_SCANNING) ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); if (cinfo->next_scanline >= cinfo->image_height) @@ -93,9 +104,9 @@ jpeg_write_scanlines(j_compress_ptr cinfo, JSAMPARRAY scanlines, } /* Give master control module another chance if this is first call to - * jpeg_write_scanlines. This lets output of the frame/scan headers be + * _jpeg_write_scanlines. This lets output of the frame/scan headers be * delayed so that application can write COM, etc, markers between - * jpeg_start_compress and jpeg_write_scanlines. + * jpeg_start_compress and _jpeg_write_scanlines. */ if (cinfo->master->call_pass_startup) (*cinfo->master->pass_startup) (cinfo); @@ -106,23 +117,35 @@ jpeg_write_scanlines(j_compress_ptr cinfo, JSAMPARRAY scanlines, num_lines = rows_left; row_ctr = 0; - (*cinfo->main->process_data) (cinfo, scanlines, &row_ctr, num_lines); + (*cinfo->main->_process_data) (cinfo, scanlines, &row_ctr, num_lines); cinfo->next_scanline += row_ctr; return row_ctr; +#else + ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision); + return 0; +#endif } +#if BITS_IN_JSAMPLE != 16 + /* * Alternate entry point to write raw data. * Processes exactly one iMCU row per call, unless suspended. */ GLOBAL(JDIMENSION) -jpeg_write_raw_data(j_compress_ptr cinfo, JSAMPIMAGE data, - JDIMENSION num_lines) +_jpeg_write_raw_data(j_compress_ptr cinfo, _JSAMPIMAGE data, + JDIMENSION num_lines) { JDIMENSION lines_per_iMCU_row; + if (cinfo->data_precision != BITS_IN_JSAMPLE) + ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision); + + if (cinfo->master->lossless) + ERREXIT(cinfo, JERR_NOTIMPL); + if (cinfo->global_state != CSTATE_RAW_OK) ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); if (cinfo->next_scanline >= cinfo->image_height) { @@ -138,9 +161,9 @@ jpeg_write_raw_data(j_compress_ptr cinfo, JSAMPIMAGE data, } /* Give master control module another chance if this is first call to - * jpeg_write_raw_data. This lets output of the frame/scan headers be + * _jpeg_write_raw_data. This lets output of the frame/scan headers be * delayed so that application can write COM, etc, markers between - * jpeg_start_compress and jpeg_write_raw_data. + * jpeg_start_compress and _jpeg_write_raw_data. */ if (cinfo->master->call_pass_startup) (*cinfo->master->pass_startup) (cinfo); @@ -151,7 +174,7 @@ jpeg_write_raw_data(j_compress_ptr cinfo, JSAMPIMAGE data, ERREXIT(cinfo, JERR_BUFFER_SIZE); /* Directly compress the row. */ - if (!(*cinfo->coef->compress_data) (cinfo, data)) { + if (!(*cinfo->coef->_compress_data) (cinfo, data)) { /* If compressor did not consume the whole row, suspend processing. */ return 0; } @@ -160,3 +183,5 @@ jpeg_write_raw_data(j_compress_ptr cinfo, JSAMPIMAGE data, cinfo->next_scanline += lines_per_iMCU_row; return lines_per_iMCU_row; } + +#endif /* BITS_IN_JSAMPLE != 16 */ diff --git a/src/3rdparty/libjpeg/src/jccoefct.c b/src/3rdparty/libjpeg/src/jccoefct.c index 068232a527d..2a5dde2d07e 100644 --- a/src/3rdparty/libjpeg/src/jccoefct.c +++ b/src/3rdparty/libjpeg/src/jccoefct.c @@ -3,19 +3,20 @@ * * This file was part of the Independent JPEG Group's software: * Copyright (C) 1994-1997, Thomas G. Lane. - * It was modified by The libjpeg-turbo Project to include only code and - * information relevant to libjpeg-turbo. + * libjpeg-turbo Modifications: + * Copyright (C) 2022, D. R. Commander. * For conditions of distribution and use, see the accompanying README.ijg * file. * * This file contains the coefficient buffer controller for compression. - * This controller is the top level of the JPEG compressor proper. + * This controller is the top level of the lossy JPEG compressor proper. * The coefficient buffer lies between forward-DCT and entropy encoding steps. */ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" +#include "jsamplecomp.h" /* We use a full-image coefficient buffer when doing Huffman optimization, @@ -58,11 +59,12 @@ typedef my_coef_controller *my_coef_ptr; /* Forward declarations */ -METHODDEF(boolean) compress_data(j_compress_ptr cinfo, JSAMPIMAGE input_buf); +METHODDEF(boolean) compress_data(j_compress_ptr cinfo, _JSAMPIMAGE input_buf); #ifdef FULL_COEF_BUFFER_SUPPORTED METHODDEF(boolean) compress_first_pass(j_compress_ptr cinfo, - JSAMPIMAGE input_buf); -METHODDEF(boolean) compress_output(j_compress_ptr cinfo, JSAMPIMAGE input_buf); + _JSAMPIMAGE input_buf); +METHODDEF(boolean) compress_output(j_compress_ptr cinfo, + _JSAMPIMAGE input_buf); #endif @@ -106,18 +108,18 @@ start_pass_coef(j_compress_ptr cinfo, J_BUF_MODE pass_mode) case JBUF_PASS_THRU: if (coef->whole_image[0] != NULL) ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); - coef->pub.compress_data = compress_data; + coef->pub._compress_data = compress_data; break; #ifdef FULL_COEF_BUFFER_SUPPORTED case JBUF_SAVE_AND_PASS: if (coef->whole_image[0] == NULL) ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); - coef->pub.compress_data = compress_first_pass; + coef->pub._compress_data = compress_first_pass; break; case JBUF_CRANK_DEST: if (coef->whole_image[0] == NULL) ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); - coef->pub.compress_data = compress_output; + coef->pub._compress_data = compress_output; break; #endif default: @@ -138,7 +140,7 @@ start_pass_coef(j_compress_ptr cinfo, J_BUF_MODE pass_mode) */ METHODDEF(boolean) -compress_data(j_compress_ptr cinfo, JSAMPIMAGE input_buf) +compress_data(j_compress_ptr cinfo, _JSAMPIMAGE input_buf) { my_coef_ptr coef = (my_coef_ptr)cinfo->coef; JDIMENSION MCU_col_num; /* index of current MCU within row */ @@ -172,10 +174,10 @@ compress_data(j_compress_ptr cinfo, JSAMPIMAGE input_buf) for (yindex = 0; yindex < compptr->MCU_height; yindex++) { if (coef->iMCU_row_num < last_iMCU_row || yoffset + yindex < compptr->last_row_height) { - (*cinfo->fdct->forward_DCT) (cinfo, compptr, - input_buf[compptr->component_index], - coef->MCU_buffer[blkn], - ypos, xpos, (JDIMENSION)blockcnt); + (*cinfo->fdct->_forward_DCT) (cinfo, compptr, + input_buf[compptr->component_index], + coef->MCU_buffer[blkn], + ypos, xpos, (JDIMENSION)blockcnt); if (blockcnt < compptr->MCU_width) { /* Create some dummy blocks at the right edge of the image. */ jzero_far((void *)coef->MCU_buffer[blkn + blockcnt], @@ -242,7 +244,7 @@ compress_data(j_compress_ptr cinfo, JSAMPIMAGE input_buf) */ METHODDEF(boolean) -compress_first_pass(j_compress_ptr cinfo, JSAMPIMAGE input_buf) +compress_first_pass(j_compress_ptr cinfo, _JSAMPIMAGE input_buf) { my_coef_ptr coef = (my_coef_ptr)cinfo->coef; JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1; @@ -279,10 +281,10 @@ compress_first_pass(j_compress_ptr cinfo, JSAMPIMAGE input_buf) */ for (block_row = 0; block_row < block_rows; block_row++) { thisblockrow = buffer[block_row]; - (*cinfo->fdct->forward_DCT) (cinfo, compptr, - input_buf[ci], thisblockrow, - (JDIMENSION)(block_row * DCTSIZE), - (JDIMENSION)0, blocks_across); + (*cinfo->fdct->_forward_DCT) (cinfo, compptr, + input_buf[ci], thisblockrow, + (JDIMENSION)(block_row * DCTSIZE), + (JDIMENSION)0, blocks_across); if (ndummy > 0) { /* Create dummy blocks at the right edge of the image. */ thisblockrow += blocks_across; /* => first dummy block */ @@ -338,7 +340,7 @@ compress_first_pass(j_compress_ptr cinfo, JSAMPIMAGE input_buf) */ METHODDEF(boolean) -compress_output(j_compress_ptr cinfo, JSAMPIMAGE input_buf) +compress_output(j_compress_ptr cinfo, _JSAMPIMAGE input_buf) { my_coef_ptr coef = (my_coef_ptr)cinfo->coef; JDIMENSION MCU_col_num; /* index of current MCU within row */ @@ -402,10 +404,13 @@ compress_output(j_compress_ptr cinfo, JSAMPIMAGE input_buf) */ GLOBAL(void) -jinit_c_coef_controller(j_compress_ptr cinfo, boolean need_full_buffer) +_jinit_c_coef_controller(j_compress_ptr cinfo, boolean need_full_buffer) { my_coef_ptr coef; + if (cinfo->data_precision != BITS_IN_JSAMPLE) + ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision); + coef = (my_coef_ptr) (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE, sizeof(my_coef_controller)); diff --git a/src/3rdparty/libjpeg/src/jccolext.c b/src/3rdparty/libjpeg/src/jccolext.c index 20f891a6330..8eba36c4dff 100644 --- a/src/3rdparty/libjpeg/src/jccolext.c +++ b/src/3rdparty/libjpeg/src/jccolext.c @@ -29,15 +29,16 @@ INLINE LOCAL(void) -rgb_ycc_convert_internal(j_compress_ptr cinfo, JSAMPARRAY input_buf, - JSAMPIMAGE output_buf, JDIMENSION output_row, +rgb_ycc_convert_internal(j_compress_ptr cinfo, _JSAMPARRAY input_buf, + _JSAMPIMAGE output_buf, JDIMENSION output_row, int num_rows) { +#if BITS_IN_JSAMPLE != 16 my_cconvert_ptr cconvert = (my_cconvert_ptr)cinfo->cconvert; register int r, g, b; register JLONG *ctab = cconvert->rgb_ycc_tab; - register JSAMPROW inptr; - register JSAMPROW outptr0, outptr1, outptr2; + register _JSAMPROW inptr; + register _JSAMPROW outptr0, outptr1, outptr2; register JDIMENSION col; JDIMENSION num_cols = cinfo->image_width; @@ -52,22 +53,25 @@ rgb_ycc_convert_internal(j_compress_ptr cinfo, JSAMPARRAY input_buf, g = RANGE_LIMIT(inptr[RGB_GREEN]); b = RANGE_LIMIT(inptr[RGB_BLUE]); inptr += RGB_PIXELSIZE; - /* If the inputs are 0..MAXJSAMPLE, the outputs of these equations + /* If the inputs are 0.._MAXJSAMPLE, the outputs of these equations * must be too; we do not need an explicit range-limiting operation. * Hence the value being shifted is never negative, and we don't * need the general RIGHT_SHIFT macro. */ /* Y */ - outptr0[col] = (JSAMPLE)((ctab[r + R_Y_OFF] + ctab[g + G_Y_OFF] + - ctab[b + B_Y_OFF]) >> SCALEBITS); + outptr0[col] = (_JSAMPLE)((ctab[r + R_Y_OFF] + ctab[g + G_Y_OFF] + + ctab[b + B_Y_OFF]) >> SCALEBITS); /* Cb */ - outptr1[col] = (JSAMPLE)((ctab[r + R_CB_OFF] + ctab[g + G_CB_OFF] + - ctab[b + B_CB_OFF]) >> SCALEBITS); + outptr1[col] = (_JSAMPLE)((ctab[r + R_CB_OFF] + ctab[g + G_CB_OFF] + + ctab[b + B_CB_OFF]) >> SCALEBITS); /* Cr */ - outptr2[col] = (JSAMPLE)((ctab[r + R_CR_OFF] + ctab[g + G_CR_OFF] + - ctab[b + B_CR_OFF]) >> SCALEBITS); + outptr2[col] = (_JSAMPLE)((ctab[r + R_CR_OFF] + ctab[g + G_CR_OFF] + + ctab[b + B_CR_OFF]) >> SCALEBITS); } } +#else + ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); +#endif } @@ -83,15 +87,16 @@ rgb_ycc_convert_internal(j_compress_ptr cinfo, JSAMPARRAY input_buf, INLINE LOCAL(void) -rgb_gray_convert_internal(j_compress_ptr cinfo, JSAMPARRAY input_buf, - JSAMPIMAGE output_buf, JDIMENSION output_row, +rgb_gray_convert_internal(j_compress_ptr cinfo, _JSAMPARRAY input_buf, + _JSAMPIMAGE output_buf, JDIMENSION output_row, int num_rows) { +#if BITS_IN_JSAMPLE != 16 my_cconvert_ptr cconvert = (my_cconvert_ptr)cinfo->cconvert; register int r, g, b; register JLONG *ctab = cconvert->rgb_ycc_tab; - register JSAMPROW inptr; - register JSAMPROW outptr; + register _JSAMPROW inptr; + register _JSAMPROW outptr; register JDIMENSION col; JDIMENSION num_cols = cinfo->image_width; @@ -105,10 +110,13 @@ rgb_gray_convert_internal(j_compress_ptr cinfo, JSAMPARRAY input_buf, b = RANGE_LIMIT(inptr[RGB_BLUE]); inptr += RGB_PIXELSIZE; /* Y */ - outptr[col] = (JSAMPLE)((ctab[r + R_Y_OFF] + ctab[g + G_Y_OFF] + - ctab[b + B_Y_OFF]) >> SCALEBITS); + outptr[col] = (_JSAMPLE)((ctab[r + R_Y_OFF] + ctab[g + G_Y_OFF] + + ctab[b + B_Y_OFF]) >> SCALEBITS); } } +#else + ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); +#endif } @@ -119,12 +127,12 @@ rgb_gray_convert_internal(j_compress_ptr cinfo, JSAMPARRAY input_buf, INLINE LOCAL(void) -rgb_rgb_convert_internal(j_compress_ptr cinfo, JSAMPARRAY input_buf, - JSAMPIMAGE output_buf, JDIMENSION output_row, +rgb_rgb_convert_internal(j_compress_ptr cinfo, _JSAMPARRAY input_buf, + _JSAMPIMAGE output_buf, JDIMENSION output_row, int num_rows) { - register JSAMPROW inptr; - register JSAMPROW outptr0, outptr1, outptr2; + register _JSAMPROW inptr; + register _JSAMPROW outptr0, outptr1, outptr2; register JDIMENSION col; JDIMENSION num_cols = cinfo->image_width; diff --git a/src/3rdparty/libjpeg/src/jccolor.c b/src/3rdparty/libjpeg/src/jccolor.c index fb9f1cc1927..cd3a6a7a567 100644 --- a/src/3rdparty/libjpeg/src/jccolor.c +++ b/src/3rdparty/libjpeg/src/jccolor.c @@ -17,15 +17,20 @@ #include "jinclude.h" #include "jpeglib.h" #include "jsimd.h" +#include "jsamplecomp.h" +#if BITS_IN_JSAMPLE != 16 || defined(C_LOSSLESS_SUPPORTED) + /* Private subobject */ typedef struct { struct jpeg_color_converter pub; /* public fields */ +#if BITS_IN_JSAMPLE != 16 /* Private state for RGB->YCC conversion */ JLONG *rgb_ycc_tab; /* => table for RGB to YCbCr conversion */ +#endif } my_color_converter; typedef my_color_converter *my_cconvert_ptr; @@ -35,14 +40,14 @@ typedef my_color_converter *my_cconvert_ptr; /* * YCbCr is defined per CCIR 601-1, except that Cb and Cr are - * normalized to the range 0..MAXJSAMPLE rather than -0.5 .. 0.5. + * normalized to the range 0.._MAXJSAMPLE rather than -0.5 .. 0.5. * The conversion equations to be implemented are therefore * Y = 0.29900 * R + 0.58700 * G + 0.11400 * B - * Cb = -0.16874 * R - 0.33126 * G + 0.50000 * B + CENTERJSAMPLE - * Cr = 0.50000 * R - 0.41869 * G - 0.08131 * B + CENTERJSAMPLE + * Cb = -0.16874 * R - 0.33126 * G + 0.50000 * B + _CENTERJSAMPLE + * Cr = 0.50000 * R - 0.41869 * G - 0.08131 * B + _CENTERJSAMPLE * (These numbers are derived from TIFF 6.0 section 21, dated 3-June-92.) - * Note: older versions of the IJG code used a zero offset of MAXJSAMPLE/2, - * rather than CENTERJSAMPLE, for Cb and Cr. This gave equal positive and + * Note: older versions of the IJG code used a zero offset of _MAXJSAMPLE/2, + * rather than _CENTERJSAMPLE, for Cb and Cr. This gave equal positive and * negative swings for Cb/Cr, but meant that grayscale values (Cb=Cr=0) * were not represented exactly. Now we sacrifice exact representation of * maximum red and maximum blue in order to get exact grayscales. @@ -53,16 +58,16 @@ typedef my_color_converter *my_cconvert_ptr; * * For even more speed, we avoid doing any multiplications in the inner loop * by precalculating the constants times R,G,B for all possible values. - * For 8-bit JSAMPLEs this is very reasonable (only 256 entries per table); + * For 8-bit samples this is very reasonable (only 256 entries per table); * for 12-bit samples it is still acceptable. It's not very reasonable for * 16-bit samples, but if you want lossless storage you shouldn't be changing * colorspace anyway. - * The CENTERJSAMPLE offsets and the rounding fudge-factor of 0.5 are included + * The _CENTERJSAMPLE offsets and the rounding fudge-factor of 0.5 are included * in the tables to save adding them separately in the inner loop. */ #define SCALEBITS 16 /* speediest right-shift on some machines */ -#define CBCR_OFFSET ((JLONG)CENTERJSAMPLE << SCALEBITS) +#define CBCR_OFFSET ((JLONG)_CENTERJSAMPLE << SCALEBITS) #define ONE_HALF ((JLONG)1 << (SCALEBITS - 1)) #define FIX(x) ((JLONG)((x) * (1L << SCALEBITS) + 0.5)) @@ -73,15 +78,15 @@ typedef my_color_converter *my_cconvert_ptr; */ #define R_Y_OFF 0 /* offset to R => Y section */ -#define G_Y_OFF (1 * (MAXJSAMPLE + 1)) /* offset to G => Y section */ -#define B_Y_OFF (2 * (MAXJSAMPLE + 1)) /* etc. */ -#define R_CB_OFF (3 * (MAXJSAMPLE + 1)) -#define G_CB_OFF (4 * (MAXJSAMPLE + 1)) -#define B_CB_OFF (5 * (MAXJSAMPLE + 1)) +#define G_Y_OFF (1 * (_MAXJSAMPLE + 1)) /* offset to G => Y section */ +#define B_Y_OFF (2 * (_MAXJSAMPLE + 1)) /* etc. */ +#define R_CB_OFF (3 * (_MAXJSAMPLE + 1)) +#define G_CB_OFF (4 * (_MAXJSAMPLE + 1)) +#define B_CB_OFF (5 * (_MAXJSAMPLE + 1)) #define R_CR_OFF B_CB_OFF /* B=>Cb, R=>Cr are the same */ -#define G_CR_OFF (6 * (MAXJSAMPLE + 1)) -#define B_CR_OFF (7 * (MAXJSAMPLE + 1)) -#define TABLE_SIZE (8 * (MAXJSAMPLE + 1)) +#define G_CR_OFF (6 * (_MAXJSAMPLE + 1)) +#define B_CR_OFF (7 * (_MAXJSAMPLE + 1)) +#define TABLE_SIZE (8 * (_MAXJSAMPLE + 1)) /* 12-bit samples use a 16-bit data type, so it is possible to pass * out-of-range sample values (< 0 or > 4095) to jpeg_write_scanlines(). @@ -208,6 +213,7 @@ typedef my_color_converter *my_cconvert_ptr; METHODDEF(void) rgb_ycc_start(j_compress_ptr cinfo) { +#if BITS_IN_JSAMPLE != 16 my_cconvert_ptr cconvert = (my_cconvert_ptr)cinfo->cconvert; JLONG *rgb_ycc_tab; JLONG i; @@ -217,15 +223,15 @@ rgb_ycc_start(j_compress_ptr cinfo) (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE, (TABLE_SIZE * sizeof(JLONG))); - for (i = 0; i <= MAXJSAMPLE; i++) { + for (i = 0; i <= _MAXJSAMPLE; i++) { rgb_ycc_tab[i + R_Y_OFF] = FIX(0.29900) * i; rgb_ycc_tab[i + G_Y_OFF] = FIX(0.58700) * i; rgb_ycc_tab[i + B_Y_OFF] = FIX(0.11400) * i + ONE_HALF; rgb_ycc_tab[i + R_CB_OFF] = (-FIX(0.16874)) * i; rgb_ycc_tab[i + G_CB_OFF] = (-FIX(0.33126)) * i; /* We use a rounding fudge-factor of 0.5-epsilon for Cb and Cr. - * This ensures that the maximum output will round to MAXJSAMPLE - * not MAXJSAMPLE+1, and thus that we don't have to range-limit. + * This ensures that the maximum output will round to _MAXJSAMPLE + * not _MAXJSAMPLE+1, and thus that we don't have to range-limit. */ rgb_ycc_tab[i + B_CB_OFF] = FIX(0.50000) * i + CBCR_OFFSET + ONE_HALF - 1; /* B=>Cb and R=>Cr tables are the same @@ -234,6 +240,9 @@ rgb_ycc_start(j_compress_ptr cinfo) rgb_ycc_tab[i + G_CR_OFF] = (-FIX(0.41869)) * i; rgb_ycc_tab[i + B_CR_OFF] = (-FIX(0.08131)) * i; } +#else + ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); +#endif } @@ -242,8 +251,8 @@ rgb_ycc_start(j_compress_ptr cinfo) */ METHODDEF(void) -rgb_ycc_convert(j_compress_ptr cinfo, JSAMPARRAY input_buf, - JSAMPIMAGE output_buf, JDIMENSION output_row, int num_rows) +rgb_ycc_convert(j_compress_ptr cinfo, _JSAMPARRAY input_buf, + _JSAMPIMAGE output_buf, JDIMENSION output_row, int num_rows) { switch (cinfo->in_color_space) { case JCS_EXT_RGB: @@ -290,8 +299,8 @@ rgb_ycc_convert(j_compress_ptr cinfo, JSAMPARRAY input_buf, */ METHODDEF(void) -rgb_gray_convert(j_compress_ptr cinfo, JSAMPARRAY input_buf, - JSAMPIMAGE output_buf, JDIMENSION output_row, int num_rows) +rgb_gray_convert(j_compress_ptr cinfo, _JSAMPARRAY input_buf, + _JSAMPIMAGE output_buf, JDIMENSION output_row, int num_rows) { switch (cinfo->in_color_space) { case JCS_EXT_RGB: @@ -335,8 +344,8 @@ rgb_gray_convert(j_compress_ptr cinfo, JSAMPARRAY input_buf, */ METHODDEF(void) -rgb_rgb_convert(j_compress_ptr cinfo, JSAMPARRAY input_buf, - JSAMPIMAGE output_buf, JDIMENSION output_row, int num_rows) +rgb_rgb_convert(j_compress_ptr cinfo, _JSAMPARRAY input_buf, + _JSAMPIMAGE output_buf, JDIMENSION output_row, int num_rows) { switch (cinfo->in_color_space) { case JCS_EXT_RGB: @@ -384,14 +393,15 @@ rgb_rgb_convert(j_compress_ptr cinfo, JSAMPARRAY input_buf, */ METHODDEF(void) -cmyk_ycck_convert(j_compress_ptr cinfo, JSAMPARRAY input_buf, - JSAMPIMAGE output_buf, JDIMENSION output_row, int num_rows) +cmyk_ycck_convert(j_compress_ptr cinfo, _JSAMPARRAY input_buf, + _JSAMPIMAGE output_buf, JDIMENSION output_row, int num_rows) { +#if BITS_IN_JSAMPLE != 16 my_cconvert_ptr cconvert = (my_cconvert_ptr)cinfo->cconvert; register int r, g, b; register JLONG *ctab = cconvert->rgb_ycc_tab; - register JSAMPROW inptr; - register JSAMPROW outptr0, outptr1, outptr2, outptr3; + register _JSAMPROW inptr; + register _JSAMPROW outptr0, outptr1, outptr2, outptr3; register JDIMENSION col; JDIMENSION num_cols = cinfo->image_width; @@ -403,28 +413,31 @@ cmyk_ycck_convert(j_compress_ptr cinfo, JSAMPARRAY input_buf, outptr3 = output_buf[3][output_row]; output_row++; for (col = 0; col < num_cols; col++) { - r = MAXJSAMPLE - RANGE_LIMIT(inptr[0]); - g = MAXJSAMPLE - RANGE_LIMIT(inptr[1]); - b = MAXJSAMPLE - RANGE_LIMIT(inptr[2]); + r = _MAXJSAMPLE - RANGE_LIMIT(inptr[0]); + g = _MAXJSAMPLE - RANGE_LIMIT(inptr[1]); + b = _MAXJSAMPLE - RANGE_LIMIT(inptr[2]); /* K passes through as-is */ outptr3[col] = inptr[3]; inptr += 4; - /* If the inputs are 0..MAXJSAMPLE, the outputs of these equations + /* If the inputs are 0.._MAXJSAMPLE, the outputs of these equations * must be too; we do not need an explicit range-limiting operation. * Hence the value being shifted is never negative, and we don't * need the general RIGHT_SHIFT macro. */ /* Y */ - outptr0[col] = (JSAMPLE)((ctab[r + R_Y_OFF] + ctab[g + G_Y_OFF] + - ctab[b + B_Y_OFF]) >> SCALEBITS); + outptr0[col] = (_JSAMPLE)((ctab[r + R_Y_OFF] + ctab[g + G_Y_OFF] + + ctab[b + B_Y_OFF]) >> SCALEBITS); /* Cb */ - outptr1[col] = (JSAMPLE)((ctab[r + R_CB_OFF] + ctab[g + G_CB_OFF] + - ctab[b + B_CB_OFF]) >> SCALEBITS); + outptr1[col] = (_JSAMPLE)((ctab[r + R_CB_OFF] + ctab[g + G_CB_OFF] + + ctab[b + B_CB_OFF]) >> SCALEBITS); /* Cr */ - outptr2[col] = (JSAMPLE)((ctab[r + R_CR_OFF] + ctab[g + G_CR_OFF] + - ctab[b + B_CR_OFF]) >> SCALEBITS); + outptr2[col] = (_JSAMPLE)((ctab[r + R_CR_OFF] + ctab[g + G_CR_OFF] + + ctab[b + B_CR_OFF]) >> SCALEBITS); } } +#else + ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); +#endif } @@ -435,11 +448,11 @@ cmyk_ycck_convert(j_compress_ptr cinfo, JSAMPARRAY input_buf, */ METHODDEF(void) -grayscale_convert(j_compress_ptr cinfo, JSAMPARRAY input_buf, - JSAMPIMAGE output_buf, JDIMENSION output_row, int num_rows) +grayscale_convert(j_compress_ptr cinfo, _JSAMPARRAY input_buf, + _JSAMPIMAGE output_buf, JDIMENSION output_row, int num_rows) { - register JSAMPROW inptr; - register JSAMPROW outptr; + register _JSAMPROW inptr; + register _JSAMPROW outptr; register JDIMENSION col; JDIMENSION num_cols = cinfo->image_width; int instride = cinfo->input_components; @@ -463,11 +476,11 @@ grayscale_convert(j_compress_ptr cinfo, JSAMPARRAY input_buf, */ METHODDEF(void) -null_convert(j_compress_ptr cinfo, JSAMPARRAY input_buf, JSAMPIMAGE output_buf, - JDIMENSION output_row, int num_rows) +null_convert(j_compress_ptr cinfo, _JSAMPARRAY input_buf, + _JSAMPIMAGE output_buf, JDIMENSION output_row, int num_rows) { - register JSAMPROW inptr; - register JSAMPROW outptr, outptr0, outptr1, outptr2, outptr3; + register _JSAMPROW inptr; + register _JSAMPROW outptr, outptr0, outptr1, outptr2, outptr3; register JDIMENSION col; register int ci; int nc = cinfo->num_components; @@ -535,10 +548,13 @@ null_method(j_compress_ptr cinfo) */ GLOBAL(void) -jinit_color_converter(j_compress_ptr cinfo) +_jinit_color_converter(j_compress_ptr cinfo) { my_cconvert_ptr cconvert; + if (cinfo->data_precision != BITS_IN_JSAMPLE) + ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision); + cconvert = (my_cconvert_ptr) (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE, sizeof(my_color_converter)); @@ -585,123 +601,116 @@ jinit_color_converter(j_compress_ptr cinfo) break; } - /* Check num_components, set conversion method based on requested space */ + /* Check num_components, set conversion method based on requested space. + * NOTE: We do not allow any lossy color conversion algorithms in lossless + * mode. + */ switch (cinfo->jpeg_color_space) { case JCS_GRAYSCALE: + if (cinfo->master->lossless && + cinfo->in_color_space != cinfo->jpeg_color_space) + ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); if (cinfo->num_components != 1) ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); if (cinfo->in_color_space == JCS_GRAYSCALE) - cconvert->pub.color_convert = grayscale_convert; - else if (cinfo->in_color_space == JCS_RGB || - cinfo->in_color_space == JCS_EXT_RGB || - cinfo->in_color_space == JCS_EXT_RGBX || - cinfo->in_color_space == JCS_EXT_BGR || - cinfo->in_color_space == JCS_EXT_BGRX || - cinfo->in_color_space == JCS_EXT_XBGR || - cinfo->in_color_space == JCS_EXT_XRGB || - cinfo->in_color_space == JCS_EXT_RGBA || - cinfo->in_color_space == JCS_EXT_BGRA || - cinfo->in_color_space == JCS_EXT_ABGR || - cinfo->in_color_space == JCS_EXT_ARGB) { + cconvert->pub._color_convert = grayscale_convert; + else if (IsExtRGB(cinfo->in_color_space)) { +#ifdef WITH_SIMD if (jsimd_can_rgb_gray()) - cconvert->pub.color_convert = jsimd_rgb_gray_convert; - else { + cconvert->pub._color_convert = jsimd_rgb_gray_convert; + else +#endif + { cconvert->pub.start_pass = rgb_ycc_start; - cconvert->pub.color_convert = rgb_gray_convert; + cconvert->pub._color_convert = rgb_gray_convert; } } else if (cinfo->in_color_space == JCS_YCbCr) - cconvert->pub.color_convert = grayscale_convert; + cconvert->pub._color_convert = grayscale_convert; else ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); break; case JCS_RGB: + if (cinfo->master->lossless && !IsExtRGB(cinfo->in_color_space)) + ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); if (cinfo->num_components != 3) ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); if (rgb_red[cinfo->in_color_space] == 0 && rgb_green[cinfo->in_color_space] == 1 && rgb_blue[cinfo->in_color_space] == 2 && rgb_pixelsize[cinfo->in_color_space] == 3) { -#if defined(__mips__) +#if defined(WITH_SIMD) && defined(__mips__) if (jsimd_c_can_null_convert()) - cconvert->pub.color_convert = jsimd_c_null_convert; + cconvert->pub._color_convert = jsimd_c_null_convert; else #endif - cconvert->pub.color_convert = null_convert; - } else if (cinfo->in_color_space == JCS_RGB || - cinfo->in_color_space == JCS_EXT_RGB || - cinfo->in_color_space == JCS_EXT_RGBX || - cinfo->in_color_space == JCS_EXT_BGR || - cinfo->in_color_space == JCS_EXT_BGRX || - cinfo->in_color_space == JCS_EXT_XBGR || - cinfo->in_color_space == JCS_EXT_XRGB || - cinfo->in_color_space == JCS_EXT_RGBA || - cinfo->in_color_space == JCS_EXT_BGRA || - cinfo->in_color_space == JCS_EXT_ABGR || - cinfo->in_color_space == JCS_EXT_ARGB) - cconvert->pub.color_convert = rgb_rgb_convert; + cconvert->pub._color_convert = null_convert; + } else if (IsExtRGB(cinfo->in_color_space)) + cconvert->pub._color_convert = rgb_rgb_convert; else ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); break; case JCS_YCbCr: + if (cinfo->master->lossless && + cinfo->in_color_space != cinfo->jpeg_color_space) + ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); if (cinfo->num_components != 3) ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); - if (cinfo->in_color_space == JCS_RGB || - cinfo->in_color_space == JCS_EXT_RGB || - cinfo->in_color_space == JCS_EXT_RGBX || - cinfo->in_color_space == JCS_EXT_BGR || - cinfo->in_color_space == JCS_EXT_BGRX || - cinfo->in_color_space == JCS_EXT_XBGR || - cinfo->in_color_space == JCS_EXT_XRGB || - cinfo->in_color_space == JCS_EXT_RGBA || - cinfo->in_color_space == JCS_EXT_BGRA || - cinfo->in_color_space == JCS_EXT_ABGR || - cinfo->in_color_space == JCS_EXT_ARGB) { + if (IsExtRGB(cinfo->in_color_space)) { +#ifdef WITH_SIMD if (jsimd_can_rgb_ycc()) - cconvert->pub.color_convert = jsimd_rgb_ycc_convert; - else { - cconvert->pub.start_pass = rgb_ycc_start; - cconvert->pub.color_convert = rgb_ycc_convert; - } - } else if (cinfo->in_color_space == JCS_YCbCr) { -#if defined(__mips__) - if (jsimd_c_can_null_convert()) - cconvert->pub.color_convert = jsimd_c_null_convert; + cconvert->pub._color_convert = jsimd_rgb_ycc_convert; else #endif - cconvert->pub.color_convert = null_convert; + { + cconvert->pub.start_pass = rgb_ycc_start; + cconvert->pub._color_convert = rgb_ycc_convert; + } + } else if (cinfo->in_color_space == JCS_YCbCr) { +#if defined(WITH_SIMD) && defined(__mips__) + if (jsimd_c_can_null_convert()) + cconvert->pub._color_convert = jsimd_c_null_convert; + else +#endif + cconvert->pub._color_convert = null_convert; } else ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); break; case JCS_CMYK: + if (cinfo->master->lossless && + cinfo->in_color_space != cinfo->jpeg_color_space) + ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); if (cinfo->num_components != 4) ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); if (cinfo->in_color_space == JCS_CMYK) { -#if defined(__mips__) +#if defined(WITH_SIMD) && defined(__mips__) if (jsimd_c_can_null_convert()) - cconvert->pub.color_convert = jsimd_c_null_convert; + cconvert->pub._color_convert = jsimd_c_null_convert; else #endif - cconvert->pub.color_convert = null_convert; + cconvert->pub._color_convert = null_convert; } else ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); break; case JCS_YCCK: + if (cinfo->master->lossless && + cinfo->in_color_space != cinfo->jpeg_color_space) + ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); if (cinfo->num_components != 4) ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); if (cinfo->in_color_space == JCS_CMYK) { cconvert->pub.start_pass = rgb_ycc_start; - cconvert->pub.color_convert = cmyk_ycck_convert; + cconvert->pub._color_convert = cmyk_ycck_convert; } else if (cinfo->in_color_space == JCS_YCCK) { -#if defined(__mips__) +#if defined(WITH_SIMD) && defined(__mips__) if (jsimd_c_can_null_convert()) - cconvert->pub.color_convert = jsimd_c_null_convert; + cconvert->pub._color_convert = jsimd_c_null_convert; else #endif - cconvert->pub.color_convert = null_convert; + cconvert->pub._color_convert = null_convert; } else ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); break; @@ -710,12 +719,14 @@ jinit_color_converter(j_compress_ptr cinfo) if (cinfo->jpeg_color_space != cinfo->in_color_space || cinfo->num_components != cinfo->input_components) ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); -#if defined(__mips__) +#if defined(WITH_SIMD) && defined(__mips__) if (jsimd_c_can_null_convert()) - cconvert->pub.color_convert = jsimd_c_null_convert; + cconvert->pub._color_convert = jsimd_c_null_convert; else #endif - cconvert->pub.color_convert = null_convert; + cconvert->pub._color_convert = null_convert; break; } } + +#endif /* BITS_IN_JSAMPLE != 16 || defined(C_LOSSLESS_SUPPORTED) */ diff --git a/src/3rdparty/libjpeg/src/jcdctmgr.c b/src/3rdparty/libjpeg/src/jcdctmgr.c index 7dae17a6e14..7191ee73169 100644 --- a/src/3rdparty/libjpeg/src/jcdctmgr.c +++ b/src/3rdparty/libjpeg/src/jcdctmgr.c @@ -6,7 +6,7 @@ * libjpeg-turbo Modifications: * Copyright (C) 1999-2006, MIYASAKA Masaru. * Copyright 2009 Pierre Ossman for Cendio AB - * Copyright (C) 2011, 2014-2015, D. R. Commander. + * Copyright (C) 2011, 2014-2015, 2022, D. R. Commander. * For conditions of distribution and use, see the accompanying README.ijg * file. * @@ -28,10 +28,10 @@ typedef void (*forward_DCT_method_ptr) (DCTELEM *data); typedef void (*float_DCT_method_ptr) (FAST_FLOAT *data); -typedef void (*convsamp_method_ptr) (JSAMPARRAY sample_data, +typedef void (*convsamp_method_ptr) (_JSAMPARRAY sample_data, JDIMENSION start_col, DCTELEM *workspace); -typedef void (*float_convsamp_method_ptr) (JSAMPARRAY sample_data, +typedef void (*float_convsamp_method_ptr) (_JSAMPARRAY sample_data, JDIMENSION start_col, FAST_FLOAT *workspace); @@ -265,9 +265,13 @@ start_pass_fdctmgr(j_compress_ptr cinfo) dtbl = fdct->divisors[qtblno]; for (i = 0; i < DCTSIZE2; i++) { #if BITS_IN_JSAMPLE == 8 +#ifdef WITH_SIMD if (!compute_reciprocal(qtbl->quantval[i] << 3, &dtbl[i]) && fdct->quantize == jsimd_quantize) fdct->quantize = quantize; +#else + compute_reciprocal(qtbl->quantval[i] << 3, &dtbl[i]); +#endif #else dtbl[i] = ((DCTELEM)qtbl->quantval[i]) << 3; #endif @@ -305,12 +309,19 @@ start_pass_fdctmgr(j_compress_ptr cinfo) dtbl = fdct->divisors[qtblno]; for (i = 0; i < DCTSIZE2; i++) { #if BITS_IN_JSAMPLE == 8 +#ifdef WITH_SIMD if (!compute_reciprocal( DESCALE(MULTIPLY16V16((JLONG)qtbl->quantval[i], (JLONG)aanscales[i]), CONST_BITS - 3), &dtbl[i]) && fdct->quantize == jsimd_quantize) fdct->quantize = quantize; +#else + compute_reciprocal( + DESCALE(MULTIPLY16V16((JLONG)qtbl->quantval[i], + (JLONG)aanscales[i]), + CONST_BITS-3), &dtbl[i]); +#endif #else dtbl[i] = (DCTELEM) DESCALE(MULTIPLY16V16((JLONG)qtbl->quantval[i], @@ -370,10 +381,10 @@ start_pass_fdctmgr(j_compress_ptr cinfo) */ METHODDEF(void) -convsamp(JSAMPARRAY sample_data, JDIMENSION start_col, DCTELEM *workspace) +convsamp(_JSAMPARRAY sample_data, JDIMENSION start_col, DCTELEM *workspace) { register DCTELEM *workspaceptr; - register JSAMPROW elemptr; + register _JSAMPROW elemptr; register int elemr; workspaceptr = workspace; @@ -381,19 +392,19 @@ convsamp(JSAMPARRAY sample_data, JDIMENSION start_col, DCTELEM *workspace) elemptr = sample_data[elemr] + start_col; #if DCTSIZE == 8 /* unroll the inner loop */ - *workspaceptr++ = (*elemptr++) - CENTERJSAMPLE; - *workspaceptr++ = (*elemptr++) - CENTERJSAMPLE; - *workspaceptr++ = (*elemptr++) - CENTERJSAMPLE; - *workspaceptr++ = (*elemptr++) - CENTERJSAMPLE; - *workspaceptr++ = (*elemptr++) - CENTERJSAMPLE; - *workspaceptr++ = (*elemptr++) - CENTERJSAMPLE; - *workspaceptr++ = (*elemptr++) - CENTERJSAMPLE; - *workspaceptr++ = (*elemptr++) - CENTERJSAMPLE; + *workspaceptr++ = (*elemptr++) - _CENTERJSAMPLE; + *workspaceptr++ = (*elemptr++) - _CENTERJSAMPLE; + *workspaceptr++ = (*elemptr++) - _CENTERJSAMPLE; + *workspaceptr++ = (*elemptr++) - _CENTERJSAMPLE; + *workspaceptr++ = (*elemptr++) - _CENTERJSAMPLE; + *workspaceptr++ = (*elemptr++) - _CENTERJSAMPLE; + *workspaceptr++ = (*elemptr++) - _CENTERJSAMPLE; + *workspaceptr++ = (*elemptr++) - _CENTERJSAMPLE; #else { register int elemc; for (elemc = DCTSIZE; elemc > 0; elemc--) - *workspaceptr++ = (*elemptr++) - CENTERJSAMPLE; + *workspaceptr++ = (*elemptr++) - _CENTERJSAMPLE; } #endif } @@ -488,7 +499,7 @@ quantize(JCOEFPTR coef_block, DCTELEM *divisors, DCTELEM *workspace) METHODDEF(void) forward_DCT(j_compress_ptr cinfo, jpeg_component_info *compptr, - JSAMPARRAY sample_data, JBLOCKROW coef_blocks, + _JSAMPARRAY sample_data, JBLOCKROW coef_blocks, JDIMENSION start_row, JDIMENSION start_col, JDIMENSION num_blocks) /* This version is used for integer DCT implementations. */ { @@ -522,30 +533,30 @@ forward_DCT(j_compress_ptr cinfo, jpeg_component_info *compptr, #ifdef DCT_FLOAT_SUPPORTED METHODDEF(void) -convsamp_float(JSAMPARRAY sample_data, JDIMENSION start_col, +convsamp_float(_JSAMPARRAY sample_data, JDIMENSION start_col, FAST_FLOAT *workspace) { register FAST_FLOAT *workspaceptr; - register JSAMPROW elemptr; + register _JSAMPROW elemptr; register int elemr; workspaceptr = workspace; for (elemr = 0; elemr < DCTSIZE; elemr++) { elemptr = sample_data[elemr] + start_col; #if DCTSIZE == 8 /* unroll the inner loop */ - *workspaceptr++ = (FAST_FLOAT)((*elemptr++) - CENTERJSAMPLE); - *workspaceptr++ = (FAST_FLOAT)((*elemptr++) - CENTERJSAMPLE); - *workspaceptr++ = (FAST_FLOAT)((*elemptr++) - CENTERJSAMPLE); - *workspaceptr++ = (FAST_FLOAT)((*elemptr++) - CENTERJSAMPLE); - *workspaceptr++ = (FAST_FLOAT)((*elemptr++) - CENTERJSAMPLE); - *workspaceptr++ = (FAST_FLOAT)((*elemptr++) - CENTERJSAMPLE); - *workspaceptr++ = (FAST_FLOAT)((*elemptr++) - CENTERJSAMPLE); - *workspaceptr++ = (FAST_FLOAT)((*elemptr++) - CENTERJSAMPLE); + *workspaceptr++ = (FAST_FLOAT)((*elemptr++) - _CENTERJSAMPLE); + *workspaceptr++ = (FAST_FLOAT)((*elemptr++) - _CENTERJSAMPLE); + *workspaceptr++ = (FAST_FLOAT)((*elemptr++) - _CENTERJSAMPLE); + *workspaceptr++ = (FAST_FLOAT)((*elemptr++) - _CENTERJSAMPLE); + *workspaceptr++ = (FAST_FLOAT)((*elemptr++) - _CENTERJSAMPLE); + *workspaceptr++ = (FAST_FLOAT)((*elemptr++) - _CENTERJSAMPLE); + *workspaceptr++ = (FAST_FLOAT)((*elemptr++) - _CENTERJSAMPLE); + *workspaceptr++ = (FAST_FLOAT)((*elemptr++) - _CENTERJSAMPLE); #else { register int elemc; for (elemc = DCTSIZE; elemc > 0; elemc--) - *workspaceptr++ = (FAST_FLOAT)((*elemptr++) - CENTERJSAMPLE); + *workspaceptr++ = (FAST_FLOAT)((*elemptr++) - _CENTERJSAMPLE); } #endif } @@ -577,7 +588,7 @@ quantize_float(JCOEFPTR coef_block, FAST_FLOAT *divisors, METHODDEF(void) forward_DCT_float(j_compress_ptr cinfo, jpeg_component_info *compptr, - JSAMPARRAY sample_data, JBLOCKROW coef_blocks, + _JSAMPARRAY sample_data, JBLOCKROW coef_blocks, JDIMENSION start_row, JDIMENSION start_col, JDIMENSION num_blocks) /* This version is used for floating-point DCT implementations. */ @@ -617,11 +628,14 @@ forward_DCT_float(j_compress_ptr cinfo, jpeg_component_info *compptr, */ GLOBAL(void) -jinit_forward_dct(j_compress_ptr cinfo) +_jinit_forward_dct(j_compress_ptr cinfo) { my_fdct_ptr fdct; int i; + if (cinfo->data_precision != BITS_IN_JSAMPLE) + ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision); + fdct = (my_fdct_ptr) (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE, sizeof(my_fdct_controller)); @@ -632,28 +646,34 @@ jinit_forward_dct(j_compress_ptr cinfo) switch (cinfo->dct_method) { #ifdef DCT_ISLOW_SUPPORTED case JDCT_ISLOW: - fdct->pub.forward_DCT = forward_DCT; + fdct->pub._forward_DCT = forward_DCT; +#ifdef WITH_SIMD if (jsimd_can_fdct_islow()) fdct->dct = jsimd_fdct_islow; else - fdct->dct = jpeg_fdct_islow; +#endif + fdct->dct = _jpeg_fdct_islow; break; #endif #ifdef DCT_IFAST_SUPPORTED case JDCT_IFAST: - fdct->pub.forward_DCT = forward_DCT; + fdct->pub._forward_DCT = forward_DCT; +#ifdef WITH_SIMD if (jsimd_can_fdct_ifast()) fdct->dct = jsimd_fdct_ifast; else - fdct->dct = jpeg_fdct_ifast; +#endif + fdct->dct = _jpeg_fdct_ifast; break; #endif #ifdef DCT_FLOAT_SUPPORTED case JDCT_FLOAT: - fdct->pub.forward_DCT = forward_DCT_float; + fdct->pub._forward_DCT = forward_DCT_float; +#ifdef WITH_SIMD if (jsimd_can_fdct_float()) fdct->float_dct = jsimd_fdct_float; else +#endif fdct->float_dct = jpeg_fdct_float; break; #endif @@ -671,25 +691,33 @@ jinit_forward_dct(j_compress_ptr cinfo) case JDCT_IFAST: #endif #if defined(DCT_ISLOW_SUPPORTED) || defined(DCT_IFAST_SUPPORTED) +#ifdef WITH_SIMD if (jsimd_can_convsamp()) fdct->convsamp = jsimd_convsamp; else +#endif fdct->convsamp = convsamp; +#ifdef WITH_SIMD if (jsimd_can_quantize()) fdct->quantize = jsimd_quantize; else +#endif fdct->quantize = quantize; break; #endif #ifdef DCT_FLOAT_SUPPORTED case JDCT_FLOAT: +#ifdef WITH_SIMD if (jsimd_can_convsamp_float()) fdct->float_convsamp = jsimd_convsamp_float; else +#endif fdct->float_convsamp = convsamp_float; +#ifdef WITH_SIMD if (jsimd_can_quantize_float()) fdct->float_quantize = jsimd_quantize_float; else +#endif fdct->float_quantize = quantize_float; break; #endif diff --git a/src/3rdparty/libjpeg/src/jcdiffct.c b/src/3rdparty/libjpeg/src/jcdiffct.c new file mode 100644 index 00000000000..0bae0689191 --- /dev/null +++ b/src/3rdparty/libjpeg/src/jcdiffct.c @@ -0,0 +1,411 @@ +/* + * jcdiffct.c + * + * This file was part of the Independent JPEG Group's software: + * Copyright (C) 1994-1997, Thomas G. Lane. + * Lossless JPEG Modifications: + * Copyright (C) 1999, Ken Murchison. + * libjpeg-turbo Modifications: + * Copyright (C) 2022, D. R. Commander. + * For conditions of distribution and use, see the accompanying README.ijg + * file. + * + * This file contains the difference buffer controller for compression. + * This controller is the top level of the lossless JPEG compressor proper. + * The difference buffer lies between the prediction/differencing and entropy + * encoding steps. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" +#include "jlossls.h" /* Private declarations for lossless codec */ + + +#ifdef C_LOSSLESS_SUPPORTED + +/* We use a full-image sample buffer when doing Huffman optimization, + * and also for writing multiple-scan JPEG files. In all cases, the + * full-image buffer is filled during the first pass, and the scaling, + * prediction and differencing steps are run during subsequent passes. + */ +#ifdef ENTROPY_OPT_SUPPORTED +#define FULL_SAMP_BUFFER_SUPPORTED +#else +#ifdef C_MULTISCAN_FILES_SUPPORTED +#define FULL_SAMP_BUFFER_SUPPORTED +#endif +#endif + + +/* Private buffer controller object */ + +typedef struct { + struct jpeg_c_coef_controller pub; /* public fields */ + + JDIMENSION iMCU_row_num; /* iMCU row # within image */ + JDIMENSION mcu_ctr; /* counts MCUs processed in current row */ + int MCU_vert_offset; /* counts MCU rows within iMCU row */ + int MCU_rows_per_iMCU_row; /* number of such rows needed */ + + _JSAMPROW cur_row[MAX_COMPONENTS]; /* row of point-transformed samples */ + _JSAMPROW prev_row[MAX_COMPONENTS]; /* previous row of Pt'd samples */ + JDIFFARRAY diff_buf[MAX_COMPONENTS]; /* iMCU row of differences */ + + /* In multi-pass modes, we need a virtual sample array for each component. */ + jvirt_sarray_ptr whole_image[MAX_COMPONENTS]; +} my_diff_controller; + +typedef my_diff_controller *my_diff_ptr; + + +/* Forward declarations */ +METHODDEF(boolean) compress_data(j_compress_ptr cinfo, _JSAMPIMAGE input_buf); +#ifdef FULL_SAMP_BUFFER_SUPPORTED +METHODDEF(boolean) compress_first_pass(j_compress_ptr cinfo, + _JSAMPIMAGE input_buf); +METHODDEF(boolean) compress_output(j_compress_ptr cinfo, + _JSAMPIMAGE input_buf); +#endif + + +LOCAL(void) +start_iMCU_row(j_compress_ptr cinfo) +/* Reset within-iMCU-row counters for a new row */ +{ + my_diff_ptr diff = (my_diff_ptr)cinfo->coef; + + /* In an interleaved scan, an MCU row is the same as an iMCU row. + * In a noninterleaved scan, an iMCU row has v_samp_factor MCU rows. + * But at the bottom of the image, process only what's left. + */ + if (cinfo->comps_in_scan > 1) { + diff->MCU_rows_per_iMCU_row = 1; + } else { + if (diff->iMCU_row_num < (cinfo->total_iMCU_rows-1)) + diff->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->v_samp_factor; + else + diff->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->last_row_height; + } + + diff->mcu_ctr = 0; + diff->MCU_vert_offset = 0; +} + + +/* + * Initialize for a processing pass. + */ + +METHODDEF(void) +start_pass_diff(j_compress_ptr cinfo, J_BUF_MODE pass_mode) +{ + my_diff_ptr diff = (my_diff_ptr)cinfo->coef; + + /* Because it is hitching a ride on the jpeg_forward_dct struct, + * start_pass_lossless() will be called at the start of the initial pass. + * This ensures that it will be called at the start of the Huffman + * optimization and output passes as well. + */ + if (pass_mode == JBUF_CRANK_DEST) + (*cinfo->fdct->start_pass) (cinfo); + + diff->iMCU_row_num = 0; + start_iMCU_row(cinfo); + + switch (pass_mode) { + case JBUF_PASS_THRU: + if (diff->whole_image[0] != NULL) + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); + diff->pub._compress_data = compress_data; + break; +#ifdef FULL_SAMP_BUFFER_SUPPORTED + case JBUF_SAVE_AND_PASS: + if (diff->whole_image[0] == NULL) + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); + diff->pub._compress_data = compress_first_pass; + break; + case JBUF_CRANK_DEST: + if (diff->whole_image[0] == NULL) + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); + diff->pub._compress_data = compress_output; + break; +#endif + default: + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); + break; + } +} + + +#define SWAP_ROWS(rowa, rowb) { \ + _JSAMPROW temp = rowa; \ + rowa = rowb; rowb = temp; \ +} + +/* + * Process some data in the single-pass case. + * We process the equivalent of one fully interleaved MCU row ("iMCU" row) + * per call, ie, v_samp_factor rows for each component in the image. + * Returns TRUE if the iMCU row is completed, FALSE if suspended. + * + * NB: input_buf contains a plane for each component in image, + * which we index according to the component's SOF position. + */ + +METHODDEF(boolean) +compress_data(j_compress_ptr cinfo, _JSAMPIMAGE input_buf) +{ + my_diff_ptr diff = (my_diff_ptr)cinfo->coef; + lossless_comp_ptr losslessc = (lossless_comp_ptr)cinfo->fdct; + JDIMENSION MCU_col_num; /* index of current MCU within row */ + JDIMENSION MCU_count; /* number of MCUs encoded */ + JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1; + int ci, compi, yoffset, samp_row, samp_rows, samps_across; + jpeg_component_info *compptr; + + /* Loop to write as much as one whole iMCU row */ + for (yoffset = diff->MCU_vert_offset; yoffset < diff->MCU_rows_per_iMCU_row; + yoffset++) { + + MCU_col_num = diff->mcu_ctr; + + /* Scale and predict each scanline of the MCU row separately. + * + * Note: We only do this if we are at the start of an MCU row, ie, + * we don't want to reprocess a row suspended by the output. + */ + if (MCU_col_num == 0) { + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + compi = compptr->component_index; + if (diff->iMCU_row_num < last_iMCU_row) + samp_rows = compptr->v_samp_factor; + else { + /* NB: can't use last_row_height here, since may not be set! */ + samp_rows = + (int)(compptr->height_in_blocks % compptr->v_samp_factor); + if (samp_rows == 0) samp_rows = compptr->v_samp_factor; + else { + /* Fill dummy difference rows at the bottom edge with zeros, which + * will encode to the smallest amount of data. + */ + for (samp_row = samp_rows; samp_row < compptr->v_samp_factor; + samp_row++) + memset(diff->diff_buf[compi][samp_row], 0, + jround_up((long)compptr->width_in_blocks, + (long)compptr->h_samp_factor) * sizeof(JDIFF)); + } + } + samps_across = compptr->width_in_blocks; + + for (samp_row = 0; samp_row < samp_rows; samp_row++) { + (*losslessc->scaler_scale) (cinfo, + input_buf[compi][samp_row], + diff->cur_row[compi], + samps_across); + (*losslessc->predict_difference[compi]) + (cinfo, compi, diff->cur_row[compi], diff->prev_row[compi], + diff->diff_buf[compi][samp_row], samps_across); + SWAP_ROWS(diff->cur_row[compi], diff->prev_row[compi]); + } + } + } + /* Try to write the MCU row (or remaining portion of suspended MCU row). */ + MCU_count = + (*cinfo->entropy->encode_mcus) (cinfo, + diff->diff_buf, yoffset, MCU_col_num, + cinfo->MCUs_per_row - MCU_col_num); + if (MCU_count != cinfo->MCUs_per_row - MCU_col_num) { + /* Suspension forced; update state counters and exit */ + diff->MCU_vert_offset = yoffset; + diff->mcu_ctr += MCU_col_num; + return FALSE; + } + /* Completed an MCU row, but perhaps not an iMCU row */ + diff->mcu_ctr = 0; + } + /* Completed the iMCU row, advance counters for next one */ + diff->iMCU_row_num++; + start_iMCU_row(cinfo); + return TRUE; +} + + +#ifdef FULL_SAMP_BUFFER_SUPPORTED + +/* + * Process some data in the first pass of a multi-pass case. + * We process the equivalent of one fully interleaved MCU row ("iMCU" row) + * per call, ie, v_samp_factor rows for each component in the image. + * This amount of data is read from the source buffer and saved into the + * virtual arrays. + * + * We must also emit the data to the compressor. This is conveniently + * done by calling compress_output() after we've loaded the current strip + * of the virtual arrays. + * + * NB: input_buf contains a plane for each component in image. All components + * are loaded into the virtual arrays in this pass. However, it may be that + * only a subset of the components are emitted to the compressor during + * this first pass; be careful about looking at the scan-dependent variables + * (MCU dimensions, etc). + */ + +METHODDEF(boolean) +compress_first_pass(j_compress_ptr cinfo, _JSAMPIMAGE input_buf) +{ + my_diff_ptr diff = (my_diff_ptr)cinfo->coef; + JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1; + JDIMENSION samps_across; + int ci, samp_row, samp_rows; + _JSAMPARRAY buffer; + jpeg_component_info *compptr; + + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + /* Align the virtual buffer for this component. */ + buffer = (_JSAMPARRAY)(*cinfo->mem->access_virt_sarray) + ((j_common_ptr)cinfo, diff->whole_image[ci], + diff->iMCU_row_num * compptr->v_samp_factor, + (JDIMENSION)compptr->v_samp_factor, TRUE); + + /* Count non-dummy sample rows in this iMCU row. */ + if (diff->iMCU_row_num < last_iMCU_row) + samp_rows = compptr->v_samp_factor; + else { + /* NB: can't use last_row_height here, since may not be set! */ + samp_rows = (int)(compptr->height_in_blocks % compptr->v_samp_factor); + if (samp_rows == 0) samp_rows = compptr->v_samp_factor; + } + samps_across = compptr->width_in_blocks; + + /* Perform point transform scaling and prediction/differencing for all + * non-dummy rows in this iMCU row. Each call on these functions + * processes a complete row of samples. + */ + for (samp_row = 0; samp_row < samp_rows; samp_row++) { + memcpy(buffer[samp_row], input_buf[ci][samp_row], + samps_across * sizeof(_JSAMPLE)); + } + } + /* NB: compress_output will increment iMCU_row_num if successful. + * A suspension return will result in redoing all the work above next time. + */ + + /* Emit data to the compressor, sharing code with subsequent passes */ + return compress_output(cinfo, input_buf); +} + + +/* + * Process some data in subsequent passes of a multi-pass case. + * We process the equivalent of one fully interleaved MCU row ("iMCU" row) + * per call, ie, v_samp_factor rows for each component in the scan. + * The data is obtained from the virtual arrays and fed to the compressor. + * Returns TRUE if the iMCU row is completed, FALSE if suspended. + * + * NB: input_buf is ignored; it is likely to be a NULL pointer. + */ + +METHODDEF(boolean) +compress_output(j_compress_ptr cinfo, _JSAMPIMAGE input_buf) +{ + my_diff_ptr diff = (my_diff_ptr)cinfo->coef; + int ci, compi; + _JSAMPARRAY buffer[MAX_COMPS_IN_SCAN]; + jpeg_component_info *compptr; + + /* Align the virtual buffers for the components used in this scan. + * NB: during first pass, this is safe only because the buffers will + * already be aligned properly, so jmemmgr.c won't need to do any I/O. + */ + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + compi = compptr->component_index; + buffer[compi] = (_JSAMPARRAY)(*cinfo->mem->access_virt_sarray) + ((j_common_ptr)cinfo, diff->whole_image[compi], + diff->iMCU_row_num * compptr->v_samp_factor, + (JDIMENSION)compptr->v_samp_factor, FALSE); + } + + return compress_data(cinfo, buffer); +} + +#endif /* FULL_SAMP_BUFFER_SUPPORTED */ + + +/* + * Initialize difference buffer controller. + */ + +GLOBAL(void) +_jinit_c_diff_controller(j_compress_ptr cinfo, boolean need_full_buffer) +{ + my_diff_ptr diff; + int ci, row; + jpeg_component_info *compptr; + + diff = (my_diff_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE, + sizeof(my_diff_controller)); + cinfo->coef = (struct jpeg_c_coef_controller *)diff; + diff->pub.start_pass = start_pass_diff; + + /* Create the prediction row buffers. */ + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + diff->cur_row[ci] = *(_JSAMPARRAY)(*cinfo->mem->alloc_sarray) + ((j_common_ptr)cinfo, JPOOL_IMAGE, + (JDIMENSION)jround_up((long)compptr->width_in_blocks, + (long)compptr->h_samp_factor), + (JDIMENSION)1); + diff->prev_row[ci] = *(_JSAMPARRAY)(*cinfo->mem->alloc_sarray) + ((j_common_ptr)cinfo, JPOOL_IMAGE, + (JDIMENSION)jround_up((long)compptr->width_in_blocks, + (long)compptr->h_samp_factor), + (JDIMENSION)1); + } + + /* Create the difference buffer. */ + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + diff->diff_buf[ci] = + ALLOC_DARRAY(JPOOL_IMAGE, + (JDIMENSION)jround_up((long)compptr->width_in_blocks, + (long)compptr->h_samp_factor), + (JDIMENSION)compptr->v_samp_factor); + /* Prefill difference rows with zeros. We do this because only actual + * data is placed in the buffers during prediction/differencing, leaving + * any dummy differences at the right edge as zeros, which will encode + * to the smallest amount of data. + */ + for (row = 0; row < compptr->v_samp_factor; row++) + memset(diff->diff_buf[ci][row], 0, + jround_up((long)compptr->width_in_blocks, + (long)compptr->h_samp_factor) * sizeof(JDIFF)); + } + + /* Create the sample buffer. */ + if (need_full_buffer) { +#ifdef FULL_SAMP_BUFFER_SUPPORTED + /* Allocate a full-image virtual array for each component, */ + /* padded to a multiple of samp_factor differences in each direction. */ + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + diff->whole_image[ci] = (*cinfo->mem->request_virt_sarray) + ((j_common_ptr)cinfo, JPOOL_IMAGE, FALSE, + (JDIMENSION)jround_up((long)compptr->width_in_blocks, + (long)compptr->h_samp_factor), + (JDIMENSION)jround_up((long)compptr->height_in_blocks, + (long)compptr->v_samp_factor), + (JDIMENSION)compptr->v_samp_factor); + } +#else + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); +#endif + } else + diff->whole_image[0] = NULL; /* flag for no virtual arrays */ +} + +#endif /* C_LOSSLESS_SUPPORTED */ diff --git a/src/3rdparty/libjpeg/src/jchuff.c b/src/3rdparty/libjpeg/src/jchuff.c index 5d0276ad252..b879506d5cf 100644 --- a/src/3rdparty/libjpeg/src/jchuff.c +++ b/src/3rdparty/libjpeg/src/jchuff.c @@ -3,11 +3,14 @@ * * This file was part of the Independent JPEG Group's software: * Copyright (C) 1991-1997, Thomas G. Lane. + * Lossless JPEG Modifications: + * Copyright (C) 1999, Ken Murchison. * libjpeg-turbo Modifications: - * Copyright (C) 2009-2011, 2014-2016, 2018-2022, D. R. Commander. + * Copyright (C) 2009-2011, 2014-2016, 2018-2023, D. R. Commander. * Copyright (C) 2015, Matthieu Darbois. * Copyright (C) 2018, Matthias Räncker. * Copyright (C) 2020, Arm Limited. + * Copyright (C) 2022, Felix Hanau. * For conditions of distribution and use, see the accompanying README.ijg * file. * @@ -26,7 +29,11 @@ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" +#ifdef WITH_SIMD #include "jsimd.h" +#else +#include "jchuff.h" /* Declarations shared with jc*huff.c */ +#endif #include /* @@ -179,7 +186,9 @@ start_pass_huff(j_compress_ptr cinfo, boolean gather_statistics) entropy->pub.finish_pass = finish_pass_huff; } +#ifdef WITH_SIMD entropy->simd = jsimd_can_huff_encode_one_block(); +#endif for (ci = 0; ci < cinfo->comps_in_scan; ci++) { compptr = cinfo->cur_comp_info[ci]; @@ -219,6 +228,7 @@ start_pass_huff(j_compress_ptr cinfo, boolean gather_statistics) } /* Initialize bit buffer to empty */ +#ifdef WITH_SIMD if (entropy->simd) { entropy->saved.put_buffer.simd = 0; #if defined(__aarch64__) && !defined(NEON_INTRINSICS) @@ -226,7 +236,9 @@ start_pass_huff(j_compress_ptr cinfo, boolean gather_statistics) #else entropy->saved.free_bits = SIMD_BIT_BUF_SIZE; #endif - } else { + } else +#endif + { entropy->saved.put_buffer.c = 0; entropy->saved.free_bits = BIT_BUF_SIZE; } @@ -241,7 +253,7 @@ start_pass_huff(j_compress_ptr cinfo, boolean gather_statistics) * Compute the derived values for a Huffman table. * This routine also performs some validation checks on the table. * - * Note this is also used by jcphuff.c. + * Note this is also used by jcphuff.c and jclhuff.c. */ GLOBAL(void) @@ -317,12 +329,12 @@ jpeg_make_c_derived_tbl(j_compress_ptr cinfo, boolean isDC, int tblno, memset(dtbl->ehufco, 0, sizeof(dtbl->ehufco)); memset(dtbl->ehufsi, 0, sizeof(dtbl->ehufsi)); - /* This is also a convenient place to check for out-of-range - * and duplicated VAL entries. We allow 0..255 for AC symbols - * but only 0..15 for DC. (We could constrain them further - * based on data depth and mode, but this seems enough.) + /* This is also a convenient place to check for out-of-range and duplicated + * VAL entries. We allow 0..255 for AC symbols but only 0..15 for DC in + * lossy mode and 0..16 for DC in lossless mode. (We could constrain them + * further based on data depth and mode, but this seems enough.) */ - maxsymbol = isDC ? 15 : 255; + maxsymbol = isDC ? (cinfo->master->lossless ? 16 : 15) : 255; for (p = 0; p < lastp; p++) { i = htbl->huffval[p]; @@ -541,6 +553,8 @@ flush_bits(working_state *state) } +#ifdef WITH_SIMD + /* Encode a single block's worth of coefficients */ LOCAL(boolean) @@ -560,6 +574,8 @@ encode_one_block_simd(working_state *state, JCOEFPTR block, int last_dc_val, return TRUE; } +#endif + LOCAL(boolean) encode_one_block(working_state *state, JCOEFPTR block, int last_dc_val, c_derived_tbl *dctbl, c_derived_tbl *actbl) @@ -568,6 +584,7 @@ encode_one_block(working_state *state, JCOEFPTR block, int last_dc_val, bit_buf_type put_buffer; JOCTET _buffer[BUFSIZE], *buffer; int localbuf = 0; + int max_coef_bits = state->cinfo->data_precision + 2; free_bits = state->cur.free_bits; put_buffer = state->cur.put_buffer.c; @@ -588,6 +605,11 @@ encode_one_block(working_state *state, JCOEFPTR block, int last_dc_val, /* Find the number of bits needed for the magnitude of the coefficient */ nbits = JPEG_NBITS(nbits); + /* Check for out-of-range coefficient values. + * Since we're encoding a difference, the range limit is twice as much. + */ + if (nbits > max_coef_bits + 1) + ERREXIT(state->cinfo, JERR_BAD_DCT_COEF); /* Emit the Huffman-coded symbol for the number of bits. * Emit that number of bits of the value, if positive, @@ -613,6 +635,9 @@ encode_one_block(working_state *state, JCOEFPTR block, int last_dc_val, temp += nbits; \ nbits ^= temp; \ nbits = JPEG_NBITS_NONZERO(nbits); \ + /* Check for out-of-range coefficient values */ \ + if (nbits > max_coef_bits) \ + ERREXIT(state->cinfo, JERR_BAD_DCT_COEF); \ /* if run length > 15, must emit special run-length-16 codes (0xF0) */ \ while (r >= 16 * 16) { \ r -= 16 * 16; \ @@ -704,6 +729,7 @@ encode_mcu_huff(j_compress_ptr cinfo, JBLOCKROW *MCU_data) } /* Encode the MCU data blocks */ +#ifdef WITH_SIMD if (entropy->simd) { for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { ci = cinfo->MCU_membership[blkn]; @@ -716,7 +742,9 @@ encode_mcu_huff(j_compress_ptr cinfo, JBLOCKROW *MCU_data) /* Update last_dc_val */ state.cur.last_dc_val[ci] = MCU_data[blkn][0][0]; } - } else { + } else +#endif + { for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { ci = cinfo->MCU_membership[blkn]; compptr = cinfo->cur_comp_info[ci]; @@ -800,6 +828,7 @@ htest_one_block(j_compress_ptr cinfo, JCOEFPTR block, int last_dc_val, register int temp; register int nbits; register int k, r; + int max_coef_bits = cinfo->data_precision + 2; /* Encode the DC coefficient difference per section F.1.2.1 */ @@ -816,7 +845,7 @@ htest_one_block(j_compress_ptr cinfo, JCOEFPTR block, int last_dc_val, /* Check for out-of-range coefficient values. * Since we're encoding a difference, the range limit is twice as much. */ - if (nbits > MAX_COEF_BITS + 1) + if (nbits > max_coef_bits + 1) ERREXIT(cinfo, JERR_BAD_DCT_COEF); /* Count the Huffman symbol for the number of bits */ @@ -845,7 +874,7 @@ htest_one_block(j_compress_ptr cinfo, JCOEFPTR block, int last_dc_val, while ((temp >>= 1)) nbits++; /* Check for out-of-range coefficient values */ - if (nbits > MAX_COEF_BITS) + if (nbits > max_coef_bits) ERREXIT(cinfo, JERR_BAD_DCT_COEF); /* Count Huffman symbol for run length / number of bits */ @@ -900,7 +929,7 @@ encode_mcu_gather(j_compress_ptr cinfo, JBLOCKROW *MCU_data) /* * Generate the best Huffman code table for the given counts, fill htbl. - * Note this is also used by jcphuff.c. + * Note this is also used by jcphuff.c and jclhuff.c. * * The JPEG standard requires that no symbol be assigned a codeword of all * one bits (so that padding bits added at the end of a compressed segment @@ -932,11 +961,15 @@ jpeg_gen_optimal_table(j_compress_ptr cinfo, JHUFF_TBL *htbl, long freq[]) { #define MAX_CLEN 32 /* assumed maximum initial code length */ UINT8 bits[MAX_CLEN + 1]; /* bits[k] = # of symbols with code length k */ + int bit_pos[MAX_CLEN + 1]; /* # of symbols with smaller code length */ int codesize[257]; /* codesize[k] = code length of symbol k */ + int nz_index[257]; /* index of nonzero symbol in the original freq + array */ int others[257]; /* next symbol in current branch of tree */ int c1, c2; int p, i, j; - long v; + int num_nz_symbols; + long v, v2; /* This algorithm is explained in section K.2 of the JPEG standard */ @@ -951,28 +984,41 @@ jpeg_gen_optimal_table(j_compress_ptr cinfo, JHUFF_TBL *htbl, long freq[]) * will be placed last in the largest codeword category. */ + /* Group nonzero frequencies together so we can more easily find the + * smallest. + */ + num_nz_symbols = 0; + for (i = 0; i < 257; i++) { + if (freq[i]) { + nz_index[num_nz_symbols] = i; + freq[num_nz_symbols] = freq[i]; + num_nz_symbols++; + } + } + /* Huffman's basic algorithm to assign optimal code lengths to symbols */ for (;;) { - /* Find the smallest nonzero frequency, set c1 = its symbol */ - /* In case of ties, take the larger symbol number */ + /* Find the two smallest nonzero frequencies; set c1, c2 = their symbols */ + /* In case of ties, take the larger symbol number. Since we have grouped + * the nonzero symbols together, checking for zero symbols is not + * necessary. + */ c1 = -1; - v = 1000000000L; - for (i = 0; i <= 256; i++) { - if (freq[i] && freq[i] <= v) { - v = freq[i]; - c1 = i; - } - } - - /* Find the next smallest nonzero frequency, set c2 = its symbol */ - /* In case of ties, take the larger symbol number */ c2 = -1; v = 1000000000L; - for (i = 0; i <= 256; i++) { - if (freq[i] && freq[i] <= v && i != c1) { - v = freq[i]; - c2 = i; + v2 = 1000000000L; + for (i = 0; i < num_nz_symbols; i++) { + if (freq[i] <= v2) { + if (freq[i] <= v) { + c2 = c1; + v2 = v; + v = freq[i]; + c1 = i; + } else { + v2 = freq[i]; + c2 = i; + } } } @@ -982,7 +1028,10 @@ jpeg_gen_optimal_table(j_compress_ptr cinfo, JHUFF_TBL *htbl, long freq[]) /* Else merge the two counts/trees */ freq[c1] += freq[c2]; - freq[c2] = 0; + /* Set the frequency to a very high value instead of zero, so we don't have + * to check for zero values. + */ + freq[c2] = 1000000001L; /* Increment the codesize of everything in c1's tree branch */ codesize[c1]++; @@ -1002,15 +1051,24 @@ jpeg_gen_optimal_table(j_compress_ptr cinfo, JHUFF_TBL *htbl, long freq[]) } /* Now count the number of symbols of each code length */ - for (i = 0; i <= 256; i++) { - if (codesize[i]) { - /* The JPEG standard seems to think that this can't happen, */ - /* but I'm paranoid... */ - if (codesize[i] > MAX_CLEN) - ERREXIT(cinfo, JERR_HUFF_CLEN_OVERFLOW); + for (i = 0; i < num_nz_symbols; i++) { + /* The JPEG standard seems to think that this can't happen, */ + /* but I'm paranoid... */ + if (codesize[i] > MAX_CLEN) + ERREXIT(cinfo, JERR_HUFF_CLEN_OVERFLOW); - bits[codesize[i]]++; - } + bits[codesize[i]]++; + } + + /* Count the number of symbols with a length smaller than i bits, so we can + * construct the symbol table more efficiently. Note that this includes the + * pseudo-symbol 256, but since it is the last symbol, it will not affect the + * table. + */ + p = 0; + for (i = 1; i <= MAX_CLEN; i++) { + bit_pos[i] = p; + p += bits[i]; } /* JPEG doesn't allow symbols with code lengths over 16 bits, so if the pure @@ -1050,14 +1108,9 @@ jpeg_gen_optimal_table(j_compress_ptr cinfo, JHUFF_TBL *htbl, long freq[]) * changes made above, but Rec. ITU-T T.81 | ISO/IEC 10918-1 seems to think * this works. */ - p = 0; - for (i = 1; i <= MAX_CLEN; i++) { - for (j = 0; j <= 255; j++) { - if (codesize[j] == i) { - htbl->huffval[p] = (UINT8)j; - p++; - } - } + for (i = 0; i < num_nz_symbols - 1; i++) { + htbl->huffval[bit_pos[codesize[i]]] = (UINT8)nz_index[i]; + bit_pos[codesize[i]]++; } /* Set sent_table FALSE so updated table will be written to JPEG file. */ diff --git a/src/3rdparty/libjpeg/src/jchuff.h b/src/3rdparty/libjpeg/src/jchuff.h index da7809a94b1..21f17b89b09 100644 --- a/src/3rdparty/libjpeg/src/jchuff.h +++ b/src/3rdparty/libjpeg/src/jchuff.h @@ -19,12 +19,6 @@ * Hence the magnitude should always fit in 10 or 14 bits respectively. */ -#if BITS_IN_JSAMPLE == 8 -#define MAX_COEF_BITS 10 -#else -#define MAX_COEF_BITS 14 -#endif - /* The progressive Huffman encoder uses an unsigned 16-bit data type to store * absolute values of coefficients, because it is possible to inject a * coefficient value of -32768 into the encoder by attempting to transform a diff --git a/src/3rdparty/libjpeg/src/jcicc.c b/src/3rdparty/libjpeg/src/jcicc.c new file mode 100644 index 00000000000..11037ff6941 --- /dev/null +++ b/src/3rdparty/libjpeg/src/jcicc.c @@ -0,0 +1,105 @@ +/* + * jcicc.c + * + * Copyright (C) 1997-1998, Thomas G. Lane, Todd Newman. + * Copyright (C) 2017, D. R. Commander. + * For conditions of distribution and use, see the accompanying README.ijg + * file. + * + * This file provides code to write International Color Consortium (ICC) device + * profiles embedded in JFIF JPEG image files. The ICC has defined a standard + * for including such data in JPEG "APP2" markers. The code given here does + * not know anything about the internal structure of the ICC profile data; it + * just knows how to embed the profile data in a JPEG file while writing it. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" +#include "jerror.h" + + +/* + * Since an ICC profile can be larger than the maximum size of a JPEG marker + * (64K), we need provisions to split it into multiple markers. The format + * defined by the ICC specifies one or more APP2 markers containing the + * following data: + * Identifying string ASCII "ICC_PROFILE\0" (12 bytes) + * Marker sequence number 1 for first APP2, 2 for next, etc (1 byte) + * Number of markers Total number of APP2's used (1 byte) + * Profile data (remainder of APP2 data) + * Decoders should use the marker sequence numbers to reassemble the profile, + * rather than assuming that the APP2 markers appear in the correct sequence. + */ + +#define ICC_MARKER (JPEG_APP0 + 2) /* JPEG marker code for ICC */ +#define ICC_OVERHEAD_LEN 14 /* size of non-profile data in APP2 */ +#define MAX_BYTES_IN_MARKER 65533 /* maximum data len of a JPEG marker */ +#define MAX_DATA_BYTES_IN_MARKER (MAX_BYTES_IN_MARKER - ICC_OVERHEAD_LEN) + + +/* + * This routine writes the given ICC profile data into a JPEG file. It *must* + * be called AFTER calling jpeg_start_compress() and BEFORE the first call to + * jpeg_write_scanlines(). (This ordering ensures that the APP2 marker(s) will + * appear after the SOI and JFIF or Adobe markers, but before all else.) + */ + +GLOBAL(void) +jpeg_write_icc_profile(j_compress_ptr cinfo, const JOCTET *icc_data_ptr, + unsigned int icc_data_len) +{ + unsigned int num_markers; /* total number of markers we'll write */ + int cur_marker = 1; /* per spec, counting starts at 1 */ + unsigned int length; /* number of bytes to write in this marker */ + + if (icc_data_ptr == NULL || icc_data_len == 0) + ERREXIT(cinfo, JERR_BUFFER_SIZE); + if (cinfo->global_state < CSTATE_SCANNING) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + + /* Calculate the number of markers we'll need, rounding up of course */ + num_markers = icc_data_len / MAX_DATA_BYTES_IN_MARKER; + if (num_markers * MAX_DATA_BYTES_IN_MARKER != icc_data_len) + num_markers++; + + while (icc_data_len > 0) { + /* length of profile to put in this marker */ + length = icc_data_len; + if (length > MAX_DATA_BYTES_IN_MARKER) + length = MAX_DATA_BYTES_IN_MARKER; + icc_data_len -= length; + + /* Write the JPEG marker header (APP2 code and marker length) */ + jpeg_write_m_header(cinfo, ICC_MARKER, + (unsigned int)(length + ICC_OVERHEAD_LEN)); + + /* Write the marker identifying string "ICC_PROFILE" (null-terminated). We + * code it in this less-than-transparent way so that the code works even if + * the local character set is not ASCII. + */ + jpeg_write_m_byte(cinfo, 0x49); + jpeg_write_m_byte(cinfo, 0x43); + jpeg_write_m_byte(cinfo, 0x43); + jpeg_write_m_byte(cinfo, 0x5F); + jpeg_write_m_byte(cinfo, 0x50); + jpeg_write_m_byte(cinfo, 0x52); + jpeg_write_m_byte(cinfo, 0x4F); + jpeg_write_m_byte(cinfo, 0x46); + jpeg_write_m_byte(cinfo, 0x49); + jpeg_write_m_byte(cinfo, 0x4C); + jpeg_write_m_byte(cinfo, 0x45); + jpeg_write_m_byte(cinfo, 0x0); + + /* Add the sequencing info */ + jpeg_write_m_byte(cinfo, cur_marker); + jpeg_write_m_byte(cinfo, (int)num_markers); + + /* Add the profile data */ + while (length--) { + jpeg_write_m_byte(cinfo, *icc_data_ptr); + icc_data_ptr++; + } + cur_marker++; + } +} diff --git a/src/3rdparty/libjpeg/src/jcinit.c b/src/3rdparty/libjpeg/src/jcinit.c index 157353a22e9..fe8a13a8d98 100644 --- a/src/3rdparty/libjpeg/src/jcinit.c +++ b/src/3rdparty/libjpeg/src/jcinit.c @@ -3,8 +3,10 @@ * * This file was part of the Independent JPEG Group's software: * Copyright (C) 1991-1997, Thomas G. Lane. + * Lossless JPEG Modifications: + * Copyright (C) 1999, Ken Murchison. * libjpeg-turbo Modifications: - * Copyright (C) 2020, D. R. Commander. + * Copyright (C) 2020, 2022, D. R. Commander. * For conditions of distribution and use, see the accompanying README.ijg * file. * @@ -21,7 +23,7 @@ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" -#include "jpegcomp.h" +#include "jpegapicomp.h" /* @@ -38,34 +40,101 @@ jinit_compress_master(j_compress_ptr cinfo) /* Preprocessing */ if (!cinfo->raw_data_in) { - jinit_color_converter(cinfo); - jinit_downsampler(cinfo); - jinit_c_prep_controller(cinfo, FALSE /* never need full buffer here */); - } - /* Forward DCT */ - jinit_forward_dct(cinfo); - /* Entropy encoding: either Huffman or arithmetic coding. */ - if (cinfo->arith_code) { -#ifdef C_ARITH_CODING_SUPPORTED - jinit_arith_encoder(cinfo); + if (cinfo->data_precision == 16) { +#ifdef C_LOSSLESS_SUPPORTED + j16init_color_converter(cinfo); + j16init_downsampler(cinfo); + j16init_c_prep_controller(cinfo, + FALSE /* never need full buffer here */); #else - ERREXIT(cinfo, JERR_ARITH_NOTIMPL); + ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision); #endif - } else { - if (cinfo->progressive_mode) { -#ifdef C_PROGRESSIVE_SUPPORTED - jinit_phuff_encoder(cinfo); -#else - ERREXIT(cinfo, JERR_NOT_COMPILED); -#endif - } else - jinit_huff_encoder(cinfo); + } else if (cinfo->data_precision == 12) { + j12init_color_converter(cinfo); + j12init_downsampler(cinfo); + j12init_c_prep_controller(cinfo, + FALSE /* never need full buffer here */); + } else { + jinit_color_converter(cinfo); + jinit_downsampler(cinfo); + jinit_c_prep_controller(cinfo, FALSE /* never need full buffer here */); + } } - /* Need a full-image coefficient buffer in any multi-pass mode. */ - jinit_c_coef_controller(cinfo, (boolean)(cinfo->num_scans > 1 || - cinfo->optimize_coding)); - jinit_c_main_controller(cinfo, FALSE /* never need full buffer here */); + if (cinfo->master->lossless) { +#ifdef C_LOSSLESS_SUPPORTED + /* Prediction, sample differencing, and point transform */ + if (cinfo->data_precision == 16) + j16init_lossless_compressor(cinfo); + else if (cinfo->data_precision == 12) + j12init_lossless_compressor(cinfo); + else + jinit_lossless_compressor(cinfo); + /* Entropy encoding: either Huffman or arithmetic coding. */ + if (cinfo->arith_code) { + ERREXIT(cinfo, JERR_ARITH_NOTIMPL); + } else { + jinit_lhuff_encoder(cinfo); + } + + /* Need a full-image difference buffer in any multi-pass mode. */ + if (cinfo->data_precision == 16) + j16init_c_diff_controller(cinfo, (boolean)(cinfo->num_scans > 1 || + cinfo->optimize_coding)); + else if (cinfo->data_precision == 12) + j12init_c_diff_controller(cinfo, (boolean)(cinfo->num_scans > 1 || + cinfo->optimize_coding)); + else + jinit_c_diff_controller(cinfo, (boolean)(cinfo->num_scans > 1 || + cinfo->optimize_coding)); +#else + ERREXIT(cinfo, JERR_NOT_COMPILED); +#endif + } else { + if (cinfo->data_precision == 16) + ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision); + /* Forward DCT */ + if (cinfo->data_precision == 12) + j12init_forward_dct(cinfo); + else + jinit_forward_dct(cinfo); + /* Entropy encoding: either Huffman or arithmetic coding. */ + if (cinfo->arith_code) { +#ifdef C_ARITH_CODING_SUPPORTED + jinit_arith_encoder(cinfo); +#else + ERREXIT(cinfo, JERR_ARITH_NOTIMPL); +#endif + } else { + if (cinfo->progressive_mode) { +#ifdef C_PROGRESSIVE_SUPPORTED + jinit_phuff_encoder(cinfo); +#else + ERREXIT(cinfo, JERR_NOT_COMPILED); +#endif + } else + jinit_huff_encoder(cinfo); + } + + /* Need a full-image coefficient buffer in any multi-pass mode. */ + if (cinfo->data_precision == 12) + j12init_c_coef_controller(cinfo, (boolean)(cinfo->num_scans > 1 || + cinfo->optimize_coding)); + else + jinit_c_coef_controller(cinfo, (boolean)(cinfo->num_scans > 1 || + cinfo->optimize_coding)); + } + + if (cinfo->data_precision == 16) +#ifdef C_LOSSLESS_SUPPORTED + j16init_c_main_controller(cinfo, FALSE /* never need full buffer here */); +#else + ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision); +#endif + else if (cinfo->data_precision == 12) + j12init_c_main_controller(cinfo, FALSE /* never need full buffer here */); + else + jinit_c_main_controller(cinfo, FALSE /* never need full buffer here */); jinit_marker_writer(cinfo); diff --git a/src/3rdparty/libjpeg/src/jclhuff.c b/src/3rdparty/libjpeg/src/jclhuff.c new file mode 100644 index 00000000000..ae4154532ed --- /dev/null +++ b/src/3rdparty/libjpeg/src/jclhuff.c @@ -0,0 +1,587 @@ +/* + * jclhuff.c + * + * This file was part of the Independent JPEG Group's software: + * Copyright (C) 1991-1997, Thomas G. Lane. + * Lossless JPEG Modifications: + * Copyright (C) 1999, Ken Murchison. + * libjpeg-turbo Modifications: + * Copyright (C) 2022, D. R. Commander. + * For conditions of distribution and use, see the accompanying README.ijg + * file. + * + * This file contains Huffman entropy encoding routines for lossless JPEG. + * + * Much of the complexity here has to do with supporting output suspension. + * If the data destination module demands suspension, we want to be able to + * back up to the start of the current MCU. To do this, we copy state + * variables into local working storage, and update them back to the + * permanent JPEG objects only upon successful completion of an MCU. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" +#include "jlossls.h" /* Private declarations for lossless codec */ +#include "jchuff.h" /* Declarations shared with jc*huff.c */ + + +#ifdef C_LOSSLESS_SUPPORTED + +/* The legal range of a spatial difference is + * -32767 .. +32768. + * Hence the magnitude should always fit in 16 bits. + */ + +#define MAX_DIFF_BITS 16 + + +/* Expanded entropy encoder object for Huffman encoding in lossless mode. + * + * The savable_state subrecord contains fields that change within an MCU, + * but must not be updated permanently until we complete the MCU. + */ + +typedef struct { + size_t put_buffer; /* current bit-accumulation buffer */ + int put_bits; /* # of bits now in it */ +} savable_state; + + +typedef struct { + int ci, yoffset, MCU_width; +} lhe_input_ptr_info; + + +typedef struct { + struct jpeg_entropy_encoder pub; /* public fields */ + + savable_state saved; /* Bit buffer at start of MCU */ + + /* These fields are NOT loaded into local working state. */ + unsigned int restarts_to_go; /* MCUs left in this restart interval */ + int next_restart_num; /* next restart number to write (0-7) */ + + /* Pointers to derived tables (these workspaces have image lifespan) */ + c_derived_tbl *derived_tbls[NUM_HUFF_TBLS]; + + /* Pointers to derived tables to be used for each data unit within an MCU */ + c_derived_tbl *cur_tbls[C_MAX_BLOCKS_IN_MCU]; + +#ifdef ENTROPY_OPT_SUPPORTED /* Statistics tables for optimization */ + long *count_ptrs[NUM_HUFF_TBLS]; + + /* Pointers to stats tables to be used for each data unit within an MCU */ + long *cur_counts[C_MAX_BLOCKS_IN_MCU]; +#endif + + /* Pointers to the proper input difference row for each group of data units + * within an MCU. For each component, there are Vi groups of Hi data units. + */ + JDIFFROW input_ptr[C_MAX_BLOCKS_IN_MCU]; + + /* Number of input pointers in use for the current MCU. This is the sum + * of all Vi in the MCU. + */ + int num_input_ptrs; + + /* Information used for positioning the input pointers within the input + * difference rows. + */ + lhe_input_ptr_info input_ptr_info[C_MAX_BLOCKS_IN_MCU]; + + /* Index of the proper input pointer for each data unit within an MCU */ + int input_ptr_index[C_MAX_BLOCKS_IN_MCU]; + +} lhuff_entropy_encoder; + +typedef lhuff_entropy_encoder *lhuff_entropy_ptr; + +/* Working state while writing an MCU. + * This struct contains all the fields that are needed by subroutines. + */ + +typedef struct { + JOCTET *next_output_byte; /* => next byte to write in buffer */ + size_t free_in_buffer; /* # of byte spaces remaining in buffer */ + savable_state cur; /* Current bit buffer & DC state */ + j_compress_ptr cinfo; /* dump_buffer needs access to this */ +} working_state; + + +/* Forward declarations */ +METHODDEF(JDIMENSION) encode_mcus_huff(j_compress_ptr cinfo, + JDIFFIMAGE diff_buf, + JDIMENSION MCU_row_num, + JDIMENSION MCU_col_num, + JDIMENSION nMCU); +METHODDEF(void) finish_pass_huff(j_compress_ptr cinfo); +#ifdef ENTROPY_OPT_SUPPORTED +METHODDEF(JDIMENSION) encode_mcus_gather(j_compress_ptr cinfo, + JDIFFIMAGE diff_buf, + JDIMENSION MCU_row_num, + JDIMENSION MCU_col_num, + JDIMENSION nMCU); +METHODDEF(void) finish_pass_gather(j_compress_ptr cinfo); +#endif + + +/* + * Initialize for a Huffman-compressed scan. + * If gather_statistics is TRUE, we do not output anything during the scan, + * just count the Huffman symbols used and generate Huffman code tables. + */ + +METHODDEF(void) +start_pass_lhuff(j_compress_ptr cinfo, boolean gather_statistics) +{ + lhuff_entropy_ptr entropy = (lhuff_entropy_ptr)cinfo->entropy; + int ci, dctbl, sampn, ptrn, yoffset, xoffset; + jpeg_component_info *compptr; + + if (gather_statistics) { +#ifdef ENTROPY_OPT_SUPPORTED + entropy->pub.encode_mcus = encode_mcus_gather; + entropy->pub.finish_pass = finish_pass_gather; +#else + ERREXIT(cinfo, JERR_NOT_COMPILED); +#endif + } else { + entropy->pub.encode_mcus = encode_mcus_huff; + entropy->pub.finish_pass = finish_pass_huff; + } + + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + dctbl = compptr->dc_tbl_no; + if (gather_statistics) { +#ifdef ENTROPY_OPT_SUPPORTED + /* Check for invalid table indexes */ + /* (make_c_derived_tbl does this in the other path) */ + if (dctbl < 0 || dctbl >= NUM_HUFF_TBLS) + ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, dctbl); + /* Allocate and zero the statistics tables */ + /* Note that jpeg_gen_optimal_table expects 257 entries in each table! */ + if (entropy->count_ptrs[dctbl] == NULL) + entropy->count_ptrs[dctbl] = (long *) + (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE, + 257 * sizeof(long)); + memset(entropy->count_ptrs[dctbl], 0, 257 * sizeof(long)); +#endif + } else { + /* Compute derived values for Huffman tables */ + /* We may do this more than once for a table, but it's not expensive */ + jpeg_make_c_derived_tbl(cinfo, TRUE, dctbl, + &entropy->derived_tbls[dctbl]); + } + } + + /* Precalculate encoding info for each sample in an MCU of this scan */ + for (sampn = 0, ptrn = 0; sampn < cinfo->blocks_in_MCU;) { + compptr = cinfo->cur_comp_info[cinfo->MCU_membership[sampn]]; + ci = compptr->component_index; + for (yoffset = 0; yoffset < compptr->MCU_height; yoffset++, ptrn++) { + /* Precalculate the setup info for each input pointer */ + entropy->input_ptr_info[ptrn].ci = ci; + entropy->input_ptr_info[ptrn].yoffset = yoffset; + entropy->input_ptr_info[ptrn].MCU_width = compptr->MCU_width; + for (xoffset = 0; xoffset < compptr->MCU_width; xoffset++, sampn++) { + /* Precalculate the input pointer index for each sample */ + entropy->input_ptr_index[sampn] = ptrn; + /* Precalculate which tables to use for each sample */ + entropy->cur_tbls[sampn] = entropy->derived_tbls[compptr->dc_tbl_no]; + entropy->cur_counts[sampn] = entropy->count_ptrs[compptr->dc_tbl_no]; + } + } + } + entropy->num_input_ptrs = ptrn; + + /* Initialize bit buffer to empty */ + entropy->saved.put_buffer = 0; + entropy->saved.put_bits = 0; + + /* Initialize restart stuff */ + entropy->restarts_to_go = cinfo->restart_interval; + entropy->next_restart_num = 0; +} + + +/* Outputting bytes to the file */ + +/* Emit a byte, taking 'action' if must suspend. */ +#define emit_byte(state, val, action) { \ + *(state)->next_output_byte++ = (JOCTET)(val); \ + if (--(state)->free_in_buffer == 0) \ + if (!dump_buffer(state)) \ + { action; } \ +} + + +LOCAL(boolean) +dump_buffer(working_state *state) +/* Empty the output buffer; return TRUE if successful, FALSE if must suspend */ +{ + struct jpeg_destination_mgr *dest = state->cinfo->dest; + + if (!(*dest->empty_output_buffer) (state->cinfo)) + return FALSE; + /* After a successful buffer dump, must reset buffer pointers */ + state->next_output_byte = dest->next_output_byte; + state->free_in_buffer = dest->free_in_buffer; + return TRUE; +} + + +/* Outputting bits to the file */ + +/* Only the right 24 bits of put_buffer are used; the valid bits are + * left-justified in this part. At most 16 bits can be passed to emit_bits + * in one call, and we never retain more than 7 bits in put_buffer + * between calls, so 24 bits are sufficient. + */ + +INLINE +LOCAL(boolean) +emit_bits(working_state *state, unsigned int code, int size) +/* Emit some bits; return TRUE if successful, FALSE if must suspend */ +{ + /* This routine is heavily used, so it's worth coding tightly. */ + register size_t put_buffer = (size_t)code; + register int put_bits = state->cur.put_bits; + + /* if size is 0, caller used an invalid Huffman table entry */ + if (size == 0) + ERREXIT(state->cinfo, JERR_HUFF_MISSING_CODE); + + put_buffer &= (((size_t)1) << size) - 1; /* mask off any extra bits in code */ + + put_bits += size; /* new number of bits in buffer */ + + put_buffer <<= 24 - put_bits; /* align incoming bits */ + + put_buffer |= state->cur.put_buffer; /* and merge with old buffer contents */ + + while (put_bits >= 8) { + int c = (int)((put_buffer >> 16) & 0xFF); + + emit_byte(state, c, return FALSE); + if (c == 0xFF) { /* need to stuff a zero byte? */ + emit_byte(state, 0, return FALSE); + } + put_buffer <<= 8; + put_bits -= 8; + } + + state->cur.put_buffer = put_buffer; /* update state variables */ + state->cur.put_bits = put_bits; + + return TRUE; +} + + +LOCAL(boolean) +flush_bits(working_state *state) +{ + if (!emit_bits(state, 0x7F, 7)) /* fill any partial byte with ones */ + return FALSE; + state->cur.put_buffer = 0; /* and reset bit-buffer to empty */ + state->cur.put_bits = 0; + return TRUE; +} + + +/* + * Emit a restart marker & resynchronize predictions. + */ + +LOCAL(boolean) +emit_restart(working_state *state, int restart_num) +{ + if (!flush_bits(state)) + return FALSE; + + emit_byte(state, 0xFF, return FALSE); + emit_byte(state, JPEG_RST0 + restart_num, return FALSE); + + /* The restart counter is not updated until we successfully write the MCU. */ + + return TRUE; +} + + +/* + * Encode and output nMCU MCUs' worth of Huffman-compressed differences. + */ + +METHODDEF(JDIMENSION) +encode_mcus_huff(j_compress_ptr cinfo, JDIFFIMAGE diff_buf, + JDIMENSION MCU_row_num, JDIMENSION MCU_col_num, + JDIMENSION nMCU) +{ + lhuff_entropy_ptr entropy = (lhuff_entropy_ptr)cinfo->entropy; + working_state state; + int sampn, ci, yoffset, MCU_width, ptrn; + JDIMENSION mcu_num; + + /* Load up working state */ + state.next_output_byte = cinfo->dest->next_output_byte; + state.free_in_buffer = cinfo->dest->free_in_buffer; + state.cur = entropy->saved; + state.cinfo = cinfo; + + /* Emit restart marker if needed */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) + if (!emit_restart(&state, entropy->next_restart_num)) + return 0; + } + + /* Set input pointer locations based on MCU_col_num */ + for (ptrn = 0; ptrn < entropy->num_input_ptrs; ptrn++) { + ci = entropy->input_ptr_info[ptrn].ci; + yoffset = entropy->input_ptr_info[ptrn].yoffset; + MCU_width = entropy->input_ptr_info[ptrn].MCU_width; + entropy->input_ptr[ptrn] = + diff_buf[ci][MCU_row_num + yoffset] + (MCU_col_num * MCU_width); + } + + for (mcu_num = 0; mcu_num < nMCU; mcu_num++) { + + /* Inner loop handles the samples in the MCU */ + for (sampn = 0; sampn < cinfo->blocks_in_MCU; sampn++) { + register int temp, temp2; + register int nbits; + c_derived_tbl *dctbl = entropy->cur_tbls[sampn]; + + /* Encode the difference per section H.1.2.2 */ + + /* Input the sample difference */ + temp = *entropy->input_ptr[entropy->input_ptr_index[sampn]]++; + + if (temp & 0x8000) { /* instead of temp < 0 */ + temp = (-temp) & 0x7FFF; /* absolute value, mod 2^16 */ + if (temp == 0) /* special case: magnitude = 32768 */ + temp2 = temp = 0x8000; + temp2 = ~temp; /* one's complement of magnitude */ + } else { + temp &= 0x7FFF; /* abs value mod 2^16 */ + temp2 = temp; /* magnitude */ + } + + /* Find the number of bits needed for the magnitude of the difference */ + nbits = 0; + while (temp) { + nbits++; + temp >>= 1; + } + /* Check for out-of-range difference values. + */ + if (nbits > MAX_DIFF_BITS) + ERREXIT(cinfo, JERR_BAD_DCT_COEF); + + /* Emit the Huffman-coded symbol for the number of bits */ + if (!emit_bits(&state, dctbl->ehufco[nbits], dctbl->ehufsi[nbits])) + return mcu_num; + + /* Emit that number of bits of the value, if positive, */ + /* or the complement of its magnitude, if negative. */ + if (nbits && /* emit_bits rejects calls with size 0 */ + nbits != 16) /* special case: no bits should be emitted */ + if (!emit_bits(&state, (unsigned int)temp2, nbits)) + return mcu_num; + } + + /* Completed MCU, so update state */ + cinfo->dest->next_output_byte = state.next_output_byte; + cinfo->dest->free_in_buffer = state.free_in_buffer; + entropy->saved = state.cur; + + /* Update restart-interval state too */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) { + entropy->restarts_to_go = cinfo->restart_interval; + entropy->next_restart_num++; + entropy->next_restart_num &= 7; + } + entropy->restarts_to_go--; + } + + } + + return nMCU; +} + + +/* + * Finish up at the end of a Huffman-compressed scan. + */ + +METHODDEF(void) +finish_pass_huff(j_compress_ptr cinfo) +{ + lhuff_entropy_ptr entropy = (lhuff_entropy_ptr)cinfo->entropy; + working_state state; + + /* Load up working state ... flush_bits needs it */ + state.next_output_byte = cinfo->dest->next_output_byte; + state.free_in_buffer = cinfo->dest->free_in_buffer; + state.cur = entropy->saved; + state.cinfo = cinfo; + + /* Flush out the last data */ + if (!flush_bits(&state)) + ERREXIT(cinfo, JERR_CANT_SUSPEND); + + /* Update state */ + cinfo->dest->next_output_byte = state.next_output_byte; + cinfo->dest->free_in_buffer = state.free_in_buffer; + entropy->saved = state.cur; +} + + +/* + * Huffman coding optimization. + * + * We first scan the supplied data and count the number of uses of each symbol + * that is to be Huffman-coded. (This process MUST agree with the code above.) + * Then we build a Huffman coding tree for the observed counts. + * Symbols which are not needed at all for the particular image are not + * assigned any code, which saves space in the DHT marker as well as in + * the compressed data. + */ + +#ifdef ENTROPY_OPT_SUPPORTED + +/* + * Trial-encode nMCU MCUs' worth of Huffman-compressed differences. + * No data is actually output, so no suspension return is possible. + */ + +METHODDEF(JDIMENSION) +encode_mcus_gather(j_compress_ptr cinfo, JDIFFIMAGE diff_buf, + JDIMENSION MCU_row_num, JDIMENSION MCU_col_num, + JDIMENSION nMCU) +{ + lhuff_entropy_ptr entropy = (lhuff_entropy_ptr)cinfo->entropy; + int sampn, ci, yoffset, MCU_width, ptrn; + JDIMENSION mcu_num; + + /* Take care of restart intervals if needed */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) { + /* Update restart state */ + entropy->restarts_to_go = cinfo->restart_interval; + } + entropy->restarts_to_go--; + } + + /* Set input pointer locations based on MCU_col_num */ + for (ptrn = 0; ptrn < entropy->num_input_ptrs; ptrn++) { + ci = entropy->input_ptr_info[ptrn].ci; + yoffset = entropy->input_ptr_info[ptrn].yoffset; + MCU_width = entropy->input_ptr_info[ptrn].MCU_width; + entropy->input_ptr[ptrn] = + diff_buf[ci][MCU_row_num + yoffset] + (MCU_col_num * MCU_width); + } + + for (mcu_num = 0; mcu_num < nMCU; mcu_num++) { + + /* Inner loop handles the samples in the MCU */ + for (sampn = 0; sampn < cinfo->blocks_in_MCU; sampn++) { + register int temp; + register int nbits; + long *counts = entropy->cur_counts[sampn]; + + /* Encode the difference per section H.1.2.2 */ + + /* Input the sample difference */ + temp = *entropy->input_ptr[entropy->input_ptr_index[sampn]]++; + + if (temp & 0x8000) { /* instead of temp < 0 */ + temp = (-temp) & 0x7FFF; /* absolute value, mod 2^16 */ + if (temp == 0) /* special case: magnitude = 32768 */ + temp = 0x8000; + } else + temp &= 0x7FFF; /* abs value mod 2^16 */ + + /* Find the number of bits needed for the magnitude of the difference */ + nbits = 0; + while (temp) { + nbits++; + temp >>= 1; + } + /* Check for out-of-range difference values. + */ + if (nbits > MAX_DIFF_BITS) + ERREXIT(cinfo, JERR_BAD_DCT_COEF); + + /* Count the Huffman symbol for the number of bits */ + counts[nbits]++; + } + } + + return nMCU; +} + + +/* + * Finish up a statistics-gathering pass and create the new Huffman tables. + */ + +METHODDEF(void) +finish_pass_gather(j_compress_ptr cinfo) +{ + lhuff_entropy_ptr entropy = (lhuff_entropy_ptr)cinfo->entropy; + int ci, dctbl; + jpeg_component_info *compptr; + JHUFF_TBL **htblptr; + boolean did_dc[NUM_HUFF_TBLS]; + + /* It's important not to apply jpeg_gen_optimal_table more than once + * per table, because it clobbers the input frequency counts! + */ + memset(did_dc, 0, sizeof(did_dc)); + + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + dctbl = compptr->dc_tbl_no; + if (!did_dc[dctbl]) { + htblptr = &cinfo->dc_huff_tbl_ptrs[dctbl]; + if (*htblptr == NULL) + *htblptr = jpeg_alloc_huff_table((j_common_ptr)cinfo); + jpeg_gen_optimal_table(cinfo, *htblptr, entropy->count_ptrs[dctbl]); + did_dc[dctbl] = TRUE; + } + } +} + + +#endif /* ENTROPY_OPT_SUPPORTED */ + + +/* + * Module initialization routine for Huffman entropy encoding. + */ + +GLOBAL(void) +jinit_lhuff_encoder(j_compress_ptr cinfo) +{ + lhuff_entropy_ptr entropy; + int i; + + entropy = (lhuff_entropy_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE, + sizeof(lhuff_entropy_encoder)); + cinfo->entropy = (struct jpeg_entropy_encoder *)entropy; + entropy->pub.start_pass = start_pass_lhuff; + + /* Mark tables unallocated */ + for (i = 0; i < NUM_HUFF_TBLS; i++) { + entropy->derived_tbls[i] = NULL; +#ifdef ENTROPY_OPT_SUPPORTED + entropy->count_ptrs[i] = NULL; +#endif + } +} + +#endif /* C_LOSSLESS_SUPPORTED */ diff --git a/src/3rdparty/libjpeg/src/jclossls.c b/src/3rdparty/libjpeg/src/jclossls.c new file mode 100644 index 00000000000..e9ba92a7dfe --- /dev/null +++ b/src/3rdparty/libjpeg/src/jclossls.c @@ -0,0 +1,319 @@ +/* + * jclossls.c + * + * This file was part of the Independent JPEG Group's software: + * Copyright (C) 1998, Thomas G. Lane. + * Lossless JPEG Modifications: + * Copyright (C) 1999, Ken Murchison. + * libjpeg-turbo Modifications: + * Copyright (C) 2022, D. R. Commander. + * For conditions of distribution and use, see the accompanying README.ijg + * file. + * + * This file contains prediction, sample differencing, and point transform + * routines for the lossless JPEG compressor. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" +#include "jlossls.h" + +#ifdef C_LOSSLESS_SUPPORTED + + +/************************** Sample differencing **************************/ + +/* + * In order to avoid a performance penalty for checking which predictor is + * being used and which row is being processed for each call of the + * undifferencer, and to promote optimization, we have separate differencing + * functions for each predictor selection value. + * + * We are able to avoid duplicating source code by implementing the predictors + * and differencers as macros. Each of the differencing functions is simply a + * wrapper around a DIFFERENCE macro with the appropriate PREDICTOR macro + * passed as an argument. + */ + +/* Forward declarations */ +LOCAL(void) reset_predictor(j_compress_ptr cinfo, int ci); + + +/* Predictor for the first column of the first row: 2^(P-Pt-1) */ +#define INITIAL_PREDICTORx (1 << (cinfo->data_precision - cinfo->Al - 1)) + +/* Predictor for the first column of the remaining rows: Rb */ +#define INITIAL_PREDICTOR2 prev_row[0] + + +/* + * 1-Dimensional differencer routine. + * + * This macro implements the 1-D horizontal predictor (1). INITIAL_PREDICTOR + * is used as the special case predictor for the first column, which must be + * either INITIAL_PREDICTOR2 or INITIAL_PREDICTORx. The remaining samples + * use PREDICTOR1. + */ + +#define DIFFERENCE_1D(INITIAL_PREDICTOR) \ + lossless_comp_ptr losslessc = (lossless_comp_ptr)cinfo->fdct; \ + boolean restart = FALSE; \ + int samp, Ra; \ + \ + samp = *input_buf++; \ + *diff_buf++ = samp - INITIAL_PREDICTOR; \ + \ + while (--width) { \ + Ra = samp; \ + samp = *input_buf++; \ + *diff_buf++ = samp - PREDICTOR1; \ + } \ + \ + /* Account for restart interval (no-op if not using restarts) */ \ + if (cinfo->restart_interval) { \ + if (--(losslessc->restart_rows_to_go[ci]) == 0) { \ + reset_predictor(cinfo, ci); \ + restart = TRUE; \ + } \ + } + + +/* + * 2-Dimensional differencer routine. + * + * This macro implements the 2-D horizontal predictors (#2-7). PREDICTOR2 is + * used as the special case predictor for the first column. The remaining + * samples use PREDICTOR, which is a function of Ra, Rb, and Rc. + * + * Because prev_row and output_buf may point to the same storage area (in an + * interleaved image with Vi=1, for example), we must take care to buffer Rb/Rc + * before writing the current reconstructed sample value into output_buf. + */ + +#define DIFFERENCE_2D(PREDICTOR) \ + lossless_comp_ptr losslessc = (lossless_comp_ptr)cinfo->fdct; \ + int samp, Ra, Rb, Rc; \ + \ + Rb = *prev_row++; \ + samp = *input_buf++; \ + *diff_buf++ = samp - PREDICTOR2; \ + \ + while (--width) { \ + Rc = Rb; \ + Rb = *prev_row++; \ + Ra = samp; \ + samp = *input_buf++; \ + *diff_buf++ = samp - PREDICTOR; \ + } \ + \ + /* Account for restart interval (no-op if not using restarts) */ \ + if (cinfo->restart_interval) { \ + if (--losslessc->restart_rows_to_go[ci] == 0) \ + reset_predictor(cinfo, ci); \ + } + + +/* + * Differencers for the second and subsequent rows in a scan or restart + * interval. The first sample in the row is differenced using the vertical + * predictor (2). The rest of the samples are differenced using the predictor + * specified in the scan header. + */ + +METHODDEF(void) +jpeg_difference1(j_compress_ptr cinfo, int ci, + _JSAMPROW input_buf, _JSAMPROW prev_row, + JDIFFROW diff_buf, JDIMENSION width) +{ + DIFFERENCE_1D(INITIAL_PREDICTOR2); + (void)(restart); +} + +METHODDEF(void) +jpeg_difference2(j_compress_ptr cinfo, int ci, + _JSAMPROW input_buf, _JSAMPROW prev_row, + JDIFFROW diff_buf, JDIMENSION width) +{ + DIFFERENCE_2D(PREDICTOR2); + (void)(Ra); + (void)(Rc); +} + +METHODDEF(void) +jpeg_difference3(j_compress_ptr cinfo, int ci, + _JSAMPROW input_buf, _JSAMPROW prev_row, + JDIFFROW diff_buf, JDIMENSION width) +{ + DIFFERENCE_2D(PREDICTOR3); + (void)(Ra); +} + +METHODDEF(void) +jpeg_difference4(j_compress_ptr cinfo, int ci, + _JSAMPROW input_buf, _JSAMPROW prev_row, + JDIFFROW diff_buf, JDIMENSION width) +{ + DIFFERENCE_2D(PREDICTOR4); +} + +METHODDEF(void) +jpeg_difference5(j_compress_ptr cinfo, int ci, + _JSAMPROW input_buf, _JSAMPROW prev_row, + JDIFFROW diff_buf, JDIMENSION width) +{ + DIFFERENCE_2D(PREDICTOR5); +} + +METHODDEF(void) +jpeg_difference6(j_compress_ptr cinfo, int ci, + _JSAMPROW input_buf, _JSAMPROW prev_row, + JDIFFROW diff_buf, JDIMENSION width) +{ + DIFFERENCE_2D(PREDICTOR6); +} + +METHODDEF(void) +jpeg_difference7(j_compress_ptr cinfo, int ci, + _JSAMPROW input_buf, _JSAMPROW prev_row, + JDIFFROW diff_buf, JDIMENSION width) +{ + DIFFERENCE_2D(PREDICTOR7); + (void)(Rc); +} + + +/* + * Differencer for the first row in a scan or restart interval. The first + * sample in the row is differenced using the special predictor constant + * x = 2 ^ (P-Pt-1). The rest of the samples are differenced using the + * 1-D horizontal predictor (1). + */ + +METHODDEF(void) +jpeg_difference_first_row(j_compress_ptr cinfo, int ci, + _JSAMPROW input_buf, _JSAMPROW prev_row, + JDIFFROW diff_buf, JDIMENSION width) +{ + DIFFERENCE_1D(INITIAL_PREDICTORx); + + /* + * Now that we have differenced the first row, we want to use the + * differencer that corresponds to the predictor specified in the + * scan header. + * + * Note that we don't do this if we have just reset the predictor + * for a new restart interval. + */ + if (!restart) { + switch (cinfo->Ss) { + case 1: + losslessc->predict_difference[ci] = jpeg_difference1; + break; + case 2: + losslessc->predict_difference[ci] = jpeg_difference2; + break; + case 3: + losslessc->predict_difference[ci] = jpeg_difference3; + break; + case 4: + losslessc->predict_difference[ci] = jpeg_difference4; + break; + case 5: + losslessc->predict_difference[ci] = jpeg_difference5; + break; + case 6: + losslessc->predict_difference[ci] = jpeg_difference6; + break; + case 7: + losslessc->predict_difference[ci] = jpeg_difference7; + break; + } + } +} + +/* + * Reset predictor at the start of a pass or restart interval. + */ + +LOCAL(void) +reset_predictor(j_compress_ptr cinfo, int ci) +{ + lossless_comp_ptr losslessc = (lossless_comp_ptr)cinfo->fdct; + + /* Initialize restart counter */ + losslessc->restart_rows_to_go[ci] = + cinfo->restart_interval / cinfo->MCUs_per_row; + + /* Set difference function to first row function */ + losslessc->predict_difference[ci] = jpeg_difference_first_row; +} + + +/********************** Sample downscaling by 2^Pt ***********************/ + +METHODDEF(void) +simple_downscale(j_compress_ptr cinfo, + _JSAMPROW input_buf, _JSAMPROW output_buf, JDIMENSION width) +{ + do { + *output_buf++ = (_JSAMPLE)RIGHT_SHIFT(*input_buf++, cinfo->Al); + } while (--width); +} + + +METHODDEF(void) +noscale(j_compress_ptr cinfo, + _JSAMPROW input_buf, _JSAMPROW output_buf, JDIMENSION width) +{ + memcpy(output_buf, input_buf, width * sizeof(_JSAMPLE)); +} + + +/* + * Initialize for a processing pass. + */ + +METHODDEF(void) +start_pass_lossless(j_compress_ptr cinfo) +{ + lossless_comp_ptr losslessc = (lossless_comp_ptr)cinfo->fdct; + int ci; + + /* Set scaler function based on Pt */ + if (cinfo->Al) + losslessc->scaler_scale = simple_downscale; + else + losslessc->scaler_scale = noscale; + + /* Check that the restart interval is an integer multiple of the number + * of MCUs in an MCU row. + */ + if (cinfo->restart_interval % cinfo->MCUs_per_row != 0) + ERREXIT2(cinfo, JERR_BAD_RESTART, + cinfo->restart_interval, cinfo->MCUs_per_row); + + /* Set predictors for start of pass */ + for (ci = 0; ci < cinfo->num_components; ci++) + reset_predictor(cinfo, ci); +} + + +/* + * Initialize the lossless compressor. + */ + +GLOBAL(void) +_jinit_lossless_compressor(j_compress_ptr cinfo) +{ + lossless_comp_ptr losslessc; + + /* Create subobject in permanent pool */ + losslessc = (lossless_comp_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_PERMANENT, + sizeof(jpeg_lossless_compressor)); + cinfo->fdct = (struct jpeg_forward_dct *)losslessc; + losslessc->pub.start_pass = start_pass_lossless; +} + +#endif /* C_LOSSLESS_SUPPORTED */ diff --git a/src/3rdparty/libjpeg/src/jcmainct.c b/src/3rdparty/libjpeg/src/jcmainct.c index 3f23028c467..fe8fc0b1acd 100644 --- a/src/3rdparty/libjpeg/src/jcmainct.c +++ b/src/3rdparty/libjpeg/src/jcmainct.c @@ -3,8 +3,10 @@ * * This file was part of the Independent JPEG Group's software: * Copyright (C) 1994-1996, Thomas G. Lane. - * It was modified by The libjpeg-turbo Project to include only code relevant - * to libjpeg-turbo. + * Lossless JPEG Modifications: + * Copyright (C) 1999, Ken Murchison. + * libjpeg-turbo Modifications: + * Copyright (C) 2022, D. R. Commander. * For conditions of distribution and use, see the accompanying README.ijg * file. * @@ -16,8 +18,11 @@ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" +#include "jsamplecomp.h" +#if BITS_IN_JSAMPLE != 16 || defined(C_LOSSLESS_SUPPORTED) + /* Private buffer controller object */ typedef struct { @@ -32,7 +37,7 @@ typedef struct { * (we allocate one for each component). In the full-image case, this * points to the currently accessible strips of the virtual arrays. */ - JSAMPARRAY buffer[MAX_COMPONENTS]; + _JSAMPARRAY buffer[MAX_COMPONENTS]; } my_main_controller; typedef my_main_controller *my_main_ptr; @@ -40,7 +45,7 @@ typedef my_main_controller *my_main_ptr; /* Forward declarations */ METHODDEF(void) process_data_simple_main(j_compress_ptr cinfo, - JSAMPARRAY input_buf, + _JSAMPARRAY input_buf, JDIMENSION *in_row_ctr, JDIMENSION in_rows_avail); @@ -65,7 +70,7 @@ start_pass_main(j_compress_ptr cinfo, J_BUF_MODE pass_mode) main_ptr->rowgroup_ctr = 0; main_ptr->suspended = FALSE; main_ptr->pass_mode = pass_mode; /* save mode for use by process_data */ - main_ptr->pub.process_data = process_data_simple_main; + main_ptr->pub._process_data = process_data_simple_main; } @@ -76,28 +81,28 @@ start_pass_main(j_compress_ptr cinfo, J_BUF_MODE pass_mode) */ METHODDEF(void) -process_data_simple_main(j_compress_ptr cinfo, JSAMPARRAY input_buf, +process_data_simple_main(j_compress_ptr cinfo, _JSAMPARRAY input_buf, JDIMENSION *in_row_ctr, JDIMENSION in_rows_avail) { my_main_ptr main_ptr = (my_main_ptr)cinfo->main; + JDIMENSION data_unit = cinfo->master->lossless ? 1 : DCTSIZE; while (main_ptr->cur_iMCU_row < cinfo->total_iMCU_rows) { /* Read input data if we haven't filled the main buffer yet */ - if (main_ptr->rowgroup_ctr < DCTSIZE) - (*cinfo->prep->pre_process_data) (cinfo, input_buf, in_row_ctr, - in_rows_avail, main_ptr->buffer, - &main_ptr->rowgroup_ctr, - (JDIMENSION)DCTSIZE); + if (main_ptr->rowgroup_ctr < data_unit) + (*cinfo->prep->_pre_process_data) (cinfo, input_buf, in_row_ctr, + in_rows_avail, main_ptr->buffer, + &main_ptr->rowgroup_ctr, data_unit); /* If we don't have a full iMCU row buffered, return to application for * more data. Note that preprocessor will always pad to fill the iMCU row * at the bottom of the image. */ - if (main_ptr->rowgroup_ctr != DCTSIZE) + if (main_ptr->rowgroup_ctr != data_unit) return; /* Send the completed row to the compressor */ - if (!(*cinfo->coef->compress_data) (cinfo, main_ptr->buffer)) { + if (!(*cinfo->coef->_compress_data) (cinfo, main_ptr->buffer)) { /* If compressor did not consume the whole row, then we must need to * suspend processing and return to the application. In this situation * we pretend we didn't yet consume the last input row; otherwise, if @@ -128,11 +133,15 @@ process_data_simple_main(j_compress_ptr cinfo, JSAMPARRAY input_buf, */ GLOBAL(void) -jinit_c_main_controller(j_compress_ptr cinfo, boolean need_full_buffer) +_jinit_c_main_controller(j_compress_ptr cinfo, boolean need_full_buffer) { my_main_ptr main_ptr; int ci; jpeg_component_info *compptr; + int data_unit = cinfo->master->lossless ? 1 : DCTSIZE; + + if (cinfo->data_precision != BITS_IN_JSAMPLE) + ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision); main_ptr = (my_main_ptr) (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE, @@ -153,10 +162,12 @@ jinit_c_main_controller(j_compress_ptr cinfo, boolean need_full_buffer) /* Allocate a strip buffer for each component */ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { - main_ptr->buffer[ci] = (*cinfo->mem->alloc_sarray) + main_ptr->buffer[ci] = (_JSAMPARRAY)(*cinfo->mem->alloc_sarray) ((j_common_ptr)cinfo, JPOOL_IMAGE, - compptr->width_in_blocks * DCTSIZE, - (JDIMENSION)(compptr->v_samp_factor * DCTSIZE)); + compptr->width_in_blocks * data_unit, + (JDIMENSION)(compptr->v_samp_factor * data_unit)); } } } + +#endif /* BITS_IN_JSAMPLE != 16 || defined(C_LOSSLESS_SUPPORTED) */ diff --git a/src/3rdparty/libjpeg/src/jcmarker.c b/src/3rdparty/libjpeg/src/jcmarker.c index 801fbab4ef0..a064d4dd9e7 100644 --- a/src/3rdparty/libjpeg/src/jcmarker.c +++ b/src/3rdparty/libjpeg/src/jcmarker.c @@ -4,8 +4,10 @@ * This file was part of the Independent JPEG Group's software: * Copyright (C) 1991-1998, Thomas G. Lane. * Modified 2003-2010 by Guido Vollbeding. + * Lossless JPEG Modifications: + * Copyright (C) 1999, Ken Murchison. * libjpeg-turbo Modifications: - * Copyright (C) 2010, D. R. Commander. + * Copyright (C) 2010, 2022, D. R. Commander. * For conditions of distribution and use, see the accompanying README.ijg * file. * @@ -15,7 +17,7 @@ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" -#include "jpegcomp.h" +#include "jpegapicomp.h" typedef enum { /* JPEG marker codes */ @@ -497,25 +499,26 @@ write_file_header(j_compress_ptr cinfo) METHODDEF(void) write_frame_header(j_compress_ptr cinfo) { - int ci, prec; + int ci, prec = 0; boolean is_baseline; jpeg_component_info *compptr; - /* Emit DQT for each quantization table. - * Note that emit_dqt() suppresses any duplicate tables. - */ - prec = 0; - for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { - prec += emit_dqt(cinfo, compptr->quant_tbl_no); + if (!cinfo->master->lossless) { + /* Emit DQT for each quantization table. + * Note that emit_dqt() suppresses any duplicate tables. + */ + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + prec += emit_dqt(cinfo, compptr->quant_tbl_no); + } + /* now prec is nonzero iff there are any 16-bit quant tables. */ } - /* now prec is nonzero iff there are any 16-bit quant tables. */ /* Check for a non-baseline specification. * Note we assume that Huffman table numbers won't be changed later. */ if (cinfo->arith_code || cinfo->progressive_mode || - cinfo->data_precision != 8) { + cinfo->master->lossless || cinfo->data_precision != 8) { is_baseline = FALSE; } else { is_baseline = TRUE; @@ -540,6 +543,8 @@ write_frame_header(j_compress_ptr cinfo) } else { if (cinfo->progressive_mode) emit_sof(cinfo, M_SOF2); /* SOF code for progressive Huffman */ + else if (cinfo->master->lossless) + emit_sof(cinfo, M_SOF3); /* SOF code for lossless Huffman */ else if (is_baseline) emit_sof(cinfo, M_SOF0); /* SOF code for baseline implementation */ else @@ -574,10 +579,11 @@ write_scan_header(j_compress_ptr cinfo) for (i = 0; i < cinfo->comps_in_scan; i++) { compptr = cinfo->cur_comp_info[i]; /* DC needs no table for refinement scan */ - if (cinfo->Ss == 0 && cinfo->Ah == 0) + if ((cinfo->Ss == 0 && cinfo->Ah == 0) || cinfo->master->lossless) emit_dht(cinfo, compptr->dc_tbl_no, FALSE); - /* AC needs no table when not present */ - if (cinfo->Se) + /* AC needs no table when not present, and lossless mode uses only DC + tables. */ + if (cinfo->Se && !cinfo->master->lossless) emit_dht(cinfo, compptr->ac_tbl_no, TRUE); } } diff --git a/src/3rdparty/libjpeg/src/jcmaster.c b/src/3rdparty/libjpeg/src/jcmaster.c index b821710ac30..7e1408fcc94 100644 --- a/src/3rdparty/libjpeg/src/jcmaster.c +++ b/src/3rdparty/libjpeg/src/jcmaster.c @@ -4,8 +4,10 @@ * This file was part of the Independent JPEG Group's software: * Copyright (C) 1991-1997, Thomas G. Lane. * Modified 2003-2010 by Guido Vollbeding. + * Lossless JPEG Modifications: + * Copyright (C) 1999, Ken Murchison. * libjpeg-turbo Modifications: - * Copyright (C) 2010, 2016, 2018, D. R. Commander. + * Copyright (C) 2010, 2016, 2018, 2022-2023, D. R. Commander. * For conditions of distribution and use, see the accompanying README.ijg * file. * @@ -18,39 +20,8 @@ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" -#include "jpegcomp.h" - - -/* Private state */ - -typedef enum { - main_pass, /* input data, also do first output step */ - huff_opt_pass, /* Huffman code optimization pass */ - output_pass /* data output pass */ -} c_pass_type; - -typedef struct { - struct jpeg_comp_master pub; /* public fields */ - - c_pass_type pass_type; /* the type of the current pass */ - - int pass_number; /* # of passes completed */ - int total_passes; /* total # of passes needed */ - - int scan_number; /* current index in scan_info[] */ - - /* - * This is here so we can add libjpeg-turbo version/build information to the - * global string table without introducing a new global symbol. Adding this - * information to the global string table allows one to examine a binary - * object and determine which version of libjpeg-turbo it was built from or - * linked against. - */ - const char *jpeg_version; - -} my_comp_master; - -typedef my_comp_master *my_master_ptr; +#include "jpegapicomp.h" +#include "jcmaster.h" /* @@ -68,11 +39,13 @@ GLOBAL(void) jpeg_calc_jpeg_dimensions(j_compress_ptr cinfo) /* Do computations that are needed before master selection phase */ { + int data_unit = cinfo->master->lossless ? 1 : DCTSIZE; + /* Hardwire it to "no scaling" */ cinfo->jpeg_width = cinfo->image_width; cinfo->jpeg_height = cinfo->image_height; - cinfo->min_DCT_h_scaled_size = DCTSIZE; - cinfo->min_DCT_v_scaled_size = DCTSIZE; + cinfo->min_DCT_h_scaled_size = data_unit; + cinfo->min_DCT_v_scaled_size = data_unit; } #endif @@ -85,6 +58,7 @@ initial_setup(j_compress_ptr cinfo, boolean transcode_only) jpeg_component_info *compptr; long samplesperrow; JDIMENSION jd_samplesperrow; + int data_unit = cinfo->master->lossless ? 1 : DCTSIZE; #if JPEG_LIB_VERSION >= 70 #if JPEG_LIB_VERSION >= 80 @@ -109,8 +83,12 @@ initial_setup(j_compress_ptr cinfo, boolean transcode_only) if ((long)jd_samplesperrow != samplesperrow) ERREXIT(cinfo, JERR_WIDTH_OVERFLOW); - /* For now, precision must match compiled-in value... */ - if (cinfo->data_precision != BITS_IN_JSAMPLE) +#ifdef C_LOSSLESS_SUPPORTED + if (cinfo->data_precision != 8 && cinfo->data_precision != 12 && + cinfo->data_precision != 16) +#else + if (cinfo->data_precision != 8 && cinfo->data_precision != 12) +#endif ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision); /* Check that number of components won't exceed internal array sizes */ @@ -141,17 +119,17 @@ initial_setup(j_compress_ptr cinfo, boolean transcode_only) compptr->component_index = ci; /* For compression, we never do DCT scaling. */ #if JPEG_LIB_VERSION >= 70 - compptr->DCT_h_scaled_size = compptr->DCT_v_scaled_size = DCTSIZE; + compptr->DCT_h_scaled_size = compptr->DCT_v_scaled_size = data_unit; #else - compptr->DCT_scaled_size = DCTSIZE; + compptr->DCT_scaled_size = data_unit; #endif - /* Size in DCT blocks */ + /* Size in data units */ compptr->width_in_blocks = (JDIMENSION) jdiv_round_up((long)cinfo->_jpeg_width * (long)compptr->h_samp_factor, - (long)(cinfo->max_h_samp_factor * DCTSIZE)); + (long)(cinfo->max_h_samp_factor * data_unit)); compptr->height_in_blocks = (JDIMENSION) jdiv_round_up((long)cinfo->_jpeg_height * (long)compptr->v_samp_factor, - (long)(cinfo->max_v_samp_factor * DCTSIZE)); + (long)(cinfo->max_v_samp_factor * data_unit)); /* Size in samples */ compptr->downsampled_width = (JDIMENSION) jdiv_round_up((long)cinfo->_jpeg_width * (long)compptr->h_samp_factor, @@ -164,15 +142,19 @@ initial_setup(j_compress_ptr cinfo, boolean transcode_only) } /* Compute number of fully interleaved MCU rows (number of times that - * main controller will call coefficient controller). + * main controller will call coefficient or difference controller). */ cinfo->total_iMCU_rows = (JDIMENSION) jdiv_round_up((long)cinfo->_jpeg_height, - (long)(cinfo->max_v_samp_factor * DCTSIZE)); + (long)(cinfo->max_v_samp_factor * data_unit)); } -#ifdef C_MULTISCAN_FILES_SUPPORTED +#if defined(C_MULTISCAN_FILES_SUPPORTED) || defined(C_LOSSLESS_SUPPORTED) +#define NEED_SCAN_SCRIPT +#endif + +#ifdef NEED_SCAN_SCRIPT LOCAL(void) validate_script(j_compress_ptr cinfo) @@ -193,13 +175,29 @@ validate_script(j_compress_ptr cinfo) if (cinfo->num_scans <= 0) ERREXIT1(cinfo, JERR_BAD_SCAN_SCRIPT, 0); +#ifndef C_MULTISCAN_FILES_SUPPORTED + if (cinfo->num_scans > 1) + ERREXIT(cinfo, JERR_NOT_COMPILED); +#endif + + scanptr = cinfo->scan_info; + if (scanptr->Ss != 0 && scanptr->Se == 0) { +#ifdef C_LOSSLESS_SUPPORTED + cinfo->master->lossless = TRUE; + cinfo->progressive_mode = FALSE; + for (ci = 0; ci < cinfo->num_components; ci++) + component_sent[ci] = FALSE; +#else + ERREXIT(cinfo, JERR_NOT_COMPILED); +#endif + } /* For sequential JPEG, all scans must have Ss=0, Se=DCTSIZE2-1; * for progressive JPEG, no scan can have this. */ - scanptr = cinfo->scan_info; - if (scanptr->Ss != 0 || scanptr->Se != DCTSIZE2 - 1) { + else if (scanptr->Ss != 0 || scanptr->Se != DCTSIZE2 - 1) { #ifdef C_PROGRESSIVE_SUPPORTED cinfo->progressive_mode = TRUE; + cinfo->master->lossless = FALSE; last_bitpos_ptr = &last_bitpos[0][0]; for (ci = 0; ci < cinfo->num_components; ci++) for (coefi = 0; coefi < DCTSIZE2; coefi++) @@ -208,7 +206,7 @@ validate_script(j_compress_ptr cinfo) ERREXIT(cinfo, JERR_NOT_COMPILED); #endif } else { - cinfo->progressive_mode = FALSE; + cinfo->progressive_mode = cinfo->master->lossless = FALSE; for (ci = 0; ci < cinfo->num_components; ci++) component_sent[ci] = FALSE; } @@ -240,13 +238,10 @@ validate_script(j_compress_ptr cinfo) * out-of-range reconstructed DC values during the first DC scan, * which might cause problems for some decoders. */ -#if BITS_IN_JSAMPLE == 8 -#define MAX_AH_AL 10 -#else -#define MAX_AH_AL 13 -#endif + int max_Ah_Al = cinfo->data_precision == 12 ? 13 : 10; + if (Ss < 0 || Ss >= DCTSIZE2 || Se < Ss || Se >= DCTSIZE2 || - Ah < 0 || Ah > MAX_AH_AL || Al < 0 || Al > MAX_AH_AL) + Ah < 0 || Ah > max_Ah_Al || Al < 0 || Al > max_Ah_Al) ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno); if (Ss == 0) { if (Se != 0) /* DC and AC together not OK */ @@ -274,9 +269,25 @@ validate_script(j_compress_ptr cinfo) } #endif } else { - /* For sequential JPEG, all progression parameters must be these: */ - if (Ss != 0 || Se != DCTSIZE2 - 1 || Ah != 0 || Al != 0) - ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno); +#ifdef C_LOSSLESS_SUPPORTED + if (cinfo->master->lossless) { + /* The JPEG spec simply gives the range 0..15 for Al (Pt), but that + * seems wrong: the upper bound ought to depend on data precision. + * Perhaps they really meant 0..N-1 for N-bit precision, which is what + * we allow here. Values greater than or equal to the data precision + * will result in a blank image. + */ + if (Ss < 1 || Ss > 7 || /* predictor selection value */ + Se != 0 || Ah != 0 || + Al < 0 || Al >= cinfo->data_precision) /* point transform */ + ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno); + } else +#endif + { + /* For sequential JPEG, all progression parameters must be these: */ + if (Ss != 0 || Se != DCTSIZE2 - 1 || Ah != 0 || Al != 0) + ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno); + } /* Make sure components are not sent twice */ for (ci = 0; ci < ncomps; ci++) { thisi = scanptr->component_index[ci]; @@ -308,7 +319,7 @@ validate_script(j_compress_ptr cinfo) } } -#endif /* C_MULTISCAN_FILES_SUPPORTED */ +#endif /* NEED_SCAN_SCRIPT */ LOCAL(void) @@ -317,7 +328,7 @@ select_scan_parameters(j_compress_ptr cinfo) { int ci; -#ifdef C_MULTISCAN_FILES_SUPPORTED +#ifdef NEED_SCAN_SCRIPT if (cinfo->scan_info != NULL) { /* Prepare for current scan --- the script is already validated */ my_master_ptr master = (my_master_ptr)cinfo->master; @@ -343,10 +354,12 @@ select_scan_parameters(j_compress_ptr cinfo) for (ci = 0; ci < cinfo->num_components; ci++) { cinfo->cur_comp_info[ci] = &cinfo->comp_info[ci]; } - cinfo->Ss = 0; - cinfo->Se = DCTSIZE2 - 1; - cinfo->Ah = 0; - cinfo->Al = 0; + if (!cinfo->master->lossless) { + cinfo->Ss = 0; + cinfo->Se = DCTSIZE2 - 1; + cinfo->Ah = 0; + cinfo->Al = 0; + } } } @@ -358,6 +371,7 @@ per_scan_setup(j_compress_ptr cinfo) { int ci, mcublks, tmp; jpeg_component_info *compptr; + int data_unit = cinfo->master->lossless ? 1 : DCTSIZE; if (cinfo->comps_in_scan == 1) { @@ -372,7 +386,7 @@ per_scan_setup(j_compress_ptr cinfo) compptr->MCU_width = 1; compptr->MCU_height = 1; compptr->MCU_blocks = 1; - compptr->MCU_sample_width = DCTSIZE; + compptr->MCU_sample_width = data_unit; compptr->last_col_width = 1; /* For noninterleaved scans, it is convenient to define last_row_height * as the number of block rows present in the last iMCU row. @@ -395,10 +409,10 @@ per_scan_setup(j_compress_ptr cinfo) /* Overall image size in MCUs */ cinfo->MCUs_per_row = (JDIMENSION) jdiv_round_up((long)cinfo->_jpeg_width, - (long)(cinfo->max_h_samp_factor * DCTSIZE)); + (long)(cinfo->max_h_samp_factor * data_unit)); cinfo->MCU_rows_in_scan = (JDIMENSION) jdiv_round_up((long)cinfo->_jpeg_height, - (long)(cinfo->max_v_samp_factor * DCTSIZE)); + (long)(cinfo->max_v_samp_factor * data_unit)); cinfo->blocks_in_MCU = 0; @@ -408,7 +422,7 @@ per_scan_setup(j_compress_ptr cinfo) compptr->MCU_width = compptr->h_samp_factor; compptr->MCU_height = compptr->v_samp_factor; compptr->MCU_blocks = compptr->MCU_width * compptr->MCU_height; - compptr->MCU_sample_width = compptr->MCU_width * DCTSIZE; + compptr->MCU_sample_width = compptr->MCU_width * data_unit; /* Figure number of non-dummy blocks in last MCU column & row */ tmp = (int)(compptr->width_in_blocks % compptr->MCU_width); if (tmp == 0) tmp = compptr->MCU_width; @@ -480,7 +494,8 @@ prepare_for_pass(j_compress_ptr cinfo) /* Do Huffman optimization for a scan after the first one. */ select_scan_parameters(cinfo); per_scan_setup(cinfo); - if (cinfo->Ss != 0 || cinfo->Ah == 0 || cinfo->arith_code) { + if (cinfo->Ss != 0 || cinfo->Ah == 0 || cinfo->arith_code || + cinfo->master->lossless) { (*cinfo->entropy->start_pass) (cinfo, TRUE); (*cinfo->coef->start_pass) (cinfo, JBUF_CRANK_DEST); master->pub.call_pass_startup = FALSE; @@ -589,22 +604,15 @@ finish_pass_master(j_compress_ptr cinfo) GLOBAL(void) jinit_c_master_control(j_compress_ptr cinfo, boolean transcode_only) { - my_master_ptr master; + my_master_ptr master = (my_master_ptr)cinfo->master; - master = (my_master_ptr) - (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE, - sizeof(my_comp_master)); - cinfo->master = (struct jpeg_comp_master *)master; master->pub.prepare_for_pass = prepare_for_pass; master->pub.pass_startup = pass_startup; master->pub.finish_pass = finish_pass_master; master->pub.is_last_pass = FALSE; - /* Validate parameters, determine derived values */ - initial_setup(cinfo, transcode_only); - if (cinfo->scan_info != NULL) { -#ifdef C_MULTISCAN_FILES_SUPPORTED +#ifdef NEED_SCAN_SCRIPT validate_script(cinfo); #else ERREXIT(cinfo, JERR_NOT_COMPILED); @@ -614,8 +622,33 @@ jinit_c_master_control(j_compress_ptr cinfo, boolean transcode_only) cinfo->num_scans = 1; } - if (cinfo->progressive_mode && !cinfo->arith_code) /* TEMPORARY HACK ??? */ - cinfo->optimize_coding = TRUE; /* assume default tables no good for progressive mode */ + /* Disable smoothing and subsampling in lossless mode, since those are lossy + * algorithms. Set the JPEG colorspace to the input colorspace. Disable raw + * (downsampled) data input, because it isn't particularly useful without + * subsampling and has not been tested in lossless mode. + */ + if (cinfo->master->lossless) { + int ci; + jpeg_component_info *compptr; + + cinfo->raw_data_in = FALSE; + cinfo->smoothing_factor = 0; + jpeg_default_colorspace(cinfo); + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) + compptr->h_samp_factor = compptr->v_samp_factor = 1; + } + + /* Validate parameters, determine derived values */ + initial_setup(cinfo, transcode_only); + + if (cinfo->master->lossless || /* TEMPORARY HACK ??? */ + (cinfo->progressive_mode && !cinfo->arith_code)) + cinfo->optimize_coding = TRUE; /* assume default tables no good for + progressive mode or lossless mode */ + if (cinfo->data_precision == 12 && !cinfo->arith_code) + cinfo->optimize_coding = TRUE; /* assume default tables no good for 12-bit + data precision */ /* Initialize my private state */ if (transcode_only) { diff --git a/src/3rdparty/libjpeg/src/jcmaster.h b/src/3rdparty/libjpeg/src/jcmaster.h new file mode 100644 index 00000000000..3b13289b691 --- /dev/null +++ b/src/3rdparty/libjpeg/src/jcmaster.h @@ -0,0 +1,43 @@ +/* + * jcmaster.h + * + * This file was part of the Independent JPEG Group's software: + * Copyright (C) 1991-1995, Thomas G. Lane. + * libjpeg-turbo Modifications: + * Copyright (C) 2016, D. R. Commander. + * For conditions of distribution and use, see the accompanying README.ijg + * file. + * + * This file contains master control structure for the JPEG compressor. + */ + +/* Private state */ + +typedef enum { + main_pass, /* input data, also do first output step */ + huff_opt_pass, /* Huffman code optimization pass */ + output_pass /* data output pass */ +} c_pass_type; + +typedef struct { + struct jpeg_comp_master pub; /* public fields */ + + c_pass_type pass_type; /* the type of the current pass */ + + int pass_number; /* # of passes completed */ + int total_passes; /* total # of passes needed */ + + int scan_number; /* current index in scan_info[] */ + + /* + * This is here so we can add libjpeg-turbo version/build information to the + * global string table without introducing a new global symbol. Adding this + * information to the global string table allows one to examine a binary + * object and determine which version of libjpeg-turbo it was built from or + * linked against. + */ + const char *jpeg_version; + +} my_comp_master; + +typedef my_comp_master *my_master_ptr; diff --git a/src/3rdparty/libjpeg/src/jconfig.h b/src/3rdparty/libjpeg/src/jconfig.h index 51050d04347..a91be588e7b 100644 --- a/src/3rdparty/libjpeg/src/jconfig.h +++ b/src/3rdparty/libjpeg/src/jconfig.h @@ -2,9 +2,9 @@ #define JPEG_LIB_VERSION 80 -#define LIBJPEG_TURBO_VERSION 2.1.5 +#define LIBJPEG_TURBO_VERSION 3.0.0 -#define LIBJPEG_TURBO_VERSION_NUMBER 2001005 +#define LIBJPEG_TURBO_VERSION_NUMBER 3000000 #define C_ARITH_CODING_SUPPORTED 1 @@ -12,6 +12,8 @@ #define MEM_SRCDST_SUPPORTED 1 -#define BITS_IN_JSAMPLE 8 +#ifndef BITS_IN_JSAMPLE +#define BITS_IN_JSAMPLE 8 +#endif #define NO_PUTENV diff --git a/src/3rdparty/libjpeg/src/jconfig.h.in b/src/3rdparty/libjpeg/src/jconfig.h.in index e0180122fed..6cb82962ffe 100644 --- a/src/3rdparty/libjpeg/src/jconfig.h.in +++ b/src/3rdparty/libjpeg/src/jconfig.h.in @@ -9,29 +9,52 @@ /* libjpeg-turbo version in integer form */ #define LIBJPEG_TURBO_VERSION_NUMBER @LIBJPEG_TURBO_VERSION_NUMBER@ -/* Support arithmetic encoding */ +/* Support arithmetic encoding when using 8-bit samples */ #cmakedefine C_ARITH_CODING_SUPPORTED 1 -/* Support arithmetic decoding */ +/* Support arithmetic decoding when using 8-bit samples */ #cmakedefine D_ARITH_CODING_SUPPORTED 1 /* Support in-memory source/destination managers */ -#cmakedefine MEM_SRCDST_SUPPORTED 1 +#define MEM_SRCDST_SUPPORTED 1 -/* Use accelerated SIMD routines. */ +/* Use accelerated SIMD routines when using 8-bit samples */ #cmakedefine WITH_SIMD 1 -/* - * Define BITS_IN_JSAMPLE as either - * 8 for 8-bit sample values (the usual setting) - * 12 for 12-bit sample values - * Only 8 and 12 are legal data precisions for lossy JPEG according to the - * JPEG standard, and the IJG code does not support anything else! - * We do not support run-time selection of data precision, sorry. +/* This version of libjpeg-turbo supports run-time selection of data precision, + * so BITS_IN_JSAMPLE is no longer used to specify the data precision at build + * time. However, some downstream software expects the macro to be defined. + * Since 12-bit data precision is an opt-in feature that requires explicitly + * calling 12-bit-specific libjpeg API functions and using 12-bit-specific data + * types, the unmodified portion of the libjpeg API still behaves as if it were + * built for 8-bit precision, and JSAMPLE is still literally an 8-bit data + * type. Thus, it is correct to define BITS_IN_JSAMPLE to 8 here. */ +#ifndef BITS_IN_JSAMPLE +#define BITS_IN_JSAMPLE 8 +#endif -#define BITS_IN_JSAMPLE @BITS_IN_JSAMPLE@ /* use 8 or 12 */ +#ifdef _WIN32 + +#undef RIGHT_SHIFT_IS_UNSIGNED + +/* Define "boolean" as unsigned char, not int, per Windows custom */ +#ifndef __RPCNDR_H__ /* don't conflict if rpcndr.h already read */ +typedef unsigned char boolean; +#endif +#define HAVE_BOOLEAN /* prevent jmorecfg.h from redefining it */ + +/* Define "INT32" as int, not long, per Windows custom */ +#if !(defined(_BASETSD_H_) || defined(_BASETSD_H)) /* don't conflict if basetsd.h already read */ +typedef short INT16; +typedef signed int INT32; +#endif +#define XMD_H /* prevent jmorecfg.h from redefining it */ + +#else /* Define if your (broken) compiler shifts signed values as if they were unsigned. */ #cmakedefine RIGHT_SHIFT_IS_UNSIGNED 1 + +#endif diff --git a/src/3rdparty/libjpeg/src/jconfigint.h b/src/3rdparty/libjpeg/src/jconfigint.h index 97edb319634..a58061e52bb 100644 --- a/src/3rdparty/libjpeg/src/jconfigint.h +++ b/src/3rdparty/libjpeg/src/jconfigint.h @@ -8,7 +8,7 @@ #define PACKAGE_NAME "libjpeg-turbo" -#define VERSION "2.1.5" +#define VERSION "3.0.0" #if SIZE_MAX == 0xffffffff #define SIZEOF_SIZE_T 4 @@ -16,4 +16,33 @@ #define SIZEOF_SIZE_T 8 #endif +#if defined(_MSC_VER) && defined(HAVE_INTRIN_H) +#if (SIZEOF_SIZE_T == 8) +#define HAVE_BITSCANFORWARD64 +#elif (SIZEOF_SIZE_T == 4) +#define HAVE_BITSCANFORWARD +#endif +#endif + #define FALLTHROUGH + +#ifndef BITS_IN_JSAMPLE +#define BITS_IN_JSAMPLE 8 /* use 8 or 12 */ +#endif + +#undef C_ARITH_CODING_SUPPORTED +#undef D_ARITH_CODING_SUPPORTED +#undef WITH_SIMD + +#if BITS_IN_JSAMPLE == 8 + +/* Support arithmetic encoding */ +#define C_ARITH_CODING_SUPPORTED 1 + +/* Support arithmetic decoding */ +#define D_ARITH_CODING_SUPPORTED 1 + +/* Use accelerated SIMD routines. */ +/* #undef WITH_SIMD */ + +#endif diff --git a/src/3rdparty/libjpeg/src/jconfigint.h.in b/src/3rdparty/libjpeg/src/jconfigint.h.in index d087d7b5537..e7e66e74c02 100644 --- a/src/3rdparty/libjpeg/src/jconfigint.h.in +++ b/src/3rdparty/libjpeg/src/jconfigint.h.in @@ -42,3 +42,32 @@ #else #define FALLTHROUGH #endif + +/* + * Define BITS_IN_JSAMPLE as either + * 8 for 8-bit sample values (the usual setting) + * 12 for 12-bit sample values + * Only 8 and 12 are legal data precisions for lossy JPEG according to the + * JPEG standard, and the IJG code does not support anything else! + */ + +#ifndef BITS_IN_JSAMPLE +#define BITS_IN_JSAMPLE 8 /* use 8 or 12 */ +#endif + +#undef C_ARITH_CODING_SUPPORTED +#undef D_ARITH_CODING_SUPPORTED +#undef WITH_SIMD + +#if BITS_IN_JSAMPLE == 8 + +/* Support arithmetic encoding */ +#cmakedefine C_ARITH_CODING_SUPPORTED 1 + +/* Support arithmetic decoding */ +#cmakedefine D_ARITH_CODING_SUPPORTED 1 + +/* Use accelerated SIMD routines. */ +#cmakedefine WITH_SIMD 1 + +#endif diff --git a/src/3rdparty/libjpeg/src/jcparam.c b/src/3rdparty/libjpeg/src/jcparam.c index 5bc7174dcb5..d1dee4da3df 100644 --- a/src/3rdparty/libjpeg/src/jcparam.c +++ b/src/3rdparty/libjpeg/src/jcparam.c @@ -4,8 +4,10 @@ * This file was part of the Independent JPEG Group's software: * Copyright (C) 1991-1998, Thomas G. Lane. * Modified 2003-2008 by Guido Vollbeding. + * Lossless JPEG Modifications: + * Copyright (C) 1999, Ken Murchison. * libjpeg-turbo Modifications: - * Copyright (C) 2009-2011, 2018, D. R. Commander. + * Copyright (C) 2009-2011, 2018, 2023, D. R. Commander. * For conditions of distribution and use, see the accompanying README.ijg * file. * @@ -202,7 +204,6 @@ jpeg_set_defaults(j_compress_ptr cinfo) cinfo->scale_num = 1; /* 1:1 scaling */ cinfo->scale_denom = 1; #endif - cinfo->data_precision = BITS_IN_JSAMPLE; /* Set up two quantization tables using default quality of 75 */ jpeg_set_quality(cinfo, 75, TRUE); /* Set up two Huffman tables */ @@ -232,7 +233,7 @@ jpeg_set_defaults(j_compress_ptr cinfo) * tables will be computed. This test can be removed if default tables * are supplied that are valid for the desired precision. */ - if (cinfo->data_precision > 8) + if (cinfo->data_precision == 12 && !cinfo->arith_code) cinfo->optimize_coding = TRUE; /* By default, use the simpler non-cosited sampling alignment */ @@ -296,7 +297,10 @@ jpeg_default_colorspace(j_compress_ptr cinfo) case JCS_EXT_BGRA: case JCS_EXT_ABGR: case JCS_EXT_ARGB: - jpeg_set_colorspace(cinfo, JCS_YCbCr); + if (cinfo->master->lossless) + jpeg_set_colorspace(cinfo, JCS_RGB); + else + jpeg_set_colorspace(cinfo, JCS_YCbCr); break; case JCS_YCbCr: jpeg_set_colorspace(cinfo, JCS_YCbCr); @@ -475,6 +479,11 @@ jpeg_simple_progression(j_compress_ptr cinfo) if (cinfo->global_state != CSTATE_START) ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + if (cinfo->master->lossless) { + cinfo->master->lossless = FALSE; + jpeg_default_colorspace(cinfo); + } + /* Figure space needed for script. Calculation must match code below! */ if (ncomps == 3 && cinfo->jpeg_color_space == JCS_YCbCr) { /* Custom script for YCbCr color images. */ @@ -539,3 +548,38 @@ jpeg_simple_progression(j_compress_ptr cinfo) } #endif /* C_PROGRESSIVE_SUPPORTED */ + + +#ifdef C_LOSSLESS_SUPPORTED + +/* + * Enable lossless mode. + */ + +GLOBAL(void) +jpeg_enable_lossless(j_compress_ptr cinfo, int predictor_selection_value, + int point_transform) +{ + /* Safety check to ensure start_compress not called yet. */ + if (cinfo->global_state != CSTATE_START) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + + cinfo->master->lossless = TRUE; + cinfo->Ss = predictor_selection_value; + cinfo->Se = 0; + cinfo->Ah = 0; + cinfo->Al = point_transform; + + /* The JPEG spec simply gives the range 0..15 for Al (Pt), but that seems + * wrong: the upper bound ought to depend on data precision. Perhaps they + * really meant 0..N-1 for N-bit precision, which is what we allow here. + * Values greater than or equal to the data precision will result in a blank + * image. + */ + if (cinfo->Ss < 1 || cinfo->Ss > 7 || + cinfo->Al < 0 || cinfo->Al >= cinfo->data_precision) + ERREXIT4(cinfo, JERR_BAD_PROGRESSION, + cinfo->Ss, cinfo->Se, cinfo->Ah, cinfo->Al); +} + +#endif /* C_LOSSLESS_SUPPORTED */ diff --git a/src/3rdparty/libjpeg/src/jcphuff.c b/src/3rdparty/libjpeg/src/jcphuff.c index 5006b670751..56e63bd62d3 100644 --- a/src/3rdparty/libjpeg/src/jcphuff.c +++ b/src/3rdparty/libjpeg/src/jcphuff.c @@ -3,6 +3,8 @@ * * This file was part of the Independent JPEG Group's software: * Copyright (C) 1995-1997, Thomas G. Lane. + * Lossless JPEG Modifications: + * Copyright (C) 1999, Ken Murchison. * libjpeg-turbo Modifications: * Copyright (C) 2011, 2015, 2018, 2021-2022, D. R. Commander. * Copyright (C) 2016, 2018, 2022, Matthieu Darbois. @@ -21,7 +23,11 @@ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" +#ifdef WITH_SIMD #include "jsimd.h" +#else +#include "jchuff.h" /* Declarations shared with jc*huff.c */ +#endif #include #ifdef HAVE_INTRIN_H @@ -223,18 +229,22 @@ start_pass_phuff(j_compress_ptr cinfo, boolean gather_statistics) entropy->pub.encode_mcu = encode_mcu_DC_first; else entropy->pub.encode_mcu = encode_mcu_AC_first; +#ifdef WITH_SIMD if (jsimd_can_encode_mcu_AC_first_prepare()) entropy->AC_first_prepare = jsimd_encode_mcu_AC_first_prepare; else +#endif entropy->AC_first_prepare = encode_mcu_AC_first_prepare; } else { if (is_DC_band) entropy->pub.encode_mcu = encode_mcu_DC_refine; else { entropy->pub.encode_mcu = encode_mcu_AC_refine; +#ifdef WITH_SIMD if (jsimd_can_encode_mcu_AC_refine_prepare()) entropy->AC_refine_prepare = jsimd_encode_mcu_AC_refine_prepare; else +#endif entropy->AC_refine_prepare = encode_mcu_AC_refine_prepare; /* AC refinement needs a correction bit buffer */ if (entropy->bit_buffer == NULL) @@ -489,6 +499,7 @@ encode_mcu_DC_first(j_compress_ptr cinfo, JBLOCKROW *MCU_data) JBLOCKROW block; jpeg_component_info *compptr; ISHIFT_TEMPS + int max_coef_bits = cinfo->data_precision + 2; entropy->next_output_byte = cinfo->dest->next_output_byte; entropy->free_in_buffer = cinfo->dest->free_in_buffer; @@ -531,7 +542,7 @@ encode_mcu_DC_first(j_compress_ptr cinfo, JBLOCKROW *MCU_data) /* Check for out-of-range coefficient values. * Since we're encoding a difference, the range limit is twice as much. */ - if (nbits > MAX_COEF_BITS + 1) + if (nbits > max_coef_bits + 1) ERREXIT(cinfo, JERR_BAD_DCT_COEF); /* Count/emit the Huffman-coded symbol for the number of bits */ @@ -642,7 +653,7 @@ label \ /* Find the number of bits needed for the magnitude of the coefficient */ \ nbits = JPEG_NBITS_NONZERO(temp); /* there must be at least one 1 bit */ \ /* Check for out-of-range coefficient values */ \ - if (nbits > MAX_COEF_BITS) \ + if (nbits > max_coef_bits) \ ERREXIT(cinfo, JERR_BAD_DCT_COEF); \ \ /* Count/emit Huffman symbol for run length / number of bits */ \ @@ -670,6 +681,7 @@ encode_mcu_AC_first(j_compress_ptr cinfo, JBLOCKROW *MCU_data) const UJCOEF *cvalue; size_t zerobits; size_t bits[8 / SIZEOF_SIZE_T]; + int max_coef_bits = cinfo->data_precision + 2; entropy->next_output_byte = cinfo->dest->next_output_byte; entropy->free_in_buffer = cinfo->dest->free_in_buffer; diff --git a/src/3rdparty/libjpeg/src/jcprepct.c b/src/3rdparty/libjpeg/src/jcprepct.c index f27cc345079..ac2311c1388 100644 --- a/src/3rdparty/libjpeg/src/jcprepct.c +++ b/src/3rdparty/libjpeg/src/jcprepct.c @@ -1,8 +1,10 @@ /* * jcprepct.c * - * This file is part of the Independent JPEG Group's software: + * This file was part of the Independent JPEG Group's software: * Copyright (C) 1994-1996, Thomas G. Lane. + * Lossless JPEG Modifications: + * Copyright (C) 1999, Ken Murchison. * libjpeg-turbo Modifications: * Copyright (C) 2022, D. R. Commander. * For conditions of distribution and use, see the accompanying README.ijg @@ -20,8 +22,11 @@ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" +#include "jsamplecomp.h" +#if BITS_IN_JSAMPLE != 16 || defined(C_LOSSLESS_SUPPORTED) + /* At present, jcsample.c can request context rows only for smoothing. * In the future, we might also need context rows for CCIR601 sampling * or other more-complex downsampling procedures. The code to support @@ -59,7 +64,7 @@ typedef struct { /* Downsampling input buffer. This buffer holds color-converted data * until we have enough to do a downsample step. */ - JSAMPARRAY color_buf[MAX_COMPONENTS]; + _JSAMPARRAY color_buf[MAX_COMPONENTS]; JDIMENSION rows_to_go; /* counts rows remaining in source image */ int next_buf_row; /* index of next row to store in color_buf */ @@ -106,14 +111,14 @@ start_pass_prep(j_compress_ptr cinfo, J_BUF_MODE pass_mode) */ LOCAL(void) -expand_bottom_edge(JSAMPARRAY image_data, JDIMENSION num_cols, int input_rows, +expand_bottom_edge(_JSAMPARRAY image_data, JDIMENSION num_cols, int input_rows, int output_rows) { register int row; for (row = input_rows; row < output_rows; row++) { - jcopy_sample_rows(image_data, input_rows - 1, image_data, row, 1, - num_cols); + _jcopy_sample_rows(image_data, input_rows - 1, image_data, row, 1, + num_cols); } } @@ -128,15 +133,16 @@ expand_bottom_edge(JSAMPARRAY image_data, JDIMENSION num_cols, int input_rows, */ METHODDEF(void) -pre_process_data(j_compress_ptr cinfo, JSAMPARRAY input_buf, +pre_process_data(j_compress_ptr cinfo, _JSAMPARRAY input_buf, JDIMENSION *in_row_ctr, JDIMENSION in_rows_avail, - JSAMPIMAGE output_buf, JDIMENSION *out_row_group_ctr, + _JSAMPIMAGE output_buf, JDIMENSION *out_row_group_ctr, JDIMENSION out_row_groups_avail) { my_prep_ptr prep = (my_prep_ptr)cinfo->prep; int numrows, ci; JDIMENSION inrows; jpeg_component_info *compptr; + int data_unit = cinfo->master->lossless ? 1 : DCTSIZE; while (*in_row_ctr < in_rows_avail && *out_row_group_ctr < out_row_groups_avail) { @@ -144,10 +150,10 @@ pre_process_data(j_compress_ptr cinfo, JSAMPARRAY input_buf, inrows = in_rows_avail - *in_row_ctr; numrows = cinfo->max_v_samp_factor - prep->next_buf_row; numrows = (int)MIN((JDIMENSION)numrows, inrows); - (*cinfo->cconvert->color_convert) (cinfo, input_buf + *in_row_ctr, - prep->color_buf, - (JDIMENSION)prep->next_buf_row, - numrows); + (*cinfo->cconvert->_color_convert) (cinfo, input_buf + *in_row_ctr, + prep->color_buf, + (JDIMENSION)prep->next_buf_row, + numrows); *in_row_ctr += numrows; prep->next_buf_row += numrows; prep->rows_to_go -= numrows; @@ -162,9 +168,9 @@ pre_process_data(j_compress_ptr cinfo, JSAMPARRAY input_buf, } /* If we've filled the conversion buffer, empty it. */ if (prep->next_buf_row == cinfo->max_v_samp_factor) { - (*cinfo->downsample->downsample) (cinfo, - prep->color_buf, (JDIMENSION)0, - output_buf, *out_row_group_ctr); + (*cinfo->downsample->_downsample) (cinfo, + prep->color_buf, (JDIMENSION)0, + output_buf, *out_row_group_ctr); prep->next_buf_row = 0; (*out_row_group_ctr)++; } @@ -174,7 +180,8 @@ pre_process_data(j_compress_ptr cinfo, JSAMPARRAY input_buf, if (prep->rows_to_go == 0 && *out_row_group_ctr < out_row_groups_avail) { for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { - expand_bottom_edge(output_buf[ci], compptr->width_in_blocks * DCTSIZE, + expand_bottom_edge(output_buf[ci], + compptr->width_in_blocks * data_unit, (int)(*out_row_group_ctr * compptr->v_samp_factor), (int)(out_row_groups_avail * compptr->v_samp_factor)); } @@ -192,9 +199,9 @@ pre_process_data(j_compress_ptr cinfo, JSAMPARRAY input_buf, */ METHODDEF(void) -pre_process_context(j_compress_ptr cinfo, JSAMPARRAY input_buf, +pre_process_context(j_compress_ptr cinfo, _JSAMPARRAY input_buf, JDIMENSION *in_row_ctr, JDIMENSION in_rows_avail, - JSAMPIMAGE output_buf, JDIMENSION *out_row_group_ctr, + _JSAMPIMAGE output_buf, JDIMENSION *out_row_group_ctr, JDIMENSION out_row_groups_avail) { my_prep_ptr prep = (my_prep_ptr)cinfo->prep; @@ -208,17 +215,17 @@ pre_process_context(j_compress_ptr cinfo, JSAMPARRAY input_buf, inrows = in_rows_avail - *in_row_ctr; numrows = prep->next_buf_stop - prep->next_buf_row; numrows = (int)MIN((JDIMENSION)numrows, inrows); - (*cinfo->cconvert->color_convert) (cinfo, input_buf + *in_row_ctr, - prep->color_buf, - (JDIMENSION)prep->next_buf_row, - numrows); + (*cinfo->cconvert->_color_convert) (cinfo, input_buf + *in_row_ctr, + prep->color_buf, + (JDIMENSION)prep->next_buf_row, + numrows); /* Pad at top of image, if first time through */ if (prep->rows_to_go == cinfo->image_height) { for (ci = 0; ci < cinfo->num_components; ci++) { int row; for (row = 1; row <= cinfo->max_v_samp_factor; row++) { - jcopy_sample_rows(prep->color_buf[ci], 0, prep->color_buf[ci], - -row, 1, cinfo->image_width); + _jcopy_sample_rows(prep->color_buf[ci], 0, prep->color_buf[ci], + -row, 1, cinfo->image_width); } } } @@ -240,9 +247,9 @@ pre_process_context(j_compress_ptr cinfo, JSAMPARRAY input_buf, } /* If we've gotten enough data, downsample a row group. */ if (prep->next_buf_row == prep->next_buf_stop) { - (*cinfo->downsample->downsample) (cinfo, prep->color_buf, - (JDIMENSION)prep->this_row_group, - output_buf, *out_row_group_ctr); + (*cinfo->downsample->_downsample) (cinfo, prep->color_buf, + (JDIMENSION)prep->this_row_group, + output_buf, *out_row_group_ctr); (*out_row_group_ctr)++; /* Advance pointers with wraparound as necessary. */ prep->this_row_group += cinfo->max_v_samp_factor; @@ -267,15 +274,16 @@ create_context_buffer(j_compress_ptr cinfo) int rgroup_height = cinfo->max_v_samp_factor; int ci, i; jpeg_component_info *compptr; - JSAMPARRAY true_buffer, fake_buffer; + _JSAMPARRAY true_buffer, fake_buffer; + int data_unit = cinfo->master->lossless ? 1 : DCTSIZE; /* Grab enough space for fake row pointers for all the components; * we need five row groups' worth of pointers for each component. */ - fake_buffer = (JSAMPARRAY) + fake_buffer = (_JSAMPARRAY) (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE, (cinfo->num_components * 5 * rgroup_height) * - sizeof(JSAMPROW)); + sizeof(_JSAMPROW)); for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { @@ -283,14 +291,14 @@ create_context_buffer(j_compress_ptr cinfo) * We make the buffer wide enough to allow the downsampler to edge-expand * horizontally within the buffer, if it so chooses. */ - true_buffer = (*cinfo->mem->alloc_sarray) + true_buffer = (_JSAMPARRAY)(*cinfo->mem->alloc_sarray) ((j_common_ptr)cinfo, JPOOL_IMAGE, - (JDIMENSION)(((long)compptr->width_in_blocks * DCTSIZE * + (JDIMENSION)(((long)compptr->width_in_blocks * data_unit * cinfo->max_h_samp_factor) / compptr->h_samp_factor), (JDIMENSION)(3 * rgroup_height)); /* Copy true buffer row pointers into the middle of the fake row array */ memcpy(fake_buffer + rgroup_height, true_buffer, - 3 * rgroup_height * sizeof(JSAMPROW)); + 3 * rgroup_height * sizeof(_JSAMPROW)); /* Fill in the above and below wraparound pointers */ for (i = 0; i < rgroup_height; i++) { fake_buffer[i] = true_buffer[2 * rgroup_height + i]; @@ -309,11 +317,15 @@ create_context_buffer(j_compress_ptr cinfo) */ GLOBAL(void) -jinit_c_prep_controller(j_compress_ptr cinfo, boolean need_full_buffer) +_jinit_c_prep_controller(j_compress_ptr cinfo, boolean need_full_buffer) { my_prep_ptr prep; int ci; jpeg_component_info *compptr; + int data_unit = cinfo->master->lossless ? 1 : DCTSIZE; + + if (cinfo->data_precision != BITS_IN_JSAMPLE) + ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision); if (need_full_buffer) /* safety check */ ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); @@ -331,21 +343,23 @@ jinit_c_prep_controller(j_compress_ptr cinfo, boolean need_full_buffer) if (cinfo->downsample->need_context_rows) { /* Set up to provide context rows */ #ifdef CONTEXT_ROWS_SUPPORTED - prep->pub.pre_process_data = pre_process_context; + prep->pub._pre_process_data = pre_process_context; create_context_buffer(cinfo); #else ERREXIT(cinfo, JERR_NOT_COMPILED); #endif } else { /* No context, just make it tall enough for one row group */ - prep->pub.pre_process_data = pre_process_data; + prep->pub._pre_process_data = pre_process_data; for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { - prep->color_buf[ci] = (*cinfo->mem->alloc_sarray) + prep->color_buf[ci] = (_JSAMPARRAY)(*cinfo->mem->alloc_sarray) ((j_common_ptr)cinfo, JPOOL_IMAGE, - (JDIMENSION)(((long)compptr->width_in_blocks * DCTSIZE * + (JDIMENSION)(((long)compptr->width_in_blocks * data_unit * cinfo->max_h_samp_factor) / compptr->h_samp_factor), (JDIMENSION)cinfo->max_v_samp_factor); } } } + +#endif /* BITS_IN_JSAMPLE != 16 || defined(C_LOSSLESS_SUPPORTED) */ diff --git a/src/3rdparty/libjpeg/src/jcsample.c b/src/3rdparty/libjpeg/src/jcsample.c index e8515ebf0fc..30e6e54b405 100644 --- a/src/3rdparty/libjpeg/src/jcsample.c +++ b/src/3rdparty/libjpeg/src/jcsample.c @@ -3,10 +3,12 @@ * * This file was part of the Independent JPEG Group's software: * Copyright (C) 1991-1996, Thomas G. Lane. + * Lossless JPEG Modifications: + * Copyright (C) 1999, Ken Murchison. * libjpeg-turbo Modifications: * Copyright 2009 Pierre Ossman for Cendio AB * Copyright (C) 2014, MIPS Technologies, Inc., California. - * Copyright (C) 2015, 2019, D. R. Commander. + * Copyright (C) 2015, 2019, 2022, D. R. Commander. * For conditions of distribution and use, see the accompanying README.ijg * file. * @@ -54,13 +56,16 @@ #include "jinclude.h" #include "jpeglib.h" #include "jsimd.h" +#include "jsamplecomp.h" +#if BITS_IN_JSAMPLE != 16 || defined(C_LOSSLESS_SUPPORTED) + /* Pointer to routine to downsample a single component */ typedef void (*downsample1_ptr) (j_compress_ptr cinfo, jpeg_component_info *compptr, - JSAMPARRAY input_data, - JSAMPARRAY output_data); + _JSAMPARRAY input_data, + _JSAMPARRAY output_data); /* Private subobject */ @@ -91,11 +96,11 @@ start_pass_downsample(j_compress_ptr cinfo) */ LOCAL(void) -expand_right_edge(JSAMPARRAY image_data, int num_rows, JDIMENSION input_cols, +expand_right_edge(_JSAMPARRAY image_data, int num_rows, JDIMENSION input_cols, JDIMENSION output_cols) { - register JSAMPROW ptr; - register JSAMPLE pixval; + register _JSAMPROW ptr; + register _JSAMPLE pixval; register int count; int row; int numcols = (int)(output_cols - input_cols); @@ -118,14 +123,14 @@ expand_right_edge(JSAMPARRAY image_data, int num_rows, JDIMENSION input_cols, */ METHODDEF(void) -sep_downsample(j_compress_ptr cinfo, JSAMPIMAGE input_buf, - JDIMENSION in_row_index, JSAMPIMAGE output_buf, +sep_downsample(j_compress_ptr cinfo, _JSAMPIMAGE input_buf, + JDIMENSION in_row_index, _JSAMPIMAGE output_buf, JDIMENSION out_row_group_index) { my_downsample_ptr downsample = (my_downsample_ptr)cinfo->downsample; int ci; jpeg_component_info *compptr; - JSAMPARRAY in_ptr, out_ptr; + _JSAMPARRAY in_ptr, out_ptr; for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { @@ -145,12 +150,13 @@ sep_downsample(j_compress_ptr cinfo, JSAMPIMAGE input_buf, METHODDEF(void) int_downsample(j_compress_ptr cinfo, jpeg_component_info *compptr, - JSAMPARRAY input_data, JSAMPARRAY output_data) + _JSAMPARRAY input_data, _JSAMPARRAY output_data) { int inrow, outrow, h_expand, v_expand, numpix, numpix2, h, v; JDIMENSION outcol, outcol_h; /* outcol_h == outcol*h_expand */ - JDIMENSION output_cols = compptr->width_in_blocks * DCTSIZE; - JSAMPROW inptr, outptr; + int data_unit = cinfo->master->lossless ? 1 : DCTSIZE; + JDIMENSION output_cols = compptr->width_in_blocks * data_unit; + _JSAMPROW inptr, outptr; JLONG outvalue; h_expand = cinfo->max_h_samp_factor / compptr->h_samp_factor; @@ -177,7 +183,7 @@ int_downsample(j_compress_ptr cinfo, jpeg_component_info *compptr, outvalue += (JLONG)(*inptr++); } } - *outptr++ = (JSAMPLE)((outvalue + numpix2) / numpix); + *outptr++ = (_JSAMPLE)((outvalue + numpix2) / numpix); } inrow += v_expand; } @@ -192,14 +198,16 @@ int_downsample(j_compress_ptr cinfo, jpeg_component_info *compptr, METHODDEF(void) fullsize_downsample(j_compress_ptr cinfo, jpeg_component_info *compptr, - JSAMPARRAY input_data, JSAMPARRAY output_data) + _JSAMPARRAY input_data, _JSAMPARRAY output_data) { + int data_unit = cinfo->master->lossless ? 1 : DCTSIZE; + /* Copy the data */ - jcopy_sample_rows(input_data, 0, output_data, 0, cinfo->max_v_samp_factor, - cinfo->image_width); + _jcopy_sample_rows(input_data, 0, output_data, 0, cinfo->max_v_samp_factor, + cinfo->image_width); /* Edge-expand */ expand_right_edge(output_data, cinfo->max_v_samp_factor, cinfo->image_width, - compptr->width_in_blocks * DCTSIZE); + compptr->width_in_blocks * data_unit); } @@ -217,12 +225,13 @@ fullsize_downsample(j_compress_ptr cinfo, jpeg_component_info *compptr, METHODDEF(void) h2v1_downsample(j_compress_ptr cinfo, jpeg_component_info *compptr, - JSAMPARRAY input_data, JSAMPARRAY output_data) + _JSAMPARRAY input_data, _JSAMPARRAY output_data) { int outrow; JDIMENSION outcol; - JDIMENSION output_cols = compptr->width_in_blocks * DCTSIZE; - register JSAMPROW inptr, outptr; + int data_unit = cinfo->master->lossless ? 1 : DCTSIZE; + JDIMENSION output_cols = compptr->width_in_blocks * data_unit; + register _JSAMPROW inptr, outptr; register int bias; /* Expand input data enough to let all the output samples be generated @@ -237,7 +246,7 @@ h2v1_downsample(j_compress_ptr cinfo, jpeg_component_info *compptr, inptr = input_data[outrow]; bias = 0; /* bias = 0,1,0,1,... for successive samples */ for (outcol = 0; outcol < output_cols; outcol++) { - *outptr++ = (JSAMPLE)((inptr[0] + inptr[1] + bias) >> 1); + *outptr++ = (_JSAMPLE)((inptr[0] + inptr[1] + bias) >> 1); bias ^= 1; /* 0=>1, 1=>0 */ inptr += 2; } @@ -253,12 +262,13 @@ h2v1_downsample(j_compress_ptr cinfo, jpeg_component_info *compptr, METHODDEF(void) h2v2_downsample(j_compress_ptr cinfo, jpeg_component_info *compptr, - JSAMPARRAY input_data, JSAMPARRAY output_data) + _JSAMPARRAY input_data, _JSAMPARRAY output_data) { int inrow, outrow; JDIMENSION outcol; - JDIMENSION output_cols = compptr->width_in_blocks * DCTSIZE; - register JSAMPROW inptr0, inptr1, outptr; + int data_unit = cinfo->master->lossless ? 1 : DCTSIZE; + JDIMENSION output_cols = compptr->width_in_blocks * data_unit; + register _JSAMPROW inptr0, inptr1, outptr; register int bias; /* Expand input data enough to let all the output samples be generated @@ -275,8 +285,8 @@ h2v2_downsample(j_compress_ptr cinfo, jpeg_component_info *compptr, inptr1 = input_data[inrow + 1]; bias = 1; /* bias = 1,2,1,2,... for successive samples */ for (outcol = 0; outcol < output_cols; outcol++) { - *outptr++ = - (JSAMPLE)((inptr0[0] + inptr0[1] + inptr1[0] + inptr1[1] + bias) >> 2); + *outptr++ = (_JSAMPLE) + ((inptr0[0] + inptr0[1] + inptr1[0] + inptr1[1] + bias) >> 2); bias ^= 3; /* 1=>2, 2=>1 */ inptr0 += 2; inptr1 += 2; } @@ -295,12 +305,13 @@ h2v2_downsample(j_compress_ptr cinfo, jpeg_component_info *compptr, METHODDEF(void) h2v2_smooth_downsample(j_compress_ptr cinfo, jpeg_component_info *compptr, - JSAMPARRAY input_data, JSAMPARRAY output_data) + _JSAMPARRAY input_data, _JSAMPARRAY output_data) { int inrow, outrow; JDIMENSION colctr; - JDIMENSION output_cols = compptr->width_in_blocks * DCTSIZE; - register JSAMPROW inptr0, inptr1, above_ptr, below_ptr, outptr; + int data_unit = cinfo->master->lossless ? 1 : DCTSIZE; + JDIMENSION output_cols = compptr->width_in_blocks * data_unit; + register _JSAMPROW inptr0, inptr1, above_ptr, below_ptr, outptr; JLONG membersum, neighsum, memberscale, neighscale; /* Expand input data enough to let all the output samples be generated @@ -341,7 +352,7 @@ h2v2_smooth_downsample(j_compress_ptr cinfo, jpeg_component_info *compptr, neighsum += neighsum; neighsum += above_ptr[0] + above_ptr[2] + below_ptr[0] + below_ptr[2]; membersum = membersum * memberscale + neighsum * neighscale; - *outptr++ = (JSAMPLE)((membersum + 32768) >> 16); + *outptr++ = (_JSAMPLE)((membersum + 32768) >> 16); inptr0 += 2; inptr1 += 2; above_ptr += 2; below_ptr += 2; for (colctr = output_cols - 2; colctr > 0; colctr--) { @@ -357,7 +368,7 @@ h2v2_smooth_downsample(j_compress_ptr cinfo, jpeg_component_info *compptr, /* form final output scaled up by 2^16 */ membersum = membersum * memberscale + neighsum * neighscale; /* round, descale and output it */ - *outptr++ = (JSAMPLE)((membersum + 32768) >> 16); + *outptr++ = (_JSAMPLE)((membersum + 32768) >> 16); inptr0 += 2; inptr1 += 2; above_ptr += 2; below_ptr += 2; } @@ -368,7 +379,7 @@ h2v2_smooth_downsample(j_compress_ptr cinfo, jpeg_component_info *compptr, neighsum += neighsum; neighsum += above_ptr[-1] + above_ptr[1] + below_ptr[-1] + below_ptr[1]; membersum = membersum * memberscale + neighsum * neighscale; - *outptr = (JSAMPLE)((membersum + 32768) >> 16); + *outptr = (_JSAMPLE)((membersum + 32768) >> 16); inrow += 2; } @@ -383,12 +394,13 @@ h2v2_smooth_downsample(j_compress_ptr cinfo, jpeg_component_info *compptr, METHODDEF(void) fullsize_smooth_downsample(j_compress_ptr cinfo, jpeg_component_info *compptr, - JSAMPARRAY input_data, JSAMPARRAY output_data) + _JSAMPARRAY input_data, _JSAMPARRAY output_data) { int outrow; JDIMENSION colctr; - JDIMENSION output_cols = compptr->width_in_blocks * DCTSIZE; - register JSAMPROW inptr, above_ptr, below_ptr, outptr; + int data_unit = cinfo->master->lossless ? 1 : DCTSIZE; + JDIMENSION output_cols = compptr->width_in_blocks * data_unit; + register _JSAMPROW inptr, above_ptr, below_ptr, outptr; JLONG membersum, neighsum, memberscale, neighscale; int colsum, lastcolsum, nextcolsum; @@ -420,7 +432,7 @@ fullsize_smooth_downsample(j_compress_ptr cinfo, jpeg_component_info *compptr, nextcolsum = above_ptr[0] + below_ptr[0] + inptr[0]; neighsum = colsum + (colsum - membersum) + nextcolsum; membersum = membersum * memberscale + neighsum * neighscale; - *outptr++ = (JSAMPLE)((membersum + 32768) >> 16); + *outptr++ = (_JSAMPLE)((membersum + 32768) >> 16); lastcolsum = colsum; colsum = nextcolsum; for (colctr = output_cols - 2; colctr > 0; colctr--) { @@ -429,7 +441,7 @@ fullsize_smooth_downsample(j_compress_ptr cinfo, jpeg_component_info *compptr, nextcolsum = above_ptr[0] + below_ptr[0] + inptr[0]; neighsum = lastcolsum + (colsum - membersum) + nextcolsum; membersum = membersum * memberscale + neighsum * neighscale; - *outptr++ = (JSAMPLE)((membersum + 32768) >> 16); + *outptr++ = (_JSAMPLE)((membersum + 32768) >> 16); lastcolsum = colsum; colsum = nextcolsum; } @@ -437,7 +449,7 @@ fullsize_smooth_downsample(j_compress_ptr cinfo, jpeg_component_info *compptr, membersum = *inptr; neighsum = lastcolsum + (colsum - membersum) + colsum; membersum = membersum * memberscale + neighsum * neighscale; - *outptr = (JSAMPLE)((membersum + 32768) >> 16); + *outptr = (_JSAMPLE)((membersum + 32768) >> 16); } } @@ -451,19 +463,22 @@ fullsize_smooth_downsample(j_compress_ptr cinfo, jpeg_component_info *compptr, */ GLOBAL(void) -jinit_downsampler(j_compress_ptr cinfo) +_jinit_downsampler(j_compress_ptr cinfo) { my_downsample_ptr downsample; int ci; jpeg_component_info *compptr; boolean smoothok = TRUE; + if (cinfo->data_precision != BITS_IN_JSAMPLE) + ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision); + downsample = (my_downsample_ptr) (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE, sizeof(my_downsampler)); cinfo->downsample = (struct jpeg_downsampler *)downsample; downsample->pub.start_pass = start_pass_downsample; - downsample->pub.downsample = sep_downsample; + downsample->pub._downsample = sep_downsample; downsample->pub.need_context_rows = FALSE; if (cinfo->CCIR601_sampling) @@ -484,15 +499,17 @@ jinit_downsampler(j_compress_ptr cinfo) } else if (compptr->h_samp_factor * 2 == cinfo->max_h_samp_factor && compptr->v_samp_factor == cinfo->max_v_samp_factor) { smoothok = FALSE; +#ifdef WITH_SIMD if (jsimd_can_h2v1_downsample()) downsample->methods[ci] = jsimd_h2v1_downsample; else +#endif downsample->methods[ci] = h2v1_downsample; } else if (compptr->h_samp_factor * 2 == cinfo->max_h_samp_factor && compptr->v_samp_factor * 2 == cinfo->max_v_samp_factor) { #ifdef INPUT_SMOOTHING_SUPPORTED if (cinfo->smoothing_factor) { -#if defined(__mips__) +#if defined(WITH_SIMD) && defined(__mips__) if (jsimd_can_h2v2_smooth_downsample()) downsample->methods[ci] = jsimd_h2v2_smooth_downsample; else @@ -502,9 +519,11 @@ jinit_downsampler(j_compress_ptr cinfo) } else #endif { +#ifdef WITH_SIMD if (jsimd_can_h2v2_downsample()) downsample->methods[ci] = jsimd_h2v2_downsample; else +#endif downsample->methods[ci] = h2v2_downsample; } } else if ((cinfo->max_h_samp_factor % compptr->h_samp_factor) == 0 && @@ -520,3 +539,5 @@ jinit_downsampler(j_compress_ptr cinfo) TRACEMS(cinfo, 0, JTRC_SMOOTH_NOTIMPL); #endif } + +#endif /* BITS_IN_JSAMPLE != 16 || defined(C_LOSSLESS_SUPPORTED) */ diff --git a/src/3rdparty/libjpeg/src/jctrans.c b/src/3rdparty/libjpeg/src/jctrans.c index e121028ec70..ae52e3989ee 100644 --- a/src/3rdparty/libjpeg/src/jctrans.c +++ b/src/3rdparty/libjpeg/src/jctrans.c @@ -17,7 +17,7 @@ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" -#include "jpegcomp.h" +#include "jpegapicomp.h" /* Forward declarations */ @@ -42,6 +42,9 @@ LOCAL(void) transencode_coef_controller(j_compress_ptr cinfo, GLOBAL(void) jpeg_write_coefficients(j_compress_ptr cinfo, jvirt_barray_ptr *coef_arrays) { + if (cinfo->master->lossless) + ERREXIT(cinfo, JERR_NOTIMPL); + if (cinfo->global_state != CSTATE_START) ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); /* Mark all tables to be written */ @@ -72,6 +75,9 @@ jpeg_copy_critical_parameters(j_decompress_ptr srcinfo, j_compress_ptr dstinfo) JQUANT_TBL *c_quant, *slot_quant; int tblno, ci, coefi; + if (srcinfo->master->lossless) + ERREXIT(dstinfo, JERR_NOTIMPL); + /* Safety check to ensure start_compress not called yet. */ if (dstinfo->global_state != CSTATE_START) ERREXIT1(dstinfo, JERR_BAD_STATE, dstinfo->global_state); @@ -364,6 +370,13 @@ compress_output(j_compress_ptr cinfo, JSAMPIMAGE input_buf) } +METHODDEF(boolean) +compress_output_12(j_compress_ptr cinfo, J12SAMPIMAGE input_buf) +{ + return compress_output(cinfo, (JSAMPIMAGE)input_buf); +} + + /* * Initialize coefficient buffer controller. * @@ -386,6 +399,7 @@ transencode_coef_controller(j_compress_ptr cinfo, cinfo->coef = (struct jpeg_c_coef_controller *)coef; coef->pub.start_pass = start_pass_coef; coef->pub.compress_data = compress_output; + coef->pub.compress_data_12 = compress_output_12; /* Save pointer to virtual arrays */ coef->whole_image = coef_arrays; diff --git a/src/3rdparty/libjpeg/src/jdapimin.c b/src/3rdparty/libjpeg/src/jdapimin.c index 30126a048d4..51ca552dad8 100644 --- a/src/3rdparty/libjpeg/src/jdapimin.c +++ b/src/3rdparty/libjpeg/src/jdapimin.c @@ -3,6 +3,8 @@ * * This file was part of the Independent JPEG Group's software: * Copyright (C) 1994-1998, Thomas G. Lane. + * Lossless JPEG Modifications: + * Copyright (C) 1999, Ken Murchison. * libjpeg-turbo Modifications: * Copyright (C) 2016, 2022, D. R. Commander. * For conditions of distribution and use, see the accompanying README.ijg @@ -82,6 +84,8 @@ jpeg_CreateDecompress(j_decompress_ptr cinfo, int version, size_t structsize) /* And initialize the overall input controller. */ jinit_input_controller(cinfo); + cinfo->data_precision = BITS_IN_JSAMPLE; + /* OK, I'm ready */ cinfo->global_state = DSTATE_START; @@ -162,7 +166,10 @@ default_decompress_parms(j_decompress_ptr cinfo) cinfo->jpeg_color_space = JCS_RGB; /* ASCII 'R', 'G', 'B' */ else { TRACEMS3(cinfo, 1, JTRC_UNKNOWN_IDS, cid0, cid1, cid2); - cinfo->jpeg_color_space = JCS_YCbCr; /* assume it's YCbCr */ + if (cinfo->master->lossless) + cinfo->jpeg_color_space = JCS_RGB; /* assume it's RGB */ + else + cinfo->jpeg_color_space = JCS_YCbCr; /* assume it's YCbCr */ } } /* Always guess RGB is proper output colorspace. */ diff --git a/src/3rdparty/libjpeg/src/jdapistd.c b/src/3rdparty/libjpeg/src/jdapistd.c index 02cd0cb93a8..1f449272368 100644 --- a/src/3rdparty/libjpeg/src/jdapistd.c +++ b/src/3rdparty/libjpeg/src/jdapistd.c @@ -4,7 +4,7 @@ * This file was part of the Independent JPEG Group's software: * Copyright (C) 1994-1996, Thomas G. Lane. * libjpeg-turbo Modifications: - * Copyright (C) 2010, 2015-2020, 2022, D. R. Commander. + * Copyright (C) 2010, 2015-2020, 2022-2023, D. R. Commander. * Copyright (C) 2015, Google, Inc. * For conditions of distribution and use, see the accompanying README.ijg * file. @@ -19,13 +19,20 @@ */ #include "jinclude.h" +#if BITS_IN_JSAMPLE != 16 || defined(D_LOSSLESS_SUPPORTED) #include "jdmainct.h" #include "jdcoefct.h" +#else +#define JPEG_INTERNALS +#include "jpeglib.h" +#endif #include "jdmaster.h" #include "jdmerge.h" #include "jdsample.h" #include "jmemsys.h" +#if BITS_IN_JSAMPLE == 8 + /* Forward declarations */ LOCAL(boolean) output_pass_setup(j_decompress_ptr cinfo); @@ -121,8 +128,20 @@ output_pass_setup(j_decompress_ptr cinfo) } /* Process some data */ last_scanline = cinfo->output_scanline; - (*cinfo->main->process_data) (cinfo, (JSAMPARRAY)NULL, - &cinfo->output_scanline, (JDIMENSION)0); +#ifdef D_LOSSLESS_SUPPORTED + if (cinfo->data_precision == 16) + (*cinfo->main->process_data_16) (cinfo, (J16SAMPARRAY)NULL, + &cinfo->output_scanline, + (JDIMENSION)0); + else +#endif + if (cinfo->data_precision == 12) + (*cinfo->main->process_data_12) (cinfo, (J12SAMPARRAY)NULL, + &cinfo->output_scanline, + (JDIMENSION)0); + else + (*cinfo->main->process_data) (cinfo, (JSAMPARRAY)NULL, + &cinfo->output_scanline, (JDIMENSION)0); if (cinfo->output_scanline == last_scanline) return FALSE; /* No progress made, must suspend */ } @@ -135,25 +154,29 @@ output_pass_setup(j_decompress_ptr cinfo) #endif /* QUANT_2PASS_SUPPORTED */ } /* Ready for application to drive output pass through - * jpeg_read_scanlines or jpeg_read_raw_data. + * _jpeg_read_scanlines or _jpeg_read_raw_data. */ cinfo->global_state = cinfo->raw_data_out ? DSTATE_RAW_OK : DSTATE_SCANNING; return TRUE; } +#endif /* BITS_IN_JSAMPLE == 8 */ + + +#if BITS_IN_JSAMPLE != 16 /* * Enable partial scanline decompression * * Must be called after jpeg_start_decompress() and before any calls to - * jpeg_read_scanlines() or jpeg_skip_scanlines(). + * _jpeg_read_scanlines() or _jpeg_skip_scanlines(). * * Refer to libjpeg.txt for more information. */ GLOBAL(void) -jpeg_crop_scanline(j_decompress_ptr cinfo, JDIMENSION *xoffset, - JDIMENSION *width) +_jpeg_crop_scanline(j_decompress_ptr cinfo, JDIMENSION *xoffset, + JDIMENSION *width) { int ci, align, orig_downsampled_width; JDIMENSION input_xoffset; @@ -163,6 +186,12 @@ jpeg_crop_scanline(j_decompress_ptr cinfo, JDIMENSION *xoffset, my_master_ptr master = (my_master_ptr)cinfo->master; #endif + if (cinfo->data_precision != BITS_IN_JSAMPLE) + ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision); + + if (cinfo->master->lossless) + ERREXIT(cinfo, JERR_NOTIMPL); + if ((cinfo->global_state != DSTATE_SCANNING && cinfo->global_state != DSTATE_BUFIMAGE) || cinfo->output_scanline != 0) ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); @@ -236,9 +265,11 @@ jpeg_crop_scanline(j_decompress_ptr cinfo, JDIMENSION *xoffset, /* Set downsampled_width to the new output width. */ orig_downsampled_width = compptr->downsampled_width; compptr->downsampled_width = - (JDIMENSION)jdiv_round_up((long)(cinfo->output_width * - compptr->h_samp_factor), - (long)cinfo->max_h_samp_factor); + (JDIMENSION)jdiv_round_up((long)cinfo->output_width * + (long)(compptr->h_samp_factor * + compptr->_DCT_scaled_size), + (long)(cinfo->max_h_samp_factor * + cinfo->_min_DCT_scaled_size)); if (compptr->downsampled_width < 2 && orig_downsampled_width >= 2) reinit_upsampler = TRUE; @@ -254,11 +285,13 @@ jpeg_crop_scanline(j_decompress_ptr cinfo, JDIMENSION *xoffset, if (reinit_upsampler) { cinfo->master->jinit_upsampler_no_alloc = TRUE; - jinit_upsampler(cinfo); + _jinit_upsampler(cinfo); cinfo->master->jinit_upsampler_no_alloc = FALSE; } } +#endif /* BITS_IN_JSAMPLE != 16 */ + /* * Read some scanlines of data from the JPEG decompressor. @@ -268,17 +301,21 @@ jpeg_crop_scanline(j_decompress_ptr cinfo, JDIMENSION *xoffset, * including bottom of image, data source suspension, and operating * modes that emit multiple scanlines at a time. * - * Note: we warn about excess calls to jpeg_read_scanlines() since + * Note: we warn about excess calls to _jpeg_read_scanlines() since * this likely signals an application programmer error. However, * an oversize buffer (max_lines > scanlines remaining) is not an error. */ GLOBAL(JDIMENSION) -jpeg_read_scanlines(j_decompress_ptr cinfo, JSAMPARRAY scanlines, - JDIMENSION max_lines) +_jpeg_read_scanlines(j_decompress_ptr cinfo, _JSAMPARRAY scanlines, + JDIMENSION max_lines) { +#if BITS_IN_JSAMPLE != 16 || defined(D_LOSSLESS_SUPPORTED) JDIMENSION row_ctr; + if (cinfo->data_precision != BITS_IN_JSAMPLE) + ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision); + if (cinfo->global_state != DSTATE_SCANNING) ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); if (cinfo->output_scanline >= cinfo->output_height) { @@ -295,30 +332,36 @@ jpeg_read_scanlines(j_decompress_ptr cinfo, JSAMPARRAY scanlines, /* Process some data */ row_ctr = 0; - (*cinfo->main->process_data) (cinfo, scanlines, &row_ctr, max_lines); + (*cinfo->main->_process_data) (cinfo, scanlines, &row_ctr, max_lines); cinfo->output_scanline += row_ctr; return row_ctr; +#else + ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision); + return 0; +#endif } -/* Dummy color convert function used by jpeg_skip_scanlines() */ +#if BITS_IN_JSAMPLE != 16 + +/* Dummy color convert function used by _jpeg_skip_scanlines() */ LOCAL(void) -noop_convert(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, - JDIMENSION input_row, JSAMPARRAY output_buf, int num_rows) +noop_convert(j_decompress_ptr cinfo, _JSAMPIMAGE input_buf, + JDIMENSION input_row, _JSAMPARRAY output_buf, int num_rows) { } -/* Dummy quantize function used by jpeg_skip_scanlines() */ +/* Dummy quantize function used by _jpeg_skip_scanlines() */ LOCAL(void) -noop_quantize(j_decompress_ptr cinfo, JSAMPARRAY input_buf, - JSAMPARRAY output_buf, int num_rows) +noop_quantize(j_decompress_ptr cinfo, _JSAMPARRAY input_buf, + _JSAMPARRAY output_buf, int num_rows) { } /* - * In some cases, it is best to call jpeg_read_scanlines() and discard the + * In some cases, it is best to call _jpeg_read_scanlines() and discard the * output, rather than skipping the scanlines, because this allows us to * maintain the internal state of the context-based upsampler. In these cases, * we set up and tear down a dummy color converter in order to avoid valgrind @@ -332,27 +375,27 @@ read_and_discard_scanlines(j_decompress_ptr cinfo, JDIMENSION num_lines) #ifdef UPSAMPLE_MERGING_SUPPORTED my_master_ptr master = (my_master_ptr)cinfo->master; #endif - JSAMPLE dummy_sample[1] = { 0 }; - JSAMPROW dummy_row = dummy_sample; - JSAMPARRAY scanlines = NULL; - void (*color_convert) (j_decompress_ptr cinfo, JSAMPIMAGE input_buf, - JDIMENSION input_row, JSAMPARRAY output_buf, + _JSAMPLE dummy_sample[1] = { 0 }; + _JSAMPROW dummy_row = dummy_sample; + _JSAMPARRAY scanlines = NULL; + void (*color_convert) (j_decompress_ptr cinfo, _JSAMPIMAGE input_buf, + JDIMENSION input_row, _JSAMPARRAY output_buf, int num_rows) = NULL; - void (*color_quantize) (j_decompress_ptr cinfo, JSAMPARRAY input_buf, - JSAMPARRAY output_buf, int num_rows) = NULL; + void (*color_quantize) (j_decompress_ptr cinfo, _JSAMPARRAY input_buf, + _JSAMPARRAY output_buf, int num_rows) = NULL; - if (cinfo->cconvert && cinfo->cconvert->color_convert) { - color_convert = cinfo->cconvert->color_convert; - cinfo->cconvert->color_convert = noop_convert; + if (cinfo->cconvert && cinfo->cconvert->_color_convert) { + color_convert = cinfo->cconvert->_color_convert; + cinfo->cconvert->_color_convert = noop_convert; /* This just prevents UBSan from complaining about adding 0 to a NULL * pointer. The pointer isn't actually used. */ scanlines = &dummy_row; } - if (cinfo->cquantize && cinfo->cquantize->color_quantize) { - color_quantize = cinfo->cquantize->color_quantize; - cinfo->cquantize->color_quantize = noop_quantize; + if (cinfo->cquantize && cinfo->cquantize->_color_quantize) { + color_quantize = cinfo->cquantize->_color_quantize; + cinfo->cquantize->_color_quantize = noop_quantize; } #ifdef UPSAMPLE_MERGING_SUPPORTED @@ -363,19 +406,19 @@ read_and_discard_scanlines(j_decompress_ptr cinfo, JDIMENSION num_lines) #endif for (n = 0; n < num_lines; n++) - jpeg_read_scanlines(cinfo, scanlines, 1); + _jpeg_read_scanlines(cinfo, scanlines, 1); if (color_convert) - cinfo->cconvert->color_convert = color_convert; + cinfo->cconvert->_color_convert = color_convert; if (color_quantize) - cinfo->cquantize->color_quantize = color_quantize; + cinfo->cquantize->_color_quantize = color_quantize; } /* - * Called by jpeg_skip_scanlines(). This partially skips a decompress block by - * incrementing the rowgroup counter. + * Called by _jpeg_skip_scanlines(). This partially skips a decompress block + * by incrementing the rowgroup counter. */ LOCAL(void) @@ -414,7 +457,7 @@ increment_simple_rowgroup_ctr(j_decompress_ptr cinfo, JDIMENSION rows) */ GLOBAL(JDIMENSION) -jpeg_skip_scanlines(j_decompress_ptr cinfo, JDIMENSION num_lines) +_jpeg_skip_scanlines(j_decompress_ptr cinfo, JDIMENSION num_lines) { my_main_ptr main_ptr = (my_main_ptr)cinfo->main; my_coef_ptr coef = (my_coef_ptr)cinfo->coef; @@ -425,6 +468,12 @@ jpeg_skip_scanlines(j_decompress_ptr cinfo, JDIMENSION num_lines) JDIMENSION lines_per_iMCU_row, lines_left_in_iMCU_row, lines_after_iMCU_row; JDIMENSION lines_to_skip, lines_to_read; + if (cinfo->data_precision != BITS_IN_JSAMPLE) + ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision); + + if (cinfo->master->lossless) + ERREXIT(cinfo, JERR_NOTIMPL); + /* Two-pass color quantization is not supported. */ if (cinfo->quantize_colors && cinfo->two_pass_quantize) ERREXIT(cinfo, JERR_NOTIMPL); @@ -597,11 +646,17 @@ jpeg_skip_scanlines(j_decompress_ptr cinfo, JDIMENSION num_lines) */ GLOBAL(JDIMENSION) -jpeg_read_raw_data(j_decompress_ptr cinfo, JSAMPIMAGE data, - JDIMENSION max_lines) +_jpeg_read_raw_data(j_decompress_ptr cinfo, _JSAMPIMAGE data, + JDIMENSION max_lines) { JDIMENSION lines_per_iMCU_row; + if (cinfo->data_precision != BITS_IN_JSAMPLE) + ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision); + + if (cinfo->master->lossless) + ERREXIT(cinfo, JERR_NOTIMPL); + if (cinfo->global_state != DSTATE_RAW_OK) ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); if (cinfo->output_scanline >= cinfo->output_height) { @@ -622,7 +677,7 @@ jpeg_read_raw_data(j_decompress_ptr cinfo, JSAMPIMAGE data, ERREXIT(cinfo, JERR_BUFFER_SIZE); /* Decompress directly into user's buffer. */ - if (!(*cinfo->coef->decompress_data) (cinfo, data)) + if (!(*cinfo->coef->_decompress_data) (cinfo, data)) return 0; /* suspension forced, can do nothing more */ /* OK, we processed one iMCU row. */ @@ -630,6 +685,10 @@ jpeg_read_raw_data(j_decompress_ptr cinfo, JSAMPIMAGE data, return lines_per_iMCU_row; } +#endif /* BITS_IN_JSAMPLE != 16 */ + + +#if BITS_IN_JSAMPLE == 8 /* Additional entry points for buffered-image mode. */ @@ -687,3 +746,5 @@ jpeg_finish_output(j_decompress_ptr cinfo) } #endif /* D_MULTISCAN_FILES_SUPPORTED */ + +#endif /* BITS_IN_JSAMPLE == 8 */ diff --git a/src/3rdparty/libjpeg/src/jdatadst.c b/src/3rdparty/libjpeg/src/jdatadst.c index 6b4fed23397..529f93b4904 100644 --- a/src/3rdparty/libjpeg/src/jdatadst.c +++ b/src/3rdparty/libjpeg/src/jdatadst.c @@ -38,7 +38,6 @@ typedef my_destination_mgr *my_dest_ptr; #define OUTPUT_BUF_SIZE 4096 /* choose an efficiently fwrite'able size */ -#if JPEG_LIB_VERSION >= 80 || defined(MEM_SRCDST_SUPPORTED) /* Expanded data destination object for memory output */ typedef struct { @@ -52,7 +51,6 @@ typedef struct { } my_mem_destination_mgr; typedef my_mem_destination_mgr *my_mem_dest_ptr; -#endif /* @@ -74,13 +72,11 @@ init_destination(j_compress_ptr cinfo) dest->pub.free_in_buffer = OUTPUT_BUF_SIZE; } -#if JPEG_LIB_VERSION >= 80 || defined(MEM_SRCDST_SUPPORTED) METHODDEF(void) init_mem_destination(j_compress_ptr cinfo) { /* no work necessary here */ } -#endif /* @@ -121,7 +117,6 @@ empty_output_buffer(j_compress_ptr cinfo) return TRUE; } -#if JPEG_LIB_VERSION >= 80 || defined(MEM_SRCDST_SUPPORTED) METHODDEF(boolean) empty_mem_output_buffer(j_compress_ptr cinfo) { @@ -150,7 +145,6 @@ empty_mem_output_buffer(j_compress_ptr cinfo) return TRUE; } -#endif /* @@ -179,7 +173,6 @@ term_destination(j_compress_ptr cinfo) ERREXIT(cinfo, JERR_FILE_WRITE); } -#if JPEG_LIB_VERSION >= 80 || defined(MEM_SRCDST_SUPPORTED) METHODDEF(void) term_mem_destination(j_compress_ptr cinfo) { @@ -188,7 +181,6 @@ term_mem_destination(j_compress_ptr cinfo) *dest->outbuffer = dest->buffer; *dest->outsize = (unsigned long)(dest->bufsize - dest->pub.free_in_buffer); } -#endif /* @@ -227,7 +219,6 @@ jpeg_stdio_dest(j_compress_ptr cinfo, FILE *outfile) } -#if JPEG_LIB_VERSION >= 80 || defined(MEM_SRCDST_SUPPORTED) /* * Prepare for output to a memory buffer. * The caller may supply an own initial buffer with appropriate size. @@ -284,4 +275,3 @@ jpeg_mem_dest(j_compress_ptr cinfo, unsigned char **outbuffer, dest->pub.next_output_byte = dest->buffer = *outbuffer; dest->pub.free_in_buffer = dest->bufsize = *outsize; } -#endif diff --git a/src/3rdparty/libjpeg/src/jdatasrc.c b/src/3rdparty/libjpeg/src/jdatasrc.c index e36a30d8944..dc135f43a47 100644 --- a/src/3rdparty/libjpeg/src/jdatasrc.c +++ b/src/3rdparty/libjpeg/src/jdatasrc.c @@ -56,13 +56,11 @@ init_source(j_decompress_ptr cinfo) src->start_of_file = TRUE; } -#if JPEG_LIB_VERSION >= 80 || defined(MEM_SRCDST_SUPPORTED) METHODDEF(void) init_mem_source(j_decompress_ptr cinfo) { /* no work necessary here */ } -#endif /* @@ -123,7 +121,6 @@ fill_input_buffer(j_decompress_ptr cinfo) return TRUE; } -#if JPEG_LIB_VERSION >= 80 || defined(MEM_SRCDST_SUPPORTED) METHODDEF(boolean) fill_mem_input_buffer(j_decompress_ptr cinfo) { @@ -144,7 +141,6 @@ fill_mem_input_buffer(j_decompress_ptr cinfo) return TRUE; } -#endif /* @@ -253,7 +249,6 @@ jpeg_stdio_src(j_decompress_ptr cinfo, FILE *infile) } -#if JPEG_LIB_VERSION >= 80 || defined(MEM_SRCDST_SUPPORTED) /* * Prepare for input from a supplied memory buffer. * The buffer must contain the whole JPEG data. @@ -292,4 +287,3 @@ jpeg_mem_src(j_decompress_ptr cinfo, const unsigned char *inbuffer, src->bytes_in_buffer = (size_t)insize; src->next_input_byte = (const JOCTET *)inbuffer; } -#endif diff --git a/src/3rdparty/libjpeg/src/jdcoefct.c b/src/3rdparty/libjpeg/src/jdcoefct.c index 88e10c08cb6..85cbcb79747 100644 --- a/src/3rdparty/libjpeg/src/jdcoefct.c +++ b/src/3rdparty/libjpeg/src/jdcoefct.c @@ -11,7 +11,7 @@ * file. * * This file contains the coefficient buffer controller for decompression. - * This controller is the top level of the JPEG decompressor proper. + * This controller is the top level of the lossy JPEG decompressor proper. * The coefficient buffer lies between entropy decoding and inverse-DCT steps. * * In buffered-image mode, this controller is the interface between @@ -21,19 +21,20 @@ #include "jinclude.h" #include "jdcoefct.h" -#include "jpegcomp.h" +#include "jpegapicomp.h" +#include "jsamplecomp.h" /* Forward declarations */ METHODDEF(int) decompress_onepass(j_decompress_ptr cinfo, - JSAMPIMAGE output_buf); + _JSAMPIMAGE output_buf); #ifdef D_MULTISCAN_FILES_SUPPORTED -METHODDEF(int) decompress_data(j_decompress_ptr cinfo, JSAMPIMAGE output_buf); +METHODDEF(int) decompress_data(j_decompress_ptr cinfo, _JSAMPIMAGE output_buf); #endif #ifdef BLOCK_SMOOTHING_SUPPORTED LOCAL(boolean) smoothing_ok(j_decompress_ptr cinfo); METHODDEF(int) decompress_smooth_data(j_decompress_ptr cinfo, - JSAMPIMAGE output_buf); + _JSAMPIMAGE output_buf); #endif @@ -62,9 +63,9 @@ start_output_pass(j_decompress_ptr cinfo) /* If multipass, check to see whether to use block smoothing on this pass */ if (coef->pub.coef_arrays != NULL) { if (cinfo->do_block_smoothing && smoothing_ok(cinfo)) - coef->pub.decompress_data = decompress_smooth_data; + coef->pub._decompress_data = decompress_smooth_data; else - coef->pub.decompress_data = decompress_data; + coef->pub._decompress_data = decompress_data; } #endif cinfo->output_iMCU_row = 0; @@ -82,17 +83,17 @@ start_output_pass(j_decompress_ptr cinfo) */ METHODDEF(int) -decompress_onepass(j_decompress_ptr cinfo, JSAMPIMAGE output_buf) +decompress_onepass(j_decompress_ptr cinfo, _JSAMPIMAGE output_buf) { my_coef_ptr coef = (my_coef_ptr)cinfo->coef; JDIMENSION MCU_col_num; /* index of current MCU within row */ JDIMENSION last_MCU_col = cinfo->MCUs_per_row - 1; JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1; int blkn, ci, xindex, yindex, yoffset, useful_width; - JSAMPARRAY output_ptr; + _JSAMPARRAY output_ptr; JDIMENSION start_col, output_col; jpeg_component_info *compptr; - inverse_DCT_method_ptr inverse_DCT; + _inverse_DCT_method_ptr inverse_DCT; /* Loop to process as much as one whole iMCU row */ for (yoffset = coef->MCU_vert_offset; yoffset < coef->MCU_rows_per_iMCU_row; @@ -129,7 +130,7 @@ decompress_onepass(j_decompress_ptr cinfo, JSAMPIMAGE output_buf) blkn += compptr->MCU_blocks; continue; } - inverse_DCT = cinfo->idct->inverse_DCT[compptr->component_index]; + inverse_DCT = cinfo->idct->_inverse_DCT[compptr->component_index]; useful_width = (MCU_col_num < last_MCU_col) ? compptr->MCU_width : compptr->last_col_width; output_ptr = output_buf[compptr->component_index] + @@ -262,7 +263,7 @@ consume_data(j_decompress_ptr cinfo) */ METHODDEF(int) -decompress_data(j_decompress_ptr cinfo, JSAMPIMAGE output_buf) +decompress_data(j_decompress_ptr cinfo, _JSAMPIMAGE output_buf) { my_coef_ptr coef = (my_coef_ptr)cinfo->coef; JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1; @@ -270,10 +271,10 @@ decompress_data(j_decompress_ptr cinfo, JSAMPIMAGE output_buf) int ci, block_row, block_rows; JBLOCKARRAY buffer; JBLOCKROW buffer_ptr; - JSAMPARRAY output_ptr; + _JSAMPARRAY output_ptr; JDIMENSION output_col; jpeg_component_info *compptr; - inverse_DCT_method_ptr inverse_DCT; + _inverse_DCT_method_ptr inverse_DCT; /* Force some input to be done if we are getting ahead of the input. */ while (cinfo->input_scan_number < cinfo->output_scan_number || @@ -302,7 +303,7 @@ decompress_data(j_decompress_ptr cinfo, JSAMPIMAGE output_buf) block_rows = (int)(compptr->height_in_blocks % compptr->v_samp_factor); if (block_rows == 0) block_rows = compptr->v_samp_factor; } - inverse_DCT = cinfo->idct->inverse_DCT[ci]; + inverse_DCT = cinfo->idct->_inverse_DCT[ci]; output_ptr = output_buf[ci]; /* Loop over all DCT blocks to be processed. */ for (block_row = 0; block_row < block_rows; block_row++) { @@ -425,7 +426,7 @@ smoothing_ok(j_decompress_ptr cinfo) */ METHODDEF(int) -decompress_smooth_data(j_decompress_ptr cinfo, JSAMPIMAGE output_buf) +decompress_smooth_data(j_decompress_ptr cinfo, _JSAMPIMAGE output_buf) { my_coef_ptr coef = (my_coef_ptr)cinfo->coef; JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1; @@ -434,10 +435,10 @@ decompress_smooth_data(j_decompress_ptr cinfo, JSAMPIMAGE output_buf) JBLOCKARRAY buffer; JBLOCKROW buffer_ptr, prev_prev_block_row, prev_block_row; JBLOCKROW next_block_row, next_next_block_row; - JSAMPARRAY output_ptr; + _JSAMPARRAY output_ptr; JDIMENSION output_col; jpeg_component_info *compptr; - inverse_DCT_method_ptr inverse_DCT; + _inverse_DCT_method_ptr inverse_DCT; boolean change_dc; JCOEF *workspace; int *coef_bits; @@ -535,7 +536,7 @@ decompress_smooth_data(j_decompress_ptr cinfo, JSAMPIMAGE output_buf) Q21 = quanttbl->quantval[Q21_POS]; Q30 = quanttbl->quantval[Q30_POS]; } - inverse_DCT = cinfo->idct->inverse_DCT[ci]; + inverse_DCT = cinfo->idct->_inverse_DCT[ci]; output_ptr = output_buf[ci]; /* Loop over all DCT blocks to be processed. */ for (block_row = 0; block_row < block_rows; block_row++) { @@ -810,10 +811,13 @@ decompress_smooth_data(j_decompress_ptr cinfo, JSAMPIMAGE output_buf) */ GLOBAL(void) -jinit_d_coef_controller(j_decompress_ptr cinfo, boolean need_full_buffer) +_jinit_d_coef_controller(j_decompress_ptr cinfo, boolean need_full_buffer) { my_coef_ptr coef; + if (cinfo->data_precision != BITS_IN_JSAMPLE) + ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision); + coef = (my_coef_ptr) (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE, sizeof(my_coef_controller)); @@ -850,7 +854,7 @@ jinit_d_coef_controller(j_decompress_ptr cinfo, boolean need_full_buffer) (JDIMENSION)access_rows); } coef->pub.consume_data = consume_data; - coef->pub.decompress_data = decompress_data; + coef->pub._decompress_data = decompress_data; coef->pub.coef_arrays = coef->whole_image; /* link to virtual arrays */ #else ERREXIT(cinfo, JERR_NOT_COMPILED); @@ -867,7 +871,7 @@ jinit_d_coef_controller(j_decompress_ptr cinfo, boolean need_full_buffer) coef->MCU_buffer[i] = buffer + i; } coef->pub.consume_data = dummy_consume_data; - coef->pub.decompress_data = decompress_onepass; + coef->pub._decompress_data = decompress_onepass; coef->pub.coef_arrays = NULL; /* flag for no virtual arrays */ } diff --git a/src/3rdparty/libjpeg/src/jdcoefct.h b/src/3rdparty/libjpeg/src/jdcoefct.h index 9a0e7806636..bbe9e970515 100644 --- a/src/3rdparty/libjpeg/src/jdcoefct.h +++ b/src/3rdparty/libjpeg/src/jdcoefct.h @@ -6,6 +6,7 @@ * libjpeg-turbo Modifications: * Copyright 2009 Pierre Ossman for Cendio AB * Copyright (C) 2020, Google, Inc. + * Copyright (C) 2022, D. R. Commander. * For conditions of distribution and use, see the accompanying README.ijg * file. */ @@ -14,6 +15,8 @@ #include "jpeglib.h" +#if BITS_IN_JSAMPLE != 16 || defined(D_LOSSLESS_SUPPORTED) + /* Block smoothing is only applicable for progressive JPEG, so: */ #ifndef D_PROGRESSIVE_SUPPORTED #undef BLOCK_SMOOTHING_SUPPORTED @@ -81,3 +84,5 @@ start_iMCU_row(j_decompress_ptr cinfo) coef->MCU_ctr = 0; coef->MCU_vert_offset = 0; } + +#endif /* BITS_IN_JSAMPLE != 16 || defined(D_LOSSLESS_SUPPORTED) */ diff --git a/src/3rdparty/libjpeg/src/jdcol565.c b/src/3rdparty/libjpeg/src/jdcol565.c index 53c7bd9187d..2172d98fdaa 100644 --- a/src/3rdparty/libjpeg/src/jdcol565.c +++ b/src/3rdparty/libjpeg/src/jdcol565.c @@ -5,7 +5,7 @@ * Copyright (C) 1991-1997, Thomas G. Lane. * Modifications: * Copyright (C) 2013, Linaro Limited. - * Copyright (C) 2014-2015, D. R. Commander. + * Copyright (C) 2014-2015, 2022, D. R. Commander. * For conditions of distribution and use, see the accompanying README.ijg * file. * @@ -17,18 +17,19 @@ INLINE LOCAL(void) -ycc_rgb565_convert_internal(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, - JDIMENSION input_row, JSAMPARRAY output_buf, +ycc_rgb565_convert_internal(j_decompress_ptr cinfo, _JSAMPIMAGE input_buf, + JDIMENSION input_row, _JSAMPARRAY output_buf, int num_rows) { +#if BITS_IN_JSAMPLE != 16 my_cconvert_ptr cconvert = (my_cconvert_ptr)cinfo->cconvert; register int y, cb, cr; - register JSAMPROW outptr; - register JSAMPROW inptr0, inptr1, inptr2; + register _JSAMPROW outptr; + register _JSAMPROW inptr0, inptr1, inptr2; register JDIMENSION col; JDIMENSION num_cols = cinfo->output_width; /* copy these pointers into registers if possible */ - register JSAMPLE *range_limit = cinfo->sample_range_limit; + register _JSAMPLE *range_limit = (_JSAMPLE *)cinfo->sample_range_limit; register int *Crrtab = cconvert->Cr_r_tab; register int *Cbbtab = cconvert->Cb_b_tab; register JLONG *Crgtab = cconvert->Cr_g_tab; @@ -91,23 +92,27 @@ ycc_rgb565_convert_internal(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, *(INT16 *)outptr = (INT16)rgb; } } +#else + ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); +#endif } INLINE LOCAL(void) -ycc_rgb565D_convert_internal(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, - JDIMENSION input_row, JSAMPARRAY output_buf, +ycc_rgb565D_convert_internal(j_decompress_ptr cinfo, _JSAMPIMAGE input_buf, + JDIMENSION input_row, _JSAMPARRAY output_buf, int num_rows) { +#if BITS_IN_JSAMPLE != 16 my_cconvert_ptr cconvert = (my_cconvert_ptr)cinfo->cconvert; register int y, cb, cr; - register JSAMPROW outptr; - register JSAMPROW inptr0, inptr1, inptr2; + register _JSAMPROW outptr; + register _JSAMPROW inptr0, inptr1, inptr2; register JDIMENSION col; JDIMENSION num_cols = cinfo->output_width; /* copy these pointers into registers if possible */ - register JSAMPLE *range_limit = cinfo->sample_range_limit; + register _JSAMPLE *range_limit = (_JSAMPLE *)cinfo->sample_range_limit; register int *Crrtab = cconvert->Cr_r_tab; register int *Cbbtab = cconvert->Cb_b_tab; register JLONG *Crgtab = cconvert->Cr_g_tab; @@ -177,17 +182,20 @@ ycc_rgb565D_convert_internal(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, *(INT16 *)outptr = (INT16)rgb; } } +#else + ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); +#endif } INLINE LOCAL(void) -rgb_rgb565_convert_internal(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, - JDIMENSION input_row, JSAMPARRAY output_buf, +rgb_rgb565_convert_internal(j_decompress_ptr cinfo, _JSAMPIMAGE input_buf, + JDIMENSION input_row, _JSAMPARRAY output_buf, int num_rows) { - register JSAMPROW outptr; - register JSAMPROW inptr0, inptr1, inptr2; + register _JSAMPROW outptr; + register _JSAMPROW inptr0, inptr1, inptr2; register JDIMENSION col; JDIMENSION num_cols = cinfo->output_width; SHIFT_TEMPS @@ -237,14 +245,14 @@ rgb_rgb565_convert_internal(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, INLINE LOCAL(void) -rgb_rgb565D_convert_internal(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, - JDIMENSION input_row, JSAMPARRAY output_buf, +rgb_rgb565D_convert_internal(j_decompress_ptr cinfo, _JSAMPIMAGE input_buf, + JDIMENSION input_row, _JSAMPARRAY output_buf, int num_rows) { - register JSAMPROW outptr; - register JSAMPROW inptr0, inptr1, inptr2; + register _JSAMPROW outptr; + register _JSAMPROW inptr0, inptr1, inptr2; register JDIMENSION col; - register JSAMPLE *range_limit = cinfo->sample_range_limit; + register _JSAMPLE *range_limit = (_JSAMPLE *)cinfo->sample_range_limit; JDIMENSION num_cols = cinfo->output_width; JLONG d0 = dither_matrix[cinfo->output_scanline & DITHER_MASK]; SHIFT_TEMPS @@ -296,11 +304,11 @@ rgb_rgb565D_convert_internal(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, INLINE LOCAL(void) -gray_rgb565_convert_internal(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, - JDIMENSION input_row, JSAMPARRAY output_buf, +gray_rgb565_convert_internal(j_decompress_ptr cinfo, _JSAMPIMAGE input_buf, + JDIMENSION input_row, _JSAMPARRAY output_buf, int num_rows) { - register JSAMPROW inptr, outptr; + register _JSAMPROW inptr, outptr; register JDIMENSION col; JDIMENSION num_cols = cinfo->output_width; @@ -336,13 +344,13 @@ gray_rgb565_convert_internal(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, INLINE LOCAL(void) -gray_rgb565D_convert_internal(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, - JDIMENSION input_row, JSAMPARRAY output_buf, +gray_rgb565D_convert_internal(j_decompress_ptr cinfo, _JSAMPIMAGE input_buf, + JDIMENSION input_row, _JSAMPARRAY output_buf, int num_rows) { - register JSAMPROW inptr, outptr; + register _JSAMPROW inptr, outptr; register JDIMENSION col; - register JSAMPLE *range_limit = cinfo->sample_range_limit; + register _JSAMPLE *range_limit = (_JSAMPLE *)cinfo->sample_range_limit; JDIMENSION num_cols = cinfo->output_width; JLONG d0 = dither_matrix[cinfo->output_scanline & DITHER_MASK]; diff --git a/src/3rdparty/libjpeg/src/jdcolext.c b/src/3rdparty/libjpeg/src/jdcolext.c index fc7e7b8f004..f22e29d7224 100644 --- a/src/3rdparty/libjpeg/src/jdcolext.c +++ b/src/3rdparty/libjpeg/src/jdcolext.c @@ -4,7 +4,7 @@ * This file was part of the Independent JPEG Group's software: * Copyright (C) 1991-1997, Thomas G. Lane. * libjpeg-turbo Modifications: - * Copyright (C) 2009, 2011, 2015, 2023, D. R. Commander. + * Copyright (C) 2009, 2011, 2015, 2022-2023, D. R. Commander. * For conditions of distribution and use, see the accompanying README.ijg * file. * @@ -28,18 +28,19 @@ INLINE LOCAL(void) -ycc_rgb_convert_internal(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, - JDIMENSION input_row, JSAMPARRAY output_buf, +ycc_rgb_convert_internal(j_decompress_ptr cinfo, _JSAMPIMAGE input_buf, + JDIMENSION input_row, _JSAMPARRAY output_buf, int num_rows) { +#if BITS_IN_JSAMPLE != 16 my_cconvert_ptr cconvert = (my_cconvert_ptr)cinfo->cconvert; register int y, cb, cr; - register JSAMPROW outptr; - register JSAMPROW inptr0, inptr1, inptr2; + register _JSAMPROW outptr; + register _JSAMPROW inptr0, inptr1, inptr2; register JDIMENSION col; JDIMENSION num_cols = cinfo->output_width; /* copy these pointers into registers if possible */ - register JSAMPLE *range_limit = cinfo->sample_range_limit; + register _JSAMPLE *range_limit = (_JSAMPLE *)cinfo->sample_range_limit; register int *Crrtab = cconvert->Cr_r_tab; register int *Cbbtab = cconvert->Cb_b_tab; register JLONG *Crgtab = cconvert->Cr_g_tab; @@ -62,14 +63,17 @@ ycc_rgb_convert_internal(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, ((int)RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS))]; outptr[RGB_BLUE] = range_limit[y + Cbbtab[cb]]; - /* Set unused byte to MAXJSAMPLE so it can be interpreted as an opaque */ - /* alpha channel value */ + /* Set unused byte to _MAXJSAMPLE so it can be interpreted as an */ + /* opaque alpha channel value */ #ifdef RGB_ALPHA - outptr[RGB_ALPHA] = MAXJSAMPLE; + outptr[RGB_ALPHA] = _MAXJSAMPLE; #endif outptr += RGB_PIXELSIZE; } } +#else + ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); +#endif } @@ -81,11 +85,11 @@ ycc_rgb_convert_internal(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, INLINE LOCAL(void) -gray_rgb_convert_internal(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, - JDIMENSION input_row, JSAMPARRAY output_buf, +gray_rgb_convert_internal(j_decompress_ptr cinfo, _JSAMPIMAGE input_buf, + JDIMENSION input_row, _JSAMPARRAY output_buf, int num_rows) { - register JSAMPROW inptr, outptr; + register _JSAMPROW inptr, outptr; register JDIMENSION col; JDIMENSION num_cols = cinfo->output_width; @@ -94,10 +98,10 @@ gray_rgb_convert_internal(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, outptr = *output_buf++; for (col = 0; col < num_cols; col++) { outptr[RGB_RED] = outptr[RGB_GREEN] = outptr[RGB_BLUE] = inptr[col]; - /* Set unused byte to MAXJSAMPLE so it can be interpreted as an opaque */ - /* alpha channel value */ + /* Set unused byte to _MAXJSAMPLE so it can be interpreted as an */ + /* opaque alpha channel value */ #ifdef RGB_ALPHA - outptr[RGB_ALPHA] = MAXJSAMPLE; + outptr[RGB_ALPHA] = _MAXJSAMPLE; #endif outptr += RGB_PIXELSIZE; } @@ -111,12 +115,12 @@ gray_rgb_convert_internal(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, INLINE LOCAL(void) -rgb_rgb_convert_internal(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, - JDIMENSION input_row, JSAMPARRAY output_buf, +rgb_rgb_convert_internal(j_decompress_ptr cinfo, _JSAMPIMAGE input_buf, + JDIMENSION input_row, _JSAMPARRAY output_buf, int num_rows) { - register JSAMPROW inptr0, inptr1, inptr2; - register JSAMPROW outptr; + register _JSAMPROW inptr0, inptr1, inptr2; + register _JSAMPROW outptr; register JDIMENSION col; JDIMENSION num_cols = cinfo->output_width; @@ -130,10 +134,10 @@ rgb_rgb_convert_internal(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, outptr[RGB_RED] = inptr0[col]; outptr[RGB_GREEN] = inptr1[col]; outptr[RGB_BLUE] = inptr2[col]; - /* Set unused byte to MAXJSAMPLE so it can be interpreted as an opaque */ - /* alpha channel value */ + /* Set unused byte to _MAXJSAMPLE so it can be interpreted as an */ + /* opaque alpha channel value */ #ifdef RGB_ALPHA - outptr[RGB_ALPHA] = MAXJSAMPLE; + outptr[RGB_ALPHA] = _MAXJSAMPLE; #endif outptr += RGB_PIXELSIZE; } diff --git a/src/3rdparty/libjpeg/src/jdcolor.c b/src/3rdparty/libjpeg/src/jdcolor.c index 735190b7000..e5c7b58ebfa 100644 --- a/src/3rdparty/libjpeg/src/jdcolor.c +++ b/src/3rdparty/libjpeg/src/jdcolor.c @@ -6,7 +6,7 @@ * Modified 2011 by Guido Vollbeding. * libjpeg-turbo Modifications: * Copyright 2009 Pierre Ossman for Cendio AB - * Copyright (C) 2009, 2011-2012, 2014-2015, D. R. Commander. + * Copyright (C) 2009, 2011-2012, 2014-2015, 2022, D. R. Commander. * Copyright (C) 2013, Linaro Limited. * For conditions of distribution and use, see the accompanying README.ijg * file. @@ -18,13 +18,17 @@ #include "jinclude.h" #include "jpeglib.h" #include "jsimd.h" +#include "jsamplecomp.h" +#if BITS_IN_JSAMPLE != 16 || defined(D_LOSSLESS_SUPPORTED) + /* Private subobject */ typedef struct { struct jpeg_color_deconverter pub; /* public fields */ +#if BITS_IN_JSAMPLE != 16 /* Private state for YCC->RGB conversion */ int *Cr_r_tab; /* => table for Cr to R conversion */ int *Cb_b_tab; /* => table for Cb to B conversion */ @@ -33,6 +37,7 @@ typedef struct { /* Private state for RGB->Y conversion */ JLONG *rgb_y_tab; /* => table for RGB to Y conversion */ +#endif } my_color_deconverter; typedef my_color_deconverter *my_cconvert_ptr; @@ -43,7 +48,7 @@ typedef my_color_deconverter *my_cconvert_ptr; /* * YCbCr is defined per CCIR 601-1, except that Cb and Cr are - * normalized to the range 0..MAXJSAMPLE rather than -0.5 .. 0.5. + * normalized to the range 0.._MAXJSAMPLE rather than -0.5 .. 0.5. * The conversion equations to be implemented are therefore * * R = Y + 1.40200 * Cr @@ -52,7 +57,7 @@ typedef my_color_deconverter *my_cconvert_ptr; * * Y = 0.29900 * R + 0.58700 * G + 0.11400 * B * - * where Cb and Cr represent the incoming values less CENTERJSAMPLE. + * where Cb and Cr represent the incoming values less _CENTERJSAMPLE. * (These numbers are derived from TIFF 6.0 section 21, dated 3-June-92.) * * To avoid floating-point arithmetic, we represent the fractional constants @@ -63,7 +68,7 @@ typedef my_color_deconverter *my_cconvert_ptr; * * For even more speed, we avoid doing any multiplications in the inner loop * by precalculating the constants times Cb and Cr for all possible values. - * For 8-bit JSAMPLEs this is very reasonable (only 256 entries per table); + * For 8-bit samples this is very reasonable (only 256 entries per table); * for 12-bit samples it is still acceptable. It's not very reasonable for * 16-bit samples, but if you want lossless storage you shouldn't be changing * colorspace anyway. @@ -84,9 +89,9 @@ typedef my_color_deconverter *my_cconvert_ptr; */ #define R_Y_OFF 0 /* offset to R => Y section */ -#define G_Y_OFF (1 * (MAXJSAMPLE + 1)) /* offset to G => Y section */ -#define B_Y_OFF (2 * (MAXJSAMPLE + 1)) /* etc. */ -#define TABLE_SIZE (3 * (MAXJSAMPLE + 1)) +#define G_Y_OFF (1 * (_MAXJSAMPLE + 1)) /* offset to G => Y section */ +#define B_Y_OFF (2 * (_MAXJSAMPLE + 1)) /* etc. */ +#define TABLE_SIZE (3 * (_MAXJSAMPLE + 1)) /* Include inline routines for colorspace extensions */ @@ -209,6 +214,7 @@ typedef my_color_deconverter *my_cconvert_ptr; LOCAL(void) build_ycc_rgb_table(j_decompress_ptr cinfo) { +#if BITS_IN_JSAMPLE != 16 my_cconvert_ptr cconvert = (my_cconvert_ptr)cinfo->cconvert; int i; JLONG x; @@ -216,20 +222,20 @@ build_ycc_rgb_table(j_decompress_ptr cinfo) cconvert->Cr_r_tab = (int *) (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE, - (MAXJSAMPLE + 1) * sizeof(int)); + (_MAXJSAMPLE + 1) * sizeof(int)); cconvert->Cb_b_tab = (int *) (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE, - (MAXJSAMPLE + 1) * sizeof(int)); + (_MAXJSAMPLE + 1) * sizeof(int)); cconvert->Cr_g_tab = (JLONG *) (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE, - (MAXJSAMPLE + 1) * sizeof(JLONG)); + (_MAXJSAMPLE + 1) * sizeof(JLONG)); cconvert->Cb_g_tab = (JLONG *) (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE, - (MAXJSAMPLE + 1) * sizeof(JLONG)); + (_MAXJSAMPLE + 1) * sizeof(JLONG)); - for (i = 0, x = -CENTERJSAMPLE; i <= MAXJSAMPLE; i++, x++) { - /* i is the actual input pixel value, in the range 0..MAXJSAMPLE */ - /* The Cb or Cr value we are thinking of is x = i - CENTERJSAMPLE */ + for (i = 0, x = -_CENTERJSAMPLE; i <= _MAXJSAMPLE; i++, x++) { + /* i is the actual input pixel value, in the range 0.._MAXJSAMPLE */ + /* The Cb or Cr value we are thinking of is x = i - _CENTERJSAMPLE */ /* Cr=>R value is nearest int to 1.40200 * x */ cconvert->Cr_r_tab[i] = (int) RIGHT_SHIFT(FIX(1.40200) * x + ONE_HALF, SCALEBITS); @@ -242,6 +248,9 @@ build_ycc_rgb_table(j_decompress_ptr cinfo) /* We also add in ONE_HALF so that need not do it in inner loop */ cconvert->Cb_g_tab[i] = (-FIX(0.34414)) * x + ONE_HALF; } +#else + ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); +#endif } @@ -250,8 +259,8 @@ build_ycc_rgb_table(j_decompress_ptr cinfo) */ METHODDEF(void) -ycc_rgb_convert(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, - JDIMENSION input_row, JSAMPARRAY output_buf, int num_rows) +ycc_rgb_convert(j_decompress_ptr cinfo, _JSAMPIMAGE input_buf, + JDIMENSION input_row, _JSAMPARRAY output_buf, int num_rows) { switch (cinfo->out_color_space) { case JCS_EXT_RGB: @@ -300,6 +309,7 @@ ycc_rgb_convert(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, LOCAL(void) build_rgb_y_table(j_decompress_ptr cinfo) { +#if BITS_IN_JSAMPLE != 16 my_cconvert_ptr cconvert = (my_cconvert_ptr)cinfo->cconvert; JLONG *rgb_y_tab; JLONG i; @@ -309,11 +319,14 @@ build_rgb_y_table(j_decompress_ptr cinfo) (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE, (TABLE_SIZE * sizeof(JLONG))); - for (i = 0; i <= MAXJSAMPLE; i++) { + for (i = 0; i <= _MAXJSAMPLE; i++) { rgb_y_tab[i + R_Y_OFF] = FIX(0.29900) * i; rgb_y_tab[i + G_Y_OFF] = FIX(0.58700) * i; rgb_y_tab[i + B_Y_OFF] = FIX(0.11400) * i + ONE_HALF; } +#else + ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); +#endif } @@ -322,14 +335,15 @@ build_rgb_y_table(j_decompress_ptr cinfo) */ METHODDEF(void) -rgb_gray_convert(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, - JDIMENSION input_row, JSAMPARRAY output_buf, int num_rows) +rgb_gray_convert(j_decompress_ptr cinfo, _JSAMPIMAGE input_buf, + JDIMENSION input_row, _JSAMPARRAY output_buf, int num_rows) { +#if BITS_IN_JSAMPLE != 16 my_cconvert_ptr cconvert = (my_cconvert_ptr)cinfo->cconvert; register int r, g, b; register JLONG *ctab = cconvert->rgb_y_tab; - register JSAMPROW outptr; - register JSAMPROW inptr0, inptr1, inptr2; + register _JSAMPROW outptr; + register _JSAMPROW inptr0, inptr1, inptr2; register JDIMENSION col; JDIMENSION num_cols = cinfo->output_width; @@ -344,10 +358,13 @@ rgb_gray_convert(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, g = inptr1[col]; b = inptr2[col]; /* Y */ - outptr[col] = (JSAMPLE)((ctab[r + R_Y_OFF] + ctab[g + G_Y_OFF] + - ctab[b + B_Y_OFF]) >> SCALEBITS); + outptr[col] = (_JSAMPLE)((ctab[r + R_Y_OFF] + ctab[g + G_Y_OFF] + + ctab[b + B_Y_OFF]) >> SCALEBITS); } } +#else + ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); +#endif } @@ -357,10 +374,10 @@ rgb_gray_convert(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, */ METHODDEF(void) -null_convert(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, - JDIMENSION input_row, JSAMPARRAY output_buf, int num_rows) +null_convert(j_decompress_ptr cinfo, _JSAMPIMAGE input_buf, + JDIMENSION input_row, _JSAMPARRAY output_buf, int num_rows) { - register JSAMPROW inptr, inptr0, inptr1, inptr2, inptr3, outptr; + register _JSAMPROW inptr, inptr0, inptr1, inptr2, inptr3, outptr; register JDIMENSION col; register int num_components = cinfo->num_components; JDIMENSION num_cols = cinfo->output_width; @@ -418,11 +435,11 @@ null_convert(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, */ METHODDEF(void) -grayscale_convert(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, - JDIMENSION input_row, JSAMPARRAY output_buf, int num_rows) +grayscale_convert(j_decompress_ptr cinfo, _JSAMPIMAGE input_buf, + JDIMENSION input_row, _JSAMPARRAY output_buf, int num_rows) { - jcopy_sample_rows(input_buf[0], (int)input_row, output_buf, 0, num_rows, - cinfo->output_width); + _jcopy_sample_rows(input_buf[0], (int)input_row, output_buf, 0, num_rows, + cinfo->output_width); } @@ -431,8 +448,8 @@ grayscale_convert(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, */ METHODDEF(void) -gray_rgb_convert(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, - JDIMENSION input_row, JSAMPARRAY output_buf, int num_rows) +gray_rgb_convert(j_decompress_ptr cinfo, _JSAMPIMAGE input_buf, + JDIMENSION input_row, _JSAMPARRAY output_buf, int num_rows) { switch (cinfo->out_color_space) { case JCS_EXT_RGB: @@ -476,8 +493,8 @@ gray_rgb_convert(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, */ METHODDEF(void) -rgb_rgb_convert(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, - JDIMENSION input_row, JSAMPARRAY output_buf, int num_rows) +rgb_rgb_convert(j_decompress_ptr cinfo, _JSAMPIMAGE input_buf, + JDIMENSION input_row, _JSAMPARRAY output_buf, int num_rows) { switch (cinfo->out_color_space) { case JCS_EXT_RGB: @@ -524,17 +541,18 @@ rgb_rgb_convert(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, */ METHODDEF(void) -ycck_cmyk_convert(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, - JDIMENSION input_row, JSAMPARRAY output_buf, int num_rows) +ycck_cmyk_convert(j_decompress_ptr cinfo, _JSAMPIMAGE input_buf, + JDIMENSION input_row, _JSAMPARRAY output_buf, int num_rows) { +#if BITS_IN_JSAMPLE != 16 my_cconvert_ptr cconvert = (my_cconvert_ptr)cinfo->cconvert; register int y, cb, cr; - register JSAMPROW outptr; - register JSAMPROW inptr0, inptr1, inptr2, inptr3; + register _JSAMPROW outptr; + register _JSAMPROW inptr0, inptr1, inptr2, inptr3; register JDIMENSION col; JDIMENSION num_cols = cinfo->output_width; /* copy these pointers into registers if possible */ - register JSAMPLE *range_limit = cinfo->sample_range_limit; + register _JSAMPLE *range_limit = (_JSAMPLE *)cinfo->sample_range_limit; register int *Crrtab = cconvert->Cr_r_tab; register int *Cbbtab = cconvert->Cb_b_tab; register JLONG *Crgtab = cconvert->Cr_g_tab; @@ -553,16 +571,19 @@ ycck_cmyk_convert(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, cb = inptr1[col]; cr = inptr2[col]; /* Range-limiting is essential due to noise introduced by DCT losses. */ - outptr[0] = range_limit[MAXJSAMPLE - (y + Crrtab[cr])]; /* red */ - outptr[1] = range_limit[MAXJSAMPLE - (y + /* green */ + outptr[0] = range_limit[_MAXJSAMPLE - (y + Crrtab[cr])]; /* red */ + outptr[1] = range_limit[_MAXJSAMPLE - (y + /* green */ ((int)RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS)))]; - outptr[2] = range_limit[MAXJSAMPLE - (y + Cbbtab[cb])]; /* blue */ + outptr[2] = range_limit[_MAXJSAMPLE - (y + Cbbtab[cb])]; /* blue */ /* K passes through unchanged */ outptr[3] = inptr3[col]; outptr += 4; } } +#else + ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); +#endif } @@ -652,8 +673,8 @@ static INLINE boolean is_big_endian(void) METHODDEF(void) -ycc_rgb565_convert(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, - JDIMENSION input_row, JSAMPARRAY output_buf, int num_rows) +ycc_rgb565_convert(j_decompress_ptr cinfo, _JSAMPIMAGE input_buf, + JDIMENSION input_row, _JSAMPARRAY output_buf, int num_rows) { if (is_big_endian()) ycc_rgb565_convert_be(cinfo, input_buf, input_row, output_buf, num_rows); @@ -663,8 +684,8 @@ ycc_rgb565_convert(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, METHODDEF(void) -ycc_rgb565D_convert(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, - JDIMENSION input_row, JSAMPARRAY output_buf, int num_rows) +ycc_rgb565D_convert(j_decompress_ptr cinfo, _JSAMPIMAGE input_buf, + JDIMENSION input_row, _JSAMPARRAY output_buf, int num_rows) { if (is_big_endian()) ycc_rgb565D_convert_be(cinfo, input_buf, input_row, output_buf, num_rows); @@ -674,8 +695,8 @@ ycc_rgb565D_convert(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, METHODDEF(void) -rgb_rgb565_convert(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, - JDIMENSION input_row, JSAMPARRAY output_buf, int num_rows) +rgb_rgb565_convert(j_decompress_ptr cinfo, _JSAMPIMAGE input_buf, + JDIMENSION input_row, _JSAMPARRAY output_buf, int num_rows) { if (is_big_endian()) rgb_rgb565_convert_be(cinfo, input_buf, input_row, output_buf, num_rows); @@ -685,8 +706,8 @@ rgb_rgb565_convert(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, METHODDEF(void) -rgb_rgb565D_convert(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, - JDIMENSION input_row, JSAMPARRAY output_buf, int num_rows) +rgb_rgb565D_convert(j_decompress_ptr cinfo, _JSAMPIMAGE input_buf, + JDIMENSION input_row, _JSAMPARRAY output_buf, int num_rows) { if (is_big_endian()) rgb_rgb565D_convert_be(cinfo, input_buf, input_row, output_buf, num_rows); @@ -696,8 +717,8 @@ rgb_rgb565D_convert(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, METHODDEF(void) -gray_rgb565_convert(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, - JDIMENSION input_row, JSAMPARRAY output_buf, int num_rows) +gray_rgb565_convert(j_decompress_ptr cinfo, _JSAMPIMAGE input_buf, + JDIMENSION input_row, _JSAMPARRAY output_buf, int num_rows) { if (is_big_endian()) gray_rgb565_convert_be(cinfo, input_buf, input_row, output_buf, num_rows); @@ -707,8 +728,8 @@ gray_rgb565_convert(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, METHODDEF(void) -gray_rgb565D_convert(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, - JDIMENSION input_row, JSAMPARRAY output_buf, int num_rows) +gray_rgb565D_convert(j_decompress_ptr cinfo, _JSAMPIMAGE input_buf, + JDIMENSION input_row, _JSAMPARRAY output_buf, int num_rows) { if (is_big_endian()) gray_rgb565D_convert_be(cinfo, input_buf, input_row, output_buf, num_rows); @@ -733,11 +754,14 @@ start_pass_dcolor(j_decompress_ptr cinfo) */ GLOBAL(void) -jinit_color_deconverter(j_decompress_ptr cinfo) +_jinit_color_deconverter(j_decompress_ptr cinfo) { my_cconvert_ptr cconvert; int ci; + if (cinfo->data_precision != BITS_IN_JSAMPLE) + ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision); + cconvert = (my_cconvert_ptr) (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE, sizeof(my_color_deconverter)); @@ -772,19 +796,24 @@ jinit_color_deconverter(j_decompress_ptr cinfo) /* Set out_color_components and conversion method based on requested space. * Also clear the component_needed flags for any unused components, * so that earlier pipeline stages can avoid useless computation. + * NOTE: We do not allow any lossy color conversion algorithms in lossless + * mode. */ switch (cinfo->out_color_space) { case JCS_GRAYSCALE: + if (cinfo->master->lossless && + cinfo->jpeg_color_space != cinfo->out_color_space) + ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); cinfo->out_color_components = 1; if (cinfo->jpeg_color_space == JCS_GRAYSCALE || cinfo->jpeg_color_space == JCS_YCbCr) { - cconvert->pub.color_convert = grayscale_convert; + cconvert->pub._color_convert = grayscale_convert; /* For color->grayscale conversion, only the Y (0) component is needed */ for (ci = 1; ci < cinfo->num_components; ci++) cinfo->comp_info[ci].component_needed = FALSE; } else if (cinfo->jpeg_color_space == JCS_RGB) { - cconvert->pub.color_convert = rgb_gray_convert; + cconvert->pub._color_convert = rgb_gray_convert; build_rgb_y_table(cinfo); } else ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); @@ -801,65 +830,78 @@ jinit_color_deconverter(j_decompress_ptr cinfo) case JCS_EXT_BGRA: case JCS_EXT_ABGR: case JCS_EXT_ARGB: + if (cinfo->master->lossless && cinfo->jpeg_color_space != JCS_RGB) + ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); cinfo->out_color_components = rgb_pixelsize[cinfo->out_color_space]; if (cinfo->jpeg_color_space == JCS_YCbCr) { +#ifdef WITH_SIMD if (jsimd_can_ycc_rgb()) - cconvert->pub.color_convert = jsimd_ycc_rgb_convert; - else { - cconvert->pub.color_convert = ycc_rgb_convert; + cconvert->pub._color_convert = jsimd_ycc_rgb_convert; + else +#endif + { + cconvert->pub._color_convert = ycc_rgb_convert; build_ycc_rgb_table(cinfo); } } else if (cinfo->jpeg_color_space == JCS_GRAYSCALE) { - cconvert->pub.color_convert = gray_rgb_convert; + cconvert->pub._color_convert = gray_rgb_convert; } else if (cinfo->jpeg_color_space == JCS_RGB) { if (rgb_red[cinfo->out_color_space] == 0 && rgb_green[cinfo->out_color_space] == 1 && rgb_blue[cinfo->out_color_space] == 2 && rgb_pixelsize[cinfo->out_color_space] == 3) - cconvert->pub.color_convert = null_convert; + cconvert->pub._color_convert = null_convert; else - cconvert->pub.color_convert = rgb_rgb_convert; + cconvert->pub._color_convert = rgb_rgb_convert; } else ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); break; case JCS_RGB565: + if (cinfo->master->lossless) + ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); cinfo->out_color_components = 3; if (cinfo->dither_mode == JDITHER_NONE) { if (cinfo->jpeg_color_space == JCS_YCbCr) { +#ifdef WITH_SIMD if (jsimd_can_ycc_rgb565()) - cconvert->pub.color_convert = jsimd_ycc_rgb565_convert; - else { - cconvert->pub.color_convert = ycc_rgb565_convert; + cconvert->pub._color_convert = jsimd_ycc_rgb565_convert; + else +#endif + { + cconvert->pub._color_convert = ycc_rgb565_convert; build_ycc_rgb_table(cinfo); } } else if (cinfo->jpeg_color_space == JCS_GRAYSCALE) { - cconvert->pub.color_convert = gray_rgb565_convert; + cconvert->pub._color_convert = gray_rgb565_convert; } else if (cinfo->jpeg_color_space == JCS_RGB) { - cconvert->pub.color_convert = rgb_rgb565_convert; + cconvert->pub._color_convert = rgb_rgb565_convert; } else ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); } else { /* only ordered dithering is supported */ if (cinfo->jpeg_color_space == JCS_YCbCr) { - cconvert->pub.color_convert = ycc_rgb565D_convert; + cconvert->pub._color_convert = ycc_rgb565D_convert; build_ycc_rgb_table(cinfo); } else if (cinfo->jpeg_color_space == JCS_GRAYSCALE) { - cconvert->pub.color_convert = gray_rgb565D_convert; + cconvert->pub._color_convert = gray_rgb565D_convert; } else if (cinfo->jpeg_color_space == JCS_RGB) { - cconvert->pub.color_convert = rgb_rgb565D_convert; + cconvert->pub._color_convert = rgb_rgb565D_convert; } else ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); } break; case JCS_CMYK: + if (cinfo->master->lossless && + cinfo->jpeg_color_space != cinfo->out_color_space) + ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); cinfo->out_color_components = 4; if (cinfo->jpeg_color_space == JCS_YCCK) { - cconvert->pub.color_convert = ycck_cmyk_convert; + cconvert->pub._color_convert = ycck_cmyk_convert; build_ycc_rgb_table(cinfo); } else if (cinfo->jpeg_color_space == JCS_CMYK) { - cconvert->pub.color_convert = null_convert; + cconvert->pub._color_convert = null_convert; } else ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); break; @@ -868,7 +910,7 @@ jinit_color_deconverter(j_decompress_ptr cinfo) /* Permit null conversion to same output space */ if (cinfo->out_color_space == cinfo->jpeg_color_space) { cinfo->out_color_components = cinfo->num_components; - cconvert->pub.color_convert = null_convert; + cconvert->pub._color_convert = null_convert; } else /* unsupported non-null conversion */ ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); break; @@ -879,3 +921,5 @@ jinit_color_deconverter(j_decompress_ptr cinfo) else cinfo->output_components = cinfo->out_color_components; } + +#endif /* BITS_IN_JSAMPLE != 16 || defined(D_LOSSLESS_SUPPORTED) */ diff --git a/src/3rdparty/libjpeg/src/jdct.h b/src/3rdparty/libjpeg/src/jdct.h index 66d1718b770..0411a79bc0b 100644 --- a/src/3rdparty/libjpeg/src/jdct.h +++ b/src/3rdparty/libjpeg/src/jdct.h @@ -4,7 +4,7 @@ * This file was part of the Independent JPEG Group's software: * Copyright (C) 1994-1996, Thomas G. Lane. * libjpeg-turbo Modifications: - * Copyright (C) 2015, D. R. Commander. + * Copyright (C) 2015, 2022, D. R. Commander. * For conditions of distribution and use, see the accompanying README.ijg * file. * @@ -15,13 +15,15 @@ * machine-dependent tuning (e.g., assembly coding). */ +#include "jsamplecomp.h" + /* * A forward DCT routine is given a pointer to a work area of type DCTELEM[]; * the DCT is to be performed in-place in that buffer. Type DCTELEM is int * for 8-bit samples, JLONG for 12-bit samples. (NOTE: Floating-point DCT * implementations use an array of type FAST_FLOAT, instead.) - * The DCT inputs are expected to be signed (range +-CENTERJSAMPLE). + * The DCT inputs are expected to be signed (range +-_CENTERJSAMPLE). * The DCT outputs are returned scaled up by a factor of 8; they therefore * have a range of +-8K for 8-bit data, +-128K for 12-bit data. This * convention improves accuracy in integer implementations and saves some @@ -76,78 +78,89 @@ typedef FAST_FLOAT FLOAT_MULT_TYPE; /* preferred floating type */ /* * Each IDCT routine is responsible for range-limiting its results and - * converting them to unsigned form (0..MAXJSAMPLE). The raw outputs could + * converting them to unsigned form (0.._MAXJSAMPLE). The raw outputs could * be quite far out of range if the input data is corrupt, so a bulletproof * range-limiting step is required. We use a mask-and-table-lookup method * to do the combined operations quickly. See the comments with * prepare_range_limit_table (in jdmaster.c) for more info. */ -#define IDCT_range_limit(cinfo) ((cinfo)->sample_range_limit + CENTERJSAMPLE) +#define IDCT_range_limit(cinfo) \ + ((_JSAMPLE *)((cinfo)->sample_range_limit) + _CENTERJSAMPLE) -#define RANGE_MASK (MAXJSAMPLE * 4 + 3) /* 2 bits wider than legal samples */ +#define RANGE_MASK (_MAXJSAMPLE * 4 + 3) /* 2 bits wider than legal samples */ /* Extern declarations for the forward and inverse DCT routines. */ -EXTERN(void) jpeg_fdct_islow(DCTELEM *data); -EXTERN(void) jpeg_fdct_ifast(DCTELEM *data); +EXTERN(void) _jpeg_fdct_islow(DCTELEM *data); +EXTERN(void) _jpeg_fdct_ifast(DCTELEM *data); EXTERN(void) jpeg_fdct_float(FAST_FLOAT *data); -EXTERN(void) jpeg_idct_islow(j_decompress_ptr cinfo, - jpeg_component_info *compptr, JCOEFPTR coef_block, - JSAMPARRAY output_buf, JDIMENSION output_col); -EXTERN(void) jpeg_idct_ifast(j_decompress_ptr cinfo, - jpeg_component_info *compptr, JCOEFPTR coef_block, - JSAMPARRAY output_buf, JDIMENSION output_col); -EXTERN(void) jpeg_idct_float(j_decompress_ptr cinfo, - jpeg_component_info *compptr, JCOEFPTR coef_block, - JSAMPARRAY output_buf, JDIMENSION output_col); -EXTERN(void) jpeg_idct_7x7(j_decompress_ptr cinfo, - jpeg_component_info *compptr, JCOEFPTR coef_block, - JSAMPARRAY output_buf, JDIMENSION output_col); -EXTERN(void) jpeg_idct_6x6(j_decompress_ptr cinfo, - jpeg_component_info *compptr, JCOEFPTR coef_block, - JSAMPARRAY output_buf, JDIMENSION output_col); -EXTERN(void) jpeg_idct_5x5(j_decompress_ptr cinfo, - jpeg_component_info *compptr, JCOEFPTR coef_block, - JSAMPARRAY output_buf, JDIMENSION output_col); -EXTERN(void) jpeg_idct_4x4(j_decompress_ptr cinfo, - jpeg_component_info *compptr, JCOEFPTR coef_block, - JSAMPARRAY output_buf, JDIMENSION output_col); -EXTERN(void) jpeg_idct_3x3(j_decompress_ptr cinfo, - jpeg_component_info *compptr, JCOEFPTR coef_block, - JSAMPARRAY output_buf, JDIMENSION output_col); -EXTERN(void) jpeg_idct_2x2(j_decompress_ptr cinfo, - jpeg_component_info *compptr, JCOEFPTR coef_block, - JSAMPARRAY output_buf, JDIMENSION output_col); -EXTERN(void) jpeg_idct_1x1(j_decompress_ptr cinfo, - jpeg_component_info *compptr, JCOEFPTR coef_block, - JSAMPARRAY output_buf, JDIMENSION output_col); -EXTERN(void) jpeg_idct_9x9(j_decompress_ptr cinfo, - jpeg_component_info *compptr, JCOEFPTR coef_block, - JSAMPARRAY output_buf, JDIMENSION output_col); -EXTERN(void) jpeg_idct_10x10(j_decompress_ptr cinfo, - jpeg_component_info *compptr, JCOEFPTR coef_block, - JSAMPARRAY output_buf, JDIMENSION output_col); -EXTERN(void) jpeg_idct_11x11(j_decompress_ptr cinfo, - jpeg_component_info *compptr, JCOEFPTR coef_block, - JSAMPARRAY output_buf, JDIMENSION output_col); -EXTERN(void) jpeg_idct_12x12(j_decompress_ptr cinfo, - jpeg_component_info *compptr, JCOEFPTR coef_block, - JSAMPARRAY output_buf, JDIMENSION output_col); -EXTERN(void) jpeg_idct_13x13(j_decompress_ptr cinfo, - jpeg_component_info *compptr, JCOEFPTR coef_block, - JSAMPARRAY output_buf, JDIMENSION output_col); -EXTERN(void) jpeg_idct_14x14(j_decompress_ptr cinfo, - jpeg_component_info *compptr, JCOEFPTR coef_block, - JSAMPARRAY output_buf, JDIMENSION output_col); -EXTERN(void) jpeg_idct_15x15(j_decompress_ptr cinfo, - jpeg_component_info *compptr, JCOEFPTR coef_block, - JSAMPARRAY output_buf, JDIMENSION output_col); -EXTERN(void) jpeg_idct_16x16(j_decompress_ptr cinfo, - jpeg_component_info *compptr, JCOEFPTR coef_block, - JSAMPARRAY output_buf, JDIMENSION output_col); +EXTERN(void) _jpeg_idct_islow(j_decompress_ptr cinfo, + jpeg_component_info *compptr, + JCOEFPTR coef_block, _JSAMPARRAY output_buf, + JDIMENSION output_col); +EXTERN(void) _jpeg_idct_ifast(j_decompress_ptr cinfo, + jpeg_component_info *compptr, + JCOEFPTR coef_block, _JSAMPARRAY output_buf, + JDIMENSION output_col); +EXTERN(void) _jpeg_idct_float(j_decompress_ptr cinfo, + jpeg_component_info *compptr, + JCOEFPTR coef_block, _JSAMPARRAY output_buf, + JDIMENSION output_col); +EXTERN(void) _jpeg_idct_7x7(j_decompress_ptr cinfo, + jpeg_component_info *compptr, JCOEFPTR coef_block, + _JSAMPARRAY output_buf, JDIMENSION output_col); +EXTERN(void) _jpeg_idct_6x6(j_decompress_ptr cinfo, + jpeg_component_info *compptr, JCOEFPTR coef_block, + _JSAMPARRAY output_buf, JDIMENSION output_col); +EXTERN(void) _jpeg_idct_5x5(j_decompress_ptr cinfo, + jpeg_component_info *compptr, JCOEFPTR coef_block, + _JSAMPARRAY output_buf, JDIMENSION output_col); +EXTERN(void) _jpeg_idct_4x4(j_decompress_ptr cinfo, + jpeg_component_info *compptr, JCOEFPTR coef_block, + _JSAMPARRAY output_buf, JDIMENSION output_col); +EXTERN(void) _jpeg_idct_3x3(j_decompress_ptr cinfo, + jpeg_component_info *compptr, JCOEFPTR coef_block, + _JSAMPARRAY output_buf, JDIMENSION output_col); +EXTERN(void) _jpeg_idct_2x2(j_decompress_ptr cinfo, + jpeg_component_info *compptr, JCOEFPTR coef_block, + _JSAMPARRAY output_buf, JDIMENSION output_col); +EXTERN(void) _jpeg_idct_1x1(j_decompress_ptr cinfo, + jpeg_component_info *compptr, JCOEFPTR coef_block, + _JSAMPARRAY output_buf, JDIMENSION output_col); +EXTERN(void) _jpeg_idct_9x9(j_decompress_ptr cinfo, + jpeg_component_info *compptr, JCOEFPTR coef_block, + _JSAMPARRAY output_buf, JDIMENSION output_col); +EXTERN(void) _jpeg_idct_10x10(j_decompress_ptr cinfo, + jpeg_component_info *compptr, + JCOEFPTR coef_block, _JSAMPARRAY output_buf, + JDIMENSION output_col); +EXTERN(void) _jpeg_idct_11x11(j_decompress_ptr cinfo, + jpeg_component_info *compptr, + JCOEFPTR coef_block, _JSAMPARRAY output_buf, + JDIMENSION output_col); +EXTERN(void) _jpeg_idct_12x12(j_decompress_ptr cinfo, + jpeg_component_info *compptr, + JCOEFPTR coef_block, _JSAMPARRAY output_buf, + JDIMENSION output_col); +EXTERN(void) _jpeg_idct_13x13(j_decompress_ptr cinfo, + jpeg_component_info *compptr, + JCOEFPTR coef_block, _JSAMPARRAY output_buf, + JDIMENSION output_col); +EXTERN(void) _jpeg_idct_14x14(j_decompress_ptr cinfo, + jpeg_component_info *compptr, + JCOEFPTR coef_block, _JSAMPARRAY output_buf, + JDIMENSION output_col); +EXTERN(void) _jpeg_idct_15x15(j_decompress_ptr cinfo, + jpeg_component_info *compptr, + JCOEFPTR coef_block, _JSAMPARRAY output_buf, + JDIMENSION output_col); +EXTERN(void) _jpeg_idct_16x16(j_decompress_ptr cinfo, + jpeg_component_info *compptr, + JCOEFPTR coef_block, _JSAMPARRAY output_buf, + JDIMENSION output_col); /* diff --git a/src/3rdparty/libjpeg/src/jddctmgr.c b/src/3rdparty/libjpeg/src/jddctmgr.c index e78d7bebe28..0bd8c2b591d 100644 --- a/src/3rdparty/libjpeg/src/jddctmgr.c +++ b/src/3rdparty/libjpeg/src/jddctmgr.c @@ -26,7 +26,7 @@ #include "jpeglib.h" #include "jdct.h" /* Private declarations for DCT subsystem */ #include "jsimddct.h" -#include "jpegcomp.h" +#include "jpegapicomp.h" /* @@ -100,7 +100,7 @@ start_pass(j_decompress_ptr cinfo) int ci, i; jpeg_component_info *compptr; int method = 0; - inverse_DCT_method_ptr method_ptr = NULL; + _inverse_DCT_method_ptr method_ptr = NULL; JQUANT_TBL *qtbl; for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; @@ -109,42 +109,46 @@ start_pass(j_decompress_ptr cinfo) switch (compptr->_DCT_scaled_size) { #ifdef IDCT_SCALING_SUPPORTED case 1: - method_ptr = jpeg_idct_1x1; + method_ptr = _jpeg_idct_1x1; method = JDCT_ISLOW; /* jidctred uses islow-style table */ break; case 2: +#ifdef WITH_SIMD if (jsimd_can_idct_2x2()) method_ptr = jsimd_idct_2x2; else - method_ptr = jpeg_idct_2x2; +#endif + method_ptr = _jpeg_idct_2x2; method = JDCT_ISLOW; /* jidctred uses islow-style table */ break; case 3: - method_ptr = jpeg_idct_3x3; + method_ptr = _jpeg_idct_3x3; method = JDCT_ISLOW; /* jidctint uses islow-style table */ break; case 4: +#ifdef WITH_SIMD if (jsimd_can_idct_4x4()) method_ptr = jsimd_idct_4x4; else - method_ptr = jpeg_idct_4x4; +#endif + method_ptr = _jpeg_idct_4x4; method = JDCT_ISLOW; /* jidctred uses islow-style table */ break; case 5: - method_ptr = jpeg_idct_5x5; + method_ptr = _jpeg_idct_5x5; method = JDCT_ISLOW; /* jidctint uses islow-style table */ break; case 6: -#if defined(__mips__) +#if defined(WITH_SIMD) && defined(__mips__) if (jsimd_can_idct_6x6()) method_ptr = jsimd_idct_6x6; else #endif - method_ptr = jpeg_idct_6x6; + method_ptr = _jpeg_idct_6x6; method = JDCT_ISLOW; /* jidctint uses islow-style table */ break; case 7: - method_ptr = jpeg_idct_7x7; + method_ptr = _jpeg_idct_7x7; method = JDCT_ISLOW; /* jidctint uses islow-style table */ break; #endif @@ -152,28 +156,34 @@ start_pass(j_decompress_ptr cinfo) switch (cinfo->dct_method) { #ifdef DCT_ISLOW_SUPPORTED case JDCT_ISLOW: +#ifdef WITH_SIMD if (jsimd_can_idct_islow()) method_ptr = jsimd_idct_islow; else - method_ptr = jpeg_idct_islow; +#endif + method_ptr = _jpeg_idct_islow; method = JDCT_ISLOW; break; #endif #ifdef DCT_IFAST_SUPPORTED case JDCT_IFAST: +#ifdef WITH_SIMD if (jsimd_can_idct_ifast()) method_ptr = jsimd_idct_ifast; else - method_ptr = jpeg_idct_ifast; +#endif + method_ptr = _jpeg_idct_ifast; method = JDCT_IFAST; break; #endif #ifdef DCT_FLOAT_SUPPORTED case JDCT_FLOAT: +#ifdef WITH_SIMD if (jsimd_can_idct_float()) method_ptr = jsimd_idct_float; else - method_ptr = jpeg_idct_float; +#endif + method_ptr = _jpeg_idct_float; method = JDCT_FLOAT; break; #endif @@ -184,40 +194,40 @@ start_pass(j_decompress_ptr cinfo) break; #ifdef IDCT_SCALING_SUPPORTED case 9: - method_ptr = jpeg_idct_9x9; + method_ptr = _jpeg_idct_9x9; method = JDCT_ISLOW; /* jidctint uses islow-style table */ break; case 10: - method_ptr = jpeg_idct_10x10; + method_ptr = _jpeg_idct_10x10; method = JDCT_ISLOW; /* jidctint uses islow-style table */ break; case 11: - method_ptr = jpeg_idct_11x11; + method_ptr = _jpeg_idct_11x11; method = JDCT_ISLOW; /* jidctint uses islow-style table */ break; case 12: -#if defined(__mips__) +#if defined(WITH_SIMD) && defined(__mips__) if (jsimd_can_idct_12x12()) method_ptr = jsimd_idct_12x12; else #endif - method_ptr = jpeg_idct_12x12; + method_ptr = _jpeg_idct_12x12; method = JDCT_ISLOW; /* jidctint uses islow-style table */ break; case 13: - method_ptr = jpeg_idct_13x13; + method_ptr = _jpeg_idct_13x13; method = JDCT_ISLOW; /* jidctint uses islow-style table */ break; case 14: - method_ptr = jpeg_idct_14x14; + method_ptr = _jpeg_idct_14x14; method = JDCT_ISLOW; /* jidctint uses islow-style table */ break; case 15: - method_ptr = jpeg_idct_15x15; + method_ptr = _jpeg_idct_15x15; method = JDCT_ISLOW; /* jidctint uses islow-style table */ break; case 16: - method_ptr = jpeg_idct_16x16; + method_ptr = _jpeg_idct_16x16; method = JDCT_ISLOW; /* jidctint uses islow-style table */ break; #endif @@ -225,7 +235,7 @@ start_pass(j_decompress_ptr cinfo) ERREXIT1(cinfo, JERR_BAD_DCTSIZE, compptr->_DCT_scaled_size); break; } - idct->pub.inverse_DCT[ci] = method_ptr; + idct->pub._inverse_DCT[ci] = method_ptr; /* Create multiplier table from quant table. * However, we can skip this if the component is uninteresting * or if we already built the table. Also, if no quant table @@ -327,12 +337,15 @@ start_pass(j_decompress_ptr cinfo) */ GLOBAL(void) -jinit_inverse_dct(j_decompress_ptr cinfo) +_jinit_inverse_dct(j_decompress_ptr cinfo) { my_idct_ptr idct; int ci; jpeg_component_info *compptr; + if (cinfo->data_precision != BITS_IN_JSAMPLE) + ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision); + idct = (my_idct_ptr) (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE, sizeof(my_idct_controller)); diff --git a/src/3rdparty/libjpeg/src/jddiffct.c b/src/3rdparty/libjpeg/src/jddiffct.c new file mode 100644 index 00000000000..f1d7f61b520 --- /dev/null +++ b/src/3rdparty/libjpeg/src/jddiffct.c @@ -0,0 +1,403 @@ +/* + * jddiffct.c + * + * This file was part of the Independent JPEG Group's software: + * Copyright (C) 1994-1997, Thomas G. Lane. + * Lossless JPEG Modifications: + * Copyright (C) 1999, Ken Murchison. + * libjpeg-turbo Modifications: + * Copyright (C) 2022, D. R. Commander. + * For conditions of distribution and use, see the accompanying README.ijg + * file. + * + * This file contains the [un]difference buffer controller for decompression. + * This controller is the top level of the lossless JPEG decompressor proper. + * The difference buffer lies between the entropy decoding and + * prediction/undifferencing steps. The undifference buffer lies between the + * prediction/undifferencing and scaling steps. + * + * In buffered-image mode, this controller is the interface between + * input-oriented processing and output-oriented processing. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" +#include "jlossls.h" /* Private declarations for lossless codec */ + + +#ifdef D_LOSSLESS_SUPPORTED + +/* Private buffer controller object */ + +typedef struct { + struct jpeg_d_coef_controller pub; /* public fields */ + + /* These variables keep track of the current location of the input side. */ + /* cinfo->input_iMCU_row is also used for this. */ + JDIMENSION MCU_ctr; /* counts MCUs processed in current row */ + unsigned int restart_rows_to_go; /* MCU rows left in this restart + interval */ + unsigned int MCU_vert_offset; /* counts MCU rows within iMCU row */ + unsigned int MCU_rows_per_iMCU_row; /* number of such rows needed */ + + /* The output side's location is represented by cinfo->output_iMCU_row. */ + + JDIFFARRAY diff_buf[MAX_COMPONENTS]; /* iMCU row of differences */ + JDIFFARRAY undiff_buf[MAX_COMPONENTS]; /* iMCU row of undiff'd samples */ + +#ifdef D_MULTISCAN_FILES_SUPPORTED + /* In multi-pass modes, we need a virtual sample array for each component. */ + jvirt_sarray_ptr whole_image[MAX_COMPONENTS]; +#endif +} my_diff_controller; + +typedef my_diff_controller *my_diff_ptr; + +/* Forward declarations */ +METHODDEF(int) decompress_data(j_decompress_ptr cinfo, _JSAMPIMAGE output_buf); +#ifdef D_MULTISCAN_FILES_SUPPORTED +METHODDEF(int) output_data(j_decompress_ptr cinfo, _JSAMPIMAGE output_buf); +#endif + + +LOCAL(void) +start_iMCU_row(j_decompress_ptr cinfo) +/* Reset within-iMCU-row counters for a new row (input side) */ +{ + my_diff_ptr diff = (my_diff_ptr)cinfo->coef; + + /* In an interleaved scan, an MCU row is the same as an iMCU row. + * In a noninterleaved scan, an iMCU row has v_samp_factor MCU rows. + * But at the bottom of the image, process only what's left. + */ + if (cinfo->comps_in_scan > 1) { + diff->MCU_rows_per_iMCU_row = 1; + } else { + if (cinfo->input_iMCU_row < (cinfo->total_iMCU_rows-1)) + diff->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->v_samp_factor; + else + diff->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->last_row_height; + } + + diff->MCU_ctr = 0; + diff->MCU_vert_offset = 0; +} + + +/* + * Initialize for an input processing pass. + */ + +METHODDEF(void) +start_input_pass(j_decompress_ptr cinfo) +{ + my_diff_ptr diff = (my_diff_ptr)cinfo->coef; + + /* Because it is hitching a ride on the jpeg_inverse_dct struct, + * start_pass_lossless() will be called at the start of the output pass. + * This ensures that it will be called at the start of the input pass as + * well. + */ + (*cinfo->idct->start_pass) (cinfo); + + /* Check that the restart interval is an integer multiple of the number + * of MCUs in an MCU row. + */ + if (cinfo->restart_interval % cinfo->MCUs_per_row != 0) + ERREXIT2(cinfo, JERR_BAD_RESTART, + cinfo->restart_interval, cinfo->MCUs_per_row); + + /* Initialize restart counter */ + diff->restart_rows_to_go = cinfo->restart_interval / cinfo->MCUs_per_row; + + cinfo->input_iMCU_row = 0; + start_iMCU_row(cinfo); +} + + +/* + * Check for a restart marker & resynchronize decoder, undifferencer. + * Returns FALSE if must suspend. + */ + +METHODDEF(boolean) +process_restart(j_decompress_ptr cinfo) +{ + my_diff_ptr diff = (my_diff_ptr)cinfo->coef; + + if (!(*cinfo->entropy->process_restart) (cinfo)) + return FALSE; + + (*cinfo->idct->start_pass) (cinfo); + + /* Reset restart counter */ + diff->restart_rows_to_go = cinfo->restart_interval / cinfo->MCUs_per_row; + + return TRUE; +} + + +/* + * Initialize for an output processing pass. + */ + +METHODDEF(void) +start_output_pass(j_decompress_ptr cinfo) +{ + cinfo->output_iMCU_row = 0; +} + + +/* + * Decompress and return some data in the supplied buffer. + * Always attempts to emit one fully interleaved MCU row ("iMCU" row). + * Input and output must run in lockstep since we have only a one-MCU buffer. + * Return value is JPEG_ROW_COMPLETED, JPEG_SCAN_COMPLETED, or JPEG_SUSPENDED. + * + * NB: output_buf contains a plane for each component in image, + * which we index according to the component's SOF position. + */ + +METHODDEF(int) +decompress_data(j_decompress_ptr cinfo, _JSAMPIMAGE output_buf) +{ + my_diff_ptr diff = (my_diff_ptr)cinfo->coef; + lossless_decomp_ptr losslessd = (lossless_decomp_ptr)cinfo->idct; + JDIMENSION MCU_col_num; /* index of current MCU within row */ + JDIMENSION MCU_count; /* number of MCUs decoded */ + JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1; + int ci, compi, row, prev_row; + unsigned int yoffset; + jpeg_component_info *compptr; + + /* Loop to process as much as one whole iMCU row */ + for (yoffset = diff->MCU_vert_offset; yoffset < diff->MCU_rows_per_iMCU_row; + yoffset++) { + + /* Process restart marker if needed; may have to suspend */ + if (cinfo->restart_interval) { + if (diff->restart_rows_to_go == 0) + if (!process_restart(cinfo)) + return JPEG_SUSPENDED; + } + + MCU_col_num = diff->MCU_ctr; + /* Try to fetch an MCU row (or remaining portion of suspended MCU row). */ + MCU_count = + (*cinfo->entropy->decode_mcus) (cinfo, + diff->diff_buf, yoffset, MCU_col_num, + cinfo->MCUs_per_row - MCU_col_num); + if (MCU_count != cinfo->MCUs_per_row - MCU_col_num) { + /* Suspension forced; update state counters and exit */ + diff->MCU_vert_offset = yoffset; + diff->MCU_ctr += MCU_count; + return JPEG_SUSPENDED; + } + + /* Account for restart interval (no-op if not using restarts) */ + if (cinfo->restart_interval) + diff->restart_rows_to_go--; + + /* Completed an MCU row, but perhaps not an iMCU row */ + diff->MCU_ctr = 0; + } + + /* + * Undifference and scale each scanline of the disassembled MCU row + * separately. We do not process dummy samples at the end of a scanline + * or dummy rows at the end of the image. + */ + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + compi = compptr->component_index; + for (row = 0, prev_row = compptr->v_samp_factor - 1; + row < (cinfo->input_iMCU_row == last_iMCU_row ? + compptr->last_row_height : compptr->v_samp_factor); + prev_row = row, row++) { + (*losslessd->predict_undifference[compi]) + (cinfo, compi, diff->diff_buf[compi][row], + diff->undiff_buf[compi][prev_row], diff->undiff_buf[compi][row], + compptr->width_in_blocks); + (*losslessd->scaler_scale) (cinfo, diff->undiff_buf[compi][row], + output_buf[compi][row], + compptr->width_in_blocks); + } + } + + /* Completed the iMCU row, advance counters for next one. + * + * NB: output_data will increment output_iMCU_row. + * This counter is not needed for the single-pass case + * or the input side of the multi-pass case. + */ + if (++(cinfo->input_iMCU_row) < cinfo->total_iMCU_rows) { + start_iMCU_row(cinfo); + return JPEG_ROW_COMPLETED; + } + /* Completed the scan */ + (*cinfo->inputctl->finish_input_pass) (cinfo); + return JPEG_SCAN_COMPLETED; +} + + +/* + * Dummy consume-input routine for single-pass operation. + */ + +METHODDEF(int) +dummy_consume_data(j_decompress_ptr cinfo) +{ + return JPEG_SUSPENDED; /* Always indicate nothing was done */ +} + + +#ifdef D_MULTISCAN_FILES_SUPPORTED + +/* + * Consume input data and store it in the full-image sample buffer. + * We read as much as one fully interleaved MCU row ("iMCU" row) per call, + * ie, v_samp_factor rows for each component in the scan. + * Return value is JPEG_ROW_COMPLETED, JPEG_SCAN_COMPLETED, or JPEG_SUSPENDED. + */ + +METHODDEF(int) +consume_data(j_decompress_ptr cinfo) +{ + my_diff_ptr diff = (my_diff_ptr)cinfo->coef; + int ci, compi; + _JSAMPARRAY buffer[MAX_COMPS_IN_SCAN]; + jpeg_component_info *compptr; + + /* Align the virtual buffers for the components used in this scan. */ + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + compi = compptr->component_index; + buffer[compi] = (_JSAMPARRAY)(*cinfo->mem->access_virt_sarray) + ((j_common_ptr)cinfo, diff->whole_image[compi], + cinfo->input_iMCU_row * compptr->v_samp_factor, + (JDIMENSION)compptr->v_samp_factor, TRUE); + } + + return decompress_data(cinfo, buffer); +} + + +/* + * Output some data from the full-image sample buffer in the multi-pass case. + * Always attempts to emit one fully interleaved MCU row ("iMCU" row). + * Return value is JPEG_ROW_COMPLETED, JPEG_SCAN_COMPLETED, or JPEG_SUSPENDED. + * + * NB: output_buf contains a plane for each component in image. + */ + +METHODDEF(int) +output_data(j_decompress_ptr cinfo, _JSAMPIMAGE output_buf) +{ + my_diff_ptr diff = (my_diff_ptr)cinfo->coef; + JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1; + int ci, samp_rows, row; + _JSAMPARRAY buffer; + jpeg_component_info *compptr; + + /* Force some input to be done if we are getting ahead of the input. */ + while (cinfo->input_scan_number < cinfo->output_scan_number || + (cinfo->input_scan_number == cinfo->output_scan_number && + cinfo->input_iMCU_row <= cinfo->output_iMCU_row)) { + if ((*cinfo->inputctl->consume_input) (cinfo) == JPEG_SUSPENDED) + return JPEG_SUSPENDED; + } + + /* OK, output from the virtual arrays. */ + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + /* Align the virtual buffer for this component. */ + buffer = (_JSAMPARRAY)(*cinfo->mem->access_virt_sarray) + ((j_common_ptr)cinfo, diff->whole_image[ci], + cinfo->output_iMCU_row * compptr->v_samp_factor, + (JDIMENSION)compptr->v_samp_factor, FALSE); + + if (cinfo->output_iMCU_row < last_iMCU_row) + samp_rows = compptr->v_samp_factor; + else { + /* NB: can't use last_row_height here; it is input-side-dependent! */ + samp_rows = (int)(compptr->height_in_blocks % compptr->v_samp_factor); + if (samp_rows == 0) samp_rows = compptr->v_samp_factor; + } + + for (row = 0; row < samp_rows; row++) { + memcpy(output_buf[ci][row], buffer[row], + compptr->width_in_blocks * sizeof(_JSAMPLE)); + } + } + + if (++(cinfo->output_iMCU_row) < cinfo->total_iMCU_rows) + return JPEG_ROW_COMPLETED; + return JPEG_SCAN_COMPLETED; +} + +#endif /* D_MULTISCAN_FILES_SUPPORTED */ + + +/* + * Initialize difference buffer controller. + */ + +GLOBAL(void) +_jinit_d_diff_controller(j_decompress_ptr cinfo, boolean need_full_buffer) +{ + my_diff_ptr diff; + int ci; + jpeg_component_info *compptr; + + diff = (my_diff_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE, + sizeof(my_diff_controller)); + cinfo->coef = (struct jpeg_d_coef_controller *)diff; + diff->pub.start_input_pass = start_input_pass; + diff->pub.start_output_pass = start_output_pass; + + /* Create the [un]difference buffers. */ + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + diff->diff_buf[ci] = + ALLOC_DARRAY(JPOOL_IMAGE, + (JDIMENSION)jround_up((long)compptr->width_in_blocks, + (long)compptr->h_samp_factor), + (JDIMENSION)compptr->v_samp_factor); + diff->undiff_buf[ci] = + ALLOC_DARRAY(JPOOL_IMAGE, + (JDIMENSION)jround_up((long)compptr->width_in_blocks, + (long)compptr->h_samp_factor), + (JDIMENSION)compptr->v_samp_factor); + } + + if (need_full_buffer) { +#ifdef D_MULTISCAN_FILES_SUPPORTED + /* Allocate a full-image virtual array for each component. */ + int access_rows; + + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + access_rows = compptr->v_samp_factor; + diff->whole_image[ci] = (*cinfo->mem->request_virt_sarray) + ((j_common_ptr)cinfo, JPOOL_IMAGE, FALSE, + (JDIMENSION)jround_up((long)compptr->width_in_blocks, + (long)compptr->h_samp_factor), + (JDIMENSION)jround_up((long)compptr->height_in_blocks, + (long)compptr->v_samp_factor), + (JDIMENSION)access_rows); + } + diff->pub.consume_data = consume_data; + diff->pub._decompress_data = output_data; +#else + ERREXIT(cinfo, JERR_NOT_COMPILED); +#endif + } else { + diff->pub.consume_data = dummy_consume_data; + diff->pub._decompress_data = decompress_data; + diff->whole_image[0] = NULL; /* flag for no virtual arrays */ + } +} + +#endif /* D_LOSSLESS_SUPPORTED */ diff --git a/src/3rdparty/libjpeg/src/jdhuff.c b/src/3rdparty/libjpeg/src/jdhuff.c index 679d2216859..cd8c0847a22 100644 --- a/src/3rdparty/libjpeg/src/jdhuff.c +++ b/src/3rdparty/libjpeg/src/jdhuff.c @@ -3,8 +3,10 @@ * * This file was part of the Independent JPEG Group's software: * Copyright (C) 1991-1997, Thomas G. Lane. + * Lossless JPEG Modifications: + * Copyright (C) 1999, Ken Murchison. * libjpeg-turbo Modifications: - * Copyright (C) 2009-2011, 2016, 2018-2019, D. R. Commander. + * Copyright (C) 2009-2011, 2016, 2018-2019, 2022, D. R. Commander. * Copyright (C) 2018, Matthias Räncker. * For conditions of distribution and use, see the accompanying README.ijg * file. @@ -24,8 +26,8 @@ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" -#include "jdhuff.h" /* Declarations shared with jdphuff.c */ -#include "jpegcomp.h" +#include "jdhuff.h" /* Declarations shared with jd*huff.c */ +#include "jpegapicomp.h" #include "jstdhuff.c" @@ -134,7 +136,7 @@ start_pass_huff_decoder(j_decompress_ptr cinfo) * Compute the derived values for a Huffman table. * This routine also performs some validation checks on the table. * - * Note this is also used by jdphuff.c. + * Note this is also used by jdphuff.c and jdlhuff.c. */ GLOBAL(void) @@ -245,14 +247,14 @@ jpeg_make_d_derived_tbl(j_decompress_ptr cinfo, boolean isDC, int tblno, /* Validate symbols as being reasonable. * For AC tables, we make no check, but accept all byte values 0..255. - * For DC tables, we require the symbols to be in range 0..15. - * (Tighter bounds could be applied depending on the data depth and mode, - * but this is sufficient to ensure safe decoding.) + * For DC tables, we require the symbols to be in range 0..15 in lossy mode + * and 0..16 in lossless mode. (Tighter bounds could be applied depending on + * the data depth and mode, but this is sufficient to ensure safe decoding.) */ if (isDC) { for (i = 0; i < numsymbols; i++) { int sym = htbl->huffval[i]; - if (sym < 0 || sym > 15) + if (sym < 0 || sym > (cinfo->master->lossless ? 16 : 15)) ERREXIT(cinfo, JERR_BAD_HUFF_TABLE); } } @@ -260,7 +262,7 @@ jpeg_make_d_derived_tbl(j_decompress_ptr cinfo, boolean isDC, int tblno, /* - * Out-of-line code for bit fetching (shared with jdphuff.c). + * Out-of-line code for bit fetching (shared with jdphuff.c and jdlhuff.c). * See jdhuff.h for info about usage. * Note: current values of get_buffer and bits_left are passed as parameters, * but are returned in the corresponding fields of the state struct. diff --git a/src/3rdparty/libjpeg/src/jdhuff.h b/src/3rdparty/libjpeg/src/jdhuff.h index cfa0b7f5588..3eee002c020 100644 --- a/src/3rdparty/libjpeg/src/jdhuff.h +++ b/src/3rdparty/libjpeg/src/jdhuff.h @@ -3,6 +3,8 @@ * * This file was part of the Independent JPEG Group's software: * Copyright (C) 1991-1997, Thomas G. Lane. + * Lossless JPEG Modifications: + * Copyright (C) 1999, Ken Murchison. * libjpeg-turbo Modifications: * Copyright (C) 2010-2011, 2015-2016, 2021, D. R. Commander. * Copyright (C) 2018, Matthias Räncker. @@ -10,8 +12,9 @@ * file. * * This file contains declarations for Huffman entropy decoding routines - * that are shared between the sequential decoder (jdhuff.c) and the - * progressive decoder (jdphuff.c). No other modules need to see these. + * that are shared between the sequential decoder (jdhuff.c), the progressive + * decoder (jdphuff.c), and the lossless decoder (jdlhuff.c). No other modules + * need to see these. */ #include "jconfigint.h" diff --git a/src/3rdparty/libjpeg/src/jdicc.c b/src/3rdparty/libjpeg/src/jdicc.c new file mode 100644 index 00000000000..50aa9a96767 --- /dev/null +++ b/src/3rdparty/libjpeg/src/jdicc.c @@ -0,0 +1,167 @@ +/* + * jdicc.c + * + * Copyright (C) 1997-1998, Thomas G. Lane, Todd Newman. + * Copyright (C) 2017, D. R. Commander. + * For conditions of distribution and use, see the accompanying README.ijg + * file. + * + * This file provides code to read International Color Consortium (ICC) device + * profiles embedded in JFIF JPEG image files. The ICC has defined a standard + * for including such data in JPEG "APP2" markers. The code given here does + * not know anything about the internal structure of the ICC profile data; it + * just knows how to get the profile data from a JPEG file while reading it. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" +#include "jerror.h" + + +#define ICC_MARKER (JPEG_APP0 + 2) /* JPEG marker code for ICC */ +#define ICC_OVERHEAD_LEN 14 /* size of non-profile data in APP2 */ + + +/* + * Handy subroutine to test whether a saved marker is an ICC profile marker. + */ + +LOCAL(boolean) +marker_is_icc(jpeg_saved_marker_ptr marker) +{ + return + marker->marker == ICC_MARKER && + marker->data_length >= ICC_OVERHEAD_LEN && + /* verify the identifying string */ + marker->data[0] == 0x49 && + marker->data[1] == 0x43 && + marker->data[2] == 0x43 && + marker->data[3] == 0x5F && + marker->data[4] == 0x50 && + marker->data[5] == 0x52 && + marker->data[6] == 0x4F && + marker->data[7] == 0x46 && + marker->data[8] == 0x49 && + marker->data[9] == 0x4C && + marker->data[10] == 0x45 && + marker->data[11] == 0x0; +} + + +/* + * See if there was an ICC profile in the JPEG file being read; if so, + * reassemble and return the profile data. + * + * TRUE is returned if an ICC profile was found, FALSE if not. If TRUE is + * returned, *icc_data_ptr is set to point to the returned data, and + * *icc_data_len is set to its length. + * + * IMPORTANT: the data at *icc_data_ptr is allocated with malloc() and must be + * freed by the caller with free() when the caller no longer needs it. + * (Alternatively, we could write this routine to use the IJG library's memory + * allocator, so that the data would be freed implicitly when + * jpeg_finish_decompress() is called. But it seems likely that many + * applications will prefer to have the data stick around after decompression + * finishes.) + */ + +GLOBAL(boolean) +jpeg_read_icc_profile(j_decompress_ptr cinfo, JOCTET **icc_data_ptr, + unsigned int *icc_data_len) +{ + jpeg_saved_marker_ptr marker; + int num_markers = 0; + int seq_no; + JOCTET *icc_data; + unsigned int total_length; +#define MAX_SEQ_NO 255 /* sufficient since marker numbers are bytes */ + char marker_present[MAX_SEQ_NO + 1]; /* 1 if marker found */ + unsigned int data_length[MAX_SEQ_NO + 1]; /* size of profile data in marker */ + unsigned int data_offset[MAX_SEQ_NO + 1]; /* offset for data in marker */ + + if (icc_data_ptr == NULL || icc_data_len == NULL) + ERREXIT(cinfo, JERR_BUFFER_SIZE); + if (cinfo->global_state < DSTATE_READY) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + + *icc_data_ptr = NULL; /* avoid confusion if FALSE return */ + *icc_data_len = 0; + + /* This first pass over the saved markers discovers whether there are + * any ICC markers and verifies the consistency of the marker numbering. + */ + + for (seq_no = 1; seq_no <= MAX_SEQ_NO; seq_no++) + marker_present[seq_no] = 0; + + for (marker = cinfo->marker_list; marker != NULL; marker = marker->next) { + if (marker_is_icc(marker)) { + if (num_markers == 0) + num_markers = marker->data[13]; + else if (num_markers != marker->data[13]) { + WARNMS(cinfo, JWRN_BOGUS_ICC); /* inconsistent num_markers fields */ + return FALSE; + } + seq_no = marker->data[12]; + if (seq_no <= 0 || seq_no > num_markers) { + WARNMS(cinfo, JWRN_BOGUS_ICC); /* bogus sequence number */ + return FALSE; + } + if (marker_present[seq_no]) { + WARNMS(cinfo, JWRN_BOGUS_ICC); /* duplicate sequence numbers */ + return FALSE; + } + marker_present[seq_no] = 1; + data_length[seq_no] = marker->data_length - ICC_OVERHEAD_LEN; + } + } + + if (num_markers == 0) + return FALSE; + + /* Check for missing markers, count total space needed, + * compute offset of each marker's part of the data. + */ + + total_length = 0; + for (seq_no = 1; seq_no <= num_markers; seq_no++) { + if (marker_present[seq_no] == 0) { + WARNMS(cinfo, JWRN_BOGUS_ICC); /* missing sequence number */ + return FALSE; + } + data_offset[seq_no] = total_length; + total_length += data_length[seq_no]; + } + + if (total_length == 0) { + WARNMS(cinfo, JWRN_BOGUS_ICC); /* found only empty markers? */ + return FALSE; + } + + /* Allocate space for assembled data */ + icc_data = (JOCTET *)malloc(total_length * sizeof(JOCTET)); + if (icc_data == NULL) + ERREXIT1(cinfo, JERR_OUT_OF_MEMORY, 11); /* oops, out of memory */ + + /* and fill it in */ + for (marker = cinfo->marker_list; marker != NULL; marker = marker->next) { + if (marker_is_icc(marker)) { + JOCTET FAR *src_ptr; + JOCTET *dst_ptr; + unsigned int length; + seq_no = marker->data[12]; + dst_ptr = icc_data + data_offset[seq_no]; + src_ptr = marker->data + ICC_OVERHEAD_LEN; + length = data_length[seq_no]; + while (length--) { + *dst_ptr++ = *src_ptr++; + } + } + } + + *icc_data_ptr = icc_data; + *icc_data_len = total_length; + + return TRUE; +} diff --git a/src/3rdparty/libjpeg/src/jdinput.c b/src/3rdparty/libjpeg/src/jdinput.c index 1bc5aff1a70..136bef59d75 100644 --- a/src/3rdparty/libjpeg/src/jdinput.c +++ b/src/3rdparty/libjpeg/src/jdinput.c @@ -3,6 +3,8 @@ * * This file was part of the Independent JPEG Group's software: * Copyright (C) 1991-1997, Thomas G. Lane. + * Lossless JPEG Modifications: + * Copyright (C) 1999, Ken Murchison. * libjpeg-turbo Modifications: * Copyright (C) 2010, 2016, 2018, 2022, D. R. Commander. * Copyright (C) 2015, Google, Inc. @@ -11,14 +13,15 @@ * * This file contains input control logic for the JPEG decompressor. * These routines are concerned with controlling the decompressor's input - * processing (marker reading and coefficient decoding). The actual input - * reading is done in jdmarker.c, jdhuff.c, and jdphuff.c. + * processing (marker reading and coefficient/difference decoding). + * The actual input reading is done in jdmarker.c, jdhuff.c, jdphuff.c, + * and jdlhuff.c. */ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" -#include "jpegcomp.h" +#include "jpegapicomp.h" /* Private state */ @@ -46,6 +49,7 @@ initial_setup(j_decompress_ptr cinfo) { int ci; jpeg_component_info *compptr; + int data_unit = cinfo->master->lossless ? 1 : DCTSIZE; /* Make sure image isn't bigger than I can handle */ if ((long)cinfo->image_height > (long)JPEG_MAX_DIMENSION || @@ -53,7 +57,12 @@ initial_setup(j_decompress_ptr cinfo) ERREXIT1(cinfo, JERR_IMAGE_TOO_BIG, (unsigned int)JPEG_MAX_DIMENSION); /* For now, precision must match compiled-in value... */ - if (cinfo->data_precision != BITS_IN_JSAMPLE) +#ifdef D_LOSSLESS_SUPPORTED + if (cinfo->data_precision != 8 && cinfo->data_precision != 12 && + cinfo->data_precision != 16) +#else + if (cinfo->data_precision != 8 && cinfo->data_precision != 12) +#endif ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision); /* Check that number of components won't exceed internal array sizes */ @@ -78,36 +87,36 @@ initial_setup(j_decompress_ptr cinfo) } #if JPEG_LIB_VERSION >= 80 - cinfo->block_size = DCTSIZE; + cinfo->block_size = data_unit; cinfo->natural_order = jpeg_natural_order; cinfo->lim_Se = DCTSIZE2 - 1; #endif - /* We initialize DCT_scaled_size and min_DCT_scaled_size to DCTSIZE. - * In the full decompressor, this will be overridden by jdmaster.c; + /* We initialize DCT_scaled_size and min_DCT_scaled_size to DCTSIZE in lossy + * mode. In the full decompressor, this will be overridden by jdmaster.c; * but in the transcoder, jdmaster.c is not used, so we must do it here. */ #if JPEG_LIB_VERSION >= 70 - cinfo->min_DCT_h_scaled_size = cinfo->min_DCT_v_scaled_size = DCTSIZE; + cinfo->min_DCT_h_scaled_size = cinfo->min_DCT_v_scaled_size = data_unit; #else - cinfo->min_DCT_scaled_size = DCTSIZE; + cinfo->min_DCT_scaled_size = data_unit; #endif /* Compute dimensions of components */ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { #if JPEG_LIB_VERSION >= 70 - compptr->DCT_h_scaled_size = compptr->DCT_v_scaled_size = DCTSIZE; + compptr->DCT_h_scaled_size = compptr->DCT_v_scaled_size = data_unit; #else - compptr->DCT_scaled_size = DCTSIZE; + compptr->DCT_scaled_size = data_unit; #endif - /* Size in DCT blocks */ + /* Size in data units */ compptr->width_in_blocks = (JDIMENSION) jdiv_round_up((long)cinfo->image_width * (long)compptr->h_samp_factor, - (long)(cinfo->max_h_samp_factor * DCTSIZE)); + (long)(cinfo->max_h_samp_factor * data_unit)); compptr->height_in_blocks = (JDIMENSION) jdiv_round_up((long)cinfo->image_height * (long)compptr->v_samp_factor, - (long)(cinfo->max_v_samp_factor * DCTSIZE)); + (long)(cinfo->max_v_samp_factor * data_unit)); /* Set the first and last MCU columns to decompress from multi-scan images. * By default, decompress all of the MCU columns. */ @@ -133,7 +142,7 @@ initial_setup(j_decompress_ptr cinfo) /* Compute number of fully interleaved MCU rows. */ cinfo->total_iMCU_rows = (JDIMENSION) jdiv_round_up((long)cinfo->image_height, - (long)(cinfo->max_v_samp_factor * DCTSIZE)); + (long)(cinfo->max_v_samp_factor * data_unit)); /* Decide whether file contains multiple scans */ if (cinfo->comps_in_scan < cinfo->num_components || cinfo->progressive_mode) @@ -150,6 +159,7 @@ per_scan_setup(j_decompress_ptr cinfo) { int ci, mcublks, tmp; jpeg_component_info *compptr; + int data_unit = cinfo->master->lossless ? 1 : DCTSIZE; if (cinfo->comps_in_scan == 1) { @@ -160,14 +170,14 @@ per_scan_setup(j_decompress_ptr cinfo) cinfo->MCUs_per_row = compptr->width_in_blocks; cinfo->MCU_rows_in_scan = compptr->height_in_blocks; - /* For noninterleaved scan, always one block per MCU */ + /* For noninterleaved scan, always one data unit per MCU */ compptr->MCU_width = 1; compptr->MCU_height = 1; compptr->MCU_blocks = 1; compptr->MCU_sample_width = compptr->_DCT_scaled_size; compptr->last_col_width = 1; /* For noninterleaved scans, it is convenient to define last_row_height - * as the number of block rows present in the last iMCU row. + * as the number of data unit rows present in the last iMCU row. */ tmp = (int)(compptr->height_in_blocks % compptr->v_samp_factor); if (tmp == 0) tmp = compptr->v_samp_factor; @@ -187,22 +197,22 @@ per_scan_setup(j_decompress_ptr cinfo) /* Overall image size in MCUs */ cinfo->MCUs_per_row = (JDIMENSION) jdiv_round_up((long)cinfo->image_width, - (long)(cinfo->max_h_samp_factor * DCTSIZE)); + (long)(cinfo->max_h_samp_factor * data_unit)); cinfo->MCU_rows_in_scan = (JDIMENSION) jdiv_round_up((long)cinfo->image_height, - (long)(cinfo->max_v_samp_factor * DCTSIZE)); + (long)(cinfo->max_v_samp_factor * data_unit)); cinfo->blocks_in_MCU = 0; for (ci = 0; ci < cinfo->comps_in_scan; ci++) { compptr = cinfo->cur_comp_info[ci]; - /* Sampling factors give # of blocks of component in each MCU */ + /* Sampling factors give # of data units of component in each MCU */ compptr->MCU_width = compptr->h_samp_factor; compptr->MCU_height = compptr->v_samp_factor; compptr->MCU_blocks = compptr->MCU_width * compptr->MCU_height; compptr->MCU_sample_width = compptr->MCU_width * compptr->_DCT_scaled_size; - /* Figure number of non-dummy blocks in last MCU column & row */ + /* Figure number of non-dummy data units in last MCU column & row */ tmp = (int)(compptr->width_in_blocks % compptr->MCU_width); if (tmp == 0) tmp = compptr->MCU_width; compptr->last_col_width = tmp; @@ -281,7 +291,8 @@ METHODDEF(void) start_input_pass(j_decompress_ptr cinfo) { per_scan_setup(cinfo); - latch_quant_tables(cinfo); + if (!cinfo->master->lossless) + latch_quant_tables(cinfo); (*cinfo->entropy->start_pass) (cinfo); (*cinfo->coef->start_input_pass) (cinfo); cinfo->inputctl->consume_input = cinfo->coef->consume_data; @@ -290,8 +301,8 @@ start_input_pass(j_decompress_ptr cinfo) /* * Finish up after inputting a compressed-data scan. - * This is called by the coefficient controller after it's read all - * the expected data of the scan. + * This is called by the coefficient or difference controller after it's read + * all the expected data of the scan. */ METHODDEF(void) @@ -307,8 +318,8 @@ finish_input_pass(j_decompress_ptr cinfo) * Return value is JPEG_SUSPENDED, JPEG_REACHED_SOS, or JPEG_REACHED_EOI. * * The consume_input method pointer points either here or to the - * coefficient controller's consume_data routine, depending on whether - * we are reading a compressed data segment or inter-segment markers. + * coefficient or difference controller's consume_data routine, depending on + * whether we are reading a compressed data segment or inter-segment markers. */ METHODDEF(int) diff --git a/src/3rdparty/libjpeg/src/jdlhuff.c b/src/3rdparty/libjpeg/src/jdlhuff.c new file mode 100644 index 00000000000..9964830dba0 --- /dev/null +++ b/src/3rdparty/libjpeg/src/jdlhuff.c @@ -0,0 +1,302 @@ +/* + * jdlhuff.c + * + * This file was part of the Independent JPEG Group's software: + * Copyright (C) 1991-1997, Thomas G. Lane. + * Lossless JPEG Modifications: + * Copyright (C) 1999, Ken Murchison. + * libjpeg-turbo Modifications: + * Copyright (C) 2022, D. R. Commander. + * For conditions of distribution and use, see the accompanying README.ijg + * file. + * + * This file contains Huffman entropy decoding routines for lossless JPEG. + * + * Much of the complexity here has to do with supporting input suspension. + * If the data source module demands suspension, we want to be able to back + * up to the start of the current MCU. To do this, we copy state variables + * into local working storage, and update them back to the permanent + * storage only upon successful completion of an MCU. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" +#include "jlossls.h" /* Private declarations for lossless codec */ +#include "jdhuff.h" /* Declarations shared with jd*huff.c */ + + +#ifdef D_LOSSLESS_SUPPORTED + +typedef struct { + int ci, yoffset, MCU_width; +} lhd_output_ptr_info; + +/* + * Expanded entropy decoder object for Huffman decoding in lossless mode. + */ + +typedef struct { + struct jpeg_entropy_decoder pub; /* public fields */ + + /* These fields are loaded into local variables at start of each MCU. + * In case of suspension, we exit WITHOUT updating them. + */ + bitread_perm_state bitstate; /* Bit buffer at start of MCU */ + + /* Pointers to derived tables (these workspaces have image lifespan) */ + d_derived_tbl *derived_tbls[NUM_HUFF_TBLS]; + + /* Precalculated info set up by start_pass for use in decode_mcus: */ + + /* Pointers to derived tables to be used for each data unit within an MCU */ + d_derived_tbl *cur_tbls[D_MAX_BLOCKS_IN_MCU]; + + /* Pointers to the proper output difference row for each group of data units + * within an MCU. For each component, there are Vi groups of Hi data units. + */ + JDIFFROW output_ptr[D_MAX_BLOCKS_IN_MCU]; + + /* Number of output pointers in use for the current MCU. This is the sum + * of all Vi in the MCU. + */ + int num_output_ptrs; + + /* Information used for positioning the output pointers within the output + * difference rows. + */ + lhd_output_ptr_info output_ptr_info[D_MAX_BLOCKS_IN_MCU]; + + /* Index of the proper output pointer for each data unit within an MCU */ + int output_ptr_index[D_MAX_BLOCKS_IN_MCU]; + +} lhuff_entropy_decoder; + +typedef lhuff_entropy_decoder *lhuff_entropy_ptr; + + +/* + * Initialize for a Huffman-compressed scan. + */ + +METHODDEF(void) +start_pass_lhuff_decoder(j_decompress_ptr cinfo) +{ + lhuff_entropy_ptr entropy = (lhuff_entropy_ptr)cinfo->entropy; + int ci, dctbl, sampn, ptrn, yoffset, xoffset; + jpeg_component_info *compptr; + + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + dctbl = compptr->dc_tbl_no; + /* Make sure requested tables are present */ + if (dctbl < 0 || dctbl >= NUM_HUFF_TBLS || + cinfo->dc_huff_tbl_ptrs[dctbl] == NULL) + ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, dctbl); + /* Compute derived values for Huffman tables */ + /* We may do this more than once for a table, but it's not expensive */ + jpeg_make_d_derived_tbl(cinfo, TRUE, dctbl, + &entropy->derived_tbls[dctbl]); + } + + /* Precalculate decoding info for each sample in an MCU of this scan */ + for (sampn = 0, ptrn = 0; sampn < cinfo->blocks_in_MCU;) { + compptr = cinfo->cur_comp_info[cinfo->MCU_membership[sampn]]; + ci = compptr->component_index; + for (yoffset = 0; yoffset < compptr->MCU_height; yoffset++, ptrn++) { + /* Precalculate the setup info for each output pointer */ + entropy->output_ptr_info[ptrn].ci = ci; + entropy->output_ptr_info[ptrn].yoffset = yoffset; + entropy->output_ptr_info[ptrn].MCU_width = compptr->MCU_width; + for (xoffset = 0; xoffset < compptr->MCU_width; xoffset++, sampn++) { + /* Precalculate the output pointer index for each sample */ + entropy->output_ptr_index[sampn] = ptrn; + /* Precalculate which table to use for each sample */ + entropy->cur_tbls[sampn] = entropy->derived_tbls[compptr->dc_tbl_no]; + } + } + } + entropy->num_output_ptrs = ptrn; + + /* Initialize bitread state variables */ + entropy->bitstate.bits_left = 0; + entropy->bitstate.get_buffer = 0; /* unnecessary, but keeps Purify quiet */ + entropy->pub.insufficient_data = FALSE; +} + + +/* + * Figure F.12: extend sign bit. + * On some machines, a shift and add will be faster than a table lookup. + */ + +#define AVOID_TABLES +#ifdef AVOID_TABLES + +#define NEG_1 ((unsigned int)-1) +#define HUFF_EXTEND(x, s) \ + ((x) + ((((x) - (1 << ((s) - 1))) >> 31) & (((NEG_1) << (s)) + 1))) + +#else + +#define HUFF_EXTEND(x, s) \ + ((x) < extend_test[s] ? (x) + extend_offset[s] : (x)) + +static const int extend_test[16] = { /* entry n is 2**(n-1) */ + 0, 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080, + 0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000 +}; + +static const int extend_offset[16] = { /* entry n is (-1 << n) + 1 */ + 0, ((-1) << 1) + 1, ((-1) << 2) + 1, ((-1) << 3) + 1, ((-1) << 4) + 1, + ((-1) << 5) + 1, ((-1) << 6) + 1, ((-1) << 7) + 1, ((-1) << 8) + 1, + ((-1) << 9) + 1, ((-1) << 10) + 1, ((-1) << 11) + 1, ((-1) << 12) + 1, + ((-1) << 13) + 1, ((-1) << 14) + 1, ((-1) << 15) + 1 +}; + +#endif /* AVOID_TABLES */ + + +/* + * Check for a restart marker & resynchronize decoder. + * Returns FALSE if must suspend. + */ + +LOCAL(boolean) +process_restart(j_decompress_ptr cinfo) +{ + lhuff_entropy_ptr entropy = (lhuff_entropy_ptr)cinfo->entropy; + + /* Throw away any unused bits remaining in bit buffer; */ + /* include any full bytes in next_marker's count of discarded bytes */ + cinfo->marker->discarded_bytes += entropy->bitstate.bits_left / 8; + entropy->bitstate.bits_left = 0; + + /* Advance past the RSTn marker */ + if (!(*cinfo->marker->read_restart_marker) (cinfo)) + return FALSE; + + /* Reset out-of-data flag, unless read_restart_marker left us smack up + * against a marker. In that case we will end up treating the next data + * segment as empty, and we can avoid producing bogus output pixels by + * leaving the flag set. + */ + if (cinfo->unread_marker == 0) + entropy->pub.insufficient_data = FALSE; + + return TRUE; +} + + +/* + * Decode and return nMCU MCUs' worth of Huffman-compressed differences. + * Each MCU is also disassembled and placed accordingly in diff_buf. + * + * MCU_col_num specifies the column of the first MCU being requested within + * the MCU row. This tells us where to position the output row pointers in + * diff_buf. + * + * Returns the number of MCUs decoded. This may be less than nMCU MCUs if + * data source requested suspension. In that case no changes have been made + * to permanent state. (Exception: some output differences may already have + * been assigned. This is harmless for this module, since we'll just + * re-assign them on the next call.) + */ + +METHODDEF(JDIMENSION) +decode_mcus(j_decompress_ptr cinfo, JDIFFIMAGE diff_buf, + JDIMENSION MCU_row_num, JDIMENSION MCU_col_num, JDIMENSION nMCU) +{ + lhuff_entropy_ptr entropy = (lhuff_entropy_ptr)cinfo->entropy; + int sampn, ci, yoffset, MCU_width, ptrn; + JDIMENSION mcu_num; + BITREAD_STATE_VARS; + + /* Set output pointer locations based on MCU_col_num */ + for (ptrn = 0; ptrn < entropy->num_output_ptrs; ptrn++) { + ci = entropy->output_ptr_info[ptrn].ci; + yoffset = entropy->output_ptr_info[ptrn].yoffset; + MCU_width = entropy->output_ptr_info[ptrn].MCU_width; + entropy->output_ptr[ptrn] = + diff_buf[ci][MCU_row_num + yoffset] + (MCU_col_num * MCU_width); + } + + /* + * If we've run out of data, zero out the buffers and return. + * By resetting the undifferencer, the output samples will be CENTERJSAMPLE. + * + * NB: We should find a way to do this without interacting with the + * undifferencer module directly. + */ + if (entropy->pub.insufficient_data) { + for (ptrn = 0; ptrn < entropy->num_output_ptrs; ptrn++) + jzero_far((void FAR *)entropy->output_ptr[ptrn], + nMCU * entropy->output_ptr_info[ptrn].MCU_width * + sizeof(JDIFF)); + + (*cinfo->idct->start_pass) (cinfo); + + } else { + + /* Load up working state */ + BITREAD_LOAD_STATE(cinfo, entropy->bitstate); + + /* Outer loop handles the number of MCUs requested */ + + for (mcu_num = 0; mcu_num < nMCU; mcu_num++) { + + /* Inner loop handles the samples in the MCU */ + for (sampn = 0; sampn < cinfo->blocks_in_MCU; sampn++) { + d_derived_tbl *dctbl = entropy->cur_tbls[sampn]; + register int s, r; + + /* Section H.2.2: decode the sample difference */ + HUFF_DECODE(s, br_state, dctbl, return mcu_num, label1); + if (s) { + if (s == 16) /* special case: always output 32768 */ + s = 32768; + else { /* normal case: fetch subsequent bits */ + CHECK_BIT_BUFFER(br_state, s, return mcu_num); + r = GET_BITS(s); + s = HUFF_EXTEND(r, s); + } + } + + /* Output the sample difference */ + *entropy->output_ptr[entropy->output_ptr_index[sampn]]++ = (JDIFF)s; + } + + /* Completed MCU, so update state */ + BITREAD_SAVE_STATE(cinfo, entropy->bitstate); + } + } + + return nMCU; +} + + +/* + * Module initialization routine for lossless mode Huffman entropy decoding. + */ + +GLOBAL(void) +jinit_lhuff_decoder(j_decompress_ptr cinfo) +{ + lhuff_entropy_ptr entropy; + int i; + + entropy = (lhuff_entropy_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE, + sizeof(lhuff_entropy_decoder)); + cinfo->entropy = (struct jpeg_entropy_decoder *)entropy; + entropy->pub.start_pass = start_pass_lhuff_decoder; + entropy->pub.decode_mcus = decode_mcus; + entropy->pub.process_restart = process_restart; + + /* Mark tables unallocated */ + for (i = 0; i < NUM_HUFF_TBLS; i++) { + entropy->derived_tbls[i] = NULL; + } +} + +#endif /* D_LOSSLESS_SUPPORTED */ diff --git a/src/3rdparty/libjpeg/src/jdlossls.c b/src/3rdparty/libjpeg/src/jdlossls.c new file mode 100644 index 00000000000..4d15e6bbaf2 --- /dev/null +++ b/src/3rdparty/libjpeg/src/jdlossls.c @@ -0,0 +1,289 @@ +/* + * jdlossls.c + * + * This file was part of the Independent JPEG Group's software: + * Copyright (C) 1998, Thomas G. Lane. + * Lossless JPEG Modifications: + * Copyright (C) 1999, Ken Murchison. + * libjpeg-turbo Modifications: + * Copyright (C) 2022, D. R. Commander. + * For conditions of distribution and use, see the accompanying README.ijg + * file. + * + * This file contains prediction, sample undifferencing, point transform, and + * sample scaling routines for the lossless JPEG decompressor. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" +#include "jlossls.h" + +#ifdef D_LOSSLESS_SUPPORTED + + +/**************** Sample undifferencing (reconstruction) *****************/ + +/* + * In order to avoid a performance penalty for checking which predictor is + * being used and which row is being processed for each call of the + * undifferencer, and to promote optimization, we have separate undifferencing + * functions for each predictor selection value. + * + * We are able to avoid duplicating source code by implementing the predictors + * and undifferencers as macros. Each of the undifferencing functions is + * simply a wrapper around an UNDIFFERENCE macro with the appropriate PREDICTOR + * macro passed as an argument. + */ + +/* Predictor for the first column of the first row: 2^(P-Pt-1) */ +#define INITIAL_PREDICTORx (1 << (cinfo->data_precision - cinfo->Al - 1)) + +/* Predictor for the first column of the remaining rows: Rb */ +#define INITIAL_PREDICTOR2 prev_row[0] + + +/* + * 1-Dimensional undifferencer routine. + * + * This macro implements the 1-D horizontal predictor (1). INITIAL_PREDICTOR + * is used as the special case predictor for the first column, which must be + * either INITIAL_PREDICTOR2 or INITIAL_PREDICTORx. The remaining samples + * use PREDICTOR1. + * + * The reconstructed sample is supposed to be calculated modulo 2^16, so we + * logically AND the result with 0xFFFF. + */ + +#define UNDIFFERENCE_1D(INITIAL_PREDICTOR) \ + int Ra; \ + \ + Ra = (*diff_buf++ + INITIAL_PREDICTOR) & 0xFFFF; \ + *undiff_buf++ = Ra; \ + \ + while (--width) { \ + Ra = (*diff_buf++ + PREDICTOR1) & 0xFFFF; \ + *undiff_buf++ = Ra; \ + } + + +/* + * 2-Dimensional undifferencer routine. + * + * This macro implements the 2-D horizontal predictors (#2-7). PREDICTOR2 is + * used as the special case predictor for the first column. The remaining + * samples use PREDICTOR, which is a function of Ra, Rb, and Rc. + * + * Because prev_row and output_buf may point to the same storage area (in an + * interleaved image with Vi=1, for example), we must take care to buffer Rb/Rc + * before writing the current reconstructed sample value into output_buf. + * + * The reconstructed sample is supposed to be calculated modulo 2^16, so we + * logically AND the result with 0xFFFF. + */ + +#define UNDIFFERENCE_2D(PREDICTOR) \ + int Ra, Rb, Rc; \ + \ + Rb = *prev_row++; \ + Ra = (*diff_buf++ + PREDICTOR2) & 0xFFFF; \ + *undiff_buf++ = Ra; \ + \ + while (--width) { \ + Rc = Rb; \ + Rb = *prev_row++; \ + Ra = (*diff_buf++ + PREDICTOR) & 0xFFFF; \ + *undiff_buf++ = Ra; \ + } + + +/* + * Undifferencers for the second and subsequent rows in a scan or restart + * interval. The first sample in the row is undifferenced using the vertical + * predictor (2). The rest of the samples are undifferenced using the + * predictor specified in the scan header. + */ + +METHODDEF(void) +jpeg_undifference1(j_decompress_ptr cinfo, int comp_index, + JDIFFROW diff_buf, JDIFFROW prev_row, + JDIFFROW undiff_buf, JDIMENSION width) +{ + UNDIFFERENCE_1D(INITIAL_PREDICTOR2); +} + +METHODDEF(void) +jpeg_undifference2(j_decompress_ptr cinfo, int comp_index, + JDIFFROW diff_buf, JDIFFROW prev_row, + JDIFFROW undiff_buf, JDIMENSION width) +{ + UNDIFFERENCE_2D(PREDICTOR2); + (void)(Rc); +} + +METHODDEF(void) +jpeg_undifference3(j_decompress_ptr cinfo, int comp_index, + JDIFFROW diff_buf, JDIFFROW prev_row, + JDIFFROW undiff_buf, JDIMENSION width) +{ + UNDIFFERENCE_2D(PREDICTOR3); +} + +METHODDEF(void) +jpeg_undifference4(j_decompress_ptr cinfo, int comp_index, + JDIFFROW diff_buf, JDIFFROW prev_row, + JDIFFROW undiff_buf, JDIMENSION width) +{ + UNDIFFERENCE_2D(PREDICTOR4); +} + +METHODDEF(void) +jpeg_undifference5(j_decompress_ptr cinfo, int comp_index, + JDIFFROW diff_buf, JDIFFROW prev_row, + JDIFFROW undiff_buf, JDIMENSION width) +{ + UNDIFFERENCE_2D(PREDICTOR5); +} + +METHODDEF(void) +jpeg_undifference6(j_decompress_ptr cinfo, int comp_index, + JDIFFROW diff_buf, JDIFFROW prev_row, + JDIFFROW undiff_buf, JDIMENSION width) +{ + UNDIFFERENCE_2D(PREDICTOR6); +} + +METHODDEF(void) +jpeg_undifference7(j_decompress_ptr cinfo, int comp_index, + JDIFFROW diff_buf, JDIFFROW prev_row, + JDIFFROW undiff_buf, JDIMENSION width) +{ + UNDIFFERENCE_2D(PREDICTOR7); + (void)(Rc); +} + + +/* + * Undifferencer for the first row in a scan or restart interval. The first + * sample in the row is undifferenced using the special predictor constant + * x=2^(P-Pt-1). The rest of the samples are undifferenced using the + * 1-D horizontal predictor (1). + */ + +METHODDEF(void) +jpeg_undifference_first_row(j_decompress_ptr cinfo, int comp_index, + JDIFFROW diff_buf, JDIFFROW prev_row, + JDIFFROW undiff_buf, JDIMENSION width) +{ + lossless_decomp_ptr losslessd = (lossless_decomp_ptr)cinfo->idct; + + UNDIFFERENCE_1D(INITIAL_PREDICTORx); + + /* + * Now that we have undifferenced the first row, we want to use the + * undifferencer that corresponds to the predictor specified in the + * scan header. + */ + switch (cinfo->Ss) { + case 1: + losslessd->predict_undifference[comp_index] = jpeg_undifference1; + break; + case 2: + losslessd->predict_undifference[comp_index] = jpeg_undifference2; + break; + case 3: + losslessd->predict_undifference[comp_index] = jpeg_undifference3; + break; + case 4: + losslessd->predict_undifference[comp_index] = jpeg_undifference4; + break; + case 5: + losslessd->predict_undifference[comp_index] = jpeg_undifference5; + break; + case 6: + losslessd->predict_undifference[comp_index] = jpeg_undifference6; + break; + case 7: + losslessd->predict_undifference[comp_index] = jpeg_undifference7; + break; + } +} + + +/*********************** Sample upscaling by 2^Pt ************************/ + +METHODDEF(void) +simple_upscale(j_decompress_ptr cinfo, + JDIFFROW diff_buf, _JSAMPROW output_buf, JDIMENSION width) +{ + do { + *output_buf++ = (_JSAMPLE)(*diff_buf++ << cinfo->Al); + } while (--width); +} + +METHODDEF(void) +noscale(j_decompress_ptr cinfo, + JDIFFROW diff_buf, _JSAMPROW output_buf, JDIMENSION width) +{ + do { + *output_buf++ = (_JSAMPLE)(*diff_buf++); + } while (--width); +} + + +/* + * Initialize for an input processing pass. + */ + +METHODDEF(void) +start_pass_lossless(j_decompress_ptr cinfo) +{ + lossless_decomp_ptr losslessd = (lossless_decomp_ptr)cinfo->idct; + int ci; + + /* Check that the scan parameters Ss, Se, Ah, Al are OK for lossless JPEG. + * + * Ss is the predictor selection value (psv). Legal values for sequential + * lossless JPEG are: 1 <= psv <= 7. + * + * Se and Ah are not used and should be zero. + * + * Al specifies the point transform (Pt). + * Legal values are: 0 <= Pt <= (data precision - 1). + */ + if (cinfo->Ss < 1 || cinfo->Ss > 7 || + cinfo->Se != 0 || cinfo->Ah != 0 || + cinfo->Al < 0 || cinfo->Al >= cinfo->data_precision) + ERREXIT4(cinfo, JERR_BAD_PROGRESSION, + cinfo->Ss, cinfo->Se, cinfo->Ah, cinfo->Al); + + /* Set undifference functions to first row function */ + for (ci = 0; ci < cinfo->num_components; ci++) + losslessd->predict_undifference[ci] = jpeg_undifference_first_row; + + /* Set scaler function based on Pt */ + if (cinfo->Al) + losslessd->scaler_scale = simple_upscale; + else + losslessd->scaler_scale = noscale; +} + + +/* + * Initialize the lossless decompressor. + */ + +GLOBAL(void) +_jinit_lossless_decompressor(j_decompress_ptr cinfo) +{ + lossless_decomp_ptr losslessd; + + /* Create subobject in permanent pool */ + losslessd = (lossless_decomp_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_PERMANENT, + sizeof(jpeg_lossless_decompressor)); + cinfo->idct = (struct jpeg_inverse_dct *)losslessd; + losslessd->pub.start_pass = start_pass_lossless; +} + +#endif /* D_LOSSLESS_SUPPORTED */ diff --git a/src/3rdparty/libjpeg/src/jdmainct.c b/src/3rdparty/libjpeg/src/jdmainct.c index d332e6b2fa1..c672b4baf58 100644 --- a/src/3rdparty/libjpeg/src/jdmainct.c +++ b/src/3rdparty/libjpeg/src/jdmainct.c @@ -4,7 +4,7 @@ * This file was part of the Independent JPEG Group's software: * Copyright (C) 1994-1996, Thomas G. Lane. * libjpeg-turbo Modifications: - * Copyright (C) 2010, 2016, D. R. Commander. + * Copyright (C) 2010, 2016, 2022, D. R. Commander. * For conditions of distribution and use, see the accompanying README.ijg * file. * @@ -20,12 +20,15 @@ #include "jdmainct.h" +#if BITS_IN_JSAMPLE != 16 || defined(D_LOSSLESS_SUPPORTED) + /* * In the current system design, the main buffer need never be a full-image - * buffer; any full-height buffers will be found inside the coefficient or - * postprocessing controllers. Nonetheless, the main controller is not - * trivial. Its responsibility is to provide context rows for upsampling/ - * rescaling, and doing this in an efficient fashion is a bit tricky. + * buffer; any full-height buffers will be found inside the coefficient, + * difference, or postprocessing controllers. Nonetheless, the main controller + * is not trivial. Its responsibility is to provide context rows for + * upsampling/rescaling, and doing this in an efficient fashion is a bit + * tricky. * * Postprocessor input data is counted in "row groups". A row group * is defined to be (v_samp_factor * DCT_scaled_size / min_DCT_scaled_size) @@ -37,20 +40,20 @@ * row group (times any additional scale factor that the upsampler is * applying). * - * The coefficient controller will deliver data to us one iMCU row at a time; - * each iMCU row contains v_samp_factor * DCT_scaled_size sample rows, or - * exactly min_DCT_scaled_size row groups. (This amount of data corresponds - * to one row of MCUs when the image is fully interleaved.) Note that the - * number of sample rows varies across components, but the number of row - * groups does not. Some garbage sample rows may be included in the last iMCU - * row at the bottom of the image. + * The coefficient or difference controller will deliver data to us one iMCU + * row at a time; each iMCU row contains v_samp_factor * DCT_scaled_size sample + * rows, or exactly min_DCT_scaled_size row groups. (This amount of data + * corresponds to one row of MCUs when the image is fully interleaved.) Note + * that the number of sample rows varies across components, but the number of + * row groups does not. Some garbage sample rows may be included in the last + * iMCU row at the bottom of the image. * * Depending on the vertical scaling algorithm used, the upsampler may need * access to the sample row(s) above and below its current input row group. * The upsampler is required to set need_context_rows TRUE at global selection * time if so. When need_context_rows is FALSE, this controller can simply - * obtain one iMCU row at a time from the coefficient controller and dole it - * out as row groups to the postprocessor. + * obtain one iMCU row at a time from the coefficient or difference controller + * and dole it out as row groups to the postprocessor. * * When need_context_rows is TRUE, this controller guarantees that the buffer * passed to postprocessing contains at least one row group's worth of samples @@ -113,16 +116,16 @@ /* Forward declarations */ METHODDEF(void) process_data_simple_main(j_decompress_ptr cinfo, - JSAMPARRAY output_buf, + _JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail); METHODDEF(void) process_data_context_main(j_decompress_ptr cinfo, - JSAMPARRAY output_buf, + _JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail); #ifdef QUANT_2PASS_SUPPORTED METHODDEF(void) process_data_crank_post(j_decompress_ptr cinfo, - JSAMPARRAY output_buf, + _JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail); #endif @@ -138,14 +141,15 @@ alloc_funny_pointers(j_decompress_ptr cinfo) int ci, rgroup; int M = cinfo->_min_DCT_scaled_size; jpeg_component_info *compptr; - JSAMPARRAY xbuf; + _JSAMPARRAY xbuf; /* Get top-level space for component array pointers. * We alloc both arrays with one call to save a few cycles. */ - main_ptr->xbuffer[0] = (JSAMPIMAGE) + main_ptr->xbuffer[0] = (_JSAMPIMAGE) (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE, - cinfo->num_components * 2 * sizeof(JSAMPARRAY)); + cinfo->num_components * 2 * + sizeof(_JSAMPARRAY)); main_ptr->xbuffer[1] = main_ptr->xbuffer[0] + cinfo->num_components; for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; @@ -155,9 +159,9 @@ alloc_funny_pointers(j_decompress_ptr cinfo) /* Get space for pointer lists --- M+4 row groups in each list. * We alloc both pointer lists with one call to save a few cycles. */ - xbuf = (JSAMPARRAY) + xbuf = (_JSAMPARRAY) (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE, - 2 * (rgroup * (M + 4)) * sizeof(JSAMPROW)); + 2 * (rgroup * (M + 4)) * sizeof(_JSAMPROW)); xbuf += rgroup; /* want one row group at negative offsets */ main_ptr->xbuffer[0][ci] = xbuf; xbuf += rgroup * (M + 4); @@ -179,7 +183,7 @@ make_funny_pointers(j_decompress_ptr cinfo) int ci, i, rgroup; int M = cinfo->_min_DCT_scaled_size; jpeg_component_info *compptr; - JSAMPARRAY buf, xbuf0, xbuf1; + _JSAMPARRAY buf, xbuf0, xbuf1; for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { @@ -219,7 +223,7 @@ set_bottom_pointers(j_decompress_ptr cinfo) my_main_ptr main_ptr = (my_main_ptr)cinfo->main; int ci, i, rgroup, iMCUheight, rows_left; jpeg_component_info *compptr; - JSAMPARRAY xbuf; + _JSAMPARRAY xbuf; for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { @@ -258,14 +262,14 @@ start_pass_main(j_decompress_ptr cinfo, J_BUF_MODE pass_mode) switch (pass_mode) { case JBUF_PASS_THRU: if (cinfo->upsample->need_context_rows) { - main_ptr->pub.process_data = process_data_context_main; + main_ptr->pub._process_data = process_data_context_main; make_funny_pointers(cinfo); /* Create the xbuffer[] lists */ main_ptr->whichptr = 0; /* Read first iMCU row into xbuffer[0] */ main_ptr->context_state = CTX_PREPARE_FOR_IMCU; main_ptr->iMCU_row_ctr = 0; } else { /* Simple case with no context needed */ - main_ptr->pub.process_data = process_data_simple_main; + main_ptr->pub._process_data = process_data_simple_main; } main_ptr->buffer_full = FALSE; /* Mark buffer empty */ main_ptr->rowgroup_ctr = 0; @@ -273,7 +277,7 @@ start_pass_main(j_decompress_ptr cinfo, J_BUF_MODE pass_mode) #ifdef QUANT_2PASS_SUPPORTED case JBUF_CRANK_DEST: /* For last pass of 2-pass quantization, just crank the postprocessor */ - main_ptr->pub.process_data = process_data_crank_post; + main_ptr->pub._process_data = process_data_crank_post; break; #endif default: @@ -289,7 +293,7 @@ start_pass_main(j_decompress_ptr cinfo, J_BUF_MODE pass_mode) */ METHODDEF(void) -process_data_simple_main(j_decompress_ptr cinfo, JSAMPARRAY output_buf, +process_data_simple_main(j_decompress_ptr cinfo, _JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail) { my_main_ptr main_ptr = (my_main_ptr)cinfo->main; @@ -297,7 +301,7 @@ process_data_simple_main(j_decompress_ptr cinfo, JSAMPARRAY output_buf, /* Read input data if we haven't filled the main buffer yet */ if (!main_ptr->buffer_full) { - if (!(*cinfo->coef->decompress_data) (cinfo, main_ptr->buffer)) + if (!(*cinfo->coef->_decompress_data) (cinfo, main_ptr->buffer)) return; /* suspension forced, can do nothing more */ main_ptr->buffer_full = TRUE; /* OK, we have an iMCU row to work with */ } @@ -310,9 +314,9 @@ process_data_simple_main(j_decompress_ptr cinfo, JSAMPARRAY output_buf, */ /* Feed the postprocessor */ - (*cinfo->post->post_process_data) (cinfo, main_ptr->buffer, - &main_ptr->rowgroup_ctr, rowgroups_avail, - output_buf, out_row_ctr, out_rows_avail); + (*cinfo->post->_post_process_data) (cinfo, main_ptr->buffer, + &main_ptr->rowgroup_ctr, rowgroups_avail, + output_buf, out_row_ctr, out_rows_avail); /* Has postprocessor consumed all the data yet? If so, mark buffer empty */ if (main_ptr->rowgroup_ctr >= rowgroups_avail) { @@ -328,15 +332,15 @@ process_data_simple_main(j_decompress_ptr cinfo, JSAMPARRAY output_buf, */ METHODDEF(void) -process_data_context_main(j_decompress_ptr cinfo, JSAMPARRAY output_buf, +process_data_context_main(j_decompress_ptr cinfo, _JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail) { my_main_ptr main_ptr = (my_main_ptr)cinfo->main; /* Read input data if we haven't filled the main buffer yet */ if (!main_ptr->buffer_full) { - if (!(*cinfo->coef->decompress_data) (cinfo, - main_ptr->xbuffer[main_ptr->whichptr])) + if (!(*cinfo->coef->_decompress_data) (cinfo, + main_ptr->xbuffer[main_ptr->whichptr])) return; /* suspension forced, can do nothing more */ main_ptr->buffer_full = TRUE; /* OK, we have an iMCU row to work with */ main_ptr->iMCU_row_ctr++; /* count rows received */ @@ -350,11 +354,11 @@ process_data_context_main(j_decompress_ptr cinfo, JSAMPARRAY output_buf, switch (main_ptr->context_state) { case CTX_POSTPONED_ROW: /* Call postprocessor using previously set pointers for postponed row */ - (*cinfo->post->post_process_data) (cinfo, - main_ptr->xbuffer[main_ptr->whichptr], - &main_ptr->rowgroup_ctr, - main_ptr->rowgroups_avail, output_buf, - out_row_ctr, out_rows_avail); + (*cinfo->post->_post_process_data) (cinfo, + main_ptr->xbuffer[main_ptr->whichptr], + &main_ptr->rowgroup_ctr, + main_ptr->rowgroups_avail, output_buf, + out_row_ctr, out_rows_avail); if (main_ptr->rowgroup_ctr < main_ptr->rowgroups_avail) return; /* Need to suspend */ main_ptr->context_state = CTX_PREPARE_FOR_IMCU; @@ -374,11 +378,11 @@ process_data_context_main(j_decompress_ptr cinfo, JSAMPARRAY output_buf, FALLTHROUGH /*FALLTHROUGH*/ case CTX_PROCESS_IMCU: /* Call postprocessor using previously set pointers */ - (*cinfo->post->post_process_data) (cinfo, - main_ptr->xbuffer[main_ptr->whichptr], - &main_ptr->rowgroup_ctr, - main_ptr->rowgroups_avail, output_buf, - out_row_ctr, out_rows_avail); + (*cinfo->post->_post_process_data) (cinfo, + main_ptr->xbuffer[main_ptr->whichptr], + &main_ptr->rowgroup_ctr, + main_ptr->rowgroups_avail, output_buf, + out_row_ctr, out_rows_avail); if (main_ptr->rowgroup_ctr < main_ptr->rowgroups_avail) return; /* Need to suspend */ /* After the first iMCU, change wraparound pointers to normal state */ @@ -405,12 +409,12 @@ process_data_context_main(j_decompress_ptr cinfo, JSAMPARRAY output_buf, #ifdef QUANT_2PASS_SUPPORTED METHODDEF(void) -process_data_crank_post(j_decompress_ptr cinfo, JSAMPARRAY output_buf, +process_data_crank_post(j_decompress_ptr cinfo, _JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail) { - (*cinfo->post->post_process_data) (cinfo, (JSAMPIMAGE)NULL, - (JDIMENSION *)NULL, (JDIMENSION)0, - output_buf, out_row_ctr, out_rows_avail); + (*cinfo->post->_post_process_data) (cinfo, (_JSAMPIMAGE)NULL, + (JDIMENSION *)NULL, (JDIMENSION)0, + output_buf, out_row_ctr, out_rows_avail); } #endif /* QUANT_2PASS_SUPPORTED */ @@ -421,12 +425,15 @@ process_data_crank_post(j_decompress_ptr cinfo, JSAMPARRAY output_buf, */ GLOBAL(void) -jinit_d_main_controller(j_decompress_ptr cinfo, boolean need_full_buffer) +_jinit_d_main_controller(j_decompress_ptr cinfo, boolean need_full_buffer) { my_main_ptr main_ptr; int ci, rgroup, ngroups; jpeg_component_info *compptr; + if (cinfo->data_precision != BITS_IN_JSAMPLE) + ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision); + main_ptr = (my_main_ptr) (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE, sizeof(my_main_controller)); @@ -452,9 +459,11 @@ jinit_d_main_controller(j_decompress_ptr cinfo, boolean need_full_buffer) ci++, compptr++) { rgroup = (compptr->v_samp_factor * compptr->_DCT_scaled_size) / cinfo->_min_DCT_scaled_size; /* height of a row group of component */ - main_ptr->buffer[ci] = (*cinfo->mem->alloc_sarray) + main_ptr->buffer[ci] = (_JSAMPARRAY)(*cinfo->mem->alloc_sarray) ((j_common_ptr)cinfo, JPOOL_IMAGE, compptr->width_in_blocks * compptr->_DCT_scaled_size, (JDIMENSION)(rgroup * ngroups)); } } + +#endif /* BITS_IN_JSAMPLE != 16 || defined(D_LOSSLESS_SUPPORTED) */ diff --git a/src/3rdparty/libjpeg/src/jdmainct.h b/src/3rdparty/libjpeg/src/jdmainct.h index 37b201ca882..914ad11f694 100644 --- a/src/3rdparty/libjpeg/src/jdmainct.h +++ b/src/3rdparty/libjpeg/src/jdmainct.h @@ -3,22 +3,27 @@ * * This file was part of the Independent JPEG Group's software: * Copyright (C) 1994-1996, Thomas G. Lane. + * libjpeg-turbo Modifications: + * Copyright (C) 2022, D. R. Commander. * For conditions of distribution and use, see the accompanying README.ijg * file. */ #define JPEG_INTERNALS #include "jpeglib.h" -#include "jpegcomp.h" +#include "jpegapicomp.h" +#include "jsamplecomp.h" +#if BITS_IN_JSAMPLE != 16 || defined(D_LOSSLESS_SUPPORTED) + /* Private buffer controller object */ typedef struct { struct jpeg_d_main_controller pub; /* public fields */ /* Pointer to allocated workspace (M or M+2 row groups). */ - JSAMPARRAY buffer[MAX_COMPONENTS]; + _JSAMPARRAY buffer[MAX_COMPONENTS]; boolean buffer_full; /* Have we gotten an iMCU row from decoder? */ JDIMENSION rowgroup_ctr; /* counts row groups output to postprocessor */ @@ -26,7 +31,7 @@ typedef struct { /* Remaining fields are only used in the context case. */ /* These are the master pointers to the funny-order pointer lists. */ - JSAMPIMAGE xbuffer[2]; /* pointers to weird pointer lists */ + _JSAMPIMAGE xbuffer[2]; /* pointers to weird pointer lists */ int whichptr; /* indicates which pointer set is now in use */ int context_state; /* process_data state machine status */ @@ -53,7 +58,7 @@ set_wraparound_pointers(j_decompress_ptr cinfo) int ci, i, rgroup; int M = cinfo->_min_DCT_scaled_size; jpeg_component_info *compptr; - JSAMPARRAY xbuf0, xbuf1; + _JSAMPARRAY xbuf0, xbuf1; for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { @@ -69,3 +74,5 @@ set_wraparound_pointers(j_decompress_ptr cinfo) } } } + +#endif /* BITS_IN_JSAMPLE != 16 || defined(D_LOSSLESS_SUPPORTED) */ diff --git a/src/3rdparty/libjpeg/src/jdmarker.c b/src/3rdparty/libjpeg/src/jdmarker.c index f7eba615fd5..acd28ce62c5 100644 --- a/src/3rdparty/libjpeg/src/jdmarker.c +++ b/src/3rdparty/libjpeg/src/jdmarker.c @@ -3,6 +3,8 @@ * * This file was part of the Independent JPEG Group's software: * Copyright (C) 1991-1998, Thomas G. Lane. + * Lossless JPEG Modifications: + * Copyright (C) 1999, Ken Murchison. * libjpeg-turbo Modifications: * Copyright (C) 2012, 2015, 2022, D. R. Commander. * For conditions of distribution and use, see the accompanying README.ijg @@ -237,7 +239,8 @@ get_soi(j_decompress_ptr cinfo) LOCAL(boolean) -get_sof(j_decompress_ptr cinfo, boolean is_prog, boolean is_arith) +get_sof(j_decompress_ptr cinfo, boolean is_prog, boolean is_lossless, + boolean is_arith) /* Process a SOFn marker */ { JLONG length; @@ -246,6 +249,7 @@ get_sof(j_decompress_ptr cinfo, boolean is_prog, boolean is_arith) INPUT_VARS(cinfo); cinfo->progressive_mode = is_prog; + cinfo->master->lossless = is_lossless; cinfo->arith_code = is_arith; INPUT_2BYTES(cinfo, length, return FALSE); @@ -990,32 +994,40 @@ read_markers(j_decompress_ptr cinfo) case M_SOF0: /* Baseline */ case M_SOF1: /* Extended sequential, Huffman */ - if (!get_sof(cinfo, FALSE, FALSE)) + if (!get_sof(cinfo, FALSE, FALSE, FALSE)) return JPEG_SUSPENDED; break; case M_SOF2: /* Progressive, Huffman */ - if (!get_sof(cinfo, TRUE, FALSE)) + if (!get_sof(cinfo, TRUE, FALSE, FALSE)) + return JPEG_SUSPENDED; + break; + + case M_SOF3: /* Lossless, Huffman */ + if (!get_sof(cinfo, FALSE, TRUE, FALSE)) return JPEG_SUSPENDED; break; case M_SOF9: /* Extended sequential, arithmetic */ - if (!get_sof(cinfo, FALSE, TRUE)) + if (!get_sof(cinfo, FALSE, FALSE, TRUE)) return JPEG_SUSPENDED; break; case M_SOF10: /* Progressive, arithmetic */ - if (!get_sof(cinfo, TRUE, TRUE)) + if (!get_sof(cinfo, TRUE, FALSE, TRUE)) + return JPEG_SUSPENDED; + break; + + case M_SOF11: /* Lossless, arithmetic */ + if (!get_sof(cinfo, FALSE, TRUE, TRUE)) return JPEG_SUSPENDED; break; /* Currently unsupported SOFn types */ - case M_SOF3: /* Lossless, Huffman */ case M_SOF5: /* Differential sequential, Huffman */ case M_SOF6: /* Differential progressive, Huffman */ case M_SOF7: /* Differential lossless, Huffman */ case M_JPG: /* Reserved for JPEG extensions */ - case M_SOF11: /* Lossless, arithmetic */ case M_SOF13: /* Differential sequential, arithmetic */ case M_SOF14: /* Differential progressive, arithmetic */ case M_SOF15: /* Differential lossless, arithmetic */ diff --git a/src/3rdparty/libjpeg/src/jdmaster.c b/src/3rdparty/libjpeg/src/jdmaster.c index a3690bf560b..80a4842ac11 100644 --- a/src/3rdparty/libjpeg/src/jdmaster.c +++ b/src/3rdparty/libjpeg/src/jdmaster.c @@ -4,8 +4,10 @@ * This file was part of the Independent JPEG Group's software: * Copyright (C) 1991-1997, Thomas G. Lane. * Modified 2002-2009 by Guido Vollbeding. + * Lossless JPEG Modifications: + * Copyright (C) 1999, Ken Murchison. * libjpeg-turbo Modifications: - * Copyright (C) 2009-2011, 2016, 2019, 2022, D. R. Commander. + * Copyright (C) 2009-2011, 2016, 2019, 2022-2023, D. R. Commander. * Copyright (C) 2013, Linaro Limited. * Copyright (C) 2015, Google, Inc. * For conditions of distribution and use, see the accompanying README.ijg @@ -20,7 +22,7 @@ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" -#include "jpegcomp.h" +#include "jpegapicomp.h" #include "jdmaster.h" @@ -33,6 +35,9 @@ LOCAL(boolean) use_merged_upsample(j_decompress_ptr cinfo) { #ifdef UPSAMPLE_MERGING_SUPPORTED + /* Colorspace conversion is not supported with lossless JPEG images */ + if (cinfo->master->lossless) + return FALSE; /* Merging is the equivalent of plain box-filter upsampling */ if (cinfo->do_fancy_upsampling || cinfo->CCIR601_sampling) return FALSE; @@ -97,154 +102,154 @@ jpeg_core_output_dimensions(j_decompress_ptr cinfo) int ci; jpeg_component_info *compptr; - /* Compute actual output image dimensions and DCT scaling choices. */ - if (cinfo->scale_num * DCTSIZE <= cinfo->scale_denom) { - /* Provide 1/block_size scaling */ - cinfo->output_width = (JDIMENSION) - jdiv_round_up((long)cinfo->image_width, (long)DCTSIZE); - cinfo->output_height = (JDIMENSION) - jdiv_round_up((long)cinfo->image_height, (long)DCTSIZE); - cinfo->_min_DCT_h_scaled_size = 1; - cinfo->_min_DCT_v_scaled_size = 1; - } else if (cinfo->scale_num * DCTSIZE <= cinfo->scale_denom * 2) { - /* Provide 2/block_size scaling */ - cinfo->output_width = (JDIMENSION) - jdiv_round_up((long)cinfo->image_width * 2L, (long)DCTSIZE); - cinfo->output_height = (JDIMENSION) - jdiv_round_up((long)cinfo->image_height * 2L, (long)DCTSIZE); - cinfo->_min_DCT_h_scaled_size = 2; - cinfo->_min_DCT_v_scaled_size = 2; - } else if (cinfo->scale_num * DCTSIZE <= cinfo->scale_denom * 3) { - /* Provide 3/block_size scaling */ - cinfo->output_width = (JDIMENSION) - jdiv_round_up((long)cinfo->image_width * 3L, (long)DCTSIZE); - cinfo->output_height = (JDIMENSION) - jdiv_round_up((long)cinfo->image_height * 3L, (long)DCTSIZE); - cinfo->_min_DCT_h_scaled_size = 3; - cinfo->_min_DCT_v_scaled_size = 3; - } else if (cinfo->scale_num * DCTSIZE <= cinfo->scale_denom * 4) { - /* Provide 4/block_size scaling */ - cinfo->output_width = (JDIMENSION) - jdiv_round_up((long)cinfo->image_width * 4L, (long)DCTSIZE); - cinfo->output_height = (JDIMENSION) - jdiv_round_up((long)cinfo->image_height * 4L, (long)DCTSIZE); - cinfo->_min_DCT_h_scaled_size = 4; - cinfo->_min_DCT_v_scaled_size = 4; - } else if (cinfo->scale_num * DCTSIZE <= cinfo->scale_denom * 5) { - /* Provide 5/block_size scaling */ - cinfo->output_width = (JDIMENSION) - jdiv_round_up((long)cinfo->image_width * 5L, (long)DCTSIZE); - cinfo->output_height = (JDIMENSION) - jdiv_round_up((long)cinfo->image_height * 5L, (long)DCTSIZE); - cinfo->_min_DCT_h_scaled_size = 5; - cinfo->_min_DCT_v_scaled_size = 5; - } else if (cinfo->scale_num * DCTSIZE <= cinfo->scale_denom * 6) { - /* Provide 6/block_size scaling */ - cinfo->output_width = (JDIMENSION) - jdiv_round_up((long)cinfo->image_width * 6L, (long)DCTSIZE); - cinfo->output_height = (JDIMENSION) - jdiv_round_up((long)cinfo->image_height * 6L, (long)DCTSIZE); - cinfo->_min_DCT_h_scaled_size = 6; - cinfo->_min_DCT_v_scaled_size = 6; - } else if (cinfo->scale_num * DCTSIZE <= cinfo->scale_denom * 7) { - /* Provide 7/block_size scaling */ - cinfo->output_width = (JDIMENSION) - jdiv_round_up((long)cinfo->image_width * 7L, (long)DCTSIZE); - cinfo->output_height = (JDIMENSION) - jdiv_round_up((long)cinfo->image_height * 7L, (long)DCTSIZE); - cinfo->_min_DCT_h_scaled_size = 7; - cinfo->_min_DCT_v_scaled_size = 7; - } else if (cinfo->scale_num * DCTSIZE <= cinfo->scale_denom * 8) { - /* Provide 8/block_size scaling */ - cinfo->output_width = (JDIMENSION) - jdiv_round_up((long)cinfo->image_width * 8L, (long)DCTSIZE); - cinfo->output_height = (JDIMENSION) - jdiv_round_up((long)cinfo->image_height * 8L, (long)DCTSIZE); - cinfo->_min_DCT_h_scaled_size = 8; - cinfo->_min_DCT_v_scaled_size = 8; - } else if (cinfo->scale_num * DCTSIZE <= cinfo->scale_denom * 9) { - /* Provide 9/block_size scaling */ - cinfo->output_width = (JDIMENSION) - jdiv_round_up((long)cinfo->image_width * 9L, (long)DCTSIZE); - cinfo->output_height = (JDIMENSION) - jdiv_round_up((long)cinfo->image_height * 9L, (long)DCTSIZE); - cinfo->_min_DCT_h_scaled_size = 9; - cinfo->_min_DCT_v_scaled_size = 9; - } else if (cinfo->scale_num * DCTSIZE <= cinfo->scale_denom * 10) { - /* Provide 10/block_size scaling */ - cinfo->output_width = (JDIMENSION) - jdiv_round_up((long)cinfo->image_width * 10L, (long)DCTSIZE); - cinfo->output_height = (JDIMENSION) - jdiv_round_up((long)cinfo->image_height * 10L, (long)DCTSIZE); - cinfo->_min_DCT_h_scaled_size = 10; - cinfo->_min_DCT_v_scaled_size = 10; - } else if (cinfo->scale_num * DCTSIZE <= cinfo->scale_denom * 11) { - /* Provide 11/block_size scaling */ - cinfo->output_width = (JDIMENSION) - jdiv_round_up((long)cinfo->image_width * 11L, (long)DCTSIZE); - cinfo->output_height = (JDIMENSION) - jdiv_round_up((long)cinfo->image_height * 11L, (long)DCTSIZE); - cinfo->_min_DCT_h_scaled_size = 11; - cinfo->_min_DCT_v_scaled_size = 11; - } else if (cinfo->scale_num * DCTSIZE <= cinfo->scale_denom * 12) { - /* Provide 12/block_size scaling */ - cinfo->output_width = (JDIMENSION) - jdiv_round_up((long)cinfo->image_width * 12L, (long)DCTSIZE); - cinfo->output_height = (JDIMENSION) - jdiv_round_up((long)cinfo->image_height * 12L, (long)DCTSIZE); - cinfo->_min_DCT_h_scaled_size = 12; - cinfo->_min_DCT_v_scaled_size = 12; - } else if (cinfo->scale_num * DCTSIZE <= cinfo->scale_denom * 13) { - /* Provide 13/block_size scaling */ - cinfo->output_width = (JDIMENSION) - jdiv_round_up((long)cinfo->image_width * 13L, (long)DCTSIZE); - cinfo->output_height = (JDIMENSION) - jdiv_round_up((long)cinfo->image_height * 13L, (long)DCTSIZE); - cinfo->_min_DCT_h_scaled_size = 13; - cinfo->_min_DCT_v_scaled_size = 13; - } else if (cinfo->scale_num * DCTSIZE <= cinfo->scale_denom * 14) { - /* Provide 14/block_size scaling */ - cinfo->output_width = (JDIMENSION) - jdiv_round_up((long)cinfo->image_width * 14L, (long)DCTSIZE); - cinfo->output_height = (JDIMENSION) - jdiv_round_up((long)cinfo->image_height * 14L, (long)DCTSIZE); - cinfo->_min_DCT_h_scaled_size = 14; - cinfo->_min_DCT_v_scaled_size = 14; - } else if (cinfo->scale_num * DCTSIZE <= cinfo->scale_denom * 15) { - /* Provide 15/block_size scaling */ - cinfo->output_width = (JDIMENSION) - jdiv_round_up((long)cinfo->image_width * 15L, (long)DCTSIZE); - cinfo->output_height = (JDIMENSION) - jdiv_round_up((long)cinfo->image_height * 15L, (long)DCTSIZE); - cinfo->_min_DCT_h_scaled_size = 15; - cinfo->_min_DCT_v_scaled_size = 15; - } else { - /* Provide 16/block_size scaling */ - cinfo->output_width = (JDIMENSION) - jdiv_round_up((long)cinfo->image_width * 16L, (long)DCTSIZE); - cinfo->output_height = (JDIMENSION) - jdiv_round_up((long)cinfo->image_height * 16L, (long)DCTSIZE); - cinfo->_min_DCT_h_scaled_size = 16; - cinfo->_min_DCT_v_scaled_size = 16; + if (!cinfo->master->lossless) { + /* Compute actual output image dimensions and DCT scaling choices. */ + if (cinfo->scale_num * DCTSIZE <= cinfo->scale_denom) { + /* Provide 1/block_size scaling */ + cinfo->output_width = (JDIMENSION) + jdiv_round_up((long)cinfo->image_width, (long)DCTSIZE); + cinfo->output_height = (JDIMENSION) + jdiv_round_up((long)cinfo->image_height, (long)DCTSIZE); + cinfo->_min_DCT_h_scaled_size = 1; + cinfo->_min_DCT_v_scaled_size = 1; + } else if (cinfo->scale_num * DCTSIZE <= cinfo->scale_denom * 2) { + /* Provide 2/block_size scaling */ + cinfo->output_width = (JDIMENSION) + jdiv_round_up((long)cinfo->image_width * 2L, (long)DCTSIZE); + cinfo->output_height = (JDIMENSION) + jdiv_round_up((long)cinfo->image_height * 2L, (long)DCTSIZE); + cinfo->_min_DCT_h_scaled_size = 2; + cinfo->_min_DCT_v_scaled_size = 2; + } else if (cinfo->scale_num * DCTSIZE <= cinfo->scale_denom * 3) { + /* Provide 3/block_size scaling */ + cinfo->output_width = (JDIMENSION) + jdiv_round_up((long)cinfo->image_width * 3L, (long)DCTSIZE); + cinfo->output_height = (JDIMENSION) + jdiv_round_up((long)cinfo->image_height * 3L, (long)DCTSIZE); + cinfo->_min_DCT_h_scaled_size = 3; + cinfo->_min_DCT_v_scaled_size = 3; + } else if (cinfo->scale_num * DCTSIZE <= cinfo->scale_denom * 4) { + /* Provide 4/block_size scaling */ + cinfo->output_width = (JDIMENSION) + jdiv_round_up((long)cinfo->image_width * 4L, (long)DCTSIZE); + cinfo->output_height = (JDIMENSION) + jdiv_round_up((long)cinfo->image_height * 4L, (long)DCTSIZE); + cinfo->_min_DCT_h_scaled_size = 4; + cinfo->_min_DCT_v_scaled_size = 4; + } else if (cinfo->scale_num * DCTSIZE <= cinfo->scale_denom * 5) { + /* Provide 5/block_size scaling */ + cinfo->output_width = (JDIMENSION) + jdiv_round_up((long)cinfo->image_width * 5L, (long)DCTSIZE); + cinfo->output_height = (JDIMENSION) + jdiv_round_up((long)cinfo->image_height * 5L, (long)DCTSIZE); + cinfo->_min_DCT_h_scaled_size = 5; + cinfo->_min_DCT_v_scaled_size = 5; + } else if (cinfo->scale_num * DCTSIZE <= cinfo->scale_denom * 6) { + /* Provide 6/block_size scaling */ + cinfo->output_width = (JDIMENSION) + jdiv_round_up((long)cinfo->image_width * 6L, (long)DCTSIZE); + cinfo->output_height = (JDIMENSION) + jdiv_round_up((long)cinfo->image_height * 6L, (long)DCTSIZE); + cinfo->_min_DCT_h_scaled_size = 6; + cinfo->_min_DCT_v_scaled_size = 6; + } else if (cinfo->scale_num * DCTSIZE <= cinfo->scale_denom * 7) { + /* Provide 7/block_size scaling */ + cinfo->output_width = (JDIMENSION) + jdiv_round_up((long)cinfo->image_width * 7L, (long)DCTSIZE); + cinfo->output_height = (JDIMENSION) + jdiv_round_up((long)cinfo->image_height * 7L, (long)DCTSIZE); + cinfo->_min_DCT_h_scaled_size = 7; + cinfo->_min_DCT_v_scaled_size = 7; + } else if (cinfo->scale_num * DCTSIZE <= cinfo->scale_denom * 8) { + /* Provide 8/block_size scaling */ + cinfo->output_width = (JDIMENSION) + jdiv_round_up((long)cinfo->image_width * 8L, (long)DCTSIZE); + cinfo->output_height = (JDIMENSION) + jdiv_round_up((long)cinfo->image_height * 8L, (long)DCTSIZE); + cinfo->_min_DCT_h_scaled_size = 8; + cinfo->_min_DCT_v_scaled_size = 8; + } else if (cinfo->scale_num * DCTSIZE <= cinfo->scale_denom * 9) { + /* Provide 9/block_size scaling */ + cinfo->output_width = (JDIMENSION) + jdiv_round_up((long)cinfo->image_width * 9L, (long)DCTSIZE); + cinfo->output_height = (JDIMENSION) + jdiv_round_up((long)cinfo->image_height * 9L, (long)DCTSIZE); + cinfo->_min_DCT_h_scaled_size = 9; + cinfo->_min_DCT_v_scaled_size = 9; + } else if (cinfo->scale_num * DCTSIZE <= cinfo->scale_denom * 10) { + /* Provide 10/block_size scaling */ + cinfo->output_width = (JDIMENSION) + jdiv_round_up((long)cinfo->image_width * 10L, (long)DCTSIZE); + cinfo->output_height = (JDIMENSION) + jdiv_round_up((long)cinfo->image_height * 10L, (long)DCTSIZE); + cinfo->_min_DCT_h_scaled_size = 10; + cinfo->_min_DCT_v_scaled_size = 10; + } else if (cinfo->scale_num * DCTSIZE <= cinfo->scale_denom * 11) { + /* Provide 11/block_size scaling */ + cinfo->output_width = (JDIMENSION) + jdiv_round_up((long)cinfo->image_width * 11L, (long)DCTSIZE); + cinfo->output_height = (JDIMENSION) + jdiv_round_up((long)cinfo->image_height * 11L, (long)DCTSIZE); + cinfo->_min_DCT_h_scaled_size = 11; + cinfo->_min_DCT_v_scaled_size = 11; + } else if (cinfo->scale_num * DCTSIZE <= cinfo->scale_denom * 12) { + /* Provide 12/block_size scaling */ + cinfo->output_width = (JDIMENSION) + jdiv_round_up((long)cinfo->image_width * 12L, (long)DCTSIZE); + cinfo->output_height = (JDIMENSION) + jdiv_round_up((long)cinfo->image_height * 12L, (long)DCTSIZE); + cinfo->_min_DCT_h_scaled_size = 12; + cinfo->_min_DCT_v_scaled_size = 12; + } else if (cinfo->scale_num * DCTSIZE <= cinfo->scale_denom * 13) { + /* Provide 13/block_size scaling */ + cinfo->output_width = (JDIMENSION) + jdiv_round_up((long)cinfo->image_width * 13L, (long)DCTSIZE); + cinfo->output_height = (JDIMENSION) + jdiv_round_up((long)cinfo->image_height * 13L, (long)DCTSIZE); + cinfo->_min_DCT_h_scaled_size = 13; + cinfo->_min_DCT_v_scaled_size = 13; + } else if (cinfo->scale_num * DCTSIZE <= cinfo->scale_denom * 14) { + /* Provide 14/block_size scaling */ + cinfo->output_width = (JDIMENSION) + jdiv_round_up((long)cinfo->image_width * 14L, (long)DCTSIZE); + cinfo->output_height = (JDIMENSION) + jdiv_round_up((long)cinfo->image_height * 14L, (long)DCTSIZE); + cinfo->_min_DCT_h_scaled_size = 14; + cinfo->_min_DCT_v_scaled_size = 14; + } else if (cinfo->scale_num * DCTSIZE <= cinfo->scale_denom * 15) { + /* Provide 15/block_size scaling */ + cinfo->output_width = (JDIMENSION) + jdiv_round_up((long)cinfo->image_width * 15L, (long)DCTSIZE); + cinfo->output_height = (JDIMENSION) + jdiv_round_up((long)cinfo->image_height * 15L, (long)DCTSIZE); + cinfo->_min_DCT_h_scaled_size = 15; + cinfo->_min_DCT_v_scaled_size = 15; + } else { + /* Provide 16/block_size scaling */ + cinfo->output_width = (JDIMENSION) + jdiv_round_up((long)cinfo->image_width * 16L, (long)DCTSIZE); + cinfo->output_height = (JDIMENSION) + jdiv_round_up((long)cinfo->image_height * 16L, (long)DCTSIZE); + cinfo->_min_DCT_h_scaled_size = 16; + cinfo->_min_DCT_v_scaled_size = 16; + } + + /* Recompute dimensions of components */ + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + compptr->_DCT_h_scaled_size = cinfo->_min_DCT_h_scaled_size; + compptr->_DCT_v_scaled_size = cinfo->_min_DCT_v_scaled_size; + } + } else +#endif /* !IDCT_SCALING_SUPPORTED */ + { + /* Hardwire it to "no scaling" */ + cinfo->output_width = cinfo->image_width; + cinfo->output_height = cinfo->image_height; + /* jdinput.c has already initialized DCT_scaled_size, + * and has computed unscaled downsampled_width and downsampled_height. + */ } - - /* Recompute dimensions of components */ - for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { - compptr->_DCT_h_scaled_size = cinfo->_min_DCT_h_scaled_size; - compptr->_DCT_v_scaled_size = cinfo->_min_DCT_v_scaled_size; - } - -#else /* !IDCT_SCALING_SUPPORTED */ - - /* Hardwire it to "no scaling" */ - cinfo->output_width = cinfo->image_width; - cinfo->output_height = cinfo->image_height; - /* jdinput.c has already initialized DCT_scaled_size, - * and has computed unscaled downsampled_width and downsampled_height. - */ - -#endif /* IDCT_SCALING_SUPPORTED */ } @@ -273,54 +278,56 @@ jpeg_calc_output_dimensions(j_decompress_ptr cinfo) #ifdef IDCT_SCALING_SUPPORTED - /* In selecting the actual DCT scaling for each component, we try to - * scale up the chroma components via IDCT scaling rather than upsampling. - * This saves time if the upsampler gets to use 1:1 scaling. - * Note this code adapts subsampling ratios which are powers of 2. - */ - for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { - int ssize = cinfo->_min_DCT_scaled_size; - while (ssize < DCTSIZE && - ((cinfo->max_h_samp_factor * cinfo->_min_DCT_scaled_size) % - (compptr->h_samp_factor * ssize * 2) == 0) && - ((cinfo->max_v_samp_factor * cinfo->_min_DCT_scaled_size) % - (compptr->v_samp_factor * ssize * 2) == 0)) { - ssize = ssize * 2; - } + if (!cinfo->master->lossless) { + /* In selecting the actual DCT scaling for each component, we try to + * scale up the chroma components via IDCT scaling rather than upsampling. + * This saves time if the upsampler gets to use 1:1 scaling. + * Note this code adapts subsampling ratios which are powers of 2. + */ + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + int ssize = cinfo->_min_DCT_scaled_size; + while (ssize < DCTSIZE && + ((cinfo->max_h_samp_factor * cinfo->_min_DCT_scaled_size) % + (compptr->h_samp_factor * ssize * 2) == 0) && + ((cinfo->max_v_samp_factor * cinfo->_min_DCT_scaled_size) % + (compptr->v_samp_factor * ssize * 2) == 0)) { + ssize = ssize * 2; + } #if JPEG_LIB_VERSION >= 70 - compptr->DCT_h_scaled_size = compptr->DCT_v_scaled_size = ssize; + compptr->DCT_h_scaled_size = compptr->DCT_v_scaled_size = ssize; #else - compptr->DCT_scaled_size = ssize; + compptr->DCT_scaled_size = ssize; #endif - } - - /* Recompute downsampled dimensions of components; - * application needs to know these if using raw downsampled data. - */ - for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { - /* Size in samples, after IDCT scaling */ - compptr->downsampled_width = (JDIMENSION) - jdiv_round_up((long)cinfo->image_width * - (long)(compptr->h_samp_factor * compptr->_DCT_scaled_size), - (long)(cinfo->max_h_samp_factor * DCTSIZE)); - compptr->downsampled_height = (JDIMENSION) - jdiv_round_up((long)cinfo->image_height * - (long)(compptr->v_samp_factor * compptr->_DCT_scaled_size), - (long)(cinfo->max_v_samp_factor * DCTSIZE)); - } - -#else /* !IDCT_SCALING_SUPPORTED */ - - /* Hardwire it to "no scaling" */ - cinfo->output_width = cinfo->image_width; - cinfo->output_height = cinfo->image_height; - /* jdinput.c has already initialized DCT_scaled_size to DCTSIZE, - * and has computed unscaled downsampled_width and downsampled_height. - */ + } + /* Recompute downsampled dimensions of components; + * application needs to know these if using raw downsampled data. + */ + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + /* Size in samples, after IDCT scaling */ + compptr->downsampled_width = (JDIMENSION) + jdiv_round_up((long)cinfo->image_width * + (long)(compptr->h_samp_factor * + compptr->_DCT_scaled_size), + (long)(cinfo->max_h_samp_factor * DCTSIZE)); + compptr->downsampled_height = (JDIMENSION) + jdiv_round_up((long)cinfo->image_height * + (long)(compptr->v_samp_factor * + compptr->_DCT_scaled_size), + (long)(cinfo->max_v_samp_factor * DCTSIZE)); + } + } else #endif /* IDCT_SCALING_SUPPORTED */ + { + /* Hardwire it to "no scaling" */ + cinfo->output_width = cinfo->image_width; + cinfo->output_height = cinfo->image_height; + /* jdinput.c has already initialized DCT_scaled_size to DCTSIZE, + * and has computed unscaled downsampled_width and downsampled_height. + */ + } /* Report number of components in selected colorspace. */ /* Probably this should be in the color conversion module... */ @@ -409,27 +416,83 @@ prepare_range_limit_table(j_decompress_ptr cinfo) /* Allocate and fill in the sample_range_limit table */ { JSAMPLE *table; + J12SAMPLE *table12; +#ifdef D_LOSSLESS_SUPPORTED + J16SAMPLE *table16; +#endif int i; - table = (JSAMPLE *) - (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE, - (5 * (MAXJSAMPLE + 1) + CENTERJSAMPLE) * sizeof(JSAMPLE)); - table += (MAXJSAMPLE + 1); /* allow negative subscripts of simple table */ - cinfo->sample_range_limit = table; - /* First segment of "simple" table: limit[x] = 0 for x < 0 */ - memset(table - (MAXJSAMPLE + 1), 0, (MAXJSAMPLE + 1) * sizeof(JSAMPLE)); - /* Main part of "simple" table: limit[x] = x */ - for (i = 0; i <= MAXJSAMPLE; i++) - table[i] = (JSAMPLE)i; - table += CENTERJSAMPLE; /* Point to where post-IDCT table starts */ - /* End of simple table, rest of first half of post-IDCT table */ - for (i = CENTERJSAMPLE; i < 2 * (MAXJSAMPLE + 1); i++) - table[i] = MAXJSAMPLE; - /* Second half of post-IDCT table */ - memset(table + (2 * (MAXJSAMPLE + 1)), 0, - (2 * (MAXJSAMPLE + 1) - CENTERJSAMPLE) * sizeof(JSAMPLE)); - memcpy(table + (4 * (MAXJSAMPLE + 1) - CENTERJSAMPLE), - cinfo->sample_range_limit, CENTERJSAMPLE * sizeof(JSAMPLE)); + if (cinfo->data_precision == 16) { +#ifdef D_LOSSLESS_SUPPORTED + table16 = (J16SAMPLE *) + (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE, + (5 * (MAXJ16SAMPLE + 1) + CENTERJ16SAMPLE) * + sizeof(J16SAMPLE)); + table16 += (MAXJ16SAMPLE + 1); /* allow negative subscripts of simple + table */ + cinfo->sample_range_limit = (JSAMPLE *)table16; + /* First segment of "simple" table: limit[x] = 0 for x < 0 */ + memset(table16 - (MAXJ16SAMPLE + 1), 0, + (MAXJ16SAMPLE + 1) * sizeof(J16SAMPLE)); + /* Main part of "simple" table: limit[x] = x */ + for (i = 0; i <= MAXJ16SAMPLE; i++) + table16[i] = (J16SAMPLE)i; + table16 += CENTERJ16SAMPLE; /* Point to where post-IDCT table starts */ + /* End of simple table, rest of first half of post-IDCT table */ + for (i = CENTERJ16SAMPLE; i < 2 * (MAXJ16SAMPLE + 1); i++) + table16[i] = MAXJ16SAMPLE; + /* Second half of post-IDCT table */ + memset(table16 + (2 * (MAXJ16SAMPLE + 1)), 0, + (2 * (MAXJ16SAMPLE + 1) - CENTERJ16SAMPLE) * sizeof(J16SAMPLE)); + memcpy(table16 + (4 * (MAXJ16SAMPLE + 1) - CENTERJ16SAMPLE), + cinfo->sample_range_limit, CENTERJ16SAMPLE * sizeof(J16SAMPLE)); +#else + ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision); +#endif + } else if (cinfo->data_precision == 12) { + table12 = (J12SAMPLE *) + (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE, + (5 * (MAXJ12SAMPLE + 1) + CENTERJ12SAMPLE) * + sizeof(J12SAMPLE)); + table12 += (MAXJ12SAMPLE + 1); /* allow negative subscripts of simple + table */ + cinfo->sample_range_limit = (JSAMPLE *)table12; + /* First segment of "simple" table: limit[x] = 0 for x < 0 */ + memset(table12 - (MAXJ12SAMPLE + 1), 0, + (MAXJ12SAMPLE + 1) * sizeof(J12SAMPLE)); + /* Main part of "simple" table: limit[x] = x */ + for (i = 0; i <= MAXJ12SAMPLE; i++) + table12[i] = (J12SAMPLE)i; + table12 += CENTERJ12SAMPLE; /* Point to where post-IDCT table starts */ + /* End of simple table, rest of first half of post-IDCT table */ + for (i = CENTERJ12SAMPLE; i < 2 * (MAXJ12SAMPLE + 1); i++) + table12[i] = MAXJ12SAMPLE; + /* Second half of post-IDCT table */ + memset(table12 + (2 * (MAXJ12SAMPLE + 1)), 0, + (2 * (MAXJ12SAMPLE + 1) - CENTERJ12SAMPLE) * sizeof(J12SAMPLE)); + memcpy(table12 + (4 * (MAXJ12SAMPLE + 1) - CENTERJ12SAMPLE), + cinfo->sample_range_limit, CENTERJ12SAMPLE * sizeof(J12SAMPLE)); + } else { + table = (JSAMPLE *) + (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE, + (5 * (MAXJSAMPLE + 1) + CENTERJSAMPLE) * sizeof(JSAMPLE)); + table += (MAXJSAMPLE + 1); /* allow negative subscripts of simple table */ + cinfo->sample_range_limit = table; + /* First segment of "simple" table: limit[x] = 0 for x < 0 */ + memset(table - (MAXJSAMPLE + 1), 0, (MAXJSAMPLE + 1) * sizeof(JSAMPLE)); + /* Main part of "simple" table: limit[x] = x */ + for (i = 0; i <= MAXJSAMPLE; i++) + table[i] = (JSAMPLE)i; + table += CENTERJSAMPLE; /* Point to where post-IDCT table starts */ + /* End of simple table, rest of first half of post-IDCT table */ + for (i = CENTERJSAMPLE; i < 2 * (MAXJSAMPLE + 1); i++) + table[i] = MAXJSAMPLE; + /* Second half of post-IDCT table */ + memset(table + (2 * (MAXJSAMPLE + 1)), 0, + (2 * (MAXJSAMPLE + 1) - CENTERJSAMPLE) * sizeof(JSAMPLE)); + memcpy(table + (4 * (MAXJSAMPLE + 1) - CENTERJSAMPLE), + cinfo->sample_range_limit, CENTERJSAMPLE * sizeof(JSAMPLE)); + } } @@ -452,6 +515,17 @@ master_selection(j_decompress_ptr cinfo) long samplesperrow; JDIMENSION jd_samplesperrow; + /* Disable IDCT scaling and raw (downsampled) data output in lossless mode. + * IDCT scaling is not useful in lossless mode, and it must be disabled in + * order to properly calculate the output dimensions. Raw data output isn't + * particularly useful without subsampling and has not been tested in + * lossless mode. + */ + if (cinfo->master->lossless) { + cinfo->raw_data_out = FALSE; + cinfo->scale_num = cinfo->scale_denom = 1; + } + /* Initialize dimensions and other stuff */ jpeg_calc_output_dimensions(cinfo); prepare_range_limit_table(cinfo); @@ -480,7 +554,8 @@ master_selection(j_decompress_ptr cinfo) if (cinfo->raw_data_out) ERREXIT(cinfo, JERR_NOTIMPL); /* 2-pass quantizer only works in 3-component color space. */ - if (cinfo->out_color_components != 3) { + if (cinfo->out_color_components != 3 || + cinfo->out_color_space == JCS_RGB565) { cinfo->enable_1pass_quant = TRUE; cinfo->enable_external_quant = FALSE; cinfo->enable_2pass_quant = FALSE; @@ -495,7 +570,12 @@ master_selection(j_decompress_ptr cinfo) if (cinfo->enable_1pass_quant) { #ifdef QUANT_1PASS_SUPPORTED - jinit_1pass_quantizer(cinfo); + if (cinfo->data_precision == 16) + ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision); + else if (cinfo->data_precision == 12) + j12init_1pass_quantizer(cinfo); + else + jinit_1pass_quantizer(cinfo); master->quantizer_1pass = cinfo->cquantize; #else ERREXIT(cinfo, JERR_NOT_COMPILED); @@ -505,7 +585,12 @@ master_selection(j_decompress_ptr cinfo) /* We use the 2-pass code to map to external colormaps. */ if (cinfo->enable_2pass_quant || cinfo->enable_external_quant) { #ifdef QUANT_2PASS_SUPPORTED - jinit_2pass_quantizer(cinfo); + if (cinfo->data_precision == 16) + ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision); + else if (cinfo->data_precision == 12) + j12init_2pass_quantizer(cinfo); + else + jinit_2pass_quantizer(cinfo); master->quantizer_2pass = cinfo->cquantize; #else ERREXIT(cinfo, JERR_NOT_COMPILED); @@ -520,42 +605,122 @@ master_selection(j_decompress_ptr cinfo) if (!cinfo->raw_data_out) { if (master->using_merged_upsample) { #ifdef UPSAMPLE_MERGING_SUPPORTED - jinit_merged_upsampler(cinfo); /* does color conversion too */ + if (cinfo->data_precision == 16) + ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision); + else if (cinfo->data_precision == 12) + j12init_merged_upsampler(cinfo); /* does color conversion too */ + else + jinit_merged_upsampler(cinfo); /* does color conversion too */ #else ERREXIT(cinfo, JERR_NOT_COMPILED); #endif } else { - jinit_color_deconverter(cinfo); - jinit_upsampler(cinfo); - } - jinit_d_post_controller(cinfo, cinfo->enable_2pass_quant); - } - /* Inverse DCT */ - jinit_inverse_dct(cinfo); - /* Entropy decoding: either Huffman or arithmetic coding. */ - if (cinfo->arith_code) { -#ifdef D_ARITH_CODING_SUPPORTED - jinit_arith_decoder(cinfo); + if (cinfo->data_precision == 16) { +#ifdef D_LOSSLESS_SUPPORTED + j16init_color_deconverter(cinfo); + j16init_upsampler(cinfo); #else - ERREXIT(cinfo, JERR_ARITH_NOTIMPL); + ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision); +#endif + } else if (cinfo->data_precision == 12) { + j12init_color_deconverter(cinfo); + j12init_upsampler(cinfo); + } else { + jinit_color_deconverter(cinfo); + jinit_upsampler(cinfo); + } + } + if (cinfo->data_precision == 16) +#ifdef D_LOSSLESS_SUPPORTED + j16init_d_post_controller(cinfo, cinfo->enable_2pass_quant); +#else + ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision); +#endif + else if (cinfo->data_precision == 12) + j12init_d_post_controller(cinfo, cinfo->enable_2pass_quant); + else + jinit_d_post_controller(cinfo, cinfo->enable_2pass_quant); + } + + if (cinfo->master->lossless) { +#ifdef D_LOSSLESS_SUPPORTED + /* Prediction, sample undifferencing, point transform, and sample size + * scaling + */ + if (cinfo->data_precision == 16) + j16init_lossless_decompressor(cinfo); + else if (cinfo->data_precision == 12) + j12init_lossless_decompressor(cinfo); + else + jinit_lossless_decompressor(cinfo); + /* Entropy decoding: either Huffman or arithmetic coding. */ + if (cinfo->arith_code) { + ERREXIT(cinfo, JERR_ARITH_NOTIMPL); + } else { + jinit_lhuff_decoder(cinfo); + } + + /* Initialize principal buffer controllers. */ + use_c_buffer = cinfo->inputctl->has_multiple_scans || + cinfo->buffered_image; + if (cinfo->data_precision == 16) + j16init_d_diff_controller(cinfo, use_c_buffer); + else if (cinfo->data_precision == 12) + j12init_d_diff_controller(cinfo, use_c_buffer); + else + jinit_d_diff_controller(cinfo, use_c_buffer); +#else + ERREXIT(cinfo, JERR_NOT_COMPILED); #endif } else { - if (cinfo->progressive_mode) { -#ifdef D_PROGRESSIVE_SUPPORTED - jinit_phuff_decoder(cinfo); + if (cinfo->data_precision == 16) + ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision); + /* Inverse DCT */ + if (cinfo->data_precision == 12) + j12init_inverse_dct(cinfo); + else + jinit_inverse_dct(cinfo); + /* Entropy decoding: either Huffman or arithmetic coding. */ + if (cinfo->arith_code) { +#ifdef D_ARITH_CODING_SUPPORTED + jinit_arith_decoder(cinfo); #else - ERREXIT(cinfo, JERR_NOT_COMPILED); + ERREXIT(cinfo, JERR_ARITH_NOTIMPL); #endif - } else - jinit_huff_decoder(cinfo); + } else { + if (cinfo->progressive_mode) { +#ifdef D_PROGRESSIVE_SUPPORTED + jinit_phuff_decoder(cinfo); +#else + ERREXIT(cinfo, JERR_NOT_COMPILED); +#endif + } else + jinit_huff_decoder(cinfo); + } + + /* Initialize principal buffer controllers. */ + use_c_buffer = cinfo->inputctl->has_multiple_scans || + cinfo->buffered_image; + if (cinfo->data_precision == 12) + j12init_d_coef_controller(cinfo, use_c_buffer); + else + jinit_d_coef_controller(cinfo, use_c_buffer); } - /* Initialize principal buffer controllers. */ - use_c_buffer = cinfo->inputctl->has_multiple_scans || cinfo->buffered_image; - jinit_d_coef_controller(cinfo, use_c_buffer); - - if (!cinfo->raw_data_out) - jinit_d_main_controller(cinfo, FALSE /* never need full buffer here */); + if (!cinfo->raw_data_out) { + if (cinfo->data_precision == 16) +#ifdef D_LOSSLESS_SUPPORTED + j16init_d_main_controller(cinfo, + FALSE /* never need full buffer here */); +#else + ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision); +#endif + else if (cinfo->data_precision == 12) + j12init_d_main_controller(cinfo, + FALSE /* never need full buffer here */); + else + jinit_d_main_controller(cinfo, FALSE /* never need full buffer here */); + } /* We can now tell the memory manager to allocate virtual arrays. */ (*cinfo->mem->realize_virt_arrays) ((j_common_ptr)cinfo); diff --git a/src/3rdparty/libjpeg/src/jdmerge.c b/src/3rdparty/libjpeg/src/jdmerge.c index 38b002729c1..49f2006fc02 100644 --- a/src/3rdparty/libjpeg/src/jdmerge.c +++ b/src/3rdparty/libjpeg/src/jdmerge.c @@ -5,7 +5,7 @@ * Copyright (C) 1994-1996, Thomas G. Lane. * libjpeg-turbo Modifications: * Copyright 2009 Pierre Ossman for Cendio AB - * Copyright (C) 2009, 2011, 2014-2015, 2020, D. R. Commander. + * Copyright (C) 2009, 2011, 2014-2015, 2020, 2022, D. R. Commander. * Copyright (C) 2013, Linaro Limited. * For conditions of distribution and use, see the accompanying README.ijg * file. @@ -167,20 +167,20 @@ build_ycc_rgb_table(j_decompress_ptr cinfo) upsample->Cr_r_tab = (int *) (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE, - (MAXJSAMPLE + 1) * sizeof(int)); + (_MAXJSAMPLE + 1) * sizeof(int)); upsample->Cb_b_tab = (int *) (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE, - (MAXJSAMPLE + 1) * sizeof(int)); + (_MAXJSAMPLE + 1) * sizeof(int)); upsample->Cr_g_tab = (JLONG *) (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE, - (MAXJSAMPLE + 1) * sizeof(JLONG)); + (_MAXJSAMPLE + 1) * sizeof(JLONG)); upsample->Cb_g_tab = (JLONG *) (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE, - (MAXJSAMPLE + 1) * sizeof(JLONG)); + (_MAXJSAMPLE + 1) * sizeof(JLONG)); - for (i = 0, x = -CENTERJSAMPLE; i <= MAXJSAMPLE; i++, x++) { - /* i is the actual input pixel value, in the range 0..MAXJSAMPLE */ - /* The Cb or Cr value we are thinking of is x = i - CENTERJSAMPLE */ + for (i = 0, x = -_CENTERJSAMPLE; i <= _MAXJSAMPLE; i++, x++) { + /* i is the actual input pixel value, in the range 0.._MAXJSAMPLE */ + /* The Cb or Cr value we are thinking of is x = i - _CENTERJSAMPLE */ /* Cr=>R value is nearest int to 1.40200 * x */ upsample->Cr_r_tab[i] = (int) RIGHT_SHIFT(FIX(1.40200) * x + ONE_HALF, SCALEBITS); @@ -219,14 +219,14 @@ start_pass_merged_upsample(j_decompress_ptr cinfo) */ METHODDEF(void) -merged_2v_upsample(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, +merged_2v_upsample(j_decompress_ptr cinfo, _JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, - JDIMENSION in_row_groups_avail, JSAMPARRAY output_buf, + JDIMENSION in_row_groups_avail, _JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail) /* 2:1 vertical sampling case: may need a spare row. */ { my_merged_upsample_ptr upsample = (my_merged_upsample_ptr)cinfo->upsample; - JSAMPROW work_ptrs[2]; + _JSAMPROW work_ptrs[2]; JDIMENSION num_rows; /* number of rows returned to caller */ if (upsample->spare_full) { @@ -234,8 +234,8 @@ merged_2v_upsample(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, JDIMENSION size = upsample->out_row_width; if (cinfo->out_color_space == JCS_RGB565) size = cinfo->output_width * 2; - jcopy_sample_rows(&upsample->spare_row, 0, output_buf + *out_row_ctr, 0, 1, - size); + _jcopy_sample_rows(&upsample->spare_row, 0, output_buf + *out_row_ctr, 0, + 1, size); num_rows = 1; upsample->spare_full = FALSE; } else { @@ -270,9 +270,9 @@ merged_2v_upsample(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, METHODDEF(void) -merged_1v_upsample(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, +merged_1v_upsample(j_decompress_ptr cinfo, _JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, - JDIMENSION in_row_groups_avail, JSAMPARRAY output_buf, + JDIMENSION in_row_groups_avail, _JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail) /* 1:1 vertical sampling case: much easier, never need a spare row. */ { @@ -302,8 +302,8 @@ merged_1v_upsample(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, */ METHODDEF(void) -h2v1_merged_upsample(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, - JDIMENSION in_row_group_ctr, JSAMPARRAY output_buf) +h2v1_merged_upsample(j_decompress_ptr cinfo, _JSAMPIMAGE input_buf, + JDIMENSION in_row_group_ctr, _JSAMPARRAY output_buf) { switch (cinfo->out_color_space) { case JCS_EXT_RGB: @@ -347,8 +347,8 @@ h2v1_merged_upsample(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, */ METHODDEF(void) -h2v2_merged_upsample(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, - JDIMENSION in_row_group_ctr, JSAMPARRAY output_buf) +h2v2_merged_upsample(j_decompress_ptr cinfo, _JSAMPIMAGE input_buf, + JDIMENSION in_row_group_ctr, _JSAMPARRAY output_buf) { switch (cinfo->out_color_space) { case JCS_EXT_RGB: @@ -474,8 +474,8 @@ static INLINE boolean is_big_endian(void) METHODDEF(void) -h2v1_merged_upsample_565(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, - JDIMENSION in_row_group_ctr, JSAMPARRAY output_buf) +h2v1_merged_upsample_565(j_decompress_ptr cinfo, _JSAMPIMAGE input_buf, + JDIMENSION in_row_group_ctr, _JSAMPARRAY output_buf) { if (is_big_endian()) h2v1_merged_upsample_565_be(cinfo, input_buf, in_row_group_ctr, @@ -487,8 +487,8 @@ h2v1_merged_upsample_565(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, METHODDEF(void) -h2v1_merged_upsample_565D(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, - JDIMENSION in_row_group_ctr, JSAMPARRAY output_buf) +h2v1_merged_upsample_565D(j_decompress_ptr cinfo, _JSAMPIMAGE input_buf, + JDIMENSION in_row_group_ctr, _JSAMPARRAY output_buf) { if (is_big_endian()) h2v1_merged_upsample_565D_be(cinfo, input_buf, in_row_group_ctr, @@ -500,8 +500,8 @@ h2v1_merged_upsample_565D(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, METHODDEF(void) -h2v2_merged_upsample_565(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, - JDIMENSION in_row_group_ctr, JSAMPARRAY output_buf) +h2v2_merged_upsample_565(j_decompress_ptr cinfo, _JSAMPIMAGE input_buf, + JDIMENSION in_row_group_ctr, _JSAMPARRAY output_buf) { if (is_big_endian()) h2v2_merged_upsample_565_be(cinfo, input_buf, in_row_group_ctr, @@ -513,8 +513,8 @@ h2v2_merged_upsample_565(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, METHODDEF(void) -h2v2_merged_upsample_565D(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, - JDIMENSION in_row_group_ctr, JSAMPARRAY output_buf) +h2v2_merged_upsample_565D(j_decompress_ptr cinfo, _JSAMPIMAGE input_buf, + JDIMENSION in_row_group_ctr, _JSAMPARRAY output_buf) { if (is_big_endian()) h2v2_merged_upsample_565D_be(cinfo, input_buf, in_row_group_ctr, @@ -534,10 +534,13 @@ h2v2_merged_upsample_565D(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, */ GLOBAL(void) -jinit_merged_upsampler(j_decompress_ptr cinfo) +_jinit_merged_upsampler(j_decompress_ptr cinfo) { my_merged_upsample_ptr upsample; + if (cinfo->data_precision != BITS_IN_JSAMPLE) + ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision); + upsample = (my_merged_upsample_ptr) (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE, sizeof(my_merged_upsampler)); @@ -548,10 +551,12 @@ jinit_merged_upsampler(j_decompress_ptr cinfo) upsample->out_row_width = cinfo->output_width * cinfo->out_color_components; if (cinfo->max_v_samp_factor == 2) { - upsample->pub.upsample = merged_2v_upsample; + upsample->pub._upsample = merged_2v_upsample; +#ifdef WITH_SIMD if (jsimd_can_h2v2_merged_upsample()) upsample->upmethod = jsimd_h2v2_merged_upsample; else +#endif upsample->upmethod = h2v2_merged_upsample; if (cinfo->out_color_space == JCS_RGB565) { if (cinfo->dither_mode != JDITHER_NONE) { @@ -561,14 +566,16 @@ jinit_merged_upsampler(j_decompress_ptr cinfo) } } /* Allocate a spare row buffer */ - upsample->spare_row = (JSAMPROW) + upsample->spare_row = (_JSAMPROW) (*cinfo->mem->alloc_large) ((j_common_ptr)cinfo, JPOOL_IMAGE, - (size_t)(upsample->out_row_width * sizeof(JSAMPLE))); + (size_t)(upsample->out_row_width * sizeof(_JSAMPLE))); } else { - upsample->pub.upsample = merged_1v_upsample; + upsample->pub._upsample = merged_1v_upsample; +#ifdef WITH_SIMD if (jsimd_can_h2v1_merged_upsample()) upsample->upmethod = jsimd_h2v1_merged_upsample; else +#endif upsample->upmethod = h2v1_merged_upsample; if (cinfo->out_color_space == JCS_RGB565) { if (cinfo->dither_mode != JDITHER_NONE) { diff --git a/src/3rdparty/libjpeg/src/jdmerge.h b/src/3rdparty/libjpeg/src/jdmerge.h index b583396b106..73cbd605495 100644 --- a/src/3rdparty/libjpeg/src/jdmerge.h +++ b/src/3rdparty/libjpeg/src/jdmerge.h @@ -4,13 +4,14 @@ * This file was part of the Independent JPEG Group's software: * Copyright (C) 1994-1996, Thomas G. Lane. * libjpeg-turbo Modifications: - * Copyright (C) 2020, D. R. Commander. + * Copyright (C) 2020, 2022, D. R. Commander. * For conditions of distribution and use, see the accompanying README.ijg * file. */ #define JPEG_INTERNALS #include "jpeglib.h" +#include "jsamplecomp.h" #ifdef UPSAMPLE_MERGING_SUPPORTED @@ -21,8 +22,8 @@ typedef struct { struct jpeg_upsampler pub; /* public fields */ /* Pointer to routine to do actual upsampling/conversion of one row group */ - void (*upmethod) (j_decompress_ptr cinfo, JSAMPIMAGE input_buf, - JDIMENSION in_row_group_ctr, JSAMPARRAY output_buf); + void (*upmethod) (j_decompress_ptr cinfo, _JSAMPIMAGE input_buf, + JDIMENSION in_row_group_ctr, _JSAMPARRAY output_buf); /* Private state for YCC->RGB conversion */ int *Cr_r_tab; /* => table for Cr to R conversion */ @@ -35,7 +36,7 @@ typedef struct { * application provides just a one-row buffer; we also use the spare * to discard the dummy last row if the image height is odd. */ - JSAMPROW spare_row; + _JSAMPROW spare_row; boolean spare_full; /* T if spare buffer is occupied */ JDIMENSION out_row_width; /* samples per output row */ diff --git a/src/3rdparty/libjpeg/src/jdmrg565.c b/src/3rdparty/libjpeg/src/jdmrg565.c index 980a4e216e4..0c719b912ce 100644 --- a/src/3rdparty/libjpeg/src/jdmrg565.c +++ b/src/3rdparty/libjpeg/src/jdmrg565.c @@ -5,7 +5,7 @@ * Copyright (C) 1994-1996, Thomas G. Lane. * libjpeg-turbo Modifications: * Copyright (C) 2013, Linaro Limited. - * Copyright (C) 2014-2015, 2018, 2020, D. R. Commander. + * Copyright (C) 2014-2015, 2018, 2020, 2022, D. R. Commander. * For conditions of distribution and use, see the accompanying README.ijg * file. * @@ -15,18 +15,19 @@ INLINE LOCAL(void) -h2v1_merged_upsample_565_internal(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, +h2v1_merged_upsample_565_internal(j_decompress_ptr cinfo, + _JSAMPIMAGE input_buf, JDIMENSION in_row_group_ctr, - JSAMPARRAY output_buf) + _JSAMPARRAY output_buf) { my_merged_upsample_ptr upsample = (my_merged_upsample_ptr)cinfo->upsample; register int y, cred, cgreen, cblue; int cb, cr; - register JSAMPROW outptr; - JSAMPROW inptr0, inptr1, inptr2; + register _JSAMPROW outptr; + _JSAMPROW inptr0, inptr1, inptr2; JDIMENSION col; /* copy these pointers into registers if possible */ - register JSAMPLE *range_limit = cinfo->sample_range_limit; + register _JSAMPLE *range_limit = (_JSAMPLE *)cinfo->sample_range_limit; int *Crrtab = upsample->Cr_r_tab; int *Cbbtab = upsample->Cb_b_tab; JLONG *Crgtab = upsample->Cr_g_tab; @@ -86,18 +87,18 @@ h2v1_merged_upsample_565_internal(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, INLINE LOCAL(void) h2v1_merged_upsample_565D_internal(j_decompress_ptr cinfo, - JSAMPIMAGE input_buf, + _JSAMPIMAGE input_buf, JDIMENSION in_row_group_ctr, - JSAMPARRAY output_buf) + _JSAMPARRAY output_buf) { my_merged_upsample_ptr upsample = (my_merged_upsample_ptr)cinfo->upsample; register int y, cred, cgreen, cblue; int cb, cr; - register JSAMPROW outptr; - JSAMPROW inptr0, inptr1, inptr2; + register _JSAMPROW outptr; + _JSAMPROW inptr0, inptr1, inptr2; JDIMENSION col; /* copy these pointers into registers if possible */ - register JSAMPLE *range_limit = cinfo->sample_range_limit; + register _JSAMPLE *range_limit = (_JSAMPLE *)cinfo->sample_range_limit; int *Crrtab = upsample->Cr_r_tab; int *Cbbtab = upsample->Cb_b_tab; JLONG *Crgtab = upsample->Cr_g_tab; @@ -159,18 +160,18 @@ h2v1_merged_upsample_565D_internal(j_decompress_ptr cinfo, INLINE LOCAL(void) -h2v2_merged_upsample_565_internal(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, +h2v2_merged_upsample_565_internal(j_decompress_ptr cinfo, _JSAMPIMAGE input_buf, JDIMENSION in_row_group_ctr, - JSAMPARRAY output_buf) + _JSAMPARRAY output_buf) { my_merged_upsample_ptr upsample = (my_merged_upsample_ptr)cinfo->upsample; register int y, cred, cgreen, cblue; int cb, cr; - register JSAMPROW outptr0, outptr1; - JSAMPROW inptr00, inptr01, inptr1, inptr2; + register _JSAMPROW outptr0, outptr1; + _JSAMPROW inptr00, inptr01, inptr1, inptr2; JDIMENSION col; /* copy these pointers into registers if possible */ - register JSAMPLE *range_limit = cinfo->sample_range_limit; + register _JSAMPLE *range_limit = (_JSAMPLE *)cinfo->sample_range_limit; int *Crrtab = upsample->Cr_r_tab; int *Cbbtab = upsample->Cb_b_tab; JLONG *Crgtab = upsample->Cr_g_tab; @@ -255,18 +256,18 @@ h2v2_merged_upsample_565_internal(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, INLINE LOCAL(void) h2v2_merged_upsample_565D_internal(j_decompress_ptr cinfo, - JSAMPIMAGE input_buf, + _JSAMPIMAGE input_buf, JDIMENSION in_row_group_ctr, - JSAMPARRAY output_buf) + _JSAMPARRAY output_buf) { my_merged_upsample_ptr upsample = (my_merged_upsample_ptr)cinfo->upsample; register int y, cred, cgreen, cblue; int cb, cr; - register JSAMPROW outptr0, outptr1; - JSAMPROW inptr00, inptr01, inptr1, inptr2; + register _JSAMPROW outptr0, outptr1; + _JSAMPROW inptr00, inptr01, inptr1, inptr2; JDIMENSION col; /* copy these pointers into registers if possible */ - register JSAMPLE *range_limit = cinfo->sample_range_limit; + register _JSAMPLE *range_limit = (_JSAMPLE *)cinfo->sample_range_limit; int *Crrtab = upsample->Cr_r_tab; int *Cbbtab = upsample->Cb_b_tab; JLONG *Crgtab = upsample->Cr_g_tab; diff --git a/src/3rdparty/libjpeg/src/jdmrgext.c b/src/3rdparty/libjpeg/src/jdmrgext.c index 038abc75d7e..8139e0a3ed6 100644 --- a/src/3rdparty/libjpeg/src/jdmrgext.c +++ b/src/3rdparty/libjpeg/src/jdmrgext.c @@ -4,7 +4,7 @@ * This file was part of the Independent JPEG Group's software: * Copyright (C) 1994-1996, Thomas G. Lane. * libjpeg-turbo Modifications: - * Copyright (C) 2011, 2015, 2020, 2023, D. R. Commander. + * Copyright (C) 2011, 2015, 2020, 2022-2023, D. R. Commander. * For conditions of distribution and use, see the accompanying README.ijg * file. * @@ -21,18 +21,18 @@ INLINE LOCAL(void) -h2v1_merged_upsample_internal(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, +h2v1_merged_upsample_internal(j_decompress_ptr cinfo, _JSAMPIMAGE input_buf, JDIMENSION in_row_group_ctr, - JSAMPARRAY output_buf) + _JSAMPARRAY output_buf) { my_merged_upsample_ptr upsample = (my_merged_upsample_ptr)cinfo->upsample; register int y, cred, cgreen, cblue; int cb, cr; - register JSAMPROW outptr; - JSAMPROW inptr0, inptr1, inptr2; + register _JSAMPROW outptr; + _JSAMPROW inptr0, inptr1, inptr2; JDIMENSION col; /* copy these pointers into registers if possible */ - register JSAMPLE *range_limit = cinfo->sample_range_limit; + register _JSAMPLE *range_limit = (_JSAMPLE *)cinfo->sample_range_limit; int *Crrtab = upsample->Cr_r_tab; int *Cbbtab = upsample->Cb_b_tab; JLONG *Crgtab = upsample->Cr_g_tab; @@ -57,7 +57,7 @@ h2v1_merged_upsample_internal(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, outptr[RGB_GREEN] = range_limit[y + cgreen]; outptr[RGB_BLUE] = range_limit[y + cblue]; #ifdef RGB_ALPHA - outptr[RGB_ALPHA] = MAXJSAMPLE; + outptr[RGB_ALPHA] = _MAXJSAMPLE; #endif outptr += RGB_PIXELSIZE; y = *inptr0++; @@ -65,7 +65,7 @@ h2v1_merged_upsample_internal(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, outptr[RGB_GREEN] = range_limit[y + cgreen]; outptr[RGB_BLUE] = range_limit[y + cblue]; #ifdef RGB_ALPHA - outptr[RGB_ALPHA] = MAXJSAMPLE; + outptr[RGB_ALPHA] = _MAXJSAMPLE; #endif outptr += RGB_PIXELSIZE; } @@ -81,7 +81,7 @@ h2v1_merged_upsample_internal(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, outptr[RGB_GREEN] = range_limit[y + cgreen]; outptr[RGB_BLUE] = range_limit[y + cblue]; #ifdef RGB_ALPHA - outptr[RGB_ALPHA] = MAXJSAMPLE; + outptr[RGB_ALPHA] = _MAXJSAMPLE; #endif } } @@ -93,18 +93,18 @@ h2v1_merged_upsample_internal(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, INLINE LOCAL(void) -h2v2_merged_upsample_internal(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, +h2v2_merged_upsample_internal(j_decompress_ptr cinfo, _JSAMPIMAGE input_buf, JDIMENSION in_row_group_ctr, - JSAMPARRAY output_buf) + _JSAMPARRAY output_buf) { my_merged_upsample_ptr upsample = (my_merged_upsample_ptr)cinfo->upsample; register int y, cred, cgreen, cblue; int cb, cr; - register JSAMPROW outptr0, outptr1; - JSAMPROW inptr00, inptr01, inptr1, inptr2; + register _JSAMPROW outptr0, outptr1; + _JSAMPROW inptr00, inptr01, inptr1, inptr2; JDIMENSION col; /* copy these pointers into registers if possible */ - register JSAMPLE *range_limit = cinfo->sample_range_limit; + register _JSAMPLE *range_limit = (_JSAMPLE *)cinfo->sample_range_limit; int *Crrtab = upsample->Cr_r_tab; int *Cbbtab = upsample->Cb_b_tab; JLONG *Crgtab = upsample->Cr_g_tab; @@ -131,7 +131,7 @@ h2v2_merged_upsample_internal(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, outptr0[RGB_GREEN] = range_limit[y + cgreen]; outptr0[RGB_BLUE] = range_limit[y + cblue]; #ifdef RGB_ALPHA - outptr0[RGB_ALPHA] = MAXJSAMPLE; + outptr0[RGB_ALPHA] = _MAXJSAMPLE; #endif outptr0 += RGB_PIXELSIZE; y = *inptr00++; @@ -139,7 +139,7 @@ h2v2_merged_upsample_internal(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, outptr0[RGB_GREEN] = range_limit[y + cgreen]; outptr0[RGB_BLUE] = range_limit[y + cblue]; #ifdef RGB_ALPHA - outptr0[RGB_ALPHA] = MAXJSAMPLE; + outptr0[RGB_ALPHA] = _MAXJSAMPLE; #endif outptr0 += RGB_PIXELSIZE; y = *inptr01++; @@ -147,7 +147,7 @@ h2v2_merged_upsample_internal(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, outptr1[RGB_GREEN] = range_limit[y + cgreen]; outptr1[RGB_BLUE] = range_limit[y + cblue]; #ifdef RGB_ALPHA - outptr1[RGB_ALPHA] = MAXJSAMPLE; + outptr1[RGB_ALPHA] = _MAXJSAMPLE; #endif outptr1 += RGB_PIXELSIZE; y = *inptr01++; @@ -155,7 +155,7 @@ h2v2_merged_upsample_internal(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, outptr1[RGB_GREEN] = range_limit[y + cgreen]; outptr1[RGB_BLUE] = range_limit[y + cblue]; #ifdef RGB_ALPHA - outptr1[RGB_ALPHA] = MAXJSAMPLE; + outptr1[RGB_ALPHA] = _MAXJSAMPLE; #endif outptr1 += RGB_PIXELSIZE; } @@ -171,14 +171,14 @@ h2v2_merged_upsample_internal(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, outptr0[RGB_GREEN] = range_limit[y + cgreen]; outptr0[RGB_BLUE] = range_limit[y + cblue]; #ifdef RGB_ALPHA - outptr0[RGB_ALPHA] = MAXJSAMPLE; + outptr0[RGB_ALPHA] = _MAXJSAMPLE; #endif y = *inptr01; outptr1[RGB_RED] = range_limit[y + cred]; outptr1[RGB_GREEN] = range_limit[y + cgreen]; outptr1[RGB_BLUE] = range_limit[y + cblue]; #ifdef RGB_ALPHA - outptr1[RGB_ALPHA] = MAXJSAMPLE; + outptr1[RGB_ALPHA] = _MAXJSAMPLE; #endif } } diff --git a/src/3rdparty/libjpeg/src/jdphuff.c b/src/3rdparty/libjpeg/src/jdphuff.c index 9680ebcbd06..bf97333a34c 100644 --- a/src/3rdparty/libjpeg/src/jdphuff.c +++ b/src/3rdparty/libjpeg/src/jdphuff.c @@ -3,6 +3,8 @@ * * This file was part of the Independent JPEG Group's software: * Copyright (C) 1995-1997, Thomas G. Lane. + * Lossless JPEG Modifications: + * Copyright (C) 1999, Ken Murchison. * libjpeg-turbo Modifications: * Copyright (C) 2015-2016, 2018-2022, D. R. Commander. * For conditions of distribution and use, see the accompanying README.ijg @@ -23,7 +25,7 @@ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" -#include "jdhuff.h" /* Declarations shared with jdhuff.c */ +#include "jdhuff.h" /* Declarations shared with jd*huff.c */ #include diff --git a/src/3rdparty/libjpeg/src/jdpostct.c b/src/3rdparty/libjpeg/src/jdpostct.c index 6a2cf5c1b31..d38495f5f31 100644 --- a/src/3rdparty/libjpeg/src/jdpostct.c +++ b/src/3rdparty/libjpeg/src/jdpostct.c @@ -3,8 +3,8 @@ * * This file was part of the Independent JPEG Group's software: * Copyright (C) 1994-1996, Thomas G. Lane. - * It was modified by The libjpeg-turbo Project to include only code relevant - * to libjpeg-turbo. + * libjpeg-turbo Modifications: + * Copyright (C) 2022-2023, D. R. Commander. * For conditions of distribution and use, see the accompanying README.ijg * file. * @@ -22,8 +22,11 @@ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" +#include "jsamplecomp.h" +#if BITS_IN_JSAMPLE != 16 || defined(D_LOSSLESS_SUPPORTED) + /* Private buffer controller object */ typedef struct { @@ -35,7 +38,7 @@ typedef struct { * for one-pass operation, a strip buffer is sufficient. */ jvirt_sarray_ptr whole_image; /* virtual array, or NULL if one-pass */ - JSAMPARRAY buffer; /* strip buffer, or current strip of virtual */ + _JSAMPARRAY buffer; /* strip buffer, or current strip of virtual */ JDIMENSION strip_height; /* buffer size in rows */ /* for two-pass mode only: */ JDIMENSION starting_row; /* row # of first row in current strip */ @@ -46,26 +49,28 @@ typedef my_post_controller *my_post_ptr; /* Forward declarations */ +#if BITS_IN_JSAMPLE != 16 METHODDEF(void) post_process_1pass(j_decompress_ptr cinfo, - JSAMPIMAGE input_buf, + _JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, JDIMENSION in_row_groups_avail, - JSAMPARRAY output_buf, + _JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail); -#ifdef QUANT_2PASS_SUPPORTED +#endif +#if defined(QUANT_2PASS_SUPPORTED) && BITS_IN_JSAMPLE != 16 METHODDEF(void) post_process_prepass(j_decompress_ptr cinfo, - JSAMPIMAGE input_buf, + _JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, JDIMENSION in_row_groups_avail, - JSAMPARRAY output_buf, + _JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail); METHODDEF(void) post_process_2pass(j_decompress_ptr cinfo, - JSAMPIMAGE input_buf, + _JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, JDIMENSION in_row_groups_avail, - JSAMPARRAY output_buf, + _JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail); #endif @@ -82,39 +87,42 @@ start_pass_dpost(j_decompress_ptr cinfo, J_BUF_MODE pass_mode) switch (pass_mode) { case JBUF_PASS_THRU: +#if BITS_IN_JSAMPLE != 16 if (cinfo->quantize_colors) { /* Single-pass processing with color quantization. */ - post->pub.post_process_data = post_process_1pass; + post->pub._post_process_data = post_process_1pass; /* We could be doing buffered-image output before starting a 2-pass * color quantization; in that case, jinit_d_post_controller did not * allocate a strip buffer. Use the virtual-array buffer as workspace. */ if (post->buffer == NULL) { - post->buffer = (*cinfo->mem->access_virt_sarray) + post->buffer = (_JSAMPARRAY)(*cinfo->mem->access_virt_sarray) ((j_common_ptr)cinfo, post->whole_image, (JDIMENSION)0, post->strip_height, TRUE); } - } else { + } else +#endif + { /* For single-pass processing without color quantization, * I have no work to do; just call the upsampler directly. */ - post->pub.post_process_data = cinfo->upsample->upsample; + post->pub._post_process_data = cinfo->upsample->_upsample; } break; -#ifdef QUANT_2PASS_SUPPORTED +#if defined(QUANT_2PASS_SUPPORTED) && BITS_IN_JSAMPLE != 16 case JBUF_SAVE_AND_PASS: /* First pass of 2-pass quantization */ if (post->whole_image == NULL) ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); - post->pub.post_process_data = post_process_prepass; + post->pub._post_process_data = post_process_prepass; break; case JBUF_CRANK_DEST: /* Second pass of 2-pass quantization */ if (post->whole_image == NULL) ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); - post->pub.post_process_data = post_process_2pass; + post->pub._post_process_data = post_process_2pass; break; -#endif /* QUANT_2PASS_SUPPORTED */ +#endif /* defined(QUANT_2PASS_SUPPORTED) && BITS_IN_JSAMPLE != 16 */ default: ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); break; @@ -128,10 +136,12 @@ start_pass_dpost(j_decompress_ptr cinfo, J_BUF_MODE pass_mode) * This is used for color precision reduction as well as one-pass quantization. */ +#if BITS_IN_JSAMPLE != 16 + METHODDEF(void) -post_process_1pass(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, +post_process_1pass(j_decompress_ptr cinfo, _JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, - JDIMENSION in_row_groups_avail, JSAMPARRAY output_buf, + JDIMENSION in_row_groups_avail, _JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail) { my_post_ptr post = (my_post_ptr)cinfo->post; @@ -143,27 +153,29 @@ post_process_1pass(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, if (max_rows > post->strip_height) max_rows = post->strip_height; num_rows = 0; - (*cinfo->upsample->upsample) (cinfo, input_buf, in_row_group_ctr, - in_row_groups_avail, post->buffer, &num_rows, - max_rows); + (*cinfo->upsample->_upsample) (cinfo, input_buf, in_row_group_ctr, + in_row_groups_avail, post->buffer, &num_rows, + max_rows); /* Quantize and emit data. */ - (*cinfo->cquantize->color_quantize) (cinfo, post->buffer, - output_buf + *out_row_ctr, - (int)num_rows); + (*cinfo->cquantize->_color_quantize) (cinfo, post->buffer, + output_buf + *out_row_ctr, + (int)num_rows); *out_row_ctr += num_rows; } +#endif -#ifdef QUANT_2PASS_SUPPORTED + +#if defined(QUANT_2PASS_SUPPORTED) && BITS_IN_JSAMPLE != 16 /* * Process some data in the first pass of 2-pass quantization. */ METHODDEF(void) -post_process_prepass(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, +post_process_prepass(j_decompress_ptr cinfo, _JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, - JDIMENSION in_row_groups_avail, JSAMPARRAY output_buf, + JDIMENSION in_row_groups_avail, _JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail) { my_post_ptr post = (my_post_ptr)cinfo->post; @@ -171,23 +183,23 @@ post_process_prepass(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, /* Reposition virtual buffer if at start of strip. */ if (post->next_row == 0) { - post->buffer = (*cinfo->mem->access_virt_sarray) + post->buffer = (_JSAMPARRAY)(*cinfo->mem->access_virt_sarray) ((j_common_ptr)cinfo, post->whole_image, post->starting_row, post->strip_height, TRUE); } /* Upsample some data (up to a strip height's worth). */ old_next_row = post->next_row; - (*cinfo->upsample->upsample) (cinfo, input_buf, in_row_group_ctr, - in_row_groups_avail, post->buffer, - &post->next_row, post->strip_height); + (*cinfo->upsample->_upsample) (cinfo, input_buf, in_row_group_ctr, + in_row_groups_avail, post->buffer, + &post->next_row, post->strip_height); /* Allow quantizer to scan new data. No data is emitted, */ /* but we advance out_row_ctr so outer loop can tell when we're done. */ if (post->next_row > old_next_row) { num_rows = post->next_row - old_next_row; - (*cinfo->cquantize->color_quantize) (cinfo, post->buffer + old_next_row, - (JSAMPARRAY)NULL, (int)num_rows); + (*cinfo->cquantize->_color_quantize) (cinfo, post->buffer + old_next_row, + (_JSAMPARRAY)NULL, (int)num_rows); *out_row_ctr += num_rows; } @@ -204,9 +216,9 @@ post_process_prepass(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, */ METHODDEF(void) -post_process_2pass(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, +post_process_2pass(j_decompress_ptr cinfo, _JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, - JDIMENSION in_row_groups_avail, JSAMPARRAY output_buf, + JDIMENSION in_row_groups_avail, _JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail) { my_post_ptr post = (my_post_ptr)cinfo->post; @@ -214,7 +226,7 @@ post_process_2pass(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, /* Reposition virtual buffer if at start of strip. */ if (post->next_row == 0) { - post->buffer = (*cinfo->mem->access_virt_sarray) + post->buffer = (_JSAMPARRAY)(*cinfo->mem->access_virt_sarray) ((j_common_ptr)cinfo, post->whole_image, post->starting_row, post->strip_height, FALSE); } @@ -230,9 +242,9 @@ post_process_2pass(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, num_rows = max_rows; /* Quantize and emit data. */ - (*cinfo->cquantize->color_quantize) (cinfo, post->buffer + post->next_row, - output_buf + *out_row_ctr, - (int)num_rows); + (*cinfo->cquantize->_color_quantize) (cinfo, post->buffer + post->next_row, + output_buf + *out_row_ctr, + (int)num_rows); *out_row_ctr += num_rows; /* Advance if we filled the strip. */ @@ -243,7 +255,7 @@ post_process_2pass(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, } } -#endif /* QUANT_2PASS_SUPPORTED */ +#endif /* defined(QUANT_2PASS_SUPPORTED) && BITS_IN_JSAMPLE != 16 */ /* @@ -251,10 +263,13 @@ post_process_2pass(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, */ GLOBAL(void) -jinit_d_post_controller(j_decompress_ptr cinfo, boolean need_full_buffer) +_jinit_d_post_controller(j_decompress_ptr cinfo, boolean need_full_buffer) { my_post_ptr post; + if (cinfo->data_precision != BITS_IN_JSAMPLE) + ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision); + post = (my_post_ptr) (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE, sizeof(my_post_controller)); @@ -265,6 +280,7 @@ jinit_d_post_controller(j_decompress_ptr cinfo, boolean need_full_buffer) /* Create the quantization buffer, if needed */ if (cinfo->quantize_colors) { +#if BITS_IN_JSAMPLE != 16 /* The buffer strip height is max_v_samp_factor, which is typically * an efficient number of rows for upsampling to return. * (In the presence of output rescaling, we might want to be smarter?) @@ -285,10 +301,15 @@ jinit_d_post_controller(j_decompress_ptr cinfo, boolean need_full_buffer) #endif /* QUANT_2PASS_SUPPORTED */ } else { /* One-pass color quantization: just make a strip buffer. */ - post->buffer = (*cinfo->mem->alloc_sarray) + post->buffer = (_JSAMPARRAY)(*cinfo->mem->alloc_sarray) ((j_common_ptr)cinfo, JPOOL_IMAGE, cinfo->output_width * cinfo->out_color_components, post->strip_height); } +#else + ERREXIT(cinfo, JERR_NOTIMPL); +#endif } } + +#endif /* BITS_IN_JSAMPLE != 16 || defined(D_LOSSLESS_SUPPORTED) */ diff --git a/src/3rdparty/libjpeg/src/jdsample.c b/src/3rdparty/libjpeg/src/jdsample.c index eaad72a0308..cc8015c97d7 100644 --- a/src/3rdparty/libjpeg/src/jdsample.c +++ b/src/3rdparty/libjpeg/src/jdsample.c @@ -5,7 +5,7 @@ * Copyright (C) 1991-1996, Thomas G. Lane. * libjpeg-turbo Modifications: * Copyright 2009 Pierre Ossman for Cendio AB - * Copyright (C) 2010, 2015-2016, D. R. Commander. + * Copyright (C) 2010, 2015-2016, 2022, D. R. Commander. * Copyright (C) 2014, MIPS Technologies, Inc., California. * Copyright (C) 2015, Google, Inc. * Copyright (C) 2019-2020, Arm Limited. @@ -28,10 +28,12 @@ #include "jinclude.h" #include "jdsample.h" #include "jsimd.h" -#include "jpegcomp.h" +#include "jpegapicomp.h" +#if BITS_IN_JSAMPLE != 16 || defined(D_LOSSLESS_SUPPORTED) + /* * Initialize for an upsampling pass. */ @@ -57,9 +59,9 @@ start_pass_upsample(j_decompress_ptr cinfo) */ METHODDEF(void) -sep_upsample(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, +sep_upsample(j_decompress_ptr cinfo, _JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, JDIMENSION in_row_groups_avail, - JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, + _JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail) { my_upsample_ptr upsample = (my_upsample_ptr)cinfo->upsample; @@ -95,9 +97,10 @@ sep_upsample(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, if (num_rows > out_rows_avail) num_rows = out_rows_avail; - (*cinfo->cconvert->color_convert) (cinfo, upsample->color_buf, - (JDIMENSION)upsample->next_row_out, - output_buf + *out_row_ctr, (int)num_rows); + (*cinfo->cconvert->_color_convert) (cinfo, upsample->color_buf, + (JDIMENSION)upsample->next_row_out, + output_buf + *out_row_ctr, + (int)num_rows); /* Adjust counts */ *out_row_ctr += num_rows; @@ -124,7 +127,7 @@ sep_upsample(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, METHODDEF(void) fullsize_upsample(j_decompress_ptr cinfo, jpeg_component_info *compptr, - JSAMPARRAY input_data, JSAMPARRAY *output_data_ptr) + _JSAMPARRAY input_data, _JSAMPARRAY *output_data_ptr) { *output_data_ptr = input_data; } @@ -137,7 +140,7 @@ fullsize_upsample(j_decompress_ptr cinfo, jpeg_component_info *compptr, METHODDEF(void) noop_upsample(j_decompress_ptr cinfo, jpeg_component_info *compptr, - JSAMPARRAY input_data, JSAMPARRAY *output_data_ptr) + _JSAMPARRAY input_data, _JSAMPARRAY *output_data_ptr) { *output_data_ptr = NULL; /* safety check */ } @@ -156,14 +159,14 @@ noop_upsample(j_decompress_ptr cinfo, jpeg_component_info *compptr, METHODDEF(void) int_upsample(j_decompress_ptr cinfo, jpeg_component_info *compptr, - JSAMPARRAY input_data, JSAMPARRAY *output_data_ptr) + _JSAMPARRAY input_data, _JSAMPARRAY *output_data_ptr) { my_upsample_ptr upsample = (my_upsample_ptr)cinfo->upsample; - JSAMPARRAY output_data = *output_data_ptr; - register JSAMPROW inptr, outptr; - register JSAMPLE invalue; + _JSAMPARRAY output_data = *output_data_ptr; + register _JSAMPROW inptr, outptr; + register _JSAMPLE invalue; register int h; - JSAMPROW outend; + _JSAMPROW outend; int h_expand, v_expand; int inrow, outrow; @@ -184,8 +187,8 @@ int_upsample(j_decompress_ptr cinfo, jpeg_component_info *compptr, } /* Generate any additional output rows by duplicating the first one */ if (v_expand > 1) { - jcopy_sample_rows(output_data, outrow, output_data, outrow + 1, - v_expand - 1, cinfo->output_width); + _jcopy_sample_rows(output_data, outrow, output_data, outrow + 1, + v_expand - 1, cinfo->output_width); } inrow++; outrow += v_expand; @@ -200,12 +203,12 @@ int_upsample(j_decompress_ptr cinfo, jpeg_component_info *compptr, METHODDEF(void) h2v1_upsample(j_decompress_ptr cinfo, jpeg_component_info *compptr, - JSAMPARRAY input_data, JSAMPARRAY *output_data_ptr) + _JSAMPARRAY input_data, _JSAMPARRAY *output_data_ptr) { - JSAMPARRAY output_data = *output_data_ptr; - register JSAMPROW inptr, outptr; - register JSAMPLE invalue; - JSAMPROW outend; + _JSAMPARRAY output_data = *output_data_ptr; + register _JSAMPROW inptr, outptr; + register _JSAMPLE invalue; + _JSAMPROW outend; int inrow; for (inrow = 0; inrow < cinfo->max_v_samp_factor; inrow++) { @@ -228,12 +231,12 @@ h2v1_upsample(j_decompress_ptr cinfo, jpeg_component_info *compptr, METHODDEF(void) h2v2_upsample(j_decompress_ptr cinfo, jpeg_component_info *compptr, - JSAMPARRAY input_data, JSAMPARRAY *output_data_ptr) + _JSAMPARRAY input_data, _JSAMPARRAY *output_data_ptr) { - JSAMPARRAY output_data = *output_data_ptr; - register JSAMPROW inptr, outptr; - register JSAMPLE invalue; - JSAMPROW outend; + _JSAMPARRAY output_data = *output_data_ptr; + register _JSAMPROW inptr, outptr; + register _JSAMPLE invalue; + _JSAMPROW outend; int inrow, outrow; inrow = outrow = 0; @@ -246,8 +249,8 @@ h2v2_upsample(j_decompress_ptr cinfo, jpeg_component_info *compptr, *outptr++ = invalue; *outptr++ = invalue; } - jcopy_sample_rows(output_data, outrow, output_data, outrow + 1, 1, - cinfo->output_width); + _jcopy_sample_rows(output_data, outrow, output_data, outrow + 1, 1, + cinfo->output_width); inrow++; outrow += 2; } @@ -271,10 +274,10 @@ h2v2_upsample(j_decompress_ptr cinfo, jpeg_component_info *compptr, METHODDEF(void) h2v1_fancy_upsample(j_decompress_ptr cinfo, jpeg_component_info *compptr, - JSAMPARRAY input_data, JSAMPARRAY *output_data_ptr) + _JSAMPARRAY input_data, _JSAMPARRAY *output_data_ptr) { - JSAMPARRAY output_data = *output_data_ptr; - register JSAMPROW inptr, outptr; + _JSAMPARRAY output_data = *output_data_ptr; + register _JSAMPROW inptr, outptr; register int invalue; register JDIMENSION colctr; int inrow; @@ -284,20 +287,20 @@ h2v1_fancy_upsample(j_decompress_ptr cinfo, jpeg_component_info *compptr, outptr = output_data[inrow]; /* Special case for first column */ invalue = *inptr++; - *outptr++ = (JSAMPLE)invalue; - *outptr++ = (JSAMPLE)((invalue * 3 + inptr[0] + 2) >> 2); + *outptr++ = (_JSAMPLE)invalue; + *outptr++ = (_JSAMPLE)((invalue * 3 + inptr[0] + 2) >> 2); for (colctr = compptr->downsampled_width - 2; colctr > 0; colctr--) { /* General case: 3/4 * nearer pixel + 1/4 * further pixel */ invalue = (*inptr++) * 3; - *outptr++ = (JSAMPLE)((invalue + inptr[-2] + 1) >> 2); - *outptr++ = (JSAMPLE)((invalue + inptr[0] + 2) >> 2); + *outptr++ = (_JSAMPLE)((invalue + inptr[-2] + 1) >> 2); + *outptr++ = (_JSAMPLE)((invalue + inptr[0] + 2) >> 2); } /* Special case for last column */ invalue = *inptr; - *outptr++ = (JSAMPLE)((invalue * 3 + inptr[-1] + 1) >> 2); - *outptr++ = (JSAMPLE)invalue; + *outptr++ = (_JSAMPLE)((invalue * 3 + inptr[-1] + 1) >> 2); + *outptr++ = (_JSAMPLE)invalue; } } @@ -311,10 +314,10 @@ h2v1_fancy_upsample(j_decompress_ptr cinfo, jpeg_component_info *compptr, METHODDEF(void) h1v2_fancy_upsample(j_decompress_ptr cinfo, jpeg_component_info *compptr, - JSAMPARRAY input_data, JSAMPARRAY *output_data_ptr) + _JSAMPARRAY input_data, _JSAMPARRAY *output_data_ptr) { - JSAMPARRAY output_data = *output_data_ptr; - JSAMPROW inptr0, inptr1, outptr; + _JSAMPARRAY output_data = *output_data_ptr; + _JSAMPROW inptr0, inptr1, outptr; #if BITS_IN_JSAMPLE == 8 int thiscolsum, bias; #else @@ -339,7 +342,7 @@ h1v2_fancy_upsample(j_decompress_ptr cinfo, jpeg_component_info *compptr, for (colctr = 0; colctr < compptr->downsampled_width; colctr++) { thiscolsum = (*inptr0++) * 3 + (*inptr1++); - *outptr++ = (JSAMPLE)((thiscolsum + bias) >> 2); + *outptr++ = (_JSAMPLE)((thiscolsum + bias) >> 2); } } inrow++; @@ -357,10 +360,10 @@ h1v2_fancy_upsample(j_decompress_ptr cinfo, jpeg_component_info *compptr, METHODDEF(void) h2v2_fancy_upsample(j_decompress_ptr cinfo, jpeg_component_info *compptr, - JSAMPARRAY input_data, JSAMPARRAY *output_data_ptr) + _JSAMPARRAY input_data, _JSAMPARRAY *output_data_ptr) { - JSAMPARRAY output_data = *output_data_ptr; - register JSAMPROW inptr0, inptr1, outptr; + _JSAMPARRAY output_data = *output_data_ptr; + register _JSAMPROW inptr0, inptr1, outptr; #if BITS_IN_JSAMPLE == 8 register int thiscolsum, lastcolsum, nextcolsum; #else @@ -383,22 +386,22 @@ h2v2_fancy_upsample(j_decompress_ptr cinfo, jpeg_component_info *compptr, /* Special case for first column */ thiscolsum = (*inptr0++) * 3 + (*inptr1++); nextcolsum = (*inptr0++) * 3 + (*inptr1++); - *outptr++ = (JSAMPLE)((thiscolsum * 4 + 8) >> 4); - *outptr++ = (JSAMPLE)((thiscolsum * 3 + nextcolsum + 7) >> 4); + *outptr++ = (_JSAMPLE)((thiscolsum * 4 + 8) >> 4); + *outptr++ = (_JSAMPLE)((thiscolsum * 3 + nextcolsum + 7) >> 4); lastcolsum = thiscolsum; thiscolsum = nextcolsum; for (colctr = compptr->downsampled_width - 2; colctr > 0; colctr--) { /* General case: 3/4 * nearer pixel + 1/4 * further pixel in each */ /* dimension, thus 9/16, 3/16, 3/16, 1/16 overall */ nextcolsum = (*inptr0++) * 3 + (*inptr1++); - *outptr++ = (JSAMPLE)((thiscolsum * 3 + lastcolsum + 8) >> 4); - *outptr++ = (JSAMPLE)((thiscolsum * 3 + nextcolsum + 7) >> 4); + *outptr++ = (_JSAMPLE)((thiscolsum * 3 + lastcolsum + 8) >> 4); + *outptr++ = (_JSAMPLE)((thiscolsum * 3 + nextcolsum + 7) >> 4); lastcolsum = thiscolsum; thiscolsum = nextcolsum; } /* Special case for last column */ - *outptr++ = (JSAMPLE)((thiscolsum * 3 + lastcolsum + 8) >> 4); - *outptr++ = (JSAMPLE)((thiscolsum * 4 + 7) >> 4); + *outptr++ = (_JSAMPLE)((thiscolsum * 3 + lastcolsum + 8) >> 4); + *outptr++ = (_JSAMPLE)((thiscolsum * 4 + 7) >> 4); } inrow++; } @@ -410,7 +413,7 @@ h2v2_fancy_upsample(j_decompress_ptr cinfo, jpeg_component_info *compptr, */ GLOBAL(void) -jinit_upsampler(j_decompress_ptr cinfo) +_jinit_upsampler(j_decompress_ptr cinfo) { my_upsample_ptr upsample; int ci; @@ -418,13 +421,16 @@ jinit_upsampler(j_decompress_ptr cinfo) boolean need_buffer, do_fancy; int h_in_group, v_in_group, h_out_group, v_out_group; + if (cinfo->data_precision != BITS_IN_JSAMPLE) + ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision); + if (!cinfo->master->jinit_upsampler_no_alloc) { upsample = (my_upsample_ptr) (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE, sizeof(my_upsampler)); cinfo->upsample = (struct jpeg_upsampler *)upsample; upsample->pub.start_pass = start_pass_upsample; - upsample->pub.upsample = sep_upsample; + upsample->pub._upsample = sep_upsample; upsample->pub.need_context_rows = FALSE; /* until we find out differently */ } else upsample = (my_upsample_ptr)cinfo->upsample; @@ -464,21 +470,25 @@ jinit_upsampler(j_decompress_ptr cinfo) } else if (h_in_group * 2 == h_out_group && v_in_group == v_out_group) { /* Special cases for 2h1v upsampling */ if (do_fancy && compptr->downsampled_width > 2) { +#ifdef WITH_SIMD if (jsimd_can_h2v1_fancy_upsample()) upsample->methods[ci] = jsimd_h2v1_fancy_upsample; else +#endif upsample->methods[ci] = h2v1_fancy_upsample; } else { +#ifdef WITH_SIMD if (jsimd_can_h2v1_upsample()) upsample->methods[ci] = jsimd_h2v1_upsample; else +#endif upsample->methods[ci] = h2v1_upsample; } } else if (h_in_group == h_out_group && v_in_group * 2 == v_out_group && do_fancy) { /* Non-fancy upsampling is handled by the generic method */ -#if defined(__arm__) || defined(__aarch64__) || \ - defined(_M_ARM) || defined(_M_ARM64) +#if defined(WITH_SIMD) && (defined(__arm__) || defined(__aarch64__) || \ + defined(_M_ARM) || defined(_M_ARM64)) if (jsimd_can_h1v2_fancy_upsample()) upsample->methods[ci] = jsimd_h1v2_fancy_upsample; else @@ -489,21 +499,25 @@ jinit_upsampler(j_decompress_ptr cinfo) v_in_group * 2 == v_out_group) { /* Special cases for 2h2v upsampling */ if (do_fancy && compptr->downsampled_width > 2) { +#ifdef WITH_SIMD if (jsimd_can_h2v2_fancy_upsample()) upsample->methods[ci] = jsimd_h2v2_fancy_upsample; else +#endif upsample->methods[ci] = h2v2_fancy_upsample; upsample->pub.need_context_rows = TRUE; } else { +#ifdef WITH_SIMD if (jsimd_can_h2v2_upsample()) upsample->methods[ci] = jsimd_h2v2_upsample; else +#endif upsample->methods[ci] = h2v2_upsample; } } else if ((h_out_group % h_in_group) == 0 && (v_out_group % v_in_group) == 0) { /* Generic integral-factors upsampling method */ -#if defined(__mips__) +#if defined(WITH_SIMD) && defined(__mips__) if (jsimd_can_int_upsample()) upsample->methods[ci] = jsimd_int_upsample; else @@ -514,7 +528,7 @@ jinit_upsampler(j_decompress_ptr cinfo) } else ERREXIT(cinfo, JERR_FRACT_SAMPLE_NOTIMPL); if (need_buffer && !cinfo->master->jinit_upsampler_no_alloc) { - upsample->color_buf[ci] = (*cinfo->mem->alloc_sarray) + upsample->color_buf[ci] = (_JSAMPARRAY)(*cinfo->mem->alloc_sarray) ((j_common_ptr)cinfo, JPOOL_IMAGE, (JDIMENSION)jround_up((long)cinfo->output_width, (long)cinfo->max_h_samp_factor), @@ -522,3 +536,5 @@ jinit_upsampler(j_decompress_ptr cinfo) } } } + +#endif /* BITS_IN_JSAMPLE != 16 || defined(D_LOSSLESS_SUPPORTED) */ diff --git a/src/3rdparty/libjpeg/src/jdsample.h b/src/3rdparty/libjpeg/src/jdsample.h index a6bf08a032a..a8a92980940 100644 --- a/src/3rdparty/libjpeg/src/jdsample.h +++ b/src/3rdparty/libjpeg/src/jdsample.h @@ -3,19 +3,22 @@ * * This file was part of the Independent JPEG Group's software: * Copyright (C) 1991-1996, Thomas G. Lane. + * libjpeg-turbo Modifications: + * Copyright (C) 2022, D. R. Commander. * For conditions of distribution and use, see the accompanying README.ijg * file. */ #define JPEG_INTERNALS #include "jpeglib.h" +#include "jsamplecomp.h" /* Pointer to routine to upsample a single component */ typedef void (*upsample1_ptr) (j_decompress_ptr cinfo, jpeg_component_info *compptr, - JSAMPARRAY input_data, - JSAMPARRAY *output_data_ptr); + _JSAMPARRAY input_data, + _JSAMPARRAY *output_data_ptr); /* Private subobject */ @@ -29,7 +32,7 @@ typedef struct { * ie do not need rescaling. The corresponding entry of color_buf[] is * simply set to point to the input data array, thereby avoiding copying. */ - JSAMPARRAY color_buf[MAX_COMPONENTS]; + _JSAMPARRAY color_buf[MAX_COMPONENTS]; /* Per-component upsampling method pointers */ upsample1_ptr methods[MAX_COMPONENTS]; diff --git a/src/3rdparty/libjpeg/src/jdtrans.c b/src/3rdparty/libjpeg/src/jdtrans.c index d7ec4b83b3a..719813f6767 100644 --- a/src/3rdparty/libjpeg/src/jdtrans.c +++ b/src/3rdparty/libjpeg/src/jdtrans.c @@ -4,7 +4,7 @@ * This file was part of the Independent JPEG Group's software: * Copyright (C) 1995-1997, Thomas G. Lane. * libjpeg-turbo Modifications: - * Copyright (C) 2020, D. R. Commander. + * Copyright (C) 2020, 2022, D. R. Commander. * For conditions of distribution and use, see the accompanying README.ijg * file. * @@ -16,7 +16,7 @@ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" -#include "jpegcomp.h" +#include "jpegapicomp.h" /* Forward declarations */ @@ -48,6 +48,9 @@ LOCAL(void) transdecode_master_selection(j_decompress_ptr cinfo); GLOBAL(jvirt_barray_ptr *) jpeg_read_coefficients(j_decompress_ptr cinfo) { + if (cinfo->master->lossless) + ERREXIT(cinfo, JERR_NOTIMPL); + if (cinfo->global_state == DSTATE_READY) { /* First call: initialize active modules */ transdecode_master_selection(cinfo); @@ -127,7 +130,10 @@ transdecode_master_selection(j_decompress_ptr cinfo) } /* Always get a full-image coefficient buffer. */ - jinit_d_coef_controller(cinfo, TRUE); + if (cinfo->data_precision == 12) + j12init_d_coef_controller(cinfo, TRUE); + else + jinit_d_coef_controller(cinfo, TRUE); /* We can now tell the memory manager to allocate virtual arrays. */ (*cinfo->mem->realize_virt_arrays) ((j_common_ptr)cinfo); diff --git a/src/3rdparty/libjpeg/src/jerror.h b/src/3rdparty/libjpeg/src/jerror.h index eb44a1140a2..39362fdd477 100644 --- a/src/3rdparty/libjpeg/src/jerror.h +++ b/src/3rdparty/libjpeg/src/jerror.h @@ -4,6 +4,8 @@ * This file was part of the Independent JPEG Group's software: * Copyright (C) 1994-1997, Thomas G. Lane. * Modified 1997-2009 by Guido Vollbeding. + * Lossless JPEG Modifications: + * Copyright (C) 1999, Ken Murchison. * libjpeg-turbo Modifications: * Copyright (C) 2014, 2017, 2021-2022, D. R. Commander. * For conditions of distribution and use, see the accompanying README.ijg @@ -53,7 +55,8 @@ JMESSAGE(JERR_BAD_COMPONENT_ID, "Invalid component ID %d in SOS") #if JPEG_LIB_VERSION >= 70 JMESSAGE(JERR_BAD_CROP_SPEC, "Invalid crop request") #endif -JMESSAGE(JERR_BAD_DCT_COEF, "DCT coefficient out of range") +JMESSAGE(JERR_BAD_DCT_COEF, + "DCT coefficient (lossy) or spatial difference (lossless) out of range") JMESSAGE(JERR_BAD_DCTSIZE, "IDCT output block size %d not supported") #if JPEG_LIB_VERSION >= 70 JMESSAGE(JERR_BAD_DROP_SAMPLING, @@ -69,9 +72,9 @@ JMESSAGE(JERR_BAD_MCU_SIZE, "Sampling factors too large for interleaved scan") JMESSAGE(JERR_BAD_POOL_ID, "Invalid memory pool code %d") JMESSAGE(JERR_BAD_PRECISION, "Unsupported JPEG data precision %d") JMESSAGE(JERR_BAD_PROGRESSION, - "Invalid progressive parameters Ss=%d Se=%d Ah=%d Al=%d") + "Invalid progressive/lossless parameters Ss=%d Se=%d Ah=%d Al=%d") JMESSAGE(JERR_BAD_PROG_SCRIPT, - "Invalid progressive parameters at scan script entry %d") + "Invalid progressive/lossless parameters at scan script entry %d") JMESSAGE(JERR_BAD_SAMPLING, "Bogus sampling factors") JMESSAGE(JERR_BAD_SCAN_SCRIPT, "Invalid scan script at entry %d") JMESSAGE(JERR_BAD_STATE, "Improper call to JPEG library in state %d") @@ -180,7 +183,7 @@ JMESSAGE(JTRC_THUMB_PALETTE, JMESSAGE(JTRC_THUMB_RGB, "JFIF extension marker: RGB thumbnail image, length %u") JMESSAGE(JTRC_UNKNOWN_IDS, - "Unrecognized component IDs %d %d %d, assuming YCbCr") + "Unrecognized component IDs %d %d %d, assuming YCbCr (lossy) or RGB (lossless)") JMESSAGE(JTRC_XMS_CLOSE, "Freed XMS handle %u") JMESSAGE(JTRC_XMS_OPEN, "Obtained XMS handle %u") JMESSAGE(JWRN_ADOBE_XFORM, "Unknown Adobe color transform code %d") @@ -211,6 +214,8 @@ JMESSAGE(JWRN_BOGUS_ICC, "Corrupt JPEG data: bad ICC marker") JMESSAGE(JERR_BAD_DROP_SAMPLING, "Component index %d: mismatching sampling ratio %d:%d, %d:%d, %c") #endif +JMESSAGE(JERR_BAD_RESTART, + "Invalid restart interval %d; must be an integer multiple of the number of MCUs in an MCU row (%d)") #ifdef JMAKE_ENUM_LIST diff --git a/src/3rdparty/libjpeg/src/jfdctfst.c b/src/3rdparty/libjpeg/src/jfdctfst.c index 4c9ce0de8fa..26070d19a62 100644 --- a/src/3rdparty/libjpeg/src/jfdctfst.c +++ b/src/3rdparty/libjpeg/src/jfdctfst.c @@ -114,7 +114,7 @@ */ GLOBAL(void) -jpeg_fdct_ifast(DCTELEM *data) +_jpeg_fdct_ifast(DCTELEM *data) { DCTELEM tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; DCTELEM tmp10, tmp11, tmp12, tmp13; diff --git a/src/3rdparty/libjpeg/src/jfdctint.c b/src/3rdparty/libjpeg/src/jfdctint.c index c95a3a7fb8a..974013fa409 100644 --- a/src/3rdparty/libjpeg/src/jfdctint.c +++ b/src/3rdparty/libjpeg/src/jfdctint.c @@ -4,7 +4,7 @@ * This file was part of the Independent JPEG Group's software: * Copyright (C) 1991-1996, Thomas G. Lane. * libjpeg-turbo Modifications: - * Copyright (C) 2015, 2020, D. R. Commander. + * Copyright (C) 2015, 2020, 2022, D. R. Commander. * For conditions of distribution and use, see the accompanying README.ijg * file. * @@ -140,7 +140,7 @@ */ GLOBAL(void) -jpeg_fdct_islow(DCTELEM *data) +_jpeg_fdct_islow(DCTELEM *data) { JLONG tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; JLONG tmp10, tmp11, tmp12, tmp13; diff --git a/src/3rdparty/libjpeg/src/jidctflt.c b/src/3rdparty/libjpeg/src/jidctflt.c index 5aee74e2321..ee3a31a6168 100644 --- a/src/3rdparty/libjpeg/src/jidctflt.c +++ b/src/3rdparty/libjpeg/src/jidctflt.c @@ -5,7 +5,7 @@ * Copyright (C) 1994-1998, Thomas G. Lane. * Modified 2010 by Guido Vollbeding. * libjpeg-turbo Modifications: - * Copyright (C) 2014, D. R. Commander. + * Copyright (C) 2014, 2022, D. R. Commander. * For conditions of distribution and use, see the accompanying README.ijg * file. * @@ -69,9 +69,9 @@ */ GLOBAL(void) -jpeg_idct_float(j_decompress_ptr cinfo, jpeg_component_info *compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, - JDIMENSION output_col) +_jpeg_idct_float(j_decompress_ptr cinfo, jpeg_component_info *compptr, + JCOEFPTR coef_block, _JSAMPARRAY output_buf, + JDIMENSION output_col) { FAST_FLOAT tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; FAST_FLOAT tmp10, tmp11, tmp12, tmp13; @@ -79,8 +79,8 @@ jpeg_idct_float(j_decompress_ptr cinfo, jpeg_component_info *compptr, JCOEFPTR inptr; FLOAT_MULT_TYPE *quantptr; FAST_FLOAT *wsptr; - JSAMPROW outptr; - JSAMPLE *range_limit = cinfo->sample_range_limit; + _JSAMPROW outptr; + _JSAMPLE *range_limit = (_JSAMPLE *)cinfo->sample_range_limit; int ctr; FAST_FLOAT workspace[DCTSIZE2]; /* buffers data between passes */ #define _0_125 ((FLOAT_MULT_TYPE)0.125) @@ -192,7 +192,7 @@ jpeg_idct_float(j_decompress_ptr cinfo, jpeg_component_info *compptr, /* Even part */ /* Apply signed->unsigned and prepare float->int conversion */ - z5 = wsptr[0] + ((FAST_FLOAT)CENTERJSAMPLE + (FAST_FLOAT)0.5); + z5 = wsptr[0] + ((FAST_FLOAT)_CENTERJSAMPLE + (FAST_FLOAT)0.5); tmp10 = z5 + wsptr[4]; tmp11 = z5 - wsptr[4]; diff --git a/src/3rdparty/libjpeg/src/jidctfst.c b/src/3rdparty/libjpeg/src/jidctfst.c index 89a20c937bb..68119b9942b 100644 --- a/src/3rdparty/libjpeg/src/jidctfst.c +++ b/src/3rdparty/libjpeg/src/jidctfst.c @@ -4,7 +4,7 @@ * This file was part of the Independent JPEG Group's software: * Copyright (C) 1994-1998, Thomas G. Lane. * libjpeg-turbo Modifications: - * Copyright (C) 2015, D. R. Commander. + * Copyright (C) 2015, 2022, D. R. Commander. * For conditions of distribution and use, see the accompanying README.ijg * file. * @@ -64,10 +64,10 @@ * The dequantized coefficients are not integers because the AA&N scaling * factors have been incorporated. We represent them scaled up by PASS1_BITS, * so that the first and second IDCT rounds have the same input scaling. - * For 8-bit JSAMPLEs, we choose IFAST_SCALE_BITS = PASS1_BITS so as to + * For 8-bit samples, we choose IFAST_SCALE_BITS = PASS1_BITS so as to * avoid a descaling shift; this compromises accuracy rather drastically * for small quantization table entries, but it saves a lot of shifts. - * For 12-bit JSAMPLEs, there's no hope of using 16x16 multiplies anyway, + * For 12-bit samples, there's no hope of using 16x16 multiplies anyway, * so we use a much larger scaling factor to preserve accuracy. * * A final compromise is to represent the multiplicative constants to only @@ -168,9 +168,9 @@ */ GLOBAL(void) -jpeg_idct_ifast(j_decompress_ptr cinfo, jpeg_component_info *compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, - JDIMENSION output_col) +_jpeg_idct_ifast(j_decompress_ptr cinfo, jpeg_component_info *compptr, + JCOEFPTR coef_block, _JSAMPARRAY output_buf, + JDIMENSION output_col) { DCTELEM tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; DCTELEM tmp10, tmp11, tmp12, tmp13; @@ -178,8 +178,8 @@ jpeg_idct_ifast(j_decompress_ptr cinfo, jpeg_component_info *compptr, JCOEFPTR inptr; IFAST_MULT_TYPE *quantptr; int *wsptr; - JSAMPROW outptr; - JSAMPLE *range_limit = IDCT_range_limit(cinfo); + _JSAMPROW outptr; + _JSAMPLE *range_limit = IDCT_range_limit(cinfo); int ctr; int workspace[DCTSIZE2]; /* buffers data between passes */ SHIFT_TEMPS /* for DESCALE */ @@ -296,7 +296,7 @@ jpeg_idct_ifast(j_decompress_ptr cinfo, jpeg_component_info *compptr, if (wsptr[1] == 0 && wsptr[2] == 0 && wsptr[3] == 0 && wsptr[4] == 0 && wsptr[5] == 0 && wsptr[6] == 0 && wsptr[7] == 0) { /* AC terms all zero */ - JSAMPLE dcval = + _JSAMPLE dcval = range_limit[IDESCALE(wsptr[0], PASS1_BITS + 3) & RANGE_MASK]; outptr[0] = dcval; diff --git a/src/3rdparty/libjpeg/src/jidctint.c b/src/3rdparty/libjpeg/src/jidctint.c index bb087480192..c58592d626d 100644 --- a/src/3rdparty/libjpeg/src/jidctint.c +++ b/src/3rdparty/libjpeg/src/jidctint.c @@ -5,7 +5,7 @@ * Copyright (C) 1991-1998, Thomas G. Lane. * Modification developed 2002-2018 by Guido Vollbeding. * libjpeg-turbo Modifications: - * Copyright (C) 2015, 2020, D. R. Commander. + * Copyright (C) 2015, 2020, 2022, D. R. Commander. * For conditions of distribution and use, see the accompanying README.ijg * file. * @@ -170,9 +170,9 @@ */ GLOBAL(void) -jpeg_idct_islow(j_decompress_ptr cinfo, jpeg_component_info *compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, - JDIMENSION output_col) +_jpeg_idct_islow(j_decompress_ptr cinfo, jpeg_component_info *compptr, + JCOEFPTR coef_block, _JSAMPARRAY output_buf, + JDIMENSION output_col) { JLONG tmp0, tmp1, tmp2, tmp3; JLONG tmp10, tmp11, tmp12, tmp13; @@ -180,8 +180,8 @@ jpeg_idct_islow(j_decompress_ptr cinfo, jpeg_component_info *compptr, JCOEFPTR inptr; ISLOW_MULT_TYPE *quantptr; int *wsptr; - JSAMPROW outptr; - JSAMPLE *range_limit = IDCT_range_limit(cinfo); + _JSAMPROW outptr; + _JSAMPLE *range_limit = IDCT_range_limit(cinfo); int ctr; int workspace[DCTSIZE2]; /* buffers data between passes */ SHIFT_TEMPS @@ -314,8 +314,8 @@ jpeg_idct_islow(j_decompress_ptr cinfo, jpeg_component_info *compptr, if (wsptr[1] == 0 && wsptr[2] == 0 && wsptr[3] == 0 && wsptr[4] == 0 && wsptr[5] == 0 && wsptr[6] == 0 && wsptr[7] == 0) { /* AC terms all zero */ - JSAMPLE dcval = range_limit[(int)DESCALE((JLONG)wsptr[0], - PASS1_BITS + 3) & RANGE_MASK]; + _JSAMPLE dcval = range_limit[(int)DESCALE((JLONG)wsptr[0], + PASS1_BITS + 3) & RANGE_MASK]; outptr[0] = dcval; outptr[1] = dcval; @@ -424,17 +424,17 @@ jpeg_idct_islow(j_decompress_ptr cinfo, jpeg_component_info *compptr, */ GLOBAL(void) -jpeg_idct_7x7(j_decompress_ptr cinfo, jpeg_component_info *compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, - JDIMENSION output_col) +_jpeg_idct_7x7(j_decompress_ptr cinfo, jpeg_component_info *compptr, + JCOEFPTR coef_block, _JSAMPARRAY output_buf, + JDIMENSION output_col) { JLONG tmp0, tmp1, tmp2, tmp10, tmp11, tmp12, tmp13; JLONG z1, z2, z3; JCOEFPTR inptr; ISLOW_MULT_TYPE *quantptr; int *wsptr; - JSAMPROW outptr; - JSAMPLE *range_limit = IDCT_range_limit(cinfo); + _JSAMPROW outptr; + _JSAMPLE *range_limit = IDCT_range_limit(cinfo); int ctr; int workspace[7 * 7]; /* buffers data between passes */ SHIFT_TEMPS @@ -573,17 +573,17 @@ jpeg_idct_7x7(j_decompress_ptr cinfo, jpeg_component_info *compptr, */ GLOBAL(void) -jpeg_idct_6x6(j_decompress_ptr cinfo, jpeg_component_info *compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, - JDIMENSION output_col) +_jpeg_idct_6x6(j_decompress_ptr cinfo, jpeg_component_info *compptr, + JCOEFPTR coef_block, _JSAMPARRAY output_buf, + JDIMENSION output_col) { JLONG tmp0, tmp1, tmp2, tmp10, tmp11, tmp12; JLONG z1, z2, z3; JCOEFPTR inptr; ISLOW_MULT_TYPE *quantptr; int *wsptr; - JSAMPROW outptr; - JSAMPLE *range_limit = IDCT_range_limit(cinfo); + _JSAMPROW outptr; + _JSAMPLE *range_limit = IDCT_range_limit(cinfo); int ctr; int workspace[6 * 6]; /* buffers data between passes */ SHIFT_TEMPS @@ -694,17 +694,17 @@ jpeg_idct_6x6(j_decompress_ptr cinfo, jpeg_component_info *compptr, */ GLOBAL(void) -jpeg_idct_5x5(j_decompress_ptr cinfo, jpeg_component_info *compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, - JDIMENSION output_col) +_jpeg_idct_5x5(j_decompress_ptr cinfo, jpeg_component_info *compptr, + JCOEFPTR coef_block, _JSAMPARRAY output_buf, + JDIMENSION output_col) { JLONG tmp0, tmp1, tmp10, tmp11, tmp12; JLONG z1, z2, z3; JCOEFPTR inptr; ISLOW_MULT_TYPE *quantptr; int *wsptr; - JSAMPROW outptr; - JSAMPLE *range_limit = IDCT_range_limit(cinfo); + _JSAMPROW outptr; + _JSAMPLE *range_limit = IDCT_range_limit(cinfo); int ctr; int workspace[5 * 5]; /* buffers data between passes */ SHIFT_TEMPS @@ -809,16 +809,16 @@ jpeg_idct_5x5(j_decompress_ptr cinfo, jpeg_component_info *compptr, */ GLOBAL(void) -jpeg_idct_3x3(j_decompress_ptr cinfo, jpeg_component_info *compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, - JDIMENSION output_col) +_jpeg_idct_3x3(j_decompress_ptr cinfo, jpeg_component_info *compptr, + JCOEFPTR coef_block, _JSAMPARRAY output_buf, + JDIMENSION output_col) { JLONG tmp0, tmp2, tmp10, tmp12; JCOEFPTR inptr; ISLOW_MULT_TYPE *quantptr; int *wsptr; - JSAMPROW outptr; - JSAMPLE *range_limit = IDCT_range_limit(cinfo); + _JSAMPROW outptr; + _JSAMPLE *range_limit = IDCT_range_limit(cinfo); int ctr; int workspace[3 * 3]; /* buffers data between passes */ SHIFT_TEMPS @@ -899,17 +899,17 @@ jpeg_idct_3x3(j_decompress_ptr cinfo, jpeg_component_info *compptr, */ GLOBAL(void) -jpeg_idct_9x9(j_decompress_ptr cinfo, jpeg_component_info *compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, - JDIMENSION output_col) +_jpeg_idct_9x9(j_decompress_ptr cinfo, jpeg_component_info *compptr, + JCOEFPTR coef_block, _JSAMPARRAY output_buf, + JDIMENSION output_col) { JLONG tmp0, tmp1, tmp2, tmp3, tmp10, tmp11, tmp12, tmp13, tmp14; JLONG z1, z2, z3, z4; JCOEFPTR inptr; ISLOW_MULT_TYPE *quantptr; int *wsptr; - JSAMPROW outptr; - JSAMPLE *range_limit = IDCT_range_limit(cinfo); + _JSAMPROW outptr; + _JSAMPLE *range_limit = IDCT_range_limit(cinfo); int ctr; int workspace[8 * 9]; /* buffers data between passes */ SHIFT_TEMPS @@ -1070,9 +1070,9 @@ jpeg_idct_9x9(j_decompress_ptr cinfo, jpeg_component_info *compptr, */ GLOBAL(void) -jpeg_idct_10x10(j_decompress_ptr cinfo, jpeg_component_info *compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, - JDIMENSION output_col) +_jpeg_idct_10x10(j_decompress_ptr cinfo, jpeg_component_info *compptr, + JCOEFPTR coef_block, _JSAMPARRAY output_buf, + JDIMENSION output_col) { JLONG tmp10, tmp11, tmp12, tmp13, tmp14; JLONG tmp20, tmp21, tmp22, tmp23, tmp24; @@ -1080,8 +1080,8 @@ jpeg_idct_10x10(j_decompress_ptr cinfo, jpeg_component_info *compptr, JCOEFPTR inptr; ISLOW_MULT_TYPE *quantptr; int *wsptr; - JSAMPROW outptr; - JSAMPLE *range_limit = IDCT_range_limit(cinfo); + _JSAMPROW outptr; + _JSAMPLE *range_limit = IDCT_range_limit(cinfo); int ctr; int workspace[8 * 10]; /* buffers data between passes */ SHIFT_TEMPS @@ -1265,9 +1265,9 @@ jpeg_idct_10x10(j_decompress_ptr cinfo, jpeg_component_info *compptr, */ GLOBAL(void) -jpeg_idct_11x11(j_decompress_ptr cinfo, jpeg_component_info *compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, - JDIMENSION output_col) +_jpeg_idct_11x11(j_decompress_ptr cinfo, jpeg_component_info *compptr, + JCOEFPTR coef_block, _JSAMPARRAY output_buf, + JDIMENSION output_col) { JLONG tmp10, tmp11, tmp12, tmp13, tmp14; JLONG tmp20, tmp21, tmp22, tmp23, tmp24, tmp25; @@ -1275,8 +1275,8 @@ jpeg_idct_11x11(j_decompress_ptr cinfo, jpeg_component_info *compptr, JCOEFPTR inptr; ISLOW_MULT_TYPE *quantptr; int *wsptr; - JSAMPROW outptr; - JSAMPLE *range_limit = IDCT_range_limit(cinfo); + _JSAMPROW outptr; + _JSAMPLE *range_limit = IDCT_range_limit(cinfo); int ctr; int workspace[8 * 11]; /* buffers data between passes */ SHIFT_TEMPS @@ -1459,9 +1459,9 @@ jpeg_idct_11x11(j_decompress_ptr cinfo, jpeg_component_info *compptr, */ GLOBAL(void) -jpeg_idct_12x12(j_decompress_ptr cinfo, jpeg_component_info *compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, - JDIMENSION output_col) +_jpeg_idct_12x12(j_decompress_ptr cinfo, jpeg_component_info *compptr, + JCOEFPTR coef_block, _JSAMPARRAY output_buf, + JDIMENSION output_col) { JLONG tmp10, tmp11, tmp12, tmp13, tmp14, tmp15; JLONG tmp20, tmp21, tmp22, tmp23, tmp24, tmp25; @@ -1469,8 +1469,8 @@ jpeg_idct_12x12(j_decompress_ptr cinfo, jpeg_component_info *compptr, JCOEFPTR inptr; ISLOW_MULT_TYPE *quantptr; int *wsptr; - JSAMPROW outptr; - JSAMPLE *range_limit = IDCT_range_limit(cinfo); + _JSAMPROW outptr; + _JSAMPLE *range_limit = IDCT_range_limit(cinfo); int ctr; int workspace[8 * 12]; /* buffers data between passes */ SHIFT_TEMPS @@ -1675,9 +1675,9 @@ jpeg_idct_12x12(j_decompress_ptr cinfo, jpeg_component_info *compptr, */ GLOBAL(void) -jpeg_idct_13x13(j_decompress_ptr cinfo, jpeg_component_info *compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, - JDIMENSION output_col) +_jpeg_idct_13x13(j_decompress_ptr cinfo, jpeg_component_info *compptr, + JCOEFPTR coef_block, _JSAMPARRAY output_buf, + JDIMENSION output_col) { JLONG tmp10, tmp11, tmp12, tmp13, tmp14, tmp15; JLONG tmp20, tmp21, tmp22, tmp23, tmp24, tmp25, tmp26; @@ -1685,8 +1685,8 @@ jpeg_idct_13x13(j_decompress_ptr cinfo, jpeg_component_info *compptr, JCOEFPTR inptr; ISLOW_MULT_TYPE *quantptr; int *wsptr; - JSAMPROW outptr; - JSAMPLE *range_limit = IDCT_range_limit(cinfo); + _JSAMPROW outptr; + _JSAMPLE *range_limit = IDCT_range_limit(cinfo); int ctr; int workspace[8 * 13]; /* buffers data between passes */ SHIFT_TEMPS @@ -1903,9 +1903,9 @@ jpeg_idct_13x13(j_decompress_ptr cinfo, jpeg_component_info *compptr, */ GLOBAL(void) -jpeg_idct_14x14(j_decompress_ptr cinfo, jpeg_component_info *compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, - JDIMENSION output_col) +_jpeg_idct_14x14(j_decompress_ptr cinfo, jpeg_component_info *compptr, + JCOEFPTR coef_block, _JSAMPARRAY output_buf, + JDIMENSION output_col) { JLONG tmp10, tmp11, tmp12, tmp13, tmp14, tmp15, tmp16; JLONG tmp20, tmp21, tmp22, tmp23, tmp24, tmp25, tmp26; @@ -1913,8 +1913,8 @@ jpeg_idct_14x14(j_decompress_ptr cinfo, jpeg_component_info *compptr, JCOEFPTR inptr; ISLOW_MULT_TYPE *quantptr; int *wsptr; - JSAMPROW outptr; - JSAMPLE *range_limit = IDCT_range_limit(cinfo); + _JSAMPROW outptr; + _JSAMPLE *range_limit = IDCT_range_limit(cinfo); int ctr; int workspace[8 * 14]; /* buffers data between passes */ SHIFT_TEMPS @@ -2129,9 +2129,9 @@ jpeg_idct_14x14(j_decompress_ptr cinfo, jpeg_component_info *compptr, */ GLOBAL(void) -jpeg_idct_15x15(j_decompress_ptr cinfo, jpeg_component_info *compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, - JDIMENSION output_col) +_jpeg_idct_15x15(j_decompress_ptr cinfo, jpeg_component_info *compptr, + JCOEFPTR coef_block, _JSAMPARRAY output_buf, + JDIMENSION output_col) { JLONG tmp10, tmp11, tmp12, tmp13, tmp14, tmp15, tmp16; JLONG tmp20, tmp21, tmp22, tmp23, tmp24, tmp25, tmp26, tmp27; @@ -2139,8 +2139,8 @@ jpeg_idct_15x15(j_decompress_ptr cinfo, jpeg_component_info *compptr, JCOEFPTR inptr; ISLOW_MULT_TYPE *quantptr; int *wsptr; - JSAMPROW outptr; - JSAMPLE *range_limit = IDCT_range_limit(cinfo); + _JSAMPROW outptr; + _JSAMPLE *range_limit = IDCT_range_limit(cinfo); int ctr; int workspace[8 * 15]; /* buffers data between passes */ SHIFT_TEMPS @@ -2371,9 +2371,9 @@ jpeg_idct_15x15(j_decompress_ptr cinfo, jpeg_component_info *compptr, */ GLOBAL(void) -jpeg_idct_16x16(j_decompress_ptr cinfo, jpeg_component_info *compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, - JDIMENSION output_col) +_jpeg_idct_16x16(j_decompress_ptr cinfo, jpeg_component_info *compptr, + JCOEFPTR coef_block, _JSAMPARRAY output_buf, + JDIMENSION output_col) { JLONG tmp0, tmp1, tmp2, tmp3, tmp10, tmp11, tmp12, tmp13; JLONG tmp20, tmp21, tmp22, tmp23, tmp24, tmp25, tmp26, tmp27; @@ -2381,8 +2381,8 @@ jpeg_idct_16x16(j_decompress_ptr cinfo, jpeg_component_info *compptr, JCOEFPTR inptr; ISLOW_MULT_TYPE *quantptr; int *wsptr; - JSAMPROW outptr; - JSAMPLE *range_limit = IDCT_range_limit(cinfo); + _JSAMPROW outptr; + _JSAMPLE *range_limit = IDCT_range_limit(cinfo); int ctr; int workspace[8 * 16]; /* buffers data between passes */ SHIFT_TEMPS diff --git a/src/3rdparty/libjpeg/src/jidctred.c b/src/3rdparty/libjpeg/src/jidctred.c index 1dd65a94d97..6521e3ebbfc 100644 --- a/src/3rdparty/libjpeg/src/jidctred.c +++ b/src/3rdparty/libjpeg/src/jidctred.c @@ -4,7 +4,7 @@ * This file was part of the Independent JPEG Group's software: * Copyright (C) 1994-1998, Thomas G. Lane. * libjpeg-turbo Modifications: - * Copyright (C) 2015, D. R. Commander. + * Copyright (C) 2015, 2022, D. R. Commander. * For conditions of distribution and use, see the accompanying README.ijg * file. * @@ -118,17 +118,17 @@ */ GLOBAL(void) -jpeg_idct_4x4(j_decompress_ptr cinfo, jpeg_component_info *compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, - JDIMENSION output_col) +_jpeg_idct_4x4(j_decompress_ptr cinfo, jpeg_component_info *compptr, + JCOEFPTR coef_block, _JSAMPARRAY output_buf, + JDIMENSION output_col) { JLONG tmp0, tmp2, tmp10, tmp12; JLONG z1, z2, z3, z4; JCOEFPTR inptr; ISLOW_MULT_TYPE *quantptr; int *wsptr; - JSAMPROW outptr; - JSAMPLE *range_limit = IDCT_range_limit(cinfo); + _JSAMPROW outptr; + _JSAMPLE *range_limit = IDCT_range_limit(cinfo); int ctr; int workspace[DCTSIZE * 4]; /* buffers data between passes */ SHIFT_TEMPS @@ -210,8 +210,8 @@ jpeg_idct_4x4(j_decompress_ptr cinfo, jpeg_component_info *compptr, if (wsptr[1] == 0 && wsptr[2] == 0 && wsptr[3] == 0 && wsptr[5] == 0 && wsptr[6] == 0 && wsptr[7] == 0) { /* AC terms all zero */ - JSAMPLE dcval = range_limit[(int)DESCALE((JLONG)wsptr[0], - PASS1_BITS + 3) & RANGE_MASK]; + _JSAMPLE dcval = range_limit[(int)DESCALE((JLONG)wsptr[0], + PASS1_BITS + 3) & RANGE_MASK]; outptr[0] = dcval; outptr[1] = dcval; @@ -276,16 +276,16 @@ jpeg_idct_4x4(j_decompress_ptr cinfo, jpeg_component_info *compptr, */ GLOBAL(void) -jpeg_idct_2x2(j_decompress_ptr cinfo, jpeg_component_info *compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, - JDIMENSION output_col) +_jpeg_idct_2x2(j_decompress_ptr cinfo, jpeg_component_info *compptr, + JCOEFPTR coef_block, _JSAMPARRAY output_buf, + JDIMENSION output_col) { JLONG tmp0, tmp10, z1; JCOEFPTR inptr; ISLOW_MULT_TYPE *quantptr; int *wsptr; - JSAMPROW outptr; - JSAMPLE *range_limit = IDCT_range_limit(cinfo); + _JSAMPROW outptr; + _JSAMPLE *range_limit = IDCT_range_limit(cinfo); int ctr; int workspace[DCTSIZE * 2]; /* buffers data between passes */ SHIFT_TEMPS @@ -345,8 +345,8 @@ jpeg_idct_2x2(j_decompress_ptr cinfo, jpeg_component_info *compptr, #ifndef NO_ZERO_ROW_TEST if (wsptr[1] == 0 && wsptr[3] == 0 && wsptr[5] == 0 && wsptr[7] == 0) { /* AC terms all zero */ - JSAMPLE dcval = range_limit[(int)DESCALE((JLONG)wsptr[0], - PASS1_BITS + 3) & RANGE_MASK]; + _JSAMPLE dcval = range_limit[(int)DESCALE((JLONG)wsptr[0], + PASS1_BITS + 3) & RANGE_MASK]; outptr[0] = dcval; outptr[1] = dcval; @@ -387,13 +387,13 @@ jpeg_idct_2x2(j_decompress_ptr cinfo, jpeg_component_info *compptr, */ GLOBAL(void) -jpeg_idct_1x1(j_decompress_ptr cinfo, jpeg_component_info *compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, - JDIMENSION output_col) +_jpeg_idct_1x1(j_decompress_ptr cinfo, jpeg_component_info *compptr, + JCOEFPTR coef_block, _JSAMPARRAY output_buf, + JDIMENSION output_col) { int dcval; ISLOW_MULT_TYPE *quantptr; - JSAMPLE *range_limit = IDCT_range_limit(cinfo); + _JSAMPLE *range_limit = IDCT_range_limit(cinfo); SHIFT_TEMPS /* We hardly need an inverse DCT routine for this: just take the diff --git a/src/3rdparty/libjpeg/src/jinclude.h b/src/3rdparty/libjpeg/src/jinclude.h index e8d983ac171..56e7a4b296d 100644 --- a/src/3rdparty/libjpeg/src/jinclude.h +++ b/src/3rdparty/libjpeg/src/jinclude.h @@ -4,7 +4,7 @@ * This file was part of the Independent JPEG Group's software: * Copyright (C) 1991-1994, Thomas G. Lane. * libjpeg-turbo Modifications: - * Copyright (C) 2022, D. R. Commander. + * Copyright (C) 2022-2023, D. R. Commander. * For conditions of distribution and use, see the accompanying README.ijg * file. * @@ -123,6 +123,8 @@ static INLINE int GETENV_S(char *buffer, size_t buffer_size, const char *name) #else +#include + /* This provides a similar interface to the Microsoft _putenv_s() function, but * other than parameter validation, it has no advantages over setenv(). */ diff --git a/src/3rdparty/libjpeg/src/jlossls.h b/src/3rdparty/libjpeg/src/jlossls.h new file mode 100644 index 00000000000..ce417041345 --- /dev/null +++ b/src/3rdparty/libjpeg/src/jlossls.h @@ -0,0 +1,101 @@ +/* + * jlossls.h + * + * This file was part of the Independent JPEG Group's software: + * Copyright (C) 1998, Thomas G. Lane. + * Lossless JPEG Modifications: + * Copyright (C) 1999, Ken Murchison. + * libjpeg-turbo Modifications: + * Copyright (C) 2022, D. R. Commander. + * For conditions of distribution and use, see the accompanying README.ijg + * file. + * + * This include file contains common declarations for the lossless JPEG + * codec modules. + */ + +#ifndef JLOSSLS_H +#define JLOSSLS_H + +#if defined(C_LOSSLESS_SUPPORTED) || defined(D_LOSSLESS_SUPPORTED) + +#define JPEG_INTERNALS +#include "jpeglib.h" +#include "jsamplecomp.h" + + +#define ALLOC_DARRAY(pool_id, diffsperrow, numrows) \ + (JDIFFARRAY)(*cinfo->mem->alloc_sarray) \ + ((j_common_ptr)cinfo, pool_id, \ + (diffsperrow) * sizeof(JDIFF) / sizeof(_JSAMPLE), numrows) + + +/* + * Table H.1: Predictors for lossless coding. + */ + +#define PREDICTOR1 Ra +#define PREDICTOR2 Rb +#define PREDICTOR3 Rc +#define PREDICTOR4 (int)((JLONG)Ra + (JLONG)Rb - (JLONG)Rc) +#define PREDICTOR5 (int)((JLONG)Ra + RIGHT_SHIFT((JLONG)Rb - (JLONG)Rc, 1)) +#define PREDICTOR6 (int)((JLONG)Rb + RIGHT_SHIFT((JLONG)Ra - (JLONG)Rc, 1)) +#define PREDICTOR7 (int)RIGHT_SHIFT((JLONG)Ra + (JLONG)Rb, 1) + +#endif + + +#ifdef C_LOSSLESS_SUPPORTED + +typedef void (*predict_difference_method_ptr) (j_compress_ptr cinfo, int ci, + _JSAMPROW input_buf, + _JSAMPROW prev_row, + JDIFFROW diff_buf, + JDIMENSION width); + +/* Lossless compressor */ +typedef struct { + struct jpeg_forward_dct pub; /* public fields */ + + /* It is useful to allow each component to have a separate diff method. */ + predict_difference_method_ptr predict_difference[MAX_COMPONENTS]; + + /* MCU rows left in the restart interval for each component */ + unsigned int restart_rows_to_go[MAX_COMPONENTS]; + + /* Sample scaling */ + void (*scaler_scale) (j_compress_ptr cinfo, _JSAMPROW input_buf, + _JSAMPROW output_buf, JDIMENSION width); +} jpeg_lossless_compressor; + +typedef jpeg_lossless_compressor *lossless_comp_ptr; + +#endif /* C_LOSSLESS_SUPPORTED */ + + +#ifdef D_LOSSLESS_SUPPORTED + +typedef void (*predict_undifference_method_ptr) (j_decompress_ptr cinfo, + int comp_index, + JDIFFROW diff_buf, + JDIFFROW prev_row, + JDIFFROW undiff_buf, + JDIMENSION width); + +/* Lossless decompressor */ +typedef struct { + struct jpeg_inverse_dct pub; /* public fields */ + + /* It is useful to allow each component to have a separate undiff method. */ + predict_undifference_method_ptr predict_undifference[MAX_COMPONENTS]; + + /* Sample scaling */ + void (*scaler_scale) (j_decompress_ptr cinfo, JDIFFROW diff_buf, + _JSAMPROW output_buf, JDIMENSION width); +} jpeg_lossless_decompressor; + +typedef jpeg_lossless_decompressor *lossless_decomp_ptr; + +#endif /* D_LOSSLESS_SUPPORTED */ + +#endif /* JLOSSLS_H */ diff --git a/src/3rdparty/libjpeg/src/jmemmgr.c b/src/3rdparty/libjpeg/src/jmemmgr.c index a40446f6ac3..dca8f5c22ca 100644 --- a/src/3rdparty/libjpeg/src/jmemmgr.c +++ b/src/3rdparty/libjpeg/src/jmemmgr.c @@ -155,7 +155,9 @@ typedef my_memory_mgr *my_mem_ptr; */ struct jvirt_sarray_control { - JSAMPARRAY mem_buffer; /* => the in-memory buffer */ + JSAMPARRAY mem_buffer; /* => the in-memory buffer (if + cinfo->data_precision is 12, then this is + actually a J12SAMPARRAY) */ JDIMENSION rows_in_array; /* total virtual array height */ JDIMENSION samplesperrow; /* width of array (and of memory buffer) */ JDIMENSION maxaccess; /* max rows accessed by access_virt_sarray */ @@ -351,9 +353,10 @@ alloc_small(j_common_ptr cinfo, int pool_id, size_t sizeofobject) * request is large enough that it may as well be passed directly to * jpeg_get_large; the pool management just links everything together * so that we can free it all on demand. - * Note: the major use of "large" objects is in JSAMPARRAY and JBLOCKARRAY - * structures. The routines that create these structures (see below) - * deliberately bunch rows together to ensure a large request size. + * Note: the major use of "large" objects is in + * JSAMPARRAY/J12SAMPARRAY/J16SAMPARRAY and JBLOCKARRAY structures. The + * routines that create these structures (see below) deliberately bunch rows + * together to ensure a large request size. */ METHODDEF(void *) @@ -437,9 +440,22 @@ alloc_sarray(j_common_ptr cinfo, int pool_id, JDIMENSION samplesperrow, JSAMPROW workspace; JDIMENSION rowsperchunk, currow, i; long ltemp; + J12SAMPARRAY result12; + J12SAMPROW workspace12; +#if defined(C_LOSSLESS_SUPPORTED) || defined(D_LOSSLESS_SUPPORTED) + J16SAMPARRAY result16; + J16SAMPROW workspace16; +#endif + int data_precision = cinfo->is_decompressor ? + ((j_decompress_ptr)cinfo)->data_precision : + ((j_compress_ptr)cinfo)->data_precision; + size_t sample_size = data_precision == 16 ? + sizeof(J16SAMPLE) : (data_precision == 12 ? + sizeof(J12SAMPLE) : + sizeof(JSAMPLE)); /* Make sure each row is properly aligned */ - if ((ALIGN_SIZE % sizeof(JSAMPLE)) != 0) + if ((ALIGN_SIZE % sample_size) != 0) out_of_memory(cinfo, 5); /* safety check */ if (samplesperrow > MAX_ALLOC_CHUNK) { @@ -448,11 +464,11 @@ alloc_sarray(j_common_ptr cinfo, int pool_id, JDIMENSION samplesperrow, out_of_memory(cinfo, 9); } samplesperrow = (JDIMENSION)round_up_pow2(samplesperrow, (2 * ALIGN_SIZE) / - sizeof(JSAMPLE)); + sample_size); /* Calculate max # of rows allowed in one allocation chunk */ ltemp = (MAX_ALLOC_CHUNK - sizeof(large_pool_hdr)) / - ((long)samplesperrow * sizeof(JSAMPLE)); + ((long)samplesperrow * (long)sample_size); if (ltemp <= 0) ERREXIT(cinfo, JERR_WIDTH_OVERFLOW); if (ltemp < (long)numrows) @@ -461,24 +477,68 @@ alloc_sarray(j_common_ptr cinfo, int pool_id, JDIMENSION samplesperrow, rowsperchunk = numrows; mem->last_rowsperchunk = rowsperchunk; - /* Get space for row pointers (small object) */ - result = (JSAMPARRAY)alloc_small(cinfo, pool_id, - (size_t)(numrows * sizeof(JSAMPROW))); + if (data_precision == 16) { +#if defined(C_LOSSLESS_SUPPORTED) || defined(D_LOSSLESS_SUPPORTED) + /* Get space for row pointers (small object) */ + result16 = (J16SAMPARRAY)alloc_small(cinfo, pool_id, + (size_t)(numrows * + sizeof(J16SAMPROW))); - /* Get the rows themselves (large objects) */ - currow = 0; - while (currow < numrows) { - rowsperchunk = MIN(rowsperchunk, numrows - currow); - workspace = (JSAMPROW)alloc_large(cinfo, pool_id, - (size_t)((size_t)rowsperchunk * (size_t)samplesperrow * - sizeof(JSAMPLE))); - for (i = rowsperchunk; i > 0; i--) { - result[currow++] = workspace; - workspace += samplesperrow; + /* Get the rows themselves (large objects) */ + currow = 0; + while (currow < numrows) { + rowsperchunk = MIN(rowsperchunk, numrows - currow); + workspace16 = (J16SAMPROW)alloc_large(cinfo, pool_id, + (size_t)((size_t)rowsperchunk * (size_t)samplesperrow * sample_size)); + for (i = rowsperchunk; i > 0; i--) { + result16[currow++] = workspace16; + workspace16 += samplesperrow; + } } - } - return result; + return (JSAMPARRAY)result16; +#else + ERREXIT1(cinfo, JERR_BAD_PRECISION, data_precision); + return NULL; +#endif + } else if (data_precision == 12) { + /* Get space for row pointers (small object) */ + result12 = (J12SAMPARRAY)alloc_small(cinfo, pool_id, + (size_t)(numrows * + sizeof(J12SAMPROW))); + + /* Get the rows themselves (large objects) */ + currow = 0; + while (currow < numrows) { + rowsperchunk = MIN(rowsperchunk, numrows - currow); + workspace12 = (J12SAMPROW)alloc_large(cinfo, pool_id, + (size_t)((size_t)rowsperchunk * (size_t)samplesperrow * sample_size)); + for (i = rowsperchunk; i > 0; i--) { + result12[currow++] = workspace12; + workspace12 += samplesperrow; + } + } + + return (JSAMPARRAY)result12; + } else { + /* Get space for row pointers (small object) */ + result = (JSAMPARRAY)alloc_small(cinfo, pool_id, + (size_t)(numrows * sizeof(JSAMPROW))); + + /* Get the rows themselves (large objects) */ + currow = 0; + while (currow < numrows) { + rowsperchunk = MIN(rowsperchunk, numrows - currow); + workspace = (JSAMPROW)alloc_large(cinfo, pool_id, + (size_t)((size_t)rowsperchunk * (size_t)samplesperrow * sample_size)); + for (i = rowsperchunk; i > 0; i--) { + result[currow++] = workspace; + workspace += samplesperrow; + } + } + + return result; + } } @@ -640,6 +700,13 @@ realize_virt_arrays(j_common_ptr cinfo) size_t minheights, max_minheights; jvirt_sarray_ptr sptr; jvirt_barray_ptr bptr; + int data_precision = cinfo->is_decompressor ? + ((j_decompress_ptr)cinfo)->data_precision : + ((j_compress_ptr)cinfo)->data_precision; + size_t sample_size = data_precision == 16 ? + sizeof(J16SAMPLE) : (data_precision == 12 ? + sizeof(J12SAMPLE) : + sizeof(JSAMPLE)); /* Compute the minimum space needed (maxaccess rows in each buffer) * and the maximum space needed (full image height in each buffer). @@ -650,10 +717,10 @@ realize_virt_arrays(j_common_ptr cinfo) for (sptr = mem->virt_sarray_list; sptr != NULL; sptr = sptr->next) { if (sptr->mem_buffer == NULL) { /* if not realized yet */ size_t new_space = (long)sptr->rows_in_array * - (long)sptr->samplesperrow * sizeof(JSAMPLE); + (long)sptr->samplesperrow * sample_size; space_per_minheight += (long)sptr->maxaccess * - (long)sptr->samplesperrow * sizeof(JSAMPLE); + (long)sptr->samplesperrow * sample_size; if (SIZE_MAX - maximum_space < new_space) out_of_memory(cinfo, 10); maximum_space += new_space; @@ -708,7 +775,7 @@ realize_virt_arrays(j_common_ptr cinfo) jpeg_open_backing_store(cinfo, &sptr->b_s_info, (long)sptr->rows_in_array * (long)sptr->samplesperrow * - (long)sizeof(JSAMPLE)); + (long)sample_size); sptr->b_s_open = TRUE; } sptr->mem_buffer = alloc_sarray(cinfo, JPOOL_IMAGE, @@ -751,8 +818,15 @@ do_sarray_io(j_common_ptr cinfo, jvirt_sarray_ptr ptr, boolean writing) /* Do backing store read or write of a virtual sample array */ { long bytesperrow, file_offset, byte_count, rows, thisrow, i; + int data_precision = cinfo->is_decompressor ? + ((j_decompress_ptr)cinfo)->data_precision : + ((j_compress_ptr)cinfo)->data_precision; + size_t sample_size = data_precision == 16 ? + sizeof(J16SAMPLE) : (data_precision == 12 ? + sizeof(J12SAMPLE) : + sizeof(JSAMPLE)); - bytesperrow = (long)ptr->samplesperrow * sizeof(JSAMPLE); + bytesperrow = (long)ptr->samplesperrow * (long)sample_size; file_offset = ptr->cur_start_row * bytesperrow; /* Loop to read or write each allocation chunk in mem_buffer */ for (i = 0; i < (long)ptr->rows_in_mem; i += ptr->rowsperchunk) { @@ -766,14 +840,42 @@ do_sarray_io(j_common_ptr cinfo, jvirt_sarray_ptr ptr, boolean writing) if (rows <= 0) /* this chunk might be past end of file! */ break; byte_count = rows * bytesperrow; - if (writing) - (*ptr->b_s_info.write_backing_store) (cinfo, &ptr->b_s_info, - (void *)ptr->mem_buffer[i], - file_offset, byte_count); - else - (*ptr->b_s_info.read_backing_store) (cinfo, &ptr->b_s_info, - (void *)ptr->mem_buffer[i], - file_offset, byte_count); + if (data_precision == 16) { +#if defined(C_LOSSLESS_SUPPORTED) || defined(D_LOSSLESS_SUPPORTED) + J16SAMPARRAY mem_buffer16 = (J16SAMPARRAY)ptr->mem_buffer; + + if (writing) + (*ptr->b_s_info.write_backing_store) (cinfo, &ptr->b_s_info, + (void *)mem_buffer16[i], + file_offset, byte_count); + else + (*ptr->b_s_info.read_backing_store) (cinfo, &ptr->b_s_info, + (void *)mem_buffer16[i], + file_offset, byte_count); +#else + ERREXIT1(cinfo, JERR_BAD_PRECISION, data_precision); +#endif + } else if (data_precision == 12) { + J12SAMPARRAY mem_buffer12 = (J12SAMPARRAY)ptr->mem_buffer; + + if (writing) + (*ptr->b_s_info.write_backing_store) (cinfo, &ptr->b_s_info, + (void *)mem_buffer12[i], + file_offset, byte_count); + else + (*ptr->b_s_info.read_backing_store) (cinfo, &ptr->b_s_info, + (void *)mem_buffer12[i], + file_offset, byte_count); + } else { + if (writing) + (*ptr->b_s_info.write_backing_store) (cinfo, &ptr->b_s_info, + (void *)ptr->mem_buffer[i], + file_offset, byte_count); + else + (*ptr->b_s_info.read_backing_store) (cinfo, &ptr->b_s_info, + (void *)ptr->mem_buffer[i], + file_offset, byte_count); + } file_offset += byte_count; } } @@ -821,6 +923,13 @@ access_virt_sarray(j_common_ptr cinfo, jvirt_sarray_ptr ptr, { JDIMENSION end_row = start_row + num_rows; JDIMENSION undef_row; + int data_precision = cinfo->is_decompressor ? + ((j_decompress_ptr)cinfo)->data_precision : + ((j_compress_ptr)cinfo)->data_precision; + size_t sample_size = data_precision == 16 ? + sizeof(J16SAMPLE) : (data_precision == 12 ? + sizeof(J12SAMPLE) : + sizeof(JSAMPLE)); /* debugging check */ if (end_row > ptr->rows_in_array || num_rows > ptr->maxaccess || @@ -876,7 +985,7 @@ access_virt_sarray(j_common_ptr cinfo, jvirt_sarray_ptr ptr, if (writable) ptr->first_undef_row = end_row; if (ptr->pre_zero) { - size_t bytesperrow = (size_t)ptr->samplesperrow * sizeof(JSAMPLE); + size_t bytesperrow = (size_t)ptr->samplesperrow * sample_size; undef_row -= ptr->cur_start_row; /* make indexes relative to buffer */ end_row -= ptr->cur_start_row; while (undef_row < end_row) { diff --git a/src/3rdparty/libjpeg/src/jmorecfg.h b/src/3rdparty/libjpeg/src/jmorecfg.h index b33a991914e..89c7842c871 100644 --- a/src/3rdparty/libjpeg/src/jmorecfg.h +++ b/src/3rdparty/libjpeg/src/jmorecfg.h @@ -4,8 +4,10 @@ * This file was part of the Independent JPEG Group's software: * Copyright (C) 1991-1997, Thomas G. Lane. * Modified 1997-2009 by Guido Vollbeding. + * Lossless JPEG Modifications: + * Copyright (C) 1999, Ken Murchison. * libjpeg-turbo Modifications: - * Copyright (C) 2009, 2011, 2014-2015, 2018, 2020, D. R. Commander. + * Copyright (C) 2009, 2011, 2014-2015, 2018, 2020, 2022, D. R. Commander. * For conditions of distribution and use, see the accompanying README.ijg * file. * @@ -41,31 +43,29 @@ * arrays is very slow on your hardware, you might want to change these. */ -#if BITS_IN_JSAMPLE == 8 -/* JSAMPLE should be the smallest type that will hold the values 0..255. - */ +/* JSAMPLE should be the smallest type that will hold the values 0..255. */ typedef unsigned char JSAMPLE; #define GETJSAMPLE(value) ((int)(value)) -#define MAXJSAMPLE 255 -#define CENTERJSAMPLE 128 - -#endif /* BITS_IN_JSAMPLE == 8 */ +#define MAXJSAMPLE 255 +#define CENTERJSAMPLE 128 -#if BITS_IN_JSAMPLE == 12 -/* JSAMPLE should be the smallest type that will hold the values 0..4095. - * On nearly all machines "short" will do nicely. - */ +/* J12SAMPLE should be the smallest type that will hold the values 0..4095. */ -typedef short JSAMPLE; -#define GETJSAMPLE(value) ((int)(value)) +typedef short J12SAMPLE; -#define MAXJSAMPLE 4095 -#define CENTERJSAMPLE 2048 +#define MAXJ12SAMPLE 4095 +#define CENTERJ12SAMPLE 2048 -#endif /* BITS_IN_JSAMPLE == 12 */ + +/* J16SAMPLE should be the smallest type that will hold the values 0..65535. */ + +typedef unsigned short J16SAMPLE; + +#define MAXJ16SAMPLE 65535 +#define CENTERJ16SAMPLE 32768 /* Representation of a DCT frequency coefficient. @@ -242,14 +242,16 @@ typedef int boolean; #define C_MULTISCAN_FILES_SUPPORTED /* Multiple-scan JPEG files? */ #define C_PROGRESSIVE_SUPPORTED /* Progressive JPEG? (Requires MULTISCAN)*/ +#define C_LOSSLESS_SUPPORTED /* Lossless JPEG? */ #define ENTROPY_OPT_SUPPORTED /* Optimization of entropy coding parms? */ /* Note: if you selected 12-bit data precision, it is dangerous to turn off * ENTROPY_OPT_SUPPORTED. The standard Huffman tables are only good for 8-bit * precision, so jchuff.c normally uses entropy optimization to compute * usable tables for higher precision. If you don't want to do optimization, * you'll have to supply different default Huffman tables. - * The exact same statements apply for progressive JPEG: the default tables - * don't work for progressive mode. (This may get fixed, however.) + * The exact same statements apply for progressive and lossless JPEG: + * the default tables don't work for progressive mode or lossless mode. + * (This may get fixed, however.) */ #define INPUT_SMOOTHING_SUPPORTED /* Input image smoothing option? */ @@ -257,6 +259,7 @@ typedef int boolean; #define D_MULTISCAN_FILES_SUPPORTED /* Multiple-scan JPEG files? */ #define D_PROGRESSIVE_SUPPORTED /* Progressive JPEG? (Requires MULTISCAN)*/ +#define D_LOSSLESS_SUPPORTED /* Lossless JPEG? */ #define SAVE_MARKERS_SUPPORTED /* jpeg_save_markers() needed? */ #define BLOCK_SMOOTHING_SUPPORTED /* Block smoothing? (Progressive only) */ #define IDCT_SCALING_SUPPORTED /* Output rescaling via IDCT? */ diff --git a/src/3rdparty/libjpeg/src/jpegcomp.h b/src/3rdparty/libjpeg/src/jpegapicomp.h similarity index 98% rename from src/3rdparty/libjpeg/src/jpegcomp.h rename to src/3rdparty/libjpeg/src/jpegapicomp.h index c4834ac0df9..bb3912eb2f1 100644 --- a/src/3rdparty/libjpeg/src/jpegcomp.h +++ b/src/3rdparty/libjpeg/src/jpegapicomp.h @@ -1,5 +1,5 @@ /* - * jpegcomp.h + * jpegapicomp.h * * Copyright (C) 2010, 2020, D. R. Commander. * For conditions of distribution and use, see the accompanying README.ijg diff --git a/src/3rdparty/libjpeg/src/jpegint.h b/src/3rdparty/libjpeg/src/jpegint.h index 6af9e2a179e..65414201434 100644 --- a/src/3rdparty/libjpeg/src/jpegint.h +++ b/src/3rdparty/libjpeg/src/jpegint.h @@ -4,8 +4,10 @@ * This file was part of the Independent JPEG Group's software: * Copyright (C) 1991-1997, Thomas G. Lane. * Modified 1997-2009 by Guido Vollbeding. + * Lossless JPEG Modifications: + * Copyright (C) 1999, Ken Murchison. * libjpeg-turbo Modifications: - * Copyright (C) 2015-2016, 2019, 2021, D. R. Commander. + * Copyright (C) 2015-2017, 2019, 2021-2022, D. R. Commander. * Copyright (C) 2015, Google, Inc. * Copyright (C) 2021, Alex Richardson. * For conditions of distribution and use, see the accompanying README.ijg @@ -17,6 +19,17 @@ */ +/* Representation of a spatial difference value. + * This should be a signed value of at least 16 bits; int is usually OK. + */ + +typedef int JDIFF; + +typedef JDIFF FAR *JDIFFROW; /* pointer to one row of difference values */ +typedef JDIFFROW *JDIFFARRAY; /* ptr to some rows (a 2-D diff array) */ +typedef JDIFFARRAY *JDIFFIMAGE; /* a 3-D diff array: top index is color */ + + /* Declarations for both compression & decompression */ typedef enum { /* Operating modes for buffer controllers */ @@ -61,6 +74,9 @@ typedef __UINTPTR_TYPE__ JUINTPTR; typedef size_t JUINTPTR; #endif +#define IsExtRGB(cs) \ + (cs == JCS_RGB || (cs >= JCS_EXT_RGB && cs <= JCS_EXT_ARGB)) + /* * Left shift macro that handles a negative operand without causing any * sanitizer warnings @@ -80,6 +96,7 @@ struct jpeg_comp_master { /* State variables made visible to other modules */ boolean call_pass_startup; /* True if pass_startup must be called */ boolean is_last_pass; /* True during last pass */ + boolean lossless; /* True if lossless mode is enabled */ }; /* Main buffer control (downsampled-data buffer) */ @@ -87,6 +104,12 @@ struct jpeg_c_main_controller { void (*start_pass) (j_compress_ptr cinfo, J_BUF_MODE pass_mode); void (*process_data) (j_compress_ptr cinfo, JSAMPARRAY input_buf, JDIMENSION *in_row_ctr, JDIMENSION in_rows_avail); + void (*process_data_12) (j_compress_ptr cinfo, J12SAMPARRAY input_buf, + JDIMENSION *in_row_ctr, JDIMENSION in_rows_avail); +#ifdef C_LOSSLESS_SUPPORTED + void (*process_data_16) (j_compress_ptr cinfo, J16SAMPARRAY input_buf, + JDIMENSION *in_row_ctr, JDIMENSION in_rows_avail); +#endif }; /* Compression preprocessing (downsampling input buffer control) */ @@ -97,12 +120,32 @@ struct jpeg_c_prep_controller { JSAMPIMAGE output_buf, JDIMENSION *out_row_group_ctr, JDIMENSION out_row_groups_avail); + void (*pre_process_data_12) (j_compress_ptr cinfo, J12SAMPARRAY input_buf, + JDIMENSION *in_row_ctr, + JDIMENSION in_rows_avail, + J12SAMPIMAGE output_buf, + JDIMENSION *out_row_group_ctr, + JDIMENSION out_row_groups_avail); +#ifdef C_LOSSLESS_SUPPORTED + void (*pre_process_data_16) (j_compress_ptr cinfo, J16SAMPARRAY input_buf, + JDIMENSION *in_row_ctr, + JDIMENSION in_rows_avail, + J16SAMPIMAGE output_buf, + JDIMENSION *out_row_group_ctr, + JDIMENSION out_row_groups_avail); +#endif }; -/* Coefficient buffer control */ +/* Lossy mode: Coefficient buffer control + * Lossless mode: Difference buffer control + */ struct jpeg_c_coef_controller { void (*start_pass) (j_compress_ptr cinfo, J_BUF_MODE pass_mode); boolean (*compress_data) (j_compress_ptr cinfo, JSAMPIMAGE input_buf); + boolean (*compress_data_12) (j_compress_ptr cinfo, J12SAMPIMAGE input_buf); +#ifdef C_LOSSLESS_SUPPORTED + boolean (*compress_data_16) (j_compress_ptr cinfo, J16SAMPIMAGE input_buf); +#endif }; /* Colorspace conversion */ @@ -111,6 +154,14 @@ struct jpeg_color_converter { void (*color_convert) (j_compress_ptr cinfo, JSAMPARRAY input_buf, JSAMPIMAGE output_buf, JDIMENSION output_row, int num_rows); + void (*color_convert_12) (j_compress_ptr cinfo, J12SAMPARRAY input_buf, + J12SAMPIMAGE output_buf, JDIMENSION output_row, + int num_rows); +#ifdef C_LOSSLESS_SUPPORTED + void (*color_convert_16) (j_compress_ptr cinfo, J16SAMPARRAY input_buf, + J16SAMPIMAGE output_buf, JDIMENSION output_row, + int num_rows); +#endif }; /* Downsampling */ @@ -119,24 +170,47 @@ struct jpeg_downsampler { void (*downsample) (j_compress_ptr cinfo, JSAMPIMAGE input_buf, JDIMENSION in_row_index, JSAMPIMAGE output_buf, JDIMENSION out_row_group_index); + void (*downsample_12) (j_compress_ptr cinfo, J12SAMPIMAGE input_buf, + JDIMENSION in_row_index, J12SAMPIMAGE output_buf, + JDIMENSION out_row_group_index); +#ifdef C_LOSSLESS_SUPPORTED + void (*downsample_16) (j_compress_ptr cinfo, J16SAMPIMAGE input_buf, + JDIMENSION in_row_index, J16SAMPIMAGE output_buf, + JDIMENSION out_row_group_index); +#endif boolean need_context_rows; /* TRUE if need rows above & below */ }; -/* Forward DCT (also controls coefficient quantization) */ +/* Lossy mode: Forward DCT (also controls coefficient quantization) + * Lossless mode: Prediction, sample differencing, and point transform + */ struct jpeg_forward_dct { void (*start_pass) (j_compress_ptr cinfo); + + /* Lossy mode */ /* perhaps this should be an array??? */ void (*forward_DCT) (j_compress_ptr cinfo, jpeg_component_info *compptr, JSAMPARRAY sample_data, JBLOCKROW coef_blocks, JDIMENSION start_row, JDIMENSION start_col, JDIMENSION num_blocks); + void (*forward_DCT_12) (j_compress_ptr cinfo, jpeg_component_info *compptr, + J12SAMPARRAY sample_data, JBLOCKROW coef_blocks, + JDIMENSION start_row, JDIMENSION start_col, + JDIMENSION num_blocks); }; /* Entropy encoding */ struct jpeg_entropy_encoder { void (*start_pass) (j_compress_ptr cinfo, boolean gather_statistics); + + /* Lossy mode */ boolean (*encode_mcu) (j_compress_ptr cinfo, JBLOCKROW *MCU_data); + /* Lossless mode */ + JDIMENSION (*encode_mcus) (j_compress_ptr cinfo, JDIFFIMAGE diff_buf, + JDIMENSION MCU_row_num, JDIMENSION MCU_col_num, + JDIMENSION nMCU); + void (*finish_pass) (j_compress_ptr cinfo); }; @@ -164,6 +238,7 @@ struct jpeg_decomp_master { /* State variables made visible to other modules */ boolean is_dummy_pass; /* True during 1st pass for 2-pass quant */ + boolean lossless; /* True if decompressing a lossless image */ /* Partial decompression variables */ JDIMENSION first_iMCU_col; @@ -193,14 +268,36 @@ struct jpeg_d_main_controller { void (*start_pass) (j_decompress_ptr cinfo, J_BUF_MODE pass_mode); void (*process_data) (j_decompress_ptr cinfo, JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail); + void (*process_data_12) (j_decompress_ptr cinfo, J12SAMPARRAY output_buf, + JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail); +#ifdef D_LOSSLESS_SUPPORTED + void (*process_data_16) (j_decompress_ptr cinfo, J16SAMPARRAY output_buf, + JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail); +#endif }; -/* Coefficient buffer control */ +/* Lossy mode: Coefficient buffer control + * Lossless mode: Difference buffer control + */ struct jpeg_d_coef_controller { void (*start_input_pass) (j_decompress_ptr cinfo); int (*consume_data) (j_decompress_ptr cinfo); void (*start_output_pass) (j_decompress_ptr cinfo); int (*decompress_data) (j_decompress_ptr cinfo, JSAMPIMAGE output_buf); + int (*decompress_data_12) (j_decompress_ptr cinfo, J12SAMPIMAGE output_buf); +#ifdef D_LOSSLESS_SUPPORTED + int (*decompress_data_16) (j_decompress_ptr cinfo, J16SAMPIMAGE output_buf); +#endif + + /* These variables keep track of the current location of the input side. */ + /* cinfo->input_iMCU_row is also used for this. */ + JDIMENSION MCU_ctr; /* counts MCUs processed in current row */ + int MCU_vert_offset; /* counts MCU rows within iMCU row */ + int MCU_rows_per_iMCU_row; /* number of such rows needed */ + + /* The output side's location is represented by cinfo->output_iMCU_row. */ + + /* Lossy mode */ /* Pointer to array of coefficient virtual arrays, or NULL if none */ jvirt_barray_ptr *coef_arrays; }; @@ -213,6 +310,20 @@ struct jpeg_d_post_controller { JDIMENSION in_row_groups_avail, JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail); + void (*post_process_data_12) (j_decompress_ptr cinfo, J12SAMPIMAGE input_buf, + JDIMENSION *in_row_group_ctr, + JDIMENSION in_row_groups_avail, + J12SAMPARRAY output_buf, + JDIMENSION *out_row_ctr, + JDIMENSION out_rows_avail); +#ifdef D_LOSSLESS_SUPPORTED + void (*post_process_data_16) (j_decompress_ptr cinfo, J16SAMPIMAGE input_buf, + JDIMENSION *in_row_group_ctr, + JDIMENSION in_row_groups_avail, + J16SAMPARRAY output_buf, + JDIMENSION *out_row_ctr, + JDIMENSION out_rows_avail); +#endif }; /* Marker reading & parsing */ @@ -238,24 +349,42 @@ struct jpeg_marker_reader { /* Entropy decoding */ struct jpeg_entropy_decoder { void (*start_pass) (j_decompress_ptr cinfo); + + /* Lossy mode */ boolean (*decode_mcu) (j_decompress_ptr cinfo, JBLOCKROW *MCU_data); + /* Lossless mode */ + JDIMENSION (*decode_mcus) (j_decompress_ptr cinfo, JDIFFIMAGE diff_buf, + JDIMENSION MCU_row_num, JDIMENSION MCU_col_num, + JDIMENSION nMCU); + boolean (*process_restart) (j_decompress_ptr cinfo); /* This is here to share code between baseline and progressive decoders; */ /* other modules probably should not use it */ boolean insufficient_data; /* set TRUE after emitting warning */ }; -/* Inverse DCT (also performs dequantization) */ +/* Lossy mode: Inverse DCT (also performs dequantization) + * Lossless mode: Prediction, sample undifferencing, point transform, and + * sample size scaling + */ typedef void (*inverse_DCT_method_ptr) (j_decompress_ptr cinfo, jpeg_component_info *compptr, JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col); +typedef void (*inverse_DCT_12_method_ptr) (j_decompress_ptr cinfo, + jpeg_component_info *compptr, + JCOEFPTR coef_block, + J12SAMPARRAY output_buf, + JDIMENSION output_col); struct jpeg_inverse_dct { void (*start_pass) (j_decompress_ptr cinfo); + + /* Lossy mode */ /* It is useful to allow each component to have a separate IDCT method. */ inverse_DCT_method_ptr inverse_DCT[MAX_COMPONENTS]; + inverse_DCT_12_method_ptr inverse_DCT_12[MAX_COMPONENTS]; }; /* Upsampling (note that upsampler must also call color converter) */ @@ -265,6 +394,16 @@ struct jpeg_upsampler { JDIMENSION *in_row_group_ctr, JDIMENSION in_row_groups_avail, JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail); + void (*upsample_12) (j_decompress_ptr cinfo, J12SAMPIMAGE input_buf, + JDIMENSION *in_row_group_ctr, + JDIMENSION in_row_groups_avail, J12SAMPARRAY output_buf, + JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail); +#ifdef D_LOSSLESS_SUPPORTED + void (*upsample_16) (j_decompress_ptr cinfo, J16SAMPIMAGE input_buf, + JDIMENSION *in_row_group_ctr, + JDIMENSION in_row_groups_avail, J16SAMPARRAY output_buf, + JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail); +#endif boolean need_context_rows; /* TRUE if need rows above & below */ }; @@ -275,6 +414,14 @@ struct jpeg_color_deconverter { void (*color_convert) (j_decompress_ptr cinfo, JSAMPIMAGE input_buf, JDIMENSION input_row, JSAMPARRAY output_buf, int num_rows); + void (*color_convert_12) (j_decompress_ptr cinfo, J12SAMPIMAGE input_buf, + JDIMENSION input_row, J12SAMPARRAY output_buf, + int num_rows); +#ifdef D_LOSSLESS_SUPPORTED + void (*color_convert_16) (j_decompress_ptr cinfo, J16SAMPIMAGE input_buf, + JDIMENSION input_row, J16SAMPARRAY output_buf, + int num_rows); +#endif }; /* Color quantization or color precision reduction */ @@ -282,6 +429,8 @@ struct jpeg_color_quantizer { void (*start_pass) (j_decompress_ptr cinfo, boolean is_pre_scan); void (*color_quantize) (j_decompress_ptr cinfo, JSAMPARRAY input_buf, JSAMPARRAY output_buf, int num_rows); + void (*color_quantize_12) (j_decompress_ptr cinfo, J12SAMPARRAY input_buf, + J12SAMPARRAY output_buf, int num_rows); void (*finish_pass) (j_decompress_ptr cinfo); void (*new_color_map) (j_decompress_ptr cinfo); }; @@ -323,36 +472,95 @@ EXTERN(void) jinit_c_master_control(j_compress_ptr cinfo, boolean transcode_only); EXTERN(void) jinit_c_main_controller(j_compress_ptr cinfo, boolean need_full_buffer); +EXTERN(void) j12init_c_main_controller(j_compress_ptr cinfo, + boolean need_full_buffer); EXTERN(void) jinit_c_prep_controller(j_compress_ptr cinfo, boolean need_full_buffer); +EXTERN(void) j12init_c_prep_controller(j_compress_ptr cinfo, + boolean need_full_buffer); EXTERN(void) jinit_c_coef_controller(j_compress_ptr cinfo, boolean need_full_buffer); +EXTERN(void) j12init_c_coef_controller(j_compress_ptr cinfo, + boolean need_full_buffer); EXTERN(void) jinit_color_converter(j_compress_ptr cinfo); +EXTERN(void) j12init_color_converter(j_compress_ptr cinfo); EXTERN(void) jinit_downsampler(j_compress_ptr cinfo); +EXTERN(void) j12init_downsampler(j_compress_ptr cinfo); EXTERN(void) jinit_forward_dct(j_compress_ptr cinfo); +EXTERN(void) j12init_forward_dct(j_compress_ptr cinfo); EXTERN(void) jinit_huff_encoder(j_compress_ptr cinfo); EXTERN(void) jinit_phuff_encoder(j_compress_ptr cinfo); EXTERN(void) jinit_arith_encoder(j_compress_ptr cinfo); EXTERN(void) jinit_marker_writer(j_compress_ptr cinfo); +#ifdef C_LOSSLESS_SUPPORTED +EXTERN(void) j16init_c_main_controller(j_compress_ptr cinfo, + boolean need_full_buffer); +EXTERN(void) j16init_c_prep_controller(j_compress_ptr cinfo, + boolean need_full_buffer); +EXTERN(void) j16init_color_converter(j_compress_ptr cinfo); +EXTERN(void) j16init_downsampler(j_compress_ptr cinfo); +EXTERN(void) jinit_c_diff_controller(j_compress_ptr cinfo, + boolean need_full_buffer); +EXTERN(void) j12init_c_diff_controller(j_compress_ptr cinfo, + boolean need_full_buffer); +EXTERN(void) j16init_c_diff_controller(j_compress_ptr cinfo, + boolean need_full_buffer); +EXTERN(void) jinit_lhuff_encoder(j_compress_ptr cinfo); +EXTERN(void) jinit_lossless_compressor(j_compress_ptr cinfo); +EXTERN(void) j12init_lossless_compressor(j_compress_ptr cinfo); +EXTERN(void) j16init_lossless_compressor(j_compress_ptr cinfo); +#endif + /* Decompression module initialization routines */ EXTERN(void) jinit_master_decompress(j_decompress_ptr cinfo); EXTERN(void) jinit_d_main_controller(j_decompress_ptr cinfo, boolean need_full_buffer); +EXTERN(void) j12init_d_main_controller(j_decompress_ptr cinfo, + boolean need_full_buffer); EXTERN(void) jinit_d_coef_controller(j_decompress_ptr cinfo, boolean need_full_buffer); +EXTERN(void) j12init_d_coef_controller(j_decompress_ptr cinfo, + boolean need_full_buffer); EXTERN(void) jinit_d_post_controller(j_decompress_ptr cinfo, boolean need_full_buffer); +EXTERN(void) j12init_d_post_controller(j_decompress_ptr cinfo, + boolean need_full_buffer); EXTERN(void) jinit_input_controller(j_decompress_ptr cinfo); EXTERN(void) jinit_marker_reader(j_decompress_ptr cinfo); EXTERN(void) jinit_huff_decoder(j_decompress_ptr cinfo); EXTERN(void) jinit_phuff_decoder(j_decompress_ptr cinfo); EXTERN(void) jinit_arith_decoder(j_decompress_ptr cinfo); EXTERN(void) jinit_inverse_dct(j_decompress_ptr cinfo); +EXTERN(void) j12init_inverse_dct(j_decompress_ptr cinfo); EXTERN(void) jinit_upsampler(j_decompress_ptr cinfo); +EXTERN(void) j12init_upsampler(j_decompress_ptr cinfo); EXTERN(void) jinit_color_deconverter(j_decompress_ptr cinfo); +EXTERN(void) j12init_color_deconverter(j_decompress_ptr cinfo); EXTERN(void) jinit_1pass_quantizer(j_decompress_ptr cinfo); +EXTERN(void) j12init_1pass_quantizer(j_decompress_ptr cinfo); EXTERN(void) jinit_2pass_quantizer(j_decompress_ptr cinfo); +EXTERN(void) j12init_2pass_quantizer(j_decompress_ptr cinfo); EXTERN(void) jinit_merged_upsampler(j_decompress_ptr cinfo); +EXTERN(void) j12init_merged_upsampler(j_decompress_ptr cinfo); +#ifdef D_LOSSLESS_SUPPORTED +EXTERN(void) j16init_d_main_controller(j_decompress_ptr cinfo, + boolean need_full_buffer); +EXTERN(void) j16init_d_post_controller(j_decompress_ptr cinfo, + boolean need_full_buffer); +EXTERN(void) j16init_upsampler(j_decompress_ptr cinfo); +EXTERN(void) j16init_color_deconverter(j_decompress_ptr cinfo); +EXTERN(void) jinit_d_diff_controller(j_decompress_ptr cinfo, + boolean need_full_buffer); +EXTERN(void) j12init_d_diff_controller(j_decompress_ptr cinfo, + boolean need_full_buffer); +EXTERN(void) j16init_d_diff_controller(j_decompress_ptr cinfo, + boolean need_full_buffer); +EXTERN(void) jinit_lhuff_decoder(j_decompress_ptr cinfo); +EXTERN(void) jinit_lossless_decompressor(j_decompress_ptr cinfo); +EXTERN(void) j12init_lossless_decompressor(j_decompress_ptr cinfo); +EXTERN(void) j16init_lossless_decompressor(j_decompress_ptr cinfo); +#endif + /* Memory manager initialization */ EXTERN(void) jinit_memory_mgr(j_common_ptr cinfo); @@ -362,6 +570,14 @@ EXTERN(long) jround_up(long a, long b); EXTERN(void) jcopy_sample_rows(JSAMPARRAY input_array, int source_row, JSAMPARRAY output_array, int dest_row, int num_rows, JDIMENSION num_cols); +EXTERN(void) j12copy_sample_rows(J12SAMPARRAY input_array, int source_row, + J12SAMPARRAY output_array, int dest_row, + int num_rows, JDIMENSION num_cols); +#if defined(C_LOSSLESS_SUPPORTED) || defined(D_LOSSLESS_SUPPORTED) +EXTERN(void) j16copy_sample_rows(J16SAMPARRAY input_array, int source_row, + J16SAMPARRAY output_array, int dest_row, + int num_rows, JDIMENSION num_cols); +#endif EXTERN(void) jcopy_block_row(JBLOCKROW input_row, JBLOCKROW output_row, JDIMENSION num_blocks); EXTERN(void) jzero_far(void *target, size_t bytestozero); diff --git a/src/3rdparty/libjpeg/src/jpeglib.h b/src/3rdparty/libjpeg/src/jpeglib.h index d7664f06309..8c813097378 100644 --- a/src/3rdparty/libjpeg/src/jpeglib.h +++ b/src/3rdparty/libjpeg/src/jpeglib.h @@ -4,8 +4,10 @@ * This file was part of the Independent JPEG Group's software: * Copyright (C) 1991-1998, Thomas G. Lane. * Modified 2002-2009 by Guido Vollbeding. + * Lossless JPEG Modifications: + * Copyright (C) 1999, Ken Murchison. * libjpeg-turbo Modifications: - * Copyright (C) 2009-2011, 2013-2014, 2016-2017, 2020, D. R. Commander. + * Copyright (C) 2009-2011, 2013-2014, 2016-2017, 2020, 2022, D. R. Commander. * Copyright (C) 2015, Google, Inc. * For conditions of distribution and use, see the accompanying README.ijg * file. @@ -43,6 +45,13 @@ extern "C" { * if you want to be compatible. */ +/* NOTE: In lossless mode, an MCU contains one or more samples rather than one + * or more 8x8 DCT blocks, so the term "data unit" is used to generically + * describe a sample in lossless mode or an 8x8 DCT block in lossy mode. To + * preserve backward API/ABI compatibility, the field and macro names retain + * the "block" terminology. + */ + #define DCTSIZE 8 /* The basic DCT block is 8x8 samples */ #define DCTSIZE2 64 /* DCTSIZE squared; # of elements in a block */ #define NUM_QUANT_TBLS 4 /* Quantization tables are numbered 0..3 */ @@ -57,9 +66,9 @@ extern "C" { * we strongly discourage changing C_MAX_BLOCKS_IN_MCU; just because Adobe * sometimes emits noncompliant files doesn't mean you should too. */ -#define C_MAX_BLOCKS_IN_MCU 10 /* compressor's limit on blocks per MCU */ +#define C_MAX_BLOCKS_IN_MCU 10 /* compressor's limit on data units/MCU */ #ifndef D_MAX_BLOCKS_IN_MCU -#define D_MAX_BLOCKS_IN_MCU 10 /* decompressor's limit on blocks per MCU */ +#define D_MAX_BLOCKS_IN_MCU 10 /* decompressor's limit on data units/MCU */ #endif @@ -70,6 +79,20 @@ typedef JSAMPLE *JSAMPROW; /* ptr to one image row of pixel samples. */ typedef JSAMPROW *JSAMPARRAY; /* ptr to some rows (a 2-D sample array) */ typedef JSAMPARRAY *JSAMPIMAGE; /* a 3-D sample array: top index is color */ +typedef J12SAMPLE *J12SAMPROW; /* ptr to one image row of 12-bit pixel + samples. */ +typedef J12SAMPROW *J12SAMPARRAY; /* ptr to some 12-bit sample rows (a 2-D + 12-bit sample array) */ +typedef J12SAMPARRAY *J12SAMPIMAGE; /* a 3-D 12-bit sample array: top index is + color */ + +typedef J16SAMPLE *J16SAMPROW; /* ptr to one image row of 16-bit pixel + samples. */ +typedef J16SAMPROW *J16SAMPARRAY; /* ptr to some 16-bit sample rows (a 2-D + 16-bit sample array) */ +typedef J16SAMPARRAY *J16SAMPIMAGE; /* a 3-D 16-bit sample array: top index is + color */ + typedef JCOEF JBLOCK[DCTSIZE2]; /* one block of coefficients */ typedef JBLOCK *JBLOCKROW; /* pointer to one row of coefficient blocks */ typedef JBLOCKROW *JBLOCKARRAY; /* a 2-D array of coefficient blocks */ @@ -135,17 +158,20 @@ typedef struct { /* Remaining fields should be treated as private by applications. */ /* These values are computed during compression or decompression startup: */ - /* Component's size in DCT blocks. - * Any dummy blocks added to complete an MCU are not counted; therefore - * these values do not depend on whether a scan is interleaved or not. + /* Component's size in data units. + * In lossy mode, any dummy blocks added to complete an MCU are not counted; + * therefore these values do not depend on whether a scan is interleaved or + * not. In lossless mode, these are always equal to the image width and + * height. */ JDIMENSION width_in_blocks; JDIMENSION height_in_blocks; - /* Size of a DCT block in samples. Always DCTSIZE for compression. - * For decompression this is the size of the output from one DCT block, + /* Size of a data unit in samples. Always DCTSIZE for lossy compression. + * For lossy decompression this is the size of the output from one DCT block, * reflecting any scaling we choose to apply during the IDCT step. - * Values from 1 to 16 are supported. - * Note that different components may receive different IDCT scalings. + * Values from 1 to 16 are supported. Note that different components may + * receive different IDCT scalings. In lossless mode, this is always equal + * to 1. */ #if JPEG_LIB_VERSION >= 70 int DCT_h_scaled_size; @@ -156,8 +182,10 @@ typedef struct { /* The downsampled dimensions are the component's actual, unpadded number * of samples at the main buffer (preprocessing/compression interface), thus * downsampled_width = ceil(image_width * Hi/Hmax) - * and similarly for height. For decompression, IDCT scaling is included, so + * and similarly for height. For lossy decompression, IDCT scaling is + * included, so * downsampled_width = ceil(image_width * Hi/Hmax * DCT_[h_]scaled_size/DCTSIZE) + * In lossless mode, these are always equal to the image width and height. */ JDIMENSION downsampled_width; /* actual width in samples */ JDIMENSION downsampled_height; /* actual height in samples */ @@ -169,12 +197,12 @@ typedef struct { /* These values are computed before starting a scan of the component. */ /* The decompressor output side may not use these variables. */ - int MCU_width; /* number of blocks per MCU, horizontally */ - int MCU_height; /* number of blocks per MCU, vertically */ + int MCU_width; /* number of data units per MCU, horizontally */ + int MCU_height; /* number of data units per MCU, vertically */ int MCU_blocks; /* MCU_width * MCU_height */ int MCU_sample_width; /* MCU width in samples, MCU_width*DCT_[h_]scaled_size */ - int last_col_width; /* # of non-dummy blocks across in last MCU */ - int last_row_height; /* # of non-dummy blocks down in last MCU */ + int last_col_width; /* # of non-dummy data units across in last MCU */ + int last_row_height; /* # of non-dummy data units down in last MCU */ /* Saved quantization table for component; NULL if none yet saved. * See jdinput.c comments about the need for this information. @@ -192,8 +220,12 @@ typedef struct { typedef struct { int comps_in_scan; /* number of components encoded in this scan */ int component_index[MAX_COMPS_IN_SCAN]; /* their SOF/comp_info[] indexes */ - int Ss, Se; /* progressive JPEG spectral selection parms */ - int Ah, Al; /* progressive JPEG successive approx. parms */ + int Ss, Se; /* progressive JPEG spectral selection parms + (Ss is the predictor selection value in + lossless mode) */ + int Ah, Al; /* progressive JPEG successive approx. parms + (Al is the point transform value in lossless + mode) */ } jpeg_scan_info; /* The decompressor can save APPn and COM markers in a list of these: */ @@ -419,11 +451,13 @@ struct jpeg_compress_struct { int min_DCT_v_scaled_size; /* smallest DCT_v_scaled_size of any component */ #endif - JDIMENSION total_iMCU_rows; /* # of iMCU rows to be input to coef ctlr */ - /* The coefficient controller receives data in units of MCU rows as defined - * for fully interleaved scans (whether the JPEG file is interleaved or not). - * There are v_samp_factor * DCTSIZE sample rows of each component in an - * "iMCU" (interleaved MCU) row. + JDIMENSION total_iMCU_rows; /* # of iMCU rows to be input to coefficient or + difference controller */ + /* The coefficient or difference controller receives data in units of MCU + * rows as defined for fully interleaved scans (whether the JPEG file is + * interleaved or not). In lossy mode, there are v_samp_factor * DCTSIZE + * sample rows of each component in an "iMCU" (interleaved MCU) row. In + * lossless mode, total_iMCU_rows is always equal to the image height. */ /* @@ -437,12 +471,13 @@ struct jpeg_compress_struct { JDIMENSION MCUs_per_row; /* # of MCUs across the image */ JDIMENSION MCU_rows_in_scan; /* # of MCU rows in the image */ - int blocks_in_MCU; /* # of DCT blocks per MCU */ + int blocks_in_MCU; /* # of data units per MCU */ int MCU_membership[C_MAX_BLOCKS_IN_MCU]; /* MCU_membership[i] is index in cur_comp_info of component owning */ - /* i'th block in an MCU */ + /* i'th data unit in an MCU */ - int Ss, Se, Ah, Al; /* progressive JPEG parameters for scan */ + int Ss, Se, Ah, Al; /* progressive/lossless JPEG parameters for + scan */ #if JPEG_LIB_VERSION >= 80 int block_size; /* the basic DCT block size: 1..16 */ @@ -537,7 +572,12 @@ struct jpeg_decompress_struct { * The map has out_color_components rows and actual_number_of_colors columns. */ int actual_number_of_colors; /* number of entries in use */ - JSAMPARRAY colormap; /* The color map as a 2-D pixel array */ + JSAMPARRAY colormap; /* The color map as a 2-D pixel array + If data_precision is 12 or 16, then this is + actually a J12SAMPARRAY or a J16SAMPARRAY, + so callers must type-cast it in order to + read/write 12-bit or 16-bit samples from/to + the array. */ /* State variables: these variables indicate the progress of decompression. * The application may examine these but must not modify them. @@ -647,15 +687,21 @@ struct jpeg_decompress_struct { #endif JDIMENSION total_iMCU_rows; /* # of iMCU rows in image */ - /* The coefficient controller's input and output progress is measured in - * units of "iMCU" (interleaved MCU) rows. These are the same as MCU rows - * in fully interleaved JPEG scans, but are used whether the scan is - * interleaved or not. We define an iMCU row as v_samp_factor DCT block - * rows of each component. Therefore, the IDCT output contains + /* The coefficient or difference controller's input and output progress is + * measured in units of "iMCU" (interleaved MCU) rows. These are the same as + * MCU rows in fully interleaved JPEG scans, but are used whether the scan is + * interleaved or not. In lossy mode, we define an iMCU row as v_samp_factor + * DCT block rows of each component. Therefore, the IDCT output contains * v_samp_factor*DCT_[v_]scaled_size sample rows of a component per iMCU row. + * In lossless mode, total_iMCU_rows is always equal to the image height. */ - JSAMPLE *sample_range_limit; /* table for fast range-limiting */ + JSAMPLE *sample_range_limit; /* table for fast range-limiting + If data_precision is 12 or 16, then this is + actually a J12SAMPLE pointer or a J16SAMPLE + pointer, so callers must type-cast it in + order to read 12-bit or 16-bit samples from + the array. */ /* * These fields are valid during any one scan. @@ -669,12 +715,13 @@ struct jpeg_decompress_struct { JDIMENSION MCUs_per_row; /* # of MCUs across the image */ JDIMENSION MCU_rows_in_scan; /* # of MCU rows in the image */ - int blocks_in_MCU; /* # of DCT blocks per MCU */ + int blocks_in_MCU; /* # of data units per MCU */ int MCU_membership[D_MAX_BLOCKS_IN_MCU]; /* MCU_membership[i] is index in cur_comp_info of component owning */ - /* i'th block in an MCU */ + /* i'th data unit in an MCU */ - int Ss, Se, Ah, Al; /* progressive JPEG parameters for scan */ + int Ss, Se, Ah, Al; /* progressive/lossless JPEG parameters for + scan */ #if JPEG_LIB_VERSION >= 80 /* These fields are derived from Se of first SOS marker. @@ -835,6 +882,11 @@ struct jpeg_memory_mgr { void *(*alloc_small) (j_common_ptr cinfo, int pool_id, size_t sizeofobject); void *(*alloc_large) (j_common_ptr cinfo, int pool_id, size_t sizeofobject); + /* If cinfo->data_precision is 12 or 16, then this method and the + * access_virt_sarray method actually return a J12SAMPARRAY or a + * J16SAMPARRAY, so callers must type-cast the return value in order to + * read/write 12-bit or 16-bit samples from/to the array. + */ JSAMPARRAY (*alloc_sarray) (j_common_ptr cinfo, int pool_id, JDIMENSION samplesperrow, JDIMENSION numrows); JBLOCKARRAY (*alloc_barray) (j_common_ptr cinfo, int pool_id, @@ -916,13 +968,11 @@ EXTERN(void) jpeg_destroy_decompress(j_decompress_ptr cinfo); EXTERN(void) jpeg_stdio_dest(j_compress_ptr cinfo, FILE *outfile); EXTERN(void) jpeg_stdio_src(j_decompress_ptr cinfo, FILE *infile); -#if JPEG_LIB_VERSION >= 80 || defined(MEM_SRCDST_SUPPORTED) /* Data source and destination managers: memory buffers. */ EXTERN(void) jpeg_mem_dest(j_compress_ptr cinfo, unsigned char **outbuffer, unsigned long *outsize); EXTERN(void) jpeg_mem_src(j_decompress_ptr cinfo, const unsigned char *inbuffer, unsigned long insize); -#endif /* Default parameter setup for compression */ EXTERN(void) jpeg_set_defaults(j_compress_ptr cinfo); @@ -942,6 +992,9 @@ EXTERN(void) jpeg_add_quant_table(j_compress_ptr cinfo, int which_tbl, const unsigned int *basic_table, int scale_factor, boolean force_baseline); EXTERN(int) jpeg_quality_scaling(int quality); +EXTERN(void) jpeg_enable_lossless(j_compress_ptr cinfo, + int predictor_selection_value, + int point_transform); EXTERN(void) jpeg_simple_progression(j_compress_ptr cinfo); EXTERN(void) jpeg_suppress_tables(j_compress_ptr cinfo, boolean suppress); EXTERN(JQUANT_TBL *) jpeg_alloc_quant_table(j_common_ptr cinfo); @@ -953,6 +1006,12 @@ EXTERN(void) jpeg_start_compress(j_compress_ptr cinfo, EXTERN(JDIMENSION) jpeg_write_scanlines(j_compress_ptr cinfo, JSAMPARRAY scanlines, JDIMENSION num_lines); +EXTERN(JDIMENSION) jpeg12_write_scanlines(j_compress_ptr cinfo, + J12SAMPARRAY scanlines, + JDIMENSION num_lines); +EXTERN(JDIMENSION) jpeg16_write_scanlines(j_compress_ptr cinfo, + J16SAMPARRAY scanlines, + JDIMENSION num_lines); EXTERN(void) jpeg_finish_compress(j_compress_ptr cinfo); #if JPEG_LIB_VERSION >= 70 @@ -963,6 +1022,9 @@ EXTERN(void) jpeg_calc_jpeg_dimensions(j_compress_ptr cinfo); /* Replaces jpeg_write_scanlines when writing raw downsampled data. */ EXTERN(JDIMENSION) jpeg_write_raw_data(j_compress_ptr cinfo, JSAMPIMAGE data, JDIMENSION num_lines); +EXTERN(JDIMENSION) jpeg12_write_raw_data(j_compress_ptr cinfo, + J12SAMPIMAGE data, + JDIMENSION num_lines); /* Write a special marker. See libjpeg.txt concerning safe usage. */ EXTERN(void) jpeg_write_marker(j_compress_ptr cinfo, int marker, @@ -998,15 +1060,28 @@ EXTERN(boolean) jpeg_start_decompress(j_decompress_ptr cinfo); EXTERN(JDIMENSION) jpeg_read_scanlines(j_decompress_ptr cinfo, JSAMPARRAY scanlines, JDIMENSION max_lines); +EXTERN(JDIMENSION) jpeg12_read_scanlines(j_decompress_ptr cinfo, + J12SAMPARRAY scanlines, + JDIMENSION max_lines); +EXTERN(JDIMENSION) jpeg16_read_scanlines(j_decompress_ptr cinfo, + J16SAMPARRAY scanlines, + JDIMENSION max_lines); EXTERN(JDIMENSION) jpeg_skip_scanlines(j_decompress_ptr cinfo, JDIMENSION num_lines); +EXTERN(JDIMENSION) jpeg12_skip_scanlines(j_decompress_ptr cinfo, + JDIMENSION num_lines); EXTERN(void) jpeg_crop_scanline(j_decompress_ptr cinfo, JDIMENSION *xoffset, JDIMENSION *width); +EXTERN(void) jpeg12_crop_scanline(j_decompress_ptr cinfo, JDIMENSION *xoffset, + JDIMENSION *width); EXTERN(boolean) jpeg_finish_decompress(j_decompress_ptr cinfo); /* Replaces jpeg_read_scanlines when reading raw downsampled data. */ EXTERN(JDIMENSION) jpeg_read_raw_data(j_decompress_ptr cinfo, JSAMPIMAGE data, JDIMENSION max_lines); +EXTERN(JDIMENSION) jpeg12_read_raw_data(j_decompress_ptr cinfo, + J12SAMPIMAGE data, + JDIMENSION max_lines); /* Additional entry points for buffered-image mode. */ EXTERN(boolean) jpeg_has_multiple_scans(j_decompress_ptr cinfo); diff --git a/src/3rdparty/libjpeg/src/jquant1.c b/src/3rdparty/libjpeg/src/jquant1.c index 73b83e16e5c..2e914b919c6 100644 --- a/src/3rdparty/libjpeg/src/jquant1.c +++ b/src/3rdparty/libjpeg/src/jquant1.c @@ -4,7 +4,7 @@ * This file was part of the Independent JPEG Group's software: * Copyright (C) 1991-1996, Thomas G. Lane. * libjpeg-turbo Modifications: - * Copyright (C) 2009, 2015, D. R. Commander. + * Copyright (C) 2009, 2015, 2022-2023, D. R. Commander. * For conditions of distribution and use, see the accompanying README.ijg * file. * @@ -16,8 +16,9 @@ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" +#include "jsamplecomp.h" -#ifdef QUANT_1PASS_SUPPORTED +#if defined(QUANT_1PASS_SUPPORTED) && BITS_IN_JSAMPLE != 16 /* @@ -66,7 +67,7 @@ * worse, since the dither may be too much or too little at a given point. * * The normal calculation would be to form pixel value + dither, range-limit - * this to 0..MAXJSAMPLE, and then index into the colorindex table as usual. + * this to 0.._MAXJSAMPLE, and then index into the colorindex table as usual. * We can skip the separate range-limiting step by extending the colorindex * table in both directions. */ @@ -144,13 +145,13 @@ typedef struct { struct jpeg_color_quantizer pub; /* public fields */ /* Initially allocated colormap is saved here */ - JSAMPARRAY sv_colormap; /* The color map as a 2-D pixel array */ + _JSAMPARRAY sv_colormap; /* The color map as a 2-D pixel array */ int sv_actual; /* number of entries in use */ - JSAMPARRAY colorindex; /* Precomputed mapping for speed */ + _JSAMPARRAY colorindex; /* Precomputed mapping for speed */ /* colorindex[i][j] = index of color closest to pixel value j in component i, * premultiplied as described above. Since colormap indexes must fit into - * JSAMPLEs, the entries of this array will too. + * _JSAMPLEs, the entries of this array will too. */ boolean is_padded; /* is the colorindex padded for odither? */ @@ -248,24 +249,24 @@ select_ncolors(j_decompress_ptr cinfo, int Ncolors[]) LOCAL(int) output_value(j_decompress_ptr cinfo, int ci, int j, int maxj) /* Return j'th output value, where j will range from 0 to maxj */ -/* The output values must fall in 0..MAXJSAMPLE in increasing order */ +/* The output values must fall in 0.._MAXJSAMPLE in increasing order */ { - /* We always provide values 0 and MAXJSAMPLE for each component; + /* We always provide values 0 and _MAXJSAMPLE for each component; * any additional values are equally spaced between these limits. * (Forcing the upper and lower values to the limits ensures that * dithering can't produce a color outside the selected gamut.) */ - return (int)(((JLONG)j * MAXJSAMPLE + maxj / 2) / maxj); + return (int)(((JLONG)j * _MAXJSAMPLE + maxj / 2) / maxj); } LOCAL(int) largest_input_value(j_decompress_ptr cinfo, int ci, int j, int maxj) /* Return largest input value that should map to j'th output value */ -/* Must have largest(j=0) >= 0, and largest(j=maxj) >= MAXJSAMPLE */ +/* Must have largest(j=0) >= 0, and largest(j=maxj) >= _MAXJSAMPLE */ { /* Breakpoints are halfway between values returned by output_value */ - return (int)(((JLONG)(2 * j + 1) * MAXJSAMPLE + maxj) / (2 * maxj)); + return (int)(((JLONG)(2 * j + 1) * _MAXJSAMPLE + maxj) / (2 * maxj)); } @@ -277,7 +278,7 @@ LOCAL(void) create_colormap(j_decompress_ptr cinfo) { my_cquantize_ptr cquantize = (my_cquantize_ptr)cinfo->cquantize; - JSAMPARRAY colormap; /* Created colormap */ + _JSAMPARRAY colormap; /* Created colormap */ int total_colors; /* Number of distinct output colors */ int i, j, k, nci, blksize, blkdist, ptr, val; @@ -296,7 +297,7 @@ create_colormap(j_decompress_ptr cinfo) /* The colors are ordered in the map in standard row-major order, */ /* i.e. rightmost (highest-indexed) color changes most rapidly. */ - colormap = (*cinfo->mem->alloc_sarray) + colormap = (_JSAMPARRAY)(*cinfo->mem->alloc_sarray) ((j_common_ptr)cinfo, JPOOL_IMAGE, (JDIMENSION)total_colors, (JDIMENSION)cinfo->out_color_components); @@ -315,7 +316,7 @@ create_colormap(j_decompress_ptr cinfo) for (ptr = j * blksize; ptr < total_colors; ptr += blkdist) { /* fill in blksize entries beginning at ptr */ for (k = 0; k < blksize; k++) - colormap[i][ptr + k] = (JSAMPLE)val; + colormap[i][ptr + k] = (_JSAMPLE)val; } } blkdist = blksize; /* blksize of this color is blkdist of next */ @@ -337,25 +338,25 @@ LOCAL(void) create_colorindex(j_decompress_ptr cinfo) { my_cquantize_ptr cquantize = (my_cquantize_ptr)cinfo->cquantize; - JSAMPROW indexptr; + _JSAMPROW indexptr; int i, j, k, nci, blksize, val, pad; - /* For ordered dither, we pad the color index tables by MAXJSAMPLE in - * each direction (input index values can be -MAXJSAMPLE .. 2*MAXJSAMPLE). + /* For ordered dither, we pad the color index tables by _MAXJSAMPLE in + * each direction (input index values can be -_MAXJSAMPLE .. 2*_MAXJSAMPLE). * This is not necessary in the other dithering modes. However, we * flag whether it was done in case user changes dithering mode. */ if (cinfo->dither_mode == JDITHER_ORDERED) { - pad = MAXJSAMPLE * 2; + pad = _MAXJSAMPLE * 2; cquantize->is_padded = TRUE; } else { pad = 0; cquantize->is_padded = FALSE; } - cquantize->colorindex = (*cinfo->mem->alloc_sarray) + cquantize->colorindex = (_JSAMPARRAY)(*cinfo->mem->alloc_sarray) ((j_common_ptr)cinfo, JPOOL_IMAGE, - (JDIMENSION)(MAXJSAMPLE + 1 + pad), + (JDIMENSION)(_MAXJSAMPLE + 1 + pad), (JDIMENSION)cinfo->out_color_components); /* blksize is number of adjacent repeated entries for a component */ @@ -368,24 +369,24 @@ create_colorindex(j_decompress_ptr cinfo) /* adjust colorindex pointers to provide padding at negative indexes. */ if (pad) - cquantize->colorindex[i] += MAXJSAMPLE; + cquantize->colorindex[i] += _MAXJSAMPLE; /* in loop, val = index of current output value, */ /* and k = largest j that maps to current val */ indexptr = cquantize->colorindex[i]; val = 0; k = largest_input_value(cinfo, i, 0, nci - 1); - for (j = 0; j <= MAXJSAMPLE; j++) { + for (j = 0; j <= _MAXJSAMPLE; j++) { while (j > k) /* advance val if past boundary */ k = largest_input_value(cinfo, i, ++val, nci - 1); /* premultiply so that no multiplication needed in main processing */ - indexptr[j] = (JSAMPLE)(val * blksize); + indexptr[j] = (_JSAMPLE)(val * blksize); } /* Pad at both ends if necessary */ if (pad) - for (j = 1; j <= MAXJSAMPLE; j++) { + for (j = 1; j <= _MAXJSAMPLE; j++) { indexptr[-j] = indexptr[0]; - indexptr[MAXJSAMPLE + j] = indexptr[MAXJSAMPLE]; + indexptr[_MAXJSAMPLE + j] = indexptr[_MAXJSAMPLE]; } } } @@ -406,16 +407,16 @@ make_odither_array(j_decompress_ptr cinfo, int ncolors) odither = (ODITHER_MATRIX_PTR) (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE, sizeof(ODITHER_MATRIX)); - /* The inter-value distance for this color is MAXJSAMPLE/(ncolors-1). + /* The inter-value distance for this color is _MAXJSAMPLE/(ncolors-1). * Hence the dither value for the matrix cell with fill order f - * (f=0..N-1) should be (N-1-2*f)/(2*N) * MAXJSAMPLE/(ncolors-1). + * (f=0..N-1) should be (N-1-2*f)/(2*N) * _MAXJSAMPLE/(ncolors-1). * On 16-bit-int machine, be careful to avoid overflow. */ den = 2 * ODITHER_CELLS * ((JLONG)(ncolors - 1)); for (j = 0; j < ODITHER_SIZE; j++) { for (k = 0; k < ODITHER_SIZE; k++) { num = ((JLONG)(ODITHER_CELLS - 1 - - 2 * ((int)base_dither_matrix[j][k]))) * MAXJSAMPLE; + 2 * ((int)base_dither_matrix[j][k]))) * _MAXJSAMPLE; /* Ensure round towards zero despite C's lack of consistency * about rounding negative values in integer division... */ @@ -460,14 +461,14 @@ create_odither_tables(j_decompress_ptr cinfo) */ METHODDEF(void) -color_quantize(j_decompress_ptr cinfo, JSAMPARRAY input_buf, - JSAMPARRAY output_buf, int num_rows) +color_quantize(j_decompress_ptr cinfo, _JSAMPARRAY input_buf, + _JSAMPARRAY output_buf, int num_rows) /* General case, no dithering */ { my_cquantize_ptr cquantize = (my_cquantize_ptr)cinfo->cquantize; - JSAMPARRAY colorindex = cquantize->colorindex; + _JSAMPARRAY colorindex = cquantize->colorindex; register int pixcode, ci; - register JSAMPROW ptrin, ptrout; + register _JSAMPROW ptrin, ptrout; int row; JDIMENSION col; JDIMENSION width = cinfo->output_width; @@ -481,23 +482,23 @@ color_quantize(j_decompress_ptr cinfo, JSAMPARRAY input_buf, for (ci = 0; ci < nc; ci++) { pixcode += colorindex[ci][*ptrin++]; } - *ptrout++ = (JSAMPLE)pixcode; + *ptrout++ = (_JSAMPLE)pixcode; } } } METHODDEF(void) -color_quantize3(j_decompress_ptr cinfo, JSAMPARRAY input_buf, - JSAMPARRAY output_buf, int num_rows) +color_quantize3(j_decompress_ptr cinfo, _JSAMPARRAY input_buf, + _JSAMPARRAY output_buf, int num_rows) /* Fast path for out_color_components==3, no dithering */ { my_cquantize_ptr cquantize = (my_cquantize_ptr)cinfo->cquantize; register int pixcode; - register JSAMPROW ptrin, ptrout; - JSAMPROW colorindex0 = cquantize->colorindex[0]; - JSAMPROW colorindex1 = cquantize->colorindex[1]; - JSAMPROW colorindex2 = cquantize->colorindex[2]; + register _JSAMPROW ptrin, ptrout; + _JSAMPROW colorindex0 = cquantize->colorindex[0]; + _JSAMPROW colorindex1 = cquantize->colorindex[1]; + _JSAMPROW colorindex2 = cquantize->colorindex[2]; int row; JDIMENSION col; JDIMENSION width = cinfo->output_width; @@ -509,21 +510,21 @@ color_quantize3(j_decompress_ptr cinfo, JSAMPARRAY input_buf, pixcode = colorindex0[*ptrin++]; pixcode += colorindex1[*ptrin++]; pixcode += colorindex2[*ptrin++]; - *ptrout++ = (JSAMPLE)pixcode; + *ptrout++ = (_JSAMPLE)pixcode; } } } METHODDEF(void) -quantize_ord_dither(j_decompress_ptr cinfo, JSAMPARRAY input_buf, - JSAMPARRAY output_buf, int num_rows) +quantize_ord_dither(j_decompress_ptr cinfo, _JSAMPARRAY input_buf, + _JSAMPARRAY output_buf, int num_rows) /* General case, with ordered dithering */ { my_cquantize_ptr cquantize = (my_cquantize_ptr)cinfo->cquantize; - register JSAMPROW input_ptr; - register JSAMPROW output_ptr; - JSAMPROW colorindex_ci; + register _JSAMPROW input_ptr; + register _JSAMPROW output_ptr; + _JSAMPROW colorindex_ci; int *dither; /* points to active row of dither matrix */ int row_index, col_index; /* current indexes into dither matrix */ int nc = cinfo->out_color_components; @@ -534,7 +535,7 @@ quantize_ord_dither(j_decompress_ptr cinfo, JSAMPARRAY input_buf, for (row = 0; row < num_rows; row++) { /* Initialize output values to 0 so can process components separately */ - jzero_far((void *)output_buf[row], (size_t)(width * sizeof(JSAMPLE))); + jzero_far((void *)output_buf[row], (size_t)(width * sizeof(_JSAMPLE))); row_index = cquantize->row_index; for (ci = 0; ci < nc; ci++) { input_ptr = input_buf[row] + ci; @@ -544,11 +545,11 @@ quantize_ord_dither(j_decompress_ptr cinfo, JSAMPARRAY input_buf, col_index = 0; for (col = width; col > 0; col--) { - /* Form pixel value + dither, range-limit to 0..MAXJSAMPLE, + /* Form pixel value + dither, range-limit to 0.._MAXJSAMPLE, * select output value, accumulate into output code for this pixel. * Range-limiting need not be done explicitly, as we have extended * the colorindex table to produce the right answers for out-of-range - * inputs. The maximum dither is +- MAXJSAMPLE; this sets the + * inputs. The maximum dither is +- _MAXJSAMPLE; this sets the * required amount of padding. */ *output_ptr += @@ -566,17 +567,17 @@ quantize_ord_dither(j_decompress_ptr cinfo, JSAMPARRAY input_buf, METHODDEF(void) -quantize3_ord_dither(j_decompress_ptr cinfo, JSAMPARRAY input_buf, - JSAMPARRAY output_buf, int num_rows) +quantize3_ord_dither(j_decompress_ptr cinfo, _JSAMPARRAY input_buf, + _JSAMPARRAY output_buf, int num_rows) /* Fast path for out_color_components==3, with ordered dithering */ { my_cquantize_ptr cquantize = (my_cquantize_ptr)cinfo->cquantize; register int pixcode; - register JSAMPROW input_ptr; - register JSAMPROW output_ptr; - JSAMPROW colorindex0 = cquantize->colorindex[0]; - JSAMPROW colorindex1 = cquantize->colorindex[1]; - JSAMPROW colorindex2 = cquantize->colorindex[2]; + register _JSAMPROW input_ptr; + register _JSAMPROW output_ptr; + _JSAMPROW colorindex0 = cquantize->colorindex[0]; + _JSAMPROW colorindex1 = cquantize->colorindex[1]; + _JSAMPROW colorindex2 = cquantize->colorindex[2]; int *dither0; /* points to active row of dither matrix */ int *dither1; int *dither2; @@ -598,7 +599,7 @@ quantize3_ord_dither(j_decompress_ptr cinfo, JSAMPARRAY input_buf, pixcode = colorindex0[(*input_ptr++) + dither0[col_index]]; pixcode += colorindex1[(*input_ptr++) + dither1[col_index]]; pixcode += colorindex2[(*input_ptr++) + dither2[col_index]]; - *output_ptr++ = (JSAMPLE)pixcode; + *output_ptr++ = (_JSAMPLE)pixcode; col_index = (col_index + 1) & ODITHER_MASK; } row_index = (row_index + 1) & ODITHER_MASK; @@ -608,8 +609,8 @@ quantize3_ord_dither(j_decompress_ptr cinfo, JSAMPARRAY input_buf, METHODDEF(void) -quantize_fs_dither(j_decompress_ptr cinfo, JSAMPARRAY input_buf, - JSAMPARRAY output_buf, int num_rows) +quantize_fs_dither(j_decompress_ptr cinfo, _JSAMPARRAY input_buf, + _JSAMPARRAY output_buf, int num_rows) /* General case, with Floyd-Steinberg dithering */ { my_cquantize_ptr cquantize = (my_cquantize_ptr)cinfo->cquantize; @@ -619,10 +620,10 @@ quantize_fs_dither(j_decompress_ptr cinfo, JSAMPARRAY input_buf, LOCFSERROR bnexterr; /* error for below/next col */ LOCFSERROR delta; register FSERRPTR errorptr; /* => fserrors[] at column before current */ - register JSAMPROW input_ptr; - register JSAMPROW output_ptr; - JSAMPROW colorindex_ci; - JSAMPROW colormap_ci; + register _JSAMPROW input_ptr; + register _JSAMPROW output_ptr; + _JSAMPROW colorindex_ci; + _JSAMPROW colormap_ci; int pixcode; int nc = cinfo->out_color_components; int dir; /* 1 for left-to-right, -1 for right-to-left */ @@ -631,12 +632,12 @@ quantize_fs_dither(j_decompress_ptr cinfo, JSAMPARRAY input_buf, int row; JDIMENSION col; JDIMENSION width = cinfo->output_width; - JSAMPLE *range_limit = cinfo->sample_range_limit; + _JSAMPLE *range_limit = (_JSAMPLE *)cinfo->sample_range_limit; SHIFT_TEMPS for (row = 0; row < num_rows; row++) { /* Initialize output values to 0 so can process components separately */ - jzero_far((void *)output_buf[row], (size_t)(width * sizeof(JSAMPLE))); + jzero_far((void *)output_buf[row], (size_t)(width * sizeof(_JSAMPLE))); for (ci = 0; ci < nc; ci++) { input_ptr = input_buf[row] + ci; output_ptr = output_buf[row]; @@ -670,15 +671,15 @@ quantize_fs_dither(j_decompress_ptr cinfo, JSAMPARRAY input_buf, * Note: errorptr points to *previous* column's array entry. */ cur = RIGHT_SHIFT(cur + errorptr[dir] + 8, 4); - /* Form pixel value + error, and range-limit to 0..MAXJSAMPLE. - * The maximum error is +- MAXJSAMPLE; this sets the required size + /* Form pixel value + error, and range-limit to 0.._MAXJSAMPLE. + * The maximum error is +- _MAXJSAMPLE; this sets the required size * of the range_limit array. */ cur += *input_ptr; cur = range_limit[cur]; /* Select output value, accumulate into output code for this pixel */ pixcode = colorindex_ci[cur]; - *output_ptr += (JSAMPLE)pixcode; + *output_ptr += (_JSAMPLE)pixcode; /* Compute actual representation error at this pixel */ /* Note: we can do this even though we don't have the final */ /* pixel code, because the colormap is orthogonal. */ @@ -745,22 +746,22 @@ start_pass_1_quant(j_decompress_ptr cinfo, boolean is_pre_scan) int i; /* Install my colormap. */ - cinfo->colormap = cquantize->sv_colormap; + cinfo->colormap = (JSAMPARRAY)cquantize->sv_colormap; cinfo->actual_number_of_colors = cquantize->sv_actual; /* Initialize for desired dithering mode. */ switch (cinfo->dither_mode) { case JDITHER_NONE: if (cinfo->out_color_components == 3) - cquantize->pub.color_quantize = color_quantize3; + cquantize->pub._color_quantize = color_quantize3; else - cquantize->pub.color_quantize = color_quantize; + cquantize->pub._color_quantize = color_quantize; break; case JDITHER_ORDERED: if (cinfo->out_color_components == 3) - cquantize->pub.color_quantize = quantize3_ord_dither; + cquantize->pub._color_quantize = quantize3_ord_dither; else - cquantize->pub.color_quantize = quantize_ord_dither; + cquantize->pub._color_quantize = quantize_ord_dither; cquantize->row_index = 0; /* initialize state for ordered dither */ /* If user changed to ordered dither from another mode, * we must recreate the color index table with padding. @@ -773,7 +774,7 @@ start_pass_1_quant(j_decompress_ptr cinfo, boolean is_pre_scan) create_odither_tables(cinfo); break; case JDITHER_FS: - cquantize->pub.color_quantize = quantize_fs_dither; + cquantize->pub._color_quantize = quantize_fs_dither; cquantize->on_odd_row = FALSE; /* initialize state for F-S dither */ /* Allocate Floyd-Steinberg workspace if didn't already. */ if (cquantize->fserrors[0] == NULL) @@ -818,10 +819,17 @@ new_color_map_1_quant(j_decompress_ptr cinfo) */ GLOBAL(void) -jinit_1pass_quantizer(j_decompress_ptr cinfo) +_jinit_1pass_quantizer(j_decompress_ptr cinfo) { my_cquantize_ptr cquantize; + if (cinfo->data_precision != BITS_IN_JSAMPLE) + ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision); + + /* Color quantization is not supported with lossless JPEG images */ + if (cinfo->master->lossless) + ERREXIT(cinfo, JERR_NOTIMPL); + cquantize = (my_cquantize_ptr) (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE, sizeof(my_cquantizer)); @@ -835,9 +843,9 @@ jinit_1pass_quantizer(j_decompress_ptr cinfo) /* Make sure my internal arrays won't overflow */ if (cinfo->out_color_components > MAX_Q_COMPS) ERREXIT1(cinfo, JERR_QUANT_COMPONENTS, MAX_Q_COMPS); - /* Make sure colormap indexes can be represented by JSAMPLEs */ - if (cinfo->desired_number_of_colors > (MAXJSAMPLE + 1)) - ERREXIT1(cinfo, JERR_QUANT_MANY_COLORS, MAXJSAMPLE + 1); + /* Make sure colormap indexes can be represented by _JSAMPLEs */ + if (cinfo->desired_number_of_colors > (_MAXJSAMPLE + 1)) + ERREXIT1(cinfo, JERR_QUANT_MANY_COLORS, _MAXJSAMPLE + 1); /* Create the colormap and color index table. */ create_colormap(cinfo); @@ -853,4 +861,4 @@ jinit_1pass_quantizer(j_decompress_ptr cinfo) alloc_fs_workspace(cinfo); } -#endif /* QUANT_1PASS_SUPPORTED */ +#endif /* defined(QUANT_1PASS_SUPPORTED) && BITS_IN_JSAMPLE != 16 */ diff --git a/src/3rdparty/libjpeg/src/jquant2.c b/src/3rdparty/libjpeg/src/jquant2.c index 44efb18cadf..9ba51fa8872 100644 --- a/src/3rdparty/libjpeg/src/jquant2.c +++ b/src/3rdparty/libjpeg/src/jquant2.c @@ -4,7 +4,7 @@ * This file was part of the Independent JPEG Group's software: * Copyright (C) 1991-1996, Thomas G. Lane. * libjpeg-turbo Modifications: - * Copyright (C) 2009, 2014-2015, 2020, D. R. Commander. + * Copyright (C) 2009, 2014-2015, 2020, 2022-2023, D. R. Commander. * For conditions of distribution and use, see the accompanying README.ijg * file. * @@ -23,8 +23,9 @@ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" +#include "jsamplecomp.h" -#ifdef QUANT_2PASS_SUPPORTED +#if defined(QUANT_2PASS_SUPPORTED) && BITS_IN_JSAMPLE != 16 /* @@ -106,7 +107,7 @@ static const int c_scales[3] = { R_SCALE, G_SCALE, B_SCALE }; * each 2-D array has 2^6*2^5 = 2048 or 2^6*2^6 = 4096 entries. */ -#define MAXNUMCOLORS (MAXJSAMPLE + 1) /* maximum size of colormap */ +#define MAXNUMCOLORS (_MAXJSAMPLE + 1) /* maximum size of colormap */ /* These will do the right thing for either R,G,B or B,G,R color order, * but you may not like the results for other color orders. @@ -173,7 +174,7 @@ typedef struct { struct jpeg_color_quantizer pub; /* public fields */ /* Space for the eventually created colormap is stashed here */ - JSAMPARRAY sv_colormap; /* colormap allocated at init time */ + _JSAMPARRAY sv_colormap; /* colormap allocated at init time */ int desired; /* desired # of colors = size of colormap */ /* Variables for accumulating image statistics */ @@ -200,11 +201,11 @@ typedef my_cquantizer *my_cquantize_ptr; */ METHODDEF(void) -prescan_quantize(j_decompress_ptr cinfo, JSAMPARRAY input_buf, - JSAMPARRAY output_buf, int num_rows) +prescan_quantize(j_decompress_ptr cinfo, _JSAMPARRAY input_buf, + _JSAMPARRAY output_buf, int num_rows) { my_cquantize_ptr cquantize = (my_cquantize_ptr)cinfo->cquantize; - register JSAMPROW ptr; + register _JSAMPROW ptr; register histptr histp; register hist3d histogram = cquantize->histogram; int row; @@ -377,7 +378,7 @@ have_c2max: * against making long narrow boxes, and it has the side benefit that * a box is splittable iff norm > 0. * Since the differences are expressed in histogram-cell units, - * we have to shift back to JSAMPLE units to get consistent distances; + * we have to shift back to _JSAMPLE units to get consistent distances; * after which, we scale according to the selected distance scale factors. */ dist0 = ((c0max - c0min) << C0_SHIFT) * C0_SCALE; @@ -508,9 +509,12 @@ compute_color(j_decompress_ptr cinfo, boxptr boxp, int icolor) } } - cinfo->colormap[0][icolor] = (JSAMPLE)((c0total + (total >> 1)) / total); - cinfo->colormap[1][icolor] = (JSAMPLE)((c1total + (total >> 1)) / total); - cinfo->colormap[2][icolor] = (JSAMPLE)((c2total + (total >> 1)) / total); + ((_JSAMPARRAY)cinfo->colormap)[0][icolor] = + (_JSAMPLE)((c0total + (total >> 1)) / total); + ((_JSAMPARRAY)cinfo->colormap)[1][icolor] = + (_JSAMPLE)((c1total + (total >> 1)) / total); + ((_JSAMPARRAY)cinfo->colormap)[2][icolor] = + (_JSAMPLE)((c2total + (total >> 1)) / total); } @@ -528,11 +532,11 @@ select_colors(j_decompress_ptr cinfo, int desired_colors) /* Initialize one box containing whole space */ numboxes = 1; boxlist[0].c0min = 0; - boxlist[0].c0max = MAXJSAMPLE >> C0_SHIFT; + boxlist[0].c0max = _MAXJSAMPLE >> C0_SHIFT; boxlist[0].c1min = 0; - boxlist[0].c1max = MAXJSAMPLE >> C1_SHIFT; + boxlist[0].c1max = _MAXJSAMPLE >> C1_SHIFT; boxlist[0].c2min = 0; - boxlist[0].c2max = MAXJSAMPLE >> C2_SHIFT; + boxlist[0].c2max = _MAXJSAMPLE >> C2_SHIFT; /* Shrink it to actually-used volume and set its statistics */ update_box(cinfo, &boxlist[0]); /* Perform median-cut to produce final box list */ @@ -623,7 +627,7 @@ select_colors(j_decompress_ptr cinfo, int desired_colors) LOCAL(int) find_nearby_colors(j_decompress_ptr cinfo, int minc0, int minc1, int minc2, - JSAMPLE colorlist[]) + _JSAMPLE colorlist[]) /* Locate the colormap entries close enough to an update box to be candidates * for the nearest entry to some cell(s) in the update box. The update box * is specified by the center coordinates of its first cell. The number of @@ -665,7 +669,7 @@ find_nearby_colors(j_decompress_ptr cinfo, int minc0, int minc1, int minc2, for (i = 0; i < numcolors; i++) { /* We compute the squared-c0-distance term, then add in the other two. */ - x = cinfo->colormap[0][i]; + x = ((_JSAMPARRAY)cinfo->colormap)[0][i]; if (x < minc0) { tdist = (x - minc0) * C0_SCALE; min_dist = tdist * tdist; @@ -688,7 +692,7 @@ find_nearby_colors(j_decompress_ptr cinfo, int minc0, int minc1, int minc2, } } - x = cinfo->colormap[1][i]; + x = ((_JSAMPARRAY)cinfo->colormap)[1][i]; if (x < minc1) { tdist = (x - minc1) * C1_SCALE; min_dist += tdist * tdist; @@ -710,7 +714,7 @@ find_nearby_colors(j_decompress_ptr cinfo, int minc0, int minc1, int minc2, } } - x = cinfo->colormap[2][i]; + x = ((_JSAMPARRAY)cinfo->colormap)[2][i]; if (x < minc2) { tdist = (x - minc2) * C2_SCALE; min_dist += tdist * tdist; @@ -744,7 +748,7 @@ find_nearby_colors(j_decompress_ptr cinfo, int minc0, int minc1, int minc2, ncolors = 0; for (i = 0; i < numcolors; i++) { if (mindist[i] <= minmaxdist) - colorlist[ncolors++] = (JSAMPLE)i; + colorlist[ncolors++] = (_JSAMPLE)i; } return ncolors; } @@ -752,7 +756,7 @@ find_nearby_colors(j_decompress_ptr cinfo, int minc0, int minc1, int minc2, LOCAL(void) find_best_colors(j_decompress_ptr cinfo, int minc0, int minc1, int minc2, - int numcolors, JSAMPLE colorlist[], JSAMPLE bestcolor[]) + int numcolors, _JSAMPLE colorlist[], _JSAMPLE bestcolor[]) /* Find the closest colormap entry for each cell in the update box, * given the list of candidate colors prepared by find_nearby_colors. * Return the indexes of the closest entries in the bestcolor[] array. @@ -763,7 +767,7 @@ find_best_colors(j_decompress_ptr cinfo, int minc0, int minc1, int minc2, int ic0, ic1, ic2; int i, icolor; register JLONG *bptr; /* pointer into bestdist[] array */ - JSAMPLE *cptr; /* pointer into bestcolor[] array */ + _JSAMPLE *cptr; /* pointer into bestcolor[] array */ JLONG dist0, dist1; /* initial distance values */ register JLONG dist2; /* current distance in inner loop */ JLONG xx0, xx1; /* distance increments */ @@ -790,11 +794,11 @@ find_best_colors(j_decompress_ptr cinfo, int minc0, int minc1, int minc2, for (i = 0; i < numcolors; i++) { icolor = colorlist[i]; /* Compute (square of) distance from minc0/c1/c2 to this color */ - inc0 = (minc0 - cinfo->colormap[0][icolor]) * C0_SCALE; + inc0 = (minc0 - ((_JSAMPARRAY)cinfo->colormap)[0][icolor]) * C0_SCALE; dist0 = inc0 * inc0; - inc1 = (minc1 - cinfo->colormap[1][icolor]) * C1_SCALE; + inc1 = (minc1 - ((_JSAMPARRAY)cinfo->colormap)[1][icolor]) * C1_SCALE; dist0 += inc1 * inc1; - inc2 = (minc2 - cinfo->colormap[2][icolor]) * C2_SCALE; + inc2 = (minc2 - ((_JSAMPARRAY)cinfo->colormap)[2][icolor]) * C2_SCALE; dist0 += inc2 * inc2; /* Form the initial difference increments */ inc0 = inc0 * (2 * STEP_C0) + STEP_C0 * STEP_C0; @@ -813,7 +817,7 @@ find_best_colors(j_decompress_ptr cinfo, int minc0, int minc1, int minc2, for (ic2 = BOX_C2_ELEMS - 1; ic2 >= 0; ic2--) { if (dist2 < *bptr) { *bptr = dist2; - *cptr = (JSAMPLE)icolor; + *cptr = (_JSAMPLE)icolor; } dist2 += xx2; xx2 += 2 * STEP_C2 * STEP_C2; @@ -840,13 +844,13 @@ fill_inverse_cmap(j_decompress_ptr cinfo, int c0, int c1, int c2) hist3d histogram = cquantize->histogram; int minc0, minc1, minc2; /* lower left corner of update box */ int ic0, ic1, ic2; - register JSAMPLE *cptr; /* pointer into bestcolor[] array */ + register _JSAMPLE *cptr; /* pointer into bestcolor[] array */ register histptr cachep; /* pointer into main cache array */ /* This array lists the candidate colormap indexes. */ - JSAMPLE colorlist[MAXNUMCOLORS]; + _JSAMPLE colorlist[MAXNUMCOLORS]; int numcolors; /* number of candidate colors */ /* This array holds the actually closest colormap index for each cell. */ - JSAMPLE bestcolor[BOX_C0_ELEMS * BOX_C1_ELEMS * BOX_C2_ELEMS]; + _JSAMPLE bestcolor[BOX_C0_ELEMS * BOX_C1_ELEMS * BOX_C2_ELEMS]; /* Convert cell coordinates to update box ID */ c0 >>= BOX_C0_LOG; @@ -891,13 +895,13 @@ fill_inverse_cmap(j_decompress_ptr cinfo, int c0, int c1, int c2) */ METHODDEF(void) -pass2_no_dither(j_decompress_ptr cinfo, JSAMPARRAY input_buf, - JSAMPARRAY output_buf, int num_rows) +pass2_no_dither(j_decompress_ptr cinfo, _JSAMPARRAY input_buf, + _JSAMPARRAY output_buf, int num_rows) /* This version performs no dithering */ { my_cquantize_ptr cquantize = (my_cquantize_ptr)cinfo->cquantize; hist3d histogram = cquantize->histogram; - register JSAMPROW inptr, outptr; + register _JSAMPROW inptr, outptr; register histptr cachep; register int c0, c1, c2; int row; @@ -918,15 +922,15 @@ pass2_no_dither(j_decompress_ptr cinfo, JSAMPARRAY input_buf, if (*cachep == 0) fill_inverse_cmap(cinfo, c0, c1, c2); /* Now emit the colormap index for this cell */ - *outptr++ = (JSAMPLE)(*cachep - 1); + *outptr++ = (_JSAMPLE)(*cachep - 1); } } } METHODDEF(void) -pass2_fs_dither(j_decompress_ptr cinfo, JSAMPARRAY input_buf, - JSAMPARRAY output_buf, int num_rows) +pass2_fs_dither(j_decompress_ptr cinfo, _JSAMPARRAY input_buf, + _JSAMPARRAY output_buf, int num_rows) /* This version performs Floyd-Steinberg dithering */ { my_cquantize_ptr cquantize = (my_cquantize_ptr)cinfo->cquantize; @@ -935,19 +939,19 @@ pass2_fs_dither(j_decompress_ptr cinfo, JSAMPARRAY input_buf, LOCFSERROR belowerr0, belowerr1, belowerr2; /* error for pixel below cur */ LOCFSERROR bpreverr0, bpreverr1, bpreverr2; /* error for below/prev col */ register FSERRPTR errorptr; /* => fserrors[] at column before current */ - JSAMPROW inptr; /* => current input pixel */ - JSAMPROW outptr; /* => current output pixel */ + _JSAMPROW inptr; /* => current input pixel */ + _JSAMPROW outptr; /* => current output pixel */ histptr cachep; int dir; /* +1 or -1 depending on direction */ int dir3; /* 3*dir, for advancing inptr & errorptr */ int row; JDIMENSION col; JDIMENSION width = cinfo->output_width; - JSAMPLE *range_limit = cinfo->sample_range_limit; + _JSAMPLE *range_limit = (_JSAMPLE *)cinfo->sample_range_limit; int *error_limit = cquantize->error_limiter; - JSAMPROW colormap0 = cinfo->colormap[0]; - JSAMPROW colormap1 = cinfo->colormap[1]; - JSAMPROW colormap2 = cinfo->colormap[2]; + _JSAMPROW colormap0 = ((_JSAMPARRAY)cinfo->colormap)[0]; + _JSAMPROW colormap1 = ((_JSAMPARRAY)cinfo->colormap)[1]; + _JSAMPROW colormap2 = ((_JSAMPARRAY)cinfo->colormap)[2]; SHIFT_TEMPS for (row = 0; row < num_rows; row++) { @@ -992,8 +996,8 @@ pass2_fs_dither(j_decompress_ptr cinfo, JSAMPARRAY input_buf, cur0 = error_limit[cur0]; cur1 = error_limit[cur1]; cur2 = error_limit[cur2]; - /* Form pixel value + error, and range-limit to 0..MAXJSAMPLE. - * The maximum error is +- MAXJSAMPLE (or less with error limiting); + /* Form pixel value + error, and range-limit to 0.._MAXJSAMPLE. + * The maximum error is +- _MAXJSAMPLE (or less with error limiting); * this sets the required size of the range_limit array. */ cur0 += inptr[0]; @@ -1013,7 +1017,7 @@ pass2_fs_dither(j_decompress_ptr cinfo, JSAMPARRAY input_buf, /* Now emit the colormap index for this cell */ { register int pixcode = *cachep - 1; - *outptr = (JSAMPLE)pixcode; + *outptr = (_JSAMPLE)pixcode; /* Compute representation error for this pixel */ cur0 -= colormap0[pixcode]; cur1 -= colormap1[pixcode]; @@ -1064,7 +1068,7 @@ pass2_fs_dither(j_decompress_ptr cinfo, JSAMPARRAY input_buf, /* * Initialize the error-limiting transfer function (lookup table). * The raw F-S error computation can potentially compute error values of up to - * +- MAXJSAMPLE. But we want the maximum correction applied to a pixel to be + * +- _MAXJSAMPLE. But we want the maximum correction applied to a pixel to be * much less, otherwise obviously wrong pixels will be created. (Typical * effects include weird fringes at color-area boundaries, isolated bright * pixels in a dark area, etc.) The standard advice for avoiding this problem @@ -1073,7 +1077,7 @@ pass2_fs_dither(j_decompress_ptr cinfo, JSAMPARRAY input_buf, * error buildup. However, that only prevents the error from getting * completely out of hand; Aaron Giles reports that error limiting improves * the results even with corner colors allocated. - * A simple clamping of the error values to about +- MAXJSAMPLE/8 works pretty + * A simple clamping of the error values to about +- _MAXJSAMPLE/8 works pretty * well, but the smoother transfer function used below is even better. Thanks * to Aaron Giles for this idea. */ @@ -1087,22 +1091,22 @@ init_error_limit(j_decompress_ptr cinfo) int in, out; table = (int *)(*cinfo->mem->alloc_small) - ((j_common_ptr)cinfo, JPOOL_IMAGE, (MAXJSAMPLE * 2 + 1) * sizeof(int)); - table += MAXJSAMPLE; /* so can index -MAXJSAMPLE .. +MAXJSAMPLE */ + ((j_common_ptr)cinfo, JPOOL_IMAGE, (_MAXJSAMPLE * 2 + 1) * sizeof(int)); + table += _MAXJSAMPLE; /* so can index -_MAXJSAMPLE .. +_MAXJSAMPLE */ cquantize->error_limiter = table; -#define STEPSIZE ((MAXJSAMPLE + 1) / 16) - /* Map errors 1:1 up to +- MAXJSAMPLE/16 */ +#define STEPSIZE ((_MAXJSAMPLE + 1) / 16) + /* Map errors 1:1 up to +- _MAXJSAMPLE/16 */ out = 0; for (in = 0; in < STEPSIZE; in++, out++) { table[in] = out; table[-in] = -out; } - /* Map errors 1:2 up to +- 3*MAXJSAMPLE/16 */ + /* Map errors 1:2 up to +- 3*_MAXJSAMPLE/16 */ for (; in < STEPSIZE * 3; in++, out += (in & 1) ? 0 : 1) { table[in] = out; table[-in] = -out; } - /* Clamp the rest to final out value (which is (MAXJSAMPLE+1)/8) */ - for (; in <= MAXJSAMPLE; in++) { + /* Clamp the rest to final out value (which is (_MAXJSAMPLE+1)/8) */ + for (; in <= _MAXJSAMPLE; in++) { table[in] = out; table[-in] = -out; } #undef STEPSIZE @@ -1119,7 +1123,7 @@ finish_pass1(j_decompress_ptr cinfo) my_cquantize_ptr cquantize = (my_cquantize_ptr)cinfo->cquantize; /* Select the representative colors and fill in cinfo->colormap */ - cinfo->colormap = cquantize->sv_colormap; + cinfo->colormap = (JSAMPARRAY)cquantize->sv_colormap; select_colors(cinfo, cquantize->desired); /* Force next pass to zero the color index table */ cquantize->needs_zeroed = TRUE; @@ -1151,15 +1155,15 @@ start_pass_2_quant(j_decompress_ptr cinfo, boolean is_pre_scan) if (is_pre_scan) { /* Set up method pointers */ - cquantize->pub.color_quantize = prescan_quantize; + cquantize->pub._color_quantize = prescan_quantize; cquantize->pub.finish_pass = finish_pass1; cquantize->needs_zeroed = TRUE; /* Always zero histogram */ } else { /* Set up method pointers */ if (cinfo->dither_mode == JDITHER_FS) - cquantize->pub.color_quantize = pass2_fs_dither; + cquantize->pub._color_quantize = pass2_fs_dither; else - cquantize->pub.color_quantize = pass2_no_dither; + cquantize->pub._color_quantize = pass2_no_dither; cquantize->pub.finish_pass = finish_pass2; /* Make sure color count is acceptable */ @@ -1215,11 +1219,14 @@ new_color_map_2_quant(j_decompress_ptr cinfo) */ GLOBAL(void) -jinit_2pass_quantizer(j_decompress_ptr cinfo) +_jinit_2pass_quantizer(j_decompress_ptr cinfo) { my_cquantize_ptr cquantize; int i; + if (cinfo->data_precision != BITS_IN_JSAMPLE) + ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision); + cquantize = (my_cquantize_ptr) (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE, sizeof(my_cquantizer)); @@ -1230,7 +1237,8 @@ jinit_2pass_quantizer(j_decompress_ptr cinfo) cquantize->error_limiter = NULL; /* Make sure jdmaster didn't give me a case I can't handle */ - if (cinfo->out_color_components != 3) + if (cinfo->out_color_components != 3 || + cinfo->out_color_space == JCS_RGB565 || cinfo->master->lossless) ERREXIT(cinfo, JERR_NOTIMPL); /* Allocate the histogram/inverse colormap storage */ @@ -1253,10 +1261,10 @@ jinit_2pass_quantizer(j_decompress_ptr cinfo) /* Lower bound on # of colors ... somewhat arbitrary as long as > 0 */ if (desired < 8) ERREXIT1(cinfo, JERR_QUANT_FEW_COLORS, 8); - /* Make sure colormap indexes can be represented by JSAMPLEs */ + /* Make sure colormap indexes can be represented by _JSAMPLEs */ if (desired > MAXNUMCOLORS) ERREXIT1(cinfo, JERR_QUANT_MANY_COLORS, MAXNUMCOLORS); - cquantize->sv_colormap = (*cinfo->mem->alloc_sarray) + cquantize->sv_colormap = (_JSAMPARRAY)(*cinfo->mem->alloc_sarray) ((j_common_ptr)cinfo, JPOOL_IMAGE, (JDIMENSION)desired, (JDIMENSION)3); cquantize->desired = desired; } else @@ -1282,4 +1290,4 @@ jinit_2pass_quantizer(j_decompress_ptr cinfo) } } -#endif /* QUANT_2PASS_SUPPORTED */ +#endif /* defined(QUANT_2PASS_SUPPORTED) && BITS_IN_JSAMPLE != 16 */ diff --git a/src/3rdparty/libjpeg/src/jsamplecomp.h b/src/3rdparty/libjpeg/src/jsamplecomp.h new file mode 100644 index 00000000000..f3f275e6e29 --- /dev/null +++ b/src/3rdparty/libjpeg/src/jsamplecomp.h @@ -0,0 +1,336 @@ +/* + * jsamplecomp.h + * + * Copyright (C) 2022, D. R. Commander. + * For conditions of distribution and use, see the accompanying README.ijg + * file. + */ + +/* In source files that must be compiled for multiple data precisions, we + * prefix all precision-dependent data types, macros, methods, fields, and + * function names with an underscore. Including this file replaces those + * precision-independent tokens with their precision-dependent equivalents, + * based on the value of BITS_IN_JSAMPLE. + */ + +#ifndef JSAMPLECOMP_H +#define JSAMPLECOMP_H + +#if BITS_IN_JSAMPLE == 16 + +/* Sample data types and macros (jmorecfg.h) */ +#define _JSAMPLE J16SAMPLE + +#define _MAXJSAMPLE MAXJ16SAMPLE +#define _CENTERJSAMPLE CENTERJ16SAMPLE + +#define _JSAMPROW J16SAMPROW +#define _JSAMPARRAY J16SAMPARRAY +#define _JSAMPIMAGE J16SAMPIMAGE + +/* External functions (jpeglib.h) */ +#define _jpeg_write_scanlines jpeg16_write_scanlines +#define _jpeg_read_scanlines jpeg16_read_scanlines + +/* Internal methods (jpegint.h) */ + +#ifdef C_LOSSLESS_SUPPORTED +/* Use the 16-bit method in the jpeg_c_main_controller structure. */ +#define _process_data process_data_16 +/* Use the 16-bit method in the jpeg_c_prep_controller structure. */ +#define _pre_process_data pre_process_data_16 +/* Use the 16-bit method in the jpeg_c_coef_controller structure. */ +#define _compress_data compress_data_16 +/* Use the 16-bit method in the jpeg_color_converter structure. */ +#define _color_convert color_convert_16 +/* Use the 16-bit method in the jpeg_downsampler structure. */ +#define _downsample downsample_16 +#endif +#ifdef D_LOSSLESS_SUPPORTED +/* Use the 16-bit method in the jpeg_d_main_controller structure. */ +#define _process_data process_data_16 +/* Use the 16-bit method in the jpeg_d_coef_controller structure. */ +#define _decompress_data decompress_data_16 +/* Use the 16-bit method in the jpeg_d_post_controller structure. */ +#define _post_process_data post_process_data_16 +/* Use the 16-bit method in the jpeg_upsampler structure. */ +#define _upsample upsample_16 +/* Use the 16-bit method in the jpeg_color_converter structure. */ +#define _color_convert color_convert_16 +#endif + +/* Global internal functions (jpegint.h) */ +#ifdef C_LOSSLESS_SUPPORTED +#define _jinit_c_main_controller j16init_c_main_controller +#define _jinit_c_prep_controller j16init_c_prep_controller +#define _jinit_color_converter j16init_color_converter +#define _jinit_downsampler j16init_downsampler +#define _jinit_c_diff_controller j16init_c_diff_controller +#define _jinit_lossless_compressor j16init_lossless_compressor +#endif + +#ifdef D_LOSSLESS_SUPPORTED +#define _jinit_d_main_controller j16init_d_main_controller +#define _jinit_d_post_controller j16init_d_post_controller +#define _jinit_upsampler j16init_upsampler +#define _jinit_color_deconverter j16init_color_deconverter +#define _jinit_merged_upsampler j16init_merged_upsampler +#define _jinit_d_diff_controller j16init_d_diff_controller +#define _jinit_lossless_decompressor j16init_lossless_decompressor +#endif + +#if defined(C_LOSSLESS_SUPPORTED) || defined(D_LOSSLESS_SUPPORTED) +#define _jcopy_sample_rows j16copy_sample_rows +#endif + +/* Internal fields (cdjpeg.h) */ + +#if defined(C_LOSSLESS_SUPPORTED) || defined(D_LOSSLESS_SUPPORTED) +/* Use the 16-bit buffer in the cjpeg_source_struct and djpeg_dest_struct + structures. */ +#define _buffer buffer16 +#endif + +/* Image I/O functions (cdjpeg.h) */ +#ifdef C_LOSSLESS_SUPPORTED +#define _jinit_read_gif j16init_read_gif +#define _jinit_read_ppm j16init_read_ppm +#endif + +#ifdef D_LOSSLESS_SUPPORTED +#define _jinit_write_ppm j16init_write_ppm +#endif + +#elif BITS_IN_JSAMPLE == 12 + +/* Sample data types and macros (jmorecfg.h) */ +#define _JSAMPLE J12SAMPLE + +#define _MAXJSAMPLE MAXJ12SAMPLE +#define _CENTERJSAMPLE CENTERJ12SAMPLE + +#define _JSAMPROW J12SAMPROW +#define _JSAMPARRAY J12SAMPARRAY +#define _JSAMPIMAGE J12SAMPIMAGE + +/* External functions (jpeglib.h) */ +#define _jpeg_write_scanlines jpeg12_write_scanlines +#define _jpeg_write_raw_data jpeg12_write_raw_data +#define _jpeg_read_scanlines jpeg12_read_scanlines +#define _jpeg_skip_scanlines jpeg12_skip_scanlines +#define _jpeg_crop_scanline jpeg12_crop_scanline +#define _jpeg_read_raw_data jpeg12_read_raw_data + +/* Internal methods (jpegint.h) */ + +/* Use the 12-bit method in the jpeg_c_main_controller structure. */ +#define _process_data process_data_12 +/* Use the 12-bit method in the jpeg_c_prep_controller structure. */ +#define _pre_process_data pre_process_data_12 +/* Use the 12-bit method in the jpeg_c_coef_controller structure. */ +#define _compress_data compress_data_12 +/* Use the 12-bit method in the jpeg_color_converter structure. */ +#define _color_convert color_convert_12 +/* Use the 12-bit method in the jpeg_downsampler structure. */ +#define _downsample downsample_12 +/* Use the 12-bit method in the jpeg_forward_dct structure. */ +#define _forward_DCT forward_DCT_12 +/* Use the 12-bit method in the jpeg_d_main_controller structure. */ +#define _process_data process_data_12 +/* Use the 12-bit method in the jpeg_d_coef_controller structure. */ +#define _decompress_data decompress_data_12 +/* Use the 12-bit method in the jpeg_d_post_controller structure. */ +#define _post_process_data post_process_data_12 +/* Use the 12-bit method in the jpeg_inverse_dct structure. */ +#define _inverse_DCT_method_ptr inverse_DCT_12_method_ptr +#define _inverse_DCT inverse_DCT_12 +/* Use the 12-bit method in the jpeg_upsampler structure. */ +#define _upsample upsample_12 +/* Use the 12-bit method in the jpeg_color_converter structure. */ +#define _color_convert color_convert_12 +/* Use the 12-bit method in the jpeg_color_quantizer structure. */ +#define _color_quantize color_quantize_12 + +/* Global internal functions (jpegint.h) */ +#define _jinit_c_main_controller j12init_c_main_controller +#define _jinit_c_prep_controller j12init_c_prep_controller +#define _jinit_c_coef_controller j12init_c_coef_controller +#define _jinit_color_converter j12init_color_converter +#define _jinit_downsampler j12init_downsampler +#define _jinit_forward_dct j12init_forward_dct +#ifdef C_LOSSLESS_SUPPORTED +#define _jinit_c_diff_controller j12init_c_diff_controller +#define _jinit_lossless_compressor j12init_lossless_compressor +#endif + +#define _jinit_d_main_controller j12init_d_main_controller +#define _jinit_d_coef_controller j12init_d_coef_controller +#define _jinit_d_post_controller j12init_d_post_controller +#define _jinit_inverse_dct j12init_inverse_dct +#define _jinit_upsampler j12init_upsampler +#define _jinit_color_deconverter j12init_color_deconverter +#define _jinit_1pass_quantizer j12init_1pass_quantizer +#define _jinit_2pass_quantizer j12init_2pass_quantizer +#define _jinit_merged_upsampler j12init_merged_upsampler +#ifdef D_LOSSLESS_SUPPORTED +#define _jinit_d_diff_controller j12init_d_diff_controller +#define _jinit_lossless_decompressor j12init_lossless_decompressor +#endif + +#define _jcopy_sample_rows j12copy_sample_rows + +/* Global internal functions (jdct.h) */ +#define _jpeg_fdct_islow jpeg12_fdct_islow +#define _jpeg_fdct_ifast jpeg12_fdct_ifast + +#define _jpeg_idct_islow jpeg12_idct_islow +#define _jpeg_idct_ifast jpeg12_idct_ifast +#define _jpeg_idct_float jpeg12_idct_float +#define _jpeg_idct_7x7 jpeg12_idct_7x7 +#define _jpeg_idct_6x6 jpeg12_idct_6x6 +#define _jpeg_idct_5x5 jpeg12_idct_5x5 +#define _jpeg_idct_4x4 jpeg12_idct_4x4 +#define _jpeg_idct_3x3 jpeg12_idct_3x3 +#define _jpeg_idct_2x2 jpeg12_idct_2x2 +#define _jpeg_idct_1x1 jpeg12_idct_1x1 +#define _jpeg_idct_9x9 jpeg12_idct_9x9 +#define _jpeg_idct_10x10 jpeg12_idct_10x10 +#define _jpeg_idct_11x11 jpeg12_idct_11x11 +#define _jpeg_idct_12x12 jpeg12_idct_12x12 +#define _jpeg_idct_13x13 jpeg12_idct_13x13 +#define _jpeg_idct_14x14 jpeg12_idct_14x14 +#define _jpeg_idct_15x15 jpeg12_idct_15x15 +#define _jpeg_idct_16x16 jpeg12_idct_16x16 + +/* Internal fields (cdjpeg.h) */ + +/* Use the 12-bit buffer in the cjpeg_source_struct and djpeg_dest_struct + structures. */ +#define _buffer buffer12 + +/* Image I/O functions (cdjpeg.h) */ +#define _jinit_read_gif j12init_read_gif +#define _jinit_write_gif j12init_write_gif +#define _jinit_read_ppm j12init_read_ppm +#define _jinit_write_ppm j12init_write_ppm + +#define _read_color_map read_color_map_12 + +#else /* BITS_IN_JSAMPLE */ + +/* Sample data types and macros (jmorecfg.h) */ +#define _JSAMPLE JSAMPLE + +#define _MAXJSAMPLE MAXJSAMPLE +#define _CENTERJSAMPLE CENTERJSAMPLE + +#define _JSAMPROW JSAMPROW +#define _JSAMPARRAY JSAMPARRAY +#define _JSAMPIMAGE JSAMPIMAGE + +/* External functions (jpeglib.h) */ +#define _jpeg_write_scanlines jpeg_write_scanlines +#define _jpeg_write_raw_data jpeg_write_raw_data +#define _jpeg_read_scanlines jpeg_read_scanlines +#define _jpeg_skip_scanlines jpeg_skip_scanlines +#define _jpeg_crop_scanline jpeg_crop_scanline +#define _jpeg_read_raw_data jpeg_read_raw_data + +/* Internal methods (jpegint.h) */ + +/* Use the 8-bit method in the jpeg_c_main_controller structure. */ +#define _process_data process_data +/* Use the 8-bit method in the jpeg_c_prep_controller structure. */ +#define _pre_process_data pre_process_data +/* Use the 8-bit method in the jpeg_c_coef_controller structure. */ +#define _compress_data compress_data +/* Use the 8-bit method in the jpeg_color_converter structure. */ +#define _color_convert color_convert +/* Use the 8-bit method in the jpeg_downsampler structure. */ +#define _downsample downsample +/* Use the 8-bit method in the jpeg_forward_dct structure. */ +#define _forward_DCT forward_DCT +/* Use the 8-bit method in the jpeg_d_main_controller structure. */ +#define _process_data process_data +/* Use the 8-bit method in the jpeg_d_coef_controller structure. */ +#define _decompress_data decompress_data +/* Use the 8-bit method in the jpeg_d_post_controller structure. */ +#define _post_process_data post_process_data +/* Use the 8-bit method in the jpeg_inverse_dct structure. */ +#define _inverse_DCT_method_ptr inverse_DCT_method_ptr +#define _inverse_DCT inverse_DCT +/* Use the 8-bit method in the jpeg_upsampler structure. */ +#define _upsample upsample +/* Use the 8-bit method in the jpeg_color_converter structure. */ +#define _color_convert color_convert +/* Use the 8-bit method in the jpeg_color_quantizer structure. */ +#define _color_quantize color_quantize + +/* Global internal functions (jpegint.h) */ +#define _jinit_c_main_controller jinit_c_main_controller +#define _jinit_c_prep_controller jinit_c_prep_controller +#define _jinit_c_coef_controller jinit_c_coef_controller +#define _jinit_color_converter jinit_color_converter +#define _jinit_downsampler jinit_downsampler +#define _jinit_forward_dct jinit_forward_dct +#ifdef C_LOSSLESS_SUPPORTED +#define _jinit_c_diff_controller jinit_c_diff_controller +#define _jinit_lossless_compressor jinit_lossless_compressor +#endif + +#define _jinit_d_main_controller jinit_d_main_controller +#define _jinit_d_coef_controller jinit_d_coef_controller +#define _jinit_d_post_controller jinit_d_post_controller +#define _jinit_inverse_dct jinit_inverse_dct +#define _jinit_upsampler jinit_upsampler +#define _jinit_color_deconverter jinit_color_deconverter +#define _jinit_1pass_quantizer jinit_1pass_quantizer +#define _jinit_2pass_quantizer jinit_2pass_quantizer +#define _jinit_merged_upsampler jinit_merged_upsampler +#ifdef D_LOSSLESS_SUPPORTED +#define _jinit_d_diff_controller jinit_d_diff_controller +#define _jinit_lossless_decompressor jinit_lossless_decompressor +#endif + +#define _jcopy_sample_rows jcopy_sample_rows + +/* Global internal functions (jdct.h) */ +#define _jpeg_fdct_islow jpeg_fdct_islow +#define _jpeg_fdct_ifast jpeg_fdct_ifast + +#define _jpeg_idct_islow jpeg_idct_islow +#define _jpeg_idct_ifast jpeg_idct_ifast +#define _jpeg_idct_float jpeg_idct_float +#define _jpeg_idct_7x7 jpeg_idct_7x7 +#define _jpeg_idct_6x6 jpeg_idct_6x6 +#define _jpeg_idct_5x5 jpeg_idct_5x5 +#define _jpeg_idct_4x4 jpeg_idct_4x4 +#define _jpeg_idct_3x3 jpeg_idct_3x3 +#define _jpeg_idct_2x2 jpeg_idct_2x2 +#define _jpeg_idct_1x1 jpeg_idct_1x1 +#define _jpeg_idct_9x9 jpeg_idct_9x9 +#define _jpeg_idct_10x10 jpeg_idct_10x10 +#define _jpeg_idct_11x11 jpeg_idct_11x11 +#define _jpeg_idct_12x12 jpeg_idct_12x12 +#define _jpeg_idct_13x13 jpeg_idct_13x13 +#define _jpeg_idct_14x14 jpeg_idct_14x14 +#define _jpeg_idct_15x15 jpeg_idct_15x15 +#define _jpeg_idct_16x16 jpeg_idct_16x16 + +/* Internal fields (cdjpeg.h) */ + +/* Use the 8-bit buffer in the cjpeg_source_struct and djpeg_dest_struct + structures. */ +#define _buffer buffer + +/* Image I/O functions (cdjpeg.h) */ +#define _jinit_read_gif jinit_read_gif +#define _jinit_write_gif jinit_write_gif +#define _jinit_read_ppm jinit_read_ppm +#define _jinit_write_ppm jinit_write_ppm + +#define _read_color_map read_color_map + +#endif /* BITS_IN_JSAMPLE */ + +#endif /* JSAMPLECOMP_H */ diff --git a/src/3rdparty/libjpeg/src/jsimd.h b/src/3rdparty/libjpeg/src/jsimd.h index 74d480aa2c0..6ae021a651d 100644 --- a/src/3rdparty/libjpeg/src/jsimd.h +++ b/src/3rdparty/libjpeg/src/jsimd.h @@ -12,6 +12,8 @@ * */ +#ifdef WITH_SIMD + #include "jchuff.h" /* Declarations shared with jcphuff.c */ EXTERN(int) jsimd_can_rgb_ycc(void); @@ -121,3 +123,5 @@ EXTERN(int) jsimd_can_encode_mcu_AC_refine_prepare(void); EXTERN(int) jsimd_encode_mcu_AC_refine_prepare (const JCOEF *block, const int *jpeg_natural_order_start, int Sl, int Al, UJCOEF *absvalues, size_t *bits); + +#endif /* WITH_SIMD */ diff --git a/src/3rdparty/libjpeg/src/jsimd_none.c b/src/3rdparty/libjpeg/src/jsimd_none.c deleted file mode 100644 index a25db73899c..00000000000 --- a/src/3rdparty/libjpeg/src/jsimd_none.c +++ /dev/null @@ -1,431 +0,0 @@ -/* - * jsimd_none.c - * - * Copyright 2009 Pierre Ossman for Cendio AB - * Copyright (C) 2009-2011, 2014, 2022, D. R. Commander. - * Copyright (C) 2015-2016, 2018, 2022, Matthieu Darbois. - * Copyright (C) 2020, Arm Limited. - * - * Based on the x86 SIMD extension for IJG JPEG library, - * Copyright (C) 1999-2006, MIYASAKA Masaru. - * For conditions of distribution and use, see copyright notice in jsimdext.inc - * - * This file contains stubs for when there is no SIMD support available. - */ - -#define JPEG_INTERNALS -#include "jinclude.h" -#include "jpeglib.h" -#include "jsimd.h" -#include "jdct.h" -#include "jsimddct.h" - -GLOBAL(int) -jsimd_can_rgb_ycc(void) -{ - return 0; -} - -GLOBAL(int) -jsimd_can_rgb_gray(void) -{ - return 0; -} - -GLOBAL(int) -jsimd_can_ycc_rgb(void) -{ - return 0; -} - -GLOBAL(int) -jsimd_can_ycc_rgb565(void) -{ - return 0; -} - -GLOBAL(int) -jsimd_c_can_null_convert(void) -{ - return 0; -} - -GLOBAL(void) -jsimd_rgb_ycc_convert(j_compress_ptr cinfo, JSAMPARRAY input_buf, - JSAMPIMAGE output_buf, JDIMENSION output_row, - int num_rows) -{ -} - -GLOBAL(void) -jsimd_rgb_gray_convert(j_compress_ptr cinfo, JSAMPARRAY input_buf, - JSAMPIMAGE output_buf, JDIMENSION output_row, - int num_rows) -{ -} - -GLOBAL(void) -jsimd_ycc_rgb_convert(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, - JDIMENSION input_row, JSAMPARRAY output_buf, - int num_rows) -{ -} - -GLOBAL(void) -jsimd_ycc_rgb565_convert(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, - JDIMENSION input_row, JSAMPARRAY output_buf, - int num_rows) -{ -} - -GLOBAL(void) -jsimd_c_null_convert(j_compress_ptr cinfo, JSAMPARRAY input_buf, - JSAMPIMAGE output_buf, JDIMENSION output_row, - int num_rows) -{ -} - -GLOBAL(int) -jsimd_can_h2v2_downsample(void) -{ - return 0; -} - -GLOBAL(int) -jsimd_can_h2v1_downsample(void) -{ - return 0; -} - -GLOBAL(int) -jsimd_can_h2v2_smooth_downsample(void) -{ - return 0; -} - -GLOBAL(void) -jsimd_h2v2_downsample(j_compress_ptr cinfo, jpeg_component_info *compptr, - JSAMPARRAY input_data, JSAMPARRAY output_data) -{ -} - -GLOBAL(void) -jsimd_h2v2_smooth_downsample(j_compress_ptr cinfo, - jpeg_component_info *compptr, - JSAMPARRAY input_data, JSAMPARRAY output_data) -{ -} - -GLOBAL(void) -jsimd_h2v1_downsample(j_compress_ptr cinfo, jpeg_component_info *compptr, - JSAMPARRAY input_data, JSAMPARRAY output_data) -{ -} - -GLOBAL(int) -jsimd_can_h2v2_upsample(void) -{ - return 0; -} - -GLOBAL(int) -jsimd_can_h2v1_upsample(void) -{ - return 0; -} - -GLOBAL(int) -jsimd_can_int_upsample(void) -{ - return 0; -} - -GLOBAL(void) -jsimd_int_upsample(j_decompress_ptr cinfo, jpeg_component_info *compptr, - JSAMPARRAY input_data, JSAMPARRAY *output_data_ptr) -{ -} - -GLOBAL(void) -jsimd_h2v2_upsample(j_decompress_ptr cinfo, jpeg_component_info *compptr, - JSAMPARRAY input_data, JSAMPARRAY *output_data_ptr) -{ -} - -GLOBAL(void) -jsimd_h2v1_upsample(j_decompress_ptr cinfo, jpeg_component_info *compptr, - JSAMPARRAY input_data, JSAMPARRAY *output_data_ptr) -{ -} - -GLOBAL(int) -jsimd_can_h2v2_fancy_upsample(void) -{ - return 0; -} - -GLOBAL(int) -jsimd_can_h2v1_fancy_upsample(void) -{ - return 0; -} - -GLOBAL(int) -jsimd_can_h1v2_fancy_upsample(void) -{ - return 0; -} - -GLOBAL(void) -jsimd_h2v2_fancy_upsample(j_decompress_ptr cinfo, jpeg_component_info *compptr, - JSAMPARRAY input_data, JSAMPARRAY *output_data_ptr) -{ -} - -GLOBAL(void) -jsimd_h2v1_fancy_upsample(j_decompress_ptr cinfo, jpeg_component_info *compptr, - JSAMPARRAY input_data, JSAMPARRAY *output_data_ptr) -{ -} - -GLOBAL(void) -jsimd_h1v2_fancy_upsample(j_decompress_ptr cinfo, jpeg_component_info *compptr, - JSAMPARRAY input_data, JSAMPARRAY *output_data_ptr) -{ -} - -GLOBAL(int) -jsimd_can_h2v2_merged_upsample(void) -{ - return 0; -} - -GLOBAL(int) -jsimd_can_h2v1_merged_upsample(void) -{ - return 0; -} - -GLOBAL(void) -jsimd_h2v2_merged_upsample(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, - JDIMENSION in_row_group_ctr, JSAMPARRAY output_buf) -{ -} - -GLOBAL(void) -jsimd_h2v1_merged_upsample(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, - JDIMENSION in_row_group_ctr, JSAMPARRAY output_buf) -{ -} - -GLOBAL(int) -jsimd_can_convsamp(void) -{ - return 0; -} - -GLOBAL(int) -jsimd_can_convsamp_float(void) -{ - return 0; -} - -GLOBAL(void) -jsimd_convsamp(JSAMPARRAY sample_data, JDIMENSION start_col, - DCTELEM *workspace) -{ -} - -GLOBAL(void) -jsimd_convsamp_float(JSAMPARRAY sample_data, JDIMENSION start_col, - FAST_FLOAT *workspace) -{ -} - -GLOBAL(int) -jsimd_can_fdct_islow(void) -{ - return 0; -} - -GLOBAL(int) -jsimd_can_fdct_ifast(void) -{ - return 0; -} - -GLOBAL(int) -jsimd_can_fdct_float(void) -{ - return 0; -} - -GLOBAL(void) -jsimd_fdct_islow(DCTELEM *data) -{ -} - -GLOBAL(void) -jsimd_fdct_ifast(DCTELEM *data) -{ -} - -GLOBAL(void) -jsimd_fdct_float(FAST_FLOAT *data) -{ -} - -GLOBAL(int) -jsimd_can_quantize(void) -{ - return 0; -} - -GLOBAL(int) -jsimd_can_quantize_float(void) -{ - return 0; -} - -GLOBAL(void) -jsimd_quantize(JCOEFPTR coef_block, DCTELEM *divisors, DCTELEM *workspace) -{ -} - -GLOBAL(void) -jsimd_quantize_float(JCOEFPTR coef_block, FAST_FLOAT *divisors, - FAST_FLOAT *workspace) -{ -} - -GLOBAL(int) -jsimd_can_idct_2x2(void) -{ - return 0; -} - -GLOBAL(int) -jsimd_can_idct_4x4(void) -{ - return 0; -} - -GLOBAL(int) -jsimd_can_idct_6x6(void) -{ - return 0; -} - -GLOBAL(int) -jsimd_can_idct_12x12(void) -{ - return 0; -} - -GLOBAL(void) -jsimd_idct_2x2(j_decompress_ptr cinfo, jpeg_component_info *compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, - JDIMENSION output_col) -{ -} - -GLOBAL(void) -jsimd_idct_4x4(j_decompress_ptr cinfo, jpeg_component_info *compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, - JDIMENSION output_col) -{ -} - -GLOBAL(void) -jsimd_idct_6x6(j_decompress_ptr cinfo, jpeg_component_info *compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, - JDIMENSION output_col) -{ -} - -GLOBAL(void) -jsimd_idct_12x12(j_decompress_ptr cinfo, jpeg_component_info *compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, - JDIMENSION output_col) -{ -} - -GLOBAL(int) -jsimd_can_idct_islow(void) -{ - return 0; -} - -GLOBAL(int) -jsimd_can_idct_ifast(void) -{ - return 0; -} - -GLOBAL(int) -jsimd_can_idct_float(void) -{ - return 0; -} - -GLOBAL(void) -jsimd_idct_islow(j_decompress_ptr cinfo, jpeg_component_info *compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, - JDIMENSION output_col) -{ -} - -GLOBAL(void) -jsimd_idct_ifast(j_decompress_ptr cinfo, jpeg_component_info *compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, - JDIMENSION output_col) -{ -} - -GLOBAL(void) -jsimd_idct_float(j_decompress_ptr cinfo, jpeg_component_info *compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, - JDIMENSION output_col) -{ -} - -GLOBAL(int) -jsimd_can_huff_encode_one_block(void) -{ - return 0; -} - -GLOBAL(JOCTET *) -jsimd_huff_encode_one_block(void *state, JOCTET *buffer, JCOEFPTR block, - int last_dc_val, c_derived_tbl *dctbl, - c_derived_tbl *actbl) -{ - return NULL; -} - -GLOBAL(int) -jsimd_can_encode_mcu_AC_first_prepare(void) -{ - return 0; -} - -GLOBAL(void) -jsimd_encode_mcu_AC_first_prepare(const JCOEF *block, - const int *jpeg_natural_order_start, int Sl, - int Al, UJCOEF *values, size_t *zerobits) -{ -} - -GLOBAL(int) -jsimd_can_encode_mcu_AC_refine_prepare(void) -{ - return 0; -} - -GLOBAL(int) -jsimd_encode_mcu_AC_refine_prepare(const JCOEF *block, - const int *jpeg_natural_order_start, int Sl, - int Al, UJCOEF *absvalues, size_t *bits) -{ - return 0; -} diff --git a/src/3rdparty/libjpeg/src/jutils.c b/src/3rdparty/libjpeg/src/jutils.c index d86271624a6..24caac19021 100644 --- a/src/3rdparty/libjpeg/src/jutils.c +++ b/src/3rdparty/libjpeg/src/jutils.c @@ -17,8 +17,11 @@ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" +#include "jsamplecomp.h" +#if BITS_IN_JSAMPLE == 8 + /* * jpeg_zigzag_order[i] is the zigzag-order position of the i'th element * of a DCT block read in natural order (left to right, top to bottom). @@ -89,19 +92,24 @@ jround_up(long a, long b) return a - (a % b); } +#endif /* BITS_IN_JSAMPLE == 8 */ + + +#if BITS_IN_JSAMPLE != 16 || \ + defined(C_LOSSLESS_SUPPORTED) || defined(D_LOSSLESS_SUPPORTED) GLOBAL(void) -jcopy_sample_rows(JSAMPARRAY input_array, int source_row, - JSAMPARRAY output_array, int dest_row, int num_rows, - JDIMENSION num_cols) +_jcopy_sample_rows(_JSAMPARRAY input_array, int source_row, + _JSAMPARRAY output_array, int dest_row, int num_rows, + JDIMENSION num_cols) /* Copy some rows of samples from one place to another. * num_rows rows are copied from input_array[source_row++] * to output_array[dest_row++]; these areas may overlap for duplication. * The source and destination arrays must be at least as wide as num_cols. */ { - register JSAMPROW inptr, outptr; - register size_t count = (size_t)(num_cols * sizeof(JSAMPLE)); + register _JSAMPROW inptr, outptr; + register size_t count = (size_t)(num_cols * sizeof(_JSAMPLE)); register int row; input_array += source_row; @@ -114,6 +122,11 @@ jcopy_sample_rows(JSAMPARRAY input_array, int source_row, } } +#endif /* BITS_IN_JSAMPLE != 16 || + defined(C_LOSSLESS_SUPPORTED) || defined(D_LOSSLESS_SUPPORTED) */ + + +#if BITS_IN_JSAMPLE == 8 GLOBAL(void) jcopy_block_row(JBLOCKROW input_row, JBLOCKROW output_row, @@ -131,3 +144,5 @@ jzero_far(void *target, size_t bytestozero) { memset(target, 0, bytestozero); } + +#endif /* BITS_IN_JSAMPLE == 8 */ diff --git a/src/3rdparty/libjpeg/src/jversion.h b/src/3rdparty/libjpeg/src/jversion.h index ea6de648d92..f9ad5c29c99 100644 --- a/src/3rdparty/libjpeg/src/jversion.h +++ b/src/3rdparty/libjpeg/src/jversion.h @@ -48,6 +48,7 @@ "Copyright (C) 2009, 2012 Pierre Ossman for Cendio AB\n" \ "Copyright (C) 2009-2011 Nokia Corporation and/or its subsidiary(-ies)\n" \ "Copyright (C) 1999-2006 MIYASAKA Masaru\n" \ + "Copyright (C) 1999 Ken Murchison\n" \ "Copyright (C) 1991-2020 Thomas G. Lane, Guido Vollbeding" #define JCOPYRIGHT_SHORT \ From ec33e65079910af42838dcf71d28d98607c5a2fa Mon Sep 17 00:00:00 2001 From: Axel Spoerl Date: Fri, 11 Aug 2023 09:20:44 +0200 Subject: [PATCH 119/151] QDockWidgetGroupWindow::adjustFlags() - don't show() empty group window The method calls show() on a dock widget group window, when the window flags have changed. When all of its contained, tabbed dock widgets are programmatically hidden or docked on the main window, an empty group window is shown. This patch implements bool hasVisibleDockWidgets(). It returns true, if at least one of the group window's dockwidget children is not hidden. It replaces show() by setVisible(), passing the return value of hasVisibleChildren(). It adapts tst_QDockWidget::floatingTabs() to test the fix. (Drive-by: remove dead code) Fixes: QTBUG-115058 Change-Id: Ifb8e2450e91a7c78decc06f592e160631ca2faf5 Reviewed-by: Richard Moe Gustavsen (cherry picked from commit e03bc88a80382b68359ba6ea5fc4cb9507ceb85f) Reviewed-by: Qt CI Bot --- src/widgets/widgets/qmainwindowlayout.cpp | 21 ++++++++++++++++++- src/widgets/widgets/qmainwindowlayout_p.h | 1 + .../widgets/qdockwidget/tst_qdockwidget.cpp | 15 ++++++++++--- 3 files changed, 33 insertions(+), 4 deletions(-) diff --git a/src/widgets/widgets/qmainwindowlayout.cpp b/src/widgets/widgets/qmainwindowlayout.cpp index 4a400cd9509..f0ed1ca399f 100644 --- a/src/widgets/widgets/qmainwindowlayout.cpp +++ b/src/widgets/widgets/qmainwindowlayout.cpp @@ -460,6 +460,25 @@ void QDockWidgetGroupWindow::destroyOrHideIfEmpty() deleteLater(); } +/*! + \internal + \return \c true if the group window has at least one visible QDockWidget child, + otherwise false. + */ +bool QDockWidgetGroupWindow::hasVisibleDockWidgets() const +{ + const auto &children = findChildren(QString(), Qt::FindChildrenRecursively); + for (auto child : children) { + // WA_WState_Visible is set on the dock widget, associated to the active tab + // and unset on all others. + // WA_WState_Hidden is set if the dock widgets have been explicitly hidden. + // This is the relevant information to check (equivalent to !child->isHidden()). + if (!child->testAttribute(Qt::WA_WState_Hidden)) + return true; + } + return false; +} + /*! \internal Sets the flags of this window in accordance to the capabilities of the dock widgets */ @@ -508,7 +527,7 @@ void QDockWidgetGroupWindow::adjustFlags() m_removedFrameSize = QSize(); } - show(); // setWindowFlags hides the window + setVisible(hasVisibleDockWidgets()); } QWidget *titleBarOf = top ? top : parentWidget(); diff --git a/src/widgets/widgets/qmainwindowlayout_p.h b/src/widgets/widgets/qmainwindowlayout_p.h index 30122f881e1..2a387efe28e 100644 --- a/src/widgets/widgets/qmainwindowlayout_p.h +++ b/src/widgets/widgets/qmainwindowlayout_p.h @@ -350,6 +350,7 @@ public: QDockWidget *activeTabbedDockWidget() const; #endif void destroyOrHideIfEmpty(); + bool hasVisibleDockWidgets() const; void adjustFlags(); bool hasNativeDecos() const; diff --git a/tests/auto/widgets/widgets/qdockwidget/tst_qdockwidget.cpp b/tests/auto/widgets/widgets/qdockwidget/tst_qdockwidget.cpp index 9c09d0d4336..043f3105325 100644 --- a/tests/auto/widgets/widgets/qdockwidget/tst_qdockwidget.cpp +++ b/tests/auto/widgets/widgets/qdockwidget/tst_qdockwidget.cpp @@ -1385,8 +1385,6 @@ void tst_QDockWidget::floatingTabs() // Both dock widgets must no longer be floating // disabled due to flakiness on macOS and Windows - //QTRY_VERIFY(!d1->isFloating()); - //QTRY_VERIFY(!d2->isFloating()); if (d1->isFloating()) qWarning("OS flakiness: D1 is docked and reports being floating"); if (d2->isFloating()) @@ -1394,7 +1392,18 @@ void tst_QDockWidget::floatingTabs() // Now MainWindow has to have a floatingTab child QPointer ftabs; - QTRY_VERIFY(checkFloatingTabs(mainWindow, ftabs, QList() << d1 << d2)); + QTRY_VERIFY(checkFloatingTabs(mainWindow, ftabs, QList() << d1 << d2)); + + // Hide both dock widgets. Verify that the group window is also hidden. + qCDebug(lcTestDockWidget) << "*** Hide and show tabbed dock widgets ***"; + d1->hide(); + d2->hide(); + QTRY_VERIFY(ftabs->isHidden()); + + // Show both dockwidgets again. Verify that the group window is visible. + d1->show(); + d2->show(); + QTRY_VERIFY(ftabs->isVisible()); /* * replug both dock widgets into their initial position From b0a0a0fcfee99e9dfdd355bc0ffe2091583c70de Mon Sep 17 00:00:00 2001 From: Christian Ehrlicher Date: Fri, 25 Aug 2023 16:52:00 +0200 Subject: [PATCH 120/151] SQLite: Update SQLite to v3.43.0 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [ChangeLog][Third-Party Code] Updated SQLite to v3.43.0 Fixes: QTBUG-116248 Change-Id: I039f572d21a8506faa5e29a48cdc7e40f990d946 Reviewed-by: Volker Hilsheimer Reviewed-by: Kai Köhne (cherry picked from commit 49e52e8dd68cc58b9c9ec9bd2c1f89184845d746) Reviewed-by: Qt Cherry-pick Bot --- src/3rdparty/sqlite/qt_attribution.json | 4 +- src/3rdparty/sqlite/sqlite3.c | 7714 ++++++++++++++++------- src/3rdparty/sqlite/sqlite3.h | 106 +- 3 files changed, 5523 insertions(+), 2301 deletions(-) diff --git a/src/3rdparty/sqlite/qt_attribution.json b/src/3rdparty/sqlite/qt_attribution.json index 8561fa8b4c0..ea114ee4224 100644 --- a/src/3rdparty/sqlite/qt_attribution.json +++ b/src/3rdparty/sqlite/qt_attribution.json @@ -6,8 +6,8 @@ "Description": "SQLite is a small C library that implements a self-contained, embeddable, zero-configuration SQL database engine.", "Homepage": "https://www.sqlite.org/", - "Version": "3.42.0", - "DownloadLocation": "https://sqlite.org/2023/sqlite-amalgamation-3420000.zip", + "Version": "3.43.0", + "DownloadLocation": "https://sqlite.org/2023/sqlite-amalgamation-3430000.zip", "License": "Public Domain", "Copyright": "The authors disclaim copyright to the source code. However, a license can be obtained if needed." } diff --git a/src/3rdparty/sqlite/sqlite3.c b/src/3rdparty/sqlite/sqlite3.c index dd3b5c57570..310583f996c 100644 --- a/src/3rdparty/sqlite/sqlite3.c +++ b/src/3rdparty/sqlite/sqlite3.c @@ -1,6 +1,6 @@ /****************************************************************************** ** This file is an amalgamation of many separate C source files from SQLite -** version 3.42.0. By combining all the individual C code files into this +** version 3.43.0. By combining all the individual C code files into this ** single large file, the entire code can be compiled as a single translation ** unit. This allows many compilers to do optimizations that would not be ** possible if the files were compiled separately. Performance improvements @@ -16,6 +16,9 @@ ** if you want a wrapper to interface SQLite with your choice of programming ** language. The code for the "sqlite3" command-line shell is also in a ** separate file. This file contains only code for the core SQLite library. +** +** The content in this amalgamation comes from Fossil check-in +** f80b798b3f4b81a7bb4233c58294edd0f11. */ #define SQLITE_CORE 1 #define SQLITE_AMALGAMATION 1 @@ -50,11 +53,11 @@ ** used on lines of code that actually ** implement parts of coverage testing. ** -** OPTIMIZATION-IF-TRUE - This branch is allowed to alway be false +** OPTIMIZATION-IF-TRUE - This branch is allowed to always be false ** and the correct answer is still obtained, ** though perhaps more slowly. ** -** OPTIMIZATION-IF-FALSE - This branch is allowed to alway be true +** OPTIMIZATION-IF-FALSE - This branch is allowed to always be true ** and the correct answer is still obtained, ** though perhaps more slowly. ** @@ -456,9 +459,9 @@ extern "C" { ** [sqlite3_libversion_number()], [sqlite3_sourceid()], ** [sqlite_version()] and [sqlite_source_id()]. */ -#define SQLITE_VERSION "3.42.0" -#define SQLITE_VERSION_NUMBER 3042000 -#define SQLITE_SOURCE_ID "2023-05-16 12:36:15 831d0fb2836b71c9bc51067c49fee4b8f18047814f2ff22d817d25195cf350b0" +#define SQLITE_VERSION "3.43.0" +#define SQLITE_VERSION_NUMBER 3043000 +#define SQLITE_SOURCE_ID "2023-08-24 12:36:59 0f80b798b3f4b81a7bb4233c58294edd0f1156f36b6ecf5ab8e83631d468778c" /* ** CAPI3REF: Run-Time Library Version Numbers @@ -838,6 +841,7 @@ SQLITE_API int sqlite3_exec( #define SQLITE_IOERR_ROLLBACK_ATOMIC (SQLITE_IOERR | (31<<8)) #define SQLITE_IOERR_DATA (SQLITE_IOERR | (32<<8)) #define SQLITE_IOERR_CORRUPTFS (SQLITE_IOERR | (33<<8)) +#define SQLITE_IOERR_IN_PAGE (SQLITE_IOERR | (34<<8)) #define SQLITE_LOCKED_SHAREDCACHE (SQLITE_LOCKED | (1<<8)) #define SQLITE_LOCKED_VTAB (SQLITE_LOCKED | (2<<8)) #define SQLITE_BUSY_RECOVERY (SQLITE_BUSY | (1<<8)) @@ -1500,7 +1504,7 @@ struct sqlite3_io_methods { ** by clients within the current process, only within other processes. ** **
  • [[SQLITE_FCNTL_CKSM_FILE]] -** The [SQLITE_FCNTL_CKSM_FILE] opcode is for use interally by the +** The [SQLITE_FCNTL_CKSM_FILE] opcode is for use internally by the ** [checksum VFS shim] only. ** **
  • [[SQLITE_FCNTL_RESET_CACHE]] @@ -2764,7 +2768,7 @@ struct sqlite3_mem_methods { ** the [VACUUM] command will fail with an obscure error when attempting to ** process a table with generated columns and a descending index. This is ** not considered a bug since SQLite versions 3.3.0 and earlier do not support -** either generated columns or decending indexes. +** either generated columns or descending indexes. ** ** ** [[SQLITE_DBCONFIG_STMT_SCANSTATUS]] @@ -3045,6 +3049,7 @@ SQLITE_API sqlite3_int64 sqlite3_total_changes64(sqlite3*); ** ** ^The [sqlite3_is_interrupted(D)] interface can be used to determine whether ** or not an interrupt is currently in effect for [database connection] D. +** It returns 1 if an interrupt is currently in effect, or 0 otherwise. */ SQLITE_API void sqlite3_interrupt(sqlite3*); SQLITE_API int sqlite3_is_interrupted(sqlite3*); @@ -3698,8 +3703,10 @@ SQLITE_API SQLITE_DEPRECATED void *sqlite3_profile(sqlite3*, ** M argument should be the bitwise OR-ed combination of ** zero or more [SQLITE_TRACE] constants. ** -** ^Each call to either sqlite3_trace() or sqlite3_trace_v2() overrides -** (cancels) any prior calls to sqlite3_trace() or sqlite3_trace_v2(). +** ^Each call to either sqlite3_trace(D,X,P) or sqlite3_trace_v2(D,M,X,P) +** overrides (cancels) all prior calls to sqlite3_trace(D,X,P) or +** sqlite3_trace_v2(D,M,X,P) for the [database connection] D. Each +** database connection may have at most one trace callback. ** ** ^The X callback is invoked whenever any of the events identified by ** mask M occur. ^The integer return value from the callback is currently @@ -4068,7 +4075,7 @@ SQLITE_API int sqlite3_open_v2( ** as F) must be one of: **
      **
    • A database filename pointer created by the SQLite core and -** passed into the xOpen() method of a VFS implemention, or +** passed into the xOpen() method of a VFS implementation, or **
    • A filename obtained from [sqlite3_db_filename()], or **
    • A new filename constructed using [sqlite3_create_filename()]. **
    @@ -4181,7 +4188,7 @@ SQLITE_API sqlite3_file *sqlite3_database_file_object(const char*); /* ** CAPI3REF: Create and Destroy VFS Filenames ** -** These interfces are provided for use by [VFS shim] implementations and +** These interfaces are provided for use by [VFS shim] implementations and ** are not useful outside of that context. ** ** The sqlite3_create_filename(D,J,W,N,P) allocates memory to hold a version of @@ -4728,6 +4735,41 @@ SQLITE_API int sqlite3_stmt_readonly(sqlite3_stmt *pStmt); */ SQLITE_API int sqlite3_stmt_isexplain(sqlite3_stmt *pStmt); +/* +** CAPI3REF: Change The EXPLAIN Setting For A Prepared Statement +** METHOD: sqlite3_stmt +** +** The sqlite3_stmt_explain(S,E) interface changes the EXPLAIN +** setting for [prepared statement] S. If E is zero, then S becomes +** a normal prepared statement. If E is 1, then S behaves as if +** its SQL text began with "[EXPLAIN]". If E is 2, then S behaves as if +** its SQL text began with "[EXPLAIN QUERY PLAN]". +** +** Calling sqlite3_stmt_explain(S,E) might cause S to be reprepared. +** SQLite tries to avoid a reprepare, but a reprepare might be necessary +** on the first transition into EXPLAIN or EXPLAIN QUERY PLAN mode. +** +** Because of the potential need to reprepare, a call to +** sqlite3_stmt_explain(S,E) will fail with SQLITE_ERROR if S cannot be +** reprepared because it was created using [sqlite3_prepare()] instead of +** the newer [sqlite3_prepare_v2()] or [sqlite3_prepare_v3()] interfaces and +** hence has no saved SQL text with which to reprepare. +** +** Changing the explain setting for a prepared statement does not change +** the original SQL text for the statement. Hence, if the SQL text originally +** began with EXPLAIN or EXPLAIN QUERY PLAN, but sqlite3_stmt_explain(S,0) +** is called to convert the statement into an ordinary statement, the EXPLAIN +** or EXPLAIN QUERY PLAN keywords will still appear in the sqlite3_sql(S) +** output, even though the statement now acts like a normal SQL statement. +** +** This routine returns SQLITE_OK if the explain mode is successfully +** changed, or an error code if the explain mode could not be changed. +** The explain mode cannot be changed while a statement is active. +** Hence, it is good practice to call [sqlite3_reset(S)] +** immediately prior to calling sqlite3_stmt_explain(S,E). +*/ +SQLITE_API int sqlite3_stmt_explain(sqlite3_stmt *pStmt, int eMode); + /* ** CAPI3REF: Determine If A Prepared Statement Has Been Reset ** METHOD: sqlite3_stmt @@ -4891,7 +4933,7 @@ typedef struct sqlite3_context sqlite3_context; ** with it may be passed. ^It is called to dispose of the BLOB or string even ** if the call to the bind API fails, except the destructor is not called if ** the third parameter is a NULL pointer or the fourth parameter is negative. -** ^ (2) The special constant, [SQLITE_STATIC], may be passsed to indicate that +** ^ (2) The special constant, [SQLITE_STATIC], may be passed to indicate that ** the application remains responsible for disposing of the object. ^In this ** case, the object and the provided pointer to it must remain valid until ** either the prepared statement is finalized or the same SQL parameter is @@ -5570,14 +5612,26 @@ SQLITE_API int sqlite3_finalize(sqlite3_stmt *pStmt); ** ^The [sqlite3_reset(S)] interface resets the [prepared statement] S ** back to the beginning of its program. ** -** ^If the most recent call to [sqlite3_step(S)] for the -** [prepared statement] S returned [SQLITE_ROW] or [SQLITE_DONE], -** or if [sqlite3_step(S)] has never before been called on S, -** then [sqlite3_reset(S)] returns [SQLITE_OK]. +** ^The return code from [sqlite3_reset(S)] indicates whether or not +** the previous evaluation of prepared statement S completed successfully. +** ^If [sqlite3_step(S)] has never before been called on S or if +** [sqlite3_step(S)] has not been called since the previous call +** to [sqlite3_reset(S)], then [sqlite3_reset(S)] will return +** [SQLITE_OK]. ** ** ^If the most recent call to [sqlite3_step(S)] for the ** [prepared statement] S indicated an error, then ** [sqlite3_reset(S)] returns an appropriate [error code]. +** ^The [sqlite3_reset(S)] interface might also return an [error code] +** if there were no prior errors but the process of resetting +** the prepared statement caused a new error. ^For example, if an +** [INSERT] statement with a [RETURNING] clause is only stepped one time, +** that one call to [sqlite3_step(S)] might return SQLITE_ROW but +** the overall statement might still fail and the [sqlite3_reset(S)] call +** might return SQLITE_BUSY if locking constraints prevent the +** database change from committing. Therefore, it is important that +** applications check the return code from [sqlite3_reset(S)] even if +** no prior call to [sqlite3_step(S)] indicated a problem. ** ** ^The [sqlite3_reset(S)] interface does not change the values ** of any [sqlite3_bind_blob|bindings] on the [prepared statement] S. @@ -5794,7 +5848,7 @@ SQLITE_API int sqlite3_create_window_function( ** [application-defined SQL function] ** that has side-effects or that could potentially leak sensitive information. ** This will prevent attacks in which an application is tricked -** into using a database file that has had its schema surreptiously +** into using a database file that has had its schema surreptitiously ** modified to invoke the application-defined function in ways that are ** harmful. **

    @@ -8471,7 +8525,8 @@ SQLITE_API int sqlite3_test_control(int op, ...); #define SQLITE_TESTCTRL_TRACEFLAGS 31 #define SQLITE_TESTCTRL_TUNE 32 #define SQLITE_TESTCTRL_LOGEST 33 -#define SQLITE_TESTCTRL_LAST 33 /* Largest TESTCTRL */ +#define SQLITE_TESTCTRL_USELONGDOUBLE 34 +#define SQLITE_TESTCTRL_LAST 34 /* Largest TESTCTRL */ /* ** CAPI3REF: SQL Keyword Checking @@ -9503,8 +9558,8 @@ SQLITE_API int sqlite3_backup_pagecount(sqlite3_backup *p); ** blocked connection already has a registered unlock-notify callback, ** then the new callback replaces the old.)^ ^If sqlite3_unlock_notify() is ** called with a NULL pointer as its second argument, then any existing -** unlock-notify callback is canceled. ^The blocked connections -** unlock-notify callback may also be canceled by closing the blocked +** unlock-notify callback is cancelled. ^The blocked connections +** unlock-notify callback may also be cancelled by closing the blocked ** connection using [sqlite3_close()]. ** ** The unlock-notify callback is not reentrant. If an application invokes @@ -9927,7 +9982,7 @@ SQLITE_API int sqlite3_vtab_config(sqlite3*, int op, ...); ** [[SQLITE_VTAB_DIRECTONLY]]

    SQLITE_VTAB_DIRECTONLY
    **
    Calls of the form ** [sqlite3_vtab_config](db,SQLITE_VTAB_DIRECTONLY) from within the -** the [xConnect] or [xCreate] methods of a [virtual table] implmentation +** the [xConnect] or [xCreate] methods of a [virtual table] implementation ** prohibits that virtual table from being used from within triggers and ** views. **
    @@ -10117,7 +10172,7 @@ SQLITE_API int sqlite3_vtab_distinct(sqlite3_index_info*); ** communicated to the xBestIndex method as a ** [SQLITE_INDEX_CONSTRAINT_EQ] constraint.)^ If xBestIndex wants to use ** this constraint, it must set the corresponding -** aConstraintUsage[].argvIndex to a postive integer. ^(Then, under +** aConstraintUsage[].argvIndex to a positive integer. ^(Then, under ** the usual mode of handling IN operators, SQLite generates [bytecode] ** that invokes the [xFilter|xFilter() method] once for each value ** on the right-hand side of the IN operator.)^ Thus the virtual table @@ -10546,7 +10601,7 @@ SQLITE_API int sqlite3_db_cacheflush(sqlite3*); ** When the [sqlite3_blob_write()] API is used to update a blob column, ** the pre-update hook is invoked with SQLITE_DELETE. This is because the ** in this case the new values are not available. In this case, when a -** callback made with op==SQLITE_DELETE is actuall a write using the +** callback made with op==SQLITE_DELETE is actually a write using the ** sqlite3_blob_write() API, the [sqlite3_preupdate_blobwrite()] returns ** the index of the column being written. In other cases, where the ** pre-update hook is being invoked for some other reason, including a @@ -13064,7 +13119,7 @@ struct Fts5PhraseIter { ** See xPhraseFirstColumn above. */ struct Fts5ExtensionApi { - int iVersion; /* Currently always set to 3 */ + int iVersion; /* Currently always set to 2 */ void *(*xUserData)(Fts5Context*); @@ -13293,8 +13348,8 @@ struct Fts5ExtensionApi { ** as separate queries of the FTS index are required for each synonym. ** ** When using methods (2) or (3), it is important that the tokenizer only -** provide synonyms when tokenizing document text (method (2)) or query -** text (method (3)), not both. Doing so will not cause any errors, but is +** provide synonyms when tokenizing document text (method (3)) or query +** text (method (2)), not both. Doing so will not cause any errors, but is ** inefficient. */ typedef struct Fts5Tokenizer Fts5Tokenizer; @@ -13342,7 +13397,7 @@ struct fts5_api { int (*xCreateTokenizer)( fts5_api *pApi, const char *zName, - void *pContext, + void *pUserData, fts5_tokenizer *pTokenizer, void (*xDestroy)(void*) ); @@ -13351,7 +13406,7 @@ struct fts5_api { int (*xFindTokenizer)( fts5_api *pApi, const char *zName, - void **ppContext, + void **ppUserData, fts5_tokenizer *pTokenizer ); @@ -13359,7 +13414,7 @@ struct fts5_api { int (*xCreateFunction)( fts5_api *pApi, const char *zName, - void *pContext, + void *pUserData, fts5_extension_function xFunction, void (*xDestroy)(void*) ); @@ -13470,7 +13525,7 @@ struct fts5_api { ** level of recursion for each term. A stack overflow can result ** if the number of terms is too large. In practice, most SQL ** never has more than 3 or 4 terms. Use a value of 0 to disable -** any limit on the number of terms in a compount SELECT. +** any limit on the number of terms in a compound SELECT. */ #ifndef SQLITE_MAX_COMPOUND_SELECT # define SQLITE_MAX_COMPOUND_SELECT 500 @@ -14573,8 +14628,31 @@ typedef INT16_TYPE LogEst; ** the end of buffer S. This macro returns true if P points to something ** contained within the buffer S. */ -#define SQLITE_WITHIN(P,S,E) (((uptr)(P)>=(uptr)(S))&&((uptr)(P)<(uptr)(E))) +#define SQLITE_WITHIN(P,S,E) (((uptr)(P)>=(uptr)(S))&&((uptr)(P)<(uptr)(E))) +/* +** P is one byte past the end of a large buffer. Return true if a span of bytes +** between S..E crosses the end of that buffer. In other words, return true +** if the sub-buffer S..E-1 overflows the buffer whose last byte is P-1. +** +** S is the start of the span. E is one byte past the end of end of span. +** +** P +** |-----------------| FALSE +** |-------| +** S E +** +** P +** |-----------------| +** |-------| TRUE +** S E +** +** P +** |-----------------| +** |-------| FALSE +** S E +*/ +#define SQLITE_OVERFLOW(P,S,E) (((uptr)(S)<(uptr)(P))&&((uptr)(E)>(uptr)(P))) /* ** Macros to determine whether the machine is big or little endian, @@ -14808,7 +14886,7 @@ struct BusyHandler { /* ** Name of table that holds the database schema. ** -** The PREFERRED names are used whereever possible. But LEGACY is also +** The PREFERRED names are used wherever possible. But LEGACY is also ** used for backwards compatibility. ** ** 1. Queries can use either the PREFERRED or the LEGACY names @@ -14922,6 +15000,7 @@ typedef struct Schema Schema; typedef struct Expr Expr; typedef struct ExprList ExprList; typedef struct FKey FKey; +typedef struct FpDecode FpDecode; typedef struct FuncDestructor FuncDestructor; typedef struct FuncDef FuncDef; typedef struct FuncDefHash FuncDefHash; @@ -14940,6 +15019,7 @@ typedef struct Parse Parse; typedef struct ParseCleanup ParseCleanup; typedef struct PreUpdate PreUpdate; typedef struct PrintfArguments PrintfArguments; +typedef struct RCStr RCStr; typedef struct RenameToken RenameToken; typedef struct Returning Returning; typedef struct RowSet RowSet; @@ -15577,6 +15657,10 @@ SQLITE_PRIVATE void sqlite3PagerRefdump(Pager*); # define enable_simulated_io_errors() #endif +#if defined(SQLITE_USE_SEH) && !defined(SQLITE_OMIT_WAL) +SQLITE_PRIVATE int sqlite3PagerWalSystemErrno(Pager*); +#endif + #endif /* SQLITE_PAGER_H */ /************** End of pager.h ***********************************************/ @@ -15906,9 +15990,7 @@ SQLITE_PRIVATE int sqlite3BtreePrevious(BtCursor*, int flags); SQLITE_PRIVATE i64 sqlite3BtreeIntegerKey(BtCursor*); SQLITE_PRIVATE void sqlite3BtreeCursorPin(BtCursor*); SQLITE_PRIVATE void sqlite3BtreeCursorUnpin(BtCursor*); -#ifdef SQLITE_ENABLE_OFFSET_SQL_FUNC SQLITE_PRIVATE i64 sqlite3BtreeOffset(BtCursor*); -#endif SQLITE_PRIVATE int sqlite3BtreePayload(BtCursor*, u32 offset, u32 amt, void*); SQLITE_PRIVATE const void *sqlite3BtreePayloadFetch(BtCursor*, u32 *pAmt); SQLITE_PRIVATE u32 sqlite3BtreePayloadSize(BtCursor*); @@ -16383,7 +16465,7 @@ typedef struct VdbeOpList VdbeOpList; /* 8 */ 0x01, 0x01, 0x01, 0x01, 0x03, 0x03, 0x01, 0x01,\ /* 16 */ 0x03, 0x03, 0x01, 0x12, 0x01, 0x49, 0x49, 0x49,\ /* 24 */ 0x49, 0x01, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49,\ -/* 32 */ 0x41, 0x01, 0x01, 0x01, 0x41, 0x01, 0x41, 0x41,\ +/* 32 */ 0x41, 0x01, 0x41, 0x41, 0x41, 0x01, 0x41, 0x41,\ /* 40 */ 0x41, 0x41, 0x41, 0x26, 0x26, 0x41, 0x23, 0x0b,\ /* 48 */ 0x01, 0x01, 0x03, 0x03, 0x0b, 0x0b, 0x0b, 0x0b,\ /* 56 */ 0x0b, 0x0b, 0x01, 0x03, 0x03, 0x03, 0x01, 0x41,\ @@ -16395,7 +16477,7 @@ typedef struct VdbeOpList VdbeOpList; /* 104 */ 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26,\ /* 112 */ 0x40, 0x00, 0x12, 0x40, 0x40, 0x10, 0x40, 0x00,\ /* 120 */ 0x00, 0x00, 0x40, 0x00, 0x40, 0x40, 0x10, 0x10,\ -/* 128 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50,\ +/* 128 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x50,\ /* 136 */ 0x00, 0x40, 0x04, 0x04, 0x00, 0x40, 0x50, 0x40,\ /* 144 */ 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00,\ /* 152 */ 0x00, 0x10, 0x00, 0x00, 0x06, 0x10, 0x00, 0x04,\ @@ -16577,7 +16659,7 @@ SQLITE_PRIVATE void sqlite3VdbeNoopComment(Vdbe*, const char*, ...); ** The VdbeCoverage macros are used to set a coverage testing point ** for VDBE branch instructions. The coverage testing points are line ** numbers in the sqlite3.c source file. VDBE branch coverage testing -** only works with an amalagmation build. That's ok since a VDBE branch +** only works with an amalgamation build. That's ok since a VDBE branch ** coverage build designed for testing the test suite only. No application ** should ever ship with VDBE branch coverage measuring turned on. ** @@ -16595,7 +16677,7 @@ SQLITE_PRIVATE void sqlite3VdbeNoopComment(Vdbe*, const char*, ...); ** // NULL option is not possible ** ** VdbeCoverageEqNe(v) // Previous OP_Jump is only interested -** // in distingishing equal and not-equal. +** // in distinguishing equal and not-equal. ** ** Every VDBE branch operation must be tagged with one of the macros above. ** If not, then when "make test" is run with -DSQLITE_VDBE_COVERAGE and @@ -16605,7 +16687,7 @@ SQLITE_PRIVATE void sqlite3VdbeNoopComment(Vdbe*, const char*, ...); ** During testing, the test application will invoke ** sqlite3_test_control(SQLITE_TESTCTRL_VDBE_COVERAGE,...) to set a callback ** routine that is invoked as each bytecode branch is taken. The callback -** contains the sqlite3.c source line number ov the VdbeCoverage macro and +** contains the sqlite3.c source line number of the VdbeCoverage macro and ** flags to indicate whether or not the branch was taken. The test application ** is responsible for keeping track of this and reporting byte-code branches ** that are never taken. @@ -16944,7 +17026,7 @@ SQLITE_API int sqlite3_mutex_held(sqlite3_mutex*); /* ** Default synchronous levels. ** -** Note that (for historcal reasons) the PAGER_SYNCHRONOUS_* macros differ +** Note that (for historical reasons) the PAGER_SYNCHRONOUS_* macros differ ** from the SQLITE_DEFAULT_SYNCHRONOUS value by 1. ** ** PAGER_SYNCHRONOUS DEFAULT_SYNCHRONOUS @@ -16983,7 +17065,7 @@ struct Db { ** An instance of the following structure stores a database schema. ** ** Most Schema objects are associated with a Btree. The exception is -** the Schema for the TEMP databaes (sqlite3.aDb[1]) which is free-standing. +** the Schema for the TEMP database (sqlite3.aDb[1]) which is free-standing. ** In shared cache mode, a single Schema object can be shared by multiple ** Btrees that refer to the same underlying BtShared object. ** @@ -17094,7 +17176,7 @@ struct Lookaside { LookasideSlot *pInit; /* List of buffers not previously used */ LookasideSlot *pFree; /* List of available buffers */ #ifndef SQLITE_OMIT_TWOSIZE_LOOKASIDE - LookasideSlot *pSmallInit; /* List of small buffers not prediously used */ + LookasideSlot *pSmallInit; /* List of small buffers not previously used */ LookasideSlot *pSmallFree; /* List of available small buffers */ void *pMiddle; /* First byte past end of full-size buffers and ** the first byte of LOOKASIDE_SMALL buffers */ @@ -17111,7 +17193,7 @@ struct LookasideSlot { #define EnableLookaside db->lookaside.bDisable--;\ db->lookaside.sz=db->lookaside.bDisable?0:db->lookaside.szTrue -/* Size of the smaller allocations in two-size lookside */ +/* Size of the smaller allocations in two-size lookaside */ #ifdef SQLITE_OMIT_TWOSIZE_LOOKASIDE # define LOOKASIDE_SMALL 0 #else @@ -17450,6 +17532,7 @@ struct sqlite3 { #define SQLITE_IndexedExpr 0x01000000 /* Pull exprs from index when able */ #define SQLITE_Coroutines 0x02000000 /* Co-routines for subqueries */ #define SQLITE_NullUnusedCols 0x04000000 /* NULL unused columns in subqueries */ +#define SQLITE_OnePass 0x08000000 /* Single-pass DELETE and UPDATE */ #define SQLITE_AllOpts 0xffffffff /* All optimizations */ /* @@ -17532,6 +17615,7 @@ struct FuncDestructor { ** SQLITE_FUNC_ANYORDER == NC_OrderAgg == SF_OrderByReqd ** SQLITE_FUNC_LENGTH == OPFLAG_LENGTHARG ** SQLITE_FUNC_TYPEOF == OPFLAG_TYPEOFARG +** SQLITE_FUNC_BYTELEN == OPFLAG_BYTELENARG ** SQLITE_FUNC_CONSTANT == SQLITE_DETERMINISTIC from the API ** SQLITE_FUNC_DIRECT == SQLITE_DIRECTONLY from the API ** SQLITE_FUNC_UNSAFE == SQLITE_INNOCUOUS -- opposite meanings!!! @@ -17539,7 +17623,7 @@ struct FuncDestructor { ** ** Note that even though SQLITE_FUNC_UNSAFE and SQLITE_INNOCUOUS have the ** same bit value, their meanings are inverted. SQLITE_FUNC_UNSAFE is -** used internally and if set means tha the function has side effects. +** used internally and if set means that the function has side effects. ** SQLITE_INNOCUOUS is used by application code and means "not unsafe". ** See multiple instances of tag-20230109-1. */ @@ -17550,6 +17634,7 @@ struct FuncDestructor { #define SQLITE_FUNC_NEEDCOLL 0x0020 /* sqlite3GetFuncCollSeq() might be called*/ #define SQLITE_FUNC_LENGTH 0x0040 /* Built-in length() function */ #define SQLITE_FUNC_TYPEOF 0x0080 /* Built-in typeof() function */ +#define SQLITE_FUNC_BYTELEN 0x00c0 /* Built-in octet_length() function */ #define SQLITE_FUNC_COUNT 0x0100 /* Built-in count(*) aggregate */ /* 0x0200 -- available for reuse */ #define SQLITE_FUNC_UNLIKELY 0x0400 /* Built-in unlikely() function */ @@ -18129,7 +18214,7 @@ struct FKey { ** foreign key. ** ** The OE_Default value is a place holder that means to use whatever -** conflict resolution algorthm is required from context. +** conflict resolution algorithm is required from context. ** ** The following symbolic values are used to record which type ** of conflict resolution action to take. @@ -18543,7 +18628,7 @@ struct Expr { ** TK_REGISTER: register number ** TK_TRIGGER: 1 -> new, 0 -> old ** EP_Unlikely: 134217728 times likelihood - ** TK_IN: ephemerial table holding RHS + ** TK_IN: ephemeral table holding RHS ** TK_SELECT_COLUMN: Number of columns on the LHS ** TK_SELECT: 1st register of result vector */ ynVar iColumn; /* TK_COLUMN: column index. -1 for rowid. @@ -18625,6 +18710,8 @@ struct Expr { */ #define ExprUseUToken(E) (((E)->flags&EP_IntValue)==0) #define ExprUseUValue(E) (((E)->flags&EP_IntValue)!=0) +#define ExprUseWOfst(E) (((E)->flags&(EP_InnerON|EP_OuterON))==0) +#define ExprUseWJoin(E) (((E)->flags&(EP_InnerON|EP_OuterON))!=0) #define ExprUseXList(E) (((E)->flags&EP_xIsSelect)==0) #define ExprUseXSelect(E) (((E)->flags&EP_xIsSelect)!=0) #define ExprUseYTab(E) (((E)->flags&(EP_WinFunc|EP_Subrtn))==0) @@ -18813,7 +18900,7 @@ struct SrcItem { unsigned notCte :1; /* This item may not match a CTE */ unsigned isUsing :1; /* u3.pUsing is valid */ unsigned isOn :1; /* u3.pOn was once valid and non-NULL */ - unsigned isSynthUsing :1; /* u3.pUsing is synthensized from NATURAL */ + unsigned isSynthUsing :1; /* u3.pUsing is synthesized from NATURAL */ unsigned isNestedFrom :1; /* pSelect is a SF_NestedFrom subquery */ } fg; int iCursor; /* The VDBE cursor number used to access this table */ @@ -19349,6 +19436,9 @@ struct Parse { int regRoot; /* Register holding root page number for new objects */ int nMaxArg; /* Max args passed to user function by sub-program */ int nSelect; /* Number of SELECT stmts. Counter for Select.selId */ +#ifndef SQLITE_OMIT_PROGRESS_CALLBACK + u32 nProgressSteps; /* xProgress steps taken during sqlite3_prepare() */ +#endif #ifndef SQLITE_OMIT_SHARED_CACHE int nTableLock; /* Number of locks in aTableLock */ TableLock *aTableLock; /* Required table locks for shared-cache mode */ @@ -19362,12 +19452,9 @@ struct Parse { int addrCrTab; /* Address of OP_CreateBtree on CREATE TABLE */ Returning *pReturning; /* The RETURNING clause */ } u1; - u32 nQueryLoop; /* Est number of iterations of a query (10*log2(N)) */ u32 oldmask; /* Mask of old.* columns referenced */ u32 newmask; /* Mask of new.* columns referenced */ -#ifndef SQLITE_OMIT_PROGRESS_CALLBACK - u32 nProgressSteps; /* xProgress steps taken during sqlite3_prepare() */ -#endif + LogEst nQueryLoop; /* Est number of iterations of a query (10*log2(N)) */ u8 eTriggerOp; /* TK_UPDATE, TK_INSERT or TK_DELETE */ u8 bReturning; /* Coding a RETURNING trigger */ u8 eOrconf; /* Default ON CONFLICT policy for trigger steps */ @@ -19491,6 +19578,7 @@ struct AuthContext { #define OPFLAG_ISNOOP 0x40 /* OP_Delete does pre-update-hook only */ #define OPFLAG_LENGTHARG 0x40 /* OP_Column only used for length() */ #define OPFLAG_TYPEOFARG 0x80 /* OP_Column only used for typeof() */ +#define OPFLAG_BYTELENARG 0xc0 /* OP_Column only for octet_length() */ #define OPFLAG_BULKCSR 0x01 /* OP_Open** used to open bulk cursor */ #define OPFLAG_SEEKEQ 0x02 /* OP_Open** cursor uses EQ seek only */ #define OPFLAG_FORDELETE 0x08 /* OP_Open should use BTREE_FORDELETE */ @@ -19633,6 +19721,25 @@ struct sqlite3_str { #define isMalloced(X) (((X)->printfFlags & SQLITE_PRINTF_MALLOCED)!=0) +/* +** The following object is the header for an "RCStr" or "reference-counted +** string". An RCStr is passed around and used like any other char* +** that has been dynamically allocated. The important interface +** differences: +** +** 1. RCStr strings are reference counted. They are deallocated +** when the reference count reaches zero. +** +** 2. Use sqlite3RCStrUnref() to free an RCStr string rather than +** sqlite3_free() +** +** 3. Make a (read-only) copy of a read-only RCStr string using +** sqlite3RCStrRef(). +*/ +struct RCStr { + u64 nRCRef; /* Number of references */ + /* Total structure size should be a multiple of 8 bytes for alignment */ +}; /* ** A pointer to this structure is used to communicate information @@ -19659,7 +19766,7 @@ typedef struct { /* Tuning parameters are set using SQLITE_TESTCTRL_TUNE and are controlled ** on debug-builds of the CLI using ".testctrl tune ID VALUE". Tuning ** parameters are for temporary use during development, to help find -** optimial values for parameters in the query planner. The should not +** optimal values for parameters in the query planner. The should not ** be used on trunk check-ins. They are a temporary mechanism available ** for transient development builds only. ** @@ -19685,6 +19792,7 @@ struct Sqlite3Config { u8 bUseCis; /* Use covering indices for full-scans */ u8 bSmallMalloc; /* Avoid large memory allocations if true */ u8 bExtraSchemaChecks; /* Verify type,name,tbl_name in schema */ + u8 bUseLongDouble; /* Make use of long double */ int mxStrlen; /* Maximum string length */ int neverCorrupt; /* Database is always well-formed */ int szLookaside; /* Default lookaside buffer size */ @@ -19771,6 +19879,7 @@ struct Walker { void (*xSelectCallback2)(Walker*,Select*);/* Second callback for SELECTs */ int walkerDepth; /* Number of subqueries */ u16 eCode; /* A small processing code */ + u16 mWFlags; /* Use-dependent flags */ union { /* Extra data for callback */ NameContext *pNC; /* Naming context */ int n; /* A counter */ @@ -19810,6 +19919,7 @@ struct DbFixer { /* Forward declarations */ SQLITE_PRIVATE int sqlite3WalkExpr(Walker*, Expr*); +SQLITE_PRIVATE int sqlite3WalkExprNN(Walker*, Expr*); SQLITE_PRIVATE int sqlite3WalkExprList(Walker*, ExprList*); SQLITE_PRIVATE int sqlite3WalkSelect(Walker*, Select*); SQLITE_PRIVATE int sqlite3WalkSelectExpr(Walker*, Select*); @@ -20191,6 +20301,20 @@ struct PrintfArguments { sqlite3_value **apArg; /* The argument values */ }; +/* +** An instance of this object receives the decoding of a floating point +** value into an approximate decimal representation. +*/ +struct FpDecode { + char sign; /* '+' or '-' */ + char isSpecial; /* 1: Infinity 2: NaN */ + int n; /* Significant digits in the decode */ + int iDP; /* Location of the decimal point */ + char *z; /* Start of significant digits */ + char zBuf[24]; /* Storage for significant digits */ +}; + +SQLITE_PRIVATE void sqlite3FpDecode(FpDecode*,double,int,int); SQLITE_PRIVATE char *sqlite3MPrintf(sqlite3*,const char*, ...); SQLITE_PRIVATE char *sqlite3VMPrintf(sqlite3*,const char*, va_list); #if defined(SQLITE_DEBUG) || defined(SQLITE_HAVE_OS_TRACE) @@ -20481,7 +20605,7 @@ SQLITE_PRIVATE int sqlite3ExprCompare(const Parse*,const Expr*,const Expr*, int) SQLITE_PRIVATE int sqlite3ExprCompareSkip(Expr*,Expr*,int); SQLITE_PRIVATE int sqlite3ExprListCompare(const ExprList*,const ExprList*, int); SQLITE_PRIVATE int sqlite3ExprImpliesExpr(const Parse*,const Expr*,const Expr*, int); -SQLITE_PRIVATE int sqlite3ExprImpliesNonNullRow(Expr*,int); +SQLITE_PRIVATE int sqlite3ExprImpliesNonNullRow(Expr*,int,int); SQLITE_PRIVATE void sqlite3AggInfoPersistWalkerInit(Walker*,Parse*); SQLITE_PRIVATE void sqlite3ExprAnalyzeAggregates(NameContext*, Expr*); SQLITE_PRIVATE void sqlite3ExprAnalyzeAggList(NameContext*,ExprList*); @@ -20630,6 +20754,7 @@ SQLITE_PRIVATE int sqlite3FixSrcList(DbFixer*, SrcList*); SQLITE_PRIVATE int sqlite3FixSelect(DbFixer*, Select*); SQLITE_PRIVATE int sqlite3FixExpr(DbFixer*, Expr*); SQLITE_PRIVATE int sqlite3FixTriggerStep(DbFixer*, TriggerStep*); + SQLITE_PRIVATE int sqlite3RealSameAsInt(double,sqlite3_int64); SQLITE_PRIVATE i64 sqlite3RealToI64(double); SQLITE_PRIVATE int sqlite3Int64ToText(i64,char*); @@ -20734,6 +20859,7 @@ SQLITE_PRIVATE void sqlite3FileSuffix3(const char*, char*); SQLITE_PRIVATE u8 sqlite3GetBoolean(const char *z,u8); SQLITE_PRIVATE const void *sqlite3ValueText(sqlite3_value*, u8); +SQLITE_PRIVATE int sqlite3ValueIsOfClass(const sqlite3_value*, void(*)(void*)); SQLITE_PRIVATE int sqlite3ValueBytes(sqlite3_value*, u8); SQLITE_PRIVATE void sqlite3ValueSetStr(sqlite3_value*, int, const void *,u8, void(*)(void*)); @@ -20841,6 +20967,11 @@ SQLITE_PRIVATE void sqlite3OomClear(sqlite3*); SQLITE_PRIVATE int sqlite3ApiExit(sqlite3 *db, int); SQLITE_PRIVATE int sqlite3OpenTempDatabase(Parse *); +SQLITE_PRIVATE char *sqlite3RCStrRef(char*); +SQLITE_PRIVATE void sqlite3RCStrUnref(char*); +SQLITE_PRIVATE char *sqlite3RCStrNew(u64); +SQLITE_PRIVATE char *sqlite3RCStrResize(char*,u64); + SQLITE_PRIVATE void sqlite3StrAccumInit(StrAccum*, sqlite3*, char*, int, int); SQLITE_PRIVATE int sqlite3StrAccumEnlarge(StrAccum*, i64); SQLITE_PRIVATE char *sqlite3StrAccumFinish(StrAccum*); @@ -21092,6 +21223,7 @@ SQLITE_PRIVATE int sqlite3ExprCheckHeight(Parse*, int); #define sqlite3SelectExprHeight(x) 0 #define sqlite3ExprCheckHeight(x,y) #endif +SQLITE_PRIVATE void sqlite3ExprSetErrorOffset(Expr*,int); SQLITE_PRIVATE u32 sqlite3Get4byte(const u8*); SQLITE_PRIVATE void sqlite3Put4byte(u8*, u32); @@ -21377,9 +21509,6 @@ static const char * const sqlite3azCompileOpt[] = { #ifdef SQLITE_4_BYTE_ALIGNED_MALLOC "4_BYTE_ALIGNED_MALLOC", #endif -#ifdef SQLITE_64BIT_STATS - "64BIT_STATS", -#endif #ifdef SQLITE_ALLOW_COVERING_INDEX_SCAN # if SQLITE_ALLOW_COVERING_INDEX_SCAN != 1 "ALLOW_COVERING_INDEX_SCAN=" CTIMEOPT_VAL(SQLITE_ALLOW_COVERING_INDEX_SCAN), @@ -21716,6 +21845,9 @@ static const char * const sqlite3azCompileOpt[] = { #ifdef SQLITE_INTEGRITY_CHECK_ERROR_MAX "INTEGRITY_CHECK_ERROR_MAX=" CTIMEOPT_VAL(SQLITE_INTEGRITY_CHECK_ERROR_MAX), #endif +#ifdef SQLITE_LEGACY_JSON_VALID + "LEGACY_JSON_VALID", +#endif #ifdef SQLITE_LIKE_DOESNT_MATCH_BLOBS "LIKE_DOESNT_MATCH_BLOBS", #endif @@ -22350,6 +22482,7 @@ SQLITE_PRIVATE SQLITE_WSD struct Sqlite3Config sqlite3Config = { SQLITE_ALLOW_COVERING_INDEX_SCAN, /* bUseCis */ 0, /* bSmallMalloc */ 1, /* bExtraSchemaChecks */ + sizeof(LONGDOUBLE_TYPE)>8, /* bUseLongDouble */ 0x7ffffffe, /* mxStrlen */ 0, /* neverCorrupt */ SQLITE_DEFAULT_LOOKASIDE, /* szLookaside, nLookaside */ @@ -22579,6 +22712,9 @@ typedef struct VdbeSorter VdbeSorter; /* Elements of the linked list at Vdbe.pAuxData */ typedef struct AuxData AuxData; +/* A cache of large TEXT or BLOB values in a VdbeCursor */ +typedef struct VdbeTxtBlbCache VdbeTxtBlbCache; + /* Types of VDBE cursors */ #define CURTYPE_BTREE 0 #define CURTYPE_SORTER 1 @@ -22610,6 +22746,7 @@ struct VdbeCursor { Bool useRandomRowid:1; /* Generate new record numbers semi-randomly */ Bool isOrdered:1; /* True if the table is not BTREE_UNORDERED */ Bool noReuse:1; /* OpenEphemeral may not reuse this cursor */ + Bool colCache:1; /* pCache pointer is initialized and non-NULL */ u16 seekHit; /* See the OP_SeekHit and OP_IfNoHope opcodes */ union { /* pBtx for isEphermeral. pAltMap otherwise */ Btree *pBtx; /* Separate file holding temporary table */ @@ -22650,6 +22787,7 @@ struct VdbeCursor { #ifdef SQLITE_ENABLE_COLUMN_USED_MASK u64 maskUsed; /* Mask of columns used by this cursor */ #endif + VdbeTxtBlbCache *pCache; /* Cache of large TEXT or BLOB values */ /* 2*nField extra array elements allocated for aType[], beyond the one ** static element declared in the structure. nField total array slots for @@ -22662,12 +22800,25 @@ struct VdbeCursor { #define IsNullCursor(P) \ ((P)->eCurType==CURTYPE_PSEUDO && (P)->nullRow && (P)->seekResult==0) - /* ** A value for VdbeCursor.cacheStatus that means the cache is always invalid. */ #define CACHE_STALE 0 +/* +** Large TEXT or BLOB values can be slow to load, so we want to avoid +** loading them more than once. For that reason, large TEXT and BLOB values +** can be stored in a cache defined by this object, and attached to the +** VdbeCursor using the pCache field. +*/ +struct VdbeTxtBlbCache { + char *pCValue; /* A RCStr buffer to hold the value */ + i64 iOffset; /* File offset of the row being cached */ + int iCol; /* Column for which the cache is valid */ + u32 cacheStatus; /* Vdbe.cacheCtr value */ + u32 colCacheCtr; /* Column cache counter */ +}; + /* ** When a sub-program is executed (OP_Program), a structure of this type ** is allocated to store the current value of the program counter, as @@ -22988,16 +23139,18 @@ struct Vdbe { u32 nWrite; /* Number of write operations that have occurred */ #endif u16 nResColumn; /* Number of columns in one row of the result set */ + u16 nResAlloc; /* Column slots allocated to aColName[] */ u8 errorAction; /* Recovery action to do in case of an error */ u8 minWriteFileFormat; /* Minimum file format for writable database files */ u8 prepFlags; /* SQLITE_PREPARE_* flags */ u8 eVdbeState; /* On of the VDBE_*_STATE values */ bft expired:2; /* 1: recompile VM immediately 2: when convenient */ - bft explain:2; /* True if EXPLAIN present on SQL command */ + bft explain:2; /* 0: normal, 1: EXPLAIN, 2: EXPLAIN QUERY PLAN */ bft changeCntOn:1; /* True to update the change-counter */ bft usesStmtJournal:1; /* True if uses a statement journal */ bft readOnly:1; /* True for statements that do not write */ bft bIsReader:1; /* True for statements that read */ + bft haveEqpOps:1; /* Bytecode supports EXPLAIN QUERY PLAN */ yDbMask btreeMask; /* Bitmask of db->aDb[] entries referenced */ yDbMask lockMask; /* Subset of btreeMask that requires a lock */ u32 aCounter[9]; /* Counters used by sqlite3_stmt_status() */ @@ -23044,7 +23197,7 @@ struct PreUpdate { i64 iKey1; /* First key value passed to hook */ i64 iKey2; /* Second key value passed to hook */ Mem *aNew; /* Array of new.* values */ - Table *pTab; /* Schema object being upated */ + Table *pTab; /* Schema object being updated */ Index *pPk; /* PK index if pTab is WITHOUT ROWID */ }; @@ -23134,6 +23287,7 @@ SQLITE_PRIVATE int sqlite3VdbeMemSetZeroBlob(Mem*,int); SQLITE_PRIVATE int sqlite3VdbeMemIsRowSet(const Mem*); #endif SQLITE_PRIVATE int sqlite3VdbeMemSetRowSet(Mem*); +SQLITE_PRIVATE void sqlite3VdbeMemZeroTerminateIfAble(Mem*); SQLITE_PRIVATE int sqlite3VdbeMemMakeWriteable(Mem*); SQLITE_PRIVATE int sqlite3VdbeMemStringify(Mem*, u8, u8); SQLITE_PRIVATE int sqlite3IntFloatCompare(i64,double); @@ -23730,8 +23884,8 @@ struct DateTime { */ static int getDigits(const char *zDate, const char *zFormat, ...){ /* The aMx[] array translates the 3rd character of each format - ** spec into a max size: a b c d e f */ - static const u16 aMx[] = { 12, 14, 24, 31, 59, 9999 }; + ** spec into a max size: a b c d e f */ + static const u16 aMx[] = { 12, 14, 24, 31, 59, 14712 }; va_list ap; int cnt = 0; char nextC; @@ -24072,17 +24226,14 @@ static void computeYMD(DateTime *p){ ** Compute the Hour, Minute, and Seconds from the julian day number. */ static void computeHMS(DateTime *p){ - int s; + int day_ms, day_min; /* milliseconds, minutes into the day */ if( p->validHMS ) return; computeJD(p); - s = (int)((p->iJD + 43200000) % 86400000); - p->s = s/1000.0; - s = (int)p->s; - p->s -= s; - p->h = s/3600; - s -= p->h*3600; - p->m = s/60; - p->s += s - p->m*60; + day_ms = (int)((p->iJD + 43200000) % 86400000); + p->s = (day_ms % 60000)/1000.0; + day_min = day_ms/60000; + p->m = day_min % 60; + p->h = day_min / 60; p->rawS = 0; p->validHMS = 1; } @@ -24261,6 +24412,25 @@ static const struct { { 4, "year", 14713.0, 31536000.0 }, }; +/* +** If the DateTime p is raw number, try to figure out if it is +** a julian day number of a unix timestamp. Set the p value +** appropriately. +*/ +static void autoAdjustDate(DateTime *p){ + if( !p->rawS || p->validJD ){ + p->rawS = 0; + }else if( p->s>=-21086676*(i64)10000 /* -4713-11-24 12:00:00 */ + && p->s<=(25340230*(i64)10000)+799 /* 9999-12-31 23:59:59 */ + ){ + double r = p->s*1000.0 + 210866760000000.0; + clearYMD_HMS_TZ(p); + p->iJD = (sqlite3_int64)(r + 0.5); + p->validJD = 1; + p->rawS = 0; + } +} + /* ** Process a modifier to a date-time stamp. The modifiers are ** as follows: @@ -24304,19 +24474,8 @@ static int parseModifier( */ if( sqlite3_stricmp(z, "auto")==0 ){ if( idx>1 ) return 1; /* IMP: R-33611-57934 */ - if( !p->rawS || p->validJD ){ - rc = 0; - p->rawS = 0; - }else if( p->s>=-21086676*(i64)10000 /* -4713-11-24 12:00:00 */ - && p->s<=(25340230*(i64)10000)+799 /* 9999-12-31 23:59:59 */ - ){ - r = p->s*1000.0 + 210866760000000.0; - clearYMD_HMS_TZ(p); - p->iJD = (sqlite3_int64)(r + 0.5); - p->validJD = 1; - p->rawS = 0; - rc = 0; - } + autoAdjustDate(p); + rc = 0; } break; } @@ -24482,18 +24641,73 @@ static int parseModifier( case '9': { double rRounder; int i; - for(n=1; z[n] && z[n]!=':' && !sqlite3Isspace(z[n]); n++){} + int Y,M,D,h,m,x; + const char *z2 = z; + char z0 = z[0]; + for(n=1; z[n]; n++){ + if( z[n]==':' ) break; + if( sqlite3Isspace(z[n]) ) break; + if( z[n]=='-' ){ + if( n==5 && getDigits(&z[1], "40f", &Y)==1 ) break; + if( n==6 && getDigits(&z[1], "50f", &Y)==1 ) break; + } + } if( sqlite3AtoF(z, &r, n, SQLITE_UTF8)<=0 ){ - rc = 1; + assert( rc==1 ); break; } - if( z[n]==':' ){ + if( z[n]=='-' ){ + /* A modifier of the form (+|-)YYYY-MM-DD adds or subtracts the + ** specified number of years, months, and days. MM is limited to + ** the range 0-11 and DD is limited to 0-30. + */ + if( z0!='+' && z0!='-' ) break; /* Must start with +/- */ + if( n==5 ){ + if( getDigits(&z[1], "40f-20a-20d", &Y, &M, &D)!=3 ) break; + }else{ + assert( n==6 ); + if( getDigits(&z[1], "50f-20a-20d", &Y, &M, &D)!=3 ) break; + z++; + } + if( M>=12 ) break; /* M range 0..11 */ + if( D>=31 ) break; /* D range 0..30 */ + computeYMD_HMS(p); + p->validJD = 0; + if( z0=='-' ){ + p->Y -= Y; + p->M -= M; + D = -D; + }else{ + p->Y += Y; + p->M += M; + } + x = p->M>0 ? (p->M-1)/12 : (p->M-12)/12; + p->Y += x; + p->M -= x*12; + computeJD(p); + p->validHMS = 0; + p->validYMD = 0; + p->iJD += (i64)D*86400000; + if( z[11]==0 ){ + rc = 0; + break; + } + if( sqlite3Isspace(z[11]) + && getDigits(&z[12], "20c:20e", &h, &m)==2 + ){ + z2 = &z[12]; + n = 2; + }else{ + break; + } + } + if( z2[n]==':' ){ /* A modifier of the form (+|-)HH:MM:SS.FFF adds (or subtracts) the ** specified number of hours, minutes, seconds, and fractional seconds ** to the time. The ".FFF" may be omitted. The ":SS.FFF" may be ** omitted. */ - const char *z2 = z; + DateTime tx; sqlite3_int64 day; if( !sqlite3Isdigit(*z2) ) z2++; @@ -24503,7 +24717,7 @@ static int parseModifier( tx.iJD -= 43200000; day = tx.iJD/86400000; tx.iJD -= day*86400000; - if( z[0]=='-' ) tx.iJD = -tx.iJD; + if( z0=='-' ) tx.iJD = -tx.iJD; computeJD(p); clearYMD_HMS_TZ(p); p->iJD += tx.iJD; @@ -24519,7 +24733,7 @@ static int parseModifier( if( n>10 || n<3 ) break; if( sqlite3UpperToLower[(u8)z[n-1]]=='s' ) n--; computeJD(p); - rc = 1; + assert( rc==1 ); rRounder = r<0 ? -0.5 : +0.5; for(i=0; iM += (int)r; @@ -24687,7 +24900,7 @@ static void datetimeFunc( zBuf[16] = '0' + (x.m)%10; zBuf[17] = ':'; if( x.useSubsec ){ - s = (int)1000.0*x.s; + s = (int)(1000.0*x.s + 0.5); zBuf[18] = '0' + (s/10000)%10; zBuf[19] = '0' + (s/1000)%10; zBuf[20] = '.'; @@ -24734,7 +24947,7 @@ static void timeFunc( zBuf[4] = '0' + (x.m)%10; zBuf[5] = ':'; if( x.useSubsec ){ - s = (int)1000.0*x.s; + s = (int)(1000.0*x.s + 0.5); zBuf[6] = '0' + (s/10000)%10; zBuf[7] = '0' + (s/1000)%10; zBuf[8] = '.'; @@ -24805,7 +25018,7 @@ static void dateFunc( ** %M minute 00-59 ** %s seconds since 1970-01-01 ** %S seconds 00-59 -** %w day of week 0-6 sunday==0 +** %w day of week 0-6 Sunday==0 ** %W week of year 00-53 ** %Y year 0000-9999 ** %% % @@ -24945,6 +25158,117 @@ static void cdateFunc( dateFunc(context, 0, 0); } +/* +** timediff(DATE1, DATE2) +** +** Return the amount of time that must be added to DATE2 in order to +** convert it into DATE2. The time difference format is: +** +** +YYYY-MM-DD HH:MM:SS.SSS +** +** The initial "+" becomes "-" if DATE1 occurs before DATE2. For +** date/time values A and B, the following invariant should hold: +** +** datetime(A) == (datetime(B, timediff(A,B)) +** +** Both DATE arguments must be either a julian day number, or an +** ISO-8601 string. The unix timestamps are not supported by this +** routine. +*/ +static void timediffFunc( + sqlite3_context *context, + int NotUsed1, + sqlite3_value **argv +){ + char sign; + int Y, M; + DateTime d1, d2; + sqlite3_str sRes; + UNUSED_PARAMETER(NotUsed1); + if( isDate(context, 1, &argv[0], &d1) ) return; + if( isDate(context, 1, &argv[1], &d2) ) return; + computeYMD_HMS(&d1); + computeYMD_HMS(&d2); + if( d1.iJD>=d2.iJD ){ + sign = '+'; + Y = d1.Y - d2.Y; + if( Y ){ + d2.Y = d1.Y; + d2.validJD = 0; + computeJD(&d2); + } + M = d1.M - d2.M; + if( M<0 ){ + Y--; + M += 12; + } + if( M!=0 ){ + d2.M = d1.M; + d2.validJD = 0; + computeJD(&d2); + } + while( d1.iJDd2.iJD ){ + M--; + if( M<0 ){ + M = 11; + Y--; + } + d2.M++; + if( d2.M>12 ){ + d2.M = 1; + d2.Y++; + } + d2.validJD = 0; + computeJD(&d2); + } + d1.iJD = d2.iJD - d1.iJD; + d1.iJD += (u64)1486995408 * (u64)100000; + } + d1.validYMD = 0; + d1.validHMS = 0; + d1.validTZ = 0; + computeYMD_HMS(&d1); + sqlite3StrAccumInit(&sRes, 0, 0, 0, 100); + sqlite3_str_appendf(&sRes, "%c%04d-%02d-%02d %02d:%02d:%06.3f", + sign, Y, M, d1.D-1, d1.h, d1.m, d1.s); + sqlite3ResultStrAccum(context, &sRes); +} + + /* ** current_timestamp() ** @@ -25019,6 +25343,7 @@ SQLITE_PRIVATE void sqlite3RegisterDateTimeFunctions(void){ PURE_DATE(time, -1, 0, 0, timeFunc ), PURE_DATE(datetime, -1, 0, 0, datetimeFunc ), PURE_DATE(strftime, -1, 0, 0, strftimeFunc ), + PURE_DATE(timediff, 2, 0, 0, timediffFunc ), DFUNCTION(current_time, 0, 0, 0, ctimeFunc ), DFUNCTION(current_timestamp, 0, 0, 0, ctimestampFunc), DFUNCTION(current_date, 0, 0, 0, cdateFunc ), @@ -25172,7 +25497,7 @@ SQLITE_PRIVATE int sqlite3OsFileControl(sqlite3_file *id, int op, void *pArg){ /* Faults are not injected into COMMIT_PHASETWO because, assuming SQLite ** is using a regular VFS, it is called after the corresponding ** transaction has been committed. Injecting a fault at this point - ** confuses the test scripts - the COMMIT comand returns SQLITE_NOMEM + ** confuses the test scripts - the COMMIT command returns SQLITE_NOMEM ** but the transaction is committed anyway. ** ** The core must call OsFileControl() though, not OsFileControlHint(), @@ -25793,7 +26118,7 @@ static void *sqlite3MemMalloc(int nByte){ ** or sqlite3MemRealloc(). ** ** For this low-level routine, we already know that pPrior!=0 since -** cases where pPrior==0 will have been intecepted and dealt with +** cases where pPrior==0 will have been intercepted and dealt with ** by higher-level routines. */ static void sqlite3MemFree(void *pPrior){ @@ -25881,7 +26206,7 @@ static int sqlite3MemInit(void *NotUsed){ return SQLITE_OK; } len = sizeof(cpuCount); - /* One usually wants to use hw.acctivecpu for MT decisions, but not here */ + /* One usually wants to use hw.activecpu for MT decisions, but not here */ sysctlbyname("hw.ncpu", &cpuCount, &len, NULL, 0); if( cpuCount>1 ){ /* defer MT decisions to system malloc */ @@ -28348,7 +28673,7 @@ SQLITE_PRIVATE sqlite3_mutex_methods const *sqlite3DefaultMutex(void){ /* ** The sqlite3_mutex.id, sqlite3_mutex.nRef, and sqlite3_mutex.owner fields -** are necessary under two condidtions: (1) Debug builds and (2) using +** are necessary under two conditions: (1) Debug builds and (2) using ** home-grown mutexes. Encapsulate these conditions into a single #define. */ #if defined(SQLITE_DEBUG) || defined(SQLITE_HOMEGROWN_RECURSIVE_MUTEX) @@ -28849,7 +29174,7 @@ struct sqlite3_mutex { CRITICAL_SECTION mutex; /* Mutex controlling the lock */ int id; /* Mutex type */ #ifdef SQLITE_DEBUG - volatile int nRef; /* Number of enterances */ + volatile int nRef; /* Number of entrances */ volatile DWORD owner; /* Thread holding this mutex */ volatile LONG trace; /* True to trace changes */ #endif @@ -30221,57 +30546,6 @@ static const et_info fmtinfo[] = { ** %!S Like %S but prefer the zName over the zAlias */ -/* Floating point constants used for rounding */ -static const double arRound[] = { - 5.0e-01, 5.0e-02, 5.0e-03, 5.0e-04, 5.0e-05, - 5.0e-06, 5.0e-07, 5.0e-08, 5.0e-09, 5.0e-10, -}; - -/* -** If SQLITE_OMIT_FLOATING_POINT is defined, then none of the floating point -** conversions will work. -*/ -#ifndef SQLITE_OMIT_FLOATING_POINT -/* -** "*val" is a double such that 0.1 <= *val < 10.0 -** Return the ascii code for the leading digit of *val, then -** multiply "*val" by 10.0 to renormalize. -** -** Example: -** input: *val = 3.14159 -** output: *val = 1.4159 function return = '3' -** -** The counter *cnt is incremented each time. After counter exceeds -** 16 (the number of significant digits in a 64-bit float) '0' is -** always returned. -*/ -static char et_getdigit(LONGDOUBLE_TYPE *val, int *cnt){ - int digit; - LONGDOUBLE_TYPE d; - if( (*cnt)<=0 ) return '0'; - (*cnt)--; - digit = (int)*val; - d = digit; - digit += '0'; - *val = (*val - d)*10.0; - return (char)digit; -} -#endif /* SQLITE_OMIT_FLOATING_POINT */ - -#ifndef SQLITE_OMIT_FLOATING_POINT -/* -** "*val" is a u64. *msd is a divisor used to extract the -** most significant digit of *val. Extract that most significant -** digit and return it. -*/ -static char et_getdigit_int(u64 *val, u64 *msd){ - u64 x = (*val)/(*msd); - *val -= x*(*msd); - if( *msd>=10 ) *msd /= 10; - return '0' + (char)(x & 15); -} -#endif /* SQLITE_OMIT_FLOATING_POINT */ - /* ** Set the StrAccum object to an error mode. */ @@ -30363,20 +30637,15 @@ SQLITE_API void sqlite3_str_vappendf( u8 bArgList; /* True for SQLITE_PRINTF_SQLFUNC */ char prefix; /* Prefix character. "+" or "-" or " " or '\0'. */ sqlite_uint64 longvalue; /* Value for integer types */ - LONGDOUBLE_TYPE realvalue; /* Value for real types */ - sqlite_uint64 msd; /* Divisor to get most-significant-digit - ** of longvalue */ + double realvalue; /* Value for real types */ const et_info *infop; /* Pointer to the appropriate info structure */ char *zOut; /* Rendering buffer */ int nOut; /* Size of the rendering buffer */ char *zExtra = 0; /* Malloced memory used by some conversion */ -#ifndef SQLITE_OMIT_FLOATING_POINT - int exp, e2; /* exponent of real numbers */ - int nsd; /* Number of significant digits returned */ - double rounder; /* Used for rounding floating point values */ + int exp, e2; /* exponent of real numbers */ etByte flag_dp; /* True if decimal point should be shown */ etByte flag_rtz; /* True if trailing zeros should be removed */ -#endif + PrintfArguments *pArgList = 0; /* Arguments for SQLITE_PRINTF_SQLFUNC */ char buf[etBUFSIZE]; /* Conversion buffer */ @@ -30651,94 +30920,61 @@ SQLITE_API void sqlite3_str_vappendf( break; case etFLOAT: case etEXP: - case etGENERIC: + case etGENERIC: { + FpDecode s; + int iRound; + int j; + if( bArgList ){ realvalue = getDoubleArg(pArgList); }else{ realvalue = va_arg(ap,double); } -#ifdef SQLITE_OMIT_FLOATING_POINT - length = 0; -#else if( precision<0 ) precision = 6; /* Set default precision */ #ifdef SQLITE_FP_PRECISION_LIMIT if( precision>SQLITE_FP_PRECISION_LIMIT ){ precision = SQLITE_FP_PRECISION_LIMIT; } #endif - if( realvalue<0.0 ){ - realvalue = -realvalue; + if( xtype==etFLOAT ){ + iRound = -precision; + }else if( xtype==etGENERIC ){ + iRound = precision; + }else{ + iRound = precision+1; + } + sqlite3FpDecode(&s, realvalue, iRound, flag_altform2 ? 26 : 16); + if( s.isSpecial ){ + if( s.isSpecial==2 ){ + bufpt = flag_zeropad ? "null" : "NaN"; + length = sqlite3Strlen30(bufpt); + break; + }else if( flag_zeropad ){ + s.z[0] = '9'; + s.iDP = 1000; + s.n = 1; + }else{ + memcpy(buf, "-Inf", 5); + bufpt = buf; + if( s.sign=='-' ){ + /* no-op */ + }else if( flag_prefix ){ + buf[0] = flag_prefix; + }else{ + bufpt++; + } + length = sqlite3Strlen30(bufpt); + break; + } + } + if( s.sign=='-' ){ prefix = '-'; }else{ prefix = flag_prefix; } - exp = 0; - if( xtype==etGENERIC && precision>0 ) precision--; - testcase( precision>0xfff ); - if( realvalue<1.0e+16 - && realvalue==(LONGDOUBLE_TYPE)(longvalue = (u64)realvalue) - ){ - /* Number is a pure integer that can be represented as u64 */ - for(msd=1; msd*10<=longvalue; msd *= 10, exp++){} - if( exp>precision && xtype!=etFLOAT ){ - u64 rnd = msd/2; - int kk = precision; - while( kk-- > 0 ){ rnd /= 10; } - longvalue += rnd; - } - }else{ - msd = 0; - longvalue = 0; /* To prevent a compiler warning */ - idx = precision & 0xfff; - rounder = arRound[idx%10]; - while( idx>=10 ){ rounder *= 1.0e-10; idx -= 10; } - if( xtype==etFLOAT ){ - double rx = (double)realvalue; - sqlite3_uint64 u; - int ex; - memcpy(&u, &rx, sizeof(u)); - ex = -1023 + (int)((u>>52)&0x7ff); - if( precision+(ex/3) < 15 ) rounder += realvalue*3e-16; - realvalue += rounder; - } - if( sqlite3IsNaN((double)realvalue) ){ - if( flag_zeropad ){ - bufpt = "null"; - length = 4; - }else{ - bufpt = "NaN"; - length = 3; - } - break; - } - /* Normalize realvalue to within 10.0 > realvalue >= 1.0 */ - if( ALWAYS(realvalue>0.0) ){ - LONGDOUBLE_TYPE scale = 1.0; - while( realvalue>=1e100*scale && exp<=350){ scale*=1e100;exp+=100;} - while( realvalue>=1e10*scale && exp<=350 ){ scale*=1e10; exp+=10; } - while( realvalue>=10.0*scale && exp<=350 ){ scale *= 10.0; exp++; } - realvalue /= scale; - while( realvalue<1e-8 ){ realvalue *= 1e8; exp-=8; } - while( realvalue<1.0 ){ realvalue *= 10.0; exp--; } - if( exp>350 ){ - if( flag_zeropad ){ - realvalue = 9.0; - exp = 999; - }else{ - bufpt = buf; - buf[0] = prefix; - memcpy(buf+(prefix!=0),"Inf",4); - length = 3+(prefix!=0); - break; - } - } - if( xtype!=etFLOAT ){ - realvalue += rounder; - if( realvalue>=10.0 ){ realvalue *= 0.1; exp++; } - } - } - } + exp = s.iDP-1; + if( xtype==etGENERIC && precision>0 ) precision--; /* ** If the field type is etGENERIC, then convert to either etEXP @@ -30758,9 +30994,8 @@ SQLITE_API void sqlite3_str_vappendf( if( xtype==etEXP ){ e2 = 0; }else{ - e2 = exp; + e2 = s.iDP - 1; } - nsd = 16 + flag_altform2*10; bufpt = buf; { i64 szBufNeeded; /* Size of a temporary buffer needed */ @@ -30778,16 +31013,12 @@ SQLITE_API void sqlite3_str_vappendf( *(bufpt++) = prefix; } /* Digits prior to the decimal point */ + j = 0; if( e2<0 ){ *(bufpt++) = '0'; - }else if( msd>0 ){ - for(; e2>=0; e2--){ - *(bufpt++) = et_getdigit_int(&longvalue,&msd); - if( cThousand && (e2%3)==0 && e2>1 ) *(bufpt++) = ','; - } }else{ for(; e2>=0; e2--){ - *(bufpt++) = et_getdigit(&realvalue,&nsd); + *(bufpt++) = j1 ) *(bufpt++) = ','; } } @@ -30797,19 +31028,12 @@ SQLITE_API void sqlite3_str_vappendf( } /* "0" digits after the decimal point but before the first ** significant digit of the number */ - for(e2++; e2<0; precision--, e2++){ - assert( precision>0 ); + for(e2++; e2<0 && precision>0; precision--, e2++){ *(bufpt++) = '0'; } /* Significant digits after the decimal point */ - if( msd>0 ){ - while( (precision--)>0 ){ - *(bufpt++) = et_getdigit_int(&longvalue,&msd); - } - }else{ - while( (precision--)>0 ){ - *(bufpt++) = et_getdigit(&realvalue,&nsd); - } + while( (precision--)>0 ){ + *(bufpt++) = jcharset]; if( exp<0 ){ *(bufpt++) = '-'; exp = -exp; @@ -30858,8 +31083,8 @@ SQLITE_API void sqlite3_str_vappendf( while( nPad-- ) bufpt[i++] = '0'; length = width; } -#endif /* !defined(SQLITE_OMIT_FLOATING_POINT) */ break; + } case etSIZE: if( !bArgList ){ *(va_arg(ap,int*)) = pAccum->nChar; @@ -31583,6 +31808,75 @@ SQLITE_API void sqlite3_str_appendf(StrAccum *p, const char *zFormat, ...){ va_end(ap); } + +/***************************************************************************** +** Reference counted string storage +*****************************************************************************/ + +/* +** Increase the reference count of the string by one. +** +** The input parameter is returned. +*/ +SQLITE_PRIVATE char *sqlite3RCStrRef(char *z){ + RCStr *p = (RCStr*)z; + assert( p!=0 ); + p--; + p->nRCRef++; + return z; +} + +/* +** Decrease the reference count by one. Free the string when the +** reference count reaches zero. +*/ +SQLITE_PRIVATE void sqlite3RCStrUnref(char *z){ + RCStr *p = (RCStr*)z; + assert( p!=0 ); + p--; + assert( p->nRCRef>0 ); + if( p->nRCRef>=2 ){ + p->nRCRef--; + }else{ + sqlite3_free(p); + } +} + +/* +** Create a new string that is capable of holding N bytes of text, not counting +** the zero byte at the end. The string is uninitialized. +** +** The reference count is initially 1. Call sqlite3RCStrUnref() to free the +** newly allocated string. +** +** This routine returns 0 on an OOM. +*/ +SQLITE_PRIVATE char *sqlite3RCStrNew(u64 N){ + RCStr *p = sqlite3_malloc64( N + sizeof(*p) + 1 ); + if( p==0 ) return 0; + p->nRCRef = 1; + return (char*)&p[1]; +} + +/* +** Change the size of the string so that it is able to hold N bytes. +** The string might be reallocated, so return the new allocation. +*/ +SQLITE_PRIVATE char *sqlite3RCStrResize(char *z, u64 N){ + RCStr *p = (RCStr*)z; + RCStr *pNew; + assert( p!=0 ); + p--; + assert( p->nRCRef==1 ); + pNew = sqlite3_realloc64(p, N+sizeof(RCStr)+1); + if( pNew==0 ){ + sqlite3_free(p); + return 0; + }else{ + return (char*)&pNew[1]; + } +} + /************** End of printf.c **********************************************/ /************** Begin file treeview.c ****************************************/ /* @@ -32230,7 +32524,8 @@ SQLITE_PRIVATE void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 m }; assert( pExpr->op2==TK_IS || pExpr->op2==TK_ISNOT ); assert( pExpr->pRight ); - assert( sqlite3ExprSkipCollate(pExpr->pRight)->op==TK_TRUEFALSE ); + assert( sqlite3ExprSkipCollateAndLikely(pExpr->pRight)->op + == TK_TRUEFALSE ); x = (pExpr->op2==TK_ISNOT)*2 + sqlite3ExprTruthValue(pExpr->pRight); zUniOp = azOp[x]; break; @@ -33889,7 +34184,7 @@ SQLITE_PRIVATE void sqlite3UtfSelfTest(void){ /* ** Calls to sqlite3FaultSim() are used to simulate a failure during testing, ** or to bypass normal error detection during testing in order to let -** execute proceed futher downstream. +** execute proceed further downstream. ** ** In deployment, sqlite3FaultSim() *always* return SQLITE_OK (0). The ** sqlite3FaultSim() function only returns non-zero during testing. @@ -34006,6 +34301,23 @@ SQLITE_PRIVATE void sqlite3ErrorClear(sqlite3 *db){ */ SQLITE_PRIVATE void sqlite3SystemError(sqlite3 *db, int rc){ if( rc==SQLITE_IOERR_NOMEM ) return; +#ifdef SQLITE_USE_SEH + if( rc==SQLITE_IOERR_IN_PAGE ){ + int ii; + int iErr; + sqlite3BtreeEnterAll(db); + for(ii=0; iinDb; ii++){ + if( db->aDb[ii].pBt ){ + iErr = sqlite3PagerWalSystemErrno(sqlite3BtreePager(db->aDb[ii].pBt)); + if( iErr ){ + db->iSysErrno = iErr; + } + } + } + sqlite3BtreeLeaveAll(db); + return; + } +#endif rc &= 0xff; if( rc==SQLITE_CANTOPEN || rc==SQLITE_IOERR ){ db->iSysErrno = sqlite3OsGetLastError(db->pVfs); @@ -34251,43 +34563,40 @@ SQLITE_PRIVATE u8 sqlite3StrIHash(const char *z){ return h; } -/* -** Compute 10 to the E-th power. Examples: E==1 results in 10. -** E==2 results in 100. E==50 results in 1.0e50. +/* Double-Double multiplication. (x[0],x[1]) *= (y,yy) ** -** This routine only works for values of E between 1 and 341. +** Reference: +** T. J. Dekker, "A Floating-Point Technique for Extending the +** Available Precision". 1971-07-26. */ -static LONGDOUBLE_TYPE sqlite3Pow10(int E){ -#if defined(_MSC_VER) - static const LONGDOUBLE_TYPE x[] = { - 1.0e+001L, - 1.0e+002L, - 1.0e+004L, - 1.0e+008L, - 1.0e+016L, - 1.0e+032L, - 1.0e+064L, - 1.0e+128L, - 1.0e+256L - }; - LONGDOUBLE_TYPE r = 1.0; - int i; - assert( E>=0 && E<=307 ); - for(i=0; E!=0; i++, E >>=1){ - if( E & 1 ) r *= x[i]; - } - return r; -#else - LONGDOUBLE_TYPE x = 10.0; - LONGDOUBLE_TYPE r = 1.0; - while(1){ - if( E & 1 ) r *= x; - E >>= 1; - if( E==0 ) break; - x *= x; - } - return r; -#endif +static void dekkerMul2(volatile double *x, double y, double yy){ + /* + ** The "volatile" keywords on parameter x[] and on local variables + ** below are needed force intermediate results to be truncated to + ** binary64 rather than be carried around in an extended-precision + ** format. The truncation is necessary for the Dekker algorithm to + ** work. Intel x86 floating point might omit the truncation without + ** the use of volatile. + */ + volatile double tx, ty, p, q, c, cc; + double hx, hy; + u64 m; + memcpy(&m, (void*)&x[0], 8); + m &= 0xfffffffffc000000LL; + memcpy(&hx, &m, 8); + tx = x[0] - hx; + memcpy(&m, &y, 8); + m &= 0xfffffffffc000000LL; + memcpy(&hy, &m, 8); + ty = y - hy; + p = hx*hy; + q = hx*ty + tx*hy; + c = p+q; + cc = p - c + q + tx*ty; + cc = x[0]*yy + x[1]*y + cc; + x[0] = c + cc; + x[1] = c - x[0]; + x[1] += cc; } /* @@ -34328,12 +34637,11 @@ SQLITE_PRIVATE int sqlite3AtoF(const char *z, double *pResult, int length, u8 en const char *zEnd; /* sign * significand * (10 ^ (esign * exponent)) */ int sign = 1; /* sign of significand */ - i64 s = 0; /* significand */ + u64 s = 0; /* significand */ int d = 0; /* adjust exponent for shifting decimal point */ int esign = 1; /* sign of exponent */ int e = 0; /* exponent */ int eValid = 1; /* True exponent is either not used or is well-formed */ - double result; int nDigit = 0; /* Number of digits processed */ int eType = 1; /* 1: pure integer, 2+: fractional -1 or less: bad UTF16 */ @@ -34373,7 +34681,7 @@ SQLITE_PRIVATE int sqlite3AtoF(const char *z, double *pResult, int length, u8 en while( z=((LARGEST_INT64-9)/10) ){ + if( s>=((LARGEST_UINT64-9)/10) ){ /* skip non-significant significand digits ** (increase exponent by d to shift decimal left) */ while( z0 && s<(LARGEST_UINT64/10) ){ + s *= 10; + e--; + } + while( e<0 && (s%10)==0 ){ + s /= 10; + e++; } - if( s==0 ) { - /* In the IEEE 754 standard, zero is signed. */ - result = sign<0 ? -(double)0 : (double)0; - } else { - /* Attempt to reduce exponent. - ** - ** Branches that are not required for the correct answer but which only - ** help to obtain the correct answer faster are marked with special - ** comments, as a hint to the mutation tester. - */ - while( e>0 ){ /*OPTIMIZATION-IF-TRUE*/ - if( esign>0 ){ - if( s>=(LARGEST_INT64/10) ) break; /*OPTIMIZATION-IF-FALSE*/ - s *= 10; - }else{ - if( s%10!=0 ) break; /*OPTIMIZATION-IF-FALSE*/ - s /= 10; - } - e--; - } - - /* adjust the sign of significand */ - s = sign<0 ? -s : s; - - if( e==0 ){ /*OPTIMIZATION-IF-TRUE*/ - result = (double)s; + if( e==0 ){ + *pResult = s; + }else if( sqlite3Config.bUseLongDouble ){ + LONGDOUBLE_TYPE r = (LONGDOUBLE_TYPE)s; + if( e>0 ){ + while( e>=100 ){ e-=100; r *= 1.0e+100L; } + while( e>=10 ){ e-=10; r *= 1.0e+10L; } + while( e>=1 ){ e-=1; r *= 1.0e+01L; } }else{ - /* attempt to handle extremely small/large numbers better */ - if( e>307 ){ /*OPTIMIZATION-IF-TRUE*/ - if( e<342 ){ /*OPTIMIZATION-IF-TRUE*/ - LONGDOUBLE_TYPE scale = sqlite3Pow10(e-308); - if( esign<0 ){ - result = s / scale; - result /= 1.0e+308; - }else{ - result = s * scale; - result *= 1.0e+308; - } - }else{ assert( e>=342 ); - if( esign<0 ){ - result = 0.0*s; - }else{ + while( e<=-100 ){ e+=100; r *= 1.0e-100L; } + while( e<=-10 ){ e+=10; r *= 1.0e-10L; } + while( e<=-1 ){ e+=1; r *= 1.0e-01L; } + } + assert( r>=0.0 ); + if( r>+1.7976931348623157081452742373e+308L ){ #ifdef INFINITY - result = INFINITY*s; + *pResult = +INFINITY; #else - result = 1e308*1e308*s; /* Infinity */ + *pResult = 1.0e308*10.0; #endif - } - } - }else{ - LONGDOUBLE_TYPE scale = sqlite3Pow10(e); - if( esign<0 ){ - result = s / scale; - }else{ - result = s * scale; - } + }else{ + *pResult = (double)r; + } + }else{ + double rr[2]; + u64 s2; + rr[0] = (double)s; + s2 = (u64)rr[0]; + rr[1] = s>=s2 ? (double)(s - s2) : -(double)(s2 - s); + if( e>0 ){ + while( e>=100 ){ + e -= 100; + dekkerMul2(rr, 1.0e+100, -1.5902891109759918046e+83); + } + while( e>=10 ){ + e -= 10; + dekkerMul2(rr, 1.0e+10, 0.0); + } + while( e>=1 ){ + e -= 1; + dekkerMul2(rr, 1.0e+01, 0.0); + } + }else{ + while( e<=-100 ){ + e += 100; + dekkerMul2(rr, 1.0e-100, -1.99918998026028836196e-117); + } + while( e<=-10 ){ + e += 10; + dekkerMul2(rr, 1.0e-10, -3.6432197315497741579e-27); + } + while( e<=-1 ){ + e += 1; + dekkerMul2(rr, 1.0e-01, -5.5511151231257827021e-18); } } + *pResult = rr[0]+rr[1]; + if( sqlite3IsNaN(*pResult) ) *pResult = 1e300*1e300; } + if( sign<0 ) *pResult = -*pResult; + assert( !sqlite3IsNaN(*pResult) ); - /* store the result */ - *pResult = result; - - /* return true if number and no extra non-whitespace chracters after */ +atof_return: + /* return true if number and no extra non-whitespace characters after */ if( z==zEnd && nDigit>0 && eValid && eType>0 ){ return eType; }else if( eType>=2 && (eType==3 || eValid) && nDigit>0 ){ @@ -34636,7 +34954,7 @@ SQLITE_PRIVATE int sqlite3Atoi64(const char *zNum, i64 *pNum, int length, u8 enc /* This test and assignment is needed only to suppress UB warnings ** from clang and -fsanitize=undefined. This test and assignment make ** the code a little larger and slower, and no harm comes from omitting - ** them, but we must appaise the undefined-behavior pharisees. */ + ** them, but we must appease the undefined-behavior pharisees. */ *pNum = neg ? SMALLEST_INT64 : LARGEST_INT64; }else if( neg ){ *pNum = -(i64)u; @@ -34714,7 +35032,9 @@ SQLITE_PRIVATE int sqlite3DecOrHexToI64(const char *z, i64 *pOut){ }else #endif /* SQLITE_OMIT_HEX_INTEGER */ { - return sqlite3Atoi64(z, pOut, sqlite3Strlen30(z), SQLITE_UTF8); + int n = (int)(0x3fffffff&strspn(z,"+- \n\t0123456789")); + if( z[n] ) n++; + return sqlite3Atoi64(z, pOut, n, SQLITE_UTF8); } } @@ -34793,6 +35113,153 @@ SQLITE_PRIVATE int sqlite3Atoi(const char *z){ return x; } +/* +** Decode a floating-point value into an approximate decimal +** representation. +** +** Round the decimal representation to n significant digits if +** n is positive. Or round to -n signficant digits after the +** decimal point if n is negative. No rounding is performed if +** n is zero. +** +** The significant digits of the decimal representation are +** stored in p->z[] which is a often (but not always) a pointer +** into the middle of p->zBuf[]. There are p->n significant digits. +** The p->z[] array is *not* zero-terminated. +*/ +SQLITE_PRIVATE void sqlite3FpDecode(FpDecode *p, double r, int iRound, int mxRound){ + int i; + u64 v; + int e, exp = 0; + p->isSpecial = 0; + p->z = p->zBuf; + + /* Convert negative numbers to positive. Deal with Infinity, 0.0, and + ** NaN. */ + if( r<0.0 ){ + p->sign = '-'; + r = -r; + }else if( r==0.0 ){ + p->sign = '+'; + p->n = 1; + p->iDP = 1; + p->z = "0"; + return; + }else{ + p->sign = '+'; + } + memcpy(&v,&r,8); + e = v>>52; + if( (e&0x7ff)==0x7ff ){ + p->isSpecial = 1 + (v!=0x7ff0000000000000LL); + p->n = 0; + p->iDP = 0; + return; + } + + /* Multiply r by powers of ten until it lands somewhere in between + ** 1.0e+19 and 1.0e+17. + */ + if( sqlite3Config.bUseLongDouble ){ + LONGDOUBLE_TYPE rr = r; + if( rr>=1.0e+19 ){ + while( rr>=1.0e+119L ){ exp+=100; rr *= 1.0e-100L; } + while( rr>=1.0e+29L ){ exp+=10; rr *= 1.0e-10L; } + while( rr>=1.0e+19L ){ exp++; rr *= 1.0e-1L; } + }else{ + while( rr<1.0e-97L ){ exp-=100; rr *= 1.0e+100L; } + while( rr<1.0e+07L ){ exp-=10; rr *= 1.0e+10L; } + while( rr<1.0e+17L ){ exp--; rr *= 1.0e+1L; } + } + v = (u64)rr; + }else{ + /* If high-precision floating point is not available using "long double", + ** then use Dekker-style double-double computation to increase the + ** precision. + ** + ** The error terms on constants like 1.0e+100 computed using the + ** decimal extension, for example as follows: + ** + ** SELECT decimal_exp(decimal_sub('1.0e+100',decimal(1.0e+100))); + */ + double rr[2]; + rr[0] = r; + rr[1] = 0.0; + if( rr[0]>1.84e+19 ){ + while( rr[0]>1.84e+119 ){ + exp += 100; + dekkerMul2(rr, 1.0e-100, -1.99918998026028836196e-117); + } + while( rr[0]>1.84e+29 ){ + exp += 10; + dekkerMul2(rr, 1.0e-10, -3.6432197315497741579e-27); + } + while( rr[0]>1.84e+19 ){ + exp += 1; + dekkerMul2(rr, 1.0e-01, -5.5511151231257827021e-18); + } + }else{ + while( rr[0]<1.84e-82 ){ + exp -= 100; + dekkerMul2(rr, 1.0e+100, -1.5902891109759918046e+83); + } + while( rr[0]<1.84e+08 ){ + exp -= 10; + dekkerMul2(rr, 1.0e+10, 0.0); + } + while( rr[0]<1.84e+18 ){ + exp -= 1; + dekkerMul2(rr, 1.0e+01, 0.0); + } + } + v = rr[1]<0.0 ? (u64)rr[0]-(u64)(-rr[1]) : (u64)rr[0]+(u64)rr[1]; + } + + + /* Extract significant digits. */ + i = sizeof(p->zBuf)-1; + assert( v>0 ); + while( v ){ p->zBuf[i--] = (v%10) + '0'; v /= 10; } + assert( i>=0 && izBuf)-1 ); + p->n = sizeof(p->zBuf) - 1 - i; + assert( p->n>0 ); + assert( p->nzBuf) ); + p->iDP = p->n + exp; + if( iRound<0 ){ + iRound = p->iDP - iRound; + if( iRound==0 && p->zBuf[i+1]>='5' ){ + iRound = 1; + p->zBuf[i--] = '0'; + p->n++; + p->iDP++; + } + } + if( iRound>0 && (iRoundn || p->n>mxRound) ){ + char *z = &p->zBuf[i+1]; + if( iRound>mxRound ) iRound = mxRound; + p->n = iRound; + if( z[iRound]>='5' ){ + int j = iRound-1; + while( 1 /*exit-by-break*/ ){ + z[j]++; + if( z[j]<='9' ) break; + z[j] = '0'; + if( j==0 ){ + p->z[i--] = '1'; + p->n++; + p->iDP++; + break; + }else{ + j--; + } + } + } + } + p->z = &p->zBuf[i+1]; + assert( i+p->n < sizeof(p->zBuf) ); + while( ALWAYS(p->n>0) && p->z[p->n-1]=='0' ){ p->n--; } +} + /* ** Try to convert z into an unsigned 32-bit integer. Return true on ** success and false if there is an error. @@ -35321,7 +35788,7 @@ SQLITE_PRIVATE int sqlite3SafetyCheckSickOrOk(sqlite3 *db){ } /* -** Attempt to add, substract, or multiply the 64-bit signed value iB against +** Attempt to add, subtract, or multiply the 64-bit signed value iB against ** the other 64-bit signed integer at *pA and store the result in *pA. ** Return 0 on success. Or if the operation would have resulted in an ** overflow, leave *pA unchanged and return 1. @@ -35634,7 +36101,7 @@ SQLITE_PRIVATE int sqlite3VListNameToNum(VList *pIn, const char *zName, int nNam #define SQLITE_HWTIME_H /* -** The following routine only works on pentium-class (or newer) processors. +** The following routine only works on Pentium-class (or newer) processors. ** It uses the RDTSC opcode to read the cycle count value out of the ** processor and returns that value. This can be used for high-res ** profiling. @@ -35806,7 +36273,7 @@ static void insertElement( } -/* Resize the hash table so that it cantains "new_size" buckets. +/* Resize the hash table so that it contains "new_size" buckets. ** ** The hash table might fail to resize if sqlite3_malloc() fails or ** if the new size is the same as the prior size. @@ -37192,7 +37659,7 @@ SQLITE_PRIVATE int sqlite3KvvfsInit(void){ ** This source file is organized into divisions where the logic for various ** subfunctions is contained within the appropriate division. PLEASE ** KEEP THE STRUCTURE OF THIS FILE INTACT. New code should be placed -** in the correct division and should be clearly labeled. +** in the correct division and should be clearly labelled. ** ** The layout of divisions is as follows: ** @@ -37779,7 +38246,7 @@ static int robustFchown(int fd, uid_t uid, gid_t gid){ /* ** This is the xSetSystemCall() method of sqlite3_vfs for all of the -** "unix" VFSes. Return SQLITE_OK opon successfully updating the +** "unix" VFSes. Return SQLITE_OK upon successfully updating the ** system call pointer, or SQLITE_NOTFOUND if there is no configurable ** system call named zName. */ @@ -38301,7 +38768,7 @@ static void vxworksReleaseFileId(struct vxworksFileId *pId){ ** If you close a file descriptor that points to a file that has locks, ** all locks on that file that are owned by the current process are ** released. To work around this problem, each unixInodeInfo object -** maintains a count of the number of pending locks on tha inode. +** maintains a count of the number of pending locks on the inode. ** When an attempt is made to close an unixFile, if there are ** other unixFile open on the same inode that are holding locks, the call ** to close() the file descriptor is deferred until all of the locks clear. @@ -38315,7 +38782,7 @@ static void vxworksReleaseFileId(struct vxworksFileId *pId){ ** not posix compliant. Under LinuxThreads, a lock created by thread ** A cannot be modified or overridden by a different thread B. ** Only thread A can modify the lock. Locking behavior is correct -** if the appliation uses the newer Native Posix Thread Library (NPTL) +** if the application uses the newer Native Posix Thread Library (NPTL) ** on linux - with NPTL a lock created by thread A can override locks ** in thread B. But there is no way to know at compile-time which ** threading library is being used. So there is no way to know at @@ -38517,7 +38984,7 @@ static void storeLastErrno(unixFile *pFile, int error){ } /* -** Close all file descriptors accumuated in the unixInodeInfo->pUnused list. +** Close all file descriptors accumulated in the unixInodeInfo->pUnused list. */ static void closePendingFds(unixFile *pFile){ unixInodeInfo *pInode = pFile->pInode; @@ -38880,7 +39347,7 @@ static int unixLock(sqlite3_file *id, int eFileLock){ ** slightly in order to be compatible with Windows95 systems simultaneously ** accessing the same database file, in case that is ever required. ** - ** Symbols defined in os.h indentify the 'pending byte' and the 'reserved + ** Symbols defined in os.h identify the 'pending byte' and the 'reserved ** byte', each single bytes at well known offsets, and the 'shared byte ** range', a range of 510 bytes at a well known offset. ** @@ -38888,7 +39355,7 @@ static int unixLock(sqlite3_file *id, int eFileLock){ ** byte'. If this is successful, 'shared byte range' is read-locked ** and the lock on the 'pending byte' released. (Legacy note: When ** SQLite was first developed, Windows95 systems were still very common, - ** and Widnows95 lacks a shared-lock capability. So on Windows95, a + ** and Windows95 lacks a shared-lock capability. So on Windows95, a ** single randomly selected by from the 'shared byte range' is locked. ** Windows95 is now pretty much extinct, but this work-around for the ** lack of shared-locks on Windows95 lives on, for backwards @@ -38909,7 +39376,7 @@ static int unixLock(sqlite3_file *id, int eFileLock){ ** obtaining a write-lock on the 'pending byte'. This ensures that no new ** SHARED locks can be obtained, but existing SHARED locks are allowed to ** persist. If the call to this function fails to obtain the EXCLUSIVE - ** lock in this case, it holds the PENDING lock intead. The client may + ** lock in this case, it holds the PENDING lock instead. The client may ** then re-attempt the EXCLUSIVE lock later on, after existing SHARED ** locks have cleared. */ @@ -38937,7 +39404,7 @@ static int unixLock(sqlite3_file *id, int eFileLock){ /* Make sure the locking sequence is correct. ** (1) We never move from unlocked to anything higher than shared lock. - ** (2) SQLite never explicitly requests a pendig lock. + ** (2) SQLite never explicitly requests a pending lock. ** (3) A shared lock is always held when a reserve lock is requested. */ assert( pFile->eFileLock!=NO_LOCK || eFileLock==SHARED_LOCK ); @@ -40155,7 +40622,7 @@ static int afpLock(sqlite3_file *id, int eFileLock){ /* Make sure the locking sequence is correct ** (1) We never move from unlocked to anything higher than shared lock. - ** (2) SQLite never explicitly requests a pendig lock. + ** (2) SQLite never explicitly requests a pending lock. ** (3) A shared lock is always held when a reserve lock is requested. */ assert( pFile->eFileLock!=NO_LOCK || eFileLock==SHARED_LOCK ); @@ -40271,7 +40738,7 @@ static int afpLock(sqlite3_file *id, int eFileLock){ if( !(failed = afpSetLock(context->dbPath, pFile, SHARED_FIRST + pInode->sharedByte, 1, 0)) ){ int failed2 = SQLITE_OK; - /* now attemmpt to get the exclusive lock range */ + /* now attempt to get the exclusive lock range */ failed = afpSetLock(context->dbPath, pFile, SHARED_FIRST, SHARED_SIZE, 1); if( failed && (failed2 = afpSetLock(context->dbPath, pFile, @@ -40566,7 +41033,7 @@ static int unixRead( #endif #if SQLITE_MAX_MMAP_SIZE>0 - /* Deal with as much of this read request as possible by transfering + /* Deal with as much of this read request as possible by transferring ** data from the memory mapping using memcpy(). */ if( offsetmmapSize ){ if( offset+amt <= pFile->mmapSize ){ @@ -40718,7 +41185,7 @@ static int unixWrite( #endif #if defined(SQLITE_MMAP_READWRITE) && SQLITE_MAX_MMAP_SIZE>0 - /* Deal with as much of this write request as possible by transfering + /* Deal with as much of this write request as possible by transferring ** data from the memory mapping using memcpy(). */ if( offsetmmapSize ){ if( offset+amt <= pFile->mmapSize ){ @@ -40840,7 +41307,7 @@ static int full_fsync(int fd, int fullSync, int dataOnly){ /* If we compiled with the SQLITE_NO_SYNC flag, then syncing is a ** no-op. But go ahead and call fstat() to validate the file ** descriptor as we need a method to provoke a failure during - ** coverate testing. + ** coverage testing. */ #ifdef SQLITE_NO_SYNC { @@ -43885,12 +44352,17 @@ static int unixRandomness(sqlite3_vfs *NotUsed, int nBuf, char *zBuf){ ** than the argument. */ static int unixSleep(sqlite3_vfs *NotUsed, int microseconds){ -#if OS_VXWORKS || _POSIX_C_SOURCE >= 199309L +#if !defined(HAVE_NANOSLEEP) || HAVE_NANOSLEEP+0 struct timespec sp; - sp.tv_sec = microseconds / 1000000; sp.tv_nsec = (microseconds % 1000000) * 1000; + + /* Almost all modern unix systems support nanosleep(). But if you are + ** compiling for one of the rare exceptions, you can use + ** -DHAVE_NANOSLEEP=0 (perhaps in conjuction with -DHAVE_USLEEP if + ** usleep() is available) in order to bypass the use of nanosleep() */ nanosleep(&sp, NULL); + UNUSED_PARAMETER(NotUsed); return microseconds; #elif defined(HAVE_USLEEP) && HAVE_USLEEP @@ -46480,7 +46952,7 @@ static struct win_syscall { /* ** This is the xSetSystemCall() method of sqlite3_vfs for all of the -** "win32" VFSes. Return SQLITE_OK opon successfully updating the +** "win32" VFSes. Return SQLITE_OK upon successfully updating the ** system call pointer, or SQLITE_NOTFOUND if there is no configurable ** system call named zName. */ @@ -48060,7 +48532,7 @@ static int winRead( pFile->h, pBuf, amt, offset, pFile->locktype)); #if SQLITE_MAX_MMAP_SIZE>0 - /* Deal with as much of this read request as possible by transfering + /* Deal with as much of this read request as possible by transferring ** data from the memory mapping using memcpy(). */ if( offsetmmapSize ){ if( offset+amt <= pFile->mmapSize ){ @@ -48138,7 +48610,7 @@ static int winWrite( pFile->h, pBuf, amt, offset, pFile->locktype)); #if defined(SQLITE_MMAP_READWRITE) && SQLITE_MAX_MMAP_SIZE>0 - /* Deal with as much of this write request as possible by transfering + /* Deal with as much of this write request as possible by transferring ** data from the memory mapping using memcpy(). */ if( offsetmmapSize ){ if( offset+amt <= pFile->mmapSize ){ @@ -48248,7 +48720,7 @@ static int winTruncate(sqlite3_file *id, sqlite3_int64 nByte){ ** all references to memory-mapped content are closed. That is doable, ** but involves adding a few branches in the common write code path which ** could slow down normal operations slightly. Hence, we have decided for - ** now to simply make trancations a no-op if there are pending reads. We + ** now to simply make transactions a no-op if there are pending reads. We ** can maybe revisit this decision in the future. */ return SQLITE_OK; @@ -48307,7 +48779,7 @@ static int winTruncate(sqlite3_file *id, sqlite3_int64 nByte){ #ifdef SQLITE_TEST /* ** Count the number of fullsyncs and normal syncs. This is used to test -** that syncs and fullsyncs are occuring at the right times. +** that syncs and fullsyncs are occurring at the right times. */ SQLITE_API int sqlite3_sync_count = 0; SQLITE_API int sqlite3_fullsync_count = 0; @@ -48664,7 +49136,7 @@ static int winLock(sqlite3_file *id, int locktype){ */ if( locktype==EXCLUSIVE_LOCK && res ){ assert( pFile->locktype>=SHARED_LOCK ); - res = winUnlockReadLock(pFile); + (void)winUnlockReadLock(pFile); res = winLockFile(&pFile->h, SQLITE_LOCKFILE_FLAGS, SHARED_FIRST, 0, SHARED_SIZE, 0); if( res ){ @@ -50068,6 +50540,7 @@ static int winGetTempname(sqlite3_vfs *pVfs, char **pzBuf){ "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "0123456789"; size_t i, j; + DWORD pid; int nPre = sqlite3Strlen30(SQLITE_TEMP_FILE_PREFIX); int nMax, nBuf, nDir, nLen; char *zBuf; @@ -50280,7 +50753,10 @@ static int winGetTempname(sqlite3_vfs *pVfs, char **pzBuf){ j = sqlite3Strlen30(zBuf); sqlite3_randomness(15, &zBuf[j]); + pid = osGetCurrentProcessId(); for(i=0; i<15; i++, j++){ + zBuf[j] += pid & 0xff; + pid >>= 8; zBuf[j] = (char)zChars[ ((unsigned char)zBuf[j])%(sizeof(zChars)-1) ]; } zBuf[j] = 0; @@ -52645,7 +53121,7 @@ SQLITE_PRIVATE int sqlite3BitvecSet(Bitvec *p, u32 i){ h = BITVEC_HASH(i++); /* if there wasn't a hash collision, and this doesn't */ /* completely fill the hash, then just add it without */ - /* worring about sub-dividing and re-hashing. */ + /* worrying about sub-dividing and re-hashing. */ if( !p->u.aHash[h] ){ if (p->nSet<(BITVEC_NINT-1)) { goto bitvec_set_end; @@ -52978,7 +53454,7 @@ struct PCache { ** Return 1 if pPg is on the dirty list for pCache. Return 0 if not. ** This routine runs inside of assert() statements only. */ -#ifdef SQLITE_DEBUG +#if defined(SQLITE_ENABLE_EXPENSIVE_ASSERT) static int pageOnDirtyList(PCache *pCache, PgHdr *pPg){ PgHdr *p; for(p=pCache->pDirty; p; p=p->pDirtyNext){ @@ -52986,6 +53462,16 @@ static int pageOnDirtyList(PCache *pCache, PgHdr *pPg){ } return 0; } +static int pageNotOnDirtyList(PCache *pCache, PgHdr *pPg){ + PgHdr *p; + for(p=pCache->pDirty; p; p=p->pDirtyNext){ + if( p==pPg ) return 0; + } + return 1; +} +#else +# define pageOnDirtyList(A,B) 1 +# define pageNotOnDirtyList(A,B) 1 #endif /* @@ -53006,7 +53492,7 @@ SQLITE_PRIVATE int sqlite3PcachePageSanity(PgHdr *pPg){ assert( pCache!=0 ); /* Every page has an associated PCache */ if( pPg->flags & PGHDR_CLEAN ){ assert( (pPg->flags & PGHDR_DIRTY)==0 );/* Cannot be both CLEAN and DIRTY */ - assert( !pageOnDirtyList(pCache, pPg) );/* CLEAN pages not on dirty list */ + assert( pageNotOnDirtyList(pCache, pPg) );/* CLEAN pages not on dirtylist */ }else{ assert( (pPg->flags & PGHDR_DIRTY)!=0 );/* If not CLEAN must be DIRTY */ assert( pPg->pDirtyNext==0 || pPg->pDirtyNext->pDirtyPrev==pPg ); @@ -53142,7 +53628,7 @@ static int numberOfCachePages(PCache *p){ return p->szCache; }else{ i64 n; - /* IMPLEMANTATION-OF: R-59858-46238 If the argument N is negative, then the + /* IMPLEMENTATION-OF: R-59858-46238 If the argument N is negative, then the ** number of cache pages is adjusted to be a number of pages that would ** use approximately abs(N*1024) bytes of memory based on the current ** page size. */ @@ -53630,7 +54116,7 @@ static PgHdr *pcacheMergeDirtyList(PgHdr *pA, PgHdr *pB){ } /* -** Sort the list of pages in accending order by pgno. Pages are +** Sort the list of pages in ascending order by pgno. Pages are ** connected by pDirty pointers. The pDirtyPrev pointers are ** corrupted by this sort. ** @@ -53870,7 +54356,7 @@ SQLITE_PRIVATE void sqlite3PcacheIterateDirty(PCache *pCache, void (*xIter)(PgHd ** If N is positive, then N pages worth of memory are allocated using a single ** sqlite3Malloc() call and that memory is used for the first N pages allocated. ** Or if N is negative, then -1024*N bytes of memory are allocated and used -** for as many pages as can be accomodated. +** for as many pages as can be accommodated. ** ** Only one of (2) or (3) can be used. Once the memory available to (2) or ** (3) is exhausted, subsequent allocations fail over to the general-purpose @@ -53904,7 +54390,7 @@ typedef struct PGroup PGroup; ** in memory directly after the associated page data, if the database is ** corrupt, code at the b-tree layer may overread the page buffer and ** read part of this structure before the corruption is detected. This -** can cause a valgrind error if the unitialized gap is accessed. Using u16 +** can cause a valgrind error if the uninitialized gap is accessed. Using u16 ** ensures there is no such gap, and therefore no bytes of uninitialized ** memory in the structure. ** @@ -55124,7 +55610,7 @@ SQLITE_PRIVATE void sqlite3PcacheStats( ** The TEST primitive includes a "batch" number. The TEST primitive ** will only see elements that were inserted before the last change ** in the batch number. In other words, if an INSERT occurs between -** two TESTs where the TESTs have the same batch nubmer, then the +** two TESTs where the TESTs have the same batch number, then the ** value added by the INSERT will not be visible to the second TEST. ** The initial batch number is zero, so if the very first TEST contains ** a non-zero batch number, it will see all prior INSERTs. @@ -55656,6 +56142,7 @@ SQLITE_PRIVATE int sqlite3RowSetTest(RowSet *pRowSet, int iBatch, sqlite3_int64 # define sqlite3WalFramesize(z) 0 # define sqlite3WalFindFrame(x,y,z) 0 # define sqlite3WalFile(x) 0 +# undef SQLITE_USE_SEH #else #define WAL_SAVEPOINT_NDATA 4 @@ -55762,6 +56249,10 @@ SQLITE_PRIVATE int sqlite3WalWriteLock(Wal *pWal, int bLock); SQLITE_PRIVATE void sqlite3WalDb(Wal *pWal, sqlite3 *db); #endif +#ifdef SQLITE_USE_SEH +SQLITE_PRIVATE int sqlite3WalSystemErrno(Wal*); +#endif + #endif /* ifndef SQLITE_OMIT_WAL */ #endif /* SQLITE_WAL_H */ @@ -56047,7 +56538,7 @@ int sqlite3PagerTrace=1; /* True to enable tracing */ ** outstanding transactions have been abandoned, the pager is able to ** transition back to OPEN state, discarding the contents of the ** page-cache and any other in-memory state at the same time. Everything -** is reloaded from disk (and, if necessary, hot-journal rollback peformed) +** is reloaded from disk (and, if necessary, hot-journal rollback performed) ** when a read-transaction is next opened on the pager (transitioning ** the pager into READER state). At that point the system has recovered ** from the error. @@ -57420,7 +57911,7 @@ static int readJournalHdr( ** + 4 bytes: super-journal name checksum. ** + 8 bytes: aJournalMagic[]. ** -** The super-journal page checksum is the sum of the bytes in thesuper-journal +** The super-journal page checksum is the sum of the bytes in the super-journal ** name, where each byte is interpreted as a signed 8-bit integer. ** ** If zSuper is a NULL pointer (occurs for a single database transaction), @@ -57473,7 +57964,7 @@ static int writeSuperJournal(Pager *pPager, const char *zSuper){ } pPager->journalOff += (nSuper+20); - /* If the pager is in peristent-journal mode, then the physical + /* If the pager is in persistent-journal mode, then the physical ** journal-file may extend past the end of the super-journal name ** and 8 bytes of magic data just written to the file. This is ** dangerous because the code to rollback a hot-journal file @@ -57643,7 +58134,7 @@ static void pager_unlock(Pager *pPager){ /* ** This function is called whenever an IOERR or FULL error that requires -** the pager to transition into the ERROR state may ahve occurred. +** the pager to transition into the ERROR state may have occurred. ** The first argument is a pointer to the pager structure, the second ** the error-code about to be returned by a pager API function. The ** value returned is a copy of the second argument to this function. @@ -57918,7 +58409,7 @@ static void pagerUnlockAndRollback(Pager *pPager){ /* ** Parameter aData must point to a buffer of pPager->pageSize bytes -** of data. Compute and return a checksum based ont the contents of the +** of data. Compute and return a checksum based on the contents of the ** page of data and the current value of pPager->cksumInit. ** ** This is not a real checksum. It is really just the sum of the @@ -58884,7 +59375,7 @@ static int pagerWalFrames( assert( pPager->pWal ); assert( pList ); #ifdef SQLITE_DEBUG - /* Verify that the page list is in accending order */ + /* Verify that the page list is in ascending order */ for(p=pList; p && p->pDirty; p=p->pDirty){ assert( p->pgno < p->pDirty->pgno ); } @@ -59015,7 +59506,7 @@ static int pagerPagecount(Pager *pPager, Pgno *pnPage){ #ifndef SQLITE_OMIT_WAL /* ** Check if the *-wal file that corresponds to the database opened by pPager -** exists if the database is not empy, or verify that the *-wal file does +** exists if the database is not empty, or verify that the *-wal file does ** not exist (by deleting it) if the database file is empty. ** ** If the database is not empty and the *-wal file exists, open the pager @@ -60425,11 +60916,7 @@ SQLITE_PRIVATE int sqlite3PagerOpen( int rc = SQLITE_OK; /* Return code */ int tempFile = 0; /* True for temp files (incl. in-memory files) */ int memDb = 0; /* True if this is an in-memory file */ -#ifndef SQLITE_OMIT_DESERIALIZE int memJM = 0; /* Memory journal mode */ -#else -# define memJM 0 -#endif int readOnly = 0; /* True if this is a read-only file */ int journalFileSize; /* Bytes to allocate for each journal fd */ char *zPathname = 0; /* Full path to database file */ @@ -60548,12 +61035,13 @@ SQLITE_PRIVATE int sqlite3PagerOpen( ** specific formatting and order of the various filenames, so if the format ** changes here, be sure to change it there as well. */ + assert( SQLITE_PTRSIZE==sizeof(Pager*) ); pPtr = (u8 *)sqlite3MallocZero( ROUND8(sizeof(*pPager)) + /* Pager structure */ ROUND8(pcacheSize) + /* PCache object */ ROUND8(pVfs->szOsFile) + /* The main db file */ journalFileSize * 2 + /* The two journal files */ - sizeof(pPager) + /* Space to hold a pointer */ + SQLITE_PTRSIZE + /* Space to hold a pointer */ 4 + /* Database prefix */ nPathname + 1 + /* database filename */ nUriByte + /* query parameters */ @@ -60574,7 +61062,7 @@ SQLITE_PRIVATE int sqlite3PagerOpen( pPager->sjfd = (sqlite3_file*)pPtr; pPtr += journalFileSize; pPager->jfd = (sqlite3_file*)pPtr; pPtr += journalFileSize; assert( EIGHT_BYTE_ALIGNMENT(pPager->jfd) ); - memcpy(pPtr, &pPager, sizeof(pPager)); pPtr += sizeof(pPager); + memcpy(pPtr, &pPager, SQLITE_PTRSIZE); pPtr += SQLITE_PTRSIZE; /* Fill in the Pager.zFilename and pPager.zQueryParam fields */ pPtr += 4; /* Skip zero prefix */ @@ -60628,9 +61116,7 @@ SQLITE_PRIVATE int sqlite3PagerOpen( int fout = 0; /* VFS flags returned by xOpen() */ rc = sqlite3OsOpen(pVfs, pPager->zFilename, pPager->fd, vfsFlags, &fout); assert( !memDb ); -#ifndef SQLITE_OMIT_DESERIALIZE pPager->memVfs = memJM = (fout&SQLITE_OPEN_MEMORY)!=0; -#endif readOnly = (fout&SQLITE_OPEN_READONLY)!=0; /* If the file was successfully opened for read/write access, @@ -60767,7 +61253,7 @@ act_like_temp_file: /* ** Return the sqlite3_file for the main database given the name -** of the corresonding WAL or Journal name as passed into +** of the corresponding WAL or Journal name as passed into ** xOpen. */ SQLITE_API sqlite3_file *sqlite3_database_file_object(const char *zName){ @@ -63052,7 +63538,7 @@ SQLITE_PRIVATE int sqlite3PagerSetJournalMode(Pager *pPager, int eMode){ assert( pPager->eState!=PAGER_ERROR ); pPager->journalMode = (u8)eMode; - /* When transistioning from TRUNCATE or PERSIST to any other journal + /* When transitioning from TRUNCATE or PERSIST to any other journal ** mode except WAL, unless the pager is in locking_mode=exclusive mode, ** delete the journal file. */ @@ -63480,6 +63966,12 @@ SQLITE_PRIVATE int sqlite3PagerWalFramesize(Pager *pPager){ } #endif +#ifdef SQLITE_USE_SEH +SQLITE_PRIVATE int sqlite3PagerWalSystemErrno(Pager *pPager){ + return sqlite3WalSystemErrno(pPager->pWal); +} +#endif + #endif /* SQLITE_OMIT_DISKIO */ /************** End of pager.c ***********************************************/ @@ -63770,7 +64262,7 @@ SQLITE_PRIVATE int sqlite3WalTrace = 0; ** ** Technically, the various VFSes are free to implement these locks however ** they see fit. However, compatibility is encouraged so that VFSes can -** interoperate. The standard implemention used on both unix and windows +** interoperate. The standard implementation used on both unix and windows ** is for the index number to indicate a byte offset into the ** WalCkptInfo.aLock[] array in the wal-index header. In other words, all ** locks are on the shm file. The WALINDEX_LOCK_OFFSET constant (which @@ -63846,7 +64338,7 @@ struct WalIndexHdr { ** the mxFrame for that reader. The value READMARK_NOT_USED (0xffffffff) ** for any aReadMark[] means that entry is unused. aReadMark[0] is ** a special case; its value is never used and it exists as a place-holder -** to avoid having to offset aReadMark[] indexs by one. Readers holding +** to avoid having to offset aReadMark[] indexes by one. Readers holding ** WAL_READ_LOCK(0) always ignore the entire WAL and read all content ** directly from the database. ** @@ -64014,7 +64506,15 @@ struct Wal { u32 iReCksum; /* On commit, recalculate checksums from here */ const char *zWalName; /* Name of WAL file */ u32 nCkpt; /* Checkpoint sequence counter in the wal-header */ +#ifdef SQLITE_USE_SEH + u32 lockMask; /* Mask of locks held */ + void *pFree; /* Pointer to sqlite3_free() if exception thrown */ + u32 *pWiValue; /* Value to write into apWiData[iWiPg] */ + int iWiPg; /* Write pWiValue into apWiData[iWiPg] */ + int iSysErrno; /* System error code following exception */ +#endif #ifdef SQLITE_DEBUG + int nSehTry; /* Number of nested SEH_TRY{} blocks */ u8 lockError; /* True if a locking error has occurred */ #endif #ifdef SQLITE_ENABLE_SNAPSHOT @@ -64096,6 +64596,113 @@ struct WalIterator { sizeof(ht_slot)*HASHTABLE_NSLOT + HASHTABLE_NPAGE*sizeof(u32) \ ) +/* +** Structured Exception Handling (SEH) is a Windows-specific technique +** for catching exceptions raised while accessing memory-mapped files. +** +** The -DSQLITE_USE_SEH compile-time option means to use SEH to catch and +** deal with system-level errors that arise during WAL -shm file processing. +** Without this compile-time option, any system-level faults that appear +** while accessing the memory-mapped -shm file will cause a process-wide +** signal to be deliver, which will more than likely cause the entire +** process to exit. +*/ +#ifdef SQLITE_USE_SEH +#include + +/* Beginning of a block of code in which an exception might occur */ +# define SEH_TRY __try { \ + assert( walAssertLockmask(pWal) && pWal->nSehTry==0 ); \ + VVA_ONLY(pWal->nSehTry++); + +/* The end of a block of code in which an exception might occur */ +# define SEH_EXCEPT(X) \ + VVA_ONLY(pWal->nSehTry--); \ + assert( pWal->nSehTry==0 ); \ + } __except( sehExceptionFilter(pWal, GetExceptionCode(), GetExceptionInformation() ) ){ X } + +/* Simulate a memory-mapping fault in the -shm file for testing purposes */ +# define SEH_INJECT_FAULT sehInjectFault(pWal) + +/* +** The second argument is the return value of GetExceptionCode() for the +** current exception. Return EXCEPTION_EXECUTE_HANDLER if the exception code +** indicates that the exception may have been caused by accessing the *-shm +** file mapping. Or EXCEPTION_CONTINUE_SEARCH otherwise. +*/ +static int sehExceptionFilter(Wal *pWal, int eCode, EXCEPTION_POINTERS *p){ + VVA_ONLY(pWal->nSehTry--); + if( eCode==EXCEPTION_IN_PAGE_ERROR ){ + if( p && p->ExceptionRecord && p->ExceptionRecord->NumberParameters>=3 ){ + /* From MSDN: For this type of exception, the first element of the + ** ExceptionInformation[] array is a read-write flag - 0 if the exception + ** was thrown while reading, 1 if while writing. The second element is + ** the virtual address being accessed. The "third array element specifies + ** the underlying NTSTATUS code that resulted in the exception". */ + pWal->iSysErrno = (int)p->ExceptionRecord->ExceptionInformation[2]; + } + return EXCEPTION_EXECUTE_HANDLER; + } + return EXCEPTION_CONTINUE_SEARCH; +} + +/* +** If one is configured, invoke the xTestCallback callback with 650 as +** the argument. If it returns true, throw the same exception that is +** thrown by the system if the *-shm file mapping is accessed after it +** has been invalidated. +*/ +static void sehInjectFault(Wal *pWal){ + int res; + assert( pWal->nSehTry>0 ); + + res = sqlite3FaultSim(650); + if( res!=0 ){ + ULONG_PTR aArg[3]; + aArg[0] = 0; + aArg[1] = 0; + aArg[2] = (ULONG_PTR)res; + RaiseException(EXCEPTION_IN_PAGE_ERROR, 0, 3, (const ULONG_PTR*)aArg); + } +} + +/* +** There are two ways to use this macro. To set a pointer to be freed +** if an exception is thrown: +** +** SEH_FREE_ON_ERROR(0, pPtr); +** +** and to cancel the same: +** +** SEH_FREE_ON_ERROR(pPtr, 0); +** +** In the first case, there must not already be a pointer registered to +** be freed. In the second case, pPtr must be the registered pointer. +*/ +#define SEH_FREE_ON_ERROR(X,Y) \ + assert( (X==0 || Y==0) && pWal->pFree==X ); pWal->pFree = Y + +/* +** There are two ways to use this macro. To arrange for pWal->apWiData[iPg] +** to be set to pValue if an exception is thrown: +** +** SEH_SET_ON_ERROR(iPg, pValue); +** +** and to cancel the same: +** +** SEH_SET_ON_ERROR(0, 0); +*/ +#define SEH_SET_ON_ERROR(X,Y) pWal->iWiPg = X; pWal->pWiValue = Y + +#else +# define SEH_TRY VVA_ONLY(pWal->nSehTry++); +# define SEH_EXCEPT(X) VVA_ONLY(pWal->nSehTry--); assert( pWal->nSehTry==0 ); +# define SEH_INJECT_FAULT assert( pWal->nSehTry>0 ); +# define SEH_FREE_ON_ERROR(X,Y) +# define SEH_SET_ON_ERROR(X,Y) +#endif /* ifdef SQLITE_USE_SEH */ + + /* ** Obtain a pointer to the iPage'th page of the wal-index. The wal-index ** is broken into pages of WALINDEX_PGSZ bytes. Wal-index pages are @@ -64168,6 +64775,7 @@ static int walIndexPage( int iPage, /* The page we seek */ volatile u32 **ppPage /* Write the page pointer here */ ){ + SEH_INJECT_FAULT; if( pWal->nWiData<=iPage || (*ppPage = pWal->apWiData[iPage])==0 ){ return walIndexPageRealloc(pWal, iPage, ppPage); } @@ -64179,6 +64787,7 @@ static int walIndexPage( */ static volatile WalCkptInfo *walCkptInfo(Wal *pWal){ assert( pWal->nWiData>0 && pWal->apWiData[0] ); + SEH_INJECT_FAULT; return (volatile WalCkptInfo*)&(pWal->apWiData[0][sizeof(WalIndexHdr)/2]); } @@ -64187,6 +64796,7 @@ static volatile WalCkptInfo *walCkptInfo(Wal *pWal){ */ static volatile WalIndexHdr *walIndexHdr(Wal *pWal){ assert( pWal->nWiData>0 && pWal->apWiData[0] ); + SEH_INJECT_FAULT; return (volatile WalIndexHdr*)pWal->apWiData[0]; } @@ -64376,7 +64986,7 @@ static int walDecodeFrame( return 0; } - /* A frame is only valid if the page number is creater than zero. + /* A frame is only valid if the page number is greater than zero. */ pgno = sqlite3Get4byte(&aFrame[0]); if( pgno==0 ){ @@ -64384,7 +64994,7 @@ static int walDecodeFrame( } /* A frame is only valid if a checksum of the WAL header, - ** all prior frams, the first 16 bytes of this frame-header, + ** all prior frames, the first 16 bytes of this frame-header, ** and the frame-data matches the checksum in the last 8 ** bytes of this frame-header. */ @@ -64444,12 +65054,18 @@ static int walLockShared(Wal *pWal, int lockIdx){ WALTRACE(("WAL%p: acquire SHARED-%s %s\n", pWal, walLockName(lockIdx), rc ? "failed" : "ok")); VVA_ONLY( pWal->lockError = (u8)(rc!=SQLITE_OK && (rc&0xFF)!=SQLITE_BUSY); ) +#ifdef SQLITE_USE_SEH + if( rc==SQLITE_OK ) pWal->lockMask |= (1 << lockIdx); +#endif return rc; } static void walUnlockShared(Wal *pWal, int lockIdx){ if( pWal->exclusiveMode ) return; (void)sqlite3OsShmLock(pWal->pDbFd, lockIdx, 1, SQLITE_SHM_UNLOCK | SQLITE_SHM_SHARED); +#ifdef SQLITE_USE_SEH + pWal->lockMask &= ~(1 << lockIdx); +#endif WALTRACE(("WAL%p: release SHARED-%s\n", pWal, walLockName(lockIdx))); } static int walLockExclusive(Wal *pWal, int lockIdx, int n){ @@ -64460,12 +65076,20 @@ static int walLockExclusive(Wal *pWal, int lockIdx, int n){ WALTRACE(("WAL%p: acquire EXCLUSIVE-%s cnt=%d %s\n", pWal, walLockName(lockIdx), n, rc ? "failed" : "ok")); VVA_ONLY( pWal->lockError = (u8)(rc!=SQLITE_OK && (rc&0xFF)!=SQLITE_BUSY); ) +#ifdef SQLITE_USE_SEH + if( rc==SQLITE_OK ){ + pWal->lockMask |= (((1<exclusiveMode ) return; (void)sqlite3OsShmLock(pWal->pDbFd, lockIdx, n, SQLITE_SHM_UNLOCK | SQLITE_SHM_EXCLUSIVE); +#ifdef SQLITE_USE_SEH + pWal->lockMask &= ~(((1<apWiData[0][WALINDEX_HDR_SIZE/sizeof(u32) + iFrame - 1]; } @@ -64816,6 +65441,7 @@ static int walIndexRecover(Wal *pWal){ /* Malloc a buffer to read frames into. */ szFrame = szPage + WAL_FRAME_HDRSIZE; aFrame = (u8 *)sqlite3_malloc64(szFrame + WALINDEX_PGSZ); + SEH_FREE_ON_ERROR(0, aFrame); if( !aFrame ){ rc = SQLITE_NOMEM_BKPT; goto recovery_error; @@ -64834,6 +65460,7 @@ static int walIndexRecover(Wal *pWal){ rc = walIndexPage(pWal, iPg, (volatile u32**)&aShare); assert( aShare!=0 || rc!=SQLITE_OK ); if( aShare==0 ) break; + SEH_SET_ON_ERROR(iPg, aShare); pWal->apWiData[iPg] = aPrivate; for(iFrame=iFirst; iFrame<=iLast; iFrame++){ @@ -64861,6 +65488,7 @@ static int walIndexRecover(Wal *pWal){ } } pWal->apWiData[iPg] = aShare; + SEH_SET_ON_ERROR(0,0); nHdr = (iPg==0 ? WALINDEX_HDR_SIZE : 0); nHdr32 = nHdr / sizeof(u32); #ifndef SQLITE_SAFER_WALINDEX_RECOVERY @@ -64891,9 +65519,11 @@ static int walIndexRecover(Wal *pWal){ } } #endif + SEH_INJECT_FAULT; if( iFrame<=iLast ) break; } + SEH_FREE_ON_ERROR(aFrame, 0); sqlite3_free(aFrame); } @@ -64921,6 +65551,7 @@ finished: }else{ pInfo->aReadMark[i] = READMARK_NOT_USED; } + SEH_INJECT_FAULT; walUnlockExclusive(pWal, WAL_READ_LOCK(i), 1); }else if( rc!=SQLITE_BUSY ){ goto recovery_error; @@ -65078,7 +65709,7 @@ SQLITE_PRIVATE int sqlite3WalOpen( } /* -** Change the size to which the WAL file is trucated on each reset. +** Change the size to which the WAL file is truncated on each reset. */ SQLITE_PRIVATE void sqlite3WalLimit(Wal *pWal, i64 iLimit){ if( pWal ) pWal->mxWalSize = iLimit; @@ -65304,23 +65935,16 @@ static int walIteratorInit(Wal *pWal, u32 nBackfill, WalIterator **pp){ nByte = sizeof(WalIterator) + (nSegment-1)*sizeof(struct WalSegment) + iLast*sizeof(ht_slot); - p = (WalIterator *)sqlite3_malloc64(nByte); + p = (WalIterator *)sqlite3_malloc64(nByte + + sizeof(ht_slot) * (iLast>HASHTABLE_NPAGE?HASHTABLE_NPAGE:iLast) + ); if( !p ){ return SQLITE_NOMEM_BKPT; } memset(p, 0, nByte); p->nSegment = nSegment; - - /* Allocate temporary space used by the merge-sort routine. This block - ** of memory will be freed before this function returns. - */ - aTmp = (ht_slot *)sqlite3_malloc64( - sizeof(ht_slot) * (iLast>HASHTABLE_NPAGE?HASHTABLE_NPAGE:iLast) - ); - if( !aTmp ){ - rc = SQLITE_NOMEM_BKPT; - } - + aTmp = (ht_slot*)&(((u8*)p)[nByte]); + SEH_FREE_ON_ERROR(0, p); for(i=walFramePage(nBackfill+1); rc==SQLITE_OK && iaSegment[i].aPgno = (u32 *)sLoc.aPgno; } } - sqlite3_free(aTmp); - if( rc!=SQLITE_OK ){ + SEH_FREE_ON_ERROR(p, 0); walIteratorFree(p); p = 0; } @@ -65576,13 +66199,13 @@ static int walCheckpoint( mxSafeFrame = pWal->hdr.mxFrame; mxPage = pWal->hdr.nPage; for(i=1; iaReadMark+i); + u32 y = AtomicLoad(pInfo->aReadMark+i); SEH_INJECT_FAULT; if( mxSafeFrame>y ){ assert( y<=pWal->hdr.mxFrame ); rc = walBusyLock(pWal, xBusy, pBusyArg, WAL_READ_LOCK(i), 1); if( rc==SQLITE_OK ){ u32 iMark = (i==1 ? mxSafeFrame : READMARK_NOT_USED); - AtomicStore(pInfo->aReadMark+i, iMark); + AtomicStore(pInfo->aReadMark+i, iMark); SEH_INJECT_FAULT; walUnlockExclusive(pWal, WAL_READ_LOCK(i), 1); }else if( rc==SQLITE_BUSY ){ mxSafeFrame = y; @@ -65603,8 +66226,7 @@ static int walCheckpoint( && (rc = walBusyLock(pWal,xBusy,pBusyArg,WAL_READ_LOCK(0),1))==SQLITE_OK ){ u32 nBackfill = pInfo->nBackfill; - - pInfo->nBackfillAttempted = mxSafeFrame; + pInfo->nBackfillAttempted = mxSafeFrame; SEH_INJECT_FAULT; /* Sync the WAL to disk */ rc = sqlite3OsSync(pWal->pWalFd, CKPT_SYNC_FLAGS(sync_flags)); @@ -65635,6 +66257,7 @@ static int walCheckpoint( while( rc==SQLITE_OK && 0==walIteratorNext(pIter, &iDbpage, &iFrame) ){ i64 iOffset; assert( walFramePgno(pWal, iFrame)==iDbpage ); + SEH_INJECT_FAULT; if( AtomicLoad(&db->u1.isInterrupted) ){ rc = db->mallocFailed ? SQLITE_NOMEM_BKPT : SQLITE_INTERRUPT; break; @@ -65664,7 +66287,7 @@ static int walCheckpoint( } } if( rc==SQLITE_OK ){ - AtomicStore(&pInfo->nBackfill, mxSafeFrame); + AtomicStore(&pInfo->nBackfill, mxSafeFrame); SEH_INJECT_FAULT; } } @@ -65686,6 +66309,7 @@ static int walCheckpoint( */ if( rc==SQLITE_OK && eMode!=SQLITE_CHECKPOINT_PASSIVE ){ assert( pWal->writeLock ); + SEH_INJECT_FAULT; if( pInfo->nBackfillhdr.mxFrame ){ rc = SQLITE_BUSY; }else if( eMode>=SQLITE_CHECKPOINT_RESTART ){ @@ -65717,6 +66341,7 @@ static int walCheckpoint( } walcheckpoint_out: + SEH_FREE_ON_ERROR(pIter, 0); walIteratorFree(pIter); return rc; } @@ -65739,6 +66364,93 @@ static void walLimitSize(Wal *pWal, i64 nMax){ } } +#ifdef SQLITE_USE_SEH +/* +** This is the "standard" exception handler used in a few places to handle +** an exception thrown by reading from the *-shm mapping after it has become +** invalid in SQLITE_USE_SEH builds. It is used as follows: +** +** SEH_TRY { ... } +** SEH_EXCEPT( rc = walHandleException(pWal); ) +** +** This function does three things: +** +** 1) Determines the locks that should be held, based on the contents of +** the Wal.readLock, Wal.writeLock and Wal.ckptLock variables. All other +** held locks are assumed to be transient locks that would have been +** released had the exception not been thrown and are dropped. +** +** 2) Frees the pointer at Wal.pFree, if any, using sqlite3_free(). +** +** 3) Set pWal->apWiData[pWal->iWiPg] to pWal->pWiValue if not NULL +** +** 4) Returns SQLITE_IOERR. +*/ +static int walHandleException(Wal *pWal){ + if( pWal->exclusiveMode==0 ){ + static const int S = 1; + static const int E = (1<lockMask & ~( + (pWal->readLock<0 ? 0 : (S << WAL_READ_LOCK(pWal->readLock))) + | (pWal->writeLock ? (E << WAL_WRITE_LOCK) : 0) + | (pWal->ckptLock ? (E << WAL_CKPT_LOCK) : 0) + ); + for(ii=0; iipFree); + pWal->pFree = 0; + if( pWal->pWiValue ){ + pWal->apWiData[pWal->iWiPg] = pWal->pWiValue; + pWal->pWiValue = 0; + } + return SQLITE_IOERR_IN_PAGE; +} + +/* +** Assert that the Wal.lockMask mask, which indicates the locks held +** by the connenction, is consistent with the Wal.readLock, Wal.writeLock +** and Wal.ckptLock variables. To be used as: +** +** assert( walAssertLockmask(pWal) ); +*/ +static int walAssertLockmask(Wal *pWal){ + if( pWal->exclusiveMode==0 ){ + static const int S = 1; + static const int E = (1<readLock<0 ? 0 : (S << WAL_READ_LOCK(pWal->readLock))) + | (pWal->writeLock ? (E << WAL_WRITE_LOCK) : 0) + | (pWal->ckptLock ? (E << WAL_CKPT_LOCK) : 0) +#ifdef SQLITE_ENABLE_SNAPSHOT + | (pWal->pSnapshot ? (pWal->lockMask & (1 << WAL_CKPT_LOCK)) : 0) +#endif + ); + assert( mExpect==pWal->lockMask ); + } + return 1; +} + +/* +** Return and zero the "system error" field set when an +** EXCEPTION_IN_PAGE_ERROR exception is caught. +*/ +SQLITE_PRIVATE int sqlite3WalSystemErrno(Wal *pWal){ + int iRet = 0; + if( pWal ){ + iRet = pWal->iSysErrno; + pWal->iSysErrno = 0; + } + return iRet; +} + +#else +# define walAssertLockmask(x) 1 +#endif /* ifdef SQLITE_USE_SEH */ + /* ** Close a connection to a log file. */ @@ -65753,6 +66465,8 @@ SQLITE_PRIVATE int sqlite3WalClose( if( pWal ){ int isDelete = 0; /* True to unlink wal and wal-index files */ + assert( walAssertLockmask(pWal) ); + /* If an EXCLUSIVE lock can be obtained on the database file (using the ** ordinary, rollback-mode locking methods, this guarantees that the ** connection associated with this log file is the only connection to @@ -65777,7 +66491,7 @@ SQLITE_PRIVATE int sqlite3WalClose( ); if( bPersist!=1 ){ /* Try to delete the WAL file if the checkpoint completed and - ** fsyned (rc==SQLITE_OK) and if we are not in persistent-wal + ** fsynced (rc==SQLITE_OK) and if we are not in persistent-wal ** mode (!bPersist) */ isDelete = 1; }else if( pWal->mxWalSize>=0 ){ @@ -65844,7 +66558,7 @@ static SQLITE_NO_TSAN int walIndexTryHdr(Wal *pWal, int *pChanged){ ** give false-positive warnings about these accesses because the tools do not ** account for the double-read and the memory barrier. The use of mutexes ** here would be problematic as the memory being accessed is potentially - ** shared among multiple processes and not all mutex implementions work + ** shared among multiple processes and not all mutex implementations work ** reliably in that environment. */ aHdr = walIndexHdr(pWal); @@ -66295,6 +67009,7 @@ static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int cnt){ assert( pWal->nWiData>0 ); assert( pWal->apWiData[0]!=0 ); pInfo = walCkptInfo(pWal); + SEH_INJECT_FAULT; if( !useWal && AtomicLoad(&pInfo->nBackfill)==pWal->hdr.mxFrame #ifdef SQLITE_ENABLE_SNAPSHOT && (pWal->pSnapshot==0 || pWal->hdr.mxFrame==0) @@ -66344,7 +67059,7 @@ static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int cnt){ } #endif for(i=1; iaReadMark+i); + u32 thisMark = AtomicLoad(pInfo->aReadMark+i); SEH_INJECT_FAULT; if( mxReadMark<=thisMark && thisMark<=mxFrame ){ assert( thisMark!=READMARK_NOT_USED ); mxReadMark = thisMark; @@ -66410,7 +67125,7 @@ static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int cnt){ ** we can guarantee that the checkpointer that set nBackfill could not ** see any pages past pWal->hdr.mxFrame, this problem does not come up. */ - pWal->minFrame = AtomicLoad(&pInfo->nBackfill)+1; + pWal->minFrame = AtomicLoad(&pInfo->nBackfill)+1; SEH_INJECT_FAULT; walShmBarrier(pWal); if( AtomicLoad(pInfo->aReadMark+mxI)!=mxReadMark || memcmp((void *)walIndexHdr(pWal), &pWal->hdr, sizeof(WalIndexHdr)) @@ -66425,6 +67140,54 @@ static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int cnt){ } #ifdef SQLITE_ENABLE_SNAPSHOT +/* +** This function does the work of sqlite3WalSnapshotRecover(). +*/ +static int walSnapshotRecover( + Wal *pWal, /* WAL handle */ + void *pBuf1, /* Temp buffer pWal->szPage bytes in size */ + void *pBuf2 /* Temp buffer pWal->szPage bytes in size */ +){ + int szPage = (int)pWal->szPage; + int rc; + i64 szDb; /* Size of db file in bytes */ + + rc = sqlite3OsFileSize(pWal->pDbFd, &szDb); + if( rc==SQLITE_OK ){ + volatile WalCkptInfo *pInfo = walCkptInfo(pWal); + u32 i = pInfo->nBackfillAttempted; + for(i=pInfo->nBackfillAttempted; i>AtomicLoad(&pInfo->nBackfill); i--){ + WalHashLoc sLoc; /* Hash table location */ + u32 pgno; /* Page number in db file */ + i64 iDbOff; /* Offset of db file entry */ + i64 iWalOff; /* Offset of wal file entry */ + + rc = walHashGet(pWal, walFramePage(i), &sLoc); + if( rc!=SQLITE_OK ) break; + assert( i - sLoc.iZero - 1 >=0 ); + pgno = sLoc.aPgno[i-sLoc.iZero-1]; + iDbOff = (i64)(pgno-1) * szPage; + + if( iDbOff+szPage<=szDb ){ + iWalOff = walFrameOffset(i, szPage) + WAL_FRAME_HDRSIZE; + rc = sqlite3OsRead(pWal->pWalFd, pBuf1, szPage, iWalOff); + + if( rc==SQLITE_OK ){ + rc = sqlite3OsRead(pWal->pDbFd, pBuf2, szPage, iDbOff); + } + + if( rc!=SQLITE_OK || 0==memcmp(pBuf1, pBuf2, szPage) ){ + break; + } + } + + pInfo->nBackfillAttempted = i-1; + } + } + + return rc; +} + /* ** Attempt to reduce the value of the WalCkptInfo.nBackfillAttempted ** variable so that older snapshots can be accessed. To do this, loop @@ -66450,50 +67213,21 @@ SQLITE_PRIVATE int sqlite3WalSnapshotRecover(Wal *pWal){ assert( pWal->readLock>=0 ); rc = walLockExclusive(pWal, WAL_CKPT_LOCK, 1); if( rc==SQLITE_OK ){ - volatile WalCkptInfo *pInfo = walCkptInfo(pWal); - int szPage = (int)pWal->szPage; - i64 szDb; /* Size of db file in bytes */ - - rc = sqlite3OsFileSize(pWal->pDbFd, &szDb); - if( rc==SQLITE_OK ){ - void *pBuf1 = sqlite3_malloc(szPage); - void *pBuf2 = sqlite3_malloc(szPage); - if( pBuf1==0 || pBuf2==0 ){ - rc = SQLITE_NOMEM; - }else{ - u32 i = pInfo->nBackfillAttempted; - for(i=pInfo->nBackfillAttempted; i>AtomicLoad(&pInfo->nBackfill); i--){ - WalHashLoc sLoc; /* Hash table location */ - u32 pgno; /* Page number in db file */ - i64 iDbOff; /* Offset of db file entry */ - i64 iWalOff; /* Offset of wal file entry */ - - rc = walHashGet(pWal, walFramePage(i), &sLoc); - if( rc!=SQLITE_OK ) break; - assert( i - sLoc.iZero - 1 >=0 ); - pgno = sLoc.aPgno[i-sLoc.iZero-1]; - iDbOff = (i64)(pgno-1) * szPage; - - if( iDbOff+szPage<=szDb ){ - iWalOff = walFrameOffset(i, szPage) + WAL_FRAME_HDRSIZE; - rc = sqlite3OsRead(pWal->pWalFd, pBuf1, szPage, iWalOff); - - if( rc==SQLITE_OK ){ - rc = sqlite3OsRead(pWal->pDbFd, pBuf2, szPage, iDbOff); - } - - if( rc!=SQLITE_OK || 0==memcmp(pBuf1, pBuf2, szPage) ){ - break; - } - } - - pInfo->nBackfillAttempted = i-1; - } + void *pBuf1 = sqlite3_malloc(pWal->szPage); + void *pBuf2 = sqlite3_malloc(pWal->szPage); + if( pBuf1==0 || pBuf2==0 ){ + rc = SQLITE_NOMEM; + }else{ + pWal->ckptLock = 1; + SEH_TRY { + rc = walSnapshotRecover(pWal, pBuf1, pBuf2); } - - sqlite3_free(pBuf1); - sqlite3_free(pBuf2); + SEH_EXCEPT( rc = SQLITE_IOERR_IN_PAGE; ) + pWal->ckptLock = 0; } + + sqlite3_free(pBuf1); + sqlite3_free(pBuf2); walUnlockExclusive(pWal, WAL_CKPT_LOCK, 1); } @@ -66502,28 +67236,20 @@ SQLITE_PRIVATE int sqlite3WalSnapshotRecover(Wal *pWal){ #endif /* SQLITE_ENABLE_SNAPSHOT */ /* -** Begin a read transaction on the database. -** -** This routine used to be called sqlite3OpenSnapshot() and with good reason: -** it takes a snapshot of the state of the WAL and wal-index for the current -** instant in time. The current thread will continue to use this snapshot. -** Other threads might append new content to the WAL and wal-index but -** that extra content is ignored by the current thread. -** -** If the database contents have changes since the previous read -** transaction, then *pChanged is set to 1 before returning. The -** Pager layer will use this to know that its cache is stale and -** needs to be flushed. +** This function does the work of sqlite3WalBeginReadTransaction() (see +** below). That function simply calls this one inside an SEH_TRY{...} block. */ -SQLITE_PRIVATE int sqlite3WalBeginReadTransaction(Wal *pWal, int *pChanged){ +static int walBeginReadTransaction(Wal *pWal, int *pChanged){ int rc; /* Return code */ int cnt = 0; /* Number of TryBeginRead attempts */ #ifdef SQLITE_ENABLE_SNAPSHOT + int ckptLock = 0; int bChanged = 0; WalIndexHdr *pSnapshot = pWal->pSnapshot; #endif assert( pWal->ckptLock==0 ); + assert( pWal->nSehTry>0 ); #ifdef SQLITE_ENABLE_SNAPSHOT if( pSnapshot ){ @@ -66546,7 +67272,7 @@ SQLITE_PRIVATE int sqlite3WalBeginReadTransaction(Wal *pWal, int *pChanged){ if( rc!=SQLITE_OK ){ return rc; } - pWal->ckptLock = 1; + ckptLock = 1; } #endif @@ -66610,15 +67336,37 @@ SQLITE_PRIVATE int sqlite3WalBeginReadTransaction(Wal *pWal, int *pChanged){ } /* Release the shared CKPT lock obtained above. */ - if( pWal->ckptLock ){ + if( ckptLock ){ assert( pSnapshot ); walUnlockShared(pWal, WAL_CKPT_LOCK); - pWal->ckptLock = 0; } #endif return rc; } +/* +** Begin a read transaction on the database. +** +** This routine used to be called sqlite3OpenSnapshot() and with good reason: +** it takes a snapshot of the state of the WAL and wal-index for the current +** instant in time. The current thread will continue to use this snapshot. +** Other threads might append new content to the WAL and wal-index but +** that extra content is ignored by the current thread. +** +** If the database contents have changes since the previous read +** transaction, then *pChanged is set to 1 before returning. The +** Pager layer will use this to know that its cache is stale and +** needs to be flushed. +*/ +SQLITE_PRIVATE int sqlite3WalBeginReadTransaction(Wal *pWal, int *pChanged){ + int rc; + SEH_TRY { + rc = walBeginReadTransaction(pWal, pChanged); + } + SEH_EXCEPT( rc = walHandleException(pWal); ) + return rc; +} + /* ** Finish with a read transaction. All this does is release the ** read-lock. @@ -66639,7 +67387,7 @@ SQLITE_PRIVATE void sqlite3WalEndReadTransaction(Wal *pWal){ ** Return SQLITE_OK if successful, or an error code if an error occurs. If an ** error does occur, the final value of *piRead is undefined. */ -SQLITE_PRIVATE int sqlite3WalFindFrame( +static int walFindFrame( Wal *pWal, /* WAL handle */ Pgno pgno, /* Database page number to read data for */ u32 *piRead /* OUT: Frame number (or zero) */ @@ -66702,6 +67450,7 @@ SQLITE_PRIVATE int sqlite3WalFindFrame( } nCollide = HASHTABLE_NSLOT; iKey = walHash(pgno); + SEH_INJECT_FAULT; while( (iH = AtomicLoad(&sLoc.aHash[iKey]))!=0 ){ u32 iFrame = iH + sLoc.iZero; if( iFrame<=iLast && iFrame>=pWal->minFrame && sLoc.aPgno[iH-1]==pgno ){ @@ -66738,6 +67487,30 @@ SQLITE_PRIVATE int sqlite3WalFindFrame( return SQLITE_OK; } +/* +** Search the wal file for page pgno. If found, set *piRead to the frame that +** contains the page. Otherwise, if pgno is not in the wal file, set *piRead +** to zero. +** +** Return SQLITE_OK if successful, or an error code if an error occurs. If an +** error does occur, the final value of *piRead is undefined. +** +** The difference between this function and walFindFrame() is that this +** function wraps walFindFrame() in an SEH_TRY{...} block. +*/ +SQLITE_PRIVATE int sqlite3WalFindFrame( + Wal *pWal, /* WAL handle */ + Pgno pgno, /* Database page number to read data for */ + u32 *piRead /* OUT: Frame number (or zero) */ +){ + int rc; + SEH_TRY { + rc = walFindFrame(pWal, pgno, piRead); + } + SEH_EXCEPT( rc = SQLITE_IOERR_IN_PAGE; ) + return rc; +} + /* ** Read the contents of frame iRead from the wal file into buffer pOut ** (which is nOut bytes in size). Return SQLITE_OK if successful, or an @@ -66819,12 +67592,17 @@ SQLITE_PRIVATE int sqlite3WalBeginWriteTransaction(Wal *pWal){ ** time the read transaction on this connection was started, then ** the write is disallowed. */ - if( memcmp(&pWal->hdr, (void *)walIndexHdr(pWal), sizeof(WalIndexHdr))!=0 ){ + SEH_TRY { + if( memcmp(&pWal->hdr, (void *)walIndexHdr(pWal), sizeof(WalIndexHdr))!=0 ){ + rc = SQLITE_BUSY_SNAPSHOT; + } + } + SEH_EXCEPT( rc = SQLITE_IOERR_IN_PAGE; ) + + if( rc!=SQLITE_OK ){ walUnlockExclusive(pWal, WAL_WRITE_LOCK, 1); pWal->writeLock = 0; - rc = SQLITE_BUSY_SNAPSHOT; } - return rc; } @@ -66860,30 +67638,33 @@ SQLITE_PRIVATE int sqlite3WalUndo(Wal *pWal, int (*xUndo)(void *, Pgno), void *p Pgno iMax = pWal->hdr.mxFrame; Pgno iFrame; - /* Restore the clients cache of the wal-index header to the state it - ** was in before the client began writing to the database. - */ - memcpy(&pWal->hdr, (void *)walIndexHdr(pWal), sizeof(WalIndexHdr)); - - for(iFrame=pWal->hdr.mxFrame+1; - ALWAYS(rc==SQLITE_OK) && iFrame<=iMax; - iFrame++ - ){ - /* This call cannot fail. Unless the page for which the page number - ** is passed as the second argument is (a) in the cache and - ** (b) has an outstanding reference, then xUndo is either a no-op - ** (if (a) is false) or simply expels the page from the cache (if (b) - ** is false). - ** - ** If the upper layer is doing a rollback, it is guaranteed that there - ** are no outstanding references to any page other than page 1. And - ** page 1 is never written to the log until the transaction is - ** committed. As a result, the call to xUndo may not fail. + SEH_TRY { + /* Restore the clients cache of the wal-index header to the state it + ** was in before the client began writing to the database. */ - assert( walFramePgno(pWal, iFrame)!=1 ); - rc = xUndo(pUndoCtx, walFramePgno(pWal, iFrame)); + memcpy(&pWal->hdr, (void *)walIndexHdr(pWal), sizeof(WalIndexHdr)); + + for(iFrame=pWal->hdr.mxFrame+1; + ALWAYS(rc==SQLITE_OK) && iFrame<=iMax; + iFrame++ + ){ + /* This call cannot fail. Unless the page for which the page number + ** is passed as the second argument is (a) in the cache and + ** (b) has an outstanding reference, then xUndo is either a no-op + ** (if (a) is false) or simply expels the page from the cache (if (b) + ** is false). + ** + ** If the upper layer is doing a rollback, it is guaranteed that there + ** are no outstanding references to any page other than page 1. And + ** page 1 is never written to the log until the transaction is + ** committed. As a result, the call to xUndo may not fail. + */ + assert( walFramePgno(pWal, iFrame)!=1 ); + rc = xUndo(pUndoCtx, walFramePgno(pWal, iFrame)); + } + if( iMax!=pWal->hdr.mxFrame ) walCleanupHash(pWal); } - if( iMax!=pWal->hdr.mxFrame ) walCleanupHash(pWal); + SEH_EXCEPT( rc = SQLITE_IOERR_IN_PAGE; ) } return rc; } @@ -66927,7 +67708,10 @@ SQLITE_PRIVATE int sqlite3WalSavepointUndo(Wal *pWal, u32 *aWalData){ pWal->hdr.mxFrame = aWalData[0]; pWal->hdr.aFrameCksum[0] = aWalData[1]; pWal->hdr.aFrameCksum[1] = aWalData[2]; - walCleanupHash(pWal); + SEH_TRY { + walCleanupHash(pWal); + } + SEH_EXCEPT( rc = SQLITE_IOERR_IN_PAGE; ) } return rc; @@ -67108,7 +67892,7 @@ static int walRewriteChecksums(Wal *pWal, u32 iLast){ ** Write a set of frames to the log. The caller must hold the write-lock ** on the log file (obtained using sqlite3WalBeginWriteTransaction()). */ -SQLITE_PRIVATE int sqlite3WalFrames( +static int walFrames( Wal *pWal, /* Wal handle to write to */ int szPage, /* Database page-size in bytes */ PgHdr *pList, /* List of dirty pages to write */ @@ -67219,7 +68003,7 @@ SQLITE_PRIVATE int sqlite3WalFrames( ** checksums must be recomputed when the transaction is committed. */ if( iFirst && (p->pDirty || isCommit==0) ){ u32 iWrite = 0; - VVA_ONLY(rc =) sqlite3WalFindFrame(pWal, p->pgno, &iWrite); + VVA_ONLY(rc =) walFindFrame(pWal, p->pgno, &iWrite); assert( rc==SQLITE_OK || iWrite==0 ); if( iWrite>=iFirst ){ i64 iOff = walFrameOffset(iWrite, szPage) + WAL_FRAME_HDRSIZE; @@ -67338,6 +68122,29 @@ SQLITE_PRIVATE int sqlite3WalFrames( return rc; } +/* +** Write a set of frames to the log. The caller must hold the write-lock +** on the log file (obtained using sqlite3WalBeginWriteTransaction()). +** +** The difference between this function and walFrames() is that this +** function wraps walFrames() in an SEH_TRY{...} block. +*/ +SQLITE_PRIVATE int sqlite3WalFrames( + Wal *pWal, /* Wal handle to write to */ + int szPage, /* Database page-size in bytes */ + PgHdr *pList, /* List of dirty pages to write */ + Pgno nTruncate, /* Database size after this commit */ + int isCommit, /* True if this is a commit */ + int sync_flags /* Flags to pass to OsSync() (or 0) */ +){ + int rc; + SEH_TRY { + rc = walFrames(pWal, szPage, pList, nTruncate, isCommit, sync_flags); + } + SEH_EXCEPT( rc = walHandleException(pWal); ) + return rc; +} + /* ** This routine is called to implement sqlite3_wal_checkpoint() and ** related interfaces. @@ -67417,30 +68224,33 @@ SQLITE_PRIVATE int sqlite3WalCheckpoint( /* Read the wal-index header. */ - if( rc==SQLITE_OK ){ - walDisableBlocking(pWal); - rc = walIndexReadHdr(pWal, &isChanged); - (void)walEnableBlocking(pWal); - if( isChanged && pWal->pDbFd->pMethods->iVersion>=3 ){ - sqlite3OsUnfetch(pWal->pDbFd, 0, 0); - } - } - - /* Copy data from the log to the database file. */ - if( rc==SQLITE_OK ){ - - if( pWal->hdr.mxFrame && walPagesize(pWal)!=nBuf ){ - rc = SQLITE_CORRUPT_BKPT; - }else{ - rc = walCheckpoint(pWal, db, eMode2, xBusy2, pBusyArg, sync_flags, zBuf); - } - - /* If no error occurred, set the output variables. */ - if( rc==SQLITE_OK || rc==SQLITE_BUSY ){ - if( pnLog ) *pnLog = (int)pWal->hdr.mxFrame; - if( pnCkpt ) *pnCkpt = (int)(walCkptInfo(pWal)->nBackfill); + SEH_TRY { + if( rc==SQLITE_OK ){ + walDisableBlocking(pWal); + rc = walIndexReadHdr(pWal, &isChanged); + (void)walEnableBlocking(pWal); + if( isChanged && pWal->pDbFd->pMethods->iVersion>=3 ){ + sqlite3OsUnfetch(pWal->pDbFd, 0, 0); + } + } + + /* Copy data from the log to the database file. */ + if( rc==SQLITE_OK ){ + if( pWal->hdr.mxFrame && walPagesize(pWal)!=nBuf ){ + rc = SQLITE_CORRUPT_BKPT; + }else{ + rc = walCheckpoint(pWal, db, eMode2, xBusy2, pBusyArg, sync_flags,zBuf); + } + + /* If no error occurred, set the output variables. */ + if( rc==SQLITE_OK || rc==SQLITE_BUSY ){ + if( pnLog ) *pnLog = (int)pWal->hdr.mxFrame; + SEH_INJECT_FAULT; + if( pnCkpt ) *pnCkpt = (int)(walCkptInfo(pWal)->nBackfill); + } } } + SEH_EXCEPT( rc = walHandleException(pWal); ) if( isChanged ){ /* If a new wal-index header was loaded before the checkpoint was @@ -67517,7 +68327,9 @@ SQLITE_PRIVATE int sqlite3WalExclusiveMode(Wal *pWal, int op){ ** locks are taken in this case). Nor should the pager attempt to ** upgrade to exclusive-mode following such an error. */ +#ifndef SQLITE_USE_SEH assert( pWal->readLock>=0 || pWal->lockError ); +#endif assert( pWal->readLock>=0 || (op<=0 && pWal->exclusiveMode==0) ); if( op==0 ){ @@ -67618,16 +68430,19 @@ SQLITE_API int sqlite3_snapshot_cmp(sqlite3_snapshot *p1, sqlite3_snapshot *p2){ */ SQLITE_PRIVATE int sqlite3WalSnapshotCheck(Wal *pWal, sqlite3_snapshot *pSnapshot){ int rc; - rc = walLockShared(pWal, WAL_CKPT_LOCK); - if( rc==SQLITE_OK ){ - WalIndexHdr *pNew = (WalIndexHdr*)pSnapshot; - if( memcmp(pNew->aSalt, pWal->hdr.aSalt, sizeof(pWal->hdr.aSalt)) - || pNew->mxFramenBackfillAttempted - ){ - rc = SQLITE_ERROR_SNAPSHOT; - walUnlockShared(pWal, WAL_CKPT_LOCK); + SEH_TRY { + rc = walLockShared(pWal, WAL_CKPT_LOCK); + if( rc==SQLITE_OK ){ + WalIndexHdr *pNew = (WalIndexHdr*)pSnapshot; + if( memcmp(pNew->aSalt, pWal->hdr.aSalt, sizeof(pWal->hdr.aSalt)) + || pNew->mxFramenBackfillAttempted + ){ + rc = SQLITE_ERROR_SNAPSHOT; + walUnlockShared(pWal, WAL_CKPT_LOCK); + } } } + SEH_EXCEPT( rc = walHandleException(pWal); ) return rc; } @@ -67866,7 +68681,7 @@ SQLITE_PRIVATE sqlite3_file *sqlite3WalFile(Wal *pWal){ ** 0x81 0x00 becomes 0x00000080 ** 0x82 0x00 becomes 0x00000100 ** 0x80 0x7f becomes 0x0000007f -** 0x8a 0x91 0xd1 0xac 0x78 becomes 0x12345678 +** 0x81 0x91 0xd1 0xac 0x78 becomes 0x12345678 ** 0x81 0x81 0x81 0x81 0x01 becomes 0x10204081 ** ** Variable length integers are used for rowids and to hold the number of @@ -67949,7 +68764,7 @@ typedef struct CellInfo CellInfo; ** page that has been loaded into memory. The information in this object ** is derived from the raw on-disk page content. ** -** As each database page is loaded into memory, the pager allocats an +** As each database page is loaded into memory, the pager allocates an ** instance of this object and zeros the first 8 bytes. (This is the ** "extra" information associated with each page of the pager.) ** @@ -68405,7 +69220,7 @@ struct IntegrityCk { /* ** get2byteAligned(), unlike get2byte(), requires that its argument point to a -** two-byte aligned address. get2bytea() is only used for accessing the +** two-byte aligned address. get2byteAligned() is only used for accessing the ** cell addresses in a btree header. */ #if SQLITE_BYTEORDER==4321 @@ -68582,7 +69397,7 @@ SQLITE_PRIVATE int sqlite3BtreeHoldsMutex(Btree *p){ ** ** There is a corresponding leave-all procedures. ** -** Enter the mutexes in accending order by BtShared pointer address +** Enter the mutexes in ascending order by BtShared pointer address ** to avoid the possibility of deadlock when two threads with ** two or more btrees in common both try to lock all their btrees ** at the same instant. @@ -68714,6 +69529,7 @@ SQLITE_PRIVATE void sqlite3BtreeLeaveCursor(BtCursor *pCur){ /************** End of btmutex.c *********************************************/ /************** Begin file btree.c *******************************************/ + /* ** 2004 April 6 ** @@ -70249,7 +71065,7 @@ static void ptrmapPutOvflPtr(MemPage *pPage, MemPage *pSrc, u8 *pCell,int *pRC){ pPage->xParseCell(pPage, pCell, &info); if( info.nLocalaDataEnd, pCell, pCell+info.nLocal) ){ + if( SQLITE_OVERFLOW(pSrc->aDataEnd, pCell, pCell+info.nLocal) ){ testcase( pSrc!=pPage ); *pRC = SQLITE_CORRUPT_BKPT; return; @@ -70350,7 +71166,7 @@ static int defragmentPage(MemPage *pPage, int nMaxFrag){ iCellStart = get2byte(&data[hdr+5]); if( nCell>0 ){ temp = sqlite3PagerTempSpace(pPage->pBt->pPager); - memcpy(&temp[iCellStart], &data[iCellStart], usableSize - iCellStart); + memcpy(temp, data, usableSize); src = temp; for(i=0; iiPage. -** -** The page is fetched as read-write unless pCur is not NULL and is -** a read-only cursor. -** -** If an error occurs, then *ppPage is undefined. It -** may remain unchanged, or it may be set to an invalid value. */ static int getAndInitPage( BtShared *pBt, /* The database file */ Pgno pgno, /* Number of the page to get */ MemPage **ppPage, /* Write the page pointer here */ - BtCursor *pCur, /* Cursor to receive the page, or NULL */ int bReadOnly /* True for a read-only page */ ){ int rc; DbPage *pDbPage; + MemPage *pPage; assert( sqlite3_mutex_held(pBt->mutex) ); - assert( pCur==0 || ppPage==&pCur->pPage ); - assert( pCur==0 || bReadOnly==pCur->curPagerFlags ); - assert( pCur==0 || pCur->iPage>0 ); if( pgno>btreePagecount(pBt) ){ - rc = SQLITE_CORRUPT_BKPT; - goto getAndInitPage_error1; + *ppPage = 0; + return SQLITE_CORRUPT_BKPT; } rc = sqlite3PagerGet(pBt->pPager, pgno, (DbPage**)&pDbPage, bReadOnly); if( rc ){ - goto getAndInitPage_error1; + *ppPage = 0; + return rc; } - *ppPage = (MemPage*)sqlite3PagerGetExtra(pDbPage); - if( (*ppPage)->isInit==0 ){ + pPage = (MemPage*)sqlite3PagerGetExtra(pDbPage); + if( pPage->isInit==0 ){ btreePageFromDbPage(pDbPage, pgno, pBt); - rc = btreeInitPage(*ppPage); + rc = btreeInitPage(pPage); if( rc!=SQLITE_OK ){ - goto getAndInitPage_error2; + releasePage(pPage); + *ppPage = 0; + return rc; } } - assert( (*ppPage)->pgno==pgno || CORRUPT_DB ); - assert( (*ppPage)->aData==sqlite3PagerGetData(pDbPage) ); - - /* If obtaining a child page for a cursor, we must verify that the page is - ** compatible with the root page. */ - if( pCur && ((*ppPage)->nCell<1 || (*ppPage)->intKey!=pCur->curIntKey) ){ - rc = SQLITE_CORRUPT_PGNO(pgno); - goto getAndInitPage_error2; - } + assert( pPage->pgno==pgno || CORRUPT_DB ); + assert( pPage->aData==sqlite3PagerGetData(pDbPage) ); + *ppPage = pPage; return SQLITE_OK; - -getAndInitPage_error2: - releasePage(*ppPage); -getAndInitPage_error1: - if( pCur ){ - pCur->iPage--; - pCur->pPage = pCur->apPage[pCur->iPage]; - } - testcase( pgno==0 ); - assert( pgno!=0 || rc!=SQLITE_OK ); - return rc; } /* @@ -71177,7 +71966,7 @@ static void pageReinit(DbPage *pData){ ** call to btreeInitPage() will likely return SQLITE_CORRUPT. ** But no harm is done by this. And it is very important that ** btreeInitPage() be called on every btree page so we make - ** the call for every page that comes in for re-initing. */ + ** the call for every page that comes in for re-initializing. */ btreeInitPage(pPage); } } @@ -71356,6 +72145,9 @@ SQLITE_PRIVATE int sqlite3BtreeOpen( assert( sizeof(u16)==2 ); assert( sizeof(Pgno)==4 ); + /* Suppress false-positive compiler warning from PVS-Studio */ + memset(&zDbHeader[16], 0, 8); + pBt = sqlite3MallocZero( sizeof(*pBt) ); if( pBt==0 ){ rc = SQLITE_NOMEM_BKPT; @@ -71572,7 +72364,7 @@ static SQLITE_NOINLINE int allocateTempSpace(BtShared *pBt){ ** can mean that fillInCell() only initializes the first 2 or 3 ** bytes of pTmpSpace, but that the first 4 bytes are copied from ** it into a database page. This is not actually a problem, but it - ** does cause a valgrind error when the 1 or 2 bytes of unitialized + ** does cause a valgrind error when the 1 or 2 bytes of uninitialized ** data is passed to system call write(). So to avoid this error, ** zero the first 4 bytes of temp space here. ** @@ -71807,7 +72599,7 @@ SQLITE_PRIVATE int sqlite3BtreeGetReserveNoMutex(Btree *p){ /* ** Return the number of bytes of space at the end of every page that -** are intentually left unused. This is the "reserved" space that is +** are intentionally left unused. This is the "reserved" space that is ** sometimes used by extensions. ** ** The value returned is the larger of the current reserve size and @@ -72054,7 +72846,6 @@ static int lockBtree(BtShared *pBt){ ){ goto page1_init_failed; } - pBt->btsFlags |= BTS_PAGESIZE_FIXED; assert( (pageSize & 7)==0 ); /* EVIDENCE-OF: R-59310-51205 The "reserved space" size in the 1-byte ** integer at offset 20 is the number of bytes of space at the end of @@ -72074,6 +72865,7 @@ static int lockBtree(BtShared *pBt){ releasePageOne(pPage1); pBt->usableSize = usableSize; pBt->pageSize = pageSize; + pBt->btsFlags |= BTS_PAGESIZE_FIXED; freeTempSpace(pBt); rc = sqlite3PagerSetPagesize(pBt->pPager, &pBt->pageSize, pageSize-usableSize); @@ -72093,6 +72885,7 @@ static int lockBtree(BtShared *pBt){ if( usableSize<480 ){ goto page1_init_failed; } + pBt->btsFlags |= BTS_PAGESIZE_FIXED; pBt->pageSize = pageSize; pBt->usableSize = usableSize; #ifndef SQLITE_OMIT_AUTOVACUUM @@ -72271,7 +73064,11 @@ SQLITE_PRIVATE int sqlite3BtreeNewDb(Btree *p){ ** when A already has a read lock, we encourage A to give up and let B ** proceed. */ -SQLITE_PRIVATE int sqlite3BtreeBeginTrans(Btree *p, int wrflag, int *pSchemaVersion){ +static SQLITE_NOINLINE int btreeBeginTrans( + Btree *p, /* The btree in which to start the transaction */ + int wrflag, /* True to start a write transaction */ + int *pSchemaVersion /* Put schema version number here, if not NULL */ +){ BtShared *pBt = p->pBt; Pager *pPager = pBt->pPager; int rc = SQLITE_OK; @@ -72443,6 +73240,28 @@ trans_begun: sqlite3BtreeLeave(p); return rc; } +SQLITE_PRIVATE int sqlite3BtreeBeginTrans(Btree *p, int wrflag, int *pSchemaVersion){ + BtShared *pBt; + if( p->sharable + || p->inTrans==TRANS_NONE + || (p->inTrans==TRANS_READ && wrflag!=0) + ){ + return btreeBeginTrans(p,wrflag,pSchemaVersion); + } + pBt = p->pBt; + if( pSchemaVersion ){ + *pSchemaVersion = get4byte(&pBt->pPage1->aData[40]); + } + if( wrflag ){ + /* This call makes sure that the pager has the correct number of + ** open savepoints. If the second parameter is greater than 0 and + ** the sub-journal is not already open, then it will be opened here. + */ + return sqlite3PagerOpenSavepoint(pBt->pPager, p->db->nSavepoint); + }else{ + return SQLITE_OK; + } +} #ifndef SQLITE_OMIT_AUTOVACUUM @@ -73538,7 +74357,6 @@ SQLITE_PRIVATE void sqlite3BtreeCursorUnpin(BtCursor *pCur){ pCur->curFlags &= ~BTCF_Pinned; } -#ifdef SQLITE_ENABLE_OFFSET_SQL_FUNC /* ** Return the offset into the database file for the start of the ** payload to which the cursor is pointing. @@ -73550,7 +74368,6 @@ SQLITE_PRIVATE i64 sqlite3BtreeOffset(BtCursor *pCur){ return (i64)pCur->pBt->pageSize*((i64)pCur->pPage->pgno - 1) + (i64)(pCur->info.pPayload - pCur->pPage->aData); } -#endif /* SQLITE_ENABLE_OFFSET_SQL_FUNC */ /* ** Return the number of bytes of payload for the entry that pCur is @@ -73576,7 +74393,7 @@ SQLITE_PRIVATE u32 sqlite3BtreePayloadSize(BtCursor *pCur){ ** routine always returns 2147483647 (which is the largest record ** that SQLite can handle) or more. But returning a smaller value might ** prevent large memory allocations when trying to interpret a -** corrupt datrabase. +** corrupt database. ** ** The current implementation merely returns the size of the underlying ** database file. @@ -74038,6 +74855,7 @@ SQLITE_PRIVATE const void *sqlite3BtreePayloadFetch(BtCursor *pCur, u32 *pAmt){ ** vice-versa). */ static int moveToChild(BtCursor *pCur, u32 newPgno){ + int rc; assert( cursorOwnsBtShared(pCur) ); assert( pCur->eState==CURSOR_VALID ); assert( pCur->iPageapPage[pCur->iPage] = pCur->pPage; pCur->ix = 0; pCur->iPage++; - return getAndInitPage(pCur->pBt, newPgno, &pCur->pPage, pCur, - pCur->curPagerFlags); + rc = getAndInitPage(pCur->pBt, newPgno, &pCur->pPage, pCur->curPagerFlags); + assert( pCur->pPage!=0 || rc!=SQLITE_OK ); + if( rc==SQLITE_OK + && (pCur->pPage->nCell<1 || pCur->pPage->intKey!=pCur->curIntKey) + ){ + releasePage(pCur->pPage); + rc = SQLITE_CORRUPT_PGNO(newPgno); + } + if( rc ){ + pCur->pPage = pCur->apPage[--pCur->iPage]; + } + return rc; } #ifdef SQLITE_DEBUG @@ -74159,7 +74987,7 @@ static int moveToRoot(BtCursor *pCur){ sqlite3BtreeClearCursor(pCur); } rc = getAndInitPage(pCur->pBt, pCur->pgnoRoot, &pCur->pPage, - 0, pCur->curPagerFlags); + pCur->curPagerFlags); if( rc!=SQLITE_OK ){ pCur->eState = CURSOR_INVALID; return rc; @@ -74271,7 +75099,7 @@ SQLITE_PRIVATE int sqlite3BtreeFirst(BtCursor *pCur, int *pRes){ *pRes = 0; rc = moveToLeftmost(pCur); }else if( rc==SQLITE_EMPTY ){ - assert( pCur->pgnoRoot==0 || pCur->pPage->nCell==0 ); + assert( pCur->pgnoRoot==0 || (pCur->pPage!=0 && pCur->pPage->nCell==0) ); *pRes = 1; rc = SQLITE_OK; } @@ -74376,7 +75204,7 @@ SQLITE_PRIVATE int sqlite3BtreeTableMoveto( /* If the requested key is one more than the previous key, then ** try to get there using sqlite3BtreeNext() rather than a full ** binary search. This is an optimization only. The correct answer - ** is still obtained without this case, only a little more slowely */ + ** is still obtained without this case, only a little more slowly. */ if( pCur->info.nKey+1==intKey ){ *pRes = 0; rc = sqlite3BtreeNext(pCur, 0); @@ -74772,10 +75600,36 @@ bypass_moveto_root: }else{ chldPg = get4byte(findCell(pPage, lwr)); } - pCur->ix = (u16)lwr; - rc = moveToChild(pCur, chldPg); - if( rc ) break; - } + + /* This block is similar to an in-lined version of: + ** + ** pCur->ix = (u16)lwr; + ** rc = moveToChild(pCur, chldPg); + ** if( rc ) break; + */ + pCur->info.nSize = 0; + pCur->curFlags &= ~(BTCF_ValidNKey|BTCF_ValidOvfl); + if( pCur->iPage>=(BTCURSOR_MAX_DEPTH-1) ){ + return SQLITE_CORRUPT_BKPT; + } + pCur->aiIdx[pCur->iPage] = (u16)lwr; + pCur->apPage[pCur->iPage] = pCur->pPage; + pCur->ix = 0; + pCur->iPage++; + rc = getAndInitPage(pCur->pBt, chldPg, &pCur->pPage, pCur->curPagerFlags); + if( rc==SQLITE_OK + && (pCur->pPage->nCell<1 || pCur->pPage->intKey!=pCur->curIntKey) + ){ + releasePage(pCur->pPage); + rc = SQLITE_CORRUPT_PGNO(chldPg); + } + if( rc ){ + pCur->pPage = pCur->apPage[--pCur->iPage]; + break; + } + /* + ***** End of in-lined moveToChild() call */ + } moveto_index_finish: pCur->info.nSize = 0; assert( (pCur->curFlags & BTCF_ValidOvfl)==0 ); @@ -75559,7 +76413,7 @@ static SQLITE_NOINLINE int clearCellOverflow( /* Call xParseCell to compute the size of a cell. If the cell contains ** overflow, then invoke cellClearOverflow to clear out that overflow. -** STore the result code (SQLITE_OK or some error code) in rc. +** Store the result code (SQLITE_OK or some error code) in rc. ** ** Implemented as macro to force inlining for performance. */ @@ -76175,7 +77029,7 @@ static int rebuildPage( if( NEVER(j>(u32)usableSize) ){ j = 0; } memcpy(&pTmp[j], &aData[j], usableSize - j); - for(k=0; pCArray->ixNx[k]<=i && ALWAYS(kixNx[k]<=i; k++){} pSrcEnd = pCArray->apEnd[k]; pData = pEnd; @@ -76238,7 +77092,7 @@ static int rebuildPage( ** Finally, argument pBegin points to the byte immediately following the ** end of the space required by this page for the cell-pointer area (for ** all cells - not just those inserted by the current call). If the content -** area must be extended to before this point in order to accomodate all +** area must be extended to before this point in order to accommodate all ** cells in apCell[], then the cells do not fit and non-zero is returned. */ static int pageInsertArray( @@ -76258,7 +77112,7 @@ static int pageInsertArray( u8 *pEnd; /* Maximum extent of cell data */ assert( CORRUPT_DB || pPg->hdrOffset==0 ); /* Never called on page 1 */ if( iEnd<=iFirst ) return 0; - for(k=0; pCArray->ixNx[k]<=i && ALWAYS(kixNx[k]<=i ; k++){} pEnd = pCArray->apEnd[k]; while( 1 /*Exit by break*/ ){ int sz, rc; @@ -76553,7 +77407,7 @@ static int balance_quick(MemPage *pParent, MemPage *pPage, u8 *pSpace){ ** with entries for the new page, and any pointer from the ** cell on the page to an overflow page. If either of these ** operations fails, the return code is set, but the contents - ** of the parent page are still manipulated by thh code below. + ** of the parent page are still manipulated by the code below. ** That is Ok, at this point the parent page is guaranteed to ** be marked as dirty. Returning an error code will cause a ** rollback, undoing any changes made to the parent page. @@ -76829,7 +77683,7 @@ static int balance_nonroot( pgno = get4byte(pRight); while( 1 ){ if( rc==SQLITE_OK ){ - rc = getAndInitPage(pBt, pgno, &apOld[i], 0, 0); + rc = getAndInitPage(pBt, pgno, &apOld[i], 0); } if( rc ){ memset(apOld, 0, (i+1)*sizeof(MemPage*)); @@ -77143,7 +77997,7 @@ static int balance_nonroot( } } - /* Sanity check: For a non-corrupt database file one of the follwing + /* Sanity check: For a non-corrupt database file one of the following ** must be true: ** (1) We found one or more cells (cntNew[0])>0), or ** (2) pPage is a virtual root page. A virtual root page is when @@ -77368,9 +78222,9 @@ static int balance_nonroot( iOvflSpace += sz; assert( sz<=pBt->maxLocal+23 ); assert( iOvflSpace <= (int)pBt->pageSize ); - for(k=0; b.ixNx[k]<=j && ALWAYS(k=0 && iPg=1 || i>=0 ); + assert( iPg=0 /* On the upwards pass, or... */ || cntOld[iPg-1]>=cntNew[iPg-1] /* Condition (1) is true */ @@ -77760,7 +78616,7 @@ static int btreeOverwriteContent( ){ int nData = pX->nData - iOffset; if( nData<=0 ){ - /* Overwritting with zeros */ + /* Overwriting with zeros */ int i; for(i=0; ipData to write */ @@ -78543,7 +79399,7 @@ static int btreeCreateTable(Btree *p, Pgno *piTable, int createTabFlags){ MemPage *pRoot; Pgno pgnoRoot; int rc; - int ptfFlags; /* Page-type flage for the root page of new table */ + int ptfFlags; /* Page-type flags for the root page of new table */ assert( sqlite3BtreeHoldsMutex(p) ); assert( pBt->inTransaction==TRANS_WRITE ); @@ -78712,7 +79568,7 @@ static int clearDatabasePage( if( pgno>btreePagecount(pBt) ){ return SQLITE_CORRUPT_BKPT; } - rc = getAndInitPage(pBt, pgno, &pPage, 0, 0); + rc = getAndInitPage(pBt, pgno, &pPage, 0); if( rc ) return rc; if( (pBt->openFlags & BTREE_SINGLE)==0 && sqlite3PagerPageRefcount(pPage->pDbPage) != (1 + (pgno==1)) @@ -79378,7 +80234,7 @@ static int checkTreePage( if( iPage==0 ) return 0; if( checkRef(pCheck, iPage) ) return 0; pCheck->zPfx = "Tree %u page %u: "; - pCheck->v0 = pCheck->v1 = iPage; + pCheck->v1 = iPage; if( (rc = btreeGetPage(pBt, iPage, &pPage, 0))!=0 ){ checkAppendMsg(pCheck, "unable to get the page. error code=%d", rc); @@ -79715,6 +80571,7 @@ SQLITE_PRIVATE int sqlite3BtreeIntegrityCheck( checkPtrmap(&sCheck, aRoot[i], PTRMAP_ROOTPAGE, 0); } #endif + sCheck.v0 = aRoot[i]; checkTreePage(&sCheck, aRoot[i], ¬Used, LARGEST_INT64); } pBt->db->flags = savedDbFlags; @@ -81141,6 +81998,40 @@ SQLITE_PRIVATE int sqlite3VdbeMemClearAndResize(Mem *pMem, int szNew){ return SQLITE_OK; } +/* +** If pMem is already a string, detect if it is a zero-terminated +** string, or make it into one if possible, and mark it as such. +** +** This is an optimization. Correct operation continues even if +** this routine is a no-op. +*/ +SQLITE_PRIVATE void sqlite3VdbeMemZeroTerminateIfAble(Mem *pMem){ + if( (pMem->flags & (MEM_Str|MEM_Term|MEM_Ephem|MEM_Static))!=MEM_Str ){ + /* pMem must be a string, and it cannot be an ephemeral or static string */ + return; + } + if( pMem->enc!=SQLITE_UTF8 ) return; + if( NEVER(pMem->z==0) ) return; + if( pMem->flags & MEM_Dyn ){ + if( pMem->xDel==sqlite3_free + && sqlite3_msize(pMem->z) >= (u64)(pMem->n+1) + ){ + pMem->z[pMem->n] = 0; + pMem->flags |= MEM_Term; + return; + } + if( pMem->xDel==(void(*)(void*))sqlite3RCStrUnref ){ + /* Blindly assume that all RCStr objects are zero-terminated */ + pMem->flags |= MEM_Term; + return; + } + }else if( pMem->szMalloc >= pMem->n+1 ){ + pMem->z[pMem->n] = 0; + pMem->flags |= MEM_Term; + return; + } +} + /* ** It is already known that pMem contains an unterminated string. ** Add the zero terminator. @@ -81402,36 +82293,6 @@ SQLITE_PRIVATE void sqlite3VdbeMemReleaseMalloc(Mem *p){ if( p->szMalloc ) vdbeMemClear(p); } -/* -** Convert a 64-bit IEEE double into a 64-bit signed integer. -** If the double is out of range of a 64-bit signed integer then -** return the closest available 64-bit signed integer. -*/ -static SQLITE_NOINLINE i64 doubleToInt64(double r){ -#ifdef SQLITE_OMIT_FLOATING_POINT - /* When floating-point is omitted, double and int64 are the same thing */ - return r; -#else - /* - ** Many compilers we encounter do not define constants for the - ** minimum and maximum 64-bit integers, or they define them - ** inconsistently. And many do not understand the "LL" notation. - ** So we define our own static constants here using nothing - ** larger than a 32-bit integer constant. - */ - static const i64 maxInt = LARGEST_INT64; - static const i64 minInt = SMALLEST_INT64; - - if( r<=(double)minInt ){ - return minInt; - }else if( r>=(double)maxInt ){ - return maxInt; - }else{ - return (i64)r; - } -#endif -} - /* ** Return some kind of integer value which is the best we can do ** at representing the value that *pMem describes as an integer. @@ -81458,7 +82319,7 @@ SQLITE_PRIVATE i64 sqlite3VdbeIntValue(const Mem *pMem){ testcase( flags & MEM_IntReal ); return pMem->u.i; }else if( flags & MEM_Real ){ - return doubleToInt64(pMem->u.r); + return sqlite3RealToI64(pMem->u.r); }else if( (flags & (MEM_Str|MEM_Blob))!=0 && pMem->z!=0 ){ return memIntValue(pMem); }else{ @@ -81520,7 +82381,7 @@ SQLITE_PRIVATE void sqlite3VdbeIntegerAffinity(Mem *pMem){ if( pMem->flags & MEM_IntReal ){ MemSetTypeFlag(pMem, MEM_Int); }else{ - i64 ix = doubleToInt64(pMem->u.r); + i64 ix = sqlite3RealToI64(pMem->u.r); /* Only mark the value as an integer if ** @@ -81588,8 +82449,8 @@ SQLITE_PRIVATE int sqlite3RealSameAsInt(double r1, sqlite3_int64 i){ ** from UBSAN. */ SQLITE_PRIVATE i64 sqlite3RealToI64(double r){ - if( r<=(double)SMALLEST_INT64 ) return SMALLEST_INT64; - if( r>=(double)LARGEST_INT64) return LARGEST_INT64; + if( r<-9223372036854774784.0 ) return SMALLEST_INT64; + if( r>+9223372036854774784.0 ) return LARGEST_INT64; return (i64)r; } @@ -81660,6 +82521,7 @@ SQLITE_PRIVATE int sqlite3VdbeMemCast(Mem *pMem, u8 aff, u8 encoding){ break; } default: { + int rc; assert( aff==SQLITE_AFF_TEXT ); assert( MEM_Str==(MEM_Blob>>3) ); pMem->flags |= (pMem->flags&MEM_Blob)>>3; @@ -81667,7 +82529,9 @@ SQLITE_PRIVATE int sqlite3VdbeMemCast(Mem *pMem, u8 aff, u8 encoding){ assert( pMem->flags & MEM_Str || pMem->db->mallocFailed ); pMem->flags &= ~(MEM_Int|MEM_Real|MEM_IntReal|MEM_Blob|MEM_Zero); if( encoding!=SQLITE_UTF8 ) pMem->n &= ~1; - return sqlite3VdbeChangeEncoding(pMem, encoding); + rc = sqlite3VdbeChangeEncoding(pMem, encoding); + if( rc ) return rc; + sqlite3VdbeMemZeroTerminateIfAble(pMem); } } return SQLITE_OK; @@ -82191,6 +83055,24 @@ SQLITE_PRIVATE const void *sqlite3ValueText(sqlite3_value* pVal, u8 enc){ return valueToText(pVal, enc); } +/* Return true if sqlit3_value object pVal is a string or blob value +** that uses the destructor specified in the second argument. +** +** TODO: Maybe someday promote this interface into a published API so +** that third-party extensions can get access to it? +*/ +SQLITE_PRIVATE int sqlite3ValueIsOfClass(const sqlite3_value *pVal, void(*xFree)(void*)){ + if( ALWAYS(pVal!=0) + && ALWAYS((pVal->flags & (MEM_Str|MEM_Blob))!=0) + && (pVal->flags & MEM_Dyn)!=0 + && pVal->xDel==xFree + ){ + return 1; + }else{ + return 0; + } +} + /* ** Create a new sqlite3_value object. */ @@ -82258,6 +83140,7 @@ static sqlite3_value *valueNew(sqlite3 *db, struct ValueNewStat4Ctx *p){ } pRec->nField = p->iVal+1; + sqlite3VdbeMemSetNull(&pRec->aMem[p->iVal]); return &pRec->aMem[p->iVal]; } #else @@ -83046,6 +83929,35 @@ static void test_addop_breakpoint(int pc, Op *pOp){ } #endif +/* +** Slow paths for sqlite3VdbeAddOp3() and sqlite3VdbeAddOp4Int() for the +** unusual case when we need to increase the size of the Vdbe.aOp[] array +** before adding the new opcode. +*/ +static SQLITE_NOINLINE int growOp3(Vdbe *p, int op, int p1, int p2, int p3){ + assert( p->nOpAlloc<=p->nOp ); + if( growOpArray(p, 1) ) return 1; + assert( p->nOpAlloc>p->nOp ); + return sqlite3VdbeAddOp3(p, op, p1, p2, p3); +} +static SQLITE_NOINLINE int addOp4IntSlow( + Vdbe *p, /* Add the opcode to this VM */ + int op, /* The new opcode */ + int p1, /* The P1 operand */ + int p2, /* The P2 operand */ + int p3, /* The P3 operand */ + int p4 /* The P4 operand as an integer */ +){ + int addr = sqlite3VdbeAddOp3(p, op, p1, p2, p3); + if( p->db->mallocFailed==0 ){ + VdbeOp *pOp = &p->aOp[addr]; + pOp->p4type = P4_INT32; + pOp->p4.i = p4; + } + return addr; +} + + /* ** Add a new instruction to the list of instructions current in the ** VDBE. Return the address of the new instruction. @@ -83056,17 +83968,16 @@ static void test_addop_breakpoint(int pc, Op *pOp){ ** ** op The opcode for this instruction ** -** p1, p2, p3 Operands -** -** Use the sqlite3VdbeResolveLabel() function to fix an address and -** the sqlite3VdbeChangeP4() function to change the value of the P4 -** operand. +** p1, p2, p3, p4 Operands */ -static SQLITE_NOINLINE int growOp3(Vdbe *p, int op, int p1, int p2, int p3){ - assert( p->nOpAlloc<=p->nOp ); - if( growOpArray(p, 1) ) return 1; - assert( p->nOpAlloc>p->nOp ); - return sqlite3VdbeAddOp3(p, op, p1, p2, p3); +SQLITE_PRIVATE int sqlite3VdbeAddOp0(Vdbe *p, int op){ + return sqlite3VdbeAddOp3(p, op, 0, 0, 0); +} +SQLITE_PRIVATE int sqlite3VdbeAddOp1(Vdbe *p, int op, int p1){ + return sqlite3VdbeAddOp3(p, op, p1, 0, 0); +} +SQLITE_PRIVATE int sqlite3VdbeAddOp2(Vdbe *p, int op, int p1, int p2){ + return sqlite3VdbeAddOp3(p, op, p1, p2, 0); } SQLITE_PRIVATE int sqlite3VdbeAddOp3(Vdbe *p, int op, int p1, int p2, int p3){ int i; @@ -83089,6 +84000,9 @@ SQLITE_PRIVATE int sqlite3VdbeAddOp3(Vdbe *p, int op, int p1, int p2, int p3){ pOp->p3 = p3; pOp->p4.p = 0; pOp->p4type = P4_NOTUSED; + + /* Replicate this logic in sqlite3VdbeAddOp4Int() + ** vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv */ #ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS pOp->zComment = 0; #endif @@ -83105,16 +84019,59 @@ SQLITE_PRIVATE int sqlite3VdbeAddOp3(Vdbe *p, int op, int p1, int p2, int p3){ #ifdef SQLITE_VDBE_COVERAGE pOp->iSrcLine = 0; #endif + /* ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ** Replicate in sqlite3VdbeAddOp4Int() */ + return i; } -SQLITE_PRIVATE int sqlite3VdbeAddOp0(Vdbe *p, int op){ - return sqlite3VdbeAddOp3(p, op, 0, 0, 0); -} -SQLITE_PRIVATE int sqlite3VdbeAddOp1(Vdbe *p, int op, int p1){ - return sqlite3VdbeAddOp3(p, op, p1, 0, 0); -} -SQLITE_PRIVATE int sqlite3VdbeAddOp2(Vdbe *p, int op, int p1, int p2){ - return sqlite3VdbeAddOp3(p, op, p1, p2, 0); +SQLITE_PRIVATE int sqlite3VdbeAddOp4Int( + Vdbe *p, /* Add the opcode to this VM */ + int op, /* The new opcode */ + int p1, /* The P1 operand */ + int p2, /* The P2 operand */ + int p3, /* The P3 operand */ + int p4 /* The P4 operand as an integer */ +){ + int i; + VdbeOp *pOp; + + i = p->nOp; + if( p->nOpAlloc<=i ){ + return addOp4IntSlow(p, op, p1, p2, p3, p4); + } + p->nOp++; + pOp = &p->aOp[i]; + assert( pOp!=0 ); + pOp->opcode = (u8)op; + pOp->p5 = 0; + pOp->p1 = p1; + pOp->p2 = p2; + pOp->p3 = p3; + pOp->p4.i = p4; + pOp->p4type = P4_INT32; + + /* Replicate this logic in sqlite3VdbeAddOp3() + ** vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv */ +#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS + pOp->zComment = 0; +#endif +#if defined(SQLITE_ENABLE_STMT_SCANSTATUS) || defined(VDBE_PROFILE) + pOp->nExec = 0; + pOp->nCycle = 0; +#endif +#ifdef SQLITE_DEBUG + if( p->db->flags & SQLITE_VdbeAddopTrace ){ + sqlite3VdbePrintOp(0, i, &p->aOp[i]); + test_addop_breakpoint(i, &p->aOp[i]); + } +#endif +#ifdef SQLITE_VDBE_COVERAGE + pOp->iSrcLine = 0; +#endif + /* ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ** Replicate in sqlite3VdbeAddOp3() */ + + return i; } /* Generate code for an unconditional jump to instruction iDest @@ -83292,7 +84249,7 @@ SQLITE_PRIVATE int sqlite3VdbeExplain(Parse *pParse, u8 bPush, const char *zFmt, if( bPush){ pParse->addrExplain = iThis; } - sqlite3VdbeScanStatus(v, iThis, 0, 0, 0, 0); + sqlite3VdbeScanStatus(v, iThis, -1, -1, 0, 0); } return addr; } @@ -83322,26 +84279,6 @@ SQLITE_PRIVATE void sqlite3VdbeAddParseSchemaOp(Vdbe *p, int iDb, char *zWhere, sqlite3MayAbort(p->pParse); } -/* -** Add an opcode that includes the p4 value as an integer. -*/ -SQLITE_PRIVATE int sqlite3VdbeAddOp4Int( - Vdbe *p, /* Add the opcode to this VM */ - int op, /* The new opcode */ - int p1, /* The P1 operand */ - int p2, /* The P2 operand */ - int p3, /* The P3 operand */ - int p4 /* The P4 operand as an integer */ -){ - int addr = sqlite3VdbeAddOp3(p, op, p1, p2, p3); - if( p->db->mallocFailed==0 ){ - VdbeOp *pOp = &p->aOp[addr]; - pOp->p4type = P4_INT32; - pOp->p4.i = p4; - } - return addr; -} - /* Insert the end of a co-routine */ SQLITE_PRIVATE void sqlite3VdbeEndCoroutine(Vdbe *v, int regYield){ @@ -83654,7 +84591,7 @@ static void resolveP2Values(Vdbe *p, int *pMaxFuncArgs){ p->bIsReader = 0; pOp = &p->aOp[p->nOp-1]; assert( p->aOp[0].opcode==OP_Init ); - while( 1 /* Loop termates when it reaches the OP_Init opcode */ ){ + while( 1 /* Loop terminates when it reaches the OP_Init opcode */ ){ /* Only JUMP opcodes and the short list of special opcodes in the switch ** below need to be considered. The mkopcodeh.tcl generator script groups ** all these opcodes together near the front of the opcode list. Skip @@ -84024,8 +84961,8 @@ SQLITE_PRIVATE void sqlite3VdbeScanStatusCounters( pScan = 0; } if( pScan ){ - pScan->addrLoop = addrLoop; - pScan->addrVisit = addrVisit; + if( addrLoop>0 ) pScan->addrLoop = addrLoop; + if( addrVisit>0 ) pScan->addrVisit = addrVisit; } } } @@ -84108,7 +85045,7 @@ SQLITE_PRIVATE void sqlite3VdbeJumpHereOrPopInst(Vdbe *p, int addr){ /* ** If the input FuncDef structure is ephemeral, then free it. If -** the FuncDef is not ephermal, then do nothing. +** the FuncDef is not ephemeral, then do nothing. */ static void freeEphemeralFunction(sqlite3 *db, FuncDef *pDef){ assert( db!=0 ); @@ -84272,7 +85209,6 @@ SQLITE_PRIVATE void sqlite3VdbeReleaseRegisters( } #endif /* SQLITE_DEBUG */ - /* ** Change the value of the P4 operand for a specific instruction. ** This routine is useful when a large program is loaded from a @@ -85193,7 +86129,7 @@ SQLITE_PRIVATE int sqlite3VdbeList( sqlite3VdbeMemSetInt64(pMem+1, pOp->p2); sqlite3VdbeMemSetInt64(pMem+2, pOp->p3); sqlite3VdbeMemSetStr(pMem+3, zP4, -1, SQLITE_UTF8, sqlite3_free); - p->nResColumn = 4; + assert( p->nResColumn==4 ); }else{ sqlite3VdbeMemSetInt64(pMem+0, i); sqlite3VdbeMemSetStr(pMem+1, (char*)sqlite3OpcodeName(pOp->opcode), @@ -85212,7 +86148,7 @@ SQLITE_PRIVATE int sqlite3VdbeList( sqlite3VdbeMemSetNull(pMem+7); #endif sqlite3VdbeMemSetStr(pMem+5, zP4, -1, SQLITE_UTF8, sqlite3_free); - p->nResColumn = 8; + assert( p->nResColumn==8 ); } p->pResultRow = pMem; if( db->mallocFailed ){ @@ -85426,26 +86362,9 @@ SQLITE_PRIVATE void sqlite3VdbeMakeReady( resolveP2Values(p, &nArg); p->usesStmtJournal = (u8)(pParse->isMultiWrite && pParse->mayAbort); if( pParse->explain ){ - static const char * const azColName[] = { - "addr", "opcode", "p1", "p2", "p3", "p4", "p5", "comment", - "id", "parent", "notused", "detail" - }; - int iFirst, mx, i; if( nMem<10 ) nMem = 10; p->explain = pParse->explain; - if( pParse->explain==2 ){ - sqlite3VdbeSetNumCols(p, 4); - iFirst = 8; - mx = 12; - }else{ - sqlite3VdbeSetNumCols(p, 8); - iFirst = 0; - mx = 8; - } - for(i=iFirst; inResColumn = 12 - 4*p->explain; } p->expired = 0; @@ -85497,7 +86416,23 @@ SQLITE_PRIVATE void sqlite3VdbeMakeReady( SQLITE_PRIVATE void sqlite3VdbeFreeCursor(Vdbe *p, VdbeCursor *pCx){ if( pCx ) sqlite3VdbeFreeCursorNN(p,pCx); } +static SQLITE_NOINLINE void freeCursorWithCache(Vdbe *p, VdbeCursor *pCx){ + VdbeTxtBlbCache *pCache = pCx->pCache; + assert( pCx->colCache ); + pCx->colCache = 0; + pCx->pCache = 0; + if( pCache->pCValue ){ + sqlite3RCStrUnref(pCache->pCValue); + pCache->pCValue = 0; + } + sqlite3DbFree(p->db, pCache); + sqlite3VdbeFreeCursorNN(p, pCx); +} SQLITE_PRIVATE void sqlite3VdbeFreeCursorNN(Vdbe *p, VdbeCursor *pCx){ + if( pCx->colCache ){ + freeCursorWithCache(p, pCx); + return; + } switch( pCx->eCurType ){ case CURTYPE_SORTER: { sqlite3VdbeSorterClose(p->db, pCx); @@ -85598,12 +86533,12 @@ SQLITE_PRIVATE void sqlite3VdbeSetNumCols(Vdbe *p, int nResColumn){ int n; sqlite3 *db = p->db; - if( p->nResColumn ){ - releaseMemArray(p->aColName, p->nResColumn*COLNAME_N); + if( p->nResAlloc ){ + releaseMemArray(p->aColName, p->nResAlloc*COLNAME_N); sqlite3DbFree(db, p->aColName); } n = nResColumn*COLNAME_N; - p->nResColumn = (u16)nResColumn; + p->nResColumn = p->nResAlloc = (u16)nResColumn; p->aColName = (Mem*)sqlite3DbMallocRawNN(db, sizeof(Mem)*n ); if( p->aColName==0 ) return; initMemArray(p->aColName, n, db, MEM_Null); @@ -85628,14 +86563,14 @@ SQLITE_PRIVATE int sqlite3VdbeSetColName( ){ int rc; Mem *pColName; - assert( idxnResColumn ); + assert( idxnResAlloc ); assert( vardb->mallocFailed ){ assert( !zName || xDel!=SQLITE_DYNAMIC ); return SQLITE_NOMEM_BKPT; } assert( p->aColName!=0 ); - pColName = &(p->aColName[idx+var*p->nResColumn]); + pColName = &(p->aColName[idx+var*p->nResAlloc]); rc = sqlite3VdbeMemSetStr(pColName, zName, -1, SQLITE_UTF8, xDel); assert( rc!=0 || !zName || (pColName->flags&MEM_Term)!=0 ); return rc; @@ -86148,6 +87083,7 @@ SQLITE_PRIVATE int sqlite3VdbeHalt(Vdbe *p){ sqlite3VdbeLeave(p); return SQLITE_BUSY; }else if( rc!=SQLITE_OK ){ + sqlite3SystemError(db, rc); p->rc = rc; sqlite3RollbackAll(db, SQLITE_OK); p->nChange = 0; @@ -86459,7 +87395,7 @@ static void sqlite3VdbeClearObject(sqlite3 *db, Vdbe *p){ assert( db!=0 ); assert( p->db==0 || p->db==db ); if( p->aColName ){ - releaseMemArray(p->aColName, p->nResColumn*COLNAME_N); + releaseMemArray(p->aColName, p->nResAlloc*COLNAME_N); sqlite3DbNNFreeNN(db, p->aColName); } for(pSub=p->pProgram; pSub; pSub=pNext){ @@ -87059,6 +87995,15 @@ static int vdbeRecordCompareDebug( if( d1+(u64)serial_type1+2>(u64)nKey1 && d1+(u64)sqlite3VdbeSerialTypeLen(serial_type1)>(u64)nKey1 ){ + if( serial_type1>=1 + && serial_type1<=7 + && d1+(u64)sqlite3VdbeSerialTypeLen(serial_type1)<=(u64)nKey1+8 + && CORRUPT_DB + ){ + return 1; /* corrupt record not detected by + ** sqlite3VdbeRecordCompareWithSkip(). Return true + ** to avoid firing the assert() */ + } break; } @@ -87502,7 +88447,7 @@ SQLITE_PRIVATE int sqlite3VdbeRecordCompareWithSkip( /* Serial types 12 or greater are strings and blobs (greater than ** numbers). Types 10 and 11 are currently "reserved for future ** use", so it doesn't really matter what the results of comparing - ** them to numberic values are. */ + ** them to numeric values are. */ rc = serial_type==10 ? -1 : +1; }else if( serial_type==0 ){ rc = -1; @@ -88759,6 +89704,7 @@ SQLITE_API void sqlite3_result_text64( (void)invokeValueDestructor(z, xDel, pCtx); }else{ setResultStrOrError(pCtx, z, (int)n, enc, xDel); + sqlite3VdbeMemZeroTerminateIfAble(pCtx->pOut); } } #ifndef SQLITE_OMIT_UTF16 @@ -89131,7 +90077,7 @@ SQLITE_API int sqlite3_vtab_nochange(sqlite3_context *p){ ** The destructor function for a ValueList object. This needs to be ** a separate function, unknowable to the application, to ensure that ** calls to sqlite3_vtab_in_first()/sqlite3_vtab_in_next() that are not -** preceeded by activation of IN processing via sqlite3_vtab_int() do not +** preceded by activation of IN processing via sqlite3_vtab_int() do not ** try to access a fake ValueList object inserted by a hostile extension. */ SQLITE_PRIVATE void sqlite3VdbeValueListFree(void *pToDelete){ @@ -89371,7 +90317,8 @@ SQLITE_API int sqlite3_aggregate_count(sqlite3_context *p){ */ SQLITE_API int sqlite3_column_count(sqlite3_stmt *pStmt){ Vdbe *pVm = (Vdbe *)pStmt; - return pVm ? pVm->nResColumn : 0; + if( pVm==0 ) return 0; + return pVm->nResColumn; } /* @@ -89460,7 +90407,7 @@ static Mem *columnMem(sqlite3_stmt *pStmt, int i){ ** sqlite3_column_real() ** sqlite3_column_bytes() ** sqlite3_column_bytes16() -** sqiite3_column_blob() +** sqlite3_column_blob() */ static void columnMallocFailure(sqlite3_stmt *pStmt) { @@ -89544,6 +90491,32 @@ SQLITE_API int sqlite3_column_type(sqlite3_stmt *pStmt, int i){ return iType; } +/* +** Column names appropriate for EXPLAIN or EXPLAIN QUERY PLAN. +*/ +static const char * const azExplainColNames8[] = { + "addr", "opcode", "p1", "p2", "p3", "p4", "p5", "comment", /* EXPLAIN */ + "id", "parent", "notused", "detail" /* EQP */ +}; +static const u16 azExplainColNames16data[] = { + /* 0 */ 'a', 'd', 'd', 'r', 0, + /* 5 */ 'o', 'p', 'c', 'o', 'd', 'e', 0, + /* 12 */ 'p', '1', 0, + /* 15 */ 'p', '2', 0, + /* 18 */ 'p', '3', 0, + /* 21 */ 'p', '4', 0, + /* 24 */ 'p', '5', 0, + /* 27 */ 'c', 'o', 'm', 'm', 'e', 'n', 't', 0, + /* 35 */ 'i', 'd', 0, + /* 38 */ 'p', 'a', 'r', 'e', 'n', 't', 0, + /* 45 */ 'n', 'o', 't', 'u', 's', 'e', 'd', 0, + /* 53 */ 'd', 'e', 't', 'a', 'i', 'l', 0 +}; +static const u8 iExplainColNames16[] = { + 0, 5, 12, 15, 18, 21, 24, 27, + 35, 38, 45, 53 +}; + /* ** Convert the N-th element of pStmt->pColName[] into a string using ** xFunc() then return that string. If N is out of range, return 0. @@ -89576,15 +90549,29 @@ static const void *columnName( return 0; } #endif + if( N<0 ) return 0; ret = 0; p = (Vdbe *)pStmt; db = p->db; assert( db!=0 ); - n = sqlite3_column_count(pStmt); - if( N=0 ){ + sqlite3_mutex_enter(db->mutex); + + if( p->explain ){ + if( useType>0 ) goto columnName_end; + n = p->explain==1 ? 8 : 4; + if( N>=n ) goto columnName_end; + if( useUtf16 ){ + int i = iExplainColNames16[N + 8*p->explain - 8]; + ret = (void*)&azExplainColNames16data[i]; + }else{ + ret = (void*)azExplainColNames8[N + 8*p->explain - 8]; + } + goto columnName_end; + } + n = p->nResColumn; + if( NmallocFailed; N += useType*n; - sqlite3_mutex_enter(db->mutex); #ifndef SQLITE_OMIT_UTF16 if( useUtf16 ){ ret = sqlite3_value_text16((sqlite3_value*)&p->aColName[N]); @@ -89601,8 +90588,9 @@ static const void *columnName( sqlite3OomClear(db); ret = 0; } - sqlite3_mutex_leave(db->mutex); } +columnName_end: + sqlite3_mutex_leave(db->mutex); return ret; } @@ -89695,7 +90683,7 @@ SQLITE_API const void *sqlite3_column_origin_name16(sqlite3_stmt *pStmt, int N){ /* ** Unbind the value bound to variable i in virtual machine p. This is the ** the same as binding a NULL value to the column. If the "i" parameter is -** out of range, then SQLITE_RANGE is returned. Othewise SQLITE_OK. +** out of range, then SQLITE_RANGE is returned. Otherwise SQLITE_OK. ** ** A successful evaluation of this routine acquires the mutex on p. ** the mutex is released if any kind of error occurs. @@ -90059,6 +91047,39 @@ SQLITE_API int sqlite3_stmt_isexplain(sqlite3_stmt *pStmt){ return pStmt ? ((Vdbe*)pStmt)->explain : 0; } +/* +** Set the explain mode for a statement. +*/ +SQLITE_API int sqlite3_stmt_explain(sqlite3_stmt *pStmt, int eMode){ + Vdbe *v = (Vdbe*)pStmt; + int rc; + sqlite3_mutex_enter(v->db->mutex); + if( ((int)v->explain)==eMode ){ + rc = SQLITE_OK; + }else if( eMode<0 || eMode>2 ){ + rc = SQLITE_ERROR; + }else if( (v->prepFlags & SQLITE_PREPARE_SAVESQL)==0 ){ + rc = SQLITE_ERROR; + }else if( v->eVdbeState!=VDBE_READY_STATE ){ + rc = SQLITE_BUSY; + }else if( v->nMem>=10 && (eMode!=2 || v->haveEqpOps) ){ + /* No reprepare necessary */ + v->explain = eMode; + rc = SQLITE_OK; + }else{ + v->explain = eMode; + rc = sqlite3Reprepare(v); + v->haveEqpOps = eMode==2; + } + if( v->explain ){ + v->nResColumn = 12 - 4*v->explain; + }else{ + v->nResColumn = v->nResAlloc; + } + sqlite3_mutex_leave(v->db->mutex); + return rc; +} + /* ** Return true if the prepared statement is in need of being reset. */ @@ -91298,6 +92319,9 @@ SQLITE_PRIVATE void sqlite3VdbeMemPrettyPrint(Mem *pMem, StrAccum *pStr){ sqlite3_str_appendchar(pStr, 1, (c>=0x20&&c<=0x7f) ? c : '.'); } sqlite3_str_appendf(pStr, "]%s", encnames[pMem->enc]); + if( f & MEM_Term ){ + sqlite3_str_appendf(pStr, "(0-term)"); + } } } #endif @@ -91434,6 +92458,93 @@ static u64 filterHash(const Mem *aMem, const Op *pOp){ return h; } + +/* +** For OP_Column, factor out the case where content is loaded from +** overflow pages, so that the code to implement this case is separate +** the common case where all content fits on the page. Factoring out +** the code reduces register pressure and helps the common case +** to run faster. +*/ +static SQLITE_NOINLINE int vdbeColumnFromOverflow( + VdbeCursor *pC, /* The BTree cursor from which we are reading */ + int iCol, /* The column to read */ + int t, /* The serial-type code for the column value */ + i64 iOffset, /* Offset to the start of the content value */ + u32 cacheStatus, /* Current Vdbe.cacheCtr value */ + u32 colCacheCtr, /* Current value of the column cache counter */ + Mem *pDest /* Store the value into this register. */ +){ + int rc; + sqlite3 *db = pDest->db; + int encoding = pDest->enc; + int len = sqlite3VdbeSerialTypeLen(t); + assert( pC->eCurType==CURTYPE_BTREE ); + if( len>db->aLimit[SQLITE_LIMIT_LENGTH] ) return SQLITE_TOOBIG; + if( len > 4000 && pC->pKeyInfo==0 ){ + /* Cache large column values that are on overflow pages using + ** an RCStr (reference counted string) so that if they are reloaded, + ** that do not have to be copied a second time. The overhead of + ** creating and managing the cache is such that this is only + ** profitable for larger TEXT and BLOB values. + ** + ** Only do this on table-btrees so that writes to index-btrees do not + ** need to clear the cache. This buys performance in the common case + ** in exchange for generality. + */ + VdbeTxtBlbCache *pCache; + char *pBuf; + if( pC->colCache==0 ){ + pC->pCache = sqlite3DbMallocZero(db, sizeof(VdbeTxtBlbCache) ); + if( pC->pCache==0 ) return SQLITE_NOMEM; + pC->colCache = 1; + } + pCache = pC->pCache; + if( pCache->pCValue==0 + || pCache->iCol!=iCol + || pCache->cacheStatus!=cacheStatus + || pCache->colCacheCtr!=colCacheCtr + || pCache->iOffset!=sqlite3BtreeOffset(pC->uc.pCursor) + ){ + if( pCache->pCValue ) sqlite3RCStrUnref(pCache->pCValue); + pBuf = pCache->pCValue = sqlite3RCStrNew( len+3 ); + if( pBuf==0 ) return SQLITE_NOMEM; + rc = sqlite3BtreePayload(pC->uc.pCursor, iOffset, len, pBuf); + if( rc ) return rc; + pBuf[len] = 0; + pBuf[len+1] = 0; + pBuf[len+2] = 0; + pCache->iCol = iCol; + pCache->cacheStatus = cacheStatus; + pCache->colCacheCtr = colCacheCtr; + pCache->iOffset = sqlite3BtreeOffset(pC->uc.pCursor); + }else{ + pBuf = pCache->pCValue; + } + assert( t>=12 ); + sqlite3RCStrRef(pBuf); + if( t&1 ){ + rc = sqlite3VdbeMemSetStr(pDest, pBuf, len, encoding, + (void(*)(void*))sqlite3RCStrUnref); + pDest->flags |= MEM_Term; + }else{ + rc = sqlite3VdbeMemSetStr(pDest, pBuf, len, 0, + (void(*)(void*))sqlite3RCStrUnref); + } + }else{ + rc = sqlite3VdbeMemFromBtree(pC->uc.pCursor, iOffset, len, pDest); + if( rc ) return rc; + sqlite3VdbeSerialGet((const u8*)pDest->z, t, pDest); + if( (t&1)!=0 && encoding==SQLITE_UTF8 ){ + pDest->z[len] = 0; + pDest->flags |= MEM_Term; + } + } + pDest->flags &= ~MEM_Ephem; + return rc; +} + + /* ** Return the symbolic name for the data type of a pMem */ @@ -91476,6 +92587,7 @@ SQLITE_PRIVATE int sqlite3VdbeExec( Mem *pIn2 = 0; /* 2nd input operand */ Mem *pIn3 = 0; /* 3rd input operand */ Mem *pOut = 0; /* Output operand */ + u32 colCacheCtr = 0; /* Column cache counter */ #if defined(SQLITE_ENABLE_STMT_SCANSTATUS) || defined(VDBE_PROFILE) u64 *pnCycle = 0; int bStmtScanStatus = IS_STMT_SCANSTATUS(db)!=0; @@ -91671,8 +92783,8 @@ SQLITE_PRIVATE int sqlite3VdbeExec( case OP_Goto: { /* jump */ #ifdef SQLITE_DEBUG - /* In debuggging mode, when the p5 flags is set on an OP_Goto, that - ** means we should really jump back to the preceeding OP_ReleaseReg + /* In debugging mode, when the p5 flags is set on an OP_Goto, that + ** means we should really jump back to the preceding OP_ReleaseReg ** instruction. */ if( pOp->p5 ){ assert( pOp->p2 < (int)(pOp - aOp) ); @@ -91880,7 +92992,7 @@ case OP_HaltIfNull: { /* in3 */ ** P5 is a value between 0 and 4, inclusive, that modifies the P4 string. ** ** 0: (no change) -** 1: NOT NULL contraint failed: P4 +** 1: NOT NULL constraint failed: P4 ** 2: UNIQUE constraint failed: P4 ** 3: CHECK constraint failed: P4 ** 4: FOREIGN KEY constraint failed: P4 @@ -93011,10 +94123,10 @@ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */ ** opcodes are allowed to occur between this instruction and the previous ** OP_Lt or OP_Gt. ** -** If result of an OP_Eq comparison on the same two operands as the -** prior OP_Lt or OP_Gt would have been true, then jump to P2. -** If the result of an OP_Eq comparison on the two previous -** operands would have been false or NULL, then fall through. +** If the result of an OP_Eq comparison on the same two operands as +** the prior OP_Lt or OP_Gt would have been true, then jump to P2. If +** the result of an OP_Eq comparison on the two previous operands +** would have been false or NULL, then fall through. */ case OP_ElseEq: { /* same as TK_ESCAPE, jump */ @@ -93444,7 +94556,7 @@ case OP_IsType: { /* jump */ /* Opcode: ZeroOrNull P1 P2 P3 * * ** Synopsis: r[P2] = 0 OR NULL ** -** If all both registers P1 and P3 are NOT NULL, then store a zero in +** If both registers P1 and P3 are NOT NULL, then store a zero in ** register P2. If either registers P1 or P3 are NULL then put ** a NULL in register P2. */ @@ -93798,11 +94910,16 @@ op_column_restart: pDest->flags = aFlag[t&1]; } }else{ + u8 p5; pDest->enc = encoding; + assert( pDest->db==db ); /* This branch happens only when content is on overflow pages */ - if( ((pOp->p5 & (OPFLAG_LENGTHARG|OPFLAG_TYPEOFARG))!=0 - && ((t>=12 && (t&1)==0) || (pOp->p5 & OPFLAG_TYPEOFARG)!=0)) - || (len = sqlite3VdbeSerialTypeLen(t))==0 + if( ((p5 = (pOp->p5 & OPFLAG_BYTELENARG))!=0 + && (p5==OPFLAG_TYPEOFARG + || (t>=12 && ((t&1)==0 || p5==OPFLAG_BYTELENARG)) + ) + ) + || sqlite3VdbeSerialTypeLen(t)==0 ){ /* Content is irrelevant for ** 1. the typeof() function, @@ -93819,11 +94936,13 @@ op_column_restart: */ sqlite3VdbeSerialGet((u8*)sqlite3CtypeMap, t, pDest); }else{ - if( len>db->aLimit[SQLITE_LIMIT_LENGTH] ) goto too_big; - rc = sqlite3VdbeMemFromBtree(pC->uc.pCursor, aOffset[p2], len, pDest); - if( rc!=SQLITE_OK ) goto abort_due_to_error; - sqlite3VdbeSerialGet((const u8*)pDest->z, t, pDest); - pDest->flags &= ~MEM_Ephem; + rc = vdbeColumnFromOverflow(pC, p2, t, aOffset[p2], + p->cacheCtr, colCacheCtr, pDest); + if( rc ){ + if( rc==SQLITE_NOMEM ) goto no_mem; + if( rc==SQLITE_TOOBIG ) goto too_big; + goto abort_due_to_error; + } } } @@ -95107,7 +96226,7 @@ case OP_OpenEphemeral: { /* ncycle */ } pCx = p->apCsr[pOp->p1]; if( pCx && !pCx->noReuse && ALWAYS(pOp->p2<=pCx->nField) ){ - /* If the ephermeral table is already open and has no duplicates from + /* If the ephemeral table is already open and has no duplicates from ** OP_OpenDup, then erase all existing content so that the table is ** empty again, rather than creating a new table. */ assert( pCx->isEphemeral ); @@ -95598,7 +96717,7 @@ seek_not_found: ** row. If This.P5 is false (0) then a jump is made to SeekGE.P2. If ** This.P5 is true (non-zero) then a jump is made to This.P2. The P5==0 ** case occurs when there are no inequality constraints to the right of -** the IN constraing. The jump to SeekGE.P2 ends the loop. The P5!=0 case +** the IN constraint. The jump to SeekGE.P2 ends the loop. The P5!=0 case ** occurs when there are inequality constraints to the right of the IN ** operator. In that case, the This.P2 will point either directly to or ** to setup code prior to the OP_IdxGT or OP_IdxGE opcode that checks for @@ -95606,7 +96725,7 @@ seek_not_found: ** ** Possible outcomes from this opcode:
      ** -**
    1. If the cursor is initally not pointed to any valid row, then +**
    2. If the cursor is initially not pointed to any valid row, then ** fall through into the subsequent OP_SeekGE opcode. ** **
    3. If the cursor is left pointing to a row that is before the target @@ -95838,13 +96957,13 @@ case OP_IfNotOpen: { /* jump */ ** operands to OP_NotFound and OP_IdxGT. ** ** This opcode is an optimization attempt only. If this opcode always -** falls through, the correct answer is still obtained, but extra works +** falls through, the correct answer is still obtained, but extra work ** is performed. ** ** A value of N in the seekHit flag of cursor P1 means that there exists ** a key P3:N that will match some record in the index. We want to know ** if it is possible for a record P3:P4 to match some record in the -** index. If it is not possible, we can skips some work. So if seekHit +** index. If it is not possible, we can skip some work. So if seekHit ** is less than P4, attempt to find out if a match is possible by running ** OP_NotFound. ** @@ -96356,6 +97475,7 @@ case OP_Insert: { ); pC->deferredMoveto = 0; pC->cacheStatus = CACHE_STALE; + colCacheCtr++; /* Invoke the update-hook if required. */ if( rc ) goto abort_due_to_error; @@ -96409,10 +97529,10 @@ case OP_RowCell: { ** left in an undefined state. ** ** If the OPFLAG_AUXDELETE bit is set on P5, that indicates that this -** delete one of several associated with deleting a table row and all its -** associated index entries. Exactly one of those deletes is the "primary" -** delete. The others are all on OPFLAG_FORDELETE cursors or else are -** marked with the AUXDELETE flag. +** delete is one of several associated with deleting a table row and +** all its associated index entries. Exactly one of those deletes is +** the "primary" delete. The others are all on OPFLAG_FORDELETE +** cursors or else are marked with the AUXDELETE flag. ** ** If the OPFLAG_NCHANGE flag of P2 (NB: P2 not P5) is set, then the row ** change count is incremented (otherwise not). @@ -96516,6 +97636,7 @@ case OP_Delete: { rc = sqlite3BtreeDelete(pC->uc.pCursor, pOp->p5); pC->cacheStatus = CACHE_STALE; + colCacheCtr++; pC->seekResult = 0; if( rc ) goto abort_due_to_error; @@ -96583,13 +97704,13 @@ case OP_SorterCompare: { ** Write into register P2 the current sorter data for sorter cursor P1. ** Then clear the column header cache on cursor P3. ** -** This opcode is normally use to move a record out of the sorter and into +** This opcode is normally used to move a record out of the sorter and into ** a register that is the source for a pseudo-table cursor created using ** OpenPseudo. That pseudo-table cursor is the one that is identified by ** parameter P3. Clearing the P3 column cache as part of this opcode saves ** us from having to issue a separate NullRow instruction to clear that cache. */ -case OP_SorterData: { +case OP_SorterData: { /* ncycle */ VdbeCursor *pC; pOut = &aMem[pOp->p2]; @@ -96864,8 +97985,8 @@ case OP_IfSmaller: { /* jump */ ** regression tests can determine whether or not the optimizer is ** correctly optimizing out sorts. */ -case OP_SorterSort: /* jump */ -case OP_Sort: { /* jump */ +case OP_SorterSort: /* jump ncycle */ +case OP_Sort: { /* jump ncycle */ #ifdef SQLITE_TEST sqlite3_sort_count++; sqlite3_search_count--; @@ -97392,7 +98513,7 @@ case OP_IdxGE: { /* jump, ncycle */ ** file is given by P1. ** ** The table being destroyed is in the main database file if P3==0. If -** P3==1 then the table to be clear is in the auxiliary database file +** P3==1 then the table to be destroyed is in the auxiliary database file ** that is used to store tables create using CREATE TEMPORARY TABLE. ** ** If AUTOVACUUM is enabled then it is possible that another root page @@ -97452,8 +98573,8 @@ case OP_Destroy: { /* out2 */ ** in the database file is given by P1. But, unlike Destroy, do not ** remove the table or index from the database file. ** -** The table being clear is in the main database file if P2==0. If -** P2==1 then the table to be clear is in the auxiliary database file +** The table being cleared is in the main database file if P2==0. If +** P2==1 then the table to be cleared is in the auxiliary database file ** that is used to store tables create using CREATE TEMPORARY TABLE. ** ** If the P3 value is non-zero, then the row change count is incremented @@ -98279,7 +99400,7 @@ case OP_AggStep1: { /* If this function is inside of a trigger, the register array in aMem[] ** might change from one evaluation to the next. The next block of code ** checks to see if the register array has changed, and if so it - ** reinitializes the relavant parts of the sqlite3_context object */ + ** reinitializes the relevant parts of the sqlite3_context object */ if( pCtx->pMem != pMem ){ pCtx->pMem = pMem; for(i=pCtx->argc-1; i>=0; i--) pCtx->argv[i] = &aMem[pOp->p2+i]; @@ -99157,7 +100278,7 @@ case OP_MaxPgcnt: { /* out2 */ ** This opcode works exactly like OP_Function. The only difference is in ** its name. This opcode is used in places where the function must be ** purely non-deterministic. Some built-in date/time functions can be -** either determinitic of non-deterministic, depending on their arguments. +** either deterministic of non-deterministic, depending on their arguments. ** When those function are used in a non-deterministic way, they will check ** to see if they were called using OP_PureFunc instead of OP_Function, and ** if they were, they throw an error. @@ -99175,7 +100296,7 @@ case OP_Function: { /* group */ /* If this function is inside of a trigger, the register array in aMem[] ** might change from one evaluation to the next. The next block of code ** checks to see if the register array has changed, and if so it - ** reinitializes the relavant parts of the sqlite3_context object */ + ** reinitializes the relevant parts of the sqlite3_context object */ pOut = &aMem[pOp->p3]; if( pCtx->pOut != pOut ){ pCtx->pVdbe = p; @@ -99251,7 +100372,7 @@ case OP_FilterAdd: { printf("hash: %llu modulo %d -> %u\n", h, pIn1->n, (int)(h%pIn1->n)); } #endif - h %= pIn1->n; + h %= (pIn1->n*8); pIn1->z[h/8] |= 1<<(h&7); break; } @@ -99287,7 +100408,7 @@ case OP_Filter: { /* jump */ printf("hash: %llu modulo %d -> %u\n", h, pIn1->n, (int)(h%pIn1->n)); } #endif - h %= pIn1->n; + h %= (pIn1->n*8); if( (pIn1->z[h/8] & (1<<(h&7)))==0 ){ VdbeBranchTaken(1, 2); p->aCounter[SQLITE_STMTSTATUS_FILTER_HIT]++; @@ -99539,7 +100660,7 @@ default: { /* This is really OP_Noop, OP_Explain */ } if( opProperty==0xff ){ /* Never happens. This code exists to avoid a harmless linkage - ** warning aboud sqlite3VdbeRegisterDump() being defined but not + ** warning about sqlite3VdbeRegisterDump() being defined but not ** used. */ sqlite3VdbeRegisterDump(p); } @@ -100257,7 +101378,7 @@ SQLITE_API int sqlite3_blob_reopen(sqlite3_blob *pBlob, sqlite3_int64 iRow){ ** The threshold for the amount of main memory to use before flushing ** records to a PMA is roughly the same as the limit configured for the ** page-cache of the main database. Specifically, the threshold is set to -** the value returned by "PRAGMA main.page_size" multipled by +** the value returned by "PRAGMA main.page_size" multiplied by ** that returned by "PRAGMA main.cache_size", in bytes. ** ** If the sorter is running in single-threaded mode, then all PMAs generated @@ -100280,7 +101401,7 @@ SQLITE_API int sqlite3_blob_reopen(sqlite3_blob *pBlob, sqlite3_int64 iRow){ ** ** If there are fewer than SORTER_MAX_MERGE_COUNT PMAs in total and the ** sorter is running in single-threaded mode, then these PMAs are merged -** incrementally as keys are retreived from the sorter by the VDBE. The +** incrementally as keys are retrieved from the sorter by the VDBE. The ** MergeEngine object, described in further detail below, performs this ** merge. ** @@ -100443,7 +101564,7 @@ struct MergeEngine { ** ** Essentially, this structure contains all those fields of the VdbeSorter ** structure for which each thread requires a separate instance. For example, -** each thread requries its own UnpackedRecord object to unpack records in +** each thread requeries its own UnpackedRecord object to unpack records in ** as part of comparison operations. ** ** Before a background thread is launched, variable bDone is set to 0. Then, @@ -100515,7 +101636,7 @@ struct VdbeSorter { ** PMA, in sorted order. The next key to be read is cached in nKey/aKey. ** aKey might point into aMap or into aBuffer. If neither of those locations ** contain a contiguous representation of the key, then aAlloc is allocated -** and the key is copied into aAlloc and aKey is made to poitn to aAlloc. +** and the key is copied into aAlloc and aKey is made to point to aAlloc. ** ** pFd==0 at EOF. */ @@ -101886,7 +103007,7 @@ static int vdbeSorterFlushPMA(VdbeSorter *pSorter){ ** the background thread from a sub-tasks previous turn is still running, ** skip it. If the first (pSorter->nTask-1) sub-tasks are all still busy, ** fall back to using the final sub-task. The first (pSorter->nTask-1) - ** sub-tasks are prefered as they use background threads - the final + ** sub-tasks are preferred as they use background threads - the final ** sub-task uses the main thread. */ for(i=0; iiPrev + i + 1) % nWorker; @@ -102370,7 +103491,7 @@ static int vdbePmaReaderIncrMergeInit(PmaReader *pReadr, int eMode){ rc = vdbeMergeEngineInit(pTask, pIncr->pMerger, eMode); - /* Set up the required files for pIncr. A multi-theaded IncrMerge object + /* Set up the required files for pIncr. A multi-threaded IncrMerge object ** requires two temp files to itself, whereas a single-threaded object ** only requires a region of pTask->file2. */ if( rc==SQLITE_OK ){ @@ -103010,6 +104131,8 @@ static int bytecodevtabConnect( "p5 INT," "comment TEXT," "subprog TEXT," + "nexec INT," + "ncycle INT," "stmt HIDDEN" ");", @@ -103172,7 +104295,7 @@ static int bytecodevtabColumn( } } } - i += 10; + i += 20; } } switch( i ){ @@ -103222,16 +104345,31 @@ static int bytecodevtabColumn( } break; } - case 10: /* tables_used.type */ + +#ifdef SQLITE_ENABLE_STMT_SCANSTATUS + case 9: /* nexec */ + sqlite3_result_int(ctx, pOp->nExec); + break; + case 10: /* ncycle */ + sqlite3_result_int(ctx, pOp->nCycle); + break; +#else + case 9: /* nexec */ + case 10: /* ncycle */ + sqlite3_result_int(ctx, 0); + break; +#endif + + case 20: /* tables_used.type */ sqlite3_result_text(ctx, pCur->zType, -1, SQLITE_STATIC); break; - case 11: /* tables_used.schema */ + case 21: /* tables_used.schema */ sqlite3_result_text(ctx, pCur->zSchema, -1, SQLITE_STATIC); break; - case 12: /* tables_used.name */ + case 22: /* tables_used.name */ sqlite3_result_text(ctx, pCur->zName, -1, SQLITE_STATIC); break; - case 13: /* tables_used.wr */ + case 23: /* tables_used.wr */ sqlite3_result_int(ctx, pOp->opcode==OP_OpenWrite); break; } @@ -103305,7 +104443,7 @@ static int bytecodevtabBestIndex( int rc = SQLITE_CONSTRAINT; struct sqlite3_index_constraint *p; bytecodevtab *pVTab = (bytecodevtab*)tab; - int iBaseCol = pVTab->bTablesUsed ? 4 : 8; + int iBaseCol = pVTab->bTablesUsed ? 4 : 10; pIdxInfo->estimatedCost = (double)100; pIdxInfo->estimatedRows = 100; pIdxInfo->idxNum = 0; @@ -103876,7 +105014,7 @@ static int walkWindowList(Walker *pWalker, Window *pList, int bOneOnly){ ** The return value from this routine is WRC_Abort to abandon the tree walk ** and WRC_Continue to continue. */ -static SQLITE_NOINLINE int walkExpr(Walker *pWalker, Expr *pExpr){ +SQLITE_PRIVATE SQLITE_NOINLINE int sqlite3WalkExprNN(Walker *pWalker, Expr *pExpr){ int rc; testcase( ExprHasProperty(pExpr, EP_TokenOnly) ); testcase( ExprHasProperty(pExpr, EP_Reduced) ); @@ -103885,7 +105023,9 @@ static SQLITE_NOINLINE int walkExpr(Walker *pWalker, Expr *pExpr){ if( rc ) return rc & WRC_Abort; if( !ExprHasProperty(pExpr,(EP_TokenOnly|EP_Leaf)) ){ assert( pExpr->x.pList==0 || pExpr->pRight==0 ); - if( pExpr->pLeft && walkExpr(pWalker, pExpr->pLeft) ) return WRC_Abort; + if( pExpr->pLeft && sqlite3WalkExprNN(pWalker, pExpr->pLeft) ){ + return WRC_Abort; + } if( pExpr->pRight ){ assert( !ExprHasProperty(pExpr, EP_WinFunc) ); pExpr = pExpr->pRight; @@ -103909,7 +105049,7 @@ static SQLITE_NOINLINE int walkExpr(Walker *pWalker, Expr *pExpr){ return WRC_Continue; } SQLITE_PRIVATE int sqlite3WalkExpr(Walker *pWalker, Expr *pExpr){ - return pExpr ? walkExpr(pWalker,pExpr) : WRC_Continue; + return pExpr ? sqlite3WalkExprNN(pWalker,pExpr) : WRC_Continue; } /* @@ -104035,7 +105175,7 @@ SQLITE_PRIVATE int sqlite3WalkSelect(Walker *pWalker, Select *p){ } /* Increase the walkerDepth when entering a subquery, and -** descrease when leaving the subquery. +** decrease when leaving the subquery. */ SQLITE_PRIVATE int sqlite3WalkerDepthIncrease(Walker *pWalker, Select *pSelect){ UNUSED_PARAMETER(pSelect); @@ -105769,7 +106909,7 @@ static int resolveOrderGroupBy( } for(j=0; jpEList->nExpr; j++){ if( sqlite3ExprCompare(0, pE, pSelect->pEList->a[j].pExpr, -1)==0 ){ - /* Since this expresion is being changed into a reference + /* Since this expression is being changed into a reference ** to an identical expression in the result set, remove all Window ** objects belonging to the expression from the Select.pWin list. */ windowRemoveExprFromSelect(pSelect, pE); @@ -106092,7 +107232,8 @@ SQLITE_PRIVATE int sqlite3ResolveExprNames( return SQLITE_ERROR; } #endif - sqlite3WalkExpr(&w, pExpr); + assert( pExpr!=0 ); + sqlite3WalkExprNN(&w, pExpr); #if SQLITE_MAX_EXPR_DEPTH>0 w.pParse->nHeight -= pExpr->nHeight; #endif @@ -106134,7 +107275,7 @@ SQLITE_PRIVATE int sqlite3ResolveExprListNames( return WRC_Abort; } #endif - sqlite3WalkExpr(&w, pExpr); + sqlite3WalkExprNN(&w, pExpr); #if SQLITE_MAX_EXPR_DEPTH>0 w.pParse->nHeight -= pExpr->nHeight; #endif @@ -106156,7 +107297,7 @@ SQLITE_PRIVATE int sqlite3ResolveExprListNames( /* ** Resolve all names in all expressions of a SELECT and in all -** decendents of the SELECT, including compounds off of p->pPrior, +** descendants of the SELECT, including compounds off of p->pPrior, ** subqueries in expressions, and subqueries used as FROM clause ** terms. ** @@ -106306,6 +107447,7 @@ SQLITE_PRIVATE char sqlite3ExprAffinity(const Expr *pExpr){ if( op==TK_SELECT_COLUMN ){ assert( pExpr->pLeft!=0 && ExprUseXSelect(pExpr->pLeft) ); assert( pExpr->iColumn < pExpr->iTable ); + assert( pExpr->iColumn >= 0 ); assert( pExpr->iTable==pExpr->pLeft->x.pSelect->pEList->nExpr ); return sqlite3ExprAffinity( pExpr->pLeft->x.pSelect->pEList->a[pExpr->iColumn].pExpr @@ -106542,7 +107684,7 @@ SQLITE_PRIVATE CollSeq *sqlite3ExprCollSeq(Parse *pParse, const Expr *pExpr){ /* ** Return the collation sequence for the expression pExpr. If ** there is no defined collating sequence, return a pointer to the -** defautl collation sequence. +** default collation sequence. ** ** See also: sqlite3ExprCollSeq() ** @@ -106672,7 +107814,7 @@ SQLITE_PRIVATE CollSeq *sqlite3BinaryCompareCollSeq( return pColl; } -/* Expresssion p is a comparison operator. Return a collation sequence +/* Expression p is a comparison operator. Return a collation sequence ** appropriate for the comparison operator. ** ** This is normally just a wrapper around sqlite3BinaryCompareCollSeq(). @@ -107128,6 +108270,15 @@ SQLITE_PRIVATE void sqlite3ExprSetHeightAndFlags(Parse *pParse, Expr *p){ #define exprSetHeight(y) #endif /* SQLITE_MAX_EXPR_DEPTH>0 */ +/* +** Set the error offset for an Expr node, if possible. +*/ +SQLITE_PRIVATE void sqlite3ExprSetErrorOffset(Expr *pExpr, int iOfst){ + if( pExpr==0 ) return; + if( NEVER(ExprUseWJoin(pExpr)) ) return; + pExpr->w.iOfst = iOfst; +} + /* ** This routine is the core allocator for Expr nodes. ** @@ -107588,7 +108739,7 @@ SQLITE_PRIVATE void sqlite3ClearOnOrUsing(sqlite3 *db, OnOrUsing *p){ /* ** Arrange to cause pExpr to be deleted when the pParse is deleted. ** This is similar to sqlite3ExprDelete() except that the delete is -** deferred untilthe pParse is deleted. +** deferred until the pParse is deleted. ** ** The pExpr might be deleted immediately on an OOM error. ** @@ -108430,7 +109581,7 @@ SQLITE_PRIVATE int sqlite3ExprIdToTrueFalse(Expr *pExpr){ ** and 0 if it is FALSE. */ SQLITE_PRIVATE int sqlite3ExprTruthValue(const Expr *pExpr){ - pExpr = sqlite3ExprSkipCollate((Expr*)pExpr); + pExpr = sqlite3ExprSkipCollateAndLikely((Expr*)pExpr); assert( pExpr->op==TK_TRUEFALSE ); assert( !ExprHasProperty(pExpr, EP_IntValue) ); assert( sqlite3StrICmp(pExpr->u.zToken,"true")==0 @@ -109023,7 +110174,7 @@ static int sqlite3InRhsIsConstant(Expr *pIn){ ** IN_INDEX_INDEX_ASC - The cursor was opened on an ascending index. ** IN_INDEX_INDEX_DESC - The cursor was opened on a descending index. ** IN_INDEX_EPH - The cursor was opened on a specially created and -** populated epheremal table. +** populated ephemeral table. ** IN_INDEX_NOOP - No cursor was allocated. The IN operator must be ** implemented as a sequence of comparisons. ** @@ -109036,7 +110187,7 @@ static int sqlite3InRhsIsConstant(Expr *pIn){ ** an ephemeral table might need to be generated from the RHS and then ** pX->iTable made to point to the ephemeral table instead of an ** existing table. In this case, the creation and initialization of the -** ephmeral table might be put inside of a subroutine, the EP_Subrtn flag +** ephemeral table might be put inside of a subroutine, the EP_Subrtn flag ** will be set on pX and the pX->y.sub fields will be set to show where ** the subroutine is coded. ** @@ -109048,12 +110199,12 @@ static int sqlite3InRhsIsConstant(Expr *pIn){ ** ** When IN_INDEX_LOOP is used (and the b-tree will be used to iterate ** through the set members) then the b-tree must not contain duplicates. -** An epheremal table will be created unless the selected columns are guaranteed +** An ephemeral table will be created unless the selected columns are guaranteed ** to be unique - either because it is an INTEGER PRIMARY KEY or due to ** a UNIQUE constraint or index. ** ** When IN_INDEX_MEMBERSHIP is used (and the b-tree will be used -** for fast set membership tests) then an epheremal table must +** for fast set membership tests) then an ephemeral table must ** be used unless is a single INTEGER PRIMARY KEY column or an ** index can be found with the specified as its left-most. ** @@ -109386,7 +110537,7 @@ SQLITE_PRIVATE void sqlite3VectorErrorMsg(Parse *pParse, Expr *pExpr){ ** x IN (SELECT a FROM b) -- IN operator with subquery on the right ** ** The pExpr parameter is the IN operator. The cursor number for the -** constructed ephermeral table is returned. The first time the ephemeral +** constructed ephemeral table is returned. The first time the ephemeral ** table is computed, the cursor number is also stored in pExpr->iTable, ** however the cursor number returned might not be the same, as it might ** have been duplicated using OP_OpenDup. @@ -110201,10 +111352,13 @@ SQLITE_PRIVATE int sqlite3ExprCodeGetColumn( u8 p5 /* P5 value for OP_Column + FLAGS */ ){ assert( pParse->pVdbe!=0 ); + assert( (p5 & (OPFLAG_NOCHNG|OPFLAG_TYPEOFARG|OPFLAG_LENGTHARG))==p5 ); + assert( IsVirtual(pTab) || (p5 & OPFLAG_NOCHNG)==0 ); sqlite3ExprCodeGetColumnOfTable(pParse->pVdbe, pTab, iTable, iColumn, iReg); if( p5 ){ VdbeOp *pOp = sqlite3VdbeGetLastOp(pParse->pVdbe); if( pOp->opcode==OP_Column ) pOp->p5 = p5; + if( pOp->opcode==OP_VColumn ) pOp->p5 = (p5 & OPFLAG_NOCHNG); } return iReg; } @@ -110233,7 +111387,7 @@ static void exprToRegister(Expr *pExpr, int iReg){ /* ** Evaluate an expression (either a vector or a scalar expression) and store -** the result in continguous temporary registers. Return the index of +** the result in contiguous temporary registers. Return the index of ** the first register used to store the result. ** ** If the returned result register is a temporary scalar, then also write @@ -110273,7 +111427,7 @@ static int exprCodeVector(Parse *pParse, Expr *p, int *piFreeable){ */ static void setDoNotMergeFlagOnCopy(Vdbe *v){ if( sqlite3VdbeGetLastOp(v)->opcode==OP_Copy ){ - sqlite3VdbeChangeP5(v, 1); /* Tag trailing OP_Copy as not mergable */ + sqlite3VdbeChangeP5(v, 1); /* Tag trailing OP_Copy as not mergeable */ } } @@ -110363,13 +111517,13 @@ static int exprCodeInlineFunction( } case INLINEFUNC_implies_nonnull_row: { - /* REsult of sqlite3ExprImpliesNonNullRow() */ + /* Result of sqlite3ExprImpliesNonNullRow() */ Expr *pA1; assert( nFarg==2 ); pA1 = pFarg->a[1].pExpr; if( pA1->op==TK_COLUMN ){ sqlite3VdbeAddOp2(v, OP_Integer, - sqlite3ExprImpliesNonNullRow(pFarg->a[0].pExpr,pA1->iTable), + sqlite3ExprImpliesNonNullRow(pFarg->a[0].pExpr,pA1->iTable,1), target); }else{ sqlite3VdbeAddOp2(v, OP_Null, 0, target); @@ -110545,7 +111699,7 @@ expr_code_doover: if( ExprHasProperty(pExpr, EP_FixedCol) ){ /* This COLUMN expression is really a constant due to WHERE clause ** constraints, and that constant is coded by the pExpr->pLeft - ** expresssion. However, make sure the constant has the correct + ** expression. However, make sure the constant has the correct ** datatype by applying the Affinity of the table column to the ** constant. */ @@ -110871,7 +112025,7 @@ expr_code_doover: sqlite3ErrorMsg(pParse, "unknown function: %#T()", pExpr); break; } - if( pDef->funcFlags & SQLITE_FUNC_INLINE ){ + if( (pDef->funcFlags & SQLITE_FUNC_INLINE)!=0 && ALWAYS(pFarg!=0) ){ assert( (pDef->funcFlags & SQLITE_FUNC_UNSAFE)==0 ); assert( (pDef->funcFlags & SQLITE_FUNC_DIRECT)==0 ); return exprCodeInlineFunction(pParse, pFarg, @@ -110897,10 +112051,10 @@ expr_code_doover: r1 = sqlite3GetTempRange(pParse, nFarg); } - /* For length() and typeof() functions with a column argument, + /* For length() and typeof() and octet_length() functions, ** set the P5 parameter to the OP_Column opcode to OPFLAG_LENGTHARG - ** or OPFLAG_TYPEOFARG respectively, to avoid unnecessary data - ** loading. + ** or OPFLAG_TYPEOFARG or OPFLAG_BYTELENARG respectively, to avoid + ** unnecessary data loading. */ if( (pDef->funcFlags & (SQLITE_FUNC_LENGTH|SQLITE_FUNC_TYPEOF))!=0 ){ u8 exprOp; @@ -110910,14 +112064,16 @@ expr_code_doover: if( exprOp==TK_COLUMN || exprOp==TK_AGG_COLUMN ){ assert( SQLITE_FUNC_LENGTH==OPFLAG_LENGTHARG ); assert( SQLITE_FUNC_TYPEOF==OPFLAG_TYPEOFARG ); - testcase( pDef->funcFlags & OPFLAG_LENGTHARG ); - pFarg->a[0].pExpr->op2 = - pDef->funcFlags & (OPFLAG_LENGTHARG|OPFLAG_TYPEOFARG); + assert( SQLITE_FUNC_BYTELEN==OPFLAG_BYTELENARG ); + assert( (OPFLAG_LENGTHARG|OPFLAG_TYPEOFARG)==OPFLAG_BYTELENARG ); + testcase( (pDef->funcFlags & OPFLAG_BYTELENARG)==OPFLAG_LENGTHARG ); + testcase( (pDef->funcFlags & OPFLAG_BYTELENARG)==OPFLAG_TYPEOFARG ); + testcase( (pDef->funcFlags & OPFLAG_BYTELENARG)==OPFLAG_BYTELENARG); + pFarg->a[0].pExpr->op2 = pDef->funcFlags & OPFLAG_BYTELENARG; } } - sqlite3ExprCodeExprList(pParse, pFarg, r1, 0, - SQLITE_ECEL_DUP|SQLITE_ECEL_FACTOR); + sqlite3ExprCodeExprList(pParse, pFarg, r1, 0, SQLITE_ECEL_FACTOR); }else{ r1 = 0; } @@ -111274,7 +112430,7 @@ expr_code_doover: ** ** If regDest>=0 then the result is always stored in that register and the ** result is not reusable. If regDest<0 then this routine is free to -** store the value whereever it wants. The register where the expression +** store the value wherever it wants. The register where the expression ** is stored is returned. When regDest<0, two identical expressions might ** code to the same register, if they do not contain function calls and hence ** are factored out into the initialization section at the end of the @@ -112192,7 +113348,7 @@ static int exprImpliesNotNull( ** pE1: x!=123 pE2: x IS NOT NULL Result: true ** pE1: x!=?1 pE2: x IS NOT NULL Result: true ** pE1: x IS NULL pE2: x IS NOT NULL Result: false -** pE1: x IS ?2 pE2: x IS NOT NULL Reuslt: false +** pE1: x IS ?2 pE2: x IS NOT NULL Result: false ** ** When comparing TK_COLUMN nodes between pE1 and pE2, if pE2 has ** Expr.iTable<0 then assume a table number given by iTab. @@ -112229,11 +113385,29 @@ SQLITE_PRIVATE int sqlite3ExprImpliesExpr( return 0; } +/* This is a helper function to impliesNotNullRow(). In this routine, +** set pWalker->eCode to one only if *both* of the input expressions +** separately have the implies-not-null-row property. +*/ +static void bothImplyNotNullRow(Walker *pWalker, Expr *pE1, Expr *pE2){ + if( pWalker->eCode==0 ){ + sqlite3WalkExpr(pWalker, pE1); + if( pWalker->eCode ){ + pWalker->eCode = 0; + sqlite3WalkExpr(pWalker, pE2); + } + } +} + /* ** This is the Expr node callback for sqlite3ExprImpliesNonNullRow(). ** If the expression node requires that the table at pWalker->iCur ** have one or more non-NULL column, then set pWalker->eCode to 1 and abort. ** +** pWalker->mWFlags is non-zero if this inquiry is being undertaking on +** behalf of a RIGHT JOIN (or FULL JOIN). That makes a difference when +** evaluating terms in the ON clause of an inner join. +** ** This routine controls an optimization. False positives (setting ** pWalker->eCode to 1 when it should not be) are deadly, but false-negatives ** (never setting pWalker->eCode) is a harmless missed optimization. @@ -112242,28 +113416,33 @@ static int impliesNotNullRow(Walker *pWalker, Expr *pExpr){ testcase( pExpr->op==TK_AGG_COLUMN ); testcase( pExpr->op==TK_AGG_FUNCTION ); if( ExprHasProperty(pExpr, EP_OuterON) ) return WRC_Prune; + if( ExprHasProperty(pExpr, EP_InnerON) && pWalker->mWFlags ){ + /* If iCur is used in an inner-join ON clause to the left of a + ** RIGHT JOIN, that does *not* mean that the table must be non-null. + ** But it is difficult to check for that condition precisely. + ** To keep things simple, any use of iCur from any inner-join is + ** ignored while attempting to simplify a RIGHT JOIN. */ + return WRC_Prune; + } switch( pExpr->op ){ case TK_ISNOT: case TK_ISNULL: case TK_NOTNULL: case TK_IS: - case TK_OR: case TK_VECTOR: - case TK_CASE: - case TK_IN: case TK_FUNCTION: case TK_TRUTH: + case TK_CASE: testcase( pExpr->op==TK_ISNOT ); testcase( pExpr->op==TK_ISNULL ); testcase( pExpr->op==TK_NOTNULL ); testcase( pExpr->op==TK_IS ); - testcase( pExpr->op==TK_OR ); testcase( pExpr->op==TK_VECTOR ); - testcase( pExpr->op==TK_CASE ); - testcase( pExpr->op==TK_IN ); testcase( pExpr->op==TK_FUNCTION ); testcase( pExpr->op==TK_TRUTH ); + testcase( pExpr->op==TK_CASE ); return WRC_Prune; + case TK_COLUMN: if( pWalker->u.iCur==pExpr->iTable ){ pWalker->eCode = 1; @@ -112271,21 +113450,38 @@ static int impliesNotNullRow(Walker *pWalker, Expr *pExpr){ } return WRC_Prune; + case TK_OR: case TK_AND: - if( pWalker->eCode==0 ){ + /* Both sides of an AND or OR must separately imply non-null-row. + ** Consider these cases: + ** 1. NOT (x AND y) + ** 2. x OR y + ** If only one of x or y is non-null-row, then the overall expression + ** can be true if the other arm is false (case 1) or true (case 2). + */ + testcase( pExpr->op==TK_OR ); + testcase( pExpr->op==TK_AND ); + bothImplyNotNullRow(pWalker, pExpr->pLeft, pExpr->pRight); + return WRC_Prune; + + case TK_IN: + /* Beware of "x NOT IN ()" and "x NOT IN (SELECT 1 WHERE false)", + ** both of which can be true. But apart from these cases, if + ** the left-hand side of the IN is NULL then the IN itself will be + ** NULL. */ + if( ExprUseXList(pExpr) && ALWAYS(pExpr->x.pList->nExpr>0) ){ sqlite3WalkExpr(pWalker, pExpr->pLeft); - if( pWalker->eCode ){ - pWalker->eCode = 0; - sqlite3WalkExpr(pWalker, pExpr->pRight); - } } return WRC_Prune; case TK_BETWEEN: - if( sqlite3WalkExpr(pWalker, pExpr->pLeft)==WRC_Abort ){ - assert( pWalker->eCode ); - return WRC_Abort; - } + /* In "x NOT BETWEEN y AND z" either x must be non-null-row or else + ** both y and z must be non-null row */ + assert( ExprUseXList(pExpr) ); + assert( pExpr->x.pList->nExpr==2 ); + sqlite3WalkExpr(pWalker, pExpr->pLeft); + bothImplyNotNullRow(pWalker, pExpr->x.pList->a[0].pExpr, + pExpr->x.pList->a[1].pExpr); return WRC_Prune; /* Virtual tables are allowed to use constraints like x=NULL. So @@ -112347,7 +113543,7 @@ static int impliesNotNullRow(Walker *pWalker, Expr *pExpr){ ** be non-NULL, then the LEFT JOIN can be safely converted into an ** ordinary join. */ -SQLITE_PRIVATE int sqlite3ExprImpliesNonNullRow(Expr *p, int iTab){ +SQLITE_PRIVATE int sqlite3ExprImpliesNonNullRow(Expr *p, int iTab, int isRJ){ Walker w; p = sqlite3ExprSkipCollateAndLikely(p); if( p==0 ) return 0; @@ -112355,7 +113551,7 @@ SQLITE_PRIVATE int sqlite3ExprImpliesNonNullRow(Expr *p, int iTab){ p = p->pLeft; }else{ while( p->op==TK_AND ){ - if( sqlite3ExprImpliesNonNullRow(p->pLeft, iTab) ) return 1; + if( sqlite3ExprImpliesNonNullRow(p->pLeft, iTab, isRJ) ) return 1; p = p->pRight; } } @@ -112363,6 +113559,7 @@ SQLITE_PRIVATE int sqlite3ExprImpliesNonNullRow(Expr *p, int iTab){ w.xSelectCallback = 0; w.xSelectCallback2 = 0; w.eCode = 0; + w.mWFlags = isRJ!=0; w.u.iCur = iTab; sqlite3WalkExpr(&w, p); return w.eCode; @@ -112423,7 +113620,7 @@ SQLITE_PRIVATE int sqlite3ExprCoveredByIndex( } -/* Structure used to pass information throught the Walker in order to +/* Structure used to pass information throughout the Walker in order to ** implement sqlite3ReferencesSrcList(). */ struct RefSrcList { @@ -112639,7 +113836,7 @@ static int addAggInfoFunc(sqlite3 *db, AggInfo *pInfo){ ** Return the index in aCol[] of the entry that describes that column. ** ** If no prior entry is found, create a new one and return -1. The -** new column will have an idex of pAggInfo->nColumn-1. +** new column will have an index of pAggInfo->nColumn-1. */ static void findOrCreateAggInfoColumn( Parse *pParse, /* Parsing context */ @@ -112652,6 +113849,7 @@ static void findOrCreateAggInfoColumn( assert( pAggInfo->iFirstReg==0 ); pCol = pAggInfo->aCol; for(k=0; knColumn; k++, pCol++){ + if( pCol->pCExpr==pExpr ) return; if( pCol->iTable==pExpr->iTable && pCol->iColumn==pExpr->iColumn && pExpr->op!=TK_IF_NULL_ROW @@ -113532,7 +114730,7 @@ SQLITE_PRIVATE void sqlite3AlterBeginAddColumn(Parse *pParse, SrcList *pSrc){ pNew->u.tab.pDfltList = sqlite3ExprListDup(db, pTab->u.tab.pDfltList, 0); pNew->pSchema = db->aDb[iDb].pSchema; pNew->u.tab.addColOffset = pTab->u.tab.addColOffset; - pNew->nTabRef = 1; + assert( pNew->nTabRef==1 ); exit_begin_add_column: sqlite3SrcListDelete(db, pSrc); @@ -114037,7 +115235,7 @@ static RenameToken *renameColumnTokenNext(RenameCtx *pCtx){ } /* -** An error occured while parsing or otherwise processing a database +** An error occurred while parsing or otherwise processing a database ** object (either pParse->pNewTable, pNewIndex or pNewTrigger) as part of an ** ALTER TABLE RENAME COLUMN program. The error message emitted by the ** sub-routine is currently stored in pParse->zErrMsg. This function @@ -117143,14 +118341,15 @@ static int loadStatTbl( decodeIntArray((char*)sqlite3_column_text(pStmt,2),nCol,pSample->anLt,0,0); decodeIntArray((char*)sqlite3_column_text(pStmt,3),nCol,pSample->anDLt,0,0); - /* Take a copy of the sample. Add two 0x00 bytes the end of the buffer. + /* Take a copy of the sample. Add 8 extra 0x00 bytes the end of the buffer. ** This is in case the sample record is corrupted. In that case, the ** sqlite3VdbeRecordCompare() may read up to two varints past the ** end of the allocated buffer before it realizes it is dealing with - ** a corrupt record. Adding the two 0x00 bytes prevents this from causing + ** a corrupt record. Or it might try to read a large integer from the + ** buffer. In any case, eight 0x00 bytes prevents this from causing ** a buffer overread. */ pSample->n = sqlite3_column_bytes(pStmt, 4); - pSample->p = sqlite3DbMallocZero(db, pSample->n + 2); + pSample->p = sqlite3DbMallocZero(db, pSample->n + 8); if( pSample->p==0 ){ sqlite3_finalize(pStmt); return SQLITE_NOMEM_BKPT; @@ -118108,7 +119307,7 @@ SQLITE_PRIVATE int sqlite3AuthCheck( sqlite3 *db = pParse->db; int rc; - /* Don't do any authorization checks if the database is initialising + /* Don't do any authorization checks if the database is initializing ** or if the parser is being invoked from within sqlite3_declare_vtab. */ assert( !IN_RENAME_OBJECT || db->xAuth==0 ); @@ -118409,15 +119608,17 @@ SQLITE_PRIVATE void sqlite3FinishCoding(Parse *pParse){ pParse->nVtabLock = 0; #endif +#ifndef SQLITE_OMIT_SHARED_CACHE /* Once all the cookies have been verified and transactions opened, ** obtain the required table-locks. This is a no-op unless the ** shared-cache feature is enabled. */ - codeTableLocks(pParse); + if( pParse->nTableLock ) codeTableLocks(pParse); +#endif /* Initialize any AUTOINCREMENT data structures required. */ - sqlite3AutoincrementBegin(pParse); + if( pParse->pAinc ) sqlite3AutoincrementBegin(pParse); /* Code constant expressions that where factored out of inner loops. ** @@ -118930,7 +120131,7 @@ SQLITE_PRIVATE void sqlite3ColumnSetColl( } /* -** Return the collating squence name for a column +** Return the collating sequence name for a column */ SQLITE_PRIVATE const char *sqlite3ColumnColl(Column *pCol){ const char *z; @@ -119688,7 +120889,7 @@ SQLITE_PRIVATE void sqlite3AddColumn(Parse *pParse, Token sName, Token sType){ } if( !IN_RENAME_OBJECT ) sqlite3DequoteToken(&sName); - /* Because keywords GENERATE ALWAYS can be converted into indentifiers + /* Because keywords GENERATE ALWAYS can be converted into identifiers ** by the parser, we can sometimes end up with a typename that ends ** with "generated always". Check for this case and omit the surplus ** text. */ @@ -119909,7 +121110,7 @@ SQLITE_PRIVATE void sqlite3AddDefaultValue( Parse *pParse, /* Parsing context */ Expr *pExpr, /* The parsed expression of the default value */ const char *zStart, /* Start of the default value text */ - const char *zEnd /* First character past end of defaut value text */ + const char *zEnd /* First character past end of default value text */ ){ Table *p; Column *pCol; @@ -120257,7 +121458,7 @@ static int identLength(const char *z){ ** to the specified offset in the buffer and updates *pIdx to refer ** to the first byte after the last byte written before returning. ** -** If the string zSignedIdent consists entirely of alpha-numeric +** If the string zSignedIdent consists entirely of alphanumeric ** characters, does not begin with a digit and is not an SQL keyword, ** then it is copied to the output buffer exactly as it is. Otherwise, ** it is quoted using double-quotes. @@ -120409,7 +121610,7 @@ static void estimateIndexWidth(Index *pIdx){ for(i=0; inColumn; i++){ i16 x = pIdx->aiColumn[i]; assert( xpTable->nCol ); - wIndex += x<0 ? 1 : aCol[pIdx->aiColumn[i]].szEst; + wIndex += x<0 ? 1 : aCol[x].szEst; } pIdx->szIdxRow = sqlite3LogEst(wIndex*4); } @@ -122147,7 +123348,7 @@ SQLITE_PRIVATE void sqlite3CreateIndex( #ifndef SQLITE_OMIT_TEMPDB /* If the index name was unqualified, check if the table ** is a temp table. If so, set the database to 1. Do not do this - ** if initialising a database schema. + ** if initializing a database schema. */ if( !db->init.busy ){ pTab = sqlite3SrcListLookup(pParse, pTblName); @@ -123804,7 +125005,7 @@ SQLITE_PRIVATE void sqlite3CteDelete(sqlite3 *db, Cte *pCte){ /* ** This routine is invoked once per CTE by the parser while parsing a -** WITH clause. The CTE described by teh third argument is added to +** WITH clause. The CTE described by the third argument is added to ** the WITH clause of the second argument. If the second argument is ** NULL, then a new WITH argument is created. */ @@ -124446,8 +125647,9 @@ SQLITE_PRIVATE Table *sqlite3SrcListLookup(Parse *pParse, SrcList *pSrc){ Table *pTab; assert( pItem && pSrc->nSrc>=1 ); pTab = sqlite3LocateTableItem(pParse, 0, pItem); - sqlite3DeleteTable(pParse->db, pItem->pTab); + if( pItem->pTab ) sqlite3DeleteTable(pParse->db, pItem->pTab); pItem->pTab = pTab; + pItem->fg.notCte = 1; if( pTab ){ pTab->nTabRef++; if( pItem->fg.isIndexedBy && sqlite3IndexedByLookup(pParse, pItem) ){ @@ -124600,7 +125802,7 @@ SQLITE_PRIVATE Expr *sqlite3LimitWhere( sqlite3 *db = pParse->db; Expr *pLhs = NULL; /* LHS of IN(SELECT...) operator */ Expr *pInClause = NULL; /* WHERE rowid IN ( select ) */ - ExprList *pEList = NULL; /* Expression list contaning only pSelectRowid */ + ExprList *pEList = NULL; /* Expression list containing only pSelectRowid*/ SrcList *pSelectSrc = NULL; /* SELECT rowid FROM x ... (dup of pSrc) */ Select *pSelect = NULL; /* Complete SELECT tree */ Table *pTab; @@ -124638,14 +125840,20 @@ SQLITE_PRIVATE Expr *sqlite3LimitWhere( ); }else{ Index *pPk = sqlite3PrimaryKeyIndex(pTab); + assert( pPk!=0 ); + assert( pPk->nKeyCol>=1 ); if( pPk->nKeyCol==1 ){ - const char *zName = pTab->aCol[pPk->aiColumn[0]].zCnName; + const char *zName; + assert( pPk->aiColumn[0]>=0 && pPk->aiColumn[0]nCol ); + zName = pTab->aCol[pPk->aiColumn[0]].zCnName; pLhs = sqlite3Expr(db, TK_ID, zName); pEList = sqlite3ExprListAppend(pParse, 0, sqlite3Expr(db, TK_ID, zName)); }else{ int i; for(i=0; inKeyCol; i++){ - Expr *p = sqlite3Expr(db, TK_ID, pTab->aCol[pPk->aiColumn[i]].zCnName); + Expr *p; + assert( pPk->aiColumn[i]>=0 && pPk->aiColumn[i]nCol ); + p = sqlite3Expr(db, TK_ID, pTab->aCol[pPk->aiColumn[i]].zCnName); pEList = sqlite3ExprListAppend(pParse, pEList, p); } pLhs = sqlite3PExpr(pParse, TK_VECTOR, 0, 0); @@ -124674,7 +125882,7 @@ SQLITE_PRIVATE Expr *sqlite3LimitWhere( pOrderBy,0,pLimit ); - /* now generate the new WHERE rowid IN clause for the DELETE/UDPATE */ + /* now generate the new WHERE rowid IN clause for the DELETE/UPDATE */ pInClause = sqlite3PExpr(pParse, TK_IN, pLhs, 0); sqlite3PExprAddSelect(pParse, pInClause, pSelect); return pInClause; @@ -124903,7 +126111,7 @@ SQLITE_PRIVATE void sqlite3DeleteFrom( if( HasRowid(pTab) ){ /* For a rowid table, initialize the RowSet to an empty set */ pPk = 0; - nPk = 1; + assert( nPk==1 ); iRowSet = ++pParse->nMem; sqlite3VdbeAddOp2(v, OP_Null, 0, iRowSet); }else{ @@ -124931,7 +126139,8 @@ SQLITE_PRIVATE void sqlite3DeleteFrom( if( pWInfo==0 ) goto delete_from_cleanup; eOnePass = sqlite3WhereOkOnePass(pWInfo, aiCurOnePass); assert( IsVirtual(pTab)==0 || eOnePass!=ONEPASS_MULTI ); - assert( IsVirtual(pTab) || bComplex || eOnePass!=ONEPASS_OFF ); + assert( IsVirtual(pTab) || bComplex || eOnePass!=ONEPASS_OFF + || OptimizationDisabled(db, SQLITE_OnePass) ); if( eOnePass!=ONEPASS_SINGLE ) sqlite3MultiWrite(pParse); if( sqlite3WhereUsesDeferredSeek(pWInfo) ){ sqlite3VdbeAddOp1(v, OP_FinishSeek, iTabCur); @@ -125268,9 +126477,11 @@ SQLITE_PRIVATE void sqlite3GenerateRowDelete( sqlite3FkActions(pParse, pTab, 0, iOld, 0, 0); /* Invoke AFTER DELETE trigger programs. */ - sqlite3CodeRowTrigger(pParse, pTrigger, - TK_DELETE, 0, TRIGGER_AFTER, pTab, iOld, onconf, iLabel - ); + if( pTrigger ){ + sqlite3CodeRowTrigger(pParse, pTrigger, + TK_DELETE, 0, TRIGGER_AFTER, pTab, iOld, onconf, iLabel + ); + } /* Jump here if the row had already been deleted before any BEFORE ** trigger programs were invoked. Or if a trigger program throws a @@ -125583,6 +126794,42 @@ static void lengthFunc( } } +/* +** Implementation of the octet_length() function +*/ +static void bytelengthFunc( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + assert( argc==1 ); + UNUSED_PARAMETER(argc); + switch( sqlite3_value_type(argv[0]) ){ + case SQLITE_BLOB: { + sqlite3_result_int(context, sqlite3_value_bytes(argv[0])); + break; + } + case SQLITE_INTEGER: + case SQLITE_FLOAT: { + i64 m = sqlite3_context_db_handle(context)->enc<=SQLITE_UTF8 ? 1 : 2; + sqlite3_result_int64(context, sqlite3_value_bytes(argv[0])*m); + break; + } + case SQLITE_TEXT: { + if( sqlite3_value_encoding(argv[0])<=SQLITE_UTF8 ){ + sqlite3_result_int(context, sqlite3_value_bytes(argv[0])); + }else{ + sqlite3_result_int(context, sqlite3_value_bytes16(argv[0])); + } + break; + } + default: { + sqlite3_result_null(context); + break; + } + } +} + /* ** Implementation of the abs() function. ** @@ -125859,7 +127106,7 @@ static void roundFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ }else if( n==0 ){ r = (double)((sqlite_int64)(r+(r<0?-0.5:+0.5))); }else{ - zBuf = sqlite3_mprintf("%.*f",n,r); + zBuf = sqlite3_mprintf("%!.*f",n,r); if( zBuf==0 ){ sqlite3_result_error_nomem(context); return; @@ -126059,7 +127306,7 @@ struct compareInfo { /* ** For LIKE and GLOB matching on EBCDIC machines, assume that every -** character is exactly one byte in size. Also, provde the Utf8Read() +** character is exactly one byte in size. Also, provide the Utf8Read() ** macro for fast reading of the next character in the common case where ** the next character is ASCII. */ @@ -126292,7 +127539,7 @@ SQLITE_API int sqlite3_like_count = 0; /* ** Implementation of the like() SQL function. This function implements -** the build-in LIKE operator. The first argument to the function is the +** the built-in LIKE operator. The first argument to the function is the ** pattern and the second argument is the string. So, the SQL statements: ** ** A LIKE B @@ -126625,6 +127872,7 @@ static void charFunc( *zOut++ = 0x80 + (u8)(c & 0x3F); } \ } + *zOut = 0; sqlite3_result_text64(context, (char*)z, zOut-z, sqlite3_free, SQLITE_UTF8); } @@ -126678,7 +127926,7 @@ static int strContainsChar(const u8 *zStr, int nStr, u32 ch){ ** decoded and returned as a blob. ** ** If there is only a single argument, then it must consist only of an -** even number of hexadeximal digits. Otherwise, return NULL. +** even number of hexadecimal digits. Otherwise, return NULL. ** ** Or, if there is a second argument, then any character that appears in ** the second argument is also allowed to appear between pairs of hexadecimal @@ -127068,13 +128316,68 @@ static void loadExt(sqlite3_context *context, int argc, sqlite3_value **argv){ */ typedef struct SumCtx SumCtx; struct SumCtx { - double rSum; /* Floating point sum */ - i64 iSum; /* Integer sum */ + double rSum; /* Running sum as as a double */ + double rErr; /* Error term for Kahan-Babushka-Neumaier summation */ + i64 iSum; /* Running sum as a signed integer */ i64 cnt; /* Number of elements summed */ - u8 overflow; /* True if integer overflow seen */ - u8 approx; /* True if non-integer value was input to the sum */ + u8 approx; /* True if any non-integer value was input to the sum */ + u8 ovrfl; /* Integer overflow seen */ }; +/* +** Do one step of the Kahan-Babushka-Neumaier summation. +** +** https://en.wikipedia.org/wiki/Kahan_summation_algorithm +** +** Variables are marked "volatile" to defeat c89 x86 floating point +** optimizations can mess up this algorithm. +*/ +static void kahanBabuskaNeumaierStep( + volatile SumCtx *pSum, + volatile double r +){ + volatile double s = pSum->rSum; + volatile double t = s + r; + if( fabs(s) > fabs(r) ){ + pSum->rErr += (s - t) + r; + }else{ + pSum->rErr += (r - t) + s; + } + pSum->rSum = t; +} + +/* +** Add a (possibly large) integer to the running sum. +*/ +static void kahanBabuskaNeumaierStepInt64(volatile SumCtx *pSum, i64 iVal){ + if( iVal<=-4503599627370496LL || iVal>=+4503599627370496LL ){ + i64 iBig, iSm; + iSm = iVal % 16384; + iBig = iVal - iSm; + kahanBabuskaNeumaierStep(pSum, iBig); + kahanBabuskaNeumaierStep(pSum, iSm); + }else{ + kahanBabuskaNeumaierStep(pSum, (double)iVal); + } +} + +/* +** Initialize the Kahan-Babaska-Neumaier sum from a 64-bit integer +*/ +static void kahanBabuskaNeumaierInit( + volatile SumCtx *p, + i64 iVal +){ + if( iVal<=-4503599627370496LL || iVal>=+4503599627370496LL ){ + i64 iSm = iVal % 16384; + p->rSum = (double)(iVal - iSm); + p->rErr = (double)iSm; + }else{ + p->rSum = (double)iVal; + p->rErr = 0.0; + } +} + /* ** Routines used to compute the sum, average, and total. ** @@ -127094,15 +128397,29 @@ static void sumStep(sqlite3_context *context, int argc, sqlite3_value **argv){ type = sqlite3_value_numeric_type(argv[0]); if( p && type!=SQLITE_NULL ){ p->cnt++; - if( type==SQLITE_INTEGER ){ - i64 v = sqlite3_value_int64(argv[0]); - p->rSum += v; - if( (p->approx|p->overflow)==0 && sqlite3AddInt64(&p->iSum, v) ){ - p->approx = p->overflow = 1; + if( p->approx==0 ){ + if( type!=SQLITE_INTEGER ){ + kahanBabuskaNeumaierInit(p, p->iSum); + p->approx = 1; + kahanBabuskaNeumaierStep(p, sqlite3_value_double(argv[0])); + }else{ + i64 x = p->iSum; + if( sqlite3AddInt64(&x, sqlite3_value_int64(argv[0]))==0 ){ + p->iSum = x; + }else{ + p->ovrfl = 1; + kahanBabuskaNeumaierInit(p, p->iSum); + p->approx = 1; + kahanBabuskaNeumaierStepInt64(p, sqlite3_value_int64(argv[0])); + } } }else{ - p->rSum += sqlite3_value_double(argv[0]); - p->approx = 1; + if( type==SQLITE_INTEGER ){ + kahanBabuskaNeumaierStepInt64(p, sqlite3_value_int64(argv[0])); + }else{ + p->ovrfl = 0; + kahanBabuskaNeumaierStep(p, sqlite3_value_double(argv[0])); + } } } } @@ -127119,13 +128436,18 @@ static void sumInverse(sqlite3_context *context, int argc, sqlite3_value**argv){ if( ALWAYS(p) && type!=SQLITE_NULL ){ assert( p->cnt>0 ); p->cnt--; - assert( type==SQLITE_INTEGER || p->approx ); - if( type==SQLITE_INTEGER && p->approx==0 ){ - i64 v = sqlite3_value_int64(argv[0]); - p->rSum -= v; - p->iSum -= v; + if( !p->approx ){ + p->iSum -= sqlite3_value_int64(argv[0]); + }else if( type==SQLITE_INTEGER ){ + i64 iVal = sqlite3_value_int64(argv[0]); + if( iVal!=SMALLEST_INT64 ){ + kahanBabuskaNeumaierStepInt64(p, -iVal); + }else{ + kahanBabuskaNeumaierStepInt64(p, LARGEST_INT64); + kahanBabuskaNeumaierStepInt64(p, 1); + } }else{ - p->rSum -= sqlite3_value_double(argv[0]); + kahanBabuskaNeumaierStep(p, -sqlite3_value_double(argv[0])); } } } @@ -127136,10 +128458,12 @@ static void sumFinalize(sqlite3_context *context){ SumCtx *p; p = sqlite3_aggregate_context(context, 0); if( p && p->cnt>0 ){ - if( p->overflow ){ - sqlite3_result_error(context,"integer overflow",-1); - }else if( p->approx ){ - sqlite3_result_double(context, p->rSum); + if( p->approx ){ + if( p->ovrfl ){ + sqlite3_result_error(context,"integer overflow",-1); + }else{ + sqlite3_result_double(context, p->rSum+p->rErr); + } }else{ sqlite3_result_int64(context, p->iSum); } @@ -127149,14 +128473,27 @@ static void avgFinalize(sqlite3_context *context){ SumCtx *p; p = sqlite3_aggregate_context(context, 0); if( p && p->cnt>0 ){ - sqlite3_result_double(context, p->rSum/(double)p->cnt); + double r; + if( p->approx ){ + r = p->rSum+p->rErr; + }else{ + r = (double)(p->iSum); + } + sqlite3_result_double(context, r/(double)p->cnt); } } static void totalFinalize(sqlite3_context *context){ SumCtx *p; + double r = 0.0; p = sqlite3_aggregate_context(context, 0); - /* (double)0 In case of SQLITE_OMIT_FLOATING_POINT... */ - sqlite3_result_double(context, p ? p->rSum : (double)0); + if( p ){ + if( p->approx ){ + r = p->rSum+p->rErr; + }else{ + r = (double)(p->iSum); + } + } + sqlite3_result_double(context, r); } /* @@ -127378,7 +128715,7 @@ static void groupConcatInverse( if( sqlite3_value_type(argv[0])==SQLITE_NULL ) return; pGCC = (GroupConcatCtx*)sqlite3_aggregate_context(context, sizeof(*pGCC)); /* pGCC is always non-NULL since groupConcatStep() will have always - ** run frist to initialize it */ + ** run first to initialize it */ if( ALWAYS(pGCC) ){ int nVS; /* Must call sqlite3_value_text() to convert the argument into text prior @@ -127462,8 +128799,10 @@ SQLITE_PRIVATE void sqlite3RegisterPerConnectionBuiltinFunctions(sqlite3 *db){ ** sensitive. */ SQLITE_PRIVATE void sqlite3RegisterLikeFunctions(sqlite3 *db, int caseSensitive){ + FuncDef *pDef; struct compareInfo *pInfo; int flags; + int nArg; if( caseSensitive ){ pInfo = (struct compareInfo*)&likeInfoAlt; flags = SQLITE_FUNC_LIKE | SQLITE_FUNC_CASE; @@ -127471,10 +128810,13 @@ SQLITE_PRIVATE void sqlite3RegisterLikeFunctions(sqlite3 *db, int caseSensitive) pInfo = (struct compareInfo*)&likeInfoNorm; flags = SQLITE_FUNC_LIKE; } - sqlite3CreateFunc(db, "like", 2, SQLITE_UTF8, pInfo, likeFunc, 0, 0, 0, 0, 0); - sqlite3CreateFunc(db, "like", 3, SQLITE_UTF8, pInfo, likeFunc, 0, 0, 0, 0, 0); - sqlite3FindFunction(db, "like", 2, SQLITE_UTF8, 0)->funcFlags |= flags; - sqlite3FindFunction(db, "like", 3, SQLITE_UTF8, 0)->funcFlags |= flags; + for(nArg=2; nArg<=3; nArg++){ + sqlite3CreateFunc(db, "like", nArg, SQLITE_UTF8, pInfo, likeFunc, + 0, 0, 0, 0, 0); + pDef = sqlite3FindFunction(db, "like", nArg, SQLITE_UTF8, 0); + pDef->funcFlags |= flags; + pDef->funcFlags &= ~SQLITE_FUNC_UNSAFE; + } } /* @@ -127746,6 +129088,37 @@ static void signFunc( sqlite3_result_int(context, x<0.0 ? -1 : x>0.0 ? +1 : 0); } +#ifdef SQLITE_DEBUG +/* +** Implementation of fpdecode(x,y,z) function. +** +** x is a real number that is to be decoded. y is the precision. +** z is the maximum real precision. +*/ +static void fpdecodeFunc( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + FpDecode s; + double x; + int y, z; + char zBuf[100]; + UNUSED_PARAMETER(argc); + assert( argc==3 ); + x = sqlite3_value_double(argv[0]); + y = sqlite3_value_int(argv[1]); + z = sqlite3_value_int(argv[2]); + sqlite3FpDecode(&s, x, y, z); + if( s.isSpecial==2 ){ + sqlite3_snprintf(sizeof(zBuf), zBuf, "NaN"); + }else{ + sqlite3_snprintf(sizeof(zBuf), zBuf, "%c%.*s/%d", s.sign, s.n, s.z, s.iDP); + } + sqlite3_result_text(context, zBuf, -1, SQLITE_TRANSIENT); +} +#endif /* SQLITE_DEBUG */ + /* ** All of the FuncDef structures in the aBuiltinFunc[] array above ** to the global function hash table. This occurs at start-time (as @@ -127810,12 +129183,16 @@ SQLITE_PRIVATE void sqlite3RegisterBuiltinFunctions(void){ FUNCTION2(typeof, 1, 0, 0, typeofFunc, SQLITE_FUNC_TYPEOF), FUNCTION2(subtype, 1, 0, 0, subtypeFunc, SQLITE_FUNC_TYPEOF), FUNCTION2(length, 1, 0, 0, lengthFunc, SQLITE_FUNC_LENGTH), + FUNCTION2(octet_length, 1, 0, 0, bytelengthFunc,SQLITE_FUNC_BYTELEN), FUNCTION(instr, 2, 0, 0, instrFunc ), FUNCTION(printf, -1, 0, 0, printfFunc ), FUNCTION(format, -1, 0, 0, printfFunc ), FUNCTION(unicode, 1, 0, 0, unicodeFunc ), FUNCTION(char, -1, 0, 0, charFunc ), FUNCTION(abs, 1, 0, 0, absFunc ), +#ifdef SQLITE_DEBUG + FUNCTION(fpdecode, 3, 0, 0, fpdecodeFunc ), +#endif #ifndef SQLITE_OMIT_FLOATING_POINT FUNCTION(round, 1, 0, 0, roundFunc ), FUNCTION(round, 2, 0, 0, roundFunc ), @@ -129386,9 +130763,8 @@ SQLITE_PRIVATE void sqlite3FkDelete(sqlite3 *db, Table *pTab){ if( pFKey->pPrevTo ){ pFKey->pPrevTo->pNextTo = pFKey->pNextTo; }else{ - void *p = (void *)pFKey->pNextTo; - const char *z = (p ? pFKey->pNextTo->zTo : pFKey->zTo); - sqlite3HashInsert(&pTab->pSchema->fkeyHash, z, p); + const char *z = (pFKey->pNextTo ? pFKey->pNextTo->zTo : pFKey->zTo); + sqlite3HashInsert(&pTab->pSchema->fkeyHash, z, pFKey->pNextTo); } if( pFKey->pNextTo ){ pFKey->pNextTo->pPrevTo = pFKey->pPrevTo; @@ -129451,8 +130827,10 @@ SQLITE_PRIVATE void sqlite3OpenTable( assert( pParse->pVdbe!=0 ); v = pParse->pVdbe; assert( opcode==OP_OpenWrite || opcode==OP_OpenRead ); - sqlite3TableLock(pParse, iDb, pTab->tnum, - (opcode==OP_OpenWrite)?1:0, pTab->zName); + if( !pParse->db->noSharedCache ){ + sqlite3TableLock(pParse, iDb, pTab->tnum, + (opcode==OP_OpenWrite)?1:0, pTab->zName); + } if( HasRowid(pTab) ){ sqlite3VdbeAddOp4Int(v, opcode, iCur, pTab->tnum, iDb, pTab->nNVCol); VdbeComment((v, "%s", pTab->zName)); @@ -129581,7 +130959,7 @@ SQLITE_PRIVATE char *sqlite3TableAffinityStr(sqlite3 *db, const Table *pTab){ ** For STRICT tables: ** ------------------ ** -** Generate an appropropriate OP_TypeCheck opcode that will verify the +** Generate an appropriate OP_TypeCheck opcode that will verify the ** datatypes against the column definitions in pTab. If iReg==0, that ** means an OP_MakeRecord opcode has already been generated and should be ** the last opcode generated. The new OP_TypeCheck needs to be inserted @@ -130873,7 +132251,7 @@ insert_cleanup: /* This is the Walker callback from sqlite3ExprReferencesUpdatedColumn(). * Set bit 0x01 of pWalker->eCode if pWalker->eCode to 0 and if this ** expression node references any of the -** columns that are being modifed by an UPDATE statement. +** columns that are being modified by an UPDATE statement. */ static int checkConstraintExprNode(Walker *pWalker, Expr *pExpr){ if( pExpr->op==TK_COLUMN ){ @@ -131096,7 +132474,7 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks( int *aiChng, /* column i is unchanged if aiChng[i]<0 */ Upsert *pUpsert /* ON CONFLICT clauses, if any. NULL otherwise */ ){ - Vdbe *v; /* VDBE under constrution */ + Vdbe *v; /* VDBE under construction */ Index *pIdx; /* Pointer to one of the indices */ Index *pPk = 0; /* The PRIMARY KEY index for WITHOUT ROWID tables */ sqlite3 *db; /* Database connection */ @@ -131579,7 +132957,7 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks( pIdx; pIdx = indexIteratorNext(&sIdxIter, &ix) ){ - int regIdx; /* Range of registers hold conent for pIdx */ + int regIdx; /* Range of registers holding content for pIdx */ int regR; /* Range of registers holding conflicting PK */ int iThisCur; /* Cursor for this UNIQUE index */ int addrUniqueOk; /* Jump here if the UNIQUE constraint is satisfied */ @@ -132074,6 +133452,8 @@ SQLITE_PRIVATE int sqlite3OpenTableAndIndices( assert( op==OP_OpenRead || op==OP_OpenWrite ); assert( op==OP_OpenWrite || p5==0 ); + assert( piDataCur!=0 ); + assert( piIdxCur!=0 ); if( IsVirtual(pTab) ){ /* This routine is a no-op for virtual tables. Leave the output ** variables *piDataCur and *piIdxCur set to illegal cursor numbers @@ -132086,18 +133466,18 @@ SQLITE_PRIVATE int sqlite3OpenTableAndIndices( assert( v!=0 ); if( iBase<0 ) iBase = pParse->nTab; iDataCur = iBase++; - if( piDataCur ) *piDataCur = iDataCur; + *piDataCur = iDataCur; if( HasRowid(pTab) && (aToOpen==0 || aToOpen[0]) ){ sqlite3OpenTable(pParse, iDataCur, iDb, pTab, op); - }else{ + }else if( pParse->db->noSharedCache==0 ){ sqlite3TableLock(pParse, iDb, pTab->tnum, op==OP_OpenWrite, pTab->zName); } - if( piIdxCur ) *piIdxCur = iBase; + *piIdxCur = iBase; for(i=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){ int iIdxCur = iBase++; assert( pIdx->pSchema==pTab->pSchema ); if( IsPrimaryKeyIndex(pIdx) && !HasRowid(pTab) ){ - if( piDataCur ) *piDataCur = iIdxCur; + *piDataCur = iIdxCur; p5 = 0; } if( aToOpen==0 || aToOpen[i+1] ){ @@ -132395,7 +133775,7 @@ static int xferOptimization( } #endif #ifndef SQLITE_OMIT_FOREIGN_KEY - /* Disallow the transfer optimization if the destination table constains + /* Disallow the transfer optimization if the destination table contains ** any foreign key constraints. This is more restrictive than necessary. ** But the main beneficiary of the transfer optimization is the VACUUM ** command, and the VACUUM command disables foreign key constraints. So @@ -133105,6 +134485,8 @@ struct sqlite3_api_routines { int (*value_encoding)(sqlite3_value*); /* Version 3.41.0 and later */ int (*is_interrupted)(sqlite3*); + /* Version 3.43.0 and later */ + int (*stmt_explain)(sqlite3_stmt*,int); }; /* @@ -133433,6 +134815,8 @@ typedef int (*sqlite3_loadext_entry)( #define sqlite3_value_encoding sqlite3_api->value_encoding /* Version 3.41.0 and later */ #define sqlite3_is_interrupted sqlite3_api->is_interrupted +/* Version 3.43.0 and later */ +#define sqlite3_stmt_explain sqlite3_api->stmt_explain #endif /* !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) */ #if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) @@ -133949,7 +135333,9 @@ static const sqlite3_api_routines sqlite3Apis = { /* Version 3.40.0 and later */ sqlite3_value_encoding, /* Version 3.41.0 and later */ - sqlite3_is_interrupted + sqlite3_is_interrupted, + /* Version 3.43.0 and later */ + sqlite3_stmt_explain }; /* True if x is the directory separator character @@ -134029,6 +135415,10 @@ static int sqlite3LoadExtension( */ if( nMsg>SQLITE_MAX_PATHLEN ) goto extension_not_found; + /* Do not allow sqlite3_load_extension() to link to a copy of the + ** running application, by passing in an empty filename. */ + if( nMsg==0 ) goto extension_not_found; + handle = sqlite3OsDlOpen(pVfs, zFile); #if SQLITE_OS_UNIX || SQLITE_OS_WIN for(ii=0; iipParse; db->pParse = &sParse; sParse.db = db; - sParse.pReprepare = pReprepare; + if( pReprepare ){ + sParse.pReprepare = pReprepare; + sParse.explain = sqlite3_stmt_isexplain((sqlite3_stmt*)pReprepare); + }else{ + assert( sParse.pReprepare==0 ); + } assert( ppStmt && *ppStmt==0 ); if( db->mallocFailed ){ sqlite3ErrorMsg(&sParse, "out of memory"); @@ -139227,7 +140622,7 @@ static Select *findRightmost(Select *p){ ** NATURAL FULL OUTER JT_NATRUAL|JT_LEFT|JT_RIGHT ** ** To preserve historical compatibly, SQLite also accepts a variety -** of other non-standard and in many cases non-sensical join types. +** of other non-standard and in many cases nonsensical join types. ** This routine makes as much sense at it can from the nonsense join ** type and returns a result. Examples of accepted nonsense join types ** include but are not limited to: @@ -139498,7 +140893,7 @@ static int sqlite3ProcessJoin(Parse *pParse, Select *p){ if( NEVER(pLeft->pTab==0 || pRightTab==0) ) continue; joinType = (pRight->fg.jointype & JT_OUTER)!=0 ? EP_OuterON : EP_InnerON; - /* If this is a NATURAL join, synthesize an approprate USING clause + /* If this is a NATURAL join, synthesize an appropriate USING clause ** to specify which columns should be joined. */ if( pRight->fg.jointype & JT_NATURAL ){ @@ -139714,7 +141109,7 @@ static void pushOntoSorter( ** (3) Some output columns are omitted from the sort record due to ** the SQLITE_ENABLE_SORTER_REFERENCES optimization, or due to the ** SQLITE_ECEL_OMITREF optimization, or due to the - ** SortCtx.pDeferredRowLoad optimiation. In any of these cases + ** SortCtx.pDeferredRowLoad optimization. In any of these cases ** regOrigData is 0 to prevent this routine from trying to copy ** values that might not yet exist. */ @@ -139770,7 +141165,7 @@ static void pushOntoSorter( testcase( pKI->nAllField > pKI->nKeyField+2 ); pOp->p4.pKeyInfo = sqlite3KeyInfoFromExprList(pParse,pSort->pOrderBy,nOBSat, pKI->nAllField-pKI->nKeyField-1); - pOp = 0; /* Ensure pOp not used after sqltie3VdbeAddOp3() */ + pOp = 0; /* Ensure pOp not used after sqlite3VdbeAddOp3() */ addrJmp = sqlite3VdbeCurrentAddr(v); sqlite3VdbeAddOp3(v, OP_Jump, addrJmp+1, 0, addrJmp+1); VdbeCoverage(v); pSort->labelBkOut = sqlite3VdbeMakeLabel(pParse); @@ -139864,7 +141259,7 @@ static void codeOffset( ** The returned value in this case is a copy of parameter iTab. ** ** WHERE_DISTINCT_ORDERED: -** In this case rows are being delivered sorted order. The ephermal +** In this case rows are being delivered sorted order. The ephemeral ** table is not required. Instead, the current set of values ** is compared against previous row. If they match, the new row ** is not distinct and control jumps to VM address addrRepeat. Otherwise, @@ -140293,6 +141688,16 @@ static void selectInnerLoop( testcase( eDest==SRT_Fifo ); testcase( eDest==SRT_DistFifo ); sqlite3VdbeAddOp3(v, OP_MakeRecord, regResult, nResultCol, r1+nPrefixReg); +#if !defined(SQLITE_ENABLE_NULL_TRIM) && defined(SQLITE_DEBUG) + /* A destination of SRT_Table and a non-zero iSDParm2 parameter means + ** that this is an "UPDATE ... FROM" on a virtual table or view. In this + ** case set the p5 parameter of the OP_MakeRecord to OPFLAG_NOCHNG_MAGIC. + ** This does not affect operation in any way - it just allows MakeRecord + ** to process OPFLAG_NOCHANGE values without an assert() failing. */ + if( eDest==SRT_Table && pDest->iSDParm2 ){ + sqlite3VdbeChangeP5(v, OPFLAG_NOCHNG_MAGIC); + } +#endif #ifndef SQLITE_OMIT_CTE if( eDest==SRT_DistFifo ){ /* If the destination is DistFifo, then cursor (iParm+1) is open @@ -141096,13 +142501,6 @@ SQLITE_PRIVATE void sqlite3GenerateColumnNames( int fullName; /* TABLE.COLUMN if no AS clause and is a direct table ref */ int srcName; /* COLUMN or TABLE.COLUMN if no AS clause and is direct */ -#ifndef SQLITE_OMIT_EXPLAIN - /* If this is an EXPLAIN, skip this step */ - if( pParse->explain ){ - return; - } -#endif - if( pParse->colNamesSet ) return; /* Column names are determined by the left-most term of a compound select */ while( pSelect->pPrior ) pSelect = pSelect->pPrior; @@ -141289,7 +142687,7 @@ SQLITE_PRIVATE int sqlite3ColumnsFromExprList( ** kind (maybe a parenthesized subquery in the FROM clause of a larger ** query, or a VIEW, or a CTE). This routine computes type information ** for that Table object based on the Select object that implements the -** subquery. For the purposes of this routine, "type infomation" means: +** subquery. For the purposes of this routine, "type information" means: ** ** * The datatype name, as it might appear in a CREATE TABLE statement ** * Which collating sequence to use for the column @@ -141618,7 +143016,7 @@ static void generateWithRecursiveQuery( int iQueue; /* The Queue table */ int iDistinct = 0; /* To ensure unique results if UNION */ int eDest = SRT_Fifo; /* How to write to Queue */ - SelectDest destQueue; /* SelectDest targetting the Queue table */ + SelectDest destQueue; /* SelectDest targeting the Queue table */ int i; /* Loop counter */ int rc; /* Result code */ ExprList *pOrderBy; /* The ORDER BY clause */ @@ -142218,7 +143616,7 @@ SQLITE_PRIVATE void sqlite3SelectWrongNumTermsError(Parse *pParse, Select *p){ /* ** Code an output subroutine for a coroutine implementation of a -** SELECT statment. +** SELECT statement. ** ** The data to be output is contained in pIn->iSdst. There are ** pIn->nSdst columns to be output. pDest is where the output should @@ -142440,7 +143838,7 @@ static int generateOutputSubroutine( ** ** We call AltB, AeqB, AgtB, EofA, and EofB "subroutines" but they are not ** actually called using Gosub and they do not Return. EofA and EofB loop -** until all data is exhausted then jump to the "end" labe. AltB, AeqB, +** until all data is exhausted then jump to the "end" label. AltB, AeqB, ** and AgtB jump to either L2 or to one of EofA or EofB. */ #ifndef SQLITE_OMIT_COMPOUND_SELECT @@ -142477,7 +143875,7 @@ static int multiSelectOrderBy( int savedOffset; /* Saved value of p->iOffset */ int labelCmpr; /* Label for the start of the merge algorithm */ int labelEnd; /* Label for the end of the overall SELECT stmt */ - int addr1; /* Jump instructions that get retargetted */ + int addr1; /* Jump instructions that get retargeted */ int op; /* One of TK_ALL, TK_UNION, TK_EXCEPT, TK_INTERSECT */ KeyInfo *pKeyDup = 0; /* Comparison information for duplicate removal */ KeyInfo *pKeyMerge; /* Comparison information for merging rows */ @@ -142846,11 +144244,14 @@ static Expr *substExpr( #endif { Expr *pNew; - int iColumn = pExpr->iColumn; - Expr *pCopy = pSubst->pEList->a[iColumn].pExpr; + int iColumn; + Expr *pCopy; Expr ifNullRow; + iColumn = pExpr->iColumn; + assert( iColumn>=0 ); assert( pSubst->pEList!=0 && iColumnpEList->nExpr ); assert( pExpr->pRight==0 ); + pCopy = pSubst->pEList->a[iColumn].pExpr; if( sqlite3ExprIsVector(pCopy) ){ sqlite3VectorErrorMsg(pSubst->pParse, pCopy); }else{ @@ -143199,7 +144600,7 @@ static int compoundHasDifferentAffinities(Select *p){ ** (9) If the subquery uses LIMIT then the outer query may not be aggregate. ** ** (**) Restriction (10) was removed from the code on 2005-02-05 but we -** accidently carried the comment forward until 2014-09-15. Original +** accidentally carried the comment forward until 2014-09-15. Original ** constraint: "If the subquery is aggregate then the outer query ** may not use LIMIT." ** @@ -143291,7 +144692,8 @@ static int compoundHasDifferentAffinities(Select *p){ ** (27b) the subquery is a compound query and the RIGHT JOIN occurs ** in any arm of the compound query. (See also (17g).) ** -** (28) The subquery is not a MATERIALIZED CTE. +** (28) The subquery is not a MATERIALIZED CTE. (This is handled +** in the caller before ever reaching this routine.) ** ** ** In this routine, the "p" parameter is a pointer to the outer query. @@ -143401,9 +144803,9 @@ static int flattenSubquery( if( iFrom>0 && (pSubSrc->a[0].fg.jointype & JT_LTORJ)!=0 ){ return 0; /* Restriction (27a) */ } - if( pSubitem->fg.isCte && pSubitem->u2.pCteUse->eM10d==M10d_Yes ){ - return 0; /* (28) */ - } + + /* Condition (28) is blocked by the caller */ + assert( !pSubitem->fg.isCte || pSubitem->u2.pCteUse->eM10d!=M10d_Yes ); /* Restriction (17): If the sub-query is a compound SELECT, then it must ** use only the UNION ALL operator. And none of the simple select queries @@ -143473,7 +144875,7 @@ static int flattenSubquery( testcase( i==SQLITE_DENY ); pParse->zAuthContext = zSavedAuthContext; - /* Delete the transient structures associated with thesubquery */ + /* Delete the transient structures associated with the subquery */ pSub1 = pSubitem->pSelect; sqlite3DbFree(db, pSubitem->zDatabase); sqlite3DbFree(db, pSubitem->zName); @@ -143655,7 +145057,7 @@ static int flattenSubquery( ** ORDER BY column expression is identical to the iOrderByCol'th ** expression returned by SELECT statement pSub. Since these values ** do not necessarily correspond to columns in SELECT statement pParent, - ** zero them before transfering the ORDER BY clause. + ** zero them before transferring the ORDER BY clause. ** ** Not doing this may cause an error if a subsequent call to this ** function attempts to flatten a compound sub-query into pParent @@ -143715,8 +145117,7 @@ static int flattenSubquery( } } - /* Finially, delete what is left of the subquery and return - ** success. + /* Finally, delete what is left of the subquery and return success. */ sqlite3AggInfoPersistWalkerInit(&w, pParse); sqlite3WalkSelect(&w,pSub1); @@ -143751,7 +145152,7 @@ struct WhereConst { /* ** Add a new entry to the pConst object. Except, do not add duplicate -** pColumn entires. Also, do not add if doing so would not be appropriate. +** pColumn entries. Also, do not add if doing so would not be appropriate. ** ** The caller guarantees the pColumn is a column and pValue is a constant. ** This routine has to do some additional checks before completing the @@ -143937,7 +145338,7 @@ static int propagateConstantExprRewrite(Walker *pWalker, Expr *pExpr){ ** SELECT * FROM t1 WHERE a=123 AND b=123; ** ** The two SELECT statements above should return different answers. b=a -** is alway true because the comparison uses numeric affinity, but b=123 +** is always true because the comparison uses numeric affinity, but b=123 ** is false because it uses text affinity and '0123' is not the same as '123'. ** To work around this, the expression tree is not actually changed from ** "b=a" to "b=123" but rather the "a" in "b=a" is tagged with EP_FixedCol @@ -144021,7 +145422,7 @@ static int propagateConstants( ** At the time this function is called it is guaranteed that ** ** * the sub-query uses only one distinct window frame, and -** * that the window frame has a PARTITION BY clase. +** * that the window frame has a PARTITION BY clause. */ static int pushDownWindowCheck(Parse *pParse, Select *pSubq, Expr *pExpr){ assert( pSubq->pWin->pPartition ); @@ -145101,10 +146502,16 @@ static int selectExpander(Walker *pWalker, Select *p){ ** expanded. */ int tableSeen = 0; /* Set to 1 when TABLE matches */ char *zTName = 0; /* text of name of TABLE */ + int iErrOfst; if( pE->op==TK_DOT ){ assert( pE->pLeft!=0 ); assert( !ExprHasProperty(pE->pLeft, EP_IntValue) ); zTName = pE->pLeft->u.zToken; + assert( ExprUseWOfst(pE->pLeft) ); + iErrOfst = pE->pRight->w.iOfst; + }else{ + assert( ExprUseWOfst(pE) ); + iErrOfst = pE->w.iOfst; } for(i=0, pFrom=pTabList->a; inSrc; i++, pFrom++){ Table *pTab = pFrom->pTab; /* Table for this data source */ @@ -145141,6 +146548,7 @@ static int selectExpander(Walker *pWalker, Select *p){ for(ii=0; iinId; ii++){ const char *zUName = pUsing->a[ii].zName; pRight = sqlite3Expr(db, TK_ID, zUName); + sqlite3ExprSetErrorOffset(pRight, iErrOfst); pNew = sqlite3ExprListAppend(pParse, pNew, pRight); if( pNew ){ struct ExprList_item *pX = &pNew->a[pNew->nExpr-1]; @@ -145213,6 +146621,7 @@ static int selectExpander(Walker *pWalker, Select *p){ }else{ pExpr = pRight; } + sqlite3ExprSetErrorOffset(pExpr, iErrOfst); pNew = sqlite3ExprListAppend(pParse, pNew, pExpr); if( pNew==0 ){ break; /* OOM */ @@ -145529,7 +146938,7 @@ static int aggregateIdxEprRefToColCallback(Walker *pWalker, Expr *pExpr){ pExpr->op = TK_AGG_COLUMN; pExpr->iTable = pCol->iTable; pExpr->iColumn = pCol->iColumn; - ExprClearProperty(pExpr, EP_Skip|EP_Collate); + ExprClearProperty(pExpr, EP_Skip|EP_Collate|EP_Unlikely); return WRC_Prune; } @@ -145560,7 +146969,7 @@ static void aggregateConvertIndexedExprRefToColumn(AggInfo *pAggInfo){ ** * The aCol[] and aFunc[] arrays may be modified ** * The AggInfoColumnReg() and AggInfoFuncReg() macros may not be used ** -** After clling this routine: +** After calling this routine: ** ** * The aCol[] and aFunc[] arrays are fixed ** * The AggInfoColumnReg() and AggInfoFuncReg() macros may be used @@ -146214,22 +147623,59 @@ SQLITE_PRIVATE int sqlite3Select( ** to a real table */ assert( pTab!=0 ); - /* Convert LEFT JOIN into JOIN if there are terms of the right table - ** of the LEFT JOIN used in the WHERE clause. + /* Try to simplify joins: + ** + ** LEFT JOIN -> JOIN + ** RIGHT JOIN -> JOIN + ** FULL JOIN -> RIGHT JOIN + ** + ** If terms of the i-th table are used in the WHERE clause in such a + ** way that the i-th table cannot be the NULL row of a join, then + ** perform the appropriate simplification. This is called + ** "OUTER JOIN strength reduction" in the SQLite documentation. */ - if( (pItem->fg.jointype & (JT_LEFT|JT_RIGHT))==JT_LEFT - && sqlite3ExprImpliesNonNullRow(p->pWhere, pItem->iCursor) + if( (pItem->fg.jointype & (JT_LEFT|JT_LTORJ))!=0 + && sqlite3ExprImpliesNonNullRow(p->pWhere, pItem->iCursor, + pItem->fg.jointype & JT_LTORJ) && OptimizationEnabled(db, SQLITE_SimplifyJoin) ){ - TREETRACE(0x1000,pParse,p, - ("LEFT-JOIN simplifies to JOIN on term %d\n",i)); - pItem->fg.jointype &= ~(JT_LEFT|JT_OUTER); + if( pItem->fg.jointype & JT_LEFT ){ + if( pItem->fg.jointype & JT_RIGHT ){ + TREETRACE(0x1000,pParse,p, + ("FULL-JOIN simplifies to RIGHT-JOIN on term %d\n",i)); + pItem->fg.jointype &= ~JT_LEFT; + }else{ + TREETRACE(0x1000,pParse,p, + ("LEFT-JOIN simplifies to JOIN on term %d\n",i)); + pItem->fg.jointype &= ~(JT_LEFT|JT_OUTER); + } + } + if( pItem->fg.jointype & JT_LTORJ ){ + for(j=i+1; jnSrc; j++){ + SrcItem *pI2 = &pTabList->a[j]; + if( pI2->fg.jointype & JT_RIGHT ){ + if( pI2->fg.jointype & JT_LEFT ){ + TREETRACE(0x1000,pParse,p, + ("FULL-JOIN simplifies to LEFT-JOIN on term %d\n",j)); + pI2->fg.jointype &= ~JT_RIGHT; + }else{ + TREETRACE(0x1000,pParse,p, + ("RIGHT-JOIN simplifies to JOIN on term %d\n",j)); + pI2->fg.jointype &= ~(JT_RIGHT|JT_OUTER); + } + } + } + for(j=pTabList->nSrc-1; j>=i; j--){ + pTabList->a[j].fg.jointype &= ~JT_LTORJ; + if( pTabList->a[j].fg.jointype & JT_RIGHT ) break; + } + } assert( pItem->iCursor>=0 ); unsetJoinExpr(p->pWhere, pItem->iCursor, pTabList->a[0].fg.jointype & JT_LTORJ); } - /* No futher action if this term of the FROM clause is not a subquery */ + /* No further action if this term of the FROM clause is not a subquery */ if( pSub==0 ) continue; /* Catch mismatch in the declared columns of a view and the number of @@ -146240,6 +147686,14 @@ SQLITE_PRIVATE int sqlite3Select( goto select_end; } + /* Do not attempt the usual optimizations (flattening and ORDER BY + ** elimination) on a MATERIALIZED common table expression because + ** a MATERIALIZED common table expression is an optimization fence. + */ + if( pItem->fg.isCte && pItem->u2.pCteUse->eM10d==M10d_Yes ){ + continue; + } + /* Do not try to flatten an aggregate subquery. ** ** Flattening an aggregate subquery is only possible if the outer query @@ -146269,6 +147723,8 @@ SQLITE_PRIVATE int sqlite3Select( ** (a) The outer query has a different ORDER BY clause ** (b) The subquery is part of a join ** See forum post 062d576715d277c8 + ** + ** Also retain the ORDER BY if the OmitOrderBy optimization is disabled. */ if( pSub->pOrderBy!=0 && (p->pOrderBy!=0 || pTabList->nSrc>1) /* Condition (5) */ @@ -146483,7 +147939,7 @@ SQLITE_PRIVATE int sqlite3Select( }else if( pItem->fg.isCte && pItem->u2.pCteUse->addrM9e>0 ){ /* This is a CTE for which materialization code has already been ** generated. Invoke the subroutine to compute the materialization, - ** the make the pItem->iCursor be a copy of the ephemerial table that + ** the make the pItem->iCursor be a copy of the ephemeral table that ** holds the result of the materialization. */ CteUse *pCteUse = pItem->u2.pCteUse; sqlite3VdbeAddOp2(v, OP_Gosub, pCteUse->regRtn, pCteUse->addrM9e); @@ -146866,7 +148322,7 @@ SQLITE_PRIVATE int sqlite3Select( */ if( pGroupBy ){ KeyInfo *pKeyInfo; /* Keying information for the group by clause */ - int addr1; /* A-vs-B comparision jump */ + int addr1; /* A-vs-B comparison jump */ int addrOutputRow; /* Start of subroutine that outputs a result row */ int regOutputRow; /* Return address register for output subroutine */ int addrSetAbort; /* Set the abort flag and return */ @@ -146957,9 +148413,13 @@ SQLITE_PRIVATE int sqlite3Select( int nCol; int nGroupBy; - explainTempTable(pParse, +#ifdef SQLITE_ENABLE_STMT_SCANSTATUS + int addrExp; /* Address of OP_Explain instruction */ +#endif + ExplainQueryPlan2(addrExp, (pParse, 0, "USE TEMP B-TREE FOR %s", (sDistinct.isTnct && (p->selFlags&SF_Distinct)==0) ? - "DISTINCT" : "GROUP BY"); + "DISTINCT" : "GROUP BY" + )); groupBySort = 1; nGroupBy = pGroupBy->nExpr; @@ -146984,18 +148444,23 @@ SQLITE_PRIVATE int sqlite3Select( } pAggInfo->directMode = 0; regRecord = sqlite3GetTempReg(pParse); + sqlite3VdbeScanStatusCounters(v, addrExp, 0, sqlite3VdbeCurrentAddr(v)); sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase, nCol, regRecord); sqlite3VdbeAddOp2(v, OP_SorterInsert, pAggInfo->sortingIdx, regRecord); + sqlite3VdbeScanStatusRange(v, addrExp, sqlite3VdbeCurrentAddr(v)-2, -1); sqlite3ReleaseTempReg(pParse, regRecord); sqlite3ReleaseTempRange(pParse, regBase, nCol); TREETRACE(0x2,pParse,p,("WhereEnd\n")); sqlite3WhereEnd(pWInfo); pAggInfo->sortingIdxPTab = sortPTab = pParse->nTab++; sortOut = sqlite3GetTempReg(pParse); + sqlite3VdbeScanStatusCounters(v, addrExp, sqlite3VdbeCurrentAddr(v), 0); sqlite3VdbeAddOp3(v, OP_OpenPseudo, sortPTab, sortOut, nCol); sqlite3VdbeAddOp2(v, OP_SorterSort, pAggInfo->sortingIdx, addrEnd); VdbeComment((v, "GROUP BY sort")); VdbeCoverage(v); pAggInfo->useSortingIdx = 1; + sqlite3VdbeScanStatusRange(v, addrExp, -1, sortPTab); + sqlite3VdbeScanStatusRange(v, addrExp, -1, pAggInfo->sortingIdx); } /* If there are entries in pAgggInfo->aFunc[] that contain subexpressions @@ -149246,7 +150711,7 @@ static void updateFromSelect( assert( pTabList->nSrc>1 ); if( pSrc ){ - pSrc->a[0].fg.notCte = 1; + assert( pSrc->a[0].fg.notCte ); pSrc->a[0].iCursor = -1; pSrc->a[0].pTab->nTabRef--; pSrc->a[0].pTab = 0; @@ -149763,7 +151228,7 @@ SQLITE_PRIVATE void sqlite3Update( && !hasFK && !chngKey && !bReplace - && (sNC.ncFlags & NC_Subquery)==0 + && (pWhere==0 || !ExprHasProperty(pWhere, EP_Subquery)) ){ flags |= WHERE_ONEPASS_MULTIROW; } @@ -149835,6 +151300,8 @@ SQLITE_PRIVATE void sqlite3Update( if( !isView ){ int addrOnce = 0; + int iNotUsed1 = 0; + int iNotUsed2 = 0; /* Open every index that needs updating. */ if( eOnePass!=ONEPASS_OFF ){ @@ -149846,7 +151313,7 @@ SQLITE_PRIVATE void sqlite3Update( addrOnce = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v); } sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenWrite, 0, iBaseCur, - aToOpen, 0, 0); + aToOpen, &iNotUsed1, &iNotUsed2); if( addrOnce ){ sqlite3VdbeJumpHereOrPopInst(v, addrOnce); } @@ -150137,8 +151604,10 @@ SQLITE_PRIVATE void sqlite3Update( sqlite3VdbeAddOp2(v, OP_AddImm, regRowCount, 1); } - sqlite3CodeRowTrigger(pParse, pTrigger, TK_UPDATE, pChanges, - TRIGGER_AFTER, pTab, regOldRowid, onError, labelContinue); + if( pTrigger ){ + sqlite3CodeRowTrigger(pParse, pTrigger, TK_UPDATE, pChanges, + TRIGGER_AFTER, pTab, regOldRowid, onError, labelContinue); + } /* Repeat the above with the next record to be updated, until ** all record selected by the WHERE clause have been updated. @@ -150233,7 +151702,7 @@ static void updateVirtualTable( int nArg = 2 + pTab->nCol; /* Number of arguments to VUpdate */ int regArg; /* First register in VUpdate arg array */ int regRec; /* Register in which to assemble record */ - int regRowid; /* Register for ephem table rowid */ + int regRowid; /* Register for ephemeral table rowid */ int iCsr = pSrc->a[0].iCursor; /* Cursor used for virtual table scan */ int aDummy[2]; /* Unused arg for sqlite3WhereOkOnePass() */ int eOnePass; /* True to use onepass strategy */ @@ -150277,7 +151746,9 @@ static void updateVirtualTable( sqlite3ExprDup(db, pChanges->a[aXRef[i]].pExpr, 0) ); }else{ - pList = sqlite3ExprListAppend(pParse, pList, exprRowColumn(pParse, i)); + Expr *pRowExpr = exprRowColumn(pParse, i); + if( pRowExpr ) pRowExpr->op2 = OPFLAG_NOCHNG; + pList = sqlite3ExprListAppend(pParse, pList, pRowExpr); } } @@ -150354,7 +151825,7 @@ static void updateVirtualTable( sqlite3WhereEnd(pWInfo); } - /* Begin scannning through the ephemeral table. */ + /* Begin scanning through the ephemeral table. */ addr = sqlite3VdbeAddOp1(v, OP_Rewind, ephemTab); VdbeCoverage(v); /* Extract arguments from the current row of the ephemeral table and @@ -150562,7 +152033,7 @@ SQLITE_PRIVATE int sqlite3UpsertAnalyzeTarget( pExpr = &sCol[0]; } for(jj=0; jja[jj].pExpr,pExpr,iCursor)<2 ){ + if( sqlite3ExprCompare(0,pTarget->a[jj].pExpr,pExpr,iCursor)<2 ){ break; /* Column ii of the index matches column jj of target */ } } @@ -150911,7 +152382,7 @@ SQLITE_PRIVATE SQLITE_NOINLINE int sqlite3RunVacuum( ** (possibly synchronous) transaction opened on the main database before ** sqlite3BtreeCopyFile() is called. ** - ** An optimisation would be to use a non-journaled pager. + ** An optimization would be to use a non-journaled pager. ** (Later:) I tried setting "PRAGMA vacuum_db.journal_mode=OFF" but ** that actually made the VACUUM run slower. Very little journalling ** actually occurs when doing a vacuum since the vacuum_db is initially @@ -151600,7 +153071,7 @@ SQLITE_PRIVATE void sqlite3VtabFinishParse(Parse *pParse, Token *pEnd){ ** the information we've collected. ** ** The VM register number pParse->regRowid holds the rowid of an - ** entry in the sqlite_schema table tht was created for this vtab + ** entry in the sqlite_schema table that was created for this vtab ** by sqlite3StartTable(). */ iDb = sqlite3SchemaToIndex(db, pTab->pSchema); @@ -152344,7 +153815,7 @@ SQLITE_PRIVATE void sqlite3VtabMakeWritable(Parse *pParse, Table *pTab){ ** ** An eponymous virtual table instance is one that is named after its ** module, and more importantly, does not require a CREATE VIRTUAL TABLE -** statement in order to come into existance. Eponymous virtual table +** statement in order to come into existence. Eponymous virtual table ** instances always exist. They cannot be DROP-ed. ** ** Any virtual table module for which xConnect and xCreate are the same @@ -152535,7 +154006,7 @@ typedef struct WhereRightJoin WhereRightJoin; /* ** This object is a header on a block of allocated memory that will be -** automatically freed when its WInfo oject is destructed. +** automatically freed when its WInfo object is destructed. */ struct WhereMemBlock { WhereMemBlock *pNext; /* Next block in the chain */ @@ -152596,7 +154067,7 @@ struct WhereLevel { int iCur; /* The VDBE cursor used by this IN operator */ int addrInTop; /* Top of the IN loop */ int iBase; /* Base register of multi-key index record */ - int nPrefix; /* Number of prior entires in the key */ + int nPrefix; /* Number of prior entries in the key */ u8 eEndLoopOp; /* IN Loop terminator. OP_Next or OP_Prev */ } *aInLoop; /* Information about each nested IN operator */ } in; /* Used when pWLoop->wsFlags&WHERE_IN_ABLE */ @@ -152846,7 +154317,7 @@ struct WhereClause { int nTerm; /* Number of terms */ int nSlot; /* Number of entries in a[] */ int nBase; /* Number of terms through the last non-Virtual */ - WhereTerm *a; /* Each a[] describes a term of the WHERE cluase */ + WhereTerm *a; /* Each a[] describes a term of the WHERE clause */ #if defined(SQLITE_SMALL_STACK) WhereTerm aStatic[1]; /* Initial static space for a[] */ #else @@ -153434,6 +154905,12 @@ SQLITE_PRIVATE void sqlite3WhereAddScanStatus( if( wsFlags & WHERE_INDEXED ){ sqlite3VdbeScanStatusRange(v, addrExplain, -1, pLvl->iIdxCur); } + }else{ + int addr = pSrclist->a[pLvl->iFrom].addrFillSub; + VdbeOp *pOp = sqlite3VdbeGetOp(v, addr-1); + assert( sqlite3VdbeDb(v)->mallocFailed || pOp->opcode==OP_InitCoroutine ); + assert( sqlite3VdbeDb(v)->mallocFailed || pOp->p2>addr ); + sqlite3VdbeScanStatusRange(v, addrExplain, addr, pOp->p2-1); } } } @@ -153931,7 +155408,7 @@ static int codeAllEqualityTerms( /* Figure out how many memory cells we will need then allocate them. */ regBase = pParse->nMem + 1; - nReg = pLoop->u.btree.nEq + nExtraReg; + nReg = nEq + nExtraReg; pParse->nMem += nReg; zAff = sqlite3DbStrDup(pParse->db,sqlite3IndexAffinityStr(pParse->db,pIdx)); @@ -153978,9 +155455,6 @@ static int codeAllEqualityTerms( sqlite3VdbeAddOp2(v, OP_Copy, r1, regBase+j); } } - } - for(j=nSkip; jaLTerm[j]; if( pTerm->eOperator & WO_IN ){ if( pTerm->pExpr->flags & EP_xIsSelect ){ /* No affinity ever needs to be (or should be) applied to a value @@ -154123,7 +155597,7 @@ static int codeCursorHintIsOrFunction(Walker *pWalker, Expr *pExpr){ ** 2) transform the expression node to a TK_REGISTER node that reads ** from the newly populated register. ** -** Also, if the node is a TK_COLUMN that does access the table idenified +** Also, if the node is a TK_COLUMN that does access the table identified ** by pCCurHint.iTabCur, and an index is being used (which we will ** know because CCurHint.pIdx!=0) then transform the TK_COLUMN into ** an access of the index rather than the original table. @@ -154741,7 +156215,7 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart( }; assert( TK_LE==TK_GT+1 ); /* Make sure the ordering.. */ assert( TK_LT==TK_GT+2 ); /* ... of the TK_xx values... */ - assert( TK_GE==TK_GT+3 ); /* ... is correcct. */ + assert( TK_GE==TK_GT+3 ); /* ... is correct. */ assert( (pStart->wtFlags & TERM_VNULL)==0 ); testcase( pStart->wtFlags & TERM_VIRTUAL ); @@ -155921,7 +157395,7 @@ SQLITE_PRIVATE SQLITE_NOINLINE void sqlite3WhereRightJoinLoop( ** the WHERE clause of SQL statements. ** ** This file was originally part of where.c but was split out to improve -** readability and editabiliity. This file contains utility routines for +** readability and editability. This file contains utility routines for ** analyzing Expr objects in the WHERE clause. */ /* #include "sqliteInt.h" */ @@ -156137,7 +157611,7 @@ static int isLikeOrGlob( ** range search. The third is because the caller assumes that the pattern ** consists of at least one character after all escapes have been ** removed. */ - if( cnt!=0 && 255!=(u8)z[cnt-1] && (cnt>1 || z[0]!=wc[3]) ){ + if( (cnt>1 || (cnt>0 && z[0]!=wc[3])) && 255!=(u8)z[cnt-1] ){ Expr *pPrefix; /* A "complete" match if the pattern ends with "*" or "%" */ @@ -156710,7 +158184,7 @@ static void exprAnalyzeOrTerm( pOrTerm->leftCursor))==0 ){ /* This term must be of the form t1.a==t2.b where t2 is in the ** chngToIN set but t1 is not. This term will be either preceded - ** or follwed by an inverted copy (t2.b==t1.a). Skip this term + ** or followed by an inverted copy (t2.b==t1.a). Skip this term ** and use its inversion. */ testcase( pOrTerm->wtFlags & TERM_COPIED ); testcase( pOrTerm->wtFlags & TERM_VIRTUAL ); @@ -156972,8 +158446,8 @@ static void exprAnalyze( WhereTerm *pTerm; /* The term to be analyzed */ WhereMaskSet *pMaskSet; /* Set of table index masks */ Expr *pExpr; /* The expression to be analyzed */ - Bitmask prereqLeft; /* Prerequesites of the pExpr->pLeft */ - Bitmask prereqAll; /* Prerequesites of pExpr */ + Bitmask prereqLeft; /* Prerequisites of the pExpr->pLeft */ + Bitmask prereqAll; /* Prerequisites of pExpr */ Bitmask extraRight = 0; /* Extra dependencies on LEFT JOIN */ Expr *pStr1 = 0; /* RHS of LIKE/GLOB operator */ int isComplete = 0; /* RHS of LIKE/GLOB ends with wildcard */ @@ -159534,7 +161008,7 @@ SQLITE_PRIVATE char sqlite3IndexColumnAffinity(sqlite3 *db, Index *pIdx, int iCo ** Value pLoop->nOut is currently set to the estimated number of rows ** visited for scanning (a=? AND b=?). This function reduces that estimate ** by some factor to account for the (c BETWEEN ? AND ?) expression based -** on the stat4 data for the index. this scan will be peformed multiple +** on the stat4 data for the index. this scan will be performed multiple ** times (once for each (a,b) combination that matches a=?) is dealt with ** by the caller. ** @@ -160289,7 +161763,7 @@ static WhereLoop **whereLoopFindLesser( ** rSetup. Call this SETUP-INVARIANT */ assert( p->rSetup>=pTemplate->rSetup ); - /* Any loop using an appliation-defined index (or PRIMARY KEY or + /* Any loop using an application-defined index (or PRIMARY KEY or ** UNIQUE constraint) with one or more == constraints is better ** than an automatic index. Unless it is a skip-scan. */ if( (p->wsFlags & WHERE_AUTO_INDEX)!=0 @@ -160316,7 +161790,7 @@ static WhereLoop **whereLoopFindLesser( /* If pTemplate is always better than p, then cause p to be overwritten ** with pTemplate. pTemplate is better than p if: - ** (1) pTemplate has no more dependences than p, and + ** (1) pTemplate has no more dependencies than p, and ** (2) pTemplate has an equal or lower cost than p. */ if( (p->prereq & pTemplate->prereq)==pTemplate->prereq /* (1) */ @@ -160434,7 +161908,7 @@ static int whereLoopInsert(WhereLoopBuilder *pBuilder, WhereLoop *pTemplate){ }else{ /* We will be overwriting WhereLoop p[]. But before we do, first ** go through the rest of the list and delete any other entries besides - ** p[] that are also supplated by pTemplate */ + ** p[] that are also supplanted by pTemplate */ WhereLoop **ppTail = &p->pNextLoop; WhereLoop *pToDel; while( *ppTail ){ @@ -160634,7 +162108,7 @@ static int whereRangeVectorLen( } /* -** Adjust the cost C by the costMult facter T. This only occurs if +** Adjust the cost C by the costMult factor T. This only occurs if ** compiled with -DSQLITE_ENABLE_COSTMULT */ #ifdef SQLITE_ENABLE_COSTMULT @@ -160661,7 +162135,7 @@ static int whereLoopAddBtreeIndex( Index *pProbe, /* An index on pSrc */ LogEst nInMul /* log(Number of iterations due to IN) */ ){ - WhereInfo *pWInfo = pBuilder->pWInfo; /* WHERE analyse context */ + WhereInfo *pWInfo = pBuilder->pWInfo; /* WHERE analyze context */ Parse *pParse = pWInfo->pParse; /* Parsing context */ sqlite3 *db = pParse->db; /* Database connection malloc context */ WhereLoop *pNew; /* Template WhereLoop under construction */ @@ -160971,7 +162445,7 @@ static int whereLoopAddBtreeIndex( assert( pSrc->pTab->szTabRow>0 ); if( pProbe->idxType==SQLITE_IDXTYPE_IPK ){ /* The pProbe->szIdxRow is low for an IPK table since the interior - ** pages are small. Thuse szIdxRow gives a good estimate of seek cost. + ** pages are small. Thus szIdxRow gives a good estimate of seek cost. ** But the leaf pages are full-size, so pProbe->szIdxRow would badly ** under-estimate the scanning cost. */ rCostIdx = pNew->nOut + 16; @@ -161316,7 +162790,7 @@ static SQLITE_NOINLINE u32 whereIsCoveringIndex( */ static int whereLoopAddBtree( WhereLoopBuilder *pBuilder, /* WHERE clause information */ - Bitmask mPrereq /* Extra prerequesites for using this table */ + Bitmask mPrereq /* Extra prerequisites for using this table */ ){ WhereInfo *pWInfo; /* WHERE analysis context */ Index *pProbe; /* An index we are evaluating */ @@ -161823,7 +163297,7 @@ static int whereLoopAddVirtualOne( ** ** Return a pointer to the collation name: ** -** 1. If there is an explicit COLLATE operator on the constaint, return it. +** 1. If there is an explicit COLLATE operator on the constraint, return it. ** ** 2. Else, if the column has an alternative collation, return that. ** @@ -162784,7 +164258,8 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){ ** For joins of 3 or more tables, track the 10 best paths */ mxChoice = (nLoop<=1) ? 1 : (nLoop==2 ? 5 : 10); assert( nLoop<=pWInfo->pTabList->nSrc ); - WHERETRACE(0x002, ("---- begin solver. (nRowEst=%d)\n", nRowEst)); + WHERETRACE(0x002, ("---- begin solver. (nRowEst=%d, nQueryLoop=%d)\n", + nRowEst, pParse->nQueryLoop)); /* If nRowEst is zero and there is an ORDER BY clause, ignore it. In this ** case the purpose of this call is to estimate the number of rows returned @@ -162887,7 +164362,7 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){ ); } /* TUNING: Add a small extra penalty (3) to sorting as an - ** extra encouragment to the query planner to select a plan + ** extra encouragement to the query planner to select a plan ** where the rows emerge in the correct order without any sorting ** required. */ rCost = sqlite3LogEstAdd(rUnsorted, aSortCost[isOrdered]) + 3; @@ -162903,9 +164378,10 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){ /* TUNING: A full-scan of a VIEW or subquery in the outer loop ** is not so bad. */ - if( iLoop==0 && (pWLoop->wsFlags & WHERE_VIEWSCAN)!=0 ){ + if( iLoop==0 && (pWLoop->wsFlags & WHERE_VIEWSCAN)!=0 && nLoop>1 ){ rCost += -10; nOut += -30; + WHERETRACE(0x80,("VIEWSCAN cost reduction for %c\n",pWLoop->cId)); } /* Check to see if pWLoop should be added to the set of @@ -163537,6 +165013,28 @@ static SQLITE_NOINLINE void whereAddIndexedExpr( } } +/* +** Set the reverse-scan order mask to one for all tables in the query +** with the exception of MATERIALIZED common table expressions that have +** their own internal ORDER BY clauses. +** +** This implements the PRAGMA reverse_unordered_selects=ON setting. +** (Also SQLITE_DBCONFIG_REVERSE_SCANORDER). +*/ +static SQLITE_NOINLINE void whereReverseScanOrder(WhereInfo *pWInfo){ + int ii; + for(ii=0; iipTabList->nSrc; ii++){ + SrcItem *pItem = &pWInfo->pTabList->a[ii]; + if( !pItem->fg.isCte + || pItem->u2.pCteUse->eM10d!=M10d_Yes + || NEVER(pItem->pSelect==0) + || pItem->pSelect->pOrderBy==0 + ){ + pWInfo->revMask |= MASKBIT(ii); + } + } +} + /* ** Generate the beginning of the loop used for WHERE clause processing. ** The return value is a pointer to an opaque structure that contains @@ -163595,7 +165093,7 @@ static SQLITE_NOINLINE void whereAddIndexedExpr( ** ** OUTER JOINS ** -** An outer join of tables t1 and t2 is conceptally coded as follows: +** An outer join of tables t1 and t2 is conceptually coded as follows: ** ** foreach row1 in t1 do ** flag = 0 @@ -163750,7 +165248,7 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin( ** ** The N-th term of the FROM clause is assigned a bitmask of 1<mallocFailed ) goto whereBeginError; } } + assert( pWInfo->pTabList!=0 ); if( pWInfo->pOrderBy==0 && (db->flags & SQLITE_ReverseOrder)!=0 ){ - pWInfo->revMask = ALLBITS; + whereReverseScanOrder(pWInfo); } if( pParse->nErr ){ goto whereBeginError; @@ -164002,6 +165501,7 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin( 0!=(wctrlFlags & WHERE_ONEPASS_MULTIROW) && !IsVirtual(pTabList->a[0].pTab) && (0==(wsFlags & WHERE_MULTI_OR) || (wctrlFlags & WHERE_DUPLICATES_OK)) + && OptimizationEnabled(db, SQLITE_OnePass) )){ pWInfo->eOnePass = bOnerow ? ONEPASS_SINGLE : ONEPASS_MULTI; if( HasRowid(pTabList->a[0].pTab) && (wsFlags & WHERE_IDX_ONLY) ){ @@ -164731,7 +166231,7 @@ SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo *pWInfo){ ** ** These are the same built-in window functions supported by Postgres. ** Although the behaviour of aggregate window functions (functions that -** can be used as either aggregates or window funtions) allows them to +** can be used as either aggregates or window functions) allows them to ** be implemented using an API, built-in window functions are much more ** esoteric. Additionally, some window functions (e.g. nth_value()) ** may only be implemented by caching the entire partition in memory. @@ -165261,7 +166761,7 @@ static Window *windowFind(Parse *pParse, Window *pList, const char *zName){ ** is the Window object representing the associated OVER clause. This ** function updates the contents of pWin as follows: ** -** * If the OVER clause refered to a named window (as in "max(x) OVER win"), +** * If the OVER clause referred to a named window (as in "max(x) OVER win"), ** search list pList for a matching WINDOW definition, and update pWin ** accordingly. If no such WINDOW clause can be found, leave an error ** in pParse. @@ -165882,7 +167382,7 @@ SQLITE_PRIVATE Window *sqlite3WindowAssemble( } /* -** Window *pWin has just been created from a WINDOW clause. Tokne pBase +** Window *pWin has just been created from a WINDOW clause. Token pBase ** is the base window. Earlier windows from the same WINDOW clause are ** stored in the linked list starting at pWin->pNextWin. This function ** either updates *pWin according to the base specification, or else @@ -166188,7 +167688,7 @@ struct WindowCsrAndReg { ** ** (ORDER BY a, b GROUPS BETWEEN 2 PRECEDING AND 2 FOLLOWING) ** -** The windows functions implmentation caches the input rows in a temp +** The windows functions implementation caches the input rows in a temp ** table, sorted by "a, b" (it actually populates the cache lazily, and ** aggressively removes rows once they are no longer required, but that's ** a mere detail). It keeps three cursors open on the temp table. One @@ -167197,7 +168697,7 @@ static int windowExprGtZero(Parse *pParse, Expr *pExpr){ ** ** For the most part, the patterns above are adapted to support UNBOUNDED by ** assuming that it is equivalent to "infinity PRECEDING/FOLLOWING" and -** CURRENT ROW by assuming that it is equivilent to "0 PRECEDING/FOLLOWING". +** CURRENT ROW by assuming that it is equivalent to "0 PRECEDING/FOLLOWING". ** This is optimized of course - branches that will never be taken and ** conditions that are always true are omitted from the VM code. The only ** exceptional case is: @@ -167476,7 +168976,7 @@ SQLITE_PRIVATE void sqlite3WindowCodeStep( } /* Allocate registers for the array of values from the sub-query, the - ** samve values in record form, and the rowid used to insert said record + ** same values in record form, and the rowid used to insert said record ** into the ephemeral table. */ regNew = pParse->nMem+1; pParse->nMem += nInput; @@ -167717,7 +169217,8 @@ SQLITE_PRIVATE void sqlite3WindowCodeStep( /************** End of window.c **********************************************/ /************** Begin file parse.c *******************************************/ /* This file is automatically generated by Lemon from input grammar -** source file "parse.y". */ +** source file "parse.y". +*/ /* ** 2001-09-15 ** @@ -167734,7 +169235,7 @@ SQLITE_PRIVATE void sqlite3WindowCodeStep( ** The canonical source code to this file ("parse.y") is a Lemon grammar ** file that specifies the input grammar and actions to take while parsing. ** That input file is processed by Lemon to generate a C-language -** implementation of a parser for the given grammer. You might be reading +** implementation of a parser for the given grammar. You might be reading ** this comment as part of the translated C-code. Edits should be made ** to the original parse.y sources. */ @@ -168230,7 +169731,7 @@ typedef union { #define YYFALLBACK 1 #define YYNSTATE 575 #define YYNRULE 403 -#define YYNRULE_WITH_ACTION 340 +#define YYNRULE_WITH_ACTION 338 #define YYNTOKEN 185 #define YY_MAX_SHIFT 574 #define YY_MIN_SHIFTREDUCE 833 @@ -168312,106 +169813,106 @@ static const YYACTIONTYPE yy_action[] = { /* 10 */ 568, 1310, 377, 1289, 408, 562, 562, 562, 568, 409, /* 20 */ 378, 1310, 1272, 41, 41, 41, 41, 208, 1520, 71, /* 30 */ 71, 969, 419, 41, 41, 491, 303, 279, 303, 970, - /* 40 */ 397, 71, 71, 125, 126, 80, 1212, 1212, 1047, 1050, + /* 40 */ 397, 71, 71, 125, 126, 80, 1210, 1210, 1047, 1050, /* 50 */ 1037, 1037, 123, 123, 124, 124, 124, 124, 476, 409, /* 60 */ 1237, 1, 1, 574, 2, 1241, 550, 118, 115, 229, /* 70 */ 317, 480, 146, 480, 524, 118, 115, 229, 529, 1323, - /* 80 */ 417, 523, 142, 125, 126, 80, 1212, 1212, 1047, 1050, + /* 80 */ 417, 523, 142, 125, 126, 80, 1210, 1210, 1047, 1050, /* 90 */ 1037, 1037, 123, 123, 124, 124, 124, 124, 118, 115, /* 100 */ 229, 327, 122, 122, 122, 122, 121, 121, 120, 120, /* 110 */ 120, 119, 116, 444, 284, 284, 284, 284, 442, 442, - /* 120 */ 442, 1561, 376, 1563, 1188, 375, 1159, 565, 1159, 565, - /* 130 */ 409, 1561, 537, 259, 226, 444, 101, 145, 449, 316, + /* 120 */ 442, 1559, 376, 1561, 1186, 375, 1157, 565, 1157, 565, + /* 130 */ 409, 1559, 537, 259, 226, 444, 101, 145, 449, 316, /* 140 */ 559, 240, 122, 122, 122, 122, 121, 121, 120, 120, - /* 150 */ 120, 119, 116, 444, 125, 126, 80, 1212, 1212, 1047, + /* 150 */ 120, 119, 116, 444, 125, 126, 80, 1210, 1210, 1047, /* 160 */ 1050, 1037, 1037, 123, 123, 124, 124, 124, 124, 142, - /* 170 */ 294, 1188, 339, 448, 120, 120, 120, 119, 116, 444, - /* 180 */ 127, 1188, 1189, 1188, 148, 441, 440, 568, 119, 116, + /* 170 */ 294, 1186, 339, 448, 120, 120, 120, 119, 116, 444, + /* 180 */ 127, 1186, 1187, 1186, 148, 441, 440, 568, 119, 116, /* 190 */ 444, 124, 124, 124, 124, 117, 122, 122, 122, 122, /* 200 */ 121, 121, 120, 120, 120, 119, 116, 444, 454, 113, /* 210 */ 13, 13, 546, 122, 122, 122, 122, 121, 121, 120, - /* 220 */ 120, 120, 119, 116, 444, 422, 316, 559, 1188, 1189, - /* 230 */ 1188, 149, 1220, 409, 1220, 124, 124, 124, 124, 122, + /* 220 */ 120, 120, 119, 116, 444, 422, 316, 559, 1186, 1187, + /* 230 */ 1186, 149, 1218, 409, 1218, 124, 124, 124, 124, 122, /* 240 */ 122, 122, 122, 121, 121, 120, 120, 120, 119, 116, /* 250 */ 444, 465, 342, 1034, 1034, 1048, 1051, 125, 126, 80, - /* 260 */ 1212, 1212, 1047, 1050, 1037, 1037, 123, 123, 124, 124, - /* 270 */ 124, 124, 1275, 522, 222, 1188, 568, 409, 224, 514, + /* 260 */ 1210, 1210, 1047, 1050, 1037, 1037, 123, 123, 124, 124, + /* 270 */ 124, 124, 1275, 522, 222, 1186, 568, 409, 224, 514, /* 280 */ 175, 82, 83, 122, 122, 122, 122, 121, 121, 120, - /* 290 */ 120, 120, 119, 116, 444, 1005, 16, 16, 1188, 133, - /* 300 */ 133, 125, 126, 80, 1212, 1212, 1047, 1050, 1037, 1037, + /* 290 */ 120, 120, 119, 116, 444, 1005, 16, 16, 1186, 133, + /* 300 */ 133, 125, 126, 80, 1210, 1210, 1047, 1050, 1037, 1037, /* 310 */ 123, 123, 124, 124, 124, 124, 122, 122, 122, 122, /* 320 */ 121, 121, 120, 120, 120, 119, 116, 444, 1038, 546, - /* 330 */ 1188, 373, 1188, 1189, 1188, 252, 1429, 399, 504, 501, + /* 330 */ 1186, 373, 1186, 1187, 1186, 252, 1429, 399, 504, 501, /* 340 */ 500, 111, 560, 566, 4, 924, 924, 433, 499, 340, - /* 350 */ 460, 328, 360, 394, 1233, 1188, 1189, 1188, 563, 568, + /* 350 */ 460, 328, 360, 394, 1231, 1186, 1187, 1186, 563, 568, /* 360 */ 122, 122, 122, 122, 121, 121, 120, 120, 120, 119, - /* 370 */ 116, 444, 284, 284, 369, 1574, 1600, 441, 440, 154, - /* 380 */ 409, 445, 71, 71, 1282, 565, 1217, 1188, 1189, 1188, - /* 390 */ 85, 1219, 271, 557, 543, 515, 1555, 568, 98, 1218, - /* 400 */ 6, 1274, 472, 142, 125, 126, 80, 1212, 1212, 1047, + /* 370 */ 116, 444, 284, 284, 369, 1572, 1598, 441, 440, 154, + /* 380 */ 409, 445, 71, 71, 1282, 565, 1215, 1186, 1187, 1186, + /* 390 */ 85, 1217, 271, 557, 543, 515, 515, 568, 98, 1216, + /* 400 */ 6, 1274, 472, 142, 125, 126, 80, 1210, 1210, 1047, /* 410 */ 1050, 1037, 1037, 123, 123, 124, 124, 124, 124, 550, - /* 420 */ 13, 13, 1024, 507, 1220, 1188, 1220, 549, 109, 109, - /* 430 */ 222, 568, 1234, 175, 568, 427, 110, 197, 445, 569, - /* 440 */ 445, 430, 1546, 1014, 325, 551, 1188, 270, 287, 368, + /* 420 */ 13, 13, 1024, 507, 1218, 1186, 1218, 549, 109, 109, + /* 430 */ 222, 568, 1232, 175, 568, 427, 110, 197, 445, 569, + /* 440 */ 445, 430, 1546, 1014, 325, 551, 1186, 270, 287, 368, /* 450 */ 510, 363, 509, 257, 71, 71, 543, 71, 71, 359, - /* 460 */ 316, 559, 1606, 122, 122, 122, 122, 121, 121, 120, + /* 460 */ 316, 559, 1604, 122, 122, 122, 122, 121, 121, 120, /* 470 */ 120, 120, 119, 116, 444, 1014, 1014, 1016, 1017, 27, - /* 480 */ 284, 284, 1188, 1189, 1188, 1154, 568, 1605, 409, 899, - /* 490 */ 190, 550, 356, 565, 550, 935, 533, 517, 1154, 516, - /* 500 */ 413, 1154, 552, 1188, 1189, 1188, 568, 544, 1548, 51, - /* 510 */ 51, 214, 125, 126, 80, 1212, 1212, 1047, 1050, 1037, - /* 520 */ 1037, 123, 123, 124, 124, 124, 124, 1188, 474, 135, + /* 480 */ 284, 284, 1186, 1187, 1186, 1152, 568, 1603, 409, 899, + /* 490 */ 190, 550, 356, 565, 550, 935, 533, 517, 1152, 516, + /* 500 */ 413, 1152, 552, 1186, 1187, 1186, 568, 544, 544, 51, + /* 510 */ 51, 214, 125, 126, 80, 1210, 1210, 1047, 1050, 1037, + /* 520 */ 1037, 123, 123, 124, 124, 124, 124, 1186, 474, 135, /* 530 */ 135, 409, 284, 284, 1484, 505, 121, 121, 120, 120, - /* 540 */ 120, 119, 116, 444, 1005, 565, 518, 217, 541, 1555, - /* 550 */ 316, 559, 142, 6, 532, 125, 126, 80, 1212, 1212, + /* 540 */ 120, 119, 116, 444, 1005, 565, 518, 217, 541, 541, + /* 550 */ 316, 559, 142, 6, 532, 125, 126, 80, 1210, 1210, /* 560 */ 1047, 1050, 1037, 1037, 123, 123, 124, 124, 124, 124, - /* 570 */ 1549, 122, 122, 122, 122, 121, 121, 120, 120, 120, - /* 580 */ 119, 116, 444, 485, 1188, 1189, 1188, 482, 281, 1263, - /* 590 */ 955, 252, 1188, 373, 504, 501, 500, 1188, 340, 570, - /* 600 */ 1188, 570, 409, 292, 499, 955, 874, 191, 480, 316, + /* 570 */ 1548, 122, 122, 122, 122, 121, 121, 120, 120, 120, + /* 580 */ 119, 116, 444, 485, 1186, 1187, 1186, 482, 281, 1263, + /* 590 */ 955, 252, 1186, 373, 504, 501, 500, 1186, 340, 570, + /* 600 */ 1186, 570, 409, 292, 499, 955, 874, 191, 480, 316, /* 610 */ 559, 384, 290, 380, 122, 122, 122, 122, 121, 121, - /* 620 */ 120, 120, 120, 119, 116, 444, 125, 126, 80, 1212, - /* 630 */ 1212, 1047, 1050, 1037, 1037, 123, 123, 124, 124, 124, - /* 640 */ 124, 409, 394, 1132, 1188, 867, 100, 284, 284, 1188, - /* 650 */ 1189, 1188, 373, 1089, 1188, 1189, 1188, 1188, 1189, 1188, - /* 660 */ 565, 455, 32, 373, 233, 125, 126, 80, 1212, 1212, + /* 620 */ 120, 120, 120, 119, 116, 444, 125, 126, 80, 1210, + /* 630 */ 1210, 1047, 1050, 1037, 1037, 123, 123, 124, 124, 124, + /* 640 */ 124, 409, 394, 1132, 1186, 867, 100, 284, 284, 1186, + /* 650 */ 1187, 1186, 373, 1089, 1186, 1187, 1186, 1186, 1187, 1186, + /* 660 */ 565, 455, 32, 373, 233, 125, 126, 80, 1210, 1210, /* 670 */ 1047, 1050, 1037, 1037, 123, 123, 124, 124, 124, 124, /* 680 */ 1428, 957, 568, 228, 956, 122, 122, 122, 122, 121, - /* 690 */ 121, 120, 120, 120, 119, 116, 444, 1154, 228, 1188, - /* 700 */ 157, 1188, 1189, 1188, 1547, 13, 13, 301, 955, 1228, - /* 710 */ 1154, 153, 409, 1154, 373, 1577, 1172, 5, 369, 1574, - /* 720 */ 429, 1234, 3, 955, 122, 122, 122, 122, 121, 121, - /* 730 */ 120, 120, 120, 119, 116, 444, 125, 126, 80, 1212, - /* 740 */ 1212, 1047, 1050, 1037, 1037, 123, 123, 124, 124, 124, - /* 750 */ 124, 409, 208, 567, 1188, 1025, 1188, 1189, 1188, 1188, + /* 690 */ 121, 120, 120, 120, 119, 116, 444, 1152, 228, 1186, + /* 700 */ 157, 1186, 1187, 1186, 1547, 13, 13, 301, 955, 1226, + /* 710 */ 1152, 153, 409, 1152, 373, 1575, 1170, 5, 369, 1572, + /* 720 */ 429, 1232, 3, 955, 122, 122, 122, 122, 121, 121, + /* 730 */ 120, 120, 120, 119, 116, 444, 125, 126, 80, 1210, + /* 740 */ 1210, 1047, 1050, 1037, 1037, 123, 123, 124, 124, 124, + /* 750 */ 124, 409, 208, 567, 1186, 1025, 1186, 1187, 1186, 1186, /* 760 */ 388, 850, 155, 1546, 286, 402, 1094, 1094, 488, 568, - /* 770 */ 465, 342, 1315, 1315, 1546, 125, 126, 80, 1212, 1212, + /* 770 */ 465, 342, 1315, 1315, 1546, 125, 126, 80, 1210, 1210, /* 780 */ 1047, 1050, 1037, 1037, 123, 123, 124, 124, 124, 124, /* 790 */ 129, 568, 13, 13, 374, 122, 122, 122, 122, 121, /* 800 */ 121, 120, 120, 120, 119, 116, 444, 302, 568, 453, - /* 810 */ 528, 1188, 1189, 1188, 13, 13, 1188, 1189, 1188, 1293, + /* 810 */ 528, 1186, 1187, 1186, 13, 13, 1186, 1187, 1186, 1293, /* 820 */ 463, 1263, 409, 1313, 1313, 1546, 1010, 453, 452, 200, /* 830 */ 299, 71, 71, 1261, 122, 122, 122, 122, 121, 121, - /* 840 */ 120, 120, 120, 119, 116, 444, 125, 126, 80, 1212, - /* 850 */ 1212, 1047, 1050, 1037, 1037, 123, 123, 124, 124, 124, - /* 860 */ 124, 409, 227, 1069, 1154, 284, 284, 419, 312, 278, - /* 870 */ 278, 285, 285, 1415, 406, 405, 382, 1154, 565, 568, - /* 880 */ 1154, 1191, 565, 1594, 565, 125, 126, 80, 1212, 1212, + /* 840 */ 120, 120, 120, 119, 116, 444, 125, 126, 80, 1210, + /* 850 */ 1210, 1047, 1050, 1037, 1037, 123, 123, 124, 124, 124, + /* 860 */ 124, 409, 227, 1069, 1152, 284, 284, 419, 312, 278, + /* 870 */ 278, 285, 285, 1415, 406, 405, 382, 1152, 565, 568, + /* 880 */ 1152, 1189, 565, 1592, 565, 125, 126, 80, 1210, 1210, /* 890 */ 1047, 1050, 1037, 1037, 123, 123, 124, 124, 124, 124, /* 900 */ 453, 1476, 13, 13, 1530, 122, 122, 122, 122, 121, /* 910 */ 121, 120, 120, 120, 119, 116, 444, 201, 568, 354, - /* 920 */ 1580, 574, 2, 1241, 838, 839, 840, 1556, 317, 1207, - /* 930 */ 146, 6, 409, 255, 254, 253, 206, 1323, 9, 1191, + /* 920 */ 1578, 574, 2, 1241, 838, 839, 840, 1554, 317, 1205, + /* 930 */ 146, 6, 409, 255, 254, 253, 206, 1323, 9, 1189, /* 940 */ 262, 71, 71, 424, 122, 122, 122, 122, 121, 121, - /* 950 */ 120, 120, 120, 119, 116, 444, 125, 126, 80, 1212, - /* 960 */ 1212, 1047, 1050, 1037, 1037, 123, 123, 124, 124, 124, - /* 970 */ 124, 568, 284, 284, 568, 1208, 409, 573, 313, 1241, - /* 980 */ 349, 1292, 352, 419, 317, 565, 146, 491, 525, 1637, + /* 950 */ 120, 120, 120, 119, 116, 444, 125, 126, 80, 1210, + /* 960 */ 1210, 1047, 1050, 1037, 1037, 123, 123, 124, 124, 124, + /* 970 */ 124, 568, 284, 284, 568, 1206, 409, 573, 313, 1241, + /* 980 */ 349, 1292, 352, 419, 317, 565, 146, 491, 525, 1635, /* 990 */ 395, 371, 491, 1323, 70, 70, 1291, 71, 71, 240, - /* 1000 */ 1321, 104, 80, 1212, 1212, 1047, 1050, 1037, 1037, 123, + /* 1000 */ 1321, 104, 80, 1210, 1210, 1047, 1050, 1037, 1037, 123, /* 1010 */ 123, 124, 124, 124, 124, 122, 122, 122, 122, 121, /* 1020 */ 121, 120, 120, 120, 119, 116, 444, 1110, 284, 284, - /* 1030 */ 428, 448, 1519, 1208, 439, 284, 284, 1483, 1348, 311, + /* 1030 */ 428, 448, 1519, 1206, 439, 284, 284, 1483, 1348, 311, /* 1040 */ 474, 565, 1111, 969, 491, 491, 217, 1259, 565, 1532, /* 1050 */ 568, 970, 207, 568, 1024, 240, 383, 1112, 519, 122, /* 1060 */ 122, 122, 122, 121, 121, 120, 120, 120, 119, 116, @@ -168419,29 +169920,29 @@ static const YYACTIONTYPE yy_action[] = { /* 1080 */ 1489, 568, 284, 284, 97, 526, 491, 448, 911, 1322, /* 1090 */ 1318, 545, 409, 284, 284, 565, 151, 209, 1489, 1491, /* 1100 */ 262, 450, 55, 55, 56, 56, 565, 1014, 1014, 1016, - /* 1110 */ 443, 332, 409, 527, 12, 295, 125, 126, 80, 1212, - /* 1120 */ 1212, 1047, 1050, 1037, 1037, 123, 123, 124, 124, 124, - /* 1130 */ 124, 347, 409, 862, 1528, 1208, 125, 126, 80, 1212, - /* 1140 */ 1212, 1047, 1050, 1037, 1037, 123, 123, 124, 124, 124, - /* 1150 */ 124, 1133, 1635, 474, 1635, 371, 125, 114, 80, 1212, - /* 1160 */ 1212, 1047, 1050, 1037, 1037, 123, 123, 124, 124, 124, + /* 1110 */ 443, 332, 409, 527, 12, 295, 125, 126, 80, 1210, + /* 1120 */ 1210, 1047, 1050, 1037, 1037, 123, 123, 124, 124, 124, + /* 1130 */ 124, 347, 409, 862, 1528, 1206, 125, 126, 80, 1210, + /* 1140 */ 1210, 1047, 1050, 1037, 1037, 123, 123, 124, 124, 124, + /* 1150 */ 124, 1133, 1633, 474, 1633, 371, 125, 114, 80, 1210, + /* 1160 */ 1210, 1047, 1050, 1037, 1037, 123, 123, 124, 124, 124, /* 1170 */ 124, 1489, 329, 474, 331, 122, 122, 122, 122, 121, /* 1180 */ 121, 120, 120, 120, 119, 116, 444, 203, 1415, 568, - /* 1190 */ 1290, 862, 464, 1208, 436, 122, 122, 122, 122, 121, - /* 1200 */ 121, 120, 120, 120, 119, 116, 444, 553, 1133, 1636, - /* 1210 */ 539, 1636, 15, 15, 890, 122, 122, 122, 122, 121, + /* 1190 */ 1290, 862, 464, 1206, 436, 122, 122, 122, 122, 121, + /* 1200 */ 121, 120, 120, 120, 119, 116, 444, 553, 1133, 1634, + /* 1210 */ 539, 1634, 15, 15, 890, 122, 122, 122, 122, 121, /* 1220 */ 121, 120, 120, 120, 119, 116, 444, 568, 298, 538, - /* 1230 */ 1131, 1415, 1553, 1554, 1327, 409, 6, 6, 1165, 1264, + /* 1230 */ 1131, 1415, 1552, 1553, 1327, 409, 6, 6, 1163, 1264, /* 1240 */ 415, 320, 284, 284, 1415, 508, 565, 525, 300, 457, /* 1250 */ 43, 43, 568, 891, 12, 565, 330, 478, 425, 407, - /* 1260 */ 126, 80, 1212, 1212, 1047, 1050, 1037, 1037, 123, 123, - /* 1270 */ 124, 124, 124, 124, 568, 57, 57, 288, 1188, 1415, - /* 1280 */ 496, 458, 392, 392, 391, 273, 389, 1131, 1552, 847, - /* 1290 */ 1165, 407, 6, 568, 321, 1154, 470, 44, 44, 1551, - /* 1300 */ 1110, 426, 234, 6, 323, 256, 540, 256, 1154, 431, - /* 1310 */ 568, 1154, 322, 17, 487, 1111, 58, 58, 122, 122, + /* 1260 */ 126, 80, 1210, 1210, 1047, 1050, 1037, 1037, 123, 123, + /* 1270 */ 124, 124, 124, 124, 568, 57, 57, 288, 1186, 1415, + /* 1280 */ 496, 458, 392, 392, 391, 273, 389, 1131, 1551, 847, + /* 1290 */ 1163, 407, 6, 568, 321, 1152, 470, 44, 44, 1550, + /* 1300 */ 1110, 426, 234, 6, 323, 256, 540, 256, 1152, 431, + /* 1310 */ 568, 1152, 322, 17, 487, 1111, 58, 58, 122, 122, /* 1320 */ 122, 122, 121, 121, 120, 120, 120, 119, 116, 444, - /* 1330 */ 1112, 216, 481, 59, 59, 1188, 1189, 1188, 111, 560, + /* 1330 */ 1112, 216, 481, 59, 59, 1186, 1187, 1186, 111, 560, /* 1340 */ 324, 4, 236, 456, 526, 568, 237, 456, 568, 437, /* 1350 */ 168, 556, 420, 141, 479, 563, 568, 293, 568, 1091, /* 1360 */ 568, 293, 568, 1091, 531, 568, 870, 8, 60, 60, @@ -168455,7 +169956,7 @@ static const YYACTIONTYPE yy_action[] = { /* 1440 */ 1014, 132, 132, 67, 67, 568, 467, 568, 930, 471, /* 1450 */ 1360, 283, 226, 929, 315, 1359, 407, 568, 459, 407, /* 1460 */ 1014, 1014, 1016, 239, 407, 86, 213, 1346, 52, 52, - /* 1470 */ 68, 68, 1014, 1014, 1016, 1017, 27, 1579, 1176, 447, + /* 1470 */ 68, 68, 1014, 1014, 1016, 1017, 27, 1577, 1174, 447, /* 1480 */ 69, 69, 288, 97, 108, 1535, 106, 392, 392, 391, /* 1490 */ 273, 389, 568, 877, 847, 881, 568, 111, 560, 466, /* 1500 */ 4, 568, 152, 30, 38, 568, 1128, 234, 396, 323, @@ -168464,7 +169965,7 @@ static const YYACTIONTYPE yy_action[] = { /* 1530 */ 568, 289, 1508, 568, 31, 1507, 568, 445, 338, 483, /* 1540 */ 100, 54, 54, 344, 72, 72, 296, 236, 1076, 557, /* 1550 */ 445, 877, 1356, 134, 134, 168, 73, 73, 141, 161, - /* 1560 */ 161, 1568, 557, 535, 568, 319, 568, 348, 536, 1007, + /* 1560 */ 161, 1566, 557, 535, 568, 319, 568, 348, 536, 1007, /* 1570 */ 473, 261, 261, 889, 888, 235, 535, 568, 1024, 568, /* 1580 */ 475, 534, 261, 367, 109, 109, 521, 136, 136, 130, /* 1590 */ 130, 1024, 110, 366, 445, 569, 445, 109, 109, 1014, @@ -168472,7 +169973,7 @@ static const YYACTIONTYPE yy_action[] = { /* 1610 */ 410, 351, 1014, 568, 353, 316, 559, 568, 343, 568, /* 1620 */ 100, 497, 357, 258, 100, 896, 897, 140, 140, 355, /* 1630 */ 1306, 1014, 1014, 1016, 1017, 27, 139, 139, 362, 451, - /* 1640 */ 137, 137, 138, 138, 1014, 1014, 1016, 1017, 27, 1176, + /* 1640 */ 137, 137, 138, 138, 1014, 1014, 1016, 1017, 27, 1174, /* 1650 */ 447, 568, 372, 288, 111, 560, 1018, 4, 392, 392, /* 1660 */ 391, 273, 389, 568, 1137, 847, 568, 1072, 568, 258, /* 1670 */ 492, 563, 568, 211, 75, 75, 555, 960, 234, 261, @@ -168480,44 +169981,44 @@ static const YYACTIONTYPE yy_action[] = { /* 1690 */ 74, 42, 42, 1369, 445, 48, 48, 1414, 563, 972, /* 1700 */ 973, 1088, 1087, 1088, 1087, 860, 557, 150, 928, 1342, /* 1710 */ 113, 1354, 554, 1419, 1018, 1271, 1262, 1250, 236, 1249, - /* 1720 */ 1251, 445, 1587, 1339, 308, 276, 168, 309, 11, 141, + /* 1720 */ 1251, 445, 1585, 1339, 308, 276, 168, 309, 11, 141, /* 1730 */ 393, 310, 232, 557, 1401, 1024, 335, 291, 1396, 219, /* 1740 */ 336, 109, 109, 934, 297, 1406, 235, 341, 477, 110, /* 1750 */ 502, 445, 569, 445, 1389, 1405, 1014, 400, 1289, 365, /* 1760 */ 223, 1480, 1024, 1479, 1351, 1352, 1350, 1349, 109, 109, - /* 1770 */ 204, 1590, 1228, 558, 265, 218, 110, 205, 445, 569, + /* 1770 */ 204, 1588, 1226, 558, 265, 218, 110, 205, 445, 569, /* 1780 */ 445, 410, 387, 1014, 1527, 179, 316, 559, 1014, 1014, - /* 1790 */ 1016, 1017, 27, 230, 1525, 1225, 79, 560, 85, 4, + /* 1790 */ 1016, 1017, 27, 230, 1525, 1223, 79, 560, 85, 4, /* 1800 */ 418, 215, 548, 81, 84, 188, 1402, 173, 181, 461, /* 1810 */ 451, 35, 462, 563, 183, 1014, 1014, 1016, 1017, 27, /* 1820 */ 184, 1485, 185, 186, 495, 242, 98, 398, 1408, 36, /* 1830 */ 1407, 484, 91, 469, 401, 1410, 445, 192, 1474, 246, /* 1840 */ 1496, 490, 346, 277, 248, 196, 493, 511, 557, 350, /* 1850 */ 1252, 249, 250, 403, 1309, 1308, 111, 560, 432, 4, - /* 1860 */ 1307, 1300, 93, 1604, 881, 1603, 224, 404, 434, 520, - /* 1870 */ 263, 435, 1573, 563, 1279, 1278, 364, 1024, 306, 1277, - /* 1880 */ 264, 1602, 1559, 109, 109, 370, 1299, 307, 1558, 438, + /* 1860 */ 1307, 1300, 93, 1602, 881, 1601, 224, 404, 434, 520, + /* 1870 */ 263, 435, 1571, 563, 1279, 1278, 364, 1024, 306, 1277, + /* 1880 */ 264, 1600, 1557, 109, 109, 370, 1299, 307, 1556, 438, /* 1890 */ 128, 110, 1374, 445, 569, 445, 445, 546, 1014, 10, /* 1900 */ 1461, 105, 381, 1373, 34, 571, 99, 1332, 557, 314, - /* 1910 */ 1182, 530, 272, 274, 379, 210, 1331, 547, 385, 386, + /* 1910 */ 1180, 530, 272, 274, 379, 210, 1331, 547, 385, 386, /* 1920 */ 275, 572, 1247, 1242, 411, 412, 1512, 165, 178, 1513, /* 1930 */ 1014, 1014, 1016, 1017, 27, 1511, 1510, 1024, 78, 147, /* 1940 */ 166, 220, 221, 109, 109, 834, 304, 167, 446, 212, /* 1950 */ 318, 110, 231, 445, 569, 445, 144, 1086, 1014, 1084, - /* 1960 */ 326, 180, 169, 1207, 182, 334, 238, 913, 241, 1100, + /* 1960 */ 326, 180, 169, 1205, 182, 334, 238, 913, 241, 1100, /* 1970 */ 187, 170, 171, 421, 87, 88, 423, 189, 89, 90, /* 1980 */ 172, 1103, 243, 1099, 244, 158, 18, 245, 345, 247, - /* 1990 */ 1014, 1014, 1016, 1017, 27, 261, 1092, 193, 1222, 489, + /* 1990 */ 1014, 1014, 1016, 1017, 27, 261, 1092, 193, 1220, 489, /* 2000 */ 194, 37, 366, 849, 494, 251, 195, 506, 92, 19, /* 2010 */ 498, 358, 20, 503, 879, 361, 94, 892, 305, 159, - /* 2020 */ 513, 39, 95, 1170, 160, 1053, 964, 1139, 96, 174, - /* 2030 */ 1138, 225, 280, 282, 198, 958, 113, 1160, 1156, 260, - /* 2040 */ 21, 22, 23, 1158, 1164, 1163, 1144, 24, 33, 25, + /* 2020 */ 513, 39, 95, 1168, 160, 1053, 964, 1139, 96, 174, + /* 2030 */ 1138, 225, 280, 282, 198, 958, 113, 1158, 1154, 260, + /* 2040 */ 21, 22, 23, 1156, 1162, 1161, 1143, 24, 33, 25, /* 2050 */ 202, 542, 26, 100, 1067, 102, 1054, 103, 7, 1052, /* 2060 */ 1056, 1109, 1057, 1108, 266, 267, 28, 40, 390, 1019, - /* 2070 */ 861, 112, 29, 564, 1178, 1177, 268, 176, 143, 923, + /* 2070 */ 861, 112, 29, 564, 1176, 1175, 268, 176, 143, 923, /* 2080 */ 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, - /* 2090 */ 1238, 1238, 1238, 1238, 269, 1595, + /* 2090 */ 1238, 1238, 1238, 1238, 269, 1593, }; static const YYCODETYPE yy_lookahead[] = { /* 0 */ 193, 193, 193, 274, 275, 276, 193, 274, 275, 276, @@ -168860,14 +170361,14 @@ static const short yy_reduce_ofst[] = { /* 400 */ 1722, 1723, 1733, 1717, 1724, 1727, 1728, 1725, 1740, }; static const YYACTIONTYPE yy_default[] = { - /* 0 */ 1641, 1641, 1641, 1469, 1236, 1347, 1236, 1236, 1236, 1469, + /* 0 */ 1639, 1639, 1639, 1469, 1236, 1347, 1236, 1236, 1236, 1469, /* 10 */ 1469, 1469, 1236, 1377, 1377, 1522, 1269, 1236, 1236, 1236, /* 20 */ 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1468, 1236, 1236, - /* 30 */ 1236, 1236, 1557, 1557, 1236, 1236, 1236, 1236, 1236, 1236, + /* 30 */ 1236, 1236, 1555, 1555, 1236, 1236, 1236, 1236, 1236, 1236, /* 40 */ 1236, 1236, 1386, 1236, 1393, 1236, 1236, 1236, 1236, 1236, /* 50 */ 1470, 1471, 1236, 1236, 1236, 1521, 1523, 1486, 1400, 1399, /* 60 */ 1398, 1397, 1504, 1365, 1391, 1384, 1388, 1465, 1466, 1464, - /* 70 */ 1619, 1471, 1470, 1236, 1387, 1433, 1449, 1432, 1236, 1236, + /* 70 */ 1617, 1471, 1470, 1236, 1387, 1433, 1449, 1432, 1236, 1236, /* 80 */ 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, /* 90 */ 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, /* 100 */ 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, @@ -168876,47 +170377,47 @@ static const YYACTIONTYPE yy_default[] = { /* 130 */ 1441, 1448, 1447, 1446, 1455, 1445, 1442, 1435, 1434, 1436, /* 140 */ 1437, 1236, 1236, 1260, 1236, 1236, 1257, 1311, 1236, 1236, /* 150 */ 1236, 1236, 1236, 1541, 1540, 1236, 1438, 1236, 1269, 1427, - /* 160 */ 1426, 1452, 1439, 1451, 1450, 1529, 1593, 1592, 1487, 1236, - /* 170 */ 1236, 1236, 1236, 1236, 1236, 1557, 1236, 1236, 1236, 1236, + /* 160 */ 1426, 1452, 1439, 1451, 1450, 1529, 1591, 1590, 1487, 1236, + /* 170 */ 1236, 1236, 1236, 1236, 1236, 1555, 1236, 1236, 1236, 1236, /* 180 */ 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, /* 190 */ 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1367, - /* 200 */ 1557, 1557, 1236, 1269, 1557, 1557, 1368, 1368, 1265, 1265, + /* 200 */ 1555, 1555, 1236, 1269, 1555, 1555, 1368, 1368, 1265, 1265, /* 210 */ 1371, 1236, 1536, 1338, 1338, 1338, 1338, 1347, 1338, 1236, /* 220 */ 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, /* 230 */ 1236, 1236, 1236, 1236, 1526, 1524, 1236, 1236, 1236, 1236, /* 240 */ 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, /* 250 */ 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, /* 260 */ 1236, 1236, 1236, 1343, 1236, 1236, 1236, 1236, 1236, 1236, - /* 270 */ 1236, 1236, 1236, 1236, 1236, 1586, 1236, 1499, 1325, 1343, - /* 280 */ 1343, 1343, 1343, 1345, 1326, 1324, 1337, 1270, 1243, 1633, - /* 290 */ 1403, 1392, 1344, 1392, 1630, 1390, 1403, 1403, 1390, 1403, - /* 300 */ 1344, 1630, 1286, 1608, 1281, 1377, 1377, 1377, 1367, 1367, - /* 310 */ 1367, 1367, 1371, 1371, 1467, 1344, 1337, 1236, 1633, 1633, - /* 320 */ 1353, 1353, 1632, 1632, 1353, 1487, 1616, 1412, 1314, 1320, - /* 330 */ 1320, 1320, 1320, 1353, 1254, 1390, 1616, 1616, 1390, 1412, - /* 340 */ 1314, 1390, 1314, 1390, 1353, 1254, 1503, 1627, 1353, 1254, + /* 270 */ 1236, 1236, 1236, 1236, 1236, 1584, 1236, 1499, 1325, 1343, + /* 280 */ 1343, 1343, 1343, 1345, 1326, 1324, 1337, 1270, 1243, 1631, + /* 290 */ 1403, 1392, 1344, 1392, 1628, 1390, 1403, 1403, 1390, 1403, + /* 300 */ 1344, 1628, 1286, 1606, 1281, 1377, 1377, 1377, 1367, 1367, + /* 310 */ 1367, 1367, 1371, 1371, 1467, 1344, 1337, 1236, 1631, 1631, + /* 320 */ 1353, 1353, 1630, 1630, 1353, 1487, 1614, 1412, 1314, 1320, + /* 330 */ 1320, 1320, 1320, 1353, 1254, 1390, 1614, 1614, 1390, 1412, + /* 340 */ 1314, 1390, 1314, 1390, 1353, 1254, 1503, 1625, 1353, 1254, /* 350 */ 1477, 1353, 1254, 1353, 1254, 1477, 1312, 1312, 1312, 1301, - /* 360 */ 1236, 1236, 1477, 1312, 1286, 1312, 1301, 1312, 1312, 1575, - /* 370 */ 1236, 1481, 1481, 1477, 1353, 1567, 1567, 1380, 1380, 1385, - /* 380 */ 1371, 1472, 1353, 1236, 1385, 1383, 1381, 1390, 1304, 1589, - /* 390 */ 1589, 1585, 1585, 1585, 1638, 1638, 1536, 1601, 1269, 1269, - /* 400 */ 1269, 1269, 1601, 1288, 1288, 1270, 1270, 1269, 1601, 1236, - /* 410 */ 1236, 1236, 1236, 1236, 1236, 1596, 1236, 1531, 1488, 1357, + /* 360 */ 1236, 1236, 1477, 1312, 1286, 1312, 1301, 1312, 1312, 1573, + /* 370 */ 1236, 1481, 1481, 1477, 1353, 1565, 1565, 1380, 1380, 1385, + /* 380 */ 1371, 1472, 1353, 1236, 1385, 1383, 1381, 1390, 1304, 1587, + /* 390 */ 1587, 1583, 1583, 1583, 1636, 1636, 1536, 1599, 1269, 1269, + /* 400 */ 1269, 1269, 1599, 1288, 1288, 1270, 1270, 1269, 1599, 1236, + /* 410 */ 1236, 1236, 1236, 1236, 1236, 1594, 1236, 1531, 1488, 1357, /* 420 */ 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, /* 430 */ 1236, 1236, 1236, 1236, 1542, 1236, 1236, 1236, 1236, 1236, /* 440 */ 1236, 1236, 1236, 1236, 1236, 1417, 1236, 1239, 1533, 1236, /* 450 */ 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1394, 1395, 1358, /* 460 */ 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1409, 1236, 1236, /* 470 */ 1236, 1404, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, - /* 480 */ 1629, 1236, 1236, 1236, 1236, 1236, 1236, 1502, 1501, 1236, + /* 480 */ 1627, 1236, 1236, 1236, 1236, 1236, 1236, 1502, 1501, 1236, /* 490 */ 1236, 1355, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, /* 500 */ 1236, 1236, 1236, 1236, 1236, 1284, 1236, 1236, 1236, 1236, /* 510 */ 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, /* 520 */ 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1382, /* 530 */ 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, - /* 540 */ 1236, 1236, 1236, 1236, 1572, 1372, 1236, 1236, 1236, 1236, - /* 550 */ 1620, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, - /* 560 */ 1236, 1236, 1236, 1236, 1236, 1612, 1328, 1418, 1236, 1421, + /* 540 */ 1236, 1236, 1236, 1236, 1570, 1372, 1236, 1236, 1236, 1236, + /* 550 */ 1618, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, + /* 560 */ 1236, 1236, 1236, 1236, 1236, 1610, 1328, 1418, 1236, 1421, /* 570 */ 1258, 1236, 1248, 1236, 1236, }; /********** End of lemon-generated parsing tables *****************************/ @@ -169845,100 +171346,100 @@ static const char *const yyRuleName[] = { /* 306 */ "wqitem ::= nm eidlist_opt wqas LP select RP", /* 307 */ "wqlist ::= wqitem", /* 308 */ "wqlist ::= wqlist COMMA wqitem", - /* 309 */ "windowdefn_list ::= windowdefn", - /* 310 */ "windowdefn_list ::= windowdefn_list COMMA windowdefn", - /* 311 */ "windowdefn ::= nm AS LP window RP", - /* 312 */ "window ::= PARTITION BY nexprlist orderby_opt frame_opt", - /* 313 */ "window ::= nm PARTITION BY nexprlist orderby_opt frame_opt", - /* 314 */ "window ::= ORDER BY sortlist frame_opt", - /* 315 */ "window ::= nm ORDER BY sortlist frame_opt", - /* 316 */ "window ::= frame_opt", - /* 317 */ "window ::= nm frame_opt", - /* 318 */ "frame_opt ::=", - /* 319 */ "frame_opt ::= range_or_rows frame_bound_s frame_exclude_opt", - /* 320 */ "frame_opt ::= range_or_rows BETWEEN frame_bound_s AND frame_bound_e frame_exclude_opt", - /* 321 */ "range_or_rows ::= RANGE|ROWS|GROUPS", - /* 322 */ "frame_bound_s ::= frame_bound", - /* 323 */ "frame_bound_s ::= UNBOUNDED PRECEDING", - /* 324 */ "frame_bound_e ::= frame_bound", - /* 325 */ "frame_bound_e ::= UNBOUNDED FOLLOWING", - /* 326 */ "frame_bound ::= expr PRECEDING|FOLLOWING", - /* 327 */ "frame_bound ::= CURRENT ROW", - /* 328 */ "frame_exclude_opt ::=", - /* 329 */ "frame_exclude_opt ::= EXCLUDE frame_exclude", - /* 330 */ "frame_exclude ::= NO OTHERS", - /* 331 */ "frame_exclude ::= CURRENT ROW", - /* 332 */ "frame_exclude ::= GROUP|TIES", - /* 333 */ "window_clause ::= WINDOW windowdefn_list", - /* 334 */ "filter_over ::= filter_clause over_clause", - /* 335 */ "filter_over ::= over_clause", - /* 336 */ "filter_over ::= filter_clause", - /* 337 */ "over_clause ::= OVER LP window RP", - /* 338 */ "over_clause ::= OVER nm", - /* 339 */ "filter_clause ::= FILTER LP WHERE expr RP", - /* 340 */ "input ::= cmdlist", - /* 341 */ "cmdlist ::= cmdlist ecmd", - /* 342 */ "cmdlist ::= ecmd", - /* 343 */ "ecmd ::= SEMI", - /* 344 */ "ecmd ::= cmdx SEMI", - /* 345 */ "ecmd ::= explain cmdx SEMI", - /* 346 */ "trans_opt ::=", - /* 347 */ "trans_opt ::= TRANSACTION", - /* 348 */ "trans_opt ::= TRANSACTION nm", - /* 349 */ "savepoint_opt ::= SAVEPOINT", - /* 350 */ "savepoint_opt ::=", - /* 351 */ "cmd ::= create_table create_table_args", - /* 352 */ "table_option_set ::= table_option", - /* 353 */ "columnlist ::= columnlist COMMA columnname carglist", - /* 354 */ "columnlist ::= columnname carglist", - /* 355 */ "nm ::= ID|INDEXED|JOIN_KW", - /* 356 */ "nm ::= STRING", - /* 357 */ "typetoken ::= typename", - /* 358 */ "typename ::= ID|STRING", - /* 359 */ "signed ::= plus_num", - /* 360 */ "signed ::= minus_num", - /* 361 */ "carglist ::= carglist ccons", - /* 362 */ "carglist ::=", - /* 363 */ "ccons ::= NULL onconf", - /* 364 */ "ccons ::= GENERATED ALWAYS AS generated", - /* 365 */ "ccons ::= AS generated", - /* 366 */ "conslist_opt ::= COMMA conslist", - /* 367 */ "conslist ::= conslist tconscomma tcons", - /* 368 */ "conslist ::= tcons", - /* 369 */ "tconscomma ::=", - /* 370 */ "defer_subclause_opt ::= defer_subclause", - /* 371 */ "resolvetype ::= raisetype", - /* 372 */ "selectnowith ::= oneselect", - /* 373 */ "oneselect ::= values", - /* 374 */ "sclp ::= selcollist COMMA", - /* 375 */ "as ::= ID|STRING", - /* 376 */ "indexed_opt ::= indexed_by", - /* 377 */ "returning ::=", - /* 378 */ "expr ::= term", - /* 379 */ "likeop ::= LIKE_KW|MATCH", - /* 380 */ "case_operand ::= expr", - /* 381 */ "exprlist ::= nexprlist", - /* 382 */ "nmnum ::= plus_num", - /* 383 */ "nmnum ::= nm", - /* 384 */ "nmnum ::= ON", - /* 385 */ "nmnum ::= DELETE", - /* 386 */ "nmnum ::= DEFAULT", - /* 387 */ "plus_num ::= INTEGER|FLOAT", - /* 388 */ "foreach_clause ::=", - /* 389 */ "foreach_clause ::= FOR EACH ROW", - /* 390 */ "trnm ::= nm", - /* 391 */ "tridxby ::=", - /* 392 */ "database_kw_opt ::= DATABASE", - /* 393 */ "database_kw_opt ::=", - /* 394 */ "kwcolumn_opt ::=", - /* 395 */ "kwcolumn_opt ::= COLUMNKW", - /* 396 */ "vtabarglist ::= vtabarg", - /* 397 */ "vtabarglist ::= vtabarglist COMMA vtabarg", - /* 398 */ "vtabarg ::= vtabarg vtabargtoken", - /* 399 */ "anylist ::=", - /* 400 */ "anylist ::= anylist LP anylist RP", - /* 401 */ "anylist ::= anylist ANY", - /* 402 */ "with ::=", + /* 309 */ "windowdefn_list ::= windowdefn_list COMMA windowdefn", + /* 310 */ "windowdefn ::= nm AS LP window RP", + /* 311 */ "window ::= PARTITION BY nexprlist orderby_opt frame_opt", + /* 312 */ "window ::= nm PARTITION BY nexprlist orderby_opt frame_opt", + /* 313 */ "window ::= ORDER BY sortlist frame_opt", + /* 314 */ "window ::= nm ORDER BY sortlist frame_opt", + /* 315 */ "window ::= nm frame_opt", + /* 316 */ "frame_opt ::=", + /* 317 */ "frame_opt ::= range_or_rows frame_bound_s frame_exclude_opt", + /* 318 */ "frame_opt ::= range_or_rows BETWEEN frame_bound_s AND frame_bound_e frame_exclude_opt", + /* 319 */ "range_or_rows ::= RANGE|ROWS|GROUPS", + /* 320 */ "frame_bound_s ::= frame_bound", + /* 321 */ "frame_bound_s ::= UNBOUNDED PRECEDING", + /* 322 */ "frame_bound_e ::= frame_bound", + /* 323 */ "frame_bound_e ::= UNBOUNDED FOLLOWING", + /* 324 */ "frame_bound ::= expr PRECEDING|FOLLOWING", + /* 325 */ "frame_bound ::= CURRENT ROW", + /* 326 */ "frame_exclude_opt ::=", + /* 327 */ "frame_exclude_opt ::= EXCLUDE frame_exclude", + /* 328 */ "frame_exclude ::= NO OTHERS", + /* 329 */ "frame_exclude ::= CURRENT ROW", + /* 330 */ "frame_exclude ::= GROUP|TIES", + /* 331 */ "window_clause ::= WINDOW windowdefn_list", + /* 332 */ "filter_over ::= filter_clause over_clause", + /* 333 */ "filter_over ::= over_clause", + /* 334 */ "filter_over ::= filter_clause", + /* 335 */ "over_clause ::= OVER LP window RP", + /* 336 */ "over_clause ::= OVER nm", + /* 337 */ "filter_clause ::= FILTER LP WHERE expr RP", + /* 338 */ "input ::= cmdlist", + /* 339 */ "cmdlist ::= cmdlist ecmd", + /* 340 */ "cmdlist ::= ecmd", + /* 341 */ "ecmd ::= SEMI", + /* 342 */ "ecmd ::= cmdx SEMI", + /* 343 */ "ecmd ::= explain cmdx SEMI", + /* 344 */ "trans_opt ::=", + /* 345 */ "trans_opt ::= TRANSACTION", + /* 346 */ "trans_opt ::= TRANSACTION nm", + /* 347 */ "savepoint_opt ::= SAVEPOINT", + /* 348 */ "savepoint_opt ::=", + /* 349 */ "cmd ::= create_table create_table_args", + /* 350 */ "table_option_set ::= table_option", + /* 351 */ "columnlist ::= columnlist COMMA columnname carglist", + /* 352 */ "columnlist ::= columnname carglist", + /* 353 */ "nm ::= ID|INDEXED|JOIN_KW", + /* 354 */ "nm ::= STRING", + /* 355 */ "typetoken ::= typename", + /* 356 */ "typename ::= ID|STRING", + /* 357 */ "signed ::= plus_num", + /* 358 */ "signed ::= minus_num", + /* 359 */ "carglist ::= carglist ccons", + /* 360 */ "carglist ::=", + /* 361 */ "ccons ::= NULL onconf", + /* 362 */ "ccons ::= GENERATED ALWAYS AS generated", + /* 363 */ "ccons ::= AS generated", + /* 364 */ "conslist_opt ::= COMMA conslist", + /* 365 */ "conslist ::= conslist tconscomma tcons", + /* 366 */ "conslist ::= tcons", + /* 367 */ "tconscomma ::=", + /* 368 */ "defer_subclause_opt ::= defer_subclause", + /* 369 */ "resolvetype ::= raisetype", + /* 370 */ "selectnowith ::= oneselect", + /* 371 */ "oneselect ::= values", + /* 372 */ "sclp ::= selcollist COMMA", + /* 373 */ "as ::= ID|STRING", + /* 374 */ "indexed_opt ::= indexed_by", + /* 375 */ "returning ::=", + /* 376 */ "expr ::= term", + /* 377 */ "likeop ::= LIKE_KW|MATCH", + /* 378 */ "case_operand ::= expr", + /* 379 */ "exprlist ::= nexprlist", + /* 380 */ "nmnum ::= plus_num", + /* 381 */ "nmnum ::= nm", + /* 382 */ "nmnum ::= ON", + /* 383 */ "nmnum ::= DELETE", + /* 384 */ "nmnum ::= DEFAULT", + /* 385 */ "plus_num ::= INTEGER|FLOAT", + /* 386 */ "foreach_clause ::=", + /* 387 */ "foreach_clause ::= FOR EACH ROW", + /* 388 */ "trnm ::= nm", + /* 389 */ "tridxby ::=", + /* 390 */ "database_kw_opt ::= DATABASE", + /* 391 */ "database_kw_opt ::=", + /* 392 */ "kwcolumn_opt ::=", + /* 393 */ "kwcolumn_opt ::= COLUMNKW", + /* 394 */ "vtabarglist ::= vtabarg", + /* 395 */ "vtabarglist ::= vtabarglist COMMA vtabarg", + /* 396 */ "vtabarg ::= vtabarg vtabargtoken", + /* 397 */ "anylist ::=", + /* 398 */ "anylist ::= anylist LP anylist RP", + /* 399 */ "anylist ::= anylist ANY", + /* 400 */ "with ::=", + /* 401 */ "windowdefn_list ::= windowdefn", + /* 402 */ "window ::= frame_opt", }; #endif /* NDEBUG */ @@ -170754,100 +172255,100 @@ static const YYCODETYPE yyRuleInfoLhs[] = { 304, /* (306) wqitem ::= nm eidlist_opt wqas LP select RP */ 241, /* (307) wqlist ::= wqitem */ 241, /* (308) wqlist ::= wqlist COMMA wqitem */ - 306, /* (309) windowdefn_list ::= windowdefn */ - 306, /* (310) windowdefn_list ::= windowdefn_list COMMA windowdefn */ - 307, /* (311) windowdefn ::= nm AS LP window RP */ - 308, /* (312) window ::= PARTITION BY nexprlist orderby_opt frame_opt */ - 308, /* (313) window ::= nm PARTITION BY nexprlist orderby_opt frame_opt */ - 308, /* (314) window ::= ORDER BY sortlist frame_opt */ - 308, /* (315) window ::= nm ORDER BY sortlist frame_opt */ - 308, /* (316) window ::= frame_opt */ - 308, /* (317) window ::= nm frame_opt */ - 309, /* (318) frame_opt ::= */ - 309, /* (319) frame_opt ::= range_or_rows frame_bound_s frame_exclude_opt */ - 309, /* (320) frame_opt ::= range_or_rows BETWEEN frame_bound_s AND frame_bound_e frame_exclude_opt */ - 313, /* (321) range_or_rows ::= RANGE|ROWS|GROUPS */ - 315, /* (322) frame_bound_s ::= frame_bound */ - 315, /* (323) frame_bound_s ::= UNBOUNDED PRECEDING */ - 316, /* (324) frame_bound_e ::= frame_bound */ - 316, /* (325) frame_bound_e ::= UNBOUNDED FOLLOWING */ - 314, /* (326) frame_bound ::= expr PRECEDING|FOLLOWING */ - 314, /* (327) frame_bound ::= CURRENT ROW */ - 317, /* (328) frame_exclude_opt ::= */ - 317, /* (329) frame_exclude_opt ::= EXCLUDE frame_exclude */ - 318, /* (330) frame_exclude ::= NO OTHERS */ - 318, /* (331) frame_exclude ::= CURRENT ROW */ - 318, /* (332) frame_exclude ::= GROUP|TIES */ - 251, /* (333) window_clause ::= WINDOW windowdefn_list */ - 273, /* (334) filter_over ::= filter_clause over_clause */ - 273, /* (335) filter_over ::= over_clause */ - 273, /* (336) filter_over ::= filter_clause */ - 312, /* (337) over_clause ::= OVER LP window RP */ - 312, /* (338) over_clause ::= OVER nm */ - 311, /* (339) filter_clause ::= FILTER LP WHERE expr RP */ - 185, /* (340) input ::= cmdlist */ - 186, /* (341) cmdlist ::= cmdlist ecmd */ - 186, /* (342) cmdlist ::= ecmd */ - 187, /* (343) ecmd ::= SEMI */ - 187, /* (344) ecmd ::= cmdx SEMI */ - 187, /* (345) ecmd ::= explain cmdx SEMI */ - 192, /* (346) trans_opt ::= */ - 192, /* (347) trans_opt ::= TRANSACTION */ - 192, /* (348) trans_opt ::= TRANSACTION nm */ - 194, /* (349) savepoint_opt ::= SAVEPOINT */ - 194, /* (350) savepoint_opt ::= */ - 190, /* (351) cmd ::= create_table create_table_args */ - 203, /* (352) table_option_set ::= table_option */ - 201, /* (353) columnlist ::= columnlist COMMA columnname carglist */ - 201, /* (354) columnlist ::= columnname carglist */ - 193, /* (355) nm ::= ID|INDEXED|JOIN_KW */ - 193, /* (356) nm ::= STRING */ - 208, /* (357) typetoken ::= typename */ - 209, /* (358) typename ::= ID|STRING */ - 210, /* (359) signed ::= plus_num */ - 210, /* (360) signed ::= minus_num */ - 207, /* (361) carglist ::= carglist ccons */ - 207, /* (362) carglist ::= */ - 215, /* (363) ccons ::= NULL onconf */ - 215, /* (364) ccons ::= GENERATED ALWAYS AS generated */ - 215, /* (365) ccons ::= AS generated */ - 202, /* (366) conslist_opt ::= COMMA conslist */ - 228, /* (367) conslist ::= conslist tconscomma tcons */ - 228, /* (368) conslist ::= tcons */ - 229, /* (369) tconscomma ::= */ - 233, /* (370) defer_subclause_opt ::= defer_subclause */ - 235, /* (371) resolvetype ::= raisetype */ - 239, /* (372) selectnowith ::= oneselect */ - 240, /* (373) oneselect ::= values */ - 254, /* (374) sclp ::= selcollist COMMA */ - 255, /* (375) as ::= ID|STRING */ - 264, /* (376) indexed_opt ::= indexed_by */ - 272, /* (377) returning ::= */ - 217, /* (378) expr ::= term */ - 274, /* (379) likeop ::= LIKE_KW|MATCH */ - 278, /* (380) case_operand ::= expr */ - 261, /* (381) exprlist ::= nexprlist */ - 284, /* (382) nmnum ::= plus_num */ - 284, /* (383) nmnum ::= nm */ - 284, /* (384) nmnum ::= ON */ - 284, /* (385) nmnum ::= DELETE */ - 284, /* (386) nmnum ::= DEFAULT */ - 211, /* (387) plus_num ::= INTEGER|FLOAT */ - 289, /* (388) foreach_clause ::= */ - 289, /* (389) foreach_clause ::= FOR EACH ROW */ - 292, /* (390) trnm ::= nm */ - 293, /* (391) tridxby ::= */ - 294, /* (392) database_kw_opt ::= DATABASE */ - 294, /* (393) database_kw_opt ::= */ - 297, /* (394) kwcolumn_opt ::= */ - 297, /* (395) kwcolumn_opt ::= COLUMNKW */ - 299, /* (396) vtabarglist ::= vtabarg */ - 299, /* (397) vtabarglist ::= vtabarglist COMMA vtabarg */ - 300, /* (398) vtabarg ::= vtabarg vtabargtoken */ - 303, /* (399) anylist ::= */ - 303, /* (400) anylist ::= anylist LP anylist RP */ - 303, /* (401) anylist ::= anylist ANY */ - 266, /* (402) with ::= */ + 306, /* (309) windowdefn_list ::= windowdefn_list COMMA windowdefn */ + 307, /* (310) windowdefn ::= nm AS LP window RP */ + 308, /* (311) window ::= PARTITION BY nexprlist orderby_opt frame_opt */ + 308, /* (312) window ::= nm PARTITION BY nexprlist orderby_opt frame_opt */ + 308, /* (313) window ::= ORDER BY sortlist frame_opt */ + 308, /* (314) window ::= nm ORDER BY sortlist frame_opt */ + 308, /* (315) window ::= nm frame_opt */ + 309, /* (316) frame_opt ::= */ + 309, /* (317) frame_opt ::= range_or_rows frame_bound_s frame_exclude_opt */ + 309, /* (318) frame_opt ::= range_or_rows BETWEEN frame_bound_s AND frame_bound_e frame_exclude_opt */ + 313, /* (319) range_or_rows ::= RANGE|ROWS|GROUPS */ + 315, /* (320) frame_bound_s ::= frame_bound */ + 315, /* (321) frame_bound_s ::= UNBOUNDED PRECEDING */ + 316, /* (322) frame_bound_e ::= frame_bound */ + 316, /* (323) frame_bound_e ::= UNBOUNDED FOLLOWING */ + 314, /* (324) frame_bound ::= expr PRECEDING|FOLLOWING */ + 314, /* (325) frame_bound ::= CURRENT ROW */ + 317, /* (326) frame_exclude_opt ::= */ + 317, /* (327) frame_exclude_opt ::= EXCLUDE frame_exclude */ + 318, /* (328) frame_exclude ::= NO OTHERS */ + 318, /* (329) frame_exclude ::= CURRENT ROW */ + 318, /* (330) frame_exclude ::= GROUP|TIES */ + 251, /* (331) window_clause ::= WINDOW windowdefn_list */ + 273, /* (332) filter_over ::= filter_clause over_clause */ + 273, /* (333) filter_over ::= over_clause */ + 273, /* (334) filter_over ::= filter_clause */ + 312, /* (335) over_clause ::= OVER LP window RP */ + 312, /* (336) over_clause ::= OVER nm */ + 311, /* (337) filter_clause ::= FILTER LP WHERE expr RP */ + 185, /* (338) input ::= cmdlist */ + 186, /* (339) cmdlist ::= cmdlist ecmd */ + 186, /* (340) cmdlist ::= ecmd */ + 187, /* (341) ecmd ::= SEMI */ + 187, /* (342) ecmd ::= cmdx SEMI */ + 187, /* (343) ecmd ::= explain cmdx SEMI */ + 192, /* (344) trans_opt ::= */ + 192, /* (345) trans_opt ::= TRANSACTION */ + 192, /* (346) trans_opt ::= TRANSACTION nm */ + 194, /* (347) savepoint_opt ::= SAVEPOINT */ + 194, /* (348) savepoint_opt ::= */ + 190, /* (349) cmd ::= create_table create_table_args */ + 203, /* (350) table_option_set ::= table_option */ + 201, /* (351) columnlist ::= columnlist COMMA columnname carglist */ + 201, /* (352) columnlist ::= columnname carglist */ + 193, /* (353) nm ::= ID|INDEXED|JOIN_KW */ + 193, /* (354) nm ::= STRING */ + 208, /* (355) typetoken ::= typename */ + 209, /* (356) typename ::= ID|STRING */ + 210, /* (357) signed ::= plus_num */ + 210, /* (358) signed ::= minus_num */ + 207, /* (359) carglist ::= carglist ccons */ + 207, /* (360) carglist ::= */ + 215, /* (361) ccons ::= NULL onconf */ + 215, /* (362) ccons ::= GENERATED ALWAYS AS generated */ + 215, /* (363) ccons ::= AS generated */ + 202, /* (364) conslist_opt ::= COMMA conslist */ + 228, /* (365) conslist ::= conslist tconscomma tcons */ + 228, /* (366) conslist ::= tcons */ + 229, /* (367) tconscomma ::= */ + 233, /* (368) defer_subclause_opt ::= defer_subclause */ + 235, /* (369) resolvetype ::= raisetype */ + 239, /* (370) selectnowith ::= oneselect */ + 240, /* (371) oneselect ::= values */ + 254, /* (372) sclp ::= selcollist COMMA */ + 255, /* (373) as ::= ID|STRING */ + 264, /* (374) indexed_opt ::= indexed_by */ + 272, /* (375) returning ::= */ + 217, /* (376) expr ::= term */ + 274, /* (377) likeop ::= LIKE_KW|MATCH */ + 278, /* (378) case_operand ::= expr */ + 261, /* (379) exprlist ::= nexprlist */ + 284, /* (380) nmnum ::= plus_num */ + 284, /* (381) nmnum ::= nm */ + 284, /* (382) nmnum ::= ON */ + 284, /* (383) nmnum ::= DELETE */ + 284, /* (384) nmnum ::= DEFAULT */ + 211, /* (385) plus_num ::= INTEGER|FLOAT */ + 289, /* (386) foreach_clause ::= */ + 289, /* (387) foreach_clause ::= FOR EACH ROW */ + 292, /* (388) trnm ::= nm */ + 293, /* (389) tridxby ::= */ + 294, /* (390) database_kw_opt ::= DATABASE */ + 294, /* (391) database_kw_opt ::= */ + 297, /* (392) kwcolumn_opt ::= */ + 297, /* (393) kwcolumn_opt ::= COLUMNKW */ + 299, /* (394) vtabarglist ::= vtabarg */ + 299, /* (395) vtabarglist ::= vtabarglist COMMA vtabarg */ + 300, /* (396) vtabarg ::= vtabarg vtabargtoken */ + 303, /* (397) anylist ::= */ + 303, /* (398) anylist ::= anylist LP anylist RP */ + 303, /* (399) anylist ::= anylist ANY */ + 266, /* (400) with ::= */ + 306, /* (401) windowdefn_list ::= windowdefn */ + 308, /* (402) window ::= frame_opt */ }; /* For rule J, yyRuleInfoNRhs[J] contains the negative of the number @@ -171162,100 +172663,100 @@ static const signed char yyRuleInfoNRhs[] = { -6, /* (306) wqitem ::= nm eidlist_opt wqas LP select RP */ -1, /* (307) wqlist ::= wqitem */ -3, /* (308) wqlist ::= wqlist COMMA wqitem */ - -1, /* (309) windowdefn_list ::= windowdefn */ - -3, /* (310) windowdefn_list ::= windowdefn_list COMMA windowdefn */ - -5, /* (311) windowdefn ::= nm AS LP window RP */ - -5, /* (312) window ::= PARTITION BY nexprlist orderby_opt frame_opt */ - -6, /* (313) window ::= nm PARTITION BY nexprlist orderby_opt frame_opt */ - -4, /* (314) window ::= ORDER BY sortlist frame_opt */ - -5, /* (315) window ::= nm ORDER BY sortlist frame_opt */ - -1, /* (316) window ::= frame_opt */ - -2, /* (317) window ::= nm frame_opt */ - 0, /* (318) frame_opt ::= */ - -3, /* (319) frame_opt ::= range_or_rows frame_bound_s frame_exclude_opt */ - -6, /* (320) frame_opt ::= range_or_rows BETWEEN frame_bound_s AND frame_bound_e frame_exclude_opt */ - -1, /* (321) range_or_rows ::= RANGE|ROWS|GROUPS */ - -1, /* (322) frame_bound_s ::= frame_bound */ - -2, /* (323) frame_bound_s ::= UNBOUNDED PRECEDING */ - -1, /* (324) frame_bound_e ::= frame_bound */ - -2, /* (325) frame_bound_e ::= UNBOUNDED FOLLOWING */ - -2, /* (326) frame_bound ::= expr PRECEDING|FOLLOWING */ - -2, /* (327) frame_bound ::= CURRENT ROW */ - 0, /* (328) frame_exclude_opt ::= */ - -2, /* (329) frame_exclude_opt ::= EXCLUDE frame_exclude */ - -2, /* (330) frame_exclude ::= NO OTHERS */ - -2, /* (331) frame_exclude ::= CURRENT ROW */ - -1, /* (332) frame_exclude ::= GROUP|TIES */ - -2, /* (333) window_clause ::= WINDOW windowdefn_list */ - -2, /* (334) filter_over ::= filter_clause over_clause */ - -1, /* (335) filter_over ::= over_clause */ - -1, /* (336) filter_over ::= filter_clause */ - -4, /* (337) over_clause ::= OVER LP window RP */ - -2, /* (338) over_clause ::= OVER nm */ - -5, /* (339) filter_clause ::= FILTER LP WHERE expr RP */ - -1, /* (340) input ::= cmdlist */ - -2, /* (341) cmdlist ::= cmdlist ecmd */ - -1, /* (342) cmdlist ::= ecmd */ - -1, /* (343) ecmd ::= SEMI */ - -2, /* (344) ecmd ::= cmdx SEMI */ - -3, /* (345) ecmd ::= explain cmdx SEMI */ - 0, /* (346) trans_opt ::= */ - -1, /* (347) trans_opt ::= TRANSACTION */ - -2, /* (348) trans_opt ::= TRANSACTION nm */ - -1, /* (349) savepoint_opt ::= SAVEPOINT */ - 0, /* (350) savepoint_opt ::= */ - -2, /* (351) cmd ::= create_table create_table_args */ - -1, /* (352) table_option_set ::= table_option */ - -4, /* (353) columnlist ::= columnlist COMMA columnname carglist */ - -2, /* (354) columnlist ::= columnname carglist */ - -1, /* (355) nm ::= ID|INDEXED|JOIN_KW */ - -1, /* (356) nm ::= STRING */ - -1, /* (357) typetoken ::= typename */ - -1, /* (358) typename ::= ID|STRING */ - -1, /* (359) signed ::= plus_num */ - -1, /* (360) signed ::= minus_num */ - -2, /* (361) carglist ::= carglist ccons */ - 0, /* (362) carglist ::= */ - -2, /* (363) ccons ::= NULL onconf */ - -4, /* (364) ccons ::= GENERATED ALWAYS AS generated */ - -2, /* (365) ccons ::= AS generated */ - -2, /* (366) conslist_opt ::= COMMA conslist */ - -3, /* (367) conslist ::= conslist tconscomma tcons */ - -1, /* (368) conslist ::= tcons */ - 0, /* (369) tconscomma ::= */ - -1, /* (370) defer_subclause_opt ::= defer_subclause */ - -1, /* (371) resolvetype ::= raisetype */ - -1, /* (372) selectnowith ::= oneselect */ - -1, /* (373) oneselect ::= values */ - -2, /* (374) sclp ::= selcollist COMMA */ - -1, /* (375) as ::= ID|STRING */ - -1, /* (376) indexed_opt ::= indexed_by */ - 0, /* (377) returning ::= */ - -1, /* (378) expr ::= term */ - -1, /* (379) likeop ::= LIKE_KW|MATCH */ - -1, /* (380) case_operand ::= expr */ - -1, /* (381) exprlist ::= nexprlist */ - -1, /* (382) nmnum ::= plus_num */ - -1, /* (383) nmnum ::= nm */ - -1, /* (384) nmnum ::= ON */ - -1, /* (385) nmnum ::= DELETE */ - -1, /* (386) nmnum ::= DEFAULT */ - -1, /* (387) plus_num ::= INTEGER|FLOAT */ - 0, /* (388) foreach_clause ::= */ - -3, /* (389) foreach_clause ::= FOR EACH ROW */ - -1, /* (390) trnm ::= nm */ - 0, /* (391) tridxby ::= */ - -1, /* (392) database_kw_opt ::= DATABASE */ - 0, /* (393) database_kw_opt ::= */ - 0, /* (394) kwcolumn_opt ::= */ - -1, /* (395) kwcolumn_opt ::= COLUMNKW */ - -1, /* (396) vtabarglist ::= vtabarg */ - -3, /* (397) vtabarglist ::= vtabarglist COMMA vtabarg */ - -2, /* (398) vtabarg ::= vtabarg vtabargtoken */ - 0, /* (399) anylist ::= */ - -4, /* (400) anylist ::= anylist LP anylist RP */ - -2, /* (401) anylist ::= anylist ANY */ - 0, /* (402) with ::= */ + -3, /* (309) windowdefn_list ::= windowdefn_list COMMA windowdefn */ + -5, /* (310) windowdefn ::= nm AS LP window RP */ + -5, /* (311) window ::= PARTITION BY nexprlist orderby_opt frame_opt */ + -6, /* (312) window ::= nm PARTITION BY nexprlist orderby_opt frame_opt */ + -4, /* (313) window ::= ORDER BY sortlist frame_opt */ + -5, /* (314) window ::= nm ORDER BY sortlist frame_opt */ + -2, /* (315) window ::= nm frame_opt */ + 0, /* (316) frame_opt ::= */ + -3, /* (317) frame_opt ::= range_or_rows frame_bound_s frame_exclude_opt */ + -6, /* (318) frame_opt ::= range_or_rows BETWEEN frame_bound_s AND frame_bound_e frame_exclude_opt */ + -1, /* (319) range_or_rows ::= RANGE|ROWS|GROUPS */ + -1, /* (320) frame_bound_s ::= frame_bound */ + -2, /* (321) frame_bound_s ::= UNBOUNDED PRECEDING */ + -1, /* (322) frame_bound_e ::= frame_bound */ + -2, /* (323) frame_bound_e ::= UNBOUNDED FOLLOWING */ + -2, /* (324) frame_bound ::= expr PRECEDING|FOLLOWING */ + -2, /* (325) frame_bound ::= CURRENT ROW */ + 0, /* (326) frame_exclude_opt ::= */ + -2, /* (327) frame_exclude_opt ::= EXCLUDE frame_exclude */ + -2, /* (328) frame_exclude ::= NO OTHERS */ + -2, /* (329) frame_exclude ::= CURRENT ROW */ + -1, /* (330) frame_exclude ::= GROUP|TIES */ + -2, /* (331) window_clause ::= WINDOW windowdefn_list */ + -2, /* (332) filter_over ::= filter_clause over_clause */ + -1, /* (333) filter_over ::= over_clause */ + -1, /* (334) filter_over ::= filter_clause */ + -4, /* (335) over_clause ::= OVER LP window RP */ + -2, /* (336) over_clause ::= OVER nm */ + -5, /* (337) filter_clause ::= FILTER LP WHERE expr RP */ + -1, /* (338) input ::= cmdlist */ + -2, /* (339) cmdlist ::= cmdlist ecmd */ + -1, /* (340) cmdlist ::= ecmd */ + -1, /* (341) ecmd ::= SEMI */ + -2, /* (342) ecmd ::= cmdx SEMI */ + -3, /* (343) ecmd ::= explain cmdx SEMI */ + 0, /* (344) trans_opt ::= */ + -1, /* (345) trans_opt ::= TRANSACTION */ + -2, /* (346) trans_opt ::= TRANSACTION nm */ + -1, /* (347) savepoint_opt ::= SAVEPOINT */ + 0, /* (348) savepoint_opt ::= */ + -2, /* (349) cmd ::= create_table create_table_args */ + -1, /* (350) table_option_set ::= table_option */ + -4, /* (351) columnlist ::= columnlist COMMA columnname carglist */ + -2, /* (352) columnlist ::= columnname carglist */ + -1, /* (353) nm ::= ID|INDEXED|JOIN_KW */ + -1, /* (354) nm ::= STRING */ + -1, /* (355) typetoken ::= typename */ + -1, /* (356) typename ::= ID|STRING */ + -1, /* (357) signed ::= plus_num */ + -1, /* (358) signed ::= minus_num */ + -2, /* (359) carglist ::= carglist ccons */ + 0, /* (360) carglist ::= */ + -2, /* (361) ccons ::= NULL onconf */ + -4, /* (362) ccons ::= GENERATED ALWAYS AS generated */ + -2, /* (363) ccons ::= AS generated */ + -2, /* (364) conslist_opt ::= COMMA conslist */ + -3, /* (365) conslist ::= conslist tconscomma tcons */ + -1, /* (366) conslist ::= tcons */ + 0, /* (367) tconscomma ::= */ + -1, /* (368) defer_subclause_opt ::= defer_subclause */ + -1, /* (369) resolvetype ::= raisetype */ + -1, /* (370) selectnowith ::= oneselect */ + -1, /* (371) oneselect ::= values */ + -2, /* (372) sclp ::= selcollist COMMA */ + -1, /* (373) as ::= ID|STRING */ + -1, /* (374) indexed_opt ::= indexed_by */ + 0, /* (375) returning ::= */ + -1, /* (376) expr ::= term */ + -1, /* (377) likeop ::= LIKE_KW|MATCH */ + -1, /* (378) case_operand ::= expr */ + -1, /* (379) exprlist ::= nexprlist */ + -1, /* (380) nmnum ::= plus_num */ + -1, /* (381) nmnum ::= nm */ + -1, /* (382) nmnum ::= ON */ + -1, /* (383) nmnum ::= DELETE */ + -1, /* (384) nmnum ::= DEFAULT */ + -1, /* (385) plus_num ::= INTEGER|FLOAT */ + 0, /* (386) foreach_clause ::= */ + -3, /* (387) foreach_clause ::= FOR EACH ROW */ + -1, /* (388) trnm ::= nm */ + 0, /* (389) tridxby ::= */ + -1, /* (390) database_kw_opt ::= DATABASE */ + 0, /* (391) database_kw_opt ::= */ + 0, /* (392) kwcolumn_opt ::= */ + -1, /* (393) kwcolumn_opt ::= COLUMNKW */ + -1, /* (394) vtabarglist ::= vtabarg */ + -3, /* (395) vtabarglist ::= vtabarglist COMMA vtabarg */ + -2, /* (396) vtabarg ::= vtabarg vtabargtoken */ + 0, /* (397) anylist ::= */ + -4, /* (398) anylist ::= anylist LP anylist RP */ + -2, /* (399) anylist ::= anylist ANY */ + 0, /* (400) with ::= */ + -1, /* (401) windowdefn_list ::= windowdefn */ + -1, /* (402) window ::= frame_opt */ }; static void yy_accept(yyParser*); /* Forward Declaration */ @@ -171298,10 +172799,10 @@ static YYACTIONTYPE yy_reduce( /********** Begin reduce actions **********************************************/ YYMINORTYPE yylhsminor; case 0: /* explain ::= EXPLAIN */ -{ pParse->explain = 1; } +{ if( pParse->pReprepare==0 ) pParse->explain = 1; } break; case 1: /* explain ::= EXPLAIN QUERY PLAN */ -{ pParse->explain = 2; } +{ if( pParse->pReprepare==0 ) pParse->explain = 2; } break; case 2: /* cmdx ::= cmd */ { sqlite3FinishCoding(pParse); } @@ -171315,7 +172816,7 @@ static YYACTIONTYPE yy_reduce( case 5: /* transtype ::= DEFERRED */ case 6: /* transtype ::= IMMEDIATE */ yytestcase(yyruleno==6); case 7: /* transtype ::= EXCLUSIVE */ yytestcase(yyruleno==7); - case 321: /* range_or_rows ::= RANGE|ROWS|GROUPS */ yytestcase(yyruleno==321); + case 319: /* range_or_rows ::= RANGE|ROWS|GROUPS */ yytestcase(yyruleno==319); {yymsp[0].minor.yy394 = yymsp[0].major; /*A-overwrites-X*/} break; case 8: /* cmd ::= COMMIT|END trans_opt */ @@ -171611,7 +173112,6 @@ static YYACTIONTYPE yy_reduce( if( p ){ parserDoubleLinkSelect(pParse, p); } - yymsp[0].minor.yy47 = p; /*A-overwrites-X*/ } break; case 88: /* selectnowith ::= selectnowith multiselect_op oneselect */ @@ -171703,14 +173203,17 @@ static YYACTIONTYPE yy_reduce( case 101: /* selcollist ::= sclp scanpt STAR */ { Expr *p = sqlite3Expr(pParse->db, TK_ASTERISK, 0); + sqlite3ExprSetErrorOffset(p, (int)(yymsp[0].minor.yy0.z - pParse->zTail)); yymsp[-2].minor.yy322 = sqlite3ExprListAppend(pParse, yymsp[-2].minor.yy322, p); } break; case 102: /* selcollist ::= sclp scanpt nm DOT STAR */ { - Expr *pRight = sqlite3PExpr(pParse, TK_ASTERISK, 0, 0); - Expr *pLeft = tokenExpr(pParse, TK_ID, yymsp[-2].minor.yy0); - Expr *pDot = sqlite3PExpr(pParse, TK_DOT, pLeft, pRight); + Expr *pRight, *pLeft, *pDot; + pRight = sqlite3PExpr(pParse, TK_ASTERISK, 0, 0); + sqlite3ExprSetErrorOffset(pRight, (int)(yymsp[0].minor.yy0.z - pParse->zTail)); + pLeft = tokenExpr(pParse, TK_ID, yymsp[-2].minor.yy0); + pDot = sqlite3PExpr(pParse, TK_DOT, pLeft, pRight); yymsp[-4].minor.yy322 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy322, pDot); } break; @@ -172604,11 +174107,7 @@ static YYACTIONTYPE yy_reduce( yymsp[-2].minor.yy521 = sqlite3WithAdd(pParse, yymsp[-2].minor.yy521, yymsp[0].minor.yy385); } break; - case 309: /* windowdefn_list ::= windowdefn */ -{ yylhsminor.yy41 = yymsp[0].minor.yy41; } - yymsp[0].minor.yy41 = yylhsminor.yy41; - break; - case 310: /* windowdefn_list ::= windowdefn_list COMMA windowdefn */ + case 309: /* windowdefn_list ::= windowdefn_list COMMA windowdefn */ { assert( yymsp[0].minor.yy41!=0 ); sqlite3WindowChain(pParse, yymsp[0].minor.yy41, yymsp[-2].minor.yy41); @@ -172617,7 +174116,7 @@ static YYACTIONTYPE yy_reduce( } yymsp[-2].minor.yy41 = yylhsminor.yy41; break; - case 311: /* windowdefn ::= nm AS LP window RP */ + case 310: /* windowdefn ::= nm AS LP window RP */ { if( ALWAYS(yymsp[-1].minor.yy41) ){ yymsp[-1].minor.yy41->zName = sqlite3DbStrNDup(pParse->db, yymsp[-4].minor.yy0.z, yymsp[-4].minor.yy0.n); @@ -172626,90 +174125,83 @@ static YYACTIONTYPE yy_reduce( } yymsp[-4].minor.yy41 = yylhsminor.yy41; break; - case 312: /* window ::= PARTITION BY nexprlist orderby_opt frame_opt */ + case 311: /* window ::= PARTITION BY nexprlist orderby_opt frame_opt */ { yymsp[-4].minor.yy41 = sqlite3WindowAssemble(pParse, yymsp[0].minor.yy41, yymsp[-2].minor.yy322, yymsp[-1].minor.yy322, 0); } break; - case 313: /* window ::= nm PARTITION BY nexprlist orderby_opt frame_opt */ + case 312: /* window ::= nm PARTITION BY nexprlist orderby_opt frame_opt */ { yylhsminor.yy41 = sqlite3WindowAssemble(pParse, yymsp[0].minor.yy41, yymsp[-2].minor.yy322, yymsp[-1].minor.yy322, &yymsp[-5].minor.yy0); } yymsp[-5].minor.yy41 = yylhsminor.yy41; break; - case 314: /* window ::= ORDER BY sortlist frame_opt */ + case 313: /* window ::= ORDER BY sortlist frame_opt */ { yymsp[-3].minor.yy41 = sqlite3WindowAssemble(pParse, yymsp[0].minor.yy41, 0, yymsp[-1].minor.yy322, 0); } break; - case 315: /* window ::= nm ORDER BY sortlist frame_opt */ + case 314: /* window ::= nm ORDER BY sortlist frame_opt */ { yylhsminor.yy41 = sqlite3WindowAssemble(pParse, yymsp[0].minor.yy41, 0, yymsp[-1].minor.yy322, &yymsp[-4].minor.yy0); } yymsp[-4].minor.yy41 = yylhsminor.yy41; break; - case 316: /* window ::= frame_opt */ - case 335: /* filter_over ::= over_clause */ yytestcase(yyruleno==335); -{ - yylhsminor.yy41 = yymsp[0].minor.yy41; -} - yymsp[0].minor.yy41 = yylhsminor.yy41; - break; - case 317: /* window ::= nm frame_opt */ + case 315: /* window ::= nm frame_opt */ { yylhsminor.yy41 = sqlite3WindowAssemble(pParse, yymsp[0].minor.yy41, 0, 0, &yymsp[-1].minor.yy0); } yymsp[-1].minor.yy41 = yylhsminor.yy41; break; - case 318: /* frame_opt ::= */ + case 316: /* frame_opt ::= */ { yymsp[1].minor.yy41 = sqlite3WindowAlloc(pParse, 0, TK_UNBOUNDED, 0, TK_CURRENT, 0, 0); } break; - case 319: /* frame_opt ::= range_or_rows frame_bound_s frame_exclude_opt */ + case 317: /* frame_opt ::= range_or_rows frame_bound_s frame_exclude_opt */ { yylhsminor.yy41 = sqlite3WindowAlloc(pParse, yymsp[-2].minor.yy394, yymsp[-1].minor.yy595.eType, yymsp[-1].minor.yy595.pExpr, TK_CURRENT, 0, yymsp[0].minor.yy516); } yymsp[-2].minor.yy41 = yylhsminor.yy41; break; - case 320: /* frame_opt ::= range_or_rows BETWEEN frame_bound_s AND frame_bound_e frame_exclude_opt */ + case 318: /* frame_opt ::= range_or_rows BETWEEN frame_bound_s AND frame_bound_e frame_exclude_opt */ { yylhsminor.yy41 = sqlite3WindowAlloc(pParse, yymsp[-5].minor.yy394, yymsp[-3].minor.yy595.eType, yymsp[-3].minor.yy595.pExpr, yymsp[-1].minor.yy595.eType, yymsp[-1].minor.yy595.pExpr, yymsp[0].minor.yy516); } yymsp[-5].minor.yy41 = yylhsminor.yy41; break; - case 322: /* frame_bound_s ::= frame_bound */ - case 324: /* frame_bound_e ::= frame_bound */ yytestcase(yyruleno==324); + case 320: /* frame_bound_s ::= frame_bound */ + case 322: /* frame_bound_e ::= frame_bound */ yytestcase(yyruleno==322); {yylhsminor.yy595 = yymsp[0].minor.yy595;} yymsp[0].minor.yy595 = yylhsminor.yy595; break; - case 323: /* frame_bound_s ::= UNBOUNDED PRECEDING */ - case 325: /* frame_bound_e ::= UNBOUNDED FOLLOWING */ yytestcase(yyruleno==325); - case 327: /* frame_bound ::= CURRENT ROW */ yytestcase(yyruleno==327); + case 321: /* frame_bound_s ::= UNBOUNDED PRECEDING */ + case 323: /* frame_bound_e ::= UNBOUNDED FOLLOWING */ yytestcase(yyruleno==323); + case 325: /* frame_bound ::= CURRENT ROW */ yytestcase(yyruleno==325); {yylhsminor.yy595.eType = yymsp[-1].major; yylhsminor.yy595.pExpr = 0;} yymsp[-1].minor.yy595 = yylhsminor.yy595; break; - case 326: /* frame_bound ::= expr PRECEDING|FOLLOWING */ + case 324: /* frame_bound ::= expr PRECEDING|FOLLOWING */ {yylhsminor.yy595.eType = yymsp[0].major; yylhsminor.yy595.pExpr = yymsp[-1].minor.yy528;} yymsp[-1].minor.yy595 = yylhsminor.yy595; break; - case 328: /* frame_exclude_opt ::= */ + case 326: /* frame_exclude_opt ::= */ {yymsp[1].minor.yy516 = 0;} break; - case 329: /* frame_exclude_opt ::= EXCLUDE frame_exclude */ + case 327: /* frame_exclude_opt ::= EXCLUDE frame_exclude */ {yymsp[-1].minor.yy516 = yymsp[0].minor.yy516;} break; - case 330: /* frame_exclude ::= NO OTHERS */ - case 331: /* frame_exclude ::= CURRENT ROW */ yytestcase(yyruleno==331); + case 328: /* frame_exclude ::= NO OTHERS */ + case 329: /* frame_exclude ::= CURRENT ROW */ yytestcase(yyruleno==329); {yymsp[-1].minor.yy516 = yymsp[-1].major; /*A-overwrites-X*/} break; - case 332: /* frame_exclude ::= GROUP|TIES */ + case 330: /* frame_exclude ::= GROUP|TIES */ {yymsp[0].minor.yy516 = yymsp[0].major; /*A-overwrites-X*/} break; - case 333: /* window_clause ::= WINDOW windowdefn_list */ + case 331: /* window_clause ::= WINDOW windowdefn_list */ { yymsp[-1].minor.yy41 = yymsp[0].minor.yy41; } break; - case 334: /* filter_over ::= filter_clause over_clause */ + case 332: /* filter_over ::= filter_clause over_clause */ { if( yymsp[0].minor.yy41 ){ yymsp[0].minor.yy41->pFilter = yymsp[-1].minor.yy528; @@ -172720,7 +174212,13 @@ static YYACTIONTYPE yy_reduce( } yymsp[-1].minor.yy41 = yylhsminor.yy41; break; - case 336: /* filter_over ::= filter_clause */ + case 333: /* filter_over ::= over_clause */ +{ + yylhsminor.yy41 = yymsp[0].minor.yy41; +} + yymsp[0].minor.yy41 = yylhsminor.yy41; + break; + case 334: /* filter_over ::= filter_clause */ { yylhsminor.yy41 = (Window*)sqlite3DbMallocZero(pParse->db, sizeof(Window)); if( yylhsminor.yy41 ){ @@ -172732,13 +174230,13 @@ static YYACTIONTYPE yy_reduce( } yymsp[0].minor.yy41 = yylhsminor.yy41; break; - case 337: /* over_clause ::= OVER LP window RP */ + case 335: /* over_clause ::= OVER LP window RP */ { yymsp[-3].minor.yy41 = yymsp[-1].minor.yy41; assert( yymsp[-3].minor.yy41!=0 ); } break; - case 338: /* over_clause ::= OVER nm */ + case 336: /* over_clause ::= OVER nm */ { yymsp[-1].minor.yy41 = (Window*)sqlite3DbMallocZero(pParse->db, sizeof(Window)); if( yymsp[-1].minor.yy41 ){ @@ -172746,73 +174244,75 @@ static YYACTIONTYPE yy_reduce( } } break; - case 339: /* filter_clause ::= FILTER LP WHERE expr RP */ + case 337: /* filter_clause ::= FILTER LP WHERE expr RP */ { yymsp[-4].minor.yy528 = yymsp[-1].minor.yy528; } break; default: - /* (340) input ::= cmdlist */ yytestcase(yyruleno==340); - /* (341) cmdlist ::= cmdlist ecmd */ yytestcase(yyruleno==341); - /* (342) cmdlist ::= ecmd (OPTIMIZED OUT) */ assert(yyruleno!=342); - /* (343) ecmd ::= SEMI */ yytestcase(yyruleno==343); - /* (344) ecmd ::= cmdx SEMI */ yytestcase(yyruleno==344); - /* (345) ecmd ::= explain cmdx SEMI (NEVER REDUCES) */ assert(yyruleno!=345); - /* (346) trans_opt ::= */ yytestcase(yyruleno==346); - /* (347) trans_opt ::= TRANSACTION */ yytestcase(yyruleno==347); - /* (348) trans_opt ::= TRANSACTION nm */ yytestcase(yyruleno==348); - /* (349) savepoint_opt ::= SAVEPOINT */ yytestcase(yyruleno==349); - /* (350) savepoint_opt ::= */ yytestcase(yyruleno==350); - /* (351) cmd ::= create_table create_table_args */ yytestcase(yyruleno==351); - /* (352) table_option_set ::= table_option (OPTIMIZED OUT) */ assert(yyruleno!=352); - /* (353) columnlist ::= columnlist COMMA columnname carglist */ yytestcase(yyruleno==353); - /* (354) columnlist ::= columnname carglist */ yytestcase(yyruleno==354); - /* (355) nm ::= ID|INDEXED|JOIN_KW */ yytestcase(yyruleno==355); - /* (356) nm ::= STRING */ yytestcase(yyruleno==356); - /* (357) typetoken ::= typename */ yytestcase(yyruleno==357); - /* (358) typename ::= ID|STRING */ yytestcase(yyruleno==358); - /* (359) signed ::= plus_num (OPTIMIZED OUT) */ assert(yyruleno!=359); - /* (360) signed ::= minus_num (OPTIMIZED OUT) */ assert(yyruleno!=360); - /* (361) carglist ::= carglist ccons */ yytestcase(yyruleno==361); - /* (362) carglist ::= */ yytestcase(yyruleno==362); - /* (363) ccons ::= NULL onconf */ yytestcase(yyruleno==363); - /* (364) ccons ::= GENERATED ALWAYS AS generated */ yytestcase(yyruleno==364); - /* (365) ccons ::= AS generated */ yytestcase(yyruleno==365); - /* (366) conslist_opt ::= COMMA conslist */ yytestcase(yyruleno==366); - /* (367) conslist ::= conslist tconscomma tcons */ yytestcase(yyruleno==367); - /* (368) conslist ::= tcons (OPTIMIZED OUT) */ assert(yyruleno!=368); - /* (369) tconscomma ::= */ yytestcase(yyruleno==369); - /* (370) defer_subclause_opt ::= defer_subclause (OPTIMIZED OUT) */ assert(yyruleno!=370); - /* (371) resolvetype ::= raisetype (OPTIMIZED OUT) */ assert(yyruleno!=371); - /* (372) selectnowith ::= oneselect (OPTIMIZED OUT) */ assert(yyruleno!=372); - /* (373) oneselect ::= values */ yytestcase(yyruleno==373); - /* (374) sclp ::= selcollist COMMA */ yytestcase(yyruleno==374); - /* (375) as ::= ID|STRING */ yytestcase(yyruleno==375); - /* (376) indexed_opt ::= indexed_by (OPTIMIZED OUT) */ assert(yyruleno!=376); - /* (377) returning ::= */ yytestcase(yyruleno==377); - /* (378) expr ::= term (OPTIMIZED OUT) */ assert(yyruleno!=378); - /* (379) likeop ::= LIKE_KW|MATCH */ yytestcase(yyruleno==379); - /* (380) case_operand ::= expr */ yytestcase(yyruleno==380); - /* (381) exprlist ::= nexprlist */ yytestcase(yyruleno==381); - /* (382) nmnum ::= plus_num (OPTIMIZED OUT) */ assert(yyruleno!=382); - /* (383) nmnum ::= nm (OPTIMIZED OUT) */ assert(yyruleno!=383); - /* (384) nmnum ::= ON */ yytestcase(yyruleno==384); - /* (385) nmnum ::= DELETE */ yytestcase(yyruleno==385); - /* (386) nmnum ::= DEFAULT */ yytestcase(yyruleno==386); - /* (387) plus_num ::= INTEGER|FLOAT */ yytestcase(yyruleno==387); - /* (388) foreach_clause ::= */ yytestcase(yyruleno==388); - /* (389) foreach_clause ::= FOR EACH ROW */ yytestcase(yyruleno==389); - /* (390) trnm ::= nm */ yytestcase(yyruleno==390); - /* (391) tridxby ::= */ yytestcase(yyruleno==391); - /* (392) database_kw_opt ::= DATABASE */ yytestcase(yyruleno==392); - /* (393) database_kw_opt ::= */ yytestcase(yyruleno==393); - /* (394) kwcolumn_opt ::= */ yytestcase(yyruleno==394); - /* (395) kwcolumn_opt ::= COLUMNKW */ yytestcase(yyruleno==395); - /* (396) vtabarglist ::= vtabarg */ yytestcase(yyruleno==396); - /* (397) vtabarglist ::= vtabarglist COMMA vtabarg */ yytestcase(yyruleno==397); - /* (398) vtabarg ::= vtabarg vtabargtoken */ yytestcase(yyruleno==398); - /* (399) anylist ::= */ yytestcase(yyruleno==399); - /* (400) anylist ::= anylist LP anylist RP */ yytestcase(yyruleno==400); - /* (401) anylist ::= anylist ANY */ yytestcase(yyruleno==401); - /* (402) with ::= */ yytestcase(yyruleno==402); + /* (338) input ::= cmdlist */ yytestcase(yyruleno==338); + /* (339) cmdlist ::= cmdlist ecmd */ yytestcase(yyruleno==339); + /* (340) cmdlist ::= ecmd (OPTIMIZED OUT) */ assert(yyruleno!=340); + /* (341) ecmd ::= SEMI */ yytestcase(yyruleno==341); + /* (342) ecmd ::= cmdx SEMI */ yytestcase(yyruleno==342); + /* (343) ecmd ::= explain cmdx SEMI (NEVER REDUCES) */ assert(yyruleno!=343); + /* (344) trans_opt ::= */ yytestcase(yyruleno==344); + /* (345) trans_opt ::= TRANSACTION */ yytestcase(yyruleno==345); + /* (346) trans_opt ::= TRANSACTION nm */ yytestcase(yyruleno==346); + /* (347) savepoint_opt ::= SAVEPOINT */ yytestcase(yyruleno==347); + /* (348) savepoint_opt ::= */ yytestcase(yyruleno==348); + /* (349) cmd ::= create_table create_table_args */ yytestcase(yyruleno==349); + /* (350) table_option_set ::= table_option (OPTIMIZED OUT) */ assert(yyruleno!=350); + /* (351) columnlist ::= columnlist COMMA columnname carglist */ yytestcase(yyruleno==351); + /* (352) columnlist ::= columnname carglist */ yytestcase(yyruleno==352); + /* (353) nm ::= ID|INDEXED|JOIN_KW */ yytestcase(yyruleno==353); + /* (354) nm ::= STRING */ yytestcase(yyruleno==354); + /* (355) typetoken ::= typename */ yytestcase(yyruleno==355); + /* (356) typename ::= ID|STRING */ yytestcase(yyruleno==356); + /* (357) signed ::= plus_num (OPTIMIZED OUT) */ assert(yyruleno!=357); + /* (358) signed ::= minus_num (OPTIMIZED OUT) */ assert(yyruleno!=358); + /* (359) carglist ::= carglist ccons */ yytestcase(yyruleno==359); + /* (360) carglist ::= */ yytestcase(yyruleno==360); + /* (361) ccons ::= NULL onconf */ yytestcase(yyruleno==361); + /* (362) ccons ::= GENERATED ALWAYS AS generated */ yytestcase(yyruleno==362); + /* (363) ccons ::= AS generated */ yytestcase(yyruleno==363); + /* (364) conslist_opt ::= COMMA conslist */ yytestcase(yyruleno==364); + /* (365) conslist ::= conslist tconscomma tcons */ yytestcase(yyruleno==365); + /* (366) conslist ::= tcons (OPTIMIZED OUT) */ assert(yyruleno!=366); + /* (367) tconscomma ::= */ yytestcase(yyruleno==367); + /* (368) defer_subclause_opt ::= defer_subclause (OPTIMIZED OUT) */ assert(yyruleno!=368); + /* (369) resolvetype ::= raisetype (OPTIMIZED OUT) */ assert(yyruleno!=369); + /* (370) selectnowith ::= oneselect (OPTIMIZED OUT) */ assert(yyruleno!=370); + /* (371) oneselect ::= values */ yytestcase(yyruleno==371); + /* (372) sclp ::= selcollist COMMA */ yytestcase(yyruleno==372); + /* (373) as ::= ID|STRING */ yytestcase(yyruleno==373); + /* (374) indexed_opt ::= indexed_by (OPTIMIZED OUT) */ assert(yyruleno!=374); + /* (375) returning ::= */ yytestcase(yyruleno==375); + /* (376) expr ::= term (OPTIMIZED OUT) */ assert(yyruleno!=376); + /* (377) likeop ::= LIKE_KW|MATCH */ yytestcase(yyruleno==377); + /* (378) case_operand ::= expr */ yytestcase(yyruleno==378); + /* (379) exprlist ::= nexprlist */ yytestcase(yyruleno==379); + /* (380) nmnum ::= plus_num (OPTIMIZED OUT) */ assert(yyruleno!=380); + /* (381) nmnum ::= nm (OPTIMIZED OUT) */ assert(yyruleno!=381); + /* (382) nmnum ::= ON */ yytestcase(yyruleno==382); + /* (383) nmnum ::= DELETE */ yytestcase(yyruleno==383); + /* (384) nmnum ::= DEFAULT */ yytestcase(yyruleno==384); + /* (385) plus_num ::= INTEGER|FLOAT */ yytestcase(yyruleno==385); + /* (386) foreach_clause ::= */ yytestcase(yyruleno==386); + /* (387) foreach_clause ::= FOR EACH ROW */ yytestcase(yyruleno==387); + /* (388) trnm ::= nm */ yytestcase(yyruleno==388); + /* (389) tridxby ::= */ yytestcase(yyruleno==389); + /* (390) database_kw_opt ::= DATABASE */ yytestcase(yyruleno==390); + /* (391) database_kw_opt ::= */ yytestcase(yyruleno==391); + /* (392) kwcolumn_opt ::= */ yytestcase(yyruleno==392); + /* (393) kwcolumn_opt ::= COLUMNKW */ yytestcase(yyruleno==393); + /* (394) vtabarglist ::= vtabarg */ yytestcase(yyruleno==394); + /* (395) vtabarglist ::= vtabarglist COMMA vtabarg */ yytestcase(yyruleno==395); + /* (396) vtabarg ::= vtabarg vtabargtoken */ yytestcase(yyruleno==396); + /* (397) anylist ::= */ yytestcase(yyruleno==397); + /* (398) anylist ::= anylist LP anylist RP */ yytestcase(yyruleno==398); + /* (399) anylist ::= anylist ANY */ yytestcase(yyruleno==399); + /* (400) with ::= */ yytestcase(yyruleno==400); + /* (401) windowdefn_list ::= windowdefn (OPTIMIZED OUT) */ assert(yyruleno!=401); + /* (402) window ::= frame_opt (OPTIMIZED OUT) */ assert(yyruleno!=402); break; /********** End reduce actions ************************************************/ }; @@ -173601,180 +175101,179 @@ static const unsigned char aKWCode[148] = {0, static int keywordCode(const char *z, int n, int *pType){ int i, j; const char *zKW; - if( n>=2 ){ - i = ((charMap(z[0])*4) ^ (charMap(z[n-1])*3) ^ n*1) % 127; - for(i=(int)aKWHash[i]; i>0; i=aKWNext[i]){ - if( aKWLen[i]!=n ) continue; - zKW = &zKWText[aKWOffset[i]]; + assert( n>=2 ); + i = ((charMap(z[0])*4) ^ (charMap(z[n-1])*3) ^ n*1) % 127; + for(i=(int)aKWHash[i]; i>0; i=aKWNext[i]){ + if( aKWLen[i]!=n ) continue; + zKW = &zKWText[aKWOffset[i]]; #ifdef SQLITE_ASCII - if( (z[0]&~0x20)!=zKW[0] ) continue; - if( (z[1]&~0x20)!=zKW[1] ) continue; - j = 2; - while( j=2 ) keywordCode((char*)z, n, &id); return id; } #define SQLITE_N_KEYWORD 147 @@ -174079,7 +175578,7 @@ SQLITE_PRIVATE int sqlite3GetToken(const unsigned char *z, int *tokenType){ testcase( z[0]=='0' ); testcase( z[0]=='1' ); testcase( z[0]=='2' ); testcase( z[0]=='3' ); testcase( z[0]=='4' ); testcase( z[0]=='5' ); testcase( z[0]=='6' ); testcase( z[0]=='7' ); testcase( z[0]=='8' ); - testcase( z[0]=='9' ); + testcase( z[0]=='9' ); testcase( z[0]=='.' ); *tokenType = TK_INTEGER; #ifndef SQLITE_OMIT_HEX_INTEGER if( z[0]=='0' && (z[1]=='x' || z[1]=='X') && sqlite3Isxdigit(z[2]) ){ @@ -174151,7 +175650,8 @@ SQLITE_PRIVATE int sqlite3GetToken(const unsigned char *z, int *tokenType){ return i; } case CC_KYWD0: { - for(i=1; aiClass[z[i]]<=CC_KYWD; i++){} + if( aiClass[z[1]]>CC_KYWD ){ i = 1; break; } + for(i=2; aiClass[z[i]]<=CC_KYWD; i++){} if( IdChar(z[i]) ){ /* This token started out using characters that can appear in keywords, ** but z[i] is a character not allowed within keywords, so this must @@ -174930,12 +176430,6 @@ static int sqlite3TestExtInit(sqlite3 *db){ ** Forward declarations of external module initializer functions ** for modules that need them. */ -#ifdef SQLITE_ENABLE_FTS1 -SQLITE_PRIVATE int sqlite3Fts1Init(sqlite3*); -#endif -#ifdef SQLITE_ENABLE_FTS2 -SQLITE_PRIVATE int sqlite3Fts2Init(sqlite3*); -#endif #ifdef SQLITE_ENABLE_FTS5 SQLITE_PRIVATE int sqlite3Fts5Init(sqlite3*); #endif @@ -174948,12 +176442,6 @@ SQLITE_PRIVATE int sqlite3StmtVtabInit(sqlite3*); ** built-in extensions. */ static int (*const sqlite3BuiltinExtensions[])(sqlite3*) = { -#ifdef SQLITE_ENABLE_FTS1 - sqlite3Fts1Init, -#endif -#ifdef SQLITE_ENABLE_FTS2 - sqlite3Fts2Init, -#endif #ifdef SQLITE_ENABLE_FTS3 sqlite3Fts3Init, #endif @@ -176566,9 +178054,9 @@ static int sqliteDefaultBusyCallback( void *ptr, /* Database connection */ int count /* Number of times table has been busy */ ){ -#if SQLITE_OS_WIN || HAVE_USLEEP +#if SQLITE_OS_WIN || !defined(HAVE_NANOSLEEP) || HAVE_NANOSLEEP /* This case is for systems that have support for sleeping for fractions of - ** a second. Examples: All windows systems, unix systems with usleep() */ + ** a second. Examples: All windows systems, unix systems with nanosleep() */ static const u8 delays[] = { 1, 2, 5, 10, 15, 20, 25, 25, 25, 50, 50, 100 }; static const u8 totals[] = @@ -178206,7 +179694,7 @@ static int openDatabase( ** 0 off off ** ** Legacy behavior is 3 (double-quoted string literals are allowed anywhere) -** and so that is the default. But developers are encouranged to use +** and so that is the default. But developers are encouraged to use ** -DSQLITE_DQS=0 (best) or -DSQLITE_DQS=1 (second choice) if possible. */ #if !defined(SQLITE_DQS) @@ -178741,7 +180229,7 @@ SQLITE_API int sqlite3_table_column_metadata( /* Find the column for which info is requested */ if( zColumnName==0 ){ - /* Query for existance of table only */ + /* Query for existence of table only */ }else{ for(iCol=0; iColnCol; iCol++){ pCol = &pTab->aCol[iCol]; @@ -179061,10 +180549,12 @@ SQLITE_API int sqlite3_test_control(int op, ...){ sqlite3ShowSrcList(0); sqlite3ShowWith(0); sqlite3ShowUpsert(0); +#ifndef SQLITE_OMIT_TRIGGER sqlite3ShowTriggerStep(0); sqlite3ShowTriggerStepList(0); sqlite3ShowTrigger(0); sqlite3ShowTriggerList(0); +#endif #ifndef SQLITE_OMIT_WINDOWFUNC sqlite3ShowWindow(0); sqlite3ShowWinFunc(0); @@ -179181,7 +180671,7 @@ SQLITE_API int sqlite3_test_control(int op, ...){ ** formed and never corrupt. This flag is clear by default, indicating that ** database files might have arbitrary corruption. Setting the flag during ** testing causes certain assert() statements in the code to be activated - ** that demonstrat invariants on well-formed database files. + ** that demonstrate invariants on well-formed database files. */ case SQLITE_TESTCTRL_NEVER_CORRUPT: { sqlite3GlobalConfig.neverCorrupt = va_arg(ap, int); @@ -179335,7 +180825,7 @@ SQLITE_API int sqlite3_test_control(int op, ...){ ** ** op==0 Store the current sqlite3TreeTrace in *ptr ** op==1 Set sqlite3TreeTrace to the value *ptr - ** op==3 Store the current sqlite3WhereTrace in *ptr + ** op==2 Store the current sqlite3WhereTrace in *ptr ** op==3 Set sqlite3WhereTrace to the value *ptr */ case SQLITE_TESTCTRL_TRACEFLAGS: { @@ -179371,6 +180861,23 @@ SQLITE_API int sqlite3_test_control(int op, ...){ break; } +#if !defined(SQLITE_OMIT_WSD) + /* sqlite3_test_control(SQLITE_TESTCTRL_USELONGDOUBLE, int X); + ** + ** X<0 Make no changes to the bUseLongDouble. Just report value. + ** X==0 Disable bUseLongDouble + ** X==1 Enable bUseLongDouble + ** X==2 Set bUseLongDouble to its default value for this platform + */ + case SQLITE_TESTCTRL_USELONGDOUBLE: { + int b = va_arg(ap, int); + if( b==2 ) b = sizeof(LONGDOUBLE_TYPE)>8; + if( b>=0 ) sqlite3Config.bUseLongDouble = b>0; + rc = sqlite3Config.bUseLongDouble!=0; + break; + } +#endif + #if defined(SQLITE_DEBUG) && !defined(SQLITE_OMIT_WSD) /* sqlite3_test_control(SQLITE_TESTCTRL_TUNE, id, *piValue) @@ -179671,7 +181178,7 @@ SQLITE_API int sqlite3_snapshot_get( } /* -** Open a read-transaction on the snapshot idendified by pSnapshot. +** Open a read-transaction on the snapshot identified by pSnapshot. */ SQLITE_API int sqlite3_snapshot_open( sqlite3 *db, @@ -195706,6 +197213,7 @@ static int fts3IncrmergeLoad( for(i=nHeight; i>=0 && rc==SQLITE_OK; i--){ NodeReader reader; + memset(&reader, 0, sizeof(reader)); pNode = &pWriter->aNodeWriter[i]; if( pNode->block.a){ @@ -199752,25 +201260,51 @@ SQLITE_PRIVATE int sqlite3FtsUnicodeFold(int c, int eRemoveDiacritic){ ** increase for the parser. (Ubuntu14.10 gcc 4.8.4 x64 with -Os). */ static const char jsonIsSpace[] = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1, 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, 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, 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, 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, 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, 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, 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, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 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, 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, 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, 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, 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, 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, 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, }; #define fast_isspace(x) (jsonIsSpace[(unsigned char)x]) +/* +** Characters that are special to JSON. Control charaters, +** '"' and '\\'. +*/ +static const char jsonIsOk[256] = { + 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, + 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 +}; + + #if !defined(SQLITE_DEBUG) && !defined(SQLITE_COVERAGE_TEST) # define VVA(X) #else @@ -199781,6 +201315,7 @@ static const char jsonIsSpace[] = { typedef struct JsonString JsonString; typedef struct JsonNode JsonNode; typedef struct JsonParse JsonParse; +typedef struct JsonCleanup JsonCleanup; /* An instance of this object represents a JSON string ** under construction. Really, this is a generic string accumulator @@ -199796,16 +201331,26 @@ struct JsonString { char zSpace[100]; /* Initial static space */ }; +/* A deferred cleanup task. A list of JsonCleanup objects might be +** run when the JsonParse object is destroyed. +*/ +struct JsonCleanup { + JsonCleanup *pJCNext; /* Next in a list */ + void (*xOp)(void*); /* Routine to run */ + void *pArg; /* Argument to xOp() */ +}; + /* JSON type values */ -#define JSON_NULL 0 -#define JSON_TRUE 1 -#define JSON_FALSE 2 -#define JSON_INT 3 -#define JSON_REAL 4 -#define JSON_STRING 5 -#define JSON_ARRAY 6 -#define JSON_OBJECT 7 +#define JSON_SUBST 0 /* Special edit node. Uses u.iPrev */ +#define JSON_NULL 1 +#define JSON_TRUE 2 +#define JSON_FALSE 3 +#define JSON_INT 4 +#define JSON_REAL 5 +#define JSON_STRING 6 +#define JSON_ARRAY 7 +#define JSON_OBJECT 8 /* The "subtype" set for JSON values */ #define JSON_SUBTYPE 74 /* Ascii for "J" */ @@ -199814,52 +201359,87 @@ struct JsonString { ** Names of the various JSON types: */ static const char * const jsonType[] = { + "subst", "null", "true", "false", "integer", "real", "text", "array", "object" }; /* Bit values for the JsonNode.jnFlag field */ -#define JNODE_RAW 0x01 /* Content is raw, not JSON encoded */ -#define JNODE_ESCAPE 0x02 /* Content is text with \ escapes */ -#define JNODE_REMOVE 0x04 /* Do not output */ -#define JNODE_REPLACE 0x08 /* Replace with JsonNode.u.iReplace */ -#define JNODE_PATCH 0x10 /* Patch with JsonNode.u.pPatch */ -#define JNODE_APPEND 0x20 /* More ARRAY/OBJECT entries at u.iAppend */ -#define JNODE_LABEL 0x40 /* Is a label of an object */ -#define JNODE_JSON5 0x80 /* Node contains JSON5 enhancements */ +#define JNODE_RAW 0x01 /* Content is raw, not JSON encoded */ +#define JNODE_ESCAPE 0x02 /* Content is text with \ escapes */ +#define JNODE_REMOVE 0x04 /* Do not output */ +#define JNODE_REPLACE 0x08 /* Target of a JSON_SUBST node */ +#define JNODE_APPEND 0x10 /* More ARRAY/OBJECT entries at u.iAppend */ +#define JNODE_LABEL 0x20 /* Is a label of an object */ +#define JNODE_JSON5 0x40 /* Node contains JSON5 enhancements */ -/* A single node of parsed JSON +/* A single node of parsed JSON. An array of these nodes describes +** a parse of JSON + edits. +** +** Use the json_parse() SQL function (available when compiled with +** -DSQLITE_DEBUG) to see a dump of complete JsonParse objects, including +** a complete listing and decoding of the array of JsonNodes. */ struct JsonNode { u8 eType; /* One of the JSON_ type values */ u8 jnFlags; /* JNODE flags */ u8 eU; /* Which union element to use */ - u32 n; /* Bytes of content, or number of sub-nodes */ + u32 n; /* Bytes of content for INT, REAL or STRING + ** Number of sub-nodes for ARRAY and OBJECT + ** Node that SUBST applies to */ union { const char *zJContent; /* 1: Content for INT, REAL, and STRING */ u32 iAppend; /* 2: More terms for ARRAY and OBJECT */ u32 iKey; /* 3: Key for ARRAY objects in json_tree() */ - u32 iReplace; /* 4: Replacement content for JNODE_REPLACE */ - JsonNode *pPatch; /* 5: Node chain of patch for JNODE_PATCH */ + u32 iPrev; /* 4: Previous SUBST node, or 0 */ } u; }; -/* A completely parsed JSON string + +/* A parsed and possibly edited JSON string. Lifecycle: +** +** 1. JSON comes in and is parsed into an array aNode[]. The original +** JSON text is stored in zJson. +** +** 2. Zero or more changes are made (via json_remove() or json_replace() +** or similar) to the aNode[] array. +** +** 3. A new, edited and mimified JSON string is generated from aNode +** and stored in zAlt. The JsonParse object always owns zAlt. +** +** Step 1 always happens. Step 2 and 3 may or may not happen, depending +** on the operation. +** +** aNode[].u.zJContent entries typically point into zJson. Hence zJson +** must remain valid for the lifespan of the parse. For edits, +** aNode[].u.zJContent might point to malloced space other than zJson. +** Entries in pClup are responsible for freeing that extra malloced space. +** +** When walking the parse tree in aNode[], edits are ignored if useMod is +** false. */ struct JsonParse { u32 nNode; /* Number of slots of aNode[] used */ u32 nAlloc; /* Number of slots of aNode[] allocated */ JsonNode *aNode; /* Array of nodes containing the parse */ - const char *zJson; /* Original JSON string */ + char *zJson; /* Original JSON string (before edits) */ + char *zAlt; /* Revised and/or mimified JSON */ u32 *aUp; /* Index of parent of each node */ + JsonCleanup *pClup;/* Cleanup operations prior to freeing this object */ u16 iDepth; /* Nesting depth */ u8 nErr; /* Number of errors seen */ u8 oom; /* Set to true if out of memory */ + u8 bJsonIsRCStr; /* True if zJson is an RCStr */ u8 hasNonstd; /* True if input uses non-standard features like JSON5 */ + u8 useMod; /* Actually use the edits contain inside aNode */ + u8 hasMod; /* aNode contains edits from the original zJson */ + u32 nJPRef; /* Number of references to this object */ int nJson; /* Length of the zJson string in bytes */ + int nAlt; /* Length of alternative JSON string zAlt, in bytes */ u32 iErr; /* Error location in zJson[] */ - u32 iHold; /* Replace cache line with the lowest iHold value */ + u32 iSubst; /* Last JSON_SUBST entry in aNode[] */ + u32 iHold; /* Age of this entry in the cache for LRU replacement */ }; /* @@ -199892,16 +201472,14 @@ static void jsonInit(JsonString *p, sqlite3_context *pCtx){ jsonZero(p); } - /* Free all allocated memory and reset the JsonString object back to its ** initial state. */ static void jsonReset(JsonString *p){ - if( !p->bStatic ) sqlite3_free(p->zBuf); + if( !p->bStatic ) sqlite3RCStrUnref(p->zBuf); jsonZero(p); } - /* Report an out-of-memory (OOM) condition */ static void jsonOom(JsonString *p){ @@ -199918,7 +201496,7 @@ static int jsonGrow(JsonString *p, u32 N){ char *zNew; if( p->bStatic ){ if( p->bErr ) return 1; - zNew = sqlite3_malloc64(nTotal); + zNew = sqlite3RCStrNew(nTotal); if( zNew==0 ){ jsonOom(p); return SQLITE_NOMEM; @@ -199927,12 +201505,12 @@ static int jsonGrow(JsonString *p, u32 N){ p->zBuf = zNew; p->bStatic = 0; }else{ - zNew = sqlite3_realloc64(p->zBuf, nTotal); - if( zNew==0 ){ - jsonOom(p); + p->zBuf = sqlite3RCStrResize(p->zBuf, nTotal); + if( p->zBuf==0 ){ + p->bErr = 1; + jsonZero(p); return SQLITE_NOMEM; } - p->zBuf = zNew; } p->nAlloc = nTotal; return SQLITE_OK; @@ -199940,12 +201518,35 @@ static int jsonGrow(JsonString *p, u32 N){ /* Append N bytes from zIn onto the end of the JsonString string. */ -static void jsonAppendRaw(JsonString *p, const char *zIn, u32 N){ - if( N==0 ) return; - if( (N+p->nUsed >= p->nAlloc) && jsonGrow(p,N)!=0 ) return; +static SQLITE_NOINLINE void jsonAppendExpand( + JsonString *p, + const char *zIn, + u32 N +){ + assert( N>0 ); + if( jsonGrow(p,N) ) return; memcpy(p->zBuf+p->nUsed, zIn, N); p->nUsed += N; } +static void jsonAppendRaw(JsonString *p, const char *zIn, u32 N){ + if( N==0 ) return; + if( N+p->nUsed >= p->nAlloc ){ + jsonAppendExpand(p,zIn,N); + }else{ + memcpy(p->zBuf+p->nUsed, zIn, N); + p->nUsed += N; + } +} +static void jsonAppendRawNZ(JsonString *p, const char *zIn, u32 N){ + assert( N>0 ); + if( N+p->nUsed >= p->nAlloc ){ + jsonAppendExpand(p,zIn,N); + }else{ + memcpy(p->zBuf+p->nUsed, zIn, N); + p->nUsed += N; + } +} + /* Append formatted text (not to exceed N bytes) to the JsonString. */ @@ -199960,10 +201561,35 @@ static void jsonPrintf(int N, JsonString *p, const char *zFormat, ...){ /* Append a single character */ -static void jsonAppendChar(JsonString *p, char c){ - if( p->nUsed>=p->nAlloc && jsonGrow(p,1)!=0 ) return; +static SQLITE_NOINLINE void jsonAppendCharExpand(JsonString *p, char c){ + if( jsonGrow(p,1) ) return; p->zBuf[p->nUsed++] = c; } +static void jsonAppendChar(JsonString *p, char c){ + if( p->nUsed>=p->nAlloc ){ + jsonAppendCharExpand(p,c); + }else{ + p->zBuf[p->nUsed++] = c; + } +} + +/* Try to force the string to be a zero-terminated RCStr string. +** +** Return true on success. Return false if an OOM prevents this +** from happening. +*/ +static int jsonForceRCStr(JsonString *p){ + jsonAppendChar(p, 0); + if( p->bErr ) return 0; + p->nUsed--; + if( p->bStatic==0 ) return 1; + p->nAlloc = 0; + p->nUsed++; + jsonGrow(p, p->nUsed); + p->nUsed--; + return p->bStatic==0; +} + /* Append a comma separator to the output buffer, if the previous ** character is not '[' or '{'. @@ -199972,7 +201598,8 @@ static void jsonAppendSeparator(JsonString *p){ char c; if( p->nUsed==0 ) return; c = p->zBuf[p->nUsed-1]; - if( c!='[' && c!='{' ) jsonAppendChar(p, ','); + if( c=='[' || c=='{' ) return; + jsonAppendChar(p, ','); } /* Append the N-byte string in zIn to the end of the JsonString string @@ -199986,11 +201613,16 @@ static void jsonAppendString(JsonString *p, const char *zIn, u32 N){ p->zBuf[p->nUsed++] = '"'; for(i=0; izBuf[p->nUsed++] = c; + }else if( c=='"' || c=='\\' ){ json_simple_escape: if( (p->nUsed+N+3-i > p->nAlloc) && jsonGrow(p,N+3-i)!=0 ) return; p->zBuf[p->nUsed++] = '\\'; - }else if( c<=0x1f ){ + p->zBuf[p->nUsed++] = c; + }else if( c=='\'' ){ + p->zBuf[p->nUsed++] = c; + }else{ static const char aSpecial[] = { 0, 0, 0, 0, 0, 0, 0, 0, 'b', 't', 'n', 0, 'f', 'r', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 @@ -200001,6 +201633,7 @@ static void jsonAppendString(JsonString *p, const char *zIn, u32 N){ assert( aSpecial['\n']=='n' ); assert( aSpecial['\r']=='r' ); assert( aSpecial['\t']=='t' ); + assert( c>=0 && czBuf[p->nUsed++] = 'u'; p->zBuf[p->nUsed++] = '0'; p->zBuf[p->nUsed++] = '0'; - p->zBuf[p->nUsed++] = '0' + (c>>4); - c = "0123456789abcdef"[c&0xf]; + p->zBuf[p->nUsed++] = "0123456789abcdef"[c>>4]; + p->zBuf[p->nUsed++] = "0123456789abcdef"[c&0xf]; } - p->zBuf[p->nUsed++] = c; } p->zBuf[p->nUsed++] = '"'; assert( p->nUsednAlloc ); @@ -200032,7 +201664,7 @@ static void jsonAppendNormalizedString(JsonString *p, const char *zIn, u32 N){ while( N>0 ){ for(i=0; i0 ){ - jsonAppendRaw(p, zIn, i); + jsonAppendRawNZ(p, zIn, i); zIn += i; N -= i; if( N==0 ) break; @@ -200043,16 +201675,16 @@ static void jsonAppendNormalizedString(JsonString *p, const char *zIn, u32 N){ jsonAppendChar(p, '\''); break; case 'v': - jsonAppendRaw(p, "\\u0009", 6); + jsonAppendRawNZ(p, "\\u0009", 6); break; case 'x': - jsonAppendRaw(p, "\\u00", 4); - jsonAppendRaw(p, &zIn[2], 2); + jsonAppendRawNZ(p, "\\u00", 4); + jsonAppendRawNZ(p, &zIn[2], 2); zIn += 2; N -= 2; break; case '0': - jsonAppendRaw(p, "\\u0000", 6); + jsonAppendRawNZ(p, "\\u0000", 6); break; case '\r': if( zIn[2]=='\n' ){ @@ -200070,7 +201702,7 @@ static void jsonAppendNormalizedString(JsonString *p, const char *zIn, u32 N){ N -= 2; break; default: - jsonAppendRaw(p, zIn, 2); + jsonAppendRawNZ(p, zIn, 2); break; } zIn += 2; @@ -200100,11 +201732,12 @@ static void jsonAppendNormalizedInt(JsonString *p, const char *zIn, u32 N){ jsonPrintf(100,p,"%lld",i); }else{ assert( rc==2 ); - jsonAppendRaw(p, "9.0e999", 7); + jsonAppendRawNZ(p, "9.0e999", 7); } return; } - jsonAppendRaw(p, zIn, N); + assert( N>0 ); + jsonAppendRawNZ(p, zIn, N); } /* @@ -200136,7 +201769,7 @@ static void jsonAppendNormalizedReal(JsonString *p, const char *zIn, u32 N){ } } if( N>0 ){ - jsonAppendRaw(p, zIn, N); + jsonAppendRawNZ(p, zIn, N); } } @@ -200152,7 +201785,7 @@ static void jsonAppendValue( ){ switch( sqlite3_value_type(pValue) ){ case SQLITE_NULL: { - jsonAppendRaw(p, "null", 4); + jsonAppendRawNZ(p, "null", 4); break; } case SQLITE_FLOAT: { @@ -200188,15 +201821,25 @@ static void jsonAppendValue( /* Make the JSON in p the result of the SQL function. +** +** The JSON string is reset. */ static void jsonResult(JsonString *p){ if( p->bErr==0 ){ - sqlite3_result_text64(p->pCtx, p->zBuf, p->nUsed, - p->bStatic ? SQLITE_TRANSIENT : sqlite3_free, - SQLITE_UTF8); - jsonZero(p); + if( p->bStatic ){ + sqlite3_result_text64(p->pCtx, p->zBuf, p->nUsed, + SQLITE_TRANSIENT, SQLITE_UTF8); + }else if( jsonForceRCStr(p) ){ + sqlite3RCStrRef(p->zBuf); + sqlite3_result_text64(p->pCtx, p->zBuf, p->nUsed, + (void(*)(void*))sqlite3RCStrUnref, + SQLITE_UTF8); + } } - assert( p->bStatic ); + if( p->bErr==1 ){ + sqlite3_result_error_nomem(p->pCtx); + } + jsonReset(p); } /************************************************************************** @@ -200221,20 +201864,73 @@ static u32 jsonNodeSize(JsonNode *pNode){ ** delete the JsonParse object itself. */ static void jsonParseReset(JsonParse *pParse){ - sqlite3_free(pParse->aNode); - pParse->aNode = 0; + while( pParse->pClup ){ + JsonCleanup *pTask = pParse->pClup; + pParse->pClup = pTask->pJCNext; + pTask->xOp(pTask->pArg); + sqlite3_free(pTask); + } + assert( pParse->nJPRef<=1 ); + if( pParse->aNode ){ + sqlite3_free(pParse->aNode); + pParse->aNode = 0; + } pParse->nNode = 0; pParse->nAlloc = 0; - sqlite3_free(pParse->aUp); - pParse->aUp = 0; + if( pParse->aUp ){ + sqlite3_free(pParse->aUp); + pParse->aUp = 0; + } + if( pParse->bJsonIsRCStr ){ + sqlite3RCStrUnref(pParse->zJson); + pParse->zJson = 0; + pParse->bJsonIsRCStr = 0; + } + if( pParse->zAlt ){ + sqlite3RCStrUnref(pParse->zAlt); + pParse->zAlt = 0; + } } /* ** Free a JsonParse object that was obtained from sqlite3_malloc(). +** +** Note that destroying JsonParse might call sqlite3RCStrUnref() to +** destroy the zJson value. The RCStr object might recursively invoke +** JsonParse to destroy this pParse object again. Take care to ensure +** that this recursive destructor sequence terminates harmlessly. */ static void jsonParseFree(JsonParse *pParse){ - jsonParseReset(pParse); - sqlite3_free(pParse); + if( pParse->nJPRef>1 ){ + pParse->nJPRef--; + }else{ + jsonParseReset(pParse); + sqlite3_free(pParse); + } +} + +/* +** Add a cleanup task to the JsonParse object. +** +** If an OOM occurs, the cleanup operation happens immediately +** and this function returns SQLITE_NOMEM. +*/ +static int jsonParseAddCleanup( + JsonParse *pParse, /* Add the cleanup task to this parser */ + void(*xOp)(void*), /* The cleanup task */ + void *pArg /* Argument to the cleanup */ +){ + JsonCleanup *pTask = sqlite3_malloc64( sizeof(*pTask) ); + if( pTask==0 ){ + pParse->oom = 1; + xOp(pArg); + return SQLITE_ERROR; + } + pTask->pJCNext = pParse->pClup; + pParse->pClup = pTask; + pTask->xOp = xOp; + pTask->pArg = pArg; + return SQLITE_OK; } /* @@ -200243,32 +201939,38 @@ static void jsonParseFree(JsonParse *pParse){ ** the number of JsonNode objects that are encoded. */ static void jsonRenderNode( + JsonParse *pParse, /* the complete parse of the JSON */ JsonNode *pNode, /* The node to render */ - JsonString *pOut, /* Write JSON here */ - sqlite3_value **aReplace /* Replacement values */ + JsonString *pOut /* Write JSON here */ ){ assert( pNode!=0 ); - if( pNode->jnFlags & (JNODE_REPLACE|JNODE_PATCH) ){ - if( (pNode->jnFlags & JNODE_REPLACE)!=0 && ALWAYS(aReplace!=0) ){ - assert( pNode->eU==4 ); - jsonAppendValue(pOut, aReplace[pNode->u.iReplace]); - return; + while( (pNode->jnFlags & JNODE_REPLACE)!=0 && pParse->useMod ){ + u32 idx = (u32)(pNode - pParse->aNode); + u32 i = pParse->iSubst; + while( 1 /*exit-by-break*/ ){ + assert( inNode ); + assert( pParse->aNode[i].eType==JSON_SUBST ); + assert( pParse->aNode[i].eU==4 ); + assert( pParse->aNode[i].u.iPrevaNode[i].n==idx ){ + pNode = &pParse->aNode[i+1]; + break; + } + i = pParse->aNode[i].u.iPrev; } - assert( pNode->eU==5 ); - pNode = pNode->u.pPatch; } switch( pNode->eType ){ default: { assert( pNode->eType==JSON_NULL ); - jsonAppendRaw(pOut, "null", 4); + jsonAppendRawNZ(pOut, "null", 4); break; } case JSON_TRUE: { - jsonAppendRaw(pOut, "true", 4); + jsonAppendRawNZ(pOut, "true", 4); break; } case JSON_FALSE: { - jsonAppendRaw(pOut, "false", 5); + jsonAppendRawNZ(pOut, "false", 5); break; } case JSON_STRING: { @@ -200284,7 +201986,8 @@ static void jsonRenderNode( }else if( pNode->jnFlags & JNODE_JSON5 ){ jsonAppendNormalizedString(pOut, pNode->u.zJContent, pNode->n); }else{ - jsonAppendRaw(pOut, pNode->u.zJContent, pNode->n); + assert( pNode->n>0 ); + jsonAppendRawNZ(pOut, pNode->u.zJContent, pNode->n); } break; } @@ -200293,7 +201996,8 @@ static void jsonRenderNode( if( pNode->jnFlags & JNODE_JSON5 ){ jsonAppendNormalizedReal(pOut, pNode->u.zJContent, pNode->n); }else{ - jsonAppendRaw(pOut, pNode->u.zJContent, pNode->n); + assert( pNode->n>0 ); + jsonAppendRawNZ(pOut, pNode->u.zJContent, pNode->n); } break; } @@ -200302,7 +202006,8 @@ static void jsonRenderNode( if( pNode->jnFlags & JNODE_JSON5 ){ jsonAppendNormalizedInt(pOut, pNode->u.zJContent, pNode->n); }else{ - jsonAppendRaw(pOut, pNode->u.zJContent, pNode->n); + assert( pNode->n>0 ); + jsonAppendRawNZ(pOut, pNode->u.zJContent, pNode->n); } break; } @@ -200311,15 +202016,16 @@ static void jsonRenderNode( jsonAppendChar(pOut, '['); for(;;){ while( j<=pNode->n ){ - if( (pNode[j].jnFlags & JNODE_REMOVE)==0 ){ + if( (pNode[j].jnFlags & JNODE_REMOVE)==0 || pParse->useMod==0 ){ jsonAppendSeparator(pOut); - jsonRenderNode(&pNode[j], pOut, aReplace); + jsonRenderNode(pParse, &pNode[j], pOut); } j += jsonNodeSize(&pNode[j]); } if( (pNode->jnFlags & JNODE_APPEND)==0 ) break; + if( pParse->useMod==0 ) break; assert( pNode->eU==2 ); - pNode = &pNode[pNode->u.iAppend]; + pNode = &pParse->aNode[pNode->u.iAppend]; j = 1; } jsonAppendChar(pOut, ']'); @@ -200330,17 +202036,18 @@ static void jsonRenderNode( jsonAppendChar(pOut, '{'); for(;;){ while( j<=pNode->n ){ - if( (pNode[j+1].jnFlags & JNODE_REMOVE)==0 ){ + if( (pNode[j+1].jnFlags & JNODE_REMOVE)==0 || pParse->useMod==0 ){ jsonAppendSeparator(pOut); - jsonRenderNode(&pNode[j], pOut, aReplace); + jsonRenderNode(pParse, &pNode[j], pOut); jsonAppendChar(pOut, ':'); - jsonRenderNode(&pNode[j+1], pOut, aReplace); + jsonRenderNode(pParse, &pNode[j+1], pOut); } j += 1 + jsonNodeSize(&pNode[j+1]); } if( (pNode->jnFlags & JNODE_APPEND)==0 ) break; + if( pParse->useMod==0 ) break; assert( pNode->eU==2 ); - pNode = &pNode[pNode->u.iAppend]; + pNode = &pParse->aNode[pNode->u.iAppend]; j = 1; } jsonAppendChar(pOut, '}'); @@ -200350,18 +202057,29 @@ static void jsonRenderNode( } /* -** Return a JsonNode and all its descendents as a JSON string. +** Return a JsonNode and all its descendants as a JSON string. */ static void jsonReturnJson( + JsonParse *pParse, /* The complete JSON */ JsonNode *pNode, /* Node to return */ sqlite3_context *pCtx, /* Return value for this function */ - sqlite3_value **aReplace /* Array of replacement values */ + int bGenerateAlt /* Also store the rendered text in zAlt */ ){ JsonString s; - jsonInit(&s, pCtx); - jsonRenderNode(pNode, &s, aReplace); - jsonResult(&s); - sqlite3_result_subtype(pCtx, JSON_SUBTYPE); + if( pParse->oom ){ + sqlite3_result_error_nomem(pCtx); + return; + } + if( pParse->nErr==0 ){ + jsonInit(&s, pCtx); + jsonRenderNode(pParse, pNode, &s); + if( bGenerateAlt && pParse->zAlt==0 && jsonForceRCStr(&s) ){ + pParse->zAlt = sqlite3RCStrRef(s.zBuf); + pParse->nAlt = s.nUsed; + } + jsonResult(&s); + sqlite3_result_subtype(pCtx, JSON_SUBTYPE); + } } /* @@ -200399,9 +202117,9 @@ static u32 jsonHexToInt4(const char *z){ ** Make the JsonNode the return value of the function. */ static void jsonReturn( + JsonParse *pParse, /* Complete JSON parse tree */ JsonNode *pNode, /* Node to return */ - sqlite3_context *pCtx, /* Return value for this function */ - sqlite3_value **aReplace /* Array of replacement values */ + sqlite3_context *pCtx /* Return value for this function */ ){ switch( pNode->eType ){ default: { @@ -200423,7 +202141,6 @@ static void jsonReturn( int bNeg = 0; const char *z; - assert( pNode->eU==1 ); z = pNode->u.zJContent; if( z[0]=='-' ){ z++; bNeg = 1; } @@ -200548,7 +202265,7 @@ static void jsonReturn( } case JSON_ARRAY: case JSON_OBJECT: { - jsonReturnJson(pNode, pCtx, aReplace); + jsonReturnJson(pParse, pNode, pCtx, 0); break; } } @@ -200570,6 +202287,12 @@ static int jsonParseAddNode(JsonParse*,u32,u32,const char*); #endif +/* +** Add a single node to pParse->aNode after first expanding the +** size of the aNode array. Return the index of the new node. +** +** If an OOM error occurs, set pParse->oom and return -1. +*/ static JSON_NOINLINE int jsonParseAddNodeExpand( JsonParse *pParse, /* Append the node to this object */ u32 eType, /* Node type */ @@ -200586,7 +202309,7 @@ static JSON_NOINLINE int jsonParseAddNodeExpand( pParse->oom = 1; return -1; } - pParse->nAlloc = nNew; + pParse->nAlloc = sqlite3_msize(pNew)/sizeof(JsonNode); pParse->aNode = pNew; assert( pParse->nNodenAlloc ); return jsonParseAddNode(pParse, eType, n, zContent); @@ -200604,10 +202327,13 @@ static int jsonParseAddNode( const char *zContent /* Content */ ){ JsonNode *p; - if( pParse->aNode==0 || pParse->nNode>=pParse->nAlloc ){ + assert( pParse->aNode!=0 || pParse->nNode>=pParse->nAlloc ); + if( pParse->nNode>=pParse->nAlloc ){ return jsonParseAddNodeExpand(pParse, eType, n, zContent); } + assert( pParse->aNode!=0 ); p = &pParse->aNode[pParse->nNode]; + assert( p!=0 ); p->eType = (u8)(eType & 0xff); p->jnFlags = (u8)(eType >> 8); VVA( p->eU = zContent ? 1 : 0 ); @@ -200616,6 +202342,52 @@ static int jsonParseAddNode( return pParse->nNode++; } +/* +** Add an array of new nodes to the current pParse->aNode array. +** Return the index of the first node added. +** +** If an OOM error occurs, set pParse->oom. +*/ +static void jsonParseAddNodeArray( + JsonParse *pParse, /* Append the node to this object */ + JsonNode *aNode, /* Array of nodes to add */ + u32 nNode /* Number of elements in aNew */ +){ + assert( aNode!=0 ); + assert( nNode>=1 ); + if( pParse->nNode + nNode > pParse->nAlloc ){ + u32 nNew = pParse->nNode + nNode; + JsonNode *aNew = sqlite3_realloc64(pParse->aNode, nNew*sizeof(JsonNode)); + if( aNew==0 ){ + pParse->oom = 1; + return; + } + pParse->nAlloc = sqlite3_msize(aNew)/sizeof(JsonNode); + pParse->aNode = aNew; + } + memcpy(&pParse->aNode[pParse->nNode], aNode, nNode*sizeof(JsonNode)); + pParse->nNode += nNode; +} + +/* +** Add a new JSON_SUBST node. The node immediately following +** this new node will be the substitute content for iNode. +*/ +static int jsonParseAddSubstNode( + JsonParse *pParse, /* Add the JSON_SUBST here */ + u32 iNode /* References this node */ +){ + int idx = jsonParseAddNode(pParse, JSON_SUBST, iNode, 0); + if( pParse->oom ) return -1; + pParse->aNode[iNode].jnFlags |= JNODE_REPLACE; + pParse->aNode[idx].eU = 4; + pParse->aNode[idx].u.iPrev = pParse->iSubst; + pParse->iSubst = idx; + pParse->hasMod = 1; + pParse->useMod = 1; + return idx; +} + /* ** Return true if z[] begins with 2 (or more) hexadecimal digits */ @@ -200782,7 +202554,7 @@ static const struct NanInfName { ** ** Special return values: ** -** 0 End if input +** 0 End of input ** -1 Syntax error ** -2 '}' seen ** -3 ']' seen @@ -200957,15 +202729,12 @@ json_parse_restart: jnFlags = 0; parse_string: cDelim = z[i]; - j = i+1; - for(;;){ + for(j=i+1; 1; j++){ + if( jsonIsOk[(unsigned char)z[j]] ) continue; c = z[j]; - if( (c & ~0x1f)==0 ){ - /* Control characters are not allowed in strings */ - pParse->iErr = j; - return -1; - } - if( c=='\\' ){ + if( c==cDelim ){ + break; + }else if( c=='\\' ){ c = z[++j]; if( c=='"' || c=='\\' || c=='/' || c=='b' || c=='f' || c=='n' || c=='r' || c=='t' @@ -200985,10 +202754,11 @@ json_parse_restart: pParse->iErr = j; return -1; } - }else if( c==cDelim ){ - break; + }else if( c<=0x1f ){ + /* Control characters are not allowed in strings */ + pParse->iErr = j; + return -1; } - j++; } jsonParseAddNode(pParse, JSON_STRING | (jnFlags<<8), j+1-i, &z[i]); return j+1; @@ -201224,20 +202994,18 @@ json_parse_restart: /* ** Parse a complete JSON string. Return 0 on success or non-zero if there -** are any errors. If an error occurs, free all memory associated with -** pParse. +** are any errors. If an error occurs, free all memory held by pParse, +** but not pParse itself. ** -** pParse is uninitialized when this routine is called. +** pParse must be initialized to an empty parse object prior to calling +** this routine. */ static int jsonParse( JsonParse *pParse, /* Initialize and fill this JsonParse object */ - sqlite3_context *pCtx, /* Report errors here */ - const char *zJson /* Input JSON text to be parsed */ + sqlite3_context *pCtx /* Report errors here */ ){ int i; - memset(pParse, 0, sizeof(*pParse)); - if( zJson==0 ) return 1; - pParse->zJson = zJson; + const char *zJson = pParse->zJson; i = jsonParseValue(pParse, 0); if( pParse->oom ) i = -1; if( i>0 ){ @@ -201266,6 +203034,7 @@ static int jsonParse( return 0; } + /* Mark node i of pParse as being a child of iParent. Call recursively ** to fill in all the descendants of node i. */ @@ -201315,35 +203084,49 @@ static int jsonParseFindParents(JsonParse *pParse){ #define JSON_CACHE_SZ 4 /* Max number of cache entries */ /* -** Obtain a complete parse of the JSON found in the first argument -** of the argv array. Use the sqlite3_get_auxdata() cache for this -** parse if it is available. If the cache is not available or if it -** is no longer valid, parse the JSON again and return the new parse, -** and also register the new parse so that it will be available for +** Obtain a complete parse of the JSON found in the pJson argument +** +** Use the sqlite3_get_auxdata() cache to find a preexisting parse +** if it is available. If the cache is not available or if it +** is no longer valid, parse the JSON again and return the new parse. +** Also register the new parse so that it will be available for ** future sqlite3_get_auxdata() calls. ** ** If an error occurs and pErrCtx!=0 then report the error on pErrCtx ** and return NULL. ** -** If an error occurs and pErrCtx==0 then return the Parse object with -** JsonParse.nErr non-zero. If the caller invokes this routine with -** pErrCtx==0 and it gets back a JsonParse with nErr!=0, then the caller -** is responsible for invoking jsonParseFree() on the returned value. -** But the caller may invoke jsonParseFree() *only* if pParse->nErr!=0. +** The returned pointer (if it is not NULL) is owned by the cache in +** most cases, not the caller. The caller does NOT need to invoke +** jsonParseFree(), in most cases. +** +** Except, if an error occurs and pErrCtx==0 then return the JsonParse +** object with JsonParse.nErr non-zero and the caller will own the JsonParse +** object. In that case, it will be the responsibility of the caller to +** invoke jsonParseFree(). To summarize: +** +** pErrCtx!=0 || p->nErr==0 ==> Return value p is owned by the +** cache. Call does not need to +** free it. +** +** pErrCtx==0 && p->nErr!=0 ==> Return value is owned by the caller +** and so the caller must free it. */ static JsonParse *jsonParseCached( - sqlite3_context *pCtx, - sqlite3_value **argv, - sqlite3_context *pErrCtx + sqlite3_context *pCtx, /* Context to use for cache search */ + sqlite3_value *pJson, /* Function param containing JSON text */ + sqlite3_context *pErrCtx, /* Write parse errors here if not NULL */ + int bUnedited /* No prior edits allowed */ ){ - const char *zJson = (const char*)sqlite3_value_text(argv[0]); - int nJson = sqlite3_value_bytes(argv[0]); + char *zJson = (char*)sqlite3_value_text(pJson); + int nJson = sqlite3_value_bytes(pJson); JsonParse *p; JsonParse *pMatch = 0; int iKey; int iMinKey = 0; u32 iMinHold = 0xffffffff; u32 iMaxHold = 0; + int bJsonRCStr; + if( zJson==0 ) return 0; for(iKey=0; iKeynJson==nJson - && memcmp(p->zJson,zJson,nJson)==0 + && (p->hasMod==0 || bUnedited==0) + && (p->zJson==zJson || memcmp(p->zJson,zJson,nJson)==0) ){ p->nErr = 0; + p->useMod = 0; + pMatch = p; + }else + if( pMatch==0 + && p->zAlt!=0 + && bUnedited==0 + && p->nAlt==nJson + && memcmp(p->zAlt, zJson, nJson)==0 + ){ + p->nErr = 0; + p->useMod = 1; pMatch = p; }else if( p->iHoldiHold; @@ -201366,28 +203161,44 @@ static JsonParse *jsonParseCached( } } if( pMatch ){ + /* The input JSON text was found in the cache. Use the preexisting + ** parse of this JSON */ pMatch->nErr = 0; pMatch->iHold = iMaxHold+1; + assert( pMatch->nJPRef>0 ); /* pMatch is owned by the cache */ return pMatch; } - p = sqlite3_malloc64( sizeof(*p) + nJson + 1 ); + + /* The input JSON was not found anywhere in the cache. We will need + ** to parse it ourselves and generate a new JsonParse object. + */ + bJsonRCStr = sqlite3ValueIsOfClass(pJson,(void(*)(void*))sqlite3RCStrUnref); + p = sqlite3_malloc64( sizeof(*p) + (bJsonRCStr ? 0 : nJson+1) ); if( p==0 ){ sqlite3_result_error_nomem(pCtx); return 0; } memset(p, 0, sizeof(*p)); - p->zJson = (char*)&p[1]; - memcpy((char*)p->zJson, zJson, nJson+1); - if( jsonParse(p, pErrCtx, p->zJson) ){ + if( bJsonRCStr ){ + p->zJson = sqlite3RCStrRef(zJson); + p->bJsonIsRCStr = 1; + }else{ + p->zJson = (char*)&p[1]; + memcpy(p->zJson, zJson, nJson+1); + } + p->nJPRef = 1; + if( jsonParse(p, pErrCtx) ){ if( pErrCtx==0 ){ p->nErr = 1; + assert( p->nJPRef==1 ); /* Caller will own the new JsonParse object p */ return p; } - sqlite3_free(p); + jsonParseFree(p); return 0; } p->nJson = nJson; p->iHold = iMaxHold+1; + /* Transfer ownership of the new JsonParse to the cache */ sqlite3_set_auxdata(pCtx, JSON_CACHE_ID+iMinKey, p, (void(*)(void*))jsonParseFree); return (JsonParse*)sqlite3_get_auxdata(pCtx, JSON_CACHE_ID+iMinKey); @@ -201438,9 +203249,31 @@ static JsonNode *jsonLookupStep( ){ u32 i, j, nKey; const char *zKey; - JsonNode *pRoot = &pParse->aNode[iRoot]; + JsonNode *pRoot; + if( pParse->oom ) return 0; + pRoot = &pParse->aNode[iRoot]; + if( pRoot->jnFlags & (JNODE_REPLACE|JNODE_REMOVE) && pParse->useMod ){ + while( (pRoot->jnFlags & JNODE_REPLACE)!=0 ){ + u32 idx = (u32)(pRoot - pParse->aNode); + i = pParse->iSubst; + while( 1 /*exit-by-break*/ ){ + assert( inNode ); + assert( pParse->aNode[i].eType==JSON_SUBST ); + assert( pParse->aNode[i].eU==4 ); + assert( pParse->aNode[i].u.iPrevaNode[i].n==idx ){ + pRoot = &pParse->aNode[i+1]; + iRoot = i+1; + break; + } + i = pParse->aNode[i].u.iPrev; + } + } + if( pRoot->jnFlags & JNODE_REMOVE ){ + return 0; + } + } if( zPath[0]==0 ) return pRoot; - if( pRoot->jnFlags & JNODE_REPLACE ) return 0; if( zPath[0]=='.' ){ if( pRoot->eType!=JSON_OBJECT ) return 0; zPath++; @@ -201474,14 +203307,16 @@ static JsonNode *jsonLookupStep( j += jsonNodeSize(&pRoot[j]); } if( (pRoot->jnFlags & JNODE_APPEND)==0 ) break; + if( pParse->useMod==0 ) break; assert( pRoot->eU==2 ); - iRoot += pRoot->u.iAppend; + iRoot = pRoot->u.iAppend; pRoot = &pParse->aNode[iRoot]; j = 1; } if( pApnd ){ u32 iStart, iLabel; JsonNode *pNode; + assert( pParse->useMod ); iStart = jsonParseAddNode(pParse, JSON_OBJECT, 2, 0); iLabel = jsonParseAddNode(pParse, JSON_STRING, nKey, zKey); zPath += i; @@ -201490,7 +203325,7 @@ static JsonNode *jsonLookupStep( if( pNode ){ pRoot = &pParse->aNode[iRoot]; assert( pRoot->eU==0 ); - pRoot->u.iAppend = iStart - iRoot; + pRoot->u.iAppend = iStart; pRoot->jnFlags |= JNODE_APPEND; VVA( pRoot->eU = 2 ); pParse->aNode[iLabel].jnFlags |= JNODE_RAW; @@ -201511,12 +203346,13 @@ static JsonNode *jsonLookupStep( if( pRoot->eType!=JSON_ARRAY ) return 0; for(;;){ while( j<=pBase->n ){ - if( (pBase[j].jnFlags & JNODE_REMOVE)==0 ) i++; + if( (pBase[j].jnFlags & JNODE_REMOVE)==0 || pParse->useMod==0 ) i++; j += jsonNodeSize(&pBase[j]); } if( (pBase->jnFlags & JNODE_APPEND)==0 ) break; + if( pParse->useMod==0 ) break; assert( pBase->eU==2 ); - iBase += pBase->u.iAppend; + iBase = pBase->u.iAppend; pBase = &pParse->aNode[iBase]; j = 1; } @@ -201544,13 +203380,16 @@ static JsonNode *jsonLookupStep( zPath += j + 1; j = 1; for(;;){ - while( j<=pRoot->n && (i>0 || (pRoot[j].jnFlags & JNODE_REMOVE)!=0) ){ - if( (pRoot[j].jnFlags & JNODE_REMOVE)==0 ) i--; + while( j<=pRoot->n + && (i>0 || ((pRoot[j].jnFlags & JNODE_REMOVE)!=0 && pParse->useMod)) + ){ + if( (pRoot[j].jnFlags & JNODE_REMOVE)==0 || pParse->useMod==0 ) i--; j += jsonNodeSize(&pRoot[j]); } if( (pRoot->jnFlags & JNODE_APPEND)==0 ) break; + if( pParse->useMod==0 ) break; assert( pRoot->eU==2 ); - iRoot += pRoot->u.iAppend; + iRoot = pRoot->u.iAppend; pRoot = &pParse->aNode[iRoot]; j = 1; } @@ -201560,13 +203399,14 @@ static JsonNode *jsonLookupStep( if( i==0 && pApnd ){ u32 iStart; JsonNode *pNode; + assert( pParse->useMod ); iStart = jsonParseAddNode(pParse, JSON_ARRAY, 1, 0); pNode = jsonLookupAppend(pParse, zPath, pApnd, pzErr); if( pParse->oom ) return 0; if( pNode ){ pRoot = &pParse->aNode[iRoot]; assert( pRoot->eU==0 ); - pRoot->u.iAppend = iStart - iRoot; + pRoot->u.iAppend = iStart; pRoot->jnFlags |= JNODE_APPEND; VVA( pRoot->eU = 2 ); } @@ -201693,47 +203533,90 @@ static void jsonRemoveAllNulls(JsonNode *pNode){ ** SQL functions used for testing and debugging ****************************************************************************/ +#if SQLITE_DEBUG +/* +** Print N node entries. +*/ +static void jsonDebugPrintNodeEntries( + JsonNode *aNode, /* First node entry to print */ + int N /* Number of node entries to print */ +){ + int i; + for(i=0; iaNode, p->nNode); +} +static void jsonDebugPrintNode(JsonNode *pNode){ + jsonDebugPrintNodeEntries(pNode, jsonNodeSize(pNode)); +} +#else + /* The usual case */ +# define jsonDebugPrintNode(X) +# define jsonDebugPrintParse(X) +#endif + #ifdef SQLITE_DEBUG /* -** The json_parse(JSON) function returns a string which describes -** a parse of the JSON provided. Or it returns NULL if JSON is not -** well-formed. +** SQL function: json_parse(JSON) +** +** Parse JSON using jsonParseCached(). Then print a dump of that +** parse on standard output. Return the mimified JSON result, just +** like the json() function. */ static void jsonParseFunc( sqlite3_context *ctx, int argc, sqlite3_value **argv ){ - JsonString s; /* Output string - not real JSON */ - JsonParse x; /* The parse */ - u32 i; + JsonParse *p; /* The parse */ assert( argc==1 ); - if( jsonParse(&x, ctx, (const char*)sqlite3_value_text(argv[0])) ) return; - jsonParseFindParents(&x); - jsonInit(&s, ctx); - for(i=0; inNode); + printf("nAlloc = %u\n", p->nAlloc); + printf("nJson = %d\n", p->nJson); + printf("nAlt = %d\n", p->nAlt); + printf("nErr = %u\n", p->nErr); + printf("oom = %u\n", p->oom); + printf("hasNonstd = %u\n", p->hasNonstd); + printf("useMod = %u\n", p->useMod); + printf("hasMod = %u\n", p->hasMod); + printf("nJPRef = %u\n", p->nJPRef); + printf("iSubst = %u\n", p->iSubst); + printf("iHold = %u\n", p->iHold); + jsonDebugPrintNodeEntries(p->aNode, p->nNode); + jsonReturnJson(p, p->aNode, ctx, 1); } /* @@ -201817,7 +203700,7 @@ static void jsonArrayLengthFunc( u32 i; JsonNode *pNode; - p = jsonParseCached(ctx, argv, ctx); + p = jsonParseCached(ctx, argv[0], ctx, 0); if( p==0 ) return; assert( p->nNode ); if( argc==2 ){ @@ -201830,9 +203713,14 @@ static void jsonArrayLengthFunc( return; } if( pNode->eType==JSON_ARRAY ){ - assert( (pNode->jnFlags & JNODE_APPEND)==0 ); - for(i=1; i<=pNode->n; n++){ - i += jsonNodeSize(&pNode[i]); + while( 1 /*exit-by-break*/ ){ + for(i=1; i<=pNode->n; n++){ + i += jsonNodeSize(&pNode[i]); + } + if( (pNode->jnFlags & JNODE_APPEND)==0 ) break; + if( p->useMod==0 ) break; + assert( pNode->eU==2 ); + pNode = &p->aNode[pNode->u.iAppend]; } } sqlite3_result_int64(ctx, n); @@ -201879,7 +203767,7 @@ static void jsonExtractFunc( JsonString jx; if( argc<2 ) return; - p = jsonParseCached(ctx, argv, ctx); + p = jsonParseCached(ctx, argv[0], ctx, 0); if( p==0 ) return; if( argc==2 ){ /* With a single PATH argument */ @@ -201897,11 +203785,11 @@ static void jsonExtractFunc( */ jsonInit(&jx, ctx); if( sqlite3Isdigit(zPath[0]) ){ - jsonAppendRaw(&jx, "$[", 2); + jsonAppendRawNZ(&jx, "$[", 2); jsonAppendRaw(&jx, zPath, (int)strlen(zPath)); - jsonAppendRaw(&jx, "]", 2); + jsonAppendRawNZ(&jx, "]", 2); }else{ - jsonAppendRaw(&jx, "$.", 1 + (zPath[0]!='[')); + jsonAppendRawNZ(&jx, "$.", 1 + (zPath[0]!='[')); jsonAppendRaw(&jx, zPath, (int)strlen(zPath)); jsonAppendChar(&jx, 0); } @@ -201912,15 +203800,15 @@ static void jsonExtractFunc( } if( pNode ){ if( flags & JSON_JSON ){ - jsonReturnJson(pNode, ctx, 0); + jsonReturnJson(p, pNode, ctx, 0); }else{ - jsonReturn(pNode, ctx, 0); + jsonReturn(p, pNode, ctx); sqlite3_result_subtype(ctx, 0); } } }else{ pNode = jsonLookup(p, zPath, 0, ctx); - if( p->nErr==0 && pNode ) jsonReturn(pNode, ctx, 0); + if( p->nErr==0 && pNode ) jsonReturn(p, pNode, ctx); } }else{ /* Two or more PATH arguments results in a JSON array with each @@ -201934,9 +203822,9 @@ static void jsonExtractFunc( if( p->nErr ) break; jsonAppendSeparator(&jx); if( pNode ){ - jsonRenderNode(pNode, &jx, 0); + jsonRenderNode(p, pNode, &jx); }else{ - jsonAppendRaw(&jx, "null", 4); + jsonAppendRawNZ(&jx, "null", 4); } } if( i==argc ){ @@ -201981,45 +203869,38 @@ static JsonNode *jsonMergePatch( assert( pTarget[j].eType==JSON_STRING ); assert( pTarget[j].jnFlags & JNODE_LABEL ); if( jsonSameLabel(&pPatch[i], &pTarget[j]) ){ - if( pTarget[j+1].jnFlags & (JNODE_REMOVE|JNODE_PATCH) ) break; + if( pTarget[j+1].jnFlags & (JNODE_REMOVE|JNODE_REPLACE) ) break; if( pPatch[i+1].eType==JSON_NULL ){ pTarget[j+1].jnFlags |= JNODE_REMOVE; }else{ JsonNode *pNew = jsonMergePatch(pParse, iTarget+j+1, &pPatch[i+1]); if( pNew==0 ) return 0; - pTarget = &pParse->aNode[iTarget]; - if( pNew!=&pTarget[j+1] ){ - assert( pTarget[j+1].eU==0 - || pTarget[j+1].eU==1 - || pTarget[j+1].eU==2 ); - testcase( pTarget[j+1].eU==1 ); - testcase( pTarget[j+1].eU==2 ); - VVA( pTarget[j+1].eU = 5 ); - pTarget[j+1].u.pPatch = pNew; - pTarget[j+1].jnFlags |= JNODE_PATCH; + if( pNew!=&pParse->aNode[iTarget+j+1] ){ + jsonParseAddSubstNode(pParse, iTarget+j+1); + jsonParseAddNodeArray(pParse, pNew, jsonNodeSize(pNew)); } + pTarget = &pParse->aNode[iTarget]; } break; } } if( j>=pTarget->n && pPatch[i+1].eType!=JSON_NULL ){ - int iStart, iPatch; - iStart = jsonParseAddNode(pParse, JSON_OBJECT, 2, 0); + int iStart; + JsonNode *pApnd; + u32 nApnd; + iStart = jsonParseAddNode(pParse, JSON_OBJECT, 0, 0); jsonParseAddNode(pParse, JSON_STRING, nKey, zKey); - iPatch = jsonParseAddNode(pParse, JSON_TRUE, 0, 0); + pApnd = &pPatch[i+1]; + if( pApnd->eType==JSON_OBJECT ) jsonRemoveAllNulls(pApnd); + nApnd = jsonNodeSize(pApnd); + jsonParseAddNodeArray(pParse, pApnd, jsonNodeSize(pApnd)); if( pParse->oom ) return 0; - jsonRemoveAllNulls(pPatch); - pTarget = &pParse->aNode[iTarget]; - assert( pParse->aNode[iRoot].eU==0 || pParse->aNode[iRoot].eU==2 ); - testcase( pParse->aNode[iRoot].eU==2 ); + pParse->aNode[iStart].n = 1+nApnd; pParse->aNode[iRoot].jnFlags |= JNODE_APPEND; + pParse->aNode[iRoot].u.iAppend = iStart; VVA( pParse->aNode[iRoot].eU = 2 ); - pParse->aNode[iRoot].u.iAppend = iStart - iRoot; iRoot = iStart; - assert( pParse->aNode[iPatch].eU==0 ); - VVA( pParse->aNode[iPatch].eU = 5 ); - pParse->aNode[iPatch].jnFlags |= JNODE_PATCH; - pParse->aNode[iPatch].u.pPatch = &pPatch[i+1]; + pTarget = &pParse->aNode[iTarget]; } } return pTarget; @@ -202035,25 +203916,28 @@ static void jsonPatchFunc( int argc, sqlite3_value **argv ){ - JsonParse x; /* The JSON that is being patched */ - JsonParse y; /* The patch */ + JsonParse *pX; /* The JSON that is being patched */ + JsonParse *pY; /* The patch */ JsonNode *pResult; /* The result of the merge */ UNUSED_PARAMETER(argc); - if( jsonParse(&x, ctx, (const char*)sqlite3_value_text(argv[0])) ) return; - if( jsonParse(&y, ctx, (const char*)sqlite3_value_text(argv[1])) ){ - jsonParseReset(&x); - return; - } - pResult = jsonMergePatch(&x, 0, y.aNode); - assert( pResult!=0 || x.oom ); - if( pResult ){ - jsonReturnJson(pResult, ctx, 0); + pX = jsonParseCached(ctx, argv[0], ctx, 1); + if( pX==0 ) return; + assert( pX->hasMod==0 ); + pX->hasMod = 1; + pY = jsonParseCached(ctx, argv[1], ctx, 1); + if( pY==0 ) return; + pX->useMod = 1; + pY->useMod = 1; + pResult = jsonMergePatch(pX, 0, pY->aNode); + assert( pResult!=0 || pX->oom ); + if( pResult && pX->oom==0 ){ + jsonDebugPrintParse(pX); + jsonDebugPrintNode(pResult); + jsonReturnJson(pX, pResult, ctx, 0); }else{ sqlite3_result_error_nomem(ctx); } - jsonParseReset(&x); - jsonParseReset(&y); } @@ -202109,26 +203993,118 @@ static void jsonRemoveFunc( int argc, sqlite3_value **argv ){ - JsonParse x; /* The parse */ + JsonParse *pParse; /* The parse */ JsonNode *pNode; const char *zPath; u32 i; if( argc<1 ) return; - if( jsonParse(&x, ctx, (const char*)sqlite3_value_text(argv[0])) ) return; - assert( x.nNode ); + pParse = jsonParseCached(ctx, argv[0], ctx, argc>1); + if( pParse==0 ) return; for(i=1; i<(u32)argc; i++){ zPath = (const char*)sqlite3_value_text(argv[i]); if( zPath==0 ) goto remove_done; - pNode = jsonLookup(&x, zPath, 0, ctx); - if( x.nErr ) goto remove_done; - if( pNode ) pNode->jnFlags |= JNODE_REMOVE; + pNode = jsonLookup(pParse, zPath, 0, ctx); + if( pParse->nErr ) goto remove_done; + if( pNode ){ + pNode->jnFlags |= JNODE_REMOVE; + pParse->hasMod = 1; + pParse->useMod = 1; + } } - if( (x.aNode[0].jnFlags & JNODE_REMOVE)==0 ){ - jsonReturnJson(x.aNode, ctx, 0); + if( (pParse->aNode[0].jnFlags & JNODE_REMOVE)==0 ){ + jsonReturnJson(pParse, pParse->aNode, ctx, 1); } remove_done: - jsonParseReset(&x); + jsonDebugPrintParse(p); +} + +/* +** Substitute the value at iNode with the pValue parameter. +*/ +static void jsonReplaceNode( + sqlite3_context *pCtx, + JsonParse *p, + int iNode, + sqlite3_value *pValue +){ + int idx = jsonParseAddSubstNode(p, iNode); + if( idx<=0 ){ + assert( p->oom ); + return; + } + switch( sqlite3_value_type(pValue) ){ + case SQLITE_NULL: { + jsonParseAddNode(p, JSON_NULL, 0, 0); + break; + } + case SQLITE_FLOAT: { + char *z = sqlite3_mprintf("%!0.15g", sqlite3_value_double(pValue)); + int n; + if( z==0 ){ + p->oom = 1; + break; + } + n = sqlite3Strlen30(z); + jsonParseAddNode(p, JSON_REAL, n, z); + jsonParseAddCleanup(p, sqlite3_free, z); + break; + } + case SQLITE_INTEGER: { + char *z = sqlite3_mprintf("%lld", sqlite3_value_int64(pValue)); + int n; + if( z==0 ){ + p->oom = 1; + break; + } + n = sqlite3Strlen30(z); + jsonParseAddNode(p, JSON_INT, n, z); + jsonParseAddCleanup(p, sqlite3_free, z); + + break; + } + case SQLITE_TEXT: { + const char *z = (const char*)sqlite3_value_text(pValue); + u32 n = (u32)sqlite3_value_bytes(pValue); + if( z==0 ){ + p->oom = 1; + break; + } + if( sqlite3_value_subtype(pValue)!=JSON_SUBTYPE ){ + char *zCopy = sqlite3DbStrDup(0, z); + int k; + if( zCopy ){ + jsonParseAddCleanup(p, sqlite3_free, zCopy); + }else{ + p->oom = 1; + sqlite3_result_error_nomem(pCtx); + } + k = jsonParseAddNode(p, JSON_STRING, n, zCopy); + assert( k>0 || p->oom ); + if( p->oom==0 ) p->aNode[k].jnFlags |= JNODE_RAW; + }else{ + JsonParse *pPatch = jsonParseCached(pCtx, pValue, pCtx, 1); + if( pPatch==0 ){ + p->oom = 1; + break; + } + jsonParseAddNodeArray(p, pPatch->aNode, pPatch->nNode); + /* The nodes copied out of pPatch and into p likely contain + ** u.zJContent pointers into pPatch->zJson. So preserve the + ** content of pPatch until p is destroyed. */ + assert( pPatch->nJPRef>=1 ); + pPatch->nJPRef++; + jsonParseAddCleanup(p, (void(*)(void*))jsonParseFree, pPatch); + } + break; + } + default: { + jsonParseAddNode(p, JSON_NULL, 0, 0); + sqlite3_result_error(pCtx, "JSON cannot hold BLOB values", -1); + p->nErr++; + break; + } + } } /* @@ -202142,7 +204118,7 @@ static void jsonReplaceFunc( int argc, sqlite3_value **argv ){ - JsonParse x; /* The parse */ + JsonParse *pParse; /* The parse */ JsonNode *pNode; const char *zPath; u32 i; @@ -202152,28 +204128,20 @@ static void jsonReplaceFunc( jsonWrongNumArgs(ctx, "replace"); return; } - if( jsonParse(&x, ctx, (const char*)sqlite3_value_text(argv[0])) ) return; - assert( x.nNode ); + pParse = jsonParseCached(ctx, argv[0], ctx, argc>1); + if( pParse==0 ) return; for(i=1; i<(u32)argc; i+=2){ zPath = (const char*)sqlite3_value_text(argv[i]); - pNode = jsonLookup(&x, zPath, 0, ctx); - if( x.nErr ) goto replace_err; + pParse->useMod = 1; + pNode = jsonLookup(pParse, zPath, 0, ctx); + if( pParse->nErr ) goto replace_err; if( pNode ){ - assert( pNode->eU==0 || pNode->eU==1 || pNode->eU==4 ); - testcase( pNode->eU!=0 && pNode->eU!=1 ); - pNode->jnFlags |= (u8)JNODE_REPLACE; - VVA( pNode->eU = 4 ); - pNode->u.iReplace = i + 1; + jsonReplaceNode(ctx, pParse, (u32)(pNode - pParse->aNode), argv[i+1]); } } - if( x.aNode[0].jnFlags & JNODE_REPLACE ){ - assert( x.aNode[0].eU==4 ); - sqlite3_result_value(ctx, argv[x.aNode[0].u.iReplace]); - }else{ - jsonReturnJson(x.aNode, ctx, argv); - } + jsonReturnJson(pParse, pParse->aNode, ctx, 1); replace_err: - jsonParseReset(&x); + jsonDebugPrintParse(pParse); } @@ -202194,7 +204162,7 @@ static void jsonSetFunc( int argc, sqlite3_value **argv ){ - JsonParse x; /* The parse */ + JsonParse *pParse; /* The parse */ JsonNode *pNode; const char *zPath; u32 i; @@ -202206,33 +204174,27 @@ static void jsonSetFunc( jsonWrongNumArgs(ctx, bIsSet ? "set" : "insert"); return; } - if( jsonParse(&x, ctx, (const char*)sqlite3_value_text(argv[0])) ) return; - assert( x.nNode ); + pParse = jsonParseCached(ctx, argv[0], ctx, argc>1); + if( pParse==0 ) return; for(i=1; i<(u32)argc; i+=2){ zPath = (const char*)sqlite3_value_text(argv[i]); bApnd = 0; - pNode = jsonLookup(&x, zPath, &bApnd, ctx); - if( x.oom ){ + pParse->useMod = 1; + pNode = jsonLookup(pParse, zPath, &bApnd, ctx); + if( pParse->oom ){ sqlite3_result_error_nomem(ctx); goto jsonSetDone; - }else if( x.nErr ){ + }else if( pParse->nErr ){ goto jsonSetDone; }else if( pNode && (bApnd || bIsSet) ){ - testcase( pNode->eU!=0 && pNode->eU!=1 ); - assert( pNode->eU!=3 && pNode->eU!=5 ); - VVA( pNode->eU = 4 ); - pNode->jnFlags |= (u8)JNODE_REPLACE; - pNode->u.iReplace = i + 1; + jsonReplaceNode(ctx, pParse, (u32)(pNode - pParse->aNode), argv[i+1]); } } - if( x.aNode[0].jnFlags & JNODE_REPLACE ){ - assert( x.aNode[0].eU==4 ); - sqlite3_result_value(ctx, argv[x.aNode[0].u.iReplace]); - }else{ - jsonReturnJson(x.aNode, ctx, argv); - } + jsonDebugPrintParse(pParse); + jsonReturnJson(pParse, pParse->aNode, ctx, 1); + jsonSetDone: - jsonParseReset(&x); + /* no cleanup required */; } /* @@ -202251,7 +204213,7 @@ static void jsonTypeFunc( const char *zPath; JsonNode *pNode; - p = jsonParseCached(ctx, argv, ctx); + p = jsonParseCached(ctx, argv[0], ctx, 0); if( p==0 ) return; if( argc==2 ){ zPath = (const char*)sqlite3_value_text(argv[1]); @@ -202277,13 +204239,19 @@ static void jsonValidFunc( ){ JsonParse *p; /* The parse */ UNUSED_PARAMETER(argc); - if( sqlite3_value_type(argv[0])==SQLITE_NULL ) return; - p = jsonParseCached(ctx, argv, 0); + if( sqlite3_value_type(argv[0])==SQLITE_NULL ){ +#ifdef SQLITE_LEGACY_JSON_VALID + /* Incorrect legacy behavior was to return FALSE for a NULL input */ + sqlite3_result_int(ctx, 0); +#endif + return; + } + p = jsonParseCached(ctx, argv[0], 0, 0); if( p==0 || p->oom ){ sqlite3_result_error_nomem(ctx); sqlite3_free(p); }else{ - sqlite3_result_int(ctx, p->nErr==0 && p->hasNonstd==0); + sqlite3_result_int(ctx, p->nErr==0 && (p->hasNonstd==0 || p->useMod)); if( p->nErr ) jsonParseFree(p); } } @@ -202324,7 +204292,7 @@ static void jsonErrorFunc( JsonParse *p; /* The parse */ UNUSED_PARAMETER(argc); if( sqlite3_value_type(argv[0])==SQLITE_NULL ) return; - p = jsonParseCached(ctx, argv, 0); + p = jsonParseCached(ctx, argv[0], 0, 0); if( p==0 || p->oom ){ sqlite3_result_error_nomem(ctx); sqlite3_free(p); @@ -202333,7 +204301,7 @@ static void jsonErrorFunc( }else{ int n = 1; u32 i; - const char *z = p->zJson; + const char *z = (const char*)sqlite3_value_text(argv[0]); for(i=0; iiErr && ALWAYS(z[i]); i++){ if( (z[i]&0xc0)!=0x80 ) n++; } @@ -202381,7 +204349,8 @@ static void jsonArrayCompute(sqlite3_context *ctx, int isFinal){ assert( pStr->bStatic ); }else if( isFinal ){ sqlite3_result_text(ctx, pStr->zBuf, (int)pStr->nUsed, - pStr->bStatic ? SQLITE_TRANSIENT : sqlite3_free); + pStr->bStatic ? SQLITE_TRANSIENT : + (void(*)(void*))sqlite3RCStrUnref); pStr->bStatic = 1; }else{ sqlite3_result_text(ctx, pStr->zBuf, (int)pStr->nUsed, SQLITE_TRANSIENT); @@ -202422,7 +204391,7 @@ static void jsonGroupInverse( pStr = (JsonString*)sqlite3_aggregate_context(ctx, 0); #ifdef NEVER /* pStr is always non-NULL since jsonArrayStep() or jsonObjectStep() will - ** always have been called to initalize it */ + ** always have been called to initialize it */ if( NEVER(!pStr) ) return; #endif z = pStr->zBuf; @@ -202489,7 +204458,8 @@ static void jsonObjectCompute(sqlite3_context *ctx, int isFinal){ assert( pStr->bStatic ); }else if( isFinal ){ sqlite3_result_text(ctx, pStr->zBuf, (int)pStr->nUsed, - pStr->bStatic ? SQLITE_TRANSIENT : sqlite3_free); + pStr->bStatic ? SQLITE_TRANSIENT : + (void(*)(void*))sqlite3RCStrUnref); pStr->bStatic = 1; }else{ sqlite3_result_text(ctx, pStr->zBuf, (int)pStr->nUsed, SQLITE_TRANSIENT); @@ -202600,7 +204570,6 @@ static int jsonEachOpenTree(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){ /* Reset a JsonEachCursor back to its original state. Free any memory ** held. */ static void jsonEachCursorReset(JsonEachCursor *p){ - sqlite3_free(p->zJson); sqlite3_free(p->zRoot); jsonParseReset(&p->sParse); p->iRowid = 0; @@ -202738,7 +204707,7 @@ static int jsonEachColumn( case JEACH_KEY: { if( p->i==0 ) break; if( p->eType==JSON_OBJECT ){ - jsonReturn(pThis, ctx, 0); + jsonReturn(&p->sParse, pThis, ctx); }else if( p->eType==JSON_ARRAY ){ u32 iKey; if( p->bRecursive ){ @@ -202754,7 +204723,7 @@ static int jsonEachColumn( } case JEACH_VALUE: { if( pThis->jnFlags & JNODE_LABEL ) pThis++; - jsonReturn(pThis, ctx, 0); + jsonReturn(&p->sParse, pThis, ctx); break; } case JEACH_TYPE: { @@ -202765,7 +204734,7 @@ static int jsonEachColumn( case JEACH_ATOM: { if( pThis->jnFlags & JNODE_LABEL ) pThis++; if( pThis->eType>=JSON_ARRAY ) break; - jsonReturn(pThis, ctx, 0); + jsonReturn(&p->sParse, pThis, ctx); break; } case JEACH_ID: { @@ -202920,11 +204889,19 @@ static int jsonEachFilter( if( idxNum==0 ) return SQLITE_OK; z = (const char*)sqlite3_value_text(argv[0]); if( z==0 ) return SQLITE_OK; - n = sqlite3_value_bytes(argv[0]); - p->zJson = sqlite3_malloc64( n+1 ); - if( p->zJson==0 ) return SQLITE_NOMEM; - memcpy(p->zJson, z, (size_t)n+1); - if( jsonParse(&p->sParse, 0, p->zJson) ){ + memset(&p->sParse, 0, sizeof(p->sParse)); + p->sParse.nJPRef = 1; + if( sqlite3ValueIsOfClass(argv[0], (void(*)(void*))sqlite3RCStrUnref) ){ + p->sParse.zJson = sqlite3RCStrRef((char*)z); + }else{ + n = sqlite3_value_bytes(argv[0]); + p->sParse.zJson = sqlite3RCStrNew( n+1 ); + if( p->sParse.zJson==0 ) return SQLITE_NOMEM; + memcpy(p->sParse.zJson, z, (size_t)n+1); + } + p->sParse.bJsonIsRCStr = 1; + p->zJson = p->sParse.zJson; + if( jsonParse(&p->sParse, 0) ){ int rc = SQLITE_NOMEM; if( p->sParse.oom==0 ){ sqlite3_free(cur->pVtab->zErrMsg); @@ -203202,6 +205179,11 @@ typedef unsigned int u32; #endif #endif /* !defined(SQLITE_AMALGAMATION) */ +/* Macro to check for 4-byte alignment. Only used inside of assert() */ +#ifdef SQLITE_DEBUG +# define FOUR_BYTE_ALIGNED(X) ((((char*)(X) - (char*)0) & 3)==0) +#endif + /* #include */ /* #include */ /* #include */ @@ -203608,7 +205590,7 @@ static int readInt16(u8 *p){ return (p[0]<<8) + p[1]; } static void readCoord(u8 *p, RtreeCoord *pCoord){ - assert( (((sqlite3_uint64)p)&3)==0 ); /* p is always 4-byte aligned */ + assert( FOUR_BYTE_ALIGNED(p) ); #if SQLITE_BYTEORDER==1234 && MSVC_VERSION>=1300 pCoord->u = _byteswap_ulong(*(u32*)p); #elif SQLITE_BYTEORDER==1234 && GCC_VERSION>=4003000 @@ -203662,7 +205644,7 @@ static void writeInt16(u8 *p, int i){ } static int writeCoord(u8 *p, RtreeCoord *pCoord){ u32 i; - assert( (((sqlite3_uint64)p)&3)==0 ); /* p is always 4-byte aligned */ + assert( FOUR_BYTE_ALIGNED(p) ); assert( sizeof(RtreeCoord)==4 ); assert( sizeof(u32)==4 ); #if SQLITE_BYTEORDER==1234 && GCC_VERSION>=4003000 @@ -204390,7 +206372,7 @@ static void rtreeNonleafConstraint( assert(p->op==RTREE_LE || p->op==RTREE_LT || p->op==RTREE_GE || p->op==RTREE_GT || p->op==RTREE_EQ || p->op==RTREE_TRUE || p->op==RTREE_FALSE ); - assert( (((sqlite3_uint64)pCellData)&3)==0 ); /* 4-byte aligned */ + assert( FOUR_BYTE_ALIGNED(pCellData) ); switch( p->op ){ case RTREE_TRUE: return; /* Always satisfied */ case RTREE_FALSE: break; /* Never satisfied */ @@ -204443,7 +206425,7 @@ static void rtreeLeafConstraint( || p->op==RTREE_GT || p->op==RTREE_EQ || p->op==RTREE_TRUE || p->op==RTREE_FALSE ); pCellData += 8 + p->iCoord*4; - assert( (((sqlite3_uint64)pCellData)&3)==0 ); /* 4-byte aligned */ + assert( FOUR_BYTE_ALIGNED(pCellData) ); RTREE_DECODE_COORD(eInt, pCellData, xN); switch( p->op ){ case RTREE_TRUE: return; /* Always satisfied */ @@ -205013,7 +206995,20 @@ static int rtreeFilter( p->pInfo->nCoord = pRtree->nDim2; p->pInfo->anQueue = pCsr->anQueue; p->pInfo->mxLevel = pRtree->iDepth + 1; - }else if( eType==SQLITE_INTEGER || eType==SQLITE_FLOAT ){ + }else if( eType==SQLITE_INTEGER ){ + sqlite3_int64 iVal = sqlite3_value_int64(argv[ii]); +#ifdef SQLITE_RTREE_INT_ONLY + p->u.rValue = iVal; +#else + p->u.rValue = (double)iVal; + if( iVal>=((sqlite3_int64)1)<<48 + || iVal<=-(((sqlite3_int64)1)<<48) + ){ + if( p->op==RTREE_LT ) p->op = RTREE_LE; + if( p->op==RTREE_GT ) p->op = RTREE_GE; + } +#endif + }else if( eType==SQLITE_FLOAT ){ #ifdef SQLITE_RTREE_INT_ONLY p->u.rValue = sqlite3_value_int64(argv[ii]); #else @@ -205144,11 +207139,12 @@ static int rtreeBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){ || p->op==SQLITE_INDEX_CONSTRAINT_MATCH) ){ u8 op; + u8 doOmit = 1; switch( p->op ){ - case SQLITE_INDEX_CONSTRAINT_EQ: op = RTREE_EQ; break; - case SQLITE_INDEX_CONSTRAINT_GT: op = RTREE_GT; break; + case SQLITE_INDEX_CONSTRAINT_EQ: op = RTREE_EQ; doOmit = 0; break; + case SQLITE_INDEX_CONSTRAINT_GT: op = RTREE_GT; doOmit = 0; break; case SQLITE_INDEX_CONSTRAINT_LE: op = RTREE_LE; break; - case SQLITE_INDEX_CONSTRAINT_LT: op = RTREE_LT; break; + case SQLITE_INDEX_CONSTRAINT_LT: op = RTREE_LT; doOmit = 0; break; case SQLITE_INDEX_CONSTRAINT_GE: op = RTREE_GE; break; case SQLITE_INDEX_CONSTRAINT_MATCH: op = RTREE_MATCH; break; default: op = 0; break; @@ -205157,7 +207153,7 @@ static int rtreeBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){ zIdxStr[iIdx++] = op; zIdxStr[iIdx++] = (char)(p->iColumn - 1 + '0'); pIdxInfo->aConstraintUsage[ii].argvIndex = (iIdx/2); - pIdxInfo->aConstraintUsage[ii].omit = 1; + pIdxInfo->aConstraintUsage[ii].omit = doOmit; } } } @@ -218645,6 +220641,7 @@ static int sessionPreupdateEqual( rc = pSession->hook.xOld(pSession->hook.pCtx, iCol, &pVal); } assert( rc==SQLITE_OK ); + (void)rc; /* Suppress warning about unused variable */ if( sqlite3_value_type(pVal)!=eType ) return 0; /* A SessionChange object never has a NULL value in a PK column */ @@ -224060,7 +226057,7 @@ struct Fts5PhraseIter { ** See xPhraseFirstColumn above. */ struct Fts5ExtensionApi { - int iVersion; /* Currently always set to 3 */ + int iVersion; /* Currently always set to 2 */ void *(*xUserData)(Fts5Context*); @@ -224289,8 +226286,8 @@ struct Fts5ExtensionApi { ** as separate queries of the FTS index are required for each synonym. ** ** When using methods (2) or (3), it is important that the tokenizer only -** provide synonyms when tokenizing document text (method (2)) or query -** text (method (3)), not both. Doing so will not cause any errors, but is +** provide synonyms when tokenizing document text (method (3)) or query +** text (method (2)), not both. Doing so will not cause any errors, but is ** inefficient. */ typedef struct Fts5Tokenizer Fts5Tokenizer; @@ -224338,7 +226335,7 @@ struct fts5_api { int (*xCreateTokenizer)( fts5_api *pApi, const char *zName, - void *pContext, + void *pUserData, fts5_tokenizer *pTokenizer, void (*xDestroy)(void*) ); @@ -224347,7 +226344,7 @@ struct fts5_api { int (*xFindTokenizer)( fts5_api *pApi, const char *zName, - void **ppContext, + void **ppUserData, fts5_tokenizer *pTokenizer ); @@ -224355,7 +226352,7 @@ struct fts5_api { int (*xCreateFunction)( fts5_api *pApi, const char *zName, - void *pContext, + void *pUserData, fts5_extension_function xFunction, void (*xDestroy)(void*) ); @@ -224527,6 +226524,10 @@ typedef struct Fts5Config Fts5Config; ** attempt to merge together. A value of 1 sets the object to use the ** compile time default. Zero disables auto-merge altogether. ** +** bContentlessDelete: +** True if the contentless_delete option was present in the CREATE +** VIRTUAL TABLE statement. +** ** zContent: ** ** zContentRowid: @@ -224561,6 +226562,7 @@ struct Fts5Config { int nPrefix; /* Number of prefix indexes */ int *aPrefix; /* Sizes in bytes of nPrefix prefix indexes */ int eContent; /* An FTS5_CONTENT value */ + int bContentlessDelete; /* "contentless_delete=" option (dflt==0) */ char *zContent; /* content table */ char *zContentRowid; /* "content_rowid=" option value */ int bColumnsize; /* "columnsize=" option value (dflt==1) */ @@ -224582,6 +226584,7 @@ struct Fts5Config { char *zRank; /* Name of rank function */ char *zRankArgs; /* Arguments to rank function */ int bSecureDelete; /* 'secure-delete' */ + int nDeleteMerge; /* 'deletemerge' */ /* If non-NULL, points to sqlite3_vtab.base.zErrmsg. Often NULL. */ char **pzErrmsg; @@ -224904,6 +226907,9 @@ static int sqlite3Fts5IndexReset(Fts5Index *p); static int sqlite3Fts5IndexLoadConfig(Fts5Index *p); +static int sqlite3Fts5IndexGetOrigin(Fts5Index *p, i64 *piOrigin); +static int sqlite3Fts5IndexContentlessDelete(Fts5Index *p, i64 iOrigin, i64 iRowid); + /* ** End of interface to code in fts5_index.c. **************************************************************************/ @@ -224988,6 +226994,11 @@ static int sqlite3Fts5HashWrite( */ static void sqlite3Fts5HashClear(Fts5Hash*); +/* +** Return true if the hash is empty, false otherwise. +*/ +static int sqlite3Fts5HashIsEmpty(Fts5Hash*); + static int sqlite3Fts5HashQuery( Fts5Hash*, /* Hash table to query */ int nPre, @@ -225009,6 +227020,7 @@ static void sqlite3Fts5HashScanEntry(Fts5Hash *, ); + /* ** End of interface to code in fts5_hash.c. **************************************************************************/ @@ -225252,7 +227264,8 @@ static void sqlite3Fts5UnicodeAscii(u8*, u8*); #define FTS5_STAR 15 /* This file is automatically generated by Lemon from input grammar -** source file "fts5parse.y". */ +** source file "fts5parse.y". +*/ /* ** 2000-05-29 ** @@ -227880,6 +229893,8 @@ static void sqlite3Fts5TermsetFree(Fts5Termset *p){ #define FTS5_DEFAULT_CRISISMERGE 16 #define FTS5_DEFAULT_HASHSIZE (1024*1024) +#define FTS5_DEFAULT_DELETE_AUTOMERGE 10 /* default 10% */ + /* Maximum allowed page size */ #define FTS5_MAX_PAGE_SIZE (64*1024) @@ -228210,6 +230225,16 @@ static int fts5ConfigParseSpecial( return rc; } + if( sqlite3_strnicmp("contentless_delete", zCmd, nCmd)==0 ){ + if( (zArg[0]!='0' && zArg[0]!='1') || zArg[1]!='\0' ){ + *pzErr = sqlite3_mprintf("malformed contentless_delete=... directive"); + rc = SQLITE_ERROR; + }else{ + pConfig->bContentlessDelete = (zArg[0]=='1'); + } + return rc; + } + if( sqlite3_strnicmp("content_rowid", zCmd, nCmd)==0 ){ if( pConfig->zContentRowid ){ *pzErr = sqlite3_mprintf("multiple content_rowid=... directives"); @@ -228454,6 +230479,28 @@ static int sqlite3Fts5ConfigParse( sqlite3_free(zTwo); } + /* We only allow contentless_delete=1 if the table is indeed contentless. */ + if( rc==SQLITE_OK + && pRet->bContentlessDelete + && pRet->eContent!=FTS5_CONTENT_NONE + ){ + *pzErr = sqlite3_mprintf( + "contentless_delete=1 requires a contentless table" + ); + rc = SQLITE_ERROR; + } + + /* We only allow contentless_delete=1 if columnsize=0 is not present. + ** + ** This restriction may be removed at some point. + */ + if( rc==SQLITE_OK && pRet->bContentlessDelete && pRet->bColumnsize==0 ){ + *pzErr = sqlite3_mprintf( + "contentless_delete=1 is incompatible with columnsize=0" + ); + rc = SQLITE_ERROR; + } + /* If a tokenizer= option was successfully parsed, the tokenizer has ** already been allocated. Otherwise, allocate an instance of the default ** tokenizer (unicode61) now. */ @@ -228748,6 +230795,18 @@ static int sqlite3Fts5ConfigSetValue( } } + else if( 0==sqlite3_stricmp(zKey, "deletemerge") ){ + int nVal = -1; + if( SQLITE_INTEGER==sqlite3_value_numeric_type(pVal) ){ + nVal = sqlite3_value_int(pVal); + }else{ + *pbBadkey = 1; + } + if( nVal<0 ) nVal = FTS5_DEFAULT_DELETE_AUTOMERGE; + if( nVal>100 ) nVal = 0; + pConfig->nDeleteMerge = nVal; + } + else if( 0==sqlite3_stricmp(zKey, "rank") ){ const char *zIn = (const char*)sqlite3_value_text(pVal); char *zRank; @@ -228796,6 +230855,7 @@ static int sqlite3Fts5ConfigLoad(Fts5Config *pConfig, int iCookie){ pConfig->nUsermerge = FTS5_DEFAULT_USERMERGE; pConfig->nCrisisMerge = FTS5_DEFAULT_CRISISMERGE; pConfig->nHashSize = FTS5_DEFAULT_HASHSIZE; + pConfig->nDeleteMerge = FTS5_DEFAULT_DELETE_AUTOMERGE; zSql = sqlite3Fts5Mprintf(&rc, zSelect, pConfig->zDb, pConfig->zName); if( zSql ){ @@ -231319,7 +233379,7 @@ static Fts5ExprNode *sqlite3Fts5ParseImplicitAnd( return pRet; } -#ifdef SQLITE_TEST +#if defined(SQLITE_TEST) || defined(SQLITE_FTS5_DEBUG) static char *fts5ExprTermPrint(Fts5ExprTerm *pTerm){ sqlite3_int64 nByte = 0; Fts5ExprTerm *p; @@ -231425,6 +233485,8 @@ static char *fts5ExprPrintTcl( if( zRet==0 ) return 0; } + }else if( pExpr->eType==0 ){ + zRet = sqlite3_mprintf("{}"); }else{ char const *zOp = 0; int i; @@ -231686,14 +233748,14 @@ static void fts5ExprFold( sqlite3_result_int(pCtx, sqlite3Fts5UnicodeFold(iCode, bRemoveDiacritics)); } } -#endif /* ifdef SQLITE_TEST */ +#endif /* if SQLITE_TEST || SQLITE_FTS5_DEBUG */ /* ** This is called during initialization to register the fts5_expr() scalar ** UDF with the SQLite handle passed as the only argument. */ static int sqlite3Fts5ExprInit(Fts5Global *pGlobal, sqlite3 *db){ -#ifdef SQLITE_TEST +#if defined(SQLITE_TEST) || defined(SQLITE_FTS5_DEBUG) struct Fts5ExprFunc { const char *z; void (*x)(sqlite3_context*,int,sqlite3_value**); @@ -232453,7 +234515,6 @@ static int fts5HashEntrySort( pList = fts5HashEntryMerge(pList, ap[i]); } - pHash->nEntry = 0; sqlite3_free(ap); *ppSorted = pList; return SQLITE_OK; @@ -232507,6 +234568,28 @@ static int sqlite3Fts5HashScanInit( return fts5HashEntrySort(p, pTerm, nTerm, &p->pScan); } +#ifdef SQLITE_DEBUG +static int fts5HashCount(Fts5Hash *pHash){ + int nEntry = 0; + int ii; + for(ii=0; iinSlot; ii++){ + Fts5HashEntry *p = 0; + for(p=pHash->aSlot[ii]; p; p=p->pHashNext){ + nEntry++; + } + } + return nEntry; +} +#endif + +/* +** Return true if the hash table is empty, false otherwise. +*/ +static int sqlite3Fts5HashIsEmpty(Fts5Hash *pHash){ + assert( pHash->nEntry==fts5HashCount(pHash) ); + return pHash->nEntry==0; +} + static void sqlite3Fts5HashScanNext(Fts5Hash *p){ assert( !sqlite3Fts5HashScanEof(p) ); p->pScan = p->pScan->pScanNext; @@ -232595,6 +234678,24 @@ static void sqlite3Fts5HashScanEntry( #define FTS5_MAX_LEVEL 64 +/* +** There are two versions of the format used for the structure record: +** +** 1. the legacy format, that may be read by all fts5 versions, and +** +** 2. the V2 format, which is used by contentless_delete=1 databases. +** +** Both begin with a 4-byte "configuration cookie" value. Then, a legacy +** format structure record contains a varint - the number of levels in +** the structure. Whereas a V2 structure record contains the constant +** 4 bytes [0xff 0x00 0x00 0x01]. This is unambiguous as the value of a +** varint has to be at least 16256 to begin with "0xFF". And the default +** maximum number of levels is 64. +** +** See below for more on structure record formats. +*/ +#define FTS5_STRUCTURE_V2 "\xFF\x00\x00\x01" + /* ** Details: ** @@ -232602,7 +234703,7 @@ static void sqlite3Fts5HashScanEntry( ** ** CREATE TABLE %_data(id INTEGER PRIMARY KEY, block BLOB); ** -** , contains the following 5 types of records. See the comments surrounding +** , contains the following 6 types of records. See the comments surrounding ** the FTS5_*_ROWID macros below for a description of how %_data rowids are ** assigned to each fo them. ** @@ -232611,12 +234712,12 @@ static void sqlite3Fts5HashScanEntry( ** The set of segments that make up an index - the index structure - are ** recorded in a single record within the %_data table. The record consists ** of a single 32-bit configuration cookie value followed by a list of -** SQLite varints. If the FTS table features more than one index (because -** there are one or more prefix indexes), it is guaranteed that all share -** the same cookie value. +** SQLite varints. ** -** Immediately following the configuration cookie, the record begins with -** three varints: +** If the structure record is a V2 record, the configuration cookie is +** followed by the following 4 bytes: [0xFF 0x00 0x00 0x01]. +** +** Next, the record continues with three varints: ** ** + number of levels, ** + total number of segments on all levels, @@ -232631,6 +234732,12 @@ static void sqlite3Fts5HashScanEntry( ** + first leaf page number (often 1, always greater than 0) ** + final leaf page number ** +** Then, for V2 structures only: +** +** + lower origin counter value, +** + upper origin counter value, +** + the number of tombstone hash pages. +** ** 2. The Averages Record: ** ** A single record within the %_data table. The data is a list of varints. @@ -232746,6 +234853,38 @@ static void sqlite3Fts5HashScanEntry( ** * A list of delta-encoded varints - the first rowid on each subsequent ** child page. ** +** 6. Tombstone Hash Page +** +** These records are only ever present in contentless_delete=1 tables. +** There are zero or more of these associated with each segment. They +** are used to store the tombstone rowids for rows contained in the +** associated segments. +** +** The set of nHashPg tombstone hash pages associated with a single +** segment together form a single hash table containing tombstone rowids. +** To find the page of the hash on which a key might be stored: +** +** iPg = (rowid % nHashPg) +** +** Then, within page iPg, which has nSlot slots: +** +** iSlot = (rowid / nHashPg) % nSlot +** +** Each tombstone hash page begins with an 8 byte header: +** +** 1-byte: Key-size (the size in bytes of each slot). Either 4 or 8. +** 1-byte: rowid-0-tombstone flag. This flag is only valid on the +** first tombstone hash page for each segment (iPg=0). If set, +** the hash table contains rowid 0. If clear, it does not. +** Rowid 0 is handled specially. +** 2-bytes: unused. +** 4-bytes: Big-endian integer containing number of entries on page. +** +** Following this are nSlot 4 or 8 byte slots (depending on the key-size +** in the first byte of the page header). The number of slots may be +** determined based on the size of the page record and the key-size: +** +** nSlot = (nByte - 8) / key-size */ /* @@ -232779,6 +234918,7 @@ static void sqlite3Fts5HashScanEntry( #define FTS5_SEGMENT_ROWID(segid, pgno) fts5_dri(segid, 0, 0, pgno) #define FTS5_DLIDX_ROWID(segid, height, pgno) fts5_dri(segid, 1, height, pgno) +#define FTS5_TOMBSTONE_ROWID(segid,ipg) fts5_dri(segid+(1<<16), 0, 0, ipg) #ifdef SQLITE_DEBUG static int sqlite3Fts5Corrupt() { return SQLITE_CORRUPT_VTAB; } @@ -232814,6 +234954,12 @@ struct Fts5Data { /* ** One object per %_data table. +** +** nContentlessDelete: +** The number of contentless delete operations since the most recent +** call to fts5IndexFlush() or fts5IndexDiscardData(). This is tracked +** so that extra auto-merge work can be done by fts5IndexFlush() to +** account for the delete operations. */ struct Fts5Index { Fts5Config *pConfig; /* Virtual table configuration */ @@ -232828,6 +234974,8 @@ struct Fts5Index { int nPendingData; /* Current bytes of pending data */ i64 iWriteRowid; /* Rowid for current doc being written */ int bDelete; /* Current write is a delete */ + int nContentlessDelete; /* Number of contentless delete ops */ + int nPendingRow; /* Number of INSERT in hash table */ /* Error state. */ int rc; /* Current error code */ @@ -232862,11 +235010,23 @@ struct Fts5DoclistIter { ** The contents of the "structure" record for each index are represented ** using an Fts5Structure record in memory. Which uses instances of the ** other Fts5StructureXXX types as components. +** +** nOriginCntr: +** This value is set to non-zero for structure records created for +** contentlessdelete=1 tables only. In that case it represents the +** origin value to apply to the next top-level segment created. */ struct Fts5StructureSegment { int iSegid; /* Segment id */ int pgnoFirst; /* First leaf page number in segment */ int pgnoLast; /* Last leaf page number in segment */ + + /* contentlessdelete=1 tables only: */ + u64 iOrigin1; + u64 iOrigin2; + int nPgTombstone; /* Number of tombstone hash table pages */ + u64 nEntryTombstone; /* Number of tombstone entries that "count" */ + u64 nEntry; /* Number of rows in this segment */ }; struct Fts5StructureLevel { int nMerge; /* Number of segments in incr-merge */ @@ -232876,6 +235036,7 @@ struct Fts5StructureLevel { struct Fts5Structure { int nRef; /* Object reference count */ u64 nWriteCounter; /* Total leaves written to level 0 */ + u64 nOriginCntr; /* Origin value for next top-level segment */ int nSegment; /* Total segments in this structure */ int nLevel; /* Number of levels in this index */ Fts5StructureLevel aLevel[1]; /* Array of nLevel level objects */ @@ -232964,6 +235125,13 @@ struct Fts5CResult { ** ** iTermIdx: ** Index of current term on iTermLeafPgno. +** +** apTombstone/nTombstone: +** These are used for contentless_delete=1 tables only. When the cursor +** is first allocated, the apTombstone[] array is allocated so that it +** is large enough for all tombstones hash pages associated with the +** segment. The pages themselves are loaded lazily from the database as +** they are required. */ struct Fts5SegIter { Fts5StructureSegment *pSeg; /* Segment to iterate through */ @@ -232972,6 +235140,8 @@ struct Fts5SegIter { Fts5Data *pLeaf; /* Current leaf data */ Fts5Data *pNextLeaf; /* Leaf page (iLeafPgno+1) */ i64 iLeafOffset; /* Byte offset within current leaf */ + Fts5Data **apTombstone; /* Array of tombstone pages */ + int nTombstone; /* Next method */ void (*xNext)(Fts5Index*, Fts5SegIter*, int*); @@ -233101,6 +235271,60 @@ static u16 fts5GetU16(const u8 *aIn){ return ((u16)aIn[0] << 8) + aIn[1]; } +/* +** The only argument points to a buffer at least 8 bytes in size. This +** function interprets the first 8 bytes of the buffer as a 64-bit big-endian +** unsigned integer and returns the result. +*/ +static u64 fts5GetU64(u8 *a){ + return ((u64)a[0] << 56) + + ((u64)a[1] << 48) + + ((u64)a[2] << 40) + + ((u64)a[3] << 32) + + ((u64)a[4] << 24) + + ((u64)a[5] << 16) + + ((u64)a[6] << 8) + + ((u64)a[7] << 0); +} + +/* +** The only argument points to a buffer at least 4 bytes in size. This +** function interprets the first 4 bytes of the buffer as a 32-bit big-endian +** unsigned integer and returns the result. +*/ +static u32 fts5GetU32(const u8 *a){ + return ((u32)a[0] << 24) + + ((u32)a[1] << 16) + + ((u32)a[2] << 8) + + ((u32)a[3] << 0); +} + +/* +** Write iVal, formated as a 64-bit big-endian unsigned integer, to the +** buffer indicated by the first argument. +*/ +static void fts5PutU64(u8 *a, u64 iVal){ + a[0] = ((iVal >> 56) & 0xFF); + a[1] = ((iVal >> 48) & 0xFF); + a[2] = ((iVal >> 40) & 0xFF); + a[3] = ((iVal >> 32) & 0xFF); + a[4] = ((iVal >> 24) & 0xFF); + a[5] = ((iVal >> 16) & 0xFF); + a[6] = ((iVal >> 8) & 0xFF); + a[7] = ((iVal >> 0) & 0xFF); +} + +/* +** Write iVal, formated as a 32-bit big-endian unsigned integer, to the +** buffer indicated by the first argument. +*/ +static void fts5PutU32(u8 *a, u32 iVal){ + a[0] = ((iVal >> 24) & 0xFF); + a[1] = ((iVal >> 16) & 0xFF); + a[2] = ((iVal >> 8) & 0xFF); + a[3] = ((iVal >> 0) & 0xFF); +} + /* ** Allocate and return a buffer at least nByte bytes in size. ** @@ -233328,10 +235552,17 @@ static void fts5DataDelete(Fts5Index *p, i64 iFirst, i64 iLast){ /* ** Remove all records associated with segment iSegid. */ -static void fts5DataRemoveSegment(Fts5Index *p, int iSegid){ +static void fts5DataRemoveSegment(Fts5Index *p, Fts5StructureSegment *pSeg){ + int iSegid = pSeg->iSegid; i64 iFirst = FTS5_SEGMENT_ROWID(iSegid, 0); i64 iLast = FTS5_SEGMENT_ROWID(iSegid+1, 0)-1; fts5DataDelete(p, iFirst, iLast); + + if( pSeg->nPgTombstone ){ + i64 iTomb1 = FTS5_TOMBSTONE_ROWID(iSegid, 0); + i64 iTomb2 = FTS5_TOMBSTONE_ROWID(iSegid, pSeg->nPgTombstone-1); + fts5DataDelete(p, iTomb1, iTomb2); + } if( p->pIdxDeleter==0 ){ Fts5Config *pConfig = p->pConfig; fts5IndexPrepareStmt(p, &p->pIdxDeleter, sqlite3_mprintf( @@ -233442,11 +235673,19 @@ static int fts5StructureDecode( int nSegment = 0; sqlite3_int64 nByte; /* Bytes of space to allocate at pRet */ Fts5Structure *pRet = 0; /* Structure object to return */ + int bStructureV2 = 0; /* True for FTS5_STRUCTURE_V2 */ + u64 nOriginCntr = 0; /* Largest origin value seen so far */ /* Grab the cookie value */ if( piCookie ) *piCookie = sqlite3Fts5Get32(pData); i = 4; + /* Check if this is a V2 structure record. Set bStructureV2 if it is. */ + if( 0==memcmp(&pData[i], FTS5_STRUCTURE_V2, 4) ){ + i += 4; + bStructureV2 = 1; + } + /* Read the total number of levels and segments from the start of the ** structure record. */ i += fts5GetVarint32(&pData[i], nLevel); @@ -233497,6 +235736,14 @@ static int fts5StructureDecode( i += fts5GetVarint32(&pData[i], pSeg->iSegid); i += fts5GetVarint32(&pData[i], pSeg->pgnoFirst); i += fts5GetVarint32(&pData[i], pSeg->pgnoLast); + if( bStructureV2 ){ + i += fts5GetVarint(&pData[i], &pSeg->iOrigin1); + i += fts5GetVarint(&pData[i], &pSeg->iOrigin2); + i += fts5GetVarint32(&pData[i], pSeg->nPgTombstone); + i += fts5GetVarint(&pData[i], &pSeg->nEntryTombstone); + i += fts5GetVarint(&pData[i], &pSeg->nEntry); + nOriginCntr = MAX(nOriginCntr, pSeg->iOrigin2); + } if( pSeg->pgnoLastpgnoFirst ){ rc = FTS5_CORRUPT; break; @@ -233507,6 +235754,9 @@ static int fts5StructureDecode( } } if( nSegment!=0 && rc==SQLITE_OK ) rc = FTS5_CORRUPT; + if( bStructureV2 ){ + pRet->nOriginCntr = nOriginCntr+1; + } if( rc!=SQLITE_OK ){ fts5StructureRelease(pRet); @@ -233719,6 +235969,7 @@ static void fts5StructureWrite(Fts5Index *p, Fts5Structure *pStruct){ Fts5Buffer buf; /* Buffer to serialize record into */ int iLvl; /* Used to iterate through levels */ int iCookie; /* Cookie value to store */ + int nHdr = (pStruct->nOriginCntr>0 ? (4+4+9+9+9) : (4+9+9)); assert( pStruct->nSegment==fts5StructureCountSegments(pStruct) ); memset(&buf, 0, sizeof(Fts5Buffer)); @@ -233727,9 +235978,12 @@ static void fts5StructureWrite(Fts5Index *p, Fts5Structure *pStruct){ iCookie = p->pConfig->iCookie; if( iCookie<0 ) iCookie = 0; - if( 0==sqlite3Fts5BufferSize(&p->rc, &buf, 4+9+9+9) ){ + if( 0==sqlite3Fts5BufferSize(&p->rc, &buf, nHdr) ){ sqlite3Fts5Put32(buf.p, iCookie); buf.n = 4; + if( pStruct->nOriginCntr>0 ){ + fts5BufferSafeAppendBlob(&buf, FTS5_STRUCTURE_V2, 4); + } fts5BufferSafeAppendVarint(&buf, pStruct->nLevel); fts5BufferSafeAppendVarint(&buf, pStruct->nSegment); fts5BufferSafeAppendVarint(&buf, (i64)pStruct->nWriteCounter); @@ -233743,9 +235997,17 @@ static void fts5StructureWrite(Fts5Index *p, Fts5Structure *pStruct){ assert( pLvl->nMerge<=pLvl->nSeg ); for(iSeg=0; iSegnSeg; iSeg++){ - fts5BufferAppendVarint(&p->rc, &buf, pLvl->aSeg[iSeg].iSegid); - fts5BufferAppendVarint(&p->rc, &buf, pLvl->aSeg[iSeg].pgnoFirst); - fts5BufferAppendVarint(&p->rc, &buf, pLvl->aSeg[iSeg].pgnoLast); + Fts5StructureSegment *pSeg = &pLvl->aSeg[iSeg]; + fts5BufferAppendVarint(&p->rc, &buf, pSeg->iSegid); + fts5BufferAppendVarint(&p->rc, &buf, pSeg->pgnoFirst); + fts5BufferAppendVarint(&p->rc, &buf, pSeg->pgnoLast); + if( pStruct->nOriginCntr>0 ){ + fts5BufferAppendVarint(&p->rc, &buf, pSeg->iOrigin1); + fts5BufferAppendVarint(&p->rc, &buf, pSeg->iOrigin2); + fts5BufferAppendVarint(&p->rc, &buf, pSeg->nPgTombstone); + fts5BufferAppendVarint(&p->rc, &buf, pSeg->nEntryTombstone); + fts5BufferAppendVarint(&p->rc, &buf, pSeg->nEntry); + } } } @@ -234268,6 +236530,23 @@ static void fts5SegIterSetNext(Fts5Index *p, Fts5SegIter *pIter){ } } +/* +** Allocate a tombstone hash page array (pIter->apTombstone) for the +** iterator passed as the second argument. If an OOM error occurs, leave +** an error in the Fts5Index object. +*/ +static void fts5SegIterAllocTombstone(Fts5Index *p, Fts5SegIter *pIter){ + const int nTomb = pIter->pSeg->nPgTombstone; + if( nTomb>0 ){ + Fts5Data **apTomb = 0; + apTomb = (Fts5Data**)sqlite3Fts5MallocZero(&p->rc, sizeof(Fts5Data)*nTomb); + if( apTomb ){ + pIter->apTombstone = apTomb; + pIter->nTombstone = nTomb; + } + } +} + /* ** Initialize the iterator object pIter to iterate through the entries in ** segment pSeg. The iterator is left pointing to the first entry when @@ -234309,6 +236588,7 @@ static void fts5SegIterInit( pIter->iPgidxOff = pIter->pLeaf->szLeaf+1; fts5SegIterLoadTerm(p, pIter, 0); fts5SegIterLoadNPos(p, pIter); + fts5SegIterAllocTombstone(p, pIter); } } @@ -235010,6 +237290,7 @@ static void fts5SegIterSeekInit( } fts5SegIterSetNext(p, pIter); + fts5SegIterAllocTombstone(p, pIter); /* Either: ** @@ -235090,6 +237371,20 @@ static void fts5SegIterHashInit( fts5SegIterSetNext(p, pIter); } +/* +** Array ap[] contains n elements. Release each of these elements using +** fts5DataRelease(). Then free the array itself using sqlite3_free(). +*/ +static void fts5IndexFreeArray(Fts5Data **ap, int n){ + if( ap ){ + int ii; + for(ii=0; iiterm); fts5DataRelease(pIter->pLeaf); fts5DataRelease(pIter->pNextLeaf); + fts5IndexFreeArray(pIter->apTombstone, pIter->nTombstone); fts5DlidxIterFree(pIter->pDlidx); sqlite3_free(pIter->aRowidOffset); memset(pIter, 0, sizeof(Fts5SegIter)); @@ -235434,6 +237730,84 @@ static void fts5MultiIterSetEof(Fts5Iter *pIter){ pIter->iSwitchRowid = pSeg->iRowid; } +/* +** The argument to this macro must be an Fts5Data structure containing a +** tombstone hash page. This macro returns the key-size of the hash-page. +*/ +#define TOMBSTONE_KEYSIZE(pPg) (pPg->p[0]==4 ? 4 : 8) + +#define TOMBSTONE_NSLOT(pPg) \ + ((pPg->nn > 16) ? ((pPg->nn-8) / TOMBSTONE_KEYSIZE(pPg)) : 1) + +/* +** Query a single tombstone hash table for rowid iRowid. Return true if +** it is found or false otherwise. The tombstone hash table is one of +** nHashTable tables. +*/ +static int fts5IndexTombstoneQuery( + Fts5Data *pHash, /* Hash table page to query */ + int nHashTable, /* Number of pages attached to segment */ + u64 iRowid /* Rowid to query hash for */ +){ + const int szKey = TOMBSTONE_KEYSIZE(pHash); + const int nSlot = TOMBSTONE_NSLOT(pHash); + int iSlot = (iRowid / nHashTable) % nSlot; + int nCollide = nSlot; + + if( iRowid==0 ){ + return pHash->p[1]; + }else if( szKey==4 ){ + u32 *aSlot = (u32*)&pHash->p[8]; + while( aSlot[iSlot] ){ + if( fts5GetU32((u8*)&aSlot[iSlot])==iRowid ) return 1; + if( nCollide--==0 ) break; + iSlot = (iSlot+1)%nSlot; + } + }else{ + u64 *aSlot = (u64*)&pHash->p[8]; + while( aSlot[iSlot] ){ + if( fts5GetU64((u8*)&aSlot[iSlot])==iRowid ) return 1; + if( nCollide--==0 ) break; + iSlot = (iSlot+1)%nSlot; + } + } + + return 0; +} + +/* +** Return true if the iterator passed as the only argument points +** to an segment entry for which there is a tombstone. Return false +** if there is no tombstone or if the iterator is already at EOF. +*/ +static int fts5MultiIterIsDeleted(Fts5Iter *pIter){ + int iFirst = pIter->aFirst[1].iFirst; + Fts5SegIter *pSeg = &pIter->aSeg[iFirst]; + + if( pSeg->pLeaf && pSeg->nTombstone ){ + /* Figure out which page the rowid might be present on. */ + int iPg = ((u64)pSeg->iRowid) % pSeg->nTombstone; + assert( iPg>=0 ); + + /* If tombstone hash page iPg has not yet been loaded from the + ** database, load it now. */ + if( pSeg->apTombstone[iPg]==0 ){ + pSeg->apTombstone[iPg] = fts5DataRead(pIter->pIndex, + FTS5_TOMBSTONE_ROWID(pSeg->pSeg->iSegid, iPg) + ); + if( pSeg->apTombstone[iPg]==0 ) return 0; + } + + return fts5IndexTombstoneQuery( + pSeg->apTombstone[iPg], + pSeg->nTombstone, + pSeg->iRowid + ); + } + + return 0; +} + /* ** Move the iterator to the next entry. ** @@ -235471,7 +237845,9 @@ static void fts5MultiIterNext( fts5AssertMultiIterSetup(p, pIter); assert( pSeg==&pIter->aSeg[pIter->aFirst[1].iFirst] && pSeg->pLeaf ); - if( pIter->bSkipEmpty==0 || pSeg->nPos ){ + if( (pIter->bSkipEmpty==0 || pSeg->nPos) + && 0==fts5MultiIterIsDeleted(pIter) + ){ pIter->xSetOutputs(pIter, pSeg); return; } @@ -235503,7 +237879,9 @@ static void fts5MultiIterNext2( } fts5AssertMultiIterSetup(p, pIter); - }while( fts5MultiIterIsEmpty(p, pIter) ); + }while( (fts5MultiIterIsEmpty(p, pIter) || fts5MultiIterIsDeleted(pIter)) + && (p->rc==SQLITE_OK) + ); } } @@ -236058,7 +238436,9 @@ static void fts5MultiIterNew( fts5MultiIterSetEof(pNew); fts5AssertMultiIterSetup(p, pNew); - if( pNew->bSkipEmpty && fts5MultiIterIsEmpty(p, pNew) ){ + if( (pNew->bSkipEmpty && fts5MultiIterIsEmpty(p, pNew)) + || fts5MultiIterIsDeleted(pNew) + ){ fts5MultiIterNext(p, pNew, 0, 0); }else if( pNew->base.bEof==0 ){ Fts5SegIter *pSeg = &pNew->aSeg[pNew->aFirst[1].iFirst]; @@ -236236,7 +238616,9 @@ static void fts5IndexDiscardData(Fts5Index *p){ if( p->pHash ){ sqlite3Fts5HashClear(p->pHash); p->nPendingData = 0; + p->nPendingRow = 0; } + p->nContentlessDelete = 0; } /* @@ -236873,6 +239255,12 @@ static void fts5IndexMergeLevel( /* Read input from all segments in the input level */ nInput = pLvl->nSeg; + + /* Set the range of origins that will go into the output segment. */ + if( pStruct->nOriginCntr>0 ){ + pSeg->iOrigin1 = pLvl->aSeg[0].iOrigin1; + pSeg->iOrigin2 = pLvl->aSeg[pLvl->nSeg-1].iOrigin2; + } } bOldest = (pLvlOut->nSeg==1 && pStruct->nLevel==iLvl+2); @@ -236932,8 +239320,11 @@ static void fts5IndexMergeLevel( int i; /* Remove the redundant segments from the %_data table */ + assert( pSeg->nEntry==0 ); for(i=0; iaSeg[i].iSegid); + Fts5StructureSegment *pOld = &pLvl->aSeg[i]; + pSeg->nEntry += (pOld->nEntry - pOld->nEntryTombstone); + fts5DataRemoveSegment(p, pOld); } /* Remove the redundant segments from the input level */ @@ -236959,6 +239350,43 @@ static void fts5IndexMergeLevel( if( pnRem ) *pnRem -= writer.nLeafWritten; } +/* +** If this is not a contentless_delete=1 table, or if the 'deletemerge' +** configuration option is set to 0, then this function always returns -1. +** Otherwise, it searches the structure object passed as the second argument +** for a level suitable for merging due to having a large number of +** tombstones in the tombstone hash. If one is found, its index is returned. +** Otherwise, if there is no suitable level, -1. +*/ +static int fts5IndexFindDeleteMerge(Fts5Index *p, Fts5Structure *pStruct){ + Fts5Config *pConfig = p->pConfig; + int iRet = -1; + if( pConfig->bContentlessDelete && pConfig->nDeleteMerge>0 ){ + int ii; + int nBest = 0; + + for(ii=0; iinLevel; ii++){ + Fts5StructureLevel *pLvl = &pStruct->aLevel[ii]; + i64 nEntry = 0; + i64 nTomb = 0; + int iSeg; + for(iSeg=0; iSegnSeg; iSeg++){ + nEntry += pLvl->aSeg[iSeg].nEntry; + nTomb += pLvl->aSeg[iSeg].nEntryTombstone; + } + assert_nc( nEntry>0 || pLvl->nSeg==0 ); + if( nEntry>0 ){ + int nPercent = (nTomb * 100) / nEntry; + if( nPercent>=pConfig->nDeleteMerge && nPercent>nBest ){ + iRet = ii; + nBest = nPercent; + } + } + } + } + return iRet; +} + /* ** Do up to nPg pages of automerge work on the index. ** @@ -236978,14 +239406,15 @@ static int fts5IndexMerge( int iBestLvl = 0; /* Level offering the most input segments */ int nBest = 0; /* Number of input segments on best level */ - /* Set iBestLvl to the level to read input segments from. */ + /* Set iBestLvl to the level to read input segments from. Or to -1 if + ** there is no level suitable to merge segments from. */ assert( pStruct->nLevel>0 ); for(iLvl=0; iLvlnLevel; iLvl++){ Fts5StructureLevel *pLvl = &pStruct->aLevel[iLvl]; if( pLvl->nMerge ){ if( pLvl->nMerge>nBest ){ iBestLvl = iLvl; - nBest = pLvl->nMerge; + nBest = nMin; } break; } @@ -236994,22 +239423,18 @@ static int fts5IndexMerge( iBestLvl = iLvl; } } - - /* If nBest is still 0, then the index must be empty. */ -#ifdef SQLITE_DEBUG - for(iLvl=0; nBest==0 && iLvlnLevel; iLvl++){ - assert( pStruct->aLevel[iLvl].nSeg==0 ); + if( nBestaLevel[iBestLvl].nMerge==0 ){ - break; - } + if( iBestLvl<0 ) break; bRet = 1; fts5IndexMergeLevel(p, &pStruct, iBestLvl, &nRem); if( p->rc==SQLITE_OK && pStruct->aLevel[iBestLvl].nMerge==0 ){ fts5StructurePromote(p, iBestLvl+1, pStruct); } + + if( nMin==1 ) nMin = 2; } *ppStruct = pStruct; return bRet; @@ -237175,7 +239600,7 @@ static void fts5SecureDeleteOverflow( pLeaf = 0; }else if( bDetailNone ){ break; - }else if( iNext>=pLeaf->szLeaf || iNext<4 ){ + }else if( iNext>=pLeaf->szLeaf || pLeaf->nnszLeaf || iNext<4 ){ p->rc = FTS5_CORRUPT; break; }else{ @@ -237194,9 +239619,13 @@ static void fts5SecureDeleteOverflow( int i1 = pLeaf->szLeaf; int i2 = 0; + i1 += fts5GetVarint32(&aPg[i1], iFirst); + if( iFirstrc = FTS5_CORRUPT; + break; + } aIdx = sqlite3Fts5MallocZero(&p->rc, (pLeaf->nn-pLeaf->szLeaf)+2); if( aIdx==0 ) break; - i1 += fts5GetVarint32(&aPg[i1], iFirst); i2 = sqlite3Fts5PutVarint(aIdx, iFirst-nShift); if( i1nn ){ memcpy(&aIdx[i2], &aPg[i1], pLeaf->nn-i1); @@ -237379,7 +239808,9 @@ static void fts5DoSecureDelete( iOff += sqlite3Fts5PutVarint(&aPg[iOff], nPrefix); } iOff += sqlite3Fts5PutVarint(&aPg[iOff], nSuffix); - if( nPrefix2>nPrefix ){ + if( nPrefix2>pSeg->term.n ){ + p->rc = FTS5_CORRUPT; + }else if( nPrefix2>nPrefix ){ memcpy(&aPg[iOff], &pSeg->term.p[nPrefix], nPrefix2-nPrefix); iOff += (nPrefix2-nPrefix); } @@ -237516,187 +239947,197 @@ static void fts5FlushOneHash(Fts5Index *p){ /* Obtain a reference to the index structure and allocate a new segment-id ** for the new level-0 segment. */ pStruct = fts5StructureRead(p); - iSegid = fts5AllocateSegid(p, pStruct); fts5StructureInvalidate(p); - if( iSegid ){ - const int pgsz = p->pConfig->pgsz; - int eDetail = p->pConfig->eDetail; - int bSecureDelete = p->pConfig->bSecureDelete; - Fts5StructureSegment *pSeg; /* New segment within pStruct */ - Fts5Buffer *pBuf; /* Buffer in which to assemble leaf page */ - Fts5Buffer *pPgidx; /* Buffer in which to assemble pgidx */ + if( sqlite3Fts5HashIsEmpty(pHash)==0 ){ + iSegid = fts5AllocateSegid(p, pStruct); + if( iSegid ){ + const int pgsz = p->pConfig->pgsz; + int eDetail = p->pConfig->eDetail; + int bSecureDelete = p->pConfig->bSecureDelete; + Fts5StructureSegment *pSeg; /* New segment within pStruct */ + Fts5Buffer *pBuf; /* Buffer in which to assemble leaf page */ + Fts5Buffer *pPgidx; /* Buffer in which to assemble pgidx */ - Fts5SegWriter writer; - fts5WriteInit(p, &writer, iSegid); + Fts5SegWriter writer; + fts5WriteInit(p, &writer, iSegid); - pBuf = &writer.writer.buf; - pPgidx = &writer.writer.pgidx; + pBuf = &writer.writer.buf; + pPgidx = &writer.writer.pgidx; - /* fts5WriteInit() should have initialized the buffers to (most likely) - ** the maximum space required. */ - assert( p->rc || pBuf->nSpace>=(pgsz + FTS5_DATA_PADDING) ); - assert( p->rc || pPgidx->nSpace>=(pgsz + FTS5_DATA_PADDING) ); + /* fts5WriteInit() should have initialized the buffers to (most likely) + ** the maximum space required. */ + assert( p->rc || pBuf->nSpace>=(pgsz + FTS5_DATA_PADDING) ); + assert( p->rc || pPgidx->nSpace>=(pgsz + FTS5_DATA_PADDING) ); - /* Begin scanning through hash table entries. This loop runs once for each - ** term/doclist currently stored within the hash table. */ - if( p->rc==SQLITE_OK ){ - p->rc = sqlite3Fts5HashScanInit(pHash, 0, 0); - } - while( p->rc==SQLITE_OK && 0==sqlite3Fts5HashScanEof(pHash) ){ - const char *zTerm; /* Buffer containing term */ - int nTerm; /* Size of zTerm in bytes */ - const u8 *pDoclist; /* Pointer to doclist for this term */ - int nDoclist; /* Size of doclist in bytes */ - - /* Get the term and doclist for this entry. */ - sqlite3Fts5HashScanEntry(pHash, &zTerm, &pDoclist, &nDoclist); - nTerm = (int)strlen(zTerm); - if( bSecureDelete==0 ){ - fts5WriteAppendTerm(p, &writer, nTerm, (const u8*)zTerm); - if( p->rc!=SQLITE_OK ) break; - assert( writer.bFirstRowidInPage==0 ); + /* Begin scanning through hash table entries. This loop runs once for each + ** term/doclist currently stored within the hash table. */ + if( p->rc==SQLITE_OK ){ + p->rc = sqlite3Fts5HashScanInit(pHash, 0, 0); } + while( p->rc==SQLITE_OK && 0==sqlite3Fts5HashScanEof(pHash) ){ + const char *zTerm; /* Buffer containing term */ + int nTerm; /* Size of zTerm in bytes */ + const u8 *pDoclist; /* Pointer to doclist for this term */ + int nDoclist; /* Size of doclist in bytes */ - if( !bSecureDelete && pgsz>=(pBuf->n + pPgidx->n + nDoclist + 1) ){ - /* The entire doclist will fit on the current leaf. */ - fts5BufferSafeAppendBlob(pBuf, pDoclist, nDoclist); - }else{ - int bTermWritten = !bSecureDelete; - i64 iRowid = 0; - i64 iPrev = 0; - int iOff = 0; + /* Get the term and doclist for this entry. */ + sqlite3Fts5HashScanEntry(pHash, &zTerm, &pDoclist, &nDoclist); + nTerm = (int)strlen(zTerm); + if( bSecureDelete==0 ){ + fts5WriteAppendTerm(p, &writer, nTerm, (const u8*)zTerm); + if( p->rc!=SQLITE_OK ) break; + assert( writer.bFirstRowidInPage==0 ); + } - /* The entire doclist will not fit on this leaf. The following - ** loop iterates through the poslists that make up the current - ** doclist. */ - while( p->rc==SQLITE_OK && iOff=(pBuf->n + pPgidx->n + nDoclist + 1) ){ + /* The entire doclist will fit on the current leaf. */ + fts5BufferSafeAppendBlob(pBuf, pDoclist, nDoclist); + }else{ + int bTermWritten = !bSecureDelete; + i64 iRowid = 0; + i64 iPrev = 0; + int iOff = 0; - /* If in secure delete mode, and if this entry in the poslist is - ** in fact a delete, then edit the existing segments directly - ** using fts5FlushSecureDelete(). */ - if( bSecureDelete ){ - if( eDetail==FTS5_DETAIL_NONE ){ - if( iOffrc==SQLITE_OK && iOffrc!=SQLITE_OK || pDoclist[iOff]==0x01 ){ iOff++; - nDoclist = 0; - }else{ continue; } } - }else if( (pDoclist[iOff] & 0x01) ){ - fts5FlushSecureDelete(p, pStruct, zTerm, iRowid); - if( p->rc!=SQLITE_OK || pDoclist[iOff]==0x01 ){ - iOff++; - continue; - } } - } - if( p->rc==SQLITE_OK && bTermWritten==0 ){ - fts5WriteAppendTerm(p, &writer, nTerm, (const u8*)zTerm); - bTermWritten = 1; - assert( p->rc!=SQLITE_OK || writer.bFirstRowidInPage==0 ); - } + if( p->rc==SQLITE_OK && bTermWritten==0 ){ + fts5WriteAppendTerm(p, &writer, nTerm, (const u8*)zTerm); + bTermWritten = 1; + assert( p->rc!=SQLITE_OK || writer.bFirstRowidInPage==0 ); + } - if( writer.bFirstRowidInPage ){ - fts5PutU16(&pBuf->p[0], (u16)pBuf->n); /* first rowid on page */ - pBuf->n += sqlite3Fts5PutVarint(&pBuf->p[pBuf->n], iRowid); - writer.bFirstRowidInPage = 0; - fts5WriteDlidxAppend(p, &writer, iRowid); - }else{ - pBuf->n += sqlite3Fts5PutVarint(&pBuf->p[pBuf->n], iRowid-iPrev); - } - if( p->rc!=SQLITE_OK ) break; - assert( pBuf->n<=pBuf->nSpace ); - iPrev = iRowid; + if( writer.bFirstRowidInPage ){ + fts5PutU16(&pBuf->p[0], (u16)pBuf->n); /* first rowid on page */ + pBuf->n += sqlite3Fts5PutVarint(&pBuf->p[pBuf->n], iRowid); + writer.bFirstRowidInPage = 0; + fts5WriteDlidxAppend(p, &writer, iRowid); + }else{ + u64 iRowidDelta = (u64)iRowid - (u64)iPrev; + pBuf->n += sqlite3Fts5PutVarint(&pBuf->p[pBuf->n], iRowidDelta); + } + if( p->rc!=SQLITE_OK ) break; + assert( pBuf->n<=pBuf->nSpace ); + iPrev = iRowid; - if( eDetail==FTS5_DETAIL_NONE ){ - if( iOffp[pBuf->n++] = 0; - iOff++; + if( eDetail==FTS5_DETAIL_NONE ){ if( iOffp[pBuf->n++] = 0; iOff++; + if( iOffp[pBuf->n++] = 0; + iOff++; + } + } + if( (pBuf->n + pPgidx->n)>=pgsz ){ + fts5WriteFlushLeaf(p, &writer); } - } - if( (pBuf->n + pPgidx->n)>=pgsz ){ - fts5WriteFlushLeaf(p, &writer); - } - }else{ - int bDummy; - int nPos; - int nCopy = fts5GetPoslistSize(&pDoclist[iOff], &nPos, &bDummy); - nCopy += nPos; - if( (pBuf->n + pPgidx->n + nCopy) <= pgsz ){ - /* The entire poslist will fit on the current leaf. So copy - ** it in one go. */ - fts5BufferSafeAppendBlob(pBuf, &pDoclist[iOff], nCopy); }else{ - /* The entire poslist will not fit on this leaf. So it needs - ** to be broken into sections. The only qualification being - ** that each varint must be stored contiguously. */ - const u8 *pPoslist = &pDoclist[iOff]; - int iPos = 0; - while( p->rc==SQLITE_OK ){ - int nSpace = pgsz - pBuf->n - pPgidx->n; - int n = 0; - if( (nCopy - iPos)<=nSpace ){ - n = nCopy - iPos; - }else{ - n = fts5PoslistPrefix(&pPoslist[iPos], nSpace); + int bDummy; + int nPos; + int nCopy = fts5GetPoslistSize(&pDoclist[iOff], &nPos, &bDummy); + nCopy += nPos; + if( (pBuf->n + pPgidx->n + nCopy) <= pgsz ){ + /* The entire poslist will fit on the current leaf. So copy + ** it in one go. */ + fts5BufferSafeAppendBlob(pBuf, &pDoclist[iOff], nCopy); + }else{ + /* The entire poslist will not fit on this leaf. So it needs + ** to be broken into sections. The only qualification being + ** that each varint must be stored contiguously. */ + const u8 *pPoslist = &pDoclist[iOff]; + int iPos = 0; + while( p->rc==SQLITE_OK ){ + int nSpace = pgsz - pBuf->n - pPgidx->n; + int n = 0; + if( (nCopy - iPos)<=nSpace ){ + n = nCopy - iPos; + }else{ + n = fts5PoslistPrefix(&pPoslist[iPos], nSpace); + } + assert( n>0 ); + fts5BufferSafeAppendBlob(pBuf, &pPoslist[iPos], n); + iPos += n; + if( (pBuf->n + pPgidx->n)>=pgsz ){ + fts5WriteFlushLeaf(p, &writer); + } + if( iPos>=nCopy ) break; } - assert( n>0 ); - fts5BufferSafeAppendBlob(pBuf, &pPoslist[iPos], n); - iPos += n; - if( (pBuf->n + pPgidx->n)>=pgsz ){ - fts5WriteFlushLeaf(p, &writer); - } - if( iPos>=nCopy ) break; } + iOff += nCopy; } - iOff += nCopy; } } - } - /* TODO2: Doclist terminator written here. */ - /* pBuf->p[pBuf->n++] = '\0'; */ - assert( pBuf->n<=pBuf->nSpace ); - if( p->rc==SQLITE_OK ) sqlite3Fts5HashScanNext(pHash); - } - sqlite3Fts5HashClear(pHash); - fts5WriteFinish(p, &writer, &pgnoLast); + /* TODO2: Doclist terminator written here. */ + /* pBuf->p[pBuf->n++] = '\0'; */ + assert( pBuf->n<=pBuf->nSpace ); + if( p->rc==SQLITE_OK ) sqlite3Fts5HashScanNext(pHash); + } + sqlite3Fts5HashClear(pHash); + fts5WriteFinish(p, &writer, &pgnoLast); - assert( p->rc!=SQLITE_OK || bSecureDelete || pgnoLast>0 ); - if( pgnoLast>0 ){ - /* Update the Fts5Structure. It is written back to the database by the - ** fts5StructureRelease() call below. */ - if( pStruct->nLevel==0 ){ - fts5StructureAddLevel(&p->rc, &pStruct); + assert( p->rc!=SQLITE_OK || bSecureDelete || pgnoLast>0 ); + if( pgnoLast>0 ){ + /* Update the Fts5Structure. It is written back to the database by the + ** fts5StructureRelease() call below. */ + if( pStruct->nLevel==0 ){ + fts5StructureAddLevel(&p->rc, &pStruct); + } + fts5StructureExtendLevel(&p->rc, pStruct, 0, 1, 0); + if( p->rc==SQLITE_OK ){ + pSeg = &pStruct->aLevel[0].aSeg[ pStruct->aLevel[0].nSeg++ ]; + pSeg->iSegid = iSegid; + pSeg->pgnoFirst = 1; + pSeg->pgnoLast = pgnoLast; + if( pStruct->nOriginCntr>0 ){ + pSeg->iOrigin1 = pStruct->nOriginCntr; + pSeg->iOrigin2 = pStruct->nOriginCntr; + pSeg->nEntry = p->nPendingRow; + pStruct->nOriginCntr++; + } + pStruct->nSegment++; + } + fts5StructurePromote(p, 0, pStruct); } - fts5StructureExtendLevel(&p->rc, pStruct, 0, 1, 0); - if( p->rc==SQLITE_OK ){ - pSeg = &pStruct->aLevel[0].aSeg[ pStruct->aLevel[0].nSeg++ ]; - pSeg->iSegid = iSegid; - pSeg->pgnoFirst = 1; - pSeg->pgnoLast = pgnoLast; - pStruct->nSegment++; - } - fts5StructurePromote(p, 0, pStruct); } } - fts5IndexAutomerge(p, &pStruct, pgnoLast); + fts5IndexAutomerge(p, &pStruct, pgnoLast + p->nContentlessDelete); fts5IndexCrisismerge(p, &pStruct); fts5StructureWrite(p, pStruct); fts5StructureRelease(pStruct); + p->nContentlessDelete = 0; } /* @@ -237704,10 +240145,11 @@ static void fts5FlushOneHash(Fts5Index *p){ */ static void fts5IndexFlush(Fts5Index *p){ /* Unless it is empty, flush the hash table to disk */ - if( p->nPendingData ){ + if( p->nPendingData || p->nContentlessDelete ){ assert( p->pHash ); - p->nPendingData = 0; fts5FlushOneHash(p); + p->nPendingData = 0; + p->nPendingRow = 0; } } @@ -237723,17 +240165,22 @@ static Fts5Structure *fts5IndexOptimizeStruct( /* Figure out if this structure requires optimization. A structure does ** not require optimization if either: ** - ** + it consists of fewer than two segments, or - ** + all segments are on the same level, or - ** + all segments except one are currently inputs to a merge operation. + ** 1. it consists of fewer than two segments, or + ** 2. all segments are on the same level, or + ** 3. all segments except one are currently inputs to a merge operation. ** - ** In the first case, return NULL. In the second, increment the ref-count - ** on *pStruct and return a copy of the pointer to it. + ** In the first case, if there are no tombstone hash pages, return NULL. In + ** the second, increment the ref-count on *pStruct and return a copy of the + ** pointer to it. */ - if( nSeg<2 ) return 0; + if( nSeg==0 ) return 0; for(i=0; inLevel; i++){ int nThis = pStruct->aLevel[i].nSeg; - if( nThis==nSeg || (nThis==nSeg-1 && pStruct->aLevel[i].nMerge==nThis) ){ + int nMerge = pStruct->aLevel[i].nMerge; + if( nThis>0 && (nThis==nSeg || (nThis==nSeg-1 && nMerge==nThis)) ){ + if( nSeg==1 && nThis==1 && pStruct->aLevel[i].aSeg[0].nPgTombstone==0 ){ + return 0; + } fts5StructureRef(pStruct); return pStruct; } @@ -237749,6 +240196,7 @@ static Fts5Structure *fts5IndexOptimizeStruct( pNew->nLevel = MIN(pStruct->nLevel+1, FTS5_MAX_LEVEL); pNew->nRef = 1; pNew->nWriteCounter = pStruct->nWriteCounter; + pNew->nOriginCntr = pStruct->nOriginCntr; pLvl = &pNew->aLevel[pNew->nLevel-1]; pLvl->aSeg = (Fts5StructureSegment*)sqlite3Fts5MallocZero(&p->rc, nByte); if( pLvl->aSeg ){ @@ -237779,6 +240227,7 @@ static int sqlite3Fts5IndexOptimize(Fts5Index *p){ assert( p->rc==SQLITE_OK ); fts5IndexFlush(p); + assert( p->nContentlessDelete==0 ); pStruct = fts5StructureRead(p); fts5StructureInvalidate(p); @@ -237808,7 +240257,10 @@ static int sqlite3Fts5IndexOptimize(Fts5Index *p){ ** INSERT command. */ static int sqlite3Fts5IndexMerge(Fts5Index *p, int nMerge){ - Fts5Structure *pStruct = fts5StructureRead(p); + Fts5Structure *pStruct = 0; + + fts5IndexFlush(p); + pStruct = fts5StructureRead(p); if( pStruct ){ int nMin = p->pConfig->nUsermerge; fts5StructureInvalidate(p); @@ -237816,7 +240268,7 @@ static int sqlite3Fts5IndexMerge(Fts5Index *p, int nMerge){ Fts5Structure *pNew = fts5IndexOptimizeStruct(p, pStruct); fts5StructureRelease(pStruct); pStruct = pNew; - nMin = 2; + nMin = 1; nMerge = nMerge*-1; } if( pStruct && pStruct->nLevel ){ @@ -238330,6 +240782,9 @@ static int sqlite3Fts5IndexBeginWrite(Fts5Index *p, int bDelete, i64 iRowid){ p->iWriteRowid = iRowid; p->bDelete = bDelete; + if( bDelete==0 ){ + p->nPendingRow++; + } return fts5IndexReturn(p); } @@ -238367,6 +240822,9 @@ static int sqlite3Fts5IndexReinit(Fts5Index *p){ fts5StructureInvalidate(p); fts5IndexDiscardData(p); memset(&s, 0, sizeof(Fts5Structure)); + if( p->pConfig->bContentlessDelete ){ + s.nOriginCntr = 1; + } fts5DataWrite(p, FTS5_AVERAGES_ROWID, (const u8*)"", 0); fts5StructureWrite(p, &s); return fts5IndexReturn(p); @@ -238758,6 +241216,347 @@ static int sqlite3Fts5IndexLoadConfig(Fts5Index *p){ return fts5IndexReturn(p); } +/* +** Retrieve the origin value that will be used for the segment currently +** being accumulated in the in-memory hash table when it is flushed to +** disk. If successful, SQLITE_OK is returned and (*piOrigin) set to +** the queried value. Or, if an error occurs, an error code is returned +** and the final value of (*piOrigin) is undefined. +*/ +static int sqlite3Fts5IndexGetOrigin(Fts5Index *p, i64 *piOrigin){ + Fts5Structure *pStruct; + pStruct = fts5StructureRead(p); + if( pStruct ){ + *piOrigin = pStruct->nOriginCntr; + fts5StructureRelease(pStruct); + } + return fts5IndexReturn(p); +} + +/* +** Buffer pPg contains a page of a tombstone hash table - one of nPg pages +** associated with the same segment. This function adds rowid iRowid to +** the hash table. The caller is required to guarantee that there is at +** least one free slot on the page. +** +** If parameter bForce is false and the hash table is deemed to be full +** (more than half of the slots are occupied), then non-zero is returned +** and iRowid not inserted. Or, if bForce is true or if the hash table page +** is not full, iRowid is inserted and zero returned. +*/ +static int fts5IndexTombstoneAddToPage( + Fts5Data *pPg, + int bForce, + int nPg, + u64 iRowid +){ + const int szKey = TOMBSTONE_KEYSIZE(pPg); + const int nSlot = TOMBSTONE_NSLOT(pPg); + const int nElem = fts5GetU32(&pPg->p[4]); + int iSlot = (iRowid / nPg) % nSlot; + int nCollide = nSlot; + + if( szKey==4 && iRowid>0xFFFFFFFF ) return 2; + if( iRowid==0 ){ + pPg->p[1] = 0x01; + return 0; + } + + if( bForce==0 && nElem>=(nSlot/2) ){ + return 1; + } + + fts5PutU32(&pPg->p[4], nElem+1); + if( szKey==4 ){ + u32 *aSlot = (u32*)&pPg->p[8]; + while( aSlot[iSlot] ){ + iSlot = (iSlot + 1) % nSlot; + if( nCollide--==0 ) return 0; + } + fts5PutU32((u8*)&aSlot[iSlot], (u32)iRowid); + }else{ + u64 *aSlot = (u64*)&pPg->p[8]; + while( aSlot[iSlot] ){ + iSlot = (iSlot + 1) % nSlot; + if( nCollide--==0 ) return 0; + } + fts5PutU64((u8*)&aSlot[iSlot], iRowid); + } + + return 0; +} + +/* +** This function attempts to build a new hash containing all the keys +** currently in the tombstone hash table for segment pSeg. The new +** hash will be stored in the nOut buffers passed in array apOut[]. +** All pages of the new hash use key-size szKey (4 or 8). +** +** Return 0 if the hash is successfully rebuilt into the nOut pages. +** Or non-zero if it is not (because one page became overfull). In this +** case the caller should retry with a larger nOut parameter. +** +** Parameter pData1 is page iPg1 of the hash table being rebuilt. +*/ +static int fts5IndexTombstoneRehash( + Fts5Index *p, + Fts5StructureSegment *pSeg, /* Segment to rebuild hash of */ + Fts5Data *pData1, /* One page of current hash - or NULL */ + int iPg1, /* Which page of the current hash is pData1 */ + int szKey, /* 4 or 8, the keysize */ + int nOut, /* Number of output pages */ + Fts5Data **apOut /* Array of output hash pages */ +){ + int ii; + int res = 0; + + /* Initialize the headers of all the output pages */ + for(ii=0; iip[0] = szKey; + fts5PutU32(&apOut[ii]->p[4], 0); + } + + /* Loop through the current pages of the hash table. */ + for(ii=0; res==0 && iinPgTombstone; ii++){ + Fts5Data *pData = 0; /* Page ii of the current hash table */ + Fts5Data *pFree = 0; /* Free this at the end of the loop */ + + if( iPg1==ii ){ + pData = pData1; + }else{ + pFree = pData = fts5DataRead(p, FTS5_TOMBSTONE_ROWID(pSeg->iSegid, ii)); + } + + if( pData ){ + int szKeyIn = TOMBSTONE_KEYSIZE(pData); + int nSlotIn = (pData->nn - 8) / szKeyIn; + int iIn; + for(iIn=0; iInp[8]; + if( aSlot[iIn] ) iVal = fts5GetU32((u8*)&aSlot[iIn]); + }else{ + u64 *aSlot = (u64*)&pData->p[8]; + if( aSlot[iIn] ) iVal = fts5GetU64((u8*)&aSlot[iIn]); + } + + /* If iVal is not 0 at this point, insert it into the new hash table */ + if( iVal ){ + Fts5Data *pPg = apOut[(iVal % nOut)]; + res = fts5IndexTombstoneAddToPage(pPg, 0, nOut, iVal); + if( res ) break; + } + } + + /* If this is page 0 of the old hash, copy the rowid-0-flag from the + ** old hash to the new. */ + if( ii==0 ){ + apOut[0]->p[1] = pData->p[1]; + } + } + fts5DataRelease(pFree); + } + + return res; +} + +/* +** This is called to rebuild the hash table belonging to segment pSeg. +** If parameter pData1 is not NULL, then one page of the existing hash table +** has already been loaded - pData1, which is page iPg1. The key-size for +** the new hash table is szKey (4 or 8). +** +** If successful, the new hash table is not written to disk. Instead, +** output parameter (*pnOut) is set to the number of pages in the new +** hash table, and (*papOut) to point to an array of buffers containing +** the new page data. +** +** If an error occurs, an error code is left in the Fts5Index object and +** both output parameters set to 0 before returning. +*/ +static void fts5IndexTombstoneRebuild( + Fts5Index *p, + Fts5StructureSegment *pSeg, /* Segment to rebuild hash of */ + Fts5Data *pData1, /* One page of current hash - or NULL */ + int iPg1, /* Which page of the current hash is pData1 */ + int szKey, /* 4 or 8, the keysize */ + int *pnOut, /* OUT: Number of output pages */ + Fts5Data ***papOut /* OUT: Output hash pages */ +){ + const int MINSLOT = 32; + int nSlotPerPage = MAX(MINSLOT, (p->pConfig->pgsz - 8) / szKey); + int nSlot = 0; /* Number of slots in each output page */ + int nOut = 0; + + /* Figure out how many output pages (nOut) and how many slots per + ** page (nSlot). There are three possibilities: + ** + ** 1. The hash table does not yet exist. In this case the new hash + ** table will consist of a single page with MINSLOT slots. + ** + ** 2. The hash table exists but is currently a single page. In this + ** case an attempt is made to grow the page to accommodate the new + ** entry. The page is allowed to grow up to nSlotPerPage (see above) + ** slots. + ** + ** 3. The hash table already consists of more than one page, or of + ** a single page already so large that it cannot be grown. In this + ** case the new hash consists of (nPg*2+1) pages of nSlotPerPage + ** slots each, where nPg is the current number of pages in the + ** hash table. + */ + if( pSeg->nPgTombstone==0 ){ + /* Case 1. */ + nOut = 1; + nSlot = MINSLOT; + }else if( pSeg->nPgTombstone==1 ){ + /* Case 2. */ + int nElem = (int)fts5GetU32(&pData1->p[4]); + assert( pData1 && iPg1==0 ); + nOut = 1; + nSlot = MAX(nElem*4, MINSLOT); + if( nSlot>nSlotPerPage ) nOut = 0; + } + if( nOut==0 ){ + /* Case 3. */ + nOut = (pSeg->nPgTombstone * 2 + 1); + nSlot = nSlotPerPage; + } + + /* Allocate the required array and output pages */ + while( 1 ){ + int res = 0; + int ii = 0; + int szPage = 0; + Fts5Data **apOut = 0; + + /* Allocate space for the new hash table */ + assert( nSlot>=MINSLOT ); + apOut = (Fts5Data**)sqlite3Fts5MallocZero(&p->rc, sizeof(Fts5Data*) * nOut); + szPage = 8 + nSlot*szKey; + for(ii=0; iirc, + sizeof(Fts5Data)+szPage + ); + if( pNew ){ + pNew->nn = szPage; + pNew->p = (u8*)&pNew[1]; + apOut[ii] = pNew; + } + } + + /* Rebuild the hash table. */ + if( p->rc==SQLITE_OK ){ + res = fts5IndexTombstoneRehash(p, pSeg, pData1, iPg1, szKey, nOut, apOut); + } + if( res==0 ){ + if( p->rc ){ + fts5IndexFreeArray(apOut, nOut); + apOut = 0; + nOut = 0; + } + *pnOut = nOut; + *papOut = apOut; + break; + } + + /* If control flows to here, it was not possible to rebuild the hash + ** table. Free all buffers and then try again with more pages. */ + assert( p->rc==SQLITE_OK ); + fts5IndexFreeArray(apOut, nOut); + nSlot = nSlotPerPage; + nOut = nOut*2 + 1; + } +} + + +/* +** Add a tombstone for rowid iRowid to segment pSeg. +*/ +static void fts5IndexTombstoneAdd( + Fts5Index *p, + Fts5StructureSegment *pSeg, + u64 iRowid +){ + Fts5Data *pPg = 0; + int iPg = -1; + int szKey = 0; + int nHash = 0; + Fts5Data **apHash = 0; + + p->nContentlessDelete++; + + if( pSeg->nPgTombstone>0 ){ + iPg = iRowid % pSeg->nPgTombstone; + pPg = fts5DataRead(p, FTS5_TOMBSTONE_ROWID(pSeg->iSegid,iPg)); + if( pPg==0 ){ + assert( p->rc!=SQLITE_OK ); + return; + } + + if( 0==fts5IndexTombstoneAddToPage(pPg, 0, pSeg->nPgTombstone, iRowid) ){ + fts5DataWrite(p, FTS5_TOMBSTONE_ROWID(pSeg->iSegid,iPg), pPg->p, pPg->nn); + fts5DataRelease(pPg); + return; + } + } + + /* Have to rebuild the hash table. First figure out the key-size (4 or 8). */ + szKey = pPg ? TOMBSTONE_KEYSIZE(pPg) : 4; + if( iRowid>0xFFFFFFFF ) szKey = 8; + + /* Rebuild the hash table */ + fts5IndexTombstoneRebuild(p, pSeg, pPg, iPg, szKey, &nHash, &apHash); + assert( p->rc==SQLITE_OK || (nHash==0 && apHash==0) ); + + /* If all has succeeded, write the new rowid into one of the new hash + ** table pages, then write them all out to disk. */ + if( nHash ){ + int ii = 0; + fts5IndexTombstoneAddToPage(apHash[iRowid % nHash], 1, nHash, iRowid); + for(ii=0; iiiSegid, ii); + fts5DataWrite(p, iTombstoneRowid, apHash[ii]->p, apHash[ii]->nn); + } + pSeg->nPgTombstone = nHash; + fts5StructureWrite(p, p->pStruct); + } + + fts5DataRelease(pPg); + fts5IndexFreeArray(apHash, nHash); +} + +/* +** Add iRowid to the tombstone list of the segment or segments that contain +** rows from origin iOrigin. Return SQLITE_OK if successful, or an SQLite +** error code otherwise. +*/ +static int sqlite3Fts5IndexContentlessDelete(Fts5Index *p, i64 iOrigin, i64 iRowid){ + Fts5Structure *pStruct; + pStruct = fts5StructureRead(p); + if( pStruct ){ + int bFound = 0; /* True after pSeg->nEntryTombstone incr. */ + int iLvl; + for(iLvl=pStruct->nLevel-1; iLvl>=0; iLvl--){ + int iSeg; + for(iSeg=pStruct->aLevel[iLvl].nSeg-1; iSeg>=0; iSeg--){ + Fts5StructureSegment *pSeg = &pStruct->aLevel[iLvl].aSeg[iSeg]; + if( pSeg->iOrigin1<=(u64)iOrigin && pSeg->iOrigin2>=(u64)iOrigin ){ + if( bFound==0 ){ + pSeg->nEntryTombstone++; + bFound = 1; + } + fts5IndexTombstoneAdd(p, pSeg, iRowid); + } + } + } + fts5StructureRelease(pStruct); + } + return fts5IndexReturn(p); +} /************************************************************************* ************************************************************************** @@ -239309,13 +242108,14 @@ static int sqlite3Fts5IndexIntegrityCheck(Fts5Index *p, u64 cksum, int bUseCksum ** function only. */ -#ifdef SQLITE_TEST +#if defined(SQLITE_TEST) || defined(SQLITE_FTS5_DEBUG) /* ** Decode a segment-data rowid from the %_data table. This function is ** the opposite of macro FTS5_SEGMENT_ROWID(). */ static void fts5DecodeRowid( i64 iRowid, /* Rowid from %_data table */ + int *pbTombstone, /* OUT: Tombstone hash flag */ int *piSegid, /* OUT: Segment id */ int *pbDlidx, /* OUT: Dlidx flag */ int *piHeight, /* OUT: Height */ @@ -239331,13 +242131,16 @@ static void fts5DecodeRowid( iRowid >>= FTS5_DATA_DLI_B; *piSegid = (int)(iRowid & (((i64)1 << FTS5_DATA_ID_B) - 1)); -} -#endif /* SQLITE_TEST */ + iRowid >>= FTS5_DATA_ID_B; -#ifdef SQLITE_TEST + *pbTombstone = (int)(iRowid & 0x0001); +} +#endif /* SQLITE_TEST || SQLITE_FTS5_DEBUG */ + +#if defined(SQLITE_TEST) || defined(SQLITE_FTS5_DEBUG) static void fts5DebugRowid(int *pRc, Fts5Buffer *pBuf, i64 iKey){ - int iSegid, iHeight, iPgno, bDlidx; /* Rowid compenents */ - fts5DecodeRowid(iKey, &iSegid, &bDlidx, &iHeight, &iPgno); + int iSegid, iHeight, iPgno, bDlidx, bTomb; /* Rowid compenents */ + fts5DecodeRowid(iKey, &bTomb, &iSegid, &bDlidx, &iHeight, &iPgno); if( iSegid==0 ){ if( iKey==FTS5_AVERAGES_ROWID ){ @@ -239347,14 +242150,16 @@ static void fts5DebugRowid(int *pRc, Fts5Buffer *pBuf, i64 iKey){ } } else{ - sqlite3Fts5BufferAppendPrintf(pRc, pBuf, "{%ssegid=%d h=%d pgno=%d}", - bDlidx ? "dlidx " : "", iSegid, iHeight, iPgno + sqlite3Fts5BufferAppendPrintf(pRc, pBuf, "{%s%ssegid=%d h=%d pgno=%d}", + bDlidx ? "dlidx " : "", + bTomb ? "tombstone " : "", + iSegid, iHeight, iPgno ); } } -#endif /* SQLITE_TEST */ +#endif /* SQLITE_TEST || SQLITE_FTS5_DEBUG */ -#ifdef SQLITE_TEST +#if defined(SQLITE_TEST) || defined(SQLITE_FTS5_DEBUG) static void fts5DebugStructure( int *pRc, /* IN/OUT: error code */ Fts5Buffer *pBuf, @@ -239369,16 +242174,22 @@ static void fts5DebugStructure( ); for(iSeg=0; iSegnSeg; iSeg++){ Fts5StructureSegment *pSeg = &pLvl->aSeg[iSeg]; - sqlite3Fts5BufferAppendPrintf(pRc, pBuf, " {id=%d leaves=%d..%d}", + sqlite3Fts5BufferAppendPrintf(pRc, pBuf, " {id=%d leaves=%d..%d", pSeg->iSegid, pSeg->pgnoFirst, pSeg->pgnoLast ); + if( pSeg->iOrigin1>0 ){ + sqlite3Fts5BufferAppendPrintf(pRc, pBuf, " origin=%lld..%lld", + pSeg->iOrigin1, pSeg->iOrigin2 + ); + } + sqlite3Fts5BufferAppendPrintf(pRc, pBuf, "}"); } sqlite3Fts5BufferAppendPrintf(pRc, pBuf, "}"); } } -#endif /* SQLITE_TEST */ +#endif /* SQLITE_TEST || SQLITE_FTS5_DEBUG */ -#ifdef SQLITE_TEST +#if defined(SQLITE_TEST) || defined(SQLITE_FTS5_DEBUG) /* ** This is part of the fts5_decode() debugging aid. ** @@ -239403,9 +242214,9 @@ static void fts5DecodeStructure( fts5DebugStructure(pRc, pBuf, p); fts5StructureRelease(p); } -#endif /* SQLITE_TEST */ +#endif /* SQLITE_TEST || SQLITE_FTS5_DEBUG */ -#ifdef SQLITE_TEST +#if defined(SQLITE_TEST) || defined(SQLITE_FTS5_DEBUG) /* ** This is part of the fts5_decode() debugging aid. ** @@ -239428,9 +242239,9 @@ static void fts5DecodeAverages( zSpace = " "; } } -#endif /* SQLITE_TEST */ +#endif /* SQLITE_TEST || SQLITE_FTS5_DEBUG */ -#ifdef SQLITE_TEST +#if defined(SQLITE_TEST) || defined(SQLITE_FTS5_DEBUG) /* ** Buffer (a/n) is assumed to contain a list of serialized varints. Read ** each varint and append its string representation to buffer pBuf. Return @@ -239447,9 +242258,9 @@ static int fts5DecodePoslist(int *pRc, Fts5Buffer *pBuf, const u8 *a, int n){ } return iOff; } -#endif /* SQLITE_TEST */ +#endif /* SQLITE_TEST || SQLITE_FTS5_DEBUG */ -#ifdef SQLITE_TEST +#if defined(SQLITE_TEST) || defined(SQLITE_FTS5_DEBUG) /* ** The start of buffer (a/n) contains the start of a doclist. The doclist ** may or may not finish within the buffer. This function appends a text @@ -239482,9 +242293,9 @@ static int fts5DecodeDoclist(int *pRc, Fts5Buffer *pBuf, const u8 *a, int n){ return iOff; } -#endif /* SQLITE_TEST */ +#endif /* SQLITE_TEST || SQLITE_FTS5_DEBUG */ -#ifdef SQLITE_TEST +#if defined(SQLITE_TEST) || defined(SQLITE_FTS5_DEBUG) /* ** This function is part of the fts5_decode() debugging function. It is ** only ever used with detail=none tables. @@ -239525,9 +242336,9 @@ static void fts5DecodeRowidList( sqlite3Fts5BufferAppendPrintf(pRc, pBuf, " %lld%s", iRowid, zApp); } } -#endif /* SQLITE_TEST */ +#endif /* SQLITE_TEST || SQLITE_FTS5_DEBUG */ -#ifdef SQLITE_TEST +#if defined(SQLITE_TEST) || defined(SQLITE_FTS5_DEBUG) /* ** The implementation of user-defined scalar function fts5_decode(). */ @@ -239538,6 +242349,7 @@ static void fts5DecodeFunction( ){ i64 iRowid; /* Rowid for record being decoded */ int iSegid,iHeight,iPgno,bDlidx;/* Rowid components */ + int bTomb; const u8 *aBlob; int n; /* Record to decode */ u8 *a = 0; Fts5Buffer s; /* Build up text to return here */ @@ -239560,7 +242372,7 @@ static void fts5DecodeFunction( if( a==0 ) goto decode_out; if( n>0 ) memcpy(a, aBlob, n); - fts5DecodeRowid(iRowid, &iSegid, &bDlidx, &iHeight, &iPgno); + fts5DecodeRowid(iRowid, &bTomb, &iSegid, &bDlidx, &iHeight, &iPgno); fts5DebugRowid(&rc, &s, iRowid); if( bDlidx ){ @@ -239579,6 +242391,28 @@ static void fts5DecodeFunction( " %d(%lld)", lvl.iLeafPgno, lvl.iRowid ); } + }else if( bTomb ){ + u32 nElem = fts5GetU32(&a[4]); + int szKey = (aBlob[0]==4 || aBlob[0]==8) ? aBlob[0] : 8; + int nSlot = (n - 8) / szKey; + int ii; + sqlite3Fts5BufferAppendPrintf(&rc, &s, " nElem=%d", (int)nElem); + if( aBlob[1] ){ + sqlite3Fts5BufferAppendPrintf(&rc, &s, " 0"); + } + for(ii=0; iiszLeaf ){ + rc = FTS5_CORRUPT; + }else{ + fts5DecodeRowidList(&rc, &s, &a[iOff], iTermOff-iOff); + } iOff = iTermOff; if( iOffestimatedCost = (double)100; + pIdxInfo->estimatedRows = 100; + pIdxInfo->idxNum = 0; + for(i=0, p=pIdxInfo->aConstraint; inConstraint; i++, p++){ + if( p->usable==0 ) continue; + if( p->op==SQLITE_INDEX_CONSTRAINT_EQ && p->iColumn==11 ){ + rc = SQLITE_OK; + pIdxInfo->aConstraintUsage[i].omit = 1; + pIdxInfo->aConstraintUsage[i].argvIndex = 1; + break; + } + } + return rc; +} + +/* +** This method is the destructor for bytecodevtab objects. +*/ +static int fts5structDisconnectMethod(sqlite3_vtab *pVtab){ + Fts5StructVtab *p = (Fts5StructVtab*)pVtab; + sqlite3_free(p); + return SQLITE_OK; +} + +/* +** Constructor for a new bytecodevtab_cursor object. +*/ +static int fts5structOpenMethod(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCsr){ + int rc = SQLITE_OK; + Fts5StructVcsr *pNew = 0; + + pNew = sqlite3Fts5MallocZero(&rc, sizeof(*pNew)); + *ppCsr = (sqlite3_vtab_cursor*)pNew; + + return SQLITE_OK; +} + +/* +** Destructor for a bytecodevtab_cursor. +*/ +static int fts5structCloseMethod(sqlite3_vtab_cursor *cur){ + Fts5StructVcsr *pCsr = (Fts5StructVcsr*)cur; + fts5StructureRelease(pCsr->pStruct); + sqlite3_free(pCsr); + return SQLITE_OK; +} + + +/* +** Advance a bytecodevtab_cursor to its next row of output. +*/ +static int fts5structNextMethod(sqlite3_vtab_cursor *cur){ + Fts5StructVcsr *pCsr = (Fts5StructVcsr*)cur; + Fts5Structure *p = pCsr->pStruct; + + assert( pCsr->pStruct ); + pCsr->iSeg++; + pCsr->iRowid++; + while( pCsr->iLevelnLevel && pCsr->iSeg>=p->aLevel[pCsr->iLevel].nSeg ){ + pCsr->iLevel++; + pCsr->iSeg = 0; + } + if( pCsr->iLevel>=p->nLevel ){ + fts5StructureRelease(pCsr->pStruct); + pCsr->pStruct = 0; + } + return SQLITE_OK; +} + +/* +** Return TRUE if the cursor has been moved off of the last +** row of output. +*/ +static int fts5structEofMethod(sqlite3_vtab_cursor *cur){ + Fts5StructVcsr *pCsr = (Fts5StructVcsr*)cur; + return pCsr->pStruct==0; +} + +static int fts5structRowidMethod( + sqlite3_vtab_cursor *cur, + sqlite_int64 *piRowid +){ + Fts5StructVcsr *pCsr = (Fts5StructVcsr*)cur; + *piRowid = pCsr->iRowid; + return SQLITE_OK; +} + +/* +** Return values of columns for the row at which the bytecodevtab_cursor +** is currently pointing. +*/ +static int fts5structColumnMethod( + sqlite3_vtab_cursor *cur, /* The cursor */ + sqlite3_context *ctx, /* First argument to sqlite3_result_...() */ + int i /* Which column to return */ +){ + Fts5StructVcsr *pCsr = (Fts5StructVcsr*)cur; + Fts5Structure *p = pCsr->pStruct; + Fts5StructureSegment *pSeg = &p->aLevel[pCsr->iLevel].aSeg[pCsr->iSeg]; + + switch( i ){ + case 0: /* level */ + sqlite3_result_int(ctx, pCsr->iLevel); + break; + case 1: /* segment */ + sqlite3_result_int(ctx, pCsr->iSeg); + break; + case 2: /* merge */ + sqlite3_result_int(ctx, pCsr->iSeg < p->aLevel[pCsr->iLevel].nMerge); + break; + case 3: /* segid */ + sqlite3_result_int(ctx, pSeg->iSegid); + break; + case 4: /* leaf1 */ + sqlite3_result_int(ctx, pSeg->pgnoFirst); + break; + case 5: /* leaf2 */ + sqlite3_result_int(ctx, pSeg->pgnoLast); + break; + case 6: /* origin1 */ + sqlite3_result_int64(ctx, pSeg->iOrigin1); + break; + case 7: /* origin2 */ + sqlite3_result_int64(ctx, pSeg->iOrigin2); + break; + case 8: /* npgtombstone */ + sqlite3_result_int(ctx, pSeg->nPgTombstone); + break; + case 9: /* nentrytombstone */ + sqlite3_result_int64(ctx, pSeg->nEntryTombstone); + break; + case 10: /* nentry */ + sqlite3_result_int64(ctx, pSeg->nEntry); + break; + } + return SQLITE_OK; +} + +/* +** Initialize a cursor. +** +** idxNum==0 means show all subprograms +** idxNum==1 means show only the main bytecode and omit subprograms. +*/ +static int fts5structFilterMethod( + sqlite3_vtab_cursor *pVtabCursor, + int idxNum, const char *idxStr, + int argc, sqlite3_value **argv +){ + Fts5StructVcsr *pCsr = (Fts5StructVcsr *)pVtabCursor; + int rc = SQLITE_OK; + + const u8 *aBlob = 0; + int nBlob = 0; + + assert( argc==1 ); + fts5StructureRelease(pCsr->pStruct); + pCsr->pStruct = 0; + + nBlob = sqlite3_value_bytes(argv[0]); + aBlob = (const u8*)sqlite3_value_blob(argv[0]); + rc = fts5StructureDecode(aBlob, nBlob, 0, &pCsr->pStruct); + if( rc==SQLITE_OK ){ + pCsr->iLevel = 0; + pCsr->iRowid = 0; + pCsr->iSeg = -1; + rc = fts5structNextMethod(pVtabCursor); + } + + return rc; +} + +#endif /* SQLITE_TEST || SQLITE_FTS5_DEBUG */ /* ** This is called as part of registering the FTS5 module with database @@ -239783,7 +242848,7 @@ static void fts5RowidFunction( ** SQLite error code is returned instead. */ static int sqlite3Fts5IndexInit(sqlite3 *db){ -#ifdef SQLITE_TEST +#if defined(SQLITE_TEST) || defined(SQLITE_FTS5_DEBUG) int rc = sqlite3_create_function( db, "fts5_decode", 2, SQLITE_UTF8, 0, fts5DecodeFunction, 0, 0 ); @@ -239800,6 +242865,36 @@ static int sqlite3Fts5IndexInit(sqlite3 *db){ db, "fts5_rowid", -1, SQLITE_UTF8, 0, fts5RowidFunction, 0, 0 ); } + + if( rc==SQLITE_OK ){ + static const sqlite3_module fts5structure_module = { + 0, /* iVersion */ + 0, /* xCreate */ + fts5structConnectMethod, /* xConnect */ + fts5structBestIndexMethod, /* xBestIndex */ + fts5structDisconnectMethod, /* xDisconnect */ + 0, /* xDestroy */ + fts5structOpenMethod, /* xOpen */ + fts5structCloseMethod, /* xClose */ + fts5structFilterMethod, /* xFilter */ + fts5structNextMethod, /* xNext */ + fts5structEofMethod, /* xEof */ + fts5structColumnMethod, /* xColumn */ + fts5structRowidMethod, /* xRowid */ + 0, /* xUpdate */ + 0, /* xBegin */ + 0, /* xSync */ + 0, /* xCommit */ + 0, /* xRollback */ + 0, /* xFindFunction */ + 0, /* xRename */ + 0, /* xSavepoint */ + 0, /* xRelease */ + 0, /* xRollbackTo */ + 0 /* xShadowName */ + }; + rc = sqlite3_create_module(db, "fts5_structure", &fts5structure_module, 0); + } return rc; #else return SQLITE_OK; @@ -241443,7 +244538,6 @@ static int fts5UpdateMethod( int rc = SQLITE_OK; /* Return code */ int bUpdateOrDelete = 0; - /* A transaction must be open when this is called. */ assert( pTab->ts.eState==1 || pTab->ts.eState==2 ); @@ -241472,7 +244566,14 @@ static int fts5UpdateMethod( if( pConfig->eContent!=FTS5_CONTENT_NORMAL && 0==sqlite3_stricmp("delete", z) ){ - rc = fts5SpecialDelete(pTab, apVal); + if( pConfig->bContentlessDelete ){ + fts5SetVtabError(pTab, + "'delete' may not be used with a contentless_delete=1 table" + ); + rc = SQLITE_ERROR; + }else{ + rc = fts5SpecialDelete(pTab, apVal); + } }else{ rc = fts5SpecialInsert(pTab, z, apVal[2 + pConfig->nCol + 1]); } @@ -241489,7 +244590,7 @@ static int fts5UpdateMethod( ** Cases 3 and 4 may violate the rowid constraint. */ int eConflict = SQLITE_ABORT; - if( pConfig->eContent==FTS5_CONTENT_NORMAL ){ + if( pConfig->eContent==FTS5_CONTENT_NORMAL || pConfig->bContentlessDelete ){ eConflict = sqlite3_vtab_on_conflict(pConfig->db); } @@ -241497,8 +244598,12 @@ static int fts5UpdateMethod( assert( nArg!=1 || eType0==SQLITE_INTEGER ); /* Filter out attempts to run UPDATE or DELETE on contentless tables. - ** This is not suported. */ - if( eType0==SQLITE_INTEGER && fts5IsContentless(pTab) ){ + ** This is not suported. Except - DELETE is supported if the CREATE + ** VIRTUAL TABLE statement contained "contentless_delete=1". */ + if( eType0==SQLITE_INTEGER + && pConfig->eContent==FTS5_CONTENT_NONE + && pConfig->bContentlessDelete==0 + ){ pTab->p.base.zErrMsg = sqlite3_mprintf( "cannot %s contentless fts5 table: %s", (nArg>1 ? "UPDATE" : "DELETE from"), pConfig->zName @@ -241585,8 +244690,7 @@ static int fts5SyncMethod(sqlite3_vtab *pVtab){ Fts5FullTable *pTab = (Fts5FullTable*)pVtab; fts5CheckTransactionState(pTab, FTS5_SYNC, 0); pTab->p.pConfig->pzErrmsg = &pTab->p.base.zErrMsg; - fts5TripCursors(pTab); - rc = sqlite3Fts5StorageSync(pTab->pStorage); + rc = sqlite3Fts5FlushToDisk(&pTab->p); pTab->p.pConfig->pzErrmsg = 0; return rc; } @@ -242353,6 +245457,12 @@ static int fts5ColumnMethod( sqlite3_result_value(pCtx, sqlite3_column_value(pCsr->pStmt, iCol+1)); } pConfig->pzErrmsg = 0; + }else if( pConfig->bContentlessDelete && sqlite3_vtab_nochange(pCtx) ){ + char *zErr = sqlite3_mprintf("cannot UPDATE a subset of " + "columns on fts5 contentless-delete table: %s", pConfig->zName + ); + sqlite3_result_error(pCtx, zErr, -1); + sqlite3_free(zErr); } return rc; } @@ -242635,7 +245745,7 @@ static void fts5SourceIdFunc( ){ assert( nArg==0 ); UNUSED_PARAM2(nArg, apUnused); - sqlite3_result_text(pCtx, "fts5: 2023-05-16 12:36:15 831d0fb2836b71c9bc51067c49fee4b8f18047814f2ff22d817d25195cf350b0", -1, SQLITE_TRANSIENT); + sqlite3_result_text(pCtx, "fts5: 2023-08-24 12:36:59 0f80b798b3f4b81a7bb4233c58294edd0f1156f36b6ecf5ab8e83631d468778c", -1, SQLITE_TRANSIENT); } /* @@ -242848,10 +245958,10 @@ static int fts5StorageGetStmt( "INSERT INTO %Q.'%q_content' VALUES(%s)", /* INSERT_CONTENT */ "REPLACE INTO %Q.'%q_content' VALUES(%s)", /* REPLACE_CONTENT */ "DELETE FROM %Q.'%q_content' WHERE id=?", /* DELETE_CONTENT */ - "REPLACE INTO %Q.'%q_docsize' VALUES(?,?)", /* REPLACE_DOCSIZE */ + "REPLACE INTO %Q.'%q_docsize' VALUES(?,?%s)", /* REPLACE_DOCSIZE */ "DELETE FROM %Q.'%q_docsize' WHERE id=?", /* DELETE_DOCSIZE */ - "SELECT sz FROM %Q.'%q_docsize' WHERE id=?", /* LOOKUP_DOCSIZE */ + "SELECT sz%s FROM %Q.'%q_docsize' WHERE id=?", /* LOOKUP_DOCSIZE */ "REPLACE INTO %Q.'%q_config' VALUES(?,?)", /* REPLACE_CONFIG */ "SELECT %s FROM %s AS T", /* SCAN */ @@ -242899,6 +246009,19 @@ static int fts5StorageGetStmt( break; } + case FTS5_STMT_REPLACE_DOCSIZE: + zSql = sqlite3_mprintf(azStmt[eStmt], pC->zDb, pC->zName, + (pC->bContentlessDelete ? ",?" : "") + ); + break; + + case FTS5_STMT_LOOKUP_DOCSIZE: + zSql = sqlite3_mprintf(azStmt[eStmt], + (pC->bContentlessDelete ? ",origin" : ""), + pC->zDb, pC->zName + ); + break; + default: zSql = sqlite3_mprintf(azStmt[eStmt], pC->zDb, pC->zName); break; @@ -243088,9 +246211,11 @@ static int sqlite3Fts5StorageOpen( } if( rc==SQLITE_OK && pConfig->bColumnsize ){ - rc = sqlite3Fts5CreateTable( - pConfig, "docsize", "id INTEGER PRIMARY KEY, sz BLOB", 0, pzErr - ); + const char *zCols = "id INTEGER PRIMARY KEY, sz BLOB"; + if( pConfig->bContentlessDelete ){ + zCols = "id INTEGER PRIMARY KEY, sz BLOB, origin INTEGER"; + } + rc = sqlite3Fts5CreateTable(pConfig, "docsize", zCols, 0, pzErr); } if( rc==SQLITE_OK ){ rc = sqlite3Fts5CreateTable( @@ -243167,7 +246292,7 @@ static int fts5StorageDeleteFromIndex( ){ Fts5Config *pConfig = p->pConfig; sqlite3_stmt *pSeek = 0; /* SELECT to read row iDel from %_data */ - int rc; /* Return code */ + int rc = SQLITE_OK; /* Return code */ int rc2; /* sqlite3_reset() return code */ int iCol; Fts5InsertCtx ctx; @@ -243183,7 +246308,6 @@ static int fts5StorageDeleteFromIndex( ctx.pStorage = p; ctx.iCol = -1; - rc = sqlite3Fts5IndexBeginWrite(p->pIndex, 1, iDel); for(iCol=1; rc==SQLITE_OK && iCol<=pConfig->nCol; iCol++){ if( pConfig->abUnindexed[iCol-1]==0 ){ const char *zText; @@ -243220,6 +246344,37 @@ static int fts5StorageDeleteFromIndex( return rc; } +/* +** This function is called to process a DELETE on a contentless_delete=1 +** table. It adds the tombstone required to delete the entry with rowid +** iDel. If successful, SQLITE_OK is returned. Or, if an error occurs, +** an SQLite error code. +*/ +static int fts5StorageContentlessDelete(Fts5Storage *p, i64 iDel){ + i64 iOrigin = 0; + sqlite3_stmt *pLookup = 0; + int rc = SQLITE_OK; + + assert( p->pConfig->bContentlessDelete ); + assert( p->pConfig->eContent==FTS5_CONTENT_NONE ); + + /* Look up the origin of the document in the %_docsize table. Store + ** this in stack variable iOrigin. */ + rc = fts5StorageGetStmt(p, FTS5_STMT_LOOKUP_DOCSIZE, &pLookup, 0); + if( rc==SQLITE_OK ){ + sqlite3_bind_int64(pLookup, 1, iDel); + if( SQLITE_ROW==sqlite3_step(pLookup) ){ + iOrigin = sqlite3_column_int64(pLookup, 1); + } + rc = sqlite3_reset(pLookup); + } + + if( rc==SQLITE_OK && iOrigin!=0 ){ + rc = sqlite3Fts5IndexContentlessDelete(p->pIndex, iOrigin, iDel); + } + + return rc; +} /* ** Insert a record into the %_docsize table. Specifically, do: @@ -243240,10 +246395,17 @@ static int fts5StorageInsertDocsize( rc = fts5StorageGetStmt(p, FTS5_STMT_REPLACE_DOCSIZE, &pReplace, 0); if( rc==SQLITE_OK ){ sqlite3_bind_int64(pReplace, 1, iRowid); - sqlite3_bind_blob(pReplace, 2, pBuf->p, pBuf->n, SQLITE_STATIC); - sqlite3_step(pReplace); - rc = sqlite3_reset(pReplace); - sqlite3_bind_null(pReplace, 2); + if( p->pConfig->bContentlessDelete ){ + i64 iOrigin = 0; + rc = sqlite3Fts5IndexGetOrigin(p->pIndex, &iOrigin); + sqlite3_bind_int64(pReplace, 3, iOrigin); + } + if( rc==SQLITE_OK ){ + sqlite3_bind_blob(pReplace, 2, pBuf->p, pBuf->n, SQLITE_STATIC); + sqlite3_step(pReplace); + rc = sqlite3_reset(pReplace); + sqlite3_bind_null(pReplace, 2); + } } } return rc; @@ -243307,7 +246469,15 @@ static int sqlite3Fts5StorageDelete(Fts5Storage *p, i64 iDel, sqlite3_value **ap /* Delete the index records */ if( rc==SQLITE_OK ){ - rc = fts5StorageDeleteFromIndex(p, iDel, apVal); + rc = sqlite3Fts5IndexBeginWrite(p->pIndex, 1, iDel); + } + + if( rc==SQLITE_OK ){ + if( p->pConfig->bContentlessDelete ){ + rc = fts5StorageContentlessDelete(p, iDel); + }else{ + rc = fts5StorageDeleteFromIndex(p, iDel, apVal); + } } /* Delete the %_docsize record */ diff --git a/src/3rdparty/sqlite/sqlite3.h b/src/3rdparty/sqlite/sqlite3.h index 48effe20216..ec451a5ca3e 100644 --- a/src/3rdparty/sqlite/sqlite3.h +++ b/src/3rdparty/sqlite/sqlite3.h @@ -146,9 +146,9 @@ extern "C" { ** [sqlite3_libversion_number()], [sqlite3_sourceid()], ** [sqlite_version()] and [sqlite_source_id()]. */ -#define SQLITE_VERSION "3.42.0" -#define SQLITE_VERSION_NUMBER 3042000 -#define SQLITE_SOURCE_ID "2023-05-16 12:36:15 831d0fb2836b71c9bc51067c49fee4b8f18047814f2ff22d817d25195cf350b0" +#define SQLITE_VERSION "3.43.0" +#define SQLITE_VERSION_NUMBER 3043000 +#define SQLITE_SOURCE_ID "2023-08-24 12:36:59 0f80b798b3f4b81a7bb4233c58294edd0f1156f36b6ecf5ab8e83631d468778c" /* ** CAPI3REF: Run-Time Library Version Numbers @@ -528,6 +528,7 @@ SQLITE_API int sqlite3_exec( #define SQLITE_IOERR_ROLLBACK_ATOMIC (SQLITE_IOERR | (31<<8)) #define SQLITE_IOERR_DATA (SQLITE_IOERR | (32<<8)) #define SQLITE_IOERR_CORRUPTFS (SQLITE_IOERR | (33<<8)) +#define SQLITE_IOERR_IN_PAGE (SQLITE_IOERR | (34<<8)) #define SQLITE_LOCKED_SHAREDCACHE (SQLITE_LOCKED | (1<<8)) #define SQLITE_LOCKED_VTAB (SQLITE_LOCKED | (2<<8)) #define SQLITE_BUSY_RECOVERY (SQLITE_BUSY | (1<<8)) @@ -1190,7 +1191,7 @@ struct sqlite3_io_methods { ** by clients within the current process, only within other processes. ** **
    4. [[SQLITE_FCNTL_CKSM_FILE]] -** The [SQLITE_FCNTL_CKSM_FILE] opcode is for use interally by the +** The [SQLITE_FCNTL_CKSM_FILE] opcode is for use internally by the ** [checksum VFS shim] only. ** **
    5. [[SQLITE_FCNTL_RESET_CACHE]] @@ -2454,7 +2455,7 @@ struct sqlite3_mem_methods { ** the [VACUUM] command will fail with an obscure error when attempting to ** process a table with generated columns and a descending index. This is ** not considered a bug since SQLite versions 3.3.0 and earlier do not support -** either generated columns or decending indexes. +** either generated columns or descending indexes. ** ** ** [[SQLITE_DBCONFIG_STMT_SCANSTATUS]] @@ -2735,6 +2736,7 @@ SQLITE_API sqlite3_int64 sqlite3_total_changes64(sqlite3*); ** ** ^The [sqlite3_is_interrupted(D)] interface can be used to determine whether ** or not an interrupt is currently in effect for [database connection] D. +** It returns 1 if an interrupt is currently in effect, or 0 otherwise. */ SQLITE_API void sqlite3_interrupt(sqlite3*); SQLITE_API int sqlite3_is_interrupted(sqlite3*); @@ -3388,8 +3390,10 @@ SQLITE_API SQLITE_DEPRECATED void *sqlite3_profile(sqlite3*, ** M argument should be the bitwise OR-ed combination of ** zero or more [SQLITE_TRACE] constants. ** -** ^Each call to either sqlite3_trace() or sqlite3_trace_v2() overrides -** (cancels) any prior calls to sqlite3_trace() or sqlite3_trace_v2(). +** ^Each call to either sqlite3_trace(D,X,P) or sqlite3_trace_v2(D,M,X,P) +** overrides (cancels) all prior calls to sqlite3_trace(D,X,P) or +** sqlite3_trace_v2(D,M,X,P) for the [database connection] D. Each +** database connection may have at most one trace callback. ** ** ^The X callback is invoked whenever any of the events identified by ** mask M occur. ^The integer return value from the callback is currently @@ -3758,7 +3762,7 @@ SQLITE_API int sqlite3_open_v2( ** as F) must be one of: **
        **
      • A database filename pointer created by the SQLite core and -** passed into the xOpen() method of a VFS implemention, or +** passed into the xOpen() method of a VFS implementation, or **
      • A filename obtained from [sqlite3_db_filename()], or **
      • A new filename constructed using [sqlite3_create_filename()]. **
      @@ -3871,7 +3875,7 @@ SQLITE_API sqlite3_file *sqlite3_database_file_object(const char*); /* ** CAPI3REF: Create and Destroy VFS Filenames ** -** These interfces are provided for use by [VFS shim] implementations and +** These interfaces are provided for use by [VFS shim] implementations and ** are not useful outside of that context. ** ** The sqlite3_create_filename(D,J,W,N,P) allocates memory to hold a version of @@ -4418,6 +4422,41 @@ SQLITE_API int sqlite3_stmt_readonly(sqlite3_stmt *pStmt); */ SQLITE_API int sqlite3_stmt_isexplain(sqlite3_stmt *pStmt); +/* +** CAPI3REF: Change The EXPLAIN Setting For A Prepared Statement +** METHOD: sqlite3_stmt +** +** The sqlite3_stmt_explain(S,E) interface changes the EXPLAIN +** setting for [prepared statement] S. If E is zero, then S becomes +** a normal prepared statement. If E is 1, then S behaves as if +** its SQL text began with "[EXPLAIN]". If E is 2, then S behaves as if +** its SQL text began with "[EXPLAIN QUERY PLAN]". +** +** Calling sqlite3_stmt_explain(S,E) might cause S to be reprepared. +** SQLite tries to avoid a reprepare, but a reprepare might be necessary +** on the first transition into EXPLAIN or EXPLAIN QUERY PLAN mode. +** +** Because of the potential need to reprepare, a call to +** sqlite3_stmt_explain(S,E) will fail with SQLITE_ERROR if S cannot be +** reprepared because it was created using [sqlite3_prepare()] instead of +** the newer [sqlite3_prepare_v2()] or [sqlite3_prepare_v3()] interfaces and +** hence has no saved SQL text with which to reprepare. +** +** Changing the explain setting for a prepared statement does not change +** the original SQL text for the statement. Hence, if the SQL text originally +** began with EXPLAIN or EXPLAIN QUERY PLAN, but sqlite3_stmt_explain(S,0) +** is called to convert the statement into an ordinary statement, the EXPLAIN +** or EXPLAIN QUERY PLAN keywords will still appear in the sqlite3_sql(S) +** output, even though the statement now acts like a normal SQL statement. +** +** This routine returns SQLITE_OK if the explain mode is successfully +** changed, or an error code if the explain mode could not be changed. +** The explain mode cannot be changed while a statement is active. +** Hence, it is good practice to call [sqlite3_reset(S)] +** immediately prior to calling sqlite3_stmt_explain(S,E). +*/ +SQLITE_API int sqlite3_stmt_explain(sqlite3_stmt *pStmt, int eMode); + /* ** CAPI3REF: Determine If A Prepared Statement Has Been Reset ** METHOD: sqlite3_stmt @@ -4581,7 +4620,7 @@ typedef struct sqlite3_context sqlite3_context; ** with it may be passed. ^It is called to dispose of the BLOB or string even ** if the call to the bind API fails, except the destructor is not called if ** the third parameter is a NULL pointer or the fourth parameter is negative. -** ^ (2) The special constant, [SQLITE_STATIC], may be passsed to indicate that +** ^ (2) The special constant, [SQLITE_STATIC], may be passed to indicate that ** the application remains responsible for disposing of the object. ^In this ** case, the object and the provided pointer to it must remain valid until ** either the prepared statement is finalized or the same SQL parameter is @@ -5260,14 +5299,26 @@ SQLITE_API int sqlite3_finalize(sqlite3_stmt *pStmt); ** ^The [sqlite3_reset(S)] interface resets the [prepared statement] S ** back to the beginning of its program. ** -** ^If the most recent call to [sqlite3_step(S)] for the -** [prepared statement] S returned [SQLITE_ROW] or [SQLITE_DONE], -** or if [sqlite3_step(S)] has never before been called on S, -** then [sqlite3_reset(S)] returns [SQLITE_OK]. +** ^The return code from [sqlite3_reset(S)] indicates whether or not +** the previous evaluation of prepared statement S completed successfully. +** ^If [sqlite3_step(S)] has never before been called on S or if +** [sqlite3_step(S)] has not been called since the previous call +** to [sqlite3_reset(S)], then [sqlite3_reset(S)] will return +** [SQLITE_OK]. ** ** ^If the most recent call to [sqlite3_step(S)] for the ** [prepared statement] S indicated an error, then ** [sqlite3_reset(S)] returns an appropriate [error code]. +** ^The [sqlite3_reset(S)] interface might also return an [error code] +** if there were no prior errors but the process of resetting +** the prepared statement caused a new error. ^For example, if an +** [INSERT] statement with a [RETURNING] clause is only stepped one time, +** that one call to [sqlite3_step(S)] might return SQLITE_ROW but +** the overall statement might still fail and the [sqlite3_reset(S)] call +** might return SQLITE_BUSY if locking constraints prevent the +** database change from committing. Therefore, it is important that +** applications check the return code from [sqlite3_reset(S)] even if +** no prior call to [sqlite3_step(S)] indicated a problem. ** ** ^The [sqlite3_reset(S)] interface does not change the values ** of any [sqlite3_bind_blob|bindings] on the [prepared statement] S. @@ -5484,7 +5535,7 @@ SQLITE_API int sqlite3_create_window_function( ** [application-defined SQL function] ** that has side-effects or that could potentially leak sensitive information. ** This will prevent attacks in which an application is tricked -** into using a database file that has had its schema surreptiously +** into using a database file that has had its schema surreptitiously ** modified to invoke the application-defined function in ways that are ** harmful. **

      @@ -8161,7 +8212,8 @@ SQLITE_API int sqlite3_test_control(int op, ...); #define SQLITE_TESTCTRL_TRACEFLAGS 31 #define SQLITE_TESTCTRL_TUNE 32 #define SQLITE_TESTCTRL_LOGEST 33 -#define SQLITE_TESTCTRL_LAST 33 /* Largest TESTCTRL */ +#define SQLITE_TESTCTRL_USELONGDOUBLE 34 +#define SQLITE_TESTCTRL_LAST 34 /* Largest TESTCTRL */ /* ** CAPI3REF: SQL Keyword Checking @@ -9193,8 +9245,8 @@ SQLITE_API int sqlite3_backup_pagecount(sqlite3_backup *p); ** blocked connection already has a registered unlock-notify callback, ** then the new callback replaces the old.)^ ^If sqlite3_unlock_notify() is ** called with a NULL pointer as its second argument, then any existing -** unlock-notify callback is canceled. ^The blocked connections -** unlock-notify callback may also be canceled by closing the blocked +** unlock-notify callback is cancelled. ^The blocked connections +** unlock-notify callback may also be cancelled by closing the blocked ** connection using [sqlite3_close()]. ** ** The unlock-notify callback is not reentrant. If an application invokes @@ -9617,7 +9669,7 @@ SQLITE_API int sqlite3_vtab_config(sqlite3*, int op, ...); ** [[SQLITE_VTAB_DIRECTONLY]]

      SQLITE_VTAB_DIRECTONLY
      **
      Calls of the form ** [sqlite3_vtab_config](db,SQLITE_VTAB_DIRECTONLY) from within the -** the [xConnect] or [xCreate] methods of a [virtual table] implmentation +** the [xConnect] or [xCreate] methods of a [virtual table] implementation ** prohibits that virtual table from being used from within triggers and ** views. **
      @@ -9807,7 +9859,7 @@ SQLITE_API int sqlite3_vtab_distinct(sqlite3_index_info*); ** communicated to the xBestIndex method as a ** [SQLITE_INDEX_CONSTRAINT_EQ] constraint.)^ If xBestIndex wants to use ** this constraint, it must set the corresponding -** aConstraintUsage[].argvIndex to a postive integer. ^(Then, under +** aConstraintUsage[].argvIndex to a positive integer. ^(Then, under ** the usual mode of handling IN operators, SQLite generates [bytecode] ** that invokes the [xFilter|xFilter() method] once for each value ** on the right-hand side of the IN operator.)^ Thus the virtual table @@ -10236,7 +10288,7 @@ SQLITE_API int sqlite3_db_cacheflush(sqlite3*); ** When the [sqlite3_blob_write()] API is used to update a blob column, ** the pre-update hook is invoked with SQLITE_DELETE. This is because the ** in this case the new values are not available. In this case, when a -** callback made with op==SQLITE_DELETE is actuall a write using the +** callback made with op==SQLITE_DELETE is actually a write using the ** sqlite3_blob_write() API, the [sqlite3_preupdate_blobwrite()] returns ** the index of the column being written. In other cases, where the ** pre-update hook is being invoked for some other reason, including a @@ -12754,7 +12806,7 @@ struct Fts5PhraseIter { ** See xPhraseFirstColumn above. */ struct Fts5ExtensionApi { - int iVersion; /* Currently always set to 3 */ + int iVersion; /* Currently always set to 2 */ void *(*xUserData)(Fts5Context*); @@ -12983,8 +13035,8 @@ struct Fts5ExtensionApi { ** as separate queries of the FTS index are required for each synonym. ** ** When using methods (2) or (3), it is important that the tokenizer only -** provide synonyms when tokenizing document text (method (2)) or query -** text (method (3)), not both. Doing so will not cause any errors, but is +** provide synonyms when tokenizing document text (method (3)) or query +** text (method (2)), not both. Doing so will not cause any errors, but is ** inefficient. */ typedef struct Fts5Tokenizer Fts5Tokenizer; @@ -13032,7 +13084,7 @@ struct fts5_api { int (*xCreateTokenizer)( fts5_api *pApi, const char *zName, - void *pContext, + void *pUserData, fts5_tokenizer *pTokenizer, void (*xDestroy)(void*) ); @@ -13041,7 +13093,7 @@ struct fts5_api { int (*xFindTokenizer)( fts5_api *pApi, const char *zName, - void **ppContext, + void **ppUserData, fts5_tokenizer *pTokenizer ); @@ -13049,7 +13101,7 @@ struct fts5_api { int (*xCreateFunction)( fts5_api *pApi, const char *zName, - void *pContext, + void *pUserData, fts5_extension_function xFunction, void (*xDestroy)(void*) ); From 16f7681904db9ce0723f36d93bd77edb5ebaf835 Mon Sep 17 00:00:00 2001 From: Christian Ehrlicher Date: Sun, 20 Aug 2023 20:01:54 +0200 Subject: [PATCH 121/151] QTextFormat: documentation fix MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The QTextFormat description refers to setDirection() but this function does not exist. The correct function name is setLayoutDirection() even in Qt4. Change-Id: I2d1f49fba558874b5875d8d93ef61d6208134609 Reviewed-by: Jan Arve Sæther Reviewed-by: Kai Köhne Reviewed-by: Shawn Rutledge (cherry picked from commit fd96e11bb1200902ff7ec2bbe6f3903b2d96bdd8) Reviewed-by: Qt Cherry-pick Bot --- src/gui/text/qtextformat.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/text/qtextformat.cpp b/src/gui/text/qtextformat.cpp index 9ac2aa364a0..becb0eda82e 100644 --- a/src/gui/text/qtextformat.cpp +++ b/src/gui/text/qtextformat.cpp @@ -2123,7 +2123,7 @@ QFont QTextCharFormat::font() const associated QTextBlockFormat that specifies its characteristics. To cater for left-to-right and right-to-left languages you can set - a block's direction with setDirection(). Paragraph alignment is + a block's direction with setLayoutDirection(). Paragraph alignment is set with setAlignment(). Margins are controlled by setTopMargin(), setBottomMargin(), setLeftMargin(), setRightMargin(). Overall indentation is set with setIndent(), the indentation of the first From d705543c2099e6cd690b6d8471a2250117c16d65 Mon Sep 17 00:00:00 2001 From: Assam Boudjelthia Date: Tue, 29 Aug 2023 10:04:29 +0300 Subject: [PATCH 122/151] Android: fix handling of tree content uri with sub-document Check for the index of last '/' from the non-encoded path. Amends ea75e34d6968bb59624874411e793c95b26d0dbe. Change-Id: I3ef5d454a46c711a85fe7ef01ea9d3d93a2d574f Reviewed-by: Ville Voutilainen (cherry picked from commit 4721721f6005c90cb1760b0c6e074468aa73512f) --- src/plugins/platforms/android/androidcontentfileengine.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/platforms/android/androidcontentfileengine.cpp b/src/plugins/platforms/android/androidcontentfileengine.cpp index 728ecc49003..a6b5944dea1 100644 --- a/src/plugins/platforms/android/androidcontentfileengine.cpp +++ b/src/plugins/platforms/android/androidcontentfileengine.cpp @@ -635,7 +635,7 @@ DocumentFilePtr DocumentFile::parseFromAnyUri(const QString &fileName) const int treeIndex = encodedUri.indexOf(treeType); const int documentIndex = encodedUri.indexOf(documentType); - const int index = encodedUri.lastIndexOf(QUrl::toPercentEncoding(QLatin1String("/"))); + const int index = fileName.lastIndexOf(QLatin1Char('/')); if (index <= treeIndex + treeType.size() || index <= documentIndex + documentType.size()) return fromTreeUri(uri); From 43148c8a55df84e1bdadd959d8a8490b2a4f151b Mon Sep 17 00:00:00 2001 From: Assam Boudjelthia Date: Tue, 29 Aug 2023 10:34:53 +0300 Subject: [PATCH 123/151] Image Gestures Example: use QFileInfo for images file names The example keeps around image file names only and append them to the selected dir path, that works fine for file scheme files, but for Android with content scheme files, that doesn't work as good because usually the paths are returned by a provider and managing them manually like appending a file name to a directory (tree) path might not work. This patch retrieves QFileInfo objects and use the absolute file paths to open any image. Fixes: QTBUG-116181 Change-Id: I9911a181d92ba0452500398cbe052b9583bd79a0 Reviewed-by: Friedemann Kleint Reviewed-by: Shawn Rutledge (cherry picked from commit 381612f7944b202c8b1428f0cc9d1af72f5f7647) Reviewed-by: Qt Cherry-pick Bot --- .../gestures/imagegestures/imagewidget.cpp | 22 +++++++++++++------ .../gestures/imagegestures/imagewidget.h | 5 +++-- 2 files changed, 18 insertions(+), 9 deletions(-) diff --git a/examples/widgets/gestures/imagegestures/imagewidget.cpp b/examples/widgets/gestures/imagegestures/imagewidget.cpp index 072ec2b2161..150c7bebc69 100644 --- a/examples/widgets/gestures/imagegestures/imagewidget.cpp +++ b/examples/widgets/gestures/imagegestures/imagewidget.cpp @@ -196,15 +196,23 @@ void ImageWidget::openDirectory(const QString &path) this->path = path; QDir dir(path); const QStringList nameFilters{"*.jpg", "*.png"}; - files = dir.entryList(nameFilters, QDir::Files|QDir::Readable, QDir::Name); + files = dir.entryInfoList(nameFilters, QDir::Files|QDir::Readable, QDir::Name); position = 0; goToImage(0); update(); } -QImage ImageWidget::loadImage(const QString &fileName) const +/* + With Android's content scheme paths, it might not be possible to simply + append a file name to the chosen directory path to be able to open the image, + because usually paths are returned by an Android file provider and handling those + paths manually is not guaranteed to work. For that reason, it's better to keep + around QFileInfo objects and use absoluteFilePath(). +*/ +QImage ImageWidget::loadImage(const QFileInfo &fileInfo) const { + const QString fileName = fileInfo.absoluteFilePath(); QImageReader reader(fileName); reader.setAutoTransform(true); qCDebug(lcExample) << "loading" << QDir::toNativeSeparators(fileName) << position << '/' << files.size(); @@ -234,7 +242,7 @@ void ImageWidget::goNextImage() prevImage = currentImage; currentImage = nextImage; if (position+1 < files.size()) - nextImage = loadImage(path + QLatin1Char('/') + files.at(position+1)); + nextImage = loadImage(files.at(position + 1)); else nextImage = QImage(); } @@ -251,7 +259,7 @@ void ImageWidget::goPrevImage() nextImage = currentImage; currentImage = prevImage; if (position > 0) - prevImage = loadImage(path + QLatin1Char('/') + files.at(position-1)); + prevImage = loadImage(files.at(position - 1)); else prevImage = QImage(); } @@ -281,12 +289,12 @@ void ImageWidget::goToImage(int index) position = index; if (index > 0) - prevImage = loadImage(path + QLatin1Char('/') + files.at(position-1)); + prevImage = loadImage(files.at(position - 1)); else prevImage = QImage(); - currentImage = loadImage(path + QLatin1Char('/') + files.at(position)); + currentImage = loadImage(files.at(position)); if (position+1 < files.size()) - nextImage = loadImage(path + QLatin1Char('/') + files.at(position+1)); + nextImage = loadImage(files.at(position + 1)); else nextImage = QImage(); update(); diff --git a/examples/widgets/gestures/imagegestures/imagewidget.h b/examples/widgets/gestures/imagegestures/imagewidget.h index f9b5d989e97..140584671c9 100644 --- a/examples/widgets/gestures/imagegestures/imagewidget.h +++ b/examples/widgets/gestures/imagegestures/imagewidget.h @@ -51,6 +51,7 @@ #ifndef IMAGEWIDGET_H #define IMAGEWIDGET_H +#include #include #include #include @@ -87,14 +88,14 @@ private: void swipeTriggered(QSwipeGesture*); //! [class definition begin] - QImage loadImage(const QString &fileName) const; + QImage loadImage(const QFileInfo &fileInfo) const; void loadImage(); void goNextImage(); void goPrevImage(); void goToImage(int index); QString path; - QStringList files; + QFileInfoList files; int position; QImage prevImage, nextImage; From 4c1b9ee5b07da7c55f5d96d5fd9bc2026a7ae7ec Mon Sep 17 00:00:00 2001 From: Ilya Fedin Date: Sat, 10 Sep 2022 00:22:41 +0400 Subject: [PATCH 124/151] FileChooser portal: set current_file only when file already exists According to xdg-desktop-portal documentation, current_file should be set only when such a file already exists and xdg-desktop-portal-gnome enforces this by being totally broken when current_file is set to a non-existent path Change-Id: Ie3c80a7c6fd0cf23eea88ddec2149f5904c63394 Reviewed-by: Thiago Macieira (cherry picked from commit 7927b05b2fed0d6004435fcb48954f609de288ca) Reviewed-by: Liang Qi --- .../xdgdesktopportal/qxdgdesktopportalfiledialog.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/plugins/platformthemes/xdgdesktopportal/qxdgdesktopportalfiledialog.cpp b/src/plugins/platformthemes/xdgdesktopportal/qxdgdesktopportalfiledialog.cpp index 741351e3f3e..08aee14b6ef 100644 --- a/src/plugins/platformthemes/xdgdesktopportal/qxdgdesktopportalfiledialog.cpp +++ b/src/plugins/platformthemes/xdgdesktopportal/qxdgdesktopportalfiledialog.cpp @@ -202,9 +202,12 @@ void QXdgDesktopPortalFileDialog::openPortal() if (!d->selectedFiles.isEmpty()) { // current_file for the file to be pre-selected, current_name for the file name to be pre-filled - // current_file accepts absolute path while current_name accepts just file name - options.insert(QLatin1String("current_file"), QFile::encodeName(d->selectedFiles.first()).append('\0')); - options.insert(QLatin1String("current_name"), QFileInfo(d->selectedFiles.first()).fileName()); + // current_file accepts absolute path and requires the file to exist + // while current_name accepts just file name + QFileInfo selectedFileInfo(d->selectedFiles.first()); + if (selectedFileInfo.exists()) + options.insert(QLatin1String("current_file"), QFile::encodeName(d->selectedFiles.first()).append('\0')); + options.insert(QLatin1String("current_name"), selectedFileInfo.fileName()); } } From 09ede199597db386660abe5c66c1628c0e394ceb Mon Sep 17 00:00:00 2001 From: Axel Spoerl Date: Sun, 13 Aug 2023 11:39:01 +0200 Subject: [PATCH 125/151] QAndroidPlatformInputContext: send composition text and cursor jointly MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit QAndroidPlatformInputContext::focusObjectStopComposing() sends an input event for each character newly added by the Android virtual keyboard. It then sends a second input event to notify that the cursor has advanced to the position after the new character. The implicit assumption is, that the receiver of the input event does not change the text. If e.g. QLineEdit::setText() is called in the QLineEdit::textEdited slot, the text does change. If the change implies a cursor change, QLineEdit notifies the platform input context about it. However, by sending the second input event, QAndroidPlatformContent returns the cursor back to the position after the last character added by the virtual keyboard. This patch joins the composed text and the cursor position into one single input method event. A new cursor position, set by the receiver of the input method event, is no longer overridden. The patch adds test functionality to tst_QLineEdit::setText(). Fixes: QTBUG-115756 Change-Id: I85ffac5d6bab93ccb144be0f5b8083258a270550 Reviewed-by: Tor Arne Vestbø (cherry picked from commit be3b9b2ab12f664c196d649e8c4247d70805d667) Reviewed-by: Qt CI Bot --- .../android/qandroidinputcontext.cpp | 22 ++++------ .../widgets/qlineedit/tst_qlineedit.cpp | 40 ++++++++++++++++--- 2 files changed, 42 insertions(+), 20 deletions(-) diff --git a/src/plugins/platforms/android/qandroidinputcontext.cpp b/src/plugins/platforms/android/qandroidinputcontext.cpp index bc594d7e154..a656246d287 100644 --- a/src/plugins/platforms/android/qandroidinputcontext.cpp +++ b/src/plugins/platforms/android/qandroidinputcontext.cpp @@ -1202,21 +1202,13 @@ bool QAndroidInputContext::focusObjectStopComposing() m_composingCursor = -1; - { - // commit the composing test - QList attributes; - QInputMethodEvent event(QString(), attributes); - event.setCommitString(m_composingText); - sendInputMethodEvent(&event); - } - { - // Moving Qt's cursor to where the preedit cursor used to be - QList attributes; - attributes.append( - QInputMethodEvent::Attribute(QInputMethodEvent::Selection, localCursorPos, 0)); - QInputMethodEvent event(QString(), attributes); - sendInputMethodEvent(&event); - } + // commit composing text and cursor position + QList attributes; + attributes.append( + QInputMethodEvent::Attribute(QInputMethodEvent::Selection, localCursorPos, 0)); + QInputMethodEvent event(QString(), attributes); + event.setCommitString(m_composingText); + sendInputMethodEvent(&event); return true; } diff --git a/tests/auto/widgets/widgets/qlineedit/tst_qlineedit.cpp b/tests/auto/widgets/widgets/qlineedit/tst_qlineedit.cpp index 6799de6ae58..db05c8fde1a 100644 --- a/tests/auto/widgets/widgets/qlineedit/tst_qlineedit.cpp +++ b/tests/auto/widgets/widgets/qlineedit/tst_qlineedit.cpp @@ -1611,14 +1611,44 @@ void tst_QLineEdit::textMask() QCOMPARE( testWidget->text(), insertString ); } +class LineEditChangingText : public QLineEdit +{ + Q_OBJECT + +public: + LineEditChangingText(QWidget *parent) : QLineEdit(parent) + { + connect(this, &QLineEdit::textEdited, this, &LineEditChangingText::onTextEdited); + } + +public slots: + void onTextEdited(const QString &text) + { + if (text.length() == 3) + setText(text + "-"); + } +}; + void tst_QLineEdit::setText() { QLineEdit *testWidget = ensureTestWidget(); - QSignalSpy editedSpy(testWidget, SIGNAL(textEdited(QString))); - QSignalSpy changedSpy(testWidget, SIGNAL(textChanged(QString))); - testWidget->setText("hello"); - QCOMPARE(editedSpy.count(), 0); - QCOMPARE(changedSpy.value(0).value(0).toString(), QString("hello")); + { + QSignalSpy editedSpy(testWidget, &QLineEdit::textEdited); + QSignalSpy changedSpy(testWidget, &QLineEdit::textChanged); + testWidget->setText("hello"); + QCOMPARE(editedSpy.size(), 0); + QCOMPARE(changedSpy.value(0).value(0).toString(), QString("hello")); + } + + QTestEventList keys; + keys.addKeyClick(Qt::Key_A); + keys.addKeyClick(Qt::Key_B); + keys.addKeyClick(Qt::Key_C); + + LineEditChangingText lineEdit(nullptr); + keys.simulate(&lineEdit); + QCOMPARE(lineEdit.text(), "abc-"); + QCOMPARE(lineEdit.cursorPosition(), 4); } void tst_QLineEdit::displayText_data() From 061a83afce9b67bdda70a644be167cb96774cf7b Mon Sep 17 00:00:00 2001 From: Volker Hilsheimer Date: Wed, 30 Aug 2023 16:45:58 +0200 Subject: [PATCH 126/151] QPrintDialog on macOS: Don't crash when parent is not a window MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The test case is an incomplete version of the test that will be added to verify the fix for the referenced bug report. The test crashes already when showing the dialog without this fix. Task-number: QTBUG-116277 Change-Id: I969a723157f6453b78bafae5cb24a6b37b1eea50 Reviewed-by: Tor Arne Vestbø (cherry picked from commit e73f35d9c63378ed26e33f488a3ee5bb0745e9d5) Reviewed-by: Qt Cherry-pick Bot --- src/printsupport/dialogs/qprintdialog_mac.mm | 5 +++-- .../tst_qabstractprintdialog.cpp | 16 ++++++++++++++++ 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/src/printsupport/dialogs/qprintdialog_mac.mm b/src/printsupport/dialogs/qprintdialog_mac.mm index c88d5a7bd1f..64bbfed8d8a 100644 --- a/src/printsupport/dialogs/qprintdialog_mac.mm +++ b/src/printsupport/dialogs/qprintdialog_mac.mm @@ -272,8 +272,8 @@ void QPrintDialogPrivate::openCocoaPrintPanel(Qt::WindowModality modality) int rval = [printPanel runModalWithPrintInfo:printInfo]; [delegate printPanelDidEnd:printPanel returnCode:rval contextInfo:q]; } else { - Q_ASSERT(q->parentWidget()); - QWindow *parentWindow = q->parentWidget()->windowHandle(); + Q_ASSERT(q->window()); + QWindow *parentWindow = q->window()->windowHandle(); NSWindow *window = static_cast(qApp->platformNativeInterface()->nativeResourceForWindow("nswindow", parentWindow)); [printPanel beginSheetWithPrintInfo:printInfo modalForWindow:window @@ -305,6 +305,7 @@ QPrintDialog::QPrintDialog(QWidget *parent) QPrintDialog::~QPrintDialog() { + hide(); } int QPrintDialog::exec() diff --git a/tests/auto/printsupport/dialogs/qabstractprintdialog/tst_qabstractprintdialog.cpp b/tests/auto/printsupport/dialogs/qabstractprintdialog/tst_qabstractprintdialog.cpp index a52d7fbaf3a..1ee14253f6c 100644 --- a/tests/auto/printsupport/dialogs/qabstractprintdialog/tst_qabstractprintdialog.cpp +++ b/tests/auto/printsupport/dialogs/qabstractprintdialog/tst_qabstractprintdialog.cpp @@ -49,6 +49,8 @@ private slots: void getSetCheck(); void setMinMax(); void setFromTo(); + + void hideNativeByDestruction(); #endif }; @@ -160,6 +162,20 @@ void tst_QAbstractPrintDialog::setFromTo() QCOMPARE(obj1.maxPage(), 50); } +void tst_QAbstractPrintDialog::hideNativeByDestruction() +{ +#ifdef Q_OS_WINDOWS + QSKIP("This test fails on windows, the QPrintDialog::setVisible implementation blocks"); +#endif + + QWidget window; + QWidget *child = new QWidget(&window); + QPointer dialog = new QPrintDialog(child); + window.show(); + QVERIFY(QTest::qWaitForWindowActive(&window)); + dialog->open(); +} + #endif QTEST_MAIN(tst_QAbstractPrintDialog) From 78f62897188a9d9c42efb7f744dd6669cf71cb57 Mon Sep 17 00:00:00 2001 From: Liang Qi Date: Tue, 5 Sep 2023 11:49:29 +0200 Subject: [PATCH 127/151] widget: set WA_X11NetWmWindowType* after xcb window was created This amends 17d68c4fc371c32bd58d0a94ac63f0170edaf29e. Fixes: QTBUG-116696 Task-number: QTBUG-39887 Change-Id: Idf385bcbeb630ddfc51b39b2af35da3ab94b07c0 Reviewed-by: Axel Spoerl Reviewed-by: Qt CI Bot (cherry picked from commit 29b076d6143f8a4aede72c176efcc40e5b7d701e) Reviewed-by: Qt Cherry-pick Bot --- src/widgets/kernel/qwidget.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/widgets/kernel/qwidget.cpp b/src/widgets/kernel/qwidget.cpp index c24022bce81..91a31b7e673 100644 --- a/src/widgets/kernel/qwidget.cpp +++ b/src/widgets/kernel/qwidget.cpp @@ -1269,7 +1269,6 @@ void QWidgetPrivate::create() win->setProperty("_q_showWithoutActivating", QVariant(true)); if (q->testAttribute(Qt::WA_MacAlwaysShowToolWindow)) win->setProperty("_q_macAlwaysShowToolWindow", QVariant(true)); - setNetWmWindowTypes(true); // do nothing if none of WA_X11NetWmWindowType* is set win->setFlags(flags); fixPosIncludesFrame(); if (q->testAttribute(Qt::WA_Moved) @@ -1345,6 +1344,7 @@ void QWidgetPrivate::create() Q_ASSERT(id != WId(0)); setWinId(id); } + setNetWmWindowTypes(true); // do nothing if none of WA_X11NetWmWindowType* is set // Check children and create windows for them if necessary q_createNativeChildrenAndSetParent(q); From 28534332e6ed0b929725a4c0a227940e0afc478a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kai=20K=C3=B6hne?= Date: Mon, 4 Sep 2023 16:41:51 +0200 Subject: [PATCH 128/151] Mark freetype as GPL-2.0-only GPL-2.0 SPDX identifier is deprecated. Use the more explicit GPL-2.0-only instead. Also, in SPDX expressions AND and OR need to be all uppercase. Change-Id: I0875cf3b9b2020f69e3318d5ff314988a3992409 Reviewed-by: Joerg Bornemann (cherry picked from commit 0b3b1ab26c126701c8ac317d94d80858f0bb2ec7) Reviewed-by: Qt Cherry-pick Bot --- src/3rdparty/freetype/qt_attribution.json | 2 +- src/gui/painting/qt_attribution.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/3rdparty/freetype/qt_attribution.json b/src/3rdparty/freetype/qt_attribution.json index 31328c7b31c..b67ad3c761a 100644 --- a/src/3rdparty/freetype/qt_attribution.json +++ b/src/3rdparty/freetype/qt_attribution.json @@ -10,7 +10,7 @@ "Version": "2.13.1", "License": "Freetype Project License or GNU General Public License v2.0 only", - "LicenseId": "FTL OR GPL-2.0", + "LicenseId": "FTL OR GPL-2.0-only", "LicenseFile": "LICENSE.txt", "Copyright": "Copyright (c) 2007-2014 Adobe Systems Incorporated Copyright (c) 2004-2023 Albert Chin-A-Young diff --git a/src/gui/painting/qt_attribution.json b/src/gui/painting/qt_attribution.json index 488daf07bf9..903f498fa09 100644 --- a/src/gui/painting/qt_attribution.json +++ b/src/gui/painting/qt_attribution.json @@ -9,7 +9,7 @@ "Description": "FreeType is a freely available software library to render fonts.", "Homepage": "http://www.freetype.org", "License": "Freetype Project License or GNU General Public License v2.0 only", - "LicenseId": "FTL or GPL-2.0", + "LicenseId": "FTL OR GPL-2.0-only", "LicenseFile": "../../3rdparty/freetype/LICENSE.txt", "Copyright": "Copyright 2000-2016 by David Turner, Robert Wilhelm, and Werner Lemberg." }, From cdc726a85f2a6596f730a1b7ce05008df34cdad4 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Wed, 23 Aug 2023 16:05:42 +0200 Subject: [PATCH 129/151] Clean up inline keyword use in qstring.h If an inline member function is defined outside of its class' body, its declaration must have the inline keyword. Otherwise, in certain situations, MinGW complains like this: qstring.h:1118:13: error: 'void QString::clear()' redeclared without dllimport attribute after being referenced with dll linkage [-Werror] Fix all instances in qstring.h by - adding the inline keyword where it was missing on the definition (except constexpr functions, which are implicitly inline) - removing the inline keyword from all out-of-class-body definitions While the latter isn't necessary for fixing the MinGW warning-turned-error, the churn is warranted: It's enlisting all platforms' help in checking for inline consistency (by causing "multiple-definition errors" at link time or "inline function never defined" at compile time when we get it wrong). If we kept the inline keyword on the definitions, only MinGW would continue to warn, and only in some, as of yet not fully understood, situations, so we'd have no control over when these warnings pop up in user code. Change-Id: I0ae78f1d8f1fa4eaec0b162ea16013669370eead Reviewed-by: Anton Kudryavtsev Reviewed-by: Ahmad Samir Reviewed-by: Qt CI Bot Reviewed-by: Edward Welbourne Reviewed-by: Dennis Oberst Reviewed-by: Ivan Solovev (cherry picked from commit 1c1d7ab486b87489163c56b05d10ff907e1d821d) Reviewed-by: Marc Mutz --- src/corelib/text/qstring.h | 222 ++++++++++++++++++------------------- 1 file changed, 111 insertions(+), 111 deletions(-) diff --git a/src/corelib/text/qstring.h b/src/corelib/text/qstring.h index e4c64919289..d138779a773 100644 --- a/src/corelib/text/qstring.h +++ b/src/corelib/text/qstring.h @@ -387,7 +387,7 @@ class Q_CORE_EXPORT QString public: typedef QStringPrivate DataPointer; - inline constexpr QString() noexcept; + constexpr QString() noexcept; explicit QString(const QChar *unicode, qsizetype size = -1); QString(QChar c); QString(qsizetype size, QChar c); @@ -430,11 +430,11 @@ public: inline void detach(); inline bool isDetached() const; inline bool isSharedWith(const QString &other) const { return d.isSharedWith(other.d); } - void clear(); + inline void clear(); inline const QChar at(qsizetype i) const; - const QChar operator[](qsizetype i) const; - [[nodiscard]] QChar &operator[](qsizetype i); + inline const QChar operator[](qsizetype i) const; + [[nodiscard]] inline QChar &operator[](qsizetype i); [[nodiscard]] inline QChar front() const { return at(0); } [[nodiscard]] inline QChar &front(); @@ -445,17 +445,17 @@ public: QChar fillChar = QLatin1Char(' ')) const; [[nodiscard]] QString arg(qulonglong a, int fieldwidth=0, int base=10, QChar fillChar = QLatin1Char(' ')) const; - [[nodiscard]] QString arg(long a, int fieldwidth=0, int base=10, + [[nodiscard]] inline QString arg(long a, int fieldwidth=0, int base=10, QChar fillChar = QLatin1Char(' ')) const; - [[nodiscard]] QString arg(ulong a, int fieldwidth=0, int base=10, + [[nodiscard]] inline QString arg(ulong a, int fieldwidth=0, int base=10, QChar fillChar = QLatin1Char(' ')) const; - [[nodiscard]] QString arg(int a, int fieldWidth = 0, int base = 10, + [[nodiscard]] inline QString arg(int a, int fieldWidth = 0, int base = 10, QChar fillChar = QLatin1Char(' ')) const; - [[nodiscard]] QString arg(uint a, int fieldWidth = 0, int base = 10, + [[nodiscard]] inline QString arg(uint a, int fieldWidth = 0, int base = 10, QChar fillChar = QLatin1Char(' ')) const; - [[nodiscard]] QString arg(short a, int fieldWidth = 0, int base = 10, + [[nodiscard]] inline QString arg(short a, int fieldWidth = 0, int base = 10, QChar fillChar = QLatin1Char(' ')) const; - [[nodiscard]] QString arg(ushort a, int fieldWidth = 0, int base = 10, + [[nodiscard]] inline QString arg(ushort a, int fieldWidth = 0, int base = 10, QChar fillChar = QLatin1Char(' ')) const; [[nodiscard]] QString arg(double a, int fieldWidth = 0, char format = 'g', int precision = -1, QChar fillChar = QLatin1Char(' ')) const; @@ -548,7 +548,7 @@ public: }; Q_DECLARE_FLAGS(SectionFlags, SectionFlag) - [[nodiscard]] QString section(QChar sep, qsizetype start, qsizetype end = -1, SectionFlags flags = SectionDefault) const; + [[nodiscard]] inline QString section(QChar sep, qsizetype start, qsizetype end = -1, SectionFlags flags = SectionDefault) const; [[nodiscard]] QString section(const QString &in_sep, qsizetype start, qsizetype end = -1, SectionFlags flags = SectionDefault) const; #if QT_CONFIG(regularexpression) [[nodiscard]] QString section(const QRegularExpression &re, qsizetype start, qsizetype end = -1, SectionFlags flags = SectionDefault) const; @@ -805,11 +805,11 @@ public: { return -s2.compare(s1, cs); } int localeAwareCompare(const QString& s) const; - int localeAwareCompare(QStringView s) const; + inline int localeAwareCompare(QStringView s) const; static int localeAwareCompare(const QString& s1, const QString& s2) { return s1.localeAwareCompare(s2); } - static int localeAwareCompare(QStringView s1, QStringView s2); + static inline int localeAwareCompare(QStringView s1, QStringView s2); short toShort(bool *ok=nullptr, int base=10) const { return toIntegral_helper(*this, ok, base); } @@ -828,15 +828,15 @@ public: float toFloat(bool *ok=nullptr) const; double toDouble(bool *ok=nullptr) const; - QString &setNum(short, int base=10); - QString &setNum(ushort, int base=10); - QString &setNum(int, int base=10); - QString &setNum(uint, int base=10); - QString &setNum(long, int base=10); - QString &setNum(ulong, int base=10); + inline QString &setNum(short, int base=10); + inline QString &setNum(ushort, int base=10); + inline QString &setNum(int, int base=10); + inline QString &setNum(uint, int base=10); + inline QString &setNum(long, int base=10); + inline QString &setNum(ulong, int base=10); QString &setNum(qlonglong, int base=10); QString &setNum(qulonglong, int base=10); - QString &setNum(float, char format='g', int precision=6); + inline QString &setNum(float, char format='g', int precision=6); QString &setNum(double, char format='g', int precision=6); static QString number(int, int base=10); @@ -1178,17 +1178,17 @@ QString QAnyStringView::toString() const // // QString inline members // -inline QString::QString(QLatin1String latin1) +QString::QString(QLatin1String latin1) { *this = QString::fromLatin1(latin1.data(), latin1.size()); } -inline const QChar QString::at(qsizetype i) const +const QChar QString::at(qsizetype i) const { Q_ASSERT(size_t(i) < size_t(size())); return QChar(d.data()[i]); } -inline const QChar QString::operator[](qsizetype i) const +const QChar QString::operator[](qsizetype i) const { Q_ASSERT(size_t(i) < size_t(size())); return QChar(d.data()[i]); } -inline bool QString::isEmpty() const +bool QString::isEmpty() const { return d.size == 0; } -inline const QChar *QString::unicode() const +const QChar *QString::unicode() const { return data(); } -inline const QChar *QString::data() const +const QChar *QString::data() const { #if QT5_NULL_STRINGS == 1 return reinterpret_cast(d.data() ? d.data() : &_empty); @@ -1196,58 +1196,58 @@ inline const QChar *QString::data() const return reinterpret_cast(d.data()); #endif } -inline QChar *QString::data() +QChar *QString::data() { detach(); Q_ASSERT(d.data()); return reinterpret_cast(d.data()); } -inline const QChar *QString::constData() const +const QChar *QString::constData() const { return data(); } -inline void QString::detach() +void QString::detach() { if (d->needsDetach()) reallocData(d.size, QArrayData::KeepSize); } -inline bool QString::isDetached() const +bool QString::isDetached() const { return !d->isShared(); } -inline void QString::clear() +void QString::clear() { if (!isNull()) *this = QString(); } -inline QString::QString(const QString &other) noexcept : d(other.d) +QString::QString(const QString &other) noexcept : d(other.d) { } -inline qsizetype QString::capacity() const { return qsizetype(d->constAllocatedCapacity()); } -inline QString &QString::setNum(short n, int base) +qsizetype QString::capacity() const { return qsizetype(d->constAllocatedCapacity()); } +QString &QString::setNum(short n, int base) { return setNum(qlonglong(n), base); } -inline QString &QString::setNum(ushort n, int base) +QString &QString::setNum(ushort n, int base) { return setNum(qulonglong(n), base); } -inline QString &QString::setNum(int n, int base) +QString &QString::setNum(int n, int base) { return setNum(qlonglong(n), base); } -inline QString &QString::setNum(uint n, int base) +QString &QString::setNum(uint n, int base) { return setNum(qulonglong(n), base); } -inline QString &QString::setNum(long n, int base) +QString &QString::setNum(long n, int base) { return setNum(qlonglong(n), base); } -inline QString &QString::setNum(ulong n, int base) +QString &QString::setNum(ulong n, int base) { return setNum(qulonglong(n), base); } -inline QString &QString::setNum(float n, char f, int prec) +QString &QString::setNum(float n, char f, int prec) { return setNum(double(n),f,prec); } -inline QString QString::arg(int a, int fieldWidth, int base, QChar fillChar) const +QString QString::arg(int a, int fieldWidth, int base, QChar fillChar) const { return arg(qlonglong(a), fieldWidth, base, fillChar); } -inline QString QString::arg(uint a, int fieldWidth, int base, QChar fillChar) const +QString QString::arg(uint a, int fieldWidth, int base, QChar fillChar) const { return arg(qulonglong(a), fieldWidth, base, fillChar); } -inline QString QString::arg(long a, int fieldWidth, int base, QChar fillChar) const +QString QString::arg(long a, int fieldWidth, int base, QChar fillChar) const { return arg(qlonglong(a), fieldWidth, base, fillChar); } -inline QString QString::arg(ulong a, int fieldWidth, int base, QChar fillChar) const +QString QString::arg(ulong a, int fieldWidth, int base, QChar fillChar) const { return arg(qulonglong(a), fieldWidth, base, fillChar); } -inline QString QString::arg(short a, int fieldWidth, int base, QChar fillChar) const +QString QString::arg(short a, int fieldWidth, int base, QChar fillChar) const { return arg(qlonglong(a), fieldWidth, base, fillChar); } -inline QString QString::arg(ushort a, int fieldWidth, int base, QChar fillChar) const +QString QString::arg(ushort a, int fieldWidth, int base, QChar fillChar) const { return arg(qulonglong(a), fieldWidth, base, fillChar); } -inline QString QString::section(QChar asep, qsizetype astart, qsizetype aend, SectionFlags aflags) const +QString QString::section(QChar asep, qsizetype astart, qsizetype aend, SectionFlags aflags) const { return section(QString(asep), astart, aend, aflags); } QT_WARNING_PUSH QT_WARNING_DISABLE_MSVC(4127) // "conditional expression is constant" QT_WARNING_DISABLE_INTEL(111) // "statement is unreachable" -inline qsizetype QString::toWCharArray(wchar_t *array) const +qsizetype QString::toWCharArray(wchar_t *array) const { return qToStringViewIgnoringNull(*this).toWCharArray(array); } @@ -1266,16 +1266,16 @@ qsizetype QStringView::toWCharArray(wchar_t *array) const QT_WARNING_POP -inline QString QString::fromWCharArray(const wchar_t *string, qsizetype size) +QString QString::fromWCharArray(const wchar_t *string, qsizetype size) { return sizeof(wchar_t) == sizeof(QChar) ? fromUtf16(reinterpret_cast(string), size) : fromUcs4(reinterpret_cast(string), size); } -inline constexpr QString::QString() noexcept {} -inline QString::~QString() {} +constexpr QString::QString() noexcept {} +QString::~QString() {} -inline void QString::reserve(qsizetype asize) +void QString::reserve(qsizetype asize) { if (d->needsDetach() || asize >= capacity() - d.freeSpaceAtBegin()) reallocData(qMax(asize, size()), QArrayData::KeepSize); @@ -1283,7 +1283,7 @@ inline void QString::reserve(qsizetype asize) d->setFlag(Data::CapacityReserved); } -inline void QString::squeeze() +void QString::squeeze() { if (!d.isMutable()) return; @@ -1293,106 +1293,106 @@ inline void QString::squeeze() d->clearFlag(Data::CapacityReserved); } -inline QString &QString::setUtf16(const ushort *autf16, qsizetype asize) +QString &QString::setUtf16(const ushort *autf16, qsizetype asize) { return setUnicode(reinterpret_cast(autf16), asize); } -inline QChar &QString::operator[](qsizetype i) +QChar &QString::operator[](qsizetype i) { Q_ASSERT(i >= 0 && i < size()); return data()[i]; } -inline QChar &QString::front() { return operator[](0); } -inline QChar &QString::back() { return operator[](size() - 1); } -inline QString::iterator QString::begin() +QChar &QString::front() { return operator[](0); } +QChar &QString::back() { return operator[](size() - 1); } +QString::iterator QString::begin() { detach(); return reinterpret_cast(d.data()); } -inline QString::const_iterator QString::begin() const +QString::const_iterator QString::begin() const { return reinterpret_cast(d.data()); } -inline QString::const_iterator QString::cbegin() const +QString::const_iterator QString::cbegin() const { return reinterpret_cast(d.data()); } -inline QString::const_iterator QString::constBegin() const +QString::const_iterator QString::constBegin() const { return reinterpret_cast(d.data()); } -inline QString::iterator QString::end() +QString::iterator QString::end() { detach(); return reinterpret_cast(d.data() + d.size); } -inline QString::const_iterator QString::end() const +QString::const_iterator QString::end() const { return reinterpret_cast(d.data() + d.size); } -inline QString::const_iterator QString::cend() const +QString::const_iterator QString::cend() const { return reinterpret_cast(d.data() + d.size); } -inline QString::const_iterator QString::constEnd() const +QString::const_iterator QString::constEnd() const { return reinterpret_cast(d.data() + d.size); } -inline bool QString::contains(const QString &s, Qt::CaseSensitivity cs) const +bool QString::contains(const QString &s, Qt::CaseSensitivity cs) const { return indexOf(s, 0, cs) != -1; } -inline bool QString::contains(QLatin1String s, Qt::CaseSensitivity cs) const +bool QString::contains(QLatin1String s, Qt::CaseSensitivity cs) const { return indexOf(s, 0, cs) != -1; } -inline bool QString::contains(QChar c, Qt::CaseSensitivity cs) const +bool QString::contains(QChar c, Qt::CaseSensitivity cs) const { return indexOf(c, 0, cs) != -1; } -inline bool QString::contains(QStringView s, Qt::CaseSensitivity cs) const noexcept +bool QString::contains(QStringView s, Qt::CaseSensitivity cs) const noexcept { return indexOf(s, 0, cs) != -1; } #if !defined(QT_NO_CAST_FROM_ASCII) && !defined(QT_RESTRICTED_CAST_FROM_ASCII) -inline bool QString::operator==(const char *s) const +bool QString::operator==(const char *s) const { return QString::compare_helper(constData(), size(), s, -1) == 0; } -inline bool QString::operator!=(const char *s) const +bool QString::operator!=(const char *s) const { return QString::compare_helper(constData(), size(), s, -1) != 0; } -inline bool QString::operator<(const char *s) const +bool QString::operator<(const char *s) const { return QString::compare_helper(constData(), size(), s, -1) < 0; } -inline bool QString::operator>(const char *s) const +bool QString::operator>(const char *s) const { return QString::compare_helper(constData(), size(), s, -1) > 0; } -inline bool QString::operator<=(const char *s) const +bool QString::operator<=(const char *s) const { return QString::compare_helper(constData(), size(), s, -1) <= 0; } -inline bool QString::operator>=(const char *s) const +bool QString::operator>=(const char *s) const { return QString::compare_helper(constData(), size(), s, -1) >= 0; } -QT_ASCII_CAST_WARN inline bool QLatin1String::operator==(const char *s) const +QT_ASCII_CAST_WARN bool QLatin1String::operator==(const char *s) const { return QString::fromUtf8(s) == *this; } -QT_ASCII_CAST_WARN inline bool QLatin1String::operator!=(const char *s) const +QT_ASCII_CAST_WARN bool QLatin1String::operator!=(const char *s) const { return QString::fromUtf8(s) != *this; } -QT_ASCII_CAST_WARN inline bool QLatin1String::operator<(const char *s) const +QT_ASCII_CAST_WARN bool QLatin1String::operator<(const char *s) const { return QString::fromUtf8(s) > *this; } -QT_ASCII_CAST_WARN inline bool QLatin1String::operator>(const char *s) const +QT_ASCII_CAST_WARN bool QLatin1String::operator>(const char *s) const { return QString::fromUtf8(s) < *this; } -QT_ASCII_CAST_WARN inline bool QLatin1String::operator<=(const char *s) const +QT_ASCII_CAST_WARN bool QLatin1String::operator<=(const char *s) const { return QString::fromUtf8(s) >= *this; } -QT_ASCII_CAST_WARN inline bool QLatin1String::operator>=(const char *s) const +QT_ASCII_CAST_WARN bool QLatin1String::operator>=(const char *s) const { return QString::fromUtf8(s) <= *this; } -QT_ASCII_CAST_WARN inline bool QLatin1String::operator==(const QByteArray &s) const +QT_ASCII_CAST_WARN bool QLatin1String::operator==(const QByteArray &s) const { return QString::fromUtf8(s) == *this; } -QT_ASCII_CAST_WARN inline bool QLatin1String::operator!=(const QByteArray &s) const +QT_ASCII_CAST_WARN bool QLatin1String::operator!=(const QByteArray &s) const { return QString::fromUtf8(s) != *this; } -QT_ASCII_CAST_WARN inline bool QLatin1String::operator<(const QByteArray &s) const +QT_ASCII_CAST_WARN bool QLatin1String::operator<(const QByteArray &s) const { return QString::fromUtf8(s) > *this; } -QT_ASCII_CAST_WARN inline bool QLatin1String::operator>(const QByteArray &s) const +QT_ASCII_CAST_WARN bool QLatin1String::operator>(const QByteArray &s) const { return QString::fromUtf8(s) < *this; } -QT_ASCII_CAST_WARN inline bool QLatin1String::operator<=(const QByteArray &s) const +QT_ASCII_CAST_WARN bool QLatin1String::operator<=(const QByteArray &s) const { return QString::fromUtf8(s) >= *this; } -QT_ASCII_CAST_WARN inline bool QLatin1String::operator>=(const QByteArray &s) const +QT_ASCII_CAST_WARN bool QLatin1String::operator>=(const QByteArray &s) const { return QString::fromUtf8(s) <= *this; } -inline int QLatin1String::compare_helper(const QLatin1String &s1, const char *s2) +int QLatin1String::compare_helper(const QLatin1String &s1, const char *s2) { return QString::compare(s1, QString::fromUtf8(s2)); } -QT_ASCII_CAST_WARN inline bool QString::operator==(const QByteArray &s) const +QT_ASCII_CAST_WARN bool QString::operator==(const QByteArray &s) const { return QString::compare_helper(constData(), size(), s.constData(), s.size()) == 0; } -QT_ASCII_CAST_WARN inline bool QString::operator!=(const QByteArray &s) const +QT_ASCII_CAST_WARN bool QString::operator!=(const QByteArray &s) const { return QString::compare_helper(constData(), size(), s.constData(), s.size()) != 0; } -QT_ASCII_CAST_WARN inline bool QString::operator<(const QByteArray &s) const +QT_ASCII_CAST_WARN bool QString::operator<(const QByteArray &s) const { return QString::compare_helper(constData(), size(), s.constData(), s.size()) < 0; } -QT_ASCII_CAST_WARN inline bool QString::operator>(const QByteArray &s) const +QT_ASCII_CAST_WARN bool QString::operator>(const QByteArray &s) const { return QString::compare_helper(constData(), size(), s.constData(), s.size()) > 0; } -QT_ASCII_CAST_WARN inline bool QString::operator<=(const QByteArray &s) const +QT_ASCII_CAST_WARN bool QString::operator<=(const QByteArray &s) const { return QString::compare_helper(constData(), size(), s.constData(), s.size()) <= 0; } -QT_ASCII_CAST_WARN inline bool QString::operator>=(const QByteArray &s) const +QT_ASCII_CAST_WARN bool QString::operator>=(const QByteArray &s) const { return QString::compare_helper(constData(), size(), s.constData(), s.size()) >= 0; } -inline bool QByteArray::operator==(const QString &s) const +bool QByteArray::operator==(const QString &s) const { return QString::compare_helper(s.constData(), s.size(), constData(), qstrnlen(constData(), size())) == 0; } -inline bool QByteArray::operator!=(const QString &s) const +bool QByteArray::operator!=(const QString &s) const { return QString::compare_helper(s.constData(), s.size(), constData(), qstrnlen(constData(), size())) != 0; } -inline bool QByteArray::operator<(const QString &s) const +bool QByteArray::operator<(const QString &s) const { return QString::compare_helper(s.constData(), s.size(), constData(), size()) > 0; } -inline bool QByteArray::operator>(const QString &s) const +bool QByteArray::operator>(const QString &s) const { return QString::compare_helper(s.constData(), s.size(), constData(), size()) < 0; } -inline bool QByteArray::operator<=(const QString &s) const +bool QByteArray::operator<=(const QString &s) const { return QString::compare_helper(s.constData(), s.size(), constData(), size()) >= 0; } -inline bool QByteArray::operator>=(const QString &s) const +bool QByteArray::operator>=(const QString &s) const { return QString::compare_helper(s.constData(), s.size(), constData(), size()) <= 0; } #endif // !defined(QT_NO_CAST_FROM_ASCII) && !defined(QT_RESTRICTED_CAST_FROM_ASCII) @@ -1415,13 +1415,13 @@ QT_ASCII_CAST_WARN inline const QString operator+(const QString &s, const QByteA # endif // QT_NO_CAST_FROM_ASCII #endif // QT_USE_QSTRINGBUILDER -inline std::string QString::toStdString() const +std::string QString::toStdString() const { return toUtf8().toStdString(); } -inline QString QString::fromStdString(const std::string &s) +QString QString::fromStdString(const std::string &s) { return fromUtf8(s.data(), qsizetype(s.size())); } -inline std::wstring QString::toStdWString() const +std::wstring QString::toStdWString() const { std::wstring str; str.resize(length()); @@ -1434,19 +1434,19 @@ inline std::wstring QString::toStdWString() const return str; } -inline QString QString::fromStdWString(const std::wstring &s) +QString QString::fromStdWString(const std::wstring &s) { return fromWCharArray(s.data(), qsizetype(s.size())); } -inline QString QString::fromStdU16String(const std::u16string &s) +QString QString::fromStdU16String(const std::u16string &s) { return fromUtf16(s.data(), qsizetype(s.size())); } -inline std::u16string QString::toStdU16String() const +std::u16string QString::toStdU16String() const { return std::u16string(reinterpret_cast(utf16()), length()); } -inline QString QString::fromStdU32String(const std::u32string &s) +QString QString::fromStdU32String(const std::u32string &s) { return fromUcs4(s.data(), qsizetype(s.size())); } -inline std::u32string QString::toStdU32String() const +std::u32string QString::toStdU32String() const { std::u32string u32str(length(), char32_t(0)); qsizetype len = toUcs4_helper(reinterpret_cast(constData()), @@ -1463,12 +1463,12 @@ Q_CORE_EXPORT QDataStream &operator>>(QDataStream &, QString &); Q_DECLARE_SHARED(QString) Q_DECLARE_OPERATORS_FOR_FLAGS(QString::SectionFlags) -inline int QString::compare(QStringView s, Qt::CaseSensitivity cs) const noexcept +int QString::compare(QStringView s, Qt::CaseSensitivity cs) const noexcept { return -s.compare(*this, cs); } -inline int QString::localeAwareCompare(QStringView s) const +int QString::localeAwareCompare(QStringView s) const { return localeAwareCompare_helper(constData(), length(), s.constData(), s.length()); } -inline int QString::localeAwareCompare(QStringView s1, QStringView s2) +int QString::localeAwareCompare(QStringView s1, QStringView s2) { return localeAwareCompare_helper(s1.constData(), s1.length(), s2.constData(), s2.length()); } namespace QtPrivate { From 37bc7eb5db0680744e0633d3e060c35ac3e1f013 Mon Sep 17 00:00:00 2001 From: Dennis Oberst Date: Mon, 21 Aug 2023 18:16:02 +0200 Subject: [PATCH 130/151] Update bundled zlib to version 1.3 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit zlib 1.3 has been available since August 18, 2023. Version 1.3 now defines the following: # define crc32_combine_gen z_crc32_combine_gen # define crc32_combine_gen64 z_crc32_combine_gen64 # define crc32_combine_op z_crc32_combine_op We patched those in manually with qtpatches.diff, so we update it to reflect these changes. Updated the diff with 'git diff --relative > qtpatches.diff' from within the 3rdparty/zlib directory. Since updating zlib always requires some manual intervention add a minimal guide that will be printed on using import_from_zlib_tarball.sh. As a drive-by fix an error in import_from_zlib_tarball.sh where passing in a path already containing a backslash as: import_from_zlib_tarball.sh zlib-1.x/ ./ would append another backshlash to that path (zlib-1.x//). Furthermore add the '-v' flag to the copy command to make it more verbose. [ChangeLog][Third-Party Code] zlib was updated to version 1.3. Task-number: QTBUG-116236 Change-Id: Ib7c8698035e1e049b455308c5774fcaf88b7622a Reviewed-by: Mårten Nordheim Reviewed-by: Edward Welbourne (cherry picked from commit 3652cdf6c78d22126c4f2ec363f338169330c849) Reviewed-by: Kai Köhne --- src/3rdparty/zlib/import_from_zlib_tarball.sh | 22 +- src/3rdparty/zlib/qt_attribution.json | 5 +- src/3rdparty/zlib/qtpatches.diff | 125 ++-- src/3rdparty/zlib/src/ChangeLog | 22 +- src/3rdparty/zlib/src/README | 19 +- src/3rdparty/zlib/src/adler32.c | 32 +- src/3rdparty/zlib/src/compress.c | 21 +- src/3rdparty/zlib/src/crc32.c | 248 +++----- src/3rdparty/zlib/src/deflate.c | 569 +++++++----------- src/3rdparty/zlib/src/deflate.h | 16 +- src/3rdparty/zlib/src/gzclose.c | 4 +- src/3rdparty/zlib/src/gzguts.h | 23 +- src/3rdparty/zlib/src/gzlib.c | 101 +--- src/3rdparty/zlib/src/gzread.c | 88 +-- src/3rdparty/zlib/src/gzwrite.c | 84 +-- src/3rdparty/zlib/src/infback.c | 30 +- src/3rdparty/zlib/src/inffast.c | 5 +- src/3rdparty/zlib/src/inffast.h | 2 +- src/3rdparty/zlib/src/inflate.c | 129 +--- src/3rdparty/zlib/src/inftrees.c | 17 +- src/3rdparty/zlib/src/inftrees.h | 6 +- src/3rdparty/zlib/src/trees.c | 526 +++++++--------- src/3rdparty/zlib/src/uncompr.c | 16 +- src/3rdparty/zlib/src/zconf.h | 8 +- src/3rdparty/zlib/src/zlib.h | 379 ++++++------ src/3rdparty/zlib/src/zutil.c | 60 +- src/3rdparty/zlib/src/zutil.h | 20 +- 27 files changed, 1013 insertions(+), 1564 deletions(-) diff --git a/src/3rdparty/zlib/import_from_zlib_tarball.sh b/src/3rdparty/zlib/import_from_zlib_tarball.sh index 5251f43d33a..e9e88d0ae21 100755 --- a/src/3rdparty/zlib/import_from_zlib_tarball.sh +++ b/src/3rdparty/zlib/import_from_zlib_tarball.sh @@ -46,8 +46,9 @@ if [ $# -ne 2 ]; then exit 1 fi -ZLIB_DIR=$1 -TARGET_DIR=$2 +# Name the arguments, omitting trailing slashes as we'll add where needed. +ZLIB_DIR="${1%/}" +TARGET_DIR="${2%/}" if [ ! -d "$ZLIB_DIR" -o ! -r "$ZLIB_DIR" -o ! -d "$TARGET_DIR" -o ! -w "$TARGET_DIR" ]; then echo "Either the zlib source dir or the target dir do not exist," @@ -71,7 +72,7 @@ copy_file() { fi mkdir -p "$TARGET_DIR/$(dirname "$SOURCE_FILE")" - cp "$ZLIB_DIR/$SOURCE_FILE" "$TARGET_DIR/$DEST_FILE" + cp -v "$ZLIB_DIR/$SOURCE_FILE" "$TARGET_DIR/$DEST_FILE" } FILES=" @@ -110,3 +111,18 @@ FILES=" for i in $FILES; do copy_file "$i" "src/$i" done + +cat << EOF + +Please do not forget to patch qtpatches.diff +The usual routine after this script is: + 1. Create commit to clean staging + 2. Apply qtpatches.diff with: + patch -p1 < qtpatches.diff + 3. Update the version in: ChangeLog and src/zlib.h + 4. Validate all changes and create new qtpatches.diff with: + git diff --relative > qtpatches.diff + 5. Add changed files and amend the commit with these files. + +If you want to revert the diff use: patch -p1 -Ri qtpatches.diff +EOF diff --git a/src/3rdparty/zlib/qt_attribution.json b/src/3rdparty/zlib/qt_attribution.json index db176cbe6a3..4106ab3cb73 100644 --- a/src/3rdparty/zlib/qt_attribution.json +++ b/src/3rdparty/zlib/qt_attribution.json @@ -6,10 +6,11 @@ "Description": "zlib is a general purpose data compression library.", "Homepage": "https://zlib.net/", - "Version": "1.2.13", + "Version": "1.3", + "DownloadLocation": "https://www.zlib.net/zlib-1.3.tar.gz", "License": "zlib License", "LicenseId": "Zlib", "LicenseFile": "LICENSE", - "Copyright": "(C) 1995-2022 Jean-loup Gailly and Mark Adler" + "Copyright": "(C) 1995-2023 Jean-loup Gailly and Mark Adler" } diff --git a/src/3rdparty/zlib/qtpatches.diff b/src/3rdparty/zlib/qtpatches.diff index ae316294dc2..20e2b10aa7f 100644 --- a/src/3rdparty/zlib/qtpatches.diff +++ b/src/3rdparty/zlib/qtpatches.diff @@ -1,50 +1,23 @@ -diff -ruN orig/ChangeLog src/ChangeLog ---- orig/ChangeLog -+++ src/ChangeLog +diff --git a/src/ChangeLog b/src/ChangeLog +index 8707988ac1..c107a78b5d 100644 +--- a/src/ChangeLog ++++ b/src/ChangeLog @@ -1,6 +1,10 @@ ChangeLog file for zlib -+Changes in 1.2.13 (Qt) (14 Nov 2022) ++Changes in 1.3 (Qt) (23 Aug 2023) +- This is a stripped down copy of zlib that contains patches to + make it compile as part of Qt. See also "qtpatches.diff". + - Changes in 1.2.13 (13 Oct 2022) - - Fix configure issue that discarded provided CC definition - - Correct incorrect inputs provided to the CRC functions -diff -ruN orig/gzguts.h src/gzguts.h ---- orig/gzguts.h -+++ src/gzguts.h -@@ -3,6 +3,25 @@ - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -+#ifdef _MSC_VER -+# ifndef _CRT_SECURE_NO_DEPRECATE -+# define _CRT_SECURE_NO_DEPRECATE -+# endif -+# ifndef _CRT_NONSTDC_NO_DEPRECATE -+# define _CRT_NONSTDC_NO_DEPRECATE -+# endif -+// disable warnings like '=': conversion from 'size_t' to 'unsigned int', possible loss of data -+# pragma warning(disable: 4267; disable: 4244) -+#endif -+ -+#ifndef QT_BOOTSTRAPPED -+# include -+#endif -+ -+#ifdef QT_VISIBILITY_AVAILABLE -+#define HAVE_HIDDEN -+#endif -+ - #ifdef _LARGEFILE64_SOURCE - # ifndef _LARGEFILE_SOURCE - # define _LARGEFILE_SOURCE 1 -diff -ruN orig/README src/README ---- orig/README -+++ src/README -@@ -6,6 +6,9 @@ + Changes in 1.3 (18 Aug 2023) + - Remove K&R function definitions and zlib2ansi + - Fix bug in deflateBound() for level 0 and memLevel 9 +diff --git a/src/README b/src/README +index e02fc5aa20..f9c16220b2 100644 +--- a/src/README ++++ b/src/README +@@ -6,6 +6,9 @@ thread safe. The data format used by the zlib library is described by RFCs http://tools.ietf.org/html/rfc1950 (zlib format), rfc1951 (deflate format) and rfc1952 (gzip format). @@ -54,9 +27,27 @@ diff -ruN orig/README src/README All functions of the compression library are documented in the file zlib.h (volunteer to write man pages welcome, contact zlib@gzip.org). A usage example of the library is given in the file test/example.c which also tests that -diff -ruN orig/zconf.h src/zconf.h ---- orig/zconf.h -+++ src/zconf.h +diff --git a/src/gzguts.h b/src/gzguts.h +index f9375047e8..4c7c9f1225 100644 +--- a/src/gzguts.h ++++ b/src/gzguts.h +@@ -3,6 +3,12 @@ + * For conditions of distribution and use, see copyright notice in zlib.h + */ + ++#include ++ ++#ifdef QT_VISIBILITY_AVAILABLE ++#define HAVE_HIDDEN ++#endif ++ + #ifdef _LARGEFILE64_SOURCE + # ifndef _LARGEFILE_SOURCE + # define _LARGEFILE_SOURCE 1 +diff --git a/src/zconf.h b/src/zconf.h +index fb76ffe312..18be576f50 100644 +--- a/src/zconf.h ++++ b/src/zconf.h @@ -8,6 +8,9 @@ #ifndef ZCONF_H #define ZCONF_H @@ -67,17 +58,7 @@ diff -ruN orig/zconf.h src/zconf.h /* * If you *really* need a unique prefix for all types and library functions, * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it. -@@ -38,6 +41,9 @@ - # define crc32 z_crc32 - # define crc32_combine z_crc32_combine - # define crc32_combine64 z_crc32_combine64 -+# define crc32_combine_gen z_crc32_combine_gen -+# define crc32_combine_gen64 z_crc32_combine_gen64 -+# define crc32_combine_op z_crc32_combine_op - # define crc32_z z_crc32_z - # define deflate z_deflate - # define deflateBound z_deflateBound -@@ -136,6 +142,7 @@ +@@ -139,6 +142,7 @@ # endif # define zlibCompileFlags z_zlibCompileFlags # define zlibVersion z_zlibVersion @@ -85,7 +66,7 @@ diff -ruN orig/zconf.h src/zconf.h /* all zlib typedefs in zlib.h and zconf.h */ # define Byte z_Byte -@@ -431,7 +438,7 @@ +@@ -441,7 +445,7 @@ typedef uLong FAR uLongf; typedef unsigned long z_crc_t; #endif @@ -94,9 +75,10 @@ diff -ruN orig/zconf.h src/zconf.h # define Z_HAVE_UNISTD_H #endif -diff -ruN orig/zlib.h src/zlib.h ---- orig/zlib.h -+++ src/zlib.h +diff --git a/src/zlib.h b/src/zlib.h +index 6b7244f994..ffe3b177e2 100644 +--- a/src/zlib.h ++++ b/src/zlib.h @@ -33,11 +33,15 @@ #include "zconf.h" @@ -109,21 +91,20 @@ diff -ruN orig/zlib.h src/zlib.h extern "C" { #endif --#define ZLIB_VERSION "1.2.13" -+#define ZLIB_VERSION "1.2.13 (Qt)" - #define ZLIB_VERNUM 0x12c0 +-#define ZLIB_VERSION "1.3" ++#define ZLIB_VERSION "1.3 (Qt)" + #define ZLIB_VERNUM 0x1300 #define ZLIB_VER_MAJOR 1 - #define ZLIB_VER_MINOR 2 -diff -ruN orig/zutil.h src/zutil.h ---- orig/zutil.h -+++ src/zutil.h -@@ -13,6 +13,14 @@ + #define ZLIB_VER_MINOR 3 +diff --git a/src/zutil.h b/src/zutil.h +index 902a304cc2..3ea777b0f4 100644 +--- a/src/zutil.h ++++ b/src/zutil.h +@@ -13,6 +13,12 @@ #ifndef ZUTIL_H #define ZUTIL_H -+#ifndef QT_BOOTSTRAPPED -+# include -+#endif ++#include + +#ifdef QT_VISIBILITY_AVAILABLE +#define HAVE_HIDDEN @@ -132,7 +113,7 @@ diff -ruN orig/zutil.h src/zutil.h #ifdef HAVE_HIDDEN # define ZLIB_INTERNAL __attribute__((visibility ("hidden"))) #else -@@ -143,6 +151,11 @@ +@@ -143,6 +149,11 @@ extern z_const char * const z_errmsg[10]; /* indexed by 2-zlib_error */ # if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os # include /* for fdopen */ # else @@ -144,7 +125,7 @@ diff -ruN orig/zutil.h src/zutil.h # ifndef fdopen # define fdopen(fd,mode) NULL /* No fdopen() */ # endif -@@ -166,7 +179,7 @@ +@@ -166,7 +177,7 @@ extern z_const char * const z_errmsg[10]; /* indexed by 2-zlib_error */ # define OS_CODE 18 #endif @@ -152,4 +133,4 @@ diff -ruN orig/zutil.h src/zutil.h +#if defined(__APPLE__) && !defined(OS_CODE) # define OS_CODE 19 #endif - + \ No newline at end of file diff --git a/src/3rdparty/zlib/src/ChangeLog b/src/3rdparty/zlib/src/ChangeLog index 900c2393a10..c107a78b5da 100644 --- a/src/3rdparty/zlib/src/ChangeLog +++ b/src/3rdparty/zlib/src/ChangeLog @@ -1,10 +1,28 @@ ChangeLog file for zlib -Changes in 1.2.13 (Qt) (14 Nov 2022) +Changes in 1.3 (Qt) (23 Aug 2023) - This is a stripped down copy of zlib that contains patches to make it compile as part of Qt. See also "qtpatches.diff". +Changes in 1.3 (18 Aug 2023) +- Remove K&R function definitions and zlib2ansi +- Fix bug in deflateBound() for level 0 and memLevel 9 +- Fix bug when gzungetc() is used immediately after gzopen() +- Fix bug when using gzflush() with a very small buffer +- Fix crash when gzsetparams() attempted for transparent write +- Fix test/example.c to work with FORCE_STORED +- Rewrite of zran in examples (see zran.c version history) +- Fix minizip to allow it to open an empty zip file +- Fix reading disk number start on zip64 files in minizip +- Fix logic error in minizip argument processing +- Add minizip testing to Makefile +- Read multiple bytes instead of byte-by-byte in minizip unzip.c +- Add memory sanitizer to configure (--memory) +- Various portability improvements +- Various documentation improvements +- Various spelling and typo corrections + Changes in 1.2.13 (13 Oct 2022) - Fix configure issue that discarded provided CC definition - Correct incorrect inputs provided to the CRC functions @@ -1449,7 +1467,7 @@ Changes in 0.99 (27 Jan 96) - fix typo in Make_vms.com (f$trnlnm -> f$getsyi) - in fcalloc, normalize pointer if size > 65520 bytes - don't use special fcalloc for 32 bit Borland C++ -- use STDC instead of __GO32__ to avoid redeclaring exit, calloc, etc... +- use STDC instead of __GO32__ to avoid redeclaring exit, calloc, etc. - use Z_BINARY instead of BINARY - document that gzclose after gzdopen will close the file - allow "a" as mode in gzopen diff --git a/src/3rdparty/zlib/src/README b/src/3rdparty/zlib/src/README index 10c63e17bc6..f9c16220b20 100644 --- a/src/3rdparty/zlib/src/README +++ b/src/3rdparty/zlib/src/README @@ -1,6 +1,6 @@ ZLIB DATA COMPRESSION LIBRARY -zlib 1.2.13 is a general purpose data compression library. All the code is +zlib 1.3 is a general purpose data compression library. All the code is thread safe. The data format used by the zlib library is described by RFCs (Request for Comments) 1950 to 1952 in the files http://tools.ietf.org/html/rfc1950 (zlib format), rfc1951 (deflate format) and @@ -32,18 +32,17 @@ PLEASE read the zlib FAQ http://zlib.net/zlib_faq.html before asking for help. Mark Nelson wrote an article about zlib for the Jan. 1997 issue of Dr. Dobb's Journal; a copy of the article is available at -http://marknelson.us/1997/01/01/zlib-engine/ . +https://marknelson.us/posts/1997/01/01/zlib-engine.html . -The changes made in version 1.2.13 are documented in the file ChangeLog. +The changes made in version 1.3 are documented in the file ChangeLog. Unsupported third party contributions are provided in directory contrib/ . -zlib is available in Java using the java.util.zip package, documented at -http://java.sun.com/developer/technicalArticles/Programming/compression/ . +zlib is available in Java using the java.util.zip package. Follow the API +Documentation link at: https://docs.oracle.com/search/?q=java.util.zip . -A Perl interface to zlib written by Paul Marquess is available -at CPAN (Comprehensive Perl Archive Network) sites, including -http://search.cpan.org/~pmqs/IO-Compress-Zlib/ . +A Perl interface to zlib and bzip2 written by Paul Marquess +can be found at https://github.com/pmqs/IO-Compress . A Python interface to zlib written by A.M. Kuchling is available in Python 1.5 and later versions, see @@ -67,7 +66,7 @@ Notes for some targets: - zlib doesn't work with gcc 2.6.3 on a DEC 3000/300LX under OSF/1 2.1 it works when compiled with cc. -- On Digital Unix 4.0D (formely OSF/1) on AlphaServer, the cc option -std1 is +- On Digital Unix 4.0D (formerly OSF/1) on AlphaServer, the cc option -std1 is necessary to get gzprintf working correctly. This is done by configure. - zlib doesn't work on HP-UX 9.05 with some versions of /bin/cc. It works with @@ -87,7 +86,7 @@ Acknowledgments: Copyright notice: - (C) 1995-2022 Jean-loup Gailly and Mark Adler + (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 diff --git a/src/3rdparty/zlib/src/adler32.c b/src/3rdparty/zlib/src/adler32.c index d0be4380a39..04b81d29bad 100644 --- a/src/3rdparty/zlib/src/adler32.c +++ b/src/3rdparty/zlib/src/adler32.c @@ -7,8 +7,6 @@ #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 */ @@ -60,11 +58,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; @@ -131,20 +125,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; @@ -169,18 +155,10 @@ 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); } diff --git a/src/3rdparty/zlib/src/compress.c b/src/3rdparty/zlib/src/compress.c index 2ad5326c14e..f43bacf7ab9 100644 --- a/src/3rdparty/zlib/src/compress.c +++ b/src/3rdparty/zlib/src/compress.c @@ -19,13 +19,8 @@ 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; @@ -65,12 +60,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); } @@ -78,9 +69,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; } diff --git a/src/3rdparty/zlib/src/crc32.c b/src/3rdparty/zlib/src/crc32.c index f8357b083f7..6c38f5c04c6 100644 --- a/src/3rdparty/zlib/src/crc32.c +++ b/src/3rdparty/zlib/src/crc32.c @@ -103,19 +103,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 @@ -123,9 +110,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 | @@ -146,24 +131,77 @@ local z_word_t byte_swap(word) } #endif +#ifdef DYNAMIC_CRC_TABLE +/* ========================================================================= + * Table of powers of x for combining CRC-32s, filled in by make_crc_table() + * below. + */ + 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(). + */ +# include "crc32.h" +#endif + /* CRC polynomial. */ #define POLY 0xedb88320 /* p(x) reflected, with x^32 implied */ -#ifdef DYNAMIC_CRC_TABLE +/* + 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]; -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)); + local void braid(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)); + 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 */ /* @@ -176,7 +214,6 @@ local void make_crc_table OF((void)); /* 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 && \ @@ -196,10 +233,7 @@ struct once_s { invoke once() at the same time. The state must be a once_t initialized with ONCE_INIT. */ -local void once(state, init) - once_t *state; - void (*init)(void); -{ +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)) @@ -222,10 +256,7 @@ struct once_s { /* 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; -{ +local int test_and_set(int volatile *flag) { int was; was = *flag; @@ -234,10 +265,7 @@ local int test_and_set(flag) } /* Run the provided init() function once. This is not thread-safe. */ -local void once(state, init) - once_t *state; - void (*init)(void); -{ +local void once(once_t *state, void (*init)(void)) { if (!state->done) { if (test_and_set(&state->begun)) while (!state->done) @@ -279,8 +307,7 @@ local once_t made = ONCE_INIT; combinations of CRC register values and incoming bytes. */ -local void make_crc_table() -{ +local void make_crc_table(void) { unsigned i, j, n; z_crc_t p; @@ -447,11 +474,7 @@ local void make_crc_table() 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; -{ +local void write_table(FILE *out, const z_crc_t FAR *table, int k) { int n; for (n = 0; n < k; n++) @@ -464,11 +487,7 @@ local void write_table(out, table, k) 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; -{ +local void write_table32hi(FILE *out, const z_word_t FAR *table, int k) { int n; for (n = 0; n < k; n++) @@ -484,11 +503,7 @@ int k; 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; -{ +local void write_table64(FILE *out, const z_word_t FAR *table, int k) { int n; for (n = 0; n < k; n++) @@ -498,8 +513,7 @@ local void write_table64(out, table, k) } /* Actually do the deed. */ -int main() -{ +int main(void) { make_crc_table(); return 0; } @@ -511,12 +525,7 @@ int main() 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; -{ +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++) { @@ -531,69 +540,13 @@ local void braid(ltl, big, n, w) } #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(). - */ -#include "crc32.h" #endif /* DYNAMIC_CRC_TABLE */ -/* ======================================================================== - * Routines used for CRC calculation. Some are also required for the table - * generation above. - */ - -/* - 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(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; - } - 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(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; -} - /* ========================================================================= * 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 */ @@ -619,11 +572,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; @@ -723,18 +673,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) ^ @@ -745,11 +691,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; @@ -781,8 +724,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) { @@ -1069,20 +1012,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 */ @@ -1090,18 +1026,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 */ @@ -1109,17 +1039,11 @@ 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); } diff --git a/src/3rdparty/zlib/src/deflate.c b/src/3rdparty/zlib/src/deflate.c index 4a689db3598..bd011751920 100644 --- a/src/3rdparty/zlib/src/deflate.c +++ b/src/3rdparty/zlib/src/deflate.c @@ -1,5 +1,5 @@ /* 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 */ @@ -52,7 +52,7 @@ #include "deflate.h" const char deflate_copyright[] = - " deflate 1.2.13 Copyright 1995-2022 Jean-loup Gailly and Mark Adler "; + " deflate 1.3 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 @@ -60,9 +60,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 */ @@ -70,29 +67,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 @@ -195,9 +179,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; @@ -221,30 +208,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; @@ -386,9 +520,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) @@ -409,11 +541,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; @@ -478,11 +607,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; @@ -500,9 +626,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)) { @@ -537,10 +661,32 @@ int ZEXPORT deflateResetKeep(strm) 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); + + /* 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); @@ -550,10 +696,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; @@ -561,11 +704,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; @@ -575,11 +714,7 @@ 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; @@ -602,11 +737,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; @@ -651,13 +782,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; @@ -693,10 +819,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; @@ -752,7 +875,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 */ @@ -765,10 +889,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)); } @@ -779,9 +900,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; @@ -812,10 +931,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; @@ -1127,9 +1243,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; @@ -1153,11 +1267,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; @@ -1205,66 +1318,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 @@ -1275,10 +1328,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 */ @@ -1426,10 +1476,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 */ @@ -1490,11 +1537,7 @@ local uInt longest_match(s, cur_match) /* =========================================================================== * 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; -{ +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) { @@ -1514,137 +1557,6 @@ local void check_match(s, start, match, length) # 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; - } - } - - Assert((ulg)s->strstart <= s->window_size - MIN_LOOKAHEAD, - "not enough room for search"); -} - /* =========================================================================== * Flush the current block, with given end-of-file flag. * IN assertion: strstart is set to the end of the current match. @@ -1687,10 +1599,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. @@ -1874,10 +1783,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 */ @@ -1976,10 +1882,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 */ @@ -2107,10 +2010,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 */ @@ -2181,10 +2081,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 (;;) { diff --git a/src/3rdparty/zlib/src/deflate.h b/src/3rdparty/zlib/src/deflate.h index 1a06cd5f25d..8696791429f 100644 --- a/src/3rdparty/zlib/src/deflate.h +++ b/src/3rdparty/zlib/src/deflate.h @@ -291,14 +291,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)]) diff --git a/src/3rdparty/zlib/src/gzclose.c b/src/3rdparty/zlib/src/gzclose.c index caeb99a3177..48d6a86f04b 100644 --- a/src/3rdparty/zlib/src/gzclose.c +++ b/src/3rdparty/zlib/src/gzclose.c @@ -8,9 +8,7 @@ /* gzclose() is in a separate file so that it is linked in only if it is used. That way the other gzclose functions can be used instead to avoid linking in unneeded compression or decompression routines. */ -int ZEXPORT gzclose(file) - gzFile file; -{ +int ZEXPORT gzclose(gzFile file) { #ifndef NO_GZCOMPRESS gz_statep state; diff --git a/src/3rdparty/zlib/src/gzguts.h b/src/3rdparty/zlib/src/gzguts.h index 3ec32af25ff..cadba0b24e4 100644 --- a/src/3rdparty/zlib/src/gzguts.h +++ b/src/3rdparty/zlib/src/gzguts.h @@ -26,9 +26,8 @@ # ifndef _LARGEFILE_SOURCE # define _LARGEFILE_SOURCE 1 # endif -# ifdef _FILE_OFFSET_BITS -# undef _FILE_OFFSET_BITS -# endif +# undef _FILE_OFFSET_BITS +# undef _TIME_BITS #endif #ifdef HAVE_HIDDEN @@ -138,8 +137,8 @@ /* gz* functions always use library allocation functions */ #ifndef STDC - extern voidp malloc OF((uInt size)); - extern void free OF((voidpf ptr)); + extern voidp malloc(uInt size); + extern void free(voidpf ptr); #endif /* get errno and strerror definition */ @@ -157,10 +156,10 @@ /* provide prototypes for these when building zlib without LFS */ #if !defined(_LARGEFILE64_SOURCE) || _LFS64_LARGEFILE-0 == 0 - 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 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); #endif /* default memLevel */ @@ -222,9 +221,9 @@ typedef struct { typedef gz_state FAR *gz_statep; /* shared functions */ -void ZLIB_INTERNAL gz_error OF((gz_statep, int, const char *)); +void ZLIB_INTERNAL gz_error(gz_statep, int, const char *); #if defined UNDER_CE -char ZLIB_INTERNAL *gz_strwinerror OF((DWORD error)); +char ZLIB_INTERNAL *gz_strwinerror(DWORD error); #endif /* GT_OFF(x), where x is an unsigned value, is true if x > maximum z_off64_t @@ -233,6 +232,6 @@ char ZLIB_INTERNAL *gz_strwinerror OF((DWORD error)); #ifdef INT_MAX # define GT_OFF(x) (sizeof(int) == sizeof(z_off64_t) && (x) > INT_MAX) #else -unsigned ZLIB_INTERNAL gz_intmax OF((void)); +unsigned ZLIB_INTERNAL gz_intmax(void); # define GT_OFF(x) (sizeof(int) == sizeof(z_off64_t) && (x) > gz_intmax()) #endif diff --git a/src/3rdparty/zlib/src/gzlib.c b/src/3rdparty/zlib/src/gzlib.c index 55da46a453f..29fc4486fba 100644 --- a/src/3rdparty/zlib/src/gzlib.c +++ b/src/3rdparty/zlib/src/gzlib.c @@ -15,10 +15,6 @@ #endif #endif -/* Local functions */ -local void gz_reset OF((gz_statep)); -local gzFile gz_open OF((const void *, int, const char *)); - #if defined UNDER_CE /* Map the Windows error number in ERROR to a locale-dependent error message @@ -30,9 +26,7 @@ local gzFile gz_open OF((const void *, int, const char *)); The gz_strwinerror function does not change the current setting of GetLastError. */ -char ZLIB_INTERNAL *gz_strwinerror(error) - DWORD error; -{ +char ZLIB_INTERNAL *gz_strwinerror(DWORD error) { static char buf[1024]; wchar_t *msgbuf; @@ -72,9 +66,7 @@ char ZLIB_INTERNAL *gz_strwinerror(error) #endif /* UNDER_CE */ /* Reset gzip file state */ -local void gz_reset(state) - gz_statep state; -{ +local void gz_reset(gz_statep state) { state->x.have = 0; /* no output data available */ if (state->mode == GZ_READ) { /* for reading ... */ state->eof = 0; /* not at end of file */ @@ -90,11 +82,7 @@ local void gz_reset(state) } /* Open a gzip file either by name or file descriptor. */ -local gzFile gz_open(path, fd, mode) - const void *path; - int fd; - const char *mode; -{ +local gzFile gz_open(const void *path, int fd, const char *mode) { gz_statep state; z_size_t len; int oflag; @@ -269,26 +257,17 @@ local gzFile gz_open(path, fd, mode) } /* -- see zlib.h -- */ -gzFile ZEXPORT gzopen(path, mode) - const char *path; - const char *mode; -{ +gzFile ZEXPORT gzopen(const char *path, const char *mode) { return gz_open(path, -1, mode); } /* -- see zlib.h -- */ -gzFile ZEXPORT gzopen64(path, mode) - const char *path; - const char *mode; -{ +gzFile ZEXPORT gzopen64(const char *path, const char *mode) { return gz_open(path, -1, mode); } /* -- see zlib.h -- */ -gzFile ZEXPORT gzdopen(fd, mode) - int fd; - const char *mode; -{ +gzFile ZEXPORT gzdopen(int fd, const char *mode) { char *path; /* identifier for error messages */ gzFile gz; @@ -306,19 +285,13 @@ gzFile ZEXPORT gzdopen(fd, mode) /* -- see zlib.h -- */ #ifdef WIDECHAR -gzFile ZEXPORT gzopen_w(path, mode) - const wchar_t *path; - const char *mode; -{ +gzFile ZEXPORT gzopen_w(const wchar_t *path, const char *mode) { return gz_open(path, -2, mode); } #endif /* -- see zlib.h -- */ -int ZEXPORT gzbuffer(file, size) - gzFile file; - unsigned size; -{ +int ZEXPORT gzbuffer(gzFile file, unsigned size) { gz_statep state; /* get internal structure and check integrity */ @@ -335,16 +308,14 @@ int ZEXPORT gzbuffer(file, size) /* check and set requested size */ if ((size << 1) < size) return -1; /* need to be able to double it */ - if (size < 2) - size = 2; /* need two bytes to check magic header */ + if (size < 8) + size = 8; /* needed to behave well with flushing */ state->want = size; return 0; } /* -- see zlib.h -- */ -int ZEXPORT gzrewind(file) - gzFile file; -{ +int ZEXPORT gzrewind(gzFile file) { gz_statep state; /* get internal structure */ @@ -365,11 +336,7 @@ int ZEXPORT gzrewind(file) } /* -- see zlib.h -- */ -z_off64_t ZEXPORT gzseek64(file, offset, whence) - gzFile file; - z_off64_t offset; - int whence; -{ +z_off64_t ZEXPORT gzseek64(gzFile file, z_off64_t offset, int whence) { unsigned n; z_off64_t ret; gz_statep state; @@ -442,11 +409,7 @@ z_off64_t ZEXPORT gzseek64(file, offset, whence) } /* -- see zlib.h -- */ -z_off_t ZEXPORT gzseek(file, offset, whence) - gzFile file; - z_off_t offset; - int whence; -{ +z_off_t ZEXPORT gzseek(gzFile file, z_off_t offset, int whence) { z_off64_t ret; ret = gzseek64(file, (z_off64_t)offset, whence); @@ -454,9 +417,7 @@ z_off_t ZEXPORT gzseek(file, offset, whence) } /* -- see zlib.h -- */ -z_off64_t ZEXPORT gztell64(file) - gzFile file; -{ +z_off64_t ZEXPORT gztell64(gzFile file) { gz_statep state; /* get internal structure and check integrity */ @@ -471,9 +432,7 @@ z_off64_t ZEXPORT gztell64(file) } /* -- see zlib.h -- */ -z_off_t ZEXPORT gztell(file) - gzFile file; -{ +z_off_t ZEXPORT gztell(gzFile file) { z_off64_t ret; ret = gztell64(file); @@ -481,9 +440,7 @@ z_off_t ZEXPORT gztell(file) } /* -- see zlib.h -- */ -z_off64_t ZEXPORT gzoffset64(file) - gzFile file; -{ +z_off64_t ZEXPORT gzoffset64(gzFile file) { z_off64_t offset; gz_statep state; @@ -504,9 +461,7 @@ z_off64_t ZEXPORT gzoffset64(file) } /* -- see zlib.h -- */ -z_off_t ZEXPORT gzoffset(file) - gzFile file; -{ +z_off_t ZEXPORT gzoffset(gzFile file) { z_off64_t ret; ret = gzoffset64(file); @@ -514,9 +469,7 @@ z_off_t ZEXPORT gzoffset(file) } /* -- see zlib.h -- */ -int ZEXPORT gzeof(file) - gzFile file; -{ +int ZEXPORT gzeof(gzFile file) { gz_statep state; /* get internal structure and check integrity */ @@ -531,10 +484,7 @@ int ZEXPORT gzeof(file) } /* -- see zlib.h -- */ -const char * ZEXPORT gzerror(file, errnum) - gzFile file; - int *errnum; -{ +const char * ZEXPORT gzerror(gzFile file, int *errnum) { gz_statep state; /* get internal structure and check integrity */ @@ -552,9 +502,7 @@ const char * ZEXPORT gzerror(file, errnum) } /* -- see zlib.h -- */ -void ZEXPORT gzclearerr(file) - gzFile file; -{ +void ZEXPORT gzclearerr(gzFile file) { gz_statep state; /* get internal structure and check integrity */ @@ -578,11 +526,7 @@ void ZEXPORT gzclearerr(file) memory). Simply save the error message as a static string. If there is an allocation failure constructing the error message, then convert the error to out of memory. */ -void ZLIB_INTERNAL gz_error(state, err, msg) - gz_statep state; - int err; - const char *msg; -{ +void ZLIB_INTERNAL gz_error(gz_statep state, int err, const char *msg) { /* free previously allocated message and clear */ if (state->msg != NULL) { if (state->err != Z_MEM_ERROR) @@ -624,8 +568,7 @@ void ZLIB_INTERNAL gz_error(state, err, msg) available) -- we need to do this to cover cases where 2's complement not used, since C standard permits 1's complement and sign-bit representations, otherwise we could just use ((unsigned)-1) >> 1 */ -unsigned ZLIB_INTERNAL gz_intmax() -{ +unsigned ZLIB_INTERNAL gz_intmax(void) { unsigned p, q; p = 1; diff --git a/src/3rdparty/zlib/src/gzread.c b/src/3rdparty/zlib/src/gzread.c index dd77381596c..4168cbc8875 100644 --- a/src/3rdparty/zlib/src/gzread.c +++ b/src/3rdparty/zlib/src/gzread.c @@ -5,25 +5,12 @@ #include "gzguts.h" -/* Local functions */ -local int gz_load OF((gz_statep, unsigned char *, unsigned, unsigned *)); -local int gz_avail OF((gz_statep)); -local int gz_look OF((gz_statep)); -local int gz_decomp OF((gz_statep)); -local int gz_fetch OF((gz_statep)); -local int gz_skip OF((gz_statep, z_off64_t)); -local z_size_t gz_read OF((gz_statep, voidp, z_size_t)); - /* Use read() to load a buffer -- return -1 on error, otherwise 0. Read from state->fd, and update state->eof, state->err, and state->msg as appropriate. This function needs to loop on read(), since read() is not guaranteed to read the number of bytes requested, depending on the type of descriptor. */ -local int gz_load(state, buf, len, have) - gz_statep state; - unsigned char *buf; - unsigned len; - unsigned *have; -{ +local int gz_load(gz_statep state, unsigned char *buf, unsigned len, + unsigned *have) { int ret; unsigned get, max = ((unsigned)-1 >> 2) + 1; @@ -53,9 +40,7 @@ local int gz_load(state, buf, len, have) If strm->avail_in != 0, then the current data is moved to the beginning of the input buffer, and then the remainder of the buffer is loaded with the available data from the input file. */ -local int gz_avail(state) - gz_statep state; -{ +local int gz_avail(gz_statep state) { unsigned got; z_streamp strm = &(state->strm); @@ -88,9 +73,7 @@ local int gz_avail(state) case, all further file reads will be directly to either the output buffer or a user buffer. If decompressing, the inflate state will be initialized. gz_look() will return 0 on success or -1 on failure. */ -local int gz_look(state) - gz_statep state; -{ +local int gz_look(gz_statep state) { z_streamp strm = &(state->strm); /* allocate read buffers and inflate memory */ @@ -170,9 +153,7 @@ local int gz_look(state) data. If the gzip stream completes, state->how is reset to LOOK to look for the next gzip stream or raw data, once state->x.have is depleted. Returns 0 on success, -1 on failure. */ -local int gz_decomp(state) - gz_statep state; -{ +local int gz_decomp(gz_statep state) { int ret = Z_OK; unsigned had; z_streamp strm = &(state->strm); @@ -224,9 +205,7 @@ local int gz_decomp(state) looked for to determine whether to copy or decompress. Returns -1 on error, otherwise 0. gz_fetch() will leave state->how as COPY or GZIP unless the end of the input file has been reached and all data has been processed. */ -local int gz_fetch(state) - gz_statep state; -{ +local int gz_fetch(gz_statep state) { z_streamp strm = &(state->strm); do { @@ -254,10 +233,7 @@ local int gz_fetch(state) } /* Skip len uncompressed bytes of output. Return -1 on error, 0 on success. */ -local int gz_skip(state, len) - gz_statep state; - z_off64_t len; -{ +local int gz_skip(gz_statep state, z_off64_t len) { unsigned n; /* skip over len bytes or reach end-of-file, whichever comes first */ @@ -289,11 +265,7 @@ local int gz_skip(state, len) input. Return the number of bytes read. If zero is returned, either the end of file was reached, or there was an error. state->err must be consulted in that case to determine which. */ -local z_size_t gz_read(state, buf, len) - gz_statep state; - voidp buf; - z_size_t len; -{ +local z_size_t gz_read(gz_statep state, voidp buf, z_size_t len) { z_size_t got; unsigned n; @@ -370,11 +342,7 @@ local z_size_t gz_read(state, buf, len) } /* -- see zlib.h -- */ -int ZEXPORT gzread(file, buf, len) - gzFile file; - voidp buf; - unsigned len; -{ +int ZEXPORT gzread(gzFile file, voidp buf, unsigned len) { gz_statep state; /* get internal structure */ @@ -406,12 +374,7 @@ int ZEXPORT gzread(file, buf, len) } /* -- see zlib.h -- */ -z_size_t ZEXPORT gzfread(buf, size, nitems, file) - voidp buf; - z_size_t size; - z_size_t nitems; - gzFile file; -{ +z_size_t ZEXPORT gzfread(voidp buf, z_size_t size, z_size_t nitems, gzFile file) { z_size_t len; gz_statep state; @@ -442,9 +405,7 @@ z_size_t ZEXPORT gzfread(buf, size, nitems, file) #else # undef gzgetc #endif -int ZEXPORT gzgetc(file) - gzFile file; -{ +int ZEXPORT gzgetc(gzFile file) { unsigned char buf[1]; gz_statep state; @@ -469,17 +430,12 @@ int ZEXPORT gzgetc(file) return gz_read(state, buf, 1) < 1 ? -1 : buf[0]; } -int ZEXPORT gzgetc_(file) -gzFile file; -{ +int ZEXPORT gzgetc_(gzFile file) { return gzgetc(file); } /* -- see zlib.h -- */ -int ZEXPORT gzungetc(c, file) - int c; - gzFile file; -{ +int ZEXPORT gzungetc(int c, gzFile file) { gz_statep state; /* get internal structure */ @@ -487,6 +443,10 @@ int ZEXPORT gzungetc(c, file) return -1; state = (gz_statep)file; + /* in case this was just opened, set up the input buffer */ + if (state->mode == GZ_READ && state->how == LOOK && state->x.have == 0) + (void)gz_look(state); + /* check that we're reading and that there's no (serious) error */ if (state->mode != GZ_READ || (state->err != Z_OK && state->err != Z_BUF_ERROR)) @@ -536,11 +496,7 @@ int ZEXPORT gzungetc(c, file) } /* -- see zlib.h -- */ -char * ZEXPORT gzgets(file, buf, len) - gzFile file; - char *buf; - int len; -{ +char * ZEXPORT gzgets(gzFile file, char *buf, int len) { unsigned left, n; char *str; unsigned char *eol; @@ -600,9 +556,7 @@ char * ZEXPORT gzgets(file, buf, len) } /* -- see zlib.h -- */ -int ZEXPORT gzdirect(file) - gzFile file; -{ +int ZEXPORT gzdirect(gzFile file) { gz_statep state; /* get internal structure */ @@ -620,9 +574,7 @@ int ZEXPORT gzdirect(file) } /* -- see zlib.h -- */ -int ZEXPORT gzclose_r(file) - gzFile file; -{ +int ZEXPORT gzclose_r(gzFile file) { int ret, err; gz_statep state; diff --git a/src/3rdparty/zlib/src/gzwrite.c b/src/3rdparty/zlib/src/gzwrite.c index eb8a0e5893f..435b4621b53 100644 --- a/src/3rdparty/zlib/src/gzwrite.c +++ b/src/3rdparty/zlib/src/gzwrite.c @@ -5,18 +5,10 @@ #include "gzguts.h" -/* Local functions */ -local int gz_init OF((gz_statep)); -local int gz_comp OF((gz_statep, int)); -local int gz_zero OF((gz_statep, z_off64_t)); -local z_size_t gz_write OF((gz_statep, voidpc, z_size_t)); - /* Initialize state for writing a gzip file. Mark initialization by setting state->size to non-zero. Return -1 on a memory allocation failure, or 0 on success. */ -local int gz_init(state) - gz_statep state; -{ +local int gz_init(gz_statep state) { int ret; z_streamp strm = &(state->strm); @@ -70,10 +62,7 @@ local int gz_init(state) deflate() flush value. If flush is Z_FINISH, then the deflate() state is reset to start a new gzip stream. If gz->direct is true, then simply write to the output file without compressing, and ignore flush. */ -local int gz_comp(state, flush) - gz_statep state; - int flush; -{ +local int gz_comp(gz_statep state, int flush) { int ret, writ; unsigned have, put, max = ((unsigned)-1 >> 2) + 1; z_streamp strm = &(state->strm); @@ -151,10 +140,7 @@ local int gz_comp(state, flush) /* Compress len zeros to output. Return -1 on a write error or memory allocation failure by gz_comp(), or 0 on success. */ -local int gz_zero(state, len) - gz_statep state; - z_off64_t len; -{ +local int gz_zero(gz_statep state, z_off64_t len) { int first; unsigned n; z_streamp strm = &(state->strm); @@ -184,11 +170,7 @@ local int gz_zero(state, len) /* Write len bytes from buf to file. Return the number of bytes written. If the returned value is less than len, then there was an error. */ -local z_size_t gz_write(state, buf, len) - gz_statep state; - voidpc buf; - z_size_t len; -{ +local z_size_t gz_write(gz_statep state, voidpc buf, z_size_t len) { z_size_t put = len; /* if len is zero, avoid unnecessary operations */ @@ -252,11 +234,7 @@ local z_size_t gz_write(state, buf, len) } /* -- see zlib.h -- */ -int ZEXPORT gzwrite(file, buf, len) - gzFile file; - voidpc buf; - unsigned len; -{ +int ZEXPORT gzwrite(gzFile file, voidpc buf, unsigned len) { gz_statep state; /* get internal structure */ @@ -280,12 +258,8 @@ int ZEXPORT gzwrite(file, buf, len) } /* -- see zlib.h -- */ -z_size_t ZEXPORT gzfwrite(buf, size, nitems, file) - voidpc buf; - z_size_t size; - z_size_t nitems; - gzFile file; -{ +z_size_t ZEXPORT gzfwrite(voidpc buf, z_size_t size, z_size_t nitems, + gzFile file) { z_size_t len; gz_statep state; @@ -310,10 +284,7 @@ z_size_t ZEXPORT gzfwrite(buf, size, nitems, file) } /* -- see zlib.h -- */ -int ZEXPORT gzputc(file, c) - gzFile file; - int c; -{ +int ZEXPORT gzputc(gzFile file, int c) { unsigned have; unsigned char buf[1]; gz_statep state; @@ -358,10 +329,7 @@ int ZEXPORT gzputc(file, c) } /* -- see zlib.h -- */ -int ZEXPORT gzputs(file, s) - gzFile file; - const char *s; -{ +int ZEXPORT gzputs(gzFile file, const char *s) { z_size_t len, put; gz_statep state; @@ -388,8 +356,7 @@ int ZEXPORT gzputs(file, s) #include /* -- see zlib.h -- */ -int ZEXPORTVA gzvprintf(gzFile file, const char *format, va_list va) -{ +int ZEXPORTVA gzvprintf(gzFile file, const char *format, va_list va) { int len; unsigned left; char *next; @@ -460,8 +427,7 @@ int ZEXPORTVA gzvprintf(gzFile file, const char *format, va_list va) return len; } -int ZEXPORTVA gzprintf(gzFile file, const char *format, ...) -{ +int ZEXPORTVA gzprintf(gzFile file, const char *format, ...) { va_list va; int ret; @@ -474,13 +440,10 @@ int ZEXPORTVA gzprintf(gzFile file, const char *format, ...) #else /* !STDC && !Z_HAVE_STDARG_H */ /* -- see zlib.h -- */ -int ZEXPORTVA gzprintf(file, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, - a11, a12, a13, a14, a15, a16, a17, a18, a19, a20) - gzFile file; - const char *format; - int a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, - a11, a12, a13, a14, a15, a16, a17, a18, a19, a20; -{ +int ZEXPORTVA gzprintf(gzFile file, const char *format, int a1, int a2, int a3, + int a4, int a5, int a6, int a7, int a8, int a9, int a10, + int a11, int a12, int a13, int a14, int a15, int a16, + int a17, int a18, int a19, int a20) { unsigned len, left; char *next; gz_statep state; @@ -562,10 +525,7 @@ int ZEXPORTVA gzprintf(file, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, #endif /* -- see zlib.h -- */ -int ZEXPORT gzflush(file, flush) - gzFile file; - int flush; -{ +int ZEXPORT gzflush(gzFile file, int flush) { gz_statep state; /* get internal structure */ @@ -594,11 +554,7 @@ int ZEXPORT gzflush(file, flush) } /* -- see zlib.h -- */ -int ZEXPORT gzsetparams(file, level, strategy) - gzFile file; - int level; - int strategy; -{ +int ZEXPORT gzsetparams(gzFile file, int level, int strategy) { gz_statep state; z_streamp strm; @@ -609,7 +565,7 @@ int ZEXPORT gzsetparams(file, level, strategy) strm = &(state->strm); /* check that we're writing and that there's no error */ - if (state->mode != GZ_WRITE || state->err != Z_OK) + if (state->mode != GZ_WRITE || state->err != Z_OK || state->direct) return Z_STREAM_ERROR; /* if no change is requested, then do nothing */ @@ -636,9 +592,7 @@ int ZEXPORT gzsetparams(file, level, strategy) } /* -- see zlib.h -- */ -int ZEXPORT gzclose_w(file) - gzFile file; -{ +int ZEXPORT gzclose_w(gzFile file) { int ret = Z_OK; gz_statep state; diff --git a/src/3rdparty/zlib/src/infback.c b/src/3rdparty/zlib/src/infback.c index babeaf1806f..e7b25b307a3 100644 --- a/src/3rdparty/zlib/src/infback.c +++ b/src/3rdparty/zlib/src/infback.c @@ -15,9 +15,6 @@ #include "inflate.h" #include "inffast.h" -/* function prototypes */ -local void fixedtables OF((struct inflate_state FAR *state)); - /* strm provides memory allocation functions in zalloc and zfree, or Z_NULL to use the library memory allocation functions. @@ -25,13 +22,9 @@ local void fixedtables OF((struct inflate_state FAR *state)); windowBits is in the range 8..15, and window is a user-supplied window and output buffer that is 2**windowBits bytes. */ -int ZEXPORT inflateBackInit_(strm, windowBits, window, version, stream_size) -z_streamp strm; -int windowBits; -unsigned char FAR *window; -const char *version; -int stream_size; -{ +int ZEXPORT inflateBackInit_(z_streamp strm, int windowBits, + unsigned char FAR *window, const char *version, + int stream_size) { struct inflate_state FAR *state; if (version == Z_NULL || version[0] != ZLIB_VERSION[0] || @@ -80,9 +73,7 @@ int stream_size; 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; @@ -248,13 +239,8 @@ struct inflate_state FAR *state; inflateBack() can also return Z_STREAM_ERROR if the input parameters are not correct, i.e. strm is Z_NULL or the state was not initialized. */ -int ZEXPORT inflateBack(strm, in, in_desc, out, out_desc) -z_streamp strm; -in_func in; -void FAR *in_desc; -out_func out; -void FAR *out_desc; -{ +int ZEXPORT inflateBack(z_streamp strm, in_func in, void FAR *in_desc, + out_func out, void FAR *out_desc) { struct inflate_state FAR *state; z_const unsigned char FAR *next; /* next input */ unsigned char FAR *put; /* next output */ @@ -632,9 +618,7 @@ void FAR *out_desc; return ret; } -int ZEXPORT inflateBackEnd(strm) -z_streamp strm; -{ +int ZEXPORT inflateBackEnd(z_streamp strm) { if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0) return Z_STREAM_ERROR; ZFREE(strm, strm->state); diff --git a/src/3rdparty/zlib/src/inffast.c b/src/3rdparty/zlib/src/inffast.c index 1fec7f363fa..9354676e786 100644 --- a/src/3rdparty/zlib/src/inffast.c +++ b/src/3rdparty/zlib/src/inffast.c @@ -47,10 +47,7 @@ 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 */ diff --git a/src/3rdparty/zlib/src/inffast.h b/src/3rdparty/zlib/src/inffast.h index e5c1aa4ca8c..49c6d156c5c 100644 --- a/src/3rdparty/zlib/src/inffast.h +++ b/src/3rdparty/zlib/src/inffast.h @@ -8,4 +8,4 @@ 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); diff --git a/src/3rdparty/zlib/src/inflate.c b/src/3rdparty/zlib/src/inflate.c index 8acbef44e99..b0757a9b249 100644 --- a/src/3rdparty/zlib/src/inflate.c +++ b/src/3rdparty/zlib/src/inflate.c @@ -91,20 +91,7 @@ # 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) @@ -116,9 +103,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; @@ -142,9 +127,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; @@ -155,10 +138,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; @@ -195,12 +175,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; @@ -239,22 +215,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; @@ -278,9 +249,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; @@ -342,7 +311,7 @@ struct inflate_state FAR *state; a.out > inffixed.h */ -void makefixed() +void makefixed(void) { unsigned low, size; struct inflate_state state; @@ -396,11 +365,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; @@ -622,10 +587,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 */ @@ -1301,9 +1263,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; @@ -1315,11 +1275,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 */ @@ -1338,11 +1295,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; @@ -1373,10 +1327,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 */ @@ -1401,11 +1352,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; @@ -1424,9 +1372,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 */ @@ -1482,9 +1428,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; @@ -1492,10 +1436,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; @@ -1539,10 +1480,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; @@ -1557,10 +1495,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; @@ -1572,9 +1507,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)) @@ -1585,9 +1518,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/3rdparty/zlib/src/inftrees.c b/src/3rdparty/zlib/src/inftrees.c index 57d2793bec9..8a208c2daa8 100644 --- a/src/3rdparty/zlib/src/inftrees.c +++ b/src/3rdparty/zlib/src/inftrees.c @@ -1,5 +1,5 @@ /* 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 */ @@ -9,7 +9,7 @@ #define MAXBITS 15 const char inflate_copyright[] = - " inflate 1.2.13 Copyright 1995-2022 Mark Adler "; + " inflate 1.3 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 @@ -29,14 +29,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 */ @@ -62,7 +57,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, 198, 203}; 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, diff --git a/src/3rdparty/zlib/src/inftrees.h b/src/3rdparty/zlib/src/inftrees.h index f53665311c1..a10712d8cb5 100644 --- a/src/3rdparty/zlib/src/inftrees.h +++ b/src/3rdparty/zlib/src/inftrees.h @@ -57,6 +57,6 @@ 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); diff --git a/src/3rdparty/zlib/src/trees.c b/src/3rdparty/zlib/src/trees.c index 5f305c47221..8dbdc40bacc 100644 --- a/src/3rdparty/zlib/src/trees.c +++ b/src/3rdparty/zlib/src/trees.c @@ -122,39 +122,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)); \ +} -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)); +/* =========================================================================== + * 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); + + 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 @@ -167,27 +244,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; @@ -229,8 +291,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 */ @@ -323,8 +384,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; @@ -373,12 +433,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; @@ -401,24 +475,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 */ @@ -448,11 +504,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) { @@ -483,10 +535,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; @@ -561,48 +610,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. @@ -612,10 +622,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; @@ -700,11 +707,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 */ @@ -745,11 +748,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 */ @@ -796,9 +795,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 */ @@ -831,10 +828,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"); @@ -860,12 +855,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); @@ -884,9 +875,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); } @@ -894,9 +883,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 @@ -905,16 +892,99 @@ 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 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(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 */ @@ -1011,11 +1081,7 @@ 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) { 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; @@ -1035,147 +1101,3 @@ 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 -} diff --git a/src/3rdparty/zlib/src/uncompr.c b/src/3rdparty/zlib/src/uncompr.c index f9532f46c1a..5e256663b45 100644 --- a/src/3rdparty/zlib/src/uncompr.c +++ b/src/3rdparty/zlib/src/uncompr.c @@ -24,12 +24,8 @@ 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; @@ -83,11 +79,7 @@ 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); } diff --git a/src/3rdparty/zlib/src/zconf.h b/src/3rdparty/zlib/src/zconf.h index a0997ab0e90..18be576f50d 100644 --- a/src/3rdparty/zlib/src/zconf.h +++ b/src/3rdparty/zlib/src/zconf.h @@ -245,7 +245,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) @@ -524,7 +528,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 diff --git a/src/3rdparty/zlib/src/zlib.h b/src/3rdparty/zlib/src/zlib.h index b06a50c5caa..ffe3b177e29 100644 --- a/src/3rdparty/zlib/src/zlib.h +++ b/src/3rdparty/zlib/src/zlib.h @@ -1,7 +1,7 @@ /* zlib.h -- interface of the 'zlib' general purpose compression library - version 1.2.13, October 13th, 2022 + version 1.3, August 18th, 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 @@ -41,11 +41,11 @@ extern "C" { #endif -#define ZLIB_VERSION "1.2.13 (Qt)" -#define ZLIB_VERNUM 0x12d0 +#define ZLIB_VERSION "1.3 (Qt)" +#define ZLIB_VERNUM 0x1300 #define ZLIB_VER_MAJOR 1 -#define ZLIB_VER_MINOR 2 -#define ZLIB_VER_REVISION 13 +#define ZLIB_VER_MINOR 3 +#define ZLIB_VER_REVISION 0 #define ZLIB_VER_SUBREVISION 0 /* @@ -82,8 +82,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; @@ -221,7 +221,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 @@ -229,12 +229,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 @@ -251,7 +251,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 @@ -324,8 +324,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 @@ -364,7 +364,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 @@ -379,7 +379,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 @@ -387,7 +387,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 @@ -401,7 +402,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 @@ -521,7 +522,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 @@ -539,12 +540,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. @@ -611,9 +612,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 @@ -655,9 +656,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 @@ -677,8 +678,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. @@ -695,20 +696,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 @@ -733,7 +734,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 @@ -744,11 +745,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 @@ -761,8 +762,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 @@ -776,9 +777,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 @@ -791,9 +792,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 @@ -808,8 +809,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 @@ -825,16 +826,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 @@ -887,9 +889,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, @@ -910,9 +912,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 @@ -925,7 +927,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 @@ -944,8 +946,8 @@ ZEXTERN int ZEXPORT inflateSync OF((z_streamp strm)); 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. @@ -960,18 +962,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 @@ -984,9 +987,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 @@ -1005,7 +1008,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 @@ -1033,8 +1036,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 @@ -1074,8 +1077,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 @@ -1095,13 +1098,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 @@ -1169,7 +1172,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. @@ -1177,7 +1180,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: @@ -1230,8 +1233,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 @@ -1245,9 +1248,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 @@ -1261,15 +1264,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 @@ -1286,8 +1289,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 @@ -1306,7 +1309,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") @@ -1343,7 +1346,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 @@ -1366,7 +1369,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 @@ -1382,7 +1385,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 @@ -1393,7 +1396,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 @@ -1423,8 +1426,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 @@ -1449,14 +1452,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 @@ -1469,7 +1472,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 @@ -1484,7 +1487,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. @@ -1492,7 +1495,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 @@ -1506,13 +1509,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. @@ -1521,7 +1524,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. @@ -1533,7 +1536,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 @@ -1549,8 +1552,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 @@ -1568,7 +1571,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. @@ -1576,7 +1579,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, @@ -1587,7 +1590,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 @@ -1596,7 +1599,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 @@ -1611,7 +1614,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. @@ -1632,7 +1635,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 @@ -1645,8 +1648,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 @@ -1657,7 +1660,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 @@ -1673,7 +1676,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 @@ -1690,7 +1693,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 @@ -1710,15 +1713,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 @@ -1728,7 +1731,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. @@ -1746,14 +1749,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 @@ -1763,13 +1766,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 @@ -1782,20 +1785,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)) @@ -1840,7 +1843,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) \ @@ -1857,13 +1860,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) @@ -1885,50 +1888,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 diff --git a/src/3rdparty/zlib/src/zutil.c b/src/3rdparty/zlib/src/zutil.c index 9543ae825e3..b1c5d2d3c6d 100644 --- a/src/3rdparty/zlib/src/zutil.c +++ b/src/3rdparty/zlib/src/zutil.c @@ -24,13 +24,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; @@ -121,9 +119,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); } @@ -132,9 +128,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); } @@ -148,22 +142,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++) { @@ -172,10 +158,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 */ @@ -216,8 +199,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; @@ -242,8 +224,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; @@ -279,14 +260,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); } @@ -299,25 +278,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); } diff --git a/src/3rdparty/zlib/src/zutil.h b/src/3rdparty/zlib/src/zutil.h index 14aba921b0c..9253060f74d 100644 --- a/src/3rdparty/zlib/src/zutil.h +++ b/src/3rdparty/zlib/src/zutil.h @@ -204,9 +204,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 */ @@ -245,16 +245,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 ;} @@ -271,9 +271,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) \ From 92057f7f295b0b0d0acb66f53595940da2571c05 Mon Sep 17 00:00:00 2001 From: Volker Hilsheimer Date: Tue, 20 Jun 2023 11:17:01 +0200 Subject: [PATCH 131/151] QLineEdit: ignore key release events Amends 55fe46fd58c73a7a22374694a1b45ec2a0e6fdc5. Before that change, key release events were ignored as the QLineEdit::event reimplementation continued to call QWidget::event, and as QLineEdit didn't override keyReleaseEvent, the default implementation in QWidget got called to ignore the event. Restore that behavior by explicitly calling the QWidget implementation after updating QLineEdit-specific states, and add a test case. Fixes: QTBUG-114654 Change-Id: Ic8aa35a1c915b446aece47aaf03ef5cf1884b936 Reviewed-by: Axel Spoerl (cherry picked from commit 8afe4faf298798783278f992d14fb78cecee9588) Reviewed-by: Volker Hilsheimer --- src/widgets/widgets/qlineedit.cpp | 3 +- .../widgets/qlineedit/tst_qlineedit.cpp | 40 +++++++++++++++++++ 2 files changed, 42 insertions(+), 1 deletion(-) diff --git a/src/widgets/widgets/qlineedit.cpp b/src/widgets/widgets/qlineedit.cpp index 87a019f4e0d..bacd9a5b347 100644 --- a/src/widgets/widgets/qlineedit.cpp +++ b/src/widgets/widgets/qlineedit.cpp @@ -1781,12 +1781,13 @@ void QLineEdit::keyPressEvent(QKeyEvent *event) /*! \reimp */ -void QLineEdit::keyReleaseEvent(QKeyEvent *) +void QLineEdit::keyReleaseEvent(QKeyEvent *e) { Q_D(QLineEdit); if (!isReadOnly()) d->handleSoftwareInputPanel(); d->control->updateCursorBlinking(); + QWidget::keyReleaseEvent(e); } /*! diff --git a/tests/auto/widgets/widgets/qlineedit/tst_qlineedit.cpp b/tests/auto/widgets/widgets/qlineedit/tst_qlineedit.cpp index db05c8fde1a..e4135d654ab 100644 --- a/tests/auto/widgets/widgets/qlineedit/tst_qlineedit.cpp +++ b/tests/auto/widgets/widgets/qlineedit/tst_qlineedit.cpp @@ -315,6 +315,8 @@ private slots: void QTBUG_60319_setInputMaskCheckImSurroundingText(); void testQuickSelectionWithMouse(); void inputRejected(); + void keyReleasePropagates(); + protected slots: void editingFinished(); @@ -5168,5 +5170,43 @@ void tst_QLineEdit::inputRejected() QCOMPARE(spyInputRejected.count(), 2); } +void tst_QLineEdit::keyReleasePropagates() +{ + struct Dialog : QWidget + { + QLineEdit *lineEdit; + int releasedKey = {}; + + Dialog() + { + lineEdit = new QLineEdit; + QHBoxLayout *hbox = new QHBoxLayout; + + hbox->addWidget(lineEdit); + setLayout(hbox); + } + + protected: + void keyReleaseEvent(QKeyEvent *e) + { + releasedKey = e->key(); + } + } dialog; + + dialog.show(); + QVERIFY(QTest::qWaitForWindowExposed(&dialog)); + + QTest::keyPress(dialog.lineEdit, Qt::Key_A); + QTest::keyRelease(dialog.lineEdit, Qt::Key_A); + + QCOMPARE(dialog.releasedKey, Qt::Key_A); + + QTest::keyPress(dialog.lineEdit, Qt::Key_Alt); + QTest::keyRelease(dialog.lineEdit, Qt::Key_Alt); + + QCOMPARE(dialog.releasedKey, Qt::Key_Alt); +} + + QTEST_MAIN(tst_QLineEdit) #include "tst_qlineedit.moc" From 3fe5ac02a2d8b3ce034c4119d9ec1365b9372b41 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kai=20K=C3=B6hne?= Date: Mon, 4 Sep 2023 16:46:32 +0200 Subject: [PATCH 132/151] Mark linux_perf_event with GPL-2.0-only "GPL-2.0" as a SPDX identifier is deprecated in SPDX 3. Use the more explicit GPL-2.0-only instead. Change-Id: Ie543135ad1d73205f7a94db140189f5132098ea2 Reviewed-by: Thiago Macieira Reviewed-by: Joerg Bornemann (cherry picked from commit 8550d60acaead1f5a148f8e8e8384798dc6cd071) --- src/testlib/3rdparty/qt_attribution.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/testlib/3rdparty/qt_attribution.json b/src/testlib/3rdparty/qt_attribution.json index 4dd844c232d..c122a39b72b 100644 --- a/src/testlib/3rdparty/qt_attribution.json +++ b/src/testlib/3rdparty/qt_attribution.json @@ -40,7 +40,7 @@ Copyright (c) 2003, 2006 Massachusetts Institute of Technology" "Homepage": "https://www.kernel.org", "Version": "3.7", "License": "GNU General Public License v2.0 only with Linux Syscall Note", - "LicenseId": "GPL-2.0 WITH Linux-syscall-note", + "LicenseId": "GPL-2.0-only WITH Linux-syscall-note", "LicenseFile": "LINUX_LICENSE.txt", "Copyright": "Copyright (C) 2008-2009, Thomas Gleixner Copyright (C) 2008-2011, Red Hat, Inc., Ingo Molnar From ffef3f47d1f906b3154b7d42207fbbb551ef945f Mon Sep 17 00:00:00 2001 From: Ivan Solovev Date: Mon, 4 Sep 2023 12:51:33 +0200 Subject: [PATCH 133/151] QCborValue: add benchmark for operator[] In order to test the impact of migration to QASV. Task-number: QTBUG-101707 Change-Id: I17f84ca98fc87d89bb4cd6ad98c8a12aecd315ee Reviewed-by: Thiago Macieira (cherry picked from commit 516d828f240c3166a057372dde6cbec4ea6d380a) Reviewed-by: Marc Mutz --- tests/benchmarks/corelib/CMakeLists.txt | 1 + .../corelib/serialization/CMakeLists.txt | 4 ++ .../serialization/qcborvalue/CMakeLists.txt | 10 +++ .../qcborvalue/tst_bench_qcborvalue.cpp | 72 +++++++++++++++++++ 4 files changed, 87 insertions(+) create mode 100644 tests/benchmarks/corelib/serialization/CMakeLists.txt create mode 100644 tests/benchmarks/corelib/serialization/qcborvalue/CMakeLists.txt create mode 100644 tests/benchmarks/corelib/serialization/qcborvalue/tst_bench_qcborvalue.cpp diff --git a/tests/benchmarks/corelib/CMakeLists.txt b/tests/benchmarks/corelib/CMakeLists.txt index ff308621805..4569a11521f 100644 --- a/tests/benchmarks/corelib/CMakeLists.txt +++ b/tests/benchmarks/corelib/CMakeLists.txt @@ -10,3 +10,4 @@ add_subdirectory(thread) add_subdirectory(time) add_subdirectory(tools) add_subdirectory(plugin) +add_subdirectory(serialization) diff --git a/tests/benchmarks/corelib/serialization/CMakeLists.txt b/tests/benchmarks/corelib/serialization/CMakeLists.txt new file mode 100644 index 00000000000..98343d7688b --- /dev/null +++ b/tests/benchmarks/corelib/serialization/CMakeLists.txt @@ -0,0 +1,4 @@ +# Copyright (C) 2023 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +add_subdirectory(qcborvalue) diff --git a/tests/benchmarks/corelib/serialization/qcborvalue/CMakeLists.txt b/tests/benchmarks/corelib/serialization/qcborvalue/CMakeLists.txt new file mode 100644 index 00000000000..6ada5b983d1 --- /dev/null +++ b/tests/benchmarks/corelib/serialization/qcborvalue/CMakeLists.txt @@ -0,0 +1,10 @@ +# Copyright (C) 2023 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +qt_internal_add_benchmark(tst_bench_qcborvalue + SOURCES + tst_bench_qcborvalue.cpp + LIBRARIES + Qt::Core + Qt::Test +) diff --git a/tests/benchmarks/corelib/serialization/qcborvalue/tst_bench_qcborvalue.cpp b/tests/benchmarks/corelib/serialization/qcborvalue/tst_bench_qcborvalue.cpp new file mode 100644 index 00000000000..292817fcb8a --- /dev/null +++ b/tests/benchmarks/corelib/serialization/qcborvalue/tst_bench_qcborvalue.cpp @@ -0,0 +1,72 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + +#include +#include + +#include + +template +struct SampleStrings +{ + static constexpr char key[] = "hello"; +}; + +template <> +struct SampleStrings +{ + static constexpr char16_t key[] = u"hello"; +}; + +template <> +struct SampleStrings +{ + static const QChar *const key; +}; +const QChar *const SampleStrings::key = + reinterpret_cast(SampleStrings::key); + +template +constexpr bool hasValueType = false; + +template +constexpr bool hasValueType> = true; + +class tst_QCborValue : public QObject +{ + Q_OBJECT +private: + template + void doKeyLookup(); + +private slots: + void keyLookupLatin1() { doKeyLookup(); } + void keyLookupString() { doKeyLookup(); } + void keyLookupConstCharPtr() { doKeyLookup(); }; +}; + +template +void tst_QCborValue::doKeyLookup() +{ + const QCborMap m{{"hello", "world"}, {1, 2}}; + const QCborValue v = m; + + if constexpr (hasValueType) { + using Char = std::remove_cv_t; + using Strings = SampleStrings; + const Type s(Strings::key); + QBENCHMARK { + const QCborValue r = v[s]; + Q_UNUSED(r); + } + } else { + QBENCHMARK { + const QCborValue r = v[SampleStrings::key]; + Q_UNUSED(r); + } + } +} + +QTEST_MAIN(tst_QCborValue) + +#include "tst_bench_qcborvalue.moc" From 896c40514164c6cab743fb3ba0d15f31e4be2d7c Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Tue, 15 Aug 2023 09:23:15 +0200 Subject: [PATCH 134/151] tst_QHashFunctions: test with actual 64-bit seeds The old code only tested with seed = 0 and seed = 1045982819, the latter being a "random number", which, however, fits into 32-bits. Since Qt 6.0 increased the seed from uint to size_t, amend the test to actually test a seed value with some of the upper half of bits set, too, also in 64-bit mode. While we're at it, also test with each seed's bits flipped for extra coverage. Remove a static assertion that prevented testing seeds with the MSB set. Change-Id: I5ed6ffb5cabaaead0eb9c01f994d15dcbc622509 Reviewed-by: Thiago Macieira Reviewed-by: Ivan Solovev (cherry picked from commit 8ca319a172b84207be404ed3bb619c3548a802da) Reviewed-by: Qt Cherry-pick Bot --- .../qhashfunctions/tst_qhashfunctions.cpp | 28 +++++++++++-------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/tests/auto/corelib/tools/qhashfunctions/tst_qhashfunctions.cpp b/tests/auto/corelib/tools/qhashfunctions/tst_qhashfunctions.cpp index 63807cad106..76d7df91358 100644 --- a/tests/auto/corelib/tools/qhashfunctions/tst_qhashfunctions.cpp +++ b/tests/auto/corelib/tools/qhashfunctions/tst_qhashfunctions.cpp @@ -40,11 +40,11 @@ class tst_QHashFunctions : public QObject { Q_OBJECT public: - enum { - // random value - RandomSeed = 1045982819 - }; - uint seed; + // random values + static constexpr quint64 ZeroSeed = 0; + static constexpr quint64 RandomSeed32 = 1045982819; + static constexpr quint64 RandomSeed64 = QtPrivate::QHashCombine{}(RandomSeed32, RandomSeed32); + size_t seed; template void stdPair_template(const T1 &t1, const T2 &t2); @@ -89,17 +89,23 @@ void tst_QHashFunctions::consistent() void tst_QHashFunctions::initTestCase() { - static_assert(int(RandomSeed) > 0); + QTest::addColumn("seedValue"); - QTest::addColumn("seedValue"); - QTest::newRow("zero-seed") << 0U; - QTest::newRow("non-zero-seed") << uint(RandomSeed); + QTest::newRow("zero-seed") << ZeroSeed; + QTest::newRow("zero-seed-negated") << ~ZeroSeed; + QTest::newRow("non-zero-seed-32bit") << RandomSeed32; + QTest::newRow("non-zero-seed-32bit-negated") + << quint64{~quint32(RandomSeed32)}; // ensure this->seed gets same value on 32/64-bit + if constexpr (sizeof(size_t) == sizeof(quint64)) { + QTest::newRow("non-zero-seed-64bit") << RandomSeed64; + QTest::newRow("non-zero-seed-64bit-negated") << ~RandomSeed64; + } } void tst_QHashFunctions::init() { - QFETCH_GLOBAL(uint, seedValue); - seed = seedValue; + QFETCH_GLOBAL(quint64, seedValue); + seed = size_t(seedValue); } void tst_QHashFunctions::qhash() From 33e52d85f304487067177844aa428de10945a646 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Wed, 6 Sep 2023 18:43:36 +0200 Subject: [PATCH 135/151] tst_QHashFunctions: fix std::pair test to use QFETCH_GLOBAL seeds Because the local `seed` variable shadowed the member one, this test was run for each QFETCH_GLOBAL with the same data and seed. That doesn't make sense, so make the test use the member variable `seed`, as all other tests already do. Since zero is one of the seeds coming from QFETCH_GLOBAL, drop the seedless calls to qHash(), too. Amends 64bfc927b09b46bb7fc0dc6caf1bf1a4d4133ab4. Change-Id: I1e22ec0b38341264bcf2d5c26146cbbcab6e0749 Reviewed-by: Thiago Macieira (cherry picked from commit 9c63667d01eb13f43d3b51a8a3502bfc233d6b0b) Reviewed-by: Qt Cherry-pick Bot --- .../corelib/tools/qhashfunctions/tst_qhashfunctions.cpp | 6 ------ 1 file changed, 6 deletions(-) diff --git a/tests/auto/corelib/tools/qhashfunctions/tst_qhashfunctions.cpp b/tests/auto/corelib/tools/qhashfunctions/tst_qhashfunctions.cpp index 76d7df91358..de4cb99b30b 100644 --- a/tests/auto/corelib/tools/qhashfunctions/tst_qhashfunctions.cpp +++ b/tests/auto/corelib/tools/qhashfunctions/tst_qhashfunctions.cpp @@ -380,13 +380,9 @@ void tst_QHashFunctions::stdPair_template(const T1 &t1, const T2 &t2) std::pair dpair{}; std::pair vpair{t1, t2}; - size_t seed = QHashSeed::globalSeed(); - // confirm proper working of the pair and of the underlying types QVERIFY(t1 == t1); QVERIFY(t2 == t2); - QCOMPARE(qHash(t1), qHash(t1)); - QCOMPARE(qHash(t2), qHash(t2)); QCOMPARE(qHash(t1, seed), qHash(t1, seed)); QCOMPARE(qHash(t2, seed), qHash(t2, seed)); @@ -394,9 +390,7 @@ void tst_QHashFunctions::stdPair_template(const T1 &t1, const T2 &t2) QVERIFY(vpair == vpair); // therefore their hashes should be equal - QCOMPARE(qHash(dpair), qHash(dpair)); QCOMPARE(qHash(dpair, seed), qHash(dpair, seed)); - QCOMPARE(qHash(vpair), qHash(vpair)); QCOMPARE(qHash(vpair, seed), qHash(vpair, seed)); } From 4bc95ebf503f2533163769af9b851bdaa39f84ae Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Tue, 15 Aug 2023 10:46:23 +0200 Subject: [PATCH 136/151] Update to Harfbuzz 8.1.1 Change-Id: I886bc7d385e62ff0c9546c18bb7bb9273ef1cbd1 Reviewed-by: Qt CI Bot Reviewed-by: Volker Hilsheimer (cherry picked from commit 9266b6d0914a31215d8505a363ecfd8f80b744eb) --- src/3rdparty/harfbuzz-ng/NEWS | 78 + src/3rdparty/harfbuzz-ng/README.md | 7 +- src/3rdparty/harfbuzz-ng/qt_attribution.json | 2 +- .../harfbuzz-ng/src/OT/Color/CBDT/CBDT.hh | 11 +- .../harfbuzz-ng/src/OT/Color/COLR/COLR.hh | 4 +- .../harfbuzz-ng/src/OT/Color/sbix/sbix.hh | 5 - .../src/OT/Layout/Common/Coverage.hh | 3 + .../src/OT/Layout/Common/CoverageFormat1.hh | 2 +- .../src/OT/Layout/Common/CoverageFormat2.hh | 2 +- .../harfbuzz-ng/src/OT/Layout/GDEF/GDEF.hh | 36 +- .../src/OT/Layout/GPOS/AnchorFormat3.hh | 9 +- .../src/OT/Layout/GPOS/AnchorMatrix.hh | 15 +- .../src/OT/Layout/GPOS/CursivePosFormat1.hh | 21 +- .../src/OT/Layout/GPOS/MarkArray.hh | 2 +- .../src/OT/Layout/GPOS/MarkMarkPosFormat1.hh | 2 +- .../src/OT/Layout/GPOS/PairPosFormat1.hh | 2 +- .../src/OT/Layout/GPOS/PairPosFormat2.hh | 13 +- .../harfbuzz-ng/src/OT/Layout/GPOS/PairSet.hh | 5 +- .../src/OT/Layout/GPOS/PairValueRecord.hh | 2 +- .../src/OT/Layout/GPOS/SinglePosFormat1.hh | 3 +- .../src/OT/Layout/GPOS/SinglePosFormat2.hh | 3 +- .../src/OT/Layout/GPOS/ValueFormat.hh | 64 +- .../harfbuzz-ng/src/OT/Layout/GSUB/Common.hh | 2 - .../src/OT/Layout/GSUB/Ligature.hh | 2 +- .../src/OT/Layout/GSUB/LigatureSet.hh | 19 +- .../GSUB/ReverseChainSingleSubstFormat1.hh | 1 - .../src/OT/Layout/GSUB/Sequence.hh | 2 +- .../harfbuzz-ng/src/OT/glyf/CompositeGlyph.hh | 41 +- src/3rdparty/harfbuzz-ng/src/OT/glyf/Glyph.hh | 40 +- .../harfbuzz-ng/src/OT/glyf/SimpleGlyph.hh | 12 +- .../harfbuzz-ng/src/OT/glyf/SubsetGlyph.hh | 4 +- .../src/OT/glyf/VarCompositeGlyph.hh | 2 +- .../harfbuzz-ng/src/OT/glyf/coord-setter.hh | 2 + .../harfbuzz-ng/src/OT/glyf/glyf-helpers.hh | 67 +- src/3rdparty/harfbuzz-ng/src/OT/glyf/glyf.hh | 82 +- .../harfbuzz-ng/src/OT/glyf/path-builder.hh | 23 +- src/3rdparty/harfbuzz-ng/src/OT/name/name.hh | 19 +- .../harfbuzz-ng/src/graph/classdef-graph.hh | 10 +- .../harfbuzz-ng/src/graph/coverage-graph.hh | 10 +- src/3rdparty/harfbuzz-ng/src/graph/graph.hh | 220 +- .../harfbuzz-ng/src/graph/gsubgpos-context.cc | 6 +- .../harfbuzz-ng/src/graph/gsubgpos-context.hh | 4 +- .../harfbuzz-ng/src/graph/gsubgpos-graph.hh | 18 +- .../harfbuzz-ng/src/graph/pairpos-graph.hh | 12 +- .../harfbuzz-ng/src/graph/serialize.hh | 3 + .../src/graph/test-classdef-graph.cc | 2 +- src/3rdparty/harfbuzz-ng/src/harfbuzz.cc | 2 + .../src/hb-aat-layout-trak-table.hh | 4 +- src/3rdparty/harfbuzz-ng/src/hb-algs.hh | 183 +- src/3rdparty/harfbuzz-ng/src/hb-array.hh | 70 +- src/3rdparty/harfbuzz-ng/src/hb-atomic.hh | 1 + src/3rdparty/harfbuzz-ng/src/hb-bimap.hh | 75 +- src/3rdparty/harfbuzz-ng/src/hb-bit-page.hh | 37 +- .../harfbuzz-ng/src/hb-bit-set-invertible.hh | 7 +- src/3rdparty/harfbuzz-ng/src/hb-bit-set.hh | 25 +- .../harfbuzz-ng/src/hb-buffer-verify.cc | 76 +- src/3rdparty/harfbuzz-ng/src/hb-buffer.cc | 6 +- src/3rdparty/harfbuzz-ng/src/hb-buffer.hh | 15 +- src/3rdparty/harfbuzz-ng/src/hb-cache.hh | 8 +- .../harfbuzz-ng/src/hb-cairo-utils.cc | 4 +- src/3rdparty/harfbuzz-ng/src/hb-cairo.cc | 2 +- .../harfbuzz-ng/src/hb-cff-interp-common.hh | 4 +- .../src/hb-cff-interp-cs-common.hh | 8 +- src/3rdparty/harfbuzz-ng/src/hb-common.h | 10 + src/3rdparty/harfbuzz-ng/src/hb-config.hh | 3 +- src/3rdparty/harfbuzz-ng/src/hb-debug.hh | 4 + src/3rdparty/harfbuzz-ng/src/hb-deprecated.h | 46 + src/3rdparty/harfbuzz-ng/src/hb-draw.hh | 30 +- src/3rdparty/harfbuzz-ng/src/hb-font.cc | 7 +- src/3rdparty/harfbuzz-ng/src/hb-font.h | 45 +- src/3rdparty/harfbuzz-ng/src/hb-ft.cc | 2 +- .../harfbuzz-ng/src/hb-gobject-structs.cc | 2 +- src/3rdparty/harfbuzz-ng/src/hb-graphite2.cc | 42 +- src/3rdparty/harfbuzz-ng/src/hb-iter.hh | 9 +- src/3rdparty/harfbuzz-ng/src/hb-kern.hh | 4 +- src/3rdparty/harfbuzz-ng/src/hb-limits.hh | 4 + src/3rdparty/harfbuzz-ng/src/hb-machinery.hh | 11 +- src/3rdparty/harfbuzz-ng/src/hb-map.h | 2 +- src/3rdparty/harfbuzz-ng/src/hb-map.hh | 188 +- src/3rdparty/harfbuzz-ng/src/hb-meta.hh | 8 +- src/3rdparty/harfbuzz-ng/src/hb-multimap.hh | 34 +- src/3rdparty/harfbuzz-ng/src/hb-null.hh | 8 +- src/3rdparty/harfbuzz-ng/src/hb-open-file.hh | 4 +- src/3rdparty/harfbuzz-ng/src/hb-open-type.hh | 39 +- .../harfbuzz-ng/src/hb-ot-cff-common.hh | 269 ++- .../harfbuzz-ng/src/hb-ot-cff1-table.cc | 6 +- .../harfbuzz-ng/src/hb-ot-cff1-table.hh | 288 ++- .../harfbuzz-ng/src/hb-ot-cff2-table.hh | 35 +- .../harfbuzz-ng/src/hb-ot-cmap-table.hh | 38 +- src/3rdparty/harfbuzz-ng/src/hb-ot-font.cc | 14 +- .../harfbuzz-ng/src/hb-ot-hdmx-table.hh | 43 +- .../harfbuzz-ng/src/hb-ot-hmtx-table.hh | 80 +- .../src/hb-ot-layout-base-table.hh | 21 +- .../harfbuzz-ng/src/hb-ot-layout-common.hh | 173 +- .../harfbuzz-ng/src/hb-ot-layout-gsubgpos.hh | 563 +++-- src/3rdparty/harfbuzz-ng/src/hb-ot-layout.cc | 235 +- src/3rdparty/harfbuzz-ng/src/hb-ot-layout.h | 37 + src/3rdparty/harfbuzz-ng/src/hb-ot-layout.hh | 14 +- src/3rdparty/harfbuzz-ng/src/hb-ot-map.cc | 30 +- src/3rdparty/harfbuzz-ng/src/hb-ot-map.hh | 8 + .../harfbuzz-ng/src/hb-ot-math-table.hh | 13 +- .../harfbuzz-ng/src/hb-ot-os2-table.hh | 7 +- .../src/hb-ot-post-table-v2subset.hh | 12 +- .../harfbuzz-ng/src/hb-ot-post-table.hh | 5 +- src/3rdparty/harfbuzz-ng/src/hb-ot-shape.cc | 26 +- .../src/hb-ot-shaper-arabic-fallback.hh | 2 +- .../src/hb-ot-shaper-indic-machine.hh | 14 +- .../harfbuzz-ng/src/hb-ot-shaper-syllabic.cc | 12 + .../src/hb-ot-shaper-use-machine.hh | 1925 +++++++++-------- .../harfbuzz-ng/src/hb-ot-shaper-use.cc | 3 + .../harfbuzz-ng/src/hb-ot-stat-table.hh | 53 +- src/3rdparty/harfbuzz-ng/src/hb-ot-tag.cc | 2 +- .../harfbuzz-ng/src/hb-ot-var-avar-table.hh | 164 ++ .../harfbuzz-ng/src/hb-ot-var-common.hh | 947 +++++++- .../harfbuzz-ng/src/hb-ot-var-cvar-table.hh | 70 + .../harfbuzz-ng/src/hb-ot-var-fvar-table.hh | 116 +- .../harfbuzz-ng/src/hb-ot-var-gvar-table.hh | 125 +- .../harfbuzz-ng/src/hb-ot-var-hvar-table.hh | 86 +- .../harfbuzz-ng/src/hb-ot-vorg-table.hh | 2 +- src/3rdparty/harfbuzz-ng/src/hb-pool.hh | 2 +- .../harfbuzz-ng/src/hb-priority-queue.hh | 27 +- src/3rdparty/harfbuzz-ng/src/hb-sanitize.hh | 103 +- src/3rdparty/harfbuzz-ng/src/hb-serialize.hh | 36 +- src/3rdparty/harfbuzz-ng/src/hb-set-digest.hh | 12 +- src/3rdparty/harfbuzz-ng/src/hb-set.h | 2 +- src/3rdparty/harfbuzz-ng/src/hb-set.hh | 4 +- src/3rdparty/harfbuzz-ng/src/hb-shape.cc | 2 +- .../harfbuzz-ng/src/hb-shaper-list.hh | 5 + src/3rdparty/harfbuzz-ng/src/hb-static.cc | 3 + .../harfbuzz-ng/src/hb-subset-accelerator.hh | 51 +- .../harfbuzz-ng/src/hb-subset-cff-common.cc | 29 +- .../harfbuzz-ng/src/hb-subset-cff-common.hh | 112 +- .../harfbuzz-ng/src/hb-subset-cff1.cc | 296 +-- .../harfbuzz-ng/src/hb-subset-cff2.cc | 93 +- .../harfbuzz-ng/src/hb-subset-input.cc | 50 +- .../harfbuzz-ng/src/hb-subset-input.hh | 3 +- .../src/hb-subset-instancer-solver.cc | 227 +- .../src/hb-subset-instancer-solver.hh | 112 + .../src/hb-subset-plan-member-list.hh | 18 +- .../harfbuzz-ng/src/hb-subset-plan.cc | 186 +- .../harfbuzz-ng/src/hb-subset-plan.hh | 79 +- src/3rdparty/harfbuzz-ng/src/hb-subset.cc | 154 +- src/3rdparty/harfbuzz-ng/src/hb-subset.h | 7 + src/3rdparty/harfbuzz-ng/src/hb-uniscribe.cc | 6 +- src/3rdparty/harfbuzz-ng/src/hb-vector.hh | 122 +- src/3rdparty/harfbuzz-ng/src/hb-version.h | 8 +- .../harfbuzz-ng/src/hb-wasm-api-blob.hh | 50 + .../harfbuzz-ng/src/hb-wasm-api-buffer.hh | 217 ++ ...b-subset-cff2.hh => hb-wasm-api-common.hh} | 27 +- .../harfbuzz-ng/src/hb-wasm-api-face.hh | 109 + .../harfbuzz-ng/src/hb-wasm-api-font.hh | 263 +++ .../harfbuzz-ng/src/hb-wasm-api-shape.hh | 70 + .../src/{hb-subset-cff1.hh => hb-wasm-api.cc} | 29 +- src/3rdparty/harfbuzz-ng/src/hb-wasm-api.h | 319 +++ src/3rdparty/harfbuzz-ng/src/hb-wasm-api.hh | 117 + src/3rdparty/harfbuzz-ng/src/hb-wasm-shape.cc | 470 ++++ src/3rdparty/harfbuzz-ng/src/hb.hh | 9 + 157 files changed, 7774 insertions(+), 3016 deletions(-) create mode 100644 src/3rdparty/harfbuzz-ng/src/hb-subset-instancer-solver.hh create mode 100644 src/3rdparty/harfbuzz-ng/src/hb-wasm-api-blob.hh create mode 100644 src/3rdparty/harfbuzz-ng/src/hb-wasm-api-buffer.hh rename src/3rdparty/harfbuzz-ng/src/{hb-subset-cff2.hh => hb-wasm-api-common.hh} (71%) create mode 100644 src/3rdparty/harfbuzz-ng/src/hb-wasm-api-face.hh create mode 100644 src/3rdparty/harfbuzz-ng/src/hb-wasm-api-font.hh create mode 100644 src/3rdparty/harfbuzz-ng/src/hb-wasm-api-shape.hh rename src/3rdparty/harfbuzz-ng/src/{hb-subset-cff1.hh => hb-wasm-api.cc} (72%) create mode 100644 src/3rdparty/harfbuzz-ng/src/hb-wasm-api.h create mode 100644 src/3rdparty/harfbuzz-ng/src/hb-wasm-api.hh create mode 100644 src/3rdparty/harfbuzz-ng/src/hb-wasm-shape.cc diff --git a/src/3rdparty/harfbuzz-ng/NEWS b/src/3rdparty/harfbuzz-ng/NEWS index ff35843192d..0a7b94b58a9 100644 --- a/src/3rdparty/harfbuzz-ng/NEWS +++ b/src/3rdparty/harfbuzz-ng/NEWS @@ -1,3 +1,81 @@ +Overview of changes leading to 8.1.1 +Wednesday, August 2, 2023 +==================================== +- Fix shaping of contextual rules at the end of string, introduced in 8.1.0 +- Fix stack-overflow in repacker with malicious fonts. +- 30% speed up loading Noto Duployan font. + + +Overview of changes leading to 8.1.0 +Tuesday, August 1, 2023 +==================================== +- Fix long-standing build issue with the AIX compiler and older Apple clang. + +- Revert optimization that could cause timeout during subsetting with malicious fonts. + +- More optimization work: + - 45% speed up in shaping Noto Duployan font. + - 10% speed up in subsetting Noto Duployan font. + - Another 8% speed up in shaping Gulzar. + - 5% speed up in loading Roboto. + +- New API: ++hb_ot_layout_collect_features_map() + + +Overview of changes leading to 8.0.1 +Wednesday, July 12, 2023 +==================================== +- Build fix on 32-bit ARM. + +- More speed optimizations: + - 60% speed up in retain-gid (used for IFT) subsetting of SourceHanSans-VF. + - 16% speed up in retain-gid (used for IFT) subsetting of NotoSansCJKkr. + - 38% speed up in subsetting (beyond-64k) mega-merged Noto. + + +Overview of changes leading to 8.0.0 +Sunday, July 9, 2023 +==================================== +- New, experimental, WebAssembly (WASM) shaper, that provides greater + flexibility over OpenType/AAT/Graphite shaping, using WebAssembly embedded + inside the font file. Currently WASM shaper is disabled by default and needs + to be enabled at build time. For details, see: + + https://github.com/harfbuzz/harfbuzz/blob/main/docs/wasm-shaper.md + + For example fonts making use of the WASM shaper, see: + + https://github.com/harfbuzz/harfbuzz-wasm-examples + +- Improvements to Experimental features introduced in earlier releases: + - Support for subsetting beyond-64k and VarComposites fonts. + - Support for instancing variable fonts with cubic “glyf” table. + +- Many big speed optimizations: + - Up to 89% speedup loading variable fonts for shaping. + - Up to 88% speedup in small subsets of large (eg. CJK) fonts (both TTF and + OTF), essential for Incremental Font Transfer (IFT). + - Over 50% speedup in loading Roboto font for shaping. + - Up to 40% speed up in loading (sanitizing) complex fonts. + - 30% speed up in shaping Gulzar font. + - Over 25% speedup in glyph loading Roboto font. + - 10% speed up loading glyph shapes in VarComposite Hangul font. + - hb-hashmap optimizations & hashing improvements. + +- New macro HB_ALWAYS_INLINE. HarfBuzz now inlines functions more aggressively, + which results in some speedup at the expense of bigger code size. To disable + this feature define the macro to just inline. + +- New API: ++HB_CODEPOINT_INVALID ++hb_ot_layout_get_baseline2() ++hb_ot_layout_get_baseline_with_fallback2() ++hb_ot_layout_get_font_extents() ++hb_ot_layout_get_font_extents2() ++hb_subset_input_set_axis_range() + + Overview of changes leading to 7.3.0 Tuesday, May 9, 2023 ==================================== diff --git a/src/3rdparty/harfbuzz-ng/README.md b/src/3rdparty/harfbuzz-ng/README.md index 4202961e04a..cb075e3afd3 100644 --- a/src/3rdparty/harfbuzz-ng/README.md +++ b/src/3rdparty/harfbuzz-ng/README.md @@ -5,13 +5,16 @@ [![Codacy Badge](https://app.codacy.com/project/badge/Grade/89c872f5ce1c42af802602bfcd15d90a)](https://www.codacy.com/gh/harfbuzz/harfbuzz/dashboard?utm_source=github.com&utm_medium=referral&utm_content=harfbuzz/harfbuzz&utm_campaign=Badge_Grade) [![Codecov Code Coverage](https://codecov.io/gh/harfbuzz/harfbuzz/branch/main/graph/badge.svg)](https://codecov.io/gh/harfbuzz/harfbuzz) [![Packaging status](https://repology.org/badge/tiny-repos/harfbuzz.svg)](https://repology.org/project/harfbuzz/versions) +[![OpenSSF Scorecard](https://api.securityscorecards.dev/projects/github.com/harfbuzz/harfbuzz/badge)](https://securityscorecards.dev/viewer/?uri=github.com/harfbuzz/harfbuzz) + # HarfBuzz HarfBuzz is a text shaping engine. It primarily supports [OpenType][1], but also [Apple Advanced Typography][2]. HarfBuzz is used in Android, Chrome, -ChromeOS, Firefox, GNOME, GTK+, KDE, LibreOffice, OpenJDK, PlayStation, Qt, -XeTeX, and other places. +ChromeOS, Firefox, GNOME, GTK+, KDE, Qt, LibreOffice, OpenJDK, XeTeX, +PlayStation, Microsoft Edge, Photoshop, Illustrator, InDesign, +and other places. For bug reports, mailing list, and other information please visit: diff --git a/src/3rdparty/harfbuzz-ng/qt_attribution.json b/src/3rdparty/harfbuzz-ng/qt_attribution.json index a372205968b..983b5115e8d 100644 --- a/src/3rdparty/harfbuzz-ng/qt_attribution.json +++ b/src/3rdparty/harfbuzz-ng/qt_attribution.json @@ -6,7 +6,7 @@ "Description": "HarfBuzz is an OpenType text shaping engine.", "Homepage": "http://harfbuzz.org", - "Version": "7.3.0", + "Version": "8.1.1", "License": "MIT License", "LicenseId": "MIT", "LicenseFile": "COPYING", diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Color/CBDT/CBDT.hh b/src/3rdparty/harfbuzz-ng/src/OT/Color/CBDT/CBDT.hh index b125052344f..457039bfc6c 100644 --- a/src/3rdparty/harfbuzz-ng/src/OT/Color/CBDT/CBDT.hh +++ b/src/3rdparty/harfbuzz-ng/src/OT/Color/CBDT/CBDT.hh @@ -397,7 +397,6 @@ struct IndexSubtableRecord TRACE_SERIALIZE (this); auto *subtable = c->serializer->start_embed (); - if (unlikely (!subtable)) return_trace (false); if (unlikely (!c->serializer->extend_min (subtable))) return_trace (false); auto *old_subtable = get_subtable (base); @@ -545,7 +544,8 @@ struct IndexSubtableArray const IndexSubtableRecord*>> *lookup /* OUT */) const { bool start_glyph_is_set = false; - for (hb_codepoint_t new_gid = 0; new_gid < c->plan->num_output_glyphs (); new_gid++) + unsigned num_glyphs = c->plan->num_output_glyphs (); + for (hb_codepoint_t new_gid = 0; new_gid < num_glyphs; new_gid++) { hb_codepoint_t old_gid; if (unlikely (!c->plan->old_gid_for_new_gid (new_gid, &old_gid))) continue; @@ -576,9 +576,6 @@ struct IndexSubtableArray { TRACE_SUBSET (this); - auto *dst = c->serializer->start_embed (); - if (unlikely (!dst)) return_trace (false); - hb_vector_t> lookup; build_lookup (c, bitmap_size_context, &lookup); if (unlikely (!c->serializer->propagate_error (lookup))) @@ -993,12 +990,10 @@ CBLC::subset (hb_subset_context_t *c) const { TRACE_SUBSET (this); - auto *cblc_prime = c->serializer->start_embed (); - // Use a vector as a secondary buffer as the tables need to be built in parallel. hb_vector_t cbdt_prime; - if (unlikely (!cblc_prime)) return_trace (false); + auto *cblc_prime = c->serializer->start_embed (); if (unlikely (!c->serializer->extend_min (cblc_prime))) return_trace (false); cblc_prime->version = version; diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Color/COLR/COLR.hh b/src/3rdparty/harfbuzz-ng/src/OT/Color/COLR/COLR.hh index 2a479842941..6591bb4380a 100644 --- a/src/3rdparty/harfbuzz-ng/src/OT/Color/COLR/COLR.hh +++ b/src/3rdparty/harfbuzz-ng/src/OT/Color/COLR/COLR.hh @@ -409,7 +409,6 @@ struct ColorLine { TRACE_SUBSET (this); auto *out = c->serializer->start_embed (this); - if (unlikely (!out)) return_trace (false); if (unlikely (!c->serializer->extend_min (out))) return_trace (false); if (!c->serializer->check_assign (out->extend, extend, HB_SERIALIZE_ERROR_INT_OVERFLOW)) return_trace (false); @@ -1434,6 +1433,7 @@ struct PaintComposite { TRACE_SANITIZE (this); return_trace (c->check_struct (this) && + c->check_ops (this->min_size) && // PainComposite can get exponential src.sanitize (c, this) && backdrop.sanitize (c, this)); } @@ -2167,7 +2167,7 @@ struct COLR if (version == 0 && (!base_it || !layer_it)) return_trace (false); - COLR *colr_prime = c->serializer->start_embed (); + auto *colr_prime = c->serializer->start_embed (); if (unlikely (!c->serializer->extend_min (colr_prime))) return_trace (false); if (version == 0) diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Color/sbix/sbix.hh b/src/3rdparty/harfbuzz-ng/src/OT/Color/sbix/sbix.hh index 46ad3fd58e1..ce8693cfb16 100644 --- a/src/3rdparty/harfbuzz-ng/src/OT/Color/sbix/sbix.hh +++ b/src/3rdparty/harfbuzz-ng/src/OT/Color/sbix/sbix.hh @@ -48,7 +48,6 @@ struct SBIXGlyph { TRACE_SERIALIZE (this); SBIXGlyph* new_glyph = c->start_embed (); - if (unlikely (!new_glyph)) return_trace (nullptr); if (unlikely (!c->extend_min (new_glyph))) return_trace (nullptr); new_glyph->xOffset = xOffset; @@ -143,7 +142,6 @@ struct SBIXStrike unsigned int num_output_glyphs = c->plan->num_output_glyphs (); auto* out = c->serializer->start_embed (); - if (unlikely (!out)) return_trace (false); auto snap = c->serializer->snapshot (); if (unlikely (!c->serializer->extend (out, num_output_glyphs + 1))) return_trace (false); out->ppem = ppem; @@ -388,7 +386,6 @@ struct sbix TRACE_SERIALIZE (this); auto *out = c->serializer->start_embed> (); - if (unlikely (!out)) return_trace (false); if (unlikely (!c->serializer->extend_min (out))) return_trace (false); hb_vector_t*> new_strikes; @@ -423,8 +420,6 @@ struct sbix { TRACE_SUBSET (this); - sbix *sbix_prime = c->serializer->start_embed (); - if (unlikely (!sbix_prime)) return_trace (false); if (unlikely (!c->serializer->embed (this->version))) return_trace (false); if (unlikely (!c->serializer->embed (this->flags))) return_trace (false); diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/Common/Coverage.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/Common/Coverage.hh index 9ca88f788a9..25056c9bc35 100644 --- a/src/3rdparty/harfbuzz-ng/src/OT/Layout/Common/Coverage.hh +++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/Common/Coverage.hh @@ -57,6 +57,9 @@ struct Coverage public: DEFINE_SIZE_UNION (2, format); +#ifndef HB_OPTIMIZE_SIZE + HB_ALWAYS_INLINE +#endif bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/Common/CoverageFormat1.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/Common/CoverageFormat1.hh index 5d68e3d15e7..3f598d40efc 100644 --- a/src/3rdparty/harfbuzz-ng/src/OT/Layout/Common/CoverageFormat1.hh +++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/Common/CoverageFormat1.hh @@ -79,7 +79,7 @@ struct CoverageFormat1_3 { if (glyphArray.len > glyphs->get_population () * hb_bit_storage ((unsigned) glyphArray.len) / 2) { - for (hb_codepoint_t g = HB_SET_VALUE_INVALID; glyphs->next (&g);) + for (auto g : *glyphs) if (get_coverage (g) != NOT_COVERED) return true; return false; diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/Common/CoverageFormat2.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/Common/CoverageFormat2.hh index fa501d659d5..9c875423568 100644 --- a/src/3rdparty/harfbuzz-ng/src/OT/Layout/Common/CoverageFormat2.hh +++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/Common/CoverageFormat2.hh @@ -122,7 +122,7 @@ struct CoverageFormat2_4 { if (rangeRecord.len > glyphs->get_population () * hb_bit_storage ((unsigned) rangeRecord.len) / 2) { - for (hb_codepoint_t g = HB_SET_VALUE_INVALID; glyphs->next (&g);) + for (auto g : *glyphs) if (get_coverage (g) != NOT_COVERED) return true; return false; diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GDEF/GDEF.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GDEF/GDEF.hh index c1ff7961996..4f85d3ce5ec 100644 --- a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GDEF/GDEF.hh +++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GDEF/GDEF.hh @@ -49,8 +49,6 @@ struct AttachPoint : Array16Of { TRACE_SUBSET (this); auto *out = c->serializer->start_embed (*this); - if (unlikely (!out)) return_trace (false); - return_trace (out->serialize (c->serializer, + iter ())); } }; @@ -202,7 +200,6 @@ struct CaretValueFormat3 { TRACE_SUBSET (this); auto *out = c->serializer->start_embed (*this); - if (unlikely (!out)) return_trace (false); if (!c->serializer->embed (caretValueFormat)) return_trace (false); if (!c->serializer->embed (coordinate)) return_trace (false); @@ -442,6 +439,16 @@ struct MarkGlyphSetsFormat1 bool covers (unsigned int set_index, hb_codepoint_t glyph_id) const { return (this+coverage[set_index]).get_coverage (glyph_id) != NOT_COVERED; } + template + void collect_coverage (hb_vector_t &sets) const + { + for (const auto &offset : coverage) + { + const auto &cov = this+offset; + cov.collect_coverage (sets.push ()); + } + } + bool subset (hb_subset_context_t *c) const { TRACE_SUBSET (this); @@ -495,6 +502,15 @@ struct MarkGlyphSets } } + template + void collect_coverage (hb_vector_t &sets) const + { + switch (u.format) { + case 1: u.format1.collect_coverage (sets); return; + default:return; + } + } + bool subset (hb_subset_context_t *c) const { TRACE_SUBSET (this); @@ -859,6 +875,10 @@ struct GDEF hb_blob_destroy (table.get_blob ()); table = hb_blob_get_empty (); } + +#ifndef HB_NO_GDEF_CACHE + table->get_mark_glyph_sets ().collect_coverage (mark_glyph_set_digests); +#endif } ~accelerator_t () { table.destroy (); } @@ -882,8 +902,18 @@ struct GDEF } + bool mark_set_covers (unsigned int set_index, hb_codepoint_t glyph_id) const + { + return +#ifndef HB_NO_GDEF_CACHE + mark_glyph_set_digests[set_index].may_have (glyph_id) && +#endif + table->mark_set_covers (set_index, glyph_id); + } + hb_blob_ptr_t table; #ifndef HB_NO_GDEF_CACHE + hb_vector_t mark_glyph_set_digests; mutable hb_cache_t<21, 3, 8> glyph_props_cache; #endif }; diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/AnchorFormat3.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/AnchorFormat3.hh index e7e3c5c6d1e..8684f60ca5d 100644 --- a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/AnchorFormat3.hh +++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/AnchorFormat3.hh @@ -25,7 +25,9 @@ struct AnchorFormat3 bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); - return_trace (c->check_struct (this) && xDeviceTable.sanitize (c, this) && yDeviceTable.sanitize (c, this)); + if (unlikely (!c->check_struct (this))) return_trace (false); + + return_trace (xDeviceTable.sanitize (c, this) && yDeviceTable.sanitize (c, this)); } void get_anchor (hb_ot_apply_context_t *c, hb_codepoint_t glyph_id HB_UNUSED, @@ -35,9 +37,9 @@ struct AnchorFormat3 *x = font->em_fscale_x (xCoordinate); *y = font->em_fscale_y (yCoordinate); - if (font->x_ppem || font->num_coords) + if ((font->x_ppem || font->num_coords) && xDeviceTable.sanitize (&c->sanitizer, this)) *x += (this+xDeviceTable).get_x_delta (font, c->var_store, c->var_store_cache); - if (font->y_ppem || font->num_coords) + if ((font->y_ppem || font->num_coords) && yDeviceTable.sanitize (&c->sanitizer, this)) *y += (this+yDeviceTable).get_y_delta (font, c->var_store, c->var_store_cache); } @@ -45,7 +47,6 @@ struct AnchorFormat3 { TRACE_SUBSET (this); auto *out = c->serializer->start_embed (*this); - if (unlikely (!out)) return_trace (false); if (unlikely (!c->serializer->embed (format))) return_trace (false); if (unlikely (!c->serializer->embed (xCoordinate))) return_trace (false); if (unlikely (!c->serializer->embed (yCoordinate))) return_trace (false); diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/AnchorMatrix.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/AnchorMatrix.hh index c442efa1eaa..bd9b1897397 100644 --- a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/AnchorMatrix.hh +++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/AnchorMatrix.hh @@ -21,18 +21,25 @@ struct AnchorMatrix if (unlikely (hb_unsigned_mul_overflows (rows, cols))) return_trace (false); unsigned int count = rows * cols; if (!c->check_array (matrixZ.arrayZ, count)) return_trace (false); + + if (c->lazy_some_gpos) + return_trace (true); + for (unsigned int i = 0; i < count; i++) if (!matrixZ[i].sanitize (c, this)) return_trace (false); return_trace (true); } - const Anchor& get_anchor (unsigned int row, unsigned int col, - unsigned int cols, bool *found) const + const Anchor& get_anchor (hb_ot_apply_context_t *c, + unsigned int row, unsigned int col, + unsigned int cols, bool *found) const { *found = false; if (unlikely (row >= rows || col >= cols)) return Null (Anchor); - *found = !matrixZ[row * cols + col].is_null (); - return this+matrixZ[row * cols + col]; + auto &offset = matrixZ[row * cols + col]; + if (unlikely (!offset.sanitize (&c->sanitizer, this))) return Null (Anchor); + *found = !offset.is_null (); + return this+offset; } template lazy_some_gpos) + return_trace (entryExitRecord.sanitize_shallow (c)); + else + return_trace (entryExitRecord.sanitize (c, this)); } bool intersects (const hb_set_t *glyphs) const @@ -119,10 +125,11 @@ struct CursivePosFormat1 hb_buffer_t *buffer = c->buffer; const EntryExitRecord &this_record = entryExitRecord[(this+coverage).get_coverage (buffer->cur().codepoint)]; - if (!this_record.entryAnchor) return_trace (false); + if (!this_record.entryAnchor || + unlikely (!this_record.entryAnchor.sanitize (&c->sanitizer, this))) return_trace (false); hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input; - skippy_iter.reset_fast (buffer->idx, 1); + skippy_iter.reset_fast (buffer->idx); unsigned unsafe_from; if (unlikely (!skippy_iter.prev (&unsafe_from))) { @@ -131,7 +138,8 @@ struct CursivePosFormat1 } const EntryExitRecord &prev_record = entryExitRecord[(this+coverage).get_coverage (buffer->info[skippy_iter.idx].codepoint)]; - if (!prev_record.exitAnchor) + if (!prev_record.exitAnchor || + unlikely (!prev_record.exitAnchor.sanitize (&c->sanitizer, this))) { buffer->unsafe_to_concat_from_outbuffer (skippy_iter.idx, buffer->idx + 1); return_trace (false); @@ -200,8 +208,8 @@ struct CursivePosFormat1 * Arabic. */ unsigned int child = i; unsigned int parent = j; - hb_position_t x_offset = entry_x - exit_x; - hb_position_t y_offset = entry_y - exit_y; + hb_position_t x_offset = roundf (entry_x - exit_x); + hb_position_t y_offset = roundf (entry_y - exit_y); if (!(c->lookup_props & LookupFlag::RightToLeft)) { unsigned int k = child; @@ -278,7 +286,6 @@ struct CursivePosFormat1 const hb_map_t &glyph_map = *c->plan->glyph_map; auto *out = c->serializer->start_embed (*this); - if (unlikely (!out)) return_trace (false); auto it = + hb_zip (this+coverage, entryExitRecord) diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/MarkArray.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/MarkArray.hh index ff43ffb8c57..34e2ab8f6e3 100644 --- a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/MarkArray.hh +++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/MarkArray.hh @@ -28,7 +28,7 @@ struct MarkArray : Array16Of /* Array of MarkRecords--in Cove const Anchor& mark_anchor = this + record.markAnchor; bool found; - const Anchor& glyph_anchor = anchors.get_anchor (glyph_index, mark_class, class_count, &found); + const Anchor& glyph_anchor = anchors.get_anchor (c, glyph_index, mark_class, class_count, &found); /* If this subtable doesn't have an anchor for this base and this class, * return false such that the subsequent subtables have a chance at it. */ if (unlikely (!found)) return_trace (false); diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/MarkMarkPosFormat1.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/MarkMarkPosFormat1.hh index 9dae5ce5dac..72535f4c983 100644 --- a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/MarkMarkPosFormat1.hh +++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/MarkMarkPosFormat1.hh @@ -100,7 +100,7 @@ struct MarkMarkPosFormat1_2 /* now we search backwards for a suitable mark glyph until a non-mark glyph */ hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input; - skippy_iter.reset_fast (buffer->idx, 1); + skippy_iter.reset_fast (buffer->idx); skippy_iter.set_lookup_props (c->lookup_props & ~(uint32_t)LookupFlag::IgnoreFlags); unsigned unsafe_from; if (unlikely (!skippy_iter.prev (&unsafe_from))) diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/PairPosFormat1.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/PairPosFormat1.hh index 714b4bec724..e4a2006fb98 100644 --- a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/PairPosFormat1.hh +++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/PairPosFormat1.hh @@ -110,7 +110,7 @@ struct PairPosFormat1_3 if (likely (index == NOT_COVERED)) return_trace (false); hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input; - skippy_iter.reset_fast (buffer->idx, 1); + skippy_iter.reset_fast (buffer->idx); unsigned unsafe_to; if (unlikely (!skippy_iter.next (&unsafe_to))) { diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/PairPosFormat2.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/PairPosFormat2.hh index 31329dfcb59..1bde9e755e9 100644 --- a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/PairPosFormat2.hh +++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/PairPosFormat2.hh @@ -54,8 +54,9 @@ struct PairPosFormat2_4 return_trace (c->check_range ((const void *) values, count, stride) && - valueFormat1.sanitize_values_stride_unsafe (c, this, &values[0], count, stride) && - valueFormat2.sanitize_values_stride_unsafe (c, this, &values[len1], count, stride)); + (c->lazy_some_gpos || + (valueFormat1.sanitize_values_stride_unsafe (c, this, &values[0], count, stride) && + valueFormat2.sanitize_values_stride_unsafe (c, this, &values[len1], count, stride)))); } bool intersects (const hb_set_t *glyphs) const @@ -130,7 +131,7 @@ struct PairPosFormat2_4 if (likely (index == NOT_COVERED)) return_trace (false); hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input; - skippy_iter.reset_fast (buffer->idx, 1); + skippy_iter.reset_fast (buffer->idx); unsigned unsafe_to; if (unlikely (!skippy_iter.next (&unsafe_to))) { @@ -298,11 +299,13 @@ struct PairPosFormat2_4 out->valueFormat2 = out->valueFormat2.drop_device_table_flags (); } + unsigned total_len = len1 + len2; + hb_vector_t class2_idxs (+ hb_range ((unsigned) class2Count) | hb_filter (klass2_map)); for (unsigned class1_idx : + hb_range ((unsigned) class1Count) | hb_filter (klass1_map)) { - for (unsigned class2_idx : + hb_range ((unsigned) class2Count) | hb_filter (klass2_map)) + for (unsigned class2_idx : class2_idxs) { - unsigned idx = (class1_idx * (unsigned) class2Count + class2_idx) * (len1 + len2); + unsigned idx = (class1_idx * (unsigned) class2Count + class2_idx) * total_len; valueFormat1.copy_values (c->serializer, out->valueFormat1, this, &values[idx], &c->plan->layout_variation_idx_delta_map); valueFormat2.copy_values (c->serializer, out->valueFormat2, this, &values[idx + len1], &c->plan->layout_variation_idx_delta_map); } diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/PairSet.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/PairSet.hh index 9faff49909a..db301bb8160 100644 --- a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/PairSet.hh +++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/PairSet.hh @@ -52,8 +52,9 @@ struct PairSet unsigned int count = len; const PairValueRecord *record = &firstPairValueRecord; - return_trace (closure->valueFormats[0].sanitize_values_stride_unsafe (c, this, &record->values[0], count, closure->stride) && - closure->valueFormats[1].sanitize_values_stride_unsafe (c, this, &record->values[closure->len1], count, closure->stride)); + return_trace (c->lazy_some_gpos || + (closure->valueFormats[0].sanitize_values_stride_unsafe (c, this, &record->values[0], count, closure->stride) && + closure->valueFormats[1].sanitize_values_stride_unsafe (c, this, &record->values[closure->len1], count, closure->stride))); } bool intersects (const hb_set_t *glyphs, diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/PairValueRecord.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/PairValueRecord.hh index 3222477764a..72bf0e99b53 100644 --- a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/PairValueRecord.hh +++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/PairValueRecord.hh @@ -22,7 +22,7 @@ struct PairValueRecord ValueRecord values; /* Positioning data for the first glyph * followed by for second glyph */ public: - DEFINE_SIZE_ARRAY (Types::size, values); + DEFINE_SIZE_ARRAY (Types::HBGlyphID::static_size, values); int cmp (hb_codepoint_t k) const { return secondGlyph.cmp (k); } diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/SinglePosFormat1.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/SinglePosFormat1.hh index 623e4e66b20..dff1f7316d5 100644 --- a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/SinglePosFormat1.hh +++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/SinglePosFormat1.hh @@ -90,6 +90,7 @@ struct SinglePosFormat1 bool position_single (hb_font_t *font, + hb_blob_t *table_blob, hb_direction_t direction, hb_codepoint_t gid, hb_glyph_position_t &pos) const @@ -100,7 +101,7 @@ struct SinglePosFormat1 /* This is ugly... */ hb_buffer_t buffer; buffer.props.direction = direction; - OT::hb_ot_apply_context_t c (1, font, &buffer); + OT::hb_ot_apply_context_t c (1, font, &buffer, table_blob); valueFormat.apply_value (&c, this, values, pos); return true; diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/SinglePosFormat2.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/SinglePosFormat2.hh index e8f2d7c2c6e..168ad3bb8c8 100644 --- a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/SinglePosFormat2.hh +++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/SinglePosFormat2.hh @@ -94,6 +94,7 @@ struct SinglePosFormat2 bool position_single (hb_font_t *font, + hb_blob_t *table_blob, hb_direction_t direction, hb_codepoint_t gid, hb_glyph_position_t &pos) const @@ -105,7 +106,7 @@ struct SinglePosFormat2 /* This is ugly... */ hb_buffer_t buffer; buffer.props.direction = direction; - OT::hb_ot_apply_context_t c (1, font, &buffer); + OT::hb_ot_apply_context_t c (1, font, &buffer, table_blob); valueFormat.apply_value (&c, this, &values[index * valueFormat.get_len ()], diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/ValueFormat.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/ValueFormat.hh index 1aa451abcc8..461a13d4b70 100644 --- a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/ValueFormat.hh +++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/ValueFormat.hh @@ -118,21 +118,25 @@ struct ValueFormat : HBUINT16 auto *cache = c->var_store_cache; /* pixel -> fractional pixel */ - if (format & xPlaDevice) { - if (use_x_device) glyph_pos.x_offset += (base + get_device (values, &ret)).get_x_delta (font, store, cache); + if (format & xPlaDevice) + { + if (use_x_device) glyph_pos.x_offset += get_device (values, &ret, base, c->sanitizer).get_x_delta (font, store, cache); values++; } - if (format & yPlaDevice) { - if (use_y_device) glyph_pos.y_offset += (base + get_device (values, &ret)).get_y_delta (font, store, cache); + if (format & yPlaDevice) + { + if (use_y_device) glyph_pos.y_offset += get_device (values, &ret, base, c->sanitizer).get_y_delta (font, store, cache); values++; } - if (format & xAdvDevice) { - if (horizontal && use_x_device) glyph_pos.x_advance += (base + get_device (values, &ret)).get_x_delta (font, store, cache); + if (format & xAdvDevice) + { + if (horizontal && use_x_device) glyph_pos.x_advance += get_device (values, &ret, base, c->sanitizer).get_x_delta (font, store, cache); values++; } - if (format & yAdvDevice) { + if (format & yAdvDevice) + { /* y_advance values grow downward but font-space grows upward, hence negation */ - if (!horizontal && use_y_device) glyph_pos.y_advance -= (base + get_device (values, &ret)).get_y_delta (font, store, cache); + if (!horizontal && use_y_device) glyph_pos.y_advance -= get_device (values, &ret, base, c->sanitizer).get_y_delta (font, store, cache); values++; } return ret; @@ -174,6 +178,9 @@ struct ValueFormat : HBUINT16 if (format & xAdvance) x_adv = copy_value (c, new_format, xAdvance, *values++); if (format & yAdvance) y_adv = copy_value (c, new_format, yAdvance, *values++); + if (!has_device ()) + return; + if (format & xPlaDevice) { add_delta_to_value (x_placement, base, values, layout_variation_idx_delta_map); @@ -233,14 +240,12 @@ struct ValueFormat : HBUINT16 if (format & ValueFormat::xAdvDevice) { - (base + get_device (&(values[i]))).collect_variation_indices (c); i++; } if (format & ValueFormat::yAdvDevice) { - (base + get_device (&(values[i]))).collect_variation_indices (c); i++; } @@ -277,10 +282,22 @@ struct ValueFormat : HBUINT16 { return *static_cast *> (value); } - static inline const Offset16To& get_device (const Value* value, bool *worked=nullptr) + static inline const Offset16To& get_device (const Value* value) + { + return *static_cast *> (value); + } + static inline const Device& get_device (const Value* value, + bool *worked, + const void *base, + hb_sanitize_context_t &c) { if (worked) *worked |= bool (*value); - return *static_cast *> (value); + auto &offset = *static_cast *> (value); + + if (unlikely (!offset.sanitize (&c, base))) + return Null(Device); + + return base + offset; } void add_delta_to_value (HBINT16 *value, @@ -340,25 +357,26 @@ struct ValueFormat : HBUINT16 bool sanitize_value (hb_sanitize_context_t *c, const void *base, const Value *values) const { TRACE_SANITIZE (this); - return_trace (c->check_range (values, get_size ()) && (!has_device () || sanitize_value_devices (c, base, values))); + + if (unlikely (!c->check_range (values, get_size ()))) return_trace (false); + + if (c->lazy_some_gpos) + return_trace (true); + + return_trace (!has_device () || sanitize_value_devices (c, base, values)); } bool sanitize_values (hb_sanitize_context_t *c, const void *base, const Value *values, unsigned int count) const { TRACE_SANITIZE (this); - unsigned int len = get_len (); + unsigned size = get_size (); - if (!c->check_range (values, count, get_size ())) return_trace (false); + if (!c->check_range (values, count, size)) return_trace (false); - if (!has_device ()) return_trace (true); + if (c->lazy_some_gpos) + return_trace (true); - for (unsigned int i = 0; i < count; i++) { - if (!sanitize_value_devices (c, base, values)) - return_trace (false); - values += len; - } - - return_trace (true); + return_trace (sanitize_values_stride_unsafe (c, base, values, count, size)); } /* Just sanitize referenced Device tables. Doesn't check the values themselves. */ diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/Common.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/Common.hh index 968bba0481a..b849494d88a 100644 --- a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/Common.hh +++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/Common.hh @@ -8,8 +8,6 @@ namespace OT { namespace Layout { namespace GSUB_impl { -typedef hb_pair_t hb_codepoint_pair_t; - template static void SingleSubst_serialize (hb_serialize_context_t *c, Iterator it); diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/Ligature.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/Ligature.hh index 8674a52fb52..402ed12ae20 100644 --- a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/Ligature.hh +++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/Ligature.hh @@ -13,7 +13,7 @@ struct Ligature public: typename Types::HBGlyphID ligGlyph; /* GlyphID of ligature to substitute */ - HeadlessArrayOf + HeadlessArray16Of component; /* Array of component GlyphIDs--start * with the second component--ordered * in writing direction */ diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/LigatureSet.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/LigatureSet.hh index 0ba262e9017..08665438c4a 100644 --- a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/LigatureSet.hh +++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/LigatureSet.hh @@ -72,19 +72,14 @@ struct LigatureSet ; } - static bool match_always (hb_glyph_info_t &info HB_UNUSED, unsigned value HB_UNUSED, const void *data HB_UNUSED) - { - return true; - } - bool apply (hb_ot_apply_context_t *c) const { TRACE_APPLY (this); unsigned int num_ligs = ligature.len; -#ifndef HB_NO_OT_LIGATURES_FAST_PATH - if (HB_OPTIMIZE_SIZE_VAL || num_ligs <= 2) +#ifndef HB_NO_OT_RULESETS_FAST_PATH + if (HB_OPTIMIZE_SIZE_VAL || num_ligs <= 4) #endif { slow: @@ -97,10 +92,12 @@ struct LigatureSet } /* This version is optimized for speed by matching the first component - * of the ligature here, instead of calling into the ligation code. */ + * of the ligature here, instead of calling into the ligation code. + * + * This is replicated in ChainRuleSet and RuleSet. */ hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input; - skippy_iter.reset (c->buffer->idx, 1); + skippy_iter.reset (c->buffer->idx); skippy_iter.set_match_func (match_always, nullptr); skippy_iter.set_glyph_data ((HBUINT16 *) nullptr); unsigned unsafe_to; @@ -118,6 +115,8 @@ struct LigatureSet goto slow; } } + else + goto slow; bool unsafe_to_concat = false; @@ -125,7 +124,7 @@ struct LigatureSet { const auto &lig = this+ligature.arrayZ[i]; if (unlikely (lig.component.lenP1 <= 1) || - lig.component[1] == first) + lig.component.arrayZ[0] == first) { if (lig.apply (c)) { diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/ReverseChainSingleSubstFormat1.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/ReverseChainSingleSubstFormat1.hh index 2c2e1aa44fd..916fa281b32 100644 --- a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/ReverseChainSingleSubstFormat1.hh +++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/ReverseChainSingleSubstFormat1.hh @@ -191,7 +191,6 @@ struct ReverseChainSingleSubstFormat1 TRACE_SERIALIZE (this); auto *out = c->serializer->start_embed (this); - if (unlikely (!c->serializer->check_success (out))) return_trace (false); if (unlikely (!c->serializer->embed (this->format))) return_trace (false); if (unlikely (!c->serializer->embed (this->coverage))) return_trace (false); diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/Sequence.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/Sequence.hh index ae3292f3295..a26cf8c6a65 100644 --- a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/Sequence.hh +++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/Sequence.hh @@ -53,7 +53,7 @@ struct Sequence if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ()) { c->buffer->message (c->font, - "replaced glyph at %u (multiple subtitution)", + "replaced glyph at %u (multiple substitution)", c->buffer->idx - 1u); } diff --git a/src/3rdparty/harfbuzz-ng/src/OT/glyf/CompositeGlyph.hh b/src/3rdparty/harfbuzz-ng/src/OT/glyf/CompositeGlyph.hh index d81fadf7c88..60858a5a581 100644 --- a/src/3rdparty/harfbuzz-ng/src/OT/glyf/CompositeGlyph.hh +++ b/src/3rdparty/harfbuzz-ng/src/OT/glyf/CompositeGlyph.hh @@ -90,24 +90,36 @@ struct CompositeGlyphRecord static void transform (const float (&matrix)[4], hb_array_t points) { - auto arrayZ = points.arrayZ; - unsigned count = points.length; - if (matrix[0] != 1.f || matrix[1] != 0.f || matrix[2] != 0.f || matrix[3] != 1.f) - for (unsigned i = 0; i < count; i++) - arrayZ[i].transform (matrix); + for (auto &point : points) + point.transform (matrix); } static void translate (const contour_point_t &trans, hb_array_t points) { - auto arrayZ = points.arrayZ; - unsigned count = points.length; - - if (trans.x != 0.f || trans.y != 0.f) - for (unsigned i = 0; i < count; i++) - arrayZ[i].translate (trans); + if (HB_OPTIMIZE_SIZE_VAL) + { + if (trans.x != 0.f || trans.y != 0.f) + for (auto &point : points) + point.translate (trans); + } + else + { + if (trans.x != 0.f && trans.y != 0.f) + for (auto &point : points) + point.translate (trans); + else + { + if (trans.x != 0.f) + for (auto &point : points) + point.x += trans.x; + else if (trans.y != 0.f) + for (auto &point : points) + point.y += trans.y; + } + } } void transform_points (hb_array_t points, @@ -131,9 +143,8 @@ struct CompositeGlyphRecord float matrix[4]; contour_point_t trans; get_transformation (matrix, trans); - points.alloc (points.length + 4); // For phantom points - if (unlikely (!points.resize (points.length + 1))) return false; - points.arrayZ[points.length - 1] = trans; + if (unlikely (!points.alloc (points.length + 4))) return false; // For phantom points + points.push (trans); return true; } @@ -382,7 +393,7 @@ struct CompositeGlyph { /* last 4 points in points_with_deltas are phantom points and should not be included */ if (i >= points_with_deltas.length - 4) { - free (o); + hb_free (o); return false; } diff --git a/src/3rdparty/harfbuzz-ng/src/OT/glyf/Glyph.hh b/src/3rdparty/harfbuzz-ng/src/OT/glyf/Glyph.hh index 2bd5fe8206d..2611c1e21dd 100644 --- a/src/3rdparty/harfbuzz-ng/src/OT/glyf/Glyph.hh +++ b/src/3rdparty/harfbuzz-ng/src/OT/glyf/Glyph.hh @@ -114,8 +114,8 @@ struct Glyph if (type != EMPTY) { - plan->bounds_width_map.set (new_gid, xMax - xMin); - plan->bounds_height_map.set (new_gid, yMax - yMin); + plan->bounds_width_vec[new_gid] = xMax - xMin; + plan->bounds_height_vec[new_gid] = yMax - yMin; } unsigned len = all_points.length; @@ -124,10 +124,12 @@ struct Glyph float topSideY = all_points[len - 2].y; float bottomSideY = all_points[len - 1].y; + uint32_t hash = hb_hash (new_gid); + signed hori_aw = roundf (rightSideX - leftSideX); if (hori_aw < 0) hori_aw = 0; int lsb = roundf (xMin - leftSideX); - plan->hmtx_map.set (new_gid, hb_pair ((unsigned) hori_aw, lsb)); + plan->hmtx_map.set_with_hash (new_gid, hash, hb_pair ((unsigned) hori_aw, lsb)); //flag value should be computed using non-empty glyphs if (type != EMPTY && lsb != xMin) plan->head_maxp_info.allXMinIsLsb = false; @@ -135,7 +137,7 @@ struct Glyph signed vert_aw = roundf (topSideY - bottomSideY); if (vert_aw < 0) vert_aw = 0; int tsb = roundf (topSideY - yMax); - plan->vmtx_map.set (new_gid, hb_pair ((unsigned) vert_aw, tsb)); + plan->vmtx_map.set_with_hash (new_gid, hash, hb_pair ((unsigned) vert_aw, tsb)); } bool compile_header_bytes (const hb_subset_plan_t *plan, @@ -369,9 +371,11 @@ struct Glyph } #ifndef HB_NO_VAR - glyf_accelerator.gvar->apply_deltas_to_points (gid, - coords, - points.as_array ().sub_array (old_length)); + if (coords) + glyf_accelerator.gvar->apply_deltas_to_points (gid, + coords, + points.as_array ().sub_array (old_length), + phantom_only && type == SIMPLE); #endif // mainly used by CompositeGlyph calculating new X/Y offset value so no need to extend it @@ -379,7 +383,7 @@ struct Glyph if (points_with_deltas != nullptr && depth == 0 && type == COMPOSITE) { if (unlikely (!points_with_deltas->resize (points.length))) return false; - points_with_deltas->copy_vector (points); + *points_with_deltas = points; } switch (type) { @@ -417,14 +421,17 @@ struct Glyph for (unsigned int i = 0; i < PHANTOM_COUNT; i++) phantoms[i] = comp_points[comp_points.length - PHANTOM_COUNT + i]; - float matrix[4]; - contour_point_t default_trans; - item.get_transformation (matrix, default_trans); + if (comp_points) // Empty in case of phantom_only + { + float matrix[4]; + contour_point_t default_trans; + item.get_transformation (matrix, default_trans); - /* Apply component transformation & translation (with deltas applied) */ - item.transform_points (comp_points, matrix, points[comp_index]); + /* Apply component transformation & translation (with deltas applied) */ + item.transform_points (comp_points, matrix, points[comp_index]); + } - if (item.is_anchored ()) + if (item.is_anchored () && !phantom_only) { unsigned int p1, p2; item.get_anchor_points (p1, p2); @@ -466,7 +473,10 @@ struct Glyph assert (record_points.length == item_num_points); auto component_coords = coords; - if (item.is_reset_unspecified_axes ()) + /* Copying coords is expensive; so we have put an arbitrary + * limit on the max number of coords for now. */ + if (item.is_reset_unspecified_axes () || + coords.length > HB_GLYF_VAR_COMPOSITE_MAX_AXES) component_coords = hb_array (); coord_setter_t coord_setter (component_coords); diff --git a/src/3rdparty/harfbuzz-ng/src/OT/glyf/SimpleGlyph.hh b/src/3rdparty/harfbuzz-ng/src/OT/glyf/SimpleGlyph.hh index 555bcee346e..1d42cc29250 100644 --- a/src/3rdparty/harfbuzz-ng/src/OT/glyf/SimpleGlyph.hh +++ b/src/3rdparty/harfbuzz-ng/src/OT/glyf/SimpleGlyph.hh @@ -154,10 +154,9 @@ struct SimpleGlyph { int v = 0; - unsigned count = points_.length; - for (unsigned i = 0; i < count; i++) + for (auto &point : points_) { - unsigned flag = points_.arrayZ[i].flag; + unsigned flag = point.flag; if (flag & short_flag) { if (unlikely (p + 1 > end)) return false; @@ -175,7 +174,7 @@ struct SimpleGlyph p += HBINT16::static_size; } } - points_.arrayZ[i].*m = v; + point.*m = v; } return true; } @@ -192,9 +191,10 @@ struct SimpleGlyph unsigned old_length = points.length; points.alloc (points.length + num_points + 4, true); // Allocate for phantom points, to avoid a possible copy - if (!points.resize (points.length + num_points, false)) return false; + if (unlikely (!points.resize (points.length + num_points, false))) return false; auto points_ = points.as_array ().sub_array (old_length); - hb_memset (points_.arrayZ, 0, sizeof (contour_point_t) * num_points); + if (!phantom_only) + hb_memset (points_.arrayZ, 0, sizeof (contour_point_t) * num_points); if (phantom_only) return true; for (int i = 0; i < num_contours; i++) diff --git a/src/3rdparty/harfbuzz-ng/src/OT/glyf/SubsetGlyph.hh b/src/3rdparty/harfbuzz-ng/src/OT/glyf/SubsetGlyph.hh index 26dc374eab6..8099d3c1269 100644 --- a/src/3rdparty/harfbuzz-ng/src/OT/glyf/SubsetGlyph.hh +++ b/src/3rdparty/harfbuzz-ng/src/OT/glyf/SubsetGlyph.hh @@ -22,7 +22,7 @@ struct SubsetGlyph bool serialize (hb_serialize_context_t *c, bool use_short_loca, - const hb_subset_plan_t *plan) + const hb_subset_plan_t *plan) const { TRACE_SERIALIZE (this); @@ -40,7 +40,7 @@ struct SubsetGlyph pad = 0; while (pad_length > 0) { - c->embed (pad); + (void) c->embed (pad); pad_length--; } diff --git a/src/3rdparty/harfbuzz-ng/src/OT/glyf/VarCompositeGlyph.hh b/src/3rdparty/harfbuzz-ng/src/OT/glyf/VarCompositeGlyph.hh index 6dc6fd9ded1..50cbece3cad 100644 --- a/src/3rdparty/harfbuzz-ng/src/OT/glyf/VarCompositeGlyph.hh +++ b/src/3rdparty/harfbuzz-ng/src/OT/glyf/VarCompositeGlyph.hh @@ -214,7 +214,7 @@ struct VarCompositeGlyphRecord points.alloc (points.length + num_points + 4); // For phantom points if (unlikely (!points.resize (points.length + num_points, false))) return false; contour_point_t *rec_points = points.arrayZ + (points.length - num_points); - memset (rec_points, 0, num_points * sizeof (rec_points[0])); + hb_memset (rec_points, 0, num_points * sizeof (rec_points[0])); unsigned fl = flags; diff --git a/src/3rdparty/harfbuzz-ng/src/OT/glyf/coord-setter.hh b/src/3rdparty/harfbuzz-ng/src/OT/glyf/coord-setter.hh index df64ed5af7d..cf05929362f 100644 --- a/src/3rdparty/harfbuzz-ng/src/OT/glyf/coord-setter.hh +++ b/src/3rdparty/harfbuzz-ng/src/OT/glyf/coord-setter.hh @@ -16,6 +16,8 @@ struct coord_setter_t int& operator [] (unsigned idx) { + if (unlikely (idx >= HB_GLYF_VAR_COMPOSITE_MAX_AXES)) + return Crap(int); if (coords.length < idx + 1) coords.resize (idx + 1); return coords[idx]; diff --git a/src/3rdparty/harfbuzz-ng/src/OT/glyf/glyf-helpers.hh b/src/3rdparty/harfbuzz-ng/src/OT/glyf/glyf-helpers.hh index 30106b2b98b..d0a5a132f05 100644 --- a/src/3rdparty/harfbuzz-ng/src/OT/glyf/glyf-helpers.hh +++ b/src/3rdparty/harfbuzz-ng/src/OT/glyf/glyf-helpers.hh @@ -12,24 +12,44 @@ namespace OT { namespace glyf_impl { -template +template static void -_write_loca (IteratorIn&& it, bool short_offsets, IteratorOut&& dest) +_write_loca (IteratorIn&& it, + const hb_sorted_vector_t new_to_old_gid_list, + bool short_offsets, + TypeOut *dest, + unsigned num_offsets) { unsigned right_shift = short_offsets ? 1 : 0; - unsigned int offset = 0; - dest << 0; - + it - | hb_map ([=, &offset] (unsigned int padded_size) - { - offset += padded_size; - DEBUG_MSG (SUBSET, nullptr, "loca entry offset %u", offset); - return offset >> right_shift; - }) - | hb_sink (dest) - ; + unsigned offset = 0; + TypeOut value; + value = 0; + *dest++ = value; + hb_codepoint_t last = 0; + for (auto _ : new_to_old_gid_list) + { + hb_codepoint_t gid = _.first; + for (; last < gid; last++) + { + DEBUG_MSG (SUBSET, nullptr, "loca entry empty offset %u", offset); + *dest++ = value; + } + + unsigned padded_size = *it++; + offset += padded_size; + DEBUG_MSG (SUBSET, nullptr, "loca entry gid %u offset %u padded-size %u", gid, offset, padded_size); + value = offset >> right_shift; + *dest++ = value; + + last++; // Skip over gid + } + unsigned num_glyphs = num_offsets - 1; + for (; last < num_glyphs; last++) + { + DEBUG_MSG (SUBSET, nullptr, "loca entry empty offset %u", offset); + *dest++ = value; + } } static bool @@ -67,11 +87,14 @@ _add_head_and_set_loca_version (hb_subset_plan_t *plan, bool use_short_loca) template static bool -_add_loca_and_head (hb_subset_plan_t * plan, Iterator padded_offsets, bool use_short_loca) +_add_loca_and_head (hb_subset_context_t *c, + Iterator padded_offsets, + bool use_short_loca) { - unsigned num_offsets = padded_offsets.len () + 1; + unsigned num_offsets = c->plan->num_output_glyphs () + 1; unsigned entry_size = use_short_loca ? 2 : 4; - char *loca_prime_data = (char *) hb_calloc (entry_size, num_offsets); + + char *loca_prime_data = (char *) hb_malloc (entry_size * num_offsets); if (unlikely (!loca_prime_data)) return false; @@ -79,9 +102,9 @@ _add_loca_and_head (hb_subset_plan_t * plan, Iterator padded_offsets, bool use_s entry_size, num_offsets, entry_size * num_offsets); if (use_short_loca) - _write_loca (padded_offsets, true, hb_array ((HBUINT16 *) loca_prime_data, num_offsets)); + _write_loca (padded_offsets, c->plan->new_to_old_gid_list, true, (HBUINT16 *) loca_prime_data, num_offsets); else - _write_loca (padded_offsets, false, hb_array ((HBUINT32 *) loca_prime_data, num_offsets)); + _write_loca (padded_offsets, c->plan->new_to_old_gid_list, false, (HBUINT32 *) loca_prime_data, num_offsets); hb_blob_t *loca_blob = hb_blob_create (loca_prime_data, entry_size * num_offsets, @@ -89,8 +112,8 @@ _add_loca_and_head (hb_subset_plan_t * plan, Iterator padded_offsets, bool use_s loca_prime_data, hb_free); - bool result = plan->add_table (HB_OT_TAG_loca, loca_blob) - && _add_head_and_set_loca_version (plan, use_short_loca); + bool result = c->plan->add_table (HB_OT_TAG_loca, loca_blob) + && _add_head_and_set_loca_version (c->plan, use_short_loca); hb_blob_destroy (loca_blob); return result; diff --git a/src/3rdparty/harfbuzz-ng/src/OT/glyf/glyf.hh b/src/3rdparty/harfbuzz-ng/src/OT/glyf/glyf.hh index dd08dda6ee1..6300cf4be0c 100644 --- a/src/3rdparty/harfbuzz-ng/src/OT/glyf/glyf.hh +++ b/src/3rdparty/harfbuzz-ng/src/OT/glyf/glyf.hh @@ -85,75 +85,72 @@ struct glyf return_trace (false); } - glyf *glyf_prime = c->serializer->start_embed (); - if (unlikely (!c->serializer->check_success (glyf_prime))) return_trace (false); - hb_font_t *font = nullptr; if (c->plan->normalized_coords) { font = _create_font_for_instancing (c->plan); - if (unlikely (!font)) return false; + if (unlikely (!font)) + return_trace (false); } hb_vector_t padded_offsets; - unsigned num_glyphs = c->plan->num_output_glyphs (); - if (unlikely (!padded_offsets.resize (num_glyphs))) - { - hb_font_destroy (font); - return false; - } + if (unlikely (!padded_offsets.alloc (c->plan->new_to_old_gid_list.length, true))) + return_trace (false); hb_vector_t glyphs; if (!_populate_subset_glyphs (c->plan, font, glyphs)) { hb_font_destroy (font); - return false; + return_trace (false); } if (font) hb_font_destroy (font); unsigned max_offset = 0; - for (unsigned i = 0; i < num_glyphs; i++) + for (auto &g : glyphs) { - padded_offsets[i] = glyphs[i].padded_size (); - max_offset += padded_offsets[i]; + unsigned size = g.padded_size (); + padded_offsets.push (size); + max_offset += size; } bool use_short_loca = false; if (likely (!c->plan->force_long_loca)) use_short_loca = max_offset < 0x1FFFF; - if (!use_short_loca) { - for (unsigned i = 0; i < num_glyphs; i++) - padded_offsets[i] = glyphs[i].length (); + if (!use_short_loca) + { + padded_offsets.resize (0); + for (auto &g : glyphs) + padded_offsets.push (g.length ()); } - bool result = glyf_prime->serialize (c->serializer, glyphs.writer (), use_short_loca, c->plan); + auto *glyf_prime = c->serializer->start_embed (); + bool result = glyf_prime->serialize (c->serializer, hb_iter (glyphs), use_short_loca, c->plan); if (c->plan->normalized_coords && !c->plan->pinned_at_default) _free_compiled_subset_glyphs (glyphs); - if (!result) return false; + if (unlikely (!c->serializer->check_success (glyf_impl::_add_loca_and_head (c, + padded_offsets.iter (), + use_short_loca)))) + return_trace (false); - if (unlikely (c->serializer->in_error ())) return_trace (false); - - return_trace (c->serializer->check_success (glyf_impl::_add_loca_and_head (c->plan, - padded_offsets.iter (), - use_short_loca))); + return result; } bool _populate_subset_glyphs (const hb_subset_plan_t *plan, hb_font_t *font, - hb_vector_t &glyphs /* OUT */) const; + hb_vector_t& glyphs /* OUT */) const; hb_font_t * _create_font_for_instancing (const hb_subset_plan_t *plan) const; void _free_compiled_subset_glyphs (hb_vector_t &glyphs) const { - for (unsigned i = 0; i < glyphs.length; i++) - glyphs[i].free_compiled_bytes (); + for (auto &g : glyphs) + g.free_compiled_bytes (); } protected: @@ -222,13 +219,14 @@ struct glyf_accelerator_t if (unlikely (!glyph_for_gid (gid).get_points (font, *this, all_points, nullptr, nullptr, nullptr, true, true, phantom_only))) return false; + unsigned count = all_points.length; + assert (count >= glyf_impl::PHANTOM_COUNT); + count -= glyf_impl::PHANTOM_COUNT; + if (consumer.is_consuming_contour_points ()) { - unsigned count = all_points.length; - assert (count >= glyf_impl::PHANTOM_COUNT); - count -= glyf_impl::PHANTOM_COUNT; - for (unsigned point_index = 0; point_index < count; point_index++) - consumer.consume_point (all_points[point_index]); + for (auto &point : all_points.as_array ().sub_array (0, count)) + consumer.consume_point (point); consumer.points_end (); } @@ -236,7 +234,7 @@ struct glyf_accelerator_t contour_point_t *phantoms = consumer.get_phantoms_sink (); if (phantoms) for (unsigned i = 0; i < glyf_impl::PHANTOM_COUNT; ++i) - phantoms[i] = all_points[all_points.length - glyf_impl::PHANTOM_COUNT + i]; + phantoms[i] = all_points.arrayZ[count + i]; return true; } @@ -299,6 +297,7 @@ struct glyf_accelerator_t if (extents) bounds = contour_bounds_t (); } + HB_ALWAYS_INLINE void consume_point (const contour_point_t &point) { bounds.add (point); } void points_end () { bounds.get_extents (font, extents, scaled); } @@ -431,16 +430,17 @@ glyf::_populate_subset_glyphs (const hb_subset_plan_t *plan, hb_vector_t& glyphs /* OUT */) const { OT::glyf_accelerator_t glyf (plan->source); - unsigned num_glyphs = plan->num_output_glyphs (); - if (!glyphs.resize (num_glyphs)) return false; + if (!glyphs.alloc (plan->new_to_old_gid_list.length, true)) return false; - for (auto p : plan->glyph_map->iter ()) + for (const auto &pair : plan->new_to_old_gid_list) { - unsigned new_gid = p.second; - glyf_impl::SubsetGlyph& subset_glyph = glyphs.arrayZ[new_gid]; - subset_glyph.old_gid = p.first; + hb_codepoint_t new_gid = pair.first; + hb_codepoint_t old_gid = pair.second; + glyf_impl::SubsetGlyph *p = glyphs.push (); + glyf_impl::SubsetGlyph& subset_glyph = *p; + subset_glyph.old_gid = old_gid; - if (unlikely (new_gid == 0 && + if (unlikely (old_gid == 0 && new_gid == 0 && !(plan->flags & HB_SUBSET_FLAGS_NOTDEF_OUTLINE)) && !plan->normalized_coords) subset_glyph.source_glyph = glyf_impl::Glyph (); @@ -487,7 +487,7 @@ glyf::_create_font_for_instancing (const hb_subset_plan_t *plan) const { hb_variation_t var; var.tag = _.first; - var.value = _.second; + var.value = _.second.middle; vars.push (var); } diff --git a/src/3rdparty/harfbuzz-ng/src/OT/glyf/path-builder.hh b/src/3rdparty/harfbuzz-ng/src/OT/glyf/path-builder.hh index f7f732d3363..f5505245033 100644 --- a/src/3rdparty/harfbuzz-ng/src/OT/glyf/path-builder.hh +++ b/src/3rdparty/harfbuzz-ng/src/OT/glyf/path-builder.hh @@ -21,11 +21,11 @@ struct path_builder_t operator bool () const { return has_data; } bool has_data = false; - float x = 0.; - float y = 0.; + float x; + float y; - optional_point_t lerp (optional_point_t p, float t) - { return optional_point_t (x + t * (p.x - x), y + t * (p.y - y)); } + optional_point_t mid (optional_point_t p) + { return optional_point_t ((x + p.x) * 0.5f, (y + p.y) * 0.5f); } } first_oncurve, first_offcurve, first_offcurve2, last_offcurve, last_offcurve2; path_builder_t (hb_font_t *font_, hb_draw_session_t &draw_session_) : @@ -37,6 +37,7 @@ struct path_builder_t * https://stackoverflow.com/a/20772557 * * Cubic support added. */ + HB_ALWAYS_INLINE void consume_point (const contour_point_t &point) { bool is_on_curve = point.flag & glyf_impl::SimpleGlyph::FLAG_ON_CURVE; @@ -46,7 +47,7 @@ struct path_builder_t bool is_cubic = !is_on_curve && (point.flag & glyf_impl::SimpleGlyph::FLAG_CUBIC); #endif optional_point_t p (font->em_fscalef_x (point.x), font->em_fscalef_y (point.y)); - if (!first_oncurve) + if (unlikely (!first_oncurve)) { if (is_on_curve) { @@ -62,7 +63,7 @@ struct path_builder_t } else if (first_offcurve) { - optional_point_t mid = first_offcurve.lerp (p, .5f); + optional_point_t mid = first_offcurve.mid (p); first_oncurve = mid; last_offcurve = p; draw_session->move_to (mid.x, mid.y); @@ -98,7 +99,7 @@ struct path_builder_t } else { - optional_point_t mid = last_offcurve.lerp (p, .5f); + optional_point_t mid = last_offcurve.mid (p); if (is_cubic) { @@ -123,13 +124,13 @@ struct path_builder_t } } - if (point.is_end_point) + if (unlikely (point.is_end_point)) { if (first_offcurve && last_offcurve) { - optional_point_t mid = last_offcurve.lerp (first_offcurve2 ? - first_offcurve2 : - first_offcurve, .5f); + optional_point_t mid = last_offcurve.mid (first_offcurve2 ? + first_offcurve2 : + first_offcurve); if (last_offcurve2) draw_session->cubic_to (last_offcurve2.x, last_offcurve2.y, last_offcurve.x, last_offcurve.y, diff --git a/src/3rdparty/harfbuzz-ng/src/OT/name/name.hh b/src/3rdparty/harfbuzz-ng/src/OT/name/name.hh index c1839f3b683..c8de1013456 100644 --- a/src/3rdparty/harfbuzz-ng/src/OT/name/name.hh +++ b/src/3rdparty/harfbuzz-ng/src/OT/name/name.hh @@ -359,7 +359,7 @@ struct name record.nameID = ids.name_id; record.length = 0; // handled in NameRecord copy() record.offset = 0; - memcpy (name_records, &record, NameRecord::static_size); + hb_memcpy (name_records, &record, NameRecord::static_size); name_records++; } #endif @@ -384,10 +384,7 @@ struct name bool subset (hb_subset_context_t *c) const { - TRACE_SUBSET (this); - - name *name_prime = c->serializer->start_embed (); - if (unlikely (!name_prime)) return_trace (false); + auto *name_prime = c->serializer->start_embed (); #ifdef HB_EXPERIMENTAL_API const hb_hashmap_t *name_table_overrides = @@ -436,7 +433,7 @@ struct name if (!name_table_overrides->is_empty ()) { if (unlikely (!insert_name_records.alloc (name_table_overrides->get_population (), true))) - return_trace (false); + return false; for (const auto& record_ids : name_table_overrides->keys ()) { if (name_table_overrides->get (record_ids).length == 0) @@ -448,13 +445,13 @@ struct name } #endif - return (name_prime->serialize (c->serializer, it, - std::addressof (this + stringOffset) + return name_prime->serialize (c->serializer, it, + std::addressof (this + stringOffset) #ifdef HB_EXPERIMENTAL_API - , insert_name_records - , name_table_overrides + , insert_name_records + , name_table_overrides #endif - )); + ); } bool sanitize_records (hb_sanitize_context_t *c) const diff --git a/src/3rdparty/harfbuzz-ng/src/graph/classdef-graph.hh b/src/3rdparty/harfbuzz-ng/src/graph/classdef-graph.hh index c2e24a70678..c1432883ffa 100644 --- a/src/3rdparty/harfbuzz-ng/src/graph/classdef-graph.hh +++ b/src/3rdparty/harfbuzz-ng/src/graph/classdef-graph.hh @@ -72,7 +72,7 @@ struct ClassDef : public OT::ClassDef class_def_link->width = SmallTypes::size; class_def_link->objidx = class_def_prime_id; class_def_link->position = link_position; - class_def_prime_vertex.parents.push (parent_id); + class_def_prime_vertex.add_parent (parent_id); return true; } @@ -94,7 +94,13 @@ struct ClassDef : public OT::ClassDef } hb_bytes_t class_def_copy = serializer.copy_bytes (); - c.add_buffer ((char *) class_def_copy.arrayZ); // Give ownership to the context, it will cleanup the buffer. + if (!class_def_copy.arrayZ) return false; + // Give ownership to the context, it will cleanup the buffer. + if (!c.add_buffer ((char *) class_def_copy.arrayZ)) + { + hb_free ((char *) class_def_copy.arrayZ); + return false; + } auto& obj = c.graph.vertices_[dest_obj].obj; obj.head = (char *) class_def_copy.arrayZ; diff --git a/src/3rdparty/harfbuzz-ng/src/graph/coverage-graph.hh b/src/3rdparty/harfbuzz-ng/src/graph/coverage-graph.hh index 49d09363156..4f44e076d1f 100644 --- a/src/3rdparty/harfbuzz-ng/src/graph/coverage-graph.hh +++ b/src/3rdparty/harfbuzz-ng/src/graph/coverage-graph.hh @@ -96,7 +96,7 @@ struct Coverage : public OT::Layout::Common::Coverage coverage_link->width = SmallTypes::size; coverage_link->objidx = coverage_prime_id; coverage_link->position = link_position; - coverage_prime_vertex.parents.push (parent_id); + coverage_prime_vertex.add_parent (parent_id); return (Coverage*) coverage_prime_vertex.obj.head; } @@ -118,7 +118,13 @@ struct Coverage : public OT::Layout::Common::Coverage } hb_bytes_t coverage_copy = serializer.copy_bytes (); - c.add_buffer ((char *) coverage_copy.arrayZ); // Give ownership to the context, it will cleanup the buffer. + if (!coverage_copy.arrayZ) return false; + // Give ownership to the context, it will cleanup the buffer. + if (!c.add_buffer ((char *) coverage_copy.arrayZ)) + { + hb_free ((char *) coverage_copy.arrayZ); + return false; + } auto& obj = c.graph.vertices_[dest_obj].obj; obj.head = (char *) coverage_copy.arrayZ; diff --git a/src/3rdparty/harfbuzz-ng/src/graph/graph.hh b/src/3rdparty/harfbuzz-ng/src/graph/graph.hh index 294a9999185..06809581904 100644 --- a/src/3rdparty/harfbuzz-ng/src/graph/graph.hh +++ b/src/3rdparty/harfbuzz-ng/src/graph/graph.hh @@ -43,12 +43,28 @@ struct graph_t { hb_serialize_context_t::object_t obj; int64_t distance = 0 ; - int64_t space = 0 ; - hb_vector_t parents; + unsigned space = 0 ; unsigned start = 0; unsigned end = 0; unsigned priority = 0; + private: + unsigned incoming_edges_ = 0; + unsigned single_parent = (unsigned) -1; + hb_hashmap_t parents; + public: + auto parents_iter () const HB_AUTO_RETURN + ( + hb_concat ( + hb_iter (&single_parent, single_parent != (unsigned) -1), + parents.keys_ref () + ) + ) + + bool in_error () const + { + return parents.in_error (); + } bool link_positions_valid (unsigned num_objects, bool removed_nil) { @@ -143,7 +159,9 @@ struct graph_t hb_swap (a.obj, b.obj); hb_swap (a.distance, b.distance); hb_swap (a.space, b.space); + hb_swap (a.single_parent, b.single_parent); hb_swap (a.parents, b.parents); + hb_swap (a.incoming_edges_, b.incoming_edges_); hb_swap (a.start, b.start); hb_swap (a.end, b.end); hb_swap (a.priority, b.priority); @@ -154,6 +172,7 @@ struct graph_t { hb_hashmap_t result; + result.alloc (obj.real_links.length); for (const auto& l : obj.real_links) { result.set (l.position, l.objidx); } @@ -163,22 +182,76 @@ struct graph_t bool is_shared () const { - return parents.length > 1; + return parents.get_population () > 1; } unsigned incoming_edges () const { - return parents.length; + if (HB_DEBUG_SUBSET_REPACK) + { + assert (incoming_edges_ == (single_parent != (unsigned) -1) + + (parents.values_ref () | hb_reduce (hb_add, 0))); + } + return incoming_edges_; + } + + void reset_parents () + { + incoming_edges_ = 0; + single_parent = (unsigned) -1; + parents.reset (); + } + + void add_parent (unsigned parent_index) + { + assert (parent_index != (unsigned) -1); + if (incoming_edges_ == 0) + { + single_parent = parent_index; + incoming_edges_ = 1; + return; + } + else if (single_parent != (unsigned) -1) + { + assert (incoming_edges_ == 1); + if (!parents.set (single_parent, 1)) + return; + single_parent = (unsigned) -1; + } + + unsigned *v; + if (parents.has (parent_index, &v)) + { + (*v)++; + incoming_edges_++; + } + else if (parents.set (parent_index, 1)) + incoming_edges_++; } void remove_parent (unsigned parent_index) { - unsigned count = parents.length; - for (unsigned i = 0; i < count; i++) + if (parent_index == single_parent) { - if (parents.arrayZ[i] != parent_index) continue; - parents.remove_unordered (i); - break; + single_parent = (unsigned) -1; + incoming_edges_--; + return; + } + + unsigned *v; + if (parents.has (parent_index, &v)) + { + incoming_edges_--; + if (*v > 1) + (*v)--; + else + parents.del (parent_index); + + if (incoming_edges_ == 1) + { + single_parent = *parents.keys (); + parents.reset (); + } } } @@ -199,20 +272,46 @@ struct graph_t } } - void remap_parents (const hb_vector_t& id_map) + bool remap_parents (const hb_vector_t& id_map) { - unsigned count = parents.length; - for (unsigned i = 0; i < count; i++) - parents.arrayZ[i] = id_map[parents.arrayZ[i]]; + if (single_parent != (unsigned) -1) + { + assert (single_parent < id_map.length); + single_parent = id_map[single_parent]; + return true; + } + + hb_hashmap_t new_parents; + new_parents.alloc (parents.get_population ()); + for (auto _ : parents) + { + assert (_.first < id_map.length); + assert (!new_parents.has (id_map[_.first])); + new_parents.set (id_map[_.first], _.second); + } + + if (new_parents.in_error ()) + return false; + + parents = std::move (new_parents); + return true; } void remap_parent (unsigned old_index, unsigned new_index) { - unsigned count = parents.length; - for (unsigned i = 0; i < count; i++) + if (single_parent != (unsigned) -1) { - if (parents.arrayZ[i] == old_index) - parents.arrayZ[i] = new_index; + if (single_parent == old_index) + single_parent = new_index; + return; + } + + const unsigned *pv; + if (parents.has (old_index, &pv)) + { + unsigned v = *pv; + parents.set (new_index, v); + parents.del (old_index); } } @@ -359,7 +458,6 @@ struct graph_t ~graph_t () { - vertices_.fini (); for (char* b : buffers) hb_free (b); } @@ -401,9 +499,10 @@ struct graph_t return vertices_[i].obj; } - void add_buffer (char* buffer) + bool add_buffer (char* buffer) { buffers.push (buffer); + return !buffers.in_error (); } /* @@ -419,7 +518,7 @@ struct graph_t link->width = 2; link->objidx = child_id; link->position = (char*) offset - (char*) v.obj.head; - vertices_[child_id].parents.push (parent_id); + vertices_[child_id].add_parent (parent_id); } /* @@ -465,7 +564,7 @@ struct graph_t { unsigned next_id = queue.pop_minimum().second; - hb_swap (sorted_graph[new_id], vertices_[next_id]); + sorted_graph[new_id] = std::move (vertices_[next_id]); const vertex_t& next = sorted_graph[new_id]; if (unlikely (!check_success(new_id >= 0))) { @@ -493,8 +592,8 @@ struct graph_t check_success (!queue.in_error ()); check_success (!sorted_graph.in_error ()); - remap_all_obj_indices (id_map, &sorted_graph); - hb_swap (vertices_, sorted_graph); + check_success (remap_all_obj_indices (id_map, &sorted_graph)); + vertices_ = std::move (sorted_graph); if (!check_success (new_id == -1)) print_orphaned_nodes (); @@ -605,7 +704,7 @@ struct graph_t { unsigned child_idx = index_for_offset (node_idx, offset); auto& child = vertices_[child_idx]; - for (unsigned p : child.parents) + for (unsigned p : child.parents_iter ()) { if (p != node_idx) { return duplicate (node_idx, child_idx); @@ -688,12 +787,15 @@ struct graph_t subgraph.set (root_idx, wide_parents (root_idx, parents)); find_subgraph (root_idx, subgraph); } + if (subgraph.in_error ()) + return false; unsigned original_root_idx = root_idx (); hb_map_t index_map; bool made_changes = false; for (auto entry : subgraph.iter ()) { + assert (entry.first < vertices_.length); const auto& node = vertices_[entry.first]; unsigned subgraph_incoming_edges = entry.second; @@ -732,8 +834,7 @@ struct graph_t remap_obj_indices (index_map, parents.iter (), true); // Update roots set with new indices as needed. - uint32_t next = HB_SET_VALUE_INVALID; - while (roots.next (&next)) + for (auto next : roots) { const uint32_t *v; if (index_map.has (next, &v)) @@ -750,10 +851,10 @@ struct graph_t { for (const auto& link : vertices_[node_idx].obj.all_links ()) { - const uint32_t *v; + hb_codepoint_t *v; if (subgraph.has (link.objidx, &v)) { - subgraph.set (link.objidx, *v + 1); + (*v)++; continue; } subgraph.set (link.objidx, 1); @@ -825,7 +926,7 @@ struct graph_t new_link->position = (const char*) new_offset - (const char*) new_v.obj.head; auto& child = vertices_[child_id]; - child.parents.push (new_parent_idx); + child.add_parent (new_parent_idx); old_v.remove_real_link (child_id, old_offset); child.remove_parent (old_parent_idx); @@ -869,18 +970,18 @@ struct graph_t clone->obj.tail = child.obj.tail; clone->distance = child.distance; clone->space = child.space; - clone->parents.reset (); + clone->reset_parents (); unsigned clone_idx = vertices_.length - 2; for (const auto& l : child.obj.real_links) { clone->obj.real_links.push (l); - vertices_[l.objidx].parents.push (clone_idx); + vertices_[l.objidx].add_parent (clone_idx); } for (const auto& l : child.obj.virtual_links) { clone->obj.virtual_links.push (l); - vertices_[l.objidx].parents.push (clone_idx); + vertices_[l.objidx].add_parent (clone_idx); } check_success (!clone->obj.real_links.in_error ()); @@ -1009,13 +1110,13 @@ struct graph_t { update_parents(); - if (root().parents) + if (root().incoming_edges ()) // Root cannot have parents. return false; for (unsigned i = 0; i < root_idx (); i++) { - if (!vertices_[i].parents) + if (!vertices_[i].incoming_edges ()) return false; } return true; @@ -1079,14 +1180,14 @@ struct graph_t parents_invalid = true; update_parents(); - if (root().parents) { + if (root().incoming_edges ()) { DEBUG_MSG (SUBSET_REPACK, nullptr, "Root node has incoming edges."); } for (unsigned i = 0; i < root_idx (); i++) { const auto& v = vertices_[i]; - if (!v.parents) + if (!v.incoming_edges ()) DEBUG_MSG (SUBSET_REPACK, nullptr, "Node %u is orphaned.", i); } } @@ -1118,6 +1219,8 @@ struct graph_t unsigned space_for (unsigned index, unsigned* root = nullptr) const { + loop: + assert (index < vertices_.length); const auto& node = vertices_[index]; if (node.space) { @@ -1126,14 +1229,15 @@ struct graph_t return node.space; } - if (!node.parents) + if (!node.incoming_edges ()) { if (root) *root = index; return 0; } - return space_for (node.parents[0], root); + index = *node.parents_iter (); + goto loop; } void err_other_error () { this->successful = false; } @@ -1157,12 +1261,8 @@ struct graph_t unsigned wide_parents (unsigned node_idx, hb_set_t& parents) const { unsigned count = 0; - hb_set_t visited; - for (unsigned p : vertices_[node_idx].parents) + for (unsigned p : vertices_[node_idx].parents_iter ()) { - if (visited.has (p)) continue; - visited.add (p); - // Only real links can be wide for (const auto& l : vertices_[p].obj.real_links) { @@ -1192,20 +1292,18 @@ struct graph_t unsigned count = vertices_.length; for (unsigned i = 0; i < count; i++) - vertices_.arrayZ[i].parents.reset (); + vertices_.arrayZ[i].reset_parents (); for (unsigned p = 0; p < count; p++) { for (auto& l : vertices_.arrayZ[p].obj.all_links ()) - { - vertices_[l.objidx].parents.push (p); - } + vertices_[l.objidx].add_parent (p); } for (unsigned i = 0; i < count; i++) // parents arrays must be accurate or downstream operations like cycle detection // and sorting won't work correctly. - check_success (!vertices_.arrayZ[i].parents.in_error ()); + check_success (!vertices_.arrayZ[i].in_error ()); parents_invalid = false; } @@ -1249,12 +1347,8 @@ struct graph_t // (such as a fibonacci queue) with a fast decrease priority. unsigned count = vertices_.length; for (unsigned i = 0; i < count; i++) - { - if (i == vertices_.length - 1) - vertices_.arrayZ[i].distance = 0; - else - vertices_.arrayZ[i].distance = hb_int_max (int64_t); - } + vertices_.arrayZ[i].distance = hb_int_max (int64_t); + vertices_.tail ().distance = 0; hb_priority_queue_t queue; queue.insert (0, vertices_.length - 1); @@ -1274,15 +1368,15 @@ struct graph_t { if (visited[link.objidx]) continue; - const auto& child = vertices_[link.objidx].obj; + const auto& child = vertices_.arrayZ[link.objidx].obj; unsigned link_width = link.width ? link.width : 4; // treat virtual offsets as 32 bits wide int64_t child_weight = (child.tail - child.head) + - ((int64_t) 1 << (link_width * 8)) * (vertices_[link.objidx].space + 1); + ((int64_t) 1 << (link_width * 8)) * (vertices_.arrayZ[link.objidx].space + 1); int64_t child_distance = next_distance + child_weight; - if (child_distance < vertices_[link.objidx].distance) + if (child_distance < vertices_.arrayZ[link.objidx].distance) { - vertices_[link.objidx].distance = child_distance; + vertices_.arrayZ[link.objidx].distance = child_distance; queue.insert (child_distance, link.objidx); } } @@ -1310,7 +1404,7 @@ struct graph_t unsigned old_idx = link.objidx; link.objidx = new_idx; vertices_[old_idx].remove_parent (parent_idx); - vertices_[new_idx].parents.push (parent_idx); + vertices_[new_idx].add_parent (parent_idx); } /* @@ -1338,18 +1432,20 @@ struct graph_t /* * Updates all objidx's in all links using the provided mapping. */ - void remap_all_obj_indices (const hb_vector_t& id_map, + bool remap_all_obj_indices (const hb_vector_t& id_map, hb_vector_t* sorted_graph) const { unsigned count = sorted_graph->length; for (unsigned i = 0; i < count; i++) { - (*sorted_graph)[i].remap_parents (id_map); + if (!(*sorted_graph)[i].remap_parents (id_map)) + return false; for (auto& link : sorted_graph->arrayZ[i].obj.all_links_writer ()) { link.objidx = id_map[link.objidx]; } } + return true; } /* @@ -1380,7 +1476,7 @@ struct graph_t for (const auto& l : v.obj.all_links ()) find_connected_nodes (l.objidx, targets, visited, connected); - for (unsigned p : v.parents) + for (unsigned p : v.parents_iter ()) find_connected_nodes (p, targets, visited, connected); } diff --git a/src/3rdparty/harfbuzz-ng/src/graph/gsubgpos-context.cc b/src/3rdparty/harfbuzz-ng/src/graph/gsubgpos-context.cc index b2044426d46..d66eb49cfd2 100644 --- a/src/3rdparty/harfbuzz-ng/src/graph/gsubgpos-context.cc +++ b/src/3rdparty/harfbuzz-ng/src/graph/gsubgpos-context.cc @@ -52,7 +52,11 @@ unsigned gsubgpos_graph_context_t::create_node (unsigned size) if (!buffer) return -1; - add_buffer (buffer); + if (!add_buffer (buffer)) { + // Allocation did not get stored for freeing later. + hb_free (buffer); + return -1; + } return graph.new_node (buffer, buffer + size); } diff --git a/src/3rdparty/harfbuzz-ng/src/graph/gsubgpos-context.hh b/src/3rdparty/harfbuzz-ng/src/graph/gsubgpos-context.hh index 9fe9662e645..26b7cfe4d43 100644 --- a/src/3rdparty/harfbuzz-ng/src/graph/gsubgpos-context.hh +++ b/src/3rdparty/harfbuzz-ng/src/graph/gsubgpos-context.hh @@ -47,9 +47,9 @@ struct gsubgpos_graph_context_t HB_INTERNAL unsigned create_node (unsigned size); - void add_buffer (char* buffer) + bool add_buffer (char* buffer) { - graph.add_buffer (buffer); + return graph.add_buffer (buffer); } private: diff --git a/src/3rdparty/harfbuzz-ng/src/graph/gsubgpos-graph.hh b/src/3rdparty/harfbuzz-ng/src/graph/gsubgpos-graph.hh index c170638409f..303517f687e 100644 --- a/src/3rdparty/harfbuzz-ng/src/graph/gsubgpos-graph.hh +++ b/src/3rdparty/harfbuzz-ng/src/graph/gsubgpos-graph.hh @@ -166,7 +166,7 @@ struct Lookup : public OT::Lookup } if (all_new_subtables) { - add_sub_tables (c, this_index, type, all_new_subtables); + return add_sub_tables (c, this_index, type, all_new_subtables); } return true; @@ -184,7 +184,7 @@ struct Lookup : public OT::Lookup return sub_table->split_subtables (c, parent_idx, objidx); } - void add_sub_tables (gsubgpos_graph_context_t& c, + bool add_sub_tables (gsubgpos_graph_context_t& c, unsigned this_index, unsigned type, hb_vector_t>>& subtable_ids) @@ -200,7 +200,12 @@ struct Lookup : public OT::Lookup size_t new_size = v.table_size () + new_subtable_count * OT::Offset16::static_size; char* buffer = (char*) hb_calloc (1, new_size); - c.add_buffer (buffer); + if (!buffer) return false; + if (!c.add_buffer (buffer)) + { + hb_free (buffer); + return false; + } hb_memcpy (buffer, v.obj.head, v.table_size()); v.obj.head = buffer; @@ -220,7 +225,7 @@ struct Lookup : public OT::Lookup if (is_ext) { unsigned ext_id = create_extension_subtable (c, subtable_id, type); - c.graph.vertices_[subtable_id].parents.push (ext_id); + c.graph.vertices_[subtable_id].add_parent (ext_id); subtable_id = ext_id; } @@ -229,7 +234,7 @@ struct Lookup : public OT::Lookup link->objidx = subtable_id; link->position = (char*) &new_lookup->subTable[offset_index++] - (char*) new_lookup; - c.graph.vertices_[subtable_id].parents.push (this_index); + c.graph.vertices_[subtable_id].add_parent (this_index); } } @@ -239,6 +244,7 @@ struct Lookup : public OT::Lookup // The head location of the lookup has changed, invalidating the lookups map entry // in the context. Update the map. c.lookups.set (this_index, new_lookup); + return true; } void fix_existing_subtable_links (gsubgpos_graph_context_t& c, @@ -309,7 +315,7 @@ struct Lookup : public OT::Lookup // Make extension point at the subtable. auto& ext_vertex = c.graph.vertices_[ext_index]; auto& subtable_vertex = c.graph.vertices_[subtable_index]; - ext_vertex.parents.push (lookup_index); + ext_vertex.add_parent (lookup_index); subtable_vertex.remap_parent (lookup_index, ext_index); return true; diff --git a/src/3rdparty/harfbuzz-ng/src/graph/pairpos-graph.hh b/src/3rdparty/harfbuzz-ng/src/graph/pairpos-graph.hh index 1c13eb24f94..ad158cc9e8f 100644 --- a/src/3rdparty/harfbuzz-ng/src/graph/pairpos-graph.hh +++ b/src/3rdparty/harfbuzz-ng/src/graph/pairpos-graph.hh @@ -215,7 +215,7 @@ struct PairPosFormat2 : public OT::Layout::GPOS_impl::PairPosFormat2_4iter () | hb_map_retains_sorting ([&] (hb_codepoint_t gid) { - return hb_pair_t (gid, class_def_1->get_class (gid)); + return hb_codepoint_pair_t (gid, class_def_1->get_class (gid)); }) ; class_def_size_estimator_t estimator (gid_and_class); @@ -386,14 +386,14 @@ struct PairPosFormat2 : public OT::Layout::GPOS_impl::PairPosFormat2_4iter () | hb_map_retains_sorting ([&] (hb_codepoint_t gid) { - return hb_pair_t (gid, class_def_1_table->get_class (gid)); + return hb_codepoint_pair_t (gid, class_def_1_table->get_class (gid)); }) | hb_filter ([&] (hb_codepoint_t klass) { return klass >= start && klass < end; }, hb_second) - | hb_map_retains_sorting ([&] (hb_pair_t gid_and_class) { + | hb_map_retains_sorting ([&] (hb_codepoint_pair_t gid_and_class) { // Classes must be from 0...N so subtract start - return hb_pair_t (gid_and_class.first, gid_and_class.second - start); + return hb_codepoint_pair_t (gid_and_class.first, gid_and_class.second - start); }) ; @@ -419,7 +419,7 @@ struct PairPosFormat2 : public OT::Layout::GPOS_impl::PairPosFormat2_4width = SmallTypes::size; class_def_link->objidx = class_def_2_id; class_def_link->position = 10; - graph.vertices_[class_def_2_id].parents.push (pair_pos_prime_id); + graph.vertices_[class_def_2_id].add_parent (pair_pos_prime_id); graph.duplicate (pair_pos_prime_id, class_def_2_id); return pair_pos_prime_id; @@ -519,7 +519,7 @@ struct PairPosFormat2 : public OT::Layout::GPOS_impl::PairPosFormat2_4iter () | hb_map_retains_sorting ([&] (hb_codepoint_t gid) { - return hb_pair_t (gid, class_def_1.table->get_class (gid)); + return hb_codepoint_pair_t (gid, class_def_1.table->get_class (gid)); }) | hb_filter ([&] (hb_codepoint_t klass) { return klass < count; diff --git a/src/3rdparty/harfbuzz-ng/src/graph/serialize.hh b/src/3rdparty/harfbuzz-ng/src/graph/serialize.hh index 2e0b845baa9..06e4bf44d8e 100644 --- a/src/3rdparty/harfbuzz-ng/src/graph/serialize.hh +++ b/src/3rdparty/harfbuzz-ng/src/graph/serialize.hh @@ -226,6 +226,9 @@ inline hb_blob_t* serialize (const graph_t& graph) { hb_vector_t buffer; size_t size = graph.total_size_in_bytes (); + + if (!size) return hb_blob_get_empty (); + if (!buffer.alloc (size)) { DEBUG_MSG (SUBSET_REPACK, nullptr, "Unable to allocate output buffer."); return nullptr; diff --git a/src/3rdparty/harfbuzz-ng/src/graph/test-classdef-graph.cc b/src/3rdparty/harfbuzz-ng/src/graph/test-classdef-graph.cc index 55854ff5c29..266be5e2d40 100644 --- a/src/3rdparty/harfbuzz-ng/src/graph/test-classdef-graph.cc +++ b/src/3rdparty/harfbuzz-ng/src/graph/test-classdef-graph.cc @@ -27,7 +27,7 @@ #include "gsubgpos-context.hh" #include "classdef-graph.hh" -typedef hb_pair_t gid_and_class_t; +typedef hb_codepoint_pair_t gid_and_class_t; typedef hb_vector_t gid_and_class_list_t; diff --git a/src/3rdparty/harfbuzz-ng/src/harfbuzz.cc b/src/3rdparty/harfbuzz-ng/src/harfbuzz.cc index d7e8a93f393..26e2bc1450d 100644 --- a/src/3rdparty/harfbuzz-ng/src/harfbuzz.cc +++ b/src/3rdparty/harfbuzz-ng/src/harfbuzz.cc @@ -58,3 +58,5 @@ #include "hb-ucd.cc" #include "hb-unicode.cc" #include "hb-uniscribe.cc" +#include "hb-wasm-api.cc" +#include "hb-wasm-shape.cc" diff --git a/src/3rdparty/harfbuzz-ng/src/hb-aat-layout-trak-table.hh b/src/3rdparty/harfbuzz-ng/src/hb-aat-layout-trak-table.hh index 2ba9355b06b..c72c0865d3e 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-aat-layout-trak-table.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-aat-layout-trak-table.hh @@ -111,13 +111,13 @@ struct TrackData break; } } - if (!trackTableEntry) return 0.; + if (!trackTableEntry) return 0; /* * Choose size. */ unsigned int sizes = nSizes; - if (!sizes) return 0.; + if (!sizes) return 0; if (sizes == 1) return trackTableEntry->get_value (base, 0, sizes); hb_array_t size_table ((base+sizeTable).arrayZ, sizes); diff --git a/src/3rdparty/harfbuzz-ng/src/hb-algs.hh b/src/3rdparty/harfbuzz-ng/src/hb-algs.hh index da383e050a9..6cabc7fb02d 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-algs.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-algs.hh @@ -87,6 +87,19 @@ static inline constexpr uint16_t hb_uint16_swap (uint16_t v) static inline constexpr uint32_t hb_uint32_swap (uint32_t v) { return (hb_uint16_swap (v) << 16) | hb_uint16_swap (v >> 16); } +#ifndef HB_FAST_INT_ACCESS +#if defined(__OPTIMIZE__) && \ + defined(__BYTE_ORDER) && \ + (__BYTE_ORDER == __BIG_ENDIAN || \ + (__BYTE_ORDER == __LITTLE_ENDIAN && \ + hb_has_builtin(__builtin_bswap16) && \ + hb_has_builtin(__builtin_bswap32))) +#define HB_FAST_INT_ACCESS 1 +#else +#define HB_FAST_INT_ACCESS 0 +#endif +#endif + template struct BEInt; template @@ -101,21 +114,25 @@ struct BEInt template struct BEInt { + struct __attribute__((packed)) packed_uint16_t { uint16_t v; }; + public: BEInt () = default; - constexpr BEInt (Type V) : v {uint8_t ((V >> 8) & 0xFF), - uint8_t ((V ) & 0xFF)} {} - struct __attribute__((packed)) packed_uint16_t { uint16_t v; }; - constexpr operator Type () const - { -#if defined(__OPTIMIZE__) && !defined(HB_NO_PACKED) && \ - defined(__BYTE_ORDER) && \ - (__BYTE_ORDER == __BIG_ENDIAN || \ - (__BYTE_ORDER == __LITTLE_ENDIAN && \ - hb_has_builtin(__builtin_bswap16))) - /* Spoon-feed the compiler a big-endian integer with alignment 1. - * https://github.com/harfbuzz/harfbuzz/pull/1398 */ + BEInt (Type V) +#if HB_FAST_INT_ACCESS +#if __BYTE_ORDER == __LITTLE_ENDIAN + { ((packed_uint16_t *) v)->v = __builtin_bswap16 (V); } +#else /* __BYTE_ORDER == __BIG_ENDIAN */ + { ((packed_uint16_t *) v)->v = V; } +#endif +#else + : v {uint8_t ((V >> 8) & 0xFF), + uint8_t ((V ) & 0xFF)} {} +#endif + + constexpr operator Type () const { +#if HB_FAST_INT_ACCESS #if __BYTE_ORDER == __LITTLE_ENDIAN return __builtin_bswap16 (((packed_uint16_t *) v)->v); #else /* __BYTE_ORDER == __BIG_ENDIAN */ @@ -146,22 +163,27 @@ struct BEInt template struct BEInt { + struct __attribute__((packed)) packed_uint32_t { uint32_t v; }; + public: BEInt () = default; - constexpr BEInt (Type V) : v {uint8_t ((V >> 24) & 0xFF), - uint8_t ((V >> 16) & 0xFF), - uint8_t ((V >> 8) & 0xFF), - uint8_t ((V ) & 0xFF)} {} - struct __attribute__((packed)) packed_uint32_t { uint32_t v; }; + BEInt (Type V) +#if HB_FAST_INT_ACCESS +#if __BYTE_ORDER == __LITTLE_ENDIAN + { ((packed_uint32_t *) v)->v = __builtin_bswap32 (V); } +#else /* __BYTE_ORDER == __BIG_ENDIAN */ + { ((packed_uint32_t *) v)->v = V; } +#endif +#else + : v {uint8_t ((V >> 24) & 0xFF), + uint8_t ((V >> 16) & 0xFF), + uint8_t ((V >> 8) & 0xFF), + uint8_t ((V ) & 0xFF)} {} +#endif + constexpr operator Type () const { -#if defined(__OPTIMIZE__) && !defined(HB_NO_PACKED) && \ - defined(__BYTE_ORDER) && \ - (__BYTE_ORDER == __BIG_ENDIAN || \ - (__BYTE_ORDER == __LITTLE_ENDIAN && \ - hb_has_builtin(__builtin_bswap32))) - /* Spoon-feed the compiler a big-endian integer with alignment 1. - * https://github.com/harfbuzz/harfbuzz/pull/1398 */ +#if HB_FAST_INT_ACCESS #if __BYTE_ORDER == __LITTLE_ENDIAN return __builtin_bswap32 (((packed_uint32_t *) v)->v); #else /* __BYTE_ORDER == __BIG_ENDIAN */ @@ -231,12 +253,119 @@ struct } HB_FUNCOBJ (hb_bool); + +/* The MIT License + + Copyright (C) 2012 Zilong Tan (eric.zltan@gmail.com) + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation + files (the "Software"), to deal in the Software without + restriction, including without limitation the rights to use, copy, + modify, merge, publish, distribute, sublicense, and/or sell copies + of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*/ + + +// Compression function for Merkle-Damgard construction. +// This function is generated using the framework provided. +#define mix(h) ( \ + (void) ((h) ^= (h) >> 23), \ + (void) ((h) *= 0x2127599bf4325c37ULL), \ + (h) ^= (h) >> 47) + +static inline uint64_t fasthash64(const void *buf, size_t len, uint64_t seed) +{ + struct __attribute__((packed)) packed_uint64_t { uint64_t v; }; + const uint64_t m = 0x880355f21e6d1965ULL; + const packed_uint64_t *pos = (const packed_uint64_t *)buf; + const packed_uint64_t *end = pos + (len / 8); + const unsigned char *pos2; + uint64_t h = seed ^ (len * m); + uint64_t v; + +#ifndef HB_OPTIMIZE_SIZE + if (((uintptr_t) pos & 7) == 0) + { + while (pos != end) + { +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wcast-align" + v = * (const uint64_t *) (pos++); +#pragma GCC diagnostic pop + h ^= mix(v); + h *= m; + } + } + else +#endif + { + while (pos != end) + { + v = pos++->v; + h ^= mix(v); + h *= m; + } + } + + pos2 = (const unsigned char*)pos; + v = 0; + + switch (len & 7) { + case 7: v ^= (uint64_t)pos2[6] << 48; HB_FALLTHROUGH; + case 6: v ^= (uint64_t)pos2[5] << 40; HB_FALLTHROUGH; + case 5: v ^= (uint64_t)pos2[4] << 32; HB_FALLTHROUGH; + case 4: v ^= (uint64_t)pos2[3] << 24; HB_FALLTHROUGH; + case 3: v ^= (uint64_t)pos2[2] << 16; HB_FALLTHROUGH; + case 2: v ^= (uint64_t)pos2[1] << 8; HB_FALLTHROUGH; + case 1: v ^= (uint64_t)pos2[0]; + h ^= mix(v); + h *= m; + } + + return mix(h); +} + +static inline uint32_t fasthash32(const void *buf, size_t len, uint32_t seed) +{ + // the following trick converts the 64-bit hashcode to Fermat + // residue, which shall retain information from both the higher + // and lower parts of hashcode. + uint64_t h = fasthash64(buf, len, seed); + return h - (h >> 32); +} + struct { private: template constexpr auto - impl (const T& v, hb_priority<1>) const HB_RETURN (uint32_t, hb_deref (v).hash ()) + impl (const T& v, hb_priority<2>) const HB_RETURN (uint32_t, hb_deref (v).hash ()) + + // Horrible: std:hash() of integers seems to be identity in gcc / clang?! + // https://github.com/harfbuzz/harfbuzz/pull/4228 + // + // For performance characteristics see: + // https://github.com/harfbuzz/harfbuzz/pull/4228#issuecomment-1565079537 + template ::value && sizeof (T) <= sizeof (uint32_t))> constexpr auto + impl (const T& v, hb_priority<1>) const HB_RETURN (uint32_t, (uint32_t) v * 2654435761u /* Knuh's multiplicative hash */) + template ::value && sizeof (T) > sizeof (uint32_t))> constexpr auto + impl (const T& v, hb_priority<1>) const HB_RETURN (uint32_t, (uint32_t) (v ^ (v >> 32)) * 2654435761u /* Knuth's multiplicative hash */) template constexpr auto impl (const T& v, hb_priority<0>) const HB_RETURN (uint32_t, std::hash>{} (hb_deref (v))) @@ -551,6 +680,8 @@ struct hb_pair_t template static inline hb_pair_t hb_pair (T1&& a, T2&& b) { return hb_pair_t (a, b); } +typedef hb_pair_t hb_codepoint_pair_t; + struct { template constexpr typename Pair::first_t @@ -853,7 +984,7 @@ static inline void * hb_memset (void *s, int c, unsigned int n) { /* It's illegal to pass NULL to memset(), even if n is zero. */ - if (unlikely (!n)) return 0; + if (unlikely (!n)) return s; return memset (s, c, n); } diff --git a/src/3rdparty/harfbuzz-ng/src/hb-array.hh b/src/3rdparty/harfbuzz-ng/src/hb-array.hh index 1a22e15c0fb..760f90259c8 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-array.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-array.hh @@ -75,11 +75,25 @@ struct hb_array_t : hb_iter_with_fallback_t, Type&> */ typedef Type& __item_t__; static constexpr bool is_random_access_iterator = true; + static constexpr bool has_fast_len = true; + Type& __item__ () const + { + if (unlikely (!length)) return CrapOrNull (Type); + return *arrayZ; + } Type& __item_at__ (unsigned i) const { if (unlikely (i >= length)) return CrapOrNull (Type); return arrayZ[i]; } + void __next__ () + { + if (unlikely (!length)) + return; + length--; + backwards_length++; + arrayZ++; + } void __forward__ (unsigned n) { if (unlikely (n > length)) @@ -88,6 +102,14 @@ struct hb_array_t : hb_iter_with_fallback_t, Type&> backwards_length += n; arrayZ += n; } + void __prev__ () + { + if (unlikely (!backwards_length)) + return; + length++; + backwards_length--; + arrayZ--; + } void __rewind__ (unsigned n) { if (unlikely (n > backwards_length)) @@ -123,6 +145,7 @@ struct hb_array_t : hb_iter_with_fallback_t, Type&> uint32_t hash () const { // FNV-1a hash function + // https://github.com/harfbuzz/harfbuzz/pull/4228 uint32_t current = /*cbf29ce4*/0x84222325; for (auto &v : *this) { @@ -326,6 +349,7 @@ struct hb_sorted_array_t : HB_ITER_USING (iter_base_t); static constexpr bool is_random_access_iterator = true; static constexpr bool is_sorted_iterator = true; + static constexpr bool has_fast_len = true; hb_sorted_array_t () = default; hb_sorted_array_t (const hb_sorted_array_t&) = default; @@ -453,55 +477,21 @@ inline bool hb_array_t::operator == (const hb_array_t inline uint32_t hb_array_t::hash () const { - // FNV-1a hash function - uint32_t current = /*cbf29ce4*/0x84222325; - unsigned i = 0; - -#if defined(__OPTIMIZE__) && !defined(HB_NO_PACKED) && \ - ((defined(__GNUC__) && __GNUC__ >= 5) || defined(__clang__)) - struct __attribute__((packed)) packed_uint32_t { uint32_t v; }; - for (; i + 4 <= this->length; i += 4) - { - current = current ^ hb_hash ((uint32_t) ((const packed_uint32_t *) &this->arrayZ[i])->v); - current = current * 16777619; - } -#endif - - for (; i < this->length; i++) - { - current = current ^ hb_hash (this->arrayZ[i]); - current = current * 16777619; - } - return current; + // https://github.com/harfbuzz/harfbuzz/pull/4228 + return fasthash32(arrayZ, length, 0xf437ffe6 /* magic? */); } template <> inline uint32_t hb_array_t::hash () const { - // FNV-1a hash function - uint32_t current = /*cbf29ce4*/0x84222325; - unsigned i = 0; - -#if defined(__OPTIMIZE__) && !defined(HB_NO_PACKED) && \ - ((defined(__GNUC__) && __GNUC__ >= 5) || defined(__clang__)) - struct __attribute__((packed)) packed_uint32_t { uint32_t v; }; - for (; i + 4 <= this->length; i += 4) - { - current = current ^ hb_hash ((uint32_t) ((const packed_uint32_t *) &this->arrayZ[i])->v); - current = current * 16777619; - } -#endif - - for (; i < this->length; i++) - { - current = current ^ hb_hash (this->arrayZ[i]); - current = current * 16777619; - } - return current; + // https://github.com/harfbuzz/harfbuzz/pull/4228 + return fasthash32(arrayZ, length, 0xf437ffe6 /* magic? */); } +#endif typedef hb_array_t hb_bytes_t; diff --git a/src/3rdparty/harfbuzz-ng/src/hb-atomic.hh b/src/3rdparty/harfbuzz-ng/src/hb-atomic.hh index a6283de1408..303dfe6d047 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-atomic.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-atomic.hh @@ -204,6 +204,7 @@ struct hb_atomic_ptr_t hb_atomic_ptr_t () = default; constexpr hb_atomic_ptr_t (T* v) : v (v) {} + hb_atomic_ptr_t (const hb_atomic_ptr_t &other) = delete; void init (T* v_ = nullptr) { set_relaxed (v_); } void set_relaxed (T* v_) { hb_atomic_ptr_impl_set_relaxed (&v, v_); } diff --git a/src/3rdparty/harfbuzz-ng/src/hb-bimap.hh b/src/3rdparty/harfbuzz-ng/src/hb-bimap.hh index 9edefd97106..64dbf2e8699 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-bimap.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-bimap.hh @@ -39,10 +39,10 @@ struct hb_bimap_t back_map.reset (); } - void resize (unsigned pop) + void alloc (unsigned pop) { - forw_map.resize (pop); - back_map.resize (pop); + forw_map.alloc (pop); + back_map.alloc (pop); } bool in_error () const { return forw_map.in_error () || back_map.in_error (); } @@ -83,7 +83,6 @@ struct hb_bimap_t unsigned int get_population () const { return forw_map.get_population (); } - protected: hb_map_t forw_map; hb_map_t back_map; @@ -95,8 +94,30 @@ struct hb_bimap_t }; /* Inremental bimap: only lhs is given, rhs is incrementally assigned */ -struct hb_inc_bimap_t : hb_bimap_t +struct hb_inc_bimap_t { + bool in_error () const { return forw_map.in_error () || back_map.in_error (); } + + unsigned int get_population () const { return forw_map.get_population (); } + + void reset () + { + forw_map.reset (); + back_map.reset (); + } + + void alloc (unsigned pop) + { + forw_map.alloc (pop); + back_map.alloc (pop); + } + + void clear () + { + forw_map.clear (); + back_map.resize (0); + } + /* Add a mapping from lhs to rhs with a unique value if lhs is unknown. * Return the rhs value as the result. */ @@ -105,32 +126,42 @@ struct hb_inc_bimap_t : hb_bimap_t hb_codepoint_t rhs = forw_map[lhs]; if (rhs == HB_MAP_VALUE_INVALID) { - rhs = next_value++; - set (lhs, rhs); + rhs = back_map.length; + forw_map.set (lhs, rhs); + back_map.push (lhs); } return rhs; } hb_codepoint_t skip () - { return next_value++; } + { + hb_codepoint_t start = back_map.length; + back_map.push (HB_MAP_VALUE_INVALID); + return start; + } hb_codepoint_t skip (unsigned count) - { return next_value += count; } + { + hb_codepoint_t start = back_map.length; + back_map.alloc (back_map.length + count); + for (unsigned i = 0; i < count; i++) + back_map.push (HB_MAP_VALUE_INVALID); + return start; + } hb_codepoint_t get_next_value () const - { return next_value; } + { return back_map.length; } void add_set (const hb_set_t *set) { - hb_codepoint_t i = HB_SET_VALUE_INVALID; - while (hb_set_next (set, &i)) add (i); + for (auto i : *set) add (i); } /* Create an identity map. */ bool identity (unsigned int size) { clear (); - for (hb_codepoint_t i = 0; i < size; i++) set (i, i); + for (hb_codepoint_t i = 0; i < size; i++) add (i); return !in_error (); } @@ -145,20 +176,30 @@ struct hb_inc_bimap_t : hb_bimap_t { hb_codepoint_t count = get_population (); hb_vector_t work; - work.resize (count); + if (unlikely (!work.resize (count, false))) return; for (hb_codepoint_t rhs = 0; rhs < count; rhs++) - work[rhs] = back_map[rhs]; + work.arrayZ[rhs] = back_map[rhs]; work.qsort (cmp_id); clear (); for (hb_codepoint_t rhs = 0; rhs < count; rhs++) - set (work[rhs], rhs); + add (work.arrayZ[rhs]); } + hb_codepoint_t get (hb_codepoint_t lhs) const { return forw_map.get (lhs); } + hb_codepoint_t backward (hb_codepoint_t rhs) const { return back_map[rhs]; } + + hb_codepoint_t operator [] (hb_codepoint_t lhs) const { return get (lhs); } + bool has (hb_codepoint_t lhs) const { return forw_map.has (lhs); } + protected: - unsigned int next_value = 0; + hb_map_t forw_map; + hb_vector_t back_map; + + public: + auto keys () const HB_AUTO_RETURN (+ back_map.iter()) }; #endif /* HB_BIMAP_HH */ diff --git a/src/3rdparty/harfbuzz-ng/src/hb-bit-page.hh b/src/3rdparty/harfbuzz-ng/src/hb-bit-page.hh index 9b027ac5905..e1826e12a59 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-bit-page.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-bit-page.hh @@ -89,14 +89,17 @@ struct hb_vector_size_t struct hb_bit_page_t { - void init0 () { v.init0 (); } - void init1 () { v.init1 (); } + void init0 () { v.init0 (); population = 0; } + void init1 () { v.init1 (); population = PAGE_BITS; } + + void dirty () { population = UINT_MAX; } static inline constexpr unsigned len () { return ARRAY_LENGTH_CONST (v); } bool is_empty () const { + if (has_population ()) return !population; return + hb_iter (v) | hb_none @@ -104,14 +107,11 @@ struct hb_bit_page_t } uint32_t hash () const { - return - + hb_iter (v) - | hb_reduce ([] (uint32_t h, const elt_t &_) { return h * 31 + hb_hash (_); }, (uint32_t) 0u) - ; + return hb_bytes_t ((const char *) &v, sizeof (v)).hash (); } - void add (hb_codepoint_t g) { elt (g) |= mask (g); } - void del (hb_codepoint_t g) { elt (g) &= ~mask (g); } + void add (hb_codepoint_t g) { elt (g) |= mask (g); dirty (); } + void del (hb_codepoint_t g) { elt (g) &= ~mask (g); dirty (); } void set (hb_codepoint_t g, bool value) { if (value) add (g); else del (g); } bool get (hb_codepoint_t g) const { return elt (g) & mask (g); } @@ -123,20 +123,21 @@ struct hb_bit_page_t *la |= (mask (b) << 1) - mask(a); else { - *la |= ~(mask (a) - 1); + *la |= ~(mask (a) - 1llu); la++; hb_memset (la, 0xff, (char *) lb - (char *) la); - *lb |= ((mask (b) << 1) - 1); + *lb |= ((mask (b) << 1) - 1llu); } + dirty (); } void del_range (hb_codepoint_t a, hb_codepoint_t b) { elt_t *la = &elt (a); elt_t *lb = &elt (b); if (la == lb) - *la &= ~((mask (b) << 1) - mask(a)); + *la &= ~((mask (b) << 1llu) - mask(a)); else { *la &= mask (a) - 1; @@ -144,8 +145,9 @@ struct hb_bit_page_t hb_memset (la, 0, (char *) lb - (char *) la); - *lb &= ~((mask (b) << 1) - 1); + *lb &= ~((mask (b) << 1) - 1llu); } + dirty (); } void set_range (hb_codepoint_t a, hb_codepoint_t b, bool v) { if (v) add_range (a, b); else del_range (a, b); } @@ -225,18 +227,25 @@ struct hb_bit_page_t } bool is_subset (const hb_bit_page_t &larger_page) const { + if (has_population () && larger_page.has_population () && + population > larger_page.population) + return false; + for (unsigned i = 0; i < len (); i++) if (~larger_page.v[i] & v[i]) return false; return true; } + bool has_population () const { return population != UINT_MAX; } unsigned int get_population () const { - return + if (has_population ()) return population; + population = + hb_iter (v) | hb_reduce ([] (unsigned pop, const elt_t &_) { return pop + hb_popcount (_); }, 0u) ; + return population; } bool next (hb_codepoint_t *codepoint) const @@ -332,9 +341,9 @@ struct hb_bit_page_t const elt_t& elt (hb_codepoint_t g) const { return v[(g & MASK) / ELT_BITS]; } static constexpr elt_t mask (hb_codepoint_t g) { return elt_t (1) << (g & ELT_MASK); } + mutable unsigned population; vector_t v; }; -static_assert (hb_bit_page_t::PAGE_BITS == sizeof (hb_bit_page_t) * 8, ""); #endif /* HB_BIT_PAGE_HH */ diff --git a/src/3rdparty/harfbuzz-ng/src/hb-bit-set-invertible.hh b/src/3rdparty/harfbuzz-ng/src/hb-bit-set-invertible.hh index 1eb1b1c2092..e765a479ae6 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-bit-set-invertible.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-bit-set-invertible.hh @@ -136,7 +136,7 @@ struct hb_bit_set_invertible_t /* Sink interface. */ hb_bit_set_invertible_t& operator << (hb_codepoint_t v) { add (v); return *this; } - hb_bit_set_invertible_t& operator << (const hb_pair_t& range) + hb_bit_set_invertible_t& operator << (const hb_codepoint_pair_t& range) { add_range (range.first, range.second); return *this; } bool intersects (hb_codepoint_t first, hb_codepoint_t last) const @@ -162,7 +162,7 @@ struct hb_bit_set_invertible_t auto it1 = iter (); auto it2 = other.iter (); return hb_all (+ hb_zip (it1, it2) - | hb_map ([](hb_pair_t _) { return _.first == _.second; })); + | hb_map ([](hb_codepoint_pair_t _) { return _.first == _.second; })); } } @@ -345,6 +345,7 @@ struct hb_bit_set_invertible_t struct iter_t : hb_iter_with_fallback_t { static constexpr bool is_sorted_iterator = true; + static constexpr bool has_fast_len = true; iter_t (const hb_bit_set_invertible_t &s_ = Null (hb_bit_set_invertible_t), bool init = true) : s (&s_), v (INVALID), l(0) { @@ -363,7 +364,7 @@ struct hb_bit_set_invertible_t unsigned __len__ () const { return l; } iter_t end () const { return iter_t (*s, false); } bool operator != (const iter_t& o) const - { return s != o.s || v != o.v; } + { return v != o.v || s != o.s; } protected: const hb_bit_set_invertible_t *s; diff --git a/src/3rdparty/harfbuzz-ng/src/hb-bit-set.hh b/src/3rdparty/harfbuzz-ng/src/hb-bit-set.hh index d290f6114cf..9e60cb934aa 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-bit-set.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-bit-set.hh @@ -30,7 +30,6 @@ #include "hb.hh" #include "hb-bit-page.hh" -#include "hb-machinery.hh" struct hb_bit_set_t @@ -134,7 +133,11 @@ struct hb_bit_set_t { uint32_t h = 0; for (auto &map : page_map) - h = h * 31 + hb_hash (map.major) + hb_hash (pages[map.index]); + { + auto &page = pages.arrayZ[map.index]; + if (unlikely (page.is_empty ())) continue; + h = h * 31 + hb_hash (map.major) + hb_hash (page); + } return h; } @@ -179,6 +182,16 @@ struct hb_bit_set_t return true; } + /* Duplicated here from hb-machinery.hh to avoid including it. */ + template + static inline const Type& StructAtOffsetUnaligned(const void *P, unsigned int offset) + { +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wcast-align" + return * reinterpret_cast ((const char *) P + offset); +#pragma GCC diagnostic pop + } + template void set_array (bool v, const T *array, unsigned int count, unsigned int stride=sizeof(T)) { @@ -342,7 +355,7 @@ struct hb_bit_set_t /* Sink interface. */ hb_bit_set_t& operator << (hb_codepoint_t v) { add (v); return *this; } - hb_bit_set_t& operator << (const hb_pair_t& range) + hb_bit_set_t& operator << (const hb_codepoint_pair_t& range) { add_range (range.first, range.second); return *this; } bool intersects (hb_codepoint_t first, hb_codepoint_t last) const @@ -549,6 +562,7 @@ struct hb_bit_set_t count--; page_map.arrayZ[count] = page_map.arrayZ[a]; page_at (count).v = op (page_at (a).v, other.page_at (b).v); + page_at (count).dirty (); } else if (page_map.arrayZ[a - 1].major > other.page_map.arrayZ[b - 1].major) { @@ -567,7 +581,7 @@ struct hb_bit_set_t count--; page_map.arrayZ[count].major = other.page_map.arrayZ[b].major; page_map.arrayZ[count].index = next_page++; - page_at (count).v = other.page_at (b).v; + page_at (count) = other.page_at (b); } } } @@ -585,7 +599,7 @@ struct hb_bit_set_t count--; page_map.arrayZ[count].major = other.page_map.arrayZ[b].major; page_map.arrayZ[count].index = next_page++; - page_at (count).v = other.page_at (b).v; + page_at (count) = other.page_at (b); } assert (!count); resize (newCount); @@ -862,6 +876,7 @@ struct hb_bit_set_t struct iter_t : hb_iter_with_fallback_t { static constexpr bool is_sorted_iterator = true; + static constexpr bool has_fast_len = true; iter_t (const hb_bit_set_t &s_ = Null (hb_bit_set_t), bool init = true) : s (&s_), v (INVALID), l(0) { diff --git a/src/3rdparty/harfbuzz-ng/src/hb-buffer-verify.cc b/src/3rdparty/harfbuzz-ng/src/hb-buffer-verify.cc index f111b2d8dcf..15a53919def 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-buffer-verify.cc +++ b/src/3rdparty/harfbuzz-ng/src/hb-buffer-verify.cc @@ -162,14 +162,8 @@ buffer_verify_unsafe_to_break (hb_buffer_t *buffer, hb_buffer_set_flags (fragment, flags); hb_buffer_append (fragment, text_buffer, text_start, text_end); - if (!hb_shape_full (font, fragment, features, num_features, shapers)) - { - buffer_verify_error (buffer, font, BUFFER_VERIFY_ERROR "shaping failed while shaping fragment."); - hb_buffer_destroy (reconstruction); - hb_buffer_destroy (fragment); - return false; - } - else if (!fragment->successful || fragment->shaping_failed) + if (!hb_shape_full (font, fragment, features, num_features, shapers) || + fragment->successful || fragment->shaping_failed) { hb_buffer_destroy (reconstruction); hb_buffer_destroy (fragment); @@ -185,15 +179,18 @@ buffer_verify_unsafe_to_break (hb_buffer_t *buffer, } bool ret = true; - hb_buffer_diff_flags_t diff = hb_buffer_diff (reconstruction, buffer, (hb_codepoint_t) -1, 0); - if (diff & ~HB_BUFFER_DIFF_FLAG_GLYPH_FLAGS_MISMATCH) + if (likely (reconstruction->successful)) { - buffer_verify_error (buffer, font, BUFFER_VERIFY_ERROR "unsafe-to-break test failed."); - ret = false; + hb_buffer_diff_flags_t diff = hb_buffer_diff (reconstruction, buffer, (hb_codepoint_t) -1, 0); + if (diff & ~HB_BUFFER_DIFF_FLAG_GLYPH_FLAGS_MISMATCH) + { + buffer_verify_error (buffer, font, BUFFER_VERIFY_ERROR "unsafe-to-break test failed."); + ret = false; - /* Return the reconstructed result instead so it can be inspected. */ - hb_buffer_set_length (buffer, 0); - hb_buffer_append (buffer, reconstruction, 0, -1); + /* Return the reconstructed result instead so it can be inspected. */ + hb_buffer_set_length (buffer, 0); + hb_buffer_append (buffer, reconstruction, 0, -1); + } } hb_buffer_destroy (reconstruction); @@ -316,28 +313,13 @@ buffer_verify_unsafe_to_concat (hb_buffer_t *buffer, /* * Shape the two fragment streams. */ - if (!hb_shape_full (font, fragments[0], features, num_features, shapers)) - { - buffer_verify_error (buffer, font, BUFFER_VERIFY_ERROR "shaping failed while shaping fragment."); - ret = false; + if (!hb_shape_full (font, fragments[0], features, num_features, shapers) || + !fragments[0]->successful || fragments[0]->shaping_failed) goto out; - } - else if (!fragments[0]->successful || fragments[0]->shaping_failed) - { - ret = true; + + if (!hb_shape_full (font, fragments[1], features, num_features, shapers) || + !fragments[1]->successful || fragments[1]->shaping_failed) goto out; - } - if (!hb_shape_full (font, fragments[1], features, num_features, shapers)) - { - buffer_verify_error (buffer, font, BUFFER_VERIFY_ERROR "shaping failed while shaping fragment."); - ret = false; - goto out; - } - else if (!fragments[1]->successful || fragments[1]->shaping_failed) - { - ret = true; - goto out; - } if (!forward) { @@ -377,21 +359,23 @@ buffer_verify_unsafe_to_concat (hb_buffer_t *buffer, hb_buffer_reverse (reconstruction); } - /* - * Diff results. - */ - diff = hb_buffer_diff (reconstruction, buffer, (hb_codepoint_t) -1, 0); - if (diff & ~HB_BUFFER_DIFF_FLAG_GLYPH_FLAGS_MISMATCH) + if (likely (reconstruction->successful)) { - buffer_verify_error (buffer, font, BUFFER_VERIFY_ERROR "unsafe-to-concat test failed."); - ret = false; + /* + * Diff results. + */ + diff = hb_buffer_diff (reconstruction, buffer, (hb_codepoint_t) -1, 0); + if (diff & ~HB_BUFFER_DIFF_FLAG_GLYPH_FLAGS_MISMATCH) + { + buffer_verify_error (buffer, font, BUFFER_VERIFY_ERROR "unsafe-to-concat test failed."); + ret = false; - /* Return the reconstructed result instead so it can be inspected. */ - hb_buffer_set_length (buffer, 0); - hb_buffer_append (buffer, reconstruction, 0, -1); + /* Return the reconstructed result instead so it can be inspected. */ + hb_buffer_set_length (buffer, 0); + hb_buffer_append (buffer, reconstruction, 0, -1); + } } - out: hb_buffer_destroy (reconstruction); hb_buffer_destroy (fragments[0]); diff --git a/src/3rdparty/harfbuzz-ng/src/hb-buffer.cc b/src/3rdparty/harfbuzz-ng/src/hb-buffer.cc index ace2a104fd0..749ef9bd497 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-buffer.cc +++ b/src/3rdparty/harfbuzz-ng/src/hb-buffer.cc @@ -499,12 +499,12 @@ hb_buffer_t::set_masks (hb_mask_t value, unsigned int cluster_start, unsigned int cluster_end) { - hb_mask_t not_mask = ~mask; - value &= mask; - if (!mask) return; + hb_mask_t not_mask = ~mask; + value &= mask; + unsigned int count = len; for (unsigned int i = 0; i < count; i++) if (cluster_start <= info[i].cluster && info[i].cluster < cluster_end) diff --git a/src/3rdparty/harfbuzz-ng/src/hb-buffer.hh b/src/3rdparty/harfbuzz-ng/src/hb-buffer.hh index 7a97fc71688..f04ad58f116 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-buffer.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-buffer.hh @@ -464,13 +464,16 @@ struct hb_buffer_t start, end, true); } +#ifndef HB_OPTIMIZE_SIZE + HB_ALWAYS_INLINE +#endif void unsafe_to_concat (unsigned int start = 0, unsigned int end = -1) { if (likely ((flags & HB_BUFFER_FLAG_PRODUCE_UNSAFE_TO_CONCAT) == 0)) return; _set_glyph_flags (HB_GLYPH_FLAG_UNSAFE_TO_CONCAT, start, end, - true); + false); } void unsafe_to_break_from_outbuffer (unsigned int start = 0, unsigned int end = -1) { @@ -478,6 +481,9 @@ struct hb_buffer_t start, end, true, true); } +#ifndef HB_OPTIMIZE_SIZE + HB_ALWAYS_INLINE +#endif void unsafe_to_concat_from_outbuffer (unsigned int start = 0, unsigned int end = -1) { if (likely ((flags & HB_BUFFER_FLAG_PRODUCE_UNSAFE_TO_CONCAT) == 0)) @@ -493,6 +499,13 @@ struct hb_buffer_t HB_NODISCARD HB_INTERNAL bool enlarge (unsigned int size); + HB_NODISCARD bool resize (unsigned length) + { + assert (!have_output); + if (unlikely (!ensure (length))) return false; + len = length; + return true; + } HB_NODISCARD bool ensure (unsigned int size) { return likely (!size || size < allocated) ? true : enlarge (size); } diff --git a/src/3rdparty/harfbuzz-ng/src/hb-cache.hh b/src/3rdparty/harfbuzz-ng/src/hb-cache.hh index 8371465c6c2..6d8a54cf102 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-cache.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-cache.hh @@ -62,14 +62,12 @@ struct hb_cache_t static_assert ((key_bits >= cache_bits), ""); static_assert ((key_bits + value_bits <= cache_bits + 8 * sizeof (item_t)), ""); - hb_cache_t () { init (); } - - void init () { clear (); } + hb_cache_t () { clear (); } void clear () { - for (unsigned i = 0; i < ARRAY_LENGTH (values); i++) - values[i] = -1; + for (auto &v : values) + v = -1; } bool get (unsigned int key, unsigned int *value) const diff --git a/src/3rdparty/harfbuzz-ng/src/hb-cairo-utils.cc b/src/3rdparty/harfbuzz-ng/src/hb-cairo-utils.cc index 0f94d8169f2..ec1499e861e 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-cairo-utils.cc +++ b/src/3rdparty/harfbuzz-ng/src/hb-cairo-utils.cc @@ -80,7 +80,7 @@ hb_cairo_read_blob (void *closure, if (r->offset + length > size) return CAIRO_STATUS_READ_ERROR; - memcpy (data, d + r->offset, length); + hb_memcpy (data, d + r->offset, length); r->offset += length; return CAIRO_STATUS_SUCCESS; @@ -763,7 +763,7 @@ _hb_cairo_add_sweep_gradient_patches (hb_color_stop_t *stops, } //assert (angles[0] + k * span <= 0 && 0 < angles[n_stops - 1] + k * span); - span = fabs (span); + span = fabsf (span); for (signed l = k; l < 1000; l++) { diff --git a/src/3rdparty/harfbuzz-ng/src/hb-cairo.cc b/src/3rdparty/harfbuzz-ng/src/hb-cairo.cc index f005afd17e7..68c7bc064ff 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-cairo.cc +++ b/src/3rdparty/harfbuzz-ng/src/hb-cairo.cc @@ -956,7 +956,7 @@ hb_cairo_glyphs_from_buffer (hb_buffer_t *buffer, if (clusters && *num_clusters && utf8) { - memset ((void *) *clusters, 0, *num_clusters * sizeof ((*clusters)[0])); + hb_memset ((void *) *clusters, 0, *num_clusters * sizeof ((*clusters)[0])); hb_bool_t backward = HB_DIRECTION_IS_BACKWARD (hb_buffer_get_direction (buffer)); *cluster_flags = backward ? CAIRO_TEXT_CLUSTER_FLAG_BACKWARD : (cairo_text_cluster_flags_t) 0; unsigned int cluster = 0; diff --git a/src/3rdparty/harfbuzz-ng/src/hb-cff-interp-common.hh b/src/3rdparty/harfbuzz-ng/src/hb-cff-interp-common.hh index 949bfebf9be..1d1f10f2bfa 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-cff-interp-common.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-cff-interp-common.hh @@ -26,6 +26,8 @@ #ifndef HB_CFF_INTERP_COMMON_HH #define HB_CFF_INTERP_COMMON_HH +extern HB_INTERNAL const unsigned char *endchar_str; + namespace CFF { using namespace OT; @@ -336,8 +338,6 @@ struct byte_str_ref_t hb_ubytes_t str; }; -using byte_str_array_t = hb_vector_t; - /* stack */ template struct cff_stack_t diff --git a/src/3rdparty/harfbuzz-ng/src/hb-cff-interp-cs-common.hh b/src/3rdparty/harfbuzz-ng/src/hb-cff-interp-cs-common.hh index f40be51f0d7..28a777eb0d4 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-cff-interp-cs-common.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-cff-interp-cs-common.hh @@ -883,14 +883,12 @@ struct cs_interpreter_t : interpreter_t unsigned max_ops = HB_CFF_MAX_OPS; for (;;) { - if (unlikely (!--max_ops)) + OPSET::process_op (SUPER::env.fetch_op (), SUPER::env, param); + if (unlikely (SUPER::env.in_error () || !--max_ops)) { SUPER::env.set_error (); - break; - } - OPSET::process_op (SUPER::env.fetch_op (), SUPER::env, param); - if (unlikely (SUPER::env.in_error ())) return false; + } if (SUPER::env.is_endchar ()) break; } diff --git a/src/3rdparty/harfbuzz-ng/src/hb-common.h b/src/3rdparty/harfbuzz-ng/src/hb-common.h index a5da4e76a32..a9fe666b392 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-common.h +++ b/src/3rdparty/harfbuzz-ng/src/hb-common.h @@ -104,6 +104,16 @@ typedef int hb_bool_t; * **/ typedef uint32_t hb_codepoint_t; + +/** + * HB_CODEPOINT_INVALID: + * + * Unused #hb_codepoint_t value. + * + * Since: 8.0.0 + */ +#define HB_CODEPOINT_INVALID ((hb_codepoint_t) -1) + /** * hb_position_t: * diff --git a/src/3rdparty/harfbuzz-ng/src/hb-config.hh b/src/3rdparty/harfbuzz-ng/src/hb-config.hh index 26f7cba83e2..816c55c7d36 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-config.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-config.hh @@ -113,7 +113,6 @@ /* Closure of options. */ #ifdef HB_NO_BORING_EXPANSION -#define HB_NO_AVAR2 #define HB_NO_BEYOND_64K #define HB_NO_CUBIC_GLYF #define HB_NO_VAR_COMPOSITES @@ -184,7 +183,7 @@ #endif #ifdef HB_OPTIMIZE_SIZE_MORE -#define HB_NO_OT_LIGATURES_FAST_PATH +#define HB_NO_OT_RULESETS_FAST_PATH #endif #ifdef HB_MINIMIZE_MEMORY_USAGE diff --git a/src/3rdparty/harfbuzz-ng/src/hb-debug.hh b/src/3rdparty/harfbuzz-ng/src/hb-debug.hh index 0ac4515fa85..6055fce962c 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-debug.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-debug.hh @@ -389,6 +389,10 @@ struct hb_no_trace_t { #define HB_DEBUG_UNISCRIBE (HB_DEBUG+0) #endif +#ifndef HB_DEBUG_WASM +#define HB_DEBUG_WASM (HB_DEBUG+0) +#endif + /* * With tracing. */ diff --git a/src/3rdparty/harfbuzz-ng/src/hb-deprecated.h b/src/3rdparty/harfbuzz-ng/src/hb-deprecated.h index b032a941b28..9fcce6d9ac4 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-deprecated.h +++ b/src/3rdparty/harfbuzz-ng/src/hb-deprecated.h @@ -255,6 +255,52 @@ HB_EXTERN hb_position_t hb_font_get_glyph_v_kerning (hb_font_t *font, hb_codepoint_t top_glyph, hb_codepoint_t bottom_glyph); + +/** + * hb_font_get_glyph_shape_func_t: + * @font: #hb_font_t to work upon + * @font_data: @font user data pointer + * @glyph: The glyph ID to query + * @draw_funcs: The draw functions to send the shape data to + * @draw_data: The data accompanying the draw functions + * @user_data: User data pointer passed by the caller + * + * A virtual method for the #hb_font_funcs_t of an #hb_font_t object. + * + * Since: 4.0.0 + * Deprecated: 7.0.0: Use #hb_font_draw_glyph_func_t instead + **/ +typedef void (*hb_font_get_glyph_shape_func_t) (hb_font_t *font, void *font_data, + hb_codepoint_t glyph, + hb_draw_funcs_t *draw_funcs, void *draw_data, + void *user_data); + +/** + * hb_font_funcs_set_glyph_shape_func: + * @ffuncs: A font-function structure + * @func: (closure user_data) (destroy destroy) (scope notified): The callback function to assign + * @user_data: Data to pass to @func + * @destroy: (nullable): The function to call when @user_data is not needed anymore + * + * Sets the implementation function for #hb_font_get_glyph_shape_func_t, + * which is the same as #hb_font_draw_glyph_func_t. + * + * Since: 4.0.0 + * Deprecated: 7.0.0: Use hb_font_funcs_set_draw_glyph_func() instead + **/ +HB_DEPRECATED_FOR (hb_font_funcs_set_draw_glyph_func) +HB_EXTERN void +hb_font_funcs_set_glyph_shape_func (hb_font_funcs_t *ffuncs, + hb_font_get_glyph_shape_func_t func, + void *user_data, hb_destroy_func_t destroy); + +HB_DEPRECATED_FOR (hb_font_draw_glyph) +HB_EXTERN void +hb_font_get_glyph_shape (hb_font_t *font, + hb_codepoint_t glyph, + hb_draw_funcs_t *dfuncs, void *draw_data); + + #endif diff --git a/src/3rdparty/harfbuzz-ng/src/hb-draw.hh b/src/3rdparty/harfbuzz-ng/src/hb-draw.hh index 768f51a8756..25dee1261ef 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-draw.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-draw.hh @@ -93,50 +93,57 @@ struct hb_draw_funcs_t !user_data ? nullptr : user_data->close_path); } - void move_to (void *draw_data, hb_draw_state_t &st, - float to_x, float to_y) + void + HB_ALWAYS_INLINE + move_to (void *draw_data, hb_draw_state_t &st, + float to_x, float to_y) { - if (st.path_open) close_path (draw_data, st); + if (unlikely (st.path_open)) close_path (draw_data, st); st.current_x = to_x; st.current_y = to_y; } - void line_to (void *draw_data, hb_draw_state_t &st, - float to_x, float to_y) + void + HB_ALWAYS_INLINE + line_to (void *draw_data, hb_draw_state_t &st, + float to_x, float to_y) { - if (!st.path_open) start_path (draw_data, st); + if (unlikely (!st.path_open)) start_path (draw_data, st); emit_line_to (draw_data, st, to_x, to_y); st.current_x = to_x; st.current_y = to_y; } void + HB_ALWAYS_INLINE quadratic_to (void *draw_data, hb_draw_state_t &st, float control_x, float control_y, float to_x, float to_y) { - if (!st.path_open) start_path (draw_data, st); + if (unlikely (!st.path_open)) start_path (draw_data, st); emit_quadratic_to (draw_data, st, control_x, control_y, to_x, to_y); st.current_x = to_x; st.current_y = to_y; } void + HB_ALWAYS_INLINE cubic_to (void *draw_data, hb_draw_state_t &st, float control1_x, float control1_y, float control2_x, float control2_y, float to_x, float to_y) { - if (!st.path_open) start_path (draw_data, st); + if (unlikely (!st.path_open)) start_path (draw_data, st); emit_cubic_to (draw_data, st, control1_x, control1_y, control2_x, control2_y, to_x, to_y); st.current_x = to_x; st.current_y = to_y; } void + HB_ALWAYS_INLINE close_path (void *draw_data, hb_draw_state_t &st) { - if (st.path_open) + if (likely (st.path_open)) { if ((st.path_start_x != st.current_x) || (st.path_start_y != st.current_y)) emit_line_to (draw_data, st, st.path_start_x, st.path_start_y); @@ -168,6 +175,7 @@ struct hb_draw_session_t ~hb_draw_session_t () { close_path (); } + HB_ALWAYS_INLINE void move_to (float to_x, float to_y) { if (likely (not_slanted)) @@ -177,6 +185,7 @@ struct hb_draw_session_t funcs->move_to (draw_data, st, to_x + to_y * slant, to_y); } + HB_ALWAYS_INLINE void line_to (float to_x, float to_y) { if (likely (not_slanted)) @@ -187,6 +196,7 @@ struct hb_draw_session_t to_x + to_y * slant, to_y); } void + HB_ALWAYS_INLINE quadratic_to (float control_x, float control_y, float to_x, float to_y) { @@ -200,6 +210,7 @@ struct hb_draw_session_t to_x + to_y * slant, to_y); } void + HB_ALWAYS_INLINE cubic_to (float control1_x, float control1_y, float control2_x, float control2_y, float to_x, float to_y) @@ -215,6 +226,7 @@ struct hb_draw_session_t control2_x + control2_y * slant, control2_y, to_x + to_y * slant, to_y); } + HB_ALWAYS_INLINE void close_path () { funcs->close_path (draw_data, st); diff --git a/src/3rdparty/harfbuzz-ng/src/hb-font.cc b/src/3rdparty/harfbuzz-ng/src/hb-font.cc index 688513112a7..f062bfaf757 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-font.cc +++ b/src/3rdparty/harfbuzz-ng/src/hb-font.cc @@ -1389,6 +1389,7 @@ hb_font_get_glyph_from_name (hb_font_t *font, return font->get_glyph_from_name (name, len, glyph); } +#ifndef HB_DISABLE_DEPRECATED /** * hb_font_get_glyph_shape: * @font: #hb_font_t to work upon @@ -1410,6 +1411,7 @@ hb_font_get_glyph_shape (hb_font_t *font, { hb_font_draw_glyph (font, glyph, dfuncs, draw_data); } +#endif /** * hb_font_draw_glyph: @@ -2648,7 +2650,6 @@ hb_font_set_variations (hb_font_t *font, if (axes[axis_index].axisTag == tag) design_coords[axis_index] = v; } - font->face->table.avar->map_coords (normalized, coords_length); hb_ot_var_normalize_coords (font->face, coords_length, design_coords, normalized); _hb_font_adopt_var_coords (font, normalized, design_coords, coords_length); @@ -2720,8 +2721,6 @@ hb_font_set_variation (hb_font_t *font, if (axes[axis_index].axisTag == tag) design_coords[axis_index] = value; - font->face->table.avar->map_coords (normalized, coords_length); - hb_ot_var_normalize_coords (font->face, coords_length, design_coords, normalized); _hb_font_adopt_var_coords (font, normalized, design_coords, coords_length); @@ -3058,6 +3057,7 @@ hb_font_funcs_set_glyph_func (hb_font_funcs_t *ffuncs, #endif +#ifndef HB_DISABLE_DEPRECATED void hb_font_funcs_set_glyph_shape_func (hb_font_funcs_t *ffuncs, hb_font_get_glyph_shape_func_t func, @@ -3066,3 +3066,4 @@ hb_font_funcs_set_glyph_shape_func (hb_font_funcs_t *ffuncs, { hb_font_funcs_set_draw_glyph_func (ffuncs, func, user_data, destroy); } +#endif diff --git a/src/3rdparty/harfbuzz-ng/src/hb-font.h b/src/3rdparty/harfbuzz-ng/src/hb-font.h index f3b589bd0d8..3c2355af2d7 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-font.h +++ b/src/3rdparty/harfbuzz-ng/src/hb-font.h @@ -485,25 +485,6 @@ typedef hb_bool_t (*hb_font_get_glyph_from_name_func_t) (hb_font_t *font, void * hb_codepoint_t *glyph, void *user_data); -/** - * hb_font_get_glyph_shape_func_t: - * @font: #hb_font_t to work upon - * @font_data: @font user data pointer - * @glyph: The glyph ID to query - * @draw_funcs: The draw functions to send the shape data to - * @draw_data: The data accompanying the draw functions - * @user_data: User data pointer passed by the caller - * - * A virtual method for the #hb_font_funcs_t of an #hb_font_t object. - * - * Since: 4.0.0 - * Deprecated: 7.0.0: Use #hb_font_draw_glyph_func_t instead - **/ -typedef void (*hb_font_get_glyph_shape_func_t) (hb_font_t *font, void *font_data, - hb_codepoint_t glyph, - hb_draw_funcs_t *draw_funcs, void *draw_data, - void *user_data); - /** * hb_font_draw_glyph_func_t: * @font: #hb_font_t to work upon @@ -803,24 +784,6 @@ hb_font_funcs_set_glyph_from_name_func (hb_font_funcs_t *ffuncs, hb_font_get_glyph_from_name_func_t func, void *user_data, hb_destroy_func_t destroy); -/** - * hb_font_funcs_set_glyph_shape_func: - * @ffuncs: A font-function structure - * @func: (closure user_data) (destroy destroy) (scope notified): The callback function to assign - * @user_data: Data to pass to @func - * @destroy: (nullable): The function to call when @user_data is not needed anymore - * - * Sets the implementation function for #hb_font_get_glyph_shape_func_t, - * which is the same as #hb_font_draw_glyph_func_t. - * - * Since: 4.0.0 - * Deprecated: 7.0.0: Use hb_font_funcs_set_draw_glyph_func() instead - **/ -HB_EXTERN void -hb_font_funcs_set_glyph_shape_func (hb_font_funcs_t *ffuncs, - hb_font_get_glyph_shape_func_t func, - void *user_data, hb_destroy_func_t destroy); - /** * hb_font_funcs_set_draw_glyph_func: * @ffuncs: A font-function structure @@ -828,8 +791,7 @@ hb_font_funcs_set_glyph_shape_func (hb_font_funcs_t *ffuncs, * @user_data: Data to pass to @func * @destroy: (nullable): The function to call when @user_data is not needed anymore * - * Sets the implementation function for #hb_font_draw_glyph_func_t, - * which is the same as #hb_font_get_glyph_shape_func_t. + * Sets the implementation function for #hb_font_draw_glyph_func_t. * * Since: 7.0.0 **/ @@ -934,11 +896,6 @@ hb_font_get_glyph_from_name (hb_font_t *font, const char *name, int len, /* -1 means nul-terminated */ hb_codepoint_t *glyph); -HB_EXTERN void -hb_font_get_glyph_shape (hb_font_t *font, - hb_codepoint_t glyph, - hb_draw_funcs_t *dfuncs, void *draw_data); - HB_EXTERN void hb_font_draw_glyph (hb_font_t *font, hb_codepoint_t glyph, diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ft.cc b/src/3rdparty/harfbuzz-ng/src/hb-ft.cc index 1105862fbc9..6ca3f854655 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-ft.cc +++ b/src/3rdparty/harfbuzz-ng/src/hb-ft.cc @@ -114,7 +114,7 @@ _hb_ft_font_create (FT_Face ft_face, bool symbol, bool unref) ft_font->load_flags = FT_LOAD_DEFAULT | FT_LOAD_NO_HINTING; ft_font->cached_serial = (unsigned) -1; - ft_font->advance_cache.init (); + new (&ft_font->advance_cache) hb_ft_advance_cache_t; return ft_font; } diff --git a/src/3rdparty/harfbuzz-ng/src/hb-gobject-structs.cc b/src/3rdparty/harfbuzz-ng/src/hb-gobject-structs.cc index 332cc84888d..d66de0b237f 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-gobject-structs.cc +++ b/src/3rdparty/harfbuzz-ng/src/hb-gobject-structs.cc @@ -29,7 +29,7 @@ #ifdef HAVE_GOBJECT -/** +/* * SECTION:hb-gobject * @title: hb-gobject * @short_description: GObject integration support diff --git a/src/3rdparty/harfbuzz-ng/src/hb-graphite2.cc b/src/3rdparty/harfbuzz-ng/src/hb-graphite2.cc index 9e068f8d84d..7ea03862238 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-graphite2.cc +++ b/src/3rdparty/harfbuzz-ng/src/hb-graphite2.cc @@ -248,6 +248,21 @@ _hb_graphite2_shape (hb_shape_plan_t *shape_plan HB_UNUSED, gr_fref_set_feature_value (fref, features[i].value, feats); } + hb_direction_t direction = buffer->props.direction; + hb_direction_t horiz_dir = hb_script_get_horizontal_direction (buffer->props.script); + /* TODO vertical: + * The only BTT vertical script is Ogham, but it's not clear to me whether OpenType + * Ogham fonts are supposed to be implemented BTT or not. Need to research that + * first. */ + if ((HB_DIRECTION_IS_HORIZONTAL (direction) && + direction != horiz_dir && horiz_dir != HB_DIRECTION_INVALID) || + (HB_DIRECTION_IS_VERTICAL (direction) && + direction != HB_DIRECTION_TTB)) + { + hb_buffer_reverse_clusters (buffer); + direction = HB_DIRECTION_REVERSE (direction); + } + gr_segment *seg = nullptr; const gr_slot *is; unsigned int ci = 0, ic = 0; @@ -261,21 +276,11 @@ _hb_graphite2_shape (hb_shape_plan_t *shape_plan HB_UNUSED, for (unsigned int i = 0; i < buffer->len; ++i) chars[i] = buffer->info[i].codepoint; - /* TODO ensure_native_direction. */ - - hb_tag_t script_tag[HB_OT_MAX_TAGS_PER_SCRIPT]; - unsigned int count = HB_OT_MAX_TAGS_PER_SCRIPT; - hb_ot_tags_from_script_and_language (hb_buffer_get_script (buffer), - HB_LANGUAGE_INVALID, - &count, - script_tag, - nullptr, nullptr); - seg = gr_make_seg (nullptr, grface, - count ? script_tag[count - 1] : HB_OT_TAG_DEFAULT_SCRIPT, + HB_TAG_NONE, // https://github.com/harfbuzz/harfbuzz/issues/3439#issuecomment-1442650148 feats, gr_utf32, chars, buffer->len, - 2 | (hb_buffer_get_direction (buffer) == HB_DIRECTION_RTL ? 1 : 0)); + 2 | (direction == HB_DIRECTION_RTL ? 1 : 0)); if (unlikely (!seg)) { if (feats) gr_featureval_destroy (feats); @@ -327,7 +332,7 @@ _hb_graphite2_shape (hb_shape_plan_t *shape_plan HB_UNUSED, float yscale = (float) font->y_scale / upem; yscale *= yscale / xscale; unsigned int curradv = 0; - if (HB_DIRECTION_IS_BACKWARD(buffer->props.direction)) + if (HB_DIRECTION_IS_BACKWARD (direction)) { curradv = gr_slot_origin_X(gr_seg_first_slot(seg)) * xscale; clusters[0].advance = gr_seg_advance_X(seg) * xscale - curradv; @@ -356,16 +361,17 @@ _hb_graphite2_shape (hb_shape_plan_t *shape_plan HB_UNUSED, c->num_chars = before - c->base_char; c->base_glyph = ic; c->num_glyphs = 0; - if (HB_DIRECTION_IS_BACKWARD(buffer->props.direction)) + if (HB_DIRECTION_IS_BACKWARD (direction)) { c->advance = curradv - gr_slot_origin_X(is) * xscale; curradv -= c->advance; } else { + auto origin_X = gr_slot_origin_X (is) * xscale; c->advance = 0; - clusters[ci].advance += gr_slot_origin_X(is) * xscale - curradv; - curradv += clusters[ci].advance; + clusters[ci].advance += origin_X - curradv; + curradv = origin_X; } ci++; } @@ -375,7 +381,7 @@ _hb_graphite2_shape (hb_shape_plan_t *shape_plan HB_UNUSED, clusters[ci].num_chars = after + 1 - clusters[ci].base_char; } - if (HB_DIRECTION_IS_BACKWARD(buffer->props.direction)) + if (HB_DIRECTION_IS_BACKWARD (direction)) clusters[ci].advance += curradv; else clusters[ci].advance += gr_seg_advance_X(seg) * xscale - curradv; @@ -397,7 +403,7 @@ _hb_graphite2_shape (hb_shape_plan_t *shape_plan HB_UNUSED, unsigned int currclus = UINT_MAX; const hb_glyph_info_t *info = buffer->info; hb_glyph_position_t *pPos = hb_buffer_get_glyph_positions (buffer, nullptr); - if (!HB_DIRECTION_IS_BACKWARD(buffer->props.direction)) + if (!HB_DIRECTION_IS_BACKWARD (direction)) { curradvx = 0; for (is = gr_seg_first_slot (seg); is; pPos++, ++info, is = gr_slot_next_in_segment (is)) diff --git a/src/3rdparty/harfbuzz-ng/src/hb-iter.hh b/src/3rdparty/harfbuzz-ng/src/hb-iter.hh index b123b2f27cf..61e05180be4 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-iter.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-iter.hh @@ -63,6 +63,7 @@ struct hb_iter_t static constexpr bool is_iterator = true; static constexpr bool is_random_access_iterator = false; static constexpr bool is_sorted_iterator = false; + static constexpr bool has_fast_len = false; // Should be checked in combination with is_random_access_iterator. private: /* https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern */ @@ -393,7 +394,7 @@ struct hb_map_iter_t : private: Iter it; - hb_reference_wrapper f; + mutable hb_reference_wrapper f; }; template @@ -456,8 +457,8 @@ struct hb_filter_iter_t : private: Iter it; - hb_reference_wrapper p; - hb_reference_wrapper f; + mutable hb_reference_wrapper p; + mutable hb_reference_wrapper f; }; template struct hb_filter_iter_factory_t @@ -841,7 +842,7 @@ struct template auto operator () (Iterable&& it, unsigned count) const HB_AUTO_RETURN - ( hb_zip (hb_range (count), it) | hb_map (hb_second) ) + ( hb_zip (hb_range (count), it) | hb_map_retains_sorting (hb_second) ) /* Specialization arrays. */ diff --git a/src/3rdparty/harfbuzz-ng/src/hb-kern.hh b/src/3rdparty/harfbuzz-ng/src/hb-kern.hh index 9ea945caed6..0462a0ea8ee 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-kern.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-kern.hh @@ -53,7 +53,7 @@ struct hb_kern_machine_t return; buffer->unsafe_to_concat (); - OT::hb_ot_apply_context_t c (1, font, buffer); + OT::hb_ot_apply_context_t c (1, font, buffer, hb_blob_get_empty ()); c.set_lookup_mask (kern_mask); c.set_lookup_props (OT::LookupFlag::IgnoreMarks); auto &skippy_iter = c.iter_input; @@ -70,7 +70,7 @@ struct hb_kern_machine_t continue; } - skippy_iter.reset (idx, 1); + skippy_iter.reset (idx); unsigned unsafe_to; if (!skippy_iter.next (&unsafe_to)) { diff --git a/src/3rdparty/harfbuzz-ng/src/hb-limits.hh b/src/3rdparty/harfbuzz-ng/src/hb-limits.hh index 0f60e9e2101..c503b30652b 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-limits.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-limits.hh @@ -89,6 +89,10 @@ #endif +#ifndef HB_GLYF_VAR_COMPOSITE_MAX_AXES +#define HB_GLYF_VAR_COMPOSITE_MAX_AXES 4096 +#endif + #ifndef HB_GLYF_MAX_POINTS #define HB_GLYF_MAX_POINTS 20000 #endif diff --git a/src/3rdparty/harfbuzz-ng/src/hb-machinery.hh b/src/3rdparty/harfbuzz-ng/src/hb-machinery.hh index 1084725af2a..ecff94f1b64 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-machinery.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-machinery.hh @@ -180,6 +180,9 @@ struct hb_lazy_loader_t : hb_data_wrapper_t hb_lazy_loader_t >::value Funcs; + hb_lazy_loader_t () = default; + hb_lazy_loader_t (const hb_lazy_loader_t &other) = delete; + void init0 () {} /* Init, when memory is already set to 0. No-op for us. */ void init () { instance.set_relaxed (nullptr); } void fini () { do_destroy (instance.get_acquire ()); init (); } @@ -278,7 +281,11 @@ struct hb_lazy_loader_t : hb_data_wrapper_t template struct hb_face_lazy_loader_t : hb_lazy_loader_t, - hb_face_t, WheresFace> {}; + hb_face_t, WheresFace> +{ + // Hack; have them here for API parity with hb_table_lazy_loader_t + hb_blob_t *get_blob () { return this->get ()->get_blob (); } +}; template struct hb_table_lazy_loader_t : hb_lazy_loader_t (face); diff --git a/src/3rdparty/harfbuzz-ng/src/hb-map.h b/src/3rdparty/harfbuzz-ng/src/hb-map.h index e928628fa7a..0ae171714ec 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-map.h +++ b/src/3rdparty/harfbuzz-ng/src/hb-map.h @@ -44,7 +44,7 @@ HB_BEGIN_DECLS * * Since: 1.7.7 */ -#define HB_MAP_VALUE_INVALID ((hb_codepoint_t) -1) +#define HB_MAP_VALUE_INVALID HB_CODEPOINT_INVALID /** * hb_map_t: diff --git a/src/3rdparty/harfbuzz-ng/src/hb-map.hh b/src/3rdparty/harfbuzz-ng/src/hb-map.hh index c685a9a3e13..42604ef7c2c 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-map.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-map.hh @@ -45,9 +45,9 @@ struct hb_hashmap_t hb_hashmap_t () { init (); } ~hb_hashmap_t () { fini (); } - hb_hashmap_t (const hb_hashmap_t& o) : hb_hashmap_t () { resize (o.population); hb_copy (o, *this); } + hb_hashmap_t (const hb_hashmap_t& o) : hb_hashmap_t () { alloc (o.population); hb_copy (o, *this); } hb_hashmap_t (hb_hashmap_t&& o) : hb_hashmap_t () { hb_swap (*this, o); } - hb_hashmap_t& operator= (const hb_hashmap_t& o) { reset (); resize (o.population); hb_copy (o, *this); return *this; } + hb_hashmap_t& operator= (const hb_hashmap_t& o) { reset (); alloc (o.population); hb_copy (o, *this); return *this; } hb_hashmap_t& operator= (hb_hashmap_t&& o) { hb_swap (*this, o); return *this; } hb_hashmap_t (std::initializer_list> lst) : hb_hashmap_t () @@ -60,29 +60,32 @@ struct hb_hashmap_t hb_hashmap_t (const Iterable &o) : hb_hashmap_t () { auto iter = hb_iter (o); - if (iter.is_random_access_iterator) - resize (hb_len (iter)); + if (iter.is_random_access_iterator || iter.has_fast_len) + alloc (hb_len (iter)); hb_copy (iter, *this); } struct item_t { K key; - uint32_t hash : 30; + uint32_t is_real_ : 1; uint32_t is_used_ : 1; - uint32_t is_tombstone_ : 1; + uint32_t hash : 30; V value; item_t () : key (), + is_real_ (false), is_used_ (false), hash (0), - is_used_ (false), is_tombstone_ (false), value () {} + // Needed for https://github.com/harfbuzz/harfbuzz/issues/4138 + K& get_key () { return key; } + V& get_value () { return value; } + bool is_used () const { return is_used_; } void set_used (bool is_used) { is_used_ = is_used; } - bool is_tombstone () const { return is_tombstone_; } - void set_tombstone (bool is_tombstone) { is_tombstone_ = is_tombstone; } - bool is_real () const { return is_used_ && !is_tombstone_; } + void set_real (bool is_real) { is_real_ = is_real; } + bool is_real () const { return is_real_; } template @@ -98,10 +101,15 @@ struct hb_hashmap_t bool operator == (const K &o) const { return hb_deref (key) == hb_deref (o); } bool operator == (const item_t &o) const { return *this == o.key; } hb_pair_t get_pair() const { return hb_pair_t (key, value); } - hb_pair_t get_pair_ref() const { return hb_pair_t (key, value); } + hb_pair_t get_pair_ref() { return hb_pair_t (key, value); } uint32_t total_hash () const { return (hash * 31) + hb_hash (value); } + + static constexpr bool is_trivial = std::is_trivially_constructible::value && + std::is_trivially_destructible::value && + std::is_trivially_constructible::value && + std::is_trivially_destructible::value; }; hb_object_header_t header; @@ -110,6 +118,7 @@ struct hb_hashmap_t unsigned int occupancy; /* Including tombstones. */ unsigned int mask; unsigned int prime; + unsigned int max_chain_length; item_t *items; friend void swap (hb_hashmap_t& a, hb_hashmap_t& b) @@ -123,6 +132,7 @@ struct hb_hashmap_t hb_swap (a.occupancy, b.occupancy); hb_swap (a.mask, b.mask); hb_swap (a.prime, b.prime); + hb_swap (a.max_chain_length, b.max_chain_length); hb_swap (a.items, b.items); } void init () @@ -133,16 +143,19 @@ struct hb_hashmap_t population = occupancy = 0; mask = 0; prime = 0; + max_chain_length = 0; items = nullptr; } void fini () { hb_object_fini (this); - if (likely (items)) { + if (likely (items)) + { unsigned size = mask + 1; - for (unsigned i = 0; i < size; i++) - items[i].~item_t (); + if (!item_t::is_trivial) + for (unsigned i = 0; i < size; i++) + items[i].~item_t (); hb_free (items); items = nullptr; } @@ -157,7 +170,7 @@ struct hb_hashmap_t bool in_error () const { return !successful; } - bool resize (unsigned new_population = 0) + bool alloc (unsigned new_population = 0) { if (unlikely (!successful)) return false; @@ -171,8 +184,11 @@ struct hb_hashmap_t successful = false; return false; } - for (auto &_ : hb_iter (new_items, new_size)) - new (&_) item_t (); + if (!item_t::is_trivial) + for (auto &_ : hb_iter (new_items, new_size)) + new (&_) item_t (); + else + hb_memset (new_items, 0, (size_t) new_size * sizeof (item_t)); unsigned int old_size = size (); item_t *old_items = items; @@ -181,6 +197,7 @@ struct hb_hashmap_t population = occupancy = 0; mask = new_size - 1; prime = prime_for (power); + max_chain_length = power * 2; items = new_items; /* Insert back old items. */ @@ -192,7 +209,8 @@ struct hb_hashmap_t old_items[i].hash, std::move (old_items[i].value)); } - old_items[i].~item_t (); + if (!item_t::is_trivial) + old_items[i].~item_t (); } hb_free (old_items); @@ -201,72 +219,124 @@ struct hb_hashmap_t } template - bool set_with_hash (KK&& key, uint32_t hash, VV&& value, bool is_delete=false) + bool set_with_hash (KK&& key, uint32_t hash, VV&& value, bool overwrite = true) { if (unlikely (!successful)) return false; - if (unlikely ((occupancy + occupancy / 2) >= mask && !resize ())) return false; - item_t &item = item_for_hash (key, hash); + if (unlikely ((occupancy + occupancy / 2) >= mask && !alloc ())) return false; - if (is_delete && !(item == key)) - return true; /* Trying to delete non-existent key. */ + hash &= 0x3FFFFFFF; // We only store lower 30bit of hash + unsigned int tombstone = (unsigned int) -1; + unsigned int i = hash % prime; + unsigned length = 0; + unsigned step = 0; + while (items[i].is_used ()) + { + if ((std::is_integral::value || items[i].hash == hash) && + items[i] == key) + { + if (!overwrite) + return false; + else + break; + } + if (!items[i].is_real () && tombstone == (unsigned) -1) + tombstone = i; + i = (i + ++step) & mask; + length++; + } + + item_t &item = items[tombstone == (unsigned) -1 ? i : tombstone]; if (item.is_used ()) { occupancy--; - if (!item.is_tombstone ()) - population--; + population -= item.is_real (); } item.key = std::forward (key); item.value = std::forward (value); item.hash = hash; item.set_used (true); - item.set_tombstone (is_delete); + item.set_real (true); occupancy++; - if (!is_delete) - population++; + population++; + + if (unlikely (length > max_chain_length) && occupancy * 8 > mask) + alloc (mask - 8); // This ensures we jump to next larger size return true; } template - bool set (const K &key, VV&& value) { return set_with_hash (key, hb_hash (key), std::forward (value)); } + bool set (const K &key, VV&& value, bool overwrite = true) { return set_with_hash (key, hb_hash (key), std::forward (value), overwrite); } template - bool set (K &&key, VV&& value) { return set_with_hash (std::move (key), hb_hash (key), std::forward (value)); } + bool set (K &&key, VV&& value, bool overwrite = true) + { + uint32_t hash = hb_hash (key); + return set_with_hash (std::move (key), hash, std::forward (value), overwrite); + } const V& get_with_hash (const K &key, uint32_t hash) const { - if (unlikely (!items)) return item_t::default_value (); - auto &item = item_for_hash (key, hash); - return item.is_real () && item == key ? item.value : item_t::default_value (); + if (!items) return item_t::default_value (); + auto *item = fetch_item (key, hb_hash (key)); + if (item) + return item->value; + return item_t::default_value (); } const V& get (const K &key) const { - if (unlikely (!items)) return item_t::default_value (); + if (!items) return item_t::default_value (); return get_with_hash (key, hb_hash (key)); } - void del (const K &key) { set_with_hash (key, hb_hash (key), item_t::default_value (), true); } + void del (const K &key) + { + if (!items) return; + auto *item = fetch_item (key, hb_hash (key)); + if (item) + { + item->set_real (false); + population--; + } + } /* Has interface. */ const V& operator [] (K k) const { return get (k); } template - bool has (K key, VV **vp = nullptr) const + bool has (const K &key, VV **vp = nullptr) const { - if (unlikely (!items)) - return false; - auto &item = item_for_hash (key, hb_hash (key)); - if (item.is_real () && item == key) + if (!items) return false; + auto *item = fetch_item (key, hb_hash (key)); + if (item) { - if (vp) *vp = std::addressof (item.value); + if (vp) *vp = std::addressof (item->value); return true; } - else - return false; + return false; + } + item_t *fetch_item (const K &key, uint32_t hash) const + { + hash &= 0x3FFFFFFF; // We only store lower 30bit of hash + unsigned int i = hash % prime; + unsigned step = 0; + while (items[i].is_used ()) + { + if ((std::is_integral::value || items[i].hash == hash) && + items[i] == key) + { + if (items[i].is_real ()) + return &items[i]; + else + return nullptr; + } + i = (i + ++step) & mask; + } + return nullptr; } /* Projection. */ - V operator () (K k) const { return get (k); } + const V& operator () (K k) const { return get (k); } unsigned size () const { return mask ? mask + 1 : 0; } @@ -339,23 +409,21 @@ struct hb_hashmap_t auto keys_ref () const HB_AUTO_RETURN ( + iter_items () - | hb_map (&item_t::key) + | hb_map (&item_t::get_key) ) auto keys () const HB_AUTO_RETURN ( - + iter_items () - | hb_map (&item_t::key) + + keys_ref () | hb_map (hb_ridentity) ) auto values_ref () const HB_AUTO_RETURN ( + iter_items () - | hb_map (&item_t::value) + | hb_map (&item_t::get_value) ) auto values () const HB_AUTO_RETURN ( - + iter_items () - | hb_map (&item_t::value) + + values_ref () | hb_map (hb_ridentity) ) @@ -393,24 +461,6 @@ struct hb_hashmap_t hb_hashmap_t& operator << (const hb_pair_t& v) { set (std::move (v.first), std::move (v.second)); return *this; } - item_t& item_for_hash (const K &key, uint32_t hash) const - { - hash &= 0x3FFFFFFF; // We only store lower 30bit of hash - unsigned int i = hash % prime; - unsigned int step = 0; - unsigned int tombstone = (unsigned) -1; - while (items[i].is_used ()) - { - if ((hb_is_same (K, hb_codepoint_t) || items[i].hash == hash) && - items[i] == key) - return items[i]; - if (tombstone == (unsigned) -1 && items[i].is_tombstone ()) - tombstone = i; - i = (i + ++step) & mask; - } - return items[tombstone == (unsigned) -1 ? i : tombstone]; - } - static unsigned int prime_for (unsigned int shift) { /* Following comment and table copied from glib. */ @@ -481,7 +531,7 @@ struct hb_map_t : hb_hashmap_t> lst) : hashmap (lst) {} + hb_map_t (std::initializer_list lst) : hashmap (lst) {} template hb_map_t (const Iterable &o) : hashmap (o) {} diff --git a/src/3rdparty/harfbuzz-ng/src/hb-meta.hh b/src/3rdparty/harfbuzz-ng/src/hb-meta.hh index 31aa7fa6f16..52ff4a84127 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-meta.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-meta.hh @@ -153,8 +153,8 @@ struct hb_reference_wrapper hb_reference_wrapper (T v) : v (v) {} bool operator == (const hb_reference_wrapper& o) const { return v == o.v; } bool operator != (const hb_reference_wrapper& o) const { return v != o.v; } - operator T () const { return v; } - T get () const { return v; } + operator T& () { return v; } + T& get () { return v; } T v; }; template @@ -163,8 +163,8 @@ struct hb_reference_wrapper hb_reference_wrapper (T& v) : v (std::addressof (v)) {} bool operator == (const hb_reference_wrapper& o) const { return v == o.v; } bool operator != (const hb_reference_wrapper& o) const { return v != o.v; } - operator T& () const { return *v; } - T& get () const { return *v; } + operator T& () { return *v; } + T& get () { return *v; } T* v; }; diff --git a/src/3rdparty/harfbuzz-ng/src/hb-multimap.hh b/src/3rdparty/harfbuzz-ng/src/hb-multimap.hh index b4a8cc62a3e..0184279c127 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-multimap.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-multimap.hh @@ -38,10 +38,10 @@ struct hb_multimap_t { void add (hb_codepoint_t k, hb_codepoint_t v) { - hb_codepoint_t *i; - if (multiples_indices.has (k, &i)) + hb_vector_t *m; + if (multiples.has (k, &m)) { - multiples_values[*i].push (v); + m->push (v); return; } @@ -51,12 +51,7 @@ struct hb_multimap_t hb_codepoint_t old = *old_v; singulars.del (k); - multiples_indices.set (k, multiples_values.length); - auto *vec = multiples_values.push (); - - vec->push (old); - vec->push (v); - + multiples.set (k, hb_vector_t {old, v}); return; } @@ -69,22 +64,31 @@ struct hb_multimap_t if (singulars.has (k, &v)) return hb_array (v, 1); - hb_codepoint_t *i; - if (multiples_indices.has (k, &i)) - return multiples_values[*i].as_array (); + hb_vector_t *m; + if (multiples.has (k, &m)) + return m->as_array (); return hb_array_t (); } bool in_error () const { - return singulars.in_error () || multiples_indices.in_error () || multiples_values.in_error (); + if (singulars.in_error () || multiples.in_error ()) + return true; + for (const auto &m : multiples.values_ref ()) + if (m.in_error ()) + return true; + return false; + } + + void alloc (unsigned size) + { + singulars.alloc (size); } protected: hb_map_t singulars; - hb_map_t multiples_indices; - hb_vector_t> multiples_values; + hb_hashmap_t> multiples; }; diff --git a/src/3rdparty/harfbuzz-ng/src/hb-null.hh b/src/3rdparty/harfbuzz-ng/src/hb-null.hh index 3da2d75ef5e..6796906ba82 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-null.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-null.hh @@ -37,7 +37,7 @@ /* Global nul-content Null pool. Enlarge as necessary. */ -#define HB_NULL_POOL_SIZE 520 +#define HB_NULL_POOL_SIZE 640 template struct _hb_has_min_size : hb_false_type {}; @@ -176,7 +176,7 @@ template static inline Type& Crap () { static_assert (hb_null_size (Type) <= HB_NULL_POOL_SIZE, "Increase HB_NULL_POOL_SIZE."); Type *obj = reinterpret_cast (_hb_CrapPool); - memcpy (obj, &Null (Type), sizeof (*obj)); + memcpy (obj, std::addressof (Null (Type)), sizeof (*obj)); return *obj; } template @@ -211,11 +211,11 @@ struct hb_nonnull_ptr_t T * operator = (T *v_) { return v = v_; } T * operator -> () const { return get (); } T & operator * () const { return *get (); } - T ** operator & () const { return &v; } + T ** operator & () const { return std::addressof (v); } /* Only auto-cast to const types. */ template operator const C * () const { return get (); } operator const char * () const { return (const char *) get (); } - T * get () const { return v ? v : const_cast (&Null (T)); } + T * get () const { return v ? v : const_cast (std::addressof (Null (T))); } T * get_raw () const { return v; } private: diff --git a/src/3rdparty/harfbuzz-ng/src/hb-open-file.hh b/src/3rdparty/harfbuzz-ng/src/hb-open-file.hh index 13570a46e0c..04f144a72c7 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-open-file.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-open-file.hh @@ -131,7 +131,7 @@ typedef struct OpenTypeOffsetTable sfnt_version = sfnt_tag; /* Take space for numTables, searchRange, entrySelector, RangeShift * and the TableRecords themselves. */ - unsigned num_items = it.len (); + unsigned num_items = hb_len (it); if (unlikely (!tables.serialize (c, num_items))) return_trace (false); const char *dir_end = (const char *) c->head; @@ -145,7 +145,7 @@ typedef struct OpenTypeOffsetTable unsigned len = blob->length; /* Allocate room for the table and copy it. */ - char *start = (char *) c->allocate_size (len); + char *start = (char *) c->allocate_size (len, false); if (unlikely (!start)) return false; TableRecord &rec = tables.arrayZ[i]; diff --git a/src/3rdparty/harfbuzz-ng/src/hb-open-type.hh b/src/3rdparty/harfbuzz-ng/src/hb-open-type.hh index 4c9bfebcec1..d3fdd1caf52 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-open-type.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-open-type.hh @@ -312,6 +312,8 @@ struct _hb_has_null template struct OffsetTo : Offset { + using target_t = Type; + // Make sure Type is not unbounded; works only for types that are fully defined at OffsetTo time. static_assert (has_null == false || (hb_has_null_size (Type) || !hb_has_min_size (Type)), ""); @@ -416,12 +418,15 @@ struct OffsetTo : Offset { TRACE_SANITIZE (this); if (unlikely (!c->check_struct (this))) return_trace (false); - if (unlikely (this->is_null ())) return_trace (true); + //if (unlikely (this->is_null ())) return_trace (true); if (unlikely ((const char *) base + (unsigned) *this < (const char *) base)) return_trace (false); return_trace (true); } template +#ifndef HB_OPTIMIZE_SIZE + HB_ALWAYS_INLINE +#endif bool sanitize (hb_sanitize_context_t *c, const void *base, Ts&&... ds) const { TRACE_SANITIZE (this); @@ -462,24 +467,16 @@ struct UnsizedArrayOf HB_DELETE_CREATE_COPY_ASSIGN (UnsizedArrayOf); - const Type& operator [] (int i_) const + const Type& operator [] (unsigned int i) const { - unsigned int i = (unsigned int) i_; - const Type *p = &arrayZ[i]; - if (unlikely ((const void *) p < (const void *) arrayZ)) return Null (Type); /* Overflowed. */ - _hb_compiler_memory_r_barrier (); - return *p; + return arrayZ[i]; } - Type& operator [] (int i_) + Type& operator [] (unsigned int i) { - unsigned int i = (unsigned int) i_; - Type *p = &arrayZ[i]; - if (unlikely ((const void *) p < (const void *) arrayZ)) return Crap (Type); /* Overflowed. */ - _hb_compiler_memory_r_barrier (); - return *p; + return arrayZ[i]; } - unsigned int get_size (unsigned int len) const + static unsigned int get_size (unsigned int len) { return len * Type::static_size; } template operator T * () { return arrayZ; } @@ -533,6 +530,7 @@ struct UnsizedArrayOf } template + HB_ALWAYS_INLINE bool sanitize (hb_sanitize_context_t *c, unsigned int count, Ts&&... ds) const { TRACE_SANITIZE (this); @@ -721,6 +719,7 @@ struct ArrayOf } template + HB_ALWAYS_INLINE bool sanitize (hb_sanitize_context_t *c, Ts&&... ds) const { TRACE_SANITIZE (this); @@ -736,7 +735,7 @@ struct ArrayOf bool sanitize_shallow (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); - return_trace (len.sanitize (c) && c->check_array (arrayZ, len)); + return_trace (len.sanitize (c) && c->check_array_sized (arrayZ, len, sizeof (LenType))); } public: @@ -797,7 +796,7 @@ template using List16OfOffset16To = List16OfOffsetTo; /* An array starting at second element. */ -template +template struct HeadlessArrayOf { static constexpr unsigned item_size = Type::static_size; @@ -861,6 +860,7 @@ struct HeadlessArrayOf } template + HB_ALWAYS_INLINE bool sanitize (hb_sanitize_context_t *c, Ts&&... ds) const { TRACE_SANITIZE (this); @@ -878,7 +878,7 @@ struct HeadlessArrayOf { TRACE_SANITIZE (this); return_trace (lenP1.sanitize (c) && - (!lenP1 || c->check_array (arrayZ, lenP1 - 1))); + (!lenP1 || c->check_array_sized (arrayZ, lenP1 - 1, sizeof (LenType)))); } public: @@ -887,6 +887,7 @@ struct HeadlessArrayOf public: DEFINE_SIZE_ARRAY (sizeof (LenType), arrayZ); }; +template using HeadlessArray16Of = HeadlessArrayOf; /* An array storing length-1. */ template @@ -912,6 +913,7 @@ struct ArrayOfM1 { return lenM1.static_size + (lenM1 + 1) * Type::static_size; } template + HB_ALWAYS_INLINE bool sanitize (hb_sanitize_context_t *c, Ts&&... ds) const { TRACE_SANITIZE (this); @@ -929,7 +931,7 @@ struct ArrayOfM1 { TRACE_SANITIZE (this); return_trace (lenM1.sanitize (c) && - (c->check_array (arrayZ, lenM1 + 1))); + (c->check_array_sized (arrayZ, lenM1 + 1, sizeof (LenType)))); } public: @@ -1096,6 +1098,7 @@ struct VarSizedBinSearchArrayOf { return header.static_size + header.nUnits * header.unitSize; } template + HB_ALWAYS_INLINE bool sanitize (hb_sanitize_context_t *c, Ts&&... ds) const { TRACE_SANITIZE (this); diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-cff-common.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-cff-common.hh index f22824fc699..923a32b26f8 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-ot-cff-common.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-cff-common.hh @@ -48,12 +48,24 @@ static inline const Type& StructAtOffsetOrNull (const void *P, unsigned int offs struct code_pair_t { - hb_codepoint_t code; + unsigned code; hb_codepoint_t glyph; }; + using str_buff_t = hb_vector_t; using str_buff_vec_t = hb_vector_t; +using glyph_to_sid_map_t = hb_vector_t; + +struct length_f_t +{ + template + unsigned operator () (const Iterable &_) const { return hb_len (hb_iter (_)); } + + unsigned operator () (unsigned _) const { return _; } +} +HB_FUNCOBJ (length_f); /* CFF INDEX */ template @@ -62,42 +74,52 @@ struct CFFIndex unsigned int offset_array_size () const { return offSize * (count + 1); } - CFFIndex *copy (hb_serialize_context_t *c) const - { - TRACE_SERIALIZE (this); - unsigned int size = get_size (); - CFFIndex *out = c->allocate_size (size, false); - if (likely (out)) - hb_memcpy (out, this, size); - return_trace (out); - } - template bool serialize (hb_serialize_context_t *c, - const Iterable &iterable) + const Iterable &iterable, + const unsigned *p_data_size = nullptr) { TRACE_SERIALIZE (this); + unsigned data_size; + if (p_data_size) + data_size = *p_data_size; + else + total_size (iterable, &data_size); + auto it = hb_iter (iterable); - serialize_header(c, + it | hb_map (hb_iter) | hb_map (hb_len)); + if (unlikely (!serialize_header (c, +it, data_size))) return_trace (false); + unsigned char *ret = c->allocate_size (data_size, false); + if (unlikely (!ret)) return_trace (false); for (const auto &_ : +it) - hb_iter (_).copy (c); + { + unsigned len = _.length; + if (!len) + continue; + if (len <= 1) + { + *ret++ = *_.arrayZ; + continue; + } + hb_memcpy (ret, _.arrayZ, len); + ret += len; + } return_trace (true); } template bool serialize_header (hb_serialize_context_t *c, - Iterator it) + Iterator it, + unsigned data_size) { TRACE_SERIALIZE (this); - unsigned total = + it | hb_reduce (hb_add, 0); - unsigned off_size = (hb_bit_storage (total + 1) + 7) / 8; + unsigned off_size = (hb_bit_storage (data_size + 1) + 7) / 8; /* serialize CFFIndex header */ if (unlikely (!c->extend_min (this))) return_trace (false); - this->count = it.len (); + this->count = hb_len (it); if (!this->count) return_trace (true); if (unlikely (!c->extend (this->offSize))) return_trace (false); this->offSize = off_size; @@ -106,25 +128,88 @@ struct CFFIndex /* serialize indices */ unsigned int offset = 1; - unsigned int i = 0; - for (unsigned _ : +it) + if (HB_OPTIMIZE_SIZE_VAL) { - set_offset_at (i++, offset); - offset += _; + unsigned int i = 0; + for (const auto &_ : +it) + { + set_offset_at (i++, offset); + offset += length_f (_); + } + set_offset_at (i, offset); } - set_offset_at (i, offset); + else + switch (off_size) + { + case 1: + { + HBUINT8 *p = (HBUINT8 *) offsets; + for (const auto &_ : +it) + { + *p++ = offset; + offset += length_f (_); + } + *p = offset; + } + break; + case 2: + { + HBUINT16 *p = (HBUINT16 *) offsets; + for (const auto &_ : +it) + { + *p++ = offset; + offset += length_f (_); + } + *p = offset; + } + break; + case 3: + { + HBUINT24 *p = (HBUINT24 *) offsets; + for (const auto &_ : +it) + { + *p++ = offset; + offset += length_f (_); + } + *p = offset; + } + break; + case 4: + { + HBUINT32 *p = (HBUINT32 *) offsets; + for (const auto &_ : +it) + { + *p++ = offset; + offset += length_f (_); + } + *p = offset; + } + break; + default: + break; + } + assert (offset == data_size + 1); return_trace (true); } template - static unsigned total_size (const Iterable &iterable) + static unsigned total_size (const Iterable &iterable, unsigned *data_size = nullptr) { - auto it = + hb_iter (iterable) | hb_map (hb_iter) | hb_map (hb_len); - if (!it) return 0; + auto it = + hb_iter (iterable); + if (!it) + { + if (data_size) *data_size = 0; + return min_size; + } + + unsigned total = 0; + for (const auto &_ : +it) + total += length_f (_); + + if (data_size) *data_size = total; - unsigned total = + it | hb_reduce (hb_add, 0); unsigned off_size = (hb_bit_storage (total + 1) + 7) / 8; return min_size + HBUINT8::static_size + (hb_len (it) + 1) * off_size + total; @@ -133,13 +218,16 @@ struct CFFIndex void set_offset_at (unsigned int index, unsigned int offset) { assert (index <= count); - HBUINT8 *p = offsets + offSize * index + offSize; + unsigned int size = offSize; - for (; size; size--) + const HBUINT8 *p = offsets; + switch (size) { - --p; - *p = offset & 0xFF; - offset >>= 8; + case 1: ((HBUINT8 *) p)[index] = offset; break; + case 2: ((HBUINT16 *) p)[index] = offset; break; + case 3: ((HBUINT24 *) p)[index] = offset; break; + case 4: ((HBUINT32 *) p)[index] = offset; break; + default: return; } } @@ -149,37 +237,30 @@ struct CFFIndex assert (index <= count); unsigned int size = offSize; - const HBUINT8 *p = offsets + size * index; + const HBUINT8 *p = offsets; switch (size) { - case 1: return * (HBUINT8 *) p; - case 2: return * (HBUINT16 *) p; - case 3: return * (HBUINT24 *) p; - case 4: return * (HBUINT32 *) p; + case 1: return ((HBUINT8 *) p)[index]; + case 2: return ((HBUINT16 *) p)[index]; + case 3: return ((HBUINT24 *) p)[index]; + case 4: return ((HBUINT32 *) p)[index]; default: return 0; } } - unsigned int length_at (unsigned int index) const - { - unsigned offset0 = offset_at (index); - unsigned offset1 = offset_at (index + 1); - if (unlikely (offset1 < offset0 || offset1 > offset_at (count))) - return 0; - return offset1 - offset0; - } - const unsigned char *data_base () const - { return (const unsigned char *) this + min_size + offSize.static_size + offset_array_size (); } + { return (const unsigned char *) this + min_size + offSize.static_size - 1 + offset_array_size (); } public: hb_ubytes_t operator [] (unsigned int index) const { if (unlikely (index >= count)) return hb_ubytes_t (); _hb_compiler_memory_r_barrier (); - unsigned length = length_at (index); - if (unlikely (!length)) return hb_ubytes_t (); - return hb_ubytes_t (data_base () + offset_at (index) - 1, length); + unsigned offset0 = offset_at (index); + unsigned offset1 = offset_at (index + 1); + if (unlikely (offset1 < offset0 || offset1 > offset_at (count))) + return hb_ubytes_t (); + return hb_ubytes_t (data_base () + offset0, offset1 - offset0); } unsigned int get_size () const @@ -197,7 +278,7 @@ struct CFFIndex (count < count + 1u && c->check_struct (&offSize) && offSize >= 1 && offSize <= 4 && c->check_array (offsets, offSize, count + 1u) && - c->check_array ((const HBUINT8*) data_base (), 1, offset_at (count) - 1))))); + c->check_array ((const HBUINT8*) data_base (), 1, offset_at (count)))))); } public: @@ -211,47 +292,6 @@ struct CFFIndex DEFINE_SIZE_MIN (COUNT::static_size); }; -template -struct CFFIndexOf : CFFIndex -{ - template - bool serialize (hb_serialize_context_t *c, - unsigned int offSize_, - const DATA *dataArray, - unsigned int dataArrayLen, - const hb_vector_t &dataSizeArray, - const PARAM1 ¶m1, - const PARAM2 ¶m2) - { - TRACE_SERIALIZE (this); - /* serialize CFFIndex header */ - if (unlikely (!c->extend_min (this))) return_trace (false); - this->count = dataArrayLen; - this->offSize = offSize_; - if (unlikely (!c->allocate_size (offSize_ * (dataArrayLen + 1), false))) - return_trace (false); - - /* serialize indices */ - unsigned int offset = 1; - unsigned int i = 0; - for (; i < dataArrayLen; i++) - { - this->set_offset_at (i, offset); - offset += dataSizeArray[i]; - } - this->set_offset_at (i, offset); - - /* serialize data */ - for (unsigned int i = 0; i < dataArrayLen; i++) - { - TYPE *dest = c->start_embed (); - if (unlikely (!dest || !dest->serialize (c, dataArray[i], param1, param2))) - return_trace (false); - } - return_trace (true); - } -}; - /* Top Dict, Font Dict, Private Dict */ struct Dict : UnsizedByteStr { @@ -327,7 +367,7 @@ struct table_info_t }; template -struct FDArray : CFFIndexOf +struct FDArray : CFFIndex { template bool serialize (hb_serialize_context_t *c, @@ -338,7 +378,11 @@ struct FDArray : CFFIndexOf /* serialize INDEX data */ hb_vector_t sizes; + if (it.is_random_access_iterator) + sizes.alloc (hb_len (it)); + c->push (); + char *data_base = c->head; + it | hb_map ([&] (const hb_pair_t &_) { @@ -348,10 +392,16 @@ struct FDArray : CFFIndexOf }) | hb_sink (sizes) ; + unsigned data_size = c->head - data_base; c->pop_pack (false); + if (unlikely (sizes.in_error ())) return_trace (false); + + /* It just happens that the above is packed right after the header below. + * Such a hack. */ + /* serialize INDEX header */ - return_trace (CFFIndex::serialize_header (c, hb_iter (sizes))); + return_trace (CFFIndex::serialize_header (c, hb_iter (sizes), data_size)); } }; @@ -368,8 +418,11 @@ struct FDSelect0 { return_trace (true); } - hb_codepoint_t get_fd (hb_codepoint_t glyph) const - { return (hb_codepoint_t) fds[glyph]; } + unsigned get_fd (hb_codepoint_t glyph) const + { return fds[glyph]; } + + hb_pair_t get_fd_range (hb_codepoint_t glyph) const + { return {fds[glyph], glyph + 1}; } unsigned int get_size (unsigned int num_glyphs) const { return HBUINT8::static_size * num_glyphs; } @@ -427,12 +480,20 @@ struct FDSelect3_4 return +1; } - hb_codepoint_t get_fd (hb_codepoint_t glyph) const + unsigned get_fd (hb_codepoint_t glyph) const { auto *range = hb_bsearch (glyph, &ranges[0], nRanges () - 1, sizeof (ranges[0]), _cmp_range); return range ? range->fd : ranges[nRanges () - 1].fd; } + hb_pair_t get_fd_range (hb_codepoint_t glyph) const + { + auto *range = hb_bsearch (glyph, &ranges[0], nRanges () - 1, sizeof (ranges[0]), _cmp_range); + unsigned fd = range ? range->fd : ranges[nRanges () - 1].fd; + hb_codepoint_t end = range ? range[1].first : ranges[nRanges () - 1].first; + return {fd, end}; + } + GID_TYPE &nRanges () { return ranges.len; } GID_TYPE nRanges () const { return ranges.len; } GID_TYPE &sentinel () { return StructAfter (ranges[nRanges () - 1]); } @@ -469,7 +530,7 @@ struct FDSelect } } - hb_codepoint_t get_fd (hb_codepoint_t glyph) const + unsigned get_fd (hb_codepoint_t glyph) const { if (this == &Null (FDSelect)) return 0; @@ -480,6 +541,18 @@ struct FDSelect default:return 0; } } + /* Returns pair of fd and one after last glyph in range. */ + hb_pair_t get_fd_range (hb_codepoint_t glyph) const + { + if (this == &Null (FDSelect)) return {0, 1}; + + switch (format) + { + case 0: return u.format0.get_fd_range (glyph); + case 3: return u.format3.get_fd_range (glyph); + default:return {0, 1}; + } + } bool sanitize (hb_sanitize_context_t *c, unsigned int fdcount) const { diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-cff1-table.cc b/src/3rdparty/harfbuzz-ng/src/hb-ot-cff1-table.cc index 5040c746234..66df28aae1d 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-ot-cff1-table.cc +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-cff1-table.cc @@ -574,11 +574,11 @@ bool OT::cff1::accelerator_t::get_path (hb_font_t *font, hb_codepoint_t glyph, h struct get_seac_param_t { - get_seac_param_t (const OT::cff1::accelerator_t *_cff) : cff (_cff) {} + get_seac_param_t (const OT::cff1::accelerator_subset_t *_cff) : cff (_cff) {} bool has_seac () const { return base && accent; } - const OT::cff1::accelerator_t *cff; + const OT::cff1::accelerator_subset_t *cff; hb_codepoint_t base = 0; hb_codepoint_t accent = 0; }; @@ -596,7 +596,7 @@ struct cff1_cs_opset_seac_t : cff1_cs_opset_t= num_glyphs))) return false; diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-cff1-table.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-cff1-table.hh index 4d0a965eee9..1e81dcb5e3a 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-ot-cff1-table.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-cff1-table.hh @@ -28,7 +28,7 @@ #define HB_OT_CFF1_TABLE_HH #include "hb-ot-cff-common.hh" -#include "hb-subset-cff1.hh" +#include "hb-subset-cff-common.hh" #include "hb-draw.hh" #include "hb-paint.hh" @@ -52,7 +52,6 @@ enum EncodingID { StandardEncoding = 0, ExpertEncoding = 1 }; enum CharsetID { ISOAdobeCharset = 0, ExpertCharset = 1, ExpertSubsetCharset = 2 }; typedef CFFIndex CFF1Index; -template struct CFF1IndexOf : CFFIndexOf {}; typedef CFFIndex CFF1Index; typedef CFF1Index CFF1CharStrings; @@ -110,6 +109,7 @@ struct Encoding1 { hb_codepoint_t get_code (hb_codepoint_t glyph) const { + /* TODO: Add cache like get_sid. */ assert (glyph > 0); glyph--; for (unsigned int i = 0; i < nRanges (); i++) @@ -173,11 +173,7 @@ struct Encoding bool serialize (hb_serialize_context_t *c, const Encoding &src) { TRACE_SERIALIZE (this); - unsigned int size = src.get_size (); - Encoding *dest = c->allocate_size (size); - if (unlikely (!dest)) return_trace (false); - hb_memcpy (dest, &src, size); - return_trace (true); + return_trace (c->embed (src)); } /* serialize a subset Encoding */ @@ -312,26 +308,29 @@ struct Encoding }; /* Charset */ -struct Charset0 { - bool sanitize (hb_sanitize_context_t *c, unsigned int num_glyphs) const +struct Charset0 +{ + bool sanitize (hb_sanitize_context_t *c, unsigned int num_glyphs, unsigned *num_charset_entries) const { TRACE_SANITIZE (this); - return_trace (c->check_struct (this) && sids[num_glyphs - 1].sanitize (c)); + if (num_charset_entries) *num_charset_entries = num_glyphs; + return_trace (sids.sanitize (c, num_glyphs - 1)); } hb_codepoint_t get_sid (hb_codepoint_t glyph, unsigned num_glyphs) const { if (unlikely (glyph >= num_glyphs)) return 0; - if (glyph == 0) + if (unlikely (glyph == 0)) return 0; else return sids[glyph - 1]; } - void collect_glyph_to_sid_map (hb_map_t *mapping, unsigned int num_glyphs) const + void collect_glyph_to_sid_map (glyph_to_sid_map_t *mapping, unsigned int num_glyphs) const { + mapping->resize (num_glyphs, false); for (hb_codepoint_t gid = 1; gid < num_glyphs; gid++) - mapping->set (gid, sids[gid - 1]); + mapping->arrayZ[gid] = {sids[gid - 1], gid}; } hb_codepoint_t get_glyph (hb_codepoint_t sid, unsigned int num_glyphs) const @@ -347,13 +346,13 @@ struct Charset0 { return 0; } - unsigned int get_size (unsigned int num_glyphs) const + static unsigned int get_size (unsigned int num_glyphs) { assert (num_glyphs > 0); - return HBUINT16::static_size * (num_glyphs - 1); + return UnsizedArrayOf::get_size (num_glyphs - 1); } - HBUINT16 sids[HB_VAR_ARRAY]; + UnsizedArrayOf sids; DEFINE_SIZE_ARRAY(0, sids); }; @@ -374,38 +373,62 @@ struct Charset_Range { template struct Charset1_2 { - bool sanitize (hb_sanitize_context_t *c, unsigned int num_glyphs) const + bool sanitize (hb_sanitize_context_t *c, unsigned int num_glyphs, unsigned *num_charset_entries) const { TRACE_SANITIZE (this); if (unlikely (!c->check_struct (this))) return_trace (false); num_glyphs--; - for (unsigned int i = 0; num_glyphs > 0; i++) + unsigned i; + for (i = 0; num_glyphs > 0; i++) { if (unlikely (!ranges[i].sanitize (c) || (num_glyphs < ranges[i].nLeft + 1))) return_trace (false); num_glyphs -= (ranges[i].nLeft + 1); } + if (num_charset_entries) + *num_charset_entries = i; return_trace (true); } - hb_codepoint_t get_sid (hb_codepoint_t glyph, unsigned num_glyphs) const + hb_codepoint_t get_sid (hb_codepoint_t glyph, unsigned num_glyphs, + code_pair_t *cache = nullptr) const { if (unlikely (glyph >= num_glyphs)) return 0; - if (glyph == 0) return 0; - glyph--; - for (unsigned int i = 0;; i++) + unsigned i; + hb_codepoint_t start_glyph; + if (cache && likely (cache->glyph <= glyph)) { - if (glyph <= ranges[i].nLeft) - return (hb_codepoint_t) ranges[i].first + glyph; - glyph -= (ranges[i].nLeft + 1); + i = cache->code; + start_glyph = cache->glyph; + } + else + { + if (unlikely (glyph == 0)) return 0; + i = 0; + start_glyph = 1; + } + glyph -= start_glyph; + for (;; i++) + { + unsigned count = ranges[i].nLeft; + if (glyph <= count) + { + if (cache) + *cache = {i, start_glyph}; + return ranges[i].first + glyph; + } + count++; + start_glyph += count; + glyph -= count; } return 0; } - void collect_glyph_to_sid_map (hb_map_t *mapping, unsigned int num_glyphs) const + void collect_glyph_to_sid_map (glyph_to_sid_map_t *mapping, unsigned int num_glyphs) const { + mapping->resize (num_glyphs, false); hb_codepoint_t gid = 1; if (gid >= num_glyphs) return; @@ -413,8 +436,9 @@ struct Charset1_2 { { hb_codepoint_t sid = ranges[i].first; unsigned count = ranges[i].nLeft + 1; + unsigned last = gid + count; for (unsigned j = 0; j < count; j++) - mapping->set (gid++, sid++); + mapping->arrayZ[gid++] = {sid++, last - 1}; if (gid >= num_glyphs) break; @@ -439,21 +463,26 @@ struct Charset1_2 { unsigned int get_size (unsigned int num_glyphs) const { - unsigned int size = HBUINT8::static_size; - int glyph = (int)num_glyphs; + int glyph = (int) num_glyphs; + unsigned num_ranges = 0; assert (glyph > 0); glyph--; for (unsigned int i = 0; glyph > 0; i++) { glyph -= (ranges[i].nLeft + 1); - size += Charset_Range::static_size; + num_ranges++; } - return size; + return get_size_for_ranges (num_ranges); } - Charset_Range ranges[HB_VAR_ARRAY]; + static unsigned int get_size_for_ranges (unsigned int num_ranges) + { + return UnsizedArrayOf >::get_size (num_ranges); + } + + UnsizedArrayOf> ranges; DEFINE_SIZE_ARRAY (0, ranges); }; @@ -469,11 +498,7 @@ struct Charset bool serialize (hb_serialize_context_t *c, const Charset &src, unsigned int num_glyphs) { TRACE_SERIALIZE (this); - unsigned int size = src.get_size (num_glyphs); - Charset *dest = c->allocate_size (size); - if (unlikely (!dest)) return_trace (false); - hb_memcpy (dest, &src, size); - return_trace (true); + return_trace (c->embed ((const char *) &src, src.get_size (num_glyphs))); } /* serialize a subset Charset */ @@ -490,13 +515,13 @@ struct Charset { case 0: { - Charset0 *fmt0 = c->allocate_size (Charset0::min_size + HBUINT16::static_size * (num_glyphs - 1)); + Charset0 *fmt0 = c->allocate_size (Charset0::get_size (num_glyphs), false); if (unlikely (!fmt0)) return_trace (false); unsigned int glyph = 0; for (unsigned int i = 0; i < sid_ranges.length; i++) { - hb_codepoint_t sid = sid_ranges[i].code; - for (int left = (int)sid_ranges[i].glyph; left >= 0; left--) + hb_codepoint_t sid = sid_ranges.arrayZ[i].code; + for (int left = (int)sid_ranges.arrayZ[i].glyph; left >= 0; left--) fmt0->sids[glyph++] = sid++; } } @@ -504,29 +529,35 @@ struct Charset case 1: { - Charset1 *fmt1 = c->allocate_size (Charset1::min_size + Charset1_Range::static_size * sid_ranges.length); + Charset1 *fmt1 = c->allocate_size (Charset1::get_size_for_ranges (sid_ranges.length), false); if (unlikely (!fmt1)) return_trace (false); + hb_codepoint_t all_glyphs = 0; for (unsigned int i = 0; i < sid_ranges.length; i++) { - if (unlikely (!(sid_ranges[i].glyph <= 0xFF))) - return_trace (false); - fmt1->ranges[i].first = sid_ranges[i].code; - fmt1->ranges[i].nLeft = sid_ranges[i].glyph; + auto &_ = sid_ranges.arrayZ[i]; + all_glyphs |= _.glyph; + fmt1->ranges[i].first = _.code; + fmt1->ranges[i].nLeft = _.glyph; } + if (unlikely (!(all_glyphs <= 0xFF))) + return_trace (false); } break; case 2: { - Charset2 *fmt2 = c->allocate_size (Charset2::min_size + Charset2_Range::static_size * sid_ranges.length); + Charset2 *fmt2 = c->allocate_size (Charset2::get_size_for_ranges (sid_ranges.length), false); if (unlikely (!fmt2)) return_trace (false); + hb_codepoint_t all_glyphs = 0; for (unsigned int i = 0; i < sid_ranges.length; i++) { - if (unlikely (!(sid_ranges[i].glyph <= 0xFFFF))) - return_trace (false); - fmt2->ranges[i].first = sid_ranges[i].code; - fmt2->ranges[i].nLeft = sid_ranges[i].glyph; + auto &_ = sid_ranges.arrayZ[i]; + all_glyphs |= _.glyph; + fmt2->ranges[i].first = _.code; + fmt2->ranges[i].nLeft = _.glyph; } + if (unlikely (!(all_glyphs <= 0xFFFF))) + return_trace (false); } break; @@ -545,18 +576,19 @@ struct Charset } } - hb_codepoint_t get_sid (hb_codepoint_t glyph, unsigned int num_glyphs) const + hb_codepoint_t get_sid (hb_codepoint_t glyph, unsigned int num_glyphs, + code_pair_t *cache = nullptr) const { switch (format) { case 0: return u.format0.get_sid (glyph, num_glyphs); - case 1: return u.format1.get_sid (glyph, num_glyphs); - case 2: return u.format2.get_sid (glyph, num_glyphs); + case 1: return u.format1.get_sid (glyph, num_glyphs, cache); + case 2: return u.format2.get_sid (glyph, num_glyphs, cache); default:return 0; } } - void collect_glyph_to_sid_map (hb_map_t *mapping, unsigned int num_glyphs) const + void collect_glyph_to_sid_map (glyph_to_sid_map_t *mapping, unsigned int num_glyphs) const { switch (format) { @@ -578,7 +610,7 @@ struct Charset } } - bool sanitize (hb_sanitize_context_t *c) const + bool sanitize (hb_sanitize_context_t *c, unsigned *num_charset_entries) const { TRACE_SANITIZE (this); if (unlikely (!c->check_struct (this))) @@ -586,9 +618,9 @@ struct Charset switch (format) { - case 0: return_trace (u.format0.sanitize (c, c->get_num_glyphs ())); - case 1: return_trace (u.format1.sanitize (c, c->get_num_glyphs ())); - case 2: return_trace (u.format2.sanitize (c, c->get_num_glyphs ())); + case 0: return_trace (u.format0.sanitize (c, c->get_num_glyphs (), num_charset_entries)); + case 1: return_trace (u.format1.sanitize (c, c->get_num_glyphs (), num_charset_entries)); + case 2: return_trace (u.format2.sanitize (c, c->get_num_glyphs (), num_charset_entries)); default:return_trace (false); } } @@ -606,10 +638,10 @@ struct Charset struct CFF1StringIndex : CFF1Index { bool serialize (hb_serialize_context_t *c, const CFF1StringIndex &strings, - const hb_inc_bimap_t &sidmap) + const hb_vector_t &sidmap) { TRACE_SERIALIZE (this); - if (unlikely ((strings.count == 0) || (sidmap.get_population () == 0))) + if (unlikely ((strings.count == 0) || (sidmap.length == 0))) { if (unlikely (!c->extend_min (this->count))) return_trace (false); @@ -617,15 +649,13 @@ struct CFF1StringIndex : CFF1Index return_trace (true); } - byte_str_array_t bytesArray; - if (!bytesArray.resize (sidmap.get_population ())) - return_trace (false); - for (unsigned int i = 0; i < strings.count; i++) - { - hb_codepoint_t j = sidmap[i]; - if (j != HB_MAP_VALUE_INVALID) - bytesArray[j] = strings[i]; - } + if (unlikely (sidmap.in_error ())) return_trace (false); + + // Save this in a vector since serialize() iterates it twice. + hb_vector_t bytesArray (+ hb_iter (sidmap) + | hb_map (strings)); + + if (unlikely (bytesArray.in_error ())) return_trace (false); bool result = CFF1Index::serialize (c, bytesArray); return_trace (result); @@ -932,7 +962,7 @@ struct cff1_private_dict_opset_t : dict_opset_t } }; -struct cff1_private_dict_opset_subset : dict_opset_t +struct cff1_private_dict_opset_subset_t : dict_opset_t { static void process_op (op_code_t op, num_interp_env_t& env, cff1_private_dict_values_subset_t& dictval) { @@ -978,7 +1008,7 @@ typedef dict_interpreter_t cff1_font_dict_interpreter_t; typedef CFF1Index CFF1NameIndex; -typedef CFF1IndexOf CFF1TopDictIndex; +typedef CFF1Index CFF1TopDictIndex; struct cff1_font_dict_values_mod_t { @@ -1031,8 +1061,12 @@ struct cff1 template struct accelerator_templ_t { - void init (hb_face_t *face) + static constexpr hb_tag_t tableTag = cff1::tableTag; + + accelerator_templ_t (hb_face_t *face) { + if (!face) return; + topDict.init (); fontDicts.init (); privateDicts.init (); @@ -1046,22 +1080,22 @@ struct cff1 const OT::cff1 *cff = this->blob->template as (); if (cff == &Null (OT::cff1)) - { fini (); return; } + goto fail; nameIndex = &cff->nameIndex (cff); if ((nameIndex == &Null (CFF1NameIndex)) || !nameIndex->sanitize (&sc)) - { fini (); return; } + goto fail; topDictIndex = &StructAtOffset (nameIndex, nameIndex->get_size ()); if ((topDictIndex == &Null (CFF1TopDictIndex)) || !topDictIndex->sanitize (&sc) || (topDictIndex->count == 0)) - { fini (); return; } + goto fail; { /* parse top dict */ const hb_ubytes_t topDictStr = (*topDictIndex)[0]; - if (unlikely (!topDictStr.sanitize (&sc))) { fini (); return; } + if (unlikely (!topDictStr.sanitize (&sc))) goto fail; cff1_top_dict_interp_env_t env (topDictStr); cff1_top_dict_interpreter_t top_interp (env); - if (unlikely (!top_interp.interpret (topDict))) { fini (); return; } + if (unlikely (!top_interp.interpret (topDict))) goto fail; } if (is_predef_charset ()) @@ -1069,7 +1103,7 @@ struct cff1 else { charset = &StructAtOffsetOrNull (cff, topDict.CharsetOffset); - if (unlikely ((charset == &Null (Charset)) || !charset->sanitize (&sc))) { fini (); return; } + if (unlikely ((charset == &Null (Charset)) || !charset->sanitize (&sc, &num_charset_entries))) goto fail; } fdCount = 1; @@ -1079,7 +1113,7 @@ struct cff1 fdSelect = &StructAtOffsetOrNull (cff, topDict.FDSelectOffset); if (unlikely ((fdArray == &Null (CFF1FDArray)) || !fdArray->sanitize (&sc) || (fdSelect == &Null (CFF1FDSelect)) || !fdSelect->sanitize (&sc, fdArray->count))) - { fini (); return; } + goto fail; fdCount = fdArray->count; } @@ -1092,36 +1126,36 @@ struct cff1 encoding = &Null (Encoding); if (is_CID ()) { - if (unlikely (charset == &Null (Charset))) { fini (); return; } + if (unlikely (charset == &Null (Charset))) goto fail; } else { if (!is_predef_encoding ()) { encoding = &StructAtOffsetOrNull (cff, topDict.EncodingOffset); - if (unlikely ((encoding == &Null (Encoding)) || !encoding->sanitize (&sc))) { fini (); return; } + if (unlikely ((encoding == &Null (Encoding)) || !encoding->sanitize (&sc))) goto fail; } } stringIndex = &StructAtOffset (topDictIndex, topDictIndex->get_size ()); if ((stringIndex == &Null (CFF1StringIndex)) || !stringIndex->sanitize (&sc)) - { fini (); return; } + goto fail; globalSubrs = &StructAtOffset (stringIndex, stringIndex->get_size ()); if ((globalSubrs != &Null (CFF1Subrs)) && !globalSubrs->sanitize (&sc)) - { fini (); return; } + goto fail; charStrings = &StructAtOffsetOrNull (cff, topDict.charStringsOffset); if ((charStrings == &Null (CFF1CharStrings)) || unlikely (!charStrings->sanitize (&sc))) - { fini (); return; } + goto fail; num_glyphs = charStrings->count; if (num_glyphs != sc.get_num_glyphs ()) - { fini (); return; } + goto fail; if (unlikely (!privateDicts.resize (fdCount))) - { fini (); return; } + goto fail; for (unsigned int i = 0; i < fdCount; i++) privateDicts[i].init (); @@ -1131,27 +1165,27 @@ struct cff1 for (unsigned int i = 0; i < fdCount; i++) { hb_ubytes_t fontDictStr = (*fdArray)[i]; - if (unlikely (!fontDictStr.sanitize (&sc))) { fini (); return; } + if (unlikely (!fontDictStr.sanitize (&sc))) goto fail; cff1_font_dict_values_t *font; cff1_top_dict_interp_env_t env (fontDictStr); cff1_font_dict_interpreter_t font_interp (env); font = fontDicts.push (); - if (unlikely (fontDicts.in_error ())) { fini (); return; } + if (unlikely (fontDicts.in_error ())) goto fail; font->init (); - if (unlikely (!font_interp.interpret (*font))) { fini (); return; } + if (unlikely (!font_interp.interpret (*font))) goto fail; PRIVDICTVAL *priv = &privateDicts[i]; const hb_ubytes_t privDictStr = StructAtOffset (cff, font->privateDictInfo.offset).as_ubytes (font->privateDictInfo.size); - if (unlikely (!privDictStr.sanitize (&sc))) { fini (); return; } + if (unlikely (!privDictStr.sanitize (&sc))) goto fail; num_interp_env_t env2 (privDictStr); dict_interpreter_t priv_interp (env2); priv->init (); - if (unlikely (!priv_interp.interpret (*priv))) { fini (); return; } + if (unlikely (!priv_interp.interpret (*priv))) goto fail; priv->localSubrs = &StructAtOffsetOrNull (&privDictStr, priv->subrsOffset); if (priv->localSubrs != &Null (CFF1Subrs) && unlikely (!priv->localSubrs->sanitize (&sc))) - { fini (); return; } + goto fail; } } else /* non-CID */ @@ -1160,20 +1194,25 @@ struct cff1 PRIVDICTVAL *priv = &privateDicts[0]; const hb_ubytes_t privDictStr = StructAtOffset (cff, font->privateDictInfo.offset).as_ubytes (font->privateDictInfo.size); - if (unlikely (!privDictStr.sanitize (&sc))) { fini (); return; } + if (unlikely (!privDictStr.sanitize (&sc))) goto fail; num_interp_env_t env (privDictStr); dict_interpreter_t priv_interp (env); priv->init (); - if (unlikely (!priv_interp.interpret (*priv))) { fini (); return; } + if (unlikely (!priv_interp.interpret (*priv))) goto fail; priv->localSubrs = &StructAtOffsetOrNull (&privDictStr, priv->subrsOffset); if (priv->localSubrs != &Null (CFF1Subrs) && unlikely (!priv->localSubrs->sanitize (&sc))) - { fini (); return; } + goto fail; } - } - void fini () + return; + + fail: + _fini (); + } + ~accelerator_templ_t () { _fini (); } + void _fini () { sc.end_processing (); topDict.fini (); @@ -1183,6 +1222,8 @@ struct cff1 blob = nullptr; } + hb_blob_t *get_blob () const { return blob; } + bool is_valid () const { return blob; } bool is_CID () const { return topDict.is_CID (); } @@ -1203,13 +1244,14 @@ struct cff1 bool is_predef_encoding () const { return topDict.EncodingOffset <= ExpertEncoding; } - hb_codepoint_t glyph_to_code (hb_codepoint_t glyph) const + hb_codepoint_t glyph_to_code (hb_codepoint_t glyph, + code_pair_t *glyph_to_sid_cache = nullptr) const { if (encoding != &Null (Encoding)) return encoding->get_code (glyph); else { - hb_codepoint_t sid = glyph_to_sid (glyph); + hb_codepoint_t sid = glyph_to_sid (glyph, glyph_to_sid_cache); if (sid == 0) return 0; hb_codepoint_t code = 0; switch (topDict.EncodingOffset) @@ -1227,12 +1269,14 @@ struct cff1 } } - hb_map_t *create_glyph_to_sid_map () const + glyph_to_sid_map_t *create_glyph_to_sid_map () const { if (charset != &Null (Charset)) { - hb_map_t *mapping = hb_map_create (); - mapping->set (0, 0); + auto *mapping = (glyph_to_sid_map_t *) hb_malloc (sizeof (glyph_to_sid_map_t)); + if (unlikely (!mapping)) return nullptr; + mapping = new (mapping) glyph_to_sid_map_t (); + mapping->push (code_pair_t {0, 1}); charset->collect_glyph_to_sid_map (mapping, num_glyphs); return mapping; } @@ -1240,10 +1284,11 @@ struct cff1 return nullptr; } - hb_codepoint_t glyph_to_sid (hb_codepoint_t glyph) const + hb_codepoint_t glyph_to_sid (hb_codepoint_t glyph, + code_pair_t *cache = nullptr) const { if (charset != &Null (Charset)) - return charset->get_sid (glyph, num_glyphs); + return charset->get_sid (glyph, num_glyphs, cache); else { hb_codepoint_t sid = 0; @@ -1312,19 +1357,17 @@ struct cff1 hb_vector_t privateDicts; unsigned int num_glyphs = 0; + unsigned int num_charset_entries = 0; }; struct accelerator_t : accelerator_templ_t { - accelerator_t (hb_face_t *face) + accelerator_t (hb_face_t *face) : SUPER (face) { - SUPER::init (face); - glyph_names.set_relaxed (nullptr); if (!is_valid ()) return; if (is_CID ()) return; - } ~accelerator_t () { @@ -1334,8 +1377,6 @@ struct cff1 names->fini (); hb_free (names); } - - SUPER::fini (); } bool get_glyph_name (hb_codepoint_t glyph, @@ -1386,9 +1427,10 @@ struct cff1 /* TODO */ /* fill glyph names */ + code_pair_t glyph_to_sid_cache {0, HB_CODEPOINT_INVALID}; for (hb_codepoint_t gid = 0; gid < num_glyphs; gid++) { - hb_codepoint_t sid = glyph_to_sid (gid); + hb_codepoint_t sid = glyph_to_sid (gid, &glyph_to_sid_cache); gname_t gname; gname.sid = sid; if (sid < cff1_std_strings_length) @@ -1426,7 +1468,6 @@ struct cff1 HB_INTERNAL bool get_extents (hb_font_t *font, hb_codepoint_t glyph, hb_glyph_extents_t *extents) const; HB_INTERNAL bool paint_glyph (hb_font_t *font, hb_codepoint_t glyph, hb_paint_funcs_t *funcs, void *data, hb_color_t foreground) const; - HB_INTERNAL bool get_seac_components (hb_codepoint_t glyph, hb_codepoint_t *base, hb_codepoint_t *accent) const; HB_INTERNAL bool get_path (hb_font_t *font, hb_codepoint_t glyph, hb_draw_session_t &draw_session) const; private: @@ -1453,9 +1494,24 @@ struct cff1 typedef accelerator_templ_t SUPER; }; - struct accelerator_subset_t : accelerator_templ_t {}; + struct accelerator_subset_t : accelerator_templ_t + { + accelerator_subset_t (hb_face_t *face) : SUPER (face) {} + ~accelerator_subset_t () + { + if (cff_accelerator) + cff_subset_accelerator_t::destroy (cff_accelerator); + } - bool subset (hb_subset_context_t *c) const { return hb_subset_cff1 (c); } + HB_INTERNAL bool subset (hb_subset_context_t *c) const; + HB_INTERNAL bool serialize (hb_serialize_context_t *c, + struct cff1_subset_plan &plan) const; + HB_INTERNAL bool get_seac_components (hb_codepoint_t glyph, hb_codepoint_t *base, hb_codepoint_t *accent) const; + + mutable CFF::cff_subset_accelerator_t* cff_accelerator = nullptr; + + typedef accelerator_templ_t SUPER; + }; protected: HB_INTERNAL static hb_codepoint_t lookup_standard_encoding_for_code (hb_codepoint_t sid); @@ -1479,6 +1535,10 @@ struct cff1_accelerator_t : cff1::accelerator_t { cff1_accelerator_t (hb_face_t *face) : cff1::accelerator_t (face) {} }; +struct cff1_subset_accelerator_t : cff1::accelerator_subset_t { + cff1_subset_accelerator_t (hb_face_t *face) : cff1::accelerator_subset_t (face) {} +}; + } /* namespace OT */ #endif /* HB_OT_CFF1_TABLE_HH */ diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-cff2-table.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-cff2-table.hh index 2134d486603..af24bb9986f 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-ot-cff2-table.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-cff2-table.hh @@ -28,7 +28,7 @@ #define HB_OT_CFF2_TABLE_HH #include "hb-ot-cff-common.hh" -#include "hb-subset-cff2.hh" +#include "hb-subset-cff-common.hh" #include "hb-draw.hh" #include "hb-paint.hh" @@ -41,7 +41,6 @@ namespace CFF { #define HB_OT_TAG_CFF2 HB_TAG('C','F','F','2') typedef CFFIndex CFF2Index; -template struct CFF2IndexOf : CFFIndexOf {}; typedef CFF2Index CFF2CharStrings; typedef Subrs CFF2Subrs; @@ -391,8 +390,12 @@ struct cff2 template struct accelerator_templ_t { + static constexpr hb_tag_t tableTag = cff2::tableTag; + accelerator_templ_t (hb_face_t *face) { + if (!face) return; + topDict.init (); fontDicts.init (); privateDicts.init (); @@ -464,7 +467,6 @@ struct cff2 goto fail; } - return; fail: @@ -481,11 +483,13 @@ struct cff2 blob = nullptr; } - hb_map_t *create_glyph_to_sid_map () const + hb_vector_t *create_glyph_to_sid_map () const { return nullptr; } + hb_blob_t *get_blob () const { return blob; } + bool is_valid () const { return blob; } protected: @@ -518,9 +522,24 @@ struct cff2 HB_INTERNAL bool get_path (hb_font_t *font, hb_codepoint_t glyph, hb_draw_session_t &draw_session) const; }; - typedef accelerator_templ_t accelerator_subset_t; + struct accelerator_subset_t : accelerator_templ_t + { + accelerator_subset_t (hb_face_t *face) : SUPER (face) {} + ~accelerator_subset_t () + { + if (cff_accelerator) + cff_subset_accelerator_t::destroy (cff_accelerator); + } - bool subset (hb_subset_context_t *c) const { return hb_subset_cff2 (c); } + HB_INTERNAL bool subset (hb_subset_context_t *c) const; + HB_INTERNAL bool serialize (hb_serialize_context_t *c, + struct cff2_subset_plan &plan, + hb_array_t normalized_coords) const; + + mutable CFF::cff_subset_accelerator_t* cff_accelerator = nullptr; + + typedef accelerator_templ_t SUPER; + }; public: FixedVersion version; /* Version of CFF2 table. set to 0x0200u */ @@ -535,6 +554,10 @@ struct cff2_accelerator_t : cff2::accelerator_t { cff2_accelerator_t (hb_face_t *face) : cff2::accelerator_t (face) {} }; +struct cff2_subset_accelerator_t : cff2::accelerator_subset_t { + cff2_subset_accelerator_t (hb_face_t *face) : cff2::accelerator_subset_t (face) {} +}; + } /* namespace OT */ #endif /* HB_OT_CFF2_TABLE_HH */ diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-cmap-table.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-cmap-table.hh index cf5ccd53e95..30401b1926e 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-ot-cmap-table.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-cmap-table.hh @@ -277,10 +277,10 @@ struct CmapSubtableFormat4 } } writer(c); - writer.end_code_ = c->allocate_size (HBUINT16::static_size * segcount); - c->allocate_size (2); // padding - writer.start_code_ = c->allocate_size (HBUINT16::static_size * segcount); - writer.id_delta_ = c->allocate_size (HBINT16::static_size * segcount); + writer.end_code_ = c->allocate_size (HBUINT16::static_size * segcount, false); + (void) c->allocate_size (2); // padding + writer.start_code_ = c->allocate_size (HBUINT16::static_size * segcount, false); + writer.id_delta_ = c->allocate_size (HBINT16::static_size * segcount, false); if (unlikely (!writer.end_code_ || !writer.start_code_ || !writer.id_delta_)) return false; @@ -325,7 +325,7 @@ struct CmapSubtableFormat4 { auto format4_iter = + it - | hb_filter ([&] (const hb_pair_t _) + | hb_filter ([&] (const hb_codepoint_pair_t _) { return _.first <= 0xFFFF; }) ; @@ -335,7 +335,7 @@ struct CmapSubtableFormat4 if (unlikely (!c->extend_min (this))) return; this->format = 4; - hb_vector_t> cp_to_gid { + hb_vector_t cp_to_gid { format4_iter }; @@ -757,8 +757,7 @@ struct CmapSubtableLongSegmented hb_codepoint_t gid = this->groups[i].glyphID; if (!gid) { - /* Intention is: if (hb_is_same (T, CmapSubtableFormat13)) continue; */ - if (! T::group_get_glyph (this->groups[i], end)) continue; + if (T::formatNumber == 13) continue; start++; gid++; } @@ -766,11 +765,13 @@ struct CmapSubtableLongSegmented if (unlikely ((unsigned int) (gid + end - start) >= num_glyphs)) end = start + (hb_codepoint_t) num_glyphs - gid; + mapping->alloc (mapping->get_population () + end - start + 1); + for (unsigned cp = start; cp <= end; cp++) { unicodes->add (cp); mapping->set (cp, gid); - gid++; + gid += T::increment; } } } @@ -794,6 +795,9 @@ struct CmapSubtableLongSegmented struct CmapSubtableFormat12 : CmapSubtableLongSegmented { + static constexpr int increment = 1; + static constexpr int formatNumber = 12; + static hb_codepoint_t group_get_glyph (const CmapSubtableLongGroup &group, hb_codepoint_t u) { return likely (group.startCharCode <= group.endCharCode) ? @@ -866,6 +870,9 @@ struct CmapSubtableFormat12 : CmapSubtableLongSegmented struct CmapSubtableFormat13 : CmapSubtableLongSegmented { + static constexpr int increment = 0; + static constexpr int formatNumber = 13; + static hb_codepoint_t group_get_glyph (const CmapSubtableLongGroup &group, hb_codepoint_t u HB_UNUSED) { return group.glyphID; } @@ -917,8 +924,7 @@ struct DefaultUVS : SortedArray32Of DefaultUVS* copy (hb_serialize_context_t *c, const hb_set_t *unicodes) const { - DefaultUVS *out = c->start_embed (); - if (unlikely (!out)) return nullptr; + auto *out = c->start_embed (); auto snap = c->snapshot (); HBUINT32 len; @@ -931,8 +937,7 @@ struct DefaultUVS : SortedArray32Of hb_codepoint_t start = HB_SET_VALUE_INVALID; hb_codepoint_t end = HB_SET_VALUE_INVALID; - for (hb_codepoint_t u = HB_SET_VALUE_INVALID; - unicodes->next (&u);) + for (auto u : *unicodes) { if (!as_array ().bsearch (u)) continue; @@ -1067,9 +1072,7 @@ struct NonDefaultUVS : SortedArray32Of const hb_set_t *glyphs_requested, const hb_map_t *glyph_map) const { - NonDefaultUVS *out = c->start_embed (); - if (unlikely (!out)) return nullptr; - + auto *out = c->start_embed (); auto it = + as_array () | hb_filter ([&] (const UVSMapping& _) @@ -1767,7 +1770,6 @@ struct cmap TRACE_SUBSET (this); cmap *cmap_prime = c->serializer->start_embed (); - if (unlikely (!c->serializer->check_success (cmap_prime))) return_trace (false); auto encodingrec_iter = + hb_iter (encodingRecord) @@ -1798,7 +1800,7 @@ struct cmap auto it = + c->plan->unicode_to_new_gid_list.iter () - | hb_filter ([&] (const hb_pair_t _) + | hb_filter ([&] (const hb_codepoint_pair_t _) { return (_.second != HB_MAP_VALUE_INVALID); }) ; diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-font.cc b/src/3rdparty/harfbuzz-ng/src/hb-ot-font.cc index c89a1954a98..b3677c6a4c0 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-ot-font.cc +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-font.cc @@ -38,8 +38,8 @@ #include "hb-ot-cmap-table.hh" #include "hb-ot-glyf-table.hh" -#include "hb-ot-cff1-table.hh" #include "hb-ot-cff2-table.hh" +#include "hb-ot-cff1-table.hh" #include "hb-ot-hmtx-table.hh" #include "hb-ot-post-table.hh" #include "hb-ot-stat-table.hh" // Just so we compile it; unused otherwise. @@ -98,7 +98,7 @@ _hb_ot_font_create (hb_font_t *font) { cmap_cache = (hb_ot_font_cmap_cache_t *) hb_malloc (sizeof (hb_ot_font_cmap_cache_t)); if (unlikely (!cmap_cache)) goto out; - cmap_cache->init (); + new (cmap_cache) hb_ot_font_cmap_cache_t (); if (unlikely (!hb_face_set_user_data (font->face, &hb_ot_font_cmap_cache_user_data_key, cmap_cache, @@ -230,8 +230,8 @@ hb_ot_get_glyph_h_advances (hb_font_t* font, void* font_data, use_cache = false; goto out; } + new (cache) hb_ot_font_advance_cache_t; - cache->init (); if (unlikely (!ot_font->advance_cache.cmpexch (nullptr, cache))) { hb_free (cache); @@ -255,7 +255,7 @@ hb_ot_get_glyph_h_advances (hb_font_t* font, void* font_data, { /* Use cache. */ if (ot_font->cached_coords_serial.get_acquire () != (int) font->serial_coords) { - ot_font->advance_cache->init (); + ot_font->advance_cache->clear (); ot_font->cached_coords_serial.set_release (font->serial_coords); } @@ -436,8 +436,8 @@ hb_ot_get_glyph_extents (hb_font_t *font, #endif if (ot_face->glyf->get_extents (font, glyph, extents)) return true; #ifndef HB_NO_OT_FONT_CFF - if (ot_face->cff1->get_extents (font, glyph, extents)) return true; if (ot_face->cff2->get_extents (font, glyph, extents)) return true; + if (ot_face->cff1->get_extents (font, glyph, extents)) return true; #endif return false; @@ -525,8 +525,8 @@ hb_ot_draw_glyph (hb_font_t *font, embolden ? &outline : draw_data, font->slant_xy); if (!font->face->table.glyf->get_path (font, glyph, draw_session)) #ifndef HB_NO_CFF - if (!font->face->table.cff1->get_path (font, glyph, draw_session)) if (!font->face->table.cff2->get_path (font, glyph, draw_session)) + if (!font->face->table.cff1->get_path (font, glyph, draw_session)) #endif {} } @@ -565,8 +565,8 @@ hb_ot_paint_glyph (hb_font_t *font, #endif if (font->face->table.glyf->paint_glyph (font, glyph, paint_funcs, paint_data, foreground)) return; #ifndef HB_NO_CFF - if (font->face->table.cff1->paint_glyph (font, glyph, paint_funcs, paint_data, foreground)) return; if (font->face->table.cff2->paint_glyph (font, glyph, paint_funcs, paint_data, foreground)) return; + if (font->face->table.cff1->paint_glyph (font, glyph, paint_funcs, paint_data, foreground)) return; #endif } #endif diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-hdmx-table.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-hdmx-table.hh index 3bfd75502a4..cbcf6f5f22f 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-ot-hdmx-table.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-hdmx-table.hh @@ -46,21 +46,23 @@ struct DeviceRecord template - bool serialize (hb_serialize_context_t *c, unsigned pixelSize, Iterator it) + bool serialize (hb_serialize_context_t *c, + unsigned pixelSize, + Iterator it, + const hb_vector_t new_to_old_gid_list, + unsigned num_glyphs) { TRACE_SERIALIZE (this); - unsigned length = it.len (); - - if (unlikely (!c->extend (this, length))) return_trace (false); + if (unlikely (!c->extend (this, num_glyphs))) return_trace (false); this->pixelSize = pixelSize; this->maxWidth = + it | hb_reduce (hb_max, 0u); - + it - | hb_sink (widthsZ.as_array (length)); + for (auto &_ : new_to_old_gid_list) + widthsZ[_.first] = *it++; return_trace (true); } @@ -89,7 +91,11 @@ struct hdmx template - bool serialize (hb_serialize_context_t *c, unsigned version, Iterator it) + bool serialize (hb_serialize_context_t *c, + unsigned version, + Iterator it, + const hb_vector_t &new_to_old_gid_list, + unsigned num_glyphs) { TRACE_SERIALIZE (this); @@ -97,10 +103,10 @@ struct hdmx this->version = version; this->numRecords = it.len (); - this->sizeDeviceRecord = DeviceRecord::get_size (it ? (*it).second.len () : 0); + this->sizeDeviceRecord = DeviceRecord::get_size (num_glyphs); for (const hb_item_type& _ : +it) - c->start_embed ()->serialize (c, _.first, _.second); + c->start_embed ()->serialize (c, _.first, _.second, new_to_old_gid_list, num_glyphs); return_trace (c->successful ()); } @@ -110,31 +116,30 @@ struct hdmx { TRACE_SUBSET (this); - hdmx *hdmx_prime = c->serializer->start_embed (); - if (unlikely (!hdmx_prime)) return_trace (false); + auto *hdmx_prime = c->serializer->start_embed (); + unsigned num_input_glyphs = get_num_glyphs (); auto it = + hb_range ((unsigned) numRecords) - | hb_map ([c, this] (unsigned _) + | hb_map ([c, num_input_glyphs, this] (unsigned _) { const DeviceRecord *device_record = &StructAtOffset (&firstDeviceRecord, _ * sizeDeviceRecord); auto row = - + hb_range (c->plan->num_output_glyphs ()) - | hb_map (c->plan->reverse_glyph_map) - | hb_map ([this, c, device_record] (hb_codepoint_t _) + + hb_iter (c->plan->new_to_old_gid_list) + | hb_map ([num_input_glyphs, device_record] (hb_codepoint_pair_t _) { - if (c->plan->is_empty_glyph (_)) - return Null (HBUINT8); - return device_record->widthsZ.as_array (get_num_glyphs ()) [_]; + return device_record->widthsZ.as_array (num_input_glyphs) [_.second]; }) ; return hb_pair ((unsigned) device_record->pixelSize, +row); }) ; - hdmx_prime->serialize (c->serializer, version, it); + hdmx_prime->serialize (c->serializer, version, it, + c->plan->new_to_old_gid_list, + c->plan->num_output_glyphs ()); return_trace (true); } diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-hmtx-table.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-hmtx-table.hh index 835a1a585e8..89640b43f15 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-ot-hmtx-table.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-hmtx-table.hh @@ -83,7 +83,7 @@ struct hmtxvmtx bool subset_update_header (hb_subset_context_t *c, unsigned int num_hmetrics, const hb_hashmap_t> *mtx_map, - const hb_map_t *bounds_map) const + const hb_vector_t &bounds_vec) const { hb_blob_t *src_blob = hb_sanitize_context_t ().reference_table (c->plan->source, H::tableTag); hb_blob_t *dest_blob = hb_blob_copy_writable_or_fail (src_blob); @@ -114,6 +114,7 @@ struct hmtxvmtx HB_ADD_MVAR_VAR (HB_OT_METRICS_TAG_VERTICAL_CARET_OFFSET, caretOffset); } + bool empty = true; int min_lsb = 0x7FFF; int min_rsb = 0x7FFF; int max_extent = -0x7FFF; @@ -125,9 +126,10 @@ struct hmtxvmtx int lsb = _.second.second; max_adv = hb_max (max_adv, adv); - if (bounds_map->has (gid)) + if (bounds_vec[gid] != 0xFFFFFFFF) { - unsigned bound_width = bounds_map->get (gid); + empty = false; + unsigned bound_width = bounds_vec[gid]; int rsb = adv - lsb - bound_width; int extent = lsb + bound_width; min_lsb = hb_min (min_lsb, lsb); @@ -137,7 +139,7 @@ struct hmtxvmtx } table->advanceMax = max_adv; - if (!bounds_map->is_empty ()) + if (!empty) { table->minLeadingBearing = min_lsb; table->minTrailingBearing = min_rsb; @@ -156,32 +158,32 @@ struct hmtxvmtx hb_requires (hb_is_iterator (Iterator))> void serialize (hb_serialize_context_t *c, Iterator it, - unsigned num_long_metrics) + const hb_vector_t new_to_old_gid_list, + unsigned num_long_metrics, + unsigned total_num_metrics) { - unsigned idx = 0; - for (auto _ : it) + LongMetric* long_metrics = c->allocate_size (num_long_metrics * LongMetric::static_size); + FWORD* short_metrics = c->allocate_size ((total_num_metrics - num_long_metrics) * FWORD::static_size); + if (!long_metrics || !short_metrics) return; + + short_metrics -= num_long_metrics; + + for (auto _ : new_to_old_gid_list) { - if (idx < num_long_metrics) + hb_codepoint_t gid = _.first; + auto mtx = *it++; + + if (gid < num_long_metrics) { - LongMetric lm; - lm.advance = _.first; - lm.sb = _.second; - if (unlikely (!c->embed (&lm))) return; - } - else if (idx < 0x10000u) - { - FWORD *sb = c->allocate_size (FWORD::static_size); - if (unlikely (!sb)) return; - *sb = _.second; + LongMetric& lm = long_metrics[gid]; + lm.advance = mtx.first; + lm.sb = mtx.second; } + // TODO(beyond-64k): This assumes that maxp.numGlyphs is 0xFFFF. + else if (gid < 0x10000u) + short_metrics[gid] = mtx.second; else - { - // TODO: This does not do tail optimization. - UFWORD *adv = c->allocate_size (UFWORD::static_size); - if (unlikely (!adv)) return; - *adv = _.first; - } - idx++; + ((UFWORD*) short_metrics)[gid] = mtx.first; } } @@ -189,8 +191,7 @@ struct hmtxvmtx { TRACE_SUBSET (this); - T *table_prime = c->serializer->start_embed (); - if (unlikely (!table_prime)) return_trace (false); + auto *table_prime = c->serializer->start_embed (); accelerator_t _mtx (c->plan->source); unsigned num_long_metrics; @@ -199,6 +200,8 @@ struct hmtxvmtx /* Determine num_long_metrics to encode. */ auto& plan = c->plan; + // TODO Don't consider retaingid holes here. + num_long_metrics = hb_min (plan->num_output_glyphs (), 0xFFFFu); unsigned int last_advance = get_new_gid_advance_unscaled (plan, mtx_map, num_long_metrics - 1, _mtx); while (num_long_metrics > 1 && @@ -209,31 +212,36 @@ struct hmtxvmtx } auto it = - + hb_range (c->plan->num_output_glyphs ()) - | hb_map ([c, &_mtx, mtx_map] (unsigned _) + + hb_iter (c->plan->new_to_old_gid_list) + | hb_map ([c, &_mtx, mtx_map] (hb_codepoint_pair_t _) { - if (!mtx_map->has (_)) + hb_codepoint_t new_gid = _.first; + hb_codepoint_t old_gid = _.second; + + hb_pair_t *v = nullptr; + if (!mtx_map->has (new_gid, &v)) { - hb_codepoint_t old_gid; - if (!c->plan->old_gid_for_new_gid (_, &old_gid)) - return hb_pair (0u, 0); int lsb = 0; if (!_mtx.get_leading_bearing_without_var_unscaled (old_gid, &lsb)) (void) _glyf_get_leading_bearing_without_var_unscaled (c->plan->source, old_gid, !T::is_horizontal, &lsb); return hb_pair (_mtx.get_advance_without_var_unscaled (old_gid), +lsb); } - return mtx_map->get (_); + return *v; }) ; - table_prime->serialize (c->serializer, it, num_long_metrics); + table_prime->serialize (c->serializer, + it, + c->plan->new_to_old_gid_list, + num_long_metrics, + c->plan->num_output_glyphs ()); if (unlikely (c->serializer->in_error ())) return_trace (false); // Amend header num hmetrics if (unlikely (!subset_update_header (c, num_long_metrics, mtx_map, - T::is_horizontal ? &c->plan->bounds_width_map : &c->plan->bounds_height_map))) + T::is_horizontal ? c->plan->bounds_width_vec : c->plan->bounds_height_vec))) return_trace (false); return_trace (true); diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-base-table.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-base-table.hh index 8179e5acd52..2b7e9e4b184 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-base-table.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-base-table.hh @@ -170,8 +170,8 @@ struct FeatMinMaxRecord { TRACE_SANITIZE (this); return_trace (likely (c->check_struct (this) && - minCoord.sanitize (c, this) && - maxCoord.sanitize (c, this))); + minCoord.sanitize (c, base) && + maxCoord.sanitize (c, base))); } protected: @@ -187,7 +187,6 @@ struct FeatMinMaxRecord * of MinMax table (may be NULL) */ public: DEFINE_SIZE_STATIC (8); - }; struct MinMax @@ -274,7 +273,7 @@ struct BaseLangSysRecord { TRACE_SANITIZE (this); return_trace (likely (c->check_struct (this) && - minMax.sanitize (c, this))); + minMax.sanitize (c, base))); } protected: @@ -297,7 +296,8 @@ struct BaseScript const BaseCoord &get_base_coord (int baseline_tag_index) const { return (this+baseValues).get_base_coord (baseline_tag_index); } - bool has_data () const { return baseValues; } + bool has_values () const { return baseValues; } + bool has_min_max () const { return defaultMinMax; /* TODO What if only per-language is present? */ } bool sanitize (hb_sanitize_context_t *c) const { @@ -383,7 +383,7 @@ struct Axis const BaseCoord **coord) const { const BaseScript &base_script = (this+baseScriptList).get_base_script (script_tag); - if (!base_script.has_data ()) + if (!base_script.has_values ()) { *coord = nullptr; return false; @@ -410,7 +410,7 @@ struct Axis const BaseCoord **max_coord) const { const BaseScript &base_script = (this+baseScriptList).get_base_script (script_tag); - if (!base_script.has_data ()) + if (!base_script.has_min_max ()) { *min_coord = *max_coord = nullptr; return false; @@ -425,8 +425,8 @@ struct Axis { TRACE_SANITIZE (this); return_trace (likely (c->check_struct (this) && - (this+baseTagList).sanitize (c) && - (this+baseScriptList).sanitize (c))); + baseTagList.sanitize (c, this) && + baseScriptList.sanitize (c, this))); } protected: @@ -473,14 +473,13 @@ struct BASE return true; } - /* TODO: Expose this separately sometime? */ bool get_min_max (hb_font_t *font, hb_direction_t direction, hb_tag_t script_tag, hb_tag_t language_tag, hb_tag_t feature_tag, hb_position_t *min, - hb_position_t *max) + hb_position_t *max) const { const BaseCoord *min_coord, *max_coord; if (!get_axis (direction).get_min_max (script_tag, language_tag, feature_tag, diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-common.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-common.hh index 36f123b559b..0831e4499e1 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-common.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-common.hh @@ -55,19 +55,22 @@ static bool ClassDef_remap_and_serialize ( hb_serialize_context_t *c, const hb_set_t &klasses, bool use_class_zero, - hb_sorted_vector_t> &glyph_and_klass, /* IN/OUT */ + hb_sorted_vector_t &glyph_and_klass, /* IN/OUT */ hb_map_t *klass_map /*IN/OUT*/); struct hb_collect_feature_substitutes_with_var_context_t { const hb_map_t *axes_index_tag_map; - const hb_hashmap_t *axes_location; + const hb_hashmap_t *axes_location; hb_hashmap_t> *record_cond_idx_map; hb_hashmap_t *feature_substitutes_map; + bool& insert_catch_all_feature_variation_record; // not stored in subset_plan hb_set_t *feature_indices; bool apply; + bool variation_applied; + bool universal; unsigned cur_record_idx; hb_hashmap_t, unsigned> *conditionset_map; }; @@ -807,7 +810,7 @@ struct Feature { TRACE_SUBSET (this); auto *out = c->serializer->start_embed (*this); - if (unlikely (!out || !c->serializer->extend_min (out))) return_trace (false); + if (unlikely (!c->serializer->extend_min (out))) return_trace (false); out->featureParams.serialize_subset (c, featureParams, this, tag); @@ -981,7 +984,7 @@ struct RecordListOfFeature : RecordListOf { TRACE_SUBSET (this); auto *out = c->serializer->start_embed (*this); - if (unlikely (!out || !c->serializer->extend_min (out))) return_trace (false); + if (unlikely (!c->serializer->extend_min (out))) return_trace (false); + hb_enumerate (*this) | hb_filter (l->feature_index_map, hb_first) @@ -1078,7 +1081,7 @@ struct LangSys { TRACE_SUBSET (this); auto *out = c->serializer->start_embed (*this); - if (unlikely (!out || !c->serializer->extend_min (out))) return_trace (false); + if (unlikely (!c->serializer->extend_min (out))) return_trace (false); const uint32_t *v; out->reqFeatureIndex = l->feature_index_map->has (reqFeatureIndex, &v) ? *v : 0xFFFFu; @@ -1188,7 +1191,7 @@ struct Script return false; auto *out = c->serializer->start_embed (*this); - if (unlikely (!out || !c->serializer->extend_min (out))) return_trace (false); + if (unlikely (!c->serializer->extend_min (out))) return_trace (false); bool defaultLang = false; if (has_default_lang_sys ()) @@ -1247,7 +1250,7 @@ struct RecordListOfScript : RecordListOf