Compare commits

..

66 Commits

Author SHA1 Message Date
WerWolv
8802a8e861 build: Bumped version to 1.33.2 2024-03-23 10:15:12 +01:00
WerWolv
8a01f3cc6b impr: Show hint if advanced data information section doesn't yield any result 2024-03-22 21:33:57 +01:00
WerWolv
7d7bd0d642 fix: Splash screen being scaled incorrectly 2024-03-22 17:53:43 +01:00
WerWolv
2b1be7bc30 fix: Icons not being scaled correctly anymore 2024-03-22 17:53:34 +01:00
WerWolv
9df21c7952 fix: Missing include in notification toasts 2024-03-22 17:52:55 +01:00
Nobutaka Mantani
70b9ceba72 build: Added support patches for FreeBSD (#1584)
This pull request fixes build on FreeBSD. The changes are conditioned
with `#if defined(__FreeBSD__)` preprocessor macro and they should not
affect build for other operating systems.

---------

Co-authored-by: Nik <werwolv98@gmail.com>
Co-authored-by: iTrooz <hey@itrooz.fr>
2024-03-22 17:52:38 +01:00
WerWolv
27f3c634ba impr: Load unifont at correct size
Fixes #1604
2024-03-22 17:50:45 +01:00
WerWolv
33b091e9e6 fix: Decompress functions not extracting full data
Thanks a lot to tocklime
2024-03-22 17:47:25 +01:00
WerWolv
976caf53ae fix: Prevent view providers from pointing to themselves and being saved as recent provider
#1607
2024-03-22 17:47:14 +01:00
WerWolv
c2bb6e37b1 fix: Crash when trying to open unopenable file 2024-03-22 17:46:50 +01:00
WerWolv
b4b47ff60e fix: Make sure pattern runtime is always properly configured 2024-03-22 17:46:24 +01:00
WerWolv
db2ad0951f fix: File open achievement not triggering when dropping a file onto ImHex 2024-03-22 17:46:13 +01:00
WerWolv
e5969c5d2e fix: Potential crash when log file is unavailable 2024-03-22 17:45:59 +01:00
WerWolv
b1d6086c0c fix: Control characters ending up in log files 2024-03-22 17:45:38 +01:00
WerWolv
7dfcbb15a4 fix: Infinite loop when exporting selection to file 2024-03-22 17:45:11 +01:00
WerWolv
4d470385d8 fix: Right clicking reverse selected regions deselecting it 2024-03-22 17:45:02 +01:00
WerWolv
b0f010690c fix: Various issues with the virtual file system 2024-03-22 17:44:49 +01:00
WerWolv
360ae718b9 fix: Advanced data information not showing up correctly 2024-03-22 17:44:36 +01:00
WerWolv
6f45a7939a fix: Diffing option popup flickering when opening 2024-03-22 17:43:00 +01:00
WerWolv
e27a4df8b0 fix: Base address issues with the data inspector and copy as array option
Fixes #1595
2024-03-22 17:42:17 +01:00
WerWolv
84cd3f989b fix: Denying server contact leaving crash upload option enabled
Fixes #1594
2024-03-22 17:41:35 +01:00
WerWolv
2e09a4e567 fix: ImHex using a ton of CPU power on Linux 2024-03-22 17:41:03 +01:00
WerWolv
0ce1a87cbf fix: Toasts not printing their message to the console correctly 2024-03-22 17:40:51 +01:00
WerWolv
6a158f99d7 fix: Highlighting not updating correctly when changing bookmark region
Fixes #1591
2024-03-22 17:40:06 +01:00
WerWolv
77f46317f0 fix: Update all task progress not increasing correctly 2024-03-22 17:39:56 +01:00
WerWolv
4c98f6bca6 fix: View provider not saving top-level data to project file 2024-03-22 17:39:41 +01:00
WerWolv
77bc45ca17 fix: View provider not correctly saving its state to a project file 2024-03-22 17:39:17 +01:00
iTrooz
1647fa9446 fix: fix ui plugin linking to pl when libimhex already does it (#1583) 2024-03-22 17:38:27 +01:00
WerWolv
41a3fdaf3c fix: Updater not working correctly on Windows 2024-03-22 17:38:05 +01:00
iTrooz
e517406f06 fix: Use find_library() instead of find_file() to find system yara library (#1581)
Discord discussion:
https://discord.com/channels/789833418631675954/789840633414025246/1213564050848485427
2024-03-22 09:44:35 +01:00
WerWolv
0cf2477988 build: Bumped version to 1.33.1 2024-03-02 16:44:54 +01:00
WerWolv
cc3a5aed9a patterns: Updated pattern language 2024-03-02 15:59:59 +01:00
WerWolv
af10317bae impr: Added testers to About screen 2024-03-02 15:59:38 +01:00
WerWolv
5153ad6458 build: Allow precompiled headers to be turned off 2024-03-02 15:59:33 +01:00
WerWolv
432f2f0862 build: Added option to disable precompiled headers 2024-03-02 15:59:11 +01:00
WerWolv
7eb3ee7150 build: Disable precompiled headers in plugins again 2024-03-02 15:58:57 +01:00
WerWolv
6cf2990808 fix: Race condition when downloading multiple elements from the content store 2024-03-02 15:58:53 +01:00
WerWolv
6cb0d4d7d8 fix: MIME based auto loading not working correctly 2024-03-02 15:58:45 +01:00
WerWolv
0d08b36a73 impr: Prevent ImHex from getting stuck in an infinite crash loop 2024-03-02 15:58:26 +01:00
WerWolv
7efdaa73f1 fix: Platform window not being updated when recovering from a crash 2024-03-02 15:58:11 +01:00
WerWolv
6d548180bb fix: Endless loop when throwing exception in deferred tasks 2024-03-02 15:58:02 +01:00
WerWolv
4b64e044f7 fix: Compile error 2024-03-02 15:57:51 +01:00
WerWolv
4a118b94cc impr: Better recovery from exceptions thrown in main thread (#1577)
This PR improves many things which can be seen by the commit name, but
the most important thing is the addition of a popup telling the user
when an exception is thrown

![image](https://github.com/WerWolv/ImHex/assets/42669835/db796416-9cce-4aa5-ad60-c22f05b5fc73)
2024-03-02 15:57:30 +01:00
WerWolv
8e27eb8d36 build: Updated libwolv 2024-02-29 23:06:49 +01:00
WerWolv
b33453f03c git: Run workflows on release branches 2024-02-29 22:28:58 +01:00
WerWolv
7cf88d128b patterns: Updated pattern language 2024-02-29 22:24:01 +01:00
WerWolv
5b7c4324ff build: Disable unknown pragmas warning 2024-02-29 22:18:31 +01:00
WerWolv
aaf9fdf61c fix: Build with precompiled headers for WebAssembly 2024-02-29 22:18:22 +01:00
WerWolv
6e36586ebc fix: Build with precompiled headers on Linux 2024-02-29 22:18:14 +01:00
WerWolv
773f9d3f1c build: Don't add defines to libimhex after precompiling headers 2024-02-29 22:18:09 +01:00
WerWolv
b448583105 build: Added precompiled headers 2024-02-29 22:17:57 +01:00
WerWolv
d1de10c606 fix: Pressing buttons while window is unfocused not working 2024-02-29 22:17:22 +01:00
WerWolv
9ce3a9e612 fix: Inserting bytes and resizing files not working correctly 2024-02-29 22:17:15 +01:00
WerWolv
99eaca4d09 fix: MIME-based pattern loading not working correctly
Fixes #1574
2024-02-29 22:17:03 +01:00
WerWolv
29443af90f fix: Buggy window detachment 2024-02-29 22:16:57 +01:00
WerWolv
d1fb41783d fix: Make sure glfw waits properly on Wayland 2024-02-29 22:16:49 +01:00
WerWolv
99277d71cc fix: Frame limiting not working correctly on Linux 2024-02-28 18:48:24 +01:00
WerWolv
db11c4c791 fix: Crash when using CRC hashes 2024-02-27 22:39:28 +01:00
WerWolv
87c254a437 fix: Read-only file toast showing up for all providers 2024-02-27 20:20:56 +01:00
WerWolv
63a4d65d96 fix: Import menu being disabled with read-only providers
Fixes #1573
2024-02-27 19:42:03 +01:00
WerWolv
cf1868b0b3 impr: Implement a better algorithm to determine if the frame content has changed 2024-02-27 18:59:06 +01:00
WerWolv
a135381b80 fix: Yara rules not being read correctly in data information section 2024-02-27 18:59:01 +01:00
WerWolv
c424e71f7e impr: Add better error handling when loading projects 2024-02-27 18:58:50 +01:00
WerWolv
976baec753 fix: Opening project files through the command line opening them as regular files 2024-02-27 18:58:31 +01:00
WerWolv
25cfa6f10b patterns: Updated pattern language 2024-02-27 18:57:02 +01:00
WerWolv
265213bbac impr: Make hex editor minimap rows stay a fixed height 2024-02-27 18:56:53 +01:00
424 changed files with 5571 additions and 72461 deletions

5
.github/codecov.yml vendored
View File

@@ -1,5 +0,0 @@
comment: false
ignore:
- "lib/third_party" # Third party libraries should be ignored
- "lib/external" # Our own libraries should be checked in their own repositories
- "tests" # https://about.codecov.io/blog/should-i-include-test-files-in-code-coverage-calculations/

View File

@@ -5,7 +5,6 @@ on:
branches:
- 'master'
- 'releases/**'
- 'tests/**'
pull_request:
workflow_dispatch:
@@ -76,7 +75,7 @@ jobs:
-DIMHEX_REPLACE_DWARF_WITH_PDB=ON \
-DDOTNET_EXECUTABLE="C:/Program Files/dotnet/dotnet.exe" \
..
- name: 🛠️ Build
run: |
cd build
@@ -153,14 +152,15 @@ jobs:
- name: ⬇️ Install dependencies
run: |
brew reinstall python || brew link --overwrite python || true
set -x
brew reinstall python || brew link --overwrite python
brew bundle --no-lock --file dist/Brewfile
rm -rf /usr/local/Cellar/capstone
- name: ⬇️ Install classic glfw
if: ${{! matrix.custom_glfw}}
run: |
brew install glfw || true
brew install glfw
- name: ⬇️ Install .NET
uses: actions/setup-dotnet@v4
@@ -173,7 +173,7 @@ jobs:
with:
repository: glfw/glfw
path: glfw
# GLFW custom build (to allow software rendering)
- name: ⬇️ Patch and install custom glfw
if: ${{matrix.custom_glfw}}
@@ -213,45 +213,21 @@ jobs:
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
-DCMAKE_OBJC_COMPILER_LAUNCHER=ccache \
-DCMAKE_OBJCXX_COMPILER_LAUNCHER=ccache \
-DCMAKE_INSTALL_PREFIX="./install" \
-DIMHEX_PATTERNS_PULL_MASTER=ON \
-DIMHEX_COMMIT_HASH_LONG="${GITHUB_SHA}" \
-DIMHEX_COMMIT_BRANCH="${GITHUB_REF##*/}" \
-DCPACK_PACKAGE_FILE_NAME="imhex-${{env.IMHEX_VERSION}}-macOS${{matrix.suffix}}-x86_64" \
..
- name: 🛠️ Build
run: cd build && ninja install
- name: ✒️ Fix Signature
run: |
set -x
cd build/install
mv imhex.app ImHex.app
codesign --remove-signature ImHex.app
codesign --force --deep --sign - ImHex.app
- name: 📁 Fix permissions
run: |
set -x
cd build/install
chmod -R 755 ImHex.app/
- name: 📦 Create DMG
run: |
set -x
mkdir bundle
mv build/install/ImHex.app bundle
cd bundle
ln -s /Applications Applications
cd ..
hdiutil create -volname "ImHex" -srcfolder bundle -ov -format UDZO imhex-${{env.IMHEX_VERSION}}-macOS${{matrix.suffix}}-x86_64.dmg
run: cd build && ninja package
- name: ⬆️ Upload DMG
uses: actions/upload-artifact@v4
with:
if-no-files-found: error
name: macOS DMG${{matrix.suffix}} x86_64
path: ./*.dmg
path: build/*.dmg
macos-arm64-build:
runs-on: ubuntu-22.04
@@ -263,7 +239,7 @@ jobs:
uses: actions/checkout@v4
with:
submodules: recursive
- name: 📁 Restore docker /cache
uses: actions/cache@v4
with:
@@ -311,15 +287,15 @@ jobs:
path: out
- name: 🗑️ Delete artifact
uses: geekyeggo/delete-artifact@v5
uses: geekyeggo/delete-artifact@v4
with:
token: ${{ secrets.GITHUB_TOKEN }}
name: macos_arm64_intermediate
- name: ✒️ Fix Signature
run: |
set -x
cd out
mv imhex.app ImHex.app
codesign --remove-signature ImHex.app
codesign --force --deep --sign - ImHex.app
@@ -345,15 +321,17 @@ jobs:
if-no-files-found: error
name: macOS DMG arm64
path: ./*.dmg
# Ubuntu build
ubuntu:
strategy:
fail-fast: false
matrix:
include:
- release_num: 22.04
- release_num: 24.04
- name: Ubuntu
release_num: 22.04
- name: Ubuntu
release_num: 23.04
name: 🐧 Ubuntu ${{ matrix.release_num }}
runs-on: ubuntu-latest
@@ -408,9 +386,9 @@ jobs:
-DIMHEX_USE_GTK_FILE_PICKER=ON \
-DDOTNET_EXECUTABLE="dotnet" \
..
- name: 🛠️ Build
run: cd build && DESTDIR=DebDir ninja install
run: cd build && DESTDIR=DebDir ninja install
- name: 📜 Set version variable
run: |
@@ -445,7 +423,7 @@ jobs:
path: cache
key: appimage-ccache-${{ github.run_id }}
restore-keys: appimage-cache
- name: 🐳 Inject /cache into docker
uses: reproducible-containers/buildkit-cache-dance@v2
with:
@@ -531,9 +509,9 @@ jobs:
-DIMHEX_ENABLE_LTO=ON \
-DIMHEX_USE_GTK_FILE_PICKER=ON \
..
- name: 🛠️ Build
run: cd build && DESTDIR=installDir ninja install
run: cd build && DESTDIR=installDir ninja install
- name: 📜 Set version variable
run: |
@@ -581,14 +559,14 @@ jobs:
mock_release: rawhide
release_num: rawhide
mock_config: fedora-rawhide
- name: Fedora
mock_release: f40
release_num: 40
mock_config: fedora-40
- name: Fedora
mock_release: f39
release_num: 39
mock_config: fedora-39
- name: Fedora
mock_release: f38
release_num: 38
mock_config: fedora-38
- name: RHEL-AlmaLinux
mock_release: epel9
release_num: 9
@@ -649,11 +627,11 @@ jobs:
- name: ✒️ Modify spec file
run: |
sed -i \
-e 's/Version: VERSION$/Version: ${{env.IMHEX_VERSION}}/g' \
-e 's/IMHEX_OFFLINE_BUILD=ON/IMHEX_OFFLINE_BUILD=OFF/g' \
-e '/IMHEX_OFFLINE_BUILD=OFF/a -D IMHEX_PATTERNS_PULL_MASTER=ON \\' \
-e '/BuildRequires: cmake/a BuildRequires: git-core' \
-e '/%files/a %{_datadir}/%{name}/' \
-e 's/Version: [0-9]*\.[0-9]*\.[0-9]*$/Version: ${{env.IMHEX_VERSION}}/g' \
-e 's/IMHEX_OFFLINE_BUILD=ON/IMHEX_OFFLINE_BUILD=OFF/g' \
-e '/IMHEX_OFFLINE_BUILD=OFF/a -D IMHEX_PATTERNS_PULL_MASTER=ON \\' \
-e '/BuildRequires: cmake/a BuildRequires: git-core' \
-e '/%files/a %{_datadir}/%{name}/' \
$GITHUB_WORKSPACE/ImHex/dist/rpm/imhex.spec
- name: 📜 Fix ccache on EL9
@@ -673,6 +651,14 @@ jobs:
config_opts['plugin_conf']['ccache_opts']['dir'] = "$GITHUB_WORKSPACE/.ccache"
EOT
- name: 📜 Setup Mock Cache
uses: actions/cache@v4
with:
path: /var/cache/mock
key: ${{ matrix.mock_release }}-mock-${{ github.run_id }}
restore-keys: |
${{ matrix.mock_release }}-mock
# Fedora cmake build (in imhex.spec)
- name: 📦 Build RPM
run: |

View File

@@ -5,7 +5,6 @@ on:
branches:
- 'master'
- 'releases/**'
- 'tests/**'
pull_request:
workflow_dispatch:
@@ -32,7 +31,7 @@ jobs:
uses: actions/cache@v4
with:
path: cache
key: web-cache-${{ hashFiles('**/CMakeLists.txt') }}
key: web-cmakecache-${{ hashFiles('**/CMakeLists.txt') }}
- name: 🐳 Inject /cache into docker
uses: reproducible-containers/buildkit-cache-dance@v2

View File

@@ -90,7 +90,7 @@ jobs:
run: tar --exclude-vcs -czvf Full.Sources.tar.gz ImHex
- name: ⬇️ Download artifacts from latest workflow
uses: dawidd6/action-download-artifact@v3
uses: dawidd6/action-download-artifact@v2
with:
github_token: ${{secrets.GITHUB_TOKEN}}
workflow: build.yml
@@ -119,7 +119,7 @@ jobs:
mv "Windows Portable NoGPU x86_64.zip" imhex-${{ env.IMHEX_VERSION }}-Windows-Portable-NoGPU-x86_64.zip
- name: ⬆️ Upload everything to release
uses: softprops/action-gh-release@4634c16e79c963813287e889244c50009e7f0981
uses: softprops/action-gh-release@v1
with:
files: '*'

View File

@@ -5,7 +5,6 @@ on:
branches:
- 'master'
- 'releases/**'
- 'tests/**'
pull_request:
branches:
- 'master'
@@ -34,51 +33,39 @@ jobs:
restore-keys: ${{ runner.os }}-tests-build
max-size: 50M
- name: 📜 Restore CMakeCache
uses: actions/cache@v4
with:
path: |
build/CMakeCache.txt
key: ${{ runner.os }}-tests-build-${{ hashFiles('**/CMakeLists.txt') }}
- name: ⬇️ Install dependencies
run: |
sudo apt update
sudo bash dist/get_deps_debian.sh
sudo apt install gcovr -y
- name: 🛠️ Build
run: |
set -x
mkdir -p build
cd build
CC=gcc-12 CXX=g++-12 cmake \
-DCMAKE_BUILD_TYPE=Debug \
-DIMHEX_ENABLE_UNIT_TESTS=ON \
-DIMHEX_ENABLE_PLUGIN_TESTS=ON \
-DCMAKE_C_COMPILER_LAUNCHER=ccache \
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
-DCMAKE_C_FLAGS="-fuse-ld=lld -fsanitize=address,leak,undefined -fno-sanitize-recover=all --coverage" \
-DCMAKE_CXX_FLAGS="-fuse-ld=lld -fsanitize=address,leak,undefined -fno-sanitize-recover=all --coverage" \
-DIMHEX_OFFLINE_BUILD=ON \
CC=gcc-12 CXX=g++-12 cmake \
-DCMAKE_BUILD_TYPE=Debug \
-DCMAKE_C_COMPILER_LAUNCHER=ccache \
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
-DCMAKE_C_FLAGS="-fuse-ld=lld -fsanitize=address,leak,undefined -fno-sanitize-recover=all" \
-DCMAKE_CXX_FLAGS="-fuse-ld=lld -fsanitize=address,leak,undefined -fno-sanitize-recover=all" \
-DIMHEX_OFFLINE_BUILD=ON \
..
make -j4 unit_tests
- name: 🧪 Perform plcli Integration Tests
run: |
cd lib/external/pattern_language
python tests/integration/integration.py ../../../build/imhex --pl
- name: 🧪 Perform Unit Tests
run: |
cd build
ctest --output-on-failure
# Generate report from all gcov .gcda files
- name: 🧪 Generate coverage report
run: |
gcovr --gcov-executable /usr/bin/gcov-12 -r . build --xml coverage_report.xml --verbose
- name: Upload coverage reports to Codecov
uses: codecov/codecov-action@v4
with:
fail_ci_if_error: true
token: ${{ secrets.CODECOV_TOKEN }}
file: coverage_report.xml
langs:
name: 🧪 Langs
runs-on: ubuntu-22.04

6
.gitignore vendored
View File

@@ -1,6 +1,5 @@
.vscode/
.idea/
.kdev4/
cmake-build-*/
build*/
@@ -8,8 +7,7 @@ local/
venv/
*.mgc
*.kdev4
imgui.ini
.DS_Store
CMakeUserPresets.json
Brewfile.lock.json
./CMakeUserPresets.json
Brewfile.lock.json

13
.gitmodules vendored
View File

@@ -22,14 +22,6 @@
path = lib/third_party/jthread/jthread
url = https://github.com/josuttis/jthread
ignore = dirty
[submodule "lib/third_party/edlib"]
path = lib/third_party/edlib
url = https://github.com/Martinsos/edlib
ignore = dirty
[submodule "lib/third_party/lunasvg"]
path = lib/third_party/lunasvg
url = https://github.com/sammycage/lunasvg
ignore = dirty
[submodule "lib/external/libromfs"]
path = lib/external/libromfs
@@ -43,4 +35,7 @@
[submodule "lib/third_party/HashLibPlus"]
path = lib/third_party/HashLibPlus
url = https://github.com/WerWolv/HashLibPlus
url = https://github.com/WerWolv/HashLibPlus
[submodule "lib/third_party/edlib"]
path = lib/third_party/edlib
url = https://github.com/Martinsos/edlib

View File

@@ -21,34 +21,24 @@ option(IMHEX_REPLACE_DWARF_WITH_PDB "Remove DWARF information from binaries
option(IMHEX_ENABLE_STD_ASSERTS "Enable debug asserts in the C++ std library. (Breaks Plugin ABI!)" OFF)
option(IMHEX_ENABLE_UNIT_TESTS "Enable building unit tests" OFF)
option(IMHEX_ENABLE_PRECOMPILED_HEADERS "Enable precompiled headers" OFF)
option(IMHEX_COMPRESS_DEBUG_INFO "Compress debug information" ON )
set(IMHEX_BASE_FOLDER "${CMAKE_CURRENT_SOURCE_DIR}")
set(CMAKE_MODULE_PATH "${IMHEX_BASE_FOLDER}/cmake/modules")
# Optional IDE support
include("${IMHEX_BASE_FOLDER}/cmake/ide_helpers.cmake")
# Basic compiler and cmake configurations
set(CMAKE_CXX_STANDARD 23)
set(CMAKE_INCLUDE_DIRECTORIES_BEFORE ON)
set(IMHEX_BASE_FOLDER "${CMAKE_CURRENT_SOURCE_DIR}")
set(CMAKE_MODULE_PATH "${IMHEX_BASE_FOLDER}/cmake/modules")
include("${IMHEX_BASE_FOLDER}/cmake/build_helpers.cmake")
# Setup project
loadVersion(IMHEX_VERSION IMHEX_VERSION_PLAIN)
loadVersion(IMHEX_VERSION)
setVariableInParent(IMHEX_VERSION ${IMHEX_VERSION})
configureCMake()
project(imhex
LANGUAGES C CXX
VERSION ${IMHEX_VERSION_PLAIN}
VERSION ${IMHEX_VERSION}
DESCRIPTION "The ImHex Hex Editor"
HOMEPAGE_URL "https://imhex.werwolv.net"
)
configureProject()
# Add ImHex sources
add_custom_target(imhex_all ALL)
# Make sure project is configured correctly
setDefaultBuiltTypeIfUnset()
@@ -66,22 +56,17 @@ configurePackingResources()
setUninstallTarget()
addBundledLibraries()
# Add ImHex sources
add_custom_target(imhex_all ALL)
add_subdirectory(lib/libimhex)
add_subdirectory(main)
addPluginDirectories()
# Add unit tests
if (IMHEX_ENABLE_UNIT_TESTS)
enable_testing()
add_subdirectory(tests EXCLUDE_FROM_ALL)
endif ()
enable_testing()
add_subdirectory(tests EXCLUDE_FROM_ALL)
# Configure more resources that will be added to the install package
generatePDBs()
generateSDKDirectory()
# Handle package generation
createPackage()
# Accomodate IDEs with FOLDER support
tweakTargetsForIDESupport()
generatePDBs()
generateSDKDirectory()

View File

@@ -28,23 +28,6 @@
"displayName": "x86_64 Build",
"description": "x86_64 build",
"inherits": [ "base" ]
},
{
"name": "xcode",
"inherits": [ "base" ],
"displayName": "Xcode",
"description": "Xcode with external compiler override",
"generator": "Xcode",
"cacheVariables": {
"CMAKE_C_COMPILER": "clang",
"CMAKE_CXX_COMPILER": "clang++",
"CMAKE_CXX_FLAGS": "-fexperimental-library -Wno-shorten-64-to-32 -Wno-deprecated-declarations",
"IMHEX_IDE_HELPERS_OVERRIDE_XCODE_COMPILER": "ON"
}
}
],
"buildPresets": [

View File

@@ -1,16 +1,14 @@
<a href="https://imhex.werwolv.net">
<h1 align="center">
<picture>
<img height="300px" style="margin: 0; padding: 0" src="./resources/dist/common/logo/ImHexLogoSVGBG.svg">
<source media="(prefers-color-scheme: dark)" srcset="./resources/projects/logo_text_light.svg">
<img height="100px" src="./resources/projects/logo_text_dark.svg">
</picture>
</h1>
</a>
<p align="center">
A Hex Editor for Reverse Engineers, Programmers and people who value their retinas when working at 3 AM.
<br>
<a href="https://itinerarium.github.io/phoneme-synthesis/?w=/'ˈɪmhɛks/"><strong>/ˈɪmhɛks/</strong></a>
</p>
<p align="center">A Hex Editor for Reverse Engineers, Programmers and people who value their retinas when working at 3 AM.</p>
<p align="center">
<a title="'Build' workflow Status" href="https://github.com/WerWolv/ImHex/actions?query=workflow%3ABuild"><img alt="'Build' workflow Status" src="https://img.shields.io/github/actions/workflow/status/WerWolv/ImHex/build.yml?longCache=true&style=for-the-badge&label=Build&logoColor=fff&logo=GitHub%20Actions&branch=master"></a>
<a title="Discord Server" href="https://discord.gg/X63jZ36xBY"><img alt="Discord Server" src="https://img.shields.io/discord/789833418631675954?label=Discord&logo=Discord&logoColor=fff&style=for-the-badge"></a>
@@ -111,7 +109,7 @@ If you like my work, please consider supporting me on GitHub Sponsors, Patreon o
<details>
<summary><strong>Data Inspector</strong></summary>
- Interpreting data as many different types with endianness, decimal, hexadecimal and octal support and bit inversion
- Interpreting data as many different types with endianess, decimal, hexadecimal and octal support and bit inversion
- Unsigned and signed integers (8, 16, 24, 32, 48, 64 bit)
- Floats (16, 32, 64 bit)
- Signed and Unsigned LEB128
@@ -160,7 +158,7 @@ If you like my work, please consider supporting me on GitHub Sponsors, Patreon o
- Numeric Value search
- Search for signed/unsigned integers and floats
- Search for ranges of values
- Option to specify size and endianness
- Option to specify size and endianess
- Option to ignore unaligned values
</details>
<details>
@@ -318,8 +316,7 @@ To use ImHex, the following minimal system requirements need to be met.
- **OS**:
- **Windows**: Windows 7 or higher (Windows 10/11 recommended)
- **macOS**: macOS 12.1 (Monterey) or higher,
- Lower versions are supported, but you'll need to compile ImHex yourself
- **macOS**: macOS 11 (Big Sur) or higher,
- **Linux**: "Modern" Linux. The following distributions have official releases available. Other distros are supported through the AppImage and Flatpak releases.
- Ubuntu 22.04/23.04
- Fedora 36/37
@@ -361,29 +358,24 @@ To develop plugins for ImHex, use the following template project to get started.
### Contributors
- [iTrooz](https://github.com/iTrooz) for getting ImHex onto the Web as well as hundreds of contributions in every part of the project
- [jumanji144](https://github.com/jumanji144) for huge contributions to the Pattern Language and ImHex's infrastructure
- [Mary](https://github.com/marysaka) for her immense help porting ImHex to MacOS and help during development
- [Roblabla](https://github.com/Roblabla) for adding MSI Installer support to ImHex
- [jam1garner](https://github.com/jam1garner) and [raytwo](https://github.com/raytwo) for their help with adding Rust support to plugins
- [Mailaender](https://github.com/Mailaender) for getting ImHex onto Flathub
- [iTrooz](https://github.com/iTrooz) for many improvements and new features to Imhex
- Everybody else who has reported issues on Discord or GitHub that I had great conversations with :)
### Dependencies
- Thanks a lot to ocornut for their amazing [Dear ImGui](https://github.com/ocornut/imgui) which is used for building the entire interface
- Thanks to epezent for [ImPlot](https://github.com/epezent/implot) used to plot data in various places
- Thanks to Nelarius for [ImNodes](https://github.com/Nelarius/imnodes) used as base for the data processor
- Thanks to BalazsJako for [ImGuiColorTextEdit](https://github.com/BalazsJako/ImGuiColorTextEdit) used for the pattern language syntax highlighting
- Thanks to nlohmann for their [json](https://github.com/nlohmann/json) library used for configuration files
- Thanks to vitaut for their [libfmt](https://github.com/fmtlib/fmt) library which makes formatting and logging so much better
- Thanks to btzy for [nativefiledialog-extended](https://github.com/btzy/nativefiledialog-extended) and their great support, used for handling file dialogs on all platforms
- Thanks to danyspin97 for [xdgpp](https://sr.ht/~danyspin97/xdgpp) used to handle folder paths on Linux
- Thanks to ocornut as well for their hex editor view used as base for this project.
- Thanks to BalazsJako for their incredible [ImGuiColorTextEdit](https://github.com/BalazsJako/ImGuiColorTextEdit) used for the pattern language syntax highlighting
- Thanks to nlohmann for their [json](https://github.com/nlohmann/json) library used for project files
- Thanks to aquynh for [capstone](https://github.com/aquynh/capstone) which is the base of the disassembly window
- Thanks to vitaut for their [libfmt](https://github.com/fmtlib/fmt) library which makes formatting and logging so much better
- Thanks to rxi for [microtar](https://github.com/rxi/microtar) used for extracting downloaded store assets
- Thanks to VirusTotal for [Yara](https://github.com/VirusTotal/yara) used by the Yara plugin
- Thanks to Martinsos for [edlib](https://github.com/Martinsos/edlib) used for sequence searching in the diffing view
- Thanks to ron4fun for [HashLibPlus](https://github.com/ron4fun/HashLibPlus) which implements every hashing algorithm under the sun
- Thanks to mackron for [miniaudio](https://github.com/mackron/miniaudio) used to play audio files
- Thanks to btzy for [nativefiledialog-extended](https://github.com/btzy/nativefiledialog-extended)
- Thanks to danyspin97 for [xdgpp](https://sr.ht/~danyspin97/xdgpp)
- Thanks to all other groups and organizations whose libraries are used in ImHex
### License

View File

@@ -1 +1 @@
1.35.2
1.33.2

View File

@@ -59,7 +59,6 @@ macro(detectOS)
set(CMAKE_INSTALL_LIBDIR ".")
set(PLUGINS_INSTALL_LOCATION "plugins")
add_compile_definitions(WIN32_LEAN_AND_MEAN)
add_compile_definitions(UNICODE)
elseif (APPLE)
add_compile_definitions(OS_MACOS)
set(CMAKE_INSTALL_BINDIR ".")
@@ -93,8 +92,6 @@ macro(detectOS)
endmacro()
macro(configurePackingResources)
set(LIBRARY_PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE)
if (WIN32)
if (NOT (CMAKE_BUILD_TYPE STREQUAL "Debug"))
set(APPLICATION_TYPE WIN32)
@@ -148,17 +145,21 @@ macro(configurePackingResources)
endif()
endmacro()
macro(addPluginDirectories)
macro(createPackage)
set(LIBRARY_PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE)
file(MAKE_DIRECTORY "plugins")
foreach (plugin IN LISTS PLUGINS)
add_subdirectory("plugins/${plugin}")
if (TARGET ${plugin})
set_target_properties(${plugin} PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${IMHEX_MAIN_OUTPUT_DIRECTORY}/plugins")
set_target_properties(${plugin} PROPERTIES LIBRARY_OUTPUT_DIRECTORY "${IMHEX_MAIN_OUTPUT_DIRECTORY}/plugins")
set_target_properties(${plugin} PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/plugins)
set_target_properties(${plugin} PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/plugins)
if (APPLE)
if (IMHEX_GENERATE_PACKAGE)
set_target_properties(${plugin} PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${PLUGINS_INSTALL_LOCATION})
else ()
set_target_properties(${plugin} PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/plugins)
endif ()
else ()
if (WIN32)
@@ -177,9 +178,9 @@ macro(addPluginDirectories)
add_dependencies(imhex_all ${plugin})
endif ()
endforeach()
endmacro()
macro(createPackage)
set_target_properties(libimhex PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
if (WIN32)
# Install binaries directly in the prefix, usually C:\Program Files\ImHex.
set(CMAKE_INSTALL_BINDIR ".")
@@ -216,6 +217,7 @@ macro(createPackage)
endforeach()
]])
install(FILES "$<TARGET_FILE:libimhex>" DESTINATION "${CMAKE_INSTALL_LIBDIR}" PERMISSIONS ${LIBRARY_PERMISSIONS})
downloadImHexPatternsFiles("./")
elseif(UNIX AND NOT APPLE)
@@ -226,6 +228,7 @@ macro(createPackage)
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/LICENSE DESTINATION ${CMAKE_INSTALL_PREFIX}/share/licenses/imhex)
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/dist/imhex.desktop DESTINATION ${CMAKE_INSTALL_PREFIX}/share/applications)
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/resources/icon.png DESTINATION ${CMAKE_INSTALL_PREFIX}/share/pixmaps RENAME imhex.png)
install(FILES "$<TARGET_FILE:libimhex>" DESTINATION "${CMAKE_INSTALL_LIBDIR}" PERMISSIONS ${LIBRARY_PERMISSIONS})
downloadImHexPatternsFiles("./share/imhex")
# install AppStream file
@@ -246,15 +249,17 @@ macro(createPackage)
set_property(TARGET main PROPERTY MACOSX_BUNDLE_INFO_PLIST ${MACOSX_BUNDLE_INFO_PLIST})
# Fix rpath
install(CODE "execute_process(COMMAND ${CMAKE_INSTALL_NAME_TOOL} -add_rpath \"@executable_path/../Frameworks/\" $<TARGET_FILE:main>)")
add_custom_command(TARGET imhex_all POST_BUILD COMMAND ${CMAKE_INSTALL_NAME_TOOL} -add_rpath "@executable_path/../Frameworks/" $<TARGET_FILE:main> || true)
add_custom_target(build-time-make-plugins-directory ALL COMMAND ${CMAKE_COMMAND} -E make_directory "${IMHEX_BUNDLE_PATH}/Contents/MacOS/plugins")
add_custom_target(build-time-make-resources-directory ALL COMMAND ${CMAKE_COMMAND} -E make_directory "${IMHEX_BUNDLE_PATH}/Contents/Resources")
downloadImHexPatternsFiles("${CMAKE_INSTALL_PREFIX}/${BUNDLE_NAME}/Contents/MacOS")
downloadImHexPatternsFiles("${IMHEX_BUNDLE_PATH}/Contents/MacOS")
install(FILES ${IMHEX_ICON} DESTINATION "${CMAKE_INSTALL_PREFIX}/${BUNDLE_NAME}/Contents/Resources")
install(FILES ${IMHEX_ICON} DESTINATION "${IMHEX_BUNDLE_PATH}/Contents/Resources")
install(TARGETS main BUNDLE DESTINATION ".")
install(FILES $<TARGET_FILE:main> DESTINATION "${IMHEX_BUNDLE_PATH}")
install(FILES $<TARGET_FILE:updater> DESTINATION "${IMHEX_BUNDLE_PATH}")
# Update library references to make the bundle portable
postprocess_bundle(imhex_all main)
@@ -263,19 +268,15 @@ macro(createPackage)
set(CPACK_GENERATOR "DragNDrop")
set(CPACK_BUNDLE_ICON "${CMAKE_SOURCE_DIR}/resources/dist/macos/AppIcon.icns")
set(CPACK_BUNDLE_PLIST "${CMAKE_INSTALL_PREFIX}/${BUNDLE_NAME}/Contents/Info.plist")
set(CPACK_BUNDLE_PLIST "${CMAKE_BINARY_DIR}/${BUNDLE_NAME}/Contents/Info.plist")
if (IMHEX_RESIGN_BUNDLE)
message(STATUS "Resigning bundle...")
find_program(CODESIGN_PATH codesign)
if (CODESIGN_PATH)
install(CODE "message(STATUS \"Signing bundle '${CMAKE_INSTALL_PREFIX}/${BUNDLE_NAME}'...\")")
install(CODE "execute_process(COMMAND ${CODESIGN_PATH} --force --deep --entitlements ${CMAKE_SOURCE_DIR}/resources/macos/Entitlements.plist --sign - ${CMAKE_INSTALL_PREFIX}/${BUNDLE_NAME} COMMAND_ERROR_IS_FATAL ANY)")
add_custom_command(TARGET imhex_all POST_BUILD COMMAND "codesign" ARGS "--force" "--deep" "--sign" "-" "${CMAKE_BINARY_DIR}/${BUNDLE_NAME}")
endif()
endif()
install(CODE [[ message(STATUS "MacOS Bundle finalized. DO NOT TOUCH IT ANYMORE! ANY MODIFICATIONS WILL BREAK IT FROM NOW ON!") ]])
else()
downloadImHexPatternsFiles("${IMHEX_MAIN_OUTPUT_DIRECTORY}")
endif()
else()
install(TARGETS main RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
@@ -343,11 +344,8 @@ macro(configureCMake)
if (LD_LLD_PATH)
set(CMAKE_LINKER ${LD_LLD_PATH})
if (NOT XCODE)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fuse-ld=lld")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fuse-ld=lld")
endif()
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fuse-ld=lld")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fuse-ld=lld")
else ()
message(WARNING "lld not found, using default linker!")
endif ()
@@ -382,15 +380,6 @@ macro(configureCMake)
set(CMAKE_WARN_DEPRECATED OFF CACHE BOOL "Disable deprecated warnings" FORCE)
endmacro()
function(configureProject)
if (XCODE)
# Support Xcode's multi configuration paradigm by placing built artifacts into separate directories
set(IMHEX_MAIN_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/Configs/$<CONFIG>" PARENT_SCOPE)
else()
set(IMHEX_MAIN_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}" PARENT_SCOPE)
endif()
endfunction()
macro(setDefaultBuiltTypeIfUnset)
if (NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
set(CMAKE_BUILD_TYPE "RelWithDebInfo" CACHE STRING "Using RelWithDebInfo build type as it was left unset" FORCE)
@@ -398,14 +387,12 @@ macro(setDefaultBuiltTypeIfUnset)
endif()
endmacro()
function(loadVersion version plain_version)
function(loadVersion version)
set(VERSION_FILE "${CMAKE_CURRENT_SOURCE_DIR}/VERSION")
set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS ${VERSION_FILE})
file(READ "${VERSION_FILE}" read_version)
string(STRIP ${read_version} read_version)
string(REPLACE ".WIP" "" read_version_plain ${read_version})
set(${version} ${read_version} PARENT_SCOPE)
set(${plain_version} ${read_version_plain} PARENT_SCOPE)
endfunction()
function(detectBadClone)
@@ -495,71 +482,20 @@ function(downloadImHexPatternsFiles dest)
message(STATUS "Finished downloading ImHex-Patterns")
else ()
set(imhex_patterns_SOURCE_DIR "")
# Maybe patterns are cloned to a subdirectory
if (NOT EXISTS ${imhex_patterns_SOURCE_DIR})
set(imhex_patterns_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ImHex-Patterns")
endif()
# Or a sibling directory
if (NOT EXISTS ${imhex_patterns_SOURCE_DIR})
set(imhex_patterns_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../ImHex-Patterns")
endif()
set(imhex_patterns_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ImHex-Patterns")
endif ()
if (NOT EXISTS ${imhex_patterns_SOURCE_DIR})
message(WARNING "Failed to locate ImHex-Patterns repository, some resources will be missing during install!")
elseif(XCODE)
# The Xcode build has multiple configurations, which each need a copy of these files
file(GLOB_RECURSE sourceFilePaths LIST_DIRECTORIES NO CONFIGURE_DEPENDS RELATIVE "${imhex_patterns_SOURCE_DIR}"
"${imhex_patterns_SOURCE_DIR}/constants/*"
"${imhex_patterns_SOURCE_DIR}/encodings/*"
"${imhex_patterns_SOURCE_DIR}/includes/*"
"${imhex_patterns_SOURCE_DIR}/patterns/*"
"${imhex_patterns_SOURCE_DIR}/magic/*"
"${imhex_patterns_SOURCE_DIR}/nodes/*"
)
list(FILTER sourceFilePaths EXCLUDE REGEX "_schema.json$")
foreach(relativePath IN LISTS sourceFilePaths)
file(GENERATE OUTPUT "${dest}/${relativePath}" INPUT "${imhex_patterns_SOURCE_DIR}/${relativePath}")
endforeach()
else()
if (EXISTS ${imhex_patterns_SOURCE_DIR})
set(PATTERNS_FOLDERS_TO_INSTALL constants encodings includes patterns magic nodes)
foreach (FOLDER ${PATTERNS_FOLDERS_TO_INSTALL})
install(DIRECTORY "${imhex_patterns_SOURCE_DIR}/${FOLDER}" DESTINATION "${dest}" PATTERN "**/_schema.json" EXCLUDE)
install(DIRECTORY "${imhex_patterns_SOURCE_DIR}/${FOLDER}" DESTINATION ${dest} PATTERN "**/_schema.json" EXCLUDE)
endforeach ()
endif ()
endfunction()
# Compress debug info. See https://github.com/WerWolv/ImHex/issues/1714 for relevant problem
macro(setupDebugCompressionFlag)
include(CheckCXXCompilerFlag)
include(CheckLinkerFlag)
check_cxx_compiler_flag(-gz=zstd ZSTD_AVAILABLE_COMPILER)
check_linker_flag(CXX -gz=zstd ZSTD_AVAILABLE_LINKER)
check_cxx_compiler_flag(-gz COMPRESS_AVAILABLE_COMPILER)
check_linker_flag(CXX -gz COMPRESS_AVAILABLE_LINKER)
if (NOT DEBUG_COMPRESSION_FLAG) # Cache variable
if (ZSTD_AVAILABLE_COMPILER AND ZSTD_AVAILABLE_LINKER)
message("Using Zstd compression for debug info because both compiler and linker support it")
set(DEBUG_COMPRESSION_FLAG "-gz=zstd" CACHE STRING "Cache to use for debug info compression")
elseif (COMPRESS_AVAILABLE_COMPILER AND COMPRESS_AVAILABLE_LINKER)
message("Using default compression for debug info because both compiler and linker support it")
set(DEBUG_COMPRESSION_FLAG "-gz" CACHE STRING "Cache to use for debug info compression")
endif()
endif()
set(IMHEX_COMMON_FLAGS "${IMHEX_COMMON_FLAGS} ${DEBUG_COMPRESSION_FLAG}")
endmacro()
macro(setupCompilerFlags target)
# IMHEX_COMMON_FLAGS: flags common for C, C++, Objective C, etc.. compilers
if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")
# Define strict compilation flags
if (IMHEX_STRICT_WARNINGS)
@@ -592,24 +528,11 @@ macro(setupCompilerFlags target)
set(IMHEX_C_CXX_FLAGS "${IMHEX_C_CXX_FLAGS} -pthread -Wno-dollar-in-identifier-extension -Wno-pthreads-mem-growth")
endif ()
if (IMHEX_COMPRESS_DEBUG_INFO)
setupDebugCompressionFlag()
endif()
# Set actual CMake flags
set_target_properties(${target} PROPERTIES COMPILE_FLAGS "${IMHEX_COMMON_FLAGS} ${IMHEX_C_CXX_FLAGS}")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${IMHEX_COMMON_FLAGS} ${IMHEX_C_CXX_FLAGS}")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${IMHEX_COMMON_FLAGS} ${IMHEX_C_CXX_FLAGS} ${IMHEX_CXX_FLAGS}")
set(CMAKE_OBJC_FLAGS "${CMAKE_OBJC_FLAGS} ${IMHEX_COMMON_FLAGS}")
# Only generate minimal debug information for stacktraces in RelWithDebInfo builds
set(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO} -g1")
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -g1")
if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
# Add flags for debug info in inline functions
set(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO} -gstatement-frontiers -ginline-points")
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -gstatement-frontiers -ginline-points")
endif()
endmacro()
# uninstall target
@@ -675,14 +598,6 @@ macro(addBundledLibraries)
set(NLOHMANN_JSON_LIBRARIES nlohmann_json::nlohmann_json)
endif()
if (NOT USE_SYSTEM_LUNASVG)
add_subdirectory(${THIRD_PARTY_LIBS_FOLDER}/lunasvg EXCLUDE_FROM_ALL)
set(LUNASVG_LIBRARIES lunasvg)
else()
find_package(LunaSVG REQUIRED)
set(LUNASVG_LIBRARIES lunasvg)
endif()
if (NOT USE_SYSTEM_LLVM)
add_subdirectory(${THIRD_PARTY_LIBS_FOLDER}/llvm-demangle EXCLUDE_FROM_ALL)
else()
@@ -701,12 +616,6 @@ macro(addBundledLibraries)
set(JTHREAD_LIBRARIES jthread)
endif()
if (USE_SYSTEM_BOOST)
find_package(boost REQUIRED)
else()
add_subdirectory(${THIRD_PARTY_LIBS_FOLDER}/boost ${CMAKE_CURRENT_BINARY_DIR}/boost EXCLUDE_FROM_ALL)
endif()
set(LIBPL_BUILD_CLI_AS_EXECUTABLE OFF CACHE BOOL "" FORCE)
set(LIBPL_ENABLE_PRECOMPILED_HEADERS ${IMHEX_ENABLE_PRECOMPILED_HEADERS} CACHE BOOL "" FORCE)
@@ -751,20 +660,20 @@ macro(addBundledLibraries)
if (${Backtrace_FOUND})
message(STATUS "Backtrace enabled! Header: ${Backtrace_HEADER}")
if (Backtrace_HEADER STREQUAL "backtrace.h")
if (Backtrace_HEADER STREQUAL "execinfo.h")
set(LIBBACKTRACE_LIBRARIES ${Backtrace_LIBRARY})
set(LIBBACKTRACE_INCLUDE_DIRS ${Backtrace_INCLUDE_DIR})
add_compile_definitions(BACKTRACE_HEADER=<${Backtrace_HEADER}>)
add_compile_definitions(HEX_HAS_BACKTRACE)
elseif (Backtrace_HEADER STREQUAL "execinfo.h")
set(LIBBACKTRACE_LIBRARIES ${Backtrace_LIBRARY})
set(LIBBACKTRACE_INCLUDE_DIRS ${Backtrace_INCLUDE_DIR})
add_compile_definitions(BACKTRACE_HEADER=<${Backtrace_HEADER}>)
add_compile_definitions(BACKTRACE_HEADER=\"${Backtrace_HEADER}\")
add_compile_definitions(HEX_HAS_EXECINFO)
endif()
elseif (Backtrace_HEADER STREQUAL "backtrace.h")
set(LIBBACKTRACE_LIBRARIES ${Backtrace_LIBRARY})
set(LIBBACKTRACE_INCLUDE_DIRS ${Backtrace_INCLUDE_DIR})
add_compile_definitions(BACKTRACE_HEADER=\"${Backtrace_HEADER}\")
add_compile_definitions(HEX_HAS_BACKTRACE)
endif ()
endif()
endif()
endif()
endif ()
endif ()
endmacro()
function(enableUnityBuild TARGET)
@@ -830,7 +739,7 @@ function(generateSDKDirectory)
if (WIN32)
set(SDK_PATH "./sdk")
elseif (APPLE)
set(SDK_PATH "${CMAKE_INSTALL_PREFIX}/${BUNDLE_NAME}/Contents/Resources/sdk")
set(SDK_PATH "${BUNDLE_NAME}/Contents/Resources/sdk")
else()
set(SDK_PATH "share/imhex/sdk")
endif()

View File

@@ -1,149 +0,0 @@
option(IMHEX_IDE_HELPERS_OVERRIDE_XCODE_COMPILER "Enable choice of compiler for Xcode builds, despite CMake's best efforts" OFF)
option(IMHEX_IDE_HELPERS_INTRUSIVE_IDE_TWEAKS "Enable intrusive CMake tweaks to better support IDEs with folder support" OFF)
# The CMake infrastructure silently ignores the CMAKE_<>_COMPILER settings when
# using the `Xcode` generator.
#
# A particularly nasty (and potentially only) way of getting around this is to
# temporarily lie about the generator being used, while CMake determines and
# locks in the compiler to use.
#
# Needless to say, this is hacky and fragile. Use at your own risk!
if (IMHEX_IDE_HELPERS_OVERRIDE_XCODE_COMPILER AND CMAKE_GENERATOR STREQUAL "Xcode")
set(CMAKE_GENERATOR "Unknown")
enable_language(C CXX)
set(CMAKE_GENERATOR "Xcode")
set(CMAKE_XCODE_ATTRIBUTE_CC "${CMAKE_C_COMPILER}")
set(CMAKE_XCODE_ATTRIBUTE_CXX "${CMAKE_CXX_COMPILER}")
if (CLANG)
set(CMAKE_XCODE_ATTRIBUTE_LD "${CMAKE_C_COMPILER}")
set(CMAKE_XCODE_ATTRIBUTE_LDPLUSPLUS "${CMAKE_CXX_COMPILER}")
endif()
# By default Xcode passes a `-index-store-path=<...>` parameter to the compiler
# during builds to build code completion indexes. This is not supported by
# anything other than AppleClang
set(CMAKE_XCODE_ATTRIBUTE_COMPILER_INDEX_STORE_ENABLE "NO")
endif()
# Generate a launch/build scheme for all targets
set(CMAKE_XCODE_GENERATE_SCHEME YES)
# Utility function that helps avoid messing with non-standard targets
macro(returnIfTargetIsNonTweakable target)
get_target_property(targetIsAliased ${target} ALIASED_TARGET)
get_target_property(targetIsImported ${target} IMPORTED)
if (targetIsAliased OR targetIsImported)
return()
endif()
get_target_property(targetType ${target} TYPE)
if (targetType MATCHES "INTERFACE_LIBRARY|UNKNOWN_LIBRARY")
return()
endif()
endmacro()
# Targets usually don't specify their private headers, nor group their source files
# which results in very spotty coverage by IDEs with folders support
#
# Unfortunately, CMake does not have a `target_source_group` like construct yet, therefore
# we have to play by the limitations of `source_group`.
#
# A particularly problematic part is that the function must be called within the directoryies
# scope for the grouping to take effect.
#
# See: https://discourse.cmake.org/t/topic/7388
function(tweakTargetForIDESupport target)
returnIfTargetIsNonTweakable(${target})
# Don't assume directory structure of third parties
get_target_property(targetSourceDir ${target} SOURCE_DIR)
if (targetSourceDir MATCHES "third_party")
return()
endif()
# Add headers to target
get_target_property(targetSourceDir ${target} SOURCE_DIR)
if (targetSourceDir)
file(GLOB_RECURSE targetPrivateHeaders CONFIGURE_DEPENDS "${targetSourceDir}/include/*.hpp")
target_sources(${target} PRIVATE "${targetPrivateHeaders}")
endif()
# Organize target sources into directory tree
get_target_property(sources ${target} SOURCES)
foreach(file IN LISTS sources)
get_filename_component(path "${file}" ABSOLUTE)
if (NOT path MATCHES "^${targetSourceDir}")
continue()
endif()
source_group(TREE "${targetSourceDir}" PREFIX "Source Tree" FILES "${file}")
endforeach()
endfunction()
if (IMHEX_IDE_HELPERS_INTRUSIVE_IDE_TWEAKS)
# See tweakTargetForIDESupport for rationale
function(add_library target)
_add_library(${target} ${ARGN})
tweakTargetForIDESupport(${target})
endfunction()
function(add_executable target)
_add_executable(${target} ${ARGN})
tweakTargetForIDESupport(${target})
endfunction()
endif()
# Adjust target's FOLDER property, which is an IDE only preference
function(_tweakTarget target path)
get_target_property(targetType ${target} TYPE)
if (TARGET generator-${target})
set_target_properties(generator-${target} PROPERTIES FOLDER "romfs/${target}")
endif()
if (TARGET romfs_file_packer-${target})
set_target_properties(romfs_file_packer-${target} PROPERTIES FOLDER "romfs/${target}")
endif()
if (TARGET libromfs-${target})
set_target_properties(libromfs-${target} PROPERTIES FOLDER "romfs/${target}")
endif()
if (${targetType} MATCHES "EXECUTABLE|LIBRARY")
set_target_properties(${target} PROPERTIES FOLDER "${path}")
endif()
endfunction()
macro(_tweakTargetsRecursive dir)
get_property(subdirectories DIRECTORY ${dir} PROPERTY SUBDIRECTORIES)
foreach(subdir IN LISTS subdirectories)
_tweakTargetsRecursive("${subdir}")
endforeach()
if(${dir} STREQUAL ${CMAKE_SOURCE_DIR})
return()
endif()
get_property(targets DIRECTORY "${dir}" PROPERTY BUILDSYSTEM_TARGETS)
file(RELATIVE_PATH rdir ${CMAKE_SOURCE_DIR} "${dir}/..")
foreach(target ${targets})
_tweakTarget(${target} "${rdir}")
endforeach()
endmacro()
# Tweak all targets this CMake build is aware about
function(tweakTargetsForIDESupport)
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
_tweakTargetsRecursive("${CMAKE_SOURCE_DIR}")
endfunction()

View File

@@ -11,14 +11,6 @@ if (UNIX)
set(CORECLR_SUBARCH "arm64")
endif()
endif()
if (APPLE)
if (CMAKE_SYSTEM_PROCESSOR STREQUAL "arm64")
set(CORECLR_ARCH "osx-arm64")
set(CORECLR_SUBARCH "arm64")
else()
set(CORECLR_ARCH "osx-x64")
endif()
endif()
if (NOT DOTNET_EXECUTABLE)
set(DOTNET_EXECUTABLE dotnet)

View File

@@ -55,7 +55,7 @@ macro(add_imhex_plugin)
# Configure build properties
set_target_properties(${IMHEX_PLUGIN_NAME}
PROPERTIES
RUNTIME_OUTPUT_DIRECTORY "${IMHEX_MAIN_OUTPUT_DIRECTORY}/plugins"
RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/plugins
CXX_STANDARD 23
PREFIX ""
SUFFIX ${IMHEX_PLUGIN_SUFFIX}
@@ -88,28 +88,12 @@ macro(add_imhex_plugin)
# Fix rpath
if (APPLE)
set_target_properties(
${IMHEX_PLUGIN_NAME}
PROPERTIES
INSTALL_RPATH "@executable_path/../Frameworks;@executable_path/plugins"
)
set_target_properties(${IMHEX_PLUGIN_NAME} PROPERTIES INSTALL_RPATH "@executable_path/../Frameworks;@executable_path/plugins")
elseif (UNIX)
set(PLUGIN_RPATH "")
list(APPEND PLUGIN_RPATH "$ORIGIN")
if (IMHEX_PLUGIN_ADD_INSTALL_PREFIX_TO_RPATH)
list(APPEND PLUGIN_RPATH "${CMAKE_INSTALL_PREFIX}/lib")
endif()
set_target_properties(
${IMHEX_PLUGIN_NAME}
PROPERTIES
INSTALL_RPATH_USE_ORIGIN ON
INSTALL_RPATH "${PLUGIN_RPATH}"
)
set_target_properties(${IMHEX_PLUGIN_NAME} PROPERTIES INSTALL_RPATH_USE_ORIGIN ON INSTALL_RPATH "$ORIGIN/")
endif()
if (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/tests/CMakeLists.txt AND IMHEX_ENABLE_UNIT_TESTS AND IMHEX_ENABLE_PLUGIN_TESTS)
if (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/tests/CMakeLists.txt AND IMHEX_ENABLE_UNIT_TESTS)
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/tests)
target_link_libraries(${IMHEX_PLUGIN_NAME} PUBLIC ${IMHEX_PLUGIN_NAME}_tests)
target_compile_definitions(${IMHEX_PLUGIN_NAME}_tests PRIVATE IMHEX_PROJECT_NAME="${IMHEX_PLUGIN_NAME}-tests")
@@ -117,10 +101,6 @@ macro(add_imhex_plugin)
endmacro()
macro(add_romfs_resource input output)
if (NOT EXISTS ${input})
message(WARNING "Resource file ${input} does not exist")
endif()
configure_file(${input} ${CMAKE_CURRENT_BINARY_DIR}/romfs/${output} COPYONLY)
list(APPEND LIBROMFS_RESOURCE_LOCATION ${CMAKE_CURRENT_BINARY_DIR}/romfs)

View File

@@ -14,11 +14,12 @@ if(CMAKE_GENERATOR)
# Being called as include(PostprocessBundle), so define a helper function.
set(_POSTPROCESS_BUNDLE_MODULE_LOCATION "${CMAKE_CURRENT_LIST_FILE}")
function(postprocess_bundle out_target in_target)
install(CODE "set(BUNDLE_PATH ${CMAKE_INSTALL_PREFIX}/${BUNDLE_NAME})")
install(CODE "set(CODE_SIGN_CERTIFICATE_ID ${CODE_SIGN_CERTIFICATE_ID})")
install(CODE "set(EXTRA_BUNDLE_LIBRARY_PATHS ${EXTRA_BUNDLE_LIBRARY_PATHS})")
install(SCRIPT ${_POSTPROCESS_BUNDLE_MODULE_LOCATION})
add_custom_command(TARGET ${out_target} POST_BUILD
COMMAND ${CMAKE_COMMAND} -DBUNDLE_PATH="$<TARGET_FILE_DIR:${in_target}>/../.."
-DCODE_SIGN_CERTIFICATE_ID="${CODE_SIGN_CERTIFICATE_ID}"
-DEXTRA_BUNDLE_LIBRARY_PATHS="${EXTRA_BUNDLE_LIBRARY_PATHS}"
-P "${_POSTPROCESS_BUNDLE_MODULE_LOCATION}"
)
endfunction()
return()
endif()
@@ -41,7 +42,7 @@ file(GLOB_RECURSE plugins "${BUNDLE_PATH}/Contents/MacOS/plugins/*.hexplug")
# makes it sometimes break on libraries that do weird things with @rpath. Specify
# equivalent search directories until https://gitlab.kitware.com/cmake/cmake/issues/16625
# is fixed and in our minimum CMake version.
set(extra_dirs "/usr/local/lib" "/lib" "/usr/lib" ${EXTRA_BUNDLE_LIBRARY_PATHS} "${BUNDLE_PATH}/Contents/MacOS/plugins" "${BUNDLE_PATH}/Contents/Frameworks")
set(extra_dirs "/usr/local/lib" "/lib" "/usr/lib" ${EXTRA_BUNDLE_LIBRARY_PATHS} "${BUNDLE_PATH}/Contents/MacOS/plugins")
message(STATUS "Fixing up application bundle: ${extra_dirs}")
# BundleUtilities is overly verbose, so disable most of its messages

View File

@@ -44,7 +44,7 @@ add_subdirectory(lib/libimhex)
if (WIN32)
set_target_properties(libimhex PROPERTIES
IMPORTED_LOCATION "${CMAKE_CURRENT_SOURCE_DIR}/../libimhex.dll"
IMPORTED_IMPLIB "${CMAKE_CURRENT_SOURCE_DIR}/lib/libimhex.dll.a"
IMPORTED_IMPLIB "${CMAKE_CURRENT_SOURCE_DIR}/lib/liblibimhex.dll.a"
INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_CURRENT_SOURCE_DIR}/lib/libimhex/include")
elseif (APPLE)
file(GLOB LIBIMHEX_DYLIB "${CMAKE_CURRENT_SOURCE_DIR}/../../Frameworks/libimhex.*.dylib")

View File

@@ -18,11 +18,11 @@ docker buildx build . -f <DOCKERFILE_PATH> --progress plain --build-arg 'JOBS=4'
where `<DOCKERFILE_PATH>` should be replaced by the wanted Dockerfile base d on the build you want to do:
| Wanted build | Dockerfile path | Target |
|--------------|-----------------------------|--------|
| MacOS M1 | dist/macOS/arm64.Dockerfile | - |
| AppImage | dist/appimage/Dockerfile | - |
| Web version | dist/web/Dockerfile | raw |
| Wanted build | Dockerfile path |
|--------------|-----------------------------|
| MacOS M1 | dist/macOS/arm64.Dockerfile |
| AppImage | dist/appimage/Dockerfile |
| Web version | dist/web/Dockerfile |
We'll explain this command in the next section
@@ -43,7 +43,6 @@ In the command saw earlier:
- `.` is the base folder that the Dockerfile will be allowed to see
- `-f <path>` is to specify the Dockerfile path
- `--progress plain` is to allow you to see the output of instructions
- `--build-arg <key>=<value>` is to allow to specify arguments to the build (like -DKEY=VALUE in CMake)
- `--build-arg <key>=<value>` is to allow to to specify arguments to the build (like -DKEY=VALUE in CMake)
- `--build-context key=<folder>` is to specify folders other than the base folder that the Dockerfile is allowed to see
- `--output <path>` is the path to write the output package to. If not specified, Docker will create an image as the output (probably not what you want)
- `--target <target>` specifies which docker target to build

View File

@@ -13,8 +13,14 @@ CC=gcc-12 CXX=g++-12 \
cmake -G "Ninja" \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_INSTALL_PREFIX="/usr" \
-DCMAKE_C_COMPILER_LAUNCHER=ccache \
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
-DCMAKE_C_FLAGS="-fuse-ld=lld" \
-DCMAKE_CXX_FLAGS="-fuse-ld=lld" \
-DCMAKE_OBJC_COMPILER_LAUNCHER=ccache \
-DCMAKE_OBJCXX_COMPILER_LAUNCHER=ccache \
..
ninja install
make -j 4 install
```
All paths follow the XDG Base Directories standard, and can thus be modified

View File

@@ -15,7 +15,7 @@ OBJC=$(brew --prefix llvm)/bin/clang \
OBJCXX=$(brew --prefix llvm)/bin/clang++ \
cmake -G "Ninja" \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_INSTALL_PREFIX="./install" \
-DCMAKE_INSTALL_PREFIX=./install \
-DIMHEX_GENERATE_PACKAGE=ON \
..
ninja install

View File

@@ -14,7 +14,7 @@ mkdir build
cd build
cmake -G "Ninja" \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_INSTALL_PREFIX="./install" \
-DCMAKE_INSTALL_PREFIX="$PWD/install" \
-DIMHEX_USE_DEFAULT_BUILD_SETTINGS=ON \
..
ninja install

View File

@@ -1,48 +0,0 @@
import subprocess
import sys
def get_commits(branch: str, start_tag: str, end_tag: str) -> list[str]:
try:
commits_raw = subprocess.check_output([ "git", "--no-pager", "log", branch, "--no-color", "--pretty=oneline", "--abbrev-commit", f"{start_tag}..{end_tag}"], stderr=subprocess.DEVNULL).decode("UTF-8").split("\n")
except:
return []
commits = []
for line in commits_raw:
commits.append(line[9:])
return commits
def main(args: list) -> int:
if len(args) != 2:
print(f"Usage: {args[0]} prev_minor")
return 1
last_minor_version = f"v1.{args[1]}"
master_commits = get_commits("master", f"{last_minor_version}.0", "master")
for i in range(1, 100):
branch_commits = get_commits(f"releases/{last_minor_version}.X", f"{last_minor_version}.0", f"{last_minor_version}.{i}")
if len(branch_commits) == 0:
break
master_commits = [commit for commit in master_commits if commit not in branch_commits]
sorted_commits = {}
for commit in master_commits:
category, commit_name = commit.split(":", 1)
if category not in sorted_commits:
sorted_commits[category] = []
sorted_commits[category].append(commit_name)
for category in sorted_commits:
print(f"## {category}\n")
for commit in sorted_commits[category]:
print(f"- {commit}")
print(f"\n")
if __name__ == "__main__":
exit(main(sys.argv))

View File

@@ -1,19 +0,0 @@
#!/usr/bin/env sh
zypper install \
cmake \
ninja \
gcc12 \
gcc12-c++ \
freetype2-devel \
libcurl-devel \
dbus-1-devel \
file-devel \
Mesa-libGL-devel \
libglfw-devel \
mbedtls-devel \
gtk3-devel \
libzstd-devel \
zlib-devel \
bzip3-devel \
xz-devel

1
dist/imhex.desktop vendored
View File

@@ -8,4 +8,3 @@ Type=Application
StartupNotify=true
Categories=Development;IDE;
StartupWMClass=imhex
Keywords=static-analysis;reverse-engineering;disassembler;disassembly;hacking;forensics;hex-editor;cybersecurity;security;binary-analysis;

238
dist/langtool.py vendored Executable file → Normal file
View File

@@ -1,208 +1,104 @@
#!/usr/bin/env python3
from pathlib import Path
import argparse
import sys
import json
# This fixes a CJK full-width character input issue
# which makes left halves of deleted characters displayed on screen
# pylint: disable=unused-import
import re
import readline
DEFAULT_LANG = "en_US"
DEFAULT_LANG_PATH = "plugins/*/romfs/lang/"
INVALID_TRANSLATION = ""
def handle_missing_key(command, lang_data, key, value):
if command == "check":
print(f"Error: Translation {lang_data['code']} is missing translation for key '{key}'")
exit(2)
elif command == "translate" or command == "create":
print(f"Key \033[1m'{key}': '{value}'\033[0m is missing in translation '{lang_data['code']}'")
new_value = input("Enter translation: ")
lang_data["translations"][key] = new_value
elif command == "update":
lang_data["translations"][key] = INVALID_TRANSLATION
def main():
parser = argparse.ArgumentParser(
prog="langtool",
description="ImHex translate tool",
)
parser.add_argument(
"command",
choices=[
"check",
"translate",
"update",
"create",
"retranslate",
"untranslate",
"fmtzh",
],
)
parser.add_argument(
"-c", "--langdir", default=DEFAULT_LANG_PATH, help="Language folder glob"
)
parser.add_argument("-l", "--lang", default="", help="Language to translate")
parser.add_argument(
"-r", "--reflang", default="", help="Language for reference when translating"
)
parser.add_argument(
"-k", "--keys", help="Keys to re-translate (only in re/untranslate mode)"
)
args = parser.parse_args()
command = args.command
lang = args.lang
print(f"Running in {command} mode")
lang_files_glob = f"{lang}.json" if lang != "" else "*.json"
lang_folders = set(Path(".").glob(args.langdir))
if len(lang_folders) == 0:
print(f"Error: {args.langdir} matches nothing")
if len(sys.argv) < 3:
print(f"Usage: {Path(sys.argv[0]).name} <check|translate|update|create> <lang folder path> <language>")
return 1
for lang_folder in lang_folders:
if not lang_folder.is_dir():
print(f"Error: {lang_folder} is not a folder")
return 1
command = sys.argv[1]
if command not in ["check", "translate", "update", "create"]:
print(f"Unknown command: {command}")
return 1
default_lang_data = {}
default_lang_path = lang_folder / Path(DEFAULT_LANG + ".json")
if not default_lang_path.exists():
print(
f"Error: Default language file {default_lang_path} does not exist in {lang_folder}"
)
return 1
with default_lang_path.open("r", encoding="utf-8") as file:
default_lang_data = json.load(file)
print(f"Using langtool in {command} mode")
reference_lang_data = None
reference_lang_path = lang_folder / Path(args.reflang + ".json")
if reference_lang_path.exists():
with reference_lang_path.open("r", encoding="utf-8") as file:
reference_lang_data = json.load(file)
lang_folder_path = Path(sys.argv[2])
if not lang_folder_path.exists():
print(f"Error: {lang_folder_path} does not exist")
return 1
if not lang_folder_path.is_dir():
print(f"Error: {lang_folder_path} is not a folder")
return 1
lang = sys.argv[3] if len(sys.argv) > 3 else ""
print(f"Processing language files in {lang_folder_path}...")
default_lang_file_path = lang_folder_path / Path(DEFAULT_LANG + ".json")
if not default_lang_file_path.exists():
print(f"Error: Default language file {default_lang_file_path} does not exist")
return 1
print(f"Using file '{default_lang_file_path.name}' as template language file")
with default_lang_file_path.open("r", encoding="utf-8") as default_lang_file:
default_lang_data = json.load(default_lang_file)
if command == "create" and lang != "":
lang_file_path = lang_folder / Path(lang + ".json")
lang_file_path = lang_folder_path / Path(lang + ".json")
if lang_file_path.exists():
continue
print(f"Error: Language file {lang_file_path} already exists")
return 1
exist_lang_data = None
for lang_folder1 in lang_folders:
lang_file_path1 = lang_folder1 / Path(lang + ".json")
if lang_file_path1.exists():
with lang_file_path1.open("r", encoding="utf-8") as file:
exist_lang_data = json.load(file)
break
print(f"Creating new language file '{lang_file_path}'")
print(f"Creating new language file '{lang_file_path.name}'")
with lang_file_path.open("w", encoding="utf-8") as new_lang_file:
new_lang_data = {
"code": lang,
"language": (
exist_lang_data["language"]
if exist_lang_data
else input("Enter language name: ")
),
"country": (
exist_lang_data["country"]
if exist_lang_data
else input("Enter country name: ")
),
"translations": {},
"language": input("Enter language: "),
"country": input("Enter country: "),
"translations": {}
}
json.dump(new_lang_data, new_lang_file, indent=4, ensure_ascii=False)
lang_files = set(lang_folder.glob(lang_files_glob))
if len(lang_files) == 0:
print(f"Warn: Language file for '{lang}' does not exist in '{lang_folder}'")
for lang_file_path in lang_files:
if (
lang_file_path.stem == f"{DEFAULT_LANG}.json"
or lang_file_path.stem == f"{args.reflang}.json"
):
for additional_lang_file_path in lang_folder_path.glob("*.json"):
if not lang == "" and not additional_lang_file_path.stem == lang:
continue
print(f"\nProcessing '{lang_file_path}'")
if not (command == "update" or command == "create"):
print("\n----------------------------\n")
if additional_lang_file_path.name.startswith(DEFAULT_LANG):
continue
with lang_file_path.open("r+", encoding="utf-8") as target_lang_file:
lang_data = json.load(target_lang_file)
print(f"\nProcessing file '{additional_lang_file_path.name}'\n----------------------------\n")
with additional_lang_file_path.open("r+", encoding="utf-8") as additional_lang_file:
additional_lang_data = json.load(additional_lang_file)
for key, value in default_lang_data["translations"].items():
has_translation = (
key in lang_data["translations"]
and lang_data["translations"][key] != INVALID_TRANSLATION
)
if not has_translation and not (
(command == "retranslate" or command == "untranslate")
and re.compile(args.keys).fullmatch(key)
):
continue
if command == "check":
print(
f"Error: Translation {lang_data['code']} is missing translation for key '{key}'"
)
exit(2)
elif (
command == "translate"
or command == "retranslate"
or command == "untranslate"
):
if command == "untranslate" and not has_translation:
continue
reference_tranlsation = (
" '%s'" % reference_lang_data["translations"][key]
if reference_lang_data
else ""
)
print(
f"\033[1m'{key}' '{value}'{reference_tranlsation}\033[0m => {lang_data['language']}",
end="",
)
if has_translation:
translation = lang_data["translations"][key]
print(f" <= \033[1m'{translation}'\033[0m")
print() # for a new line
if command == "untranslate":
lang_data["translations"][key] = INVALID_TRANSLATION
continue
try:
new_value = input("=> ")
lang_data["translations"][key] = new_value
except KeyboardInterrupt:
break
elif command == "update" or command == "create":
lang_data["translations"][key] = INVALID_TRANSLATION
elif command == "fmtzh":
if has_translation:
lang_data["translations"][key] = fmtzh(
lang_data["translations"][key]
)
if key not in additional_lang_data["translations"] or additional_lang_data["translations"][key] == INVALID_TRANSLATION:
handle_missing_key(command, additional_lang_data, key, value)
keys_to_remove = []
for key, value in lang_data["translations"].items():
for key, value in additional_lang_data["translations"].items():
if key not in default_lang_data["translations"]:
keys_to_remove.append(key)
for key in keys_to_remove:
lang_data["translations"].pop(key)
print(
f"Removed unused key '{key}' from translation '{lang_data['code']}'"
)
additional_lang_data["translations"].pop(key)
print(f"Removed unused key '{key}' from translation '{additional_lang_data['code']}'")
target_lang_file.seek(0)
target_lang_file.truncate()
json.dump(
lang_data,
target_lang_file,
indent=4,
sort_keys=True,
ensure_ascii=False,
)
additional_lang_file.seek(0)
additional_lang_file.truncate()
json.dump(additional_lang_data, additional_lang_file, indent=4, sort_keys=True, ensure_ascii=False)
def fmtzh(text: str) -> str:
text = re.sub(r"(\.{3}|\.{6})", "……", text)
text = text.replace("!", "")
text = re.sub(r"([^\.\na-zA-Z\d])\.$", "\1", text, flags=re.M)
text = text.replace("?", "")
return text
if __name__ == "__main__":
if __name__ == '__main__':
exit(main())

View File

@@ -35,9 +35,9 @@ EOF
## Download libmagic
### Clone libmagic
RUN git clone --depth 1 --branch FILE5_45 https://github.com/file/file /mnt/file
RUN git clone https://github.com/file/file /mnt/file
### Download libmagic dependencies
RUN --mount=type=cache,target=/var/lib/apt/lists/ apt update && apt install -y libtool autoconf
RUN --mount=type=cache,target=/var/lib/apt/lists/ apt install -y libtool autoconf
# -- DOWNLOADING + BUILDING STUFF
@@ -170,4 +170,4 @@ EOF
FROM scratch
COPY --from=build /mnt/ImHex/build/install/imhex.app imhex.app
COPY --from=build /mnt/ImHex/build/install/imhex.app ImHex.app

13
dist/rpm/imhex.spec vendored
View File

@@ -1,7 +1,5 @@
%define source_date_epoch_from_changelog 0
Name: imhex
Version: VERSION
Version: 1.26.2
Release: 0%{?dist}
Summary: A hex editor for reverse engineers and programmers
@@ -97,6 +95,10 @@ CXXFLAGS+=" -std=gnu++2b"
%set_build_flags
CXXFLAGS+=" -std=gnu++2b"
%endif
# build binaries required for tests
%cmake_build --target unit_tests
%ctest --exclude-regex '(Helpers/StoreAPI|Helpers/TipsAPI|Helpers/ContentAPI)'
# Helpers/*API exclude tests that require network access
%install
@@ -126,4 +128,7 @@ cp -a lib/third_party/xdgpp/LICENSE %{buildroot
%{_datadir}/applications/%{name}.desktop
%{_libdir}/libimhex.so*
%{_libdir}/%{name}/
%{_metainfodir}/net.werwolv.%{name}.metainfo.xml
%{_metainfodir}/net.werwolv.%{name}.metainfo.xml
%changelog

1
dist/web/Dockerfile vendored
View File

@@ -59,7 +59,6 @@ cmake /imhex
-DIMHEX_OFFLINE_BUILD=ON \
-DIMHEX_STATIC_LINK_PLUGINS=ON \
-DIMHEX_EXCLUDE_PLUGINS="script_loader" \
-DIMHEX_COMPRESS_DEBUG_INFO=OFF \
-DNATIVE_CMAKE_C_COMPILER=gcc \
-DNATIVE_CMAKE_CXX_COMPILER=g++ \
-DCMAKE_C_COMPILER_LAUNCHER=ccache \

View File

@@ -2,6 +2,7 @@ cmake_minimum_required(VERSION 3.16)
project(libimhex)
set(CMAKE_CXX_STANDARD 23)
set(CMAKE_SHARED_LIBRARY_PREFIX "")
set(LIBIMHEX_SOURCES
source/api/imhex_api.cpp
@@ -36,10 +37,6 @@ set(LIBIMHEX_SOURCES
source/helpers/logger.cpp
source/helpers/tar.cpp
source/helpers/debugging.cpp
source/helpers/default_paths.cpp
source/helpers/imgui_hooks.cpp
source/test/tests.cpp
source/providers/provider.cpp
source/providers/memory_provider.cpp
@@ -125,7 +122,7 @@ target_link_directories(libimhex ${LIBIMHEX_LIBRARY_TYPE} ${MBEDTLS_LIBRARY_DIR}
if (NOT EMSCRIPTEN)
# curl is only used in non-emscripten builds
target_link_libraries(libimhex ${LIBIMHEX_LIBRARY_TYPE} CURL::libcurl)
target_link_libraries(libimhex ${LIBIMHEX_LIBRARY_TYPE} ${CURL_LIBRARIES})
endif()
@@ -144,12 +141,8 @@ if (NOT IMHEX_EXTERNAL_PLUGIN_BUILD)
precompileHeaders(libimhex "${CMAKE_CURRENT_SOURCE_DIR}/include")
endif()
target_link_libraries(libimhex ${LIBIMHEX_LIBRARY_TYPE} ${NLOHMANN_JSON_LIBRARIES} imgui_all_includes ${MBEDTLS_LIBRARIES} ${FMT_LIBRARIES} ${LUNASVG_LIBRARIES} boost::regex)
target_link_libraries(libimhex ${LIBIMHEX_LIBRARY_TYPE} ${NLOHMANN_JSON_LIBRARIES} imgui_all_includes ${MBEDTLS_LIBRARIES} ${FMT_LIBRARIES})
set_property(TARGET libimhex PROPERTY INTERPROCEDURAL_OPTIMIZATION FALSE)
add_dependencies(imhex_all libimhex)
install(FILES "$<TARGET_FILE:libimhex>" DESTINATION "${CMAKE_INSTALL_LIBDIR}" PERMISSIONS ${LIBRARY_PERMISSIONS})
set_target_properties(libimhex PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
set_target_properties(libimhex PROPERTIES PREFIX "")
add_dependencies(imhex_all libimhex)

View File

@@ -151,7 +151,7 @@ namespace hex {
if (m_icon.isValid())
return m_icon;
m_icon = ImGuiExt::Texture::fromImage(m_iconData.data(), m_iconData.size(), ImGuiExt::Texture::Filter::Linear);
m_icon = ImGuiExt::Texture(m_iconData.data(), m_iconData.size(), ImGuiExt::Texture::Filter::Linear);
return m_icon;
}

View File

@@ -6,7 +6,6 @@
#include <functional>
#include <map>
#include <mutex>
#include <span>
#include <string>
#include <utility>
@@ -99,7 +98,7 @@ namespace hex {
bool m_requiresRestart = false;
std::function<bool()> m_enabledCallback;
std::function<void(Widget&)> m_changedCallback;
std::optional<UnlocalizedString> m_tooltip;
std::optional<std::string> m_tooltip;
};
[[nodiscard]]
@@ -113,7 +112,7 @@ namespace hex {
}
[[nodiscard]]
const std::optional<UnlocalizedString>& getTooltip() const {
const std::optional<std::string>& getTooltip() const {
return m_interface.m_tooltip;
}
@@ -176,21 +175,6 @@ namespace hex {
float m_min, m_max;
};
class SliderDataSize : public Widget {
public:
SliderDataSize(u64 defaultValue, u64 min, u64 max) : m_value(defaultValue), m_min(min), m_max(max) { }
bool draw(const std::string &name) override;
void load(const nlohmann::json &data) override;
nlohmann::json store() override;
[[nodiscard]] i32 getValue() const { return m_value; }
protected:
u64 m_value;
u64 m_min, m_max;
};
class ColorPicker : public Widget {
public:
explicit ColorPicker(ImColor defaultColor);
@@ -356,8 +340,6 @@ namespace hex {
void write(const UnlocalizedString &unlocalizedCategory, const UnlocalizedString &unlocalizedName, const std::common_type_t<T> &value) {
impl::getSetting(unlocalizedCategory, unlocalizedName, value) = value;
impl::runOnChangeHandlers(unlocalizedCategory, unlocalizedName, value);
impl::store();
}
using OnChangeCallback = std::function<void(const SettingsValue &)>;
@@ -774,7 +756,6 @@ namespace hex {
const std::multimap<u32, MainMenuItem>& getMainMenuItems();
const std::multimap<u32, MenuItem>& getMenuItems();
const std::vector<MenuItem*>& getToolbarMenuItems();
std::multimap<u32, MenuItem>& getMenuItemsMutable();
const std::vector<DrawCallback>& getWelcomeScreenEntries();
@@ -917,11 +898,6 @@ namespace hex {
*/
void addMenuItemToToolbar(const UnlocalizedString &unlocalizedName, ImGuiCustomCol color);
/**
* @brief Reconstructs the toolbar items list after they have been modified
*/
void updateToolbarItems();
/**
* @brief Adds a new sidebar item
* @param icon The icon to use for the item
@@ -955,7 +931,7 @@ namespace hex {
void addProviderName(const UnlocalizedString &unlocalizedName);
using ProviderCreationFunction = std::function<std::unique_ptr<prv::Provider>()>;
using ProviderCreationFunction = std::unique_ptr<prv::Provider>(*)();
void add(const std::string &typeName, ProviderCreationFunction creationFunction);
const std::vector<std::string>& getEntries();
@@ -987,34 +963,12 @@ namespace hex {
namespace impl {
using Callback = std::function<std::string(prv::Provider *provider, u64 address, size_t size)>;
struct ExportMenuEntry {
struct Entry {
UnlocalizedString unlocalizedName;
Callback callback;
};
struct FindOccurrence {
Region region;
enum class DecodeType { ASCII, Binary, UTF16, Unsigned, Signed, Float, Double } decodeType;
std::endian endian = std::endian::native;
bool selected;
};
using FindExporterCallback = std::function<std::vector<u8>(const std::vector<FindOccurrence>&, std::function<std::string(FindOccurrence)>)>;
struct FindExporterEntry {
UnlocalizedString unlocalizedName;
std::string fileExtension;
FindExporterCallback callback;
};
/**
* @brief Retrieves a list of all registered data formatters used by the 'File -> Export' menu
*/
const std::vector<ExportMenuEntry>& getExportMenuEntries();
/**
* @brief Retrieves a list of all registered data formatters used in the Results section of the 'Find' view
*/
const std::vector<FindExporterEntry>& getFindExporterEntries();
const std::vector<Entry>& getEntries();
}
@@ -1024,14 +978,7 @@ namespace hex {
* @param unlocalizedName The unlocalized name of the formatter
* @param callback The function to call to format the data
*/
void addExportMenuEntry(const UnlocalizedString &unlocalizedName, const impl::Callback &callback);
/**
* @brief Adds a new data exporter for Find results
* @param unlocalizedName The unlocalized name of the formatter
* @param callback The function to call to format the data
*/
void addFindExportFormatter(const UnlocalizedString &unlocalizedName, const std::string fileExtension, const impl::FindExporterCallback &callback);
void add(const UnlocalizedString &unlocalizedName, const impl::Callback &callback);
}
@@ -1092,7 +1039,7 @@ namespace hex {
};
struct MiniMapVisualizer {
using Callback = std::function<void(u64, std::span<const u8>, std::vector<ImColor>&)>;
using Callback = std::function<ImColor(const std::vector<u8>&)>;
UnlocalizedString unlocalizedName;
Callback callback;

View File

@@ -2,30 +2,28 @@
#include <hex.hpp>
#include <algorithm>
#include <functional>
#include <list>
#include <mutex>
#include <map>
#include <string_view>
#include <functional>
#include <hex/api/imhex_api.hpp>
#include <hex/helpers/logger.hpp>
#include <wolv/types/type_name.hpp>
#define EVENT_DEF_IMPL(event_name, event_name_string, should_log, ...) \
struct event_name final : public hex::impl::Event<__VA_ARGS__> { \
constexpr static auto Id = [] { return hex::impl::EventId(event_name_string); }(); \
constexpr static auto ShouldLog = (should_log); \
explicit event_name(Callback func) noexcept : Event(std::move(func)) { } \
\
static EventManager::EventList::iterator subscribe(Event::Callback function) { return EventManager::subscribe<event_name>(std::move(function)); } \
static void subscribe(void *token, Event::Callback function) { EventManager::subscribe<event_name>(token, std::move(function)); } \
static void unsubscribe(const EventManager::EventList::iterator &token) noexcept { EventManager::unsubscribe(token); } \
static void unsubscribe(void *token) noexcept { EventManager::unsubscribe<event_name>(token); } \
static void post(auto &&...args) { EventManager::post<event_name>(std::forward<decltype(args)>(args)...); } \
}
#define EVENT_DEF_IMPL(event_name, event_name_string, should_log, ...) \
struct event_name final : public hex::impl::Event<__VA_ARGS__> { \
constexpr static auto Id = [] { return hex::impl::EventId(event_name_string); }(); \
constexpr static auto ShouldLog = (should_log); \
explicit event_name(Callback func) noexcept : Event(std::move(func)) { } \
\
static EventManager::EventList::iterator subscribe(Event::Callback function) { return EventManager::subscribe<event_name>(function); } \
static void subscribe(void *token, Event::Callback function) { EventManager::subscribe<event_name>(token, function); } \
static void unsubscribe(const EventManager::EventList::iterator &token) noexcept { EventManager::unsubscribe(token); } \
static void unsubscribe(void *token) noexcept { EventManager::unsubscribe<event_name>(token); } \
static void post(auto &&...args) { EventManager::post<event_name>(std::forward<decltype(args)>(args)...); } \
};
#define EVENT_DEF(event_name, ...) EVENT_DEF_IMPL(event_name, #event_name, true, __VA_ARGS__)
#define EVENT_DEF_NO_LOG(event_name, ...) EVENT_DEF_IMPL(event_name, #event_name, false, __VA_ARGS__)
@@ -58,10 +56,6 @@ namespace hex {
return m_hash == other.m_hash;
}
constexpr auto operator<=>(const EventId &other) const {
return m_hash <=> other.m_hash;
}
private:
u32 m_hash;
};
@@ -77,12 +71,11 @@ namespace hex {
explicit Event(Callback func) noexcept : m_func(std::move(func)) { }
template<typename E>
void call(Params... params) const {
void operator()(std::string_view eventName, Params... params) const {
try {
m_func(params...);
} catch (const std::exception &e) {
log::error("An exception occurred while handling event {}: {}", wolv::type::getTypeName<E>(), e.what());
log::error("An exception occurred while handling event {}: {}", eventName, e.what());
throw;
}
}
@@ -103,7 +96,7 @@ namespace hex {
*/
class EventManager {
public:
using EventList = std::multimap<impl::EventId, std::unique_ptr<impl::EventBase>>;
using EventList = std::list<std::pair<impl::EventId, std::unique_ptr<impl::EventBase>>>;
/**
* @brief Subscribes to an event
@@ -116,7 +109,7 @@ namespace hex {
std::scoped_lock lock(getEventMutex());
auto &events = getEvents();
return events.insert({ E::Id, std::make_unique<E>(function) });
return events.insert(events.end(), std::make_pair(E::Id, std::make_unique<E>(function)));
}
/**
@@ -168,7 +161,7 @@ namespace hex {
});
if (iter != tokenStore.end()) {
getEvents().erase(iter->second);
getEvents().remove(*iter->second);
tokenStore.erase(iter);
}
@@ -183,14 +176,14 @@ namespace hex {
static void post(auto && ...args) {
std::scoped_lock lock(getEventMutex());
auto [begin, end] = getEvents().equal_range(E::Id);
for (auto it = begin; it != end; ++it) {
const auto &[id, event] = *it;
(*static_cast<E *const>(event.get())).template call<E>(std::forward<decltype(args)>(args)...);
for (const auto &[id, event] : getEvents()) {
if (id == E::Id) {
(*static_cast<E *const>(event.get()))(wolv::type::getTypeName<E>(), std::forward<decltype(args)>(args)...);
}
}
#if defined (DEBUG)
if constexpr (E::ShouldLog)
if (E::ShouldLog)
log::debug("Event posted: '{}'", wolv::type::getTypeName<E>());
#endif
}
@@ -270,7 +263,6 @@ namespace hex {
EVENT_DEF(EventProviderDataModified, prv::Provider *, u64, u64, const u8*);
EVENT_DEF(EventProviderDataInserted, prv::Provider *, u64, u64);
EVENT_DEF(EventProviderDataRemoved, prv::Provider *, u64, u64);
EVENT_DEF(EventProviderDirtied, prv::Provider *);
/**
* @brief Called when a project has been loaded
@@ -280,7 +272,6 @@ namespace hex {
EVENT_DEF_NO_LOG(EventFrameBegin);
EVENT_DEF_NO_LOG(EventFrameEnd);
EVENT_DEF_NO_LOG(EventSetTaskBarIconState, u32, u32, u32);
EVENT_DEF_NO_LOG(EventImGuiElementRendered, ImGuiID, const std::array<float, 4>&);
EVENT_DEF(RequestAddInitTask, std::string, bool, std::function<bool()>);
EVENT_DEF(RequestAddExitTask, std::string, std::function<bool()>);

View File

@@ -3,13 +3,11 @@
#include <hex.hpp>
#include <hex/api/localization_manager.hpp>
#include <functional>
#include <optional>
#include <span>
#include <string>
#include <vector>
#include <map>
#include <set>
#include <wolv/io/fs.hpp>
@@ -293,7 +291,7 @@ namespace hex {
namespace impl {
void resetClosingProvider();
std::set<prv::Provider*> getClosingProviders();
const std::vector<prv::Provider*>& getClosingProviders();
}
@@ -434,7 +432,6 @@ namespace hex {
void setInitialWindowProperties(InitialWindowProperties properties);
void setGPUVendor(const std::string &vendor);
void setGLRenderer(const std::string &renderer);
void addInitArgument(const std::string &key, const std::string &value = { });
@@ -574,12 +571,6 @@ namespace hex {
*/
const std::string& getGPUVendor();
/**
* @brief Gets the current GPU vendor
* @return The current GPU vendor
*/
const std::string& getGLRenderer();
/**
* @brief Checks if ImHex is running in portable mode
* @return Whether ImHex is running in portable mode
@@ -604,16 +595,6 @@ namespace hex {
*/
std::string getArchitecture();
struct LinuxDistro {
std::string name;
std::string version;
};
/**
* @brief Gets information related to the Linux distribution, if running on Linux
*/
std::optional<LinuxDistro> getLinuxDistro();
/**
* @brief Gets the current ImHex version
* @return ImHex version
@@ -639,12 +620,6 @@ namespace hex {
*/
bool isDebugBuild();
/**
* @brief Checks if this version of ImHex is a nightly build
* @return True if this version is a nightly, false if it's a release
*/
bool isNightlyBuild();
enum class UpdateType {
Stable,
Nightly
@@ -689,12 +664,6 @@ namespace hex {
*/
std::optional<InitialWindowProperties> getInitialWindowProperties();
/**
* @brief Gets the module handle of libimhex
* @return Module handle
*/
void* getLibImHexModuleHandle();
}
/**

View File

@@ -46,13 +46,7 @@ namespace hex {
* @brief Get a list of all layouts
* @return List of all added layouts
*/
static const std::vector<Layout> &getLayouts();
/**
* @brief Removes the layout with the given name
* @param name Name of the layout
*/
static void removeLayout(const std::string &name);
static std::vector<Layout> getLayouts();
/**
* @brief Handles loading of layouts if needed

View File

@@ -15,10 +15,8 @@ struct ImGuiContext;
namespace hex {
struct SubCommand {
std::string commandLong;
std::string commandShort;
std::string commandDescription;
std::string commandKey;
std::string commandDesc;
std::function<void(const std::vector<std::string>&)> callback;
};
@@ -106,10 +104,6 @@ namespace hex {
static bool load();
static bool load(const std::fs::path &pluginFolder);
static bool loadLibraries();
static bool loadLibraries(const std::fs::path &libraryFolder);
static void unload();
static void reload();
static void initializeNewPlugins();
@@ -117,7 +111,6 @@ namespace hex {
static void addPlugin(const std::string &name, PluginFunctions functions);
static Plugin* getPlugin(const std::string &name);
static const std::list<Plugin>& getPlugins();
static const std::vector<std::fs::path>& getPluginPaths();
static const std::vector<std::fs::path>& getPluginLoadPaths();
@@ -128,7 +121,6 @@ namespace hex {
static std::list<Plugin>& getPluginsMutable();
static AutoReset<std::vector<std::fs::path>> s_pluginPaths, s_pluginLoadPaths;
static AutoReset<std::vector<uintptr_t>> s_loadedLibraries;
};
}

View File

@@ -119,8 +119,6 @@ namespace hex {
decltype(m_steps)::iterator m_currentStep, m_latestStep;
};
static void init();
/**
* @brief Gets a list of all tutorials
* @return List of all tutorials
@@ -147,10 +145,6 @@ namespace hex {
*/
static void startTutorial(const UnlocalizedString &unlocalizedName);
static void startHelpHover();
static void addInteractiveHelpText(std::initializer_list<std::variant<Lang, std::string, int>> &&ids, UnlocalizedString unlocalizedString);
static void addInteractiveHelpLink(std::initializer_list<std::variant<Lang, std::string, int>> &&ids, std::string link);
/**
* @brief Draws the tutorial

View File

@@ -13,22 +13,18 @@ namespace hex {
struct Workspace {
std::string layout;
std::fs::path path;
bool builtin;
};
static void createWorkspace(const std::string &name, const std::string &layout = "");
static void switchWorkspace(const std::string &name);
static void importFromFile(const std::fs::path &path);
static bool exportToFile(std::fs::path path = {}, std::string workspaceName = {}, bool builtin = false);
static void removeWorkspace(const std::string &name);
static bool exportToFile(std::fs::path path = {}, std::string workspaceName = {});
static const auto& getWorkspaces() { return *s_workspaces; }
static const auto& getCurrentWorkspace() { return s_currentWorkspace; }
static void reset();
static void reload();
static void process();
@@ -36,7 +32,7 @@ namespace hex {
WorkspaceManager() = default;
static AutoReset<std::map<std::string, Workspace>> s_workspaces;
static decltype(s_workspaces)::Type::iterator s_currentWorkspace, s_previousWorkspace, s_workspaceToRemove;
static decltype(s_workspaces)::Type::iterator s_currentWorkspace, s_previousWorkspace;
};
}

View File

@@ -50,23 +50,14 @@ namespace hex {
T& operator=(const T &value) {
m_value = value;
m_valid = true;
return m_value;
}
T& operator=(T &&value) noexcept {
m_value = std::move(value);
m_valid = true;
return m_value;
}
bool isValid() const {
return m_valid;
}
private:
friend void ImHexApi::System::impl::cleanup();
void reset() override {
if constexpr (requires { m_value.reset(); }) {
m_value.reset();
@@ -77,12 +68,9 @@ namespace hex {
} else {
m_value = { };
}
m_valid = false;
}
private:
bool m_valid = true;
T m_value;
};

View File

@@ -1,111 +0,0 @@
#pragma once
#include <hex/helpers/fs.hpp>
#include <vector>
namespace hex::paths {
namespace impl {
class DefaultPath {
protected:
constexpr DefaultPath() = default;
virtual ~DefaultPath() = default;
public:
DefaultPath(const DefaultPath&) = delete;
DefaultPath(DefaultPath&&) = delete;
DefaultPath& operator=(const DefaultPath&) = delete;
DefaultPath& operator=(DefaultPath&&) = delete;
virtual std::vector<std::fs::path> all() const = 0;
virtual std::vector<std::fs::path> read() const;
virtual std::vector<std::fs::path> write() const;
};
class ConfigPath : public DefaultPath {
public:
explicit ConfigPath(std::fs::path postfix) : m_postfix(std::move(postfix)) {}
std::vector<std::fs::path> all() const override;
private:
std::fs::path m_postfix;
};
class DataPath : public DefaultPath {
public:
explicit DataPath(std::fs::path postfix) : m_postfix(std::move(postfix)) {}
std::vector<std::fs::path> all() const override;
std::vector<std::fs::path> write() const override;
private:
std::fs::path m_postfix;
};
class PluginPath : public DefaultPath {
public:
explicit PluginPath(std::fs::path postfix) : m_postfix(std::move(postfix)) {}
std::vector<std::fs::path> all() const override;
private:
std::fs::path m_postfix;
};
}
std::vector<std::fs::path> getDataPaths(bool includeSystemFolders);
std::vector<std::fs::path> getConfigPaths(bool includeSystemFolders);
const static inline impl::ConfigPath Config("config");
const static inline impl::ConfigPath Recent("recent");
const static inline impl::PluginPath Libraries("lib");
const static inline impl::PluginPath Plugins("plugins");
const static inline impl::DataPath Patterns("patterns");
const static inline impl::DataPath PatternsInclude("includes");
const static inline impl::DataPath Magic("magic");
const static inline impl::DataPath Yara("yara");
const static inline impl::DataPath YaraAdvancedAnalysis("yara/advanced_analysis");
const static inline impl::DataPath Backups("backups");
const static inline impl::DataPath Resources("resources");
const static inline impl::DataPath Constants("constants");
const static inline impl::DataPath Encodings("encodings");
const static inline impl::DataPath Logs("logs");
const static inline impl::DataPath Scripts("scripts");
const static inline impl::DataPath Inspectors("scripts/inspectors");
const static inline impl::DataPath Themes("themes");
const static inline impl::DataPath Nodes("scripts/nodes");
const static inline impl::DataPath Layouts("layouts");
const static inline impl::DataPath Workspaces("workspaces");
constexpr static inline std::array<const impl::DefaultPath*, 20> All = {
&Config,
&Recent,
&Libraries,
&Plugins,
&Patterns,
&PatternsInclude,
&Magic,
&Yara,
&YaraAdvancedAnalysis,
&Backups,
&Resources,
&Constants,
&Encodings,
&Logs,
&Scripts,
&Inspectors,
&Themes,
&Nodes,
&Layouts,
&Workspaces,
};
}

View File

@@ -1,5 +1,7 @@
#pragma once
#include <hex.hpp>
#include <string>
#include <vector>
#include <filesystem>
@@ -29,7 +31,36 @@ namespace hex::fs {
void openFolderExternal(const std::fs::path &dirPath);
void openFolderWithSelectionExternal(const std::fs::path &selectedFilePath);
enum class ImHexPath : u32 {
Patterns = 0,
PatternsInclude,
Magic,
Plugins,
Yara,
YaraAdvancedAnalysis,
Config,
Backups,
Resources,
Constants,
Encodings,
Logs,
Recent,
Scripts,
Inspectors,
Themes,
Libraries,
Nodes,
Layouts,
Workspaces,
END
};
bool isPathWritable(const std::fs::path &path);
std::vector<std::fs::path> getDefaultPaths(ImHexPath path, bool listNonExisting = false);
// Temporarily expose these for the migration function
std::vector<std::fs::path> getDataPaths();
std::vector<std::fs::path> appendPath(std::vector<std::fs::path> paths, const std::fs::path &folder);
}

View File

@@ -2,11 +2,12 @@
#include <hex.hpp>
#include <mutex>
#include <fmt/core.h>
#include <fmt/color.h>
#include <wolv/io/file.hpp>
#include <wolv/utils/guards.hpp>
namespace hex::log {
@@ -18,11 +19,8 @@ namespace hex::log {
[[maybe_unused]] void redirectToFile();
[[maybe_unused]] void enableColorPrinting();
[[nodiscard]] std::recursive_mutex& getLoggerMutex();
[[nodiscard]] bool isLoggingSuspended();
[[nodiscard]] bool isDebugLoggingEnabled();
void lockLoggerMutex();
void unlockLoggerMutex();
struct LogEntry {
std::string project;
@@ -39,8 +37,7 @@ namespace hex::log {
if (isLoggingSuspended()) [[unlikely]]
return;
lockLoggerMutex();
ON_SCOPE_EXIT { unlockLoggerMutex(); };
std::scoped_lock lock(getLoggerMutex());
auto dest = getDestination();
try {
@@ -68,14 +65,13 @@ namespace hex::log {
void suspendLogging();
void resumeLogging();
void enableDebugLogging();
[[maybe_unused]] void debug(const std::string &fmt, auto && ... args) {
if (impl::isDebugLoggingEnabled()) [[unlikely]] {
#if defined(DEBUG)
hex::log::impl::print(fg(impl::color::debug()) | fmt::emphasis::bold, "[DEBUG]", fmt, args...);
} else {
#else
impl::addLogEntry(IMHEX_PROJECT_NAME, "[DEBUG]", fmt::format(fmt::runtime(fmt), args...));
}
#endif
}
[[maybe_unused]] void info(const std::string &fmt, auto && ... args) {
@@ -94,9 +90,9 @@ namespace hex::log {
hex::log::impl::print(fg(impl::color::fatal()) | fmt::emphasis::bold, "[FATAL]", fmt, args...);
}
[[maybe_unused]] void print(const std::string &fmt, auto && ... args) {
impl::lockLoggerMutex();
ON_SCOPE_EXIT { impl::unlockLoggerMutex(); };
std::scoped_lock lock(impl::getLoggerMutex());
try {
auto dest = impl::getDestination();
@@ -107,8 +103,7 @@ namespace hex::log {
}
[[maybe_unused]] void println(const std::string &fmt, auto && ... args) {
impl::lockLoggerMutex();
ON_SCOPE_EXIT { impl::unlockLoggerMutex(); };
std::scoped_lock lock(impl::getLoggerMutex());
try {
auto dest = impl::getDestination();
@@ -118,4 +113,4 @@ namespace hex::log {
} catch (const std::exception&) { }
}
}
}

View File

@@ -152,7 +152,7 @@ namespace hex {
using SizeType = typename SizeTypeImpl<Size>::Type;
template<typename T>
[[nodiscard]] constexpr T changeEndianness(const T &value, size_t size, std::endian endian) {
[[nodiscard]] constexpr T changeEndianess(const T &value, size_t size, std::endian endian) {
if (endian == std::endian::native)
return value;
@@ -172,8 +172,8 @@ namespace hex {
}
template<typename T>
[[nodiscard]] constexpr T changeEndianness(const T &value, std::endian endian) {
return changeEndianness(value, sizeof(value), endian);
[[nodiscard]] constexpr T changeEndianess(const T &value, std::endian endian) {
return changeEndianess(value, sizeof(value), endian);
}
[[nodiscard]] constexpr u128 bitmask(u8 bits) {
@@ -298,7 +298,31 @@ namespace hex {
[[nodiscard]] std::optional<std::string> getEnvironmentVariable(const std::string &env);
[[nodiscard]] std::string limitStringLength(const std::string &string, size_t maxLength);
[[nodiscard]] inline std::string limitStringLength(const std::string &string, size_t maxLength) {
// If the string is shorter than the max length, return it as is
if (string.size() < maxLength)
return string;
// If the string is longer than the max length, find the last space before the max length
auto it = string.begin() + maxLength;
while (it != string.begin() && !std::isspace(*it)) --it;
// If there's no space before the max length, just cut the string
if (it == string.begin()) {
it = string.begin() + maxLength;
// Try to find a UTF-8 character boundary
while (it != string.begin() && (*it & 0x80) != 0x00) --it;
++it;
}
// If we still didn't find a valid boundary, just return the string as is
if (it == string.begin())
return string;
// Append
return std::string(string.begin(), it) + "";
}
[[nodiscard]] std::optional<std::fs::path> getInitialFilePath();
@@ -307,14 +331,4 @@ namespace hex {
[[nodiscard]] std::string formatSystemError(i32 error);
/**
* Gets the shared library handle for a given pointer
* @param symbol Pointer to any function or variable in the shared library
* @return The module handle
* @warning Important! Calling this function on functions defined in other modules will return the handle of the current module!
* This is because you're not actually passing a pointer to the function in the other module but rather a pointer to a thunk
* that is defined in the current module.
*/
[[nodiscard]] void* getContainingModule(void* symbol);
}

View File

@@ -15,10 +15,6 @@
void setupMacosWindowStyle(GLFWwindow *window, bool borderlessWindowMode);
void enumerateFontsMacos();
void macosHandleTitlebarDoubleClickGesture(GLFWwindow *window);
bool macosIsWindowBeingResizedByUser(GLFWwindow *window);
void macosMarkContentEdited(GLFWwindow *window, bool edited = true);
}
#endif
#endif

View File

@@ -131,8 +131,8 @@ void* PluginSubCommandsFunctionHelper<T>::getSubCommands() {
std::vector<hex::SubCommand> g_subCommands
#define IMHEX_FEATURE_ENABLED(feature) WOLV_TOKEN_CONCAT(WOLV_TOKEN_CONCAT(WOLV_TOKEN_CONCAT(IMHEX_PLUGIN_, IMHEX_PLUGIN_NAME), _FEATURE_), feature)
#define IMHEX_DEFINE_PLUGIN_FEATURES() IMHEX_DEFINE_PLUGIN_FEATURES_IMPL()
#define IMHEX_DEFINE_PLUGIN_FEATURES_IMPL() \
#define IMHEX_PLUGIN_FEATURES() IMHEX_PLUGIN_FEATURES_IMPL()
#define IMHEX_PLUGIN_FEATURES_IMPL() \
extern std::vector<hex::Feature> g_features; \
template<> \
struct PluginFeatureFunctionHelper<PluginFunctionHelperInstantiation> { \
@@ -142,5 +142,3 @@ void* PluginSubCommandsFunctionHelper<T>::getSubCommands() {
return &g_features; \
} \
std::vector<hex::Feature> g_features
#define IMHEX_PLUGIN_FEATURES g_features

View File

@@ -35,6 +35,8 @@ namespace hex::prv {
[[nodiscard]] u64 getActualSize() const override { return m_data.size(); }
void resizeRaw(u64 newSize) override;
void insertRaw(u64 offset, u64 size) override;
void removeRaw(u64 offset, u64 size) override;
[[nodiscard]] std::string getName() const override { return m_name; }

View File

@@ -148,7 +148,7 @@ namespace hex::prv {
* @brief Gets the type name of this provider
* @note This is mainly used to be stored in project files and recents to be able to later on
* recreate this exact provider type. This needs to be unique across all providers, this is usually something
* like "hex.builtin.provider.mem_file" or "hex.builtin.provider.file"
* like "hex.builtin.provider.memory" or "hex.builtin.provider.file"
* @return The provider's type name
*/
[[nodiscard]] virtual std::string getTypeName() const = 0;
@@ -161,13 +161,13 @@ namespace hex::prv {
*/
[[nodiscard]] virtual std::string getName() const = 0;
bool resize(u64 newSize);
void resize(u64 newSize);
void insert(u64 offset, u64 size);
void remove(u64 offset, u64 size);
virtual void resizeRaw(u64 newSize) { hex::unused(newSize); }
virtual void insertRaw(u64 offset, u64 size);
virtual void removeRaw(u64 offset, u64 size);
virtual void insertRaw(u64 offset, u64 size) { hex::unused(offset, size); }
virtual void removeRaw(u64 offset, u64 size) { hex::unused(offset, size); }
virtual void save();
virtual void saveAs(const std::fs::path &path);
@@ -258,7 +258,7 @@ namespace hex::prv {
*/
bool m_skipLoadInterface = false;
std::string m_errorMessage = "Unspecified error";
std::string m_errorMessage;
u64 m_pageSize = MaxPageSize;
};

View File

@@ -78,10 +78,6 @@ namespace hex {
m_onCreateCallback = std::move(callback);
}
void setOnDestroyCallback(std::function<void(prv::Provider *, T&)> callback) {
m_onDestroyCallback = std::move(callback);
}
private:
void onCreate() {
EventProviderOpened::subscribe(this, [this](prv::Provider *provider) {
@@ -92,12 +88,7 @@ namespace hex {
});
EventProviderDeleted::subscribe(this, [this](prv::Provider *provider){
if (auto it = m_data.find(provider); it != m_data.end()) {
if (m_onDestroyCallback)
m_onDestroyCallback(provider, m_data.at(provider));
m_data.erase(it);
}
m_data.erase(provider);
});
EventImHexClosing::subscribe(this, [this] {
@@ -122,7 +113,6 @@ namespace hex {
}
void onDestroy() {
EventProviderOpened::unsubscribe(this);
EventProviderDeleted::unsubscribe(this);
EventImHexClosing::unsubscribe(this);
@@ -131,7 +121,7 @@ namespace hex {
private:
std::map<const prv::Provider *, T> m_data;
std::function<void(prv::Provider *, T&)> m_onCreateCallback, m_onDestroyCallback;
std::function<void(prv::Provider *, T&)> m_onCreateCallback;
};
}

View File

@@ -27,7 +27,6 @@ namespace hex::prv::undo {
void groupOperations(u32 count, const UnlocalizedString &unlocalizedName);
void apply(const Stack &otherStack);
void reapply();
[[nodiscard]] bool canUndo() const;
[[nodiscard]] bool canRedo() const;

View File

@@ -76,21 +76,14 @@ namespace ImGuiExt {
};
Texture() = default;
Texture(const ImU8 *buffer, int size, Filter filter = Filter::Nearest, int width = 0, int height = 0);
Texture(std::span<const std::byte> bytes, Filter filter = Filter::Nearest, int width = 0, int height = 0);
explicit Texture(const char *path, Filter filter = Filter::Nearest);
explicit Texture(const std::fs::path &path, Filter filter = Filter::Nearest);
Texture(unsigned int texture, int width, int height);
Texture(const Texture&) = delete;
Texture(Texture&& other) noexcept;
static Texture fromImage(const ImU8 *buffer, int size, Filter filter = Filter::Nearest);
static Texture fromImage(std::span<const std::byte> buffer, Filter filter = Filter::Nearest);
static Texture fromImage(const char *path, Filter filter = Filter::Nearest);
static Texture fromImage(const std::fs::path &path, Filter filter = Filter::Nearest);
static Texture fromGLTexture(unsigned int texture, int width, int height);
static Texture fromBitmap(const ImU8 *buffer, int size, int width, int height, Filter filter = Filter::Nearest);
static Texture fromBitmap(std::span<const std::byte> buffer, int width, int height, Filter filter = Filter::Nearest);
static Texture fromSVG(const char *path, int width = 0, int height = 0, Filter filter = Filter::Nearest);
static Texture fromSVG(const std::fs::path &path, int width = 0, int height = 0, Filter filter = Filter::Nearest);
static Texture fromSVG(std::span<const std::byte> buffer, int width = 0, int height = 0, Filter filter = Filter::Nearest);
~Texture();
Texture& operator=(const Texture&) = delete;
@@ -123,8 +116,6 @@ namespace ImGuiExt {
int m_width = 0, m_height = 0;
};
float GetTextWrapPos();
int UpdateStringSizeCallback(ImGuiInputTextCallbackData *data);
bool IconHyperlink(const char *icon, const char *label, const ImVec2 &size_arg = ImVec2(0, 0), ImGuiButtonFlags flags = 0);
@@ -133,7 +124,7 @@ namespace ImGuiExt {
bool DescriptionButton(const char *label, const char *description, const ImVec2 &size_arg = ImVec2(0, 0), ImGuiButtonFlags flags = 0);
bool DescriptionButtonProgress(const char *label, const char *description, float fraction, const ImVec2 &size_arg = ImVec2(0, 0), ImGuiButtonFlags flags = 0);
void HelpHover(const char *text, const char *icon = "(?)", ImU32 iconColor = ImGui::GetColorU32(ImGuiCol_ButtonActive));
void HelpHover(const char *text);
void UnderlinedText(const char *label, ImColor color = ImGui::GetStyleColorVec4(ImGuiCol_Text), const ImVec2 &size_arg = ImVec2(0, 0));
@@ -152,8 +143,6 @@ namespace ImGuiExt {
bool InputHexadecimal(const char* label, u32 *value, ImGuiInputTextFlags flags = ImGuiInputTextFlags_None);
bool InputHexadecimal(const char* label, u64 *value, ImGuiInputTextFlags flags = ImGuiInputTextFlags_None);
bool SliderBytes(const char *label, u64 *value, u64 min, u64 max, ImGuiSliderFlags flags = ImGuiSliderFlags_None);
inline bool HasSecondPassed() {
return static_cast<ImU32>(ImGui::GetTime() * 100) % 100 <= static_cast<ImU32>(ImGui::GetIO().DeltaTime * 100);
}
@@ -165,7 +154,6 @@ namespace ImGuiExt {
struct Styles {
float WindowBlur = 0.0F;
float PopupWindowAlpha = 0.0F; // Alpha used by Popup tool windows when the user is not hovering over them
} styles;
};
@@ -187,16 +175,11 @@ namespace ImGuiExt {
void SmallProgressBar(float fraction, float yOffset = 0.0F);
inline void TextFormatted(std::string_view fmt, auto &&...args) {
if constexpr (sizeof...(args) == 0) {
ImGui::TextUnformatted(fmt.data(), fmt.data() + fmt.size());
} else {
const auto string = hex::format(fmt, std::forward<decltype(args)>(args)...);
ImGui::TextUnformatted(string.c_str(), string.c_str() + string.size());
}
inline void TextFormatted(const std::string &fmt, auto &&...args) {
ImGui::TextUnformatted(hex::format(fmt, std::forward<decltype(args)>(args)...).c_str());
}
inline void TextFormattedSelectable(std::string_view fmt, auto &&...args) {
inline void TextFormattedSelectable(const std::string &fmt, auto &&...args) {
auto text = hex::format(fmt, std::forward<decltype(args)>(args)...);
ImGui::PushID(text.c_str());
@@ -204,8 +187,8 @@ namespace ImGuiExt {
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2());
ImGui::PushStyleColor(ImGuiCol_FrameBg, ImVec4());
ImGui::PushItemWidth(ImGui::CalcTextSize(text.c_str()).x + ImGui::GetStyle().FramePadding.x * 2);
ImGui::InputText("##", const_cast<char *>(text.c_str()), text.size(), ImGuiInputTextFlags_ReadOnly | ImGuiInputTextFlags_NoHorizontalScroll);
ImGui::PushItemWidth(-FLT_MIN);
ImGui::InputText("##", const_cast<char *>(text.c_str()), text.size(), ImGuiInputTextFlags_ReadOnly);
ImGui::PopItemWidth();
ImGui::PopStyleColor();
@@ -214,28 +197,19 @@ namespace ImGuiExt {
ImGui::PopID();
}
inline void TextFormattedColored(ImColor color, std::string_view fmt, auto &&...args) {
ImGui::PushStyleColor(ImGuiCol_Text, color.Value);
ImGuiExt::TextFormatted(fmt, std::forward<decltype(args)>(args)...);
ImGui::PopStyleColor();
inline void TextFormattedColored(ImColor color, const std::string &fmt, auto &&...args) {
ImGui::TextColored(color, "%s", hex::format(fmt, std::forward<decltype(args)>(args)...).c_str());
}
inline void TextFormattedDisabled(std::string_view fmt, auto &&...args) {
ImGui::PushStyleColor(ImGuiCol_Text, ImGui::GetStyle().Colors[ImGuiCol_TextDisabled]);
ImGuiExt::TextFormatted(fmt, std::forward<decltype(args)>(args)...);
ImGui::PopStyleColor();
inline void TextFormattedDisabled(const std::string &fmt, auto &&...args) {
ImGui::TextDisabled("%s", hex::format(fmt, std::forward<decltype(args)>(args)...).c_str());
}
inline void TextFormattedWrapped(std::string_view fmt, auto &&...args) {
const bool need_backup = ImGuiExt::GetTextWrapPos() < 0.0F; // Keep existing wrap position if one is already set
if (need_backup)
ImGui::PushTextWrapPos(0.0F);
ImGuiExt::TextFormatted(fmt, std::forward<decltype(args)>(args)...);
if (need_backup)
ImGui::PopTextWrapPos();
inline void TextFormattedWrapped(const std::string &fmt, auto &&...args) {
ImGui::TextWrapped("%s", hex::format(fmt, std::forward<decltype(args)>(args)...).c_str());
}
inline void TextFormattedWrappedSelectable(std::string_view fmt, auto &&...args) {
inline void TextFormattedWrappedSelectable(const std::string &fmt, auto &&...args) {
// Manually wrap text, using the letter M (generally the widest character in non-monospaced fonts) to calculate the character width to use.
auto text = wolv::util::wrapMonospacedString(
hex::format(fmt, std::forward<decltype(args)>(args)...),
@@ -248,7 +222,7 @@ namespace ImGuiExt {
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2());
ImGui::PushStyleColor(ImGuiCol_FrameBg, ImVec4());
ImGui::PushItemWidth(ImGui::CalcTextSize(text.c_str()).x + ImGui::GetStyle().FramePadding.x * 2);
ImGui::PushItemWidth(-FLT_MIN);
ImGui::InputTextMultiline(
"##",
const_cast<char *>(text.c_str()),
@@ -265,13 +239,13 @@ namespace ImGuiExt {
}
void TextUnformattedCentered(const char *text);
inline void TextFormattedCentered(std::string_view fmt, auto &&...args) {
inline void TextFormattedCentered(const std::string &fmt, auto &&...args) {
auto text = hex::format(fmt, std::forward<decltype(args)>(args)...);
TextUnformattedCentered(text.c_str());
}
inline void TextFormattedCenteredHorizontal(std::string_view fmt, auto &&...args) {
inline void TextFormattedCenteredHorizontal(const std::string &fmt, auto &&...args) {
auto text = hex::format(fmt, std::forward<decltype(args)>(args)...);
auto availableSpace = ImGui::GetContentRegionAvail();
auto textSize = ImGui::CalcTextSize(text.c_str(), nullptr, false, availableSpace.x * 0.75F);
@@ -302,7 +276,7 @@ namespace ImGuiExt {
bool BeginBox();
void EndBox();
bool BeginSubWindow(const char *label, bool *collapsed = nullptr, ImVec2 size = ImVec2(0, 0), ImGuiChildFlags flags = ImGuiChildFlags_None);
void BeginSubWindow(const char *label, ImVec2 size = ImVec2(0, 0), ImGuiChildFlags flags = ImGuiChildFlags_None);
void EndSubWindow();
void ConfirmButtons(const char *textLeft, const char *textRight, const auto &leftButtonCallback, const auto &rightButtonCallback) {
@@ -323,9 +297,6 @@ namespace ImGuiExt {
bool ToggleSwitch(const char *label, bool *v);
bool ToggleSwitch(const char *label, bool v);
bool PopupTitleBarButton(const char* label, bool p_enabled);
void PopupTitleBarText(const char* text);
template<typename T>
constexpr ImGuiDataType getImGuiDataType() {
if constexpr (std::same_as<T, u8>) return ImGuiDataType_U8;

View File

@@ -80,8 +80,6 @@ namespace hex {
*/
[[nodiscard]] virtual ImGuiWindowFlags getWindowFlags() const;
[[nodiscard]] virtual bool shouldStoreWindowState() const { return true; }
[[nodiscard]] const char *getIcon() const { return m_icon; }
[[nodiscard]] bool &getWindowOpenState();
@@ -158,7 +156,6 @@ namespace hex {
explicit Floating(UnlocalizedString unlocalizedName) : Window(std::move(unlocalizedName), "") {}
[[nodiscard]] ImGuiWindowFlags getWindowFlags() const override { return ImGuiWindowFlags_NoDocking; }
[[nodiscard]] bool shouldStoreWindowState() const override { return false; }
};
/**
@@ -181,13 +178,12 @@ namespace hex {
ImGui::EndPopup();
}
if (ImGui::IsKeyPressed(ImGuiKey_Escape))
if (ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_Escape)))
this->getWindowOpenState() = false;
}
}
[[nodiscard]] virtual bool hasCloseButton() const { return true; }
[[nodiscard]] bool shouldStoreWindowState() const override { return false; }
virtual bool hasCloseButton() const { return true; }
};
}

View File

@@ -2,7 +2,6 @@
#include <hex/api/event_manager.hpp>
#include <hex/helpers/auto_reset.hpp>
#include <hex/helpers/default_paths.hpp>
#include <nlohmann/json.hpp>
@@ -198,7 +197,7 @@ namespace hex {
constexpr static auto AchievementsFile = "achievements.json";
void AchievementManager::loadProgress() {
for (const auto &directory : paths::Config.read()) {
for (const auto &directory : fs::getDefaultPaths(fs::ImHexPath::Config)) {
auto path = directory / AchievementsFile;
if (!wolv::io::fs::exists(path)) {
@@ -247,7 +246,7 @@ namespace hex {
if (json.empty())
return;
for (const auto &directory : paths::Config.write()) {
for (const auto &directory : fs::getDefaultPaths(fs::ImHexPath::Config)) {
auto path = directory / AchievementsFile;
wolv::io::File file(path, wolv::io::File::Mode::Create);

View File

@@ -4,7 +4,6 @@
#include <hex/helpers/fs.hpp>
#include <hex/helpers/logger.hpp>
#include <hex/helpers/auto_reset.hpp>
#include <hex/helpers/default_paths.hpp>
#include <hex/ui/view.hpp>
#include <hex/data_processor/node.hpp>
@@ -52,14 +51,10 @@ namespace hex {
if (!settings[unlocalizedCategory].contains(unlocalizedName))
settings[unlocalizedCategory][unlocalizedName] = defaultValue;
if (settings[unlocalizedCategory][unlocalizedName].is_null())
settings[unlocalizedCategory][unlocalizedName] = defaultValue;
return settings[unlocalizedCategory][unlocalizedName];
}
#if defined(OS_WEB)
void load() {
char *data = (char *) MAIN_THREAD_EM_ASM_INT({
let data = localStorage.getItem("config");
@@ -75,11 +70,7 @@ namespace hex {
for (const auto &[category, rest] : *impl::s_onChangeCallbacks) {
for (const auto &[name, callbacks] : rest) {
for (const auto &[id, callback] : callbacks) {
try {
callback(getSetting(category, name, {}));
} catch (const std::exception &e) {
log::error("Failed to load setting [{}/{}]: {}", category, name, e.what());
}
callback(getSetting(category, name, {}));
}
}
}
@@ -102,7 +93,7 @@ namespace hex {
void load() {
bool loaded = false;
for (const auto &dir : paths::Config.read()) {
for (const auto &dir : fs::getDefaultPaths(fs::ImHexPath::Config)) {
wolv::io::File file(dir / SettingsFile, wolv::io::File::Mode::Read);
if (file.isValid()) {
@@ -118,21 +109,14 @@ namespace hex {
for (const auto &[category, rest] : *impl::s_onChangeCallbacks) {
for (const auto &[name, callbacks] : rest) {
for (const auto &[id, callback] : callbacks) {
try {
callback(getSetting(category, name, {}));
} catch (const std::exception &e) {
log::error("Failed to load setting [{}/{}]: {}", category, name, e.what());
}
callback(getSetting(category, name, {}));
}
}
}
}
void store() {
if (!s_settings.isValid())
return;
const auto &settingsData = *s_settings;
const auto &settingsData = getSettingsData();
// During a crash settings can be empty, causing them to be overwritten.
if (settingsData.empty()) {
@@ -143,7 +127,7 @@ namespace hex {
if (result.empty()) {
return;
}
for (const auto &dir : paths::Config.write()) {
for (const auto &dir : fs::getDefaultPaths(fs::ImHexPath::Config)) {
wolv::io::File file(dir / SettingsFile, wolv::io::File::Mode::Create);
if (file.isValid()) {
@@ -154,7 +138,7 @@ namespace hex {
}
void clear() {
for (const auto &dir : paths::Config.write()) {
for (const auto &dir : fs::getDefaultPaths(fs::ImHexPath::Config)) {
wolv::io::fs::remove(dir / SettingsFile);
}
}
@@ -313,23 +297,6 @@ namespace hex {
}
bool SliderDataSize::draw(const std::string &name) {
return ImGuiExt::SliderBytes(name.c_str(), &m_value, m_min, m_max);
}
void SliderDataSize::load(const nlohmann::json &data) {
if (data.is_number_integer()) {
m_value = data.get<u64>();
} else {
log::warn("Invalid data type loaded from settings for slider!");
}
}
nlohmann::json SliderDataSize::store() {
return m_value;
}
ColorPicker::ColorPicker(ImColor defaultColor) {
m_value = {
defaultColor.Value.x,
@@ -596,7 +563,7 @@ namespace hex {
);
}
runtime.setIncludePaths(paths::PatternsInclude.read() | paths::Patterns.read());
runtime.setIncludePaths(fs::getDefaultPaths(fs::ImHexPath::PatternsInclude) | fs::getDefaultPaths(fs::ImHexPath::Patterns));
for (const auto &[ns, name, paramCount, callback, dangerous] : impl::getFunctions()) {
if (dangerous)
@@ -821,12 +788,6 @@ namespace hex {
return *s_menuItems;
}
static AutoReset<std::vector<MenuItem*>> s_toolbarMenuItems;
const std::vector<MenuItem*>& getToolbarMenuItems() {
return s_toolbarMenuItems;
}
std::multimap<u32, MenuItem>& getMenuItemsMutable() {
return *s_menuItems;
}
@@ -936,35 +897,11 @@ namespace hex {
if (menuItem.unlocalizedNames.back() == unlocalizedName) {
menuItem.toolbarIndex = maxIndex + 1;
menuItem.icon.color = color;
updateToolbarItems();
break;
}
}
}
struct MenuItemSorter {
bool operator()(const auto *a, const auto *b) const {
return a->toolbarIndex < b->toolbarIndex;
}
};
void updateToolbarItems() {
std::set<ContentRegistry::Interface::impl::MenuItem*, MenuItemSorter> menuItems;
for (auto &[priority, menuItem] : impl::getMenuItemsMutable()) {
if (menuItem.toolbarIndex != -1) {
menuItems.insert(&menuItem);
}
}
impl::s_toolbarMenuItems->clear();
for (auto menuItem : menuItems) {
impl::s_toolbarMenuItems->push_back(menuItem);
}
}
void addSidebarItem(const std::string &icon, const impl::DrawCallback &function, const impl::EnabledCallback &enabledCallback) {
impl::s_sidebarItems->push_back({ icon, function, enabledCallback });
@@ -1013,28 +950,17 @@ namespace hex {
namespace impl {
static AutoReset<std::vector<ExportMenuEntry>> s_exportMenuEntries;
const std::vector<ExportMenuEntry>& getExportMenuEntries() {
return *s_exportMenuEntries;
}
static AutoReset<std::vector<FindExporterEntry>> s_findExportEntries;
const std::vector<FindExporterEntry>& getFindExporterEntries() {
return *s_findExportEntries;
static AutoReset<std::vector<Entry>> s_entries;
const std::vector<Entry>& getEntries() {
return *s_entries;
}
}
void addExportMenuEntry(const UnlocalizedString &unlocalizedName, const impl::Callback &callback) {
void add(const UnlocalizedString &unlocalizedName, const impl::Callback &callback) {
log::debug("Registered new data formatter: {}", unlocalizedName.get());
impl::s_exportMenuEntries->push_back({ unlocalizedName, callback });
}
void addFindExportFormatter(const UnlocalizedString &unlocalizedName, const std::string fileExtension, const impl::FindExporterCallback &callback) {
log::debug("Registered new export formatter: {}", unlocalizedName.get());
impl::s_findExportEntries->push_back({ unlocalizedName, fileExtension, callback });
impl::s_entries->push_back({ unlocalizedName, callback });
}
}

View File

@@ -14,8 +14,6 @@
#include <imgui.h>
#include <imgui_internal.h>
#include <set>
#include <algorithm>
#include <GLFW/glfw3.h>
#if defined(OS_WINDOWS)
@@ -77,11 +75,7 @@ namespace hex {
static AutoReset<std::optional<ProviderRegion>> s_currentSelection;
void setCurrentSelection(const std::optional<ProviderRegion> &region) {
if (region == Region::Invalid()) {
clearSelection();
} else {
*s_currentSelection = region;
}
*s_currentSelection = region;
}
static PerProvider<std::optional<Region>> s_hoveredRegion;
@@ -184,24 +178,24 @@ namespace hex {
impl::s_hoveringFunctions->erase(id);
}
static u32 s_tooltipId = 0;
static u32 tooltipId = 0;
u32 addTooltip(Region region, std::string value, color_t color) {
s_tooltipId++;
impl::s_tooltips->insert({ s_tooltipId, { region, std::move(value), color } });
tooltipId++;
impl::s_tooltips->insert({ tooltipId, { region, std::move(value), color } });
return s_tooltipId;
return tooltipId;
}
void removeTooltip(u32 id) {
impl::s_tooltips->erase(id);
}
static u32 s_tooltipFunctionId;
static u32 tooltipFunctionId;
u32 addTooltipProvider(TooltipFunction function) {
s_tooltipFunctionId++;
impl::s_tooltipFunctions->insert({ s_tooltipFunctionId, std::move(function) });
tooltipFunctionId++;
impl::s_tooltipFunctions->insert({ tooltipFunctionId, std::move(function) });
return s_tooltipFunctionId;
return tooltipFunctionId;
}
void removeTooltipProvider(u32 id) {
@@ -218,7 +212,7 @@ namespace hex {
}
void clearSelection() {
impl::s_currentSelection->reset();
impl::s_currentSelection.reset();
}
void setSelection(const Region &region, prv::Provider *provider) {
@@ -268,20 +262,18 @@ namespace hex {
static i64 s_currentProvider = -1;
static AutoReset<std::vector<std::unique_ptr<prv::Provider>>> s_providers;
static AutoReset<std::list<std::unique_ptr<prv::Provider>>> s_providersToRemove;
namespace impl {
static std::set<prv::Provider*> s_closingProviders;
static std::vector<prv::Provider*> s_closingProviders;
void resetClosingProvider() {
s_closingProviders.clear();
}
std::set<prv::Provider*> getClosingProviders() {
const std::vector<prv::Provider*>& getClosingProviders() {
return s_closingProviders;
}
static std::recursive_mutex s_providerMutex;
}
prv::Provider *get() {
@@ -301,8 +293,6 @@ namespace hex {
}
void setCurrentProvider(i64 index) {
std::scoped_lock lock(impl::s_providerMutex);
if (TaskManager::getRunningTaskCount() > 0)
return;
@@ -316,8 +306,6 @@ namespace hex {
}
void setCurrentProvider(NonNull<prv::Provider*> provider) {
std::scoped_lock lock(impl::s_providerMutex);
if (TaskManager::getRunningTaskCount() > 0)
return;
@@ -338,7 +326,6 @@ namespace hex {
void markDirty() {
get()->markDirty();
EventProviderDirtied::post(get());
}
void resetDirty() {
@@ -353,8 +340,6 @@ namespace hex {
}
void add(std::unique_ptr<prv::Provider> &&provider, bool skipLoadInterface, bool select) {
std::scoped_lock lock(impl::s_providerMutex);
if (TaskManager::getRunningTaskCount() > 0)
return;
@@ -369,8 +354,6 @@ namespace hex {
}
void remove(prv::Provider *provider, bool noQuestions) {
std::scoped_lock lock(impl::s_providerMutex);
if (provider == nullptr)
return;
@@ -378,7 +361,7 @@ namespace hex {
return;
if (!noQuestions) {
impl::s_closingProviders.insert(provider);
impl::s_closingProviders.push_back(provider);
bool shouldClose = true;
EventProviderClosing::post(provider, &shouldClose);
@@ -426,37 +409,20 @@ namespace hex {
}
}
static std::mutex eraseMutex;
// Move provider over to a list of providers to delete
eraseMutex.lock();
auto removeIt = s_providersToRemove->emplace(s_providersToRemove->end(), std::move(*it));
eraseMutex.unlock();
// Remove left over references from the main provider list
s_providers->erase(it);
impl::s_closingProviders.erase(provider);
if (s_currentProvider >= i64(s_providers->size()) && !s_providers->empty())
setCurrentProvider(s_providers->size() - 1);
if (s_providers->empty())
EventProviderChanged::post(provider, nullptr);
EventProviderClosed::post(removeIt->get());
provider->close();
EventProviderClosed::post(provider);
RequestUpdateWindowTitle::post();
// Do the destruction of the provider in the background once all tasks have finished
TaskManager::runWhenTasksFinished([removeIt] {
EventProviderDeleted::post(removeIt->get());
TaskManager::createBackgroundTask("Closing Provider", [removeIt](Task &) {
eraseMutex.lock();
auto provider = std::move(*removeIt);
s_providersToRemove->erase(removeIt);
eraseMutex.unlock();
TaskManager::runWhenTasksFinished([it, provider] {
EventProviderDeleted::post(provider);
std::erase(impl::s_closingProviders, provider);
provider->close();
});
s_providers->erase(it);
if (s_currentProvider >= i64(s_providers->size()))
setCurrentProvider(0);
if (s_providers->empty())
EventProviderChanged::post(provider, nullptr);
});
}
@@ -471,6 +437,7 @@ namespace hex {
namespace ImHexApi::System {
namespace impl {
// Default to true means we forward to ourselves by default
@@ -532,11 +499,6 @@ namespace hex {
s_gpuVendor = vendor;
}
static AutoReset<std::string> s_glRenderer;
void setGLRenderer(const std::string &renderer) {
s_glRenderer = renderer;
}
static AutoReset<std::map<std::string, std::string>> s_initArguments;
void addInitArgument(const std::string &key, const std::string &value) {
static std::mutex initArgumentsMutex;
@@ -637,11 +599,6 @@ namespace hex {
return impl::s_initialWindowProperties;
}
void* getLibImHexModuleHandle() {
return hex::getContainingModule(reinterpret_cast<void*>(&getLibImHexModuleHandle));
}
const std::map<std::string, std::string>& getInitArguments() {
return *impl::s_initArguments;
}
@@ -681,10 +638,6 @@ namespace hex {
return impl::s_gpuVendor;
}
const std::string &getGLRenderer() {
return impl::s_glRenderer;
}
bool isPortableVersion() {
static std::optional<bool> portable;
if (portable.has_value())
@@ -771,25 +724,6 @@ namespace hex {
#endif
}
std::optional<LinuxDistro> getLinuxDistro() {
wolv::io::File file("/etc/os-release", wolv::io::File::Mode::Read);
std::string name;
std::string version;
auto fileContent = file.readString();
for (const auto &line : wolv::util::splitString(fileContent, "\n")) {
if (line.find("PRETTY_NAME=") != std::string::npos) {
name = line.substr(line.find("=") + 1);
std::erase(name, '\"');
} else if (line.find("VERSION_ID=") != std::string::npos) {
version = line.substr(line.find("=") + 1);
std::erase(version, '\"');
}
}
return { { name, version } };
}
std::string getImHexVersion(bool withBuildType) {
#if defined IMHEX_VERSION
if (withBuildType) {
@@ -832,10 +766,6 @@ namespace hex {
#endif
}
bool isNightlyBuild() {
return getImHexVersion(false).ends_with("WIP");
}
bool updateImHex(UpdateType updateType) {
// Get the path of the updater executable
std::fs::path executablePath;
@@ -941,9 +871,9 @@ namespace hex {
s_fontSize = size;
}
static AutoReset<ImFontAtlas*> s_fontAtlas;
static AutoReset<std::unique_ptr<ImFontAtlas>> s_fontAtlas;
void setFontAtlas(ImFontAtlas* fontAtlas) {
s_fontAtlas = fontAtlas;
s_fontAtlas = std::unique_ptr<ImFontAtlas>(fontAtlas);
}
static ImFont *s_boldFont = nullptr;
@@ -1026,7 +956,7 @@ namespace hex {
}
ImFontAtlas* getFontAtlas() {
return impl::s_fontAtlas;
return impl::s_fontAtlas->get();
}
ImFont* Bold() {

View File

@@ -1,15 +1,13 @@
#include <hex/api/layout_manager.hpp>
#include <hex/api/content_registry.hpp>
#include <hex/ui/view.hpp>
#include <hex/helpers/fs.hpp>
#include <hex/helpers/logger.hpp>
#include <hex/helpers/auto_reset.hpp>
#include <hex/helpers/default_paths.hpp>
#include <wolv/utils/string.hpp>
#include <imgui.h>
#include <hex/api/content_registry.hpp>
#include <hex/ui/view.hpp>
namespace hex {
@@ -42,7 +40,10 @@ namespace hex {
fileName += ".hexlyt";
std::fs::path layoutPath;
for (const auto &path : paths::Layouts.write()) {
for (const auto &path : hex::fs::getDefaultPaths(fs::ImHexPath::Layouts)) {
if (!hex::fs::isPathWritable(layoutPath))
continue;
layoutPath = path / fileName;
}
@@ -63,25 +64,10 @@ namespace hex {
}
const std::vector<LayoutManager::Layout>& LayoutManager::getLayouts() {
std::vector<LayoutManager::Layout> LayoutManager::getLayouts() {
return s_layouts;
}
void LayoutManager::removeLayout(const std::string& name) {
for (const auto &layout : *s_layouts) {
if (layout.name == name) {
if (wolv::io::fs::remove(layout.path)) {
log::info("Removed layout '{}'", name);
} else {
log::error("Failed to remove layout '{}'", name);
}
}
}
LayoutManager::reload();
}
void LayoutManager::closeAllViews() {
for (const auto &[name, view] : ContentRegistry::Views::impl::getEntries())
view->getWindowOpenState() = false;
@@ -89,26 +75,28 @@ namespace hex {
void LayoutManager::process() {
if (s_layoutPathToLoad->has_value()) {
LayoutManager::closeAllViews();
const auto pathString = wolv::util::toUTF8String(**s_layoutPathToLoad);
wolv::io::File file(**s_layoutPathToLoad, wolv::io::File::Mode::Read);
s_layoutStringToLoad = file.readString();
s_layoutPathToLoad->reset();
LayoutManager::closeAllViews();
ImGui::LoadIniSettingsFromDisk(pathString.c_str());
s_layoutPathToLoad = std::nullopt;
log::info("Loaded layout from {}", pathString);
}
if (s_layoutStringToLoad->has_value()) {
LayoutManager::closeAllViews();
ImGui::LoadIniSettingsFromMemory((*s_layoutStringToLoad)->c_str());
s_layoutStringToLoad->reset();
log::info("Loaded new Layout");
s_layoutStringToLoad = std::nullopt;
log::info("Loaded layout from string");
}
}
void LayoutManager::reload() {
s_layouts->clear();
for (const auto &directory : paths::Layouts.read()) {
for (const auto &directory : hex::fs::getDefaultPaths(fs::ImHexPath::Layouts)) {
for (const auto &entry : std::fs::directory_iterator(directory)) {
const auto &path = entry.path();
@@ -131,8 +119,8 @@ namespace hex {
}
void LayoutManager::reset() {
s_layoutPathToLoad->reset();
s_layoutStringToLoad->reset();
s_layoutPathToLoad.reset();
s_layoutStringToLoad.reset();
s_layouts->clear();
}

View File

@@ -5,7 +5,6 @@
#include <hex/helpers/fmt.hpp>
#include <hex/helpers/auto_reset.hpp>
#include <hex/helpers/utils.hpp>
#include <hex/helpers/default_paths.hpp>
#include <wolv/utils/string.hpp>
@@ -19,50 +18,24 @@
namespace hex {
static uintptr_t loadLibrary(const std::fs::path &path) {
#if defined(OS_WINDOWS)
auto handle = uintptr_t(LoadLibraryW(path.c_str()));
if (handle == uintptr_t(INVALID_HANDLE_VALUE) || handle == 0) {
log::error("Loading library '{}' failed: {} {}!", wolv::util::toUTF8String(path.filename()), ::GetLastError(), hex::formatSystemError(::GetLastError()));
return 0;
}
return handle;
#else
auto handle = uintptr_t(dlopen(wolv::util::toUTF8String(path).c_str(), RTLD_LAZY));
if (handle == 0) {
log::error("Loading library '{}' failed: {}!", wolv::util::toUTF8String(path.filename()), dlerror());
return 0;
}
return handle;
#endif
}
static void unloadLibrary(uintptr_t handle, const std::fs::path &path) {
#if defined(OS_WINDOWS)
if (handle != 0) {
if (FreeLibrary(HMODULE(handle)) == FALSE) {
log::error("Error when unloading library '{}': {}!", wolv::util::toUTF8String(path.filename()), hex::formatSystemError(::GetLastError()));
}
}
#else
if (handle != 0) {
if (dlclose(reinterpret_cast<void*>(handle)) != 0) {
log::error("Error when unloading library '{}': {}!", path.filename().string(), dlerror());
}
}
#endif
}
Plugin::Plugin(const std::fs::path &path) : m_path(path) {
log::info("Loading plugin '{}'", wolv::util::toUTF8String(path.filename()));
m_handle = loadLibrary(path);
if (m_handle == 0)
return;
#if defined(OS_WINDOWS)
m_handle = uintptr_t(LoadLibraryW(path.c_str()));
if (m_handle == uintptr_t(INVALID_HANDLE_VALUE) || m_handle == 0) {
log::error("Loading plugin '{}' failed: {} {}!", wolv::util::toUTF8String(path.filename()), ::GetLastError(), hex::formatSystemError(::GetLastError()));
return;
}
#else
m_handle = uintptr_t(dlopen(wolv::util::toUTF8String(path).c_str(), RTLD_LAZY));
if (m_handle == 0) {
log::error("Loading plugin '{}' failed: {}!", wolv::util::toUTF8String(path.filename()), dlerror());
return;
}
#endif
const auto fileName = path.stem().string();
@@ -116,7 +89,15 @@ namespace hex {
log::info("Trying to unload plugin '{}'", getPluginName());
}
unloadLibrary(m_handle, m_path);
#if defined(OS_WINDOWS)
if (m_handle != 0)
if (FreeLibrary(HMODULE(m_handle)) == FALSE) {
log::error("Error when unloading plugin '{}': {}!", wolv::util::toUTF8String(m_path.filename()), hex::formatSystemError(::GetLastError()));
}
#else
if (m_handle != 0)
dlclose(reinterpret_cast<void*>(m_handle));
#endif
}
bool Plugin::initializePlugin() const {
@@ -303,35 +284,6 @@ namespace hex {
return true;
}
AutoReset<std::vector<uintptr_t>> PluginManager::s_loadedLibraries;
bool PluginManager::loadLibraries() {
bool success = true;
for (const auto &loadPath : paths::Libraries.read())
success = PluginManager::loadLibraries(loadPath) && success;
return success;
}
bool PluginManager::loadLibraries(const std::fs::path& libraryFolder) {
bool success = true;
for (const auto &entry : std::fs::directory_iterator(libraryFolder)) {
if (!(entry.path().extension() == ".dll" || entry.path().extension() == ".so" || entry.path().extension() == ".dylib"))
continue;
auto handle = loadLibrary(entry);
if (handle == 0) {
success = false;
}
PluginManager::s_loadedLibraries->push_back(handle);
}
return success;
}
void PluginManager::initializeNewPlugins() {
for (const auto &plugin : getPlugins()) {
if (!plugin.isLoaded())
@@ -352,11 +304,6 @@ namespace hex {
plugins.pop_back();
}
while (!s_loadedLibraries->empty()) {
unloadLibrary(s_loadedLibraries->back(), "");
s_loadedLibraries->pop_back();
}
getPluginsMutable() = std::move(savedPlugins);
}
@@ -374,15 +321,6 @@ namespace hex {
return plugins;
}
Plugin* PluginManager::getPlugin(const std::string &name) {
for (auto &plugin : getPluginsMutable()) {
if (plugin.getPluginName() == name)
return &plugin;
}
return nullptr;
}
const std::vector<std::fs::path>& PluginManager::getPluginPaths() {
return s_pluginPaths;
}
@@ -397,4 +335,5 @@ namespace hex {
});
}
}

View File

@@ -426,10 +426,6 @@ namespace hex {
void TaskManager::runWhenTasksFinished(const std::function<void()> &function) {
std::scoped_lock lock(s_tasksFinishedMutex);
for (const auto &task : s_tasks) {
task->interrupt();
}
s_tasksFinishedCallbacks.push_back(function);
}
@@ -443,7 +439,7 @@ namespace hex {
static auto setThreadDescription = reinterpret_cast<SetThreadDescriptionFunc>(
reinterpret_cast<uintptr_t>(
::GetProcAddress(
::GetModuleHandleW(L"Kernel32.dll"),
::GetModuleHandle("Kernel32.dll"),
"SetThreadDescription"
)
)

View File

@@ -17,25 +17,18 @@ namespace hex {
AutoReset<std::string> s_imageTheme;
AutoReset<std::string> s_currTheme;
std::recursive_mutex s_themeMutex;
}
void ThemeManager::addThemeHandler(const std::string &name, const ColorMap &colorMap, const std::function<ImColor(u32)> &getFunction, const std::function<void(u32, ImColor)> &setFunction) {
std::unique_lock lock(s_themeMutex);
(*s_themeHandlers)[name] = { colorMap, getFunction, setFunction };
}
void ThemeManager::addStyleHandler(const std::string &name, const StyleMap &styleMap) {
std::unique_lock lock(s_themeMutex);
(*s_styleHandlers)[name] = { styleMap };
}
void ThemeManager::addTheme(const std::string &content) {
std::unique_lock lock(s_themeMutex);
try {
auto theme = nlohmann::json::parse(content);
@@ -73,7 +66,7 @@ namespace hex {
if (color == 0x00000000)
return ImVec4(0, 0, 0, -1);
return ImColor(hex::changeEndianness(color, std::endian::big));
return ImColor(hex::changeEndianess(color, std::endian::big));
}
nlohmann::json ThemeManager::exportCurrentTheme(const std::string &name) {
@@ -90,7 +83,7 @@ namespace hex {
for (const auto &[key, value] : handler.colorMap) {
auto color = handler.getFunction(value);
theme["colors"][type][key] = fmt::format("#{:08X}", hex::changeEndianness(u32(color), std::endian::big));
theme["colors"][type][key] = fmt::format("#{:08X}", hex::changeEndianess(u32(color), std::endian::big));
}
}
@@ -113,8 +106,6 @@ namespace hex {
}
void ThemeManager::changeTheme(std::string name) {
std::unique_lock lock(s_themeMutex);
if (!s_themes->contains(name)) {
if (s_themes->empty()) {
return;
@@ -177,12 +168,12 @@ namespace hex {
const float scale = style.needsScaling ? 1_scaled : 1.0F;
if (value.is_number_float()) {
if (const auto newValue = std::get_if<float*>(&style.value); newValue != nullptr && *newValue != nullptr)
if (const auto newValue = std::get_if<float*>(&style.value); newValue != nullptr)
**newValue = value.get<float>() * scale;
else
log::warn("Style variable '{}' was of type ImVec2 but a float was expected.", name);
} else if (value.is_array() && value.size() == 2 && value[0].is_number_float() && value[1].is_number_float()) {
if (const auto newValue = std::get_if<ImVec2*>(&style.value); newValue != nullptr && *newValue != nullptr)
if (const auto newValue = std::get_if<ImVec2*>(&style.value); newValue != nullptr)
**newValue = ImVec2(value[0].get<float>() * scale, value[1].get<float>() * scale);
else
log::warn("Style variable '{}' was of type float but a ImVec2 was expected.", name);
@@ -200,8 +191,6 @@ namespace hex {
hex::log::error("Theme '{}' has invalid image theme!", name);
s_imageTheme = "dark";
}
} else {
s_imageTheme = "dark";
}
s_currTheme = name;
@@ -222,8 +211,6 @@ namespace hex {
}
void ThemeManager::reset() {
std::unique_lock lock(s_themeMutex);
s_themes->clear();
s_styleHandlers->clear();
s_themeHandlers->clear();

View File

@@ -21,11 +21,6 @@ namespace hex {
AutoReset<std::map<ImGuiID, std::string>> s_highlights;
AutoReset<std::vector<std::pair<ImRect, std::string>>> s_highlightDisplays;
AutoReset<std::map<ImGuiID, std::function<void()>>> s_interactiveHelpItems;
ImRect s_hoveredRect;
ImGuiID s_hoveredId;
bool s_helpHoverActive = false;
class IDStack {
public:
@@ -61,42 +56,8 @@ namespace hex {
ImVector<ImGuiID> idStack;
};
ImGuiID calculateId(const auto &ids) {
IDStack idStack;
for (const auto &id : ids) {
std::visit(wolv::util::overloaded {
[&idStack](const Lang &id) {
idStack.add(id.get());
},
[&idStack](const auto &id) {
idStack.add(id);
}
}, id);
}
return idStack.get();
}
}
void TutorialManager::init() {
EventImGuiElementRendered::subscribe([](ImGuiID id, const std::array<float, 4> bb){
const auto boundingBox = ImRect(bb[0], bb[1], bb[2], bb[3]);
const auto element = hex::s_highlights->find(id);
if (element != hex::s_highlights->end()) {
hex::s_highlightDisplays->emplace_back(boundingBox, element->second);
}
if (id != 0 && boundingBox.Contains(ImGui::GetMousePos())) {
if ((s_hoveredRect.GetArea() == 0 || boundingBox.GetArea() < s_hoveredRect.GetArea()) && s_interactiveHelpItems->contains(id)) {
s_hoveredRect = boundingBox;
s_hoveredId = id;
}
}
});
}
const std::map<std::string, TutorialManager::Tutorial>& TutorialManager::getTutorials() {
return s_tutorials;
@@ -111,28 +72,6 @@ namespace hex {
return s_tutorials->try_emplace(unlocalizedName, Tutorial(unlocalizedName, unlocalizedDescription)).first->second;
}
void TutorialManager::startHelpHover() {
TaskManager::doLater([]{
s_helpHoverActive = true;
});
}
void TutorialManager::addInteractiveHelpText(std::initializer_list<std::variant<Lang, std::string, int>> &&ids, UnlocalizedString text) {
auto id = calculateId(ids);
s_interactiveHelpItems->emplace(id, [text = std::move(text)]{
log::info("{}", Lang(text).get());
});
}
void TutorialManager::addInteractiveHelpLink(std::initializer_list<std::variant<Lang, std::string, int>> &&ids, std::string link) {
auto id = calculateId(ids);
s_interactiveHelpItems->emplace(id, [link = std::move(link)]{
hex::openWebpage(link);
});
}
void TutorialManager::startTutorial(const UnlocalizedString &unlocalizedName) {
s_currentTutorial = s_tutorials->find(unlocalizedName);
if (s_currentTutorial == s_tutorials->end())
@@ -142,30 +81,6 @@ namespace hex {
}
void TutorialManager::drawHighlights() {
if (s_helpHoverActive) {
const auto &drawList = ImGui::GetForegroundDrawList();
drawList->AddText(ImGui::GetMousePos() + scaled({ 10, -5, }), ImGui::GetColorU32(ImGuiCol_Text), "?");
const bool mouseClicked = ImGui::IsMouseClicked(ImGuiMouseButton_Left);
if (s_hoveredId != 0) {
drawList->AddRectFilled(s_hoveredRect.Min, s_hoveredRect.Max, 0x30FFFFFF);
if (mouseClicked) {
auto it = s_interactiveHelpItems->find(s_hoveredId);
if (it != s_interactiveHelpItems->end()) {
it->second();
}
}
s_hoveredId = 0;
s_hoveredRect = {};
}
if (mouseClicked || ImGui::IsKeyPressed(ImGuiKey_Escape)) {
s_helpHoverActive = false;
}
}
for (const auto &[rect, unlocalizedText] : *s_highlightDisplays) {
const auto drawList = ImGui::GetForegroundDrawList();
@@ -326,13 +241,39 @@ namespace hex {
m_onAppear();
for (const auto &[text, ids] : m_highlights) {
s_highlights->emplace(calculateId(ids), text);
IDStack idStack;
for (const auto &id : ids) {
std::visit(wolv::util::overloaded {
[&idStack](const Lang &id) {
idStack.add(id.get());
},
[&idStack](const auto &id) {
idStack.add(id);
}
}, id);
}
s_highlights->emplace(idStack.get(), text);
}
}
void TutorialManager::Tutorial::Step::removeHighlights() const {
for (const auto &[text, ids] : m_highlights) {
s_highlights->erase(calculateId(ids));
IDStack idStack;
for (const auto &id : ids) {
std::visit(wolv::util::overloaded {
[&idStack](const Lang &id) {
idStack.add(id.get());
},
[&idStack](const auto &id) {
idStack.add(id);
}
}, id);
}
s_highlights->erase(idStack.get());
}
}
@@ -427,4 +368,15 @@ namespace hex {
}
}
}
}
void ImGuiTestEngineHook_ItemAdd(ImGuiContext*, ImGuiID id, const ImRect& bb, const ImGuiLastItemData*) {
const auto element = hex::s_highlights->find(id);
if (element != hex::s_highlights->end()) {
hex::s_highlightDisplays->emplace_back(bb, element->second);
}
}
void ImGuiTestEngineHook_ItemInfo(ImGuiContext*, ImGuiID, const char*, ImGuiItemStatusFlags) {}
void ImGuiTestEngineHook_Log(ImGuiContext*, const char*, ...) {}
const char* ImGuiTestEngine_FindItemDebugLabel(ImGuiContext*, ImGuiID) { return nullptr; }

View File

@@ -3,35 +3,28 @@
#include <hex/helpers/logger.hpp>
#include <hex/helpers/auto_reset.hpp>
#include <hex/helpers/default_paths.hpp>
#include <wolv/io/file.hpp>
#include <nlohmann/json.hpp>
#include <imgui.h>
#include <wolv/utils/string.hpp>
namespace hex {
AutoReset<std::map<std::string, WorkspaceManager::Workspace>> WorkspaceManager::s_workspaces;
decltype(WorkspaceManager::s_workspaces)::Type::iterator WorkspaceManager::s_currentWorkspace = s_workspaces->end();
decltype(WorkspaceManager::s_workspaces)::Type::iterator WorkspaceManager::s_previousWorkspace = s_workspaces->end();
decltype(WorkspaceManager::s_workspaces)::Type::iterator WorkspaceManager::s_workspaceToRemove = s_workspaces->end();
void WorkspaceManager::createWorkspace(const std::string& name, const std::string &layout) {
s_currentWorkspace = s_workspaces->insert_or_assign(name, Workspace {
.layout = layout.empty() ? LayoutManager::saveToString() : layout,
.path = {},
.builtin = false
.layout = layout.empty() ? LayoutManager::saveToString() : layout,
.path = {}
}).first;
for (const auto &workspaceFolder : paths::Workspaces.write()) {
const auto workspacePath = workspaceFolder / (name + ".hexws");
if (exportToFile(workspacePath)) {
s_currentWorkspace->second.path = workspacePath;
for (const auto &path : fs::getDefaultPaths(fs::ImHexPath::Workspaces)) {
if (exportToFile(path / (name + ".hexws")))
break;
}
}
}
@@ -44,10 +37,6 @@ namespace hex {
}
void WorkspaceManager::importFromFile(const std::fs::path& path) {
if (std::ranges::any_of(*s_workspaces, [path](const auto &pair) { return pair.second.path == path; })) {
return;
}
wolv::io::File file(path, wolv::io::File::Mode::Read);
if (!file.isValid()) {
log::error("Failed to load workspace from file '{}'", path.string());
@@ -61,12 +50,10 @@ namespace hex {
const std::string name = json["name"];
std::string layout = json["layout"];
const bool builtin = json.value("builtin", false);
(*s_workspaces)[name] = Workspace {
.layout = std::move(layout),
.path = path,
.builtin = builtin
.path = path
};
} catch (nlohmann::json::exception &e) {
log::error("Failed to load workspace from file '{}': {}", path.string(), e.what());
@@ -74,77 +61,41 @@ namespace hex {
}
}
bool WorkspaceManager::exportToFile(std::fs::path path, std::string workspaceName, bool builtin) {
bool WorkspaceManager::exportToFile(std::fs::path path, std::string workspaceName) {
if (path.empty()) {
if (s_currentWorkspace == s_workspaces->end()) {
if (s_currentWorkspace == s_workspaces->end())
return false;
}
path = s_currentWorkspace->second.path;
}
if (workspaceName.empty()) {
if (workspaceName.empty())
workspaceName = s_currentWorkspace->first;
}
wolv::io::File file(path, wolv::io::File::Mode::Create);
if (!file.isValid()) {
if (!file.isValid())
return false;
}
nlohmann::json json;
json["name"] = workspaceName;
json["layout"] = LayoutManager::saveToString();
json["builtin"] = builtin;
file.writeString(json.dump(4));
return true;
}
void WorkspaceManager::removeWorkspace(const std::string& name) {
bool deletedCurrentWorkspace = false;
for (const auto &[workspaceName, workspace] : *s_workspaces) {
if (workspaceName == name) {
log::info("Removing workspace file '{}'", wolv::util::toUTF8String(workspace.path));
if (wolv::io::fs::remove(workspace.path)) {
log::info("Removed workspace '{}'", name);
if (workspaceName == s_currentWorkspace->first) {
deletedCurrentWorkspace = true;
}
} else {
log::error("Failed to remove workspace '{}'", name);
}
}
}
WorkspaceManager::reload();
if (deletedCurrentWorkspace && !s_workspaces->empty()) {
s_currentWorkspace = s_workspaces->begin();
}
}
void WorkspaceManager::process() {
if (s_previousWorkspace != s_currentWorkspace) {
log::info("Updating workspace");
if (s_previousWorkspace != s_workspaces->end()) {
exportToFile(s_previousWorkspace->second.path, s_previousWorkspace->first, s_previousWorkspace->second.builtin);
}
if (s_previousWorkspace != s_workspaces->end())
exportToFile(s_previousWorkspace->second.path, s_previousWorkspace->first);
LayoutManager::closeAllViews();
ImGui::LoadIniSettingsFromMemory(s_currentWorkspace->second.layout.c_str());
s_previousWorkspace = s_currentWorkspace;
if (s_workspaceToRemove != s_workspaces->end()) {
s_workspaces->erase(s_workspaceToRemove);
s_workspaceToRemove = s_workspaces->end();
}
}
}
@@ -155,26 +106,6 @@ namespace hex {
s_previousWorkspace = s_workspaces->end();
}
void WorkspaceManager::reload() {
WorkspaceManager::reset();
for (const auto &defaultPath : paths::Workspaces.read()) {
for (const auto &entry : std::fs::directory_iterator(defaultPath)) {
if (!entry.is_regular_file()) {
continue;
}
const auto &path = entry.path();
if (path.extension() != ".hexws") {
continue;
}
WorkspaceManager::importFromFile(path);
}
}
}
}

View File

@@ -1,153 +0,0 @@
#include <hex/helpers/default_paths.hpp>
#include <hex/api/imhex_api.hpp>
#include <hex/api/project_file_manager.hpp>
#if defined(OS_WINDOWS)
#include <windows.h>
#include <shlobj.h>
#elif defined(OS_LINUX) || defined(OS_WEB)
#include <xdg.hpp>
# endif
namespace hex::paths {
std::vector<std::fs::path> getDataPaths(bool includeSystemFolders) {
std::vector<std::fs::path> paths;
#if defined(OS_WINDOWS)
// In the portable Windows version, we just use the executable directory
// Prevent the use of the AppData folder here
if (!ImHexApi::System::isPortableVersion()) {
PWSTR wAppDataPath = nullptr;
if (SUCCEEDED(SHGetKnownFolderPath(FOLDERID_LocalAppData, KF_FLAG_CREATE, nullptr, &wAppDataPath))) {
paths.emplace_back(wAppDataPath);
CoTaskMemFree(wAppDataPath);
}
}
#elif defined(OS_MACOS)
paths.push_back(wolv::io::fs::getApplicationSupportDirectoryPath());
#elif defined(OS_LINUX) || defined(OS_WEB)
paths.push_back(xdg::DataHomeDir());
auto dataDirs = xdg::DataDirs();
std::copy(dataDirs.begin(), dataDirs.end(), std::back_inserter(paths));
#endif
#if defined(OS_MACOS)
if (includeSystemFolders) {
if (auto executablePath = wolv::io::fs::getExecutablePath(); executablePath.has_value()) {
paths.push_back(*executablePath);
}
}
#else
for (auto &path : paths)
path = path / "imhex";
if (ImHexApi::System::isPortableVersion() || includeSystemFolders) {
if (auto executablePath = wolv::io::fs::getExecutablePath(); executablePath.has_value())
paths.push_back(executablePath->parent_path());
}
#endif
// Add additional data directories to the path
auto additionalDirs = ImHexApi::System::getAdditionalFolderPaths();
std::ranges::copy(additionalDirs, std::back_inserter(paths));
// Add the project file directory to the path, if one is loaded
if (ProjectFile::hasPath()) {
paths.push_back(ProjectFile::getPath().parent_path());
}
return paths;
}
std::vector<std::fs::path> getConfigPaths(bool includeSystemFolders) {
#if defined(OS_WINDOWS)
return getDataPaths(includeSystemFolders);
#elif defined(OS_MACOS)
return getDataPaths(includeSystemFolders);
#elif defined(OS_LINUX) || defined(OS_WEB)
hex::unused(includeSystemFolders);
return {xdg::ConfigHomeDir() / "imhex"};
#endif
}
static std::vector<std::fs::path> appendPath(std::vector<std::fs::path> paths, std::fs::path folder) {
folder.make_preferred();
for (auto &path : paths)
path = path / folder;
return paths;
}
static std::vector<std::fs::path> getPluginPaths() {
std::vector<std::fs::path> paths = getDataPaths(true);
// Add the system plugin directory to the path if one was provided at compile time
#if defined(OS_LINUX) && defined(SYSTEM_PLUGINS_LOCATION)
paths.push_back(SYSTEM_PLUGINS_LOCATION);
#endif
return paths;
}
namespace impl {
std::vector<std::fs::path> DefaultPath::read() const {
auto result = this->all();
std::erase_if(result, [](const auto &entryPath) {
return !wolv::io::fs::isDirectory(entryPath);
});
return result;
}
std::vector<std::fs::path> DefaultPath::write() const {
auto result = this->read();
std::erase_if(result, [](const auto &entryPath) {
return !hex::fs::isPathWritable(entryPath);
});
return result;
}
std::vector<std::fs::path> ConfigPath::all() const {
return appendPath(getConfigPaths(false), m_postfix);
}
std::vector<std::fs::path> DataPath::all() const {
return appendPath(getDataPaths(true), m_postfix);
}
std::vector<std::fs::path> DataPath::write() const {
auto result = appendPath(getDataPaths(false), m_postfix);
std::erase_if(result, [](const auto &entryPath) {
return !hex::fs::isPathWritable(entryPath);
});
return result;
}
std::vector<std::fs::path> PluginPath::all() const {
return appendPath(getPluginPaths(), m_postfix);
}
}
}

View File

@@ -32,9 +32,6 @@
#include <wolv/io/fs.hpp>
#include <wolv/utils/string.hpp>
#include <fmt/format.h>
#include <fmt/xchar.h>
namespace hex::fs {
static AutoReset<std::function<void(const std::string&)>> s_fileBrowserErrorCallback;
@@ -51,7 +48,7 @@ namespace hex::fs {
#if defined(OS_WINDOWS)
hex::unused(
ShellExecuteW(nullptr, L"open", filePath.c_str(), nullptr, nullptr, SW_SHOWNORMAL)
ShellExecute(nullptr, "open", wolv::util::toUTF8String(filePath).c_str(), nullptr, nullptr, SW_SHOWNORMAL)
);
#elif defined(OS_MACOS)
hex::unused(system(
@@ -69,8 +66,9 @@ namespace hex::fs {
}
#if defined(OS_WINDOWS)
auto args = fmt::format(L"\"{}\"", dirPath.c_str());
ShellExecuteW(nullptr, L"open", L"explorer.exe", args.c_str(), nullptr, SW_SHOWNORMAL);
hex::unused(system(
hex::format("explorer.exe {}", wolv::util::toUTF8String(dirPath)).c_str()
));
#elif defined(OS_MACOS)
hex::unused(system(
hex::format("open {}", wolv::util::toUTF8String(dirPath)).c_str()
@@ -87,8 +85,9 @@ namespace hex::fs {
}
#if defined(OS_WINDOWS)
auto args = fmt::format(L"/select,\"{}\"", selectedFilePath.c_str());
ShellExecuteW(nullptr, L"open", L"explorer.exe", args.c_str(), nullptr, SW_SHOWNORMAL);
hex::unused(system(
hex::format(R"(explorer.exe /select,"{}")", wolv::util::toUTF8String(selectedFilePath)).c_str()
));
#elif defined(OS_MACOS)
hex::unused(system(
hex::format(
@@ -287,6 +286,170 @@ namespace hex::fs {
#endif
std::vector<std::fs::path> getDataPaths() {
std::vector<std::fs::path> paths;
#if defined(OS_WINDOWS)
// In the portable Windows version, we just use the executable directory
// Prevent the use of the AppData folder here
if (!ImHexApi::System::isPortableVersion()) {
PWSTR wAppDataPath = nullptr;
if (SUCCEEDED(SHGetKnownFolderPath(FOLDERID_LocalAppData, KF_FLAG_CREATE, nullptr, &wAppDataPath))) {
paths.emplace_back(wAppDataPath);
CoTaskMemFree(wAppDataPath);
}
}
#elif defined(OS_MACOS)
paths.push_back(wolv::io::fs::getApplicationSupportDirectoryPath());
#elif defined(OS_LINUX) || defined(OS_WEB)
paths.push_back(xdg::DataHomeDir());
auto dataDirs = xdg::DataDirs();
std::copy(dataDirs.begin(), dataDirs.end(), std::back_inserter(paths));
#endif
#if defined(OS_MACOS)
if (auto executablePath = wolv::io::fs::getExecutablePath(); executablePath.has_value())
paths.push_back(*executablePath);
#else
for (auto &path : paths)
path = path / "imhex";
if (auto executablePath = wolv::io::fs::getExecutablePath(); executablePath.has_value())
paths.push_back(executablePath->parent_path());
#endif
// Add additional data directories to the path
auto additionalDirs = ImHexApi::System::getAdditionalFolderPaths();
std::ranges::copy(additionalDirs, std::back_inserter(paths));
// Add the project file directory to the path, if one is loaded
if (ProjectFile::hasPath()) {
paths.push_back(ProjectFile::getPath().parent_path());
}
return paths;
}
static std::vector<std::fs::path> getConfigPaths() {
#if defined(OS_WINDOWS)
return getDataPaths();
#elif defined(OS_MACOS)
return getDataPaths();
#elif defined(OS_LINUX) || defined(OS_WEB)
return {xdg::ConfigHomeDir() / "imhex"};
#endif
}
std::vector<std::fs::path> appendPath(std::vector<std::fs::path> paths, const std::fs::path &folder) {
for (auto &path : paths)
path = path / folder;
return paths;
}
std::vector<std::fs::path> getPluginPaths() {
std::vector<std::fs::path> paths = getDataPaths();
// Add the system plugin directory to the path if one was provided at compile time
#if defined(OS_LINUX) && defined(SYSTEM_PLUGINS_LOCATION)
paths.push_back(SYSTEM_PLUGINS_LOCATION);
#endif
return paths;
}
std::vector<std::fs::path> getDefaultPaths(ImHexPath path, bool listNonExisting) {
std::vector<std::fs::path> result;
// Return the correct path based on the ImHexPath enum
switch (path) {
case ImHexPath::END:
return { };
case ImHexPath::Constants:
result = appendPath(getDataPaths(), "constants");
break;
case ImHexPath::Config:
result = appendPath(getConfigPaths(), "config");
break;
case ImHexPath::Backups:
result = appendPath(getDataPaths(), "backups");
break;
case ImHexPath::Encodings:
result = appendPath(getDataPaths(), "encodings");
break;
case ImHexPath::Logs:
result = appendPath(getDataPaths(), "logs");
break;
case ImHexPath::Plugins:
result = appendPath(getPluginPaths(), "plugins");
break;
case ImHexPath::Libraries:
result = appendPath(getPluginPaths(), "lib");
break;
case ImHexPath::Resources:
result = appendPath(getDataPaths(), "resources");
break;
case ImHexPath::Magic:
result = appendPath(getDataPaths(), "magic");
break;
case ImHexPath::Patterns:
result = appendPath(getDataPaths(), "patterns");
break;
case ImHexPath::PatternsInclude:
result = appendPath(getDataPaths(), "includes");
break;
case ImHexPath::Yara:
result = appendPath(getDataPaths(), "yara");
break;
case ImHexPath::YaraAdvancedAnalysis:
result = appendPath(getDefaultPaths(ImHexPath::Yara), "advanced_analysis");
break;
case ImHexPath::Recent:
result = appendPath(getConfigPaths(), "recent");
break;
case ImHexPath::Scripts:
result = appendPath(getDataPaths(), "scripts");
break;
case ImHexPath::Inspectors:
result = appendPath(getDefaultPaths(ImHexPath::Scripts), "inspectors");
break;
case ImHexPath::Nodes:
result = appendPath(getDefaultPaths(ImHexPath::Scripts), "nodes");
break;
case ImHexPath::Themes:
result = appendPath(getDataPaths(), "themes");
break;
case ImHexPath::Layouts:
result = appendPath(getDataPaths(), "layouts");
break;
case ImHexPath::Workspaces:
result = appendPath(getDataPaths(), "workspaces");
break;
}
// Remove all paths that don't exist if requested
if (!listNonExisting) {
std::erase_if(result, [](const auto &entryPath) {
return !wolv::io::fs::isDirectory(entryPath);
});
}
return result;
}
bool isPathWritable(const std::fs::path &path) {
constexpr static auto TestFileName = "__imhex__tmp__";

View File

@@ -1,15 +0,0 @@
#include <hex/api/event_manager.hpp>
#include <imgui.h>
#include <imgui_internal.h>
#include <array>
void ImGuiTestEngineHook_ItemAdd(ImGuiContext*, ImGuiID id, const ImRect& bb, const ImGuiLastItemData*) {
std::array<float, 4> boundingBox = { bb.Min.x, bb.Min.y, bb.Max.x, bb.Max.y };
hex::EventImGuiElementRendered::post(id, boundingBox);
}
void ImGuiTestEngineHook_ItemInfo(ImGuiContext*, ImGuiID, const char*, ImGuiItemStatusFlags) {}
void ImGuiTestEngineHook_Log(ImGuiContext*, const char*, ...) {}
const char* ImGuiTestEngine_FindItemDebugLabel(ImGuiContext*, ImGuiID) { return nullptr; }

View File

@@ -1,17 +1,12 @@
#include <hex/helpers/logger.hpp>
#include <hex/api/task_manager.hpp>
#include <hex/api/event_manager.hpp>
#include <hex/helpers/fs.hpp>
#include <hex/helpers/fmt.hpp>
#include <hex/helpers/default_paths.hpp>
#include <wolv/io/file.hpp>
#include <mutex>
#include <chrono>
#include <fmt/chrono.h>
#include <hex/api/task_manager.hpp>
#if defined(OS_WINDOWS)
#include <Windows.h>
@@ -25,7 +20,6 @@ namespace hex::log {
bool s_colorOutputEnabled = false;
std::recursive_mutex s_loggerMutex;
bool s_loggingSuspended = false;
bool s_debugLoggingEnabled = false;
}
@@ -37,33 +31,16 @@ namespace hex::log {
s_loggingSuspended = false;
}
void enableDebugLogging() {
s_debugLoggingEnabled = true;
}
namespace impl {
void lockLoggerMutex() {
s_loggerMutex.lock();
std::recursive_mutex& getLoggerMutex() {
return s_loggerMutex;
}
void unlockLoggerMutex() {
s_loggerMutex.unlock();
}
bool isLoggingSuspended() {
return s_loggingSuspended;
}
bool isDebugLoggingEnabled() {
#if defined(DEBUG)
return true;
#else
return s_debugLoggingEnabled;
#endif
}
FILE *getDestination() {
if (s_loggerFile.isValid())
return s_loggerFile.getHandle();
@@ -82,7 +59,7 @@ namespace hex::log {
void redirectToFile() {
if (s_loggerFile.isValid()) return;
for (const auto &path : paths::Logs.all()) {
for (const auto &path : fs::getDefaultPaths(fs::ImHexPath::Logs, true)) {
wolv::io::fs::createDirectories(path);
s_loggerFile = wolv::io::File(path / hex::format("{0:%Y%m%d_%H%M%S}.log", fmt::localtime(std::chrono::system_clock::to_time_t(std::chrono::system_clock::now()))), wolv::io::File::Mode::Create);
s_loggerFile.disableBuffering();
@@ -144,12 +121,14 @@ namespace hex::log {
fmt::print(dest, "{0}", std::string(projectNameLength > MaxTagLength ? 0 : MaxTagLength - projectNameLength, ' '));
}
void assertionHandler(const char* exprString, const char* file, int line) {
log::error("Assertion failed: {} at {}:{}", exprString, file, line);
void assertionHandler(bool expr, const char* exprString, const char* file, int line) {
if (!expr) {
log::error("Assertion failed: {} at {}:{}", exprString, file, line);
#if defined (DEBUG)
std::abort();
#endif
#if defined (DEBUG)
std::abort();
#endif
}
}
namespace color {

View File

@@ -3,7 +3,6 @@
#include <hex/helpers/utils.hpp>
#include <hex/helpers/fs.hpp>
#include <hex/helpers/logger.hpp>
#include <hex/helpers/default_paths.hpp>
#include <wolv/utils/guards.hpp>
#include <wolv/utils/string.hpp>
@@ -30,7 +29,7 @@ namespace hex::magic {
std::string magicFiles;
std::error_code error;
for (const auto &dir : paths::Magic.read()) {
for (const auto &dir : fs::getDefaultPaths(fs::ImHexPath::Magic)) {
for (const auto &entry : std::fs::directory_iterator(dir, error)) {
auto path = std::fs::absolute(entry.path());
@@ -65,12 +64,12 @@ namespace hex::magic {
if (magicFiles->empty())
return true;
std::array<char, 1024> cwd = { };
std::array<char, 1024> cwd = { 0x00 };
if (getcwd(cwd.data(), cwd.size()) == nullptr)
return false;
std::optional<std::fs::path> magicFolder;
for (const auto &dir : paths::Magic.write()) {
for (const auto &dir : fs::getDefaultPaths(fs::ImHexPath::Magic)) {
if (std::fs::exists(dir) && fs::isPathWritable(dir)) {
magicFolder = dir;
break;
@@ -106,13 +105,8 @@ namespace hex::magic {
ON_SCOPE_EXIT { magic_close(ctx); };
if (magic_load(ctx, magicFiles->c_str()) == 0) {
if (auto description = magic_buffer(ctx, data.data(), data.size()); description != nullptr) {
auto result = wolv::util::replaceStrings(description, "\\012-", "\n-");
if (result.ends_with("- data"))
result = result.substr(0, result.size() - 6);
return result;
}
if (auto result = magic_buffer(ctx, data.data(), data.size()); result != nullptr)
return wolv::util::replaceStrings(result, "\\012-", "\n-");
}
}
@@ -136,13 +130,8 @@ namespace hex::magic {
ON_SCOPE_EXIT { magic_close(ctx); };
if (magic_load(ctx, magicFiles->c_str()) == 0) {
if (auto mimeType = magic_buffer(ctx, data.data(), data.size()); mimeType != nullptr) {
auto result = wolv::util::replaceStrings(mimeType, "\\012-", "\n-");
if (result.ends_with("- application/octet-stream"))
result = result.substr(0, result.size() - 26);
return result;
}
if (auto result = magic_buffer(ctx, data.data(), data.size()); result != nullptr)
return wolv::util::replaceStrings(result, "\\012-", "\n-");
}
}
@@ -173,13 +162,8 @@ namespace hex::magic {
ON_SCOPE_EXIT { magic_close(ctx); };
if (magic_load(ctx, magicFiles->c_str()) == 0) {
if (auto extension = magic_buffer(ctx, data.data(), data.size()); extension != nullptr) {
auto result = wolv::util::replaceStrings(extension, "\\012-", "\n-");
if (result.ends_with("- ???"))
result = result.substr(0, result.size() - 5);
return result;
}
if (auto result = magic_buffer(ctx, data.data(), data.size()); result != nullptr)
return wolv::util::replaceStrings(result, "\\012-", "\n-");
}
}

View File

@@ -138,7 +138,7 @@ namespace hex {
result.push_back(addressBytes[2]);
result.push_back(addressBytes[1]);
result.push_back(addressBytes[0]);
pushBytesBack<u16>(result, changeEndianness<u16>(bytes.size(), std::endian::big));
pushBytesBack<u16>(result, changeEndianess<u16>(bytes.size(), std::endian::big));
for (auto byte : bytes)
result.push_back(byte);
@@ -189,7 +189,7 @@ namespace hex {
result.push_back(addressBytes[2]);
result.push_back(addressBytes[1]);
result.push_back(addressBytes[0]);
pushBytesBack<u16>(result, changeEndianness<u16>(bytes.size(), std::endian::big));
pushBytesBack<u16>(result, changeEndianess<u16>(bytes.size(), std::endian::big));
for (auto byte : bytes)
result.push_back(byte);

View File

@@ -90,7 +90,11 @@ namespace hex {
bool Tar::contains(const std::fs::path &path) const {
mtar_header_t header;
const auto fixedPath = wolv::io::fs::toNormalizedPathString(path);
auto fixedPath = path.string();
#if defined(OS_WINDOWS)
std::replace(fixedPath.begin(), fixedPath.end(), '\\', '/');
#endif
return mtar_find(m_ctx.get(), fixedPath.c_str(), &header) == MTAR_ESUCCESS;
}
@@ -111,7 +115,10 @@ namespace hex {
std::vector<u8> Tar::readVector(const std::fs::path &path) const {
mtar_header_t header;
const auto fixedPath = wolv::io::fs::toNormalizedPathString(path);
auto fixedPath = path.string();
#if defined(OS_WINDOWS)
std::replace(fixedPath.begin(), fixedPath.end(), '\\', '/');
#endif
int ret = mtar_find(m_ctx.get(), fixedPath.c_str(), &header);
if (ret != MTAR_ESUCCESS){
log::debug("Failed to read vector from path {} in tarred file {}: {}",
@@ -136,12 +143,18 @@ namespace hex {
for (const auto &part : path.parent_path()) {
pathPart /= part;
auto fixedPath = wolv::io::fs::toNormalizedPathString(pathPart);
auto fixedPath = pathPart.string();
#if defined(OS_WINDOWS)
std::replace(fixedPath.begin(), fixedPath.end(), '\\', '/');
#endif
mtar_write_dir_header(m_ctx.get(), fixedPath.c_str());
}
}
const auto fixedPath = wolv::io::fs::toNormalizedPathString(path);
auto fixedPath = path.string();
#if defined(OS_WINDOWS)
std::replace(fixedPath.begin(), fixedPath.end(), '\\', '/');
#endif
mtar_write_file_header(m_ctx.get(), fixedPath.c_str(), data.size());
mtar_write_data(m_ctx.get(), data.data(), data.size());
}

View File

@@ -16,11 +16,9 @@
#include <wolv/utils/guards.hpp>
#elif defined(OS_LINUX)
#include <unistd.h>
#include <dlfcn.h>
#include <hex/helpers/utils_linux.hpp>
#elif defined(OS_MACOS)
#include <unistd.h>
#include <dlfcn.h>
#include <hex/helpers/utils_macos.hpp>
#elif defined(OS_WEB)
#include "emscripten.h"
@@ -355,7 +353,7 @@ namespace hex {
url = "https://" + url;
#if defined(OS_WINDOWS)
ShellExecuteA(nullptr, "open", url.c_str(), nullptr, nullptr, SW_SHOWNORMAL);
ShellExecute(nullptr, "open", url.c_str(), nullptr, nullptr, SW_SHOWNORMAL);
#elif defined(OS_MACOS)
openWebpageMacos(url.c_str());
#elif defined(OS_LINUX)
@@ -679,44 +677,6 @@ namespace hex {
return value;
}
[[nodiscard]] std::string limitStringLength(const std::string &string, size_t maxLength) {
// If the string is shorter than the max length, return it as is
if (string.size() < maxLength)
return string;
// If the string is longer than the max length, find the last space before the max length
auto it = string.begin() + maxLength / 2;
while (it != string.begin() && !std::isspace(*it)) --it;
// If there's no space before the max length, just cut the string
if (it == string.begin()) {
it = string.begin() + maxLength / 2;
// Try to find a UTF-8 character boundary
while (it != string.begin() && (*it & 0xC0) == 0x80) --it;
}
// If we still didn't find a valid boundary, just return the string as is
if (it == string.begin())
return string;
auto result = std::string(string.begin(), it) + "";
// If the string is longer than the max length, find the last space before the max length
it = string.end() - 1 - maxLength / 2;
while (it != string.end() && !std::isspace(*it)) ++it;
// If there's no space before the max length, just cut the string
if (it == string.end()) {
it = string.end() - 1 - maxLength / 2;
// Try to find a UTF-8 character boundary
while (it != string.end() && (*it & 0xC0) == 0x80) ++it;
}
return result + std::string(it, string.end());
}
static std::optional<std::fs::path> s_fileToOpen;
extern "C" void openFile(const char *path) {
log::info("Opening file: {0}", path);
@@ -824,24 +784,4 @@ namespace hex {
#endif
}
void* getContainingModule(void* symbol) {
#if defined(OS_WINDOWS)
MEMORY_BASIC_INFORMATION mbi;
if (VirtualQuery(symbol, &mbi, sizeof(mbi)))
return mbi.AllocationBase;
return nullptr;
#elif !defined(OS_WEB)
Dl_info info = {};
if (dladdr(symbol, &info) == 0)
return nullptr;
return dlopen(info.dli_fname, RTLD_LAZY);
#else
hex::unused(symbol);
return nullptr;
#endif
}
}

View File

@@ -88,42 +88,6 @@
CFRelease(fontDescriptors);
}
void macosHandleTitlebarDoubleClickGesture(GLFWwindow *window) {
NSWindow* cocoaWindow = glfwGetCocoaWindow(window);
// Consult user preferences: "System Settings -> Desktop & Dock -> Double-click a window's title bar to"
NSString* action = [[NSUserDefaults standardUserDefaults] stringForKey:@"AppleActionOnDoubleClick"];
if (action == nil || [action isEqualToString:@"None"]) {
// Nothing to do
} else if ([action isEqualToString:@"Minimize"]) {
if ([cocoaWindow isMiniaturizable]) {
[cocoaWindow miniaturize:nil];
}
} else if ([action isEqualToString:@"Maximize"]) {
// `[NSWindow zoom:_ sender]` takes over pumping the main runloop for the duration of the resize,
// and would interfere with our renderer's frame logic. Schedule it for the next frame
CFRunLoopPerformBlock(CFRunLoopGetMain(), kCFRunLoopCommonModes, ^{
if ([cocoaWindow isZoomable]) {
[cocoaWindow zoom:nil];
}
});
}
}
bool macosIsWindowBeingResizedByUser(GLFWwindow *window) {
NSWindow* cocoaWindow = glfwGetCocoaWindow(window);
return cocoaWindow.inLiveResize;
}
void macosMarkContentEdited(GLFWwindow *window, bool edited) {
NSWindow* cocoaWindow = glfwGetCocoaWindow(window);
[cocoaWindow setDocumentEdited:edited];
}
@interface HexDocument : NSDocument
@end

View File

@@ -31,4 +31,41 @@ namespace hex::prv {
m_data.resize(newSize);
}
void MemoryProvider::insertRaw(u64 offset, u64 size) {
auto oldSize = this->getActualSize();
this->resizeRaw(oldSize + size);
std::vector<u8> buffer(0x1000);
const std::vector<u8> zeroBuffer(0x1000);
auto position = oldSize;
while (position > offset) {
const auto readSize = std::min<size_t>(position - offset, buffer.size());
position -= readSize;
this->readRaw(position, buffer.data(), readSize);
this->writeRaw(position, zeroBuffer.data(), readSize);
this->writeRaw(position + size, buffer.data(), readSize);
}
}
void MemoryProvider::removeRaw(u64 offset, u64 size) {
auto oldSize = this->getActualSize();
std::vector<u8> buffer(0x1000);
const auto newSize = oldSize - size;
auto position = offset;
while (position < newSize) {
const auto readSize = std::min<size_t>(newSize - position, buffer.size());
this->readRaw(position + size, buffer.data(), readSize);
this->writeRaw(position, buffer.data(), readSize);
position += readSize;
}
this->resizeRaw(oldSize - size);
}
}

View File

@@ -74,11 +74,7 @@ namespace hex::prv {
}
}
bool Provider::resize(u64 newSize) {
if (newSize >> 63) {
log::error("new provider size is very large ({}). Is it a negative number ?", newSize);
return false;
}
void Provider::resize(u64 newSize) {
i64 difference = newSize - this->getActualSize();
if (difference > 0)
@@ -87,7 +83,6 @@ namespace hex::prv {
EventProviderDataRemoved::post(this, this->getActualSize() + difference, -difference);
this->markDirty();
return true;
}
void Provider::insert(u64 offset, u64 size) {
@@ -102,52 +97,6 @@ namespace hex::prv {
this->markDirty();
}
void Provider::insertRaw(u64 offset, u64 size) {
auto oldSize = this->getActualSize();
this->resizeRaw(oldSize + size);
std::vector<u8> buffer(0x1000);
const std::vector<u8> zeroBuffer(0x1000);
auto position = oldSize;
while (position > offset) {
const auto readSize = std::min<size_t>(position - offset, buffer.size());
position -= readSize;
this->readRaw(position, buffer.data(), readSize);
this->writeRaw(position, zeroBuffer.data(), readSize);
this->writeRaw(position + size, buffer.data(), readSize);
}
}
void Provider::removeRaw(u64 offset, u64 size) {
if (offset > this->getActualSize() || size == 0)
return;
if ((offset + size) > this->getActualSize())
size = this->getActualSize() - offset;
auto oldSize = this->getActualSize();
std::vector<u8> buffer(0x1000);
const auto newSize = oldSize - size;
auto position = offset;
while (position < newSize) {
const auto readSize = std::min<size_t>(newSize - position, buffer.size());
this->readRaw(position + size, buffer.data(), readSize);
this->writeRaw(position, buffer.data(), readSize);
position += readSize;
}
this->resizeRaw(newSize);
}
void Provider::applyOverlays(u64 offset, void *buffer, size_t size) const {
for (auto &overlay : m_overlays) {
auto overlayOffset = overlay->getAddress();

View File

@@ -79,7 +79,6 @@ namespace hex::prv::undo {
for (u32 i = 0; i < count; i += 1) {
i64 index = startIndex + i;
m_undoStack[index]->undo(m_provider);
operation->addOperation(std::move(m_undoStack[index]));
}
@@ -94,13 +93,6 @@ namespace hex::prv::undo {
}
}
void Stack::reapply() {
for (const auto &operation : m_undoStack) {
operation->redo(m_provider);
}
}
bool Stack::add(std::unique_ptr<Operation> &&operation) {

View File

@@ -15,12 +15,11 @@ namespace hex::subcommands {
std::optional<SubCommand> findSubCommand(const std::string &arg) {
for (auto &plugin : PluginManager::getPlugins()) {
for (auto &subCommand : plugin.getSubCommands()) {
if (hex::format("--{}", subCommand.commandLong) == arg || hex::format("-{}", subCommand.commandShort) == arg) {
if (hex::format("--{}", subCommand.commandKey) == arg) {
return subCommand;
}
}
}
return std::nullopt;
}
@@ -28,8 +27,7 @@ namespace hex::subcommands {
// If no arguments, do not even try to process arguments
// (important because this function will exit ImHex if an instance is already opened,
// and we don't want that if no arguments were provided)
if (args.empty())
return;
if (args.empty()) return;
std::vector<std::pair<SubCommand, std::vector<std::string>>> subCommands;
@@ -78,18 +76,18 @@ namespace hex::subcommands {
}
// Save last command to run
if (currentSubCommand.has_value()) {
if (currentSubCommand) {
subCommands.emplace_back(*currentSubCommand, currentSubCommandArgs);
}
// Run the subcommands
for (auto &[subcommand, args] : subCommands) {
subcommand.callback(args);
for (auto& subCommandPair : subCommands) {
subCommandPair.first.callback(subCommandPair.second);
}
// Exit the process if it's not the main instance (the commands have been forwarded to another instance)
// Exit the process if its not the main instance (the commands have been forwarded to another instance)
if (!ImHexApi::System::isMainInstance()) {
std::exit(0);
exit(0);
}
}
@@ -97,15 +95,12 @@ namespace hex::subcommands {
log::debug("Forwarding subcommand {} (maybe to us)", cmdName);
std::vector<u8> data;
if (!args.empty()) {
for (const auto &arg: args) {
data.insert(data.end(), arg.begin(), arg.end());
data.push_back('\0');
}
data.pop_back();
for (const auto &arg: args) {
data.insert(data.end(), arg.begin(), arg.end());
data.push_back('\0');
}
data.erase(data.end()-1);
SendMessageToMainInstance::post(hex::format("command/{}", cmdName), data);
}
@@ -117,8 +112,8 @@ namespace hex::subcommands {
std::vector<std::string> args;
for (const auto &argument : std::views::split(string, char(0x00))) {
std::string arg(argument.data(), argument.size());
for (const auto &arg_view : std::views::split(string, char(0x00))) {
std::string arg(arg_view.data(), arg_view.size());
args.push_back(arg);
}

View File

@@ -1,23 +0,0 @@
#include <hex/test/tests.hpp>
namespace hex::test {
std::map<std::string, Test> Tests::s_tests;
bool initPluginImpl(std::string name) {
if (name != "Built-in") {
if(!initPluginImpl("Built-in")) return false;
}
hex::Plugin *plugin = hex::PluginManager::getPlugin(name);
if (plugin == nullptr) {
hex::log::fatal("Plugin '{}' was not found !", name);
return false;
}else if (!plugin->initializePlugin()) {
hex::log::fatal("Failed to initialize plugin '{}' !", name);
return false;
}
hex::log::info("Initialized plugin '{}' successfully", name);
return true;
}
}

View File

@@ -4,7 +4,6 @@
#include <imgui_internal.h>
#include <implot.h>
#include <implot_internal.h>
#include <cimgui.h>
#include <opengl_support.h>
#undef IMGUI_DEFINE_MATH_OPERATORS
@@ -12,17 +11,14 @@
#define STB_IMAGE_IMPLEMENTATION
#include <stb_image.h>
#include <lunasvg.h>
#include <set>
#include <string>
#include <algorithm>
#include <hex/api/imhex_api.hpp>
#include <hex/api/task_manager.hpp>
#include <hex/api/theme_manager.hpp>
#include <hex/helpers/logger.hpp>
namespace ImGuiExt {
@@ -31,32 +27,6 @@ namespace ImGuiExt {
namespace {
bool isOpenGLExtensionSupported(const char *name) {
static std::set<std::string> extensions;
if (extensions.empty()) {
GLint extensionCount = 0;
glGetIntegerv(GL_NUM_EXTENSIONS, &extensionCount);
for (GLint i = 0; i < extensionCount; i++) {
std::string extension = reinterpret_cast<const char*>(glGetStringi(GL_EXTENSIONS, i));
extensions.emplace(std::move(extension));
}
}
return extensions.contains(name);
}
bool isOpenGLVersionAtLeast(u8 major, u8 minor) {
static GLint actualMajor = 0, actualMinor = 0;
if (actualMajor == 0 || actualMinor == 0) {
glGetIntegerv(GL_MAJOR_VERSION, &actualMajor);
glGetIntegerv(GL_MINOR_VERSION, &actualMinor);
}
return actualMajor > major || (actualMajor == major && actualMinor >= minor);
}
constexpr auto getGLFilter(Texture::Filter filter) {
switch (filter) {
using enum Texture::Filter;
@@ -69,189 +39,74 @@ namespace ImGuiExt {
return GL_NEAREST;
}
[[maybe_unused]] GLint getMaxSamples(GLenum target, GLenum format) {
GLint maxSamples;
glGetInternalformativ(target, format, GL_SAMPLES, 1, &maxSamples);
return maxSamples;
}
GLuint createTextureFromRGBA8Array(const ImU8 *buffer, int width, int height, Texture::Filter filter) {
GLuint texture;
// Generate texture
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, getGLFilter(filter));
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, getGLFilter(filter));
#if defined(GL_UNPACK_ROW_LENGTH)
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
#endif
// Allocate storage for the texture
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
return texture;
}
GLuint createMultisampleTextureFromRGBA8Array(const ImU8 *buffer, int width, int height, Texture::Filter filter) {
// Create a regular texture from the RGBA8 array
GLuint texture = createTextureFromRGBA8Array(buffer, width, height, filter);
if (filter == Texture::Filter::Nearest) {
return texture;
}
if (!isOpenGLVersionAtLeast(3,2)) {
return texture;
}
if (!isOpenGLExtensionSupported("GL_ARB_texture_multisample")) {
return texture;
}
#if defined(GL_TEXTURE_2D_MULTISAMPLE)
static const auto sampleCount = std::min(static_cast<GLint>(8), getMaxSamples(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8));
// Generate renderbuffer
GLuint renderbuffer;
glGenRenderbuffers(1, &renderbuffer);
glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer);
glRenderbufferStorageMultisample(GL_RENDERBUFFER, sampleCount, GL_DEPTH24_STENCIL8, width, height);
// Generate framebuffer
GLuint framebuffer;
glGenFramebuffers(1, &framebuffer);
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
// Unbind framebuffer on exit
ON_SCOPE_EXIT {
glBindFramebuffer(GL_FRAMEBUFFER, 0);
};
// Attach texture to color attachment 0
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, texture, 0);
// Attach renderbuffer to depth-stencil attachment
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, renderbuffer);
// Check framebuffer status
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
hex::log::error("Driver claims to support texture multisampling but it's not working");
return texture;
}
#endif
return texture;
}
}
Texture Texture::fromImage(const ImU8 *buffer, int size, Filter filter) {
Texture::Texture(const ImU8 *buffer, int size, Filter filter, int width, int height) {
if (size == 0)
return {};
return;
unsigned char *imageData = nullptr;
Texture result;
imageData = stbi_load_from_memory(buffer, size, &result.m_width, &result.m_height, nullptr, 4);
if (width == 0 || height == 0)
imageData = stbi_load_from_memory(buffer, size, &m_width, &m_height, nullptr, 4);
if (imageData == nullptr) {
if (width * height * 4 > size)
return;
imageData = static_cast<unsigned char *>(STBI_MALLOC(size));
std::memcpy(imageData, buffer, size);
m_width = width;
m_height = height;
}
if (imageData == nullptr)
return {};
return;
GLuint texture = createMultisampleTextureFromRGBA8Array(imageData, result.m_width, result.m_height, filter);
GLuint texture;
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, getGLFilter(filter));
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, getGLFilter(filter));
#if defined(GL_UNPACK_ROW_LENGTH)
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
#endif
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_width, m_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, imageData);
STBI_FREE(imageData);
result.m_textureId = reinterpret_cast<ImTextureID>(static_cast<intptr_t>(texture));
return result;
m_textureId = reinterpret_cast<ImTextureID>(static_cast<intptr_t>(texture));
}
Texture Texture::fromImage(std::span<const std::byte> buffer, Filter filter) {
return Texture::fromImage(reinterpret_cast<const ImU8*>(buffer.data()), buffer.size(), filter);
}
Texture::Texture(std::span<const std::byte> bytes, Filter filter, int width, int height) : Texture(reinterpret_cast<const ImU8*>(bytes.data()), bytes.size(), filter, width, height) { }
Texture::Texture(const std::fs::path &path, Filter filter) : Texture(reinterpret_cast<const char *>(path.u8string().c_str()), filter) { }
Texture Texture::fromImage(const std::fs::path &path, Filter filter) {
return Texture::fromImage(wolv::util::toUTF8String(path).c_str(), filter);
}
Texture Texture::fromImage(const char *path, Filter filter) {
Texture result;
unsigned char *imageData = stbi_load(path, &result.m_width, &result.m_height, nullptr, 4);
Texture::Texture(const char *path, Filter filter) {
unsigned char *imageData = stbi_load(path, &m_width, &m_height, nullptr, 4);
if (imageData == nullptr)
return {};
return;
GLuint texture = createMultisampleTextureFromRGBA8Array(imageData, result.m_width, result.m_height, filter);
GLuint texture;
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, getGLFilter(filter));
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, getGLFilter(filter));
#if defined(GL_UNPACK_ROW_LENGTH)
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
#endif
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_width, m_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, imageData);
STBI_FREE(imageData);
result.m_textureId = reinterpret_cast<ImTextureID>(static_cast<intptr_t>(texture));
return result;
m_textureId = reinterpret_cast<ImTextureID>(static_cast<intptr_t>(texture));
}
Texture Texture::fromGLTexture(unsigned int glTexture, int width, int height) {
Texture texture;
texture.m_textureId = reinterpret_cast<ImTextureID>(static_cast<intptr_t>(glTexture));
texture.m_width = width;
texture.m_height = height;
Texture::Texture(unsigned int texture, int width, int height) : m_textureId(reinterpret_cast<ImTextureID>(static_cast<intptr_t>(texture))), m_width(width), m_height(height) {
return texture;
}
Texture Texture::fromBitmap(std::span<const std::byte> buffer, int width, int height, Filter filter) {
return Texture::fromBitmap(reinterpret_cast<const ImU8*>(buffer.data()), buffer.size(), width, height, filter);
}
Texture Texture::fromBitmap(const ImU8 *buffer, int size, int width, int height, Filter filter) {
if (width * height * 4 > size)
return {};
GLuint texture = createMultisampleTextureFromRGBA8Array(buffer, width, height, filter);
Texture result;
result.m_width = width;
result.m_height = height;
result.m_textureId = reinterpret_cast<ImTextureID>(static_cast<intptr_t>(texture));
return result;
}
Texture Texture::fromSVG(const char *path, int width, int height, Filter filter) {
auto document = lunasvg::Document::loadFromFile(path);
auto bitmap = document->renderToBitmap(width, height);
auto texture = createMultisampleTextureFromRGBA8Array(bitmap.data(), bitmap.width(), bitmap.height(), filter);
Texture result;
result.m_width = bitmap.width();
result.m_height = bitmap.height();
result.m_textureId = reinterpret_cast<ImTextureID>(static_cast<intptr_t>(texture));
return result;
}
Texture Texture::fromSVG(const std::fs::path &path, int width, int height, Filter filter) {
return Texture::fromSVG(wolv::util::toUTF8String(path).c_str(), width, height, filter);
}
Texture Texture::fromSVG(std::span<const std::byte> buffer, int width, int height, Filter filter) {
auto document = lunasvg::Document::loadFromData(reinterpret_cast<const char*>(buffer.data()), buffer.size());
auto bitmap = document->renderToBitmap(width, height);
bitmap.convertToRGBA();
auto texture = createMultisampleTextureFromRGBA8Array(bitmap.data(), bitmap.width(), bitmap.height(), filter);
Texture result;
result.m_width = bitmap.width();
result.m_height = bitmap.height();
result.m_textureId = reinterpret_cast<ImTextureID>(static_cast<intptr_t>(texture));
return result;
}
Texture::Texture(Texture&& other) noexcept {
@@ -282,11 +137,8 @@ namespace ImGuiExt {
if (m_textureId == nullptr)
return;
glDeleteTextures(1, reinterpret_cast<GLuint*>(&m_textureId));
}
float GetTextWrapPos() {
return GImGui->CurrentWindow->DC.TextWrapPos;
auto glTextureId = static_cast<GLuint>(reinterpret_cast<intptr_t>(m_textureId));
glDeleteTextures(1, &glTextureId);
}
int UpdateStringSizeCallback(ImGuiInputTextCallbackData *data) {
@@ -327,10 +179,7 @@ namespace ImGuiExt {
PushStyleColor(ImGuiCol_Text, ImU32(col));
Text("%s %s", icon, label);
if (hovered)
GetWindowDrawList()->AddLine(ImVec2(pos.x, pos.y + size.y), pos + size, ImU32(col));
GetWindowDrawList()->AddLine(ImVec2(pos.x, pos.y + size.y), pos + size, ImU32(col));
PopStyleColor();
IMGUI_TEST_ENGINE_ITEM_INFO(id, label, g.LastItemData.StatusFlags);
@@ -359,10 +208,7 @@ namespace ImGuiExt {
const ImU32 col = hovered ? GetColorU32(ImGuiCol_ButtonHovered) : GetColorU32(ImGuiCol_ButtonActive);
PushStyleColor(ImGuiCol_Text, ImU32(col));
TextEx(label, nullptr, ImGuiTextFlags_NoWidthForLargeClippedText); // Skip formatting
if (hovered)
GetWindowDrawList()->AddLine(ImVec2(pos.x, pos.y + size.y), pos + size, ImU32(col));
GetWindowDrawList()->AddLine(ImVec2(pos.x, pos.y + size.y), pos + size, ImU32(col));
PopStyleColor();
IMGUI_TEST_ENGINE_ITEM_INFO(id, label, g.LastItemData.StatusFlags);
@@ -514,25 +360,26 @@ namespace ImGuiExt {
return pressed;
}
void HelpHover(const char *text, const char *icon, ImU32 iconColor) {
void HelpHover(const char *text) {
const auto iconColor = GetStyleColorVec4(ImGuiCol_ButtonActive);
PushStyleColor(ImGuiCol_Button, ImVec4(0, 0, 0, 0));
PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(0, 0, 0, 0));
PushStyleColor(ImGuiCol_ButtonActive, ImVec4(0, 0, 0, 0));
PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0, 0));
PushStyleVar(ImGuiStyleVar_FrameBorderSize, 0.0F);
PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0, GetStyle().FramePadding.y));
PushStyleColor(ImGuiCol_Text, iconColor);
Button(icon);
Button("(?)");
PopStyleColor();
if (IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled)) {
SetNextWindowSizeConstraints(ImVec2(GetTextLineHeight() * 25, 0), ImVec2(GetTextLineHeight() * 35, FLT_MAX));
SetNextWindowSizeConstraints(ImVec2(GetTextLineHeight() * 25, 0), ImVec2(GetTextLineHeight() * 25, FLT_MAX));
BeginTooltip();
TextFormattedWrapped("{}", text);
EndTooltip();
}
PopStyleVar(2);
PopStyleVar();
PopStyleColor(3);
}
@@ -575,30 +422,14 @@ namespace ImGuiExt {
ImGuiID hoveredID = GetHoveredID();
bool result = false;
if (IsItemHovered(ImGuiHoveredFlags_DelayNormal) && (currTime - lastMoveTime) >= 0.5 && hoveredID == lastHoveredID) {
if (IsItemHovered() && (currTime - lastMoveTime) >= 0.5 && hoveredID == lastHoveredID) {
if (!std::string_view(text).empty()) {
const auto textWidth = CalcTextSize(text).x;
const auto maxWidth = 300 * hex::ImHexApi::System::getGlobalScale();
const bool wrapping = textWidth > maxWidth;
if (wrapping)
ImGui::SetNextWindowSizeConstraints(ImVec2(maxWidth, 0), ImVec2(maxWidth, FLT_MAX));
BeginTooltip();
if (isSeparator)
SeparatorText(text);
else
ImGui::SetNextWindowSize(ImVec2(textWidth + GetStyle().WindowPadding.x * 2, 0));
if (BeginTooltip()) {
if (isSeparator)
SeparatorText(text);
else {
if (wrapping)
TextFormattedWrapped("{}", text);
else
TextFormatted("{}", text);
}
EndTooltip();
}
TextUnformatted(text);
EndTooltip();
}
result = true;
@@ -743,7 +574,7 @@ namespace ImGuiExt {
const ImU32 col = GetColorU32((held && hovered) ? ImGuiCol_ButtonActive : hovered ? ImGuiCol_ButtonHovered
: ImGuiCol_Button);
RenderNavHighlight(bb, id);
RenderFrame(bb.Min, bb.Max, col, false, style.FrameRounding);
RenderFrame(bb.Min, bb.Max, col, true, style.FrameRounding);
RenderTextClipped(bb.Min + style.FramePadding, bb.Max - style.FramePadding, label, nullptr, &label_size, style.ButtonTextAlign, &bb);
// Automatically close popups
@@ -768,9 +599,7 @@ namespace ImGuiExt {
ImVec2 pos = window->DC.CursorPos;
ImVec2 size = CalcItemSize(ImVec2(1, 1) * GetCurrentWindow()->MenuBarHeight, label_size.x + style.FramePadding.x * 2.0F, label_size.y + style.FramePadding.y * 2.0F);
ImVec2 padding = (size - label_size) / 2;
ImVec2 size = CalcItemSize(ImVec2(1, 1) * GetCurrentWindow()->MenuBarHeight(), label_size.x + style.FramePadding.x * 2.0F, label_size.y + style.FramePadding.y * 2.0F);
const ImRect bb(pos, pos + size);
ItemSize(size, style.FramePadding.y);
@@ -787,7 +616,7 @@ namespace ImGuiExt {
: ImGuiCol_MenuBarBg);
RenderNavHighlight(bb, id);
RenderFrame(bb.Min, bb.Max, col, false, style.FrameRounding);
RenderTextClipped(bb.Min + padding, bb.Max - padding, symbol, nullptr, &size, style.ButtonTextAlign, &bb);
RenderTextClipped(bb.Min + style.FramePadding, bb.Max - style.FramePadding, symbol, nullptr, &label_size, style.ButtonTextAlign, &bb);
PopStyleColor();
@@ -850,13 +679,20 @@ namespace ImGuiExt {
const ImVec2 label_size = CalcTextSize(label, nullptr, true);
const ImVec2 frame_size = CalcItemSize(ImVec2(0, 0), CalcTextSize(prefix).x, label_size.y + style.FramePadding.y * 2.0F);
const ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(CalcItemWidth(), frame_size.y));
const ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + frame_size);
SetCursorPosX(GetCursorPosX() + frame_size.x);
char buf[64];
DataTypeFormatString(buf, IM_ARRAYSIZE(buf), type, value, format);
bool value_changed = false;
if (InputTextEx(label, nullptr, buf, IM_ARRAYSIZE(buf), ImVec2(CalcItemWidth() - frame_size.x, label_size.y + style.FramePadding.y * 2.0F), flags))
value_changed = DataTypeApplyFromText(buf, type, value, format);
if (value_changed)
MarkItemEdited(GImGui->LastItemData.ID);
RenderNavHighlight(frame_bb, id);
RenderFrame(frame_bb.Min, frame_bb.Max, GetColorU32(ImGuiCol_FrameBg), true, style.FrameRounding);
@@ -864,19 +700,6 @@ namespace ImGuiExt {
RenderText(ImVec2(frame_bb.Min.x + style.FramePadding.x, frame_bb.Min.y + style.FramePadding.y), prefix);
PopStyleVar();
bool value_changed = false;
PushStyleVar(ImGuiStyleVar_FrameBorderSize, 0);
PushStyleColor(ImGuiCol_FrameBg, 0x00000000);
PushStyleColor(ImGuiCol_FrameBgHovered, 0x00000000);
PushStyleColor(ImGuiCol_FrameBgActive, 0x00000000);
if (InputTextEx(label, nullptr, buf, IM_ARRAYSIZE(buf), ImVec2(CalcItemWidth() - frame_size.x, label_size.y + style.FramePadding.y * 2.0F), flags))
value_changed = DataTypeApplyFromText(buf, type, value, format);
PopStyleColor(3);
PopStyleVar();
if (value_changed)
MarkItemEdited(GImGui->LastItemData.ID);
return value_changed;
}
@@ -888,21 +711,6 @@ namespace ImGuiExt {
return InputIntegerPrefix(label, "0x", value, ImGuiDataType_U64, "%llX", flags | ImGuiInputTextFlags_CharsHexadecimal);
}
bool SliderBytes(const char *label, u64 *value, u64 min, u64 max, ImGuiSliderFlags flags) {
std::string format;
if (*value < 1024) {
format = hex::format("{} Bytes", *value);
} else if (*value < 1024 * 1024) {
format = hex::format("{:.2f} KB", *value / 1024.0);
} else if (*value < 1024 * 1024 * 1024) {
format = hex::format("{:.2f} MB", *value / (1024.0 * 1024.0));
} else {
format = hex::format("{:.2f} GB", *value / (1024.0 * 1024.0 * 1024.0));
}
return ImGui::SliderScalar(label, ImGuiDataType_U64, value, &min, &max, format.c_str(), flags | ImGuiSliderFlags_Logarithmic);
}
void SmallProgressBar(float fraction, float yOffset) {
ImGuiWindow *window = GetCurrentWindow();
if (window->SkipItems)
@@ -1174,37 +982,17 @@ namespace ImGuiExt {
PopStyleVar();
}
bool BeginSubWindow(const char *label, bool *collapsed, ImVec2 size, ImGuiChildFlags flags) {
void BeginSubWindow(const char *label, ImVec2 size, ImGuiChildFlags flags) {
const bool hasMenuBar = !std::string_view(label).empty();
bool result = false;
ImGui::PushStyleVar(ImGuiStyleVar_ChildRounding, 5.0F);
if (ImGui::BeginChild(hex::format("{}##SubWindow", label).c_str(), size, ImGuiChildFlags_Border | ImGuiChildFlags_AutoResizeY | flags, hasMenuBar ? ImGuiWindowFlags_MenuBar : ImGuiWindowFlags_None)) {
result = true;
if (hasMenuBar && ImGui::BeginMenuBar()) {
if (collapsed == nullptr)
ImGui::TextUnformatted(label);
else {
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0, ImGui::GetStyle().FramePadding.y));
ImGui::PushStyleColor(ImGuiCol_Button, 0x00);
if (ImGui::Button(label))
*collapsed = !*collapsed;
ImGui::PopStyleColor();
ImGui::PopStyleVar();
}
ImGui::TextUnformatted(label);
ImGui::EndMenuBar();
}
if (collapsed != nullptr && *collapsed) {
ImGui::SetCursorPosY(ImGui::GetCursorPosY() - (ImGui::GetStyle().FramePadding.y * 2));
ImGuiExt::TextFormattedDisabled("...");
result = false;
}
}
ImGui::PopStyleVar();
return result;
}
void EndSubWindow() {
@@ -1285,9 +1073,9 @@ namespace ImGuiExt {
window->DrawList->AddRectFilled(knob_bb.Min, knob_bb.Max, GetColorU32(held ? ImGuiCol_ButtonActive : hovered ? ImGuiCol_ButtonHovered : *v ? ImGuiCol_ButtonActive : ImGuiCol_Button), size.y / 2);
if (*v)
window->DrawList->AddCircleFilled(knob_bb.Max - ImVec2(size.y / 2, size.y / 2), (size.y - style.ItemInnerSpacing.y) / 2, GetColorU32(ImGuiCol_ScrollbarGrabActive), 16);
window->DrawList->AddCircleFilled(knob_bb.Max - ImVec2(size.y / 2, size.y / 2), (size.y - style.ItemInnerSpacing.y) / 2, GetColorU32(ImGuiCol_Text), 16);
else
window->DrawList->AddCircleFilled(knob_bb.Min + ImVec2(size.y / 2, size.y / 2), (size.y - style.ItemInnerSpacing.y) / 2, GetColorU32(ImGuiCol_ScrollbarGrabActive), 16);
window->DrawList->AddCircleFilled(knob_bb.Min + ImVec2(size.y / 2, size.y / 2), (size.y - style.ItemInnerSpacing.y) / 2, GetColorU32(ImGuiCol_Text), 16);
ImVec2 label_pos = ImVec2(knob_bb.Max.x + style.ItemInnerSpacing.x, knob_bb.Min.y + style.FramePadding.y);
if (g.LogEnabled)
@@ -1303,59 +1091,6 @@ namespace ImGuiExt {
return ToggleSwitch(label, &v);
}
bool PopupTitleBarButton(const char* label, bool p_enabled)
{
ImGuiContext& g = *GImGui;
ImGuiWindow* window = g.CurrentWindow;
const ImGuiID id = window->GetID(label);
const ImRect title_rect = window->TitleBarRect();
const ImVec2 size(g.FontSize, g.FontSize); // Button size matches font size for aesthetic consistency.
const ImVec2 pos = window->DC.CursorPos;
const ImVec2 max_pos = pos + size;
const ImRect bb(pos.x, title_rect.Min.y, max_pos.x, title_rect.Max.y);
ImGui::PushClipRect(title_rect.Min, title_rect.Max, false);
// Check for item addition (similar to how clipping is handled in the original button functions).
bool is_clipped = !ItemAdd(bb, id);
bool hovered, held;
bool pressed = ButtonBehavior(bb, id, &hovered, &held, ImGuiButtonFlags_None);
if (is_clipped)
{
ImGui::PopClipRect();
return pressed;
}
// const ImU32 bg_col = GetColorU32((held && hovered) ? ImGuiCol_ButtonActive : hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button);
// window->DrawList->AddCircleFilled(bb.GetCenter(), ImMax(2.0f, g.FontSize * 0.5f + 1.0f), bg_col);
// Draw the label in the center
ImU32 text_col = GetColorU32(p_enabled || hovered ? ImGuiCol_Text : ImGuiCol_TextDisabled);
window->DrawList->AddText(bb.GetCenter() - ImVec2(g.FontSize * 0.45F, g.FontSize * 0.5F), text_col, label);
// Return the button press state
ImGui::PopClipRect();
return pressed;
}
void PopupTitleBarText(const char* text) {
ImGuiContext& g = *GImGui;
ImGuiWindow* window = g.CurrentWindow;
const ImRect title_rect = window->TitleBarRect();
const ImVec2 size(g.FontSize, g.FontSize); // Button size matches font size for aesthetic consistency.
const ImVec2 pos = window->DC.CursorPos;
const ImVec2 max_pos = pos + size;
const ImRect bb(pos.x, title_rect.Min.y, max_pos.x, title_rect.Max.y);
ImGui::PushClipRect(title_rect.Min, title_rect.Max, false);
// Draw the label in the center
ImU32 text_col = GetColorU32(ImGuiCol_Text);
window->DrawList->AddText(bb.GetCenter() - ImVec2(g.FontSize * 0.45F, g.FontSize * 0.5F), text_col, text);
// Return the button press state
ImGui::PopClipRect();
}
}
namespace ImGui {
@@ -1376,4 +1111,4 @@ namespace ImGui {
return ImGui::InputTextWithHint(label, hint, buffer.data(), buffer.size() + 1, ImGuiInputTextFlags_CallbackResize | flags, ImGuiExt::UpdateStringSizeCallback, &buffer);
}
}
}

View File

@@ -71,7 +71,7 @@ namespace hex {
}
std::string View::toWindowName(const UnlocalizedString &unlocalizedName) {
return fmt::format("{}###{}", Lang(unlocalizedName), unlocalizedName.get());
return Lang(unlocalizedName) + "###" + unlocalizedName.get();
}
}

View File

@@ -1,3 +0,0 @@
project(boost)
add_subdirectory(regex)

View File

@@ -1,10 +0,0 @@
project(boost-regex)
add_library(boost-regex INTERFACE)
target_include_directories(boost-regex INTERFACE
include
)
target_compile_definitions(boost-regex INTERFACE BOOST_REGEX_STANDALONE)
add_library(boost::regex ALIAS boost-regex)

View File

@@ -1,43 +0,0 @@
/*
*
* Copyright (c) 1998-2002
* John Maddock
*
* Use, modification and distribution are subject to the
* Boost Software License, Version 1.0. (See accompanying file
* LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
*
*/
/*
* LOCATION: see http://www.boost.org/libs/regex for most recent version.
* FILE cregex.cpp
* VERSION see <boost/version.hpp>
* DESCRIPTION: Declares POSIX API functions
* + boost::RegEx high level wrapper.
*/
#ifndef BOOST_RE_CREGEX_HPP
#define BOOST_RE_CREGEX_HPP
#ifndef BOOST_REGEX_CONFIG_HPP
#include <boost/regex/config.hpp>
#endif
#ifdef BOOST_REGEX_CXX03
#include <boost/regex/v4/cregex.hpp>
#else
#include <boost/regex/v5/cregex.hpp>
#endif
#endif /* include guard */

View File

@@ -1,100 +0,0 @@
/*
*
* Copyright (c) 1998-2000
* Dr John Maddock
*
* Use, modification and distribution are subject to the
* Boost Software License, Version 1.0. (See accompanying file
* LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
*
*/
/*
* LOCATION: see http://www.boost.org/libs/regex for documentation.
* FILE regex.h
* VERSION 3.12
* DESCRIPTION: Declares POSIX API functions
*/
#ifndef BOOST_RE_REGEX_H
#define BOOST_RE_REGEX_H
#include <boost/cregex.hpp>
/*
* add using declarations to bring POSIX API functions into
* global scope, only if this is C++ (and not C).
*/
#ifdef __cplusplus
using boost::regoff_t;
using boost::regex_tA;
using boost::regmatch_t;
using boost::REG_BASIC;
using boost::REG_EXTENDED;
using boost::REG_ICASE;
using boost::REG_NOSUB;
using boost::REG_NEWLINE;
using boost::REG_NOSPEC;
using boost::REG_PEND;
using boost::REG_DUMP;
using boost::REG_NOCOLLATE;
using boost::REG_ESCAPE_IN_LISTS;
using boost::REG_NEWLINE_ALT;
using boost::REG_PERL;
using boost::REG_AWK;
using boost::REG_GREP;
using boost::REG_EGREP;
using boost::REG_ASSERT;
using boost::REG_INVARG;
using boost::REG_ATOI;
using boost::REG_ITOA;
using boost::REG_NOTBOL;
using boost::REG_NOTEOL;
using boost::REG_STARTEND;
using boost::reg_comp_flags;
using boost::reg_exec_flags;
using boost::regcompA;
using boost::regerrorA;
using boost::regexecA;
using boost::regfreeA;
#ifndef BOOST_NO_WREGEX
using boost::regcompW;
using boost::regerrorW;
using boost::regexecW;
using boost::regfreeW;
using boost::regex_tW;
#endif
using boost::REG_NOERROR;
using boost::REG_NOMATCH;
using boost::REG_BADPAT;
using boost::REG_ECOLLATE;
using boost::REG_ECTYPE;
using boost::REG_EESCAPE;
using boost::REG_ESUBREG;
using boost::REG_EBRACK;
using boost::REG_EPAREN;
using boost::REG_EBRACE;
using boost::REG_BADBR;
using boost::REG_ERANGE;
using boost::REG_ESPACE;
using boost::REG_BADRPT;
using boost::REG_EEND;
using boost::REG_ESIZE;
using boost::REG_ERPAREN;
using boost::REG_EMPTY;
using boost::REG_E_MEMORY;
using boost::REG_E_UNKNOWN;
using boost::reg_errcode_t;
#endif /* __cplusplus */
#endif /* BOOST_RE_REGEX_H */

View File

@@ -1,41 +0,0 @@
/*
*
* Copyright (c) 1998-2002
* John Maddock
*
* Use, modification and distribution are subject to the
* Boost Software License, Version 1.0. (See accompanying file
* LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
*
*/
/*
* LOCATION: see http://www.boost.org/libs/regex for documentation.
* FILE regex.cpp
* VERSION see <boost/version.hpp>
* DESCRIPTION: Declares boost::basic_regex<> and associated
* functions and classes. This header is the main
* entry point for the template regex code.
*/
/* start with C compatibility API */
#ifndef BOOST_RE_REGEX_HPP
#define BOOST_RE_REGEX_HPP
#ifndef BOOST_REGEX_CONFIG_HPP
#include <boost/regex/config.hpp>
#endif
#ifdef BOOST_REGEX_CXX03
#include <boost/regex/v4/regex.hpp>
#else
#include <boost/regex/v5/regex.hpp>
#endif
#endif // include

File diff suppressed because it is too large Load Diff

View File

@@ -1,480 +0,0 @@
/*
*
* Copyright (c) 1998-2002
* John Maddock
*
* Use, modification and distribution are subject to the
* Boost Software License, Version 1.0. (See accompanying file
* LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
*
*/
/*
* LOCATION: see http://www.boost.org for most recent version.
* FILE config.hpp
* VERSION see <boost/version.hpp>
* DESCRIPTION: regex extended config setup.
*/
#ifndef BOOST_REGEX_CONFIG_HPP
#define BOOST_REGEX_CONFIG_HPP
#if !((__cplusplus >= 201103L) || (defined(_MSC_VER) && (_MSC_VER >= 1600)) || defined(BOOST_REGEX_CXX03))
# define BOOST_REGEX_CXX03
#endif
#if defined(BOOST_REGEX_RECURSIVE) && !defined(BOOST_REGEX_CXX03)
# define BOOST_REGEX_CXX03
#endif
#if defined(__has_include)
#if !defined(BOOST_REGEX_STANDALONE) && !__has_include(<boost/version.hpp>)
#define BOOST_REGEX_STANDALONE
#endif
#endif
/*
* Borland C++ Fix/error check
* this has to go *before* we include any std lib headers:
*/
#if defined(__BORLANDC__) && !defined(__clang__)
# include <boost/regex/config/borland.hpp>
#endif
#ifndef BOOST_REGEX_STANDALONE
#include <boost/version.hpp>
#endif
/*************************************************************************
*
* Asserts:
*
*************************************************************************/
#ifdef BOOST_REGEX_STANDALONE
#include <cassert>
# define BOOST_REGEX_ASSERT(x) assert(x)
#else
#include <boost/assert.hpp>
# define BOOST_REGEX_ASSERT(x) BOOST_ASSERT(x)
#endif
/*****************************************************************************
*
* Include all the headers we need here:
*
****************************************************************************/
#ifdef __cplusplus
# ifndef BOOST_REGEX_USER_CONFIG
# define BOOST_REGEX_USER_CONFIG <boost/regex/user.hpp>
# endif
# include BOOST_REGEX_USER_CONFIG
#ifndef BOOST_REGEX_STANDALONE
# include <boost/config.hpp>
# include <boost/predef.h>
#endif
#else
/*
* C build,
* don't include <boost/config.hpp> because that may
* do C++ specific things in future...
*/
# include <stdlib.h>
# include <stddef.h>
# ifdef _MSC_VER
# define BOOST_MSVC _MSC_VER
# endif
#endif
/****************************************************************************
*
* Legacy support:
*
*******************************************************************************/
#if defined(BOOST_NO_STD_LOCALE) || defined(BOOST_NO_CXX11_HDR_MUTEX) || defined(BOOST_NO_CXX11_HDR_TYPE_TRAITS) \
|| defined(BOOST_NO_CXX11_HDR_ATOMIC) || defined(BOOST_NO_CXX11_ALLOCATOR) || defined(BOOST_NO_CXX11_SMART_PTR) \
|| defined(BOOST_NO_CXX11_STATIC_ASSERT) || defined(BOOST_NO_NOEXCEPT)
#ifndef BOOST_REGEX_CXX03
# define BOOST_REGEX_CXX03
#endif
#endif
/*****************************************************************************
*
* Boilerplate regex config options:
*
****************************************************************************/
/* Obsolete macro, use BOOST_VERSION instead: */
#define BOOST_RE_VERSION 500
/* fix: */
#if defined(_UNICODE) && !defined(UNICODE)
#define UNICODE
#endif
#define BOOST_REGEX_JOIN(X, Y) BOOST_REGEX_DO_JOIN(X, Y)
#define BOOST_REGEX_DO_JOIN(X, Y) BOOST_REGEX_DO_JOIN2(X,Y)
#define BOOST_REGEX_DO_JOIN2(X, Y) X##Y
#ifdef BOOST_FALLTHROUGH
# define BOOST_REGEX_FALLTHROUGH BOOST_FALLTHROUGH
#else
#if defined(__clang__) && (__cplusplus >= 201103L) && defined(__has_warning)
# if __has_feature(cxx_attributes) && __has_warning("-Wimplicit-fallthrough")
# define BOOST_REGEX_FALLTHROUGH [[clang::fallthrough]]
# endif
#endif
#if !defined(BOOST_REGEX_FALLTHROUGH) && defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 1800) && (__cplusplus >= 201703)
# define BOOST_REGEX_FALLTHROUGH [[fallthrough]]
#endif
#if !defined(BOOST_REGEX_FALLTHROUGH) && defined(__GNUC__) && (__GNUC__ >= 7)
# define BOOST_REGEX_FALLTHROUGH __attribute__((fallthrough))
#endif
#if !defined(BOOST_REGEX_FALLTHROUGH)
# define BOOST_REGEX_FALLTHROUGH
#endif
#endif
#ifdef BOOST_NORETURN
# define BOOST_REGEX_NORETURN BOOST_NORETURN
#else
# define BOOST_REGEX_NORETURN
#endif
/*
* Define a macro for the namespace that details are placed in, this includes the Boost
* version number to avoid mismatched header and library versions:
*/
#define BOOST_REGEX_DETAIL_NS BOOST_REGEX_JOIN(re_detail_, BOOST_RE_VERSION)
/*
* Fix for gcc prior to 3.4: std::ctype<wchar_t> doesn't allow
* masks to be combined, for example:
* std::use_facet<std::ctype<wchar_t> >.is(std::ctype_base::lower|std::ctype_base::upper, L'a');
* returns *false*.
*/
#if defined(__GLIBCPP__) && defined(BOOST_REGEX_CXX03)
# define BOOST_REGEX_BUGGY_CTYPE_FACET
#endif
/*
* If there isn't good enough wide character support then there will
* be no wide character regular expressions:
*/
#if (defined(BOOST_NO_CWCHAR) || defined(BOOST_NO_CWCTYPE) || defined(BOOST_NO_STD_WSTRING))
# if !defined(BOOST_NO_WREGEX)
# define BOOST_NO_WREGEX
# endif
#else
# if defined(__sgi) && (defined(__SGI_STL_PORT) || defined(_STLPORT_VERSION))
/* STLPort on IRIX is misconfigured: <cwctype> does not compile
* as a temporary fix include <wctype.h> instead and prevent inclusion
* of STLPort version of <cwctype> */
# include <wctype.h>
# define __STLPORT_CWCTYPE
# define _STLP_CWCTYPE
# endif
#if defined(__cplusplus) && defined(BOOST_REGEX_CXX03)
# include <boost/regex/config/cwchar.hpp>
#endif
#endif
/*
* If Win32 support has been disabled for boost in general, then
* it is for regex in particular:
*/
#if defined(BOOST_DISABLE_WIN32) && !defined(BOOST_REGEX_NO_W32)
# define BOOST_REGEX_NO_W32
#endif
/* disable our own file-iterators and mapfiles if we can't
* support them: */
#if defined(_WIN32)
# if defined(BOOST_REGEX_NO_W32) || BOOST_PLAT_WINDOWS_RUNTIME
# define BOOST_REGEX_NO_FILEITER
# endif
#else /* defined(_WIN32) */
# if !defined(BOOST_HAS_DIRENT_H)
# define BOOST_REGEX_NO_FILEITER
# endif
#endif
/* backwards compatibitity: */
#if defined(BOOST_RE_NO_LIB)
# define BOOST_REGEX_NO_LIB
#endif
#if defined(__GNUC__) && !defined(_MSC_VER) && (defined(_WIN32) || defined(__CYGWIN__))
/* gcc on win32 has problems if you include <windows.h>
(sporadically generates bad code). */
# define BOOST_REGEX_NO_W32
#endif
#if defined(__COMO__) && !defined(BOOST_REGEX_NO_W32) && !defined(_MSC_EXTENSIONS)
# define BOOST_REGEX_NO_W32
#endif
#ifdef BOOST_REGEX_STANDALONE
# if defined(_MSC_VER) && !defined(__clang__) && !defined(__GNUC__)
# define BOOST_REGEX_MSVC _MSC_VER
#endif
#elif defined(BOOST_MSVC)
# define BOOST_REGEX_MSVC BOOST_MSVC
#endif
/*****************************************************************************
*
* Set up dll import/export options:
*
****************************************************************************/
#if (defined(BOOST_REGEX_DYN_LINK) || defined(BOOST_ALL_DYN_LINK)) && !defined(BOOST_REGEX_STATIC_LINK) && defined(BOOST_SYMBOL_IMPORT)
# if defined(BOOST_REGEX_SOURCE)
# define BOOST_REGEX_BUILD_DLL
# define BOOST_REGEX_DECL BOOST_SYMBOL_EXPORT
# else
# define BOOST_REGEX_DECL BOOST_SYMBOL_IMPORT
# endif
#else
# define BOOST_REGEX_DECL
#endif
#ifdef BOOST_REGEX_CXX03
#if !defined(BOOST_REGEX_NO_LIB) && !defined(BOOST_REGEX_SOURCE) && !defined(BOOST_ALL_NO_LIB) && defined(__cplusplus)
# define BOOST_LIB_NAME boost_regex
# if defined(BOOST_REGEX_DYN_LINK) || defined(BOOST_ALL_DYN_LINK)
# define BOOST_DYN_LINK
# endif
# ifdef BOOST_REGEX_DIAG
# define BOOST_LIB_DIAGNOSTIC
# endif
# include <boost/config/auto_link.hpp>
#endif
#endif
/*****************************************************************************
*
* Set up function call type:
*
****************************************************************************/
#if defined(_MSC_VER) && defined(_MSC_EXTENSIONS)
#if defined(_DEBUG) || defined(__MSVC_RUNTIME_CHECKS) || defined(_MANAGED) || defined(BOOST_REGEX_NO_FASTCALL)
# define BOOST_REGEX_CALL __cdecl
#else
# define BOOST_REGEX_CALL __fastcall
#endif
# define BOOST_REGEX_CCALL __cdecl
#endif
#if defined(__BORLANDC__) && !defined(BOOST_DISABLE_WIN32)
#if defined(__clang__)
# define BOOST_REGEX_CALL __cdecl
# define BOOST_REGEX_CCALL __cdecl
#else
# define BOOST_REGEX_CALL __fastcall
# define BOOST_REGEX_CCALL __stdcall
#endif
#endif
#ifndef BOOST_REGEX_CALL
# define BOOST_REGEX_CALL
#endif
#ifndef BOOST_REGEX_CCALL
#define BOOST_REGEX_CCALL
#endif
/*****************************************************************************
*
* Set up localisation model:
*
****************************************************************************/
/* backwards compatibility: */
#ifdef BOOST_RE_LOCALE_C
# define BOOST_REGEX_USE_C_LOCALE
#endif
#ifdef BOOST_RE_LOCALE_CPP
# define BOOST_REGEX_USE_CPP_LOCALE
#endif
#if defined(__CYGWIN__)
# define BOOST_REGEX_USE_C_LOCALE
#endif
/* use C++ locale when targeting windows store */
#if BOOST_PLAT_WINDOWS_RUNTIME
# define BOOST_REGEX_USE_CPP_LOCALE
# define BOOST_REGEX_NO_WIN32_LOCALE
#endif
/* Win32 defaults to native Win32 locale: */
#if defined(_WIN32) && \
!defined(BOOST_REGEX_USE_WIN32_LOCALE) && \
!defined(BOOST_REGEX_USE_C_LOCALE) && \
!defined(BOOST_REGEX_USE_CPP_LOCALE) && \
!defined(BOOST_REGEX_NO_W32) && \
!defined(BOOST_REGEX_NO_WIN32_LOCALE)
# define BOOST_REGEX_USE_WIN32_LOCALE
#endif
/* otherwise use C++ locale if supported: */
#if !defined(BOOST_REGEX_USE_WIN32_LOCALE) && !defined(BOOST_REGEX_USE_C_LOCALE) && !defined(BOOST_REGEX_USE_CPP_LOCALE) && !defined(BOOST_NO_STD_LOCALE)
# define BOOST_REGEX_USE_CPP_LOCALE
#endif
/* otherwise use C locale: */
#if !defined(BOOST_REGEX_USE_WIN32_LOCALE) && !defined(BOOST_REGEX_USE_C_LOCALE) && !defined(BOOST_REGEX_USE_CPP_LOCALE)
# define BOOST_REGEX_USE_C_LOCALE
#endif
#ifndef BOOST_REGEX_MAX_STATE_COUNT
# define BOOST_REGEX_MAX_STATE_COUNT 100000000
#endif
/*****************************************************************************
*
* Error Handling for exception free compilers:
*
****************************************************************************/
#ifdef BOOST_NO_EXCEPTIONS
/*
* If there are no exceptions then we must report critical-errors
* the only way we know how; by terminating.
*/
#include <stdexcept>
#include <string>
#include <boost/throw_exception.hpp>
# define BOOST_REGEX_NOEH_ASSERT(x)\
if(0 == (x))\
{\
std::string s("Error: critical regex++ failure in: ");\
s.append(#x);\
std::runtime_error e(s);\
boost::throw_exception(e);\
}
#else
/*
* With exceptions then error handling is taken care of and
* there is no need for these checks:
*/
# define BOOST_REGEX_NOEH_ASSERT(x)
#endif
/*****************************************************************************
*
* Stack protection under MS Windows:
*
****************************************************************************/
#if !defined(BOOST_REGEX_NO_W32) && !defined(BOOST_REGEX_V3)
# if(defined(_WIN32) || defined(_WIN64) || defined(_WINCE)) \
&& !(defined(__GNUC__) || defined(__BORLANDC__) && defined(__clang__)) \
&& !(defined(__BORLANDC__) && (__BORLANDC__ >= 0x600)) \
&& !(defined(__MWERKS__) && (__MWERKS__ <= 0x3003))
# define BOOST_REGEX_HAS_MS_STACK_GUARD
# endif
#elif defined(BOOST_REGEX_HAS_MS_STACK_GUARD)
# undef BOOST_REGEX_HAS_MS_STACK_GUARD
#endif
#if defined(__cplusplus) && defined(BOOST_REGEX_HAS_MS_STACK_GUARD)
namespace boost{
namespace BOOST_REGEX_DETAIL_NS{
BOOST_REGEX_DECL void BOOST_REGEX_CALL reset_stack_guard_page();
}
}
#endif
/*****************************************************************************
*
* Algorithm selection and configuration.
* These options are now obsolete for C++11 and later (regex v5).
*
****************************************************************************/
#if !defined(BOOST_REGEX_RECURSIVE) && !defined(BOOST_REGEX_NON_RECURSIVE)
# if defined(BOOST_REGEX_HAS_MS_STACK_GUARD) && !defined(_STLP_DEBUG) && !defined(__STL_DEBUG) && !(defined(_MSC_VER) && (_MSC_VER >= 1400)) && defined(BOOST_REGEX_CXX03)
# define BOOST_REGEX_RECURSIVE
# else
# define BOOST_REGEX_NON_RECURSIVE
# endif
#endif
#ifdef BOOST_REGEX_NON_RECURSIVE
# ifdef BOOST_REGEX_RECURSIVE
# error "Can't set both BOOST_REGEX_RECURSIVE and BOOST_REGEX_NON_RECURSIVE"
# endif
# ifndef BOOST_REGEX_BLOCKSIZE
# define BOOST_REGEX_BLOCKSIZE 4096
# endif
# if BOOST_REGEX_BLOCKSIZE < 512
# error "BOOST_REGEX_BLOCKSIZE must be at least 512"
# endif
# ifndef BOOST_REGEX_MAX_BLOCKS
# define BOOST_REGEX_MAX_BLOCKS 1024
# endif
# ifdef BOOST_REGEX_HAS_MS_STACK_GUARD
# undef BOOST_REGEX_HAS_MS_STACK_GUARD
# endif
# ifndef BOOST_REGEX_MAX_CACHE_BLOCKS
# define BOOST_REGEX_MAX_CACHE_BLOCKS 16
# endif
#endif
/*****************************************************************************
*
* Diagnostics:
*
****************************************************************************/
#ifdef BOOST_REGEX_CONFIG_INFO
BOOST_REGEX_DECL void BOOST_REGEX_CALL print_regex_library_info();
#endif
#if defined(BOOST_REGEX_DIAG)
# pragma message ("BOOST_REGEX_DECL" BOOST_STRINGIZE(=BOOST_REGEX_DECL))
# pragma message ("BOOST_REGEX_CALL" BOOST_STRINGIZE(=BOOST_REGEX_CALL))
# pragma message ("BOOST_REGEX_CCALL" BOOST_STRINGIZE(=BOOST_REGEX_CCALL))
#ifdef BOOST_REGEX_USE_C_LOCALE
# pragma message ("Using C locale in regex traits class")
#elif BOOST_REGEX_USE_CPP_LOCALE
# pragma message ("Using C++ locale in regex traits class")
#else
# pragma message ("Using Win32 locale in regex traits class")
#endif
#if defined(BOOST_REGEX_DYN_LINK) || defined(BOOST_ALL_DYN_LINK)
# pragma message ("Dynamic linking enabled")
#endif
#if defined(BOOST_REGEX_NO_LIB) || defined(BOOST_ALL_NO_LIB)
# pragma message ("Auto-linking disabled")
#endif
#ifdef BOOST_REGEX_NO_EXTERNAL_TEMPLATES
# pragma message ("Extern templates disabled")
#endif
#endif
#endif

View File

@@ -1,72 +0,0 @@
/*
*
* Copyright (c) 1998-2002
* John Maddock
*
* Use, modification and distribution are subject to the
* Boost Software License, Version 1.0. (See accompanying file
* LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
*
*/
/*
* LOCATION: see http://www.boost.org for most recent version.
* FILE boost/regex/config/borland.hpp
* VERSION see <boost/version.hpp>
* DESCRIPTION: regex borland-specific config setup.
*/
#if defined(__BORLANDC__) && !defined(__clang__)
# if (__BORLANDC__ == 0x550) || (__BORLANDC__ == 0x551)
// problems with std::basic_string and dll RTL:
# if defined(_RTLDLL) && defined(_RWSTD_COMPILE_INSTANTIATE)
# ifdef BOOST_REGEX_BUILD_DLL
# error _RWSTD_COMPILE_INSTANTIATE must not be defined when building regex++ as a DLL
# else
# pragma message("Defining _RWSTD_COMPILE_INSTANTIATE when linking to the DLL version of the RTL may produce memory corruption problems in std::basic_string, as a result of separate versions of basic_string's static data in the RTL and you're exe/dll: be warned!!")
# endif
# endif
# ifndef _RTLDLL
// this is harmless for a staic link:
# define _RWSTD_COMPILE_INSTANTIATE
# endif
// external templates cause problems for some reason:
# define BOOST_REGEX_NO_EXTERNAL_TEMPLATES
# endif
# if (__BORLANDC__ <= 0x540) && !defined(BOOST_REGEX_NO_LIB) && !defined(_NO_VCL)
// C++ Builder 4 and earlier, we can't tell whether we should be using
// the VCL runtime or not, do a static link instead:
# define BOOST_REGEX_STATIC_LINK
# endif
//
// VCL support:
// if we're building a console app then there can't be any VCL (can there?)
# if !defined(__CONSOLE__) && !defined(_NO_VCL)
# define BOOST_REGEX_USE_VCL
# endif
//
// if this isn't Win32 then don't automatically select link
// libraries:
//
# ifndef _Windows
# ifndef BOOST_REGEX_NO_LIB
# define BOOST_REGEX_NO_LIB
# endif
# ifndef BOOST_REGEX_STATIC_LINK
# define BOOST_REGEX_STATIC_LINK
# endif
# endif
#if __BORLANDC__ < 0x600
//
// string workarounds:
//
#include <cstring>
#undef strcmp
#undef strcpy
#endif
#endif

View File

@@ -1,207 +0,0 @@
/*
*
* Copyright (c) 1998-2002
* John Maddock
*
* Use, modification and distribution are subject to the
* Boost Software License, Version 1.0. (See accompanying file
* LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
*
*/
/*
* LOCATION: see http://www.boost.org for most recent version.
* FILE boost/regex/config/cwchar.hpp
* VERSION see <boost/version.hpp>
* DESCRIPTION: regex wide character string fixes.
*/
#ifndef BOOST_REGEX_CONFIG_CWCHAR_HPP
#define BOOST_REGEX_CONFIG_CWCHAR_HPP
#include <cwchar>
#include <cwctype>
#include <boost/config.hpp>
#if defined(__STD_RWCOMPILER_H__) || defined(_RWSTD_VER)
// apparently this is required for the RW STL on Linux:
#undef iswalnum
#undef iswalpha
#undef iswblank
#undef iswcntrl
#undef iswdigit
#undef iswgraph
#undef iswlower
#undef iswprint
#undef iswprint
#undef iswpunct
#undef iswspace
#undef iswupper
#undef iswxdigit
#undef iswctype
#undef towlower
#undef towupper
#undef towctrans
#undef wctrans
#undef wctype
#endif
namespace std{
#ifndef BOOST_NO_STDC_NAMESPACE
extern "C"{
#endif
#ifdef iswalnum
inline int (iswalnum)(wint_t i)
{ return iswalnum(i); }
#undef iswalnum
#elif defined(BOOST_NO_STDC_NAMESPACE)
using ::iswalnum;
#endif
#ifdef iswalpha
inline int (iswalpha)(wint_t i)
{ return iswalpha(i); }
#undef iswalpha
#elif defined(BOOST_NO_STDC_NAMESPACE)
using ::iswalpha;
#endif
#ifdef iswcntrl
inline int (iswcntrl)(wint_t i)
{ return iswcntrl(i); }
#undef iswcntrl
#elif defined(BOOST_NO_STDC_NAMESPACE)
using ::iswcntrl;
#endif
#ifdef iswdigit
inline int (iswdigit)(wint_t i)
{ return iswdigit(i); }
#undef iswdigit
#elif defined(BOOST_NO_STDC_NAMESPACE)
using ::iswdigit;
#endif
#ifdef iswgraph
inline int (iswgraph)(wint_t i)
{ return iswgraph(i); }
#undef iswgraph
#elif defined(BOOST_NO_STDC_NAMESPACE)
using ::iswgraph;
#endif
#ifdef iswlower
inline int (iswlower)(wint_t i)
{ return iswlower(i); }
#undef iswlower
#elif defined(BOOST_NO_STDC_NAMESPACE)
using ::iswlower;
#endif
#ifdef iswprint
inline int (iswprint)(wint_t i)
{ return iswprint(i); }
#undef iswprint
#elif defined(BOOST_NO_STDC_NAMESPACE)
using ::iswprint;
#endif
#ifdef iswpunct
inline int (iswpunct)(wint_t i)
{ return iswpunct(i); }
#undef iswpunct
#elif defined(BOOST_NO_STDC_NAMESPACE)
using ::iswpunct;
#endif
#ifdef iswspace
inline int (iswspace)(wint_t i)
{ return iswspace(i); }
#undef iswspace
#elif defined(BOOST_NO_STDC_NAMESPACE)
using ::iswspace;
#endif
#ifdef iswupper
inline int (iswupper)(wint_t i)
{ return iswupper(i); }
#undef iswupper
#elif defined(BOOST_NO_STDC_NAMESPACE)
using ::iswupper;
#endif
#ifdef iswxdigit
inline int (iswxdigit)(wint_t i)
{ return iswxdigit(i); }
#undef iswxdigit
#elif defined(BOOST_NO_STDC_NAMESPACE)
using ::iswxdigit;
#endif
#ifdef towlower
inline wint_t (towlower)(wint_t i)
{ return towlower(i); }
#undef towlower
#elif defined(BOOST_NO_STDC_NAMESPACE)
using ::towlower;
#endif
#ifdef towupper
inline wint_t (towupper)(wint_t i)
{ return towupper(i); }
#undef towupper
#elif defined(BOOST_NO_STDC_NAMESPACE)
using :: towupper;
#endif
#ifdef wcscmp
inline int (wcscmp)(const wchar_t *p1, const wchar_t *p2)
{ return wcscmp(p1,p2); }
#undef wcscmp
#elif defined(BOOST_NO_STDC_NAMESPACE)
using ::wcscmp;
#endif
#ifdef wcscoll
inline int (wcscoll)(const wchar_t *p1, const wchar_t *p2)
{ return wcscoll(p1,p2); }
#undef wcscoll
#elif defined(BOOST_NO_STDC_NAMESPACE) && !defined(UNDER_CE)
using ::wcscoll;
#endif
#ifdef wcscpy
inline wchar_t *(wcscpy)(wchar_t *p1, const wchar_t *p2)
{ return wcscpy(p1,p2); }
#undef wcscpy
#elif defined(BOOST_NO_STDC_NAMESPACE)
using ::wcscpy;
#endif
#ifdef wcslen
inline size_t (wcslen)(const wchar_t *p)
{ return wcslen(p); }
#undef wcslen
#elif defined(BOOST_NO_STDC_NAMESPACE)
using ::wcslen;
#endif
#ifdef wcsxfrm
size_t wcsxfrm(wchar_t *p1, const wchar_t *p2, size_t s)
{ return wcsxfrm(p1,p2,s); }
#undef wcsxfrm
#elif defined(BOOST_NO_STDC_NAMESPACE)
using ::wcsxfrm;
#endif
#ifndef BOOST_NO_STDC_NAMESPACE
} // extern "C"
#endif
} // namespace std
#endif

View File

@@ -1,30 +0,0 @@
/*
*
* Copyright (c) 2020
* John Maddock
*
* Use, modification and distribution are subject to the
* Boost Software License, Version 1.0. (See accompanying file
* LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
*
*/
/*
* LOCATION: see http://www.boost.org for most recent version.
* FILE icu.hpp
* VERSION see <boost/version.hpp>
* DESCRIPTION: Unicode regular expressions on top of the ICU Library.
*/
#ifndef BOOST_REGEX_ICU_HPP
#define BOOST_REGEX_ICU_HPP
#include <boost/regex/config.hpp>
#ifdef BOOST_REGEX_CXX03
#include <boost/regex/v4/icu.hpp>
#else
#include <boost/regex/v5/icu.hpp>
#endif
#endif

View File

@@ -1,186 +0,0 @@
/*
*
* Copyright (c) 2004
* John Maddock
*
* Use, modification and distribution are subject to the
* Boost Software License, Version 1.0. (See accompanying file
* LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
*
*/
/*
* LOCATION: see http://www.boost.org for most recent version.
* FILE mfc.hpp
* VERSION see <boost/version.hpp>
* DESCRIPTION: Overloads and helpers for using MFC/ATL string types with Boost.Regex.
*/
#ifndef BOOST_REGEX_MFC_HPP
#define BOOST_REGEX_MFC_HPP
#include <atlsimpstr.h>
#include <boost/regex.hpp>
namespace boost{
//
// define the types used for TCHAR's:
typedef basic_regex<TCHAR> tregex;
typedef match_results<TCHAR const*> tmatch;
typedef regex_iterator<TCHAR const*> tregex_iterator;
typedef regex_token_iterator<TCHAR const*> tregex_token_iterator;
// Obsolete. Remove
#define SIMPLE_STRING_PARAM class B, bool b
#define SIMPLE_STRING_ARG_LIST B, b
//
// define regex creation functions:
//
template <class B, bool b>
inline basic_regex<B>
make_regex(const ATL::CSimpleStringT<B, b>& s, ::boost::regex_constants::syntax_option_type f = boost::regex_constants::normal)
{
basic_regex<B> result(s.GetString(), s.GetString() + s.GetLength(), f);
return result;
}
//
// regex_match overloads:
//
template <class B, bool b, class A, class T>
inline bool regex_match(const ATL::CSimpleStringT<B, b>& s,
match_results<const B*, A>& what,
const basic_regex<B, T>& e,
boost::regex_constants::match_flag_type f = boost::regex_constants::match_default)
{
return ::boost::regex_match(s.GetString(),
s.GetString() + s.GetLength(),
what,
e,
f);
}
template <class B, bool b, class T>
inline bool regex_match(const ATL::CSimpleStringT<B, b>& s,
const basic_regex<B, T>& e,
boost::regex_constants::match_flag_type f = boost::regex_constants::match_default)
{
return ::boost::regex_match(s.GetString(),
s.GetString() + s.GetLength(),
e,
f);
}
//
// regex_search overloads:
//
template <class B, bool b, class A, class T>
inline bool regex_search(const ATL::CSimpleStringT<B, b>& s,
match_results<const B*, A>& what,
const basic_regex<B, T>& e,
boost::regex_constants::match_flag_type f = boost::regex_constants::match_default)
{
return ::boost::regex_search(s.GetString(),
s.GetString() + s.GetLength(),
what,
e,
f);
}
template <class B, bool b, class T>
inline bool regex_search(const ATL::CSimpleStringT<B, b>& s,
const basic_regex<B, T>& e,
boost::regex_constants::match_flag_type f = boost::regex_constants::match_default)
{
return ::boost::regex_search(s.GetString(),
s.GetString() + s.GetLength(),
e,
f);
}
//
// regex_iterator creation:
//
template <class B, bool b>
inline regex_iterator<B const*>
make_regex_iterator(const ATL::CSimpleStringT<B, b>& s, const basic_regex<B>& e, ::boost::regex_constants::match_flag_type f = boost::regex_constants::match_default)
{
regex_iterator<B const*> result(s.GetString(), s.GetString() + s.GetLength(), e, f);
return result;
}
template <class B, bool b>
inline regex_token_iterator<B const*>
make_regex_token_iterator(const ATL::CSimpleStringT<B, b>& s, const basic_regex<B>& e, int sub = 0, ::boost::regex_constants::match_flag_type f = boost::regex_constants::match_default)
{
regex_token_iterator<B const*> result(s.GetString(), s.GetString() + s.GetLength(), e, sub, f);
return result;
}
template <class B, bool b>
inline regex_token_iterator<B const*>
make_regex_token_iterator(const ATL::CSimpleStringT<B, b>& s, const basic_regex<B>& e, const std::vector<int>& subs, ::boost::regex_constants::match_flag_type f = boost::regex_constants::match_default)
{
regex_token_iterator<B const*> result(s.GetString(), s.GetString() + s.GetLength(), e, subs, f);
return result;
}
template <class B, bool b, std::size_t N>
inline regex_token_iterator<B const*>
make_regex_token_iterator(const ATL::CSimpleStringT<B, b>& s, const basic_regex<B>& e, const int (& subs)[N], ::boost::regex_constants::match_flag_type f = boost::regex_constants::match_default)
{
regex_token_iterator<B const*> result(s.GetString(), s.GetString() + s.GetLength(), e, subs, f);
return result;
}
template <class OutputIterator, class BidirectionalIterator, class traits,
class B, bool b>
OutputIterator regex_replace(OutputIterator out,
BidirectionalIterator first,
BidirectionalIterator last,
const basic_regex<B, traits>& e,
const ATL::CSimpleStringT<B, b>& fmt,
match_flag_type flags = match_default)
{
return ::boost::regex_replace(out, first, last, e, fmt.GetString(), flags);
}
namespace BOOST_REGEX_DETAIL_NS{
template <class B, bool b>
class mfc_string_out_iterator
{
ATL::CSimpleStringT<B, b>* out;
public:
mfc_string_out_iterator(ATL::CSimpleStringT<B, b>& s) : out(&s) {}
mfc_string_out_iterator& operator++() { return *this; }
mfc_string_out_iterator& operator++(int) { return *this; }
mfc_string_out_iterator& operator*() { return *this; }
mfc_string_out_iterator& operator=(B v)
{
out->AppendChar(v);
return *this;
}
typedef std::ptrdiff_t difference_type;
typedef B value_type;
typedef value_type* pointer;
typedef value_type& reference;
typedef std::output_iterator_tag iterator_category;
};
}
template <class traits, class B, bool b>
ATL::CSimpleStringT<B, b> regex_replace(const ATL::CSimpleStringT<B, b>& s,
const basic_regex<B, traits>& e,
const ATL::CSimpleStringT<B, b>& fmt,
match_flag_type flags = match_default)
{
ATL::CSimpleStringT<B, b> result(s.GetManager());
BOOST_REGEX_DETAIL_NS::mfc_string_out_iterator<B, b> i(result);
regex_replace(i, s.GetString(), s.GetString() + s.GetLength(), e, fmt.GetString(), flags);
return result;
}
} // namespace boost.
#endif

View File

@@ -1,32 +0,0 @@
/*
*
* Copyright (c) 1998-2002
* John Maddock
*
* Use, modification and distribution are subject to the
* Boost Software License, Version 1.0. (See accompanying file
* LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
*
*/
/*
* LOCATION: see http://www.boost.org for most recent version.
* FILE pattern_except.hpp
* VERSION see <boost/version.hpp>
* DESCRIPTION: Declares pattern-matching exception classes.
*/
#ifndef BOOST_RE_PAT_EXCEPT_HPP
#define BOOST_RE_PAT_EXCEPT_HPP
#ifndef BOOST_REGEX_CONFIG_HPP
#include <boost/regex/config.hpp>
#endif
#ifdef BOOST_REGEX_CXX03
#include <boost/regex/v4/pattern_except.hpp>
#else
#include <boost/regex/v5/pattern_except.hpp>
#endif
#endif

View File

@@ -1,29 +0,0 @@
/*
*
* Copyright (c) 2004
* John Maddock
*
* Use, modification and distribution are subject to the
* Boost Software License, Version 1.0. (See accompanying file
* LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
*
*/
/*
* LOCATION: see http://www.boost.org for most recent version.
* FILE object_cache.hpp
* VERSION see <boost/version.hpp>
* DESCRIPTION: Implements a generic object cache.
*/
#ifndef BOOST_REGEX_OBJECT_CACHE_HPP
#define BOOST_REGEX_OBJECT_CACHE_HPP
#include <boost/regex/config.hpp>
#ifdef BOOST_REGEX_CXX03
#include <boost/regex/v4/object_cache.hpp>
#else
#include <boost/regex/v5/object_cache.hpp>
#endif
#endif

View File

@@ -1,182 +0,0 @@
/*
*
* Copyright (c) 2004
* John Maddock
*
* Use, modification and distribution are subject to the
* Boost Software License, Version 1.0. (See accompanying file
* LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
*
*/
/*
* LOCATION: see http://www.boost.org for most recent version.
* FILE static_mutex.hpp
* VERSION see <boost/version.hpp>
* DESCRIPTION: Declares static_mutex lock type, there are three different
* implementations: POSIX pthreads, WIN32 threads, and portable,
* these are described in more detail below.
*/
#ifndef BOOST_REGEX_STATIC_MUTEX_HPP
#define BOOST_REGEX_STATIC_MUTEX_HPP
#include <boost/config.hpp>
#include <boost/regex/config.hpp> // dll import/export options.
#ifdef BOOST_HAS_PTHREADS
#include <pthread.h>
#endif
#if defined(BOOST_HAS_PTHREADS) && defined(PTHREAD_MUTEX_INITIALIZER)
//
// pthreads version:
// simple wrap around a pthread_mutex_t initialized with
// PTHREAD_MUTEX_INITIALIZER.
//
namespace boost{
class static_mutex;
#define BOOST_STATIC_MUTEX_INIT { PTHREAD_MUTEX_INITIALIZER, }
class BOOST_REGEX_DECL scoped_static_mutex_lock
{
public:
scoped_static_mutex_lock(static_mutex& mut, bool lk = true);
~scoped_static_mutex_lock();
inline bool locked()const
{
return m_have_lock;
}
inline operator void const*()const
{
return locked() ? this : 0;
}
void lock();
void unlock();
private:
static_mutex& m_mutex;
bool m_have_lock;
};
class static_mutex
{
public:
typedef scoped_static_mutex_lock scoped_lock;
pthread_mutex_t m_mutex;
};
} // namespace boost
#elif defined(BOOST_HAS_WINTHREADS)
//
// Win32 version:
// Use a 32-bit int as a lock, along with a test-and-set
// implementation using InterlockedCompareExchange.
//
#include <boost/cstdint.hpp>
namespace boost{
class BOOST_REGEX_DECL scoped_static_mutex_lock;
class static_mutex
{
public:
typedef scoped_static_mutex_lock scoped_lock;
boost::int32_t m_mutex;
};
#define BOOST_STATIC_MUTEX_INIT { 0, }
class BOOST_REGEX_DECL scoped_static_mutex_lock
{
public:
scoped_static_mutex_lock(static_mutex& mut, bool lk = true);
~scoped_static_mutex_lock();
operator void const*()const
{
return locked() ? this : 0;
}
bool locked()const
{
return m_have_lock;
}
void lock();
void unlock();
private:
static_mutex& m_mutex;
bool m_have_lock;
scoped_static_mutex_lock(const scoped_static_mutex_lock&);
scoped_static_mutex_lock& operator=(const scoped_static_mutex_lock&);
};
} // namespace
#else
//
// Portable version of a static mutex based on Boost.Thread library:
// This has to use a single mutex shared by all instances of static_mutex
// because boost::call_once doesn't alow us to pass instance information
// down to the initialisation proceedure. In fact the initialisation routine
// may need to be called more than once - but only once per instance.
//
// Since this preprocessor path is almost never taken, we hide these header
// dependencies so that build tools don't find them.
//
#define BOOST_REGEX_H1 <boost/thread/once.hpp>
#define BOOST_REGEX_H2 <boost/thread/recursive_mutex.hpp>
#define BOOST_REGEX_H3 <boost/thread/lock_types.hpp>
#include BOOST_REGEX_H1
#include BOOST_REGEX_H2
#include BOOST_REGEX_H3
#undef BOOST_REGEX_H1
#undef BOOST_REGEX_H2
#undef BOOST_REGEX_H3
namespace boost{
class BOOST_REGEX_DECL scoped_static_mutex_lock;
extern "C" BOOST_REGEX_DECL void boost_regex_free_static_mutex();
class BOOST_REGEX_DECL static_mutex
{
public:
typedef scoped_static_mutex_lock scoped_lock;
static void init();
static boost::recursive_mutex* m_pmutex;
static boost::once_flag m_once;
};
#define BOOST_STATIC_MUTEX_INIT { }
class BOOST_REGEX_DECL scoped_static_mutex_lock
{
public:
scoped_static_mutex_lock(static_mutex& mut, bool lk = true);
~scoped_static_mutex_lock();
operator void const*()const;
bool locked()const;
void lock();
void unlock();
private:
boost::unique_lock<boost::recursive_mutex>* m_plock;
bool m_have_lock;
};
inline scoped_static_mutex_lock::operator void const*()const
{
return locked() ? this : 0;
}
inline bool scoped_static_mutex_lock::locked()const
{
return m_have_lock;
}
} // namespace
#endif
#endif

View File

@@ -1,32 +0,0 @@
/*
*
* Copyright (c) 2020
* John Maddock
*
* Use, modification and distribution are subject to the
* Boost Software License, Version 1.0. (See accompanying file
* LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
*
*/
/*
* LOCATION: see http://www.boost.org for most recent version.
* FILE unicode_iterator.hpp
* VERSION see <boost/version.hpp>
* DESCRIPTION: Iterator adapters for converting between different Unicode encodings.
*/
#ifndef BOOST_REGEX_PENDING_UNICODE_ITERATOR_HPP
#define BOOST_REGEX_PENDING_UNICODE_ITERATOR_HPP
#include <boost/regex/config.hpp>
#if defined(BOOST_REGEX_CXX03)
#include <boost/regex/v4/unicode_iterator.hpp>
#else
#include <boost/regex/v5/unicode_iterator.hpp>
#endif
#endif // BOOST_REGEX_PENDING_UNICODE_ITERATOR_HPP

View File

@@ -1,39 +0,0 @@
/*
*
* Copyright (c) 1998-2002
* John Maddock
*
* Use, modification and distribution are subject to the
* Boost Software License, Version 1.0. (See accompanying file
* LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
*
*/
/*
* LOCATION: see http://www.boost.org for most recent version.
* FILE regex_traits.hpp
* VERSION see <boost/version.hpp>
* DESCRIPTION: Declares regular expression traits classes.
*/
#ifndef BOOST_REGEX_TRAITS_HPP
#define BOOST_REGEX_TRAITS_HPP
#ifndef BOOST_REGEX_CONFIG_HPP
# include <boost/regex/config.hpp>
#endif
# ifndef BOOST_REGEX_TRAITS_HPP_INCLUDED
#ifdef BOOST_REGEX_CXX03
# include <boost/regex/v4/regex_traits.hpp>
#else
# include <boost/regex/v5/regex_traits.hpp>
#endif
# endif
#endif // include

View File

@@ -1,95 +0,0 @@
/*
*
* Copyright (c) 1998-2002
* John Maddock
*
* Use, modification and distribution are subject to the
* Boost Software License, Version 1.0. (See accompanying file
* LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
*
*/
/*
* LOCATION: see http://www.boost.org for most recent version.
* FILE user.hpp
* VERSION see <boost/version.hpp>
* DESCRIPTION: User settable options.
*/
// define if you want the regex library to use the C locale
// even on Win32:
// #define BOOST_REGEX_USE_C_LOCALE
// define this is you want the regex library to use the C++
// locale:
// #define BOOST_REGEX_USE_CPP_LOCALE
// define this if the runtime library is a dll, and you
// want BOOST_REGEX_DYN_LINK to set up dll exports/imports
// with __declspec(dllexport)/__declspec(dllimport.)
// #define BOOST_REGEX_HAS_DLL_RUNTIME
// define this if you want to dynamically link to regex,
// if the runtime library is also a dll (Probably Win32 specific,
// and has no effect unless BOOST_REGEX_HAS_DLL_RUNTIME is set):
// #define BOOST_REGEX_DYN_LINK
// define this if you don't want the lib to automatically
// select its link libraries:
// #define BOOST_REGEX_NO_LIB
// define this if templates with switch statements cause problems:
// #define BOOST_REGEX_NO_TEMPLATE_SWITCH_MERGE
// define this to disable Win32 support when available:
// #define BOOST_REGEX_NO_W32
// define this if bool is not a real type:
// #define BOOST_REGEX_NO_BOOL
// define this if no template instances are to be placed in
// the library rather than users object files:
// #define BOOST_REGEX_NO_EXTERNAL_TEMPLATES
// define this if the forward declarations in regex_fwd.hpp
// cause more problems than they are worth:
// #define BOOST_REGEX_NO_FWD
// define this if your compiler supports MS Windows structured
// exception handling.
// #define BOOST_REGEX_HAS_MS_STACK_GUARD
// define this if you want to use the recursive algorithm
// even if BOOST_REGEX_HAS_MS_STACK_GUARD is not defined.
// NOTE: OBSOLETE!!
// #define BOOST_REGEX_RECURSIVE
// define this if you want to use the non-recursive
// algorithm, even if the recursive version would be the default.
// NOTE: OBSOLETE!!
// #define BOOST_REGEX_NON_RECURSIVE
// define this if you want to set the size of the memory blocks
// used by the non-recursive algorithm.
// #define BOOST_REGEX_BLOCKSIZE 4096
// define this if you want to set the maximum number of memory blocks
// used by the non-recursive algorithm.
// #define BOOST_REGEX_MAX_BLOCKS 1024
// define this if you want to set the maximum number of memory blocks
// cached by the non-recursive algorithm: Normally this is 16, but can be
// higher if you have multiple threads all using boost.regex, or lower
// if you don't want boost.regex to cache memory.
// #define BOOST_REGEX_MAX_CACHE_BLOCKS 16
// define this if you want to be able to access extended capture
// information in your sub_match's (caution this will slow things
// down quite a bit).
// #define BOOST_REGEX_MATCH_EXTRA
// define this if you want to enable support for Unicode via ICU.
// #define BOOST_HAS_ICU
// define this if you want regex to use __cdecl calling convensions, even when __fastcall is available:
// #define BOOST_REGEX_NO_FASTCALL

View File

@@ -1,797 +0,0 @@
/*
*
* Copyright (c) 1998-2004 John Maddock
* Copyright 2011 Garmin Ltd. or its subsidiaries
*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
*/
/*
* LOCATION: see http://www.boost.org/ for most recent version.
* FILE basic_regex.cpp
* VERSION see <boost/version.hpp>
* DESCRIPTION: Declares template class basic_regex.
*/
#ifndef BOOST_REGEX_V4_BASIC_REGEX_HPP
#define BOOST_REGEX_V4_BASIC_REGEX_HPP
#include <boost/type_traits/is_same.hpp>
#include <boost/container_hash/hash.hpp>
#ifdef BOOST_MSVC
#pragma warning(push)
#pragma warning(disable: 4103)
#endif
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_PREFIX
#endif
#ifdef BOOST_MSVC
#pragma warning(pop)
#endif
namespace boost{
#ifdef BOOST_MSVC
#pragma warning(push)
#pragma warning(disable : 4251)
#if BOOST_MSVC < 1700
# pragma warning(disable : 4231)
#endif
#if BOOST_MSVC < 1600
#pragma warning(disable : 4660)
#endif
#if BOOST_MSVC < 1910
#pragma warning(disable:4800)
#endif
#endif
namespace BOOST_REGEX_DETAIL_NS{
//
// forward declaration, we will need this one later:
//
template <class charT, class traits>
class basic_regex_parser;
template <class I>
void bubble_down_one(I first, I last)
{
if(first != last)
{
I next = last - 1;
while((next != first) && (*next < *(next-1)))
{
(next-1)->swap(*next);
--next;
}
}
}
static const int hash_value_mask = 1 << (std::numeric_limits<int>::digits - 1);
template <class Iterator>
inline int hash_value_from_capture_name(Iterator i, Iterator j)
{
std::size_t r = boost::hash_range(i, j);
r %= ((std::numeric_limits<int>::max)());
return static_cast<int>(r) | hash_value_mask;
}
class named_subexpressions
{
public:
struct name
{
template <class charT>
name(const charT* i, const charT* j, int idx)
: index(idx)
{
hash = hash_value_from_capture_name(i, j);
}
name(int h, int idx)
: index(idx), hash(h)
{
}
int index;
int hash;
bool operator < (const name& other)const
{
return hash < other.hash;
}
bool operator == (const name& other)const
{
return hash == other.hash;
}
void swap(name& other)
{
std::swap(index, other.index);
std::swap(hash, other.hash);
}
};
typedef std::vector<name>::const_iterator const_iterator;
typedef std::pair<const_iterator, const_iterator> range_type;
named_subexpressions(){}
template <class charT>
void set_name(const charT* i, const charT* j, int index)
{
m_sub_names.push_back(name(i, j, index));
bubble_down_one(m_sub_names.begin(), m_sub_names.end());
}
template <class charT>
int get_id(const charT* i, const charT* j)const
{
name t(i, j, 0);
typename std::vector<name>::const_iterator pos = std::lower_bound(m_sub_names.begin(), m_sub_names.end(), t);
if((pos != m_sub_names.end()) && (*pos == t))
{
return pos->index;
}
return -1;
}
template <class charT>
range_type equal_range(const charT* i, const charT* j)const
{
name t(i, j, 0);
return std::equal_range(m_sub_names.begin(), m_sub_names.end(), t);
}
int get_id(int h)const
{
name t(h, 0);
std::vector<name>::const_iterator pos = std::lower_bound(m_sub_names.begin(), m_sub_names.end(), t);
if((pos != m_sub_names.end()) && (*pos == t))
{
return pos->index;
}
return -1;
}
range_type equal_range(int h)const
{
name t(h, 0);
return std::equal_range(m_sub_names.begin(), m_sub_names.end(), t);
}
private:
std::vector<name> m_sub_names;
};
//
// class regex_data:
// represents the data we wish to expose to the matching algorithms.
//
template <class charT, class traits>
struct regex_data : public named_subexpressions
{
typedef regex_constants::syntax_option_type flag_type;
typedef std::size_t size_type;
regex_data(const ::boost::shared_ptr<
::boost::regex_traits_wrapper<traits> >& t)
: m_ptraits(t), m_flags(0), m_status(0), m_expression(0), m_expression_len(0),
m_mark_count(0), m_first_state(0), m_restart_type(0),
#if !defined(BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX) && !(defined(BOOST_MSVC) && (BOOST_MSVC < 1900))
m_startmap{ 0 },
#endif
m_can_be_null(0), m_word_mask(0), m_has_recursions(false), m_disable_match_any(false) {}
regex_data()
: m_ptraits(new ::boost::regex_traits_wrapper<traits>()), m_flags(0), m_status(0), m_expression(0), m_expression_len(0),
m_mark_count(0), m_first_state(0), m_restart_type(0),
#if !defined(BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX) && !(defined(BOOST_MSVC) && (BOOST_MSVC < 1900))
m_startmap{ 0 },
#endif
m_can_be_null(0), m_word_mask(0), m_has_recursions(false), m_disable_match_any(false) {}
::boost::shared_ptr<
::boost::regex_traits_wrapper<traits>
> m_ptraits; // traits class instance
flag_type m_flags; // flags with which we were compiled
int m_status; // error code (0 implies OK).
const charT* m_expression; // the original expression
std::ptrdiff_t m_expression_len; // the length of the original expression
size_type m_mark_count; // the number of marked sub-expressions
BOOST_REGEX_DETAIL_NS::re_syntax_base* m_first_state; // the first state of the machine
unsigned m_restart_type; // search optimisation type
unsigned char m_startmap[1 << CHAR_BIT]; // which characters can start a match
unsigned int m_can_be_null; // whether we can match a null string
BOOST_REGEX_DETAIL_NS::raw_storage m_data; // the buffer in which our states are constructed
typename traits::char_class_type m_word_mask; // mask used to determine if a character is a word character
std::vector<
std::pair<
std::size_t, std::size_t> > m_subs; // Position of sub-expressions within the *string*.
bool m_has_recursions; // whether we have recursive expressions;
bool m_disable_match_any; // when set we need to disable the match_any flag as it causes different/buggy behaviour.
};
//
// class basic_regex_implementation
// pimpl implementation class for basic_regex.
//
template <class charT, class traits>
class basic_regex_implementation
: public regex_data<charT, traits>
{
public:
typedef regex_constants::syntax_option_type flag_type;
typedef std::ptrdiff_t difference_type;
typedef std::size_t size_type;
typedef typename traits::locale_type locale_type;
typedef const charT* const_iterator;
basic_regex_implementation(){}
basic_regex_implementation(const ::boost::shared_ptr<
::boost::regex_traits_wrapper<traits> >& t)
: regex_data<charT, traits>(t) {}
void assign(const charT* arg_first,
const charT* arg_last,
flag_type f)
{
regex_data<charT, traits>* pdat = this;
basic_regex_parser<charT, traits> parser(pdat);
parser.parse(arg_first, arg_last, f);
}
locale_type BOOST_REGEX_CALL imbue(locale_type l)
{
return this->m_ptraits->imbue(l);
}
locale_type BOOST_REGEX_CALL getloc()const
{
return this->m_ptraits->getloc();
}
std::basic_string<charT> BOOST_REGEX_CALL str()const
{
std::basic_string<charT> result;
if(this->m_status == 0)
result = std::basic_string<charT>(this->m_expression, this->m_expression_len);
return result;
}
const_iterator BOOST_REGEX_CALL expression()const
{
return this->m_expression;
}
std::pair<const_iterator, const_iterator> BOOST_REGEX_CALL subexpression(std::size_t n)const
{
const std::pair<std::size_t, std::size_t>& pi = this->m_subs.at(n);
std::pair<const_iterator, const_iterator> p(expression() + pi.first, expression() + pi.second);
return p;
}
//
// begin, end:
const_iterator BOOST_REGEX_CALL begin()const
{
return (this->m_status ? 0 : this->m_expression);
}
const_iterator BOOST_REGEX_CALL end()const
{
return (this->m_status ? 0 : this->m_expression + this->m_expression_len);
}
flag_type BOOST_REGEX_CALL flags()const
{
return this->m_flags;
}
size_type BOOST_REGEX_CALL size()const
{
return this->m_expression_len;
}
int BOOST_REGEX_CALL status()const
{
return this->m_status;
}
size_type BOOST_REGEX_CALL mark_count()const
{
return this->m_mark_count - 1;
}
const BOOST_REGEX_DETAIL_NS::re_syntax_base* get_first_state()const
{
return this->m_first_state;
}
unsigned get_restart_type()const
{
return this->m_restart_type;
}
const unsigned char* get_map()const
{
return this->m_startmap;
}
const ::boost::regex_traits_wrapper<traits>& get_traits()const
{
return *(this->m_ptraits);
}
bool can_be_null()const
{
return this->m_can_be_null;
}
const regex_data<charT, traits>& get_data()const
{
basic_regex_implementation<charT, traits> const* p = this;
return *static_cast<const regex_data<charT, traits>*>(p);
}
};
} // namespace BOOST_REGEX_DETAIL_NS
//
// class basic_regex:
// represents the compiled
// regular expression:
//
#ifdef BOOST_REGEX_NO_FWD
template <class charT, class traits = regex_traits<charT> >
#else
template <class charT, class traits >
#endif
class basic_regex : public regbase
{
public:
// typedefs:
typedef std::size_t traits_size_type;
typedef typename traits::string_type traits_string_type;
typedef charT char_type;
typedef traits traits_type;
typedef charT value_type;
typedef charT& reference;
typedef const charT& const_reference;
typedef const charT* const_iterator;
typedef const_iterator iterator;
typedef std::ptrdiff_t difference_type;
typedef std::size_t size_type;
typedef regex_constants::syntax_option_type flag_type;
// locale_type
// placeholder for actual locale type used by the
// traits class to localise *this.
typedef typename traits::locale_type locale_type;
public:
explicit basic_regex(){}
explicit basic_regex(const charT* p, flag_type f = regex_constants::normal)
{
assign(p, f);
}
basic_regex(const charT* p1, const charT* p2, flag_type f = regex_constants::normal)
{
assign(p1, p2, f);
}
basic_regex(const charT* p, size_type len, flag_type f)
{
assign(p, len, f);
}
basic_regex(const basic_regex& that)
: m_pimpl(that.m_pimpl) {}
~basic_regex(){}
basic_regex& BOOST_REGEX_CALL operator=(const basic_regex& that)
{
return assign(that);
}
basic_regex& BOOST_REGEX_CALL operator=(const charT* ptr)
{
return assign(ptr);
}
//
// assign:
basic_regex& assign(const basic_regex& that)
{
m_pimpl = that.m_pimpl;
return *this;
}
basic_regex& assign(const charT* p, flag_type f = regex_constants::normal)
{
return assign(p, p + traits::length(p), f);
}
basic_regex& assign(const charT* p, size_type len, flag_type f)
{
return assign(p, p + len, f);
}
private:
basic_regex& do_assign(const charT* p1,
const charT* p2,
flag_type f);
public:
basic_regex& assign(const charT* p1,
const charT* p2,
flag_type f = regex_constants::normal)
{
return do_assign(p1, p2, f);
}
#if !defined(BOOST_NO_MEMBER_TEMPLATES)
template <class ST, class SA>
unsigned int BOOST_REGEX_CALL set_expression(const std::basic_string<charT, ST, SA>& p, flag_type f = regex_constants::normal)
{
return set_expression(p.data(), p.data() + p.size(), f);
}
template <class ST, class SA>
explicit basic_regex(const std::basic_string<charT, ST, SA>& p, flag_type f = regex_constants::normal)
{
assign(p, f);
}
template <class InputIterator>
basic_regex(InputIterator arg_first, InputIterator arg_last, flag_type f = regex_constants::normal)
{
typedef typename traits::string_type seq_type;
seq_type a(arg_first, arg_last);
if(!a.empty())
assign(static_cast<const charT*>(&*a.begin()), static_cast<const charT*>(&*a.begin() + a.size()), f);
else
assign(static_cast<const charT*>(0), static_cast<const charT*>(0), f);
}
template <class ST, class SA>
basic_regex& BOOST_REGEX_CALL operator=(const std::basic_string<charT, ST, SA>& p)
{
return assign(p.data(), p.data() + p.size(), regex_constants::normal);
}
template <class string_traits, class A>
basic_regex& BOOST_REGEX_CALL assign(
const std::basic_string<charT, string_traits, A>& s,
flag_type f = regex_constants::normal)
{
return assign(s.data(), s.data() + s.size(), f);
}
template <class InputIterator>
basic_regex& BOOST_REGEX_CALL assign(InputIterator arg_first,
InputIterator arg_last,
flag_type f = regex_constants::normal)
{
typedef typename traits::string_type seq_type;
seq_type a(arg_first, arg_last);
if(a.size())
{
const charT* p1 = &*a.begin();
const charT* p2 = &*a.begin() + a.size();
return assign(p1, p2, f);
}
return assign(static_cast<const charT*>(0), static_cast<const charT*>(0), f);
}
#else
unsigned int BOOST_REGEX_CALL set_expression(const std::basic_string<charT>& p, flag_type f = regex_constants::normal)
{
return set_expression(p.data(), p.data() + p.size(), f);
}
basic_regex(const std::basic_string<charT>& p, flag_type f = regex_constants::normal)
{
assign(p, f);
}
basic_regex& BOOST_REGEX_CALL operator=(const std::basic_string<charT>& p)
{
return assign(p.data(), p.data() + p.size(), regex_constants::normal);
}
basic_regex& BOOST_REGEX_CALL assign(
const std::basic_string<charT>& s,
flag_type f = regex_constants::normal)
{
return assign(s.data(), s.data() + s.size(), f);
}
#endif
//
// locale:
locale_type BOOST_REGEX_CALL imbue(locale_type l);
locale_type BOOST_REGEX_CALL getloc()const
{
return m_pimpl.get() ? m_pimpl->getloc() : locale_type();
}
//
// getflags:
// retained for backwards compatibility only, "flags"
// is now the preferred name:
flag_type BOOST_REGEX_CALL getflags()const
{
return flags();
}
flag_type BOOST_REGEX_CALL flags()const
{
return m_pimpl.get() ? m_pimpl->flags() : 0;
}
//
// str:
std::basic_string<charT> BOOST_REGEX_CALL str()const
{
return m_pimpl.get() ? m_pimpl->str() : std::basic_string<charT>();
}
//
// begin, end, subexpression:
std::pair<const_iterator, const_iterator> BOOST_REGEX_CALL subexpression(std::size_t n)const
{
if(!m_pimpl.get())
boost::throw_exception(std::logic_error("Can't access subexpressions in an invalid regex."));
return m_pimpl->subexpression(n);
}
const_iterator BOOST_REGEX_CALL begin()const
{
return (m_pimpl.get() ? m_pimpl->begin() : 0);
}
const_iterator BOOST_REGEX_CALL end()const
{
return (m_pimpl.get() ? m_pimpl->end() : 0);
}
//
// swap:
void BOOST_REGEX_CALL swap(basic_regex& that)throw()
{
m_pimpl.swap(that.m_pimpl);
}
//
// size:
size_type BOOST_REGEX_CALL size()const
{
return (m_pimpl.get() ? m_pimpl->size() : 0);
}
//
// max_size:
size_type BOOST_REGEX_CALL max_size()const
{
return UINT_MAX;
}
//
// empty:
bool BOOST_REGEX_CALL empty()const
{
return (m_pimpl.get() ? 0 != m_pimpl->status() : true);
}
size_type BOOST_REGEX_CALL mark_count()const
{
return (m_pimpl.get() ? m_pimpl->mark_count() : 0);
}
int status()const
{
return (m_pimpl.get() ? m_pimpl->status() : regex_constants::error_empty);
}
int BOOST_REGEX_CALL compare(const basic_regex& that) const
{
if(m_pimpl.get() == that.m_pimpl.get())
return 0;
if(!m_pimpl.get())
return -1;
if(!that.m_pimpl.get())
return 1;
if(status() != that.status())
return status() - that.status();
if(flags() != that.flags())
return flags() - that.flags();
return str().compare(that.str());
}
bool BOOST_REGEX_CALL operator==(const basic_regex& e)const
{
return compare(e) == 0;
}
bool BOOST_REGEX_CALL operator != (const basic_regex& e)const
{
return compare(e) != 0;
}
bool BOOST_REGEX_CALL operator<(const basic_regex& e)const
{
return compare(e) < 0;
}
bool BOOST_REGEX_CALL operator>(const basic_regex& e)const
{
return compare(e) > 0;
}
bool BOOST_REGEX_CALL operator<=(const basic_regex& e)const
{
return compare(e) <= 0;
}
bool BOOST_REGEX_CALL operator>=(const basic_regex& e)const
{
return compare(e) >= 0;
}
//
// The following are deprecated as public interfaces
// but are available for compatibility with earlier versions.
const charT* BOOST_REGEX_CALL expression()const
{
return (m_pimpl.get() && !m_pimpl->status() ? m_pimpl->expression() : 0);
}
unsigned int BOOST_REGEX_CALL set_expression(const charT* p1, const charT* p2, flag_type f = regex_constants::normal)
{
assign(p1, p2, f | regex_constants::no_except);
return status();
}
unsigned int BOOST_REGEX_CALL set_expression(const charT* p, flag_type f = regex_constants::normal)
{
assign(p, f | regex_constants::no_except);
return status();
}
unsigned int BOOST_REGEX_CALL error_code()const
{
return status();
}
//
// private access methods:
//
const BOOST_REGEX_DETAIL_NS::re_syntax_base* get_first_state()const
{
BOOST_REGEX_ASSERT(0 != m_pimpl.get());
return m_pimpl->get_first_state();
}
unsigned get_restart_type()const
{
BOOST_REGEX_ASSERT(0 != m_pimpl.get());
return m_pimpl->get_restart_type();
}
const unsigned char* get_map()const
{
BOOST_REGEX_ASSERT(0 != m_pimpl.get());
return m_pimpl->get_map();
}
const ::boost::regex_traits_wrapper<traits>& get_traits()const
{
BOOST_REGEX_ASSERT(0 != m_pimpl.get());
return m_pimpl->get_traits();
}
bool can_be_null()const
{
BOOST_REGEX_ASSERT(0 != m_pimpl.get());
return m_pimpl->can_be_null();
}
const BOOST_REGEX_DETAIL_NS::regex_data<charT, traits>& get_data()const
{
BOOST_REGEX_ASSERT(0 != m_pimpl.get());
return m_pimpl->get_data();
}
boost::shared_ptr<BOOST_REGEX_DETAIL_NS::named_subexpressions > get_named_subs()const
{
return m_pimpl;
}
private:
shared_ptr<BOOST_REGEX_DETAIL_NS::basic_regex_implementation<charT, traits> > m_pimpl;
};
//
// out of line members;
// these are the only members that mutate the basic_regex object,
// and are designed to provide the strong exception guarantee
// (in the event of a throw, the state of the object remains unchanged).
//
template <class charT, class traits>
basic_regex<charT, traits>& basic_regex<charT, traits>::do_assign(const charT* p1,
const charT* p2,
flag_type f)
{
shared_ptr<BOOST_REGEX_DETAIL_NS::basic_regex_implementation<charT, traits> > temp;
if(!m_pimpl.get())
{
temp = shared_ptr<BOOST_REGEX_DETAIL_NS::basic_regex_implementation<charT, traits> >(new BOOST_REGEX_DETAIL_NS::basic_regex_implementation<charT, traits>());
}
else
{
temp = shared_ptr<BOOST_REGEX_DETAIL_NS::basic_regex_implementation<charT, traits> >(new BOOST_REGEX_DETAIL_NS::basic_regex_implementation<charT, traits>(m_pimpl->m_ptraits));
}
temp->assign(p1, p2, f);
temp.swap(m_pimpl);
return *this;
}
template <class charT, class traits>
typename basic_regex<charT, traits>::locale_type BOOST_REGEX_CALL basic_regex<charT, traits>::imbue(locale_type l)
{
shared_ptr<BOOST_REGEX_DETAIL_NS::basic_regex_implementation<charT, traits> > temp(new BOOST_REGEX_DETAIL_NS::basic_regex_implementation<charT, traits>());
locale_type result = temp->imbue(l);
temp.swap(m_pimpl);
return result;
}
//
// non-members:
//
template <class charT, class traits>
void swap(basic_regex<charT, traits>& e1, basic_regex<charT, traits>& e2)
{
e1.swap(e2);
}
#ifndef BOOST_NO_STD_LOCALE
template <class charT, class traits, class traits2>
std::basic_ostream<charT, traits>&
operator << (std::basic_ostream<charT, traits>& os,
const basic_regex<charT, traits2>& e)
{
return (os << e.str());
}
#else
template <class traits>
std::ostream& operator << (std::ostream& os, const basic_regex<char, traits>& e)
{
return (os << e.str());
}
#endif
//
// class reg_expression:
// this is provided for backwards compatibility only,
// it is deprecated, no not use!
//
#ifdef BOOST_REGEX_NO_FWD
template <class charT, class traits = regex_traits<charT> >
#else
template <class charT, class traits >
#endif
class reg_expression : public basic_regex<charT, traits>
{
public:
typedef typename basic_regex<charT, traits>::flag_type flag_type;
typedef typename basic_regex<charT, traits>::size_type size_type;
explicit reg_expression(){}
explicit reg_expression(const charT* p, flag_type f = regex_constants::normal)
: basic_regex<charT, traits>(p, f){}
reg_expression(const charT* p1, const charT* p2, flag_type f = regex_constants::normal)
: basic_regex<charT, traits>(p1, p2, f){}
reg_expression(const charT* p, size_type len, flag_type f)
: basic_regex<charT, traits>(p, len, f){}
reg_expression(const reg_expression& that)
: basic_regex<charT, traits>(that) {}
~reg_expression(){}
reg_expression& BOOST_REGEX_CALL operator=(const reg_expression& that)
{
return this->assign(that);
}
#if !defined(BOOST_NO_MEMBER_TEMPLATES)
template <class ST, class SA>
explicit reg_expression(const std::basic_string<charT, ST, SA>& p, flag_type f = regex_constants::normal)
: basic_regex<charT, traits>(p, f)
{
}
template <class InputIterator>
reg_expression(InputIterator arg_first, InputIterator arg_last, flag_type f = regex_constants::normal)
: basic_regex<charT, traits>(arg_first, arg_last, f)
{
}
template <class ST, class SA>
reg_expression& BOOST_REGEX_CALL operator=(const std::basic_string<charT, ST, SA>& p)
{
this->assign(p);
return *this;
}
#else
explicit reg_expression(const std::basic_string<charT>& p, flag_type f = regex_constants::normal)
: basic_regex<charT, traits>(p, f)
{
}
reg_expression& BOOST_REGEX_CALL operator=(const std::basic_string<charT>& p)
{
this->assign(p);
return *this;
}
#endif
};
#ifdef BOOST_MSVC
#pragma warning (pop)
#endif
} // namespace boost
#ifdef BOOST_MSVC
#pragma warning(push)
#pragma warning(disable: 4103)
#endif
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_SUFFIX
#endif
#ifdef BOOST_MSVC
#pragma warning(pop)
#endif
#endif

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,511 +0,0 @@
/*
*
* Copyright (c) 2004
* John Maddock
*
* Use, modification and distribution are subject to the
* Boost Software License, Version 1.0. (See accompanying file
* LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
*
*/
/*
* LOCATION: see http://www.boost.org for most recent version.
* FILE c_regex_traits.hpp
* VERSION see <boost/version.hpp>
* DESCRIPTION: Declares regular expression traits class that wraps the global C locale.
*/
#ifndef BOOST_C_REGEX_TRAITS_HPP_INCLUDED
#define BOOST_C_REGEX_TRAITS_HPP_INCLUDED
#ifndef BOOST_REGEX_CONFIG_HPP
#include <boost/regex/config.hpp>
#endif
#ifndef BOOST_REGEX_WORKAROUND_HPP
#include <boost/regex/v4/regex_workaround.hpp>
#endif
#include <cctype>
#ifdef BOOST_NO_STDC_NAMESPACE
namespace std{
using ::strlen; using ::tolower;
}
#endif
#ifdef BOOST_MSVC
#pragma warning(push)
#pragma warning(disable: 4103 4244)
#endif
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_PREFIX
#endif
#ifdef BOOST_MSVC
#pragma warning(pop)
#endif
namespace boost{
namespace BOOST_REGEX_DETAIL_NS {
enum
{
char_class_space = 1 << 0,
char_class_print = 1 << 1,
char_class_cntrl = 1 << 2,
char_class_upper = 1 << 3,
char_class_lower = 1 << 4,
char_class_alpha = 1 << 5,
char_class_digit = 1 << 6,
char_class_punct = 1 << 7,
char_class_xdigit = 1 << 8,
char_class_alnum = char_class_alpha | char_class_digit,
char_class_graph = char_class_alnum | char_class_punct,
char_class_blank = 1 << 9,
char_class_word = 1 << 10,
char_class_unicode = 1 << 11,
char_class_horizontal = 1 << 12,
char_class_vertical = 1 << 13
};
}
template <class charT>
struct c_regex_traits;
template<>
struct c_regex_traits<char>
{
c_regex_traits(){}
typedef char char_type;
typedef std::size_t size_type;
typedef std::string string_type;
struct locale_type{};
typedef boost::uint32_t char_class_type;
static size_type length(const char_type* p)
{
return (std::strlen)(p);
}
char translate(char c) const
{
return c;
}
char translate_nocase(char c) const
{
return static_cast<char>((std::tolower)(static_cast<unsigned char>(c)));
}
static string_type BOOST_REGEX_CALL transform(const char* p1, const char* p2);
static string_type BOOST_REGEX_CALL transform_primary(const char* p1, const char* p2);
static char_class_type BOOST_REGEX_CALL lookup_classname(const char* p1, const char* p2);
static string_type BOOST_REGEX_CALL lookup_collatename(const char* p1, const char* p2);
static bool BOOST_REGEX_CALL isctype(char, char_class_type);
static int BOOST_REGEX_CALL value(char, int);
locale_type imbue(locale_type l)
{ return l; }
locale_type getloc()const
{ return locale_type(); }
private:
// this type is not copyable:
c_regex_traits(const c_regex_traits&);
c_regex_traits& operator=(const c_regex_traits&);
};
#ifndef BOOST_NO_WREGEX
template<>
struct c_regex_traits<wchar_t>
{
c_regex_traits(){}
typedef wchar_t char_type;
typedef std::size_t size_type;
typedef std::wstring string_type;
struct locale_type{};
typedef boost::uint32_t char_class_type;
static size_type length(const char_type* p)
{
return (std::wcslen)(p);
}
wchar_t translate(wchar_t c) const
{
return c;
}
wchar_t translate_nocase(wchar_t c) const
{
return (std::towlower)(c);
}
static string_type BOOST_REGEX_CALL transform(const wchar_t* p1, const wchar_t* p2);
static string_type BOOST_REGEX_CALL transform_primary(const wchar_t* p1, const wchar_t* p2);
static char_class_type BOOST_REGEX_CALL lookup_classname(const wchar_t* p1, const wchar_t* p2);
static string_type BOOST_REGEX_CALL lookup_collatename(const wchar_t* p1, const wchar_t* p2);
static bool BOOST_REGEX_CALL isctype(wchar_t, char_class_type);
static int BOOST_REGEX_CALL value(wchar_t, int);
locale_type imbue(locale_type l)
{ return l; }
locale_type getloc()const
{ return locale_type(); }
private:
// this type is not copyable:
c_regex_traits(const c_regex_traits&);
c_regex_traits& operator=(const c_regex_traits&);
};
#endif // BOOST_NO_WREGEX
inline c_regex_traits<char>::string_type BOOST_REGEX_CALL c_regex_traits<char>::transform(const char* p1, const char* p2)
{
std::string result(10, ' ');
std::size_t s = result.size();
std::size_t r;
std::string src(p1, p2);
while (s < (r = std::strxfrm(&*result.begin(), src.c_str(), s)))
{
#if defined(_CPPLIB_VER)
//
// A bug in VC11 and 12 causes the program to hang if we pass a null-string
// to std::strxfrm, but only for certain locales :-(
// Probably effects Intel and Clang or any compiler using the VC std library (Dinkumware).
//
if (r == INT_MAX)
{
result.erase();
result.insert(result.begin(), static_cast<char>(0));
return result;
}
#endif
result.append(r - s + 3, ' ');
s = result.size();
}
result.erase(r);
return result;
}
inline c_regex_traits<char>::string_type BOOST_REGEX_CALL c_regex_traits<char>::transform_primary(const char* p1, const char* p2)
{
static char s_delim;
static const int s_collate_type = ::boost::BOOST_REGEX_DETAIL_NS::find_sort_syntax(static_cast<c_regex_traits<char>*>(0), &s_delim);
std::string result;
//
// What we do here depends upon the format of the sort key returned by
// sort key returned by this->transform:
//
switch (s_collate_type)
{
case ::boost::BOOST_REGEX_DETAIL_NS::sort_C:
case ::boost::BOOST_REGEX_DETAIL_NS::sort_unknown:
// the best we can do is translate to lower case, then get a regular sort key:
{
result.assign(p1, p2);
for (std::string::size_type i = 0; i < result.size(); ++i)
result[i] = static_cast<char>((std::tolower)(static_cast<unsigned char>(result[i])));
result = transform(&*result.begin(), &*result.begin() + result.size());
break;
}
case ::boost::BOOST_REGEX_DETAIL_NS::sort_fixed:
{
// get a regular sort key, and then truncate it:
result = transform(p1, p2);
result.erase(s_delim);
break;
}
case ::boost::BOOST_REGEX_DETAIL_NS::sort_delim:
// get a regular sort key, and then truncate everything after the delim:
result = transform(p1, p2);
if ((!result.empty()) && (result[0] == s_delim))
break;
std::size_t i;
for (i = 0; i < result.size(); ++i)
{
if (result[i] == s_delim)
break;
}
result.erase(i);
break;
}
if (result.empty())
result = std::string(1, char(0));
return result;
}
inline c_regex_traits<char>::char_class_type BOOST_REGEX_CALL c_regex_traits<char>::lookup_classname(const char* p1, const char* p2)
{
using namespace BOOST_REGEX_DETAIL_NS;
static const char_class_type masks[] =
{
0,
char_class_alnum,
char_class_alpha,
char_class_blank,
char_class_cntrl,
char_class_digit,
char_class_digit,
char_class_graph,
char_class_horizontal,
char_class_lower,
char_class_lower,
char_class_print,
char_class_punct,
char_class_space,
char_class_space,
char_class_upper,
char_class_unicode,
char_class_upper,
char_class_vertical,
char_class_alnum | char_class_word,
char_class_alnum | char_class_word,
char_class_xdigit,
};
int idx = ::boost::BOOST_REGEX_DETAIL_NS::get_default_class_id(p1, p2);
if (idx < 0)
{
std::string s(p1, p2);
for (std::string::size_type i = 0; i < s.size(); ++i)
s[i] = static_cast<char>((std::tolower)(static_cast<unsigned char>(s[i])));
idx = ::boost::BOOST_REGEX_DETAIL_NS::get_default_class_id(&*s.begin(), &*s.begin() + s.size());
}
BOOST_REGEX_ASSERT(std::size_t(idx) + 1u < sizeof(masks) / sizeof(masks[0]));
return masks[idx + 1];
}
inline bool BOOST_REGEX_CALL c_regex_traits<char>::isctype(char c, char_class_type mask)
{
using namespace BOOST_REGEX_DETAIL_NS;
return
((mask & char_class_space) && (std::isspace)(static_cast<unsigned char>(c)))
|| ((mask & char_class_print) && (std::isprint)(static_cast<unsigned char>(c)))
|| ((mask & char_class_cntrl) && (std::iscntrl)(static_cast<unsigned char>(c)))
|| ((mask & char_class_upper) && (std::isupper)(static_cast<unsigned char>(c)))
|| ((mask & char_class_lower) && (std::islower)(static_cast<unsigned char>(c)))
|| ((mask & char_class_alpha) && (std::isalpha)(static_cast<unsigned char>(c)))
|| ((mask & char_class_digit) && (std::isdigit)(static_cast<unsigned char>(c)))
|| ((mask & char_class_punct) && (std::ispunct)(static_cast<unsigned char>(c)))
|| ((mask & char_class_xdigit) && (std::isxdigit)(static_cast<unsigned char>(c)))
|| ((mask & char_class_blank) && (std::isspace)(static_cast<unsigned char>(c)) && !::boost::BOOST_REGEX_DETAIL_NS::is_separator(c))
|| ((mask & char_class_word) && (c == '_'))
|| ((mask & char_class_vertical) && (::boost::BOOST_REGEX_DETAIL_NS::is_separator(c) || (c == '\v')))
|| ((mask & char_class_horizontal) && (std::isspace)(static_cast<unsigned char>(c)) && !::boost::BOOST_REGEX_DETAIL_NS::is_separator(c) && (c != '\v'));
}
inline c_regex_traits<char>::string_type BOOST_REGEX_CALL c_regex_traits<char>::lookup_collatename(const char* p1, const char* p2)
{
std::string s(p1, p2);
s = ::boost::BOOST_REGEX_DETAIL_NS::lookup_default_collate_name(s);
if (s.empty() && (p2 - p1 == 1))
s.append(1, *p1);
return s;
}
inline int BOOST_REGEX_CALL c_regex_traits<char>::value(char c, int radix)
{
char b[2] = { c, '\0', };
char* ep;
int result = std::strtol(b, &ep, radix);
if (ep == b)
return -1;
return result;
}
#ifndef BOOST_NO_WREGEX
inline c_regex_traits<wchar_t>::string_type BOOST_REGEX_CALL c_regex_traits<wchar_t>::transform(const wchar_t* p1, const wchar_t* p2)
{
std::size_t r;
std::size_t s = 10;
std::wstring src(p1, p2);
std::wstring result(s, L' ');
while (s < (r = std::wcsxfrm(&*result.begin(), src.c_str(), s)))
{
#if defined(_CPPLIB_VER)
//
// A bug in VC11 and 12 causes the program to hang if we pass a null-string
// to std::strxfrm, but only for certain locales :-(
// Probably effects Intel and Clang or any compiler using the VC std library (Dinkumware).
//
if (r == INT_MAX)
{
result.erase();
result.insert(result.begin(), static_cast<wchar_t>(0));
return result;
}
#endif
result.append(r - s + 3, L' ');
s = result.size();
}
result.erase(r);
return result;
}
inline c_regex_traits<wchar_t>::string_type BOOST_REGEX_CALL c_regex_traits<wchar_t>::transform_primary(const wchar_t* p1, const wchar_t* p2)
{
static wchar_t s_delim;
static const int s_collate_type = ::boost::BOOST_REGEX_DETAIL_NS::find_sort_syntax(static_cast<const c_regex_traits<wchar_t>*>(0), &s_delim);
std::wstring result;
//
// What we do here depends upon the format of the sort key returned by
// sort key returned by this->transform:
//
switch (s_collate_type)
{
case ::boost::BOOST_REGEX_DETAIL_NS::sort_C:
case ::boost::BOOST_REGEX_DETAIL_NS::sort_unknown:
// the best we can do is translate to lower case, then get a regular sort key:
{
result.assign(p1, p2);
for (std::wstring::size_type i = 0; i < result.size(); ++i)
result[i] = (std::towlower)(result[i]);
result = c_regex_traits<wchar_t>::transform(&*result.begin(), &*result.begin() + result.size());
break;
}
case ::boost::BOOST_REGEX_DETAIL_NS::sort_fixed:
{
// get a regular sort key, and then truncate it:
result = c_regex_traits<wchar_t>::transform(&*result.begin(), &*result.begin() + result.size());
result.erase(s_delim);
break;
}
case ::boost::BOOST_REGEX_DETAIL_NS::sort_delim:
// get a regular sort key, and then truncate everything after the delim:
result = c_regex_traits<wchar_t>::transform(&*result.begin(), &*result.begin() + result.size());
if ((!result.empty()) && (result[0] == s_delim))
break;
std::size_t i;
for (i = 0; i < result.size(); ++i)
{
if (result[i] == s_delim)
break;
}
result.erase(i);
break;
}
if (result.empty())
result = std::wstring(1, char(0));
return result;
}
inline c_regex_traits<wchar_t>::char_class_type BOOST_REGEX_CALL c_regex_traits<wchar_t>::lookup_classname(const wchar_t* p1, const wchar_t* p2)
{
using namespace BOOST_REGEX_DETAIL_NS;
static const char_class_type masks[] =
{
0,
char_class_alnum,
char_class_alpha,
char_class_blank,
char_class_cntrl,
char_class_digit,
char_class_digit,
char_class_graph,
char_class_horizontal,
char_class_lower,
char_class_lower,
char_class_print,
char_class_punct,
char_class_space,
char_class_space,
char_class_upper,
char_class_unicode,
char_class_upper,
char_class_vertical,
char_class_alnum | char_class_word,
char_class_alnum | char_class_word,
char_class_xdigit,
};
int idx = ::boost::BOOST_REGEX_DETAIL_NS::get_default_class_id(p1, p2);
if (idx < 0)
{
std::wstring s(p1, p2);
for (std::wstring::size_type i = 0; i < s.size(); ++i)
s[i] = (std::towlower)(s[i]);
idx = ::boost::BOOST_REGEX_DETAIL_NS::get_default_class_id(&*s.begin(), &*s.begin() + s.size());
}
BOOST_REGEX_ASSERT(idx + 1 < static_cast<int>(sizeof(masks) / sizeof(masks[0])));
return masks[idx + 1];
}
inline bool BOOST_REGEX_CALL c_regex_traits<wchar_t>::isctype(wchar_t c, char_class_type mask)
{
using namespace BOOST_REGEX_DETAIL_NS;
return
((mask & char_class_space) && (std::iswspace)(c))
|| ((mask & char_class_print) && (std::iswprint)(c))
|| ((mask & char_class_cntrl) && (std::iswcntrl)(c))
|| ((mask & char_class_upper) && (std::iswupper)(c))
|| ((mask & char_class_lower) && (std::iswlower)(c))
|| ((mask & char_class_alpha) && (std::iswalpha)(c))
|| ((mask & char_class_digit) && (std::iswdigit)(c))
|| ((mask & char_class_punct) && (std::iswpunct)(c))
|| ((mask & char_class_xdigit) && (std::iswxdigit)(c))
|| ((mask & char_class_blank) && (std::iswspace)(c) && !::boost::BOOST_REGEX_DETAIL_NS::is_separator(c))
|| ((mask & char_class_word) && (c == '_'))
|| ((mask & char_class_unicode) && (c & ~static_cast<wchar_t>(0xff)))
|| ((mask & char_class_vertical) && (::boost::BOOST_REGEX_DETAIL_NS::is_separator(c) || (c == L'\v')))
|| ((mask & char_class_horizontal) && (std::iswspace)(c) && !::boost::BOOST_REGEX_DETAIL_NS::is_separator(c) && (c != L'\v'));
}
inline c_regex_traits<wchar_t>::string_type BOOST_REGEX_CALL c_regex_traits<wchar_t>::lookup_collatename(const wchar_t* p1, const wchar_t* p2)
{
#ifdef BOOST_MSVC
#pragma warning(push)
#pragma warning(disable: 4244)
#endif
std::string name(p1, p2);
#ifdef BOOST_MSVC
#pragma warning(pop)
#endif
name = ::boost::BOOST_REGEX_DETAIL_NS::lookup_default_collate_name(name);
if (!name.empty())
return string_type(name.begin(), name.end());
if (p2 - p1 == 1)
return string_type(1, *p1);
return string_type();
}
inline int BOOST_REGEX_CALL c_regex_traits<wchar_t>::value(wchar_t c, int radix)
{
#ifdef BOOST_BORLANDC
// workaround for broken wcstol:
if ((std::iswxdigit)(c) == 0)
return -1;
#endif
wchar_t b[2] = { c, '\0', };
wchar_t* ep;
int result = std::wcstol(b, &ep, radix);
if (ep == b)
return -1;
return result;
}
#endif
}
#ifdef BOOST_MSVC
#pragma warning(push)
#pragma warning(disable: 4103)
#endif
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_SUFFIX
#endif
#ifdef BOOST_MSVC
#pragma warning(pop)
#endif
#endif

Some files were not shown because too many files have changed in this diff Show More