mirror of
https://github.com/PCSX2/pcsx2.git
synced 2026-01-31 01:15:24 +01:00
Compare commits
62 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e971a9ebf5 | ||
|
|
19f85713ce | ||
|
|
4c41de6013 | ||
|
|
96f9cde1bc | ||
|
|
3feef0824c | ||
|
|
5f2ab55c93 | ||
|
|
0f75bfe17d | ||
|
|
7faa132622 | ||
|
|
b69e6da105 | ||
|
|
11edb128e9 | ||
|
|
fc4407aaef | ||
|
|
2a418e3282 | ||
|
|
59415542ff | ||
|
|
00416e26bb | ||
|
|
e936398e17 | ||
|
|
e3b45c3efd | ||
|
|
7ad759007a | ||
|
|
2fab554360 | ||
|
|
e98b6e6cb3 | ||
|
|
aa5147a52b | ||
|
|
83ebbe95c5 | ||
|
|
2ad71d046b | ||
|
|
099e1f900d | ||
|
|
0c6537e917 | ||
|
|
8937fb3d11 | ||
|
|
028085f8f9 | ||
|
|
b33932f47b | ||
|
|
d122939183 | ||
|
|
b09eb4e42d | ||
|
|
e75ddb878a | ||
|
|
6e3dca5a1a | ||
|
|
b069f51e6f | ||
|
|
bb1e6d06e4 | ||
|
|
f747abcc3b | ||
|
|
77738f72b4 | ||
|
|
61f11d12ff | ||
|
|
7e00b2c9a9 | ||
|
|
7dd4ab947b | ||
|
|
be213695a0 | ||
|
|
cde548a2f9 | ||
|
|
e76481f454 | ||
|
|
1a8d1d443e | ||
|
|
a14c8eb7d5 | ||
|
|
97ea52a6c1 | ||
|
|
0617182dfc | ||
|
|
bd99d76416 | ||
|
|
fdbe9305a9 | ||
|
|
fd772e42da | ||
|
|
df56797b38 | ||
|
|
28e72110bb | ||
|
|
e451c5f70c | ||
|
|
20b8fef950 | ||
|
|
47449a424d | ||
|
|
e8ab761be4 | ||
|
|
6463fc541b | ||
|
|
08b3194b96 | ||
|
|
62fa768e60 | ||
|
|
cafe7a9dc2 | ||
|
|
7ffc671c3a | ||
|
|
eaeea83547 | ||
|
|
76b758dbd2 | ||
|
|
ab19b109ce |
6
.github/workflows/macos_build.yml
vendored
6
.github/workflows/macos_build.yml
vendored
@@ -12,7 +12,7 @@ on:
|
||||
os:
|
||||
required: false
|
||||
type: string
|
||||
default: macos-14
|
||||
default: macos-15
|
||||
patchesUrl:
|
||||
required: false
|
||||
type: string
|
||||
@@ -62,8 +62,8 @@ jobs:
|
||||
echo "#define DEFAULT_UPDATER_CHANNEL \"stable\"" > ./pcsx2-qt/DefaultUpdaterChannel.h
|
||||
cat ./pcsx2-qt/DefaultUpdaterChannel.h
|
||||
|
||||
- name: Use Xcode 15.2
|
||||
run: sudo xcode-select -s /Applications/Xcode_15.2.app
|
||||
- name: Use Xcode 16.4
|
||||
run: sudo xcode-select -s /Applications/Xcode_16.4.app
|
||||
|
||||
- name: Prepare Artifact Metadata
|
||||
id: artifact-metadata
|
||||
|
||||
@@ -9,6 +9,5 @@ set -e
|
||||
"$SCRIPTDIR/../../../../tools/retry.sh" sudo apt-get -y install qt6-l10n-tools python3
|
||||
|
||||
"$SCRIPTDIR/../../../../tools/generate_fullscreen_ui_translation_strings.py"
|
||||
"$SCRIPTDIR/../../../../pcsx2-qt/Translations/update_glyph_ranges.py"
|
||||
"$SCRIPTDIR/../../../../tools/generate_update_fa_glyph_ranges.py"
|
||||
PATH=/usr/lib/qt6/bin:$PATH "$SCRIPTDIR/../../../../pcsx2-qt/Translations/update_base_translation.sh"
|
||||
|
||||
@@ -68,7 +68,7 @@ if [ ! -f "$LINUXDEPLOY_PLUGIN_QT" ]; then
|
||||
fi
|
||||
|
||||
if [ ! -f "$APPIMAGETOOL" ]; then
|
||||
"$PCSX2DIR/tools/retry.sh" wget -O "$APPIMAGETOOL" https://github.com/AppImage/AppImageKit/releases/download/continuous/appimagetool-x86_64.AppImage
|
||||
"$PCSX2DIR/tools/retry.sh" wget -O "$APPIMAGETOOL" https://github.com/AppImage/appimagetool/releases/download/continuous/appimagetool-x86_64.AppImage
|
||||
chmod +x "$APPIMAGETOOL"
|
||||
fi
|
||||
|
||||
|
||||
@@ -15,10 +15,10 @@ if [ "${INSTALLDIR:0:1}" != "/" ]; then
|
||||
fi
|
||||
|
||||
LIBBACKTRACE=ad106d5fdd5d960bd33fae1c48a351af567fd075
|
||||
LIBJPEGTURBO=3.1.0
|
||||
LIBPNG=1.6.48
|
||||
LIBJPEGTURBO=3.1.1
|
||||
LIBPNG=1.6.50
|
||||
LIBWEBP=1.5.0
|
||||
SDL=SDL3-3.2.16
|
||||
SDL=SDL3-3.2.18
|
||||
QT=6.9.1
|
||||
LZ4=1.10.0
|
||||
ZSTD=1.5.7
|
||||
@@ -36,10 +36,10 @@ cd deps-build
|
||||
|
||||
cat > SHASUMS <<EOF
|
||||
fd6f417fe9e3a071cf1424a5152d926a34c4a3c5070745470be6cf12a404ed79 $LIBBACKTRACE.zip
|
||||
9564c72b1dfd1d6fe6274c5f95a8d989b59854575d4bbee44ade7bc17aa9bc93 libjpeg-turbo-$LIBJPEGTURBO.tar.gz
|
||||
46fd06ff37db1db64c0dc288d78a3f5efd23ad9ac41561193f983e20937ece03 libpng-$LIBPNG.tar.xz
|
||||
aadc97ea91f6ef078b0ae3a62bba69e008d9a7db19b34e4ac973b19b71b4217c libjpeg-turbo-$LIBJPEGTURBO.tar.gz
|
||||
4df396518620a7aa3651443e87d1b2862e4e88cad135a8b93423e01706232307 libpng-$LIBPNG.tar.xz
|
||||
7d6fab70cf844bf6769077bd5d7a74893f8ffd4dfb42861745750c63c2a5c92c libwebp-$LIBWEBP.tar.gz
|
||||
6340e58879b2d15830c8460d2f589a385c444d1faa2a4828a9626c7322562be8 $SDL.tar.gz
|
||||
1a775bde924397a8e0c08bfda198926c17be859d0288ad0dec1dea1b2ee04f8f $SDL.tar.gz
|
||||
537512904744b35e232912055ccf8ec66d768639ff3abe5788d90d792ec5f48b lz4-$LZ4.tar.gz
|
||||
eb33e51f49a15e023950cd7825ca74a4a2b43db8354825ac24fc1b7ee09e6fa3 zstd-$ZSTD.tar.gz
|
||||
40caedbf83cc9a1959610830563565889878bc95f115868bbf545d1914acf28e qtbase-everywhere-src-$QT.tar.xz
|
||||
|
||||
@@ -14,8 +14,8 @@
|
||||
"sources": [
|
||||
{
|
||||
"type": "archive",
|
||||
"url": "https://libsdl.org/release/SDL3-3.2.16.tar.gz",
|
||||
"sha256": "6340e58879b2d15830c8460d2f589a385c444d1faa2a4828a9626c7322562be8"
|
||||
"url": "https://libsdl.org/release/SDL3-3.2.18.tar.gz",
|
||||
"sha256": "1a775bde924397a8e0c08bfda198926c17be859d0288ad0dec1dea1b2ee04f8f"
|
||||
}
|
||||
],
|
||||
"cleanup": [
|
||||
|
||||
@@ -40,11 +40,11 @@ fi
|
||||
|
||||
FREETYPE=2.13.3
|
||||
HARFBUZZ=11.2.0
|
||||
SDL=SDL3-3.2.16
|
||||
SDL=SDL3-3.2.18
|
||||
ZSTD=1.5.7
|
||||
LZ4=1.10.0
|
||||
LIBPNG=1.6.48
|
||||
LIBJPEGTURBO=3.1.0
|
||||
LIBPNG=1.6.50
|
||||
LIBJPEGTURBO=3.1.1
|
||||
LIBWEBP=1.5.0
|
||||
FFMPEG=6.0
|
||||
MOLTENVK=1.2.9
|
||||
@@ -79,12 +79,12 @@ CMAKE_ARCH_UNIVERSAL=-DCMAKE_OSX_ARCHITECTURES="x86_64;arm64"
|
||||
cat > SHASUMS <<EOF
|
||||
0550350666d427c74daeb85d5ac7bb353acba5f76956395995311a9c6f063289 freetype-$FREETYPE.tar.xz
|
||||
16c0204704f3ebeed057aba100fe7db18d71035505cb10e595ea33d346457fc8 harfbuzz-$HARFBUZZ.tar.gz
|
||||
6340e58879b2d15830c8460d2f589a385c444d1faa2a4828a9626c7322562be8 $SDL.tar.gz
|
||||
1a775bde924397a8e0c08bfda198926c17be859d0288ad0dec1dea1b2ee04f8f $SDL.tar.gz
|
||||
eb33e51f49a15e023950cd7825ca74a4a2b43db8354825ac24fc1b7ee09e6fa3 zstd-$ZSTD.tar.gz
|
||||
537512904744b35e232912055ccf8ec66d768639ff3abe5788d90d792ec5f48b lz4-$LZ4.tar.gz
|
||||
46fd06ff37db1db64c0dc288d78a3f5efd23ad9ac41561193f983e20937ece03 libpng-$LIBPNG.tar.xz
|
||||
4df396518620a7aa3651443e87d1b2862e4e88cad135a8b93423e01706232307 libpng-$LIBPNG.tar.xz
|
||||
7d6fab70cf844bf6769077bd5d7a74893f8ffd4dfb42861745750c63c2a5c92c libwebp-$LIBWEBP.tar.gz
|
||||
9564c72b1dfd1d6fe6274c5f95a8d989b59854575d4bbee44ade7bc17aa9bc93 libjpeg-turbo-$LIBJPEGTURBO.tar.gz
|
||||
aadc97ea91f6ef078b0ae3a62bba69e008d9a7db19b34e4ac973b19b71b4217c libjpeg-turbo-$LIBJPEGTURBO.tar.gz
|
||||
57be87c22d9b49c112b6d24bc67d42508660e6b718b3db89c44e47e289137082 ffmpeg-$FFMPEG.tar.xz
|
||||
f415a09385030c6510a936155ce211f617c31506db5fbc563e804345f1ecf56e v$MOLTENVK.tar.gz
|
||||
8ccbb9ab055205ac76632c9eeddd1ed6fc66936fc56afc2ed0fd5d9e23da3097 qtbase-everywhere-src-$QT.tar.xz
|
||||
|
||||
@@ -22,11 +22,11 @@ fi
|
||||
|
||||
FREETYPE=2.13.3
|
||||
HARFBUZZ=11.2.0
|
||||
SDL=SDL3-3.2.16
|
||||
SDL=SDL3-3.2.18
|
||||
ZSTD=1.5.7
|
||||
LZ4=1.10.0
|
||||
LIBPNG=1.6.48
|
||||
LIBJPEGTURBO=3.1.0
|
||||
LIBPNG=1.6.50
|
||||
LIBJPEGTURBO=3.1.1
|
||||
LIBWEBP=1.5.0
|
||||
FFMPEG=6.0
|
||||
MOLTENVK=1.2.9
|
||||
@@ -59,12 +59,12 @@ CMAKE_COMMON=(
|
||||
cat > SHASUMS <<EOF
|
||||
0550350666d427c74daeb85d5ac7bb353acba5f76956395995311a9c6f063289 freetype-$FREETYPE.tar.xz
|
||||
16c0204704f3ebeed057aba100fe7db18d71035505cb10e595ea33d346457fc8 harfbuzz-$HARFBUZZ.tar.gz
|
||||
6340e58879b2d15830c8460d2f589a385c444d1faa2a4828a9626c7322562be8 $SDL.tar.gz
|
||||
1a775bde924397a8e0c08bfda198926c17be859d0288ad0dec1dea1b2ee04f8f $SDL.tar.gz
|
||||
eb33e51f49a15e023950cd7825ca74a4a2b43db8354825ac24fc1b7ee09e6fa3 zstd-$ZSTD.tar.gz
|
||||
537512904744b35e232912055ccf8ec66d768639ff3abe5788d90d792ec5f48b lz4-$LZ4.tar.gz
|
||||
46fd06ff37db1db64c0dc288d78a3f5efd23ad9ac41561193f983e20937ece03 libpng-$LIBPNG.tar.xz
|
||||
4df396518620a7aa3651443e87d1b2862e4e88cad135a8b93423e01706232307 libpng-$LIBPNG.tar.xz
|
||||
7d6fab70cf844bf6769077bd5d7a74893f8ffd4dfb42861745750c63c2a5c92c libwebp-$LIBWEBP.tar.gz
|
||||
9564c72b1dfd1d6fe6274c5f95a8d989b59854575d4bbee44ade7bc17aa9bc93 libjpeg-turbo-$LIBJPEGTURBO.tar.gz
|
||||
aadc97ea91f6ef078b0ae3a62bba69e008d9a7db19b34e4ac973b19b71b4217c libjpeg-turbo-$LIBJPEGTURBO.tar.gz
|
||||
57be87c22d9b49c112b6d24bc67d42508660e6b718b3db89c44e47e289137082 ffmpeg-$FFMPEG.tar.xz
|
||||
f415a09385030c6510a936155ce211f617c31506db5fbc563e804345f1ecf56e v$MOLTENVK.tar.gz
|
||||
8ccbb9ab055205ac76632c9eeddd1ed6fc66936fc56afc2ed0fd5d9e23da3097 qtbase-everywhere-src-$QT.tar.xz
|
||||
|
||||
@@ -44,9 +44,9 @@ cd "%BUILDDIR%"
|
||||
|
||||
set FREETYPE=2.13.3
|
||||
set HARFBUZZ=11.2.0
|
||||
set LIBJPEGTURBO=3.1.0
|
||||
set LIBPNG=1648
|
||||
set SDL=SDL3-3.2.16
|
||||
set LIBJPEGTURBO=3.1.1
|
||||
set LIBPNG=1650
|
||||
set SDL=SDL3-3.2.18
|
||||
set QT=6.9.1
|
||||
set QTMINOR=6.9
|
||||
set LZ4=1.10.0
|
||||
@@ -65,10 +65,10 @@ set SHADERC_SPIRVTOOLS=33e02568181e3312f49a3cf33df470bf96ef293a
|
||||
|
||||
call :downloadfile "freetype-%FREETYPE%.tar.gz" https://sourceforge.net/projects/freetype/files/freetype2/%FREETYPE%/freetype-%FREETYPE%.tar.gz/download 5c3a8e78f7b24c20b25b54ee575d6daa40007a5f4eea2845861c3409b3021747 || goto error
|
||||
call :downloadfile "harfbuzz-%HARFBUZZ%.zip" https://github.com/harfbuzz/harfbuzz/archive/refs/tags/%HARFBUZZ%.zip 850cb5e38e21106c0abba86c5b73f8f74b9a32d7725505901d081080b0d3f0b3 || goto error
|
||||
call :downloadfile "lpng%LIBPNG%.zip" https://download.sourceforge.net/libpng/lpng1648.zip 2e5f080360f77376eb2bfa9e2ed773b9c7728159aba47b638ad53ca839379040 || goto error
|
||||
call :downloadfile "libjpeg-turbo-%LIBJPEGTURBO%.tar.gz" "https://github.com/libjpeg-turbo/libjpeg-turbo/releases/download/%LIBJPEGTURBO%/libjpeg-turbo-%LIBJPEGTURBO%.tar.gz" 9564c72b1dfd1d6fe6274c5f95a8d989b59854575d4bbee44ade7bc17aa9bc93 || goto error
|
||||
call :downloadfile "lpng%LIBPNG%.zip" https://download.sourceforge.net/libpng/lpng1650.zip 4be6938313b08d5921f9dede13f2789b653c96f4f8595d92ff3f09c9320e51c7 || goto error
|
||||
call :downloadfile "libjpeg-turbo-%LIBJPEGTURBO%.tar.gz" "https://github.com/libjpeg-turbo/libjpeg-turbo/releases/download/%LIBJPEGTURBO%/libjpeg-turbo-%LIBJPEGTURBO%.tar.gz" aadc97ea91f6ef078b0ae3a62bba69e008d9a7db19b34e4ac973b19b71b4217c || goto error
|
||||
call :downloadfile "libwebp-%WEBP%.tar.gz" "https://storage.googleapis.com/downloads.webmproject.org/releases/webp/libwebp-%WEBP%.tar.gz" 7d6fab70cf844bf6769077bd5d7a74893f8ffd4dfb42861745750c63c2a5c92c || goto error
|
||||
call :downloadfile "%SDL%.zip" "https://libsdl.org/release/%SDL%.zip" 0cc7430fb827c1f843e31b8b26ba7f083b1eeb8f6315a65d3744fd4d25b6c373 || goto error
|
||||
call :downloadfile "%SDL%.zip" "https://libsdl.org/release/%SDL%.zip" 208028b3b6225b3c9eae3942e50ed243d8798b4b3a56b98a59b3f7e37baa55fd || goto error
|
||||
call :downloadfile "qtbase-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtbase-everywhere-src-%QT%.zip" efa6d8ef9f7ae0fd9f7d280fbff574d71882b60a357ae639e516dc173cf26986 || goto error
|
||||
call :downloadfile "qtimageformats-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtimageformats-everywhere-src-%QT%.zip" 8439d3394bc380fd17a920ee96df1d2272bf8d3490871d948ef750f95e0ded06 || goto error
|
||||
call :downloadfile "qtsvg-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtsvg-everywhere-src-%QT%.zip" a8f90c768b54e28d61e02c1229b74a2b834e9852af523e5c70bcd2ae4c34a772 || goto error
|
||||
|
||||
@@ -42,9 +42,9 @@ cd "%BUILDDIR%"
|
||||
|
||||
set FREETYPE=2.13.3
|
||||
set HARFBUZZ=11.2.0
|
||||
set LIBJPEGTURBO=3.1.0
|
||||
set LIBPNG=1648
|
||||
set SDL=SDL3-3.2.16
|
||||
set LIBJPEGTURBO=3.1.1
|
||||
set LIBPNG=1650
|
||||
set SDL=SDL3-3.2.18
|
||||
set QT=6.9.1
|
||||
set QTMINOR=6.9
|
||||
set LZ4=1.10.0
|
||||
@@ -63,10 +63,10 @@ set SHADERC_SPIRVTOOLS=33e02568181e3312f49a3cf33df470bf96ef293a
|
||||
|
||||
call :downloadfile "freetype-%FREETYPE%.tar.gz" https://sourceforge.net/projects/freetype/files/freetype2/%FREETYPE%/freetype-%FREETYPE%.tar.gz/download 5c3a8e78f7b24c20b25b54ee575d6daa40007a5f4eea2845861c3409b3021747 || goto error
|
||||
call :downloadfile "harfbuzz-%HARFBUZZ%.zip" https://github.com/harfbuzz/harfbuzz/archive/refs/tags/%HARFBUZZ%.zip 850cb5e38e21106c0abba86c5b73f8f74b9a32d7725505901d081080b0d3f0b3 || goto error
|
||||
call :downloadfile "lpng%LIBPNG%.zip" https://download.sourceforge.net/libpng/lpng1648.zip 2e5f080360f77376eb2bfa9e2ed773b9c7728159aba47b638ad53ca839379040 || goto error
|
||||
call :downloadfile "libjpeg-turbo-%LIBJPEGTURBO%.tar.gz" "https://github.com/libjpeg-turbo/libjpeg-turbo/releases/download/%LIBJPEGTURBO%/libjpeg-turbo-%LIBJPEGTURBO%.tar.gz" 9564c72b1dfd1d6fe6274c5f95a8d989b59854575d4bbee44ade7bc17aa9bc93 || goto error
|
||||
call :downloadfile "lpng%LIBPNG%.zip" https://download.sourceforge.net/libpng/lpng1650.zip 4be6938313b08d5921f9dede13f2789b653c96f4f8595d92ff3f09c9320e51c7 || goto error
|
||||
call :downloadfile "libjpeg-turbo-%LIBJPEGTURBO%.tar.gz" "https://github.com/libjpeg-turbo/libjpeg-turbo/releases/download/%LIBJPEGTURBO%/libjpeg-turbo-%LIBJPEGTURBO%.tar.gz" aadc97ea91f6ef078b0ae3a62bba69e008d9a7db19b34e4ac973b19b71b4217c || goto error
|
||||
call :downloadfile "libwebp-%WEBP%.tar.gz" "https://storage.googleapis.com/downloads.webmproject.org/releases/webp/libwebp-%WEBP%.tar.gz" 7d6fab70cf844bf6769077bd5d7a74893f8ffd4dfb42861745750c63c2a5c92c || goto error
|
||||
call :downloadfile "%SDL%.zip" "https://libsdl.org/release/%SDL%.zip" 0cc7430fb827c1f843e31b8b26ba7f083b1eeb8f6315a65d3744fd4d25b6c373 || goto error
|
||||
call :downloadfile "%SDL%.zip" "https://libsdl.org/release/%SDL%.zip" 208028b3b6225b3c9eae3942e50ed243d8798b4b3a56b98a59b3f7e37baa55fd || goto error
|
||||
call :downloadfile "qtbase-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtbase-everywhere-src-%QT%.zip" efa6d8ef9f7ae0fd9f7d280fbff574d71882b60a357ae639e516dc173cf26986 || goto error
|
||||
call :downloadfile "qtimageformats-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtimageformats-everywhere-src-%QT%.zip" 8439d3394bc380fd17a920ee96df1d2272bf8d3490871d948ef750f95e0ded06 || goto error
|
||||
call :downloadfile "qtsvg-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtsvg-everywhere-src-%QT%.zip" a8f90c768b54e28d61e02c1229b74a2b834e9852af523e5c70bcd2ae4c34a772 || goto error
|
||||
|
||||
4
3rdparty/cpuinfo/README.md
vendored
4
3rdparty/cpuinfo/README.md
vendored
@@ -9,7 +9,7 @@ cpuinfo is a library to detect essential for performance optimization informatio
|
||||
## Features
|
||||
|
||||
- **Cross-platform** availability:
|
||||
- Linux, Windows, macOS, Android, and iOS operating systems
|
||||
- Linux, Windows, macOS, Android, iOS and FreeBSD operating systems
|
||||
- x86, x86-64, ARM, and ARM64 architectures
|
||||
- Modern **C/C++ interface**
|
||||
- Thread-safe
|
||||
@@ -258,6 +258,8 @@ LDFLAGS+= $(pkg-config --libs libcpuinfo)
|
||||
- [x] x86
|
||||
- [x] x86-64
|
||||
- [x] arm64
|
||||
- [x] FreeBSD
|
||||
- [x] x86-64
|
||||
|
||||
## Methods
|
||||
|
||||
|
||||
34
3rdparty/cpuinfo/include/cpuinfo.h
vendored
34
3rdparty/cpuinfo/include/cpuinfo.h
vendored
@@ -353,6 +353,8 @@ enum cpuinfo_uarch {
|
||||
cpuinfo_uarch_palm_cove = 0x0010020B,
|
||||
/** Intel Sunny Cove microarchitecture (10 nm, Ice Lake). */
|
||||
cpuinfo_uarch_sunny_cove = 0x0010020C,
|
||||
/** Intel Willow Cove microarchitecture (10 nm, Tiger Lake). */
|
||||
cpuinfo_uarch_willow_cove = 0x0010020D,
|
||||
|
||||
/** Pentium 4 with Willamette, Northwood, or Foster cores. */
|
||||
cpuinfo_uarch_willamette = 0x00100300,
|
||||
@@ -371,6 +373,10 @@ enum cpuinfo_uarch {
|
||||
cpuinfo_uarch_goldmont = 0x00100404,
|
||||
/** Intel Goldmont Plus microarchitecture (Gemini Lake). */
|
||||
cpuinfo_uarch_goldmont_plus = 0x00100405,
|
||||
/** Intel Gracemont microarchitecture (Twin Lake). */
|
||||
cpuinfo_uarch_gracemont = 0x00100406,
|
||||
/** Intel Crestmont microarchitecture (Sierra Forest). */
|
||||
cpuinfo_uarch_crestmont = 0x00100407,
|
||||
|
||||
/** Intel Knights Ferry HPC boards. */
|
||||
cpuinfo_uarch_knights_ferry = 0x00100500,
|
||||
@@ -382,6 +388,8 @@ enum cpuinfo_uarch {
|
||||
cpuinfo_uarch_knights_hill = 0x00100503,
|
||||
/** Intel Knights Mill Xeon Phi. */
|
||||
cpuinfo_uarch_knights_mill = 0x00100504,
|
||||
/** Intel Darkmont microarchitecture (e-core used in Clearwater Forest). */
|
||||
cpuinfo_uarch_darkmont = 0x00100505,
|
||||
|
||||
/** Intel/Marvell XScale series. */
|
||||
cpuinfo_uarch_xscale = 0x00100600,
|
||||
@@ -581,6 +589,22 @@ enum cpuinfo_uarch {
|
||||
cpuinfo_uarch_avalanche = 0x0070010D,
|
||||
/** Apple A15 / M2 processor (little cores). */
|
||||
cpuinfo_uarch_blizzard = 0x0070010E,
|
||||
/** Apple A16 processor (big cores). */
|
||||
cpuinfo_uarch_everest = 0x00700200,
|
||||
/** Apple A16 processor (little cores). */
|
||||
cpuinfo_uarch_sawtooth = 0x00700201,
|
||||
/** Apple A17 processor (big cores). */
|
||||
cpuinfo_uarch_coll_everest = 0x00700202,
|
||||
/** Apple A17 processor (little cores). */
|
||||
cpuinfo_uarch_coll_sawtooth = 0x00700203,
|
||||
/** Apple A18 processor (big cores). */
|
||||
cpuinfo_uarch_tupai_everest = 0x00700204,
|
||||
/** Apple A18 processor (little cores). */
|
||||
cpuinfo_uarch_tupai_sawtooth = 0x00700205,
|
||||
/** Apple A18 pro processor (big cores). */
|
||||
cpuinfo_uarch_tahiti_everest = 0x00700206,
|
||||
/** Apple A18 pro processor (little cores). */
|
||||
cpuinfo_uarch_tahiti_sawtooth = 0x00700207,
|
||||
|
||||
/** Cavium ThunderX. */
|
||||
cpuinfo_uarch_thunderx = 0x00800100,
|
||||
@@ -1700,6 +1724,7 @@ struct cpuinfo_arm_isa {
|
||||
bool sme_b16b16;
|
||||
bool sme_f16f16;
|
||||
uint32_t svelen;
|
||||
uint32_t smelen;
|
||||
#endif
|
||||
bool rdm;
|
||||
bool fp16arith;
|
||||
@@ -2081,6 +2106,15 @@ static inline uint32_t cpuinfo_get_max_arm_sve_length(void) {
|
||||
#endif
|
||||
}
|
||||
|
||||
// Function to get the max SME vector length on ARM CPU's which support SME.
|
||||
static inline uint32_t cpuinfo_get_max_arm_sme_length(void) {
|
||||
#if CPUINFO_ARCH_ARM64
|
||||
return cpuinfo_isa.smelen * 8; // bytes * 8 = bit length(vector length)
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline bool cpuinfo_has_arm_sme(void) {
|
||||
#if CPUINFO_ARCH_ARM64
|
||||
return cpuinfo_isa.sme;
|
||||
|
||||
2
3rdparty/cpuinfo/src/arm/linux/aarch32-isa.c
vendored
2
3rdparty/cpuinfo/src/arm/linux/aarch32-isa.c
vendored
@@ -149,6 +149,8 @@ void cpuinfo_arm_linux_decode_isa_from_proc_cpuinfo(
|
||||
cpuinfo_log_warning("VDOT instructions disabled: cause occasional SIGILL on Unisoc T310");
|
||||
} else if (chipset->series == cpuinfo_arm_chipset_series_unisoc_ums && chipset->model == 312) {
|
||||
cpuinfo_log_warning("VDOT instructions disabled: cause occasional SIGILL on Unisoc UMS312");
|
||||
} else if (chipset->vendor == cpuinfo_arm_chipset_vendor_unknown) {
|
||||
cpuinfo_log_warning("VDOT instructions disabled: unknown chipset");
|
||||
} else {
|
||||
switch (midr & (CPUINFO_ARM_MIDR_IMPLEMENTER_MASK | CPUINFO_ARM_MIDR_PART_MASK)) {
|
||||
case UINT32_C(0x4100D0B0): /* Cortex-A76 */
|
||||
|
||||
17
3rdparty/cpuinfo/src/arm/linux/aarch64-isa.c
vendored
17
3rdparty/cpuinfo/src/arm/linux/aarch64-isa.c
vendored
@@ -191,4 +191,21 @@ void cpuinfo_arm64_linux_decode_isa_from_proc_cpuinfo(
|
||||
// Mask out the SVE vector length bits
|
||||
isa->svelen = ret & PR_SVE_VL_LEN_MASK;
|
||||
}
|
||||
|
||||
#ifndef PR_SME_GET_VL
|
||||
#define PR_SME_GET_VL 64
|
||||
#endif
|
||||
|
||||
#ifndef PR_SME_VL_LEN_MASK
|
||||
#define PR_SME_VL_LEN_MASK 0xffff
|
||||
#endif
|
||||
|
||||
ret = prctl(PR_SME_GET_VL);
|
||||
if (ret < 0) {
|
||||
cpuinfo_log_warning("No SME support on this machine");
|
||||
isa->smelen = 0; // Assume no SME support if the call fails
|
||||
} else {
|
||||
// Mask out the SME vector length bits
|
||||
isa->smelen = ret & PR_SME_VL_LEN_MASK;
|
||||
}
|
||||
}
|
||||
|
||||
56
3rdparty/cpuinfo/src/arm/mach/init.c
vendored
56
3rdparty/cpuinfo/src/arm/mach/init.c
vendored
@@ -27,6 +27,45 @@
|
||||
#ifndef CPUFAMILY_ARM_AVALANCHE_BLIZZARD
|
||||
#define CPUFAMILY_ARM_AVALANCHE_BLIZZARD 0xDA33D83D
|
||||
#endif
|
||||
// Following are copied over from ncnn/src/cpu.cpp
|
||||
// A16
|
||||
#ifndef CPUFAMILY_ARM_EVEREST_SAWTOOTH
|
||||
#define CPUFAMILY_ARM_EVEREST_SAWTOOTH 0x8765edea
|
||||
#endif
|
||||
// A17
|
||||
#ifndef CPUFAMILY_ARM_COLL
|
||||
#define CPUFAMILY_ARM_COLL 0x2876f5b5
|
||||
#endif
|
||||
// A18
|
||||
#ifndef CPUFAMILY_ARM_TUPAI
|
||||
#define CPUFAMILY_ARM_TUPAI 0x204526d0
|
||||
#endif
|
||||
// A18 Pro
|
||||
#ifndef CPUFAMILY_ARM_TAHITI
|
||||
#define CPUFAMILY_ARM_TAHITI 0x75d4acb9
|
||||
#endif
|
||||
// For M3/M4 we need to populate more information about
|
||||
// efficiency and perf cores.
|
||||
// M3
|
||||
#ifndef CPUFAMILY_ARM_IBIZA
|
||||
#define CPUFAMILY_ARM_IBIZA 0xfa33415e
|
||||
#endif
|
||||
// M3 Pro
|
||||
#ifndef CPUFAMILY_ARM_LOBOS
|
||||
#define CPUFAMILY_ARM_LOBOS 0x5f4dea93
|
||||
#endif
|
||||
// M3 Max
|
||||
#ifndef CPUFAMILY_ARM_PALMA
|
||||
#define CPUFAMILY_ARM_PALMA 0x72015832
|
||||
#endif
|
||||
// M4
|
||||
#ifndef CPUFAMILY_ARM_DONAN
|
||||
#define CPUFAMILY_ARM_DONAN 0x6f5129ac
|
||||
#endif
|
||||
// M4 Pro / M4 Max
|
||||
#ifndef CPUFAMILY_ARM_BRAVA
|
||||
#define CPUFAMILY_ARM_BRAVA 0x17d5b93a
|
||||
#endif
|
||||
|
||||
struct cpuinfo_arm_isa cpuinfo_isa = {
|
||||
.aes = true,
|
||||
@@ -93,6 +132,23 @@ static enum cpuinfo_uarch decode_uarch(uint32_t cpu_family, uint32_t core_index,
|
||||
case CPUFAMILY_ARM_AVALANCHE_BLIZZARD:
|
||||
/* Hexa-core: 2x Avalanche + 4x Blizzard */
|
||||
return core_index + 4 < core_count ? cpuinfo_uarch_avalanche : cpuinfo_uarch_blizzard;
|
||||
case CPUFAMILY_ARM_EVEREST_SAWTOOTH:
|
||||
/* Hexa-core: 2x Avalanche + 4x Blizzard */
|
||||
return core_index + 4 < core_count ? cpuinfo_uarch_everest : cpuinfo_uarch_sawtooth;
|
||||
return core_index + 4 < core_count ? cpuinfo_uarch_avalanche : cpuinfo_uarch_blizzard;
|
||||
case CPUFAMILY_ARM_COLL:
|
||||
/* Hexa-core: 2x Avalanche + 4x Blizzard */
|
||||
return core_index + 4 < core_count ? cpuinfo_uarch_coll_everest : cpuinfo_uarch_coll_sawtooth;
|
||||
|
||||
case CPUFAMILY_ARM_TUPAI:
|
||||
/* Hexa-core: 2x Avalanche + 4x Blizzard */
|
||||
return core_index + 4 < core_count ? cpuinfo_uarch_tupai_everest : cpuinfo_uarch_tupai_sawtooth;
|
||||
|
||||
case CPUFAMILY_ARM_TAHITI:
|
||||
/* Hexa-core: 2x Avalanche + 4x Blizzard */
|
||||
return core_index + 4 < core_count ? cpuinfo_uarch_tahiti_everest
|
||||
: cpuinfo_uarch_tahiti_sawtooth;
|
||||
|
||||
default:
|
||||
/* Use hw.cpusubtype for detection */
|
||||
break;
|
||||
|
||||
2
3rdparty/cpuinfo/src/riscv/linux/riscv-hw.c
vendored
2
3rdparty/cpuinfo/src/riscv/linux/riscv-hw.c
vendored
@@ -112,7 +112,7 @@ void cpuinfo_riscv_linux_decode_vendor_uarch_from_hwprobe(
|
||||
*
|
||||
* for more details.
|
||||
*/
|
||||
int ret = syscall(NR_riscv_hwprobe, pairs, pairs_count, cpu_set_size, (unsigned long*)cpu_set, 0 /* flags */);
|
||||
int ret = syscall(NR_riscv_hwprobe, pairs, pairs_count, cpu_set_size, cpu_set, 0 /* flags */);
|
||||
#else
|
||||
int ret = __riscv_hwprobe(pairs, pairs_count, cpu_set_size, (unsigned long*)cpu_set, 0 /* flags */);
|
||||
#endif
|
||||
|
||||
9
3rdparty/cpuinfo/src/x86/linux/cpuinfo.c
vendored
9
3rdparty/cpuinfo/src/x86/linux/cpuinfo.c
vendored
@@ -80,11 +80,7 @@ struct proc_cpuinfo_parser_state {
|
||||
* Decode a single line of /proc/cpuinfo information.
|
||||
* Lines have format <words-with-spaces>[ ]*:[ ]<space-separated words>
|
||||
*/
|
||||
static bool parse_line(
|
||||
const char* line_start,
|
||||
const char* line_end,
|
||||
void* context,
|
||||
uint64_t line_number) {
|
||||
static bool parse_line(const char* line_start, const char* line_end, void* context, uint64_t line_number) {
|
||||
struct proc_cpuinfo_parser_state* restrict state = context;
|
||||
/* Empty line. Skip. */
|
||||
if (line_start == line_end) {
|
||||
@@ -215,6 +211,5 @@ bool cpuinfo_x86_linux_parse_proc_cpuinfo(
|
||||
.max_processors_count = max_processors_count,
|
||||
.processors = processors,
|
||||
};
|
||||
return cpuinfo_linux_parse_multiline_file(
|
||||
"/proc/cpuinfo", BUFFER_SIZE, parse_line, &state);
|
||||
return cpuinfo_linux_parse_multiline_file("/proc/cpuinfo", BUFFER_SIZE, parse_line, &state);
|
||||
}
|
||||
|
||||
9
3rdparty/cpuinfo/src/x86/uarch.c
vendored
9
3rdparty/cpuinfo/src/x86/uarch.c
vendored
@@ -168,6 +168,9 @@ enum cpuinfo_uarch cpuinfo_x86_decode_uarch(
|
||||
case 0x7E: // Ice Lake-U
|
||||
return cpuinfo_uarch_sunny_cove;
|
||||
|
||||
case 0x8C: // Tiger U
|
||||
case 0x8D: // Tiger H
|
||||
return cpuinfo_uarch_willow_cove;
|
||||
/* Low-power cores */
|
||||
case 0x1C: // Diamondville,
|
||||
// Silverthorne,
|
||||
@@ -185,6 +188,10 @@ enum cpuinfo_uarch cpuinfo_x86_decode_uarch(
|
||||
case 0x5A: // Moorefield
|
||||
case 0x5D: // SoFIA
|
||||
return cpuinfo_uarch_silvermont;
|
||||
case 0xBE: // Twin Lake
|
||||
return cpuinfo_uarch_gracemont;
|
||||
case 0xAF: // Sierra Forest
|
||||
return cpuinfo_uarch_crestmont;
|
||||
case 0x4C: // Braswell, Cherry
|
||||
// Trail
|
||||
case 0x75: // Spreadtrum
|
||||
@@ -201,6 +208,8 @@ enum cpuinfo_uarch cpuinfo_x86_decode_uarch(
|
||||
return cpuinfo_uarch_knights_landing;
|
||||
case 0x85:
|
||||
return cpuinfo_uarch_knights_mill;
|
||||
case 0xDD: // Clearwater Forest
|
||||
return cpuinfo_uarch_darkmont;
|
||||
}
|
||||
break;
|
||||
case 0x0F:
|
||||
|
||||
8
3rdparty/googletest/CONTRIBUTING.md
vendored
8
3rdparty/googletest/CONTRIBUTING.md
vendored
@@ -47,11 +47,11 @@ PR is acceptable as an alternative.
|
||||
## The Google Test and Google Mock Communities
|
||||
|
||||
The Google Test community exists primarily through the
|
||||
[discussion group](http://groups.google.com/group/googletestframework) and the
|
||||
[discussion group](https://groups.google.com/group/googletestframework) and the
|
||||
GitHub repository. Likewise, the Google Mock community exists primarily through
|
||||
their own [discussion group](http://groups.google.com/group/googlemock). You are
|
||||
definitely encouraged to contribute to the discussion and you can also help us
|
||||
to keep the effectiveness of the group high by following and promoting the
|
||||
their own [discussion group](https://groups.google.com/group/googlemock). You
|
||||
are definitely encouraged to contribute to the discussion and you can also help
|
||||
us to keep the effectiveness of the group high by following and promoting the
|
||||
guidelines listed here.
|
||||
|
||||
### Please Be Friendly
|
||||
|
||||
15
3rdparty/googletest/README.md
vendored
15
3rdparty/googletest/README.md
vendored
@@ -2,27 +2,18 @@
|
||||
|
||||
### Announcements
|
||||
|
||||
#### Live at Head
|
||||
|
||||
GoogleTest now follows the
|
||||
[Abseil Live at Head philosophy](https://abseil.io/about/philosophy#upgrade-support).
|
||||
We recommend
|
||||
[updating to the latest commit in the `main` branch as often as possible](https://github.com/abseil/abseil-cpp/blob/master/FAQ.md#what-is-live-at-head-and-how-do-i-do-it).
|
||||
We do publish occasional semantic versions, tagged with
|
||||
`v${major}.${minor}.${patch}` (e.g. `v1.16.0`).
|
||||
|
||||
#### Documentation Updates
|
||||
|
||||
Our documentation is now live on GitHub Pages at
|
||||
https://google.github.io/googletest/. We recommend browsing the documentation on
|
||||
GitHub Pages rather than directly in the repository.
|
||||
|
||||
#### Release 1.16.0
|
||||
#### Release 1.17.0
|
||||
|
||||
[Release 1.16.0](https://github.com/google/googletest/releases/tag/v1.16.0) is
|
||||
[Release 1.17.0](https://github.com/google/googletest/releases/tag/v1.17.0) is
|
||||
now available.
|
||||
|
||||
The 1.16.x branch requires at least C++14.
|
||||
The 1.17.x branch [requires at least C++17]((https://opensource.google/documentation/policies/cplusplus-support#c_language_standard).
|
||||
|
||||
#### Continuous Integration
|
||||
|
||||
|
||||
@@ -835,6 +835,10 @@ class Action<R(Args...)> {
|
||||
Result operator()(const InArgs&...) const {
|
||||
return function_impl();
|
||||
}
|
||||
template <typename... InArgs>
|
||||
Result operator()(const InArgs&...) {
|
||||
return function_impl();
|
||||
}
|
||||
|
||||
FunctionImpl function_impl;
|
||||
};
|
||||
@@ -1451,6 +1455,30 @@ struct WithArgsAction {
|
||||
return OA{std::move(inner_action)};
|
||||
}
|
||||
|
||||
// As above, but in the case where we want to create a OnceAction from a const
|
||||
// WithArgsAction. This is fine as long as the inner action doesn't need to
|
||||
// move any of its state to create a OnceAction.
|
||||
template <
|
||||
typename R, typename... Args,
|
||||
typename std::enable_if<
|
||||
std::is_convertible<const InnerAction&,
|
||||
OnceAction<R(internal::TupleElement<
|
||||
I, std::tuple<Args...>>...)>>::value,
|
||||
int>::type = 0>
|
||||
operator OnceAction<R(Args...)>() const& { // NOLINT
|
||||
struct OA {
|
||||
OnceAction<InnerSignature<R, Args...>> inner_action;
|
||||
|
||||
R operator()(Args&&... args) && {
|
||||
return std::move(inner_action)
|
||||
.Call(std::get<I>(
|
||||
std::forward_as_tuple(std::forward<Args>(args)...))...);
|
||||
}
|
||||
};
|
||||
|
||||
return OA{inner_action};
|
||||
}
|
||||
|
||||
template <
|
||||
typename R, typename... Args,
|
||||
typename std::enable_if<
|
||||
@@ -1703,9 +1731,8 @@ template <size_t k>
|
||||
struct ReturnArgAction {
|
||||
template <typename... Args,
|
||||
typename = typename std::enable_if<(k < sizeof...(Args))>::type>
|
||||
auto operator()(Args&&... args) const
|
||||
-> decltype(std::get<k>(
|
||||
std::forward_as_tuple(std::forward<Args>(args)...))) {
|
||||
auto operator()(Args&&... args) const -> decltype(std::get<k>(
|
||||
std::forward_as_tuple(std::forward<Args>(args)...))) {
|
||||
return std::get<k>(std::forward_as_tuple(std::forward<Args>(args)...));
|
||||
}
|
||||
};
|
||||
@@ -1720,6 +1747,16 @@ struct SaveArgAction {
|
||||
}
|
||||
};
|
||||
|
||||
template <size_t k, typename Ptr>
|
||||
struct SaveArgByMoveAction {
|
||||
Ptr pointer;
|
||||
|
||||
template <typename... Args>
|
||||
void operator()(Args&&... args) const {
|
||||
*pointer = std::move(std::get<k>(std::tie(args...)));
|
||||
}
|
||||
};
|
||||
|
||||
template <size_t k, typename Ptr>
|
||||
struct SaveArgPointeeAction {
|
||||
Ptr pointer;
|
||||
@@ -2070,6 +2107,13 @@ internal::SaveArgAction<k, Ptr> SaveArg(Ptr pointer) {
|
||||
return {pointer};
|
||||
}
|
||||
|
||||
// Action SaveArgByMove<k>(pointer) moves the k-th (0-based) argument of the
|
||||
// mock function into *pointer.
|
||||
template <size_t k, typename Ptr>
|
||||
internal::SaveArgByMoveAction<k, Ptr> SaveArgByMove(Ptr pointer) {
|
||||
return {pointer};
|
||||
}
|
||||
|
||||
// Action SaveArgPointee<k>(pointer) saves the value pointed to
|
||||
// by the k-th (0-based) argument of the mock function to *pointer.
|
||||
template <size_t k, typename Ptr>
|
||||
@@ -2213,9 +2257,9 @@ template <typename F, typename Impl>
|
||||
}
|
||||
|
||||
#define GMOCK_INTERNAL_ARG_UNUSED(i, data, el) \
|
||||
, GTEST_INTERNAL_ATTRIBUTE_MAYBE_UNUSED const arg##i##_type& arg##i
|
||||
#define GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_ \
|
||||
GTEST_INTERNAL_ATTRIBUTE_MAYBE_UNUSED const args_type& args GMOCK_PP_REPEAT( \
|
||||
, [[maybe_unused]] const arg##i##_type& arg##i
|
||||
#define GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_ \
|
||||
[[maybe_unused]] const args_type& args GMOCK_PP_REPEAT( \
|
||||
GMOCK_INTERNAL_ARG_UNUSED, , 10)
|
||||
|
||||
#define GMOCK_INTERNAL_ARG(i, data, el) , const arg##i##_type& arg##i
|
||||
@@ -2280,8 +2324,8 @@ template <typename F, typename Impl>
|
||||
std::shared_ptr<const gmock_Impl> impl_; \
|
||||
}; \
|
||||
template <GMOCK_ACTION_TYPENAME_PARAMS_(params)> \
|
||||
inline full_name<GMOCK_ACTION_TYPE_PARAMS_(params)> name( \
|
||||
GMOCK_ACTION_TYPE_GVALUE_PARAMS_(params)) GTEST_MUST_USE_RESULT_; \
|
||||
[[nodiscard]] inline full_name<GMOCK_ACTION_TYPE_PARAMS_(params)> name( \
|
||||
GMOCK_ACTION_TYPE_GVALUE_PARAMS_(params)); \
|
||||
template <GMOCK_ACTION_TYPENAME_PARAMS_(params)> \
|
||||
inline full_name<GMOCK_ACTION_TYPE_PARAMS_(params)> name( \
|
||||
GMOCK_ACTION_TYPE_GVALUE_PARAMS_(params)) { \
|
||||
@@ -2316,7 +2360,7 @@ template <typename F, typename Impl>
|
||||
return_type gmock_PerformImpl(GMOCK_ACTION_ARG_TYPES_AND_NAMES_) const; \
|
||||
}; \
|
||||
}; \
|
||||
inline name##Action name() GTEST_MUST_USE_RESULT_; \
|
||||
[[nodiscard]] inline name##Action name(); \
|
||||
inline name##Action name() { return name##Action(); } \
|
||||
template <typename function_type, typename return_type, typename args_type, \
|
||||
GMOCK_ACTION_TEMPLATE_ARGS_NAMES_> \
|
||||
|
||||
@@ -257,6 +257,7 @@
|
||||
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
#include <cstddef>
|
||||
#include <exception>
|
||||
#include <functional>
|
||||
#include <initializer_list>
|
||||
@@ -1311,6 +1312,15 @@ class AllOfMatcherImpl : public MatcherInterface<const T&> {
|
||||
|
||||
bool MatchAndExplain(const T& x,
|
||||
MatchResultListener* listener) const override {
|
||||
if (!listener->IsInterested()) {
|
||||
// Fast path to avoid unnecessary formatting.
|
||||
for (const Matcher<T>& matcher : matchers_) {
|
||||
if (!matcher.Matches(x)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
// This method uses matcher's explanation when explaining the result.
|
||||
// However, if matcher doesn't provide one, this method uses matcher's
|
||||
// description.
|
||||
@@ -1430,6 +1440,15 @@ class AnyOfMatcherImpl : public MatcherInterface<const T&> {
|
||||
|
||||
bool MatchAndExplain(const T& x,
|
||||
MatchResultListener* listener) const override {
|
||||
if (!listener->IsInterested()) {
|
||||
// Fast path to avoid unnecessary formatting of match explanations.
|
||||
for (const Matcher<T>& matcher : matchers_) {
|
||||
if (matcher.Matches(x)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
// This method uses matcher's explanation when explaining the result.
|
||||
// However, if matcher doesn't provide one, this method uses matcher's
|
||||
// description.
|
||||
@@ -2097,11 +2116,11 @@ class WhenDynamicCastToMatcher<To&> : public WhenDynamicCastToMatcherBase<To&> {
|
||||
template <typename Class, typename FieldType>
|
||||
class FieldMatcher {
|
||||
public:
|
||||
FieldMatcher(FieldType Class::*field,
|
||||
FieldMatcher(FieldType Class::* field,
|
||||
const Matcher<const FieldType&>& matcher)
|
||||
: field_(field), matcher_(matcher), whose_field_("whose given field ") {}
|
||||
|
||||
FieldMatcher(const std::string& field_name, FieldType Class::*field,
|
||||
FieldMatcher(const std::string& field_name, FieldType Class::* field,
|
||||
const Matcher<const FieldType&>& matcher)
|
||||
: field_(field),
|
||||
matcher_(matcher),
|
||||
@@ -2145,7 +2164,7 @@ class FieldMatcher {
|
||||
return MatchAndExplainImpl(std::false_type(), *p, listener);
|
||||
}
|
||||
|
||||
const FieldType Class::*field_;
|
||||
const FieldType Class::* field_;
|
||||
const Matcher<const FieldType&> matcher_;
|
||||
|
||||
// Contains either "whose given field " if the name of the field is unknown
|
||||
@@ -2855,6 +2874,54 @@ class ContainsMatcherImpl : public QuantifierMatcherImpl<Container> {
|
||||
}
|
||||
};
|
||||
|
||||
// Implements DistanceFrom(target, get_distance, distance_matcher) for the given
|
||||
// argument types:
|
||||
// * V is the type of the value to be matched.
|
||||
// * T is the type of the target value.
|
||||
// * Distance is the type of the distance between V and T.
|
||||
// * GetDistance is the type of the functor for computing the distance between
|
||||
// V and T.
|
||||
template <typename V, typename T, typename Distance, typename GetDistance>
|
||||
class DistanceFromMatcherImpl : public MatcherInterface<V> {
|
||||
public:
|
||||
// Arguments:
|
||||
// * target: the target value.
|
||||
// * get_distance: the functor for computing the distance between the value
|
||||
// being matched and target.
|
||||
// * distance_matcher: the matcher for checking the distance.
|
||||
DistanceFromMatcherImpl(T target, GetDistance get_distance,
|
||||
Matcher<const Distance&> distance_matcher)
|
||||
: target_(std::move(target)),
|
||||
get_distance_(std::move(get_distance)),
|
||||
distance_matcher_(std::move(distance_matcher)) {}
|
||||
|
||||
// Describes what this matcher does.
|
||||
void DescribeTo(::std::ostream* os) const override {
|
||||
distance_matcher_.DescribeTo(os);
|
||||
*os << " away from " << PrintToString(target_);
|
||||
}
|
||||
|
||||
void DescribeNegationTo(::std::ostream* os) const override {
|
||||
distance_matcher_.DescribeNegationTo(os);
|
||||
*os << " away from " << PrintToString(target_);
|
||||
}
|
||||
|
||||
bool MatchAndExplain(V value, MatchResultListener* listener) const override {
|
||||
const auto distance = get_distance_(value, target_);
|
||||
const bool match = distance_matcher_.Matches(distance);
|
||||
if (!match && listener->IsInterested()) {
|
||||
*listener << "which is " << PrintToString(distance) << " away from "
|
||||
<< PrintToString(target_);
|
||||
}
|
||||
return match;
|
||||
}
|
||||
|
||||
private:
|
||||
const T target_;
|
||||
const GetDistance get_distance_;
|
||||
const Matcher<const Distance&> distance_matcher_;
|
||||
};
|
||||
|
||||
// Implements Each(element_matcher) for the given argument type Container.
|
||||
// Symmetric to ContainsMatcherImpl.
|
||||
template <typename Container>
|
||||
@@ -2990,6 +3057,52 @@ auto Second(T& x, Rank1) -> decltype((x.second)) { // NOLINT
|
||||
}
|
||||
} // namespace pair_getters
|
||||
|
||||
// Default functor for computing the distance between two values.
|
||||
struct DefaultGetDistance {
|
||||
template <typename T, typename U>
|
||||
auto operator()(const T& lhs, const U& rhs) const {
|
||||
using std::abs;
|
||||
// Allow finding abs() in the type's namespace via ADL.
|
||||
return abs(lhs - rhs);
|
||||
}
|
||||
};
|
||||
|
||||
// Implements polymorphic DistanceFrom(target, get_distance, distance_matcher)
|
||||
// matcher. Template arguments:
|
||||
// * T is the type of the target value.
|
||||
// * GetDistance is the type of the functor for computing the distance between
|
||||
// the value being matched and the target.
|
||||
// * DistanceMatcher is the type of the matcher for checking the distance.
|
||||
template <typename T, typename GetDistance, typename DistanceMatcher>
|
||||
class DistanceFromMatcher {
|
||||
public:
|
||||
// Arguments:
|
||||
// * target: the target value.
|
||||
// * get_distance: the functor for computing the distance between the value
|
||||
// being matched and target.
|
||||
// * distance_matcher: the matcher for checking the distance.
|
||||
DistanceFromMatcher(T target, GetDistance get_distance,
|
||||
DistanceMatcher distance_matcher)
|
||||
: target_(std::move(target)),
|
||||
get_distance_(std::move(get_distance)),
|
||||
distance_matcher_(std::move(distance_matcher)) {}
|
||||
|
||||
DistanceFromMatcher(const DistanceFromMatcher& other) = default;
|
||||
|
||||
// Implicitly converts to a monomorphic matcher of the given type.
|
||||
template <typename V>
|
||||
operator Matcher<V>() const { // NOLINT
|
||||
using Distance = decltype(get_distance_(std::declval<V>(), target_));
|
||||
return Matcher<V>(new DistanceFromMatcherImpl<V, T, Distance, GetDistance>(
|
||||
target_, get_distance_, distance_matcher_));
|
||||
}
|
||||
|
||||
private:
|
||||
const T target_;
|
||||
const GetDistance get_distance_;
|
||||
const DistanceMatcher distance_matcher_;
|
||||
};
|
||||
|
||||
// Implements Key(inner_matcher) for the given argument pair type.
|
||||
// Key(inner_matcher) matches an std::pair whose 'first' field matches
|
||||
// inner_matcher. For example, Contains(Key(Ge(5))) can be used to match an
|
||||
@@ -3197,8 +3310,8 @@ class PairMatcher {
|
||||
};
|
||||
|
||||
template <typename T, size_t... I>
|
||||
auto UnpackStructImpl(const T& t, std::index_sequence<I...>,
|
||||
int) -> decltype(std::tie(get<I>(t)...)) {
|
||||
auto UnpackStructImpl(const T& t, std::index_sequence<I...>, int)
|
||||
-> decltype(std::tie(get<I>(t)...)) {
|
||||
static_assert(std::tuple_size<T>::value == sizeof...(I),
|
||||
"Number of arguments doesn't match the number of fields.");
|
||||
return std::tie(get<I>(t)...);
|
||||
@@ -3305,6 +3418,21 @@ auto UnpackStructImpl(const T& u, std::make_index_sequence<20>, char) {
|
||||
const auto& [a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t] = u;
|
||||
return std::tie(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t);
|
||||
}
|
||||
template <typename T>
|
||||
auto UnpackStructImpl(const T& in, std::make_index_sequence<21>, char) {
|
||||
const auto& [a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u] =
|
||||
in;
|
||||
return std::tie(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t,
|
||||
u);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
auto UnpackStructImpl(const T& in, std::make_index_sequence<22>, char) {
|
||||
const auto& [a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u,
|
||||
v] = in;
|
||||
return std::tie(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u,
|
||||
v);
|
||||
}
|
||||
#endif // defined(__cpp_structured_bindings)
|
||||
|
||||
template <size_t I, typename T>
|
||||
@@ -3480,7 +3608,7 @@ class ElementsAreMatcherImpl : public MatcherInterface<Container> {
|
||||
StlContainerReference stl_container = View::ConstReference(container);
|
||||
auto it = stl_container.begin();
|
||||
size_t exam_pos = 0;
|
||||
bool mismatch_found = false; // Have we found a mismatched element yet?
|
||||
bool unmatched_found = false;
|
||||
|
||||
// Go through the elements and matchers in pairs, until we reach
|
||||
// the end of either the elements or the matchers, or until we find a
|
||||
@@ -3496,11 +3624,23 @@ class ElementsAreMatcherImpl : public MatcherInterface<Container> {
|
||||
}
|
||||
|
||||
if (!match) {
|
||||
mismatch_found = true;
|
||||
unmatched_found = true;
|
||||
// We cannot store the iterator for the unmatched element to be used
|
||||
// later, as some users use ElementsAre() with a "container" whose
|
||||
// iterator is not copy-constructible or copy-assignable.
|
||||
//
|
||||
// We cannot store a pointer to the element either, as some container's
|
||||
// iterators return a temporary.
|
||||
//
|
||||
// We cannot store the element itself either, as the element may not be
|
||||
// copyable.
|
||||
//
|
||||
// Therefore, we just remember the index of the unmatched element,
|
||||
// and use it later to print the unmatched element.
|
||||
break;
|
||||
}
|
||||
}
|
||||
// If mismatch_found is true, 'exam_pos' is the index of the mismatch.
|
||||
// If unmatched_found is true, exam_pos is the index of the mismatch.
|
||||
|
||||
// Find how many elements the actual container has. We avoid
|
||||
// calling size() s.t. this code works for stream-like "containers"
|
||||
@@ -3521,10 +3661,27 @@ class ElementsAreMatcherImpl : public MatcherInterface<Container> {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (mismatch_found) {
|
||||
if (unmatched_found) {
|
||||
// The element count matches, but the exam_pos-th element doesn't match.
|
||||
if (listener_interested) {
|
||||
*listener << "whose element #" << exam_pos << " doesn't match";
|
||||
// Find the unmatched element.
|
||||
auto unmatched_it = stl_container.begin();
|
||||
// We cannot call std::advance() on the iterator, as some users use
|
||||
// ElementsAre() with a "container" whose iterator is incompatible with
|
||||
// std::advance() (e.g. it may not have the difference_type member
|
||||
// type).
|
||||
for (size_t i = 0; i != exam_pos; ++i) {
|
||||
++unmatched_it;
|
||||
}
|
||||
|
||||
// If the array is long or the elements' print-out is large, it may be
|
||||
// hard for the user to find the mismatched element and its
|
||||
// corresponding matcher description. Therefore we print the index, the
|
||||
// value of the mismatched element, and the corresponding matcher
|
||||
// description to ease debugging.
|
||||
*listener << "whose element #" << exam_pos << " ("
|
||||
<< PrintToString(*unmatched_it) << ") ";
|
||||
matchers_[exam_pos].DescribeNegationTo(listener->stream());
|
||||
PrintIfNotEmpty(explanations[exam_pos], listener->stream());
|
||||
}
|
||||
return false;
|
||||
@@ -3930,15 +4087,15 @@ GTEST_API_ std::string FormatMatcherDescription(
|
||||
// Overloads to support `OptionalMatcher` being used with a type that either
|
||||
// supports implicit conversion to bool or a `has_value()` method.
|
||||
template <typename Optional>
|
||||
auto IsOptionalEngaged(const Optional& optional,
|
||||
Rank1) -> decltype(!!optional) {
|
||||
auto IsOptionalEngaged(const Optional& optional, Rank1)
|
||||
-> decltype(!!optional) {
|
||||
// The use of double-negation here is to preserve historical behavior where
|
||||
// the matcher used `operator!` rather than directly using `operator bool`.
|
||||
return !static_cast<bool>(!optional);
|
||||
}
|
||||
template <typename Optional>
|
||||
auto IsOptionalEngaged(const Optional& optional,
|
||||
Rank0) -> decltype(!optional.has_value()) {
|
||||
auto IsOptionalEngaged(const Optional& optional, Rank0)
|
||||
-> decltype(!optional.has_value()) {
|
||||
return optional.has_value();
|
||||
}
|
||||
|
||||
@@ -3979,6 +4136,10 @@ class OptionalMatcher {
|
||||
return false;
|
||||
}
|
||||
const ValueType& value = *optional;
|
||||
if (!listener->IsInterested()) {
|
||||
// Fast path to avoid unnecessary generation of match explanation.
|
||||
return value_matcher_.Matches(value);
|
||||
}
|
||||
StringMatchResultListener value_listener;
|
||||
const bool match = value_matcher_.MatchAndExplain(value, &value_listener);
|
||||
*listener << "whose value " << PrintToString(value)
|
||||
@@ -4365,6 +4526,42 @@ inline internal::FloatingEqMatcher<double> DoubleNear(double rhs,
|
||||
return internal::FloatingEqMatcher<double>(rhs, false, max_abs_error);
|
||||
}
|
||||
|
||||
// The DistanceFrom(target, get_distance, m) and DistanceFrom(target, m)
|
||||
// matchers work on arbitrary types that have the "distance" concept. What they
|
||||
// do:
|
||||
//
|
||||
// 1. compute the distance between the value and the target using
|
||||
// get_distance(value, target) if get_distance is provided; otherwise compute
|
||||
// the distance as abs(value - target).
|
||||
// 2. match the distance against the user-provided matcher m; if the match
|
||||
// succeeds, the DistanceFrom() match succeeds.
|
||||
//
|
||||
// Examples:
|
||||
//
|
||||
// // 0.5's distance from 0.6 should be <= 0.2.
|
||||
// EXPECT_THAT(0.5, DistanceFrom(0.6, Le(0.2)));
|
||||
//
|
||||
// Vector2D v1(3.0, 4.0), v2(3.2, 6.0);
|
||||
// // v1's distance from v2, as computed by EuclideanDistance(v1, v2),
|
||||
// // should be >= 1.0.
|
||||
// EXPECT_THAT(v1, DistanceFrom(v2, EuclideanDistance, Ge(1.0)));
|
||||
|
||||
template <typename T, typename GetDistance, typename DistanceMatcher>
|
||||
inline internal::DistanceFromMatcher<T, GetDistance, DistanceMatcher>
|
||||
DistanceFrom(T target, GetDistance get_distance,
|
||||
DistanceMatcher distance_matcher) {
|
||||
return internal::DistanceFromMatcher<T, GetDistance, DistanceMatcher>(
|
||||
std::move(target), std::move(get_distance), std::move(distance_matcher));
|
||||
}
|
||||
|
||||
template <typename T, typename DistanceMatcher>
|
||||
inline internal::DistanceFromMatcher<T, internal::DefaultGetDistance,
|
||||
DistanceMatcher>
|
||||
DistanceFrom(T target, DistanceMatcher distance_matcher) {
|
||||
return DistanceFrom(std::move(target), internal::DefaultGetDistance(),
|
||||
std::move(distance_matcher));
|
||||
}
|
||||
|
||||
// Creates a matcher that matches any double argument approximately equal to
|
||||
// rhs, up to the specified max absolute error bound, including NaN values when
|
||||
// rhs is NaN. The max absolute error bound must be non-negative.
|
||||
@@ -4430,7 +4627,7 @@ WhenDynamicCastTo(const Matcher<To>& inner_matcher) {
|
||||
// matches a Foo object x if and only if x.number >= 5.
|
||||
template <typename Class, typename FieldType, typename FieldMatcher>
|
||||
inline PolymorphicMatcher<internal::FieldMatcher<Class, FieldType>> Field(
|
||||
FieldType Class::*field, const FieldMatcher& matcher) {
|
||||
FieldType Class::* field, const FieldMatcher& matcher) {
|
||||
return MakePolymorphicMatcher(internal::FieldMatcher<Class, FieldType>(
|
||||
field, MatcherCast<const FieldType&>(matcher)));
|
||||
// The call to MatcherCast() is required for supporting inner
|
||||
@@ -4443,7 +4640,7 @@ inline PolymorphicMatcher<internal::FieldMatcher<Class, FieldType>> Field(
|
||||
// messages.
|
||||
template <typename Class, typename FieldType, typename FieldMatcher>
|
||||
inline PolymorphicMatcher<internal::FieldMatcher<Class, FieldType>> Field(
|
||||
const std::string& field_name, FieldType Class::*field,
|
||||
const std::string& field_name, FieldType Class::* field,
|
||||
const FieldMatcher& matcher) {
|
||||
return MakePolymorphicMatcher(internal::FieldMatcher<Class, FieldType>(
|
||||
field_name, field, MatcherCast<const FieldType&>(matcher)));
|
||||
@@ -4453,6 +4650,10 @@ inline PolymorphicMatcher<internal::FieldMatcher<Class, FieldType>> Field(
|
||||
// matches 'matcher'. For example,
|
||||
// Property(&Foo::str, StartsWith("hi"))
|
||||
// matches a Foo object x if and only if x.str() starts with "hi".
|
||||
//
|
||||
// Warning: Don't use `Property()` against member functions that you do not
|
||||
// own, because taking addresses of functions is fragile and generally not part
|
||||
// of the contract of the function.
|
||||
template <typename Class, typename PropertyType, typename PropertyMatcher>
|
||||
inline PolymorphicMatcher<internal::PropertyMatcher<
|
||||
Class, PropertyType, PropertyType (Class::*)() const>>
|
||||
@@ -5551,8 +5752,7 @@ PolymorphicMatcher<internal::ExceptionMatcherImpl<Err>> ThrowsMessage(
|
||||
template <typename arg_type> \
|
||||
bool name##Matcher::gmock_Impl<arg_type>::MatchAndExplain( \
|
||||
const arg_type& arg, \
|
||||
GTEST_INTERNAL_ATTRIBUTE_MAYBE_UNUSED ::testing::MatchResultListener* \
|
||||
result_listener) const
|
||||
[[maybe_unused]] ::testing::MatchResultListener* result_listener) const
|
||||
|
||||
#define MATCHER_P(name, p0, description) \
|
||||
GMOCK_INTERNAL_MATCHER(name, name##MatcherP, description, (#p0), (p0))
|
||||
@@ -5637,8 +5837,8 @@ PolymorphicMatcher<internal::ExceptionMatcherImpl<Err>> ThrowsMessage(
|
||||
bool full_name<GMOCK_INTERNAL_MATCHER_TYPE_PARAMS(args)>:: \
|
||||
gmock_Impl<arg_type>::MatchAndExplain( \
|
||||
const arg_type& arg, \
|
||||
GTEST_INTERNAL_ATTRIBUTE_MAYBE_UNUSED ::testing:: \
|
||||
MatchResultListener* result_listener) const
|
||||
[[maybe_unused]] ::testing::MatchResultListener* result_listener) \
|
||||
const
|
||||
|
||||
#define GMOCK_INTERNAL_MATCHER_TEMPLATE_PARAMS(args) \
|
||||
GMOCK_PP_TAIL( \
|
||||
|
||||
@@ -521,9 +521,8 @@
|
||||
GMOCK_INTERNAL_DECL_##value_params) \
|
||||
GMOCK_PP_IF(GMOCK_PP_IS_EMPTY(GMOCK_INTERNAL_COUNT_##value_params), \
|
||||
= default; \
|
||||
, \
|
||||
: impl_(std::make_shared<gmock_Impl>( \
|
||||
GMOCK_INTERNAL_LIST_##value_params)){}) \
|
||||
, : impl_(std::make_shared<gmock_Impl>( \
|
||||
GMOCK_INTERNAL_LIST_##value_params)){}) \
|
||||
GMOCK_ACTION_CLASS_(name, value_params)(const GMOCK_ACTION_CLASS_( \
|
||||
name, value_params) &) noexcept GMOCK_INTERNAL_DEFN_COPY_ \
|
||||
##value_params \
|
||||
@@ -551,10 +550,10 @@
|
||||
}; \
|
||||
template <GMOCK_INTERNAL_DECL_##template_params \
|
||||
GMOCK_INTERNAL_DECL_TYPE_##value_params> \
|
||||
GMOCK_ACTION_CLASS_( \
|
||||
[[nodiscard]] GMOCK_ACTION_CLASS_( \
|
||||
name, value_params)<GMOCK_INTERNAL_LIST_##template_params \
|
||||
GMOCK_INTERNAL_LIST_TYPE_##value_params> \
|
||||
name(GMOCK_INTERNAL_DECL_##value_params) GTEST_MUST_USE_RESULT_; \
|
||||
name(GMOCK_INTERNAL_DECL_##value_params); \
|
||||
template <GMOCK_INTERNAL_DECL_##template_params \
|
||||
GMOCK_INTERNAL_DECL_TYPE_##value_params> \
|
||||
inline GMOCK_ACTION_CLASS_( \
|
||||
|
||||
@@ -467,11 +467,6 @@ struct Function<R(Args...)> {
|
||||
using MakeResultIgnoredValue = IgnoredValue(Args...);
|
||||
};
|
||||
|
||||
#ifdef GTEST_INTERNAL_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
template <typename R, typename... Args>
|
||||
constexpr size_t Function<R(Args...)>::ArgumentCount;
|
||||
#endif
|
||||
|
||||
// Workaround for MSVC error C2039: 'type': is not a member of 'std'
|
||||
// when std::tuple_element is used.
|
||||
// See: https://github.com/google/googletest/issues/3931
|
||||
|
||||
6
3rdparty/googletest/googletest/README.md
vendored
6
3rdparty/googletest/googletest/README.md
vendored
@@ -25,7 +25,7 @@ When building GoogleTest as a standalone project, the typical workflow starts
|
||||
with
|
||||
|
||||
```
|
||||
git clone https://github.com/google/googletest.git -b v1.16.0
|
||||
git clone https://github.com/google/googletest.git -b v1.17.0
|
||||
cd googletest # Main directory of the cloned repository.
|
||||
mkdir build # Create a directory to hold the build output.
|
||||
cd build
|
||||
@@ -124,9 +124,9 @@ match the project in which it is included.
|
||||
|
||||
#### C++ Standard Version
|
||||
|
||||
An environment that supports C++14 is required in order to successfully build
|
||||
An environment that supports C++17 is required in order to successfully build
|
||||
GoogleTest. One way to ensure this is to specify the standard in the top-level
|
||||
project, for example by using the `set(CMAKE_CXX_STANDARD 14)` command along
|
||||
project, for example by using the `set(CMAKE_CXX_STANDARD 17)` command along
|
||||
with `set(CMAKE_CXX_STANDARD_REQUIRED ON)`. If this is not feasible, for example
|
||||
in a C project using GoogleTest for validation, then it can be specified by
|
||||
adding it to the options for cmake via the`-DCMAKE_CXX_FLAGS` option.
|
||||
|
||||
@@ -129,6 +129,13 @@ namespace testing {
|
||||
//
|
||||
// Expected: Foo() is even
|
||||
// Actual: it's 5
|
||||
//
|
||||
|
||||
// Returned AssertionResult objects may not be ignored.
|
||||
// Note: Disabled for SWIG as it doesn't parse attributes correctly.
|
||||
#if !defined(SWIG)
|
||||
class [[nodiscard]] AssertionResult;
|
||||
#endif // !SWIG
|
||||
|
||||
class GTEST_API_ AssertionResult {
|
||||
public:
|
||||
|
||||
@@ -174,6 +174,7 @@ TEST_P(DerivedTest, DoesBlah) {
|
||||
|
||||
#endif // 0
|
||||
|
||||
#include <functional>
|
||||
#include <iterator>
|
||||
#include <utility>
|
||||
|
||||
@@ -413,7 +414,8 @@ internal::CartesianProductHolder<Generator...> Combine(const Generator&... g) {
|
||||
// Synopsis:
|
||||
// ConvertGenerator<T>(gen)
|
||||
// - returns a generator producing the same elements as generated by gen, but
|
||||
// each element is static_cast to type T before being returned
|
||||
// each T-typed element is static_cast to a type deduced from the interface
|
||||
// that accepts this generator, and then returned
|
||||
//
|
||||
// It is useful when using the Combine() function to get the generated
|
||||
// parameters in a custom type instead of std::tuple
|
||||
@@ -441,10 +443,65 @@ internal::CartesianProductHolder<Generator...> Combine(const Generator&... g) {
|
||||
// Combine(Values("cat", "dog"),
|
||||
// Values(BLACK, WHITE))));
|
||||
//
|
||||
template <typename T>
|
||||
internal::ParamConverterGenerator<T> ConvertGenerator(
|
||||
internal::ParamGenerator<T> gen) {
|
||||
return internal::ParamConverterGenerator<T>(gen);
|
||||
template <typename RequestedT>
|
||||
internal::ParamConverterGenerator<RequestedT> ConvertGenerator(
|
||||
internal::ParamGenerator<RequestedT> gen) {
|
||||
return internal::ParamConverterGenerator<RequestedT>(std::move(gen));
|
||||
}
|
||||
|
||||
// As above, but takes a callable as a second argument. The callable converts
|
||||
// the generated parameter to the test fixture's parameter type. This allows you
|
||||
// to use a parameter type that does not have a converting constructor from the
|
||||
// generated type.
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// This will instantiate tests in test suite AnimalTest each one with
|
||||
// the parameter values tuple("cat", BLACK), tuple("cat", WHITE),
|
||||
// tuple("dog", BLACK), and tuple("dog", WHITE):
|
||||
//
|
||||
// enum Color { BLACK, GRAY, WHITE };
|
||||
// struct ParamType {
|
||||
// std::string animal;
|
||||
// Color color;
|
||||
// };
|
||||
// class AnimalTest
|
||||
// : public testing::TestWithParam<ParamType> {...};
|
||||
//
|
||||
// TEST_P(AnimalTest, AnimalLooksNice) {...}
|
||||
//
|
||||
// INSTANTIATE_TEST_SUITE_P(
|
||||
// AnimalVariations, AnimalTest,
|
||||
// ConvertGenerator(Combine(Values("cat", "dog"), Values(BLACK, WHITE)),
|
||||
// [](std::tuple<std::string, Color> t) {
|
||||
// return ParamType{.animal = std::get<0>(t),
|
||||
// .color = std::get<1>(t)};
|
||||
// }));
|
||||
//
|
||||
template <typename T, int&... ExplicitArgumentBarrier, typename Gen,
|
||||
typename Func,
|
||||
typename StdFunction = decltype(std::function(std::declval<Func>()))>
|
||||
internal::ParamConverterGenerator<T, StdFunction> ConvertGenerator(Gen&& gen,
|
||||
Func&& f) {
|
||||
return internal::ParamConverterGenerator<T, StdFunction>(
|
||||
std::forward<Gen>(gen), std::forward<Func>(f));
|
||||
}
|
||||
|
||||
// As above, but infers the T from the supplied std::function instead of
|
||||
// having the caller specify it.
|
||||
template <int&... ExplicitArgumentBarrier, typename Gen, typename Func,
|
||||
typename StdFunction = decltype(std::function(std::declval<Func>()))>
|
||||
auto ConvertGenerator(Gen&& gen, Func&& f) {
|
||||
constexpr bool is_single_arg_std_function =
|
||||
internal::IsSingleArgStdFunction<StdFunction>::value;
|
||||
if constexpr (is_single_arg_std_function) {
|
||||
return ConvertGenerator<
|
||||
typename internal::FuncSingleParamType<StdFunction>::type>(
|
||||
std::forward<Gen>(gen), std::forward<Func>(f));
|
||||
} else {
|
||||
static_assert(is_single_arg_std_function,
|
||||
"The call signature must contain a single argument.");
|
||||
}
|
||||
}
|
||||
|
||||
#define TEST_P(test_suite_name, test_name) \
|
||||
@@ -469,7 +526,7 @@ internal::ParamConverterGenerator<T> ConvertGenerator(
|
||||
::testing::internal::CodeLocation(__FILE__, __LINE__)); \
|
||||
return 0; \
|
||||
} \
|
||||
GTEST_INTERNAL_ATTRIBUTE_MAYBE_UNUSED static int gtest_registering_dummy_; \
|
||||
[[maybe_unused]] static int gtest_registering_dummy_; \
|
||||
}; \
|
||||
int GTEST_TEST_CLASS_NAME_(test_suite_name, \
|
||||
test_name)::gtest_registering_dummy_ = \
|
||||
@@ -493,39 +550,38 @@ internal::ParamConverterGenerator<T> ConvertGenerator(
|
||||
#define GTEST_GET_FIRST_(first, ...) first
|
||||
#define GTEST_GET_SECOND_(first, second, ...) second
|
||||
|
||||
#define INSTANTIATE_TEST_SUITE_P(prefix, test_suite_name, ...) \
|
||||
static ::testing::internal::ParamGenerator<test_suite_name::ParamType> \
|
||||
gtest_##prefix##test_suite_name##_EvalGenerator_() { \
|
||||
return GTEST_EXPAND_(GTEST_GET_FIRST_(__VA_ARGS__, DUMMY_PARAM_)); \
|
||||
} \
|
||||
static ::std::string gtest_##prefix##test_suite_name##_EvalGenerateName_( \
|
||||
const ::testing::TestParamInfo<test_suite_name::ParamType>& info) { \
|
||||
if (::testing::internal::AlwaysFalse()) { \
|
||||
::testing::internal::TestNotEmpty(GTEST_EXPAND_(GTEST_GET_SECOND_( \
|
||||
__VA_ARGS__, \
|
||||
::testing::internal::DefaultParamName<test_suite_name::ParamType>, \
|
||||
DUMMY_PARAM_))); \
|
||||
auto t = std::make_tuple(__VA_ARGS__); \
|
||||
static_assert(std::tuple_size<decltype(t)>::value <= 2, \
|
||||
"Too Many Args!"); \
|
||||
} \
|
||||
return ((GTEST_EXPAND_(GTEST_GET_SECOND_( \
|
||||
__VA_ARGS__, \
|
||||
::testing::internal::DefaultParamName<test_suite_name::ParamType>, \
|
||||
DUMMY_PARAM_))))(info); \
|
||||
} \
|
||||
GTEST_INTERNAL_ATTRIBUTE_MAYBE_UNUSED static int \
|
||||
gtest_##prefix##test_suite_name##_dummy_ = \
|
||||
::testing::UnitTest::GetInstance() \
|
||||
->parameterized_test_registry() \
|
||||
.GetTestSuitePatternHolder<test_suite_name>( \
|
||||
GTEST_STRINGIFY_(test_suite_name), \
|
||||
::testing::internal::CodeLocation(__FILE__, __LINE__)) \
|
||||
->AddTestSuiteInstantiation( \
|
||||
GTEST_STRINGIFY_(prefix), \
|
||||
>est_##prefix##test_suite_name##_EvalGenerator_, \
|
||||
>est_##prefix##test_suite_name##_EvalGenerateName_, \
|
||||
__FILE__, __LINE__)
|
||||
#define INSTANTIATE_TEST_SUITE_P(prefix, test_suite_name, ...) \
|
||||
static ::testing::internal::ParamGenerator<test_suite_name::ParamType> \
|
||||
gtest_##prefix##test_suite_name##_EvalGenerator_() { \
|
||||
return GTEST_EXPAND_(GTEST_GET_FIRST_(__VA_ARGS__, DUMMY_PARAM_)); \
|
||||
} \
|
||||
static ::std::string gtest_##prefix##test_suite_name##_EvalGenerateName_( \
|
||||
const ::testing::TestParamInfo<test_suite_name::ParamType>& info) { \
|
||||
if (::testing::internal::AlwaysFalse()) { \
|
||||
::testing::internal::TestNotEmpty(GTEST_EXPAND_(GTEST_GET_SECOND_( \
|
||||
__VA_ARGS__, \
|
||||
::testing::internal::DefaultParamName<test_suite_name::ParamType>, \
|
||||
DUMMY_PARAM_))); \
|
||||
auto t = std::make_tuple(__VA_ARGS__); \
|
||||
static_assert(std::tuple_size<decltype(t)>::value <= 2, \
|
||||
"Too Many Args!"); \
|
||||
} \
|
||||
return ((GTEST_EXPAND_(GTEST_GET_SECOND_( \
|
||||
__VA_ARGS__, \
|
||||
::testing::internal::DefaultParamName<test_suite_name::ParamType>, \
|
||||
DUMMY_PARAM_))))(info); \
|
||||
} \
|
||||
[[maybe_unused]] static int gtest_##prefix##test_suite_name##_dummy_ = \
|
||||
::testing::UnitTest::GetInstance() \
|
||||
->parameterized_test_registry() \
|
||||
.GetTestSuitePatternHolder<test_suite_name>( \
|
||||
GTEST_STRINGIFY_(test_suite_name), \
|
||||
::testing::internal::CodeLocation(__FILE__, __LINE__)) \
|
||||
->AddTestSuiteInstantiation( \
|
||||
GTEST_STRINGIFY_(prefix), \
|
||||
>est_##prefix##test_suite_name##_EvalGenerator_, \
|
||||
>est_##prefix##test_suite_name##_EvalGenerateName_, __FILE__, \
|
||||
__LINE__)
|
||||
|
||||
// Allow Marking a Parameterized test class as not needing to be instantiated.
|
||||
#define GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(T) \
|
||||
|
||||
@@ -194,34 +194,33 @@ INSTANTIATE_TYPED_TEST_SUITE_P(My, FooTest, MyTypes);
|
||||
typedef ::testing::internal::NameGeneratorSelector<__VA_ARGS__>::type \
|
||||
GTEST_NAME_GENERATOR_(CaseName)
|
||||
|
||||
#define TYPED_TEST(CaseName, TestName) \
|
||||
static_assert(sizeof(GTEST_STRINGIFY_(TestName)) > 1, \
|
||||
"test-name must not be empty"); \
|
||||
template <typename gtest_TypeParam_> \
|
||||
class GTEST_TEST_CLASS_NAME_(CaseName, TestName) \
|
||||
: public CaseName<gtest_TypeParam_> { \
|
||||
private: \
|
||||
typedef CaseName<gtest_TypeParam_> TestFixture; \
|
||||
typedef gtest_TypeParam_ TypeParam; \
|
||||
void TestBody() override; \
|
||||
}; \
|
||||
GTEST_INTERNAL_ATTRIBUTE_MAYBE_UNUSED static bool \
|
||||
gtest_##CaseName##_##TestName##_registered_ = \
|
||||
::testing::internal::TypeParameterizedTest< \
|
||||
CaseName, \
|
||||
::testing::internal::TemplateSel<GTEST_TEST_CLASS_NAME_( \
|
||||
CaseName, TestName)>, \
|
||||
GTEST_TYPE_PARAMS_( \
|
||||
CaseName)>::Register("", \
|
||||
::testing::internal::CodeLocation( \
|
||||
__FILE__, __LINE__), \
|
||||
GTEST_STRINGIFY_(CaseName), \
|
||||
GTEST_STRINGIFY_(TestName), 0, \
|
||||
::testing::internal::GenerateNames< \
|
||||
GTEST_NAME_GENERATOR_(CaseName), \
|
||||
GTEST_TYPE_PARAMS_(CaseName)>()); \
|
||||
template <typename gtest_TypeParam_> \
|
||||
void GTEST_TEST_CLASS_NAME_(CaseName, \
|
||||
#define TYPED_TEST(CaseName, TestName) \
|
||||
static_assert(sizeof(GTEST_STRINGIFY_(TestName)) > 1, \
|
||||
"test-name must not be empty"); \
|
||||
template <typename gtest_TypeParam_> \
|
||||
class GTEST_TEST_CLASS_NAME_(CaseName, TestName) \
|
||||
: public CaseName<gtest_TypeParam_> { \
|
||||
private: \
|
||||
typedef CaseName<gtest_TypeParam_> TestFixture; \
|
||||
typedef gtest_TypeParam_ TypeParam; \
|
||||
void TestBody() override; \
|
||||
}; \
|
||||
[[maybe_unused]] static bool gtest_##CaseName##_##TestName##_registered_ = \
|
||||
::testing::internal::TypeParameterizedTest< \
|
||||
CaseName, \
|
||||
::testing::internal::TemplateSel<GTEST_TEST_CLASS_NAME_(CaseName, \
|
||||
TestName)>, \
|
||||
GTEST_TYPE_PARAMS_( \
|
||||
CaseName)>::Register("", \
|
||||
::testing::internal::CodeLocation( \
|
||||
__FILE__, __LINE__), \
|
||||
GTEST_STRINGIFY_(CaseName), \
|
||||
GTEST_STRINGIFY_(TestName), 0, \
|
||||
::testing::internal::GenerateNames< \
|
||||
GTEST_NAME_GENERATOR_(CaseName), \
|
||||
GTEST_TYPE_PARAMS_(CaseName)>()); \
|
||||
template <typename gtest_TypeParam_> \
|
||||
void GTEST_TEST_CLASS_NAME_(CaseName, \
|
||||
TestName)<gtest_TypeParam_>::TestBody()
|
||||
|
||||
// Legacy API is deprecated but still available
|
||||
@@ -268,23 +267,22 @@ INSTANTIATE_TYPED_TEST_SUITE_P(My, FooTest, MyTypes);
|
||||
TYPED_TEST_SUITE_P
|
||||
#endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_
|
||||
|
||||
#define TYPED_TEST_P(SuiteName, TestName) \
|
||||
namespace GTEST_SUITE_NAMESPACE_(SuiteName) { \
|
||||
template <typename gtest_TypeParam_> \
|
||||
class TestName : public SuiteName<gtest_TypeParam_> { \
|
||||
private: \
|
||||
typedef SuiteName<gtest_TypeParam_> TestFixture; \
|
||||
typedef gtest_TypeParam_ TypeParam; \
|
||||
void TestBody() override; \
|
||||
}; \
|
||||
GTEST_INTERNAL_ATTRIBUTE_MAYBE_UNUSED static bool \
|
||||
gtest_##TestName##_defined_ = \
|
||||
GTEST_TYPED_TEST_SUITE_P_STATE_(SuiteName).AddTestName( \
|
||||
__FILE__, __LINE__, GTEST_STRINGIFY_(SuiteName), \
|
||||
GTEST_STRINGIFY_(TestName)); \
|
||||
} \
|
||||
template <typename gtest_TypeParam_> \
|
||||
void GTEST_SUITE_NAMESPACE_( \
|
||||
#define TYPED_TEST_P(SuiteName, TestName) \
|
||||
namespace GTEST_SUITE_NAMESPACE_(SuiteName) { \
|
||||
template <typename gtest_TypeParam_> \
|
||||
class TestName : public SuiteName<gtest_TypeParam_> { \
|
||||
private: \
|
||||
typedef SuiteName<gtest_TypeParam_> TestFixture; \
|
||||
typedef gtest_TypeParam_ TypeParam; \
|
||||
void TestBody() override; \
|
||||
}; \
|
||||
[[maybe_unused]] static bool gtest_##TestName##_defined_ = \
|
||||
GTEST_TYPED_TEST_SUITE_P_STATE_(SuiteName).AddTestName( \
|
||||
__FILE__, __LINE__, GTEST_STRINGIFY_(SuiteName), \
|
||||
GTEST_STRINGIFY_(TestName)); \
|
||||
} \
|
||||
template <typename gtest_TypeParam_> \
|
||||
void GTEST_SUITE_NAMESPACE_( \
|
||||
SuiteName)::TestName<gtest_TypeParam_>::TestBody()
|
||||
|
||||
// Note: this won't work correctly if the trailing arguments are macros.
|
||||
@@ -292,8 +290,8 @@ INSTANTIATE_TYPED_TEST_SUITE_P(My, FooTest, MyTypes);
|
||||
namespace GTEST_SUITE_NAMESPACE_(SuiteName) { \
|
||||
typedef ::testing::internal::Templates<__VA_ARGS__> gtest_AllTests_; \
|
||||
} \
|
||||
GTEST_INTERNAL_ATTRIBUTE_MAYBE_UNUSED static const char* const \
|
||||
GTEST_REGISTERED_TEST_NAMES_(SuiteName) = \
|
||||
[[maybe_unused]] static const char* const GTEST_REGISTERED_TEST_NAMES_( \
|
||||
SuiteName) = \
|
||||
GTEST_TYPED_TEST_SUITE_P_STATE_(SuiteName).VerifyRegisteredTestNames( \
|
||||
GTEST_STRINGIFY_(SuiteName), __FILE__, __LINE__, #__VA_ARGS__)
|
||||
|
||||
@@ -305,24 +303,22 @@ INSTANTIATE_TYPED_TEST_SUITE_P(My, FooTest, MyTypes);
|
||||
REGISTER_TYPED_TEST_SUITE_P
|
||||
#endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_
|
||||
|
||||
#define INSTANTIATE_TYPED_TEST_SUITE_P(Prefix, SuiteName, Types, ...) \
|
||||
static_assert(sizeof(GTEST_STRINGIFY_(Prefix)) > 1, \
|
||||
"test-suit-prefix must not be empty"); \
|
||||
GTEST_INTERNAL_ATTRIBUTE_MAYBE_UNUSED static bool \
|
||||
gtest_##Prefix##_##SuiteName = \
|
||||
::testing::internal::TypeParameterizedTestSuite< \
|
||||
SuiteName, GTEST_SUITE_NAMESPACE_(SuiteName)::gtest_AllTests_, \
|
||||
::testing::internal::GenerateTypeList<Types>::type>:: \
|
||||
Register( \
|
||||
GTEST_STRINGIFY_(Prefix), \
|
||||
::testing::internal::CodeLocation(__FILE__, __LINE__), \
|
||||
>EST_TYPED_TEST_SUITE_P_STATE_(SuiteName), \
|
||||
GTEST_STRINGIFY_(SuiteName), \
|
||||
GTEST_REGISTERED_TEST_NAMES_(SuiteName), \
|
||||
::testing::internal::GenerateNames< \
|
||||
::testing::internal::NameGeneratorSelector< \
|
||||
__VA_ARGS__>::type, \
|
||||
::testing::internal::GenerateTypeList<Types>::type>())
|
||||
#define INSTANTIATE_TYPED_TEST_SUITE_P(Prefix, SuiteName, Types, ...) \
|
||||
static_assert(sizeof(GTEST_STRINGIFY_(Prefix)) > 1, \
|
||||
"test-suit-prefix must not be empty"); \
|
||||
[[maybe_unused]] static bool gtest_##Prefix##_##SuiteName = \
|
||||
::testing::internal::TypeParameterizedTestSuite< \
|
||||
SuiteName, GTEST_SUITE_NAMESPACE_(SuiteName)::gtest_AllTests_, \
|
||||
::testing::internal::GenerateTypeList<Types>::type>:: \
|
||||
Register(GTEST_STRINGIFY_(Prefix), \
|
||||
::testing::internal::CodeLocation(__FILE__, __LINE__), \
|
||||
>EST_TYPED_TEST_SUITE_P_STATE_(SuiteName), \
|
||||
GTEST_STRINGIFY_(SuiteName), \
|
||||
GTEST_REGISTERED_TEST_NAMES_(SuiteName), \
|
||||
::testing::internal::GenerateNames< \
|
||||
::testing::internal::NameGeneratorSelector< \
|
||||
__VA_ARGS__>::type, \
|
||||
::testing::internal::GenerateTypeList<Types>::type>())
|
||||
|
||||
// Legacy API is deprecated but still available
|
||||
#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
|
||||
|
||||
@@ -1123,7 +1123,7 @@ class GTEST_API_ UnitTest {
|
||||
// This method can only be called from the main thread.
|
||||
//
|
||||
// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
|
||||
int Run() GTEST_MUST_USE_RESULT_;
|
||||
[[nodiscard]] int Run();
|
||||
|
||||
// Returns the working directory when the first TEST() or TEST_F()
|
||||
// was executed. The UnitTest object owns the string.
|
||||
@@ -2329,7 +2329,7 @@ TestInfo* RegisterTest(const char* test_suite_name, const char* test_name,
|
||||
//
|
||||
// This function was formerly a macro; thus, it is in the global
|
||||
// namespace and has an all-caps name.
|
||||
int RUN_ALL_TESTS() GTEST_MUST_USE_RESULT_;
|
||||
[[nodiscard]] int RUN_ALL_TESTS();
|
||||
|
||||
inline int RUN_ALL_TESTS() { return ::testing::UnitTest::GetInstance()->Run(); }
|
||||
|
||||
|
||||
@@ -290,17 +290,17 @@ class FloatingPoint {
|
||||
// around may change its bits, although the new value is guaranteed
|
||||
// to be also a NAN. Therefore, don't expect this constructor to
|
||||
// preserve the bits in x when x is a NAN.
|
||||
explicit FloatingPoint(const RawType& x) { u_.value_ = x; }
|
||||
explicit FloatingPoint(RawType x) { memcpy(&bits_, &x, sizeof(x)); }
|
||||
|
||||
// Static methods
|
||||
|
||||
// Reinterprets a bit pattern as a floating-point number.
|
||||
//
|
||||
// This function is needed to test the AlmostEquals() method.
|
||||
static RawType ReinterpretBits(const Bits bits) {
|
||||
FloatingPoint fp(0);
|
||||
fp.u_.bits_ = bits;
|
||||
return fp.u_.value_;
|
||||
static RawType ReinterpretBits(Bits bits) {
|
||||
RawType fp;
|
||||
memcpy(&fp, &bits, sizeof(fp));
|
||||
return fp;
|
||||
}
|
||||
|
||||
// Returns the floating-point number that represent positive infinity.
|
||||
@@ -309,16 +309,16 @@ class FloatingPoint {
|
||||
// Non-static methods
|
||||
|
||||
// Returns the bits that represents this number.
|
||||
const Bits& bits() const { return u_.bits_; }
|
||||
const Bits& bits() const { return bits_; }
|
||||
|
||||
// Returns the exponent bits of this number.
|
||||
Bits exponent_bits() const { return kExponentBitMask & u_.bits_; }
|
||||
Bits exponent_bits() const { return kExponentBitMask & bits_; }
|
||||
|
||||
// Returns the fraction bits of this number.
|
||||
Bits fraction_bits() const { return kFractionBitMask & u_.bits_; }
|
||||
Bits fraction_bits() const { return kFractionBitMask & bits_; }
|
||||
|
||||
// Returns the sign bit of this number.
|
||||
Bits sign_bit() const { return kSignBitMask & u_.bits_; }
|
||||
Bits sign_bit() const { return kSignBitMask & bits_; }
|
||||
|
||||
// Returns true if and only if this is NAN (not a number).
|
||||
bool is_nan() const {
|
||||
@@ -332,23 +332,16 @@ class FloatingPoint {
|
||||
//
|
||||
// - returns false if either number is (or both are) NAN.
|
||||
// - treats really large numbers as almost equal to infinity.
|
||||
// - thinks +0.0 and -0.0 are 0 DLP's apart.
|
||||
// - thinks +0.0 and -0.0 are 0 ULP's apart.
|
||||
bool AlmostEquals(const FloatingPoint& rhs) const {
|
||||
// The IEEE standard says that any comparison operation involving
|
||||
// a NAN must return false.
|
||||
if (is_nan() || rhs.is_nan()) return false;
|
||||
|
||||
return DistanceBetweenSignAndMagnitudeNumbers(u_.bits_, rhs.u_.bits_) <=
|
||||
kMaxUlps;
|
||||
return DistanceBetweenSignAndMagnitudeNumbers(bits_, rhs.bits_) <= kMaxUlps;
|
||||
}
|
||||
|
||||
private:
|
||||
// The data type used to store the actual floating-point number.
|
||||
union FloatingPointUnion {
|
||||
RawType value_; // The raw floating-point number.
|
||||
Bits bits_; // The bits that represent the number.
|
||||
};
|
||||
|
||||
// Converts an integer from the sign-and-magnitude representation to
|
||||
// the biased representation. More precisely, let N be 2 to the
|
||||
// power of (kBitCount - 1), an integer x is represented by the
|
||||
@@ -364,7 +357,7 @@ class FloatingPoint {
|
||||
//
|
||||
// Read https://en.wikipedia.org/wiki/Signed_number_representations
|
||||
// for more details on signed number representations.
|
||||
static Bits SignAndMagnitudeToBiased(const Bits& sam) {
|
||||
static Bits SignAndMagnitudeToBiased(Bits sam) {
|
||||
if (kSignBitMask & sam) {
|
||||
// sam represents a negative number.
|
||||
return ~sam + 1;
|
||||
@@ -376,14 +369,13 @@ class FloatingPoint {
|
||||
|
||||
// Given two numbers in the sign-and-magnitude representation,
|
||||
// returns the distance between them as an unsigned number.
|
||||
static Bits DistanceBetweenSignAndMagnitudeNumbers(const Bits& sam1,
|
||||
const Bits& sam2) {
|
||||
static Bits DistanceBetweenSignAndMagnitudeNumbers(Bits sam1, Bits sam2) {
|
||||
const Bits biased1 = SignAndMagnitudeToBiased(sam1);
|
||||
const Bits biased2 = SignAndMagnitudeToBiased(sam2);
|
||||
return (biased1 >= biased2) ? (biased1 - biased2) : (biased2 - biased1);
|
||||
}
|
||||
|
||||
FloatingPointUnion u_;
|
||||
Bits bits_; // The bits that represent the number.
|
||||
};
|
||||
|
||||
// Typedefs the instances of the FloatingPoint template class that we
|
||||
@@ -894,11 +886,6 @@ class HasDebugStringAndShortDebugString {
|
||||
HasDebugStringType::value && HasShortDebugStringType::value;
|
||||
};
|
||||
|
||||
#ifdef GTEST_INTERNAL_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
template <typename T>
|
||||
constexpr bool HasDebugStringAndShortDebugString<T>::value;
|
||||
#endif
|
||||
|
||||
// When the compiler sees expression IsContainerTest<C>(0), if C is an
|
||||
// STL-style container class, the first overload of IsContainerTest
|
||||
// will be viable (since both C::iterator* and C::const_iterator* are
|
||||
@@ -1241,30 +1228,40 @@ class FlatTuple
|
||||
|
||||
// Utility functions to be called with static_assert to induce deprecation
|
||||
// warnings.
|
||||
GTEST_INTERNAL_DEPRECATED(
|
||||
[[deprecated(
|
||||
"INSTANTIATE_TEST_CASE_P is deprecated, please use "
|
||||
"INSTANTIATE_TEST_SUITE_P")
|
||||
constexpr bool InstantiateTestCase_P_IsDeprecated() { return true; }
|
||||
"INSTANTIATE_TEST_SUITE_P")]]
|
||||
constexpr bool InstantiateTestCase_P_IsDeprecated() {
|
||||
return true;
|
||||
}
|
||||
|
||||
GTEST_INTERNAL_DEPRECATED(
|
||||
[[deprecated(
|
||||
"TYPED_TEST_CASE_P is deprecated, please use "
|
||||
"TYPED_TEST_SUITE_P")
|
||||
constexpr bool TypedTestCase_P_IsDeprecated() { return true; }
|
||||
"TYPED_TEST_SUITE_P")]]
|
||||
constexpr bool TypedTestCase_P_IsDeprecated() {
|
||||
return true;
|
||||
}
|
||||
|
||||
GTEST_INTERNAL_DEPRECATED(
|
||||
[[deprecated(
|
||||
"TYPED_TEST_CASE is deprecated, please use "
|
||||
"TYPED_TEST_SUITE")
|
||||
constexpr bool TypedTestCaseIsDeprecated() { return true; }
|
||||
"TYPED_TEST_SUITE")]]
|
||||
constexpr bool TypedTestCaseIsDeprecated() {
|
||||
return true;
|
||||
}
|
||||
|
||||
GTEST_INTERNAL_DEPRECATED(
|
||||
[[deprecated(
|
||||
"REGISTER_TYPED_TEST_CASE_P is deprecated, please use "
|
||||
"REGISTER_TYPED_TEST_SUITE_P")
|
||||
constexpr bool RegisterTypedTestCase_P_IsDeprecated() { return true; }
|
||||
"REGISTER_TYPED_TEST_SUITE_P")]]
|
||||
constexpr bool RegisterTypedTestCase_P_IsDeprecated() {
|
||||
return true;
|
||||
}
|
||||
|
||||
GTEST_INTERNAL_DEPRECATED(
|
||||
[[deprecated(
|
||||
"INSTANTIATE_TYPED_TEST_CASE_P is deprecated, please use "
|
||||
"INSTANTIATE_TYPED_TEST_SUITE_P")
|
||||
constexpr bool InstantiateTypedTestCase_P_IsDeprecated() { return true; }
|
||||
"INSTANTIATE_TYPED_TEST_SUITE_P")]]
|
||||
constexpr bool InstantiateTypedTestCase_P_IsDeprecated() {
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
} // namespace testing
|
||||
@@ -1501,8 +1498,7 @@ class NeverThrown {
|
||||
\
|
||||
private: \
|
||||
void TestBody() override; \
|
||||
GTEST_INTERNAL_ATTRIBUTE_MAYBE_UNUSED static ::testing::TestInfo* const \
|
||||
test_info_; \
|
||||
[[maybe_unused]] static ::testing::TestInfo* const test_info_; \
|
||||
}; \
|
||||
\
|
||||
::testing::TestInfo* const GTEST_TEST_CLASS_NAME_(test_suite_name, \
|
||||
|
||||
@@ -39,6 +39,7 @@
|
||||
#include <ctype.h>
|
||||
|
||||
#include <cassert>
|
||||
#include <functional>
|
||||
#include <iterator>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
@@ -529,8 +530,7 @@ class ParameterizedTestSuiteInfo : public ParameterizedTestSuiteInfoBase {
|
||||
// prefix). test_base_name is the name of an individual test without
|
||||
// parameter index. For the test SequenceA/FooTest.DoBar/1 FooTest is
|
||||
// test suite base name and DoBar is test base name.
|
||||
void AddTestPattern(const char*,
|
||||
const char* test_base_name,
|
||||
void AddTestPattern(const char*, const char* test_base_name,
|
||||
TestMetaFactoryBase<ParamType>* meta_factory,
|
||||
CodeLocation code_location) {
|
||||
tests_.emplace_back(
|
||||
@@ -952,11 +952,11 @@ class CartesianProductHolder {
|
||||
std::tuple<Gen...> generators_;
|
||||
};
|
||||
|
||||
template <typename From, typename To>
|
||||
template <typename From, typename To, typename Func>
|
||||
class ParamGeneratorConverter : public ParamGeneratorInterface<To> {
|
||||
public:
|
||||
ParamGeneratorConverter(ParamGenerator<From> gen) // NOLINT
|
||||
: generator_(std::move(gen)) {}
|
||||
ParamGeneratorConverter(ParamGenerator<From> gen, Func converter) // NOLINT
|
||||
: generator_(std::move(gen)), converter_(std::move(converter)) {}
|
||||
|
||||
ParamIteratorInterface<To>* Begin() const override {
|
||||
return new Iterator(this, generator_.begin(), generator_.end());
|
||||
@@ -965,13 +965,21 @@ class ParamGeneratorConverter : public ParamGeneratorInterface<To> {
|
||||
return new Iterator(this, generator_.end(), generator_.end());
|
||||
}
|
||||
|
||||
// Returns the std::function wrapping the user-supplied converter callable. It
|
||||
// is used by the iterator (see class Iterator below) to convert the object
|
||||
// (of type FROM) returned by the ParamGenerator to an object of a type that
|
||||
// can be static_cast to type TO.
|
||||
const Func& TypeConverter() const { return converter_; }
|
||||
|
||||
private:
|
||||
class Iterator : public ParamIteratorInterface<To> {
|
||||
public:
|
||||
Iterator(const ParamGeneratorInterface<To>* base, ParamIterator<From> it,
|
||||
Iterator(const ParamGeneratorConverter* base, ParamIterator<From> it,
|
||||
ParamIterator<From> end)
|
||||
: base_(base), it_(it), end_(end) {
|
||||
if (it_ != end_) value_ = std::make_shared<To>(static_cast<To>(*it_));
|
||||
if (it_ != end_)
|
||||
value_ =
|
||||
std::make_shared<To>(static_cast<To>(base->TypeConverter()(*it_)));
|
||||
}
|
||||
~Iterator() override = default;
|
||||
|
||||
@@ -980,7 +988,9 @@ class ParamGeneratorConverter : public ParamGeneratorInterface<To> {
|
||||
}
|
||||
void Advance() override {
|
||||
++it_;
|
||||
if (it_ != end_) value_ = std::make_shared<To>(static_cast<To>(*it_));
|
||||
if (it_ != end_)
|
||||
value_ =
|
||||
std::make_shared<To>(static_cast<To>(base_->TypeConverter()(*it_)));
|
||||
}
|
||||
ParamIteratorInterface<To>* Clone() const override {
|
||||
return new Iterator(*this);
|
||||
@@ -1000,30 +1010,54 @@ class ParamGeneratorConverter : public ParamGeneratorInterface<To> {
|
||||
private:
|
||||
Iterator(const Iterator& other) = default;
|
||||
|
||||
const ParamGeneratorInterface<To>* const base_;
|
||||
const ParamGeneratorConverter* const base_;
|
||||
ParamIterator<From> it_;
|
||||
ParamIterator<From> end_;
|
||||
std::shared_ptr<To> value_;
|
||||
}; // class ParamGeneratorConverter::Iterator
|
||||
|
||||
ParamGenerator<From> generator_;
|
||||
Func converter_;
|
||||
}; // class ParamGeneratorConverter
|
||||
|
||||
template <class Gen>
|
||||
template <class GeneratedT,
|
||||
typename StdFunction =
|
||||
std::function<const GeneratedT&(const GeneratedT&)>>
|
||||
class ParamConverterGenerator {
|
||||
public:
|
||||
ParamConverterGenerator(ParamGenerator<Gen> g) // NOLINT
|
||||
: generator_(std::move(g)) {}
|
||||
ParamConverterGenerator(ParamGenerator<GeneratedT> g) // NOLINT
|
||||
: generator_(std::move(g)), converter_(Identity) {}
|
||||
|
||||
ParamConverterGenerator(ParamGenerator<GeneratedT> g, StdFunction converter)
|
||||
: generator_(std::move(g)), converter_(std::move(converter)) {}
|
||||
|
||||
template <typename T>
|
||||
operator ParamGenerator<T>() const { // NOLINT
|
||||
return ParamGenerator<T>(new ParamGeneratorConverter<Gen, T>(generator_));
|
||||
return ParamGenerator<T>(
|
||||
new ParamGeneratorConverter<GeneratedT, T, StdFunction>(generator_,
|
||||
converter_));
|
||||
}
|
||||
|
||||
private:
|
||||
ParamGenerator<Gen> generator_;
|
||||
static const GeneratedT& Identity(const GeneratedT& v) { return v; }
|
||||
|
||||
ParamGenerator<GeneratedT> generator_;
|
||||
StdFunction converter_;
|
||||
};
|
||||
|
||||
// Template to determine the param type of a single-param std::function.
|
||||
template <typename T>
|
||||
struct FuncSingleParamType;
|
||||
template <typename R, typename P>
|
||||
struct FuncSingleParamType<std::function<R(P)>> {
|
||||
using type = std::remove_cv_t<std::remove_reference_t<P>>;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct IsSingleArgStdFunction : public std::false_type {};
|
||||
template <typename R, typename P>
|
||||
struct IsSingleArgStdFunction<std::function<R(P)>> : public std::true_type {};
|
||||
|
||||
} // namespace internal
|
||||
} // namespace testing
|
||||
|
||||
|
||||
@@ -194,7 +194,6 @@
|
||||
//
|
||||
// Macros for basic C++ coding:
|
||||
// GTEST_AMBIGUOUS_ELSE_BLOCKER_ - for disabling a gcc warning.
|
||||
// GTEST_MUST_USE_RESULT_ - declares that a function's result must be used.
|
||||
// GTEST_INTENTIONAL_CONST_COND_PUSH_ - start code section where MSVC C4127 is
|
||||
// suppressed (constant conditional).
|
||||
// GTEST_INTENTIONAL_CONST_COND_POP_ - finish code section where MSVC C4127
|
||||
@@ -260,11 +259,6 @@
|
||||
// BoolFromGTestEnv() - parses a bool environment variable.
|
||||
// Int32FromGTestEnv() - parses an int32_t environment variable.
|
||||
// StringFromGTestEnv() - parses a string environment variable.
|
||||
//
|
||||
// Deprecation warnings:
|
||||
// GTEST_INTERNAL_DEPRECATED(message) - attribute marking a function as
|
||||
// deprecated; calling a marked function
|
||||
// should generate a compiler warning
|
||||
|
||||
// The definition of GTEST_INTERNAL_CPLUSPLUS_LANG comes first because it can
|
||||
// potentially be used as an #include guard.
|
||||
@@ -275,8 +269,8 @@
|
||||
#endif
|
||||
|
||||
#if !defined(GTEST_INTERNAL_CPLUSPLUS_LANG) || \
|
||||
GTEST_INTERNAL_CPLUSPLUS_LANG < 201402L
|
||||
#error C++ versions less than C++14 are not supported.
|
||||
GTEST_INTERNAL_CPLUSPLUS_LANG < 201703L
|
||||
#error C++ versions less than C++17 are not supported.
|
||||
#endif
|
||||
|
||||
// MSVC >= 19.11 (VS 2017 Update 3) supports __has_include.
|
||||
@@ -288,10 +282,14 @@
|
||||
|
||||
// Detect C++ feature test macros as gracefully as possible.
|
||||
// MSVC >= 19.15, Clang >= 3.4.1, and GCC >= 4.1.2 support feature test macros.
|
||||
#if GTEST_INTERNAL_CPLUSPLUS_LANG >= 202002L && \
|
||||
(!defined(__has_include) || GTEST_INTERNAL_HAS_INCLUDE(<version>))
|
||||
#include <version> // C++20 and later
|
||||
#elif (!defined(__has_include) || GTEST_INTERNAL_HAS_INCLUDE(<ciso646>))
|
||||
//
|
||||
// GCC15 warns that <ciso646> is deprecated in C++17 and suggests using
|
||||
// <version> instead, even though <version> is not available in C++17 mode prior
|
||||
// to GCC9.
|
||||
#if GTEST_INTERNAL_CPLUSPLUS_LANG >= 202002L || \
|
||||
GTEST_INTERNAL_HAS_INCLUDE(<version>)
|
||||
#include <version> // C++20 or <version> support.
|
||||
#else
|
||||
#include <ciso646> // Pre-C++20
|
||||
#endif
|
||||
|
||||
@@ -772,25 +770,6 @@ typedef struct _RTL_CRITICAL_SECTION GTEST_CRITICAL_SECTION;
|
||||
#define GTEST_HAVE_FEATURE_(x) 0
|
||||
#endif
|
||||
|
||||
// Use this annotation after a variable or parameter declaration to tell the
|
||||
// compiler the variable/parameter may be used.
|
||||
// Example:
|
||||
//
|
||||
// GTEST_INTERNAL_ATTRIBUTE_MAYBE_UNUSED int foo = bar();
|
||||
//
|
||||
// This can be removed once we only support only C++17 or newer and
|
||||
// [[maybe_unused]] is available on all supported platforms.
|
||||
#if GTEST_INTERNAL_HAVE_CPP_ATTRIBUTE(maybe_unused)
|
||||
#define GTEST_INTERNAL_ATTRIBUTE_MAYBE_UNUSED [[maybe_unused]]
|
||||
#elif GTEST_HAVE_ATTRIBUTE_(unused)
|
||||
// This is inferior to [[maybe_unused]] as it can produce a
|
||||
// -Wused-but-marked-unused warning on optionally used symbols, but it is all we
|
||||
// have.
|
||||
#define GTEST_INTERNAL_ATTRIBUTE_MAYBE_UNUSED __attribute__((__unused__))
|
||||
#else
|
||||
#define GTEST_INTERNAL_ATTRIBUTE_MAYBE_UNUSED
|
||||
#endif
|
||||
|
||||
// Use this annotation before a function that takes a printf format string.
|
||||
#if GTEST_HAVE_ATTRIBUTE_(format) && defined(__MINGW_PRINTF_FORMAT)
|
||||
// MinGW has two different printf implementations. Ensure the format macro
|
||||
@@ -805,17 +784,6 @@ typedef struct _RTL_CRITICAL_SECTION GTEST_CRITICAL_SECTION;
|
||||
#define GTEST_ATTRIBUTE_PRINTF_(string_index, first_to_check)
|
||||
#endif
|
||||
|
||||
// Tell the compiler to warn about unused return values for functions declared
|
||||
// with this macro. The macro should be used on function declarations
|
||||
// following the argument list:
|
||||
//
|
||||
// Sprocket* AllocateSprocket() GTEST_MUST_USE_RESULT_;
|
||||
#if GTEST_HAVE_ATTRIBUTE_(warn_unused_result)
|
||||
#define GTEST_MUST_USE_RESULT_ __attribute__((warn_unused_result))
|
||||
#else
|
||||
#define GTEST_MUST_USE_RESULT_
|
||||
#endif
|
||||
|
||||
// MS C++ compiler emits warning when a conditional expression is compile time
|
||||
// constant. In some contexts this warning is false positive and needs to be
|
||||
// suppressed. Use the following two macros in such cases:
|
||||
@@ -2367,26 +2335,6 @@ const char* StringFromGTestEnv(const char* flag, const char* default_val);
|
||||
} // namespace internal
|
||||
} // namespace testing
|
||||
|
||||
#if !defined(GTEST_INTERNAL_DEPRECATED)
|
||||
|
||||
// Internal Macro to mark an API deprecated, for googletest usage only
|
||||
// Usage: class GTEST_INTERNAL_DEPRECATED(message) MyClass or
|
||||
// GTEST_INTERNAL_DEPRECATED(message) <return_type> myFunction(); Every usage of
|
||||
// a deprecated entity will trigger a warning when compiled with
|
||||
// `-Wdeprecated-declarations` option (clang, gcc, any __GNUC__ compiler).
|
||||
// For msvc /W3 option will need to be used
|
||||
// Note that for 'other' compilers this macro evaluates to nothing to prevent
|
||||
// compilations errors.
|
||||
#if defined(_MSC_VER)
|
||||
#define GTEST_INTERNAL_DEPRECATED(message) __declspec(deprecated(message))
|
||||
#elif defined(__GNUC__)
|
||||
#define GTEST_INTERNAL_DEPRECATED(message) __attribute__((deprecated(message)))
|
||||
#else
|
||||
#define GTEST_INTERNAL_DEPRECATED(message)
|
||||
#endif
|
||||
|
||||
#endif // !defined(GTEST_INTERNAL_DEPRECATED)
|
||||
|
||||
#ifdef GTEST_HAS_ABSL
|
||||
// Always use absl::any for UniversalPrinter<> specializations if googletest
|
||||
// is built with absl support.
|
||||
@@ -2527,12 +2475,6 @@ using Variant = ::std::variant<T...>;
|
||||
#define GTEST_INTERNAL_HAS_VARIANT 0
|
||||
#endif
|
||||
|
||||
#if (defined(__cpp_constexpr) && !defined(__cpp_inline_variables)) || \
|
||||
(defined(GTEST_INTERNAL_CPLUSPLUS_LANG) && \
|
||||
GTEST_INTERNAL_CPLUSPLUS_LANG < 201703L)
|
||||
#define GTEST_INTERNAL_NEED_REDUNDANT_CONSTEXPR_DECL 1
|
||||
#endif
|
||||
|
||||
#if (defined(__cpp_lib_three_way_comparison) || \
|
||||
(GTEST_INTERNAL_HAS_INCLUDE(<compare>) && \
|
||||
GTEST_INTERNAL_CPLUSPLUS_LANG >= 201907L))
|
||||
|
||||
@@ -826,6 +826,10 @@ class GTEST_API_ UnitTestImpl {
|
||||
bool catch_exceptions() const { return catch_exceptions_; }
|
||||
|
||||
private:
|
||||
// Returns true if a warning should be issued if no tests match the test
|
||||
// filter flag.
|
||||
bool ShouldWarnIfNoTestsMatchFilter() const;
|
||||
|
||||
struct CompareTestSuitesByPointer {
|
||||
bool operator()(const TestSuite* lhs, const TestSuite* rhs) const {
|
||||
return lhs->name_ < rhs->name_;
|
||||
|
||||
86
3rdparty/googletest/googletest/src/gtest.cc
vendored
86
3rdparty/googletest/googletest/src/gtest.cc
vendored
@@ -192,12 +192,17 @@ static const char kDefaultOutputFormat[] = "xml";
|
||||
// The default output file.
|
||||
static const char kDefaultOutputFile[] = "test_detail";
|
||||
|
||||
// These environment variables are set by Bazel.
|
||||
// https://bazel.build/reference/test-encyclopedia#initial-conditions
|
||||
//
|
||||
// The environment variable name for the test shard index.
|
||||
static const char kTestShardIndex[] = "GTEST_SHARD_INDEX";
|
||||
// The environment variable name for the total number of test shards.
|
||||
static const char kTestTotalShards[] = "GTEST_TOTAL_SHARDS";
|
||||
// The environment variable name for the test shard status file.
|
||||
static const char kTestShardStatusFile[] = "GTEST_SHARD_STATUS_FILE";
|
||||
// The environment variable name for the test output warnings file.
|
||||
static const char kTestWarningsOutputFile[] = "TEST_WARNINGS_OUTPUT_FILE";
|
||||
|
||||
namespace internal {
|
||||
|
||||
@@ -258,6 +263,12 @@ GTEST_DEFINE_bool_(
|
||||
testing::GetDefaultFailFast()),
|
||||
"True if and only if a test failure should stop further test execution.");
|
||||
|
||||
GTEST_DEFINE_bool_(
|
||||
fail_if_no_test_linked,
|
||||
testing::internal::BoolFromGTestEnv("fail_if_no_test_linked", false),
|
||||
"True if and only if the test should fail if no test case (including "
|
||||
"disabled test cases) is linked.");
|
||||
|
||||
GTEST_DEFINE_bool_(
|
||||
also_run_disabled_tests,
|
||||
testing::internal::BoolFromGTestEnv("also_run_disabled_tests", false),
|
||||
@@ -5869,6 +5880,23 @@ TestSuite* UnitTestImpl::GetTestSuite(
|
||||
static void SetUpEnvironment(Environment* env) { env->SetUp(); }
|
||||
static void TearDownEnvironment(Environment* env) { env->TearDown(); }
|
||||
|
||||
// If the environment variable TEST_WARNINGS_OUTPUT_FILE was provided, appends
|
||||
// `str` to the file, creating the file if necessary.
|
||||
#if GTEST_HAS_FILE_SYSTEM
|
||||
static void AppendToTestWarningsOutputFile(const std::string& str) {
|
||||
const char* const filename = posix::GetEnv(kTestWarningsOutputFile);
|
||||
if (filename == nullptr) {
|
||||
return;
|
||||
}
|
||||
auto* const file = posix::FOpen(filename, "a");
|
||||
if (file == nullptr) {
|
||||
return;
|
||||
}
|
||||
GTEST_CHECK_(fwrite(str.data(), 1, str.size(), file) == str.size());
|
||||
GTEST_CHECK_(posix::FClose(file) == 0);
|
||||
}
|
||||
#endif // GTEST_HAS_FILE_SYSTEM
|
||||
|
||||
// Runs all tests in this UnitTest object, prints the result, and
|
||||
// returns true if all tests are successful. If any exception is
|
||||
// thrown during a test, the test is considered to be failed, but the
|
||||
@@ -5890,6 +5918,28 @@ bool UnitTestImpl::RunAllTests() {
|
||||
// user didn't call InitGoogleTest.
|
||||
PostFlagParsingInit();
|
||||
|
||||
// Handle the case where the program has no tests linked.
|
||||
// Sometimes this is a programmer mistake, but sometimes it is intended.
|
||||
if (total_test_count() == 0) {
|
||||
constexpr char kNoTestLinkedMessage[] =
|
||||
"This test program does NOT link in any test case.";
|
||||
constexpr char kNoTestLinkedFatal[] =
|
||||
"This is INVALID. Please make sure to link in at least one test case.";
|
||||
constexpr char kNoTestLinkedWarning[] =
|
||||
"Please make sure this is intended.";
|
||||
const bool fail_if_no_test_linked = GTEST_FLAG_GET(fail_if_no_test_linked);
|
||||
ColoredPrintf(
|
||||
GTestColor::kRed, "%s %s\n", kNoTestLinkedMessage,
|
||||
fail_if_no_test_linked ? kNoTestLinkedFatal : kNoTestLinkedWarning);
|
||||
if (fail_if_no_test_linked) {
|
||||
return false;
|
||||
}
|
||||
#if GTEST_HAS_FILE_SYSTEM
|
||||
AppendToTestWarningsOutputFile(std::string(kNoTestLinkedMessage) + ' ' +
|
||||
kNoTestLinkedWarning + '\n');
|
||||
#endif // GTEST_HAS_FILE_SYSTEM
|
||||
}
|
||||
|
||||
#if GTEST_HAS_FILE_SYSTEM
|
||||
// Even if sharding is not on, test runners may want to use the
|
||||
// GTEST_SHARD_STATUS_FILE to query whether the test supports the sharding
|
||||
@@ -6063,6 +6113,17 @@ bool UnitTestImpl::RunAllTests() {
|
||||
environments_.clear();
|
||||
}
|
||||
|
||||
// Try to warn the user if no tests matched the test filter.
|
||||
if (ShouldWarnIfNoTestsMatchFilter()) {
|
||||
const std::string filter_warning =
|
||||
std::string("filter \"") + GTEST_FLAG_GET(filter) +
|
||||
"\" did not match any test; no tests were run\n";
|
||||
ColoredPrintf(GTestColor::kRed, "WARNING: %s", filter_warning.c_str());
|
||||
#if GTEST_HAS_FILE_SYSTEM
|
||||
AppendToTestWarningsOutputFile(filter_warning);
|
||||
#endif // GTEST_HAS_FILE_SYSTEM
|
||||
}
|
||||
|
||||
if (!gtest_is_initialized_before_run_all_tests) {
|
||||
ColoredPrintf(
|
||||
GTestColor::kRed,
|
||||
@@ -6231,6 +6292,30 @@ int UnitTestImpl::FilterTests(ReactionToSharding shard_tests) {
|
||||
return num_selected_tests;
|
||||
}
|
||||
|
||||
// Returns true if a warning should be issued if no tests match the test filter
|
||||
// flag. We can't simply count the number of tests that ran because, for
|
||||
// instance, test sharding and death tests might mean no tests are expected to
|
||||
// run in this process, but will run in another process.
|
||||
bool UnitTestImpl::ShouldWarnIfNoTestsMatchFilter() const {
|
||||
if (total_test_count() == 0) {
|
||||
// No tests were linked in to program.
|
||||
// This case is handled by a different warning.
|
||||
return false;
|
||||
}
|
||||
const PositiveAndNegativeUnitTestFilter gtest_flag_filter(
|
||||
GTEST_FLAG_GET(filter));
|
||||
for (auto* test_suite : test_suites_) {
|
||||
const std::string& test_suite_name = test_suite->name_;
|
||||
for (TestInfo* test_info : test_suite->test_info_list()) {
|
||||
const std::string& test_name = test_info->name_;
|
||||
if (gtest_flag_filter.MatchesTest(test_suite_name, test_name)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Prints the given C-string on a single line by replacing all '\n'
|
||||
// characters with string "\\n". If the output takes more than
|
||||
// max_length characters, only prints the first max_length characters
|
||||
@@ -6677,6 +6762,7 @@ static bool ParseGoogleTestFlag(const char* const arg) {
|
||||
GTEST_INTERNAL_PARSE_FLAG(death_test_style);
|
||||
GTEST_INTERNAL_PARSE_FLAG(death_test_use_fork);
|
||||
GTEST_INTERNAL_PARSE_FLAG(fail_fast);
|
||||
GTEST_INTERNAL_PARSE_FLAG(fail_if_no_test_linked);
|
||||
GTEST_INTERNAL_PARSE_FLAG(filter);
|
||||
GTEST_INTERNAL_PARSE_FLAG(internal_run_death_test);
|
||||
GTEST_INTERNAL_PARSE_FLAG(list_tests);
|
||||
|
||||
4
3rdparty/imgui/include/imconfig.h
vendored
4
3rdparty/imgui/include/imconfig.h
vendored
@@ -129,6 +129,10 @@
|
||||
//#define IM_DEBUG_BREAK IM_ASSERT(0)
|
||||
//#define IM_DEBUG_BREAK __debugbreak()
|
||||
|
||||
//---- Debug Tools: Enable highlight ID conflicts _before_ hovering items. When io.ConfigDebugHighlightIdConflicts is set.
|
||||
// (THIS WILL SLOW DOWN DEAR IMGUI. Only use occasionally and disable after use)
|
||||
//#define IMGUI_DEBUG_HIGHLIGHT_ALL_ID_CONFLICTS
|
||||
|
||||
//---- Debug Tools: Enable slower asserts
|
||||
//#define IMGUI_DEBUG_PARANOID
|
||||
|
||||
|
||||
829
3rdparty/imgui/include/imgui.h
vendored
829
3rdparty/imgui/include/imgui.h
vendored
File diff suppressed because it is too large
Load Diff
65
3rdparty/imgui/include/imgui_freetype.h
vendored
65
3rdparty/imgui/include/imgui_freetype.h
vendored
@@ -6,7 +6,9 @@
|
||||
#ifndef IMGUI_DISABLE
|
||||
|
||||
// Usage:
|
||||
// - Add '#define IMGUI_ENABLE_FREETYPE' in your imconfig to enable support for imgui_freetype in imgui.
|
||||
// - Add '#define IMGUI_ENABLE_FREETYPE' in your imconfig to automatically enable support
|
||||
// for imgui_freetype in imgui. It is equivalent to selecting the default loader with:
|
||||
// io.Fonts->SetFontLoader(ImGuiFreeType::GetFontLoader())
|
||||
|
||||
// Optional support for OpenType SVG fonts:
|
||||
// - Add '#define IMGUI_ENABLE_FREETYPE_PLUTOSVG' to use plutosvg (not provided). See #7927.
|
||||
@@ -14,44 +16,67 @@
|
||||
|
||||
// Forward declarations
|
||||
struct ImFontAtlas;
|
||||
struct ImFontBuilderIO;
|
||||
struct ImFontLoader;
|
||||
|
||||
// Hinting greatly impacts visuals (and glyph sizes).
|
||||
// - By default, hinting is enabled and the font's native hinter is preferred over the auto-hinter.
|
||||
// - When disabled, FreeType generates blurrier glyphs, more or less matches the stb_truetype.h
|
||||
// - The Default hinting mode usually looks good, but may distort glyphs in an unusual way.
|
||||
// - The Light hinting mode generates fuzzier glyphs but better matches Microsoft's rasterizer.
|
||||
// You can set those flags globaly in ImFontAtlas::FontBuilderFlags
|
||||
// You can set those flags on a per font basis in ImFontConfig::FontBuilderFlags
|
||||
enum ImGuiFreeTypeBuilderFlags
|
||||
// You can set those flags globally in ImFontAtlas::FontLoaderFlags
|
||||
// You can set those flags on a per font basis in ImFontConfig::FontLoaderFlags
|
||||
typedef unsigned int ImGuiFreeTypeLoaderFlags;
|
||||
enum ImGuiFreeTypeLoaderFlags_
|
||||
{
|
||||
ImGuiFreeTypeBuilderFlags_NoHinting = 1 << 0, // Disable hinting. This generally generates 'blurrier' bitmap glyphs when the glyph are rendered in any of the anti-aliased modes.
|
||||
ImGuiFreeTypeBuilderFlags_NoAutoHint = 1 << 1, // Disable auto-hinter.
|
||||
ImGuiFreeTypeBuilderFlags_ForceAutoHint = 1 << 2, // Indicates that the auto-hinter is preferred over the font's native hinter.
|
||||
ImGuiFreeTypeBuilderFlags_LightHinting = 1 << 3, // A lighter hinting algorithm for gray-level modes. Many generated glyphs are fuzzier but better resemble their original shape. This is achieved by snapping glyphs to the pixel grid only vertically (Y-axis), as is done by Microsoft's ClearType and Adobe's proprietary font renderer. This preserves inter-glyph spacing in horizontal text.
|
||||
ImGuiFreeTypeBuilderFlags_MonoHinting = 1 << 4, // Strong hinting algorithm that should only be used for monochrome output.
|
||||
ImGuiFreeTypeBuilderFlags_Bold = 1 << 5, // Styling: Should we artificially embolden the font?
|
||||
ImGuiFreeTypeBuilderFlags_Oblique = 1 << 6, // Styling: Should we slant the font, emulating italic style?
|
||||
ImGuiFreeTypeBuilderFlags_Monochrome = 1 << 7, // Disable anti-aliasing. Combine this with MonoHinting for best results!
|
||||
ImGuiFreeTypeBuilderFlags_LoadColor = 1 << 8, // Enable FreeType color-layered glyphs
|
||||
ImGuiFreeTypeBuilderFlags_Bitmap = 1 << 9 // Enable FreeType bitmap glyphs
|
||||
ImGuiFreeTypeLoaderFlags_NoHinting = 1 << 0, // Disable hinting. This generally generates 'blurrier' bitmap glyphs when the glyph are rendered in any of the anti-aliased modes.
|
||||
ImGuiFreeTypeLoaderFlags_NoAutoHint = 1 << 1, // Disable auto-hinter.
|
||||
ImGuiFreeTypeLoaderFlags_ForceAutoHint = 1 << 2, // Indicates that the auto-hinter is preferred over the font's native hinter.
|
||||
ImGuiFreeTypeLoaderFlags_LightHinting = 1 << 3, // A lighter hinting algorithm for gray-level modes. Many generated glyphs are fuzzier but better resemble their original shape. This is achieved by snapping glyphs to the pixel grid only vertically (Y-axis), as is done by Microsoft's ClearType and Adobe's proprietary font renderer. This preserves inter-glyph spacing in horizontal text.
|
||||
ImGuiFreeTypeLoaderFlags_MonoHinting = 1 << 4, // Strong hinting algorithm that should only be used for monochrome output.
|
||||
ImGuiFreeTypeLoaderFlags_Bold = 1 << 5, // Styling: Should we artificially embolden the font?
|
||||
ImGuiFreeTypeLoaderFlags_Oblique = 1 << 6, // Styling: Should we slant the font, emulating italic style?
|
||||
ImGuiFreeTypeLoaderFlags_Monochrome = 1 << 7, // Disable anti-aliasing. Combine this with MonoHinting for best results!
|
||||
ImGuiFreeTypeLoaderFlags_LoadColor = 1 << 8, // Enable FreeType color-layered glyphs
|
||||
ImGuiFreeTypeLoaderFlags_Bitmap = 1 << 9, // Enable FreeType bitmap glyphs
|
||||
|
||||
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
|
||||
ImGuiFreeTypeBuilderFlags_NoHinting = ImGuiFreeTypeLoaderFlags_NoHinting,
|
||||
ImGuiFreeTypeBuilderFlags_NoAutoHint = ImGuiFreeTypeLoaderFlags_NoAutoHint,
|
||||
ImGuiFreeTypeBuilderFlags_ForceAutoHint = ImGuiFreeTypeLoaderFlags_ForceAutoHint,
|
||||
ImGuiFreeTypeBuilderFlags_LightHinting = ImGuiFreeTypeLoaderFlags_LightHinting,
|
||||
ImGuiFreeTypeBuilderFlags_MonoHinting = ImGuiFreeTypeLoaderFlags_MonoHinting,
|
||||
ImGuiFreeTypeBuilderFlags_Bold = ImGuiFreeTypeLoaderFlags_Bold,
|
||||
ImGuiFreeTypeBuilderFlags_Oblique = ImGuiFreeTypeLoaderFlags_Oblique,
|
||||
ImGuiFreeTypeBuilderFlags_Monochrome = ImGuiFreeTypeLoaderFlags_Monochrome,
|
||||
ImGuiFreeTypeBuilderFlags_LoadColor = ImGuiFreeTypeLoaderFlags_LoadColor,
|
||||
ImGuiFreeTypeBuilderFlags_Bitmap = ImGuiFreeTypeLoaderFlags_Bitmap,
|
||||
#endif
|
||||
};
|
||||
|
||||
// Obsolete names (will be removed)
|
||||
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
|
||||
typedef ImGuiFreeTypeLoaderFlags_ ImGuiFreeTypeBuilderFlags_;
|
||||
#endif
|
||||
|
||||
namespace ImGuiFreeType
|
||||
{
|
||||
// This is automatically assigned when using '#define IMGUI_ENABLE_FREETYPE'.
|
||||
// If you need to dynamically select between multiple builders:
|
||||
// - you can manually assign this builder with 'atlas->FontBuilderIO = ImGuiFreeType::GetBuilderForFreeType()'
|
||||
// - prefer deep-copying this into your own ImFontBuilderIO instance if you use hot-reloading that messes up static data.
|
||||
IMGUI_API const ImFontBuilderIO* GetBuilderForFreeType();
|
||||
// - you can manually assign this builder with 'atlas->SetFontLoader(ImGuiFreeType::GetFontLoader())'
|
||||
// - prefer deep-copying this into your own ImFontLoader instance if you use hot-reloading that messes up static data.
|
||||
IMGUI_API const ImFontLoader* GetFontLoader();
|
||||
|
||||
// Override allocators. By default ImGuiFreeType will use IM_ALLOC()/IM_FREE()
|
||||
// However, as FreeType does lots of allocations we provide a way for the user to redirect it to a separate memory heap if desired.
|
||||
IMGUI_API void SetAllocatorFunctions(void* (*alloc_func)(size_t sz, void* user_data), void (*free_func)(void* ptr, void* user_data), void* user_data = nullptr);
|
||||
|
||||
// Obsolete names (will be removed soon)
|
||||
// Display UI to edit ImFontAtlas::FontLoaderFlags (shared) or ImFontConfig::FontLoaderFlags (single source)
|
||||
IMGUI_API bool DebugEditFontLoaderFlags(ImGuiFreeTypeLoaderFlags* p_font_loader_flags);
|
||||
|
||||
// Obsolete names (will be removed)
|
||||
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
|
||||
//static inline bool BuildFontAtlas(ImFontAtlas* atlas, unsigned int flags = 0) { atlas->FontBuilderIO = GetBuilderForFreeType(); atlas->FontBuilderFlags = flags; return atlas->Build(); } // Prefer using '#define IMGUI_ENABLE_FREETYPE'
|
||||
//IMGUI_API const ImFontBuilderIO* GetBuilderForFreeType(); // Renamed/changed in 1.92. Change 'io.Fonts->FontBuilderIO = ImGuiFreeType::GetBuilderForFreeType()' to 'io.Fonts->SetFontLoader(ImGuiFreeType::GetFontLoader())' if you need runtime selection.
|
||||
//static inline bool BuildFontAtlas(ImFontAtlas* atlas, unsigned int flags = 0) { atlas->FontBuilderIO = GetBuilderForFreeType(); atlas->FontLoaderFlags = flags; return atlas->Build(); } // Prefer using '#define IMGUI_ENABLE_FREETYPE'
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
384
3rdparty/imgui/include/imgui_internal.h
vendored
384
3rdparty/imgui/include/imgui_internal.h
vendored
@@ -1,4 +1,4 @@
|
||||
// dear imgui, v1.91.9b
|
||||
// dear imgui, v1.92.1
|
||||
// (internal structures/api)
|
||||
|
||||
// You may use this file to debug, understand or extend Dear ImGui features but we don't provide any guarantee of forward compatibility.
|
||||
@@ -37,6 +37,7 @@ Index of this file:
|
||||
// [SECTION] Tab bar, Tab item support
|
||||
// [SECTION] Table support
|
||||
// [SECTION] ImGui internal API
|
||||
// [SECTION] ImFontLoader
|
||||
// [SECTION] ImFontAtlas internal API
|
||||
// [SECTION] Test Engine specific hooks (imgui_test_engine)
|
||||
|
||||
@@ -132,7 +133,7 @@ Index of this file:
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// Utilities
|
||||
// (other types which are not forwarded declared are: ImBitArray<>, ImSpan<>, ImSpanAllocator<>, ImPool<>, ImChunkStream<>)
|
||||
// (other types which are not forwarded declared are: ImBitArray<>, ImSpan<>, ImSpanAllocator<>, ImStableVector<>, ImPool<>, ImChunkStream<>)
|
||||
struct ImBitVector; // Store 1-bit per value
|
||||
struct ImRect; // An axis-aligned rectangle (2 points)
|
||||
struct ImGuiTextIndex; // Maintain a line index for a text buffer.
|
||||
@@ -140,6 +141,9 @@ struct ImGuiTextIndex; // Maintain a line index for a text buffer.
|
||||
// ImDrawList/ImFontAtlas
|
||||
struct ImDrawDataBuilder; // Helper to build a ImDrawData instance
|
||||
struct ImDrawListSharedData; // Data shared between all ImDrawList instances
|
||||
struct ImFontAtlasBuilder; // Internal storage for incrementally packing and building a ImFontAtlas
|
||||
struct ImFontAtlasPostProcessData; // Data available to potential texture post-processing functions
|
||||
struct ImFontAtlasRectEntry; // Packed rectangle lookup entry
|
||||
|
||||
// ImGui
|
||||
struct ImGuiBoxSelectState; // Box-selection state (currently used by multi-selection, could potentially be used by others)
|
||||
@@ -206,6 +210,10 @@ typedef int ImGuiTooltipFlags; // -> enum ImGuiTooltipFlags_ // F
|
||||
typedef int ImGuiTypingSelectFlags; // -> enum ImGuiTypingSelectFlags_ // Flags: for GetTypingSelectRequest()
|
||||
typedef int ImGuiWindowRefreshFlags; // -> enum ImGuiWindowRefreshFlags_ // Flags: for SetNextWindowRefreshPolicy()
|
||||
|
||||
// Table column indexing
|
||||
typedef ImS16 ImGuiTableColumnIdx;
|
||||
typedef ImU16 ImGuiTableDrawChannelIdx;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// [SECTION] Context pointer
|
||||
// See implementation of this variable in imgui.cpp for comments and details.
|
||||
@@ -238,7 +246,7 @@ extern IMGUI_API ImGuiContext* GImGui; // Current implicit context pointer
|
||||
#define IMGUI_DEBUG_LOG_SELECTION(...) do { if (g.DebugLogFlags & ImGuiDebugLogFlags_EventSelection) IMGUI_DEBUG_LOG(__VA_ARGS__); } while (0)
|
||||
#define IMGUI_DEBUG_LOG_CLIPPER(...) do { if (g.DebugLogFlags & ImGuiDebugLogFlags_EventClipper) IMGUI_DEBUG_LOG(__VA_ARGS__); } while (0)
|
||||
#define IMGUI_DEBUG_LOG_IO(...) do { if (g.DebugLogFlags & ImGuiDebugLogFlags_EventIO) IMGUI_DEBUG_LOG(__VA_ARGS__); } while (0)
|
||||
#define IMGUI_DEBUG_LOG_FONT(...) do { if (g.DebugLogFlags & ImGuiDebugLogFlags_EventFont) IMGUI_DEBUG_LOG(__VA_ARGS__); } while (0)
|
||||
#define IMGUI_DEBUG_LOG_FONT(...) do { ImGuiContext* g2 = GImGui; if (g2 && g2->DebugLogFlags & ImGuiDebugLogFlags_EventFont) IMGUI_DEBUG_LOG(__VA_ARGS__); } while (0) // Called from ImFontAtlas function which may operate without a context.
|
||||
#define IMGUI_DEBUG_LOG_INPUTROUTING(...) do{if (g.DebugLogFlags & ImGuiDebugLogFlags_EventInputRouting)IMGUI_DEBUG_LOG(__VA_ARGS__); } while (0)
|
||||
|
||||
// Static Asserts
|
||||
@@ -348,6 +356,7 @@ extern IMGUI_API ImGuiContext* GImGui; // Current implicit context pointer
|
||||
// - Helper: ImBitArray
|
||||
// - Helper: ImBitVector
|
||||
// - Helper: ImSpan<>, ImSpanAllocator<>
|
||||
// - Helper: ImStableVector<>
|
||||
// - Helper: ImPool<>
|
||||
// - Helper: ImChunkStream<>
|
||||
// - Helper: ImGuiTextIndex
|
||||
@@ -379,6 +388,7 @@ IMGUI_API int ImStricmp(const char* str1, const char* str2);
|
||||
IMGUI_API int ImStrnicmp(const char* str1, const char* str2, size_t count); // Case insensitive compare to a certain count.
|
||||
IMGUI_API void ImStrncpy(char* dst, const char* src, size_t count); // Copy to a certain count and always zero terminate (strncpy doesn't).
|
||||
IMGUI_API char* ImStrdup(const char* str); // Duplicate a string.
|
||||
IMGUI_API void* ImMemdup(const void* src, size_t size); // Duplicate a chunk of memory.
|
||||
IMGUI_API char* ImStrdupcpy(char* dst, size_t* p_dst_size, const char* str); // Copy in provided buffer, recreate buffer if needed.
|
||||
IMGUI_API const char* ImStrchrRange(const char* str_begin, const char* str_end, char c); // Find first occurrence of 'c' in string range.
|
||||
IMGUI_API const char* ImStreolRange(const char* str, const char* str_end); // End end-of-line
|
||||
@@ -492,6 +502,8 @@ static inline float ImTrunc(float f)
|
||||
static inline ImVec2 ImTrunc(const ImVec2& v) { return ImVec2((float)(int)(v.x), (float)(int)(v.y)); }
|
||||
static inline float ImFloor(float f) { return (float)((f >= 0 || (float)(int)f == f) ? (int)f : (int)f - 1); } // Decent replacement for floorf()
|
||||
static inline ImVec2 ImFloor(const ImVec2& v) { return ImVec2(ImFloor(v.x), ImFloor(v.y)); }
|
||||
static inline float ImTrunc64(float f) { return (float)(ImS64)(f); }
|
||||
static inline float ImRound64(float f) { return (float)(ImS64)(f + 0.5f); }
|
||||
static inline int ImModPositive(int a, int b) { return (a + b) % b; }
|
||||
static inline float ImDot(const ImVec2& a, const ImVec2& b) { return a.x * b.x + a.y * b.y; }
|
||||
static inline ImVec2 ImRotate(const ImVec2& v, float cos_a, float sin_a) { return ImVec2(v.x * cos_a - v.y * sin_a, v.x * sin_a + v.y * cos_a); }
|
||||
@@ -524,6 +536,14 @@ struct ImVec1
|
||||
constexpr ImVec1(float _x) : x(_x) { }
|
||||
};
|
||||
|
||||
// Helper: ImVec2i (2D vector, integer)
|
||||
struct ImVec2i
|
||||
{
|
||||
int x, y;
|
||||
constexpr ImVec2i() : x(0), y(0) {}
|
||||
constexpr ImVec2i(int _x, int _y) : x(_x), y(_y) {}
|
||||
};
|
||||
|
||||
// Helper: ImVec2ih (2D vector, half-size integer, for long-term packed storage)
|
||||
struct ImVec2ih
|
||||
{
|
||||
@@ -675,6 +695,39 @@ struct ImSpanAllocator
|
||||
inline void GetSpan(int n, ImSpan<T>* span) { span->set((T*)GetSpanPtrBegin(n), (T*)GetSpanPtrEnd(n)); }
|
||||
};
|
||||
|
||||
// Helper: ImStableVector<>
|
||||
// Allocating chunks of BLOCK_SIZE items. Objects pointers are never invalidated when growing, only by clear().
|
||||
// Important: does not destruct anything!
|
||||
// Implemented only the minimum set of functions we need for it.
|
||||
template<typename T, int BLOCK_SIZE>
|
||||
struct ImStableVector
|
||||
{
|
||||
int Size = 0;
|
||||
int Capacity = 0;
|
||||
ImVector<T*> Blocks;
|
||||
|
||||
// Functions
|
||||
inline ~ImStableVector() { for (T* block : Blocks) IM_FREE(block); }
|
||||
|
||||
inline void clear() { Size = Capacity = 0; Blocks.clear_delete(); }
|
||||
inline void resize(int new_size) { if (new_size > Capacity) reserve(new_size); Size = new_size; }
|
||||
inline void reserve(int new_cap)
|
||||
{
|
||||
new_cap = IM_MEMALIGN(new_cap, BLOCK_SIZE);
|
||||
int old_count = Capacity / BLOCK_SIZE;
|
||||
int new_count = new_cap / BLOCK_SIZE;
|
||||
if (new_count <= old_count)
|
||||
return;
|
||||
Blocks.resize(new_count);
|
||||
for (int n = old_count; n < new_count; n++)
|
||||
Blocks[n] = (T*)IM_ALLOC(sizeof(T) * BLOCK_SIZE);
|
||||
Capacity = new_cap;
|
||||
}
|
||||
inline T& operator[](int i) { IM_ASSERT(i >= 0 && i < Size); return Blocks[i / BLOCK_SIZE][i % BLOCK_SIZE]; }
|
||||
inline const T& operator[](int i) const { IM_ASSERT(i >= 0 && i < Size); return Blocks[i / BLOCK_SIZE][i % BLOCK_SIZE]; }
|
||||
inline T* push_back(const T& v) { int i = Size; IM_ASSERT(i >= 0); if (Size == Capacity) reserve(Capacity + BLOCK_SIZE); void* ptr = &Blocks[i / BLOCK_SIZE][i % BLOCK_SIZE]; memcpy(ptr, &v, sizeof(v)); Size++; return (T*)ptr; }
|
||||
};
|
||||
|
||||
// Helper: ImPool<>
|
||||
// Basic keyed storage for contiguous instances, slow/amortized insertion, O(1) indexable, O(Log N) queries by ID over a dense/hot buffer,
|
||||
// Honor constructor/destructor. Add/remove invalidate all pointers. Indexes have the same lifetime as the associated object.
|
||||
@@ -783,17 +836,20 @@ IMGUI_API ImGuiStoragePair* ImLowerBound(ImGuiStoragePair* in_begin, ImGuiStorag
|
||||
// You may want to create your own instance of you try to ImDrawList completely without ImGui. In that case, watch out for future changes to this structure.
|
||||
struct IMGUI_API ImDrawListSharedData
|
||||
{
|
||||
ImVec2 TexUvWhitePixel; // UV of white pixel in the atlas
|
||||
const ImVec4* TexUvLines; // UV of anti-aliased lines in the atlas
|
||||
ImFont* Font; // Current/default font (optional, for simplified AddText overload)
|
||||
float FontSize; // Current/default font size (optional, for simplified AddText overload)
|
||||
float FontScale; // Current/default font scale (== FontSize / Font->FontSize)
|
||||
ImVec2 TexUvWhitePixel; // UV of white pixel in the atlas (== FontAtlas->TexUvWhitePixel)
|
||||
const ImVec4* TexUvLines; // UV of anti-aliased lines in the atlas (== FontAtlas->TexUvLines)
|
||||
ImFontAtlas* FontAtlas; // Current font atlas
|
||||
ImFont* Font; // Current font (used for simplified AddText overload)
|
||||
float FontSize; // Current font size (used for for simplified AddText overload)
|
||||
float FontScale; // Current font scale (== FontSize / Font->FontSize)
|
||||
float CurveTessellationTol; // Tessellation tolerance when using PathBezierCurveTo()
|
||||
float CircleSegmentMaxError; // Number of circle segments to use per pixel of radius for AddCircle() etc
|
||||
float InitialFringeScale; // Initial scale to apply to AA fringe
|
||||
ImDrawListFlags InitialFlags; // Initial flags at the beginning of the frame (it is possible to alter flags on a per-drawlist basis afterwards)
|
||||
ImVec4 ClipRectFullscreen; // Value for PushClipRectFullscreen()
|
||||
ImVector<ImVec2> TempBuffer; // Temporary write buffer
|
||||
ImVector<ImDrawList*> DrawLists; // All draw lists associated to this ImDrawListSharedData
|
||||
ImGuiContext* Context; // [OPTIONAL] Link to Dear ImGui context. 99% of ImDrawList/ImFontAtlas can function without an ImGui context, but this facilitate handling one legacy edge case.
|
||||
|
||||
// Lookup tables
|
||||
ImVec2 ArcFastVtx[IM_DRAWLIST_ARCFAST_TABLE_SIZE]; // Sample points on the quarter of the circle.
|
||||
@@ -801,6 +857,7 @@ struct IMGUI_API ImDrawListSharedData
|
||||
ImU8 CircleSegmentCounts[64]; // Precomputed segment count for given radius before we calculate it dynamically (to avoid calculation overhead)
|
||||
|
||||
ImDrawListSharedData();
|
||||
~ImDrawListSharedData();
|
||||
void SetCircleTessellationMaxError(float max_error);
|
||||
};
|
||||
|
||||
@@ -812,6 +869,13 @@ struct ImDrawDataBuilder
|
||||
ImDrawDataBuilder() { memset(this, 0, sizeof(*this)); }
|
||||
};
|
||||
|
||||
struct ImFontStackData
|
||||
{
|
||||
ImFont* Font;
|
||||
float FontSizeBeforeScaling; // ~~ style.FontSizeBase
|
||||
float FontSizeAfterScaling; // ~~ g.FontSize
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// [SECTION] Style support
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -883,6 +947,7 @@ enum ImGuiItemFlagsPrivate_
|
||||
ImGuiItemFlags_AllowOverlap = 1 << 14, // false // Allow being overlapped by another widget. Not-hovered to Hovered transition deferred by a frame.
|
||||
ImGuiItemFlags_NoNavDisableMouseHover = 1 << 15, // false // Nav keyboard/gamepad mode doesn't disable hover highlight (behave as if NavHighlightItemUnderNav==false).
|
||||
ImGuiItemFlags_NoMarkEdited = 1 << 16, // false // Skip calling MarkItemEdited()
|
||||
ImGuiItemFlags_NoFocus = 1 << 17, // false // [EXPERIMENTAL: Not very well specced] Clicking doesn't take focus. Automatically sets ImGuiButtonFlags_NoFocus + ImGuiButtonFlags_NoNavFocus in ButtonBehavior().
|
||||
|
||||
// Controlled by widget code
|
||||
ImGuiItemFlags_Inputable = 1 << 20, // false // [WIP] Auto-activate input mode when tab focused. Currently only used and supported by a few items before it becomes a generic feature.
|
||||
@@ -911,6 +976,7 @@ enum ImGuiItemStatusFlags_
|
||||
ImGuiItemStatusFlags_Visible = 1 << 8, // [WIP] Set when item is overlapping the current clipping rectangle (Used internally. Please don't use yet: API/system will change as we refactor Itemadd()).
|
||||
ImGuiItemStatusFlags_HasClipRect = 1 << 9, // g.LastItemData.ClipRect is valid.
|
||||
ImGuiItemStatusFlags_HasShortcut = 1 << 10, // g.LastItemData.Shortcut valid. Set by SetNextItemShortcut() -> ItemAdd().
|
||||
//ImGuiItemStatusFlags_FocusedByTabbing = 1 << 8, // Removed IN 1.90.1 (Dec 2023). The trigger is part of g.NavActivateId. See commit 54c1bdeceb.
|
||||
|
||||
// Additional status + semantic for ImGuiTestEngine
|
||||
#ifdef IMGUI_ENABLE_TEST_ENGINE
|
||||
@@ -960,8 +1026,10 @@ enum ImGuiButtonFlagsPrivate_
|
||||
ImGuiButtonFlags_NoHoveredOnFocus = 1 << 19, // don't report as hovered when nav focus is on this item
|
||||
ImGuiButtonFlags_NoSetKeyOwner = 1 << 20, // don't set key/input owner on the initial click (note: mouse buttons are keys! often, the key in question will be ImGuiKey_MouseLeft!)
|
||||
ImGuiButtonFlags_NoTestKeyOwner = 1 << 21, // don't test key/input owner when polling the key (note: mouse buttons are keys! often, the key in question will be ImGuiKey_MouseLeft!)
|
||||
ImGuiButtonFlags_NoFocus = 1 << 22, // [EXPERIMENTAL: Not very well specced]. Don't focus parent window when clicking.
|
||||
ImGuiButtonFlags_PressedOnMask_ = ImGuiButtonFlags_PressedOnClick | ImGuiButtonFlags_PressedOnClickRelease | ImGuiButtonFlags_PressedOnClickReleaseAnywhere | ImGuiButtonFlags_PressedOnRelease | ImGuiButtonFlags_PressedOnDoubleClick | ImGuiButtonFlags_PressedOnDragDropHold,
|
||||
ImGuiButtonFlags_PressedOnDefault_ = ImGuiButtonFlags_PressedOnClickRelease,
|
||||
//ImGuiButtonFlags_NoKeyModifiers = ImGuiButtonFlags_NoKeyModsAllowed, // Renamed in 1.91.4
|
||||
};
|
||||
|
||||
// Extend ImGuiComboFlags_
|
||||
@@ -994,9 +1062,11 @@ enum ImGuiSelectableFlagsPrivate_
|
||||
// Extend ImGuiTreeNodeFlags_
|
||||
enum ImGuiTreeNodeFlagsPrivate_
|
||||
{
|
||||
ImGuiTreeNodeFlags_NoNavFocus = 1 << 27,// Don't claim nav focus when interacting with this item (#8551)
|
||||
ImGuiTreeNodeFlags_ClipLabelForTrailingButton = 1 << 28,// FIXME-WIP: Hard-coded for CollapsingHeader()
|
||||
ImGuiTreeNodeFlags_UpsideDownArrow = 1 << 29,// FIXME-WIP: Turn Down arrow into an Up arrow, for reversed trees (#6517)
|
||||
ImGuiTreeNodeFlags_OpenOnMask_ = ImGuiTreeNodeFlags_OpenOnDoubleClick | ImGuiTreeNodeFlags_OpenOnArrow,
|
||||
ImGuiTreeNodeFlags_DrawLinesMask_ = ImGuiTreeNodeFlags_DrawLinesNone | ImGuiTreeNodeFlags_DrawLinesFull | ImGuiTreeNodeFlags_DrawLinesToNodes,
|
||||
};
|
||||
|
||||
enum ImGuiSeparatorFlags_
|
||||
@@ -1283,15 +1353,18 @@ struct ImGuiLastItemData
|
||||
};
|
||||
|
||||
// Store data emitted by TreeNode() for usage by TreePop()
|
||||
// - To implement ImGuiTreeNodeFlags_NavLeftJumpsBackHere: store the minimum amount of data
|
||||
// - To implement ImGuiTreeNodeFlags_NavLeftJumpsToParent: store the minimum amount of data
|
||||
// which we can't infer in TreePop(), to perform the equivalent of NavApplyItemToResult().
|
||||
// Only stored when the node is a potential candidate for landing on a Left arrow jump.
|
||||
struct ImGuiTreeNodeStackData
|
||||
{
|
||||
ImGuiID ID;
|
||||
ImGuiTreeNodeFlags TreeFlags;
|
||||
ImGuiItemFlags ItemFlags; // Used for nav landing
|
||||
ImRect NavRect; // Used for nav landing
|
||||
ImGuiItemFlags ItemFlags; // Used for nav landing
|
||||
ImRect NavRect; // Used for nav landing
|
||||
float DrawLinesX1;
|
||||
float DrawLinesToNodesY2;
|
||||
ImGuiTableColumnIdx DrawLinesTableColumn;
|
||||
};
|
||||
|
||||
// sizeof() = 20
|
||||
@@ -1607,6 +1680,7 @@ enum ImGuiNavRenderCursorFlags_
|
||||
ImGuiNavHighlightFlags_Compact = ImGuiNavRenderCursorFlags_Compact, // Renamed in 1.91.4
|
||||
ImGuiNavHighlightFlags_AlwaysDraw = ImGuiNavRenderCursorFlags_AlwaysDraw, // Renamed in 1.91.4
|
||||
ImGuiNavHighlightFlags_NoRounding = ImGuiNavRenderCursorFlags_NoRounding, // Renamed in 1.91.4
|
||||
//ImGuiNavHighlightFlags_TypeThin = ImGuiNavRenderCursorFlags_Compact, // Renamed in 1.90.2
|
||||
#endif
|
||||
};
|
||||
|
||||
@@ -2007,10 +2081,12 @@ struct ImGuiMetricsConfig
|
||||
bool ShowDrawCmdMesh = true;
|
||||
bool ShowDrawCmdBoundingBoxes = true;
|
||||
bool ShowTextEncodingViewer = false;
|
||||
bool ShowTextureUsedRect = false;
|
||||
int ShowWindowsRectsType = -1;
|
||||
int ShowTablesRectsType = -1;
|
||||
int HighlightMonitorIdx = -1;
|
||||
ImGuiID HighlightViewportID = 0;
|
||||
bool ShowFontPreview = true;
|
||||
};
|
||||
|
||||
struct ImGuiStackLevelInfo
|
||||
@@ -2063,15 +2139,17 @@ struct ImGuiContextHook
|
||||
struct ImGuiContext
|
||||
{
|
||||
bool Initialized;
|
||||
bool FontAtlasOwnedByContext; // IO.Fonts-> is owned by the ImGuiContext and will be destructed along with it.
|
||||
ImGuiIO IO;
|
||||
ImGuiPlatformIO PlatformIO;
|
||||
ImGuiStyle Style;
|
||||
ImFont* Font; // (Shortcut) == FontStack.empty() ? IO.Font : FontStack.back()
|
||||
float FontSize; // (Shortcut) == FontBaseSize * g.CurrentWindow->FontWindowScale == window->FontSize(). Text height for current window.
|
||||
float FontBaseSize; // (Shortcut) == IO.FontGlobalScale * Font->Scale * Font->FontSize. Base text height.
|
||||
float FontScale; // == FontSize / Font->FontSize
|
||||
float CurrentDpiScale; // Current window/viewport DpiScale
|
||||
ImVector<ImFontAtlas*> FontAtlases; // List of font atlases used by the context (generally only contains g.IO.Fonts aka the main font atlas)
|
||||
ImFont* Font; // Currently bound font. (== FontStack.back().Font)
|
||||
ImFontBaked* FontBaked; // Currently bound font at currently bound size. (== Font->GetFontBaked(FontSize))
|
||||
float FontSize; // Currently bound font size == line height (== FontSizeBase + externals scales applied in the UpdateCurrentFontSize() function).
|
||||
float FontSizeBase; // Font size before scaling == style.FontSizeBase == value passed to PushFont() when specified.
|
||||
float FontBakedScale; // == FontBaked->Size / FontSize. Scale factor over baked size. Rarely used nowadays, very often == 1.0f.
|
||||
float FontRasterizerDensity; // Current font density. Used by all calls to GetFontBaked().
|
||||
float CurrentDpiScale; // Current window/viewport DpiScale == CurrentViewport->DpiScale
|
||||
ImDrawListSharedData DrawListSharedData;
|
||||
double Time;
|
||||
int FrameCount;
|
||||
@@ -2114,7 +2192,7 @@ struct ImGuiContext
|
||||
ImVec2 WheelingAxisAvg;
|
||||
|
||||
// Item/widgets state and tracking information
|
||||
ImGuiID DebugDrawIdConflicts; // Set when we detect multiple items with the same identifier
|
||||
ImGuiID DebugDrawIdConflictsId; // Set when we detect multiple items with the same identifier
|
||||
ImGuiID DebugHookIdInfo; // Will call core hooks: DebugHookIdInfo() from GetID functions, used by ID Stack Tool [next HoveredId/ActiveId to not pull in an extra cache-line]
|
||||
ImGuiID HoveredId; // Hovered widget, filled during the frame
|
||||
ImGuiID HoveredIdPreviousFrame;
|
||||
@@ -2172,7 +2250,7 @@ struct ImGuiContext
|
||||
ImGuiCol DebugFlashStyleColorIdx; // (Keep close to ColorStack to share cache line)
|
||||
ImVector<ImGuiColorMod> ColorStack; // Stack for PushStyleColor()/PopStyleColor() - inherited by Begin()
|
||||
ImVector<ImGuiStyleMod> StyleVarStack; // Stack for PushStyleVar()/PopStyleVar() - inherited by Begin()
|
||||
ImVector<ImFont*> FontStack; // Stack for PushFont()/PopFont() - inherited by Begin()
|
||||
ImVector<ImFontStackData> FontStack; // Stack for PushFont()/PopFont() - inherited by Begin()
|
||||
ImVector<ImGuiFocusScopeData> FocusScopeStack; // Stack for PushFocusScope()/PopFocusScope() - inherited by BeginChild(), pushed into by Begin()
|
||||
ImVector<ImGuiItemFlags> ItemFlagsStack; // Stack for PushItemFlag()/PopItemFlag() - inherited by Begin()
|
||||
ImVector<ImGuiGroupData> GroupStack; // Stack for BeginGroup()/EndGroup() - not inherited by Begin()
|
||||
@@ -2194,18 +2272,19 @@ struct ImGuiContext
|
||||
ImGuiWindow* NavWindow; // Focused window for navigation. Could be called 'FocusedWindow'
|
||||
ImGuiID NavFocusScopeId; // Focused focus scope (e.g. selection code often wants to "clear other items" when landing on an item of the same scope)
|
||||
ImGuiNavLayer NavLayer; // Focused layer (main scrolling layer, or menu/title bar layer)
|
||||
ImGuiID NavActivateId; // ~~ (g.ActiveId == 0) && (IsKeyPressed(ImGuiKey_Space) || IsKeyDown(ImGuiKey_Enter) || IsKeyPressed(ImGuiKey_NavGamepadActivate)) ? NavId : 0, also set when calling ActivateItem()
|
||||
ImGuiID NavActivateId; // ~~ (g.ActiveId == 0) && (IsKeyPressed(ImGuiKey_Space) || IsKeyDown(ImGuiKey_Enter) || IsKeyPressed(ImGuiKey_NavGamepadActivate)) ? NavId : 0, also set when calling ActivateItemByID()
|
||||
ImGuiID NavActivateDownId; // ~~ IsKeyDown(ImGuiKey_Space) || IsKeyDown(ImGuiKey_Enter) || IsKeyDown(ImGuiKey_NavGamepadActivate) ? NavId : 0
|
||||
ImGuiID NavActivatePressedId; // ~~ IsKeyPressed(ImGuiKey_Space) || IsKeyPressed(ImGuiKey_Enter) || IsKeyPressed(ImGuiKey_NavGamepadActivate) ? NavId : 0 (no repeat)
|
||||
ImGuiActivateFlags NavActivateFlags;
|
||||
ImVector<ImGuiFocusScopeData> NavFocusRoute; // Reversed copy focus scope stack for NavId (should contains NavFocusScopeId). This essentially follow the window->ParentWindowForFocusRoute chain.
|
||||
ImGuiID NavHighlightActivatedId;
|
||||
float NavHighlightActivatedTimer;
|
||||
ImGuiID NavNextActivateId; // Set by ActivateItem(), queued until next frame.
|
||||
ImGuiID NavNextActivateId; // Set by ActivateItemByID(), queued until next frame.
|
||||
ImGuiActivateFlags NavNextActivateFlags;
|
||||
ImGuiInputSource NavInputSource; // Keyboard or Gamepad mode? THIS CAN ONLY BE ImGuiInputSource_Keyboard or ImGuiInputSource_Mouse
|
||||
ImGuiSelectionUserData NavLastValidSelectionUserData; // Last valid data passed to SetNextItemSelectionUser(), or -1. For current window. Not reset when focusing an item that doesn't have selection data.
|
||||
ImS8 NavCursorHideFrames;
|
||||
//ImGuiID NavActivateInputId; // Removed in 1.89.4 (July 2023). This is now part of g.NavActivateId and sets g.NavActivateFlags |= ImGuiActivateFlags_PreferInput. See commit c9a53aa74, issue #5606.
|
||||
|
||||
// Navigation: Init & Move Requests
|
||||
bool NavAnyRequest; // ~~ NavMoveRequest || NavInitRequest this is to perform early out in ItemAdd()
|
||||
@@ -2240,6 +2319,7 @@ struct ImGuiContext
|
||||
bool NavJustMovedToHasSelectionData; // Copy of move result's ItemFlags & ImGuiItemFlags_HasSelectionUserData). Maybe we should just store ImGuiNavItemData.
|
||||
|
||||
// Navigation: Windowing (CTRL+TAB for list, or Menu button + keys or directional pads to move/resize)
|
||||
bool ConfigNavWindowingWithGamepad; // = true. Enable CTRL+TAB by holding ImGuiKey_GamepadFaceLeft (== ImGuiKey_NavGamepadMenu). When false, the button may still be used to toggle Menu layer.
|
||||
ImGuiKeyChord ConfigNavWindowingKeyNext; // = ImGuiMod_Ctrl | ImGuiKey_Tab (or ImGuiMod_Super | ImGuiKey_Tab on OS X). For reconfiguration (see #4828)
|
||||
ImGuiKeyChord ConfigNavWindowingKeyPrev; // = ImGuiMod_Ctrl | ImGuiMod_Shift | ImGuiKey_Tab (or ImGuiMod_Super | ImGuiMod_Shift | ImGuiKey_Tab on OS X)
|
||||
ImGuiWindow* NavWindowingTarget; // Target window when doing CTRL+Tab (or Pad Menu + FocusPrev/Next), this window is temporarily displayed top-most!
|
||||
@@ -2247,6 +2327,7 @@ struct ImGuiContext
|
||||
ImGuiWindow* NavWindowingListWindow; // Internal window actually listing the CTRL+Tab contents
|
||||
float NavWindowingTimer;
|
||||
float NavWindowingHighlightAlpha;
|
||||
ImGuiInputSource NavWindowingInputSource;
|
||||
bool NavWindowingToggleLayer;
|
||||
ImGuiKey NavWindowingToggleKey;
|
||||
ImVec2 NavWindowingAccumDeltaPos;
|
||||
@@ -2317,7 +2398,8 @@ struct ImGuiContext
|
||||
// Widget state
|
||||
ImGuiInputTextState InputTextState;
|
||||
ImGuiInputTextDeactivatedState InputTextDeactivatedState;
|
||||
ImFont InputTextPasswordFont;
|
||||
ImFontBaked InputTextPasswordFontBackupBaked;
|
||||
ImFontFlags InputTextPasswordFontBackupFlags;
|
||||
ImGuiID TempInputId; // Temporary text input when CTRL+clicking on a slider, etc.
|
||||
ImGuiDataTypeStorage DataTypeZeroValue; // 0 for all data types
|
||||
int BeginMenuDepth;
|
||||
@@ -2349,9 +2431,13 @@ struct ImGuiContext
|
||||
ImGuiTypingSelectState TypingSelectState; // State for GetTypingSelectRequest()
|
||||
|
||||
// Platform support
|
||||
ImGuiPlatformImeData PlatformImeData; // Data updated by current frame
|
||||
ImGuiPlatformImeData PlatformImeData; // Data updated by current frame. Will be applied at end of the frame. For some backends, this is required to have WantVisible=true in order to receive text message.
|
||||
ImGuiPlatformImeData PlatformImeDataPrev; // Previous frame data. When changed we call the platform_io.Platform_SetImeDataFn() handler.
|
||||
|
||||
// Extensions
|
||||
// FIXME: We could provide an API to register one slot in an array held in ImGuiContext?
|
||||
ImVector<ImTextureData*> UserTextures; // List of textures created/managed by user or third-party extension. Automatically appended into platform_io.Textures[].
|
||||
|
||||
// Settings
|
||||
bool SettingsLoaded;
|
||||
float SettingsDirtyTimer; // Save .ini Settings to memory when time reaches zero
|
||||
@@ -2409,6 +2495,10 @@ struct ImGuiContext
|
||||
ImGuiMetricsConfig DebugMetricsConfig;
|
||||
ImGuiIDStackTool DebugIDStackTool;
|
||||
ImGuiDebugAllocInfo DebugAllocInfo;
|
||||
#if defined(IMGUI_DEBUG_HIGHLIGHT_ALL_ID_CONFLICTS) && !defined(IMGUI_DISABLE_DEBUG_TOOLS)
|
||||
ImGuiStorage DebugDrawIdConflictsAliveCount;
|
||||
ImGuiStorage DebugDrawIdConflictsHighlightSet;
|
||||
#endif
|
||||
|
||||
// Misc
|
||||
float FramerateSecPerFrame[60]; // Calculate estimate of framerate for user over the last 60 frames..
|
||||
@@ -2417,7 +2507,7 @@ struct ImGuiContext
|
||||
float FramerateSecPerFrameAccum;
|
||||
int WantCaptureMouseNextFrame; // Explicit capture override via SetNextFrameWantCaptureMouse()/SetNextFrameWantCaptureKeyboard(). Default to -1.
|
||||
int WantCaptureKeyboardNextFrame; // "
|
||||
int WantTextInputNextFrame;
|
||||
int WantTextInputNextFrame; // Copied in EndFrame() from g.PlatformImeData.WantTextInput. Needs to be set for some backends (SDL3) to emit character inputs.
|
||||
ImVector<char> TempBuffer; // Temporary text buffer
|
||||
char TempKeychordName[64];
|
||||
|
||||
@@ -2463,7 +2553,8 @@ struct IMGUI_API ImGuiWindowTempData
|
||||
ImVec2 MenuBarOffset; // MenuBarOffset.x is sort of equivalent of a per-layer CursorPos.x, saved/restored as we switch to the menu bar. The only situation when MenuBarOffset.y is > 0 if when (SafeAreaPadding.y > FramePadding.y), often used on TVs.
|
||||
ImGuiMenuColumns MenuColumns; // Simplified columns storage for menu items measurement
|
||||
int TreeDepth; // Current tree depth.
|
||||
ImU32 TreeHasStackDataDepthMask; // Store whether given depth has ImGuiTreeNodeStackData data. Could be turned into a ImU64 if necessary.
|
||||
ImU32 TreeHasStackDataDepthMask; // Store whether given depth has ImGuiTreeNodeStackData data. Could be turned into a ImU64 if necessary.
|
||||
ImU32 TreeRecordsClippedNodesY2Mask; // Store whether we should keep recording Y2. Cleared when passing clip max. Equivalent TreeHasStackDataDepthMask value should always be set.
|
||||
ImVector<ImGuiWindow*> ChildWindows;
|
||||
ImGuiStorage* StateStorage; // Current persistent per-window storage (store e.g. tree node open/close state)
|
||||
ImGuiOldColumns* CurrentColumns; // Current columns set
|
||||
@@ -2606,9 +2697,11 @@ public:
|
||||
|
||||
// We don't use g.FontSize because the window may be != g.CurrentWindow.
|
||||
ImRect Rect() const { return ImRect(Pos.x, Pos.y, Pos.x + Size.x, Pos.y + Size.y); }
|
||||
float CalcFontSize() const { ImGuiContext& g = *Ctx; return g.FontBaseSize * FontWindowScale * FontWindowScaleParents; }
|
||||
ImRect TitleBarRect() const { return ImRect(Pos, ImVec2(Pos.x + SizeFull.x, Pos.y + TitleBarHeight)); }
|
||||
ImRect MenuBarRect() const { float y1 = Pos.y + TitleBarHeight; return ImRect(Pos.x, y1, Pos.x + SizeFull.x, y1 + MenuBarHeight); }
|
||||
|
||||
// [Obsolete] ImGuiWindow::CalcFontSize() was removed in 1.92.x because error-prone/misleading. You can use window->FontRefSize for a copy of g.FontSize at the time of the last Begin() call for this window.
|
||||
//float CalcFontSize() const { ImGuiContext& g = *Ctx; return g.FontSizeBase * FontWindowScale * FontWindowScaleParents;
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -2698,11 +2791,7 @@ struct IMGUI_API ImGuiTabBar
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#define IM_COL32_DISABLE IM_COL32(0,0,0,1) // Special sentinel code which cannot be used as a regular color.
|
||||
#define IMGUI_TABLE_MAX_COLUMNS 512 // May be further lifted
|
||||
|
||||
// Our current column maximum is 64 but we may raise that in the future.
|
||||
typedef ImS16 ImGuiTableColumnIdx;
|
||||
typedef ImU16 ImGuiTableDrawChannelIdx;
|
||||
#define IMGUI_TABLE_MAX_COLUMNS 512 // Arbitrary "safety" maximum, may be lifted in the future if needed. Must fit in ImGuiTableColumnIdx/ImGuiTableDrawChannelIdx.
|
||||
|
||||
// [Internal] sizeof() ~ 112
|
||||
// We use the terminology "Enabled" to refer to a column that is not Hidden by user/api.
|
||||
@@ -2901,7 +2990,7 @@ struct IMGUI_API ImGuiTable
|
||||
bool IsSortSpecsDirty;
|
||||
bool IsUsingHeaders; // Set when the first row had the ImGuiTableRowFlags_Headers flag.
|
||||
bool IsContextPopupOpen; // Set when default context menu is open (also see: ContextPopupColumn, InstanceInteracted).
|
||||
bool DisableDefaultContextMenu; // Disable default context menu contents. You may submit your own using TableBeginContextMenuPopup()/EndPopup()
|
||||
bool DisableDefaultContextMenu; // Disable default context menu. You may submit your own using TableBeginContextMenuPopup()/EndPopup()
|
||||
bool IsSettingsRequestLoad;
|
||||
bool IsSettingsDirty; // Set when table settings have changed and needs to be reported into ImGuiTableSetttings data.
|
||||
bool IsDefaultDisplayOrder; // Set when display order is unchanged from default (DisplayOrder contains 0...Count-1)
|
||||
@@ -3035,9 +3124,18 @@ namespace ImGui
|
||||
IMGUI_API void SetNextWindowRefreshPolicy(ImGuiWindowRefreshFlags flags);
|
||||
|
||||
// Fonts, drawing
|
||||
IMGUI_API void SetCurrentFont(ImFont* font);
|
||||
inline ImFont* GetDefaultFont() { ImGuiContext& g = *GImGui; return g.IO.FontDefault ? g.IO.FontDefault : g.IO.Fonts->Fonts[0]; }
|
||||
IMGUI_API void RegisterUserTexture(ImTextureData* tex); // Register external texture
|
||||
IMGUI_API void UnregisterUserTexture(ImTextureData* tex);
|
||||
IMGUI_API void RegisterFontAtlas(ImFontAtlas* atlas);
|
||||
IMGUI_API void UnregisterFontAtlas(ImFontAtlas* atlas);
|
||||
IMGUI_API void SetCurrentFont(ImFont* font, float font_size_before_scaling, float font_size_after_scaling);
|
||||
IMGUI_API void UpdateCurrentFontSize(float restore_font_size_after_scaling);
|
||||
IMGUI_API void SetFontRasterizerDensity(float rasterizer_density);
|
||||
inline float GetFontRasterizerDensity() { return GImGui->FontRasterizerDensity; }
|
||||
inline float GetRoundedFontSize(float size) { return IM_ROUND(size); }
|
||||
IMGUI_API ImFont* GetDefaultFont();
|
||||
IMGUI_API void PushPasswordFont();
|
||||
IMGUI_API void PopPasswordFont();
|
||||
inline ImDrawList* GetForegroundDrawList(ImGuiWindow* window) { IM_UNUSED(window); return GetForegroundDrawList(); } // This seemingly unnecessary wrapper simplifies compatibility between the 'master' and 'docking' branches.
|
||||
IMGUI_API ImDrawList* GetBackgroundDrawList(ImGuiViewport* viewport); // get background draw list for the given viewport. this draw list will be the first rendering one. Useful to quickly draw shapes/text behind dear imgui contents.
|
||||
IMGUI_API ImDrawList* GetForegroundDrawList(ImGuiViewport* viewport); // get foreground draw list for the given viewport. this draw list will be the last rendered one. Useful to quickly draw shapes/text over dear imgui contents.
|
||||
@@ -3049,7 +3147,7 @@ namespace ImGui
|
||||
|
||||
// NewFrame
|
||||
IMGUI_API void UpdateInputEvents(bool trickle_fast_inputs);
|
||||
IMGUI_API void UpdateHoveredWindowAndCaptureFlags();
|
||||
IMGUI_API void UpdateHoveredWindowAndCaptureFlags(const ImVec2& mouse_pos);
|
||||
IMGUI_API void FindHoveredWindowEx(const ImVec2& pos, bool find_first_and_in_any_viewport, ImGuiWindow** out_hovered_window, ImGuiWindow** out_hovered_window_under_moving_window);
|
||||
IMGUI_API void StartMouseMovingWindow(ImGuiWindow* window);
|
||||
IMGUI_API void UpdateMouseMovingWindowNewFrame();
|
||||
@@ -3175,7 +3273,7 @@ namespace ImGui
|
||||
IMGUI_API void NavMoveRequestSubmit(ImGuiDir move_dir, ImGuiDir clip_dir, ImGuiNavMoveFlags move_flags, ImGuiScrollFlags scroll_flags);
|
||||
IMGUI_API void NavMoveRequestForward(ImGuiDir move_dir, ImGuiDir clip_dir, ImGuiNavMoveFlags move_flags, ImGuiScrollFlags scroll_flags);
|
||||
IMGUI_API void NavMoveRequestResolveWithLastItem(ImGuiNavItemData* result);
|
||||
IMGUI_API void NavMoveRequestResolveWithPastTreeNode(ImGuiNavItemData* result, ImGuiTreeNodeStackData* tree_node_data);
|
||||
IMGUI_API void NavMoveRequestResolveWithPastTreeNode(ImGuiNavItemData* result, const ImGuiTreeNodeStackData* tree_node_data);
|
||||
IMGUI_API void NavMoveRequestCancel();
|
||||
IMGUI_API void NavMoveRequestApplyResult();
|
||||
IMGUI_API void NavMoveRequestTryWrapping(ImGuiWindow* window, ImGuiNavMoveFlags move_flags);
|
||||
@@ -3191,7 +3289,7 @@ namespace ImGui
|
||||
// This should be part of a larger set of API: FocusItem(offset = -1), FocusItemByID(id), ActivateItem(offset = -1), ActivateItemByID(id) etc. which are
|
||||
// much harder to design and implement than expected. I have a couple of private branches on this matter but it's not simple. For now implementing the easy ones.
|
||||
IMGUI_API void FocusItem(); // Focus last item (no selection/activation).
|
||||
IMGUI_API void ActivateItemByID(ImGuiID id); // Activate an item by ID (button, checkbox, tree node etc.). Activation is queued and processed on the next frame when the item is encountered again.
|
||||
IMGUI_API void ActivateItemByID(ImGuiID id); // Activate an item by ID (button, checkbox, tree node etc.). Activation is queued and processed on the next frame when the item is encountered again. Was called 'ActivateItem()' before 1.89.7.
|
||||
|
||||
// Inputs
|
||||
// FIXME: Eventually we should aim to move e.g. IsActiveIdUsingKey() into IsKeyXXX functions.
|
||||
@@ -3338,6 +3436,8 @@ namespace ImGui
|
||||
IMGUI_API float TableGetHeaderAngledMaxLabelWidth();
|
||||
IMGUI_API void TablePushBackgroundChannel();
|
||||
IMGUI_API void TablePopBackgroundChannel();
|
||||
IMGUI_API void TablePushColumnChannel(int column_n);
|
||||
IMGUI_API void TablePopColumnChannel();
|
||||
IMGUI_API void TableAngledHeadersRowEx(ImGuiID row_id, float angle, float max_label_width, const ImGuiTableHeaderData* data, int data_count);
|
||||
|
||||
// Tables: Internals
|
||||
@@ -3414,7 +3514,7 @@ namespace ImGui
|
||||
IMGUI_API void RenderTextWrapped(ImVec2 pos, const char* text, const char* text_end, float wrap_width);
|
||||
IMGUI_API void RenderTextClipped(const ImVec2& pos_min, const ImVec2& pos_max, const char* text, const char* text_end, const ImVec2* text_size_if_known, const ImVec2& align = ImVec2(0, 0), const ImRect* clip_rect = NULL);
|
||||
IMGUI_API void RenderTextClippedEx(ImDrawList* draw_list, const ImVec2& pos_min, const ImVec2& pos_max, const char* text, const char* text_end, const ImVec2* text_size_if_known, const ImVec2& align = ImVec2(0, 0), const ImRect* clip_rect = NULL);
|
||||
IMGUI_API void RenderTextEllipsis(ImDrawList* draw_list, const ImVec2& pos_min, const ImVec2& pos_max, float clip_max_x, float ellipsis_max_x, const char* text, const char* text_end, const ImVec2* text_size_if_known);
|
||||
IMGUI_API void RenderTextEllipsis(ImDrawList* draw_list, const ImVec2& pos_min, const ImVec2& pos_max, float ellipsis_max_x, const char* text, const char* text_end, const ImVec2* text_size_if_known);
|
||||
IMGUI_API void RenderFrame(ImVec2 p_min, ImVec2 p_max, ImU32 fill_col, bool borders = true, float rounding = 0.0f);
|
||||
IMGUI_API void RenderFrameBorder(ImVec2 p_min, ImVec2 p_max, float rounding = 0.0f);
|
||||
IMGUI_API void RenderColorRectWithAlphaCheckerboard(ImDrawList* draw_list, ImVec2 p_min, ImVec2 p_max, ImU32 fill_col, float grid_step, ImVec2 grid_off, float rounding = 0.0f, ImDrawFlags flags = 0);
|
||||
@@ -3433,11 +3533,15 @@ namespace ImGui
|
||||
IMGUI_API void RenderRectFilledRangeH(ImDrawList* draw_list, const ImRect& rect, ImU32 col, float x_start_norm, float x_end_norm, float rounding);
|
||||
IMGUI_API void RenderRectFilledWithHole(ImDrawList* draw_list, const ImRect& outer, const ImRect& inner, ImU32 col, float rounding);
|
||||
|
||||
// Widgets
|
||||
// Widgets: Text
|
||||
IMGUI_API void TextEx(const char* text, const char* text_end = NULL, ImGuiTextFlags flags = 0);
|
||||
IMGUI_API void TextAligned(float align_x, float size_x, const char* fmt, ...); // FIXME-WIP: Works but API is likely to be reworked. This is designed for 1 item on the line. (#7024)
|
||||
IMGUI_API void TextAlignedV(float align_x, float size_x, const char* fmt, va_list args);
|
||||
|
||||
// Widgets
|
||||
IMGUI_API bool ButtonEx(const char* label, const ImVec2& size_arg = ImVec2(0, 0), ImGuiButtonFlags flags = 0);
|
||||
IMGUI_API bool ArrowButtonEx(const char* str_id, ImGuiDir dir, ImVec2 size_arg, ImGuiButtonFlags flags = 0);
|
||||
IMGUI_API bool ImageButtonEx(ImGuiID id, ImTextureID user_texture_id, const ImVec2& image_size, const ImVec2& uv0, const ImVec2& uv1, const ImVec4& bg_col, const ImVec4& tint_col, ImGuiButtonFlags flags = 0);
|
||||
IMGUI_API bool ImageButtonEx(ImGuiID id, ImTextureRef tex_ref, const ImVec2& image_size, const ImVec2& uv0, const ImVec2& uv1, const ImVec4& bg_col, const ImVec4& tint_col, ImGuiButtonFlags flags = 0);
|
||||
IMGUI_API void SeparatorEx(ImGuiSeparatorFlags flags, float thickness = 1.0f);
|
||||
IMGUI_API void SeparatorTextEx(ImGuiID id, const char* label, const char* label_end, float extra_width);
|
||||
IMGUI_API bool CheckboxFlags(const char* label, ImS64* flags, ImS64 flags_value);
|
||||
@@ -3461,6 +3565,8 @@ namespace ImGui
|
||||
|
||||
// Widgets: Tree Nodes
|
||||
IMGUI_API bool TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* label, const char* label_end = NULL);
|
||||
IMGUI_API void TreeNodeDrawLineToChildNode(const ImVec2& target_pos);
|
||||
IMGUI_API void TreeNodeDrawLineToTreePop(const ImGuiTreeNodeStackData* data);
|
||||
IMGUI_API void TreePushOverrideID(ImGuiID id);
|
||||
IMGUI_API bool TreeNodeGetOpen(ImGuiID storage_id);
|
||||
IMGUI_API void TreeNodeSetOpen(ImGuiID storage_id, bool open);
|
||||
@@ -3541,7 +3647,9 @@ namespace ImGui
|
||||
IMGUI_API void DebugNodeDrawList(ImGuiWindow* window, ImGuiViewportP* viewport, const ImDrawList* draw_list, const char* label);
|
||||
IMGUI_API void DebugNodeDrawCmdShowMeshAndBoundingBox(ImDrawList* out_draw_list, const ImDrawList* draw_list, const ImDrawCmd* draw_cmd, bool show_mesh, bool show_aabb);
|
||||
IMGUI_API void DebugNodeFont(ImFont* font);
|
||||
IMGUI_API void DebugNodeFontGlyphesForSrcMask(ImFont* font, ImFontBaked* baked, int src_mask);
|
||||
IMGUI_API void DebugNodeFontGlyph(ImFont* font, const ImFontGlyph* glyph);
|
||||
IMGUI_API void DebugNodeTexture(ImTextureData* tex, int int_id, const ImFontAtlasRect* highlight_rect = NULL); // ID used to facilitate persisting the "current" texture.
|
||||
IMGUI_API void DebugNodeStorage(ImGuiStorage* storage, const char* label);
|
||||
IMGUI_API void DebugNodeTabBar(ImGuiTabBar* tab_bar, const char* label);
|
||||
IMGUI_API void DebugNodeTable(ImGuiTable* table);
|
||||
@@ -3563,6 +3671,7 @@ namespace ImGui
|
||||
//inline bool TreeNodeBehaviorIsOpen(ImGuiID id, ImGuiTreeNodeFlags flags = 0) { return TreeNodeUpdateNextOpen(id, flags); } // Renamed in 1.89
|
||||
//inline bool IsKeyPressedMap(ImGuiKey key, bool repeat = true) { IM_ASSERT(IsNamedKey(key)); return IsKeyPressed(key, repeat); } // Removed in 1.87: Mapping from named key is always identity!
|
||||
|
||||
// Refactored focus/nav/tabbing system in 1.82 and 1.84. If you have old/custom copy-and-pasted widgets which used FocusableItemRegister():
|
||||
// Refactored focus/nav/tabbing system in 1.82 and 1.84. If you have old/custom copy-and-pasted widgets which used FocusableItemRegister():
|
||||
// (Old) IMGUI_VERSION_NUM < 18209: using 'ItemAdd(....)' and 'bool tab_focused = FocusableItemRegister(...)'
|
||||
// (Old) IMGUI_VERSION_NUM >= 18209: using 'ItemAdd(..., ImGuiItemAddFlags_Focusable)' and 'bool tab_focused = (g.LastItemData.StatusFlags & ImGuiItemStatusFlags_Focused) != 0'
|
||||
@@ -3574,31 +3683,192 @@ namespace ImGui
|
||||
} // namespace ImGui
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// [SECTION] ImFontLoader
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// Hooks and storage for a given font backend.
|
||||
// This structure is likely to evolve as we add support for incremental atlas updates.
|
||||
// Conceptually this could be public, but API is still going to be evolve.
|
||||
struct ImFontLoader
|
||||
{
|
||||
const char* Name;
|
||||
bool (*LoaderInit)(ImFontAtlas* atlas);
|
||||
void (*LoaderShutdown)(ImFontAtlas* atlas);
|
||||
bool (*FontSrcInit)(ImFontAtlas* atlas, ImFontConfig* src);
|
||||
void (*FontSrcDestroy)(ImFontAtlas* atlas, ImFontConfig* src);
|
||||
bool (*FontSrcContainsGlyph)(ImFontAtlas* atlas, ImFontConfig* src, ImWchar codepoint);
|
||||
bool (*FontBakedInit)(ImFontAtlas* atlas, ImFontConfig* src, ImFontBaked* baked, void* loader_data_for_baked_src);
|
||||
void (*FontBakedDestroy)(ImFontAtlas* atlas, ImFontConfig* src, ImFontBaked* baked, void* loader_data_for_baked_src);
|
||||
bool (*FontBakedLoadGlyph)(ImFontAtlas* atlas, ImFontConfig* src, ImFontBaked* baked, void* loader_data_for_baked_src, ImWchar codepoint, ImFontGlyph* out_glyph, float* out_advance_x);
|
||||
|
||||
// Size of backend data, Per Baked * Per Source. Buffers are managed by core to avoid excessive allocations.
|
||||
// FIXME: At this point the two other types of buffers may be managed by core to be consistent?
|
||||
size_t FontBakedSrcLoaderDataSize;
|
||||
|
||||
ImFontLoader() { memset(this, 0, sizeof(*this)); }
|
||||
};
|
||||
|
||||
#ifdef IMGUI_ENABLE_STB_TRUETYPE
|
||||
IMGUI_API const ImFontLoader* ImFontAtlasGetFontLoaderForStbTruetype();
|
||||
#endif
|
||||
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
|
||||
typedef ImFontLoader ImFontBuilderIO; // [renamed/changed in 1.92] The types are not actually compatible but we provide this as a compile-time error report helper.
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// [SECTION] ImFontAtlas internal API
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// This structure is likely to evolve as we add support for incremental atlas updates.
|
||||
// Conceptually this could be in ImGuiPlatformIO, but we are far from ready to make this public.
|
||||
struct ImFontBuilderIO
|
||||
#define IMGUI_FONT_SIZE_MAX (512.0f)
|
||||
#define IMGUI_FONT_SIZE_THRESHOLD_FOR_LOADADVANCEXONLYMODE (128.0f)
|
||||
|
||||
// Helpers: ImTextureRef ==/!= operators provided as convenience
|
||||
// (note that _TexID and _TexData are never set simultaneously)
|
||||
inline bool operator==(const ImTextureRef& lhs, const ImTextureRef& rhs) { return lhs._TexID == rhs._TexID && lhs._TexData == rhs._TexData; }
|
||||
inline bool operator!=(const ImTextureRef& lhs, const ImTextureRef& rhs) { return lhs._TexID != rhs._TexID || lhs._TexData != rhs._TexData; }
|
||||
|
||||
// Refer to ImFontAtlasPackGetRect() to better understand how this works.
|
||||
#define ImFontAtlasRectId_IndexMask_ (0x000FFFFF) // 20-bits: index to access builder->RectsIndex[].
|
||||
#define ImFontAtlasRectId_GenerationMask_ (0x3FF00000) // 10-bits: entry generation, so each ID is unique and get can safely detected old identifiers.
|
||||
#define ImFontAtlasRectId_GenerationShift_ (20)
|
||||
inline int ImFontAtlasRectId_GetIndex(ImFontAtlasRectId id) { return id & ImFontAtlasRectId_IndexMask_; }
|
||||
inline int ImFontAtlasRectId_GetGeneration(ImFontAtlasRectId id) { return (id & ImFontAtlasRectId_GenerationMask_) >> ImFontAtlasRectId_GenerationShift_; }
|
||||
inline ImFontAtlasRectId ImFontAtlasRectId_Make(int index_idx, int gen_idx) { IM_ASSERT(index_idx < ImFontAtlasRectId_IndexMask_ && gen_idx < (ImFontAtlasRectId_GenerationMask_ >> ImFontAtlasRectId_GenerationShift_)); return (ImFontAtlasRectId)(index_idx | (gen_idx << ImFontAtlasRectId_GenerationShift_)); }
|
||||
|
||||
// Packed rectangle lookup entry (we need an indirection to allow removing/reordering rectangles)
|
||||
// User are returned ImFontAtlasRectId values which are meant to be persistent.
|
||||
// We handle this with an indirection. While Rects[] may be in theory shuffled, compacted etc., RectsIndex[] cannot it is keyed by ImFontAtlasRectId.
|
||||
// RectsIndex[] is used both as an index into Rects[] and an index into itself. This is basically a free-list. See ImFontAtlasBuildAllocRectIndexEntry() code.
|
||||
// Having this also makes it easier to e.g. sort rectangles during repack.
|
||||
struct ImFontAtlasRectEntry
|
||||
{
|
||||
bool (*FontBuilder_Build)(ImFontAtlas* atlas);
|
||||
int TargetIndex : 20; // When Used: ImFontAtlasRectId -> into Rects[]. When unused: index to next unused RectsIndex[] slot to consume free-list.
|
||||
int Generation : 10; // Increased each time the entry is reused for a new rectangle.
|
||||
unsigned int IsUsed : 1;
|
||||
};
|
||||
|
||||
// Helper for font builder
|
||||
#ifdef IMGUI_ENABLE_STB_TRUETYPE
|
||||
IMGUI_API const ImFontBuilderIO* ImFontAtlasGetBuilderForStbTruetype();
|
||||
// Data available to potential texture post-processing functions
|
||||
struct ImFontAtlasPostProcessData
|
||||
{
|
||||
ImFontAtlas* FontAtlas;
|
||||
ImFont* Font;
|
||||
ImFontConfig* FontSrc;
|
||||
ImFontBaked* FontBaked;
|
||||
ImFontGlyph* Glyph;
|
||||
|
||||
// Pixel data
|
||||
void* Pixels;
|
||||
ImTextureFormat Format;
|
||||
int Pitch;
|
||||
int Width;
|
||||
int Height;
|
||||
};
|
||||
|
||||
// We avoid dragging imstb_rectpack.h into public header (partly because binding generators are having issues with it)
|
||||
#ifdef IMGUI_STB_NAMESPACE
|
||||
namespace IMGUI_STB_NAMESPACE { struct stbrp_node; }
|
||||
typedef IMGUI_STB_NAMESPACE::stbrp_node stbrp_node_im;
|
||||
#else
|
||||
struct stbrp_node;
|
||||
typedef stbrp_node stbrp_node_im;
|
||||
#endif
|
||||
struct stbrp_context_opaque { char data[80]; };
|
||||
|
||||
// Internal storage for incrementally packing and building a ImFontAtlas
|
||||
struct ImFontAtlasBuilder
|
||||
{
|
||||
stbrp_context_opaque PackContext; // Actually 'stbrp_context' but we don't want to define this in the header file.
|
||||
ImVector<stbrp_node_im> PackNodes;
|
||||
ImVector<ImTextureRect> Rects;
|
||||
ImVector<ImFontAtlasRectEntry> RectsIndex; // ImFontAtlasRectId -> index into Rects[]
|
||||
ImVector<unsigned char> TempBuffer; // Misc scratch buffer
|
||||
int RectsIndexFreeListStart;// First unused entry
|
||||
int RectsPackedCount; // Number of packed rectangles.
|
||||
int RectsPackedSurface; // Number of packed pixels. Used when compacting to heuristically find the ideal texture size.
|
||||
int RectsDiscardedCount;
|
||||
int RectsDiscardedSurface;
|
||||
int FrameCount; // Current frame count
|
||||
ImVec2i MaxRectSize; // Largest rectangle to pack (de-facto used as a "minimum texture size")
|
||||
ImVec2i MaxRectBounds; // Bottom-right most used pixels
|
||||
bool LockDisableResize; // Disable resizing texture
|
||||
bool PreloadedAllGlyphsRanges; // Set when missing ImGuiBackendFlags_RendererHasTextures features forces atlas to preload everything.
|
||||
|
||||
// Cache of all ImFontBaked
|
||||
ImStableVector<ImFontBaked,32> BakedPool;
|
||||
ImGuiStorage BakedMap; // BakedId --> ImFontBaked*
|
||||
int BakedDiscardedCount;
|
||||
|
||||
// Custom rectangle identifiers
|
||||
ImFontAtlasRectId PackIdMouseCursors; // White pixel + mouse cursors. Also happen to be fallback in case of packing failure.
|
||||
ImFontAtlasRectId PackIdLinesTexData;
|
||||
|
||||
ImFontAtlasBuilder() { memset(this, 0, sizeof(*this)); FrameCount = -1; RectsIndexFreeListStart = -1; PackIdMouseCursors = PackIdLinesTexData = -1; }
|
||||
};
|
||||
|
||||
IMGUI_API void ImFontAtlasBuildInit(ImFontAtlas* atlas);
|
||||
IMGUI_API void ImFontAtlasBuildDestroy(ImFontAtlas* atlas);
|
||||
IMGUI_API void ImFontAtlasBuildMain(ImFontAtlas* atlas);
|
||||
IMGUI_API void ImFontAtlasBuildSetupFontLoader(ImFontAtlas* atlas, const ImFontLoader* font_loader);
|
||||
IMGUI_API void ImFontAtlasBuildUpdatePointers(ImFontAtlas* atlas);
|
||||
IMGUI_API void ImFontAtlasBuildRenderBitmapFromString(ImFontAtlas* atlas, int x, int y, int w, int h, const char* in_str, char in_marker_char);
|
||||
IMGUI_API void ImFontAtlasBuildClear(ImFontAtlas* atlas); // Clear output and custom rects
|
||||
|
||||
IMGUI_API ImTextureData* ImFontAtlasTextureAdd(ImFontAtlas* atlas, int w, int h);
|
||||
IMGUI_API void ImFontAtlasTextureMakeSpace(ImFontAtlas* atlas);
|
||||
IMGUI_API void ImFontAtlasTextureRepack(ImFontAtlas* atlas, int w, int h);
|
||||
IMGUI_API void ImFontAtlasTextureGrow(ImFontAtlas* atlas, int old_w = -1, int old_h = -1);
|
||||
IMGUI_API void ImFontAtlasTextureCompact(ImFontAtlas* atlas);
|
||||
IMGUI_API ImVec2i ImFontAtlasTextureGetSizeEstimate(ImFontAtlas* atlas);
|
||||
|
||||
IMGUI_API void ImFontAtlasBuildSetupFontSpecialGlyphs(ImFontAtlas* atlas, ImFont* font, ImFontConfig* src);
|
||||
IMGUI_API void ImFontAtlasBuildLegacyPreloadAllGlyphRanges(ImFontAtlas* atlas); // Legacy
|
||||
IMGUI_API void ImFontAtlasBuildGetOversampleFactors(ImFontConfig* src, ImFontBaked* baked, int* out_oversample_h, int* out_oversample_v);
|
||||
IMGUI_API void ImFontAtlasBuildDiscardBakes(ImFontAtlas* atlas, int unused_frames);
|
||||
|
||||
IMGUI_API bool ImFontAtlasFontSourceInit(ImFontAtlas* atlas, ImFontConfig* src);
|
||||
IMGUI_API void ImFontAtlasFontSourceAddToFont(ImFontAtlas* atlas, ImFont* font, ImFontConfig* src);
|
||||
IMGUI_API void ImFontAtlasFontDestroySourceData(ImFontAtlas* atlas, ImFontConfig* src);
|
||||
IMGUI_API bool ImFontAtlasFontInitOutput(ImFontAtlas* atlas, ImFont* font); // Using FontDestroyOutput/FontInitOutput sequence useful notably if font loader params have changed
|
||||
IMGUI_API void ImFontAtlasFontDestroyOutput(ImFontAtlas* atlas, ImFont* font);
|
||||
IMGUI_API void ImFontAtlasFontDiscardBakes(ImFontAtlas* atlas, ImFont* font, int unused_frames);
|
||||
|
||||
IMGUI_API ImGuiID ImFontAtlasBakedGetId(ImGuiID font_id, float baked_size, float rasterizer_density);
|
||||
IMGUI_API ImFontBaked* ImFontAtlasBakedGetOrAdd(ImFontAtlas* atlas, ImFont* font, float font_size, float font_rasterizer_density);
|
||||
IMGUI_API ImFontBaked* ImFontAtlasBakedGetClosestMatch(ImFontAtlas* atlas, ImFont* font, float font_size, float font_rasterizer_density);
|
||||
IMGUI_API ImFontBaked* ImFontAtlasBakedAdd(ImFontAtlas* atlas, ImFont* font, float font_size, float font_rasterizer_density, ImGuiID baked_id);
|
||||
IMGUI_API void ImFontAtlasBakedDiscard(ImFontAtlas* atlas, ImFont* font, ImFontBaked* baked);
|
||||
IMGUI_API ImFontGlyph* ImFontAtlasBakedAddFontGlyph(ImFontAtlas* atlas, ImFontBaked* baked, ImFontConfig* src, const ImFontGlyph* in_glyph);
|
||||
IMGUI_API void ImFontAtlasBakedAddFontGlyphAdvancedX(ImFontAtlas* atlas, ImFontBaked* baked, ImFontConfig* src, ImWchar codepoint, float advance_x);
|
||||
IMGUI_API void ImFontAtlasBakedDiscardFontGlyph(ImFontAtlas* atlas, ImFont* font, ImFontBaked* baked, ImFontGlyph* glyph);
|
||||
IMGUI_API void ImFontAtlasBakedSetFontGlyphBitmap(ImFontAtlas* atlas, ImFontBaked* baked, ImFontConfig* src, ImFontGlyph* glyph, ImTextureRect* r, const unsigned char* src_pixels, ImTextureFormat src_fmt, int src_pitch);
|
||||
|
||||
IMGUI_API void ImFontAtlasPackInit(ImFontAtlas* atlas);
|
||||
IMGUI_API ImFontAtlasRectId ImFontAtlasPackAddRect(ImFontAtlas* atlas, int w, int h, ImFontAtlasRectEntry* overwrite_entry = NULL);
|
||||
IMGUI_API ImTextureRect* ImFontAtlasPackGetRect(ImFontAtlas* atlas, ImFontAtlasRectId id);
|
||||
IMGUI_API ImTextureRect* ImFontAtlasPackGetRectSafe(ImFontAtlas* atlas, ImFontAtlasRectId id);
|
||||
IMGUI_API void ImFontAtlasPackDiscardRect(ImFontAtlas* atlas, ImFontAtlasRectId id);
|
||||
|
||||
IMGUI_API void ImFontAtlasUpdateNewFrame(ImFontAtlas* atlas, int frame_count, bool renderer_has_textures);
|
||||
IMGUI_API void ImFontAtlasAddDrawListSharedData(ImFontAtlas* atlas, ImDrawListSharedData* data);
|
||||
IMGUI_API void ImFontAtlasRemoveDrawListSharedData(ImFontAtlas* atlas, ImDrawListSharedData* data);
|
||||
IMGUI_API void ImFontAtlasUpdateDrawListsTextures(ImFontAtlas* atlas, ImTextureRef old_tex, ImTextureRef new_tex);
|
||||
IMGUI_API void ImFontAtlasUpdateDrawListsSharedData(ImFontAtlas* atlas);
|
||||
|
||||
IMGUI_API void ImFontAtlasTextureBlockConvert(const unsigned char* src_pixels, ImTextureFormat src_fmt, int src_pitch, unsigned char* dst_pixels, ImTextureFormat dst_fmt, int dst_pitch, int w, int h);
|
||||
IMGUI_API void ImFontAtlasTextureBlockPostProcess(ImFontAtlasPostProcessData* data);
|
||||
IMGUI_API void ImFontAtlasTextureBlockPostProcessMultiply(ImFontAtlasPostProcessData* data, float multiply_factor);
|
||||
IMGUI_API void ImFontAtlasTextureBlockFill(ImTextureData* dst_tex, int dst_x, int dst_y, int w, int h, ImU32 col);
|
||||
IMGUI_API void ImFontAtlasTextureBlockCopy(ImTextureData* src_tex, int src_x, int src_y, ImTextureData* dst_tex, int dst_x, int dst_y, int w, int h);
|
||||
IMGUI_API void ImFontAtlasTextureBlockQueueUpload(ImFontAtlas* atlas, ImTextureData* tex, int x, int y, int w, int h);
|
||||
|
||||
IMGUI_API int ImTextureDataGetFormatBytesPerPixel(ImTextureFormat format);
|
||||
IMGUI_API const char* ImTextureDataGetStatusName(ImTextureStatus status);
|
||||
IMGUI_API const char* ImTextureDataGetFormatName(ImTextureFormat format);
|
||||
|
||||
#ifndef IMGUI_DISABLE_DEBUG_TOOLS
|
||||
IMGUI_API void ImFontAtlasDebugLogTextureRequests(ImFontAtlas* atlas);
|
||||
#endif
|
||||
IMGUI_API void ImFontAtlasUpdateSourcesPointers(ImFontAtlas* atlas);
|
||||
IMGUI_API void ImFontAtlasBuildInit(ImFontAtlas* atlas);
|
||||
IMGUI_API void ImFontAtlasBuildSetupFont(ImFontAtlas* atlas, ImFont* font, ImFontConfig* src, float ascent, float descent);
|
||||
IMGUI_API void ImFontAtlasBuildPackCustomRects(ImFontAtlas* atlas, void* stbrp_context_opaque);
|
||||
IMGUI_API void ImFontAtlasBuildFinish(ImFontAtlas* atlas);
|
||||
IMGUI_API void ImFontAtlasBuildRender8bppRectFromString(ImFontAtlas* atlas, int x, int y, int w, int h, const char* in_str, char in_marker_char, unsigned char in_marker_pixel_value);
|
||||
IMGUI_API void ImFontAtlasBuildRender32bppRectFromString(ImFontAtlas* atlas, int x, int y, int w, int h, const char* in_str, char in_marker_char, unsigned int in_marker_pixel_value);
|
||||
IMGUI_API void ImFontAtlasBuildMultiplyCalcLookupTable(unsigned char out_table[256], float in_multiply_factor);
|
||||
IMGUI_API void ImFontAtlasBuildMultiplyRectAlpha8(const unsigned char table[256], unsigned char* pixels, int x, int y, int w, int h, int stride);
|
||||
IMGUI_API void ImFontAtlasBuildGetOversampleFactors(const ImFontConfig* src, int* out_oversample_h, int* out_oversample_v);
|
||||
|
||||
IMGUI_API bool ImFontAtlasGetMouseCursorTexData(ImFontAtlas* atlas, ImGuiMouseCursor cursor_type, ImVec2* out_offset, ImVec2* out_size, ImVec2 out_uv_border[2], ImVec2 out_uv_fill[2]);
|
||||
|
||||
|
||||
81
3rdparty/imgui/include/imstb_textedit.h
vendored
81
3rdparty/imgui/include/imstb_textedit.h
vendored
@@ -141,6 +141,7 @@
|
||||
// with previous char)
|
||||
// STB_TEXTEDIT_KEYTOTEXT(k) maps a keyboard input to an insertable character
|
||||
// (return type is int, -1 means not valid to insert)
|
||||
// (not supported if you want to use UTF-8, see below)
|
||||
// STB_TEXTEDIT_GETCHAR(obj,i) returns the i'th character of obj, 0-based
|
||||
// STB_TEXTEDIT_NEWLINE the character returned by _GETCHAR() we recognize
|
||||
// as manually wordwrapping for end-of-line positioning
|
||||
@@ -178,6 +179,13 @@
|
||||
// STB_TEXTEDIT_K_TEXTSTART2 secondary keyboard input to move cursor to start of text
|
||||
// STB_TEXTEDIT_K_TEXTEND2 secondary keyboard input to move cursor to end of text
|
||||
//
|
||||
// To support UTF-8:
|
||||
//
|
||||
// STB_TEXTEDIT_GETPREVCHARINDEX returns index of previous character
|
||||
// STB_TEXTEDIT_GETNEXTCHARINDEX returns index of next character
|
||||
// Do NOT define STB_TEXTEDIT_KEYTOTEXT.
|
||||
// Instead, call stb_textedit_text() directly for text contents.
|
||||
//
|
||||
// Keyboard input must be encoded as a single integer value; e.g. a character code
|
||||
// and some bitflags that represent shift states. to simplify the interface, SHIFT must
|
||||
// be a bitflag, so we can test the shifted state of cursor movements to allow selection,
|
||||
@@ -250,8 +258,10 @@
|
||||
// if the STB_TEXTEDIT_KEYTOTEXT function is defined, selected keys are
|
||||
// transformed into text and stb_textedit_text() is automatically called.
|
||||
//
|
||||
// text: [DEAR IMGUI] added 2024-09
|
||||
// call this to text inputs sent to the textfield.
|
||||
// text: (added 2025)
|
||||
// call this to directly send text input the textfield, which is required
|
||||
// for UTF-8 support, because stb_textedit_key() + STB_TEXTEDIT_KEYTOTEXT()
|
||||
// cannot infer text length.
|
||||
//
|
||||
//
|
||||
// When rendering, you can read the cursor position and selection state from
|
||||
@@ -400,6 +410,16 @@ typedef struct
|
||||
#define IMSTB_TEXTEDIT_memmove memmove
|
||||
#endif
|
||||
|
||||
// [DEAR IMGUI]
|
||||
// Functions must be implemented for UTF8 support
|
||||
// Code in this file that uses those functions is modified for [DEAR IMGUI] and deviates from the original stb_textedit.
|
||||
// There is not necessarily a '[DEAR IMGUI]' at the usage sites.
|
||||
#ifndef IMSTB_TEXTEDIT_GETPREVCHARINDEX
|
||||
#define IMSTB_TEXTEDIT_GETPREVCHARINDEX(OBJ, IDX) ((IDX) - 1)
|
||||
#endif
|
||||
#ifndef IMSTB_TEXTEDIT_GETNEXTCHARINDEX
|
||||
#define IMSTB_TEXTEDIT_GETNEXTCHARINDEX(OBJ, IDX) ((IDX) + 1)
|
||||
#endif
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
@@ -648,17 +668,6 @@ static void stb_textedit_move_to_last(IMSTB_TEXTEDIT_STRING *str, STB_TexteditSt
|
||||
}
|
||||
}
|
||||
|
||||
// [DEAR IMGUI]
|
||||
// Functions must be implemented for UTF8 support
|
||||
// Code in this file that uses those functions is modified for [DEAR IMGUI] and deviates from the original stb_textedit.
|
||||
// There is not necessarily a '[DEAR IMGUI]' at the usage sites.
|
||||
#ifndef IMSTB_TEXTEDIT_GETPREVCHARINDEX
|
||||
#define IMSTB_TEXTEDIT_GETPREVCHARINDEX(obj, idx) (idx - 1)
|
||||
#endif
|
||||
#ifndef IMSTB_TEXTEDIT_GETNEXTCHARINDEX
|
||||
#define IMSTB_TEXTEDIT_GETNEXTCHARINDEX(obj, idx) (idx + 1)
|
||||
#endif
|
||||
|
||||
#ifdef STB_TEXTEDIT_IS_SPACE
|
||||
static int is_word_boundary( IMSTB_TEXTEDIT_STRING *str, int idx )
|
||||
{
|
||||
@@ -668,9 +677,9 @@ static int is_word_boundary( IMSTB_TEXTEDIT_STRING *str, int idx )
|
||||
#ifndef STB_TEXTEDIT_MOVEWORDLEFT
|
||||
static int stb_textedit_move_to_word_previous( IMSTB_TEXTEDIT_STRING *str, int c )
|
||||
{
|
||||
--c; // always move at least one character
|
||||
while( c >= 0 && !is_word_boundary( str, c ) )
|
||||
--c;
|
||||
c = IMSTB_TEXTEDIT_GETPREVCHARINDEX( str, c ); // always move at least one character
|
||||
while (c >= 0 && !is_word_boundary(str, c))
|
||||
c = IMSTB_TEXTEDIT_GETPREVCHARINDEX(str, c);
|
||||
|
||||
if( c < 0 )
|
||||
c = 0;
|
||||
@@ -684,9 +693,9 @@ static int stb_textedit_move_to_word_previous( IMSTB_TEXTEDIT_STRING *str, int c
|
||||
static int stb_textedit_move_to_word_next( IMSTB_TEXTEDIT_STRING *str, int c )
|
||||
{
|
||||
const int len = STB_TEXTEDIT_STRINGLEN(str);
|
||||
++c; // always move at least one character
|
||||
c = IMSTB_TEXTEDIT_GETNEXTCHARINDEX(str, c); // always move at least one character
|
||||
while( c < len && !is_word_boundary( str, c ) )
|
||||
++c;
|
||||
c = IMSTB_TEXTEDIT_GETNEXTCHARINDEX(str, c);
|
||||
|
||||
if( c > len )
|
||||
c = len;
|
||||
@@ -739,6 +748,7 @@ static int stb_textedit_paste_internal(IMSTB_TEXTEDIT_STRING *str, STB_TexteditS
|
||||
#define STB_TEXTEDIT_KEYTYPE int
|
||||
#endif
|
||||
|
||||
// API key: process text input
|
||||
// [DEAR IMGUI] Added stb_textedit_text(), extracted out and called by stb_textedit_key() for backward compatibility.
|
||||
static void stb_textedit_text(IMSTB_TEXTEDIT_STRING* str, STB_TexteditState* state, const IMSTB_TEXTEDIT_CHARTYPE* text, int text_len)
|
||||
{
|
||||
@@ -753,8 +763,7 @@ static void stb_textedit_text(IMSTB_TEXTEDIT_STRING* str, STB_TexteditState* sta
|
||||
state->cursor += text_len;
|
||||
state->has_preferred_x = 0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
stb_textedit_delete_selection(str, state); // implicitly clamps
|
||||
if (STB_TEXTEDIT_INSERTCHARS(str, state->cursor, text, text_len)) {
|
||||
stb_text_makeundo_insert(state, state->cursor, text_len);
|
||||
@@ -771,6 +780,7 @@ retry:
|
||||
switch (key) {
|
||||
default: {
|
||||
#ifdef STB_TEXTEDIT_KEYTOTEXT
|
||||
// This is not suitable for UTF-8 support.
|
||||
int c = STB_TEXTEDIT_KEYTOTEXT(key);
|
||||
if (c > 0) {
|
||||
IMSTB_TEXTEDIT_CHARTYPE ch = (IMSTB_TEXTEDIT_CHARTYPE)c;
|
||||
@@ -918,8 +928,9 @@ retry:
|
||||
state->cursor = start;
|
||||
STB_TEXTEDIT_LAYOUTROW(&row, str, state->cursor);
|
||||
x = row.x0;
|
||||
for (i=0; i < row.num_chars; ++i) {
|
||||
for (i=0; i < row.num_chars; ) {
|
||||
float dx = STB_TEXTEDIT_GETWIDTH(str, start, i);
|
||||
int next = IMSTB_TEXTEDIT_GETNEXTCHARINDEX(str, state->cursor);
|
||||
#ifdef IMSTB_TEXTEDIT_GETWIDTH_NEWLINE
|
||||
if (dx == IMSTB_TEXTEDIT_GETWIDTH_NEWLINE)
|
||||
break;
|
||||
@@ -927,7 +938,8 @@ retry:
|
||||
x += dx;
|
||||
if (x > goal_x)
|
||||
break;
|
||||
state->cursor = IMSTB_TEXTEDIT_GETNEXTCHARINDEX(str, state->cursor);
|
||||
i += next - state->cursor;
|
||||
state->cursor = next;
|
||||
}
|
||||
stb_textedit_clamp(str, state);
|
||||
|
||||
@@ -980,8 +992,9 @@ retry:
|
||||
state->cursor = find.prev_first;
|
||||
STB_TEXTEDIT_LAYOUTROW(&row, str, state->cursor);
|
||||
x = row.x0;
|
||||
for (i=0; i < row.num_chars; ++i) {
|
||||
for (i=0; i < row.num_chars; ) {
|
||||
float dx = STB_TEXTEDIT_GETWIDTH(str, find.prev_first, i);
|
||||
int next = IMSTB_TEXTEDIT_GETNEXTCHARINDEX(str, state->cursor);
|
||||
#ifdef IMSTB_TEXTEDIT_GETWIDTH_NEWLINE
|
||||
if (dx == IMSTB_TEXTEDIT_GETWIDTH_NEWLINE)
|
||||
break;
|
||||
@@ -989,7 +1002,8 @@ retry:
|
||||
x += dx;
|
||||
if (x > goal_x)
|
||||
break;
|
||||
state->cursor = IMSTB_TEXTEDIT_GETNEXTCHARINDEX(str, state->cursor);
|
||||
i += next - state->cursor;
|
||||
state->cursor = next;
|
||||
}
|
||||
stb_textedit_clamp(str, state);
|
||||
|
||||
@@ -1002,8 +1016,13 @@ retry:
|
||||
// go to previous line
|
||||
// (we need to scan previous line the hard way. maybe we could expose this as a new API function?)
|
||||
prev_scan = find.prev_first > 0 ? find.prev_first - 1 : 0;
|
||||
while (prev_scan > 0 && STB_TEXTEDIT_GETCHAR(str, prev_scan - 1) != STB_TEXTEDIT_NEWLINE)
|
||||
--prev_scan;
|
||||
while (prev_scan > 0)
|
||||
{
|
||||
int prev = IMSTB_TEXTEDIT_GETPREVCHARINDEX(str, prev_scan);
|
||||
if (STB_TEXTEDIT_GETCHAR(str, prev) == STB_TEXTEDIT_NEWLINE)
|
||||
break;
|
||||
prev_scan = prev;
|
||||
}
|
||||
find.first_char = find.prev_first;
|
||||
find.prev_first = prev_scan;
|
||||
}
|
||||
@@ -1082,7 +1101,7 @@ retry:
|
||||
if (state->single_line)
|
||||
state->cursor = 0;
|
||||
else while (state->cursor > 0 && STB_TEXTEDIT_GETCHAR(str, state->cursor-1) != STB_TEXTEDIT_NEWLINE)
|
||||
--state->cursor;
|
||||
state->cursor = IMSTB_TEXTEDIT_GETPREVCHARINDEX(str, state->cursor);
|
||||
state->has_preferred_x = 0;
|
||||
break;
|
||||
|
||||
@@ -1094,9 +1113,9 @@ retry:
|
||||
stb_textedit_clamp(str, state);
|
||||
stb_textedit_move_to_first(state);
|
||||
if (state->single_line)
|
||||
state->cursor = n;
|
||||
state->cursor = n;
|
||||
else while (state->cursor < n && STB_TEXTEDIT_GETCHAR(str, state->cursor) != STB_TEXTEDIT_NEWLINE)
|
||||
++state->cursor;
|
||||
state->cursor = IMSTB_TEXTEDIT_GETNEXTCHARINDEX(str, state->cursor);
|
||||
state->has_preferred_x = 0;
|
||||
break;
|
||||
}
|
||||
@@ -1110,7 +1129,7 @@ retry:
|
||||
if (state->single_line)
|
||||
state->cursor = 0;
|
||||
else while (state->cursor > 0 && STB_TEXTEDIT_GETCHAR(str, state->cursor-1) != STB_TEXTEDIT_NEWLINE)
|
||||
--state->cursor;
|
||||
state->cursor = IMSTB_TEXTEDIT_GETPREVCHARINDEX(str, state->cursor);
|
||||
state->select_end = state->cursor;
|
||||
state->has_preferred_x = 0;
|
||||
break;
|
||||
@@ -1125,7 +1144,7 @@ retry:
|
||||
if (state->single_line)
|
||||
state->cursor = n;
|
||||
else while (state->cursor < n && STB_TEXTEDIT_GETCHAR(str, state->cursor) != STB_TEXTEDIT_NEWLINE)
|
||||
++state->cursor;
|
||||
state->cursor = IMSTB_TEXTEDIT_GETNEXTCHARINDEX(str, state->cursor);
|
||||
state->select_end = state->cursor;
|
||||
state->has_preferred_x = 0;
|
||||
break;
|
||||
|
||||
1451
3rdparty/imgui/src/imgui.cpp
vendored
1451
3rdparty/imgui/src/imgui.cpp
vendored
File diff suppressed because it is too large
Load Diff
661
3rdparty/imgui/src/imgui_demo.cpp
vendored
661
3rdparty/imgui/src/imgui_demo.cpp
vendored
File diff suppressed because it is too large
Load Diff
3278
3rdparty/imgui/src/imgui_draw.cpp
vendored
3278
3rdparty/imgui/src/imgui_draw.cpp
vendored
File diff suppressed because it is too large
Load Diff
1094
3rdparty/imgui/src/imgui_freetype.cpp
vendored
1094
3rdparty/imgui/src/imgui_freetype.cpp
vendored
File diff suppressed because it is too large
Load Diff
46
3rdparty/imgui/src/imgui_tables.cpp
vendored
46
3rdparty/imgui/src/imgui_tables.cpp
vendored
@@ -1,4 +1,4 @@
|
||||
// dear imgui, v1.91b
|
||||
// dear imgui, v1.92.1
|
||||
// (tables and columns code)
|
||||
|
||||
/*
|
||||
@@ -451,6 +451,7 @@ bool ImGui::BeginTableEx(const char* name, ImGuiID id, int columns_count, ImG
|
||||
// But at this point we do NOT have a correct value for .Max.y (unless a height has been explicitly passed in). It will only be updated in EndTable().
|
||||
table->WorkRect = table->OuterRect = table->InnerRect = outer_rect;
|
||||
table->HasScrollbarYPrev = table->HasScrollbarYCurr = false;
|
||||
table->InnerWindow->DC.TreeDepth++; // This is designed to always linking ImGuiTreeNodeFlags_DrawLines linking accross a table
|
||||
}
|
||||
|
||||
// Push a standardized ID for both child-using and not-child-using tables
|
||||
@@ -1250,7 +1251,7 @@ void ImGui::TableUpdateLayout(ImGuiTable* table)
|
||||
|
||||
// [Part 11] Default context menu
|
||||
// - To append to this menu: you can call TableBeginContextMenuPopup()/.../EndPopup().
|
||||
// - To modify or replace this: set table->IsContextPopupNoDefaultContents = true, then call TableBeginContextMenuPopup()/.../EndPopup().
|
||||
// - To modify or replace this: set table->DisableDefaultContextMenu = true, then call TableBeginContextMenuPopup()/.../EndPopup().
|
||||
// - You may call TableDrawDefaultContextMenu() with selected flags to display specific sections of the default menu,
|
||||
// e.g. TableDrawDefaultContextMenu(table, table->Flags & ~ImGuiTableFlags_Hideable) will display everything EXCEPT columns visibility options.
|
||||
if (table->DisableDefaultContextMenu == false && TableBeginContextMenuPopup(table))
|
||||
@@ -1510,6 +1511,7 @@ void ImGui::EndTable()
|
||||
}
|
||||
else
|
||||
{
|
||||
table->InnerWindow->DC.TreeDepth--;
|
||||
ItemSize(table->OuterRect.GetSize());
|
||||
ItemAdd(table->OuterRect, 0);
|
||||
}
|
||||
@@ -1951,7 +1953,10 @@ void ImGui::TableEndRow(ImGuiTable* table)
|
||||
IM_ASSERT(table->IsInsideRow);
|
||||
|
||||
if (table->CurrentColumn != -1)
|
||||
{
|
||||
TableEndCell(table);
|
||||
table->CurrentColumn = -1;
|
||||
}
|
||||
|
||||
// Logging
|
||||
if (g.LogEnabled)
|
||||
@@ -2191,6 +2196,7 @@ void ImGui::TableBeginCell(ImGuiTable* table, int column_n)
|
||||
g.LastItemData.StatusFlags = 0;
|
||||
}
|
||||
|
||||
// Also see TablePushColumnChannel()
|
||||
if (table->Flags & ImGuiTableFlags_NoClip)
|
||||
{
|
||||
// FIXME: if we end up drawing all borders/bg in EndTable, could remove this and just assert that channel hasn't changed.
|
||||
@@ -2464,10 +2470,38 @@ void ImGui::TablePopBackgroundChannel()
|
||||
ImGuiContext& g = *GImGui;
|
||||
ImGuiWindow* window = g.CurrentWindow;
|
||||
ImGuiTable* table = g.CurrentTable;
|
||||
ImGuiTableColumn* column = &table->Columns[table->CurrentColumn];
|
||||
|
||||
// Optimization: avoid PopClipRect() + SetCurrentChannel()
|
||||
SetWindowClipRectBeforeSetChannel(window, table->HostBackupInnerClipRect);
|
||||
table->DrawSplitter->SetCurrentChannel(window->DrawList, table->Columns[table->CurrentColumn].DrawChannelCurrent);
|
||||
}
|
||||
|
||||
// Also see TableBeginCell()
|
||||
void ImGui::TablePushColumnChannel(int column_n)
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
ImGuiTable* table = g.CurrentTable;
|
||||
|
||||
// Optimization: avoid SetCurrentChannel() + PushClipRect()
|
||||
if (table->Flags & ImGuiTableFlags_NoClip)
|
||||
return;
|
||||
ImGuiWindow* window = g.CurrentWindow;
|
||||
const ImGuiTableColumn* column = &table->Columns[column_n];
|
||||
SetWindowClipRectBeforeSetChannel(window, column->ClipRect);
|
||||
table->DrawSplitter->SetCurrentChannel(window->DrawList, column->DrawChannelCurrent);
|
||||
}
|
||||
|
||||
void ImGui::TablePopColumnChannel()
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
ImGuiTable* table = g.CurrentTable;
|
||||
|
||||
// Optimization: avoid PopClipRect() + SetCurrentChannel()
|
||||
if ((table->Flags & ImGuiTableFlags_NoClip) || (table->CurrentColumn == -1)) // Calling TreePop() after TableNextRow() is supported.
|
||||
return;
|
||||
ImGuiWindow* window = g.CurrentWindow;
|
||||
const ImGuiTableColumn* column = &table->Columns[table->CurrentColumn];
|
||||
SetWindowClipRectBeforeSetChannel(window, column->ClipRect);
|
||||
table->DrawSplitter->SetCurrentChannel(window->DrawList, column->DrawChannelCurrent);
|
||||
}
|
||||
|
||||
@@ -3244,7 +3278,7 @@ void ImGui::TableHeader(const char* label)
|
||||
// Render clipped label. Clipping here ensure that in the majority of situations, all our header cells will
|
||||
// be merged into a single draw call.
|
||||
//window->DrawList->AddCircleFilled(ImVec2(ellipsis_max, label_pos.y), 40, IM_COL32_WHITE);
|
||||
RenderTextEllipsis(window->DrawList, label_pos, ImVec2(ellipsis_max, label_pos.y + label_height + g.Style.FramePadding.y), ellipsis_max, ellipsis_max, label, label_end, &label_size);
|
||||
RenderTextEllipsis(window->DrawList, label_pos, ImVec2(ellipsis_max, bb.Max.y), ellipsis_max, label, label_end, &label_size);
|
||||
|
||||
const bool text_clipped = label_size.x > (ellipsis_max - label_pos.x);
|
||||
if (text_clipped && hovered && g.ActiveId == 0)
|
||||
@@ -3341,7 +3375,7 @@ void ImGui::TableAngledHeadersRowEx(ImGuiID row_id, float angle, float max_label
|
||||
ButtonBehavior(row_r, row_id, NULL, NULL);
|
||||
KeepAliveID(row_id);
|
||||
|
||||
const float ascent_scaled = g.Font->Ascent * g.FontScale; // FIXME: Standardize those scaling factors better
|
||||
const float ascent_scaled = g.FontBaked->Ascent * g.FontBakedScale; // FIXME: Standardize those scaling factors better
|
||||
const float line_off_for_ascent_x = (ImMax((g.FontSize - ascent_scaled) * 0.5f, 0.0f) / -sin_a) * (flip_label ? -1.0f : 1.0f);
|
||||
const ImVec2 padding = g.Style.CellPadding; // We will always use swapped component
|
||||
const ImVec2 align = g.Style.TableAngledHeadersTextAlign;
|
||||
@@ -3396,7 +3430,7 @@ void ImGui::TableAngledHeadersRowEx(ImGuiID row_id, float angle, float max_label
|
||||
ImRect clip_r(window->ClipRect.Min, window->ClipRect.Min + ImVec2(clip_width, clip_height));
|
||||
int vtx_idx_begin = draw_list->_VtxCurrentIdx;
|
||||
PushStyleColor(ImGuiCol_Text, request->TextColor);
|
||||
RenderTextEllipsis(draw_list, clip_r.Min, clip_r.Max, clip_r.Max.x, clip_r.Max.x, label_name, label_name_eol, &label_size);
|
||||
RenderTextEllipsis(draw_list, clip_r.Min, clip_r.Max, clip_r.Max.x, label_name, label_name_eol, &label_size);
|
||||
PopStyleColor();
|
||||
int vtx_idx_end = draw_list->_VtxCurrentIdx;
|
||||
|
||||
|
||||
347
3rdparty/imgui/src/imgui_widgets.cpp
vendored
347
3rdparty/imgui/src/imgui_widgets.cpp
vendored
@@ -1,4 +1,4 @@
|
||||
// dear imgui, v1.91b
|
||||
// dear imgui, v1.92.1
|
||||
// (widgets code)
|
||||
|
||||
/*
|
||||
@@ -339,6 +339,46 @@ void ImGui::TextWrappedV(const char* fmt, va_list args)
|
||||
PopTextWrapPos();
|
||||
}
|
||||
|
||||
void ImGui::TextAligned(float align_x, float size_x, const char* fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
TextAlignedV(align_x, size_x, fmt, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
// align_x: 0.0f = left, 0.5f = center, 1.0f = right.
|
||||
// size_x : 0.0f = shortcut for GetContentRegionAvail().x
|
||||
// FIXME-WIP: Works but API is likely to be reworked. This is designed for 1 item on the line. (#7024)
|
||||
void ImGui::TextAlignedV(float align_x, float size_x, const char* fmt, va_list args)
|
||||
{
|
||||
ImGuiWindow* window = GetCurrentWindow();
|
||||
if (window->SkipItems)
|
||||
return;
|
||||
|
||||
const char* text, *text_end;
|
||||
ImFormatStringToTempBufferV(&text, &text_end, fmt, args);
|
||||
const ImVec2 text_size = CalcTextSize(text, text_end);
|
||||
size_x = CalcItemSize(ImVec2(size_x, 0.0f), 0.0f, text_size.y).x;
|
||||
|
||||
ImVec2 pos(window->DC.CursorPos.x, window->DC.CursorPos.y + window->DC.CurrLineTextBaseOffset);
|
||||
ImVec2 pos_max(pos.x + size_x, window->ClipRect.Max.y);
|
||||
ImVec2 size(ImMin(size_x, text_size.x), text_size.y);
|
||||
window->DC.CursorMaxPos.x = ImMax(window->DC.CursorMaxPos.x, pos.x + text_size.x);
|
||||
window->DC.IdealMaxPos.x = ImMax(window->DC.IdealMaxPos.x, pos.x + text_size.x);
|
||||
if (align_x > 0.0f && text_size.x < size_x)
|
||||
pos.x += ImTrunc((size_x - text_size.x) * align_x);
|
||||
RenderTextEllipsis(window->DrawList, pos, pos_max, pos_max.x, text, text_end, &text_size);
|
||||
|
||||
const ImVec2 backup_max_pos = window->DC.CursorMaxPos;
|
||||
ItemSize(size);
|
||||
ItemAdd(ImRect(pos, pos + size), 0);
|
||||
window->DC.CursorMaxPos.x = backup_max_pos.x; // Cancel out extending content size because right-aligned text would otherwise mess it up.
|
||||
|
||||
if (size_x < text_size.x && IsItemHovered(ImGuiHoveredFlags_NoNavOverride | ImGuiHoveredFlags_AllowWhenDisabled | ImGuiHoveredFlags_ForTooltip))
|
||||
SetTooltip("%.*s", (int)(text_end - text), text);
|
||||
}
|
||||
|
||||
void ImGui::LabelText(const char* label, const char* fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
@@ -494,7 +534,7 @@ void ImGui::BulletTextV(const char* fmt, va_list args)
|
||||
// And better standardize how widgets use 'GetColor32((held && hovered) ? ... : hovered ? ...)' vs 'GetColor32(held ? ... : hovered ? ...);'
|
||||
// For mouse feedback we typically prefer the 'held && hovered' test, but for nav feedback not always. Outputting hovered=true on Activation may be misleading.
|
||||
// - Since v1.91.2 (Sept 2024) we included io.ConfigDebugHighlightIdConflicts feature.
|
||||
// One idiom which was previously valid which will now emit a warning is when using multiple overlayed ButtonBehavior()
|
||||
// One idiom which was previously valid which will now emit a warning is when using multiple overlaid ButtonBehavior()
|
||||
// with same ID and different MouseButton (see #8030). You can fix it by:
|
||||
// (1) switching to use a single ButtonBehavior() with multiple _MouseButton flags.
|
||||
// or (2) surrounding those calls with PushItemFlag(ImGuiItemFlags_AllowDuplicateId, true); ... PopItemFlag()
|
||||
@@ -508,6 +548,8 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool
|
||||
ImGuiItemFlags item_flags = (g.LastItemData.ID == id ? g.LastItemData.ItemFlags : g.CurrentItemFlags);
|
||||
if (flags & ImGuiButtonFlags_AllowOverlap)
|
||||
item_flags |= ImGuiItemFlags_AllowOverlap;
|
||||
if (item_flags & ImGuiItemFlags_NoFocus)
|
||||
flags |= ImGuiButtonFlags_NoFocus | ImGuiButtonFlags_NoNavFocus;
|
||||
|
||||
// Default only reacts to left mouse button
|
||||
if ((flags & ImGuiButtonFlags_MouseButtonMask_) == 0)
|
||||
@@ -518,7 +560,7 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool
|
||||
flags |= (item_flags & ImGuiItemFlags_ButtonRepeat) ? ImGuiButtonFlags_PressedOnClick : ImGuiButtonFlags_PressedOnDefault_;
|
||||
|
||||
ImGuiWindow* backup_hovered_window = g.HoveredWindow;
|
||||
const bool flatten_hovered_children = (flags & ImGuiButtonFlags_FlattenChildren) && g.HoveredWindow && g.HoveredWindow->RootWindow == window;
|
||||
const bool flatten_hovered_children = (flags & ImGuiButtonFlags_FlattenChildren) && g.HoveredWindow && g.HoveredWindow->RootWindow == window->RootWindow;
|
||||
if (flatten_hovered_children)
|
||||
g.HoveredWindow = window;
|
||||
|
||||
@@ -531,7 +573,8 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool
|
||||
bool pressed = false;
|
||||
bool hovered = ItemHoverable(bb, id, item_flags);
|
||||
|
||||
// Special mode for Drag and Drop where holding button pressed for a long time while dragging another item triggers the button
|
||||
// Special mode for Drag and Drop used by openables (tree nodes, tabs etc.)
|
||||
// where holding the button pressed for a long time while drag a payload item triggers the button.
|
||||
if (g.DragDropActive && (flags & ImGuiButtonFlags_PressedOnDragDropHold) && !(g.DragDropSourceFlags & ImGuiDragDropFlags_SourceNoHoldToOpenOthers))
|
||||
if (IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByActiveItem))
|
||||
{
|
||||
@@ -583,7 +626,7 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool
|
||||
SetFocusID(id, window);
|
||||
FocusWindow(window);
|
||||
}
|
||||
else
|
||||
else if (!(flags & ImGuiButtonFlags_NoFocus))
|
||||
{
|
||||
FocusWindow(window, ImGuiFocusRequestFlags_RestoreFocusedChild); // Still need to focus and bring to front, but try to avoid losing NavId when navigating a child
|
||||
}
|
||||
@@ -601,7 +644,7 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool
|
||||
SetFocusID(id, window);
|
||||
FocusWindow(window);
|
||||
}
|
||||
else
|
||||
else if (!(flags & ImGuiButtonFlags_NoFocus))
|
||||
{
|
||||
FocusWindow(window, ImGuiFocusRequestFlags_RestoreFocusedChild); // Still need to focus and bring to front, but try to avoid losing NavId when navigating a child
|
||||
}
|
||||
@@ -867,11 +910,12 @@ bool ImGui::CloseButton(ImGuiID id, const ImVec2& pos)
|
||||
if (hovered)
|
||||
window->DrawList->AddRectFilled(bb.Min, bb.Max, bg_col);
|
||||
RenderNavCursor(bb, id, ImGuiNavRenderCursorFlags_Compact);
|
||||
ImU32 cross_col = GetColorU32(ImGuiCol_Text);
|
||||
ImVec2 cross_center = bb.GetCenter() - ImVec2(0.5f, 0.5f);
|
||||
float cross_extent = g.FontSize * 0.5f * 0.7071f - 1.0f;
|
||||
window->DrawList->AddLine(cross_center + ImVec2(+cross_extent, +cross_extent), cross_center + ImVec2(-cross_extent, -cross_extent), cross_col, 1.0f);
|
||||
window->DrawList->AddLine(cross_center + ImVec2(+cross_extent, -cross_extent), cross_center + ImVec2(-cross_extent, +cross_extent), cross_col, 1.0f);
|
||||
const ImU32 cross_col = GetColorU32(ImGuiCol_Text);
|
||||
const ImVec2 cross_center = bb.GetCenter() - ImVec2(0.5f, 0.5f);
|
||||
const float cross_extent = g.FontSize * 0.5f * 0.7071f - 1.0f;
|
||||
const float cross_thickness = 1.0f; // FIXME-DPI
|
||||
window->DrawList->AddLine(cross_center + ImVec2(+cross_extent, +cross_extent), cross_center + ImVec2(-cross_extent, -cross_extent), cross_col, cross_thickness);
|
||||
window->DrawList->AddLine(cross_center + ImVec2(+cross_extent, -cross_extent), cross_center + ImVec2(-cross_extent, +cross_extent), cross_col, cross_thickness);
|
||||
|
||||
return pressed;
|
||||
}
|
||||
@@ -1062,9 +1106,9 @@ bool ImGui::ScrollbarEx(const ImRect& bb_frame, ImGuiID id, ImGuiAxis axis, ImS6
|
||||
return held;
|
||||
}
|
||||
|
||||
// - Read about ImTextureID here: https://github.com/ocornut/imgui/wiki/Image-Loading-and-Displaying-Examples
|
||||
// - Read about ImTextureID/ImTextureRef here: https://github.com/ocornut/imgui/wiki/Image-Loading-and-Displaying-Examples
|
||||
// - 'uv0' and 'uv1' are texture coordinates. Read about them from the same link above.
|
||||
void ImGui::ImageWithBg(ImTextureID user_texture_id, const ImVec2& image_size, const ImVec2& uv0, const ImVec2& uv1, const ImVec4& bg_col, const ImVec4& tint_col)
|
||||
void ImGui::ImageWithBg(ImTextureRef tex_ref, const ImVec2& image_size, const ImVec2& uv0, const ImVec2& uv1, const ImVec4& bg_col, const ImVec4& tint_col)
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
ImGuiWindow* window = GetCurrentWindow();
|
||||
@@ -1082,28 +1126,28 @@ void ImGui::ImageWithBg(ImTextureID user_texture_id, const ImVec2& image_size, c
|
||||
window->DrawList->AddRect(bb.Min, bb.Max, GetColorU32(ImGuiCol_Border), 0.0f, ImDrawFlags_None, g.Style.ImageBorderSize);
|
||||
if (bg_col.w > 0.0f)
|
||||
window->DrawList->AddRectFilled(bb.Min + padding, bb.Max - padding, GetColorU32(bg_col));
|
||||
window->DrawList->AddImage(user_texture_id, bb.Min + padding, bb.Max - padding, uv0, uv1, GetColorU32(tint_col));
|
||||
window->DrawList->AddImage(tex_ref, bb.Min + padding, bb.Max - padding, uv0, uv1, GetColorU32(tint_col));
|
||||
}
|
||||
|
||||
void ImGui::Image(ImTextureID user_texture_id, const ImVec2& image_size, const ImVec2& uv0, const ImVec2& uv1)
|
||||
void ImGui::Image(ImTextureRef tex_ref, const ImVec2& image_size, const ImVec2& uv0, const ImVec2& uv1)
|
||||
{
|
||||
ImageWithBg(user_texture_id, image_size, uv0, uv1);
|
||||
ImageWithBg(tex_ref, image_size, uv0, uv1);
|
||||
}
|
||||
|
||||
// 1.91.9 (February 2025) removed 'tint_col' and 'border_col' parameters, made border size not depend on color value. (#8131, #8238)
|
||||
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
|
||||
void ImGui::Image(ImTextureID user_texture_id, const ImVec2& image_size, const ImVec2& uv0, const ImVec2& uv1, const ImVec4& tint_col, const ImVec4& border_col)
|
||||
void ImGui::Image(ImTextureRef tex_ref, const ImVec2& image_size, const ImVec2& uv0, const ImVec2& uv1, const ImVec4& tint_col, const ImVec4& border_col)
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
PushStyleVar(ImGuiStyleVar_ImageBorderSize, (border_col.w > 0.0f) ? ImMax(1.0f, g.Style.ImageBorderSize) : 0.0f); // Preserve legacy behavior where border is always visible when border_col's Alpha is >0.0f
|
||||
PushStyleColor(ImGuiCol_Border, border_col);
|
||||
ImageWithBg(user_texture_id, image_size, uv0, uv1, ImVec4(0, 0, 0, 0), tint_col);
|
||||
ImageWithBg(tex_ref, image_size, uv0, uv1, ImVec4(0, 0, 0, 0), tint_col);
|
||||
PopStyleColor();
|
||||
PopStyleVar();
|
||||
}
|
||||
#endif
|
||||
|
||||
bool ImGui::ImageButtonEx(ImGuiID id, ImTextureID user_texture_id, const ImVec2& image_size, const ImVec2& uv0, const ImVec2& uv1, const ImVec4& bg_col, const ImVec4& tint_col, ImGuiButtonFlags flags)
|
||||
bool ImGui::ImageButtonEx(ImGuiID id, ImTextureRef tex_ref, const ImVec2& image_size, const ImVec2& uv0, const ImVec2& uv1, const ImVec4& bg_col, const ImVec4& tint_col, ImGuiButtonFlags flags)
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
ImGuiWindow* window = GetCurrentWindow();
|
||||
@@ -1125,21 +1169,21 @@ bool ImGui::ImageButtonEx(ImGuiID id, ImTextureID user_texture_id, const ImVec2&
|
||||
RenderFrame(bb.Min, bb.Max, col, true, ImClamp((float)ImMin(padding.x, padding.y), 0.0f, g.Style.FrameRounding));
|
||||
if (bg_col.w > 0.0f)
|
||||
window->DrawList->AddRectFilled(bb.Min + padding, bb.Max - padding, GetColorU32(bg_col));
|
||||
window->DrawList->AddImage(user_texture_id, bb.Min + padding, bb.Max - padding, uv0, uv1, GetColorU32(tint_col));
|
||||
window->DrawList->AddImage(tex_ref, bb.Min + padding, bb.Max - padding, uv0, uv1, GetColorU32(tint_col));
|
||||
|
||||
return pressed;
|
||||
}
|
||||
|
||||
// - ImageButton() adds style.FramePadding*2.0f to provided size. This is in order to facilitate fitting an image in a button.
|
||||
// - ImageButton() draws a background based on regular Button() color + optionally an inner background if specified. (#8165) // FIXME: Maybe that's not the best design?
|
||||
bool ImGui::ImageButton(const char* str_id, ImTextureID user_texture_id, const ImVec2& image_size, const ImVec2& uv0, const ImVec2& uv1, const ImVec4& bg_col, const ImVec4& tint_col)
|
||||
bool ImGui::ImageButton(const char* str_id, ImTextureRef tex_ref, const ImVec2& image_size, const ImVec2& uv0, const ImVec2& uv1, const ImVec4& bg_col, const ImVec4& tint_col)
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
ImGuiWindow* window = g.CurrentWindow;
|
||||
if (window->SkipItems)
|
||||
return false;
|
||||
|
||||
return ImageButtonEx(window->GetID(str_id), user_texture_id, image_size, uv0, uv1, bg_col, tint_col);
|
||||
return ImageButtonEx(window->GetID(str_id), tex_ref, image_size, uv0, uv1, bg_col, tint_col);
|
||||
}
|
||||
|
||||
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
|
||||
@@ -1477,8 +1521,8 @@ bool ImGui::TextLink(const char* label)
|
||||
ColorConvertHSVtoRGB(h, s, v, line_colf.x, line_colf.y, line_colf.z);
|
||||
}
|
||||
|
||||
float line_y = bb.Max.y + ImFloor(g.Font->Descent * g.FontScale * 0.20f);
|
||||
window->DrawList->AddLine(ImVec2(bb.Min.x, line_y), ImVec2(bb.Max.x, line_y), GetColorU32(line_colf)); // FIXME-TEXT: Underline mode.
|
||||
float line_y = bb.Max.y + ImFloor(g.FontBaked->Descent * g.FontBakedScale * 0.20f);
|
||||
window->DrawList->AddLine(ImVec2(bb.Min.x, line_y), ImVec2(bb.Max.x, line_y), GetColorU32(line_colf)); // FIXME-TEXT: Underline mode // FIXME-DPI
|
||||
|
||||
PushStyleColor(ImGuiCol_Text, GetColorU32(text_colf));
|
||||
RenderText(bb.Min, label, label_end);
|
||||
@@ -1488,14 +1532,14 @@ bool ImGui::TextLink(const char* label)
|
||||
return pressed;
|
||||
}
|
||||
|
||||
void ImGui::TextLinkOpenURL(const char* label, const char* url)
|
||||
bool ImGui::TextLinkOpenURL(const char* label, const char* url)
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
if (url == NULL)
|
||||
url = label;
|
||||
if (TextLink(label))
|
||||
if (g.PlatformIO.Platform_OpenInShellFn != NULL)
|
||||
g.PlatformIO.Platform_OpenInShellFn(&g, url);
|
||||
bool pressed = TextLink(label);
|
||||
if (pressed && g.PlatformIO.Platform_OpenInShellFn != NULL)
|
||||
g.PlatformIO.Platform_OpenInShellFn(&g, url);
|
||||
SetItemTooltip(LocalizeGetMsg(ImGuiLocKey_OpenLink_s), url); // It is more reassuring for user to _always_ display URL when we same as label
|
||||
if (BeginPopupContextItem())
|
||||
{
|
||||
@@ -1503,6 +1547,7 @@ void ImGui::TextLinkOpenURL(const char* label, const char* url)
|
||||
SetClipboardText(url);
|
||||
EndPopup();
|
||||
}
|
||||
return pressed;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
@@ -1689,7 +1734,7 @@ void ImGui::SeparatorTextEx(ImGuiID id, const char* label, const char* label_end
|
||||
window->DrawList->AddLine(ImVec2(sep2_x1, seps_y), ImVec2(sep2_x2, seps_y), separator_col, separator_thickness);
|
||||
if (g.LogEnabled)
|
||||
LogSetNextTextDecoration("---", NULL);
|
||||
RenderTextEllipsis(window->DrawList, label_pos, ImVec2(bb.Max.x, bb.Max.y + style.ItemSpacing.y), bb.Max.x, bb.Max.x, label, label_end, &label_size);
|
||||
RenderTextEllipsis(window->DrawList, label_pos, ImVec2(bb.Max.x, bb.Max.y + style.ItemSpacing.y), bb.Max.x, label, label_end, &label_size);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -3890,7 +3935,7 @@ bool ImGui::InputTextWithHint(const char* label, const char* hint, char* buf, si
|
||||
return InputTextEx(label, hint, buf, (int)buf_size, ImVec2(0, 0), flags, callback, user_data);
|
||||
}
|
||||
|
||||
// This is only used in the path where the multiline widget is inactivate.
|
||||
// This is only used in the path where the multiline widget is inactive.
|
||||
static int InputTextCalcTextLenAndLineCount(const char* text_begin, const char** out_text_end)
|
||||
{
|
||||
int line_count = 0;
|
||||
@@ -3914,9 +3959,10 @@ static int InputTextCalcTextLenAndLineCount(const char* text_begin, const char**
|
||||
static ImVec2 InputTextCalcTextSize(ImGuiContext* ctx, const char* text_begin, const char* text_end, const char** remaining, ImVec2* out_offset, bool stop_on_new_line)
|
||||
{
|
||||
ImGuiContext& g = *ctx;
|
||||
ImFont* font = g.Font;
|
||||
//ImFont* font = g.Font;
|
||||
ImFontBaked* baked = g.FontBaked;
|
||||
const float line_height = g.FontSize;
|
||||
const float scale = line_height / font->FontSize;
|
||||
const float scale = line_height / baked->Size;
|
||||
|
||||
ImVec2 text_size = ImVec2(0, 0);
|
||||
float line_width = 0.0f;
|
||||
@@ -3942,8 +3988,7 @@ static ImVec2 InputTextCalcTextSize(ImGuiContext* ctx, const char* text_begin, c
|
||||
if (c == '\r')
|
||||
continue;
|
||||
|
||||
const float char_width = ((int)c < font->IndexAdvanceX.Size ? font->IndexAdvanceX.Data[c] : font->FallbackAdvanceX) * scale;
|
||||
line_width += char_width;
|
||||
line_width += baked->GetCharAdvance((ImWchar)c) * scale;
|
||||
}
|
||||
|
||||
if (text_size.x < line_width)
|
||||
@@ -3970,7 +4015,7 @@ namespace ImStb
|
||||
{
|
||||
static int STB_TEXTEDIT_STRINGLEN(const ImGuiInputTextState* obj) { return obj->TextLen; }
|
||||
static char STB_TEXTEDIT_GETCHAR(const ImGuiInputTextState* obj, int idx) { IM_ASSERT(idx <= obj->TextLen); return obj->TextSrc[idx]; }
|
||||
static float STB_TEXTEDIT_GETWIDTH(ImGuiInputTextState* obj, int line_start_idx, int char_idx) { unsigned int c; ImTextCharFromUtf8(&c, obj->TextSrc + line_start_idx + char_idx, obj->TextSrc + obj->TextLen); if ((ImWchar)c == '\n') return IMSTB_TEXTEDIT_GETWIDTH_NEWLINE; ImGuiContext& g = *obj->Ctx; return g.Font->GetCharAdvance((ImWchar)c) * g.FontScale; }
|
||||
static float STB_TEXTEDIT_GETWIDTH(ImGuiInputTextState* obj, int line_start_idx, int char_idx) { unsigned int c; ImTextCharFromUtf8(&c, obj->TextSrc + line_start_idx + char_idx, obj->TextSrc + obj->TextLen); if ((ImWchar)c == '\n') return IMSTB_TEXTEDIT_GETWIDTH_NEWLINE; ImGuiContext& g = *obj->Ctx; return g.FontBaked->GetCharAdvance((ImWchar)c) * g.FontBakedScale; }
|
||||
static char STB_TEXTEDIT_NEWLINE = '\n';
|
||||
static void STB_TEXTEDIT_LAYOUTROW(StbTexteditRow* r, ImGuiInputTextState* obj, int line_start_idx)
|
||||
{
|
||||
@@ -4238,23 +4283,24 @@ void ImGuiInputTextCallbackData::InsertChars(int pos, const char* new_text, cons
|
||||
if (new_text == new_text_end)
|
||||
return;
|
||||
|
||||
ImGuiContext& g = *Ctx;
|
||||
ImGuiInputTextState* obj = &g.InputTextState;
|
||||
IM_ASSERT(obj->ID != 0 && g.ActiveId == obj->ID);
|
||||
|
||||
// Grow internal buffer if needed
|
||||
const bool is_resizable = (Flags & ImGuiInputTextFlags_CallbackResize) != 0;
|
||||
const int new_text_len = new_text_end ? (int)(new_text_end - new_text) : (int)ImStrlen(new_text);
|
||||
if (new_text_len + BufTextLen >= BufSize)
|
||||
if (new_text_len + BufTextLen + 1 > obj->TextA.Size && (Flags & ImGuiInputTextFlags_ReadOnly) == 0)
|
||||
{
|
||||
if (!is_resizable)
|
||||
return;
|
||||
|
||||
ImGuiContext& g = *Ctx;
|
||||
ImGuiInputTextState* edit_state = &g.InputTextState;
|
||||
IM_ASSERT(edit_state->ID != 0 && g.ActiveId == edit_state->ID);
|
||||
IM_ASSERT(Buf == edit_state->TextA.Data);
|
||||
IM_ASSERT(Buf == obj->TextA.Data);
|
||||
int new_buf_size = BufTextLen + ImClamp(new_text_len * 4, 32, ImMax(256, new_text_len)) + 1;
|
||||
edit_state->TextA.resize(new_buf_size + 1);
|
||||
edit_state->TextSrc = edit_state->TextA.Data;
|
||||
Buf = edit_state->TextA.Data;
|
||||
BufSize = edit_state->BufCapacity = new_buf_size;
|
||||
obj->TextA.resize(new_buf_size + 1);
|
||||
obj->TextSrc = obj->TextA.Data;
|
||||
Buf = obj->TextA.Data;
|
||||
BufSize = obj->BufCapacity = new_buf_size;
|
||||
}
|
||||
|
||||
if (BufTextLen != pos)
|
||||
@@ -4272,18 +4318,29 @@ void ImGuiInputTextCallbackData::InsertChars(int pos, const char* new_text, cons
|
||||
void ImGui::PushPasswordFont()
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
ImFont* in_font = g.Font;
|
||||
ImFont* out_font = &g.InputTextPasswordFont;
|
||||
ImFontGlyph* glyph = in_font->FindGlyph('*');
|
||||
out_font->FontSize = in_font->FontSize;
|
||||
out_font->Scale = in_font->Scale;
|
||||
out_font->Ascent = in_font->Ascent;
|
||||
out_font->Descent = in_font->Descent;
|
||||
out_font->ContainerAtlas = in_font->ContainerAtlas;
|
||||
out_font->FallbackGlyph = glyph;
|
||||
out_font->FallbackAdvanceX = glyph->AdvanceX;
|
||||
IM_ASSERT(out_font->Glyphs.Size == 0 && out_font->IndexAdvanceX.Size == 0 && out_font->IndexLookup.Size == 0);
|
||||
PushFont(out_font);
|
||||
ImFontBaked* backup = &g.InputTextPasswordFontBackupBaked;
|
||||
IM_ASSERT(backup->IndexAdvanceX.Size == 0 && backup->IndexLookup.Size == 0);
|
||||
ImFontGlyph* glyph = g.FontBaked->FindGlyph('*');
|
||||
g.InputTextPasswordFontBackupFlags = g.Font->Flags;
|
||||
backup->FallbackGlyphIndex = g.FontBaked->FallbackGlyphIndex;
|
||||
backup->FallbackAdvanceX = g.FontBaked->FallbackAdvanceX;
|
||||
backup->IndexLookup.swap(g.FontBaked->IndexLookup);
|
||||
backup->IndexAdvanceX.swap(g.FontBaked->IndexAdvanceX);
|
||||
g.Font->Flags |= ImFontFlags_NoLoadGlyphs;
|
||||
g.FontBaked->FallbackGlyphIndex = g.FontBaked->Glyphs.index_from_ptr(glyph);
|
||||
g.FontBaked->FallbackAdvanceX = glyph->AdvanceX;
|
||||
}
|
||||
|
||||
void ImGui::PopPasswordFont()
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
ImFontBaked* backup = &g.InputTextPasswordFontBackupBaked;
|
||||
g.Font->Flags = g.InputTextPasswordFontBackupFlags;
|
||||
g.FontBaked->FallbackGlyphIndex = backup->FallbackGlyphIndex;
|
||||
g.FontBaked->FallbackAdvanceX = backup->FallbackAdvanceX;
|
||||
g.FontBaked->IndexLookup.swap(backup->IndexLookup);
|
||||
g.FontBaked->IndexAdvanceX.swap(backup->IndexAdvanceX);
|
||||
IM_ASSERT(backup->IndexAdvanceX.Size == 0 && backup->IndexLookup.Size == 0);
|
||||
}
|
||||
|
||||
// Return false to discard a character.
|
||||
@@ -4647,7 +4704,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
|
||||
if (g.ActiveId == id)
|
||||
{
|
||||
// Declare some inputs, the other are registered and polled via Shortcut() routing system.
|
||||
// FIXME: The reason we don't use Shortcut() is we would need a routing flag to specify multiple mods, or to all mods combinaison into individual shortcuts.
|
||||
// FIXME: The reason we don't use Shortcut() is we would need a routing flag to specify multiple mods, or to all mods combination into individual shortcuts.
|
||||
const ImGuiKey always_owned_keys[] = { ImGuiKey_LeftArrow, ImGuiKey_RightArrow, ImGuiKey_Enter, ImGuiKey_KeypadEnter, ImGuiKey_Delete, ImGuiKey_Backspace, ImGuiKey_Home, ImGuiKey_End };
|
||||
for (ImGuiKey key : always_owned_keys)
|
||||
SetKeyOwner(key, id);
|
||||
@@ -5160,8 +5217,6 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
|
||||
// Otherwise request text input ahead for next frame.
|
||||
if (g.ActiveId == id && clear_active_id)
|
||||
ClearActiveID();
|
||||
else if (g.ActiveId == id)
|
||||
g.WantTextInputNextFrame = 1;
|
||||
|
||||
// Render frame
|
||||
if (!is_multiline)
|
||||
@@ -5187,7 +5242,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
|
||||
if (new_is_displaying_hint != is_displaying_hint)
|
||||
{
|
||||
if (is_password && !is_displaying_hint)
|
||||
PopFont();
|
||||
PopPasswordFont();
|
||||
is_displaying_hint = new_is_displaying_hint;
|
||||
if (is_password && !is_displaying_hint)
|
||||
PushPasswordFont();
|
||||
@@ -5312,7 +5367,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
|
||||
else
|
||||
{
|
||||
ImVec2 rect_size = InputTextCalcTextSize(&g, p, text_selected_end, &p, NULL, true);
|
||||
if (rect_size.x <= 0.0f) rect_size.x = IM_TRUNC(g.Font->GetCharAdvance((ImWchar)' ') * 0.50f); // So we can see selected empty lines
|
||||
if (rect_size.x <= 0.0f) rect_size.x = IM_TRUNC(g.FontBaked->GetCharAdvance((ImWchar)' ') * 0.50f); // So we can see selected empty lines
|
||||
ImRect rect(rect_pos + ImVec2(0.0f, bg_offy_up - g.FontSize), rect_pos + ImVec2(rect_size.x, bg_offy_dn));
|
||||
rect.ClipWith(clip_rect);
|
||||
if (rect.Overlaps(clip_rect))
|
||||
@@ -5339,14 +5394,19 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
|
||||
ImVec2 cursor_screen_pos = ImTrunc(draw_pos + cursor_offset - draw_scroll);
|
||||
ImRect cursor_screen_rect(cursor_screen_pos.x, cursor_screen_pos.y - g.FontSize + 0.5f, cursor_screen_pos.x + 1.0f, cursor_screen_pos.y - 1.5f);
|
||||
if (cursor_is_visible && cursor_screen_rect.Overlaps(clip_rect))
|
||||
draw_window->DrawList->AddLine(cursor_screen_rect.Min, cursor_screen_rect.GetBL(), GetColorU32(ImGuiCol_Text));
|
||||
draw_window->DrawList->AddLine(cursor_screen_rect.Min, cursor_screen_rect.GetBL(), GetColorU32(ImGuiCol_InputTextCursor), 1.0f); // FIXME-DPI: Cursor thickness (#7031)
|
||||
|
||||
// Notify OS of text input position for advanced IME (-1 x offset so that Windows IME can cover our cursor. Bit of an extra nicety.)
|
||||
if (!is_readonly)
|
||||
// This is required for some backends (SDL3) to start emitting character/text inputs.
|
||||
// As per #6341, make sure we don't set that on the deactivating frame.
|
||||
if (!is_readonly && g.ActiveId == id)
|
||||
{
|
||||
g.PlatformImeData.WantVisible = true;
|
||||
g.PlatformImeData.InputPos = ImVec2(cursor_screen_pos.x - 1.0f, cursor_screen_pos.y - g.FontSize);
|
||||
g.PlatformImeData.InputLineHeight = g.FontSize;
|
||||
ImGuiPlatformImeData* ime_data = &g.PlatformImeData; // (this is a public struct, passed to io.Platform_SetImeDataFn() handler)
|
||||
ime_data->WantVisible = true;
|
||||
ime_data->WantTextInput = true;
|
||||
ime_data->InputPos = ImVec2(cursor_screen_pos.x - 1.0f, cursor_screen_pos.y - g.FontSize);
|
||||
ime_data->InputLineHeight = g.FontSize;
|
||||
ime_data->ViewportId = window->Viewport->ID;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5373,7 +5433,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
|
||||
}
|
||||
|
||||
if (is_password && !is_displaying_hint)
|
||||
PopFont();
|
||||
PopPasswordFont();
|
||||
|
||||
if (is_multiline)
|
||||
{
|
||||
@@ -5425,7 +5485,7 @@ void ImGui::DebugNodeInputTextState(ImGuiInputTextState* state)
|
||||
Text("ID: 0x%08X, ActiveID: 0x%08X", state->ID, g.ActiveId);
|
||||
DebugLocateItemOnHover(state->ID);
|
||||
Text("CurLenA: %d, Cursor: %d, Selection: %d..%d", state->TextLen, stb_state->cursor, stb_state->select_start, stb_state->select_end);
|
||||
Text("BufCapacityA: %d", state->BufCapacity);
|
||||
Text("BufCapacity: %d", state->BufCapacity);
|
||||
Text("(Internal Buffer: TextA Size: %d, Capacity: %d)", state->TextA.Size, state->TextA.Capacity);
|
||||
Text("has_preferred_x: %d (%.2f)", stb_state->has_preferred_x, stb_state->preferred_x);
|
||||
Text("undo_point: %d, redo_point: %d, undo_char_point: %d, redo_char_point: %d", undo_state->undo_point, undo_state->redo_point, undo_state->undo_char_point, undo_state->redo_char_point);
|
||||
@@ -6207,7 +6267,7 @@ bool ImGui::ColorButton(const char* desc_id, const ImVec4& col, ImGuiColorEditFl
|
||||
if (g.Style.FrameBorderSize > 0.0f)
|
||||
RenderFrameBorder(bb.Min, bb.Max, rounding);
|
||||
else
|
||||
window->DrawList->AddRect(bb.Min, bb.Max, GetColorU32(ImGuiCol_FrameBg), rounding); // Color buttons are often in need of some sort of border
|
||||
window->DrawList->AddRect(bb.Min, bb.Max, GetColorU32(ImGuiCol_FrameBg), rounding); // Color buttons are often in need of some sort of border // FIXME-DPI
|
||||
}
|
||||
|
||||
// Drag and Drop Source
|
||||
@@ -6389,6 +6449,7 @@ void ImGui::ColorPickerOptionsPopup(const float* ref_col, ImGuiColorEditFlags fl
|
||||
// - TreeNodeV()
|
||||
// - TreeNodeEx()
|
||||
// - TreeNodeExV()
|
||||
// - TreeNodeStoreStackData() [Internal]
|
||||
// - TreeNodeBehavior() [Internal]
|
||||
// - TreePush()
|
||||
// - TreePop()
|
||||
@@ -6547,18 +6608,26 @@ bool ImGui::TreeNodeUpdateNextOpen(ImGuiID storage_id, ImGuiTreeNodeFlags flags)
|
||||
|
||||
// Store ImGuiTreeNodeStackData for just submitted node.
|
||||
// Currently only supports 32 level deep and we are fine with (1 << Depth) overflowing into a zero, easy to increase.
|
||||
static void TreeNodeStoreStackData(ImGuiTreeNodeFlags flags)
|
||||
static void TreeNodeStoreStackData(ImGuiTreeNodeFlags flags, float x1)
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
ImGuiWindow* window = g.CurrentWindow;
|
||||
|
||||
g.TreeNodeStack.resize(g.TreeNodeStack.Size + 1);
|
||||
ImGuiTreeNodeStackData* tree_node_data = &g.TreeNodeStack.back();
|
||||
ImGuiTreeNodeStackData* tree_node_data = &g.TreeNodeStack.Data[g.TreeNodeStack.Size - 1];
|
||||
tree_node_data->ID = g.LastItemData.ID;
|
||||
tree_node_data->TreeFlags = flags;
|
||||
tree_node_data->ItemFlags = g.LastItemData.ItemFlags;
|
||||
tree_node_data->NavRect = g.LastItemData.NavRect;
|
||||
|
||||
// Initially I tried to latch value for GetColorU32(ImGuiCol_TreeLines) but it's not a good trade-off for very large trees.
|
||||
const bool draw_lines = (flags & (ImGuiTreeNodeFlags_DrawLinesFull | ImGuiTreeNodeFlags_DrawLinesToNodes)) != 0;
|
||||
tree_node_data->DrawLinesX1 = draw_lines ? (x1 + g.FontSize * 0.5f + g.Style.FramePadding.x) : +FLT_MAX;
|
||||
tree_node_data->DrawLinesTableColumn = (draw_lines && g.CurrentTable) ? (ImGuiTableColumnIdx)g.CurrentTable->CurrentColumn : -1;
|
||||
tree_node_data->DrawLinesToNodesY2 = -FLT_MAX;
|
||||
window->DC.TreeHasStackDataDepthMask |= (1 << window->DC.TreeDepth);
|
||||
if (flags & ImGuiTreeNodeFlags_DrawLinesToNodes)
|
||||
window->DC.TreeRecordsClippedNodesY2Mask |= (1 << window->DC.TreeDepth);
|
||||
}
|
||||
|
||||
// When using public API, currently 'id == storage_id' is always true, but we separate the values to facilitate advanced user code doing storage queries outside of UI loop.
|
||||
@@ -6628,14 +6697,18 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l
|
||||
g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_HasDisplayRect;
|
||||
g.LastItemData.DisplayRect = frame_bb;
|
||||
|
||||
// If a NavLeft request is happening and ImGuiTreeNodeFlags_NavLeftJumpsBackHere enabled:
|
||||
// If a NavLeft request is happening and ImGuiTreeNodeFlags_NavLeftJumpsToParent enabled:
|
||||
// Store data for the current depth to allow returning to this node from any child item.
|
||||
// For this purpose we essentially compare if g.NavIdIsAlive went from 0 to 1 between TreeNode() and TreePop().
|
||||
// It will become tempting to enable ImGuiTreeNodeFlags_NavLeftJumpsBackHere by default or move it to ImGuiStyle.
|
||||
// It will become tempting to enable ImGuiTreeNodeFlags_NavLeftJumpsToParent by default or move it to ImGuiStyle.
|
||||
bool store_tree_node_stack_data = false;
|
||||
if ((flags & ImGuiTreeNodeFlags_DrawLinesMask_) == 0)
|
||||
flags |= g.Style.TreeLinesFlags;
|
||||
const bool draw_tree_lines = (flags & (ImGuiTreeNodeFlags_DrawLinesFull | ImGuiTreeNodeFlags_DrawLinesToNodes)) && (frame_bb.Min.y < window->ClipRect.Max.y) && (g.Style.TreeLinesSize > 0.0f);
|
||||
if (!(flags & ImGuiTreeNodeFlags_NoTreePushOnOpen))
|
||||
{
|
||||
if ((flags & ImGuiTreeNodeFlags_NavLeftJumpsBackHere) && is_open && !g.NavIdIsAlive)
|
||||
store_tree_node_stack_data = draw_tree_lines;
|
||||
if ((flags & ImGuiTreeNodeFlags_NavLeftJumpsToParent) && !g.NavIdIsAlive)
|
||||
if (g.NavMoveDir == ImGuiDir_Left && g.NavWindow == window && NavMoveRequestButNoResultYet())
|
||||
store_tree_node_stack_data = true;
|
||||
}
|
||||
@@ -6643,8 +6716,15 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l
|
||||
const bool is_leaf = (flags & ImGuiTreeNodeFlags_Leaf) != 0;
|
||||
if (!is_visible)
|
||||
{
|
||||
if (store_tree_node_stack_data && is_open)
|
||||
TreeNodeStoreStackData(flags); // Call before TreePushOverrideID()
|
||||
if ((flags & ImGuiTreeNodeFlags_DrawLinesToNodes) && (window->DC.TreeRecordsClippedNodesY2Mask & (1 << (window->DC.TreeDepth - 1))))
|
||||
{
|
||||
ImGuiTreeNodeStackData* parent_data = &g.TreeNodeStack.Data[g.TreeNodeStack.Size - 1];
|
||||
parent_data->DrawLinesToNodesY2 = ImMax(parent_data->DrawLinesToNodesY2, window->DC.CursorPos.y); // Don't need to aim to mid Y position as we are clipped anyway.
|
||||
if (frame_bb.Min.y >= window->ClipRect.Max.y)
|
||||
window->DC.TreeRecordsClippedNodesY2Mask &= ~(1 << (window->DC.TreeDepth - 1)); // Done
|
||||
}
|
||||
if (is_open && store_tree_node_stack_data)
|
||||
TreeNodeStoreStackData(flags, text_pos.x - text_offset_x); // Call before TreePushOverrideID()
|
||||
if (is_open && !(flags & ImGuiTreeNodeFlags_NoTreePushOnOpen))
|
||||
TreePushOverrideID(id);
|
||||
IMGUI_TEST_ENGINE_ITEM_INFO(g.LastItemData.ID, label, g.LastItemData.StatusFlags | (is_leaf ? 0 : ImGuiItemStatusFlags_Openable) | (is_open ? ImGuiItemStatusFlags_Opened : 0));
|
||||
@@ -6690,6 +6770,8 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l
|
||||
button_flags |= ImGuiButtonFlags_PressedOnClickRelease | ImGuiButtonFlags_PressedOnDoubleClick;
|
||||
else
|
||||
button_flags |= ImGuiButtonFlags_PressedOnClickRelease;
|
||||
if (flags & ImGuiTreeNodeFlags_NoNavFocus)
|
||||
button_flags |= ImGuiButtonFlags_NoNavFocus;
|
||||
|
||||
bool selected = (flags & ImGuiTreeNodeFlags_Selected) != 0;
|
||||
const bool was_selected = selected;
|
||||
@@ -6776,6 +6858,8 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l
|
||||
const ImU32 bg_col = GetColorU32((held && hovered) ? ImGuiCol_HeaderActive : hovered ? ImGuiCol_HeaderHovered : ImGuiCol_Header);
|
||||
RenderFrame(frame_bb.Min, frame_bb.Max, bg_col, true, style.FrameRounding);
|
||||
RenderNavCursor(frame_bb, id, nav_render_cursor_flags);
|
||||
if (span_all_columns && !span_all_columns_label)
|
||||
TablePopBackgroundChannel();
|
||||
if (flags & ImGuiTreeNodeFlags_Bullet)
|
||||
RenderBullet(window->DrawList, ImVec2(text_pos.x - text_offset_x * 0.60f, text_pos.y + g.FontSize * 0.5f), text_col);
|
||||
else if (!is_leaf)
|
||||
@@ -6796,6 +6880,8 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l
|
||||
RenderFrame(frame_bb.Min, frame_bb.Max, bg_col, false);
|
||||
}
|
||||
RenderNavCursor(frame_bb, id, nav_render_cursor_flags);
|
||||
if (span_all_columns && !span_all_columns_label)
|
||||
TablePopBackgroundChannel();
|
||||
if (flags & ImGuiTreeNodeFlags_Bullet)
|
||||
RenderBullet(window->DrawList, ImVec2(text_pos.x - text_offset_x * 0.5f, text_pos.y + g.FontSize * 0.5f), text_col);
|
||||
else if (!is_leaf)
|
||||
@@ -6804,8 +6890,8 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l
|
||||
LogSetNextTextDecoration(">", NULL);
|
||||
}
|
||||
|
||||
if (span_all_columns && !span_all_columns_label)
|
||||
TablePopBackgroundChannel();
|
||||
if (draw_tree_lines)
|
||||
TreeNodeDrawLineToChildNode(ImVec2(text_pos.x - text_offset_x + padding.x, text_pos.y + g.FontSize * 0.5f));
|
||||
|
||||
// Label
|
||||
if (display_frame)
|
||||
@@ -6817,8 +6903,8 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l
|
||||
TablePopBackgroundChannel();
|
||||
}
|
||||
|
||||
if (store_tree_node_stack_data && is_open)
|
||||
TreeNodeStoreStackData(flags); // Call before TreePushOverrideID()
|
||||
if (is_open && store_tree_node_stack_data)
|
||||
TreeNodeStoreStackData(flags, text_pos.x - text_offset_x); // Call before TreePushOverrideID()
|
||||
if (is_open && !(flags & ImGuiTreeNodeFlags_NoTreePushOnOpen))
|
||||
TreePushOverrideID(id); // Could use TreePush(label) but this avoid computing twice
|
||||
|
||||
@@ -6826,6 +6912,64 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l
|
||||
return is_open;
|
||||
}
|
||||
|
||||
// Draw horizontal line from our parent node
|
||||
// This is only called for visible child nodes so we are not too fussy anymore about performances
|
||||
void ImGui::TreeNodeDrawLineToChildNode(const ImVec2& target_pos)
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
ImGuiWindow* window = g.CurrentWindow;
|
||||
if (window->DC.TreeDepth == 0 || (window->DC.TreeHasStackDataDepthMask & (1 << (window->DC.TreeDepth - 1))) == 0)
|
||||
return;
|
||||
|
||||
ImGuiTreeNodeStackData* parent_data = &g.TreeNodeStack.Data[g.TreeNodeStack.Size - 1];
|
||||
float x1 = ImTrunc(parent_data->DrawLinesX1);
|
||||
float x2 = ImTrunc(target_pos.x - g.Style.ItemInnerSpacing.x);
|
||||
float y = ImTrunc(target_pos.y);
|
||||
float rounding = (g.Style.TreeLinesRounding > 0.0f) ? ImMin(x2 - x1, g.Style.TreeLinesRounding) : 0.0f;
|
||||
parent_data->DrawLinesToNodesY2 = ImMax(parent_data->DrawLinesToNodesY2, y - rounding);
|
||||
if (x1 >= x2)
|
||||
return;
|
||||
if (rounding > 0.0f)
|
||||
{
|
||||
x1 += 0.5f + rounding;
|
||||
window->DrawList->PathArcToFast(ImVec2(x1, y - rounding), rounding, 6, 3);
|
||||
if (x1 < x2)
|
||||
window->DrawList->PathLineTo(ImVec2(x2, y));
|
||||
window->DrawList->PathStroke(GetColorU32(ImGuiCol_TreeLines), ImDrawFlags_None, g.Style.TreeLinesSize);
|
||||
}
|
||||
else
|
||||
{
|
||||
window->DrawList->AddLine(ImVec2(x1, y), ImVec2(x2, y), GetColorU32(ImGuiCol_TreeLines), g.Style.TreeLinesSize);
|
||||
}
|
||||
}
|
||||
|
||||
// Draw vertical line of the hierarchy
|
||||
void ImGui::TreeNodeDrawLineToTreePop(const ImGuiTreeNodeStackData* data)
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
ImGuiWindow* window = g.CurrentWindow;
|
||||
float y1 = ImMax(data->NavRect.Max.y, window->ClipRect.Min.y);
|
||||
float y2 = data->DrawLinesToNodesY2;
|
||||
if (data->TreeFlags & ImGuiTreeNodeFlags_DrawLinesFull)
|
||||
{
|
||||
float y2_full = window->DC.CursorPos.y;
|
||||
if (g.CurrentTable)
|
||||
y2_full = ImMax(g.CurrentTable->RowPosY2, y2_full);
|
||||
y2_full = ImTrunc(y2_full - g.Style.ItemSpacing.y - g.FontSize * 0.5f);
|
||||
if (y2 + (g.Style.ItemSpacing.y + g.Style.TreeLinesRounding) < y2_full) // FIXME: threshold to use ToNodes Y2 instead of Full Y2 when close by ItemSpacing.y
|
||||
y2 = y2_full;
|
||||
}
|
||||
y2 = ImMin(y2, window->ClipRect.Max.y);
|
||||
if (y2 <= y1)
|
||||
return;
|
||||
float x = ImTrunc(data->DrawLinesX1);
|
||||
if (data->DrawLinesTableColumn != -1)
|
||||
TablePushColumnChannel(data->DrawLinesTableColumn);
|
||||
window->DrawList->AddLine(ImVec2(x, y1), ImVec2(x, y2), GetColorU32(ImGuiCol_TreeLines), g.Style.TreeLinesSize);
|
||||
if (data->DrawLinesTableColumn != -1)
|
||||
TablePopColumnChannel();
|
||||
}
|
||||
|
||||
void ImGui::TreePush(const char* str_id)
|
||||
{
|
||||
ImGuiWindow* window = GetCurrentWindow();
|
||||
@@ -6860,18 +7004,23 @@ void ImGui::TreePop()
|
||||
window->DC.TreeDepth--;
|
||||
ImU32 tree_depth_mask = (1 << window->DC.TreeDepth);
|
||||
|
||||
if (window->DC.TreeHasStackDataDepthMask & tree_depth_mask) // Only set during request
|
||||
if (window->DC.TreeHasStackDataDepthMask & tree_depth_mask)
|
||||
{
|
||||
ImGuiTreeNodeStackData* data = &g.TreeNodeStack.back();
|
||||
const ImGuiTreeNodeStackData* data = &g.TreeNodeStack.Data[g.TreeNodeStack.Size - 1];
|
||||
IM_ASSERT(data->ID == window->IDStack.back());
|
||||
if (data->TreeFlags & ImGuiTreeNodeFlags_NavLeftJumpsBackHere)
|
||||
{
|
||||
// Handle Left arrow to move to parent tree node (when ImGuiTreeNodeFlags_NavLeftJumpsBackHere is enabled)
|
||||
|
||||
// Handle Left arrow to move to parent tree node (when ImGuiTreeNodeFlags_NavLeftJumpsToParent is enabled)
|
||||
if (data->TreeFlags & ImGuiTreeNodeFlags_NavLeftJumpsToParent)
|
||||
if (g.NavIdIsAlive && g.NavMoveDir == ImGuiDir_Left && g.NavWindow == window && NavMoveRequestButNoResultYet())
|
||||
NavMoveRequestResolveWithPastTreeNode(&g.NavMoveResultLocal, data);
|
||||
}
|
||||
|
||||
// Draw hierarchy lines
|
||||
if (data->DrawLinesX1 != +FLT_MAX && window->DC.CursorPos.y >= window->ClipRect.Min.y)
|
||||
TreeNodeDrawLineToTreePop(data);
|
||||
|
||||
g.TreeNodeStack.pop_back();
|
||||
window->DC.TreeHasStackDataDepthMask &= ~tree_depth_mask;
|
||||
window->DC.TreeRecordsClippedNodesY2Mask &= ~tree_depth_mask;
|
||||
}
|
||||
|
||||
IM_ASSERT(window->IDStack.Size > 1); // There should always be 1 element in the IDStack (pushed during window creation). If this triggers you called TreePop/PopID too much.
|
||||
@@ -7486,7 +7635,7 @@ void ImGui::EndBoxSelect(const ImRect& scope_rect, ImGuiMultiSelectFlags ms_flag
|
||||
ImRect box_select_r = bs->BoxSelectRectCurr;
|
||||
box_select_r.ClipWith(scope_rect);
|
||||
window->DrawList->AddRectFilled(box_select_r.Min, box_select_r.Max, GetColorU32(ImGuiCol_SeparatorHovered, 0.30f)); // FIXME-MULTISELECT: Styling
|
||||
window->DrawList->AddRect(box_select_r.Min, box_select_r.Max, GetColorU32(ImGuiCol_NavCursor)); // FIXME-MULTISELECT: Styling
|
||||
window->DrawList->AddRect(box_select_r.Min, box_select_r.Max, GetColorU32(ImGuiCol_NavCursor)); // FIXME-MULTISELECT FIXME-DPI: Styling
|
||||
|
||||
// Scroll
|
||||
const bool enable_scroll = (ms_flags & ImGuiMultiSelectFlags_ScopeWindow) && (ms_flags & ImGuiMultiSelectFlags_BoxSelectNoScroll) == 0;
|
||||
@@ -7690,7 +7839,7 @@ ImGuiMultiSelectIO* ImGui::EndMultiSelect()
|
||||
if (ms->IsFocused)
|
||||
{
|
||||
// We currently don't allow user code to modify RangeSrcItem by writing to BeginIO's version, but that would be an easy change here.
|
||||
if (ms->IO.RangeSrcReset || (ms->RangeSrcPassedBy == false && ms->IO.RangeSrcItem != ImGuiSelectionUserData_Invalid)) // Can't read storage->RangeSrcItem here -> we want the state at begining of the scope (see tests for easy failure)
|
||||
if (ms->IO.RangeSrcReset || (ms->RangeSrcPassedBy == false && ms->IO.RangeSrcItem != ImGuiSelectionUserData_Invalid)) // Can't read storage->RangeSrcItem here -> we want the state at beginning of the scope (see tests for easy failure)
|
||||
{
|
||||
IMGUI_DEBUG_LOG_SELECTION("[selection] EndMultiSelect: Reset RangeSrcItem.\n"); // Will set be to NavId.
|
||||
storage->RangeSrcItem = ImGuiSelectionUserData_Invalid;
|
||||
@@ -10376,13 +10525,12 @@ void ImGui::TabItemLabelAndCloseButton(ImDrawList* draw_list, const ImRect& bb,
|
||||
#endif
|
||||
|
||||
// Render text label (with clipping + alpha gradient) + unsaved marker
|
||||
ImRect text_pixel_clip_bb(bb.Min.x + frame_padding.x, bb.Min.y + frame_padding.y, bb.Max.x - frame_padding.x, bb.Max.y);
|
||||
ImRect text_ellipsis_clip_bb = text_pixel_clip_bb;
|
||||
ImRect text_ellipsis_clip_bb(bb.Min.x + frame_padding.x, bb.Min.y + frame_padding.y, bb.Max.x - frame_padding.x, bb.Max.y);
|
||||
|
||||
// Return clipped state ignoring the close button
|
||||
if (out_text_clipped)
|
||||
{
|
||||
*out_text_clipped = (text_ellipsis_clip_bb.Min.x + label_size.x) > text_pixel_clip_bb.Max.x;
|
||||
*out_text_clipped = (text_ellipsis_clip_bb.Min.x + label_size.x) > text_ellipsis_clip_bb.Max.x;
|
||||
//draw_list->AddCircle(text_ellipsis_clip_bb.Min, 3.0f, *out_text_clipped ? IM_COL32(255, 0, 0, 255) : IM_COL32(0, 255, 0, 255));
|
||||
}
|
||||
|
||||
@@ -10428,15 +10576,22 @@ void ImGui::TabItemLabelAndCloseButton(ImDrawList* draw_list, const ImRect& bb,
|
||||
// This is all rather complicated
|
||||
// (the main idea is that because the close button only appears on hover, we don't want it to alter the ellipsis position)
|
||||
// FIXME: if FramePadding is noticeably large, ellipsis_max_x will be wrong here (e.g. #3497), maybe for consistency that parameter of RenderTextEllipsis() shouldn't exist..
|
||||
float ellipsis_max_x = close_button_visible ? text_pixel_clip_bb.Max.x : bb.Max.x - 1.0f;
|
||||
float ellipsis_max_x = text_ellipsis_clip_bb.Max.x;
|
||||
if (close_button_visible || unsaved_marker_visible)
|
||||
{
|
||||
text_pixel_clip_bb.Max.x -= close_button_visible ? (button_sz) : (button_sz * 0.80f);
|
||||
text_ellipsis_clip_bb.Max.x -= unsaved_marker_visible ? (button_sz * 0.80f) : 0.0f;
|
||||
ellipsis_max_x = text_pixel_clip_bb.Max.x;
|
||||
const bool visible_without_hover = unsaved_marker_visible || (is_contents_visible ? g.Style.TabCloseButtonMinWidthSelected : g.Style.TabCloseButtonMinWidthUnselected) < 0.0f;
|
||||
if (visible_without_hover)
|
||||
{
|
||||
text_ellipsis_clip_bb.Max.x -= button_sz * 0.90f;
|
||||
ellipsis_max_x -= button_sz * 0.90f;
|
||||
}
|
||||
else
|
||||
{
|
||||
text_ellipsis_clip_bb.Max.x -= button_sz * 1.00f;
|
||||
}
|
||||
}
|
||||
LogSetNextTextDecoration("/", "\\");
|
||||
RenderTextEllipsis(draw_list, text_ellipsis_clip_bb.Min, text_ellipsis_clip_bb.Max, text_pixel_clip_bb.Max.x, ellipsis_max_x, label, NULL, &label_size);
|
||||
RenderTextEllipsis(draw_list, text_ellipsis_clip_bb.Min, text_ellipsis_clip_bb.Max, ellipsis_max_x, label, NULL, &label_size);
|
||||
|
||||
#if 0
|
||||
if (!is_contents_visible)
|
||||
|
||||
4
3rdparty/imgui/src/imstb_truetype.h
vendored
4
3rdparty/imgui/src/imstb_truetype.h
vendored
@@ -4516,8 +4516,8 @@ static int stbtt__compute_crossings_x(float x, float y, int nverts, stbtt_vertex
|
||||
q2[0] = (float)x2;
|
||||
q2[1] = (float)y2;
|
||||
if (equal(q0,q1) || equal(q1,q2)) {
|
||||
x0 = (int)verts[i-1].x;
|
||||
y0 = (int)verts[i-1].y;
|
||||
x0 = (int)verts[i-1].x; //-V1048
|
||||
y0 = (int)verts[i-1].y; //-V1048
|
||||
x1 = (int)verts[i ].x;
|
||||
y1 = (int)verts[i ].y;
|
||||
if (y > STBTT_min(y0,y1) && y < STBTT_max(y0,y1) && x > STBTT_min(x0,x1)) {
|
||||
|
||||
1
3rdparty/libzip/CMakeLists.txt
vendored
1
3rdparty/libzip/CMakeLists.txt
vendored
@@ -196,6 +196,7 @@ add_library(zip STATIC
|
||||
lib/zip_name_locate.c
|
||||
lib/zip_new.c
|
||||
lib/zip_open.c
|
||||
lib/zip_realloc.c
|
||||
lib/zip_pkware.c
|
||||
lib/zip_progress.c
|
||||
lib/zip_rename.c
|
||||
|
||||
9
3rdparty/libzip/lib/zip.h
vendored
9
3rdparty/libzip/lib/zip.h
vendored
@@ -34,6 +34,15 @@
|
||||
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#if defined(__has_feature)
|
||||
#if !__has_feature(nullability)
|
||||
#define _Nullable
|
||||
#define _Nonnull
|
||||
#endif
|
||||
#else
|
||||
#define _Nullable
|
||||
#define _Nonnull
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
||||
18
3rdparty/libzip/lib/zip_add_entry.c
vendored
18
3rdparty/libzip/lib/zip_add_entry.c
vendored
@@ -44,10 +44,7 @@ _zip_add_entry(zip_t *za) {
|
||||
zip_uint64_t idx;
|
||||
|
||||
if (za->nentry + 1 >= za->nentry_alloc) {
|
||||
zip_entry_t *rentries;
|
||||
zip_uint64_t nalloc = za->nentry_alloc;
|
||||
zip_uint64_t additional_entries = 2 * nalloc;
|
||||
zip_uint64_t realloc_size;
|
||||
zip_uint64_t additional_entries = 2 * za->nentry_alloc;
|
||||
|
||||
if (additional_entries < 16) {
|
||||
additional_entries = 16;
|
||||
@@ -55,21 +52,10 @@ _zip_add_entry(zip_t *za) {
|
||||
else if (additional_entries > 1024) {
|
||||
additional_entries = 1024;
|
||||
}
|
||||
/* neither + nor * overflows can happen: nentry_alloc * sizeof(struct zip_entry) < UINT64_MAX */
|
||||
nalloc += additional_entries;
|
||||
realloc_size = sizeof(struct zip_entry) * (size_t)nalloc;
|
||||
|
||||
if (sizeof(struct zip_entry) * (size_t)za->nentry_alloc > realloc_size) {
|
||||
zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
|
||||
if (!ZIP_REALLOC(za->entry, za->nentry_alloc, additional_entries, &za->error)) {
|
||||
return -1;
|
||||
}
|
||||
rentries = (zip_entry_t *)realloc(za->entry, sizeof(struct zip_entry) * (size_t)nalloc);
|
||||
if (rentries == NULL) {
|
||||
zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
|
||||
return -1;
|
||||
}
|
||||
za->entry = rentries;
|
||||
za->nentry_alloc = nalloc;
|
||||
}
|
||||
|
||||
idx = za->nentry++;
|
||||
|
||||
4
3rdparty/libzip/lib/zip_algorithm_bzip2.c
vendored
4
3rdparty/libzip/lib/zip_algorithm_bzip2.c
vendored
@@ -208,11 +208,11 @@ input(void *ud, zip_uint8_t *data, zip_uint64_t length) {
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
end_of_input(void *ud) {
|
||||
static bool end_of_input(void *ud) {
|
||||
struct ctx *ctx = (struct ctx *)ud;
|
||||
|
||||
ctx->end_of_input = true;
|
||||
return ctx->zstr.avail_in != 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
4
3rdparty/libzip/lib/zip_algorithm_deflate.c
vendored
4
3rdparty/libzip/lib/zip_algorithm_deflate.c
vendored
@@ -196,11 +196,11 @@ input(void *ud, zip_uint8_t *data, zip_uint64_t length) {
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
end_of_input(void *ud) {
|
||||
static bool end_of_input(void *ud) {
|
||||
struct ctx *ctx = (struct ctx *)ud;
|
||||
|
||||
ctx->end_of_input = true;
|
||||
return ctx->zstr.avail_in != 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
4
3rdparty/libzip/lib/zip_algorithm_xz.c
vendored
4
3rdparty/libzip/lib/zip_algorithm_xz.c
vendored
@@ -302,11 +302,11 @@ input(void *ud, zip_uint8_t *data, zip_uint64_t length) {
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
end_of_input(void *ud) {
|
||||
static bool end_of_input(void *ud) {
|
||||
struct ctx *ctx = (struct ctx *)ud;
|
||||
|
||||
ctx->end_of_input = true;
|
||||
return ctx->zstr.avail_in != 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
4
3rdparty/libzip/lib/zip_algorithm_zstd.c
vendored
4
3rdparty/libzip/lib/zip_algorithm_zstd.c
vendored
@@ -211,11 +211,11 @@ input(void *ud, zip_uint8_t *data, zip_uint64_t length) {
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
end_of_input(void *ud) {
|
||||
static bool end_of_input(void *ud) {
|
||||
struct ctx *ctx = (struct ctx *)ud;
|
||||
|
||||
ctx->end_of_input = true;
|
||||
return ctx->in.pos != ctx->in.size;
|
||||
}
|
||||
|
||||
|
||||
|
||||
140
3rdparty/libzip/lib/zip_close.c
vendored
140
3rdparty/libzip/lib/zip_close.c
vendored
@@ -42,7 +42,7 @@
|
||||
#endif
|
||||
|
||||
|
||||
static int add_data(zip_t *, zip_source_t *, zip_dirent_t *, zip_uint32_t);
|
||||
static int add_data(zip_t *, zip_source_t *, zip_dirent_t *);
|
||||
static int copy_data(zip_t *, zip_uint64_t);
|
||||
static int copy_source(zip_t *, zip_source_t *, zip_source_t *, zip_int64_t);
|
||||
static int torrentzip_compare_names(const void *a, const void *b);
|
||||
@@ -195,6 +195,12 @@ zip_close(zip_t *za) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (entry->orig != NULL) {
|
||||
if (!_zip_dirent_merge(entry->changes, entry->orig, ZIP_ENTRY_DATA_CHANGED(entry), &za->error)) {
|
||||
error = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
de = entry->changes;
|
||||
|
||||
if (_zip_read_local_ef(za, i) < 0) {
|
||||
@@ -225,7 +231,7 @@ zip_close(zip_t *za) {
|
||||
}
|
||||
|
||||
/* add_data writes dirent */
|
||||
if (add_data(za, zs ? zs : entry->source, de, entry->changes ? entry->changes->changed : 0) < 0) {
|
||||
if (add_data(za, zs ? zs : entry->source, de) < 0) {
|
||||
error = 1;
|
||||
if (zs)
|
||||
zip_source_free(zs);
|
||||
@@ -295,8 +301,7 @@ zip_close(zip_t *za) {
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
add_data(zip_t *za, zip_source_t *src, zip_dirent_t *de, zip_uint32_t changed) {
|
||||
static int add_data(zip_t *za, zip_source_t *src, zip_dirent_t *de) {
|
||||
zip_int64_t offstart, offdata, offend, data_length;
|
||||
zip_stat_t st;
|
||||
zip_file_attributes_t attributes;
|
||||
@@ -305,19 +310,25 @@ add_data(zip_t *za, zip_source_t *src, zip_dirent_t *de, zip_uint32_t changed) {
|
||||
int is_zip64;
|
||||
zip_flags_t flags;
|
||||
bool needs_recompress, needs_decompress, needs_crc, needs_compress, needs_reencrypt, needs_decrypt, needs_encrypt;
|
||||
bool dirent_changed;
|
||||
bool have_dos_time = false;
|
||||
time_t mtime_before_copy;
|
||||
|
||||
if (zip_source_stat(src, &st) < 0) {
|
||||
zip_error_set_from_source(&za->error, src);
|
||||
return -1;
|
||||
}
|
||||
|
||||
de->bitflags &= ~ZIP_GPBF_DATA_DESCRIPTOR;
|
||||
|
||||
if ((st.valid & ZIP_STAT_COMP_METHOD) == 0) {
|
||||
st.valid |= ZIP_STAT_COMP_METHOD;
|
||||
st.comp_method = ZIP_CM_STORE;
|
||||
}
|
||||
|
||||
if (ZIP_CM_IS_DEFAULT(de->comp_method) && st.comp_method != ZIP_CM_STORE)
|
||||
if (ZIP_CM_IS_DEFAULT(de->comp_method) && st.comp_method != ZIP_CM_STORE) {
|
||||
de->comp_method = st.comp_method;
|
||||
}
|
||||
else if (de->comp_method == ZIP_CM_STORE && (st.valid & ZIP_STAT_SIZE)) {
|
||||
st.valid |= ZIP_STAT_COMP_SIZE;
|
||||
st.comp_size = st.size;
|
||||
@@ -372,14 +383,30 @@ add_data(zip_t *za, zip_source_t *src, zip_dirent_t *de, zip_uint32_t changed) {
|
||||
}
|
||||
}
|
||||
|
||||
if ((offstart = zip_source_tell_write(za->src)) < 0) {
|
||||
zip_error_set_from_source(&za->error, za->src);
|
||||
return -1;
|
||||
if ((de->changed & ZIP_DIRENT_LAST_MOD) == 0) {
|
||||
int ret2 = zip_source_get_dos_time(src, &de->last_mod);
|
||||
if (ret2 < 0) {
|
||||
zip_error_set_from_source(&za->error, src);
|
||||
return -1;
|
||||
}
|
||||
if (ret2 == 1) {
|
||||
have_dos_time = true;
|
||||
}
|
||||
else {
|
||||
if (st.valid & ZIP_STAT_MTIME) {
|
||||
mtime_before_copy = st.mtime;
|
||||
}
|
||||
else {
|
||||
time(&mtime_before_copy);
|
||||
}
|
||||
if (_zip_u2d_time(mtime_before_copy, &de->last_mod, &za->error) < 0) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* as long as we don't support non-seekable output, clear data descriptor bit */
|
||||
de->bitflags &= (zip_uint16_t)~ZIP_GPBF_DATA_DESCRIPTOR;
|
||||
if ((is_zip64 = _zip_dirent_write(za, de, flags)) < 0) {
|
||||
if ((offstart = zip_source_tell_write(za->src)) < 0) {
|
||||
zip_error_set_from_source(&za->error, za->src);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -485,9 +512,24 @@ add_data(zip_t *za, zip_source_t *src, zip_dirent_t *de, zip_uint32_t changed) {
|
||||
src_final = src_tmp;
|
||||
}
|
||||
|
||||
if (!ZIP_WANT_TORRENTZIP(za)) {
|
||||
if (zip_source_get_file_attributes(src_final, &attributes) != 0) {
|
||||
zip_error_set_from_source(&za->error, src_final);
|
||||
zip_source_free(src_final);
|
||||
return -1;
|
||||
}
|
||||
_zip_dirent_apply_attributes(de, &attributes, (flags & ZIP_FL_FORCE_ZIP64) != 0);
|
||||
}
|
||||
|
||||
/* as long as we don't support non-seekable output, clear data descriptor bit */
|
||||
if ((is_zip64 = _zip_dirent_write(za, de, flags)) < 0) {
|
||||
zip_source_free(src_final);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((offdata = zip_source_tell_write(za->src)) < 0) {
|
||||
zip_error_set_from_source(&za->error, za->src);
|
||||
zip_source_free(src_final);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -498,9 +540,11 @@ add_data(zip_t *za, zip_source_t *src, zip_dirent_t *de, zip_uint32_t changed) {
|
||||
ret = -1;
|
||||
}
|
||||
|
||||
if (zip_source_get_file_attributes(src_final, &attributes) != 0) {
|
||||
zip_error_set_from_source(&za->error, src_final);
|
||||
ret = -1;
|
||||
if (!ZIP_WANT_TORRENTZIP(za)) {
|
||||
if (zip_source_get_file_attributes(src_final, &attributes) != 0) {
|
||||
zip_error_set_from_source(&za->error, src_final);
|
||||
ret = -1;
|
||||
}
|
||||
}
|
||||
|
||||
zip_source_free(src_final);
|
||||
@@ -514,57 +558,51 @@ add_data(zip_t *za, zip_source_t *src, zip_dirent_t *de, zip_uint32_t changed) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (zip_source_seek_write(za->src, offstart, SEEK_SET) < 0) {
|
||||
zip_error_set_from_source(&za->error, za->src);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((st.valid & (ZIP_STAT_COMP_METHOD | ZIP_STAT_CRC | ZIP_STAT_SIZE)) != (ZIP_STAT_COMP_METHOD | ZIP_STAT_CRC | ZIP_STAT_SIZE)) {
|
||||
zip_error_set(&za->error, ZIP_ER_INTERNAL, 0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((de->changed & ZIP_DIRENT_LAST_MOD) == 0) {
|
||||
int ret2 = zip_source_get_dos_time(src, &de->last_mod);
|
||||
if (ret2 < 0) {
|
||||
zip_error_set_from_source(&za->error, src);
|
||||
return -1;
|
||||
}
|
||||
if (ret2 == 0) {
|
||||
time_t mtime;
|
||||
if (st.valid & ZIP_STAT_MTIME) {
|
||||
mtime = st.mtime;
|
||||
}
|
||||
else {
|
||||
time(&mtime);
|
||||
}
|
||||
if (_zip_u2d_time(mtime, &de->last_mod, &za->error) < 0) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
dirent_changed = ZIP_CM_ACTUAL(de->comp_method) != st.comp_method || de->crc != st.crc || de->uncomp_size != st.size || de->comp_size != (zip_uint64_t)(offend - offdata);
|
||||
de->comp_method = st.comp_method;
|
||||
de->crc = st.crc;
|
||||
de->uncomp_size = st.size;
|
||||
de->comp_size = (zip_uint64_t)(offend - offdata);
|
||||
_zip_dirent_apply_attributes(de, &attributes, (flags & ZIP_FL_FORCE_ZIP64) != 0, changed);
|
||||
|
||||
if (ZIP_WANT_TORRENTZIP(za)) {
|
||||
zip_dirent_torrentzip_normalize(de);
|
||||
if (!ZIP_WANT_TORRENTZIP(za)) {
|
||||
dirent_changed |= _zip_dirent_apply_attributes(de, &attributes, (flags & ZIP_FL_FORCE_ZIP64) != 0);
|
||||
|
||||
if ((de->changed & ZIP_DIRENT_LAST_MOD) == 0 && !have_dos_time) {
|
||||
if (st.valid & ZIP_STAT_MTIME) {
|
||||
if (st.mtime != mtime_before_copy) {
|
||||
if (_zip_u2d_time(st.mtime, &de->last_mod, &za->error) < 0) {
|
||||
return -1;
|
||||
}
|
||||
dirent_changed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((ret = _zip_dirent_write(za, de, flags)) < 0)
|
||||
return -1;
|
||||
if (dirent_changed) {
|
||||
if (zip_source_seek_write(za->src, offstart, SEEK_SET) < 0) {
|
||||
zip_error_set_from_source(&za->error, za->src);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (is_zip64 != ret) {
|
||||
/* Zip64 mismatch between preliminary file header written before data and final file header written afterwards */
|
||||
zip_error_set(&za->error, ZIP_ER_INTERNAL, 0);
|
||||
return -1;
|
||||
}
|
||||
if ((ret = _zip_dirent_write(za, de, flags)) < 0)
|
||||
return -1;
|
||||
|
||||
if (zip_source_seek_write(za->src, offend, SEEK_SET) < 0) {
|
||||
zip_error_set_from_source(&za->error, za->src);
|
||||
return -1;
|
||||
if (is_zip64 != ret) {
|
||||
/* Zip64 mismatch between preliminary file header written before data and final file header written afterwards */
|
||||
zip_error_set(&za->error, ZIP_ER_INTERNAL, 0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (zip_source_seek_write(za->src, offend, SEEK_SET) < 0) {
|
||||
zip_error_set_from_source(&za->error, za->src);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (de->bitflags & ZIP_GPBF_DATA_DESCRIPTOR) {
|
||||
|
||||
157
3rdparty/libzip/lib/zip_dirent.c
vendored
157
3rdparty/libzip/lib/zip_dirent.c
vendored
@@ -83,32 +83,21 @@ _zip_cdir_new(zip_error_t *error) {
|
||||
|
||||
bool
|
||||
_zip_cdir_grow(zip_cdir_t *cd, zip_uint64_t additional_entries, zip_error_t *error) {
|
||||
zip_uint64_t i, new_alloc;
|
||||
zip_entry_t *new_entry;
|
||||
zip_uint64_t i;
|
||||
|
||||
if (additional_entries == 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
new_alloc = cd->nentry_alloc + additional_entries;
|
||||
|
||||
if (new_alloc < additional_entries || new_alloc > SIZE_MAX / sizeof(*(cd->entry))) {
|
||||
zip_error_set(error, ZIP_ER_MEMORY, 0);
|
||||
if (!ZIP_REALLOC(cd->entry, cd->nentry_alloc, additional_entries, error)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((new_entry = (zip_entry_t *)realloc(cd->entry, sizeof(*(cd->entry)) * (size_t)new_alloc)) == NULL) {
|
||||
zip_error_set(error, ZIP_ER_MEMORY, 0);
|
||||
return false;
|
||||
}
|
||||
|
||||
cd->entry = new_entry;
|
||||
|
||||
for (i = cd->nentry; i < new_alloc; i++) {
|
||||
for (i = cd->nentry; i < cd->nentry_alloc; i++) {
|
||||
_zip_entry_init(cd->entry + i);
|
||||
}
|
||||
|
||||
cd->nentry = cd->nentry_alloc = new_alloc;
|
||||
cd->nentry = cd->nentry_alloc;
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -275,6 +264,55 @@ _zip_dirent_free(zip_dirent_t *zde) {
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
_zip_dirent_merge(zip_dirent_t *de, zip_dirent_t *de_orig, bool replacing_data, zip_error_t *error) {
|
||||
if (!de->cloned) {
|
||||
zip_error_set(error, ZIP_ER_INTERNAL, 0);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!(de->changed & ZIP_DIRENT_ATTRIBUTES)) {
|
||||
de->ext_attrib = de_orig->ext_attrib;
|
||||
de->int_attrib = de_orig->int_attrib;
|
||||
}
|
||||
if (!(de->changed & ZIP_DIRENT_COMMENT)) {
|
||||
de->comment = de_orig->comment;
|
||||
}
|
||||
if (!(de->changed & ZIP_DIRENT_COMP_METHOD)) {
|
||||
if (replacing_data) {
|
||||
de->comp_method = ZIP_CM_DEFAULT;
|
||||
de->compression_level = 0;
|
||||
}
|
||||
else {
|
||||
de->comp_method = de_orig->comp_method;
|
||||
de->compression_level = de_orig->compression_level;
|
||||
}
|
||||
}
|
||||
if (!(de->changed & ZIP_DIRENT_ENCRYPTION_METHOD)) {
|
||||
if (replacing_data) {
|
||||
de->encryption_method = ZIP_EM_NONE;
|
||||
}
|
||||
else {
|
||||
de->encryption_method = de_orig->encryption_method;
|
||||
}
|
||||
}
|
||||
if (!(de->changed & ZIP_DIRENT_EXTRA_FIELD)) {
|
||||
de->extra_fields = de_orig->extra_fields;
|
||||
}
|
||||
if (!(de->changed & ZIP_DIRENT_FILENAME)) {
|
||||
de->filename = de_orig->filename;
|
||||
}
|
||||
if (!(de->changed & ZIP_DIRENT_LAST_MOD)) {
|
||||
de->last_mod = de_orig->last_mod;
|
||||
}
|
||||
if (!(de->changed & ZIP_DIRENT_PASSWORD)) {
|
||||
de->password = de_orig->password;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
_zip_dirent_init(zip_dirent_t *de) {
|
||||
de->changed = 0;
|
||||
@@ -968,7 +1006,7 @@ _zip_dirent_write(zip_t *za, zip_dirent_t *de, zip_flags_t flags) {
|
||||
_zip_buffer_put_16(buffer, ZIP_CM_WINZIP_AES);
|
||||
}
|
||||
else {
|
||||
_zip_buffer_put_16(buffer, (zip_uint16_t)de->comp_method);
|
||||
_zip_buffer_put_16(buffer, (zip_uint16_t)ZIP_CM_ACTUAL(de->comp_method));
|
||||
}
|
||||
|
||||
if (ZIP_WANT_TORRENTZIP(za)) {
|
||||
@@ -1190,52 +1228,76 @@ _zip_u2d_time(time_t intime, zip_dostime_t *dtime, zip_error_t *ze) {
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
_zip_dirent_apply_attributes(zip_dirent_t *de, zip_file_attributes_t *attributes, bool force_zip64, zip_uint32_t changed) {
|
||||
bool
|
||||
_zip_dirent_apply_attributes(zip_dirent_t *de, zip_file_attributes_t *attributes, bool force_zip64) {
|
||||
zip_uint16_t length;
|
||||
bool has_changed = false;
|
||||
|
||||
if (attributes->valid & ZIP_FILE_ATTRIBUTES_GENERAL_PURPOSE_BIT_FLAGS) {
|
||||
zip_uint16_t mask = attributes->general_purpose_bit_mask & ZIP_FILE_ATTRIBUTES_GENERAL_PURPOSE_BIT_FLAGS_ALLOWED_MASK;
|
||||
de->bitflags = (de->bitflags & ~mask) | (attributes->general_purpose_bit_flags & mask);
|
||||
zip_uint16_t bitflags = (de->bitflags & ~mask) | (attributes->general_purpose_bit_flags & mask);
|
||||
if (de->bitflags != bitflags) {
|
||||
de->bitflags = bitflags;
|
||||
has_changed = true;
|
||||
}
|
||||
}
|
||||
if (attributes->valid & ZIP_FILE_ATTRIBUTES_ASCII) {
|
||||
de->int_attrib = (de->int_attrib & ~0x1) | (attributes->ascii ? 1 : 0);
|
||||
zip_uint16_t int_attrib = (de->int_attrib & ~0x1) | (attributes->ascii ? 1 : 0);
|
||||
if (de->int_attrib != int_attrib) {
|
||||
de->int_attrib = int_attrib;
|
||||
has_changed = true;
|
||||
}
|
||||
}
|
||||
/* manually set attributes are preferred over attributes provided by source */
|
||||
if ((changed & ZIP_DIRENT_ATTRIBUTES) == 0 && (attributes->valid & ZIP_FILE_ATTRIBUTES_EXTERNAL_FILE_ATTRIBUTES)) {
|
||||
de->ext_attrib = attributes->external_file_attributes;
|
||||
if ((de->changed & ZIP_DIRENT_ATTRIBUTES) == 0 && (attributes->valid & ZIP_FILE_ATTRIBUTES_EXTERNAL_FILE_ATTRIBUTES)) {
|
||||
if (de->ext_attrib != attributes->external_file_attributes) {
|
||||
de->ext_attrib = attributes->external_file_attributes;
|
||||
has_changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
zip_uint16_t version_needed;
|
||||
if (de->comp_method == ZIP_CM_LZMA) {
|
||||
de->version_needed = 63;
|
||||
version_needed = 63;
|
||||
}
|
||||
else if (de->encryption_method == ZIP_EM_AES_128 || de->encryption_method == ZIP_EM_AES_192 || de->encryption_method == ZIP_EM_AES_256) {
|
||||
de->version_needed = 51;
|
||||
version_needed = 51;
|
||||
}
|
||||
else if (de->comp_method == ZIP_CM_BZIP2) {
|
||||
de->version_needed = 46;
|
||||
version_needed = 46;
|
||||
}
|
||||
else if (force_zip64 || _zip_dirent_needs_zip64(de, 0)) {
|
||||
de->version_needed = 45;
|
||||
version_needed = 45;
|
||||
}
|
||||
else if (de->comp_method == ZIP_CM_DEFLATE || de->encryption_method == ZIP_EM_TRAD_PKWARE) {
|
||||
de->version_needed = 20;
|
||||
version_needed = 20;
|
||||
}
|
||||
else if ((length = _zip_string_length(de->filename)) > 0 && de->filename->raw[length - 1] == '/') {
|
||||
de->version_needed = 20;
|
||||
version_needed = 20;
|
||||
}
|
||||
else {
|
||||
de->version_needed = 10;
|
||||
version_needed = 10;
|
||||
}
|
||||
|
||||
if (attributes->valid & ZIP_FILE_ATTRIBUTES_VERSION_NEEDED) {
|
||||
de->version_needed = ZIP_MAX(de->version_needed, attributes->version_needed);
|
||||
version_needed = ZIP_MAX(version_needed, attributes->version_needed);
|
||||
}
|
||||
|
||||
de->version_madeby = 63 | (de->version_madeby & 0xff00);
|
||||
if ((changed & ZIP_DIRENT_ATTRIBUTES) == 0 && (attributes->valid & ZIP_FILE_ATTRIBUTES_HOST_SYSTEM)) {
|
||||
de->version_madeby = (de->version_madeby & 0xff) | (zip_uint16_t)(attributes->host_system << 8);
|
||||
if (de->version_needed != version_needed) {
|
||||
de->version_needed = version_needed;
|
||||
has_changed = true;
|
||||
}
|
||||
|
||||
zip_int16_t version_madeby = 63 | (de->version_madeby & 0xff00);
|
||||
if ((de->changed & ZIP_DIRENT_ATTRIBUTES) == 0 && (attributes->valid & ZIP_FILE_ATTRIBUTES_HOST_SYSTEM)) {
|
||||
version_madeby = (version_madeby & 0xff) | (zip_uint16_t)(attributes->host_system << 8);
|
||||
}
|
||||
if (de->version_madeby != version_madeby) {
|
||||
de->version_madeby = version_madeby;
|
||||
has_changed = true;
|
||||
}
|
||||
|
||||
return has_changed;
|
||||
}
|
||||
|
||||
|
||||
@@ -1259,13 +1321,36 @@ zip_dirent_torrentzip_normalize(zip_dirent_t *de) {
|
||||
|
||||
int
|
||||
zip_dirent_check_consistency(zip_dirent_t *dirent) {
|
||||
if (dirent->comp_method == ZIP_CM_STORE && dirent->comp_size != dirent->uncomp_size) {
|
||||
return ZIP_ER_DETAIL_STORED_SIZE_MISMATCH;
|
||||
if (dirent->comp_method == ZIP_CM_STORE) {
|
||||
zip_uint64_t header_size = 0;
|
||||
switch (dirent->encryption_method) {
|
||||
case ZIP_EM_NONE:
|
||||
break;
|
||||
case ZIP_EM_TRAD_PKWARE:
|
||||
header_size = 12;
|
||||
break;
|
||||
case ZIP_EM_AES_128:
|
||||
header_size = 20;
|
||||
break;
|
||||
case ZIP_EM_AES_192:
|
||||
header_size = 24;
|
||||
break;
|
||||
case ZIP_EM_AES_256:
|
||||
header_size = 28;
|
||||
break;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
if (dirent->uncomp_size + header_size < dirent->uncomp_size || dirent->comp_size != dirent->uncomp_size + header_size) {
|
||||
return ZIP_ER_DETAIL_STORED_SIZE_MISMATCH;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
time_t zip_dirent_get_last_mod_mtime(zip_dirent_t *de) {
|
||||
time_t
|
||||
zip_dirent_get_last_mod_mtime(zip_dirent_t *de) {
|
||||
if (!de->last_mod_mtime_valid) {
|
||||
de->last_mod_mtime = _zip_d2u_time(&de->last_mod);
|
||||
de->last_mod_mtime_valid = true;
|
||||
|
||||
3
3rdparty/libzip/lib/zip_fclose.c
vendored
3
3rdparty/libzip/lib/zip_fclose.c
vendored
@@ -41,6 +41,9 @@ ZIP_EXTERN int
|
||||
zip_fclose(zip_file_t *zf) {
|
||||
int ret;
|
||||
|
||||
if (zf == NULL)
|
||||
return ZIP_ER_INVAL;
|
||||
|
||||
if (zf->src)
|
||||
zip_source_free(zf->src);
|
||||
|
||||
|
||||
71
3rdparty/libzip/lib/zip_file_set_encryption.c
vendored
71
3rdparty/libzip/lib/zip_file_set_encryption.c
vendored
@@ -40,7 +40,7 @@
|
||||
ZIP_EXTERN int
|
||||
zip_file_set_encryption(zip_t *za, zip_uint64_t idx, zip_uint16_t method, const char *password) {
|
||||
zip_entry_t *e;
|
||||
zip_uint16_t old_method;
|
||||
char *our_password = NULL;
|
||||
|
||||
if (idx >= za->nentry) {
|
||||
zip_error_set(&za->error, ZIP_ER_INVAL, 0);
|
||||
@@ -63,56 +63,33 @@ zip_file_set_encryption(zip_t *za, zip_uint64_t idx, zip_uint16_t method, const
|
||||
|
||||
e = za->entry + idx;
|
||||
|
||||
old_method = (e->orig == NULL ? ZIP_EM_NONE : e->orig->encryption_method);
|
||||
|
||||
if (method == old_method && password == NULL) {
|
||||
if (e->changes) {
|
||||
if (e->changes->changed & ZIP_DIRENT_PASSWORD) {
|
||||
_zip_crypto_clear(e->changes->password, strlen(e->changes->password));
|
||||
free(e->changes->password);
|
||||
e->changes->password = (e->orig == NULL ? NULL : e->orig->password);
|
||||
}
|
||||
e->changes->changed &= ~(ZIP_DIRENT_ENCRYPTION_METHOD | ZIP_DIRENT_PASSWORD);
|
||||
if (e->changes->changed == 0) {
|
||||
_zip_dirent_free(e->changes);
|
||||
e->changes = NULL;
|
||||
}
|
||||
if (e->changes == NULL) {
|
||||
if ((e->changes = _zip_dirent_clone(e->orig)) == NULL) {
|
||||
zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (password) {
|
||||
if ((our_password = strdup(password)) == NULL) {
|
||||
zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
e->changes->encryption_method = method;
|
||||
e->changes->changed |= ZIP_DIRENT_ENCRYPTION_METHOD;
|
||||
if (password) {
|
||||
e->changes->password = our_password;
|
||||
e->changes->changed |= ZIP_DIRENT_PASSWORD;
|
||||
}
|
||||
else {
|
||||
char *our_password = NULL;
|
||||
|
||||
if (password) {
|
||||
if ((our_password = strdup(password)) == NULL) {
|
||||
zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (e->changes == NULL) {
|
||||
if ((e->changes = _zip_dirent_clone(e->orig)) == NULL) {
|
||||
if (our_password) {
|
||||
_zip_crypto_clear(our_password, strlen(our_password));
|
||||
}
|
||||
free(our_password);
|
||||
zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
e->changes->encryption_method = method;
|
||||
e->changes->changed |= ZIP_DIRENT_ENCRYPTION_METHOD;
|
||||
if (password) {
|
||||
e->changes->password = our_password;
|
||||
e->changes->changed |= ZIP_DIRENT_PASSWORD;
|
||||
}
|
||||
else {
|
||||
if (e->changes->changed & ZIP_DIRENT_PASSWORD) {
|
||||
_zip_crypto_clear(e->changes->password, strlen(e->changes->password));
|
||||
free(e->changes->password);
|
||||
e->changes->password = e->orig ? e->orig->password : NULL;
|
||||
e->changes->changed &= ~ZIP_DIRENT_PASSWORD;
|
||||
}
|
||||
if (e->changes->changed & ZIP_DIRENT_PASSWORD) {
|
||||
_zip_crypto_clear(e->changes->password, strlen(e->changes->password));
|
||||
free(e->changes->password);
|
||||
e->changes->password = e->orig ? e->orig->password : NULL;
|
||||
e->changes->changed &= ~ZIP_DIRENT_PASSWORD;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
2
3rdparty/libzip/lib/zip_open.c
vendored
2
3rdparty/libzip/lib/zip_open.c
vendored
@@ -207,7 +207,7 @@ _zip_open(zip_source_t *src, unsigned int flags, zip_error_t *error) {
|
||||
|
||||
if ((cdir = _zip_find_central_dir(za, len)) == NULL) {
|
||||
_zip_error_copy(error, &za->error);
|
||||
if (zip_error_code_zip(error) == ZIP_ER_NOZIP) {
|
||||
if (zip_error_code_zip(&za->error) == ZIP_ER_NOZIP) {
|
||||
/* not a zip - find out if it's truncated */
|
||||
if (_is_truncated_zip(src)) {
|
||||
zip_error_set(error, ZIP_ER_TRUNCATED_ZIP, 0);
|
||||
|
||||
62
3rdparty/libzip/lib/zip_realloc.c
vendored
Normal file
62
3rdparty/libzip/lib/zip_realloc.c
vendored
Normal file
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
zip_realloc.c -- reallocate with additional elements
|
||||
Copyright (C) 2009-2025 Dieter Baron and Thomas Klausner
|
||||
|
||||
This file is part of libzip, a library to manipulate ZIP archives.
|
||||
The authors can be contacted at <info@libzip.org>
|
||||
|
||||
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.
|
||||
3. The names of the authors may not be used to endorse or promote
|
||||
products derived from this software without specific prior
|
||||
written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``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 AUTHORS 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.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "zipint.h"
|
||||
|
||||
bool zip_realloc(void **memory, zip_uint64_t *alloced_elements, zip_uint64_t element_size, zip_uint64_t additional_elements, zip_error_t *error) {
|
||||
zip_uint64_t new_alloced_elements;
|
||||
void *new_memory;
|
||||
|
||||
if (additional_elements == 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
new_alloced_elements = *alloced_elements + additional_elements;
|
||||
|
||||
if (new_alloced_elements < additional_elements || new_alloced_elements > SIZE_MAX / element_size) {
|
||||
zip_error_set(error, ZIP_ER_MEMORY, 0);
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((new_memory = realloc(*memory, (size_t)(new_alloced_elements * element_size))) == NULL) {
|
||||
zip_error_set(error, ZIP_ER_MEMORY, 0);
|
||||
return false;
|
||||
}
|
||||
|
||||
*memory = new_memory;
|
||||
*alloced_elements = new_alloced_elements;
|
||||
|
||||
return true;
|
||||
}
|
||||
29
3rdparty/libzip/lib/zip_set_file_compression.c
vendored
29
3rdparty/libzip/lib/zip_set_file_compression.c
vendored
@@ -38,7 +38,6 @@
|
||||
ZIP_EXTERN int
|
||||
zip_set_file_compression(zip_t *za, zip_uint64_t idx, zip_int32_t method, zip_uint32_t flags) {
|
||||
zip_entry_t *e;
|
||||
zip_int32_t old_method;
|
||||
|
||||
if (idx >= za->nentry) {
|
||||
zip_error_set(&za->error, ZIP_ER_INVAL, 0);
|
||||
@@ -61,35 +60,21 @@ zip_set_file_compression(zip_t *za, zip_uint64_t idx, zip_int32_t method, zip_ui
|
||||
|
||||
e = za->entry + idx;
|
||||
|
||||
old_method = (e->orig == NULL ? ZIP_CM_DEFAULT : e->orig->comp_method);
|
||||
|
||||
/* TODO: do we want to recompress if level is set? Only if it's
|
||||
* different than what bit flags tell us, but those are not
|
||||
* defined for all compression methods, or not directly mappable
|
||||
* to levels */
|
||||
|
||||
if (method == old_method) {
|
||||
if (e->changes) {
|
||||
e->changes->changed &= ~ZIP_DIRENT_COMP_METHOD;
|
||||
e->changes->compression_level = 0;
|
||||
if (e->changes->changed == 0) {
|
||||
_zip_dirent_free(e->changes);
|
||||
e->changes = NULL;
|
||||
}
|
||||
if (e->changes == NULL) {
|
||||
if ((e->changes = _zip_dirent_clone(e->orig)) == NULL) {
|
||||
zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (e->changes == NULL) {
|
||||
if ((e->changes = _zip_dirent_clone(e->orig)) == NULL) {
|
||||
zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
e->changes->comp_method = method;
|
||||
e->changes->compression_level = (zip_uint16_t)flags;
|
||||
e->changes->changed |= ZIP_DIRENT_COMP_METHOD;
|
||||
}
|
||||
e->changes->comp_method = method;
|
||||
e->changes->compression_level = (zip_uint16_t)flags;
|
||||
e->changes->changed |= ZIP_DIRENT_COMP_METHOD;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
26
3rdparty/libzip/lib/zip_source_buffer.c
vendored
26
3rdparty/libzip/lib/zip_source_buffer.c
vendored
@@ -340,6 +340,7 @@ buffer_clone(buffer_t *buffer, zip_uint64_t offset, zip_error_t *error) {
|
||||
fragment_offset = offset - buffer->fragment_offsets[fragment];
|
||||
|
||||
if (fragment_offset == 0) {
|
||||
/* We can't be at beginning of fragment zero if offset > 0. */
|
||||
fragment--;
|
||||
fragment_offset = buffer->fragments[fragment].length;
|
||||
}
|
||||
@@ -427,32 +428,23 @@ buffer_free(buffer_t *buffer) {
|
||||
|
||||
static bool
|
||||
buffer_grow_fragments(buffer_t *buffer, zip_uint64_t capacity, zip_error_t *error) {
|
||||
zip_buffer_fragment_t *fragments;
|
||||
zip_uint64_t *offsets;
|
||||
zip_uint64_t additional_fragments;
|
||||
zip_uint64_t offset_capacity = buffer->fragments_capacity + 1;
|
||||
|
||||
if (capacity < buffer->fragments_capacity) {
|
||||
if (capacity <= buffer->fragments_capacity) {
|
||||
return true;
|
||||
}
|
||||
|
||||
zip_uint64_t fragments_size = sizeof(buffer->fragments[0]) * capacity;
|
||||
zip_uint64_t offsets_size = sizeof(buffer->fragment_offsets[0]) * (capacity + 1);
|
||||
additional_fragments = capacity - buffer->fragments_capacity;
|
||||
|
||||
if (capacity == ZIP_UINT64_MAX || fragments_size < capacity || fragments_size > SIZE_MAX|| offsets_size < capacity || offsets_size > SIZE_MAX) {
|
||||
zip_error_set(error, ZIP_ER_MEMORY, 0);
|
||||
if (!ZIP_REALLOC(buffer->fragments, buffer->fragments_capacity, additional_fragments, error)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((fragments = realloc(buffer->fragments, (size_t)fragments_size)) == NULL) {
|
||||
zip_error_set(error, ZIP_ER_MEMORY, 0);
|
||||
/* The size of both buffer->fragments and buffer->fragment_offsets is stored in buffer->fragments_capacity, so use a temporary capacity variable here for reallocating buffer->fragment_offsets. */
|
||||
if (!ZIP_REALLOC(buffer->fragment_offsets, offset_capacity, additional_fragments, error)) {
|
||||
buffer->fragments_capacity -= additional_fragments;
|
||||
return false;
|
||||
}
|
||||
buffer->fragments = fragments;
|
||||
if ((offsets = realloc(buffer->fragment_offsets, (size_t)offsets_size)) == NULL) {
|
||||
zip_error_set(error, ZIP_ER_MEMORY, 0);
|
||||
return false;
|
||||
}
|
||||
buffer->fragment_offsets = offsets;
|
||||
buffer->fragments_capacity = capacity;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
39
3rdparty/libzip/lib/zip_source_compress.c
vendored
39
3rdparty/libzip/lib/zip_source_compress.c
vendored
@@ -44,6 +44,7 @@ struct context {
|
||||
bool can_store;
|
||||
bool is_stored; /* only valid if end_of_stream is true */
|
||||
bool compress;
|
||||
bool check_consistency;
|
||||
zip_int32_t method;
|
||||
|
||||
zip_uint64_t size;
|
||||
@@ -86,11 +87,10 @@ static size_t implementations_size = sizeof(implementations) / sizeof(implementa
|
||||
static zip_source_t *compression_source_new(zip_t *za, zip_source_t *src, zip_int32_t method, bool compress, zip_uint32_t compression_flags);
|
||||
static zip_int64_t compress_callback(zip_source_t *, void *, void *, zip_uint64_t, zip_source_cmd_t);
|
||||
static void context_free(struct context *ctx);
|
||||
static struct context *context_new(zip_int32_t method, bool compress, zip_uint32_t compression_flags, zip_compression_algorithm_t *algorithm);
|
||||
static struct context *context_new(zip_int32_t method, bool compress, zip_uint32_t compression_flags, zip_compression_algorithm_t *algorithm, bool check_consistency);
|
||||
static zip_int64_t compress_read(zip_source_t *, struct context *, void *, zip_uint64_t);
|
||||
|
||||
zip_compression_algorithm_t *
|
||||
_zip_get_compression_algorithm(zip_int32_t method, bool compress) {
|
||||
zip_compression_algorithm_t *_zip_get_compression_algorithm(zip_int32_t method, bool compress) {
|
||||
size_t i;
|
||||
zip_uint16_t real_method = ZIP_CM_ACTUAL(method);
|
||||
|
||||
@@ -108,16 +108,14 @@ _zip_get_compression_algorithm(zip_int32_t method, bool compress) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ZIP_EXTERN int
|
||||
zip_compression_method_supported(zip_int32_t method, int compress) {
|
||||
ZIP_EXTERN int zip_compression_method_supported(zip_int32_t method, int compress) {
|
||||
if (method == ZIP_CM_STORE) {
|
||||
return 1;
|
||||
}
|
||||
return _zip_get_compression_algorithm(method, compress) != NULL;
|
||||
}
|
||||
|
||||
zip_source_t *
|
||||
zip_source_compress(zip_t *za, zip_source_t *src, zip_int32_t method, zip_uint32_t compression_flags) {
|
||||
zip_source_t *zip_source_compress(zip_t *za, zip_source_t *src, zip_int32_t method, zip_uint32_t compression_flags) {
|
||||
return compression_source_new(za, src, method, true, compression_flags);
|
||||
}
|
||||
|
||||
@@ -127,8 +125,7 @@ zip_source_decompress(zip_t *za, zip_source_t *src, zip_int32_t method) {
|
||||
}
|
||||
|
||||
|
||||
static zip_source_t *
|
||||
compression_source_new(zip_t *za, zip_source_t *src, zip_int32_t method, bool compress, zip_uint32_t compression_flags) {
|
||||
static zip_source_t *compression_source_new(zip_t *za, zip_source_t *src, zip_int32_t method, bool compress, zip_uint32_t compression_flags) {
|
||||
struct context *ctx;
|
||||
zip_source_t *s2;
|
||||
zip_compression_algorithm_t *algorithm = NULL;
|
||||
@@ -143,7 +140,7 @@ compression_source_new(zip_t *za, zip_source_t *src, zip_int32_t method, bool co
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ((ctx = context_new(method, compress, compression_flags, algorithm)) == NULL) {
|
||||
if ((ctx = context_new(method, compress, compression_flags, algorithm, za->open_flags & ZIP_CHECKCONS)) == NULL) {
|
||||
zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
|
||||
return NULL;
|
||||
}
|
||||
@@ -157,8 +154,7 @@ compression_source_new(zip_t *za, zip_source_t *src, zip_int32_t method, bool co
|
||||
}
|
||||
|
||||
|
||||
static struct context *
|
||||
context_new(zip_int32_t method, bool compress, zip_uint32_t compression_flags, zip_compression_algorithm_t *algorithm) {
|
||||
static struct context *context_new(zip_int32_t method, bool compress, zip_uint32_t compression_flags, zip_compression_algorithm_t *algorithm, bool check_consistency) {
|
||||
struct context *ctx;
|
||||
|
||||
if ((ctx = (struct context *)malloc(sizeof(*ctx))) == NULL) {
|
||||
@@ -172,6 +168,7 @@ context_new(zip_int32_t method, bool compress, zip_uint32_t compression_flags, z
|
||||
ctx->end_of_input = false;
|
||||
ctx->end_of_stream = false;
|
||||
ctx->is_stored = false;
|
||||
ctx->check_consistency = check_consistency;
|
||||
|
||||
if ((ctx->ud = ctx->algorithm->allocate(ZIP_CM_ACTUAL(method), compression_flags, &ctx->error)) == NULL) {
|
||||
zip_error_fini(&ctx->error);
|
||||
@@ -228,7 +225,23 @@ compress_read(zip_source_t *src, struct context *ctx, void *data, zip_uint64_t l
|
||||
ctx->end_of_stream = true;
|
||||
|
||||
if (!ctx->end_of_input) {
|
||||
/* TODO: garbage after stream, or compression ended before all data read */
|
||||
n = zip_source_read(src, ctx->buffer, 1);
|
||||
if (n < 0) {
|
||||
zip_error_set_from_source(&ctx->error, src);
|
||||
end = true;
|
||||
break;
|
||||
}
|
||||
else if (n == 0) {
|
||||
ctx->end_of_input = true;
|
||||
n = ctx->algorithm->end_of_input(ctx->ud) ? 1 : 0;
|
||||
}
|
||||
|
||||
if (n > 0 && ctx->check_consistency) {
|
||||
/* garbage after stream, or compression ended before all data read */
|
||||
zip_error_set(&ctx->error, ZIP_ER_INCONS, ZIP_ER_DETAIL_COMPRESSED_DATA_TRAILING_GARBAGE);
|
||||
end = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (ctx->first_read < 0) {
|
||||
|
||||
2
3rdparty/libzip/lib/zip_source_file_stdio.c
vendored
2
3rdparty/libzip/lib/zip_source_file_stdio.c
vendored
@@ -95,9 +95,11 @@ _zip_stdio_op_close(zip_source_file_context_t *ctx) {
|
||||
zip_int64_t
|
||||
_zip_stdio_op_read(zip_source_file_context_t *ctx, void *buf, zip_uint64_t len) {
|
||||
size_t i;
|
||||
#if SIZE_MAX < ZIP_UINT64_MAX
|
||||
if (len > SIZE_MAX) {
|
||||
len = SIZE_MAX;
|
||||
}
|
||||
#endif
|
||||
|
||||
if ((i = fread(buf, 1, (size_t)len, ctx->f)) == 0) {
|
||||
if (ferror((FILE *)ctx->f)) {
|
||||
|
||||
@@ -33,13 +33,6 @@
|
||||
|
||||
#include "zip_source_file_win32.h"
|
||||
|
||||
/* ACL is not available when targeting the games API partition */
|
||||
#if defined(WINAPI_FAMILY_PARTITION) && defined(WINAPI_PARTITION_GAMES)
|
||||
#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_GAMES)
|
||||
#define ACL_UNSUPPORTED
|
||||
#endif
|
||||
#endif
|
||||
|
||||
static zip_int64_t _zip_win32_named_op_commit_write(zip_source_file_context_t *ctx);
|
||||
static zip_int64_t _zip_win32_named_op_create_temp_output(zip_source_file_context_t *ctx);
|
||||
static bool _zip_win32_named_op_open(zip_source_file_context_t *ctx);
|
||||
@@ -106,29 +99,24 @@ _zip_win32_named_op_create_temp_output(zip_source_file_context_t *ctx) {
|
||||
|
||||
zip_uint32_t value, i;
|
||||
HANDLE th = INVALID_HANDLE_VALUE;
|
||||
PSECURITY_DESCRIPTOR psd = NULL;
|
||||
PSECURITY_ATTRIBUTES psa = NULL;
|
||||
PSECURITY_DESCRIPTOR psd = NULL;
|
||||
#ifdef HAVE_GETSECURITYINFO
|
||||
SECURITY_ATTRIBUTES sa;
|
||||
SECURITY_INFORMATION si;
|
||||
DWORD success;
|
||||
PACL dacl = NULL;
|
||||
#endif
|
||||
char *tempname = NULL;
|
||||
size_t tempname_size = 0;
|
||||
|
||||
#ifdef HAVE_GETSECURITYINFO
|
||||
if ((HANDLE)ctx->f != INVALID_HANDLE_VALUE && GetFileType((HANDLE)ctx->f) == FILE_TYPE_DISK) {
|
||||
si = DACL_SECURITY_INFORMATION | UNPROTECTED_DACL_SECURITY_INFORMATION;
|
||||
#ifdef ACL_UNSUPPORTED
|
||||
success = ERROR_NOT_SUPPORTED;
|
||||
#else
|
||||
success = GetSecurityInfo((HANDLE)ctx->f, SE_FILE_OBJECT, si, NULL, NULL, &dacl, NULL, &psd);
|
||||
#endif
|
||||
if (success == ERROR_SUCCESS) {
|
||||
if (GetSecurityInfo((HANDLE)ctx->f, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION | UNPROTECTED_DACL_SECURITY_INFORMATION, NULL, NULL, NULL, NULL, &psd) == ERROR_SUCCESS) {
|
||||
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
|
||||
sa.bInheritHandle = FALSE;
|
||||
sa.lpSecurityDescriptor = psd;
|
||||
psa = &sa;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef MS_UWP
|
||||
value = GetTickCount();
|
||||
|
||||
@@ -39,8 +39,7 @@ zip_file_attributes_init(zip_file_attributes_t *attributes) {
|
||||
attributes->version = 1;
|
||||
}
|
||||
|
||||
int
|
||||
zip_source_get_file_attributes(zip_source_t *src, zip_file_attributes_t *attributes) {
|
||||
int zip_source_get_file_attributes(zip_source_t *src, zip_file_attributes_t *attributes) {
|
||||
if (src->source_closed) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -198,8 +198,10 @@ pkware_encrypt(zip_source_t *src, void *ud, void *data, zip_uint64_t length, zip
|
||||
zip_error_set(&ctx->error, ZIP_ER_INVAL, 0);
|
||||
return -1;
|
||||
}
|
||||
attributes->valid |= ZIP_FILE_ATTRIBUTES_VERSION_NEEDED;
|
||||
attributes->valid |= ZIP_FILE_ATTRIBUTES_VERSION_NEEDED | ZIP_FILE_ATTRIBUTES_GENERAL_PURPOSE_BIT_FLAGS;
|
||||
attributes->version_needed = 20;
|
||||
attributes->general_purpose_bit_flags = ZIP_GPBF_DATA_DESCRIPTOR;
|
||||
attributes->general_purpose_bit_mask = ZIP_GPBF_DATA_DESCRIPTOR;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
12
3rdparty/libzip/lib/zip_source_window.c
vendored
12
3rdparty/libzip/lib/zip_source_window.c
vendored
@@ -345,7 +345,7 @@ window_read(zip_source_t *src, void *_ctx, void *data, zip_uint64_t len, zip_sou
|
||||
|
||||
void
|
||||
_zip_deregister_source(zip_t *za, zip_source_t *src) {
|
||||
unsigned int i;
|
||||
zip_uint64_t i;
|
||||
|
||||
for (i = 0; i < za->nopen_source; i++) {
|
||||
if (za->open_source[i] == src) {
|
||||
@@ -359,18 +359,10 @@ _zip_deregister_source(zip_t *za, zip_source_t *src) {
|
||||
|
||||
int
|
||||
_zip_register_source(zip_t *za, zip_source_t *src) {
|
||||
zip_source_t **open_source;
|
||||
|
||||
if (za->nopen_source + 1 >= za->nopen_source_alloc) {
|
||||
unsigned int n;
|
||||
n = za->nopen_source_alloc + 10;
|
||||
open_source = (zip_source_t **)realloc(za->open_source, n * sizeof(zip_source_t *));
|
||||
if (open_source == NULL) {
|
||||
zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
|
||||
if (!ZIP_REALLOC(za->open_source, za->nopen_source_alloc, 10, &za->error)) {
|
||||
return -1;
|
||||
}
|
||||
za->nopen_source_alloc = n;
|
||||
za->open_source = open_source;
|
||||
}
|
||||
|
||||
za->open_source[za->nopen_source++] = src;
|
||||
|
||||
17
3rdparty/libzip/lib/zipint.h
vendored
17
3rdparty/libzip/lib/zipint.h
vendored
@@ -102,11 +102,14 @@
|
||||
/* according to unzip-6.0's zipinfo.c, this corresponds to a directory with rwx permissions for everyone */
|
||||
#define ZIP_EXT_ATTRIB_DEFAULT_DIR (0040777u << 16)
|
||||
|
||||
#define ZIP_FILE_ATTRIBUTES_GENERAL_PURPOSE_BIT_FLAGS_ALLOWED_MASK 0x0836
|
||||
/* Allowed: Encryption specific bits, data descriptor, compression specific, UTF-8 filename */
|
||||
#define ZIP_FILE_ATTRIBUTES_GENERAL_PURPOSE_BIT_FLAGS_ALLOWED_MASK 0x083e
|
||||
|
||||
#define ZIP_MAX(a, b) ((a) > (b) ? (a) : (b))
|
||||
#define ZIP_MIN(a, b) ((a) < (b) ? (a) : (b))
|
||||
|
||||
#define ZIP_REALLOC(memory, alloced_elements, additional_elements, error) zip_realloc((void **)&memory, &alloced_elements, sizeof(*memory), additional_elements, error)
|
||||
|
||||
/* This section contains API that won't materialize like this. It's
|
||||
placed in the internal section, pending cleanup. */
|
||||
|
||||
@@ -152,7 +155,7 @@ struct zip_compression_algorithm {
|
||||
bool (*input)(void *ctx, zip_uint8_t *data, zip_uint64_t length);
|
||||
|
||||
/* all input data has been provided */
|
||||
void (*end_of_input)(void *ctx);
|
||||
bool (*end_of_input)(void *ctx);
|
||||
|
||||
/* process input data, writing to data, which has room for length bytes, update length to number of bytes written */
|
||||
zip_compression_status_t (*process)(void *ctx, zip_uint8_t *data, zip_uint64_t *length);
|
||||
@@ -241,6 +244,7 @@ extern const int _zip_err_details_count;
|
||||
#define ZIP_ER_DETAIL_EOCD64_LOCATOR_MISMATCH 22 /* G EOCD64 and EOCD64 locator do not match */
|
||||
#define ZIP_ER_DETAIL_UTF8_FILENAME_MISMATCH 23 /* E UTF-8 filename is ASCII and doesn't match filename */
|
||||
#define ZIP_ER_DETAIL_UTF8_COMMENT_MISMATCH 24 /* E UTF-8 comment is ASCII and doesn't match comment */
|
||||
#define ZIP_ER_DETAIL_COMPRESSED_DATA_TRAILING_GARBAGE 25 /* G garbage at end of compressed data */
|
||||
|
||||
/* directory entry: general purpose bit flags */
|
||||
|
||||
@@ -305,8 +309,8 @@ struct zip {
|
||||
zip_uint64_t nentry_alloc; /* number of entries allocated */
|
||||
zip_entry_t *entry; /* entries */
|
||||
|
||||
unsigned int nopen_source; /* number of open sources using archive */
|
||||
unsigned int nopen_source_alloc; /* number of sources allocated */
|
||||
zip_uint64_t nopen_source; /* number of open sources using archive */
|
||||
zip_uint64_t nopen_source_alloc; /* number of sources allocated */
|
||||
zip_source_t **open_source; /* open sources using archive */
|
||||
|
||||
zip_hash_t *names; /* hash table for name lookup */
|
||||
@@ -552,13 +556,14 @@ zip_int64_t _zip_cdir_write(zip_t *za, const zip_filelist_t *filelist, zip_uint6
|
||||
time_t _zip_d2u_time(const zip_dostime_t*);
|
||||
void _zip_deregister_source(zip_t *za, zip_source_t *src);
|
||||
|
||||
void _zip_dirent_apply_attributes(zip_dirent_t *, zip_file_attributes_t *, bool, zip_uint32_t);
|
||||
bool _zip_dirent_apply_attributes(zip_dirent_t *, zip_file_attributes_t *, bool);
|
||||
int zip_dirent_check_consistency(zip_dirent_t *dirent);
|
||||
zip_dirent_t *_zip_dirent_clone(const zip_dirent_t *);
|
||||
void _zip_dirent_free(zip_dirent_t *);
|
||||
void _zip_dirent_finalize(zip_dirent_t *);
|
||||
time_t zip_dirent_get_last_mod_mtime(zip_dirent_t *de);
|
||||
void _zip_dirent_init(zip_dirent_t *);
|
||||
bool _zip_dirent_merge(zip_dirent_t *de, zip_dirent_t *de_orig, bool replacing_data, zip_error_t *error);
|
||||
bool _zip_dirent_needs_zip64(const zip_dirent_t *, zip_flags_t);
|
||||
zip_dirent_t *_zip_dirent_new(void);
|
||||
bool zip_dirent_process_ef_zip64(zip_dirent_t * zde, const zip_uint8_t * ef, zip_uint64_t got_len, bool local, zip_error_t * error);
|
||||
@@ -618,6 +623,8 @@ int _zip_progress_start(zip_progress_t *progress);
|
||||
int _zip_progress_subrange(zip_progress_t *progress, double start, double end);
|
||||
int _zip_progress_update(zip_progress_t *progress, double value);
|
||||
|
||||
bool zip_realloc(void **memory, zip_uint64_t *alloced_elements, zip_uint64_t element_size, zip_uint64_t additional_elements, zip_error_t *error);
|
||||
|
||||
/* this symbol is extern so it can be overridden for regression testing */
|
||||
ZIP_EXTERN bool zip_secure_random(zip_uint8_t *buffer, zip_uint16_t length);
|
||||
zip_uint32_t zip_random_uint32(void);
|
||||
|
||||
1
3rdparty/libzip/libzip.vcxproj
vendored
1
3rdparty/libzip/libzip.vcxproj
vendored
@@ -86,6 +86,7 @@
|
||||
<ClCompile Include="lib\zip_name_locate.c" />
|
||||
<ClCompile Include="lib\zip_new.c" />
|
||||
<ClCompile Include="lib\zip_open.c" />
|
||||
<ClCompile Include="lib\zip_realloc.c" />
|
||||
<ClCompile Include="lib\zip_pkware.c" />
|
||||
<ClCompile Include="lib\zip_progress.c" />
|
||||
<ClCompile Include="lib\zip_random_win32.c" />
|
||||
|
||||
10
3rdparty/lzma/include/7zVersion.h
vendored
10
3rdparty/lzma/include/7zVersion.h
vendored
@@ -1,7 +1,7 @@
|
||||
#define MY_VER_MAJOR 24
|
||||
#define MY_VER_MINOR 8
|
||||
#define MY_VER_MAJOR 25
|
||||
#define MY_VER_MINOR 0
|
||||
#define MY_VER_BUILD 0
|
||||
#define MY_VERSION_NUMBERS "24.08"
|
||||
#define MY_VERSION_NUMBERS "25.00"
|
||||
#define MY_VERSION MY_VERSION_NUMBERS
|
||||
|
||||
#ifdef MY_CPU_NAME
|
||||
@@ -10,12 +10,12 @@
|
||||
#define MY_VERSION_CPU MY_VERSION
|
||||
#endif
|
||||
|
||||
#define MY_DATE "2024-08-11"
|
||||
#define MY_DATE "2025-07-05"
|
||||
#undef MY_COPYRIGHT
|
||||
#undef MY_VERSION_COPYRIGHT_DATE
|
||||
#define MY_AUTHOR_NAME "Igor Pavlov"
|
||||
#define MY_COPYRIGHT_PD "Igor Pavlov : Public domain"
|
||||
#define MY_COPYRIGHT_CR "Copyright (c) 1999-2024 Igor Pavlov"
|
||||
#define MY_COPYRIGHT_CR "Copyright (c) 1999-2025 Igor Pavlov"
|
||||
|
||||
#ifdef USE_COPYRIGHT_CR
|
||||
#define MY_COPYRIGHT MY_COPYRIGHT_CR
|
||||
|
||||
12
3rdparty/lzma/include/Compiler.h
vendored
12
3rdparty/lzma/include/Compiler.h
vendored
@@ -1,5 +1,5 @@
|
||||
/* Compiler.h : Compiler specific defines and pragmas
|
||||
2024-01-22 : Igor Pavlov : Public domain */
|
||||
: Igor Pavlov : Public domain */
|
||||
|
||||
#ifndef ZIP7_INC_COMPILER_H
|
||||
#define ZIP7_INC_COMPILER_H
|
||||
@@ -183,6 +183,16 @@ typedef void (*Z7_void_Function)(void);
|
||||
#define Z7_ATTRIB_NO_VECTORIZE
|
||||
#endif
|
||||
|
||||
#if defined(Z7_MSC_VER_ORIGINAL) && (Z7_MSC_VER_ORIGINAL >= 1920)
|
||||
#define Z7_PRAGMA_OPTIMIZE_FOR_CODE_SIZE _Pragma("optimize ( \"s\", on )")
|
||||
#define Z7_PRAGMA_OPTIMIZE_DEFAULT _Pragma("optimize ( \"\", on )")
|
||||
#else
|
||||
#define Z7_PRAGMA_OPTIMIZE_FOR_CODE_SIZE
|
||||
#define Z7_PRAGMA_OPTIMIZE_DEFAULT
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#if defined(MY_CPU_X86_OR_AMD64) && ( \
|
||||
defined(__clang__) && (__clang_major__ >= 4) \
|
||||
|| defined(__GNUC__) && (__GNUC__ >= 5))
|
||||
|
||||
41
3rdparty/lzma/include/CpuArch.h
vendored
41
3rdparty/lzma/include/CpuArch.h
vendored
@@ -1,5 +1,5 @@
|
||||
/* CpuArch.h -- CPU specific code
|
||||
2024-06-17 : Igor Pavlov : Public domain */
|
||||
Igor Pavlov : Public domain */
|
||||
|
||||
#ifndef ZIP7_INC_CPU_ARCH_H
|
||||
#define ZIP7_INC_CPU_ARCH_H
|
||||
@@ -47,6 +47,12 @@ MY_CPU_64BIT means that processor can work with 64-bit registers.
|
||||
#define MY_CPU_SIZEOF_POINTER 4
|
||||
#endif
|
||||
|
||||
#if defined(__SSE2__) \
|
||||
|| defined(MY_CPU_AMD64) \
|
||||
|| defined(_M_IX86_FP) && (_M_IX86_FP >= 2)
|
||||
#define MY_CPU_SSE2
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(_M_ARM64) \
|
||||
|| defined(_M_ARM64EC) \
|
||||
@@ -509,11 +515,19 @@ problem-4 : performace:
|
||||
|
||||
#if defined(MY_CPU_LE_UNALIGN) && defined(Z7_CPU_FAST_BSWAP_SUPPORTED)
|
||||
|
||||
#if 0
|
||||
// Z7_BSWAP16 can be slow for x86-msvc
|
||||
#define GetBe16_to32(p) (Z7_BSWAP16 (*(const UInt16 *)(const void *)(p)))
|
||||
#else
|
||||
#define GetBe16_to32(p) (Z7_BSWAP32 (*(const UInt16 *)(const void *)(p)) >> 16)
|
||||
#endif
|
||||
|
||||
#define GetBe32(p) Z7_BSWAP32 (*(const UInt32 *)(const void *)(p))
|
||||
#define SetBe32(p, v) { (*(UInt32 *)(void *)(p)) = Z7_BSWAP32(v); }
|
||||
|
||||
#if defined(MY_CPU_LE_UNALIGN_64)
|
||||
#define GetBe64(p) Z7_BSWAP64 (*(const UInt64 *)(const void *)(p))
|
||||
#define SetBe64(p, v) { (*(UInt64 *)(void *)(p)) = Z7_BSWAP64(v); }
|
||||
#endif
|
||||
|
||||
#else
|
||||
@@ -536,21 +550,39 @@ problem-4 : performace:
|
||||
#define GetBe64(p) (((UInt64)GetBe32(p) << 32) | GetBe32(((const Byte *)(p)) + 4))
|
||||
#endif
|
||||
|
||||
#ifndef SetBe64
|
||||
#define SetBe64(p, v) { Byte *_ppp_ = (Byte *)(p); UInt64 _vvv_ = (v); \
|
||||
_ppp_[0] = (Byte)(_vvv_ >> 56); \
|
||||
_ppp_[1] = (Byte)(_vvv_ >> 48); \
|
||||
_ppp_[2] = (Byte)(_vvv_ >> 40); \
|
||||
_ppp_[3] = (Byte)(_vvv_ >> 32); \
|
||||
_ppp_[4] = (Byte)(_vvv_ >> 24); \
|
||||
_ppp_[5] = (Byte)(_vvv_ >> 16); \
|
||||
_ppp_[6] = (Byte)(_vvv_ >> 8); \
|
||||
_ppp_[7] = (Byte)_vvv_; }
|
||||
#endif
|
||||
|
||||
#ifndef GetBe16
|
||||
#ifdef GetBe16_to32
|
||||
#define GetBe16(p) ( (UInt16) GetBe16_to32(p))
|
||||
#else
|
||||
#define GetBe16(p) ( (UInt16) ( \
|
||||
((UInt16)((const Byte *)(p))[0] << 8) | \
|
||||
((const Byte *)(p))[1] ))
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(MY_CPU_BE)
|
||||
#define Z7_CONV_BE_TO_NATIVE_CONST32(v) (v)
|
||||
#define Z7_CONV_LE_TO_NATIVE_CONST32(v) Z7_BSWAP32_CONST(v)
|
||||
#define Z7_CONV_NATIVE_TO_BE_32(v) (v)
|
||||
// #define Z7_GET_NATIVE16_FROM_2_BYTES(b0, b1) ((b1) | ((b0) << 8))
|
||||
#elif defined(MY_CPU_LE)
|
||||
#define Z7_CONV_BE_TO_NATIVE_CONST32(v) Z7_BSWAP32_CONST(v)
|
||||
#define Z7_CONV_LE_TO_NATIVE_CONST32(v) (v)
|
||||
#define Z7_CONV_NATIVE_TO_BE_32(v) Z7_BSWAP32(v)
|
||||
// #define Z7_GET_NATIVE16_FROM_2_BYTES(b0, b1) ((b0) | ((b1) << 8))
|
||||
#else
|
||||
#error Stop_Compiling_Unknown_Endian_CONV
|
||||
#endif
|
||||
@@ -589,6 +621,11 @@ problem-4 : performace:
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef GetBe16_to32
|
||||
#define GetBe16_to32(p) GetBe16(p)
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(MY_CPU_X86_OR_AMD64) \
|
||||
|| defined(MY_CPU_ARM_OR_ARM64) \
|
||||
|| defined(MY_CPU_PPC_OR_PPC64)
|
||||
@@ -617,6 +654,7 @@ BoolInt CPU_IsSupported_SSE2(void);
|
||||
BoolInt CPU_IsSupported_SSSE3(void);
|
||||
BoolInt CPU_IsSupported_SSE41(void);
|
||||
BoolInt CPU_IsSupported_SHA(void);
|
||||
BoolInt CPU_IsSupported_SHA512(void);
|
||||
BoolInt CPU_IsSupported_PageGB(void);
|
||||
|
||||
#elif defined(MY_CPU_ARM_OR_ARM64)
|
||||
@@ -634,6 +672,7 @@ BoolInt CPU_IsSupported_SHA1(void);
|
||||
BoolInt CPU_IsSupported_SHA2(void);
|
||||
BoolInt CPU_IsSupported_AES(void);
|
||||
#endif
|
||||
BoolInt CPU_IsSupported_SHA512(void);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
6
3rdparty/lzma/include/LzFindMt.h
vendored
6
3rdparty/lzma/include/LzFindMt.h
vendored
@@ -1,5 +1,5 @@
|
||||
/* LzFindMt.h -- multithreaded Match finder for LZ algorithms
|
||||
2024-01-22 : Igor Pavlov : Public domain */
|
||||
: Igor Pavlov : Public domain */
|
||||
|
||||
#ifndef ZIP7_INC_LZ_FIND_MT_H
|
||||
#define ZIP7_INC_LZ_FIND_MT_H
|
||||
@@ -12,8 +12,10 @@ EXTERN_C_BEGIN
|
||||
typedef struct
|
||||
{
|
||||
UInt32 numProcessedBlocks;
|
||||
CThread thread;
|
||||
Int32 affinityGroup;
|
||||
UInt64 affinityInGroup;
|
||||
UInt64 affinity;
|
||||
CThread thread;
|
||||
|
||||
BoolInt wasCreated;
|
||||
BoolInt needStart;
|
||||
|
||||
1
3rdparty/lzma/include/Lzma2Enc.h
vendored
1
3rdparty/lzma/include/Lzma2Enc.h
vendored
@@ -18,6 +18,7 @@ typedef struct
|
||||
int numBlockThreads_Reduced;
|
||||
int numBlockThreads_Max;
|
||||
int numTotalThreads;
|
||||
unsigned numThreadGroups; // 0 : no groups
|
||||
} CLzma2EncProps;
|
||||
|
||||
void Lzma2EncProps_Init(CLzma2EncProps *p);
|
||||
|
||||
4
3rdparty/lzma/include/LzmaEnc.h
vendored
4
3rdparty/lzma/include/LzmaEnc.h
vendored
@@ -1,5 +1,5 @@
|
||||
/* LzmaEnc.h -- LZMA Encoder
|
||||
2023-04-13 : Igor Pavlov : Public domain */
|
||||
: Igor Pavlov : Public domain */
|
||||
|
||||
#ifndef ZIP7_INC_LZMA_ENC_H
|
||||
#define ZIP7_INC_LZMA_ENC_H
|
||||
@@ -29,11 +29,13 @@ typedef struct
|
||||
int numThreads; /* 1 or 2, default = 2 */
|
||||
|
||||
// int _pad;
|
||||
Int32 affinityGroup;
|
||||
|
||||
UInt64 reduceSize; /* estimated size of data that will be compressed. default = (UInt64)(Int64)-1.
|
||||
Encoder uses this value to reduce dictionary size */
|
||||
|
||||
UInt64 affinity;
|
||||
UInt64 affinityInGroup;
|
||||
} CLzmaEncProps;
|
||||
|
||||
void LzmaEncProps_Init(CLzmaEncProps *p);
|
||||
|
||||
7
3rdparty/lzma/include/MtCoder.h
vendored
7
3rdparty/lzma/include/MtCoder.h
vendored
@@ -1,5 +1,5 @@
|
||||
/* MtCoder.h -- Multi-thread Coder
|
||||
2023-04-13 : Igor Pavlov : Public domain */
|
||||
: Igor Pavlov : Public domain */
|
||||
|
||||
#ifndef ZIP7_INC_MT_CODER_H
|
||||
#define ZIP7_INC_MT_CODER_H
|
||||
@@ -16,7 +16,7 @@ EXTERN_C_BEGIN
|
||||
|
||||
#ifndef Z7_ST
|
||||
#define MTCODER_GET_NUM_BLOCKS_FROM_THREADS(numThreads) ((numThreads) + (numThreads) / 8 + 1)
|
||||
#define MTCODER_THREADS_MAX 64
|
||||
#define MTCODER_THREADS_MAX 256
|
||||
#define MTCODER_BLOCKS_MAX (MTCODER_GET_NUM_BLOCKS_FROM_THREADS(MTCODER_THREADS_MAX) + 3)
|
||||
#else
|
||||
#define MTCODER_THREADS_MAX 1
|
||||
@@ -77,6 +77,7 @@ typedef struct CMtCoder_
|
||||
|
||||
size_t blockSize; /* size of input block */
|
||||
unsigned numThreadsMax;
|
||||
unsigned numThreadGroups;
|
||||
UInt64 expectedDataSize;
|
||||
|
||||
ISeqInStreamPtr inStream;
|
||||
@@ -125,6 +126,8 @@ typedef struct CMtCoder_
|
||||
CMtProgress mtProgress;
|
||||
CMtCoderBlock blocks[MTCODER_BLOCKS_MAX];
|
||||
CMtCoderThread threads[MTCODER_THREADS_MAX];
|
||||
|
||||
CThreadNextGroup nextGroup;
|
||||
} CMtCoder;
|
||||
|
||||
|
||||
|
||||
18
3rdparty/lzma/include/Sha256.h
vendored
18
3rdparty/lzma/include/Sha256.h
vendored
@@ -1,5 +1,5 @@
|
||||
/* Sha256.h -- SHA-256 Hash
|
||||
2023-04-02 : Igor Pavlov : Public domain */
|
||||
: Igor Pavlov : Public domain */
|
||||
|
||||
#ifndef ZIP7_INC_SHA256_H
|
||||
#define ZIP7_INC_SHA256_H
|
||||
@@ -14,6 +14,9 @@ EXTERN_C_BEGIN
|
||||
#define SHA256_BLOCK_SIZE (SHA256_NUM_BLOCK_WORDS * 4)
|
||||
#define SHA256_DIGEST_SIZE (SHA256_NUM_DIGEST_WORDS * 4)
|
||||
|
||||
|
||||
|
||||
|
||||
typedef void (Z7_FASTCALL *SHA256_FUNC_UPDATE_BLOCKS)(UInt32 state[8], const Byte *data, size_t numBlocks);
|
||||
|
||||
/*
|
||||
@@ -32,9 +35,16 @@ typedef void (Z7_FASTCALL *SHA256_FUNC_UPDATE_BLOCKS)(UInt32 state[8], const Byt
|
||||
|
||||
typedef struct
|
||||
{
|
||||
SHA256_FUNC_UPDATE_BLOCKS func_UpdateBlocks;
|
||||
UInt64 count;
|
||||
UInt64 _pad_2[2];
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
SHA256_FUNC_UPDATE_BLOCKS func_UpdateBlocks;
|
||||
UInt64 count;
|
||||
} vars;
|
||||
UInt64 _pad_64bit[4];
|
||||
void *_pad_align_ptr[2];
|
||||
} v;
|
||||
UInt32 state[SHA256_NUM_DIGEST_WORDS];
|
||||
|
||||
Byte buffer[SHA256_BLOCK_SIZE];
|
||||
|
||||
7
3rdparty/lzma/include/Sort.h
vendored
7
3rdparty/lzma/include/Sort.h
vendored
@@ -1,5 +1,5 @@
|
||||
/* Sort.h -- Sort functions
|
||||
2023-03-05 : Igor Pavlov : Public domain */
|
||||
: Igor Pavlov : Public domain */
|
||||
|
||||
#ifndef ZIP7_INC_SORT_H
|
||||
#define ZIP7_INC_SORT_H
|
||||
@@ -8,10 +8,7 @@
|
||||
|
||||
EXTERN_C_BEGIN
|
||||
|
||||
void HeapSort(UInt32 *p, size_t size);
|
||||
void HeapSort64(UInt64 *p, size_t size);
|
||||
|
||||
/* void HeapSortRef(UInt32 *p, UInt32 *vals, size_t size); */
|
||||
void Z7_FASTCALL HeapSort(UInt32 *p, size_t size);
|
||||
|
||||
EXTERN_C_END
|
||||
|
||||
|
||||
12
3rdparty/lzma/include/Threads.h
vendored
12
3rdparty/lzma/include/Threads.h
vendored
@@ -1,5 +1,5 @@
|
||||
/* Threads.h -- multithreading library
|
||||
2024-03-28 : Igor Pavlov : Public domain */
|
||||
: Igor Pavlov : Public domain */
|
||||
|
||||
#ifndef ZIP7_INC_THREADS_H
|
||||
#define ZIP7_INC_THREADS_H
|
||||
@@ -140,12 +140,22 @@ WRes Thread_Create_With_Affinity(CThread *p, THREAD_FUNC_TYPE func, LPVOID param
|
||||
WRes Thread_Wait_Close(CThread *p);
|
||||
|
||||
#ifdef _WIN32
|
||||
WRes Thread_Create_With_Group(CThread *p, THREAD_FUNC_TYPE func, LPVOID param, unsigned group, CAffinityMask affinityMask);
|
||||
#define Thread_Create_With_CpuSet(p, func, param, cs) \
|
||||
Thread_Create_With_Affinity(p, func, param, *cs)
|
||||
#else
|
||||
WRes Thread_Create_With_CpuSet(CThread *p, THREAD_FUNC_TYPE func, LPVOID param, const CCpuSet *cpuSet);
|
||||
#endif
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned NumGroups;
|
||||
unsigned NextGroup;
|
||||
} CThreadNextGroup;
|
||||
|
||||
void ThreadNextGroup_Init(CThreadNextGroup *p, unsigned numGroups, unsigned startGroup);
|
||||
unsigned ThreadNextGroup_GetNext(CThreadNextGroup *p);
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
|
||||
12
3rdparty/lzma/include/Xz.h
vendored
12
3rdparty/lzma/include/Xz.h
vendored
@@ -1,5 +1,5 @@
|
||||
/* Xz.h - Xz interface
|
||||
2024-01-26 : Igor Pavlov : Public domain */
|
||||
Igor Pavlov : Public domain */
|
||||
|
||||
#ifndef ZIP7_INC_XZ_H
|
||||
#define ZIP7_INC_XZ_H
|
||||
@@ -121,6 +121,7 @@ typedef struct
|
||||
UInt64 startOffset;
|
||||
} CXzStream;
|
||||
|
||||
#define Xz_CONSTRUCT(p) { (p)->numBlocks = 0; (p)->blocks = NULL; (p)->flags = 0; }
|
||||
void Xz_Construct(CXzStream *p);
|
||||
void Xz_Free(CXzStream *p, ISzAllocPtr alloc);
|
||||
|
||||
@@ -136,8 +137,13 @@ typedef struct
|
||||
CXzStream *streams;
|
||||
} CXzs;
|
||||
|
||||
#define Xzs_CONSTRUCT(p) { (p)->num = 0; (p)->numAllocated = 0; (p)->streams = NULL; }
|
||||
void Xzs_Construct(CXzs *p);
|
||||
void Xzs_Free(CXzs *p, ISzAllocPtr alloc);
|
||||
/*
|
||||
Xzs_ReadBackward() must be called for empty CXzs object.
|
||||
Xzs_ReadBackward() can return non empty object with (p->num != 0) even in case of error.
|
||||
*/
|
||||
SRes Xzs_ReadBackward(CXzs *p, ILookInStreamPtr inStream, Int64 *startOffset, ICompressProgressPtr progress, ISzAllocPtr alloc);
|
||||
|
||||
UInt64 Xzs_GetNumBlocks(const CXzs *p);
|
||||
@@ -268,8 +274,8 @@ typedef struct
|
||||
size_t outBufSize;
|
||||
size_t outDataWritten; // the size of data in (outBuf) that were fully unpacked
|
||||
|
||||
Byte shaDigest[SHA256_DIGEST_SIZE];
|
||||
Byte buf[XZ_BLOCK_HEADER_SIZE_MAX];
|
||||
UInt32 shaDigest32[SHA256_DIGEST_SIZE / 4];
|
||||
Byte buf[XZ_BLOCK_HEADER_SIZE_MAX]; // it must be aligned for 4-bytes
|
||||
} CXzUnpacker;
|
||||
|
||||
/* alloc : aligned for cache line allocation is better */
|
||||
|
||||
3
3rdparty/lzma/include/XzEnc.h
vendored
3
3rdparty/lzma/include/XzEnc.h
vendored
@@ -1,5 +1,5 @@
|
||||
/* XzEnc.h -- Xz Encode
|
||||
2023-04-13 : Igor Pavlov : Public domain */
|
||||
: Igor Pavlov : Public domain */
|
||||
|
||||
#ifndef ZIP7_INC_XZ_ENC_H
|
||||
#define ZIP7_INC_XZ_ENC_H
|
||||
@@ -31,6 +31,7 @@ typedef struct
|
||||
CLzma2EncProps lzma2Props;
|
||||
CXzFilterProps filterProps;
|
||||
unsigned checkId;
|
||||
unsigned numThreadGroups; // 0 : no groups
|
||||
UInt64 blockSize;
|
||||
int numBlockThreads_Reduced;
|
||||
int numBlockThreads_Max;
|
||||
|
||||
5
3rdparty/lzma/src/7zDec.c
vendored
5
3rdparty/lzma/src/7zDec.c
vendored
@@ -1,5 +1,5 @@
|
||||
/* 7zDec.c -- Decoding from 7z folder
|
||||
2024-03-01 : Igor Pavlov : Public domain */
|
||||
: Igor Pavlov : Public domain */
|
||||
|
||||
#include "Precomp.h"
|
||||
|
||||
@@ -312,8 +312,9 @@ static BoolInt IS_MAIN_METHOD(UInt32 m)
|
||||
case k_PPMD:
|
||||
#endif
|
||||
return True;
|
||||
default:
|
||||
return False;
|
||||
}
|
||||
return False;
|
||||
}
|
||||
|
||||
static BoolInt IS_SUPPORTED_CODER(const CSzCoderInfo *c)
|
||||
|
||||
233
3rdparty/lzma/src/AesOpt.c
vendored
233
3rdparty/lzma/src/AesOpt.c
vendored
@@ -1,5 +1,5 @@
|
||||
/* AesOpt.c -- AES optimized code for x86 AES hardware instructions
|
||||
2024-03-01 : Igor Pavlov : Public domain */
|
||||
Igor Pavlov : Public domain */
|
||||
|
||||
#include "Precomp.h"
|
||||
|
||||
@@ -80,19 +80,39 @@ AES_FUNC_START (name)
|
||||
|
||||
#define MM_XOR( dest, src) MM_OP(_mm_xor_si128, dest, src)
|
||||
|
||||
#if 1
|
||||
// use aligned SSE load/store for data.
|
||||
// It is required for our Aes functions, that data is aligned for 16-bytes.
|
||||
// So we can use this branch of code.
|
||||
// and compiler can use fused load-op SSE instructions:
|
||||
// xorps xmm0, XMMWORD PTR [rdx]
|
||||
#define LOAD_128(pp) (*(__m128i *)(void *)(pp))
|
||||
#define STORE_128(pp, _v) *(__m128i *)(void *)(pp) = _v
|
||||
// use aligned SSE load/store for data. Alternative code with direct access
|
||||
// #define LOAD_128(pp) _mm_load_si128(pp)
|
||||
// #define STORE_128(pp, _v) _mm_store_si128(pp, _v)
|
||||
#else
|
||||
// use unaligned load/store for data: movdqu XMMWORD PTR [rdx]
|
||||
#define LOAD_128(pp) _mm_loadu_si128(pp)
|
||||
#define STORE_128(pp, _v) _mm_storeu_si128(pp, _v)
|
||||
#endif
|
||||
|
||||
AES_FUNC_START2 (AesCbc_Encode_HW)
|
||||
{
|
||||
if (numBlocks == 0)
|
||||
return;
|
||||
{
|
||||
__m128i *p = (__m128i *)(void *)ivAes;
|
||||
__m128i *data = (__m128i *)(void *)data8;
|
||||
__m128i m = *p;
|
||||
const __m128i k0 = p[2];
|
||||
const __m128i k1 = p[3];
|
||||
const UInt32 numRounds2 = *(const UInt32 *)(p + 1) - 1;
|
||||
for (; numBlocks != 0; numBlocks--, data++)
|
||||
do
|
||||
{
|
||||
UInt32 r = numRounds2;
|
||||
const __m128i *w = p + 4;
|
||||
__m128i temp = *data;
|
||||
__m128i temp = LOAD_128(data);
|
||||
MM_XOR (temp, k0)
|
||||
MM_XOR (m, temp)
|
||||
MM_OP_m (_mm_aesenc_si128, k1)
|
||||
@@ -104,9 +124,12 @@ AES_FUNC_START2 (AesCbc_Encode_HW)
|
||||
}
|
||||
while (--r);
|
||||
MM_OP_m (_mm_aesenclast_si128, w[0])
|
||||
*data = m;
|
||||
STORE_128(data, m);
|
||||
data++;
|
||||
}
|
||||
while (--numBlocks);
|
||||
*p = m;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -139,12 +162,12 @@ AES_FUNC_START2 (AesCbc_Encode_HW)
|
||||
|
||||
#define WOP(op) op (m0, 0) WOP_M1(op)
|
||||
|
||||
|
||||
#define DECLARE_VAR(reg, ii) __m128i reg;
|
||||
#define LOAD_data( reg, ii) reg = data[ii];
|
||||
#define STORE_data( reg, ii) data[ii] = reg;
|
||||
#define LOAD_data_ii(ii) LOAD_128(data + (ii))
|
||||
#define LOAD_data( reg, ii) reg = LOAD_data_ii(ii);
|
||||
#define STORE_data( reg, ii) STORE_128(data + (ii), reg);
|
||||
#if (NUM_WAYS > 1)
|
||||
#define XOR_data_M1(reg, ii) MM_XOR (reg, data[ii- 1])
|
||||
#define XOR_data_M1(reg, ii) MM_XOR (reg, LOAD_128(data + (ii- 1)))
|
||||
#endif
|
||||
|
||||
#define MM_OP_key(op, reg) MM_OP(op, reg, key);
|
||||
@@ -156,25 +179,22 @@ AES_FUNC_START2 (AesCbc_Encode_HW)
|
||||
#define AES_XOR( reg, ii) MM_OP_key (_mm_xor_si128, reg)
|
||||
|
||||
#define CTR_START(reg, ii) MM_OP (_mm_add_epi64, ctr, one) reg = ctr;
|
||||
#define CTR_END( reg, ii) MM_XOR (data[ii], reg)
|
||||
|
||||
#define CTR_END( reg, ii) STORE_128(data + (ii), _mm_xor_si128(reg, \
|
||||
LOAD_128 (data + (ii))));
|
||||
#define WOP_KEY(op, n) { \
|
||||
const __m128i key = w[n]; \
|
||||
WOP(op); }
|
||||
|
||||
WOP(op) }
|
||||
|
||||
#define WIDE_LOOP_START \
|
||||
dataEnd = data + numBlocks; \
|
||||
if (numBlocks >= NUM_WAYS) \
|
||||
{ dataEnd -= NUM_WAYS; do { \
|
||||
|
||||
|
||||
#define WIDE_LOOP_END \
|
||||
data += NUM_WAYS; \
|
||||
} while (data <= dataEnd); \
|
||||
dataEnd += NUM_WAYS; } \
|
||||
|
||||
|
||||
#define SINGLE_LOOP \
|
||||
for (; data < dataEnd; data++)
|
||||
|
||||
@@ -184,54 +204,73 @@ AES_FUNC_START2 (AesCbc_Encode_HW)
|
||||
|
||||
#define AVX_XOR(dest, src) MM_OP(_mm256_xor_si256, dest, src)
|
||||
#define AVX_DECLARE_VAR(reg, ii) __m256i reg;
|
||||
#define AVX_LOAD_data( reg, ii) reg = ((const __m256i *)(const void *)data)[ii];
|
||||
#define AVX_STORE_data( reg, ii) ((__m256i *)(void *)data)[ii] = reg;
|
||||
|
||||
#if 1
|
||||
// use unaligned AVX load/store for data.
|
||||
// It is required for our Aes functions, that data is aligned for 16-bytes.
|
||||
// But we need 32-bytes reading.
|
||||
// So we use intrinsics for unaligned AVX load/store.
|
||||
// notes for _mm256_storeu_si256:
|
||||
// msvc2022: uses vmovdqu and keeps the order of instruction sequence.
|
||||
// new gcc11 uses vmovdqu
|
||||
// old gcc9 could use pair of instructions:
|
||||
// vmovups %xmm7, -224(%rax)
|
||||
// vextracti128 $0x1, %ymm7, -208(%rax)
|
||||
#define AVX_LOAD(p) _mm256_loadu_si256((const __m256i *)(const void *)(p))
|
||||
#define AVX_STORE(p, _v) _mm256_storeu_si256((__m256i *)(void *)(p), _v);
|
||||
#else
|
||||
// use aligned AVX load/store for data.
|
||||
// for debug: we can use this branch, if we are sure that data is aligned for 32-bytes.
|
||||
// msvc2022 uses vmovdqu still
|
||||
// gcc uses vmovdqa (that requires 32-bytes alignment)
|
||||
#define AVX_LOAD(p) (*(const __m256i *)(const void *)(p))
|
||||
#define AVX_STORE(p, _v) (*(__m256i *)(void *)(p)) = _v;
|
||||
#endif
|
||||
|
||||
#define AVX_LOAD_data( reg, ii) reg = AVX_LOAD((const __m256i *)(const void *)data + (ii));
|
||||
#define AVX_STORE_data( reg, ii) AVX_STORE((__m256i *)(void *)data + (ii), reg)
|
||||
/*
|
||||
AVX_XOR_data_M1() needs unaligned memory load
|
||||
if (we don't use _mm256_loadu_si256() here)
|
||||
{
|
||||
Most compilers with enabled optimizations generate fused AVX (LOAD + OP)
|
||||
instruction that can load unaligned data.
|
||||
But GCC and CLANG without -O2 or -O1 optimizations can generate separated
|
||||
LOAD-ALIGNED (vmovdqa) instruction that will fail on execution.
|
||||
}
|
||||
Note: some compilers generate more instructions, if we use _mm256_loadu_si256() here.
|
||||
v23.02: we use _mm256_loadu_si256() here, because we need compatibility with any compiler.
|
||||
AVX_XOR_data_M1() needs unaligned memory load, even if (data)
|
||||
is aligned for 256-bits, because we read 32-bytes chunk that
|
||||
crosses (data) position: from (data - 16bytes) to (data + 16bytes).
|
||||
*/
|
||||
#define AVX_XOR_data_M1(reg, ii) AVX_XOR (reg, _mm256_loadu_si256(&(((const __m256i *)(const void *)(data - 1))[ii])))
|
||||
// for debug only: the following code will fail on execution, if compiled by some compilers:
|
||||
// #define AVX_XOR_data_M1(reg, ii) AVX_XOR (reg, (((const __m256i *)(const void *)(data - 1))[ii]))
|
||||
#define AVX_XOR_data_M1(reg, ii) AVX_XOR (reg, _mm256_loadu_si256((const __m256i *)(const void *)(data - 1) + (ii)))
|
||||
|
||||
#define AVX_AES_DEC( reg, ii) MM_OP_key (_mm256_aesdec_epi128, reg)
|
||||
#define AVX_AES_DEC_LAST( reg, ii) MM_OP_key (_mm256_aesdeclast_epi128, reg)
|
||||
#define AVX_AES_ENC( reg, ii) MM_OP_key (_mm256_aesenc_epi128, reg)
|
||||
#define AVX_AES_ENC_LAST( reg, ii) MM_OP_key (_mm256_aesenclast_epi128, reg)
|
||||
#define AVX_AES_XOR( reg, ii) MM_OP_key (_mm256_xor_si256, reg)
|
||||
#define AVX_CTR_START(reg, ii) MM_OP (_mm256_add_epi64, ctr2, two) reg = _mm256_xor_si256(ctr2, key);
|
||||
#define AVX_CTR_END( reg, ii) AVX_XOR (((__m256i *)(void *)data)[ii], reg)
|
||||
#define AVX_CTR_START(reg, ii) \
|
||||
MM_OP (_mm256_add_epi64, ctr2, two) \
|
||||
reg = _mm256_xor_si256(ctr2, key);
|
||||
|
||||
#define AVX_CTR_END(reg, ii) \
|
||||
AVX_STORE((__m256i *)(void *)data + (ii), _mm256_xor_si256(reg, \
|
||||
AVX_LOAD ((__m256i *)(void *)data + (ii))));
|
||||
|
||||
#define AVX_WOP_KEY(op, n) { \
|
||||
const __m256i key = w[n]; \
|
||||
WOP(op); }
|
||||
WOP(op) }
|
||||
|
||||
#define NUM_AES_KEYS_MAX 15
|
||||
|
||||
#define WIDE_LOOP_START_AVX(OP) \
|
||||
dataEnd = data + numBlocks; \
|
||||
if (numBlocks >= NUM_WAYS * 2) \
|
||||
{ __m256i keys[NUM_AES_KEYS_MAX]; \
|
||||
UInt32 ii; \
|
||||
OP \
|
||||
for (ii = 0; ii < numRounds; ii++) \
|
||||
keys[ii] = _mm256_broadcastsi128_si256(p[ii]); \
|
||||
dataEnd -= NUM_WAYS * 2; do { \
|
||||
|
||||
{ __m256i keys[NUM_AES_KEYS_MAX]; \
|
||||
OP \
|
||||
{ UInt32 ii; for (ii = 0; ii < numRounds; ii++) \
|
||||
keys[ii] = _mm256_broadcastsi128_si256(p[ii]); } \
|
||||
dataEnd -= NUM_WAYS * 2; \
|
||||
do { \
|
||||
|
||||
#define WIDE_LOOP_END_AVX(OP) \
|
||||
data += NUM_WAYS * 2; \
|
||||
} while (data <= dataEnd); \
|
||||
dataEnd += NUM_WAYS * 2; \
|
||||
OP \
|
||||
_mm256_zeroupper(); \
|
||||
data += NUM_WAYS * 2; \
|
||||
} while (data <= dataEnd); \
|
||||
dataEnd += NUM_WAYS * 2; \
|
||||
OP \
|
||||
_mm256_zeroupper(); \
|
||||
} \
|
||||
|
||||
/* MSVC for x86: If we don't call _mm256_zeroupper(), and -arch:IA32 is not specified,
|
||||
@@ -246,21 +285,20 @@ AES_FUNC_START2 (AesCbc_Decode_HW)
|
||||
__m128i *p = (__m128i *)(void *)ivAes;
|
||||
__m128i *data = (__m128i *)(void *)data8;
|
||||
__m128i iv = *p;
|
||||
const __m128i *wStart = p + *(const UInt32 *)(p + 1) * 2 + 2 - 1;
|
||||
const __m128i * const wStart = p + (size_t)*(const UInt32 *)(p + 1) * 2 + 2 - 1;
|
||||
const __m128i *dataEnd;
|
||||
p += 2;
|
||||
|
||||
WIDE_LOOP_START
|
||||
{
|
||||
const __m128i *w = wStart;
|
||||
|
||||
WOP (DECLARE_VAR)
|
||||
WOP (LOAD_data)
|
||||
WOP_KEY (AES_XOR, 1)
|
||||
|
||||
do
|
||||
{
|
||||
WOP_KEY (AES_DEC, 0)
|
||||
|
||||
w--;
|
||||
}
|
||||
while (w != p);
|
||||
@@ -268,7 +306,7 @@ AES_FUNC_START2 (AesCbc_Decode_HW)
|
||||
|
||||
MM_XOR (m0, iv)
|
||||
WOP_M1 (XOR_data_M1)
|
||||
iv = data[NUM_WAYS - 1];
|
||||
LOAD_data(iv, NUM_WAYS - 1)
|
||||
WOP (STORE_data)
|
||||
}
|
||||
WIDE_LOOP_END
|
||||
@@ -276,7 +314,8 @@ AES_FUNC_START2 (AesCbc_Decode_HW)
|
||||
SINGLE_LOOP
|
||||
{
|
||||
const __m128i *w = wStart - 1;
|
||||
__m128i m = _mm_xor_si128 (w[2], *data);
|
||||
__m128i m = _mm_xor_si128 (w[2], LOAD_data_ii(0));
|
||||
|
||||
do
|
||||
{
|
||||
MM_OP_m (_mm_aesdec_si128, w[1])
|
||||
@@ -286,10 +325,9 @@ AES_FUNC_START2 (AesCbc_Decode_HW)
|
||||
while (w != p);
|
||||
MM_OP_m (_mm_aesdec_si128, w[1])
|
||||
MM_OP_m (_mm_aesdeclast_si128, w[0])
|
||||
|
||||
MM_XOR (m, iv)
|
||||
iv = *data;
|
||||
*data = m;
|
||||
LOAD_data(iv, 0)
|
||||
STORE_data(m, 0)
|
||||
}
|
||||
|
||||
p[-2] = iv;
|
||||
@@ -301,9 +339,9 @@ AES_FUNC_START2 (AesCtr_Code_HW)
|
||||
__m128i *p = (__m128i *)(void *)ivAes;
|
||||
__m128i *data = (__m128i *)(void *)data8;
|
||||
__m128i ctr = *p;
|
||||
UInt32 numRoundsMinus2 = *(const UInt32 *)(p + 1) * 2 - 1;
|
||||
const UInt32 numRoundsMinus2 = *(const UInt32 *)(p + 1) * 2 - 1;
|
||||
const __m128i *dataEnd;
|
||||
__m128i one = _mm_cvtsi32_si128(1);
|
||||
const __m128i one = _mm_cvtsi32_si128(1);
|
||||
|
||||
p += 2;
|
||||
|
||||
@@ -322,7 +360,6 @@ AES_FUNC_START2 (AesCtr_Code_HW)
|
||||
}
|
||||
while (--r);
|
||||
WOP_KEY (AES_ENC_LAST, 0)
|
||||
|
||||
WOP (CTR_END)
|
||||
}
|
||||
WIDE_LOOP_END
|
||||
@@ -344,7 +381,7 @@ AES_FUNC_START2 (AesCtr_Code_HW)
|
||||
while (--numRounds2);
|
||||
MM_OP_m (_mm_aesenc_si128, w[0])
|
||||
MM_OP_m (_mm_aesenclast_si128, w[1])
|
||||
MM_XOR (*data, m)
|
||||
CTR_END (m, 0)
|
||||
}
|
||||
|
||||
p[-2] = ctr;
|
||||
@@ -421,7 +458,7 @@ VAES_FUNC_START2 (AesCbc_Decode_HW_256)
|
||||
__m128i *data = (__m128i *)(void *)data8;
|
||||
__m128i iv = *p;
|
||||
const __m128i *dataEnd;
|
||||
UInt32 numRounds = *(const UInt32 *)(p + 1) * 2 + 1;
|
||||
const UInt32 numRounds = *(const UInt32 *)(p + 1) * 2 + 1;
|
||||
p += 2;
|
||||
|
||||
WIDE_LOOP_START_AVX(;)
|
||||
@@ -440,17 +477,17 @@ VAES_FUNC_START2 (AesCbc_Decode_HW_256)
|
||||
while (w != keys);
|
||||
AVX_WOP_KEY (AVX_AES_DEC_LAST, 0)
|
||||
|
||||
AVX_XOR (m0, _mm256_setr_m128i(iv, data[0]))
|
||||
AVX_XOR (m0, _mm256_setr_m128i(iv, LOAD_data_ii(0)))
|
||||
WOP_M1 (AVX_XOR_data_M1)
|
||||
iv = data[NUM_WAYS * 2 - 1];
|
||||
LOAD_data (iv, NUM_WAYS * 2 - 1)
|
||||
WOP (AVX_STORE_data)
|
||||
}
|
||||
WIDE_LOOP_END_AVX(;)
|
||||
|
||||
SINGLE_LOOP
|
||||
{
|
||||
const __m128i *w = p + *(const UInt32 *)(p + 1 - 2) * 2 + 1 - 3;
|
||||
__m128i m = _mm_xor_si128 (w[2], *data);
|
||||
const __m128i *w = p - 2 + (size_t)*(const UInt32 *)(p + 1 - 2) * 2;
|
||||
__m128i m = _mm_xor_si128 (w[2], LOAD_data_ii(0));
|
||||
do
|
||||
{
|
||||
MM_OP_m (_mm_aesdec_si128, w[1])
|
||||
@@ -462,8 +499,8 @@ VAES_FUNC_START2 (AesCbc_Decode_HW_256)
|
||||
MM_OP_m (_mm_aesdeclast_si128, w[0])
|
||||
|
||||
MM_XOR (m, iv)
|
||||
iv = *data;
|
||||
*data = m;
|
||||
LOAD_data(iv, 0)
|
||||
STORE_data(m, 0)
|
||||
}
|
||||
|
||||
p[-2] = iv;
|
||||
@@ -493,9 +530,9 @@ VAES_FUNC_START2 (AesCtr_Code_HW_256)
|
||||
__m128i *p = (__m128i *)(void *)ivAes;
|
||||
__m128i *data = (__m128i *)(void *)data8;
|
||||
__m128i ctr = *p;
|
||||
UInt32 numRounds = *(const UInt32 *)(p + 1) * 2 + 1;
|
||||
const UInt32 numRounds = *(const UInt32 *)(p + 1) * 2 + 1;
|
||||
const __m128i *dataEnd;
|
||||
__m128i one = _mm_cvtsi32_si128(1);
|
||||
const __m128i one = _mm_cvtsi32_si128(1);
|
||||
__m256i ctr2, two;
|
||||
p += 2;
|
||||
|
||||
@@ -536,7 +573,7 @@ VAES_FUNC_START2 (AesCtr_Code_HW_256)
|
||||
while (--numRounds2);
|
||||
MM_OP_m (_mm_aesenc_si128, w[0])
|
||||
MM_OP_m (_mm_aesenclast_si128, w[1])
|
||||
MM_XOR (*data, m)
|
||||
CTR_END (m, 0)
|
||||
}
|
||||
|
||||
p[-2] = ctr;
|
||||
@@ -731,9 +768,14 @@ AES_FUNC_START (name)
|
||||
|
||||
AES_FUNC_START2 (AesCbc_Encode_HW)
|
||||
{
|
||||
v128 * const p = (v128*)(void*)ivAes;
|
||||
v128 *data = (v128*)(void*)data8;
|
||||
if (numBlocks == 0)
|
||||
return;
|
||||
{
|
||||
v128 * const p = (v128 *)(void *)ivAes;
|
||||
v128 *data = (v128 *)(void *)data8;
|
||||
v128 m = *p;
|
||||
const UInt32 numRounds2 = *(const UInt32 *)(p + 1);
|
||||
const v128 *w = p + (size_t)numRounds2 * 2;
|
||||
const v128 k0 = p[2];
|
||||
const v128 k1 = p[3];
|
||||
const v128 k2 = p[4];
|
||||
@@ -744,11 +786,14 @@ AES_FUNC_START2 (AesCbc_Encode_HW)
|
||||
const v128 k7 = p[9];
|
||||
const v128 k8 = p[10];
|
||||
const v128 k9 = p[11];
|
||||
const UInt32 numRounds2 = *(const UInt32 *)(p + 1);
|
||||
const v128 *w = p + ((size_t)numRounds2 * 2);
|
||||
const v128 k_z4 = w[-2];
|
||||
const v128 k_z3 = w[-1];
|
||||
const v128 k_z2 = w[0];
|
||||
const v128 k_z1 = w[1];
|
||||
const v128 k_z0 = w[2];
|
||||
for (; numBlocks != 0; numBlocks--, data++)
|
||||
// we don't use optimization veorq_u8(*data, k_z0) that can reduce one cycle,
|
||||
// because gcc/clang compilers are not good for that optimization.
|
||||
do
|
||||
{
|
||||
MM_XOR_m (*data)
|
||||
AES_E_MC_m (k0)
|
||||
@@ -757,24 +802,26 @@ AES_FUNC_START2 (AesCbc_Encode_HW)
|
||||
AES_E_MC_m (k3)
|
||||
AES_E_MC_m (k4)
|
||||
AES_E_MC_m (k5)
|
||||
AES_E_MC_m (k6)
|
||||
AES_E_MC_m (k7)
|
||||
AES_E_MC_m (k8)
|
||||
if (numRounds2 >= 6)
|
||||
{
|
||||
AES_E_MC_m (k9)
|
||||
AES_E_MC_m (p[12])
|
||||
AES_E_MC_m (k6)
|
||||
AES_E_MC_m (k7)
|
||||
if (numRounds2 != 6)
|
||||
{
|
||||
AES_E_MC_m (p[13])
|
||||
AES_E_MC_m (p[14])
|
||||
AES_E_MC_m (k8)
|
||||
AES_E_MC_m (k9)
|
||||
}
|
||||
}
|
||||
AES_E_m (k_z1)
|
||||
MM_XOR_m (k_z0)
|
||||
*data = m;
|
||||
AES_E_MC_m (k_z4)
|
||||
AES_E_MC_m (k_z3)
|
||||
AES_E_MC_m (k_z2)
|
||||
AES_E_m (k_z1)
|
||||
MM_XOR_m (k_z0)
|
||||
*data++ = m;
|
||||
}
|
||||
while (--numBlocks);
|
||||
*p = m;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -834,10 +881,10 @@ AES_FUNC_START2 (AesCbc_Encode_HW)
|
||||
|
||||
AES_FUNC_START2 (AesCbc_Decode_HW)
|
||||
{
|
||||
v128 *p = (v128*)(void*)ivAes;
|
||||
v128 *data = (v128*)(void*)data8;
|
||||
v128 *p = (v128 *)(void *)ivAes;
|
||||
v128 *data = (v128 *)(void *)data8;
|
||||
v128 iv = *p;
|
||||
const v128 *wStart = p + ((size_t)*(const UInt32 *)(p + 1)) * 2;
|
||||
const v128 * const wStart = p + (size_t)*(const UInt32 *)(p + 1) * 2;
|
||||
const v128 *dataEnd;
|
||||
p += 2;
|
||||
|
||||
@@ -858,7 +905,7 @@ AES_FUNC_START2 (AesCbc_Decode_HW)
|
||||
WOP_KEY (AES_XOR, 0)
|
||||
MM_XOR (m0, iv)
|
||||
WOP_M1 (XOR_data_M1)
|
||||
iv = data[NUM_WAYS - 1];
|
||||
LOAD_data(iv, NUM_WAYS - 1)
|
||||
WOP (STORE_data)
|
||||
}
|
||||
WIDE_LOOP_END
|
||||
@@ -866,7 +913,7 @@ AES_FUNC_START2 (AesCbc_Decode_HW)
|
||||
SINGLE_LOOP
|
||||
{
|
||||
const v128 *w = wStart;
|
||||
v128 m = *data;
|
||||
v128 m; LOAD_data(m, 0)
|
||||
AES_D_IMC_m (w[2])
|
||||
do
|
||||
{
|
||||
@@ -878,8 +925,8 @@ AES_FUNC_START2 (AesCbc_Decode_HW)
|
||||
AES_D_m (w[1])
|
||||
MM_XOR_m (w[0])
|
||||
MM_XOR_m (iv)
|
||||
iv = *data;
|
||||
*data = m;
|
||||
LOAD_data(iv, 0)
|
||||
STORE_data(m, 0)
|
||||
}
|
||||
|
||||
p[-2] = iv;
|
||||
@@ -888,19 +935,17 @@ AES_FUNC_START2 (AesCbc_Decode_HW)
|
||||
|
||||
AES_FUNC_START2 (AesCtr_Code_HW)
|
||||
{
|
||||
v128 *p = (v128*)(void*)ivAes;
|
||||
v128 *data = (v128*)(void*)data8;
|
||||
v128 *p = (v128 *)(void *)ivAes;
|
||||
v128 *data = (v128 *)(void *)data8;
|
||||
uint64x2_t ctr = vreinterpretq_u64_u8(*p);
|
||||
const v128 *wEnd = p + ((size_t)*(const UInt32 *)(p + 1)) * 2;
|
||||
const v128 * const wEnd = p + (size_t)*(const UInt32 *)(p + 1) * 2;
|
||||
const v128 *dataEnd;
|
||||
uint64x2_t one = vdupq_n_u64(0);
|
||||
|
||||
// the bug in clang:
|
||||
// __builtin_neon_vsetq_lane_i64(__s0, (int8x16_t)__s1, __p2);
|
||||
#if defined(__clang__) && (__clang_major__ <= 9)
|
||||
#pragma GCC diagnostic ignored "-Wvector-conversion"
|
||||
#endif
|
||||
one = vsetq_lane_u64(1, one, 0);
|
||||
const uint64x2_t one = vsetq_lane_u64(1, vdupq_n_u64(0), 0);
|
||||
p += 2;
|
||||
|
||||
WIDE_LOOP_START
|
||||
|
||||
109
3rdparty/lzma/src/CpuArch.c
vendored
109
3rdparty/lzma/src/CpuArch.c
vendored
@@ -1,5 +1,5 @@
|
||||
/* CpuArch.c -- CPU specific code
|
||||
2024-07-04 : Igor Pavlov : Public domain */
|
||||
Igor Pavlov : Public domain */
|
||||
|
||||
#include "Precomp.h"
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
/*
|
||||
cpuid instruction supports (subFunction) parameter in ECX,
|
||||
that is used only with some specific (function) parameter values.
|
||||
But we always use only (subFunction==0).
|
||||
most functions use only (subFunction==0).
|
||||
*/
|
||||
/*
|
||||
__cpuid(): MSVC and GCC/CLANG use same function/macro name
|
||||
@@ -49,43 +49,49 @@
|
||||
#if defined(MY_CPU_AMD64) && defined(__PIC__) \
|
||||
&& ((defined (__GNUC__) && (__GNUC__ < 5)) || defined(__clang__))
|
||||
|
||||
#define x86_cpuid_MACRO(p, func) { \
|
||||
/* "=&r" selects free register. It can select even rbx, if that register is free.
|
||||
"=&D" for (RDI) also works, but the code can be larger with "=&D"
|
||||
"2"(subFun) : 2 is (zero-based) index in the output constraint list "=c" (ECX). */
|
||||
|
||||
#define x86_cpuid_MACRO_2(p, func, subFunc) { \
|
||||
__asm__ __volatile__ ( \
|
||||
ASM_LN "mov %%rbx, %q1" \
|
||||
ASM_LN "cpuid" \
|
||||
ASM_LN "xchg %%rbx, %q1" \
|
||||
: "=a" ((p)[0]), "=&r" ((p)[1]), "=c" ((p)[2]), "=d" ((p)[3]) : "0" (func), "2"(0)); }
|
||||
|
||||
/* "=&r" selects free register. It can select even rbx, if that register is free.
|
||||
"=&D" for (RDI) also works, but the code can be larger with "=&D"
|
||||
"2"(0) means (subFunction = 0),
|
||||
2 is (zero-based) index in the output constraint list "=c" (ECX). */
|
||||
: "=a" ((p)[0]), "=&r" ((p)[1]), "=c" ((p)[2]), "=d" ((p)[3]) : "0" (func), "2"(subFunc)); }
|
||||
|
||||
#elif defined(MY_CPU_X86) && defined(__PIC__) \
|
||||
&& ((defined (__GNUC__) && (__GNUC__ < 5)) || defined(__clang__))
|
||||
|
||||
#define x86_cpuid_MACRO(p, func) { \
|
||||
#define x86_cpuid_MACRO_2(p, func, subFunc) { \
|
||||
__asm__ __volatile__ ( \
|
||||
ASM_LN "mov %%ebx, %k1" \
|
||||
ASM_LN "cpuid" \
|
||||
ASM_LN "xchg %%ebx, %k1" \
|
||||
: "=a" ((p)[0]), "=&r" ((p)[1]), "=c" ((p)[2]), "=d" ((p)[3]) : "0" (func), "2"(0)); }
|
||||
: "=a" ((p)[0]), "=&r" ((p)[1]), "=c" ((p)[2]), "=d" ((p)[3]) : "0" (func), "2"(subFunc)); }
|
||||
|
||||
#else
|
||||
|
||||
#define x86_cpuid_MACRO(p, func) { \
|
||||
#define x86_cpuid_MACRO_2(p, func, subFunc) { \
|
||||
__asm__ __volatile__ ( \
|
||||
ASM_LN "cpuid" \
|
||||
: "=a" ((p)[0]), "=b" ((p)[1]), "=c" ((p)[2]), "=d" ((p)[3]) : "0" (func), "2"(0)); }
|
||||
: "=a" ((p)[0]), "=b" ((p)[1]), "=c" ((p)[2]), "=d" ((p)[3]) : "0" (func), "2"(subFunc)); }
|
||||
|
||||
#endif
|
||||
|
||||
#define x86_cpuid_MACRO(p, func) x86_cpuid_MACRO_2(p, func, 0)
|
||||
|
||||
void Z7_FASTCALL z7_x86_cpuid(UInt32 p[4], UInt32 func)
|
||||
{
|
||||
x86_cpuid_MACRO(p, func)
|
||||
}
|
||||
|
||||
static
|
||||
void Z7_FASTCALL z7_x86_cpuid_subFunc(UInt32 p[4], UInt32 func, UInt32 subFunc)
|
||||
{
|
||||
x86_cpuid_MACRO_2(p, func, subFunc)
|
||||
}
|
||||
|
||||
|
||||
Z7_NO_INLINE
|
||||
UInt32 Z7_FASTCALL z7_x86_cpuid_GetMaxFunc(void)
|
||||
@@ -205,11 +211,39 @@ void __declspec(naked) Z7_FASTCALL z7_x86_cpuid(UInt32 p[4], UInt32 func)
|
||||
__asm ret 0
|
||||
}
|
||||
|
||||
static
|
||||
void __declspec(naked) Z7_FASTCALL z7_x86_cpuid_subFunc(UInt32 p[4], UInt32 func, UInt32 subFunc)
|
||||
{
|
||||
UNUSED_VAR(p)
|
||||
UNUSED_VAR(func)
|
||||
UNUSED_VAR(subFunc)
|
||||
__asm push ebx
|
||||
__asm push edi
|
||||
__asm mov edi, ecx // p
|
||||
__asm mov eax, edx // func
|
||||
__asm mov ecx, [esp + 12] // subFunc
|
||||
__asm cpuid
|
||||
__asm mov [edi ], eax
|
||||
__asm mov [edi + 4], ebx
|
||||
__asm mov [edi + 8], ecx
|
||||
__asm mov [edi + 12], edx
|
||||
__asm pop edi
|
||||
__asm pop ebx
|
||||
__asm ret 4
|
||||
}
|
||||
|
||||
#else // MY_CPU_AMD64
|
||||
|
||||
#if _MSC_VER >= 1600
|
||||
#include <intrin.h>
|
||||
#define MY_cpuidex __cpuidex
|
||||
|
||||
static
|
||||
void Z7_FASTCALL z7_x86_cpuid_subFunc(UInt32 p[4], UInt32 func, UInt32 subFunc)
|
||||
{
|
||||
__cpuidex((int *)p, func, subFunc);
|
||||
}
|
||||
|
||||
#else
|
||||
/*
|
||||
__cpuid (func == (0 or 7)) requires subfunction number in ECX.
|
||||
@@ -219,7 +253,7 @@ void __declspec(naked) Z7_FASTCALL z7_x86_cpuid(UInt32 p[4], UInt32 func)
|
||||
We still can use __cpuid for low (func) values that don't require ECX,
|
||||
but __cpuid() in old MSVC will be incorrect for some func values: (func == 7).
|
||||
So here we use the hack for old MSVC to send (subFunction) in ECX register to cpuid instruction,
|
||||
where ECX value is first parameter for FASTCALL / NO_INLINE func,
|
||||
where ECX value is first parameter for FASTCALL / NO_INLINE func.
|
||||
So the caller of MY_cpuidex_HACK() sets ECX as subFunction, and
|
||||
old MSVC for __cpuid() doesn't change ECX and cpuid instruction gets (subFunction) value.
|
||||
|
||||
@@ -233,6 +267,11 @@ Z7_NO_INLINE void Z7_FASTCALL MY_cpuidex_HACK(Int32 subFunction, Int32 func, Int
|
||||
}
|
||||
#define MY_cpuidex(info, func, func2) MY_cpuidex_HACK(func2, func, info)
|
||||
#pragma message("======== MY_cpuidex_HACK WAS USED ========")
|
||||
static
|
||||
void Z7_FASTCALL z7_x86_cpuid_subFunc(UInt32 p[4], UInt32 func, UInt32 subFunc)
|
||||
{
|
||||
MY_cpuidex_HACK(subFunc, func, (Int32 *)p);
|
||||
}
|
||||
#endif // _MSC_VER >= 1600
|
||||
|
||||
#if !defined(MY_CPU_AMD64)
|
||||
@@ -445,6 +484,23 @@ BoolInt CPU_IsSupported_SHA(void)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
BoolInt CPU_IsSupported_SHA512(void)
|
||||
{
|
||||
if (!CPU_IsSupported_AVX2()) return False; // maybe CPU_IsSupported_AVX() is enough here
|
||||
|
||||
if (z7_x86_cpuid_GetMaxFunc() < 7)
|
||||
return False;
|
||||
{
|
||||
UInt32 d[4];
|
||||
z7_x86_cpuid_subFunc(d, 7, 0);
|
||||
if (d[0] < 1) // d[0] - is max supported subleaf value
|
||||
return False;
|
||||
z7_x86_cpuid_subFunc(d, 7, 1);
|
||||
return (BoolInt)(d[0]) & 1;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
MSVC: _xgetbv() intrinsic is available since VS2010SP1.
|
||||
MSVC also defines (_XCR_XFEATURE_ENABLED_MASK) macro in
|
||||
@@ -776,6 +832,18 @@ BoolInt CPU_IsSupported_NEON(void)
|
||||
return z7_sysctlbyname_Get_BoolInt("hw.optional.neon");
|
||||
}
|
||||
|
||||
BoolInt CPU_IsSupported_SHA512(void)
|
||||
{
|
||||
return z7_sysctlbyname_Get_BoolInt("hw.optional.armv8_2_sha512");
|
||||
}
|
||||
|
||||
/*
|
||||
BoolInt CPU_IsSupported_SHA3(void)
|
||||
{
|
||||
return z7_sysctlbyname_Get_BoolInt("hw.optional.armv8_2_sha3");
|
||||
}
|
||||
*/
|
||||
|
||||
#ifdef MY_CPU_ARM64
|
||||
#define APPLE_CRYPTO_SUPPORT_VAL 1
|
||||
#else
|
||||
@@ -860,6 +928,19 @@ MY_HWCAP_CHECK_FUNC (CRC32)
|
||||
MY_HWCAP_CHECK_FUNC (SHA1)
|
||||
MY_HWCAP_CHECK_FUNC (SHA2)
|
||||
MY_HWCAP_CHECK_FUNC (AES)
|
||||
#ifdef MY_CPU_ARM64
|
||||
// <hwcap.h> supports HWCAP_SHA512 and HWCAP_SHA3 since 2017.
|
||||
// we define them here, if they are not defined
|
||||
#ifndef HWCAP_SHA3
|
||||
// #define HWCAP_SHA3 (1 << 17)
|
||||
#endif
|
||||
#ifndef HWCAP_SHA512
|
||||
// #pragma message("=== HWCAP_SHA512 define === ")
|
||||
#define HWCAP_SHA512 (1 << 21)
|
||||
#endif
|
||||
MY_HWCAP_CHECK_FUNC (SHA512)
|
||||
// MY_HWCAP_CHECK_FUNC (SHA3)
|
||||
#endif
|
||||
|
||||
#endif // __APPLE__
|
||||
#endif // _WIN32
|
||||
|
||||
24
3rdparty/lzma/src/LzFind.c
vendored
24
3rdparty/lzma/src/LzFind.c
vendored
@@ -1,5 +1,5 @@
|
||||
/* LzFind.c -- Match finder for LZ algorithms
|
||||
2024-03-01 : Igor Pavlov : Public domain */
|
||||
: Igor Pavlov : Public domain */
|
||||
|
||||
#include "Precomp.h"
|
||||
|
||||
@@ -404,7 +404,7 @@ int MatchFinder_Create(CMatchFinder *p, UInt32 historySize,
|
||||
const unsigned nbMax =
|
||||
(p->numHashBytes == 2 ? 16 :
|
||||
(p->numHashBytes == 3 ? 24 : 32));
|
||||
if (numBits > nbMax)
|
||||
if (numBits >= nbMax)
|
||||
numBits = nbMax;
|
||||
if (numBits >= 32)
|
||||
hs = (UInt32)0 - 1;
|
||||
@@ -416,14 +416,14 @@ int MatchFinder_Create(CMatchFinder *p, UInt32 historySize,
|
||||
hs |= (256 << kLzHash_CrcShift_2) - 1;
|
||||
{
|
||||
const UInt32 hs2 = MatchFinder_GetHashMask2(p, historySize);
|
||||
if (hs > hs2)
|
||||
if (hs >= hs2)
|
||||
hs = hs2;
|
||||
}
|
||||
hsCur = hs;
|
||||
if (p->expectedDataSize < historySize)
|
||||
{
|
||||
const UInt32 hs2 = MatchFinder_GetHashMask2(p, (UInt32)p->expectedDataSize);
|
||||
if (hsCur > hs2)
|
||||
if (hsCur >= hs2)
|
||||
hsCur = hs2;
|
||||
}
|
||||
}
|
||||
@@ -434,7 +434,7 @@ int MatchFinder_Create(CMatchFinder *p, UInt32 historySize,
|
||||
if (p->expectedDataSize < historySize)
|
||||
{
|
||||
hsCur = MatchFinder_GetHashMask(p, (UInt32)p->expectedDataSize);
|
||||
if (hsCur > hs) // is it possible?
|
||||
if (hsCur >= hs) // is it possible?
|
||||
hsCur = hs;
|
||||
}
|
||||
}
|
||||
@@ -890,7 +890,7 @@ static UInt32 * Hc_GetMatchesSpec(size_t lenLimit, UInt32 curMatch, UInt32 pos,
|
||||
return d;
|
||||
{
|
||||
const Byte *pb = cur - delta;
|
||||
curMatch = son[_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)];
|
||||
curMatch = son[_cyclicBufferPos - delta + (_cyclicBufferPos < delta ? _cyclicBufferSize : 0)];
|
||||
if (pb[maxLen] == cur[maxLen] && *pb == *cur)
|
||||
{
|
||||
UInt32 len = 0;
|
||||
@@ -925,7 +925,7 @@ static UInt32 * Hc_GetMatchesSpec(size_t lenLimit, UInt32 curMatch, UInt32 pos,
|
||||
break;
|
||||
{
|
||||
ptrdiff_t diff;
|
||||
curMatch = son[_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)];
|
||||
curMatch = son[_cyclicBufferPos - delta + (_cyclicBufferPos < delta ? _cyclicBufferSize : 0)];
|
||||
diff = (ptrdiff_t)0 - (ptrdiff_t)delta;
|
||||
if (cur[maxLen] == cur[(ptrdiff_t)maxLen + diff])
|
||||
{
|
||||
@@ -972,7 +972,7 @@ UInt32 * GetMatchesSpec1(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byt
|
||||
// if (curMatch >= pos) { *ptr0 = *ptr1 = kEmptyHashValue; return NULL; }
|
||||
|
||||
cmCheck = (UInt32)(pos - _cyclicBufferSize);
|
||||
if ((UInt32)pos <= _cyclicBufferSize)
|
||||
if ((UInt32)pos < _cyclicBufferSize)
|
||||
cmCheck = 0;
|
||||
|
||||
if (cmCheck < curMatch)
|
||||
@@ -980,7 +980,7 @@ UInt32 * GetMatchesSpec1(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byt
|
||||
{
|
||||
const UInt32 delta = pos - curMatch;
|
||||
{
|
||||
CLzRef *pair = son + ((size_t)(_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1);
|
||||
CLzRef *pair = son + ((size_t)(_cyclicBufferPos - delta + (_cyclicBufferPos < delta ? _cyclicBufferSize : 0)) << 1);
|
||||
const Byte *pb = cur - delta;
|
||||
unsigned len = (len0 < len1 ? len0 : len1);
|
||||
const UInt32 pair0 = pair[0];
|
||||
@@ -1039,7 +1039,7 @@ static void SkipMatchesSpec(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const
|
||||
UInt32 cmCheck;
|
||||
|
||||
cmCheck = (UInt32)(pos - _cyclicBufferSize);
|
||||
if ((UInt32)pos <= _cyclicBufferSize)
|
||||
if ((UInt32)pos < _cyclicBufferSize)
|
||||
cmCheck = 0;
|
||||
|
||||
if (// curMatch >= pos || // failure
|
||||
@@ -1048,7 +1048,7 @@ static void SkipMatchesSpec(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const
|
||||
{
|
||||
const UInt32 delta = pos - curMatch;
|
||||
{
|
||||
CLzRef *pair = son + ((size_t)(_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1);
|
||||
CLzRef *pair = son + ((size_t)(_cyclicBufferPos - delta + (_cyclicBufferPos < delta ? _cyclicBufferSize : 0)) << 1);
|
||||
const Byte *pb = cur - delta;
|
||||
unsigned len = (len0 < len1 ? len0 : len1);
|
||||
if (pb[len] == cur[len])
|
||||
@@ -1595,7 +1595,7 @@ static void Bt5_MatchFinder_Skip(void *_p, UInt32 num)
|
||||
UInt32 pos = p->pos; \
|
||||
UInt32 num2 = num; \
|
||||
/* (p->pos == p->posLimit) is not allowed here !!! */ \
|
||||
{ const UInt32 rem = p->posLimit - pos; if (num2 > rem) num2 = rem; } \
|
||||
{ const UInt32 rem = p->posLimit - pos; if (num2 >= rem) num2 = rem; } \
|
||||
num -= num2; \
|
||||
{ const UInt32 cycPos = p->cyclicBufferPos; \
|
||||
son = p->son + cycPos; \
|
||||
|
||||
10
3rdparty/lzma/src/LzFindMt.c
vendored
10
3rdparty/lzma/src/LzFindMt.c
vendored
@@ -1,5 +1,5 @@
|
||||
/* LzFindMt.c -- multithreaded Match finder for LZ algorithms
|
||||
2024-01-22 : Igor Pavlov : Public domain */
|
||||
: Igor Pavlov : Public domain */
|
||||
|
||||
#include "Precomp.h"
|
||||
|
||||
@@ -82,6 +82,8 @@ extern UInt64 g_NumIters_Bytes;
|
||||
Z7_NO_INLINE
|
||||
static void MtSync_Construct(CMtSync *p)
|
||||
{
|
||||
p->affinityGroup = -1;
|
||||
p->affinityInGroup = 0;
|
||||
p->affinity = 0;
|
||||
p->wasCreated = False;
|
||||
p->csWasInitialized = False;
|
||||
@@ -259,6 +261,12 @@ static WRes MtSync_Create_WRes(CMtSync *p, THREAD_FUNC_TYPE startAddress, void *
|
||||
// return ERROR_TOO_MANY_POSTS; // for debug
|
||||
// return EINVAL; // for debug
|
||||
|
||||
#ifdef _WIN32
|
||||
if (p->affinityGroup >= 0)
|
||||
wres = Thread_Create_With_Group(&p->thread, startAddress, obj,
|
||||
(unsigned)(UInt32)p->affinityGroup, (CAffinityMask)p->affinityInGroup);
|
||||
else
|
||||
#endif
|
||||
if (p->affinity != 0)
|
||||
wres = Thread_Create_With_Affinity(&p->thread, startAddress, obj, (CAffinityMask)p->affinity);
|
||||
else
|
||||
|
||||
4
3rdparty/lzma/src/Lzma2Enc.c
vendored
4
3rdparty/lzma/src/Lzma2Enc.c
vendored
@@ -1,5 +1,5 @@
|
||||
/* Lzma2Enc.c -- LZMA2 Encoder
|
||||
2023-04-13 : Igor Pavlov : Public domain */
|
||||
: Igor Pavlov : Public domain */
|
||||
|
||||
#include "Precomp.h"
|
||||
|
||||
@@ -235,6 +235,7 @@ void Lzma2EncProps_Init(CLzma2EncProps *p)
|
||||
p->numBlockThreads_Reduced = -1;
|
||||
p->numBlockThreads_Max = -1;
|
||||
p->numTotalThreads = -1;
|
||||
p->numThreadGroups = 0;
|
||||
}
|
||||
|
||||
void Lzma2EncProps_Normalize(CLzma2EncProps *p)
|
||||
@@ -781,6 +782,7 @@ SRes Lzma2Enc_Encode2(CLzma2EncHandle p,
|
||||
}
|
||||
|
||||
p->mtCoder.numThreadsMax = (unsigned)p->props.numBlockThreads_Max;
|
||||
p->mtCoder.numThreadGroups = p->props.numThreadGroups;
|
||||
p->mtCoder.expectedDataSize = p->expectedDataSize;
|
||||
|
||||
{
|
||||
|
||||
22
3rdparty/lzma/src/LzmaEnc.c
vendored
22
3rdparty/lzma/src/LzmaEnc.c
vendored
@@ -1,5 +1,5 @@
|
||||
/* LzmaEnc.c -- LZMA Encoder
|
||||
2024-01-24: Igor Pavlov : Public domain */
|
||||
Igor Pavlov : Public domain */
|
||||
|
||||
#include "Precomp.h"
|
||||
|
||||
@@ -62,7 +62,9 @@ void LzmaEncProps_Init(CLzmaEncProps *p)
|
||||
p->lc = p->lp = p->pb = p->algo = p->fb = p->btMode = p->numHashBytes = p->numThreads = -1;
|
||||
p->numHashOutBits = 0;
|
||||
p->writeEndMark = 0;
|
||||
p->affinityGroup = -1;
|
||||
p->affinity = 0;
|
||||
p->affinityInGroup = 0;
|
||||
}
|
||||
|
||||
void LzmaEncProps_Normalize(CLzmaEncProps *p)
|
||||
@@ -72,11 +74,11 @@ void LzmaEncProps_Normalize(CLzmaEncProps *p)
|
||||
p->level = level;
|
||||
|
||||
if (p->dictSize == 0)
|
||||
p->dictSize =
|
||||
( level <= 3 ? ((UInt32)1 << (level * 2 + 16)) :
|
||||
( level <= 6 ? ((UInt32)1 << (level + 19)) :
|
||||
( level <= 7 ? ((UInt32)1 << 25) : ((UInt32)1 << 26)
|
||||
)));
|
||||
p->dictSize = (unsigned)level <= 4 ?
|
||||
(UInt32)1 << (level * 2 + 16) :
|
||||
(unsigned)level <= sizeof(size_t) / 2 + 4 ?
|
||||
(UInt32)1 << (level + 20) :
|
||||
(UInt32)1 << (sizeof(size_t) / 2 + 24);
|
||||
|
||||
if (p->dictSize > p->reduceSize)
|
||||
{
|
||||
@@ -92,8 +94,8 @@ void LzmaEncProps_Normalize(CLzmaEncProps *p)
|
||||
if (p->lp < 0) p->lp = 0;
|
||||
if (p->pb < 0) p->pb = 2;
|
||||
|
||||
if (p->algo < 0) p->algo = (level < 5 ? 0 : 1);
|
||||
if (p->fb < 0) p->fb = (level < 7 ? 32 : 64);
|
||||
if (p->algo < 0) p->algo = (unsigned)level < 5 ? 0 : 1;
|
||||
if (p->fb < 0) p->fb = (unsigned)level < 7 ? 32 : 64;
|
||||
if (p->btMode < 0) p->btMode = (p->algo == 0 ? 0 : 1);
|
||||
if (p->numHashBytes < 0) p->numHashBytes = (p->btMode ? 4 : 5);
|
||||
if (p->mc == 0) p->mc = (16 + ((unsigned)p->fb >> 1)) >> (p->btMode ? 0 : 1);
|
||||
@@ -598,6 +600,10 @@ SRes LzmaEnc_SetProps(CLzmaEncHandle p, const CLzmaEncProps *props2)
|
||||
p->multiThread = (props.numThreads > 1);
|
||||
p->matchFinderMt.btSync.affinity =
|
||||
p->matchFinderMt.hashSync.affinity = props.affinity;
|
||||
p->matchFinderMt.btSync.affinityGroup =
|
||||
p->matchFinderMt.hashSync.affinityGroup = props.affinityGroup;
|
||||
p->matchFinderMt.btSync.affinityInGroup =
|
||||
p->matchFinderMt.hashSync.affinityInGroup = props.affinityInGroup;
|
||||
#endif
|
||||
|
||||
return SZ_OK;
|
||||
|
||||
61
3rdparty/lzma/src/MtCoder.c
vendored
61
3rdparty/lzma/src/MtCoder.c
vendored
@@ -1,5 +1,5 @@
|
||||
/* MtCoder.c -- Multi-thread Coder
|
||||
2023-09-07 : Igor Pavlov : Public domain */
|
||||
: Igor Pavlov : Public domain */
|
||||
|
||||
#include "Precomp.h"
|
||||
|
||||
@@ -39,14 +39,28 @@ void MtProgressThunk_CreateVTable(CMtProgressThunk *p)
|
||||
static THREAD_FUNC_DECL ThreadFunc(void *pp);
|
||||
|
||||
|
||||
static SRes MtCoderThread_CreateAndStart(CMtCoderThread *t)
|
||||
static SRes MtCoderThread_CreateAndStart(CMtCoderThread *t
|
||||
#ifdef _WIN32
|
||||
, CMtCoder * const mtc
|
||||
#endif
|
||||
)
|
||||
{
|
||||
WRes wres = AutoResetEvent_OptCreate_And_Reset(&t->startEvent);
|
||||
// printf("\n====== MtCoderThread_CreateAndStart : \n");
|
||||
if (wres == 0)
|
||||
{
|
||||
t->stop = False;
|
||||
if (!Thread_WasCreated(&t->thread))
|
||||
wres = Thread_Create(&t->thread, ThreadFunc, t);
|
||||
{
|
||||
#ifdef _WIN32
|
||||
if (mtc->numThreadGroups)
|
||||
wres = Thread_Create_With_Group(&t->thread, ThreadFunc, t,
|
||||
ThreadNextGroup_GetNext(&mtc->nextGroup), // group
|
||||
0); // affinityMask
|
||||
else
|
||||
#endif
|
||||
wres = Thread_Create(&t->thread, ThreadFunc, t);
|
||||
}
|
||||
if (wres == 0)
|
||||
wres = Event_Set(&t->startEvent);
|
||||
}
|
||||
@@ -56,6 +70,7 @@ static SRes MtCoderThread_CreateAndStart(CMtCoderThread *t)
|
||||
}
|
||||
|
||||
|
||||
Z7_FORCE_INLINE
|
||||
static void MtCoderThread_Destruct(CMtCoderThread *t)
|
||||
{
|
||||
if (Thread_WasCreated(&t->thread))
|
||||
@@ -85,7 +100,7 @@ static void MtCoderThread_Destruct(CMtCoderThread *t)
|
||||
|
||||
static SRes ThreadFunc2(CMtCoderThread *t)
|
||||
{
|
||||
CMtCoder *mtc = t->mtCoder;
|
||||
CMtCoder * const mtc = t->mtCoder;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
@@ -185,7 +200,11 @@ static SRes ThreadFunc2(CMtCoderThread *t)
|
||||
if (mtc->numStartedThreads < mtc->numStartedThreadsLimit
|
||||
&& mtc->expectedDataSize != readProcessed)
|
||||
{
|
||||
res = MtCoderThread_CreateAndStart(&mtc->threads[mtc->numStartedThreads]);
|
||||
res = MtCoderThread_CreateAndStart(&mtc->threads[mtc->numStartedThreads]
|
||||
#ifdef _WIN32
|
||||
, mtc
|
||||
#endif
|
||||
);
|
||||
if (res == SZ_OK)
|
||||
mtc->numStartedThreads++;
|
||||
else
|
||||
@@ -221,7 +240,7 @@ static SRes ThreadFunc2(CMtCoderThread *t)
|
||||
}
|
||||
|
||||
{
|
||||
CMtCoderBlock *block = &mtc->blocks[bi];
|
||||
CMtCoderBlock * const block = &mtc->blocks[bi];
|
||||
block->res = res;
|
||||
block->bufIndex = bufIndex;
|
||||
block->finished = finished;
|
||||
@@ -311,7 +330,7 @@ static SRes ThreadFunc2(CMtCoderThread *t)
|
||||
|
||||
static THREAD_FUNC_DECL ThreadFunc(void *pp)
|
||||
{
|
||||
CMtCoderThread *t = (CMtCoderThread *)pp;
|
||||
CMtCoderThread * const t = (CMtCoderThread *)pp;
|
||||
for (;;)
|
||||
{
|
||||
if (Event_Wait(&t->startEvent) != 0)
|
||||
@@ -319,7 +338,7 @@ static THREAD_FUNC_DECL ThreadFunc(void *pp)
|
||||
if (t->stop)
|
||||
return 0;
|
||||
{
|
||||
SRes res = ThreadFunc2(t);
|
||||
const SRes res = ThreadFunc2(t);
|
||||
CMtCoder *mtc = t->mtCoder;
|
||||
if (res != SZ_OK)
|
||||
{
|
||||
@@ -328,7 +347,7 @@ static THREAD_FUNC_DECL ThreadFunc(void *pp)
|
||||
|
||||
#ifndef MTCODER_USE_WRITE_THREAD
|
||||
{
|
||||
unsigned numFinished = (unsigned)InterlockedIncrement(&mtc->numFinishedThreads);
|
||||
const unsigned numFinished = (unsigned)InterlockedIncrement(&mtc->numFinishedThreads);
|
||||
if (numFinished == mtc->numStartedThreads)
|
||||
if (Event_Set(&mtc->finishedEvent) != 0)
|
||||
return (THREAD_FUNC_RET_TYPE)SZ_ERROR_THREAD;
|
||||
@@ -346,6 +365,7 @@ void MtCoder_Construct(CMtCoder *p)
|
||||
|
||||
p->blockSize = 0;
|
||||
p->numThreadsMax = 0;
|
||||
p->numThreadGroups = 0;
|
||||
p->expectedDataSize = (UInt64)(Int64)-1;
|
||||
|
||||
p->inStream = NULL;
|
||||
@@ -429,6 +449,8 @@ SRes MtCoder_Code(CMtCoder *p)
|
||||
unsigned i;
|
||||
SRes res = SZ_OK;
|
||||
|
||||
// printf("\n====== MtCoder_Code : \n");
|
||||
|
||||
if (numThreads > MTCODER_THREADS_MAX)
|
||||
numThreads = MTCODER_THREADS_MAX;
|
||||
numBlocksMax = MTCODER_GET_NUM_BLOCKS_FROM_THREADS(numThreads);
|
||||
@@ -492,11 +514,22 @@ SRes MtCoder_Code(CMtCoder *p)
|
||||
|
||||
p->numStartedThreadsLimit = numThreads;
|
||||
p->numStartedThreads = 0;
|
||||
ThreadNextGroup_Init(&p->nextGroup, p->numThreadGroups, 0); // startGroup
|
||||
|
||||
// for (i = 0; i < numThreads; i++)
|
||||
{
|
||||
// here we create new thread for first block.
|
||||
// And each new thread will create another new thread after block reading
|
||||
// until numStartedThreadsLimit is reached.
|
||||
CMtCoderThread *nextThread = &p->threads[p->numStartedThreads++];
|
||||
RINOK(MtCoderThread_CreateAndStart(nextThread))
|
||||
{
|
||||
const SRes res2 = MtCoderThread_CreateAndStart(nextThread
|
||||
#ifdef _WIN32
|
||||
, p
|
||||
#endif
|
||||
);
|
||||
RINOK(res2)
|
||||
}
|
||||
}
|
||||
|
||||
RINOK_THREAD(Event_Set(&p->readEvent))
|
||||
@@ -513,9 +546,9 @@ SRes MtCoder_Code(CMtCoder *p)
|
||||
RINOK_THREAD(Event_Wait(&p->writeEvents[bi]))
|
||||
|
||||
{
|
||||
const CMtCoderBlock *block = &p->blocks[bi];
|
||||
unsigned bufIndex = block->bufIndex;
|
||||
BoolInt finished = block->finished;
|
||||
const CMtCoderBlock * const block = &p->blocks[bi];
|
||||
const unsigned bufIndex = block->bufIndex;
|
||||
const BoolInt finished = block->finished;
|
||||
if (res == SZ_OK && block->res != SZ_OK)
|
||||
res = block->res;
|
||||
|
||||
@@ -545,7 +578,7 @@ SRes MtCoder_Code(CMtCoder *p)
|
||||
}
|
||||
#else
|
||||
{
|
||||
WRes wres = Event_Wait(&p->finishedEvent);
|
||||
const WRes wres = Event_Wait(&p->finishedEvent);
|
||||
res = MY_SRes_HRESULT_FROM_WRes(wres);
|
||||
}
|
||||
#endif
|
||||
|
||||
166
3rdparty/lzma/src/Sha256.c
vendored
166
3rdparty/lzma/src/Sha256.c
vendored
@@ -1,18 +1,14 @@
|
||||
/* Sha256.c -- SHA-256 Hash
|
||||
2024-03-01 : Igor Pavlov : Public domain
|
||||
: Igor Pavlov : Public domain
|
||||
This code is based on public domain code from Wei Dai's Crypto++ library. */
|
||||
|
||||
#include "Precomp.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "CpuArch.h"
|
||||
#include "RotateDefs.h"
|
||||
#include "Sha256.h"
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER < 1900)
|
||||
// #define USE_MY_MM
|
||||
#endif
|
||||
#include "RotateDefs.h"
|
||||
#include "CpuArch.h"
|
||||
|
||||
#ifdef MY_CPU_X86_OR_AMD64
|
||||
#if defined(Z7_LLVM_CLANG_VERSION) && (Z7_LLVM_CLANG_VERSION >= 30800) \
|
||||
@@ -56,7 +52,7 @@ void Z7_FASTCALL Sha256_UpdateBlocks(UInt32 state[8], const Byte *data, size_t n
|
||||
static SHA256_FUNC_UPDATE_BLOCKS g_SHA256_FUNC_UPDATE_BLOCKS = Sha256_UpdateBlocks;
|
||||
static SHA256_FUNC_UPDATE_BLOCKS g_SHA256_FUNC_UPDATE_BLOCKS_HW;
|
||||
|
||||
#define SHA256_UPDATE_BLOCKS(p) p->func_UpdateBlocks
|
||||
#define SHA256_UPDATE_BLOCKS(p) p->v.vars.func_UpdateBlocks
|
||||
#else
|
||||
#define SHA256_UPDATE_BLOCKS(p) Sha256_UpdateBlocks
|
||||
#endif
|
||||
@@ -85,7 +81,7 @@ BoolInt Sha256_SetFunction(CSha256 *p, unsigned algo)
|
||||
return False;
|
||||
#endif
|
||||
|
||||
p->func_UpdateBlocks = func;
|
||||
p->v.vars.func_UpdateBlocks = func;
|
||||
return True;
|
||||
}
|
||||
|
||||
@@ -111,7 +107,7 @@ BoolInt Sha256_SetFunction(CSha256 *p, unsigned algo)
|
||||
|
||||
void Sha256_InitState(CSha256 *p)
|
||||
{
|
||||
p->count = 0;
|
||||
p->v.vars.count = 0;
|
||||
p->state[0] = 0x6a09e667;
|
||||
p->state[1] = 0xbb67ae85;
|
||||
p->state[2] = 0x3c6ef372;
|
||||
@@ -122,9 +118,16 @@ void Sha256_InitState(CSha256 *p)
|
||||
p->state[7] = 0x5be0cd19;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void Sha256_Init(CSha256 *p)
|
||||
{
|
||||
p->func_UpdateBlocks =
|
||||
p->v.vars.func_UpdateBlocks =
|
||||
#ifdef Z7_COMPILER_SHA256_SUPPORTED
|
||||
g_SHA256_FUNC_UPDATE_BLOCKS;
|
||||
#else
|
||||
@@ -133,10 +136,10 @@ void Sha256_Init(CSha256 *p)
|
||||
Sha256_InitState(p);
|
||||
}
|
||||
|
||||
#define S0(x) (rotrFixed(x, 2) ^ rotrFixed(x,13) ^ rotrFixed(x, 22))
|
||||
#define S1(x) (rotrFixed(x, 6) ^ rotrFixed(x,11) ^ rotrFixed(x, 25))
|
||||
#define S0(x) (rotrFixed(x, 2) ^ rotrFixed(x,13) ^ rotrFixed(x,22))
|
||||
#define S1(x) (rotrFixed(x, 6) ^ rotrFixed(x,11) ^ rotrFixed(x,25))
|
||||
#define s0(x) (rotrFixed(x, 7) ^ rotrFixed(x,18) ^ (x >> 3))
|
||||
#define s1(x) (rotrFixed(x,17) ^ rotrFixed(x,19) ^ (x >> 10))
|
||||
#define s1(x) (rotrFixed(x,17) ^ rotrFixed(x,19) ^ (x >>10))
|
||||
|
||||
#define Ch(x,y,z) (z^(x&(y^z)))
|
||||
#define Maj(x,y,z) ((x&y)|(z&(x|y)))
|
||||
@@ -224,12 +227,10 @@ void Sha256_Init(CSha256 *p)
|
||||
|
||||
#endif
|
||||
|
||||
// static
|
||||
extern MY_ALIGN(64)
|
||||
const UInt32 SHA256_K_ARRAY[64];
|
||||
|
||||
MY_ALIGN(64)
|
||||
const UInt32 SHA256_K_ARRAY[64] = {
|
||||
extern
|
||||
MY_ALIGN(64) const UInt32 SHA256_K_ARRAY[64];
|
||||
MY_ALIGN(64) const UInt32 SHA256_K_ARRAY[64] = {
|
||||
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
|
||||
0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
|
||||
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
|
||||
@@ -248,27 +249,29 @@ const UInt32 SHA256_K_ARRAY[64] = {
|
||||
0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
|
||||
};
|
||||
|
||||
#define K SHA256_K_ARRAY
|
||||
|
||||
|
||||
|
||||
|
||||
#define K SHA256_K_ARRAY
|
||||
|
||||
Z7_NO_INLINE
|
||||
void Z7_FASTCALL Sha256_UpdateBlocks(UInt32 state[8], const Byte *data, size_t numBlocks)
|
||||
{
|
||||
UInt32 W
|
||||
#ifdef Z7_SHA256_BIG_W
|
||||
#ifdef Z7_SHA256_BIG_W
|
||||
[64];
|
||||
#else
|
||||
#else
|
||||
[16];
|
||||
#endif
|
||||
|
||||
#endif
|
||||
unsigned j;
|
||||
|
||||
UInt32 a,b,c,d,e,f,g,h;
|
||||
|
||||
#if !defined(Z7_SHA256_UNROLL) || (STEP_MAIN <= 4) || (STEP_PRE <= 4)
|
||||
#if !defined(Z7_SHA256_UNROLL) || (STEP_MAIN <= 4) || (STEP_PRE <= 4)
|
||||
UInt32 tmp;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
if (numBlocks == 0) return;
|
||||
|
||||
a = state[0];
|
||||
b = state[1];
|
||||
c = state[2];
|
||||
@@ -278,7 +281,7 @@ void Z7_FASTCALL Sha256_UpdateBlocks(UInt32 state[8], const Byte *data, size_t n
|
||||
g = state[6];
|
||||
h = state[7];
|
||||
|
||||
while (numBlocks)
|
||||
do
|
||||
{
|
||||
|
||||
for (j = 0; j < 16; j += STEP_PRE)
|
||||
@@ -352,19 +355,11 @@ void Z7_FASTCALL Sha256_UpdateBlocks(UInt32 state[8], const Byte *data, size_t n
|
||||
g += state[6]; state[6] = g;
|
||||
h += state[7]; state[7] = h;
|
||||
|
||||
data += 64;
|
||||
numBlocks--;
|
||||
data += SHA256_BLOCK_SIZE;
|
||||
}
|
||||
|
||||
/* Wipe variables */
|
||||
/* memset(W, 0, sizeof(W)); */
|
||||
while (--numBlocks);
|
||||
}
|
||||
|
||||
#undef S0
|
||||
#undef S1
|
||||
#undef s0
|
||||
#undef s1
|
||||
#undef K
|
||||
|
||||
#define Sha256_UpdateBlock(p) SHA256_UPDATE_BLOCKS(p)(p->state, p->buffer, 1)
|
||||
|
||||
@@ -372,20 +367,15 @@ void Sha256_Update(CSha256 *p, const Byte *data, size_t size)
|
||||
{
|
||||
if (size == 0)
|
||||
return;
|
||||
|
||||
{
|
||||
unsigned pos = (unsigned)p->count & 0x3F;
|
||||
unsigned num;
|
||||
|
||||
p->count += size;
|
||||
|
||||
num = 64 - pos;
|
||||
const unsigned pos = (unsigned)p->v.vars.count & (SHA256_BLOCK_SIZE - 1);
|
||||
const unsigned num = SHA256_BLOCK_SIZE - pos;
|
||||
p->v.vars.count += size;
|
||||
if (num > size)
|
||||
{
|
||||
memcpy(p->buffer + pos, data, size);
|
||||
return;
|
||||
}
|
||||
|
||||
if (pos != 0)
|
||||
{
|
||||
size -= num;
|
||||
@@ -395,9 +385,10 @@ void Sha256_Update(CSha256 *p, const Byte *data, size_t size)
|
||||
}
|
||||
}
|
||||
{
|
||||
size_t numBlocks = size >> 6;
|
||||
const size_t numBlocks = size >> 6;
|
||||
// if (numBlocks)
|
||||
SHA256_UPDATE_BLOCKS(p)(p->state, data, numBlocks);
|
||||
size &= 0x3F;
|
||||
size &= SHA256_BLOCK_SIZE - 1;
|
||||
if (size == 0)
|
||||
return;
|
||||
data += (numBlocks << 6);
|
||||
@@ -408,82 +399,69 @@ void Sha256_Update(CSha256 *p, const Byte *data, size_t size)
|
||||
|
||||
void Sha256_Final(CSha256 *p, Byte *digest)
|
||||
{
|
||||
unsigned pos = (unsigned)p->count & 0x3F;
|
||||
unsigned i;
|
||||
|
||||
unsigned pos = (unsigned)p->v.vars.count & (SHA256_BLOCK_SIZE - 1);
|
||||
p->buffer[pos++] = 0x80;
|
||||
|
||||
if (pos > (64 - 8))
|
||||
if (pos > (SHA256_BLOCK_SIZE - 4 * 2))
|
||||
{
|
||||
while (pos != 64) { p->buffer[pos++] = 0; }
|
||||
// memset(&p->buf.buffer[pos], 0, 64 - pos);
|
||||
while (pos != SHA256_BLOCK_SIZE) { p->buffer[pos++] = 0; }
|
||||
// memset(&p->buf.buffer[pos], 0, SHA256_BLOCK_SIZE - pos);
|
||||
Sha256_UpdateBlock(p);
|
||||
pos = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
if (pos & 3)
|
||||
memset(&p->buffer[pos], 0, (SHA256_BLOCK_SIZE - 4 * 2) - pos);
|
||||
{
|
||||
p->buffer[pos] = 0;
|
||||
p->buffer[pos + 1] = 0;
|
||||
p->buffer[pos + 2] = 0;
|
||||
pos += 3;
|
||||
pos &= ~3;
|
||||
const UInt64 numBits = p->v.vars.count << 3;
|
||||
SetBe32(p->buffer + SHA256_BLOCK_SIZE - 4 * 2, (UInt32)(numBits >> 32))
|
||||
SetBe32(p->buffer + SHA256_BLOCK_SIZE - 4 * 1, (UInt32)(numBits))
|
||||
}
|
||||
{
|
||||
for (; pos < 64 - 8; pos += 4)
|
||||
*(UInt32 *)(&p->buffer[pos]) = 0;
|
||||
}
|
||||
*/
|
||||
|
||||
memset(&p->buffer[pos], 0, (64 - 8) - pos);
|
||||
|
||||
{
|
||||
UInt64 numBits = (p->count << 3);
|
||||
SetBe32(p->buffer + 64 - 8, (UInt32)(numBits >> 32))
|
||||
SetBe32(p->buffer + 64 - 4, (UInt32)(numBits))
|
||||
}
|
||||
|
||||
Sha256_UpdateBlock(p);
|
||||
|
||||
for (i = 0; i < 8; i += 2)
|
||||
#if 1 && defined(MY_CPU_BE)
|
||||
memcpy(digest, p->state, SHA256_DIGEST_SIZE);
|
||||
#else
|
||||
{
|
||||
UInt32 v0 = p->state[i];
|
||||
UInt32 v1 = p->state[(size_t)i + 1];
|
||||
SetBe32(digest , v0)
|
||||
SetBe32(digest + 4, v1)
|
||||
digest += 8;
|
||||
unsigned i;
|
||||
for (i = 0; i < 8; i += 2)
|
||||
{
|
||||
const UInt32 v0 = p->state[i];
|
||||
const UInt32 v1 = p->state[(size_t)i + 1];
|
||||
SetBe32(digest , v0)
|
||||
SetBe32(digest + 4, v1)
|
||||
digest += 4 * 2;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
Sha256_InitState(p);
|
||||
}
|
||||
|
||||
|
||||
void Sha256Prepare(void)
|
||||
{
|
||||
#ifdef Z7_COMPILER_SHA256_SUPPORTED
|
||||
#ifdef Z7_COMPILER_SHA256_SUPPORTED
|
||||
SHA256_FUNC_UPDATE_BLOCKS f, f_hw;
|
||||
f = Sha256_UpdateBlocks;
|
||||
f_hw = NULL;
|
||||
#ifdef MY_CPU_X86_OR_AMD64
|
||||
#ifndef USE_MY_MM
|
||||
#ifdef MY_CPU_X86_OR_AMD64
|
||||
if (CPU_IsSupported_SHA()
|
||||
&& CPU_IsSupported_SSSE3()
|
||||
// && CPU_IsSupported_SSE41()
|
||||
)
|
||||
#endif
|
||||
#else
|
||||
#else
|
||||
if (CPU_IsSupported_SHA2())
|
||||
#endif
|
||||
#endif
|
||||
{
|
||||
// printf("\n========== HW SHA256 ======== \n");
|
||||
f = f_hw = Sha256_UpdateBlocks_HW;
|
||||
}
|
||||
g_SHA256_FUNC_UPDATE_BLOCKS = f;
|
||||
g_SHA256_FUNC_UPDATE_BLOCKS_HW = f_hw;
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
#undef U64C
|
||||
#undef K
|
||||
#undef S0
|
||||
#undef S1
|
||||
#undef s0
|
||||
|
||||
172
3rdparty/lzma/src/Sha256Opt.c
vendored
172
3rdparty/lzma/src/Sha256Opt.c
vendored
@@ -1,18 +1,11 @@
|
||||
/* Sha256Opt.c -- SHA-256 optimized code for SHA-256 hardware instructions
|
||||
2024-03-01 : Igor Pavlov : Public domain */
|
||||
: Igor Pavlov : Public domain */
|
||||
|
||||
#include "Precomp.h"
|
||||
#include "Compiler.h"
|
||||
#include "CpuArch.h"
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#if (_MSC_VER < 1900) && (_MSC_VER >= 1200)
|
||||
// #define USE_MY_MM
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// #define Z7_USE_HW_SHA_STUB // for debug
|
||||
|
||||
#ifdef MY_CPU_X86_OR_AMD64
|
||||
#if defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 1600) // fix that check
|
||||
#define USE_HW_SHA
|
||||
@@ -20,19 +13,14 @@
|
||||
|| defined(Z7_APPLE_CLANG_VERSION) && (Z7_APPLE_CLANG_VERSION >= 50100) \
|
||||
|| defined(Z7_GCC_VERSION) && (Z7_GCC_VERSION >= 40900)
|
||||
#define USE_HW_SHA
|
||||
#if !defined(_INTEL_COMPILER)
|
||||
#if !defined(__INTEL_COMPILER)
|
||||
// icc defines __GNUC__, but icc doesn't support __attribute__(__target__)
|
||||
#if !defined(__SHA__) || !defined(__SSSE3__)
|
||||
#define ATTRIB_SHA __attribute__((__target__("sha,ssse3")))
|
||||
#endif
|
||||
#endif
|
||||
#elif defined(_MSC_VER)
|
||||
#ifdef USE_MY_MM
|
||||
#define USE_VER_MIN 1300
|
||||
#else
|
||||
#define USE_VER_MIN 1900
|
||||
#endif
|
||||
#if (_MSC_VER >= USE_VER_MIN)
|
||||
#if (_MSC_VER >= 1900)
|
||||
#define USE_HW_SHA
|
||||
#else
|
||||
#define Z7_USE_HW_SHA_STUB
|
||||
@@ -47,23 +35,20 @@
|
||||
|
||||
// #pragma message("Sha256 HW")
|
||||
|
||||
|
||||
|
||||
|
||||
// sse/sse2/ssse3:
|
||||
#include <tmmintrin.h>
|
||||
// sha*:
|
||||
#include <immintrin.h>
|
||||
|
||||
#if defined (__clang__) && defined(_MSC_VER)
|
||||
// #if !defined(__SSSE3__)
|
||||
// #endif
|
||||
#if !defined(__SHA__)
|
||||
#include <shaintrin.h>
|
||||
#endif
|
||||
#else
|
||||
|
||||
#ifdef USE_MY_MM
|
||||
#include "My_mm.h"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
@@ -91,60 +76,44 @@ SHA:
|
||||
extern
|
||||
MY_ALIGN(64)
|
||||
const UInt32 SHA256_K_ARRAY[64];
|
||||
|
||||
#define K SHA256_K_ARRAY
|
||||
|
||||
|
||||
#define ADD_EPI32(dest, src) dest = _mm_add_epi32(dest, src);
|
||||
#define SHA256_MSG1(dest, src) dest = _mm_sha256msg1_epu32(dest, src);
|
||||
#define SHA25G_MSG2(dest, src) dest = _mm_sha256msg2_epu32(dest, src);
|
||||
|
||||
#define SHA256_MSG2(dest, src) dest = _mm_sha256msg2_epu32(dest, src);
|
||||
|
||||
#define LOAD_SHUFFLE(m, k) \
|
||||
m = _mm_loadu_si128((const __m128i *)(const void *)(data + (k) * 16)); \
|
||||
m = _mm_shuffle_epi8(m, mask); \
|
||||
|
||||
#define SM1(g0, g1, g2, g3) \
|
||||
SHA256_MSG1(g3, g0); \
|
||||
#define NNN(m0, m1, m2, m3)
|
||||
|
||||
#define SM2(g0, g1, g2, g3) \
|
||||
tmp = _mm_alignr_epi8(g1, g0, 4); \
|
||||
ADD_EPI32(g2, tmp) \
|
||||
SHA25G_MSG2(g2, g1); \
|
||||
|
||||
// #define LS0(k, g0, g1, g2, g3) LOAD_SHUFFLE(g0, k)
|
||||
// #define LS1(k, g0, g1, g2, g3) LOAD_SHUFFLE(g1, k+1)
|
||||
|
||||
|
||||
#define NNN(g0, g1, g2, g3)
|
||||
#define SM1(m1, m2, m3, m0) \
|
||||
SHA256_MSG1(m0, m1); \
|
||||
|
||||
#define SM2(m2, m3, m0, m1) \
|
||||
ADD_EPI32(m0, _mm_alignr_epi8(m3, m2, 4)) \
|
||||
SHA256_MSG2(m0, m3); \
|
||||
|
||||
#define RND2(t0, t1) \
|
||||
t0 = _mm_sha256rnds2_epu32(t0, t1, msg);
|
||||
|
||||
#define RND2_0(m, k) \
|
||||
msg = _mm_add_epi32(m, *(const __m128i *) (const void *) &K[(k) * 4]); \
|
||||
|
||||
|
||||
#define R4(k, m0, m1, m2, m3, OP0, OP1) \
|
||||
msg = _mm_add_epi32(m0, *(const __m128i *) (const void *) &K[(k) * 4]); \
|
||||
RND2(state0, state1); \
|
||||
msg = _mm_shuffle_epi32(msg, 0x0E); \
|
||||
|
||||
|
||||
#define RND2_1 \
|
||||
OP0(m0, m1, m2, m3) \
|
||||
RND2(state1, state0); \
|
||||
|
||||
|
||||
// We use scheme with 3 rounds ahead for SHA256_MSG1 / 2 rounds ahead for SHA256_MSG2
|
||||
|
||||
#define R4(k, g0, g1, g2, g3, OP0, OP1) \
|
||||
RND2_0(g0, k) \
|
||||
OP0(g0, g1, g2, g3) \
|
||||
RND2_1 \
|
||||
OP1(g0, g1, g2, g3) \
|
||||
OP1(m0, m1, m2, m3) \
|
||||
|
||||
#define R16(k, OP0, OP1, OP2, OP3, OP4, OP5, OP6, OP7) \
|
||||
R4 ( (k)*4+0, m0,m1,m2,m3, OP0, OP1 ) \
|
||||
R4 ( (k)*4+1, m1,m2,m3,m0, OP2, OP3 ) \
|
||||
R4 ( (k)*4+2, m2,m3,m0,m1, OP4, OP5 ) \
|
||||
R4 ( (k)*4+3, m3,m0,m1,m2, OP6, OP7 ) \
|
||||
R4 ( (k)*4+0, m0,m1,m2,m3, OP0, OP1 ) \
|
||||
R4 ( (k)*4+1, m1,m2,m3,m0, OP2, OP3 ) \
|
||||
R4 ( (k)*4+2, m2,m3,m0,m1, OP4, OP5 ) \
|
||||
R4 ( (k)*4+3, m3,m0,m1,m2, OP6, OP7 ) \
|
||||
|
||||
#define PREPARE_STATE \
|
||||
tmp = _mm_shuffle_epi32(state0, 0x1B); /* abcd */ \
|
||||
@@ -161,8 +130,9 @@ ATTRIB_SHA
|
||||
void Z7_FASTCALL Sha256_UpdateBlocks_HW(UInt32 state[8], const Byte *data, size_t numBlocks)
|
||||
{
|
||||
const __m128i mask = _mm_set_epi32(0x0c0d0e0f, 0x08090a0b, 0x04050607, 0x00010203);
|
||||
__m128i tmp;
|
||||
__m128i state0, state1;
|
||||
|
||||
|
||||
__m128i tmp, state0, state1;
|
||||
|
||||
if (numBlocks == 0)
|
||||
return;
|
||||
@@ -262,22 +232,10 @@ void Z7_FASTCALL Sha256_UpdateBlocks_HW(UInt32 state[8], const Byte *data, size_
|
||||
#define _ARM_USE_NEW_NEON_INTRINSICS
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#if defined(Z7_MSC_VER_ORIGINAL) && defined(MY_CPU_ARM64)
|
||||
#include <arm64_neon.h>
|
||||
#else
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#if defined(__clang__) && __clang_major__ < 16
|
||||
#if !defined(__ARM_FEATURE_SHA2) && \
|
||||
!defined(__ARM_FEATURE_CRYPTO)
|
||||
@@ -324,41 +282,70 @@ typedef uint32x4_t v128;
|
||||
// typedef __n128 v128; // MSVC
|
||||
|
||||
#ifdef MY_CPU_BE
|
||||
#define MY_rev32_for_LE(x)
|
||||
#define MY_rev32_for_LE(x) x
|
||||
#else
|
||||
#define MY_rev32_for_LE(x) x = vreinterpretq_u32_u8(vrev32q_u8(vreinterpretq_u8_u32(x)))
|
||||
#define MY_rev32_for_LE(x) vrev32q_u8(x)
|
||||
#endif
|
||||
|
||||
#define LOAD_128(_p) (*(const v128 *)(const void *)(_p))
|
||||
#define STORE_128(_p, _v) *(v128 *)(void *)(_p) = (_v)
|
||||
#if 1 // 0 for debug
|
||||
// for arm32: it works slower by some reason than direct code
|
||||
/*
|
||||
for arm32 it generates:
|
||||
MSVC-2022, GCC-9:
|
||||
vld1.32 {d18,d19}, [r10]
|
||||
vst1.32 {d4,d5}, [r3]
|
||||
vld1.8 {d20-d21}, [r4]
|
||||
there is no align hint (like [r10:128]). So instruction allows unaligned access
|
||||
*/
|
||||
#define LOAD_128_32(_p) vld1q_u32(_p)
|
||||
#define LOAD_128_8(_p) vld1q_u8 (_p)
|
||||
#define STORE_128_32(_p, _v) vst1q_u32(_p, _v)
|
||||
#else
|
||||
/*
|
||||
for arm32:
|
||||
MSVC-2022:
|
||||
vldm r10,{d18,d19}
|
||||
vstm r3,{d4,d5}
|
||||
does it require strict alignment?
|
||||
GCC-9:
|
||||
vld1.64 {d30-d31}, [r0:64]
|
||||
vldr d28, [r0, #16]
|
||||
vldr d29, [r0, #24]
|
||||
vst1.64 {d30-d31}, [r0:64]
|
||||
vstr d28, [r0, #16]
|
||||
vstr d29, [r0, #24]
|
||||
there is hint [r0:64], so does it requires 64-bit alignment.
|
||||
*/
|
||||
#define LOAD_128_32(_p) (*(const v128 *)(const void *)(_p))
|
||||
#define LOAD_128_8(_p) vreinterpretq_u8_u32(*(const v128 *)(const void *)(_p))
|
||||
#define STORE_128_32(_p, _v) *(v128 *)(void *)(_p) = (_v)
|
||||
#endif
|
||||
|
||||
#define LOAD_SHUFFLE(m, k) \
|
||||
m = LOAD_128((data + (k) * 16)); \
|
||||
MY_rev32_for_LE(m); \
|
||||
m = vreinterpretq_u32_u8( \
|
||||
MY_rev32_for_LE( \
|
||||
LOAD_128_8(data + (k) * 16))); \
|
||||
|
||||
// K array must be aligned for 16-bytes at least.
|
||||
extern
|
||||
MY_ALIGN(64)
|
||||
const UInt32 SHA256_K_ARRAY[64];
|
||||
|
||||
#define K SHA256_K_ARRAY
|
||||
|
||||
|
||||
#define SHA256_SU0(dest, src) dest = vsha256su0q_u32(dest, src);
|
||||
#define SHA25G_SU1(dest, src2, src3) dest = vsha256su1q_u32(dest, src2, src3);
|
||||
#define SHA256_SU1(dest, src2, src3) dest = vsha256su1q_u32(dest, src2, src3);
|
||||
|
||||
#define SM1(g0, g1, g2, g3) SHA256_SU0(g3, g0)
|
||||
#define SM2(g0, g1, g2, g3) SHA25G_SU1(g2, g0, g1)
|
||||
#define NNN(g0, g1, g2, g3)
|
||||
#define SM1(m0, m1, m2, m3) SHA256_SU0(m3, m0)
|
||||
#define SM2(m0, m1, m2, m3) SHA256_SU1(m2, m0, m1)
|
||||
#define NNN(m0, m1, m2, m3)
|
||||
|
||||
|
||||
#define R4(k, g0, g1, g2, g3, OP0, OP1) \
|
||||
msg = vaddq_u32(g0, *(const v128 *) (const void *) &K[(k) * 4]); \
|
||||
#define R4(k, m0, m1, m2, m3, OP0, OP1) \
|
||||
msg = vaddq_u32(m0, *(const v128 *) (const void *) &K[(k) * 4]); \
|
||||
tmp = state0; \
|
||||
state0 = vsha256hq_u32( state0, state1, msg ); \
|
||||
state1 = vsha256h2q_u32( state1, tmp, msg ); \
|
||||
OP0(g0, g1, g2, g3); \
|
||||
OP1(g0, g1, g2, g3); \
|
||||
OP0(m0, m1, m2, m3); \
|
||||
OP1(m0, m1, m2, m3); \
|
||||
|
||||
|
||||
#define R16(k, OP0, OP1, OP2, OP3, OP4, OP5, OP6, OP7) \
|
||||
@@ -379,8 +366,8 @@ void Z7_FASTCALL Sha256_UpdateBlocks_HW(UInt32 state[8], const Byte *data, size_
|
||||
if (numBlocks == 0)
|
||||
return;
|
||||
|
||||
state0 = LOAD_128(&state[0]);
|
||||
state1 = LOAD_128(&state[4]);
|
||||
state0 = LOAD_128_32(&state[0]);
|
||||
state1 = LOAD_128_32(&state[4]);
|
||||
|
||||
do
|
||||
{
|
||||
@@ -408,8 +395,8 @@ void Z7_FASTCALL Sha256_UpdateBlocks_HW(UInt32 state[8], const Byte *data, size_
|
||||
}
|
||||
while (--numBlocks);
|
||||
|
||||
STORE_128(&state[0], state0);
|
||||
STORE_128(&state[4], state1);
|
||||
STORE_128_32(&state[0], state0);
|
||||
STORE_128_32(&state[4], state1);
|
||||
}
|
||||
|
||||
#endif // USE_HW_SHA
|
||||
@@ -443,13 +430,10 @@ void Z7_FASTCALL Sha256_UpdateBlocks_HW(UInt32 state[8], const Byte *data, size_
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#undef K
|
||||
#undef RND2
|
||||
#undef RND2_0
|
||||
#undef RND2_1
|
||||
|
||||
#undef MY_rev32_for_LE
|
||||
|
||||
#undef NNN
|
||||
#undef LOAD_128
|
||||
#undef STORE_128
|
||||
@@ -457,7 +441,7 @@ void Z7_FASTCALL Sha256_UpdateBlocks_HW(UInt32 state[8], const Byte *data, size_
|
||||
#undef SM1
|
||||
#undef SM2
|
||||
|
||||
#undef NNN
|
||||
|
||||
#undef R4
|
||||
#undef R16
|
||||
#undef PREPARE_STATE
|
||||
|
||||
367
3rdparty/lzma/src/Sort.c
vendored
367
3rdparty/lzma/src/Sort.c
vendored
@@ -1,141 +1,268 @@
|
||||
/* Sort.c -- Sort functions
|
||||
2014-04-05 : Igor Pavlov : Public domain */
|
||||
: Igor Pavlov : Public domain */
|
||||
|
||||
#include "Precomp.h"
|
||||
|
||||
#include "Sort.h"
|
||||
#include "CpuArch.h"
|
||||
|
||||
#define HeapSortDown(p, k, size, temp) \
|
||||
{ for (;;) { \
|
||||
size_t s = (k << 1); \
|
||||
if (s > size) break; \
|
||||
if (s < size && p[s + 1] > p[s]) s++; \
|
||||
if (temp >= p[s]) break; \
|
||||
p[k] = p[s]; k = s; \
|
||||
} p[k] = temp; }
|
||||
#if ( (defined(__GNUC__) && (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1))) \
|
||||
|| (defined(__clang__) && Z7_has_builtin(__builtin_prefetch)) \
|
||||
)
|
||||
// the code with prefetch is slow for small arrays on x86.
|
||||
// So we disable prefetch for x86.
|
||||
#ifndef MY_CPU_X86
|
||||
// #pragma message("Z7_PREFETCH : __builtin_prefetch")
|
||||
#define Z7_PREFETCH(a) __builtin_prefetch((a))
|
||||
#endif
|
||||
|
||||
void HeapSort(UInt32 *p, size_t size)
|
||||
{
|
||||
if (size <= 1)
|
||||
return;
|
||||
p--;
|
||||
{
|
||||
size_t i = size / 2;
|
||||
do
|
||||
{
|
||||
UInt32 temp = p[i];
|
||||
size_t k = i;
|
||||
HeapSortDown(p, k, size, temp)
|
||||
}
|
||||
while (--i != 0);
|
||||
}
|
||||
/*
|
||||
do
|
||||
{
|
||||
size_t k = 1;
|
||||
UInt32 temp = p[size];
|
||||
p[size--] = p[1];
|
||||
HeapSortDown(p, k, size, temp)
|
||||
}
|
||||
while (size > 1);
|
||||
*/
|
||||
while (size > 3)
|
||||
{
|
||||
UInt32 temp = p[size];
|
||||
size_t k = (p[3] > p[2]) ? 3 : 2;
|
||||
p[size--] = p[1];
|
||||
p[1] = p[k];
|
||||
HeapSortDown(p, k, size, temp)
|
||||
}
|
||||
{
|
||||
UInt32 temp = p[size];
|
||||
p[size] = p[1];
|
||||
if (size > 2 && p[2] < temp)
|
||||
{
|
||||
p[1] = p[2];
|
||||
p[2] = temp;
|
||||
}
|
||||
else
|
||||
p[1] = temp;
|
||||
}
|
||||
}
|
||||
#elif defined(_WIN32) // || defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
|
||||
void HeapSort64(UInt64 *p, size_t size)
|
||||
{
|
||||
if (size <= 1)
|
||||
return;
|
||||
p--;
|
||||
{
|
||||
size_t i = size / 2;
|
||||
do
|
||||
{
|
||||
UInt64 temp = p[i];
|
||||
size_t k = i;
|
||||
HeapSortDown(p, k, size, temp)
|
||||
}
|
||||
while (--i != 0);
|
||||
}
|
||||
/*
|
||||
do
|
||||
{
|
||||
size_t k = 1;
|
||||
UInt64 temp = p[size];
|
||||
p[size--] = p[1];
|
||||
HeapSortDown(p, k, size, temp)
|
||||
}
|
||||
while (size > 1);
|
||||
*/
|
||||
while (size > 3)
|
||||
{
|
||||
UInt64 temp = p[size];
|
||||
size_t k = (p[3] > p[2]) ? 3 : 2;
|
||||
p[size--] = p[1];
|
||||
p[1] = p[k];
|
||||
HeapSortDown(p, k, size, temp)
|
||||
}
|
||||
{
|
||||
UInt64 temp = p[size];
|
||||
p[size] = p[1];
|
||||
if (size > 2 && p[2] < temp)
|
||||
{
|
||||
p[1] = p[2];
|
||||
p[2] = temp;
|
||||
}
|
||||
else
|
||||
p[1] = temp;
|
||||
}
|
||||
}
|
||||
#include "7zWindows.h"
|
||||
|
||||
// NOTE: CLANG/GCC/MSVC can define different values for _MM_HINT_T0 / PF_TEMPORAL_LEVEL_1.
|
||||
// For example, clang-cl can generate "prefetcht2" instruction for
|
||||
// PreFetchCacheLine(PF_TEMPORAL_LEVEL_1) call.
|
||||
// But we want to generate "prefetcht0" instruction.
|
||||
// So for CLANG/GCC we must use __builtin_prefetch() in code branch above
|
||||
// instead of PreFetchCacheLine() / _mm_prefetch().
|
||||
|
||||
// New msvc-x86 compiler generates "prefetcht0" instruction for PreFetchCacheLine() call.
|
||||
// But old x86 cpus don't support "prefetcht0".
|
||||
// So we will use PreFetchCacheLine(), only if we are sure that
|
||||
// generated instruction is supported by all cpus of that isa.
|
||||
#if defined(MY_CPU_AMD64) \
|
||||
|| defined(MY_CPU_ARM64) \
|
||||
|| defined(MY_CPU_IA64)
|
||||
// we need to use additional braces for (a) in PreFetchCacheLine call, because
|
||||
// PreFetchCacheLine macro doesn't use braces:
|
||||
// #define PreFetchCacheLine(l, a) _mm_prefetch((CHAR CONST *) a, l)
|
||||
// #pragma message("Z7_PREFETCH : PreFetchCacheLine")
|
||||
#define Z7_PREFETCH(a) PreFetchCacheLine(PF_TEMPORAL_LEVEL_1, (a))
|
||||
#endif
|
||||
|
||||
#endif // _WIN32
|
||||
|
||||
|
||||
#define PREFETCH_NO(p,k,s,size)
|
||||
|
||||
#ifndef Z7_PREFETCH
|
||||
#define SORT_PREFETCH(p,k,s,size)
|
||||
#else
|
||||
|
||||
// #define PREFETCH_LEVEL 2 // use it if cache line is 32-bytes
|
||||
#define PREFETCH_LEVEL 3 // it is fast for most cases (64-bytes cache line prefetch)
|
||||
// #define PREFETCH_LEVEL 4 // it can be faster for big array (128-bytes prefetch)
|
||||
|
||||
#if PREFETCH_LEVEL == 0
|
||||
|
||||
#define SORT_PREFETCH(p,k,s,size)
|
||||
|
||||
#else // PREFETCH_LEVEL != 0
|
||||
|
||||
/*
|
||||
#define HeapSortRefDown(p, vals, n, size, temp) \
|
||||
{ size_t k = n; UInt32 val = vals[temp]; for (;;) { \
|
||||
size_t s = (k << 1); \
|
||||
if (s > size) break; \
|
||||
if (s < size && vals[p[s + 1]] > vals[p[s]]) s++; \
|
||||
if (val >= vals[p[s]]) break; \
|
||||
p[k] = p[s]; k = s; \
|
||||
} p[k] = temp; }
|
||||
if defined(USE_PREFETCH_FOR_ALIGNED_ARRAY)
|
||||
we prefetch one value per cache line.
|
||||
Use it if array is aligned for cache line size (64 bytes)
|
||||
or if array is small (less than L1 cache size).
|
||||
|
||||
void HeapSortRef(UInt32 *p, UInt32 *vals, size_t size)
|
||||
if !defined(USE_PREFETCH_FOR_ALIGNED_ARRAY)
|
||||
we perfetch all cache lines that can be required.
|
||||
it can be faster for big unaligned arrays.
|
||||
*/
|
||||
#define USE_PREFETCH_FOR_ALIGNED_ARRAY
|
||||
|
||||
// s == k * 2
|
||||
#if 0 && PREFETCH_LEVEL <= 3 && defined(MY_CPU_X86_OR_AMD64)
|
||||
// x86 supports (lea r1*8+offset)
|
||||
#define PREFETCH_OFFSET(k,s) ((s) << PREFETCH_LEVEL)
|
||||
#else
|
||||
#define PREFETCH_OFFSET(k,s) ((k) << (PREFETCH_LEVEL + 1))
|
||||
#endif
|
||||
|
||||
#if 1 && PREFETCH_LEVEL <= 3 && defined(USE_PREFETCH_FOR_ALIGNED_ARRAY)
|
||||
#define PREFETCH_ADD_OFFSET 0
|
||||
#else
|
||||
// last offset that can be reqiured in PREFETCH_LEVEL step:
|
||||
#define PREFETCH_RANGE ((2 << PREFETCH_LEVEL) - 1)
|
||||
#define PREFETCH_ADD_OFFSET PREFETCH_RANGE / 2
|
||||
#endif
|
||||
|
||||
#if PREFETCH_LEVEL <= 3
|
||||
|
||||
#ifdef USE_PREFETCH_FOR_ALIGNED_ARRAY
|
||||
#define SORT_PREFETCH(p,k,s,size) \
|
||||
{ const size_t s2 = PREFETCH_OFFSET(k,s) + PREFETCH_ADD_OFFSET; \
|
||||
if (s2 <= size) { \
|
||||
Z7_PREFETCH((p + s2)); \
|
||||
}}
|
||||
#else /* for unaligned array */
|
||||
#define SORT_PREFETCH(p,k,s,size) \
|
||||
{ const size_t s2 = PREFETCH_OFFSET(k,s) + PREFETCH_RANGE; \
|
||||
if (s2 <= size) { \
|
||||
Z7_PREFETCH((p + s2 - PREFETCH_RANGE)); \
|
||||
Z7_PREFETCH((p + s2)); \
|
||||
}}
|
||||
#endif
|
||||
|
||||
#else // PREFETCH_LEVEL > 3
|
||||
|
||||
#ifdef USE_PREFETCH_FOR_ALIGNED_ARRAY
|
||||
#define SORT_PREFETCH(p,k,s,size) \
|
||||
{ const size_t s2 = PREFETCH_OFFSET(k,s) + PREFETCH_RANGE - 16 / 2; \
|
||||
if (s2 <= size) { \
|
||||
Z7_PREFETCH((p + s2 - 16)); \
|
||||
Z7_PREFETCH((p + s2)); \
|
||||
}}
|
||||
#else /* for unaligned array */
|
||||
#define SORT_PREFETCH(p,k,s,size) \
|
||||
{ const size_t s2 = PREFETCH_OFFSET(k,s) + PREFETCH_RANGE; \
|
||||
if (s2 <= size) { \
|
||||
Z7_PREFETCH((p + s2 - PREFETCH_RANGE)); \
|
||||
Z7_PREFETCH((p + s2 - PREFETCH_RANGE / 2)); \
|
||||
Z7_PREFETCH((p + s2)); \
|
||||
}}
|
||||
#endif
|
||||
|
||||
#endif // PREFETCH_LEVEL > 3
|
||||
#endif // PREFETCH_LEVEL != 0
|
||||
#endif // Z7_PREFETCH
|
||||
|
||||
|
||||
#if defined(MY_CPU_ARM64) \
|
||||
/* || defined(MY_CPU_AMD64) */ \
|
||||
/* || defined(MY_CPU_ARM) && !defined(_MSC_VER) */
|
||||
// we want to use cmov, if cmov is very fast:
|
||||
// - this cmov version is slower for clang-x64.
|
||||
// - this cmov version is faster for gcc-arm64 for some fast arm64 cpus.
|
||||
#define Z7_FAST_CMOV_SUPPORTED
|
||||
#endif
|
||||
|
||||
#ifdef Z7_FAST_CMOV_SUPPORTED
|
||||
// we want to use cmov here, if cmov is fast: new arm64 cpus.
|
||||
// we want the compiler to use conditional move for this branch
|
||||
#define GET_MAX_VAL(n0, n1, max_val_slow) if (n0 < n1) n0 = n1;
|
||||
#else
|
||||
// use this branch, if cpu doesn't support fast conditional move.
|
||||
// it uses slow array access reading:
|
||||
#define GET_MAX_VAL(n0, n1, max_val_slow) n0 = max_val_slow;
|
||||
#endif
|
||||
|
||||
#define HeapSortDown(p, k, size, temp, macro_prefetch) \
|
||||
{ \
|
||||
for (;;) { \
|
||||
UInt32 n0, n1; \
|
||||
size_t s = k * 2; \
|
||||
if (s >= size) { \
|
||||
if (s == size) { \
|
||||
n0 = p[s]; \
|
||||
p[k] = n0; \
|
||||
if (temp < n0) k = s; \
|
||||
} \
|
||||
break; \
|
||||
} \
|
||||
n0 = p[k * 2]; \
|
||||
n1 = p[k * 2 + 1]; \
|
||||
s += n0 < n1; \
|
||||
GET_MAX_VAL(n0, n1, p[s]) \
|
||||
if (temp >= n0) break; \
|
||||
macro_prefetch(p, k, s, size) \
|
||||
p[k] = n0; \
|
||||
k = s; \
|
||||
} \
|
||||
p[k] = temp; \
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
stage-1 : O(n) :
|
||||
we generate intermediate partially sorted binary tree:
|
||||
p[0] : it's additional item for better alignment of tree structure in memory.
|
||||
p[1]
|
||||
p[2] p[3]
|
||||
p[4] p[5] p[6] p[7]
|
||||
...
|
||||
p[x] >= p[x * 2]
|
||||
p[x] >= p[x * 2 + 1]
|
||||
|
||||
stage-2 : O(n)*log2(N):
|
||||
we move largest item p[0] from head of tree to the end of array
|
||||
and insert last item to sorted binary tree.
|
||||
*/
|
||||
|
||||
// (p) must be aligned for cache line size (64-bytes) for best performance
|
||||
|
||||
void Z7_FASTCALL HeapSort(UInt32 *p, size_t size)
|
||||
{
|
||||
if (size <= 1)
|
||||
if (size < 2)
|
||||
return;
|
||||
p--;
|
||||
if (size == 2)
|
||||
{
|
||||
size_t i = size / 2;
|
||||
const UInt32 a0 = p[0];
|
||||
const UInt32 a1 = p[1];
|
||||
const unsigned k = a1 < a0;
|
||||
p[k] = a0;
|
||||
p[k ^ 1] = a1;
|
||||
return;
|
||||
}
|
||||
{
|
||||
// stage-1 : O(n)
|
||||
// we transform array to partially sorted binary tree.
|
||||
size_t i = --size / 2;
|
||||
// (size) now is the index of the last item in tree,
|
||||
// if (i)
|
||||
{
|
||||
do
|
||||
{
|
||||
const UInt32 temp = p[i];
|
||||
size_t k = i;
|
||||
HeapSortDown(p, k, size, temp, PREFETCH_NO)
|
||||
}
|
||||
while (--i);
|
||||
}
|
||||
{
|
||||
const UInt32 temp = p[0];
|
||||
const UInt32 a1 = p[1];
|
||||
if (temp < a1)
|
||||
{
|
||||
size_t k = 1;
|
||||
p[0] = a1;
|
||||
HeapSortDown(p, k, size, temp, PREFETCH_NO)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (size < 3)
|
||||
{
|
||||
// size == 2
|
||||
const UInt32 a0 = p[0];
|
||||
p[0] = p[2];
|
||||
p[2] = a0;
|
||||
return;
|
||||
}
|
||||
if (size != 3)
|
||||
{
|
||||
// stage-2 : O(size) * log2(size):
|
||||
// we move largest item p[0] from head to the end of array,
|
||||
// and insert last item to sorted binary tree.
|
||||
do
|
||||
{
|
||||
UInt32 temp = p[i];
|
||||
HeapSortRefDown(p, vals, i, size, temp);
|
||||
const UInt32 temp = p[size];
|
||||
size_t k = p[2] < p[3] ? 3 : 2;
|
||||
p[size--] = p[0];
|
||||
p[0] = p[1];
|
||||
p[1] = p[k];
|
||||
HeapSortDown(p, k, size, temp, SORT_PREFETCH) // PREFETCH_NO
|
||||
}
|
||||
while (--i != 0);
|
||||
while (size != 3);
|
||||
}
|
||||
do
|
||||
{
|
||||
UInt32 temp = p[size];
|
||||
p[size--] = p[1];
|
||||
HeapSortRefDown(p, vals, 1, size, temp);
|
||||
const UInt32 a2 = p[2];
|
||||
const UInt32 a3 = p[3];
|
||||
const size_t k = a2 < a3;
|
||||
p[2] = p[1];
|
||||
p[3] = p[0];
|
||||
p[k] = a3;
|
||||
p[k ^ 1] = a2;
|
||||
}
|
||||
while (size > 1);
|
||||
}
|
||||
*/
|
||||
|
||||
237
3rdparty/lzma/src/Threads.c
vendored
237
3rdparty/lzma/src/Threads.c
vendored
@@ -1,5 +1,5 @@
|
||||
/* Threads.c -- multithreading library
|
||||
2024-03-28 : Igor Pavlov : Public domain */
|
||||
: Igor Pavlov : Public domain */
|
||||
|
||||
#include "Precomp.h"
|
||||
|
||||
@@ -59,6 +59,100 @@ WRes Thread_Wait_Close(CThread *p)
|
||||
return (res != 0 ? res : res2);
|
||||
}
|
||||
|
||||
typedef struct MY_PROCESSOR_NUMBER {
|
||||
WORD Group;
|
||||
BYTE Number;
|
||||
BYTE Reserved;
|
||||
} MY_PROCESSOR_NUMBER, *MY_PPROCESSOR_NUMBER;
|
||||
|
||||
typedef struct MY_GROUP_AFFINITY {
|
||||
#if defined(Z7_GCC_VERSION) && (Z7_GCC_VERSION < 100000)
|
||||
// KAFFINITY is not defined in old mingw
|
||||
ULONG_PTR
|
||||
#else
|
||||
KAFFINITY
|
||||
#endif
|
||||
Mask;
|
||||
WORD Group;
|
||||
WORD Reserved[3];
|
||||
} MY_GROUP_AFFINITY, *MY_PGROUP_AFFINITY;
|
||||
|
||||
typedef BOOL (WINAPI *Func_SetThreadGroupAffinity)(
|
||||
HANDLE hThread,
|
||||
CONST MY_GROUP_AFFINITY *GroupAffinity,
|
||||
MY_PGROUP_AFFINITY PreviousGroupAffinity);
|
||||
|
||||
typedef BOOL (WINAPI *Func_GetThreadGroupAffinity)(
|
||||
HANDLE hThread,
|
||||
MY_PGROUP_AFFINITY GroupAffinity);
|
||||
|
||||
typedef BOOL (WINAPI *Func_GetProcessGroupAffinity)(
|
||||
HANDLE hProcess,
|
||||
PUSHORT GroupCount,
|
||||
PUSHORT GroupArray);
|
||||
|
||||
Z7_DIAGNOSTIC_IGNORE_CAST_FUNCTION
|
||||
|
||||
#if 0
|
||||
#include <stdio.h>
|
||||
#define PRF(x) x
|
||||
/*
|
||||
--
|
||||
before call of SetThreadGroupAffinity()
|
||||
GetProcessGroupAffinity return one group.
|
||||
after call of SetThreadGroupAffinity():
|
||||
GetProcessGroupAffinity return more than group,
|
||||
if SetThreadGroupAffinity() was to another group.
|
||||
--
|
||||
GetProcessAffinityMask MS DOCs:
|
||||
{
|
||||
If the calling process contains threads in multiple groups,
|
||||
the function returns zero for both affinity masks.
|
||||
}
|
||||
but tests in win10 with 2 groups (less than 64 cores total):
|
||||
GetProcessAffinityMask() still returns non-zero affinity masks
|
||||
even after SetThreadGroupAffinity() calls.
|
||||
*/
|
||||
static void PrintProcess_Info()
|
||||
{
|
||||
{
|
||||
const
|
||||
Func_GetProcessGroupAffinity fn_GetProcessGroupAffinity =
|
||||
(Func_GetProcessGroupAffinity) Z7_CAST_FUNC_C GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")),
|
||||
"GetProcessGroupAffinity");
|
||||
if (fn_GetProcessGroupAffinity)
|
||||
{
|
||||
unsigned i;
|
||||
USHORT GroupCounts[64];
|
||||
USHORT GroupCount = Z7_ARRAY_SIZE(GroupCounts);
|
||||
BOOL boolRes = fn_GetProcessGroupAffinity(GetCurrentProcess(),
|
||||
&GroupCount, GroupCounts);
|
||||
printf("\n====== GetProcessGroupAffinity : "
|
||||
"boolRes=%u GroupCounts = %u :",
|
||||
boolRes, (unsigned)GroupCount);
|
||||
for (i = 0; i < GroupCount; i++)
|
||||
printf(" %u", GroupCounts[i]);
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
{
|
||||
DWORD_PTR processAffinityMask, systemAffinityMask;
|
||||
if (GetProcessAffinityMask(GetCurrentProcess(), &processAffinityMask, &systemAffinityMask))
|
||||
{
|
||||
PRF(printf("\n====== GetProcessAffinityMask : "
|
||||
": processAffinityMask=%x, systemAffinityMask=%x\n",
|
||||
(UInt32)processAffinityMask, (UInt32)systemAffinityMask);)
|
||||
}
|
||||
else
|
||||
printf("\n==GetProcessAffinityMask FAIL");
|
||||
}
|
||||
}
|
||||
#else
|
||||
#ifndef USE_THREADS_CreateThread
|
||||
// #define PRF(x)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
WRes Thread_Create(CThread *p, THREAD_FUNC_TYPE func, LPVOID param)
|
||||
{
|
||||
/* Windows Me/98/95: threadId parameter may not be NULL in _beginthreadex/CreateThread functions */
|
||||
@@ -72,7 +166,43 @@ WRes Thread_Create(CThread *p, THREAD_FUNC_TYPE func, LPVOID param)
|
||||
|
||||
unsigned threadId;
|
||||
*p = (HANDLE)(_beginthreadex(NULL, 0, func, param, 0, &threadId));
|
||||
|
||||
|
||||
#if 0 // 1 : for debug
|
||||
{
|
||||
DWORD_PTR prevMask;
|
||||
DWORD_PTR affinity = 1 << 0;
|
||||
prevMask = SetThreadAffinityMask(*p, (DWORD_PTR)affinity);
|
||||
prevMask = prevMask;
|
||||
}
|
||||
#endif
|
||||
#if 0 // 1 : for debug
|
||||
{
|
||||
/* win10: new thread will be created in same group that is assigned to parent thread
|
||||
but affinity mask will contain all allowed threads of that group,
|
||||
even if affinity mask of parent group is not full
|
||||
win11: what group it will be created, if we have set
|
||||
affinity of parent thread with ThreadGroupAffinity?
|
||||
*/
|
||||
const
|
||||
Func_GetThreadGroupAffinity fn =
|
||||
(Func_GetThreadGroupAffinity) Z7_CAST_FUNC_C GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")),
|
||||
"GetThreadGroupAffinity");
|
||||
if (fn)
|
||||
{
|
||||
// BOOL wres2;
|
||||
MY_GROUP_AFFINITY groupAffinity;
|
||||
memset(&groupAffinity, 0, sizeof(groupAffinity));
|
||||
/* wres2 = */ fn(*p, &groupAffinity);
|
||||
PRF(printf("\n==Thread_Create cur = %6u GetThreadGroupAffinity(): "
|
||||
"wres2_BOOL = %u, group=%u mask=%x\n",
|
||||
GetCurrentThreadId(),
|
||||
wres2,
|
||||
groupAffinity.Group,
|
||||
(UInt32)groupAffinity.Mask);)
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
/* maybe we must use errno here, but probably GetLastError() is also OK. */
|
||||
@@ -110,7 +240,84 @@ WRes Thread_Create_With_Affinity(CThread *p, THREAD_FUNC_TYPE func, LPVOID param
|
||||
*/
|
||||
}
|
||||
{
|
||||
DWORD prevSuspendCount = ResumeThread(h);
|
||||
const DWORD prevSuspendCount = ResumeThread(h);
|
||||
/* ResumeThread() returns:
|
||||
0 : was_not_suspended
|
||||
1 : was_resumed
|
||||
-1 : error
|
||||
*/
|
||||
if (prevSuspendCount == (DWORD)-1)
|
||||
wres = GetError();
|
||||
}
|
||||
}
|
||||
|
||||
/* maybe we must use errno here, but probably GetLastError() is also OK. */
|
||||
return wres;
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
WRes Thread_Create_With_Group(CThread *p, THREAD_FUNC_TYPE func, LPVOID param, unsigned group, CAffinityMask affinityMask)
|
||||
{
|
||||
#ifdef USE_THREADS_CreateThread
|
||||
|
||||
UNUSED_VAR(group)
|
||||
UNUSED_VAR(affinityMask)
|
||||
return Thread_Create(p, func, param);
|
||||
|
||||
#else
|
||||
|
||||
/* Windows Me/98/95: threadId parameter may not be NULL in _beginthreadex/CreateThread functions */
|
||||
HANDLE h;
|
||||
WRes wres;
|
||||
unsigned threadId;
|
||||
h = (HANDLE)(_beginthreadex(NULL, 0, func, param, CREATE_SUSPENDED, &threadId));
|
||||
*p = h;
|
||||
wres = HandleToWRes(h);
|
||||
if (h)
|
||||
{
|
||||
// PrintProcess_Info();
|
||||
{
|
||||
const
|
||||
Func_SetThreadGroupAffinity fn =
|
||||
(Func_SetThreadGroupAffinity) Z7_CAST_FUNC_C GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")),
|
||||
"SetThreadGroupAffinity");
|
||||
if (fn)
|
||||
{
|
||||
// WRes wres2;
|
||||
MY_GROUP_AFFINITY groupAffinity, prev_groupAffinity;
|
||||
memset(&groupAffinity, 0, sizeof(groupAffinity));
|
||||
// groupAffinity.Mask must use only bits that supported by current group
|
||||
// (groupAffinity.Mask = 0) means all allowed bits
|
||||
groupAffinity.Mask = affinityMask;
|
||||
groupAffinity.Group = (WORD)group;
|
||||
// wres2 =
|
||||
fn(h, &groupAffinity, &prev_groupAffinity);
|
||||
/*
|
||||
if (groupAffinity.Group == prev_groupAffinity.Group)
|
||||
wres2 = wres2;
|
||||
else
|
||||
wres2 = wres2;
|
||||
if (wres2 == 0)
|
||||
{
|
||||
wres2 = GetError();
|
||||
PRF(printf("\n==SetThreadGroupAffinity error: %u\n", wres2);)
|
||||
}
|
||||
else
|
||||
{
|
||||
PRF(printf("\n==Thread_Create_With_Group::SetThreadGroupAffinity()"
|
||||
" threadId = %6u"
|
||||
" group=%u mask=%x\n",
|
||||
threadId,
|
||||
prev_groupAffinity.Group,
|
||||
(UInt32)prev_groupAffinity.Mask);)
|
||||
}
|
||||
*/
|
||||
}
|
||||
}
|
||||
{
|
||||
const DWORD prevSuspendCount = ResumeThread(h);
|
||||
/* ResumeThread() returns:
|
||||
0 : was_not_suspended
|
||||
1 : was_resumed
|
||||
@@ -297,6 +504,13 @@ WRes Thread_Create(CThread *p, THREAD_FUNC_TYPE func, LPVOID param)
|
||||
return Thread_Create_With_CpuSet(p, func, param, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
WRes Thread_Create_With_Group(CThread *p, THREAD_FUNC_TYPE func, LPVOID param, unsigned group, CAffinityMask affinity)
|
||||
{
|
||||
UNUSED_VAR(group)
|
||||
return Thread_Create_With_Affinity(p, func, param, affinity);
|
||||
}
|
||||
*/
|
||||
|
||||
WRes Thread_Create_With_Affinity(CThread *p, THREAD_FUNC_TYPE func, LPVOID param, CAffinityMask affinity)
|
||||
{
|
||||
@@ -577,5 +791,22 @@ WRes AutoResetEvent_OptCreate_And_Reset(CAutoResetEvent *p)
|
||||
return AutoResetEvent_CreateNotSignaled(p);
|
||||
}
|
||||
|
||||
void ThreadNextGroup_Init(CThreadNextGroup *p, UInt32 numGroups, UInt32 startGroup)
|
||||
{
|
||||
// printf("\n====== ThreadNextGroup_Init numGroups = %x: startGroup=%x\n", numGroups, startGroup);
|
||||
if (numGroups == 0)
|
||||
numGroups = 1;
|
||||
p->NumGroups = numGroups;
|
||||
p->NextGroup = startGroup % numGroups;
|
||||
}
|
||||
|
||||
|
||||
UInt32 ThreadNextGroup_GetNext(CThreadNextGroup *p)
|
||||
{
|
||||
const UInt32 next = p->NextGroup;
|
||||
p->NextGroup = (next + 1) % p->NumGroups;
|
||||
return next;
|
||||
}
|
||||
|
||||
#undef PRF
|
||||
#undef Print
|
||||
|
||||
4
3rdparty/lzma/src/XzCrc64Opt.c
vendored
4
3rdparty/lzma/src/XzCrc64Opt.c
vendored
@@ -1,5 +1,5 @@
|
||||
/* XzCrc64Opt.c -- CRC64 calculation (optimized functions)
|
||||
2023-12-08 : Igor Pavlov : Public domain */
|
||||
: Igor Pavlov : Public domain */
|
||||
|
||||
#include "Precomp.h"
|
||||
|
||||
@@ -235,7 +235,7 @@ CRC64_FUNC_PRE_BE(Z7_CRC64_NUM_TABLES_USE)
|
||||
v = Q32BE(1, w1) ^ Q32BE(0, w0);
|
||||
v ^= Q32BE(3, d1) ^ Q32BE(2, d0);
|
||||
#endif
|
||||
#elif
|
||||
#else
|
||||
#error Stop_Compiling_Bad_CRC64_NUM_TABLES
|
||||
#endif
|
||||
p += Z7_CRC64_NUM_TABLES_USE;
|
||||
|
||||
29
3rdparty/lzma/src/XzDec.c
vendored
29
3rdparty/lzma/src/XzDec.c
vendored
@@ -1,5 +1,5 @@
|
||||
/* XzDec.c -- Xz Decode
|
||||
2024-03-01 : Igor Pavlov : Public domain */
|
||||
: Igor Pavlov : Public domain */
|
||||
|
||||
#include "Precomp.h"
|
||||
|
||||
@@ -59,7 +59,7 @@ unsigned Xz_ReadVarInt(const Byte *p, size_t maxSize, UInt64 *value)
|
||||
|
||||
for (i = 0; i < limit;)
|
||||
{
|
||||
Byte b = p[i];
|
||||
const unsigned b = p[i];
|
||||
*value |= (UInt64)(b & 0x7F) << (7 * i++);
|
||||
if ((b & 0x80) == 0)
|
||||
return (b == 0 && i != 1) ? 0 : i;
|
||||
@@ -796,11 +796,10 @@ SRes Xz_ParseHeader(CXzStreamFlags *p, const Byte *buf)
|
||||
|
||||
static BoolInt Xz_CheckFooter(CXzStreamFlags flags, UInt64 indexSize, const Byte *buf)
|
||||
{
|
||||
return indexSize == (((UInt64)GetUi32(buf + 4) + 1) << 2)
|
||||
&& GetUi32(buf) == CrcCalc(buf + 4, 6)
|
||||
&& flags == GetBe16(buf + 8)
|
||||
&& buf[10] == XZ_FOOTER_SIG_0
|
||||
&& buf[11] == XZ_FOOTER_SIG_1;
|
||||
return indexSize == (((UInt64)GetUi32a(buf + 4) + 1) << 2)
|
||||
&& GetUi32a(buf) == CrcCalc(buf + 4, 6)
|
||||
&& flags == GetBe16a(buf + 8)
|
||||
&& GetUi16a(buf + 10) == (XZ_FOOTER_SIG_0 | (XZ_FOOTER_SIG_1 << 8));
|
||||
}
|
||||
|
||||
#define READ_VARINT_AND_CHECK(buf, pos, size, res) \
|
||||
@@ -1166,7 +1165,7 @@ SRes XzUnpacker_Code(CXzUnpacker *p, Byte *dest, SizeT *destLen,
|
||||
p->indexPreSize = 1 + Xz_WriteVarInt(p->buf + 1, p->numBlocks);
|
||||
p->indexPos = p->indexPreSize;
|
||||
p->indexSize += p->indexPreSize;
|
||||
Sha256_Final(&p->sha, p->shaDigest);
|
||||
Sha256_Final(&p->sha, (Byte *)(void *)p->shaDigest32);
|
||||
Sha256_Init(&p->sha);
|
||||
p->crc = CrcUpdate(CRC_INIT_VAL, p->buf, p->indexPreSize);
|
||||
p->state = XZ_STATE_STREAM_INDEX;
|
||||
@@ -1241,10 +1240,10 @@ SRes XzUnpacker_Code(CXzUnpacker *p, Byte *dest, SizeT *destLen,
|
||||
break;
|
||||
}
|
||||
{
|
||||
Byte digest[XZ_CHECK_SIZE_MAX];
|
||||
UInt32 digest32[XZ_CHECK_SIZE_MAX / 4];
|
||||
p->state = XZ_STATE_BLOCK_HEADER;
|
||||
p->pos = 0;
|
||||
if (XzCheck_Final(&p->check, digest) && memcmp(digest, p->buf, checkSize) != 0)
|
||||
if (XzCheck_Final(&p->check, (void *)digest32) && memcmp(digest32, p->buf, checkSize) != 0)
|
||||
return SZ_ERROR_CRC;
|
||||
if (p->decodeOnlyOneBlock)
|
||||
{
|
||||
@@ -1289,12 +1288,12 @@ SRes XzUnpacker_Code(CXzUnpacker *p, Byte *dest, SizeT *destLen,
|
||||
}
|
||||
else
|
||||
{
|
||||
Byte digest[SHA256_DIGEST_SIZE];
|
||||
UInt32 digest32[SHA256_DIGEST_SIZE / 4];
|
||||
p->state = XZ_STATE_STREAM_INDEX_CRC;
|
||||
p->indexSize += 4;
|
||||
p->pos = 0;
|
||||
Sha256_Final(&p->sha, digest);
|
||||
if (memcmp(digest, p->shaDigest, SHA256_DIGEST_SIZE) != 0)
|
||||
Sha256_Final(&p->sha, (void *)digest32);
|
||||
if (memcmp(digest32, p->shaDigest32, SHA256_DIGEST_SIZE) != 0)
|
||||
return SZ_ERROR_CRC;
|
||||
}
|
||||
}
|
||||
@@ -1313,7 +1312,7 @@ SRes XzUnpacker_Code(CXzUnpacker *p, Byte *dest, SizeT *destLen,
|
||||
const Byte *ptr = p->buf;
|
||||
p->state = XZ_STATE_STREAM_FOOTER;
|
||||
p->pos = 0;
|
||||
if (CRC_GET_DIGEST(p->crc) != GetUi32(ptr))
|
||||
if (CRC_GET_DIGEST(p->crc) != GetUi32a(ptr))
|
||||
return SZ_ERROR_CRC;
|
||||
}
|
||||
break;
|
||||
@@ -1343,7 +1342,7 @@ SRes XzUnpacker_Code(CXzUnpacker *p, Byte *dest, SizeT *destLen,
|
||||
{
|
||||
if (*src != 0)
|
||||
{
|
||||
if (((UInt32)p->padSize & 3) != 0)
|
||||
if ((unsigned)p->padSize & 3)
|
||||
return SZ_ERROR_NO_ARCHIVE;
|
||||
p->pos = 0;
|
||||
p->state = XZ_STATE_STREAM_HEADER;
|
||||
|
||||
8
3rdparty/lzma/src/XzEnc.c
vendored
8
3rdparty/lzma/src/XzEnc.c
vendored
@@ -1,5 +1,5 @@
|
||||
/* XzEnc.c -- Xz Encode
|
||||
2024-03-01 : Igor Pavlov : Public domain */
|
||||
: Igor Pavlov : Public domain */
|
||||
|
||||
#include "Precomp.h"
|
||||
|
||||
@@ -411,6 +411,7 @@ static SRes SeqInFilter_Read(ISeqInStreamPtr pp, void *data, size_t *size)
|
||||
}
|
||||
}
|
||||
|
||||
Z7_FORCE_INLINE
|
||||
static void SeqInFilter_Construct(CSeqInFilter *p)
|
||||
{
|
||||
p->buf = NULL;
|
||||
@@ -418,6 +419,7 @@ static void SeqInFilter_Construct(CSeqInFilter *p)
|
||||
p->vt.Read = SeqInFilter_Read;
|
||||
}
|
||||
|
||||
Z7_FORCE_INLINE
|
||||
static void SeqInFilter_Free(CSeqInFilter *p, ISzAllocPtr alloc)
|
||||
{
|
||||
if (p->StateCoder.p)
|
||||
@@ -507,6 +509,7 @@ void XzFilterProps_Init(CXzFilterProps *p)
|
||||
void XzProps_Init(CXzProps *p)
|
||||
{
|
||||
p->checkId = XZ_CHECK_CRC32;
|
||||
p->numThreadGroups = 0;
|
||||
p->blockSize = XZ_PROPS_BLOCK_SIZE_AUTO;
|
||||
p->numBlockThreads_Reduced = -1;
|
||||
p->numBlockThreads_Max = -1;
|
||||
@@ -689,6 +692,7 @@ typedef struct
|
||||
} CLzma2WithFilters;
|
||||
|
||||
|
||||
Z7_FORCE_INLINE
|
||||
static void Lzma2WithFilters_Construct(CLzma2WithFilters *p)
|
||||
{
|
||||
p->lzma2 = NULL;
|
||||
@@ -712,6 +716,7 @@ static SRes Lzma2WithFilters_Create(CLzma2WithFilters *p, ISzAllocPtr alloc, ISz
|
||||
}
|
||||
|
||||
|
||||
Z7_FORCE_INLINE
|
||||
static void Lzma2WithFilters_Free(CLzma2WithFilters *p, ISzAllocPtr alloc)
|
||||
{
|
||||
#ifdef USE_SUBBLOCK
|
||||
@@ -1236,6 +1241,7 @@ SRes XzEnc_Encode(CXzEncHandle p, ISeqOutStreamPtr outStream, ISeqInStreamPtr in
|
||||
}
|
||||
|
||||
p->mtCoder.numThreadsMax = (unsigned)props->numBlockThreads_Max;
|
||||
p->mtCoder.numThreadGroups = props->numThreadGroups;
|
||||
p->mtCoder.expectedDataSize = p->expectedDataSize;
|
||||
|
||||
RINOK(MtCoder_Code(&p->mtCoder))
|
||||
|
||||
265
3rdparty/lzma/src/XzIn.c
vendored
265
3rdparty/lzma/src/XzIn.c
vendored
@@ -1,38 +1,39 @@
|
||||
/* XzIn.c - Xz input
|
||||
2023-09-07 : Igor Pavlov : Public domain */
|
||||
: Igor Pavlov : Public domain */
|
||||
|
||||
#include "Precomp.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "7zCrc.h"
|
||||
#include "CpuArch.h"
|
||||
#include "Xz.h"
|
||||
#include "CpuArch.h"
|
||||
|
||||
/*
|
||||
#define XZ_FOOTER_SIG_CHECK(p) (memcmp((p), XZ_FOOTER_SIG, XZ_FOOTER_SIG_SIZE) == 0)
|
||||
*/
|
||||
#define XZ_FOOTER_SIG_CHECK(p) ((p)[0] == XZ_FOOTER_SIG_0 && (p)[1] == XZ_FOOTER_SIG_1)
|
||||
|
||||
#define XZ_FOOTER_12B_ALIGNED16_SIG_CHECK(p) \
|
||||
(GetUi16a((const Byte *)(const void *)(p) + 10) == \
|
||||
(XZ_FOOTER_SIG_0 | (XZ_FOOTER_SIG_1 << 8)))
|
||||
|
||||
SRes Xz_ReadHeader(CXzStreamFlags *p, ISeqInStreamPtr inStream)
|
||||
{
|
||||
Byte sig[XZ_STREAM_HEADER_SIZE];
|
||||
UInt32 data32[XZ_STREAM_HEADER_SIZE / 4];
|
||||
size_t processedSize = XZ_STREAM_HEADER_SIZE;
|
||||
RINOK(SeqInStream_ReadMax(inStream, sig, &processedSize))
|
||||
RINOK(SeqInStream_ReadMax(inStream, data32, &processedSize))
|
||||
if (processedSize != XZ_STREAM_HEADER_SIZE
|
||||
|| memcmp(sig, XZ_SIG, XZ_SIG_SIZE) != 0)
|
||||
|| memcmp(data32, XZ_SIG, XZ_SIG_SIZE) != 0)
|
||||
return SZ_ERROR_NO_ARCHIVE;
|
||||
return Xz_ParseHeader(p, sig);
|
||||
return Xz_ParseHeader(p, (const Byte *)(const void *)data32);
|
||||
}
|
||||
|
||||
#define READ_VARINT_AND_CHECK(buf, pos, size, res) \
|
||||
{ const unsigned s = Xz_ReadVarInt(buf + pos, size - pos, res); \
|
||||
#define READ_VARINT_AND_CHECK(buf, size, res) \
|
||||
{ const unsigned s = Xz_ReadVarInt(buf, size, res); \
|
||||
if (s == 0) return SZ_ERROR_ARCHIVE; \
|
||||
pos += s; }
|
||||
size -= s; \
|
||||
buf += s; \
|
||||
}
|
||||
|
||||
SRes XzBlock_ReadHeader(CXzBlock *p, ISeqInStreamPtr inStream, BoolInt *isIndex, UInt32 *headerSizeRes)
|
||||
{
|
||||
MY_ALIGN(4)
|
||||
Byte header[XZ_BLOCK_HEADER_SIZE_MAX];
|
||||
unsigned headerSize;
|
||||
*headerSizeRes = 0;
|
||||
@@ -57,8 +58,12 @@ SRes XzBlock_ReadHeader(CXzBlock *p, ISeqInStreamPtr inStream, BoolInt *isIndex,
|
||||
return XzBlock_Parse(p, header);
|
||||
}
|
||||
|
||||
|
||||
#define ADD_SIZE_CHECK(size, val) \
|
||||
{ const UInt64 newSize = size + (val); if (newSize < size) return XZ_SIZE_OVERFLOW; size = newSize; }
|
||||
{ const UInt64 newSize = size + (val); \
|
||||
if (newSize < size) return XZ_SIZE_OVERFLOW; \
|
||||
size = newSize; \
|
||||
}
|
||||
|
||||
UInt64 Xz_GetUnpackSize(const CXzStream *p)
|
||||
{
|
||||
@@ -82,76 +87,85 @@ UInt64 Xz_GetPackSize(const CXzStream *p)
|
||||
return size;
|
||||
}
|
||||
|
||||
/*
|
||||
SRes XzBlock_ReadFooter(CXzBlock *p, CXzStreamFlags f, ISeqInStreamPtr inStream)
|
||||
{
|
||||
return SeqInStream_Read(inStream, p->check, XzFlags_GetCheckSize(f));
|
||||
}
|
||||
*/
|
||||
|
||||
static SRes Xz_ReadIndex2(CXzStream *p, const Byte *buf, size_t size, ISzAllocPtr alloc)
|
||||
// input;
|
||||
// CXzStream (p) is empty object.
|
||||
// size != 0
|
||||
// (size & 3) == 0
|
||||
// (buf) is aligned for at least 4 bytes.
|
||||
// output:
|
||||
// p->numBlocks is number of allocated items in p->blocks
|
||||
// p->blocks[*] values must be ignored, if function returns error.
|
||||
static SRes Xz_ParseIndex(CXzStream *p, const Byte *buf, size_t size, ISzAllocPtr alloc)
|
||||
{
|
||||
size_t numBlocks, pos = 1;
|
||||
UInt32 crc;
|
||||
|
||||
size_t numBlocks;
|
||||
if (size < 5 || buf[0] != 0)
|
||||
return SZ_ERROR_ARCHIVE;
|
||||
|
||||
size -= 4;
|
||||
crc = CrcCalc(buf, size);
|
||||
if (crc != GetUi32(buf + size))
|
||||
return SZ_ERROR_ARCHIVE;
|
||||
|
||||
{
|
||||
const UInt32 crc = CrcCalc(buf, size);
|
||||
if (crc != GetUi32a(buf + size))
|
||||
return SZ_ERROR_ARCHIVE;
|
||||
}
|
||||
buf++;
|
||||
size--;
|
||||
{
|
||||
UInt64 numBlocks64;
|
||||
READ_VARINT_AND_CHECK(buf, pos, size, &numBlocks64)
|
||||
READ_VARINT_AND_CHECK(buf, size, &numBlocks64)
|
||||
// (numBlocks64) is 63-bit value, so we can calculate (numBlocks64 * 2):
|
||||
if (numBlocks64 * 2 > size)
|
||||
return SZ_ERROR_ARCHIVE;
|
||||
if (numBlocks64 >= ((size_t)1 << (sizeof(size_t) * 8 - 1)) / sizeof(CXzBlockSizes))
|
||||
return SZ_ERROR_MEM; // SZ_ERROR_ARCHIVE
|
||||
numBlocks = (size_t)numBlocks64;
|
||||
if (numBlocks != numBlocks64 || numBlocks * 2 > size)
|
||||
return SZ_ERROR_ARCHIVE;
|
||||
}
|
||||
|
||||
Xz_Free(p, alloc);
|
||||
if (numBlocks != 0)
|
||||
// Xz_Free(p, alloc); // it's optional, because (p) is empty already
|
||||
if (numBlocks)
|
||||
{
|
||||
size_t i;
|
||||
p->numBlocks = numBlocks;
|
||||
p->blocks = (CXzBlockSizes *)ISzAlloc_Alloc(alloc, sizeof(CXzBlockSizes) * numBlocks);
|
||||
if (!p->blocks)
|
||||
CXzBlockSizes *blocks = (CXzBlockSizes *)ISzAlloc_Alloc(alloc, sizeof(CXzBlockSizes) * numBlocks);
|
||||
if (!blocks)
|
||||
return SZ_ERROR_MEM;
|
||||
for (i = 0; i < numBlocks; i++)
|
||||
p->blocks = blocks;
|
||||
p->numBlocks = numBlocks;
|
||||
// the caller will call Xz_Free() in case of error
|
||||
do
|
||||
{
|
||||
CXzBlockSizes *block = &p->blocks[i];
|
||||
READ_VARINT_AND_CHECK(buf, pos, size, &block->totalSize)
|
||||
READ_VARINT_AND_CHECK(buf, pos, size, &block->unpackSize)
|
||||
if (block->totalSize == 0)
|
||||
READ_VARINT_AND_CHECK(buf, size, &blocks->totalSize)
|
||||
READ_VARINT_AND_CHECK(buf, size, &blocks->unpackSize)
|
||||
if (blocks->totalSize == 0)
|
||||
return SZ_ERROR_ARCHIVE;
|
||||
blocks++;
|
||||
}
|
||||
while (--numBlocks);
|
||||
}
|
||||
while ((pos & 3) != 0)
|
||||
if (buf[pos++] != 0)
|
||||
if (size >= 4)
|
||||
return SZ_ERROR_ARCHIVE;
|
||||
while (size)
|
||||
if (buf[--size])
|
||||
return SZ_ERROR_ARCHIVE;
|
||||
return (pos == size) ? SZ_OK : SZ_ERROR_ARCHIVE;
|
||||
return SZ_OK;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
static SRes Xz_ReadIndex(CXzStream *p, ILookInStreamPtr stream, UInt64 indexSize, ISzAllocPtr alloc)
|
||||
{
|
||||
SRes res;
|
||||
size_t size;
|
||||
Byte *buf;
|
||||
if (indexSize > ((UInt32)1 << 31))
|
||||
return SZ_ERROR_UNSUPPORTED;
|
||||
if (indexSize >= ((size_t)1 << (sizeof(size_t) * 8 - 1)))
|
||||
return SZ_ERROR_MEM; // SZ_ERROR_ARCHIVE
|
||||
size = (size_t)indexSize;
|
||||
if (size != indexSize)
|
||||
return SZ_ERROR_UNSUPPORTED;
|
||||
buf = (Byte *)ISzAlloc_Alloc(alloc, size);
|
||||
if (!buf)
|
||||
return SZ_ERROR_MEM;
|
||||
res = LookInStream_Read2(stream, buf, size, SZ_ERROR_UNSUPPORTED);
|
||||
if (res == SZ_OK)
|
||||
res = Xz_ReadIndex2(p, buf, size, alloc);
|
||||
res = Xz_ParseIndex(p, buf, size, alloc);
|
||||
ISzAlloc_Free(alloc, buf);
|
||||
return res;
|
||||
}
|
||||
*/
|
||||
|
||||
static SRes LookInStream_SeekRead_ForArc(ILookInStreamPtr stream, UInt64 offset, void *buf, size_t size)
|
||||
{
|
||||
@@ -160,84 +174,102 @@ static SRes LookInStream_SeekRead_ForArc(ILookInStreamPtr stream, UInt64 offset,
|
||||
/* return LookInStream_Read2(stream, buf, size, SZ_ERROR_NO_ARCHIVE); */
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
in:
|
||||
(*startOffset) is position in (stream) where xz_stream must be finished.
|
||||
out:
|
||||
if returns SZ_OK, then (*startOffset) is position in stream that shows start of xz_stream.
|
||||
*/
|
||||
static SRes Xz_ReadBackward(CXzStream *p, ILookInStreamPtr stream, Int64 *startOffset, ISzAllocPtr alloc)
|
||||
{
|
||||
UInt64 indexSize;
|
||||
Byte buf[XZ_STREAM_FOOTER_SIZE];
|
||||
#define TEMP_BUF_SIZE (1 << 10)
|
||||
UInt32 buf32[TEMP_BUF_SIZE / 4];
|
||||
UInt64 pos = (UInt64)*startOffset;
|
||||
|
||||
if ((pos & 3) != 0 || pos < XZ_STREAM_FOOTER_SIZE)
|
||||
if ((pos & 3) || pos < XZ_STREAM_FOOTER_SIZE)
|
||||
return SZ_ERROR_NO_ARCHIVE;
|
||||
|
||||
pos -= XZ_STREAM_FOOTER_SIZE;
|
||||
RINOK(LookInStream_SeekRead_ForArc(stream, pos, buf, XZ_STREAM_FOOTER_SIZE))
|
||||
RINOK(LookInStream_SeekRead_ForArc(stream, pos, buf32, XZ_STREAM_FOOTER_SIZE))
|
||||
|
||||
if (!XZ_FOOTER_SIG_CHECK(buf + 10))
|
||||
if (!XZ_FOOTER_12B_ALIGNED16_SIG_CHECK(buf32))
|
||||
{
|
||||
UInt32 total = 0;
|
||||
pos += XZ_STREAM_FOOTER_SIZE;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
size_t i;
|
||||
#define TEMP_BUF_SIZE (1 << 10)
|
||||
Byte temp[TEMP_BUF_SIZE];
|
||||
|
||||
i = (pos > TEMP_BUF_SIZE) ? TEMP_BUF_SIZE : (size_t)pos;
|
||||
// pos != 0
|
||||
// (pos & 3) == 0
|
||||
size_t i = pos >= TEMP_BUF_SIZE ? TEMP_BUF_SIZE : (size_t)pos;
|
||||
pos -= i;
|
||||
RINOK(LookInStream_SeekRead_ForArc(stream, pos, temp, i))
|
||||
total += (UInt32)i;
|
||||
for (; i != 0; i--)
|
||||
if (temp[i - 1] != 0)
|
||||
RINOK(LookInStream_SeekRead_ForArc(stream, pos, buf32, i))
|
||||
i /= 4;
|
||||
do
|
||||
if (buf32[i - 1] != 0)
|
||||
break;
|
||||
if (i != 0)
|
||||
{
|
||||
if ((i & 3) != 0)
|
||||
return SZ_ERROR_NO_ARCHIVE;
|
||||
pos += i;
|
||||
break;
|
||||
}
|
||||
if (pos < XZ_STREAM_FOOTER_SIZE || total > (1 << 16))
|
||||
while (--i);
|
||||
|
||||
pos += i * 4;
|
||||
#define XZ_STREAM_BACKWARD_READING_PAD_MAX (1 << 16)
|
||||
// here we don't support rare case with big padding for xz stream.
|
||||
// so we have padding limit for backward reading.
|
||||
if ((UInt64)*startOffset - pos > XZ_STREAM_BACKWARD_READING_PAD_MAX)
|
||||
return SZ_ERROR_NO_ARCHIVE;
|
||||
if (i)
|
||||
break;
|
||||
}
|
||||
|
||||
// we try to open xz stream after skipping zero padding.
|
||||
// ((UInt64)*startOffset == pos) is possible here!
|
||||
if (pos < XZ_STREAM_FOOTER_SIZE)
|
||||
return SZ_ERROR_NO_ARCHIVE;
|
||||
pos -= XZ_STREAM_FOOTER_SIZE;
|
||||
RINOK(LookInStream_SeekRead_ForArc(stream, pos, buf, XZ_STREAM_FOOTER_SIZE))
|
||||
if (!XZ_FOOTER_SIG_CHECK(buf + 10))
|
||||
RINOK(LookInStream_SeekRead_ForArc(stream, pos, buf32, XZ_STREAM_FOOTER_SIZE))
|
||||
if (!XZ_FOOTER_12B_ALIGNED16_SIG_CHECK(buf32))
|
||||
return SZ_ERROR_NO_ARCHIVE;
|
||||
}
|
||||
|
||||
p->flags = (CXzStreamFlags)GetBe16(buf + 8);
|
||||
|
||||
p->flags = (CXzStreamFlags)GetBe16a(buf32 + 2);
|
||||
if (!XzFlags_IsSupported(p->flags))
|
||||
return SZ_ERROR_UNSUPPORTED;
|
||||
|
||||
{
|
||||
/* to eliminate GCC 6.3 warning:
|
||||
dereferencing type-punned pointer will break strict-aliasing rules */
|
||||
const Byte *buf_ptr = buf;
|
||||
if (GetUi32(buf_ptr) != CrcCalc(buf + 4, 6))
|
||||
const UInt32 *buf_ptr = buf32;
|
||||
if (GetUi32a(buf_ptr) != CrcCalc(buf32 + 1, 6))
|
||||
return SZ_ERROR_ARCHIVE;
|
||||
}
|
||||
|
||||
indexSize = ((UInt64)GetUi32(buf + 4) + 1) << 2;
|
||||
|
||||
if (pos < indexSize)
|
||||
return SZ_ERROR_ARCHIVE;
|
||||
|
||||
pos -= indexSize;
|
||||
RINOK(LookInStream_SeekTo(stream, pos))
|
||||
RINOK(Xz_ReadIndex(p, stream, indexSize, alloc))
|
||||
|
||||
{
|
||||
UInt64 totalSize = Xz_GetPackSize(p);
|
||||
if (totalSize == XZ_SIZE_OVERFLOW
|
||||
|| totalSize >= ((UInt64)1 << 63)
|
||||
|| pos < totalSize + XZ_STREAM_HEADER_SIZE)
|
||||
const UInt64 indexSize = ((UInt64)GetUi32a(buf32 + 1) + 1) << 2;
|
||||
if (pos < indexSize)
|
||||
return SZ_ERROR_ARCHIVE;
|
||||
pos -= (totalSize + XZ_STREAM_HEADER_SIZE);
|
||||
pos -= indexSize;
|
||||
// v25.00: relaxed indexSize check. We allow big index table.
|
||||
// if (indexSize > ((UInt32)1 << 31))
|
||||
if (indexSize >= ((size_t)1 << (sizeof(size_t) * 8 - 1)))
|
||||
return SZ_ERROR_MEM; // SZ_ERROR_ARCHIVE
|
||||
RINOK(LookInStream_SeekTo(stream, pos))
|
||||
// RINOK(Xz_ReadIndex(p, stream, indexSize, alloc))
|
||||
{
|
||||
SRes res;
|
||||
const size_t size = (size_t)indexSize;
|
||||
// if (size != indexSize) return SZ_ERROR_UNSUPPORTED;
|
||||
Byte *buf = (Byte *)ISzAlloc_Alloc(alloc, size);
|
||||
if (!buf)
|
||||
return SZ_ERROR_MEM;
|
||||
res = LookInStream_Read2(stream, buf, size, SZ_ERROR_UNSUPPORTED);
|
||||
if (res == SZ_OK)
|
||||
res = Xz_ParseIndex(p, buf, size, alloc);
|
||||
ISzAlloc_Free(alloc, buf);
|
||||
RINOK(res)
|
||||
}
|
||||
}
|
||||
{
|
||||
UInt64 total = Xz_GetPackSize(p);
|
||||
if (total == XZ_SIZE_OVERFLOW || total >= ((UInt64)1 << 63))
|
||||
return SZ_ERROR_ARCHIVE;
|
||||
total += XZ_STREAM_HEADER_SIZE;
|
||||
if (pos < total)
|
||||
return SZ_ERROR_ARCHIVE;
|
||||
pos -= total;
|
||||
RINOK(LookInStream_SeekTo(stream, pos))
|
||||
*startOffset = (Int64)pos;
|
||||
}
|
||||
@@ -246,7 +278,6 @@ static SRes Xz_ReadBackward(CXzStream *p, ILookInStreamPtr stream, Int64 *startO
|
||||
CSecToRead secToRead;
|
||||
SecToRead_CreateVTable(&secToRead);
|
||||
secToRead.realStream = stream;
|
||||
|
||||
RINOK(Xz_ReadHeader(&headerFlags, &secToRead.vt))
|
||||
return (p->flags == headerFlags) ? SZ_OK : SZ_ERROR_ARCHIVE;
|
||||
}
|
||||
@@ -257,8 +288,7 @@ static SRes Xz_ReadBackward(CXzStream *p, ILookInStreamPtr stream, Int64 *startO
|
||||
|
||||
void Xzs_Construct(CXzs *p)
|
||||
{
|
||||
p->num = p->numAllocated = 0;
|
||||
p->streams = 0;
|
||||
Xzs_CONSTRUCT(p)
|
||||
}
|
||||
|
||||
void Xzs_Free(CXzs *p, ISzAllocPtr alloc)
|
||||
@@ -268,7 +298,7 @@ void Xzs_Free(CXzs *p, ISzAllocPtr alloc)
|
||||
Xz_Free(&p->streams[i], alloc);
|
||||
ISzAlloc_Free(alloc, p->streams);
|
||||
p->num = p->numAllocated = 0;
|
||||
p->streams = 0;
|
||||
p->streams = NULL;
|
||||
}
|
||||
|
||||
UInt64 Xzs_GetNumBlocks(const CXzs *p)
|
||||
@@ -307,34 +337,49 @@ UInt64 Xzs_GetPackSize(const CXzs *p)
|
||||
SRes Xzs_ReadBackward(CXzs *p, ILookInStreamPtr stream, Int64 *startOffset, ICompressProgressPtr progress, ISzAllocPtr alloc)
|
||||
{
|
||||
Int64 endOffset = 0;
|
||||
// it's supposed that CXzs object is empty here.
|
||||
// if CXzs object is not empty, it will add new streams to that non-empty object.
|
||||
// Xzs_Free(p, alloc); // it's optional call to empty CXzs object.
|
||||
RINOK(ILookInStream_Seek(stream, &endOffset, SZ_SEEK_END))
|
||||
*startOffset = endOffset;
|
||||
for (;;)
|
||||
{
|
||||
CXzStream st;
|
||||
SRes res;
|
||||
Xz_Construct(&st);
|
||||
Xz_CONSTRUCT(&st)
|
||||
res = Xz_ReadBackward(&st, stream, startOffset, alloc);
|
||||
// if (res == SZ_OK), then (*startOffset) is start offset of new stream if
|
||||
// if (res != SZ_OK), then (*startOffset) is unchend or it's expected start offset of stream with error
|
||||
st.startOffset = (UInt64)*startOffset;
|
||||
RINOK(res)
|
||||
// we must store (st) object to array, or we must free (st) local object.
|
||||
if (res != SZ_OK)
|
||||
{
|
||||
Xz_Free(&st, alloc);
|
||||
return res;
|
||||
}
|
||||
if (p->num == p->numAllocated)
|
||||
{
|
||||
const size_t newNum = p->num + p->num / 4 + 1;
|
||||
void *data = ISzAlloc_Alloc(alloc, newNum * sizeof(CXzStream));
|
||||
if (!data)
|
||||
{
|
||||
Xz_Free(&st, alloc);
|
||||
return SZ_ERROR_MEM;
|
||||
}
|
||||
p->numAllocated = newNum;
|
||||
if (p->num != 0)
|
||||
memcpy(data, p->streams, p->num * sizeof(CXzStream));
|
||||
ISzAlloc_Free(alloc, p->streams);
|
||||
p->streams = (CXzStream *)data;
|
||||
}
|
||||
// we use direct copying of raw data from local variable (st) to object in array.
|
||||
// so we don't need to call Xz_Free(&st, alloc) after copying and after p->num++
|
||||
p->streams[p->num++] = st;
|
||||
if (*startOffset == 0)
|
||||
break;
|
||||
RINOK(LookInStream_SeekTo(stream, (UInt64)*startOffset))
|
||||
return SZ_OK;
|
||||
// seek operation is optional:
|
||||
// RINOK(LookInStream_SeekTo(stream, (UInt64)*startOffset))
|
||||
if (progress && ICompressProgress_Progress(progress, (UInt64)(endOffset - *startOffset), (UInt64)(Int64)-1) != SZ_OK)
|
||||
return SZ_ERROR_PROGRESS;
|
||||
}
|
||||
return SZ_OK;
|
||||
}
|
||||
|
||||
15
3rdparty/winwil/include/wil/Tracelogging.h
vendored
15
3rdparty/winwil/include/wil/Tracelogging.h
vendored
@@ -65,7 +65,7 @@
|
||||
#define _wiltlg_STRINGIZE_imp(x) #x
|
||||
#define _wiltlg_LSTRINGIZE(x) _wiltlg_LSTRINGIZE_imp1(x)
|
||||
#define _wiltlg_LSTRINGIZE_imp1(x) _wiltlg_LSTRINGIZE_imp2(#x)
|
||||
#define _wiltlg_LSTRINGIZE_imp2(s) L##s
|
||||
#define _wiltlg_LSTRINGIZE_imp2(s) L"" #s
|
||||
|
||||
/*
|
||||
Macro __TRACELOGGING_DEFINE_PROVIDER_STORAGE_LINK(name1, name2):
|
||||
@@ -261,7 +261,8 @@ namespace details
|
||||
public:
|
||||
StoredCallContextInfo() WI_NOEXCEPT
|
||||
{
|
||||
::ZeroMemory(this, sizeof(*this));
|
||||
// Suppress '-Wnontrivial-memcall' with 'static_cast'
|
||||
::ZeroMemory(static_cast<void*>(this), sizeof(*this));
|
||||
}
|
||||
|
||||
StoredCallContextInfo(StoredCallContextInfo&& other) WI_NOEXCEPT : StoredCallContextInfo()
|
||||
@@ -1510,7 +1511,7 @@ public: \
|
||||
|
||||
#define __IMPLEMENT_CALLCONTEXT_CLASS(ActivityClassName) \
|
||||
protected: \
|
||||
ActivityClassName(_In_opt_ void**, PCSTR contextName, _In_opt_ _Printf_format_string_ PCSTR formatString, _In_opt_ va_list argList) : \
|
||||
ActivityClassName(_In_opt_ void**, PCSTR contextName, _In_ _Printf_format_string_ PCSTR formatString, _In_opt_ va_list argList) : \
|
||||
ActivityBase(contextName) \
|
||||
{ \
|
||||
GetCallContext()->SetMessage(formatString, argList); \
|
||||
@@ -6444,7 +6445,13 @@ namespace details
|
||||
|
||||
if (*lastNamespaceNode)
|
||||
{
|
||||
root.swap((*lastNamespaceNode)->next);
|
||||
// Delete everything from the current root to the lastNamespaceNode
|
||||
// (inclusive), considering the possibility that they are the same. Continue
|
||||
// processing from the node following lastNamespaceNode, if any. root will
|
||||
// be made to point to that.
|
||||
auto newRoot = wistd::move((*lastNamespaceNode)->next);
|
||||
const auto toDelete = wistd::move(root);
|
||||
root = wistd::move(newRoot);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
140
3rdparty/winwil/include/wil/com.h
vendored
140
3rdparty/winwil/include/wil/com.h
vendored
@@ -16,12 +16,13 @@
|
||||
#include <WeakReference.h>
|
||||
#include <combaseapi.h>
|
||||
#include "result.h"
|
||||
#include "win32_helpers.h"
|
||||
#include "resource.h" // last to ensure _COMBASEAPI_H_ protected definitions are available
|
||||
|
||||
#if __has_include(<tuple>)
|
||||
#if WIL_USE_STL && WI_HAS_INCLUDE(<tuple>, 1) // Tuple is C++11... assume available
|
||||
#include <tuple>
|
||||
#endif
|
||||
#if __has_include(<type_traits>)
|
||||
#if WIL_USE_STL && WI_HAS_INCLUDE(<type_traits>, 1) // Type traits is old... assume available
|
||||
#include <type_traits>
|
||||
#endif
|
||||
|
||||
@@ -2112,7 +2113,7 @@ wil::com_ptr_nothrow<Interface> CoGetClassObjectNoThrow(DWORD dwClsContext = CLS
|
||||
return CoGetClassObjectNoThrow<Interface>(__uuidof(Class), dwClsContext);
|
||||
}
|
||||
|
||||
#if __cpp_lib_apply && __has_include(<type_traits>)
|
||||
#if __cpp_lib_apply && WIL_USE_STL && WI_HAS_INCLUDE(<type_traits>, 1)
|
||||
/// @cond
|
||||
namespace details
|
||||
{
|
||||
@@ -2246,7 +2247,7 @@ auto try_com_multi_query(IUnknown* obj)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // __cpp_lib_apply && __has_include(<type_traits>)
|
||||
#endif // __cpp_lib_apply && WI_HAS_INCLUDE(<type_traits>, 1)
|
||||
|
||||
#pragma endregion
|
||||
|
||||
@@ -3135,8 +3136,7 @@ void for_each_site(_In_opt_ IUnknown* siteInput, TLambda&& callback)
|
||||
|
||||
#endif // __IObjectWithSite_INTERFACE_DEFINED__
|
||||
|
||||
// if C++17 or greater
|
||||
#if WIL_HAS_CXX_17
|
||||
#if __cpp_deduction_guides >= 201703L
|
||||
#ifdef WIL_ENABLE_EXCEPTIONS
|
||||
/// @cond
|
||||
namespace details
|
||||
@@ -3303,14 +3303,14 @@ WI_NODISCARD auto make_range(IEnumXxx* enumPtr)
|
||||
|
||||
using enumerator_type = com_iterator<TActualStoredType, IEnumXxx>;
|
||||
|
||||
IEnumXxx* m_enumerator{};
|
||||
wil::com_ptr<IEnumXxx> m_enumerator{};
|
||||
iterator_range(IEnumXxx* enumPtr) : m_enumerator(enumPtr)
|
||||
{
|
||||
}
|
||||
|
||||
WI_NODISCARD auto begin()
|
||||
{
|
||||
return enumerator_type(m_enumerator);
|
||||
return enumerator_type(m_enumerator.get());
|
||||
}
|
||||
|
||||
WI_NODISCARD constexpr auto end() const noexcept
|
||||
@@ -3322,9 +3322,131 @@ WI_NODISCARD auto make_range(IEnumXxx* enumPtr)
|
||||
return iterator_range(enumPtr);
|
||||
}
|
||||
|
||||
#endif // WIL_HAS_CXX_17
|
||||
template <typename TEnum, typename = wistd::enable_if_t<wil::details::has_next_v<TEnum*>>>
|
||||
auto make_range(const wil::com_ptr<TEnum>& e)
|
||||
{
|
||||
using Enumerated = typename wil::details::com_enumerator_traits<TEnum>::smart_result;
|
||||
return wil::make_range<Enumerated>(e.get());
|
||||
}
|
||||
|
||||
#ifdef __IShellItemArray_INTERFACE_DEFINED__
|
||||
inline auto make_range(IShellItemArray* sia)
|
||||
{
|
||||
wil::com_ptr<IEnumShellItems> enumShellItems;
|
||||
THROW_IF_FAILED(sia->EnumItems(&enumShellItems));
|
||||
return make_range(enumShellItems);
|
||||
}
|
||||
|
||||
inline auto make_range(const wil::com_ptr<IShellItemArray>& sia)
|
||||
{
|
||||
return make_range(sia.get());
|
||||
}
|
||||
#endif // __IShellItemArray_INTERFACE_DEFINED__
|
||||
|
||||
#endif // __cpp_deduction_guides >= 201703L
|
||||
#endif // WIL_ENABLE_EXCEPTIONS
|
||||
|
||||
#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP | WINAPI_PARTITION_SYSTEM)
|
||||
|
||||
namespace details
|
||||
{
|
||||
inline void CoDisableCallCancellationNull()
|
||||
{
|
||||
(void)::CoDisableCallCancellation(nullptr);
|
||||
}
|
||||
} // namespace details
|
||||
|
||||
/** RAII support for making cross-apartment (or cross process) COM calls with a timeout applied to them.
|
||||
* When this is active any timed out calls will fail with an RPC error code such as RPC_E_CALL_CANCELED.
|
||||
* This is a shared timeout that applies to all calls made on the current thread for the lifetime of
|
||||
* the wil::com_timeout object.
|
||||
* A periodic timer is used to cancel calls that have been blocked too long. If multiple blocking calls
|
||||
* are made, and multiple are timing out, then there may be a total delay of (timeoutInMilliseconds * N)
|
||||
* where N is the number of calls.
|
||||
~~~
|
||||
{
|
||||
auto timeout = wil::com_timeout(5000);
|
||||
remote_object->BlockingCOMCall();
|
||||
remote_object->AnotherBlockingCOMCall();
|
||||
}
|
||||
~~~
|
||||
*/
|
||||
template <typename err_policy>
|
||||
class com_timeout_t
|
||||
{
|
||||
public:
|
||||
com_timeout_t(DWORD timeoutInMilliseconds) : m_threadId(GetCurrentThreadId())
|
||||
{
|
||||
const HRESULT cancelEnablementResult = CoEnableCallCancellation(nullptr);
|
||||
err_policy::HResult(cancelEnablementResult);
|
||||
if (SUCCEEDED(cancelEnablementResult))
|
||||
{
|
||||
m_ensureDisable.activate();
|
||||
|
||||
m_timer.reset(CreateThreadpoolTimer(&com_timeout_t::timer_callback, this, nullptr));
|
||||
err_policy::LastErrorIfFalse(static_cast<bool>(m_timer));
|
||||
if (m_timer)
|
||||
{
|
||||
FILETIME ft = filetime::get_system_time();
|
||||
ft = filetime::add(ft, filetime::convert_msec_to_100ns(timeoutInMilliseconds));
|
||||
SetThreadpoolTimer(m_timer.get(), &ft, timeoutInMilliseconds, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool timed_out() const
|
||||
{
|
||||
return m_timedOut;
|
||||
}
|
||||
|
||||
operator bool() const noexcept
|
||||
{
|
||||
// All construction calls must succeed to provide us with a non-null m_timer value.
|
||||
return static_cast<bool>(m_timer);
|
||||
}
|
||||
|
||||
private:
|
||||
// Disable use of new as this class should only be declared on the stack, never the heap.
|
||||
void* operator new(size_t) = delete;
|
||||
void* operator new[](size_t) = delete;
|
||||
|
||||
// not copyable or movable because the timer_callback receives "this"
|
||||
com_timeout_t(com_timeout_t const&) = delete;
|
||||
void operator=(com_timeout_t const&) = delete;
|
||||
|
||||
static void __stdcall timer_callback(PTP_CALLBACK_INSTANCE /*instance*/, PVOID context, PTP_TIMER /*timer*/)
|
||||
{
|
||||
// The timer is waited upon during destruction so it is safe to rely on the this pointer in context.
|
||||
com_timeout_t* self = static_cast<com_timeout_t*>(context);
|
||||
if (SUCCEEDED(CoCancelCall(self->m_threadId, 0)))
|
||||
{
|
||||
self->m_timedOut = true;
|
||||
}
|
||||
}
|
||||
|
||||
wil::unique_call<decltype(&details::CoDisableCallCancellationNull), details::CoDisableCallCancellationNull, false> m_ensureDisable{};
|
||||
DWORD m_threadId{};
|
||||
bool m_timedOut{};
|
||||
|
||||
// The threadpool timer goes last so that it destructs first, waiting until the timer callback has completed.
|
||||
wil::unique_threadpool_timer_nocancel m_timer;
|
||||
};
|
||||
|
||||
// Error-policy driven forms of com_timeout
|
||||
|
||||
#ifdef WIL_ENABLE_EXCEPTIONS
|
||||
//! COM timeout, errors throw exceptions (see @ref com_timeout_t for details)
|
||||
using com_timeout = com_timeout_t<err_exception_policy>;
|
||||
#endif
|
||||
|
||||
//! COM timeout, errors return error codes (see @ref com_timeout_t for details)
|
||||
using com_timeout_nothrow = com_timeout_t<err_returncode_policy>;
|
||||
|
||||
//! COM timeout, errors fail-fast (see @ref com_timeout_t for details)
|
||||
using com_timeout_failfast = com_timeout_t<err_failfast_policy>;
|
||||
|
||||
#endif // WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP | WINAPI_PARTITION_SYSTEM)
|
||||
|
||||
} // namespace wil
|
||||
|
||||
#endif
|
||||
|
||||
64
3rdparty/winwil/include/wil/common.h
vendored
64
3rdparty/winwil/include/wil/common.h
vendored
@@ -69,15 +69,14 @@
|
||||
|
||||
/// @cond
|
||||
#if defined(_MSVC_LANG)
|
||||
#define __WI_SUPPRESS_4127_S \
|
||||
__pragma(warning(push)) __pragma(warning(disable : 4127)) __pragma(warning(disable : 26498)) __pragma(warning(disable : 4245))
|
||||
#define __WI_SUPPRESS_4127_E __pragma(warning(pop))
|
||||
#define __WI_SUPPRESS_NULLPTR_ANALYSIS __pragma(warning(suppress : 28285)) __pragma(warning(suppress : 6504))
|
||||
#define __WI_SUPPRESS_BREAKING_WARNINGS_S __pragma(warning(push)) __pragma(warning(disable : 4127 26498 4245 26814))
|
||||
#define __WI_SUPPRESS_BREAKING_WARNINGS_E __pragma(warning(pop))
|
||||
#define __WI_SUPPRESS_NULLPTR_ANALYSIS __pragma(warning(suppress : 28285 6504))
|
||||
#define __WI_SUPPRESS_NONINIT_ANALYSIS __pragma(warning(suppress : 26495))
|
||||
#define __WI_SUPPRESS_NOEXCEPT_ANALYSIS __pragma(warning(suppress : 26439))
|
||||
#else
|
||||
#define __WI_SUPPRESS_4127_S
|
||||
#define __WI_SUPPRESS_4127_E
|
||||
#define __WI_SUPPRESS_BREAKING_WARNINGS_S
|
||||
#define __WI_SUPPRESS_BREAKING_WARNINGS_E
|
||||
#define __WI_SUPPRESS_NULLPTR_ANALYSIS
|
||||
#define __WI_SUPPRESS_NONINIT_ANALYSIS
|
||||
#define __WI_SUPPRESS_NOEXCEPT_ANALYSIS
|
||||
@@ -306,6 +305,29 @@ static_assert(WIL_EXCEPTION_MODE <= 2, "Invalid exception mode");
|
||||
#error Must enable exceptions when WIL_EXCEPTION_MODE == 1
|
||||
#endif
|
||||
|
||||
#ifdef WIL_DOXYGEN
|
||||
/** This define is used to control whether or not WIL assumes safe access to the STL.
|
||||
This define can be set manually (1 to enable, 0 to disable), otherwise heuristics will be applied in an attempt to
|
||||
deduce whether or not the STL is available and can be safely used.
|
||||
*/
|
||||
#define WIL_USE_STL 1
|
||||
#elif !defined(WIL_USE_STL)
|
||||
#if !defined(WIL_ENABLE_EXCEPTIONS) || !defined(__has_include)
|
||||
// Assume it's not safe to use the STL when:
|
||||
// * Exceptions are not enabled, OR
|
||||
// * We can't check for header presence
|
||||
#define WIL_USE_STL 0
|
||||
#else
|
||||
// Check for several STL headers that have been around since the dawn of time
|
||||
#if __has_include(<algorithm>) && __has_include(<exception>) && __has_include(<iterator>) && __has_include(<new>) && \
|
||||
__has_include(<string>) && __has_include(<utility>) && __has_include(<vector>)
|
||||
#define WIL_USE_STL 1
|
||||
#else
|
||||
#define WIL_USE_STL 0
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/// @cond
|
||||
#ifndef WIL_ITERATOR_DEBUG_LEVEL
|
||||
// NOTE: See the definition of 'RESULT_DEBUG' for commentary on the use of 'WIL_KERNEL_MODE' below
|
||||
@@ -373,19 +395,19 @@ check fails as opposed to the invalid parameter handler that the STL invokes. Th
|
||||
#endif
|
||||
|
||||
/// @cond
|
||||
#if (__cplusplus >= 201703) || (_MSVC_LANG >= 201703)
|
||||
#define WIL_HAS_CXX_17 1
|
||||
#else
|
||||
#define WIL_HAS_CXX_17 0
|
||||
#endif
|
||||
|
||||
// Until we'll have C++17 enabled in our code base, we're falling back to SAL
|
||||
#define WI_NODISCARD __WI_LIBCPP_NODISCARD_ATTRIBUTE
|
||||
/// @endcond
|
||||
|
||||
/// @cond
|
||||
#define __R_ENABLE_IF_IS_CLASS(ptrType) wistd::enable_if_t<wistd::is_class<ptrType>::value, void*> = nullptr
|
||||
#define __R_ENABLE_IF_IS_NOT_CLASS(ptrType) wistd::enable_if_t<!wistd::is_class<ptrType>::value, void*> = nullptr
|
||||
|
||||
// Uses the __has_include macro, if available. Otherwise uses a user-provided fallback. E.g. the fallback could always
|
||||
// default to true or false, or it could do something like a C++ standard version check
|
||||
#ifdef __has_include
|
||||
#define WI_HAS_INCLUDE(header, fallback) __has_include(header)
|
||||
#else
|
||||
#define WI_HAS_INCLUDE(header, fallback) (fallback)
|
||||
#endif
|
||||
/// @endcond
|
||||
|
||||
//! @defgroup bitwise Bitwise Inspection and Manipulation
|
||||
@@ -690,32 +712,32 @@ boolean, BOOLEAN, and classes with an explicit bool cast.
|
||||
@param val The logical bool expression
|
||||
@return A C++ bool representing the evaluation of `val`. */
|
||||
template <typename T, __R_ENABLE_IF_IS_CLASS(T)>
|
||||
_Post_satisfies_(return == static_cast<bool>(val)) __forceinline constexpr bool verify_bool(const T& val) WI_NOEXCEPT
|
||||
_Post_satisfies_(return == static_cast<bool>(val)) inline constexpr bool verify_bool(const T& val) WI_NOEXCEPT
|
||||
{
|
||||
return static_cast<bool>(val);
|
||||
}
|
||||
|
||||
template <typename T, __R_ENABLE_IF_IS_NOT_CLASS(T)>
|
||||
__forceinline constexpr bool verify_bool(T /*val*/) WI_NOEXCEPT
|
||||
inline constexpr bool verify_bool(T /*val*/) WI_NOEXCEPT
|
||||
{
|
||||
static_assert(!wistd::is_same<T, T>::value, "Wrong Type: bool/BOOL/BOOLEAN/boolean expected");
|
||||
return false;
|
||||
}
|
||||
|
||||
template <>
|
||||
_Post_satisfies_(return == val) __forceinline constexpr bool verify_bool<bool>(bool val) WI_NOEXCEPT
|
||||
_Post_satisfies_(return == val) inline constexpr bool verify_bool<bool>(bool val) WI_NOEXCEPT
|
||||
{
|
||||
return val;
|
||||
}
|
||||
|
||||
template <>
|
||||
_Post_satisfies_(return == (val != 0)) __forceinline constexpr bool verify_bool<int>(int val) WI_NOEXCEPT
|
||||
_Post_satisfies_(return == (val != 0)) inline constexpr bool verify_bool<int>(int val) WI_NOEXCEPT
|
||||
{
|
||||
return (val != 0);
|
||||
}
|
||||
|
||||
template <>
|
||||
_Post_satisfies_(return == (val != 0)) __forceinline constexpr bool verify_bool<unsigned char>(unsigned char val) WI_NOEXCEPT
|
||||
_Post_satisfies_(return == (val != 0)) inline constexpr bool verify_bool<unsigned char>(unsigned char val) WI_NOEXCEPT
|
||||
{
|
||||
return (val != 0);
|
||||
}
|
||||
@@ -726,7 +748,7 @@ accept any `int` value as long as that is the underlying typedef behind `BOOL`.
|
||||
@param val The Win32 BOOL returning expression
|
||||
@return A Win32 BOOL representing the evaluation of `val`. */
|
||||
template <typename T>
|
||||
_Post_satisfies_(return == val) __forceinline constexpr int verify_BOOL(T val) WI_NOEXCEPT
|
||||
_Post_satisfies_(return == val) inline constexpr int verify_BOOL(T val) WI_NOEXCEPT
|
||||
{
|
||||
// Note: Written in terms of 'int' as BOOL is actually: typedef int BOOL;
|
||||
static_assert((wistd::is_same<T, int>::value), "Wrong Type: BOOL expected");
|
||||
@@ -820,7 +842,7 @@ namespace details
|
||||
: sizeof(val) == 2 ? static_cast<unsigned short>(val) \
|
||||
: sizeof(val) == 4 ? static_cast<unsigned long>(val) \
|
||||
: static_cast<unsigned long long>(val)) __pragma(warning(pop)))
|
||||
#define __WI_IS_UNSIGNED_SINGLE_FLAG_SET(val) ((val) && !((val) & ((val)-1)))
|
||||
#define __WI_IS_UNSIGNED_SINGLE_FLAG_SET(val) ((val) && !((val) & ((val) - 1)))
|
||||
#define __WI_IS_SINGLE_FLAG_SET(val) __WI_IS_UNSIGNED_SINGLE_FLAG_SET(__WI_MAKE_UNSIGNED(val))
|
||||
|
||||
template <typename TVal, typename TFlags>
|
||||
|
||||
6
3rdparty/winwil/include/wil/filesystem.h
vendored
6
3rdparty/winwil/include/wil/filesystem.h
vendored
@@ -26,6 +26,10 @@
|
||||
#include "win32_helpers.h"
|
||||
#include "resource.h"
|
||||
|
||||
#if WIL_USE_STL
|
||||
#include <iterator>
|
||||
#endif
|
||||
|
||||
namespace wil
|
||||
{
|
||||
//! Determines if a path is an extended length path that can be used to access paths longer than MAX_PATH.
|
||||
@@ -403,7 +407,7 @@ struct next_entry_offset_iterator
|
||||
using value_type = T;
|
||||
using pointer = const T*;
|
||||
using reference = const T&;
|
||||
#ifdef _XUTILITY_
|
||||
#if WIL_USE_STL
|
||||
using iterator_category = ::std::forward_iterator_tag;
|
||||
#endif
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user