diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml new file mode 100644 index 0000000..2c7451d --- /dev/null +++ b/.idea/inspectionProfiles/profiles_settings.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/app/src/main/cpp/CMakeLists.txt b/app/src/main/cpp/CMakeLists.txt new file mode 100644 index 0000000..12e47ad --- /dev/null +++ b/app/src/main/cpp/CMakeLists.txt @@ -0,0 +1,17 @@ +cmake_minimum_required(VERSION 3.22.1) + +project(zygisk) + +include_directories(${CMAKE_SOURCE_DIR}/libcxx/include) + +link_libraries(${CMAKE_SOURCE_DIR}/libcxx/${CMAKE_ANDROID_ARCH_ABI}.a) + +add_library(${CMAKE_PROJECT_NAME} SHARED ${CMAKE_SOURCE_DIR}/main.cpp) + +add_subdirectory(${CMAKE_SOURCE_DIR}/Dobby) + +SET_OPTION(Plugin.Android.BionicLinkerUtil ON) + +target_compile_features(${CMAKE_PROJECT_NAME} PRIVATE c_std_23 cxx_std_23) + +target_link_libraries(${CMAKE_PROJECT_NAME} PRIVATE log dobby_static) \ No newline at end of file diff --git a/app/src/main/cpp/Dobby/.clang-format b/app/src/main/cpp/Dobby/.clang-format new file mode 100644 index 0000000..17d6bc4 --- /dev/null +++ b/app/src/main/cpp/Dobby/.clang-format @@ -0,0 +1,18 @@ +BasedOnStyle: LLVM + +IndentWidth: 2 +TabWidth: 2 +UseTab: Never +ColumnLimit: 120 + +FixNamespaceComments: true + +# default is false +#AlignConsecutiveMacros: true +#AlignConsecutiveAssignments: true +#AlignConsecutiveDeclarations: true + +# default is true +ReflowComments: false +SortIncludes : false +AllowShortFunctionsOnASingleLine: false \ No newline at end of file diff --git a/app/src/main/cpp/Dobby/.github/workflows/Builder.yaml b/app/src/main/cpp/Dobby/.github/workflows/Builder.yaml new file mode 100644 index 0000000..761ff86 --- /dev/null +++ b/app/src/main/cpp/Dobby/.github/workflows/Builder.yaml @@ -0,0 +1,114 @@ +name: Builder + +on: + push: + branches: + - master + +env: + CMAKE_VERSION: 3.25.2 + LLVM_VERSION: 15.0.6 + NDK_VERSION: r25b + +jobs: + delete_latest_release: + runs-on: ubuntu-latest + steps: + - name: checkout master + uses: actions/checkout@master + + - name: delete latest release + uses: dev-drprasad/delete-tag-and-release@v0.2.1 + with: + delete_release: true + tag_name: latest + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + linux_and_android: + runs-on: ubuntu-latest + needs: delete_latest_release + steps: + - name: checkout master + uses: actions/checkout@master + + - name: init linux cross compile env + run: | + sh scripts/setup_linux_cross_compile.sh + mkdir -p artifact + shell: bash + + - name: compile linux + run: | + python3 scripts/platform_builder.py --platform=linux --arch=all --cmake_dir=$HOME/opt/cmake-$CMAKE_VERSION --llvm_dir=$HOME/opt/llvm-$LLVM_VERSION + cp include/dobby.h build/linux + tar -zcvf build/dobby-linux-all.tar.gz build/linux + cp build/dobby-linux-all.tar.gz artifact/ + + shell: bash + + - name: compile android + run: | + python3 scripts/platform_builder.py --platform=android --arch=all --cmake_dir=$HOME/opt/cmake-$CMAKE_VERSION --llvm_dir=$HOME/opt/llvm-$LLVM_VERSION --android_ndk_dir=$HOME/opt/ndk-$NDK_VERSION + cp include/dobby.h build/android + tar -zcvf build/dobby-android-all.tar.gz build/android + cp build/dobby-android-all.tar.gz artifact/ + shell: bash + + - name: print output + run: | + ls -lha . + + - name: update release + uses: ncipollo/release-action@v1 + with: + token: ${{ secrets.GITHUB_TOKEN }} + tag: latest + body: "a lightweight, multi-platform, multi-architecture exploit hook framework" + artifacts: "build/dobby-linux-all.tar.gz,build/dobby-android-all.tar.gz" + allowUpdates: true + replacesArtifacts: true + + macos_and_iphoneos: + runs-on: macos-latest + needs: delete_latest_release + steps: + - name: checkout dev + uses: actions/checkout@master + + - name: init macos compile env + run: | + sh scripts/setup_macos_cross_compile.sh + mkdir -p artifact + shell: bash + + - name: compile macos + run: | + python3 scripts/platform_builder.py --platform=macos --arch=all --cmake_dir=$HOME/opt/cmake-$CMAKE_VERSION/CMake.app/Contents + cp include/dobby.h build/macos + tar -zcvf build/dobby-macos-all.tar.gz build/macos + cp build/dobby-macos-all.tar.gz artifact/ + + shell: bash + + - name: compile iphoneos + run: | + python3 scripts/platform_builder.py --platform=iphoneos --arch=all --cmake_dir=$HOME/opt/cmake-$CMAKE_VERSION/CMake.app/Contents + cp include/dobby.h build/iphoneos + tar -zcvf build/dobby-iphoneos-all.tar.gz build/iphoneos + cp build/dobby-iphoneos-all.tar.gz artifact/ + shell: bash + + - name: print output + run: | + ls -lha . + + - name: update release + uses: ncipollo/release-action@v1 + with: + token: ${{ secrets.GITHUB_TOKEN }} + tag: latest + body: "a lightweight, multi-platform, multi-architecture exploit hook framework" + artifacts: "build/dobby-macos-all.tar.gz,build/dobby-iphoneos-all.tar.gz" + allowUpdates: true + replacesArtifacts: true \ No newline at end of file diff --git a/app/src/main/cpp/Dobby/.gitignore b/app/src/main/cpp/Dobby/.gitignore new file mode 100644 index 0000000..4bbed76 --- /dev/null +++ b/app/src/main/cpp/Dobby/.gitignore @@ -0,0 +1,80 @@ +.DS_Store +.idea/ +*-build*/ +build-output/ + +CMakeLists.txt.user +CMakeCache.txt +CMakeFiles +CMakeScripts +Testing +Makefile +cmake_install.cmake +install_manifest.txt +compile_commands.json +CTestTestfile.cmake +_deps + +## Build generated +build/ +DerivedData/ + +## Various settings +*.pbxuser +!default.pbxuser +*.mode1v3 +!default.mode1v3 +*.mode2v3 +!default.mode2v3 +*.perspectivev3 +!default.perspectivev3 +xcuserdata/ + +## Other +*.moved-aside +*.xccheckout +*.xcscmblueprint + +## Obj-C/Swift specific +*.hmap +*.ipa +*.dSYM.zip +*.dSYM + +# Prerequisites +*.d + +# Compiled Object files +*.slo +*.lo +*.o +*.obj + +# Precompiled Headers +*.gch +*.pch + +# Compiled Dynamic libraries +*.so +*.dylib +*.dll + +# Fortran module files +*.mod +*.smod + +# Compiled Static libraries +*.lai +*.la +*.a +*.lib + +# Executables +*.exe +*.out +*.app + +# Prefab +/prefab/**/*.a +/prefab/**/*.h +/AndroidManifest.xml diff --git a/app/src/main/cpp/Dobby/.vscode/c_cpp_properties.json b/app/src/main/cpp/Dobby/.vscode/c_cpp_properties.json new file mode 100644 index 0000000..c624a58 --- /dev/null +++ b/app/src/main/cpp/Dobby/.vscode/c_cpp_properties.json @@ -0,0 +1,74 @@ +{ + "configurations": [ + { + "name": "Mac", + "includePath": [ + "/usr/local/include", + "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1", + "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include", + "${workspaceRoot}" + ], + "defines": [], + "intelliSenseMode": "clang-x64", + "browse": { + "path": [ + "/usr/local/include", + "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include", + "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1", + "${workspaceRoot}" + ], + "limitSymbolsToIncludedHeaders": true, + "databaseFilename": "" + }, + "macFrameworkPath": [ + "/System/Library/Frameworks", + "/Library/Frameworks" + ], + "compilerPath": "/usr/bin/clang", + "cStandard": "c11", + "cppStandard": "c++11", + "configurationProvider": "vector-of-bool.cmake-tools", + "compileCommands": "${workspaceRoot}/ninja-build/compile_commands.json" + }, + { + "name": "Linux", + "includePath": [ + "/usr/include", + "/usr/local/include", + "${workspaceRoot}" + ], + "defines": [], + "intelliSenseMode": "clang-x64", + "browse": { + "path": [ + "/usr/include", + "/usr/local/include", + "${workspaceRoot}" + ], + "limitSymbolsToIncludedHeaders": true, + "databaseFilename": "" + } + }, + { + "name": "Win32", + "includePath": [ + "C:/Program Files (x86)/Microsoft Visual Studio 14.0/VC/include", + "${workspaceRoot}" + ], + "defines": [ + "_DEBUG", + "UNICODE" + ], + "intelliSenseMode": "msvc-x64", + "browse": { + "path": [ + "C:/Program Files (x86)/Microsoft Visual Studio 14.0/VC/include/*", + "${workspaceRoot}" + ], + "limitSymbolsToIncludedHeaders": true, + "databaseFilename": "" + } + } + ], + "version": 4 +} \ No newline at end of file diff --git a/app/src/main/cpp/Dobby/.vscode/launch.json b/app/src/main/cpp/Dobby/.vscode/launch.json new file mode 100644 index 0000000..36ab19f --- /dev/null +++ b/app/src/main/cpp/Dobby/.vscode/launch.json @@ -0,0 +1,17 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "name": "(lldb) Launch", + "type": "cppdbg", + "request": "launch", + "program": "enter program name, for example ${workspaceRoot}/a.out", + "args": [], + "stopAtEntry": false, + "cwd": "${workspaceRoot}", + "environment": [], + "externalConsole": true, + "MIMode": "lldb" + } + ] +} \ No newline at end of file diff --git a/app/src/main/cpp/Dobby/.vscode/settings.json b/app/src/main/cpp/Dobby/.vscode/settings.json new file mode 100644 index 0000000..e925cff --- /dev/null +++ b/app/src/main/cpp/Dobby/.vscode/settings.json @@ -0,0 +1,121 @@ +{ + "files.autoSave": "onFocusChange", + "files.autoSaveDelay": 3000, + "editor.formatOnSave": true, + "cmake.environment": { + "ANDROID_NDK": "/Users/jmpews/Library/Android/sdk/ndk-bundle" + }, + "cmake.configureArgs": [ + "-DCMAKE_SYSTEM_NAME=Android", + "-DCMAKE_ANDROID_ARCH_ABI=armeabi-v7a", + "-DCMAKE_ANDROID_NDK=/Users/jmpews/Library/Android/sdk/ndk/21.3.6528147", + "-DCMAKE_SYSTEM_VERSION=16", + "-DCMAKE_ANDROID_NDK_TOOLCHAIN_VERSION=clang" + ], + "cmake.buildArgs": [], + "cmake.buildToolArgs": [], + "cmake.parallelJobs": 1, + "files.associations": { + "stack": "cpp", + "regex": "cpp", + "bitset": "cpp", + "functional": "cpp", + "iterator": "cpp", + "memory": "cpp", + "__bit_reference": "cpp", + "__functional_base": "cpp", + "algorithm": "cpp", + "atomic": "cpp", + "chrono": "cpp", + "deque": "cpp", + "optional": "cpp", + "limits": "cpp", + "locale": "cpp", + "ratio": "cpp", + "system_error": "cpp", + "tuple": "cpp", + "type_traits": "cpp", + "vector": "cpp", + "utility": "cpp", + "__functional_03": "cpp", + "__locale": "cpp", + "__hash_table": "cpp", + "__split_buffer": "cpp", + "__tree": "cpp", + "hash_map": "cpp", + "hash_set": "cpp", + "map": "cpp", + "set": "cpp", + "string": "cpp", + "string_view": "cpp", + "unordered_map": "cpp", + "unordered_set": "cpp", + "initializer_list": "cpp", + "hashtable": "cpp", + "__config": "cpp", + "__nullptr": "cpp", + "cstddef": "cpp", + "exception": "cpp", + "new": "cpp", + "stdexcept": "cpp", + "typeinfo": "cpp", + "*.tcc": "cpp", + "xstring": "cpp", + "xlocmon": "cpp", + "xtr1common": "cpp", + "list": "cpp", + "xhash": "cpp", + "xtree": "cpp", + "xutility": "cpp", + "iosfwd": "cpp", + "__debug": "cpp", + "__mutex_base": "cpp", + "__string": "cpp", + "__threading_support": "cpp", + "__tuple": "cpp", + "cctype": "cpp", + "cstdarg": "cpp", + "cstdint": "cpp", + "cstdio": "cpp", + "cstdlib": "cpp", + "cstring": "cpp", + "ctime": "cpp", + "cwchar": "cpp", + "cwctype": "cpp", + "ios": "cpp", + "iostream": "cpp", + "istream": "cpp", + "mutex": "cpp", + "ostream": "cpp", + "streambuf": "cpp", + "cmath": "cpp", + "array": "cpp", + "fstream": "cpp", + "stdio.h": "c", + "__functional_base_03": "cpp", + "filesystem": "cpp", + "queue": "cpp", + "random": "cpp", + "__errc": "cpp", + "__node_handle": "cpp", + "bit": "cpp", + "complex": "cpp", + "iomanip": "cpp", + "sstream": "cpp", + "stdarg.h": "c", + "clocale": "cpp", + "codecvt": "cpp", + "condition_variable": "cpp", + "numeric": "cpp", + "shared_mutex": "cpp", + "thread": "cpp", + "memory_resource": "cpp", + "cinttypes": "cpp", + "shared_cache_internal.h": "c", + "coroutine": "cpp", + "__bits": "cpp" + }, + "C_Cpp.configurationWarnings": "Disabled", + "lldb.showDisassembly": "auto", + "lldb.dereferencePointers": true, +} \ No newline at end of file diff --git a/app/src/main/cpp/Dobby/.vscode/tags b/app/src/main/cpp/Dobby/.vscode/tags new file mode 100644 index 0000000..db0ba7e --- /dev/null +++ b/app/src/main/cpp/Dobby/.vscode/tags @@ -0,0 +1,13 @@ +!_TAG_FILE_FORMAT 2 /extended format; --format=1 will not append ;" to lines/ +!_TAG_FILE_SORTED 1 /0=unsorted, 1=sorted, 2=foldcase/ +!_TAG_PROGRAM_AUTHOR Darren Hiebert /dhiebert@users.sourceforge.net/ +!_TAG_PROGRAM_NAME Exuberant Ctags // +!_TAG_PROGRAM_URL http://ctags.sourceforge.net /official site/ +!_TAG_PROGRAM_VERSION 5.8 // +HookZzCodeSegment ../tools/zzsolidifyhook.py /^HookZzCodeSegment = [$/;" kind:variable line:4 +lief ../tools/zzsolidifyhook.py /^import lief$/;" kind:namespace line:2 +new_target_file ../tools/zzsolidifyhook.py /^new_target_file = "\/Users\/jmpews\/Desktop\/test\/test.hook.dylib"$/;" kind:variable line:31 +target_file ../tools/zzsolidifyhook.py /^target_file = "\/Users\/jmpews\/Desktop\/test\/test.dylib"$/;" kind:variable line:30 +zz_macho_get_segment_with_name ../tools/zzsolidifyhook.py /^def zz_macho_get_segment_with_name(target_parsed, seg_name):$/;" kind:function line:13 +zz_macho_insert_segment ../tools/zzsolidifyhook.py /^def zz_macho_insert_segment(target_file, new_target_file):$/;" kind:function line:20 +zzsolidifyhook.py ../tools/zzsolidifyhook.py 1;" kind:file line:1 diff --git a/app/src/main/cpp/Dobby/CMakeLists.txt b/app/src/main/cpp/Dobby/CMakeLists.txt new file mode 100644 index 0000000..2e6cbd4 --- /dev/null +++ b/app/src/main/cpp/Dobby/CMakeLists.txt @@ -0,0 +1,407 @@ +cmake_minimum_required(VERSION 3.5) +project(Dobby) +enable_language(ASM) + +include(cmake/Util.cmake) +include(cmake/Macros.cmake) +include(cmake/build_environment_check.cmake) +include(cmake/auto_source_group.cmake) +include(cmake/xcode_generator_helper.cmake) + +set(CMAKE_CXX_STANDARD 11) +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_C_STANDARD 11) + +auto_source_group("." "auto-source-group" "\\.(cc|cpp|c|h)$") + +# --- options + +option(DOBBY_DEBUG "Enable debug logging" OFF) + +option(NearBranch "Enable near branch trampoline" ON) + +option(FullFloatingPointRegisterPack "Save and pack all floating-point registers" OFF) + +option(Plugin.SymbolResolver "Enable symbol resolver" ON) + +option(Plugin.ImportTableReplace "Enable import table replace " OFF) + +option(Plugin.Android.BionicLinkerUtil "Enable android bionic linker util" OFF) + +option(DOBBY_BUILD_EXAMPLE "Build example" OFF) + +option(DOBBY_BUILD_TEST "Build test" OFF) + +# --- private +option(DOBBY_BUILD_KERNEL_MODE "Build xnu kernel mode" OFF) + +option(Private.Obfuscation "Enable llvm obfuscation" OFF) + +if ((NOT DEFINED CMAKE_BUILD_TYPE) OR (CMAKE_BUILD_TYPE STREQUAL "Debug")) + set(DOBBY_DEBUG ON) +endif () + + +set(compile_definitions "") + +# for arm64, allow access q8 - q31 +if (FullFloatingPointRegisterPack) + set(compile_definitions "${compile_definitions} -DFULL_FLOATING_POINT_REGISTER_PACK") +endif () + +if (DOBBY_BUILD_KERNEL_MODE) + set(compile_definitions "${compile_definitions} -DBUILDING_KERNEL") +endif () + +if (DOBBY_DEBUG) + set(compile_definitions "${compile_definitions} -DDOBBY_DEBUG") +else () + set(compile_definitions "${compile_definitions} -DDOBBY_LOGGING_DISABLE") +endif () + +if (CMAKE_GENERATOR STREQUAL Xcode) +endif () + +include(cmake/compiler_and_linker.cmake) + +message(STATUS "[Dobby] CMAKE_BUILD_TYPE: ${CMAKE_BUILD_TYPE}") +message(STATUS "[Dobby] DOBBY_DEBUG: ${DOBBY_DEBUG}") +message(STATUS "[Dobby] NearBranch: ${NearBranch}") +message(STATUS "[Dobby] FullFloatingPointRegisterPack: ${FullFloatingPointRegisterPack}") +message(STATUS "[Dobby] Plugin.SymbolResolver: ${Plugin.SymbolResolver}") +message(STATUS "[Dobby] Plugin.ImportTableReplace: ${Plugin.ImportTableReplace}") +message(STATUS "[Dobby] Plugin.Android.BionicLinkerUtil: ${Plugin.Android.BionicLinkerUtil}") +message(STATUS "[Dobby] DOBBY_BUILD_EXAMPLE: ${DOBBY_BUILD_EXAMPLE}") +message(STATUS "[Dobby] DOBBY_BUILD_TEST: ${DOBBY_BUILD_TEST}") +message(STATUS "[Dobby] DOBBY_BUILD_KERNEL_MODE: ${DOBBY_BUILD_KERNEL_MODE}") +message(STATUS "[Dobby] Private.Obfuscation: ${Private.Obfuscation}") + +# --- + +include_directories( + . + ./include + ./source + source/dobby + + ./external + ./external/logging + + ./builtin-plugin +) + +if (SYSTEM.Darwin AND DOBBY_BUILD_KERNEL_MODE) + include_directories( + source/Backend/KernelMode + ) +else () + include_directories( + source/Backend/UserMode + ) +endif () + +# --- + +set(DOBBY_DIR ${CMAKE_CURRENT_SOURCE_DIR}) +set(dobby.SOURCE_FILE_LIST ${dobby.SOURCE_FILE_LIST} + # cpu + source/core/arch/CpuFeature.cc + source/core/arch/CpuRegister.cc + + # assembler + source/core/assembler/assembler.cc + source/core/assembler/assembler-arm.cc + source/core/assembler/assembler-arm64.cc + source/core/assembler/assembler-ia32.cc + source/core/assembler/assembler-x64.cc + + # codegen + source/core/codegen/codegen-arm.cc + source/core/codegen/codegen-arm64.cc + source/core/codegen/codegen-ia32.cc + source/core/codegen/codegen-x64.cc + + # memory kit + source/MemoryAllocator/CodeBuffer/CodeBufferBase.cc + source/MemoryAllocator/AssemblyCodeBuilder.cc + source/MemoryAllocator/MemoryAllocator.cc + + # instruction relocation + source/InstructionRelocation/arm/InstructionRelocationARM.cc + source/InstructionRelocation/arm64/InstructionRelocationARM64.cc + source/InstructionRelocation/x86/InstructionRelocationX86.cc + source/InstructionRelocation/x86/InstructionRelocationX86Shared.cc + source/InstructionRelocation/x64/InstructionRelocationX64.cc + source/InstructionRelocation/x86/x86_insn_decode/x86_insn_decode.c + + # intercept routing + source/InterceptRouting/InterceptRouting.cpp + + # intercept routing trampoline + source/TrampolineBridge/Trampoline/arm/trampoline_arm.cc + source/TrampolineBridge/Trampoline/arm64/trampoline_arm64.cc + source/TrampolineBridge/Trampoline/x86/trampoline_x86.cc + source/TrampolineBridge/Trampoline/x64/trampoline_x64.cc + + # closure trampoline bridge - arm + source/TrampolineBridge/ClosureTrampolineBridge/common_bridge_handler.cc + source/TrampolineBridge/ClosureTrampolineBridge/arm/helper_arm.cc + source/TrampolineBridge/ClosureTrampolineBridge/arm/closure_bridge_arm.cc + source/TrampolineBridge/ClosureTrampolineBridge/arm/ClosureTrampolineARM.cc + # closure trampoline bridge - arm64 + source/TrampolineBridge/ClosureTrampolineBridge/arm64/helper_arm64.cc + source/TrampolineBridge/ClosureTrampolineBridge/arm64/closure_bridge_arm64.cc + source/TrampolineBridge/ClosureTrampolineBridge/arm64/ClosureTrampolineARM64.cc + # closure trampoline bridge - x86 + source/TrampolineBridge/ClosureTrampolineBridge/x86/helper_x86.cc + source/TrampolineBridge/ClosureTrampolineBridge/x86/closure_bridge_x86.cc + source/TrampolineBridge/ClosureTrampolineBridge/x86/ClosureTrampolineX86.cc + # closure trampoline bridge - x64 + source/TrampolineBridge/ClosureTrampolineBridge/x64/helper_x64.cc + source/TrampolineBridge/ClosureTrampolineBridge/x64/closure_bridge_x64.cc + source/TrampolineBridge/ClosureTrampolineBridge/x64/ClosureTrampolineX64.cc + + source/InterceptRouting/Routing/InstructionInstrument/InstructionInstrument.cc + source/InterceptRouting/Routing/InstructionInstrument/RoutingImpl.cc + source/InterceptRouting/Routing/InstructionInstrument/instrument_routing_handler.cc + + source/InterceptRouting/Routing/FunctionInlineHook/FunctionInlineHook.cc + source/InterceptRouting/Routing/FunctionInlineHook/RoutingImpl.cc + + # plugin register + source/InterceptRouting/RoutingPlugin/RoutingPlugin.cc + + # main + source/dobby.cpp + source/Interceptor.cpp + source/InterceptEntry.cpp + ) + +if (SYSTEM.Darwin AND DOBBY_BUILD_KERNEL_MODE) + set(dobby.SOURCE_FILE_LIST ${dobby.SOURCE_FILE_LIST} + # platform util + source/Backend/KernelMode/PlatformUtil/Darwin/ProcessRuntimeUtility.cc + + # kernel mode - platform interface + source/Backend/KernelMode/UnifiedInterface/platform-darwin.cc + source/Backend/KernelMode/UnifiedInterface/exec_mem_placeholder.asm + + # kernel mode - executable memory + source/Backend/KernelMode/ExecMemory/code-patch-tool-darwin.cc + source/Backend/KernelMode/ExecMemory/clear-cache-tool-all.c + ) +elseif (SYSTEM.Darwin) + set(dobby.SOURCE_FILE_LIST ${dobby.SOURCE_FILE_LIST} + # platform util + source/Backend/UserMode/PlatformUtil/Darwin/ProcessRuntimeUtility.cc + + # user mode - platform interface + source/Backend/UserMode/UnifiedInterface/platform-posix.cc + + # user mode - executable memory + source/Backend/UserMode/ExecMemory/code-patch-tool-darwin.cc + source/Backend/UserMode/ExecMemory/clear-cache-tool-all.c + ) + +elseif (SYSTEM.Linux OR SYSTEM.Android) + set(dobby.SOURCE_FILE_LIST ${dobby.SOURCE_FILE_LIST} + # platform util + source/Backend/UserMode/PlatformUtil/Linux/ProcessRuntimeUtility.cc + + # user mode - platform interface + source/Backend/UserMode/UnifiedInterface/platform-posix.cc + + # user mode - executable memory + source/Backend/UserMode/ExecMemory/code-patch-tool-posix.cc + source/Backend/UserMode/ExecMemory/clear-cache-tool-all.c + ) +elseif (SYSTEM.Windows) + set(dobby.SOURCE_FILE_LIST ${dobby.SOURCE_FILE_LIST} + # platform util + source/Backend/UserMode/PlatformUtil/Windows/ProcessRuntimeUtility.cc + + # user mode - platform interface + source/Backend/UserMode/UnifiedInterface/platform-windows.cc + + # user mode - executable memory + source/Backend/UserMode/ExecMemory/code-patch-tool-windows.cc + source/Backend/UserMode/ExecMemory/clear-cache-tool-all.c + ) +endif () + +if (PROCESSOR.X86_64 OR PROCESSOR.X86) + set(NearBranch ON) +endif () + +# --- + +if (0 AND SYSTEM.iOS AND (NOT DOBBY_BUILD_KERNEL_MODE)) + include_directories( + source/Backend/UserMode/ExecMemory/substrated + ) + set(compile_definitions "${compile_definitions} -DCODE_PATCH_WITH_SUBSTRATED") + set(dobby.SOURCE_FILE_LIST ${dobby.SOURCE_FILE_LIST} + source/Backend/UserMode/ExecMemory/substrated/mach_interface_support + ) +endif () + +# ----- instrument ----- + +if (FunctionWrapper) + set(dobby.SOURCE_FILE_LIST ${dobby.SOURCE_FILE_LIST} + # user mode - multi thread support + # source/UserMode/MultiThreadSupport/ThreadSupport.cpp + # source/UserMode/Thread/PlatformThread.cc + # source/UserMode/Thread/platform-thread-${platform1}.cc + ) + message(FATAL_ERROR "[!] FunctionWrapper plugin is not supported") +endif () + +# --- + +if (NearBranch) + set(dobby.SOURCE_FILE_LIST ${dobby.SOURCE_FILE_LIST} + source/InterceptRouting/RoutingPlugin/NearBranchTrampoline/near_trampoline_arm64.cc + source/InterceptRouting/RoutingPlugin/NearBranchTrampoline/NearBranchTrampoline.cc + source/MemoryAllocator/NearMemoryAllocator.cc) +endif () + +# --- + +# add logging library +add_subdirectory(external/logging) +get_target_property(logging.SOURCE_FILE_LIST logging SOURCES) + +# add osbase library +add_subdirectory(external/osbase) + +# --- + +if (Plugin.SymbolResolver) + include_directories(builtin-plugin/SymbolResolver) + add_subdirectory(builtin-plugin/SymbolResolver) + get_target_property(symbol_resolver.SOURCE_FILE_LIST dobby_symbol_resolver SOURCES) + set(dobby.plugin.SOURCE_FILE_LIST ${dobby.plugin.SOURCE_FILE_LIST} + ${symbol_resolver.SOURCE_FILE_LIST} + ) +endif () + +# --- + +set(dobby.HEADER_FILE_LIST + include/dobby.h + ) + +# --- + +# add build version +string(TIMESTAMP TODAY "%Y%m%d") +set(VERSION_REVISION "-${TODAY}") +if (EXISTS "${CMAKE_SOURCE_DIR}/.git") + execute_process( + COMMAND git rev-parse --short --verify HEAD + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} + OUTPUT_VARIABLE VERSION_COMMIT_HASH + OUTPUT_STRIP_TRAILING_WHITESPACE + ) + if (VERSION_COMMIT_HASH) + set(VERSION_REVISION "${VERSION_REVISION}-${VERSION_COMMIT_HASH}") + endif () +endif () +set(DOBBY_BUILD_VERSION "Dobby${VERSION_REVISION}") +set(compile_definitions "${compile_definitions} -D__DOBBY_BUILD_VERSION__=\"${DOBBY_BUILD_VERSION}\"") +message(STATUS "[Dobby] ${DOBBY_BUILD_VERSION}") + +# --- + +add_library(dobby SHARED + ${dobby.HEADER_FILE_LIST} + ${dobby.SOURCE_FILE_LIST} + ${logging.SOURCE_FILE_LIST} + ${misc_helper.SOURCE_FILE_LIST} + ${dobby.plugin.SOURCE_FILE_LIST} + ) + +target_include_directories(dobby PUBLIC + include + ) + +# --- + +add_library(dobby_static STATIC + ${dobby.HEADER_FILE_LIST} + ${dobby.SOURCE_FILE_LIST} + ${logging.SOURCE_FILE_LIST} + ${misc_helper.SOURCE_FILE_LIST} + ${dobby.plugin.SOURCE_FILE_LIST} + ) + +target_include_directories(dobby_static PUBLIC + include + ) + +set_target_properties(dobby_static + PROPERTIES OUTPUT_NAME "dobby" + ) + +# --- + +set_target_properties(dobby + PROPERTIES + LINK_FLAGS "${linker_flags}" + COMPILE_FLAGS "${compiler_flags}" + ) + +set_target_properties(dobby_static + PROPERTIES + COMPILE_FLAGS "${compiler_flags}" + ) + +target_compile_definitions(dobby PRIVATE + "COMPILE_DEFINITIONS ${compile_definitions}" + ) +target_compile_definitions(dobby_static PRIVATE + "COMPILE_DEFINITIONS ${compile_definitions}" + ) + +# --- + +if (Private.Obfuscation) + set(linker_flags "${linker_flags} -Wl,-mllvm -Wl,-obfuscator-conf=all") +endif () + +# --- + +if (SYSTEM.Android) + target_link_libraries(dobby log) + if (PROCESSOR.ARM) + set_target_properties(dobby + PROPERTIES + ANDROID_ARM_MODE arm + ) + set_target_properties(dobby_static + PROPERTIES + ANDROID_ARM_MODE arm + ) + endif () +endif () + +if (SYSTEM.Linux) + target_link_libraries(dobby dl) +endif () + +# --- + +if (DOBBY_BUILD_EXAMPLE AND (NOT DOBBY_BUILD_KERNEL_MODE)) + add_subdirectory(examples) +endif () + +if (DOBBY_BUILD_TEST AND (NOT DOBBY_BUILD_KERNEL_MODE)) + add_subdirectory(tests) +endif () + +# --- + +if (SYSTEM.Darwin AND (NOT DOBBY_BUILD_KERNEL_MODE)) + include(cmake/platform/platform-darwin.cmake) +endif () \ No newline at end of file diff --git a/app/src/main/cpp/Dobby/LICENSE b/app/src/main/cpp/Dobby/LICENSE new file mode 100644 index 0000000..f49a4e1 --- /dev/null +++ b/app/src/main/cpp/Dobby/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. \ No newline at end of file diff --git a/app/src/main/cpp/Dobby/README.md b/app/src/main/cpp/Dobby/README.md new file mode 100644 index 0000000..c0c0195 --- /dev/null +++ b/app/src/main/cpp/Dobby/README.md @@ -0,0 +1,26 @@ +## Dobby + +[![Contact me Telegram](https://img.shields.io/badge/Contact%20me-Telegram-blue.svg)](https://t.me/IOFramebuffer) [![Join group Telegram](https://img.shields.io/badge/Join%20group-Telegram-brightgreen.svg)](https://t.me/dobby_group) + +Dobby a lightweight, multi-platform, multi-architecture exploit hook framework. + +- Minimal and modular library +- Multi-platform support(Windows/macOS/iOS/Android/Linux) +- Multiple architecture support(X86, X86-64, ARM, ARM64) + +## Compile + +[docs/compile.md](docs/compile.md) + +## Download + +[download latest library](https://github.com/jmpews/Dobby/releases/tag/latest) + +## Credits + +1. [frida-gum](https://github.com/frida/frida-gum) +2. [minhook](https://github.com/TsudaKageyu/minhook) +3. [substrate](https://github.com/jevinskie/substrate). +4. [v8](https://github.com/v8/v8) +5. [dart](https://github.com/dart-lang/sdk) +6. [vixl](https://git.linaro.org/arm/vixl.git) diff --git a/app/src/main/cpp/Dobby/README_zh-cn.md b/app/src/main/cpp/Dobby/README_zh-cn.md new file mode 100644 index 0000000..2f528b4 --- /dev/null +++ b/app/src/main/cpp/Dobby/README_zh-cn.md @@ -0,0 +1,3 @@ +## Dobby + +**待更新** \ No newline at end of file diff --git a/app/src/main/cpp/Dobby/builtin-plugin/ApplicationEventMonitor/MGCopyAnswerMonitor.cc b/app/src/main/cpp/Dobby/builtin-plugin/ApplicationEventMonitor/MGCopyAnswerMonitor.cc new file mode 100644 index 0000000..ddf2ee2 --- /dev/null +++ b/app/src/main/cpp/Dobby/builtin-plugin/ApplicationEventMonitor/MGCopyAnswerMonitor.cc @@ -0,0 +1,46 @@ +#include "./dobby_monitor.h" + +#include +#include + +#define LOG_TAG "MGCopyAnswer" + +static uintptr_t getCallFirstArg(DobbyRegisterContext *ctx) { + uintptr_t result; +#if defined(_M_X64) || defined(__x86_64__) +#if defined(_WIN32) + result = ctx->general.regs.rcx; +#else + result = ctx->general.regs.rdi; +#endif +#elif defined(__arm64__) || defined(__aarch64__) + result = ctx->general.regs.x0; +#elif defined(__arm__) + result = ctx->general.regs.r0; +#else +#error "Not Support Architecture." +#endif + return result; +} + +void common_handler(DobbyRegisterContext *ctx, const InterceptEntry *info) { + CFStringRef key_ = 0; + key_ = (CFStringRef)getCallFirstArg(ctx); + + char str_key[256] = {0}; + CFStringGetCString(key_, str_key, 256, kCFStringEncodingUTF8); + LOG("[#] MGCopyAnswer:: %s\n", str_key); +} + +#if 0 +__attribute__((constructor)) static void ctor() { + void *lib = dlopen("/usr/lib/libMobileGestalt.dylib", RTLD_NOW); + void *MGCopyAnswer_addr = DobbySymbolResolver("libMobileGestalt.dylib", "MGCopyAnswer"); + + sleep(1); + + dobby_enable_near_branch_trampoline(); + DobbyInstrument((void *)MGCopyAnswer_addr, common_handler); + dobby_disable_near_branch_trampoline(); +} +#endif diff --git a/app/src/main/cpp/Dobby/builtin-plugin/ApplicationEventMonitor/dynamic_loader_monitor.cc b/app/src/main/cpp/Dobby/builtin-plugin/ApplicationEventMonitor/dynamic_loader_monitor.cc new file mode 100644 index 0000000..3a9764d --- /dev/null +++ b/app/src/main/cpp/Dobby/builtin-plugin/ApplicationEventMonitor/dynamic_loader_monitor.cc @@ -0,0 +1,94 @@ +#include /* getenv */ +#include +#include + +#include +#include + +#include +#include + +#include +#include + +#include "dobby.h" + +#include "dobby/common.h" + +#define LOG_TAG "DynamicLoaderMonitor" + +std::unordered_map traced_dlopen_handle_list; + +static void *(*orig_dlopen)(const char *__file, int __mode); +static void *fake_dlopen(const char *__file, int __mode) { + void *result = orig_dlopen(__file, __mode); + if (result != NULL && __file) { + char *traced_filename = (char *)malloc(MAXPATHLEN); + // FIXME: strncpy + strcpy(traced_filename, __file); + INFO_LOG("[-] dlopen handle: %s", __file); + traced_dlopen_handle_list.insert(std::make_pair(result, (const char *)traced_filename)); + } + return result; +} + +static void *(*orig_loader_dlopen)(const char *filename, int flags, const void *caller_addr); +static void *fake_loader_dlopen(const char *filename, int flags, const void *caller_addr) { + void *result = orig_loader_dlopen(filename, flags, caller_addr); + if (result != NULL) { + char *traced_filename = (char *)malloc(MAXPATHLEN); + // FIXME: strncpy + strcpy(traced_filename, filename); + INFO_LOG("[-] dlopen handle: %s", filename); + traced_dlopen_handle_list.insert(std::make_pair(result, (const char *)traced_filename)); + } + return result; +} + +static const char *get_traced_filename(void *handle, bool removed) { + std::unordered_map::iterator it; + it = traced_dlopen_handle_list.find(handle); + if (it != traced_dlopen_handle_list.end()) { + if (removed) + traced_dlopen_handle_list.erase(it); + return it->second; + } + return NULL; +} + +static void *(*orig_dlsym)(void *__handle, const char *__symbol); +static void *fake_dlsym(void *__handle, const char *__symbol) { + const char *traced_filename = get_traced_filename(__handle, false); + if (traced_filename) { + INFO_LOG("[-] dlsym: %s, symbol: %s", traced_filename, __symbol); + } + return orig_dlsym(__handle, __symbol); +} + +static int (*orig_dlclose)(void *__handle); +static int fake_dlclose(void *__handle) { + const char *traced_filename = get_traced_filename(__handle, true); + if (traced_filename) { + INFO_LOG("[-] dlclose: %s", traced_filename); + free((void *)traced_filename); + } + return orig_dlclose(__handle); +} + +#if 0 +__attribute__((constructor)) static void ctor() { +#if defined(__ANDROID__) +#if 0 + void *dl = dlopen("libdl.so", RTLD_LAZY); + void *__loader_dlopen = dlsym(dl, "__loader_dlopen"); +#endif + DobbyHook((void *)DobbySymbolResolver(NULL, "__loader_dlopen"), (void *)fake_loader_dlopen, + (void **)&orig_loader_dlopen); +#else + DobbyHook((void *)DobbySymbolResolver(NULL, "dlopen"), (void *)fake_dlopen, (void **)&orig_dlopen); +#endif + + DobbyHook((void *)dlsym, (void *)fake_dlsym, (void **)&orig_dlsym); + DobbyHook((void *)dlclose, (void *)fake_dlclose, (void **)&orig_dlclose); +} +#endif diff --git a/app/src/main/cpp/Dobby/builtin-plugin/ApplicationEventMonitor/file_operation_monitor.cc b/app/src/main/cpp/Dobby/builtin-plugin/ApplicationEventMonitor/file_operation_monitor.cc new file mode 100644 index 0000000..d4f09ca --- /dev/null +++ b/app/src/main/cpp/Dobby/builtin-plugin/ApplicationEventMonitor/file_operation_monitor.cc @@ -0,0 +1,97 @@ +#include /* getenv */ +#include +#include + +#include +#include + +#include +#include + +#include + +#include "./dobby_monitor.h" + +std::unordered_map *TracedFopenFileList; + +FILE *(*orig_fopen)(const char *filename, const char *mode); +FILE *fake_fopen(const char *filename, const char *mode) { + FILE *result = NULL; + result = orig_fopen(filename, mode); + if (result != NULL) { + char *traced_filename = (char *)malloc(MAXPATHLEN); + // FIXME: strncpy + strcpy(traced_filename, filename); + std::cout << "[-] trace file: " << filename << std::endl; + TracedFopenFileList->insert(std::make_pair(result, traced_filename)); + } + return result; +} + +static const char *GetFileDescriptorTraced(FILE *stream, bool removed) { + std::unordered_map::iterator it; + it = TracedFopenFileList->find(stream); + if (it != TracedFopenFileList->end()) { + if (removed) + TracedFopenFileList->erase(it); + return it->second; + } + return NULL; +} + +size_t (*orig_fread)(void *ptr, size_t size, size_t count, FILE *stream); +size_t fake_fread(void *ptr, size_t size, size_t count, FILE *stream) { + const char *file_name = GetFileDescriptorTraced(stream, false); + if (file_name) { + LOG("[-] fread: %s, buffer: %p\n", file_name, ptr); + } + return orig_fread(ptr, size, count, stream); +} + +size_t (*orig_fwrite)(const void *ptr, size_t size, size_t count, FILE *stream); +size_t fake_fwrite(void *ptr, size_t size, size_t count, FILE *stream) { + const char *file_name = GetFileDescriptorTraced(stream, false); + if (file_name) { + LOG("[-] fwrite %s\n from %p\n", file_name, ptr); + } + return orig_fwrite(ptr, size, count, stream); +} + +__attribute__((constructor)) void __main() { + + TracedFopenFileList = new std::unordered_map(); + +#if defined(__APPLE__) +#include +#if (TARGET_OS_IPHONE || TARGET_OS_MAC) + std::ifstream file; + file.open("/System/Library/CoreServices/SystemVersion.plist"); + std::cout << file.rdbuf(); +#endif +#endif + + // DobbyHook((void *)fopen, (void *)fake_fopen, (void **)&orig_fopen); + // DobbyHook((void *)fwrite, (void *)fake_fwrite, (void **)&orig_fwrite); + // DobbyHook((void *)fread, (void *)fake_fread, (void **)&orig_fread); + + char *home = getenv("HOME"); + char *subdir = (char *)"/Library/Caches/"; + + std::string filePath = std::string(home) + std::string(subdir) + "temp.log"; + + char buffer[64]; + memset(buffer, 'B', 64); + + FILE *fd = fopen(filePath.c_str(), "w+"); + if (!fd) + std::cout << "[!] open " << filePath << "failed!\n"; + + fwrite(buffer, 64, 1, fd); + fflush(fd); + fseek(fd, 0, SEEK_SET); + memset(buffer, 0, 64); + + fread(buffer, 64, 1, fd); + + return; +} diff --git a/app/src/main/cpp/Dobby/builtin-plugin/ApplicationEventMonitor/memory_operation_instrument.cc b/app/src/main/cpp/Dobby/builtin-plugin/ApplicationEventMonitor/memory_operation_instrument.cc new file mode 100644 index 0000000..0298275 --- /dev/null +++ b/app/src/main/cpp/Dobby/builtin-plugin/ApplicationEventMonitor/memory_operation_instrument.cc @@ -0,0 +1,58 @@ +#include "./dobby_monitor.h" + +#include +#include +#include + +static uintptr_t getCallFirstArg(DobbyRegisterContext *ctx) { + uintptr_t result; +#if defined(_M_X64) || defined(__x86_64__) +#if defined(_WIN32) + result = ctx->general.regs.rcx; +#else + result = ctx->general.regs.rdi; +#endif +#elif defined(__arm64__) || defined(__aarch64__) + result = ctx->general.regs.x0; +#elif defined(__arm__) + result = ctx->general.regs.r0; +#else +#error "Not Support Architecture." +#endif + return result; +} + +void format_integer_manually(char *buf, uint64_t integer) { + int tmp = 0; + for (tmp = (int)integer; tmp > 0; tmp = (tmp >> 4)) { + buf += (tmp % 16); + buf--; + } +} + +// [ATTENTION]: +// printf will call 'malloc' internally, and will crash in a loop. +// so, use 'puts' is a better choice. +void malloc_handler(DobbyRegisterContext *ctx, const InterceptEntry *info) { + size_t size_ = 0; + size_ = getCallFirstArg(ctx); + char *buffer_ = (char *)"[-] function malloc first arg: 0x00000000.\n"; + format_integer_manually(strchr(buffer_, '.') - 1, size_); + puts(buffer_); +} + +void free_handler(DobbyRegisterContext *ctx, const InterceptEntry *info) { + uintptr_t mem_ptr; + + mem_ptr = getCallFirstArg(ctx); + + char *buffer = (char *)"[-] function free first arg: 0x00000000.\n"; + format_integer_manually(strchr(buffer, '.') - 1, mem_ptr); + puts(buffer); +} + +__attribute__((constructor)) static void ctor() { + // DobbyInstrument((void *)mmap, malloc_handler); + // DobbyInstrument((void *)free, free_handler); + return; +} diff --git a/app/src/main/cpp/Dobby/builtin-plugin/ApplicationEventMonitor/posix_file_descriptor_operation_monitor.cc b/app/src/main/cpp/Dobby/builtin-plugin/ApplicationEventMonitor/posix_file_descriptor_operation_monitor.cc new file mode 100644 index 0000000..4c0db6c --- /dev/null +++ b/app/src/main/cpp/Dobby/builtin-plugin/ApplicationEventMonitor/posix_file_descriptor_operation_monitor.cc @@ -0,0 +1,120 @@ +#include /* getenv */ +#include +#include + +#include +#include +#include + +#include + +#include +#include + +#include +#include + +#include + +#include "dobby.h" +#include "dobby/common.h" + +#define LOG_TAG "PosixFileOperationMonitor" + +std::unordered_map *posix_file_descriptors; + +int (*orig_open)(const char *pathname, int flags, ...); +int fake_open(const char *pathname, int flags, ...) { + mode_t mode = 0; + if (flags & O_CREAT) { + va_list args; + va_start(args, flags); + mode = (mode_t)va_arg(args, int); + va_end(args); + } + + int result = orig_open(pathname, flags, mode); + if (result != -1) { + char *traced_filename = (char *)malloc(MAXPATHLEN); + // FIXME: strncpy + strcpy(traced_filename, pathname); + INFO_LOG("[-] trace open handle: %s", pathname); + + if (posix_file_descriptors == NULL) { + posix_file_descriptors = new std::unordered_map(); + } + posix_file_descriptors->insert(std::make_pair(result, (const char *)traced_filename)); + } + return result; +} + +int (*orig___open)(const char *pathname, int flags, int mode); +int fake___open(const char *pathname, int flags, int mode) { + char *traced_filename = NULL; + if (pathname) { + traced_filename = (char *)malloc(MAXPATHLEN); + // FIXME: strncpy + strcpy(traced_filename, pathname); + INFO_LOG("[-] trace open handle: ", pathname); + } + int result = orig___open(pathname, flags, mode); + if (result != -1) { + if (posix_file_descriptors == NULL) { + posix_file_descriptors = new std::unordered_map(); + } + posix_file_descriptors->insert(std::make_pair(result, (const char *)traced_filename)); + } + return result; +} + +static const char *get_traced_filename(int fd, bool removed) { + if (posix_file_descriptors == NULL) + return NULL; + std::unordered_map::iterator it; + it = posix_file_descriptors->find(fd); + if (it != posix_file_descriptors->end()) { + if (removed) + posix_file_descriptors->erase(it); + return it->second; + } + return NULL; +} + +ssize_t (*orig_read)(int fd, void *buf, size_t count); +ssize_t fake_read(int fd, void *buf, size_t count) { + const char *traced_filename = get_traced_filename(fd, false); + if (traced_filename) { + INFO_LOG("[-] read: %s, buffer: %p, size: %zu", traced_filename, buf, count); + } + return orig_read(fd, buf, count); +} + +ssize_t (*orig_write)(int fd, const void *buf, size_t count); +ssize_t fake_write(int fd, const void *buf, size_t count) { + const char *traced_filename = get_traced_filename(fd, false); + if (traced_filename) { + INFO_LOG("[-] write: %s, buffer: %p, size: %zu", traced_filename, buf, count); + } + return orig_write(fd, buf, count); +} +int (*orig_close)(int fd); +int fake_close(int fd) { + const char *traced_filename = get_traced_filename(fd, true); + if (traced_filename) { + INFO_LOG("[-] close: %s", traced_filename); + free((void *)traced_filename); + } + return orig_close(fd); +} + +#if 0 +__attribute__((constructor)) static void ctor() { + DobbyHook((void *)DobbySymbolResolver(NULL, "open"), (void *)fake_open, (void **)&orig_open); + + DobbyHook((void *)DobbySymbolResolver(NULL, "write"), (void *)fake_write, (void **)&orig_write); + + DobbyHook((void *)DobbySymbolResolver(NULL, "read"), (void *)fake_read, (void **)&orig_read); + + DobbyHook((void *)DobbySymbolResolver(NULL, "close"), (void *)fake_close, (void **)&orig_close); +} +#endif diff --git a/app/src/main/cpp/Dobby/builtin-plugin/ApplicationEventMonitor/posix_socket_network_monitor.cc b/app/src/main/cpp/Dobby/builtin-plugin/ApplicationEventMonitor/posix_socket_network_monitor.cc new file mode 100644 index 0000000..a6e6e6c --- /dev/null +++ b/app/src/main/cpp/Dobby/builtin-plugin/ApplicationEventMonitor/posix_socket_network_monitor.cc @@ -0,0 +1,57 @@ +#include /* getenv */ +#include +#include + +#include +#include + +#include + +#include + +#include +#include + +std::unordered_map posix_socket_file_descriptors; + +int (*orig_bind)(int sockfd, const struct sockaddr *addr, socklen_t addrlen); +int fake_bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen) { +} + +static const char *get_traced_socket(int fd, bool removed) { + std::unordered_map::iterator it; + it = posix_socket_file_descriptors.find(fd); + if (it != posix_socket_file_descriptors.end()) { + if (removed) + posix_socket_file_descriptors.erase(it); + return it->second; + } + return NULL; +} + +int (*orig_connect)(int sockfd, const struct sockaddr *addr, socklen_t addrlen); +int fake_connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen) { + const char *traced_socket = get_traced_socket(sockfd, false); + if (traced_socket) { + INFO_LOG("[-] connect: %s\n", traced_socket); + } + return orig_connect(sockfd, addr, addrlen); +} + +ssize_t (*orig_send)(int sockfd, const void *buf, size_t len, int flags); +ssize_t fake_send(int sockfd, const void *buf, size_t len, int flags) { + const char *traced_socket = get_traced_socket(sockfd, false); + if (traced_socket) { + INFO_LOG("[-] send: %s, buf: %p, len: %zu\n", traced_socket, buf, len); + } + return orig_send(sockfd, buf, len, flags); +} + +ssize_t (*orig_recv)(int sockfd, void *buf, size_t len, int flags); +ssize_t fake_recv(int sockfd, void *buf, size_t len, int flags) { + const char *traced_socket = get_traced_socket(sockfd, false); + if (traced_socket) { + INFO_LOG("[-] recv: %s, buf: %p, len: %zu\n", traced_socket, buf, len); + } + return orig_recv(sockfd, buf, len, flags); +} \ No newline at end of file diff --git a/app/src/main/cpp/Dobby/builtin-plugin/BionicLinkerUtil/bionic_linker_demo.cc b/app/src/main/cpp/Dobby/builtin-plugin/BionicLinkerUtil/bionic_linker_demo.cc new file mode 100644 index 0000000..f68264c --- /dev/null +++ b/app/src/main/cpp/Dobby/builtin-plugin/BionicLinkerUtil/bionic_linker_demo.cc @@ -0,0 +1,36 @@ +#include "dobby.h" + +#include "bionic_linker_util.h" + +#include "logging/logging.h" + +#include + +#define LOG_TAG "BionicLinkerUtil" + +__attribute__((constructor)) static void ctor() { + const char *lib = NULL; + +#if defined(__LP64__) + lib = "/system/lib64/libandroid_runtime.so"; +#else + lib = "/system/lib/libandroid_runtime.so"; +#endif + + void *vm = NULL; + + vm = DobbySymbolResolver(lib, "_ZN7android14AndroidRuntime7mJavaVME"); + INFO_LOG("DobbySymbolResolver::vm %p", vm); + +#if 0 + linker_disable_namespace_restriction(); + void *handle = NULL; + handle = dlopen(lib, RTLD_LAZY); + vm = dlsym(handle, "_ZN7android14AndroidRuntime7mJavaVME"); +#else + void *handle = NULL; + handle = linker_dlopen(lib, RTLD_LAZY); + vm = dlsym(handle, "_ZN7android14AndroidRuntime7mJavaVME"); +#endif + INFO_LOG("vm %p", vm); +} diff --git a/app/src/main/cpp/Dobby/builtin-plugin/BionicLinkerUtil/bionic_linker_util.cc b/app/src/main/cpp/Dobby/builtin-plugin/BionicLinkerUtil/bionic_linker_util.cc new file mode 100644 index 0000000..f3c9f0b --- /dev/null +++ b/app/src/main/cpp/Dobby/builtin-plugin/BionicLinkerUtil/bionic_linker_util.cc @@ -0,0 +1,197 @@ +#include "bionic_linker_util.h" + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include + +#include "dobby.h" +#include "dobby_symbol_resolver.h" + +#include "dobby/common.h" + +#undef LOG_TAG +#define LOG_TAG "BionicLinkerUtil" + +#undef Q +#define Q 29 +// impl at "dobby_symbol_resolver.cc" +extern void *resolve_elf_internal_symbol(const char *library_name, const char *symbol_name); + +#include +static int get_android_system_version() { + char os_version_str[PROP_VALUE_MAX + 1]; + __system_property_get("ro.build.version.sdk", os_version_str); + int os_version_int = atoi(os_version_str); + return os_version_int; +} + +static const char *get_android_linker_path() { +#if __LP64__ + if (get_android_system_version() >= Q) { + return (const char *)"/apex/com.android.runtime/bin/linker64"; + } else { + return (const char *)"/system/bin/linker64"; + } +#else + if (get_android_system_version() >= Q) { + return (const char *)"/apex/com.android.runtime/bin/linker"; + } else { + return (const char *)"/system/bin/linker"; + } +#endif +} + +PUBLIC void *linker_dlopen(const char *filename, int flag) { + typedef void *(*__loader_dlopen_t)(const char *filename, int flags, const void *caller_addr); + static __loader_dlopen_t __loader_dlopen = NULL; + if (!__loader_dlopen) + __loader_dlopen = (__loader_dlopen_t)DobbySymbolResolver(NULL, "__loader_dlopen"); + + // fake caller address + void *open_ptr = dlsym(RTLD_DEFAULT, "open"); + return __loader_dlopen(filename, flag, (const void *)open_ptr); +} + +std::vector linker_solist; +std::vector linker_get_solist() { + if (!linker_solist.empty()) { + linker_solist.clear(); + } + + static soinfo_t (*solist_get_head)() = NULL; + if (!solist_get_head) + solist_get_head = + (soinfo_t(*)())resolve_elf_internal_symbol(get_android_linker_path(), "__dl__Z15solist_get_headv"); + + static soinfo_t (*solist_get_somain)() = NULL; + if (!solist_get_somain) + solist_get_somain = + (soinfo_t(*)())resolve_elf_internal_symbol(get_android_linker_path(), "__dl__Z17solist_get_somainv"); + + static addr_t *solist_head = NULL; + if (!solist_head) + solist_head = (addr_t *)solist_get_head(); + + static addr_t somain = 0; + if (!somain) + somain = (addr_t)solist_get_somain(); + + // Generate the name for an offset. +#define PARAM_OFFSET(type_, member_) __##type_##__##member_##__offset_ +#define STRUCT_OFFSET PARAM_OFFSET + int STRUCT_OFFSET(solist, next) = 0; + for (size_t i = 0; i < 1024 / sizeof(void *); i++) { + if (*(addr_t *)((addr_t)solist_head + i * sizeof(void *)) == somain) { + STRUCT_OFFSET(solist, next) = i * sizeof(void *); + break; + } + } + + linker_solist.push_back(solist_head); + + addr_t sonext = 0; + sonext = *(addr_t *)((addr_t)solist_head + STRUCT_OFFSET(solist, next)); + while (sonext) { + linker_solist.push_back((void *)sonext); + sonext = *(addr_t *)((addr_t)sonext + STRUCT_OFFSET(solist, next)); + } + + return linker_solist; +} + +char *linker_soinfo_get_realpath(soinfo_t soinfo) { + static char *(*_get_realpath)(soinfo_t) = NULL; + if (!_get_realpath) + _get_realpath = + (char *(*)(soinfo_t))resolve_elf_internal_symbol(get_android_linker_path(), "__dl__ZNK6soinfo12get_realpathEv"); + return _get_realpath(soinfo); +} + +uintptr_t linker_soinfo_to_handle(soinfo_t soinfo) { + static uintptr_t (*_linker_soinfo_to_handle)(soinfo_t) = NULL; + if (!_linker_soinfo_to_handle) + _linker_soinfo_to_handle = + (uintptr_t(*)(soinfo_t))resolve_elf_internal_symbol(get_android_linker_path(), "__dl__ZN6soinfo9to_handleEv"); + return _linker_soinfo_to_handle(soinfo); +} + +typedef void *android_namespace_t; +android_namespace_t linker_soinfo_get_primary_namespace(soinfo_t soinfo) { + static android_namespace_t (*_get_primary_namespace)(soinfo_t) = NULL; + if (!_get_primary_namespace) + _get_primary_namespace = (android_namespace_t(*)(soinfo_t))resolve_elf_internal_symbol( + get_android_linker_path(), "__dl__ZN6soinfo21get_primary_namespaceEv"); + return _get_primary_namespace(soinfo); +} + +void linker_iterate_soinfo(int (*cb)(soinfo_t soinfo)) { + auto solist = linker_get_solist(); + for (auto it = solist.begin(); it != solist.end(); it++) { + int ret = cb(*it); + if (ret != 0) + break; + } +} + +static int iterate_soinfo_cb(soinfo_t soinfo) { + android_namespace_t ns = NULL; + ns = linker_soinfo_get_primary_namespace(soinfo); + INFO_LOG("lib: %s", linker_soinfo_get_realpath(soinfo)); + + // set is_isolated_ as false + // no need for this actually + int STRUCT_OFFSET(android_namespace_t, is_isolated_) = 0x8; + *(uint8_t *)((addr_t)ns + STRUCT_OFFSET(android_namespace_t, is_isolated_)) = false; + + std::vector ld_library_paths = {"/system/lib64", "/sytem/lib"}; + if (get_android_system_version() >= Q) { + ld_library_paths.push_back("/apex/com.android.runtime/lib64"); + ld_library_paths.push_back("/apex/com.android.runtime/lib"); + } + int STRUCT_OFFSET(android_namespace_t, ld_library_paths_) = 0x10; + if (*(void **)((addr_t)ns + STRUCT_OFFSET(android_namespace_t, ld_library_paths_))) { + std::vector orig_ld_library_paths = + *(std::vector *)((addr_t)ns + STRUCT_OFFSET(android_namespace_t, ld_library_paths_)); + orig_ld_library_paths.insert(orig_ld_library_paths.end(), ld_library_paths.begin(), ld_library_paths.end()); + + // remove duplicates + { + std::set paths(orig_ld_library_paths.begin(), orig_ld_library_paths.end()); + orig_ld_library_paths.assign(paths.begin(), paths.end()); + } + } else { + *(std::vector *)((addr_t)ns + STRUCT_OFFSET(android_namespace_t, ld_library_paths_)) = + std::move(ld_library_paths); + } + return 0; +} + +bool (*orig_linker_namespace_is_is_accessible)(android_namespace_t ns, const std::string &file); +bool linker_namespace_is_is_accessible(android_namespace_t ns, const std::string &file) { + INFO_LOG("check %s", file.c_str()); + return true; + return orig_linker_namespace_is_is_accessible(ns, file); +} + +void linker_disable_namespace_restriction() { + linker_iterate_soinfo(iterate_soinfo_cb); + + // no need for this actually + void *linker_namespace_is_is_accessible_ptr = resolve_elf_internal_symbol( + get_android_linker_path(), "__dl__ZN19android_namespace_t13is_accessibleERKNSt3__112basic_" + "stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEE"); + DobbyHook(linker_namespace_is_is_accessible_ptr, (void *)linker_namespace_is_is_accessible, + (void **)&orig_linker_namespace_is_is_accessible); + + INFO_LOG("disable namespace restriction done"); +} diff --git a/app/src/main/cpp/Dobby/builtin-plugin/BionicLinkerUtil/bionic_linker_util.h b/app/src/main/cpp/Dobby/builtin-plugin/BionicLinkerUtil/bionic_linker_util.h new file mode 100644 index 0000000..55c2911 --- /dev/null +++ b/app/src/main/cpp/Dobby/builtin-plugin/BionicLinkerUtil/bionic_linker_util.h @@ -0,0 +1,23 @@ +#pragma once + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef void *soinfo_t; + +soinfo_t linker_dlopen(const char *filename, int flag); + +char *linker_soinfo_get_realpath(soinfo_t soinfo); + +uintptr_t linker_soinfo_to_handle(soinfo_t soinfo); + +void linker_iterate_soinfo(int (*cb)(soinfo_t soinfo)); + +void linker_disable_namespace_restriction(); + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/app/src/main/cpp/Dobby/builtin-plugin/CMakeLists.txt b/app/src/main/cpp/Dobby/builtin-plugin/CMakeLists.txt new file mode 100644 index 0000000..3730cb9 --- /dev/null +++ b/app/src/main/cpp/Dobby/builtin-plugin/CMakeLists.txt @@ -0,0 +1,15 @@ +if (Plugin.ImportTableReplace AND SYSTEM.Darwin) + message(STATUS "[Dobby] Enable got hook") + include_directories(builtin-plugin/ImportTableReplace) + add_subdirectory(builtin-plugin/ImportTableReplace) +endif () + +if (Plugin.Android.BionicLinkerUtil) + if (NOT SYSTEM.Android) + message(FATAL_ERROR "[!] Plugin.Android.BionicLinkerUtil only works on Android.") + endif () + message(STATUS "[Dobby] Enable Plugin.Android.BionicLinkerUtil") + set(dobby.plugin.SOURCE_FILE_LIST ${dobby.plugin.SOURCE_FILE_LIST} + BionicLinkerUtil/bionic_linker_util.cc + ) +endif () \ No newline at end of file diff --git a/app/src/main/cpp/Dobby/builtin-plugin/ImportTableReplace/CMakeLists.txt b/app/src/main/cpp/Dobby/builtin-plugin/ImportTableReplace/CMakeLists.txt new file mode 100644 index 0000000..1a2b4b3 --- /dev/null +++ b/app/src/main/cpp/Dobby/builtin-plugin/ImportTableReplace/CMakeLists.txt @@ -0,0 +1,3 @@ +add_library(dobby_import_replace INTERFACE + dobby_import_replace.cc + ) \ No newline at end of file diff --git a/app/src/main/cpp/Dobby/builtin-plugin/ImportTableReplace/dobby_import_replace.cc b/app/src/main/cpp/Dobby/builtin-plugin/ImportTableReplace/dobby_import_replace.cc new file mode 100644 index 0000000..eab1af9 --- /dev/null +++ b/app/src/main/cpp/Dobby/builtin-plugin/ImportTableReplace/dobby_import_replace.cc @@ -0,0 +1,192 @@ +#include "dobby_import_replace.h" + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +#include + +#include "dobby/common.h" + +#include "logging/logging.h" + +#include "PlatformUtil/ProcessRuntimeUtility.h" + +#if defined(__LP64__) +typedef struct mach_header_64 mach_header_t; +typedef struct segment_command_64 segment_command_t; +typedef struct section_64 section_t; +typedef struct nlist_64 nlist_t; +#define LC_SEGMENT_ARCH_DEPENDENT LC_SEGMENT_64 +#else +typedef struct mach_header mach_header_t; +typedef struct segment_command segment_command_t; +typedef struct section section_t; +typedef struct nlist nlist_t; +#define LC_SEGMENT_ARCH_DEPENDENT LC_SEGMENT +#endif + +static void *iterate_indirect_symtab(char *symbol_name, section_t *section, intptr_t slide, nlist_t *symtab, + char *strtab, uint32_t *indirect_symtab) { + const bool is_data_const = strcmp(section->segname, "__DATA_CONST") == 0; + uint32_t *indirect_symbol_indices = indirect_symtab + section->reserved1; + void **indirect_symbol_bindings = (void **)((uintptr_t)slide + section->addr); + + vm_prot_t old_protection = VM_PROT_READ; + if (is_data_const) { + mprotect(indirect_symbol_bindings, section->size, PROT_READ | PROT_WRITE); + } + + for (uint i = 0; i < section->size / sizeof(void *); i++) { + uint32_t symtab_index = indirect_symbol_indices[i]; + if (symtab_index == INDIRECT_SYMBOL_ABS || symtab_index == INDIRECT_SYMBOL_LOCAL || + symtab_index == (INDIRECT_SYMBOL_LOCAL | INDIRECT_SYMBOL_ABS)) { + continue; + } + uint32_t strtab_offset = symtab[symtab_index].n_un.n_strx; + char *local_symbol_name = strtab + strtab_offset; + bool symbol_name_longer_than_1 = symbol_name[0] && symbol_name[1]; + if (strcmp(local_symbol_name, symbol_name) == 0) { + return &indirect_symbol_bindings[i]; + } + if (local_symbol_name[0] == '_') { + if (strcmp(symbol_name, &local_symbol_name[1]) == 0) { + return &indirect_symbol_bindings[i]; + } + } + } + + if (is_data_const && 0) { + int protection = 0; + if (old_protection & VM_PROT_READ) { + protection |= PROT_READ; + } + if (old_protection & VM_PROT_WRITE) { + protection |= PROT_WRITE; + } + if (old_protection & VM_PROT_EXECUTE) { + protection |= PROT_EXEC; + } + mprotect(indirect_symbol_bindings, section->size, protection); + } + return NULL; +} + +static void *get_global_offset_table_stub(mach_header_t *header, char *symbol_name) { + segment_command_t *curr_seg_cmd; + segment_command_t *text_segment, *data_segment, *linkedit_segment; + struct symtab_command *symtab_cmd = NULL; + struct dysymtab_command *dysymtab_cmd = NULL; + + uintptr_t cur = (uintptr_t)header + sizeof(mach_header_t); + for (uint i = 0; i < header->ncmds; i++, cur += curr_seg_cmd->cmdsize) { + curr_seg_cmd = (segment_command_t *)cur; + if (curr_seg_cmd->cmd == LC_SEGMENT_ARCH_DEPENDENT) { + if (strcmp(curr_seg_cmd->segname, "__LINKEDIT") == 0) { + linkedit_segment = curr_seg_cmd; + } else if (strcmp(curr_seg_cmd->segname, "__DATA") == 0) { + data_segment = curr_seg_cmd; + } else if (strcmp(curr_seg_cmd->segname, "__TEXT") == 0) { + text_segment = curr_seg_cmd; + } + } else if (curr_seg_cmd->cmd == LC_SYMTAB) { + symtab_cmd = (struct symtab_command *)curr_seg_cmd; + } else if (curr_seg_cmd->cmd == LC_DYSYMTAB) { + dysymtab_cmd = (struct dysymtab_command *)curr_seg_cmd; + } + } + + if (!symtab_cmd || !linkedit_segment || !linkedit_segment) { + return NULL; + } + + uintptr_t slide = (uintptr_t)header - (uintptr_t)text_segment->vmaddr; + uintptr_t linkedit_base = (uintptr_t)slide + linkedit_segment->vmaddr - linkedit_segment->fileoff; + nlist_t *symtab = (nlist_t *)(linkedit_base + symtab_cmd->symoff); + char *strtab = (char *)(linkedit_base + symtab_cmd->stroff); + uint32_t symtab_count = symtab_cmd->nsyms; + + uint32_t *indirect_symtab = (uint32_t *)(linkedit_base + dysymtab_cmd->indirectsymoff); + + cur = (uintptr_t)header + sizeof(mach_header_t); + for (uint i = 0; i < header->ncmds; i++, cur += curr_seg_cmd->cmdsize) { + curr_seg_cmd = (segment_command_t *)cur; + if (curr_seg_cmd->cmd == LC_SEGMENT_ARCH_DEPENDENT) { + if (strcmp(curr_seg_cmd->segname, "__DATA") != 0 && strcmp(curr_seg_cmd->segname, "__DATA_CONST") != 0) { + continue; + } + for (uint j = 0; j < curr_seg_cmd->nsects; j++) { + section_t *sect = (section_t *)(cur + sizeof(segment_command_t)) + j; + if ((sect->flags & SECTION_TYPE) == S_LAZY_SYMBOL_POINTERS) { + void *stub = iterate_indirect_symtab(symbol_name, sect, slide, symtab, strtab, indirect_symtab); + if (stub) + return stub; + } + if ((sect->flags & SECTION_TYPE) == S_NON_LAZY_SYMBOL_POINTERS) { + void *stub = iterate_indirect_symtab(symbol_name, sect, slide, symtab, strtab, indirect_symtab); + if (stub) + return stub; + } + } + } + } + + return NULL; +} + +PUBLIC int DobbyImportTableReplace(char *image_name, char *symbol_name, void *fake_func, void **orig_func_ptr) { + std::vector ProcessModuleMap = ProcessRuntimeUtility::GetProcessModuleMap(); + + for (auto module : ProcessModuleMap) { + if (image_name != NULL && strstr(module.path, image_name) == NULL) + continue; + + addr_t header = (addr_t)module.load_address; + size_t slide = 0; + +#if 0 + if (header) { + if (((struct mach_header *)header)->magic == MH_MAGIC_64) + slide = macho_kit_get_slide64(header); + } +#endif + +#if 0 + INFO_LOG("resolve image: %s", module.path); +#endif + + uint32_t nlist_count = 0; + nlist_t *nlist_array = 0; + char *string_pool = 0; + + void *stub = get_global_offset_table_stub((mach_header_t *)header, symbol_name); + if (stub) { + void *orig_func; + orig_func = *(void **)stub; +#if __has_feature(ptrauth_calls) + orig_func = ptrauth_strip(orig_func, ptrauth_key_asia); + orig_func = ptrauth_sign_unauthenticated(orig_func, ptrauth_key_asia, 0); +#endif + *orig_func_ptr = orig_func; + +#if __has_feature(ptrauth_calls) + fake_func = (void *)ptrauth_strip(fake_func, ptrauth_key_asia); + fake_func = ptrauth_sign_unauthenticated(fake_func, ptrauth_key_asia, stub); +#endif + *(void **)stub = fake_func; + } + + if (image_name) + return 0; + } + return -1; +} diff --git a/app/src/main/cpp/Dobby/builtin-plugin/ImportTableReplace/dobby_import_replace.h b/app/src/main/cpp/Dobby/builtin-plugin/ImportTableReplace/dobby_import_replace.h new file mode 100644 index 0000000..c51b0f7 --- /dev/null +++ b/app/src/main/cpp/Dobby/builtin-plugin/ImportTableReplace/dobby_import_replace.h @@ -0,0 +1,11 @@ +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +// int DobbyImportTableReplace(char *image_name, char *symbol_name, void *fake_func, void **orig_func); + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/app/src/main/cpp/Dobby/builtin-plugin/ObjcRuntimeReplace/CMakeLists.txt b/app/src/main/cpp/Dobby/builtin-plugin/ObjcRuntimeReplace/CMakeLists.txt new file mode 100644 index 0000000..5430d9f --- /dev/null +++ b/app/src/main/cpp/Dobby/builtin-plugin/ObjcRuntimeReplace/CMakeLists.txt @@ -0,0 +1,7 @@ +add_library(objc_runtime_replace + dobby_objc_runtime_replace.mm + ) + +target_link_libraries(objc_runtime_replace + "-framework Foundation" + ) \ No newline at end of file diff --git a/app/src/main/cpp/Dobby/builtin-plugin/ObjcRuntimeReplace/dobby_objc_runtime_repalce.h b/app/src/main/cpp/Dobby/builtin-plugin/ObjcRuntimeReplace/dobby_objc_runtime_repalce.h new file mode 100644 index 0000000..da959e7 --- /dev/null +++ b/app/src/main/cpp/Dobby/builtin-plugin/ObjcRuntimeReplace/dobby_objc_runtime_repalce.h @@ -0,0 +1,18 @@ +#pragma once + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +IMP DobbyObjcReplace(Class _class, SEL _selector, IMP replacement); + +void DobbyObjcReplaceEx(const char *class_name, const char *selector_name, void *fake_impl, void **orig_impl); + +void *DobbyObjcResolveMethodImp(const char *class_name, const char *selector_name); + +#ifdef __cplusplus +} +#endif diff --git a/app/src/main/cpp/Dobby/builtin-plugin/ObjcRuntimeReplace/dobby_objc_runtime_replace.mm b/app/src/main/cpp/Dobby/builtin-plugin/ObjcRuntimeReplace/dobby_objc_runtime_replace.mm new file mode 100644 index 0000000..d794880 --- /dev/null +++ b/app/src/main/cpp/Dobby/builtin-plugin/ObjcRuntimeReplace/dobby_objc_runtime_replace.mm @@ -0,0 +1,54 @@ +#include "dobby_objc_runtime_repalce.h" + +#include +#include + +/* clang -rewrite-objc main.m */ + +IMP DobbyObjcReplace(Class class_, SEL sel_, IMP fake_impl) { + Method method_ = class_getInstanceMethod(class_, sel_); + if (!method_) + method_ = class_getClassMethod(class_, sel_); + + if (!method_) { + // DEBUG_LOG("Not found class: %s, selector: %s method\n", class_getName(class_), sel_getName(sel_)); + return NULL; + } + + return method_setImplementation(method_, (IMP)fake_impl); +} + +void DobbyObjcReplaceEx(const char *class_name, const char *selector_name, void *fake_impl, void **out_orig_impl) { + Class class_ = objc_getClass(class_name); + SEL sel_ = sel_registerName(selector_name); + + Method method_ = class_getInstanceMethod(class_, sel_); + if (!method_) { + method_ = class_getClassMethod(class_, sel_); + if (!method_) { + // ERROR_LOG("Not found class: %s, selector: %s method\n", class_name, selector_name); + return; + } + } + + auto orig_impl = (void *)method_setImplementation(method_, (IMP)fake_impl); + if (out_orig_impl) { + *out_orig_impl = orig_impl; + } + return; +} + +void *DobbyObjcResolveMethodImp(const char *class_name, const char *selector_name) { + Class class_ = objc_getClass(class_name); + SEL sel_ = sel_registerName(selector_name); + + Method method_ = class_getInstanceMethod(class_, sel_); + if (!method_) + method_ = class_getClassMethod(class_, sel_); + + if (!method_) { + // DEBUG_LOG("Not found class: %s, selector: %s method\n", class_name, selector_name); + return NULL; + } + return (void *)method_getImplementation(method_); +} diff --git a/app/src/main/cpp/Dobby/builtin-plugin/SupervisorCallMonitor/CMakeLists.txt b/app/src/main/cpp/Dobby/builtin-plugin/SupervisorCallMonitor/CMakeLists.txt new file mode 100644 index 0000000..ddddfd7 --- /dev/null +++ b/app/src/main/cpp/Dobby/builtin-plugin/SupervisorCallMonitor/CMakeLists.txt @@ -0,0 +1,23 @@ +add_library(supervisor_call_monitor STATIC + mach_system_call_log_handler.cc + system_call_log_handler.cc + supervisor_call_monitor.cc + sensitive_api_monitor.cc + misc_utility.cc + ) +target_link_libraries(supervisor_call_monitor + misc_helper + dobby + ) + +add_library(test_supervisor_call_monitor SHARED + test_supervisor_call_monitor.cc + ) +target_link_libraries(test_supervisor_call_monitor + supervisor_call_monitor +) + +include_directories( + . +) + diff --git a/app/src/main/cpp/Dobby/builtin-plugin/SupervisorCallMonitor/README b/app/src/main/cpp/Dobby/builtin-plugin/SupervisorCallMonitor/README new file mode 100644 index 0000000..3832eb5 --- /dev/null +++ b/app/src/main/cpp/Dobby/builtin-plugin/SupervisorCallMonitor/README @@ -0,0 +1 @@ +Monitor all supervisor call \ No newline at end of file diff --git a/app/src/main/cpp/Dobby/builtin-plugin/SupervisorCallMonitor/mach_system_call_log_handler.cc b/app/src/main/cpp/Dobby/builtin-plugin/SupervisorCallMonitor/mach_system_call_log_handler.cc new file mode 100644 index 0000000..970a1be --- /dev/null +++ b/app/src/main/cpp/Dobby/builtin-plugin/SupervisorCallMonitor/mach_system_call_log_handler.cc @@ -0,0 +1,193 @@ +#include "dobby/dobby_internal.h" + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "misc-helper/async_logger.h" +#include "PlatformUtil/ProcessRuntimeUtility.h" +#include "SupervisorCallMonitor/misc_utility.h" +#include "SupervisorCallMonitor/supervisor_call_monitor.h" + +#include "XnuInternal/syscall_sw.c" + +#include "XnuInternal/mach/clock_priv.h" +#include "XnuInternal/mach/clock_reply.h" +#include "XnuInternal/mach/clock.h" +#include "XnuInternal/mach/exc.h" +#include "XnuInternal/mach/host_priv.h" +#include "XnuInternal/mach/host_security.h" +#include "XnuInternal/mach/lock_set.h" +#include "XnuInternal/mach/mach_host.h" +#include "XnuInternal/mach/mach_port.h" +#include "XnuInternal/mach/mach_vm.h" +#include "XnuInternal/mach/mach_voucher.h" +#include "XnuInternal/mach/memory_entry.h" +#include "XnuInternal/mach/processor_set.h" +#include "XnuInternal/mach/processor.h" +#include "XnuInternal/mach/task.h" +#include "XnuInternal/mach/thread_act.h" +#include "XnuInternal/mach/vm_map.h" + +typedef struct { + char *mach_msg_name; + int mach_msg_id; +} mach_msg_entry_t; + +// clang-format off +mach_msg_entry_t mach_msg_array[] = { + subsystem_to_name_map_clock_priv, + subsystem_to_name_map_clock_reply, + subsystem_to_name_map_clock, + subsystem_to_name_map_exc, + subsystem_to_name_map_host_priv, + subsystem_to_name_map_host_security, + subsystem_to_name_map_lock_set, + subsystem_to_name_map_mach_host, + subsystem_to_name_map_mach_port, + subsystem_to_name_map_mach_vm, + subsystem_to_name_map_mach_voucher, + subsystem_to_name_map_memory_entry, + subsystem_to_name_map_processor_set, + subsystem_to_name_map_processor, + subsystem_to_name_map_task, + subsystem_to_name_map_thread_act, + subsystem_to_name_map_vm_map, +}; +// clang-format on + +#define PRIME_NUMBER 8387 +char *mach_msg_name_table[PRIME_NUMBER] = {0}; +static int hash_mach_msg_num_to_ndx(int mach_msg_num) { + return mach_msg_num % PRIME_NUMBER; +} +static void mach_msg_id_hash_table_init() { + static bool initialized = false; + if (initialized == true) { + return; + } + initialized = true; + + int count = sizeof(mach_msg_array) / sizeof(mach_msg_array[0]); + for (size_t i = 0; i < count; i++) { + mach_msg_entry_t entry = mach_msg_array[i]; + int ndx = hash_mach_msg_num_to_ndx(entry.mach_msg_id); + mach_msg_name_table[ndx] = entry.mach_msg_name; + } +} + +const char *mach_syscall_num_to_str(int num) { + return mach_syscall_name_table[0 - num]; +} + +char *mach_msg_id_to_str(int msgh_id) { + int ndx = hash_mach_msg_num_to_ndx(msgh_id); + return mach_msg_name_table[ndx]; +} + +char *mach_msg_to_str(mach_msg_header_t *msg) { + static mach_port_t self_port = MACH_PORT_NULL; + + if (self_port == MACH_PORT_NULL) { + self_port = mach_task_self(); + } + + if (msg->msgh_remote_port == self_port) { + return mach_msg_id_to_str(msg->msgh_id); + } + return NULL; +} + +static addr_t getCallFirstArg(DobbyRegisterContext *ctx) { + addr_t result; +#if defined(_M_X64) || defined(__x86_64__) +#if defined(_WIN32) + result = ctx->general.regs.rcx; +#else + result = ctx->general.regs.rdi; +#endif +#elif defined(__arm64__) || defined(__aarch64__) + result = ctx->general.regs.x0; +#elif defined(__arm__) + result = ctx->general.regs.r0; +#else +#error "Not Support Architecture." +#endif + return result; +} + +static addr_t getRealLr(DobbyRegisterContext *ctx) { + addr_t closure_trampoline_reserved_stack = ctx->sp - sizeof(addr_t); + return *(addr_t *)closure_trampoline_reserved_stack; +} + +static addr_t fast_get_caller_from_main_binary(DobbyRegisterContext *ctx) { + static addr_t text_section_start = 0, text_section_end = 0; + static addr_t slide = 0; + if (text_section_start == 0 || text_section_end == 0) { + auto main = ProcessRuntimeUtility::GetProcessModule("mobilex"); + addr_t main_header = (addr_t)main.load_address; + + auto text_segment = macho_kit_get_segment_by_name((mach_header_t *)main_header, "__TEXT"); + slide = main_header - text_segment->vmaddr; + + auto text_section = macho_kit_get_section_by_name((mach_header_t *)main_header, "__TEXT", "__text"); + text_section_start = main_header + (addr_t)text_section->offset; + text_section_end = text_section_start + text_section->size; + } + + if (ctx == NULL) + return 0; + + addr_t lr = getRealLr(ctx); + if (lr > text_section_start && lr < text_section_end) + return lr - slide; + +#define MAX_STACK_ITERATE_LEVEL 8 + addr_t fp = ctx->fp; + if (fp == 0) + return 0; + for (int i = 0; i < MAX_STACK_ITERATE_LEVEL; i++) { + addr_t lr = *(addr_t *)(fp + sizeof(addr_t)); + if (lr > text_section_start && lr < text_section_end) + return lr - slide; + fp = *(addr_t *)fp; + if (fp == 0) + return 0; + } + return 0; +} + +static void mach_syscall_log_handler(DobbyRegisterContext *ctx, const InterceptEntry *info) { + addr_t caller = fast_get_caller_from_main_binary(ctx); + if (caller == 0) + return; + + char buffer[256] = {0}; + int syscall_rum = ctx->general.regs.x16; + if (syscall_rum == -31) { + // mach_msg_trap + mach_msg_header_t *msg = (typeof(msg))getCallFirstArg(ctx); + char *mach_msg_name = mach_msg_to_str(msg); + if (mach_msg_name) { + sprintf(buffer, "[mach msg svc] %s\n", mach_msg_name); + } else { + buffer[0] = 0; + } + } else if (syscall_rum < 0) { + sprintf(buffer, "[mach svc-%d] %s\n", syscall_rum, mach_syscall_num_to_str(syscall_rum)); + } + async_logger_print(buffer); +} + +void supervisor_call_monitor_register_mach_syscall_call_log_handler() { + mach_msg_id_hash_table_init(); + fast_get_caller_from_main_binary(NULL); + supervisor_call_monitor_register_handler(mach_syscall_log_handler); +} diff --git a/app/src/main/cpp/Dobby/builtin-plugin/SupervisorCallMonitor/misc_utility.cc b/app/src/main/cpp/Dobby/builtin-plugin/SupervisorCallMonitor/misc_utility.cc new file mode 100644 index 0000000..2a0a05b --- /dev/null +++ b/app/src/main/cpp/Dobby/builtin-plugin/SupervisorCallMonitor/misc_utility.cc @@ -0,0 +1,44 @@ +#include "misc_utility.h" + +#include + +segment_command_t *macho_kit_get_segment_by_name(mach_header_t *header, const char *segname) { + segment_command_t *curr_seg_cmd = NULL; + + curr_seg_cmd = (segment_command_t *)((addr_t)header + sizeof(mach_header_t)); + for (int i = 0; i < header->ncmds; i++) { + if (curr_seg_cmd->cmd == LC_SEGMENT_ARCH_DEPENDENT) { + if (!strncmp(curr_seg_cmd->segname, segname, sizeof(curr_seg_cmd->segname))) { + break; + } + } + curr_seg_cmd = (segment_command_t *)((addr_t)curr_seg_cmd + curr_seg_cmd->cmdsize); + } + + return curr_seg_cmd; +} + +section_t *macho_kit_get_section_by_name(mach_header_t *header, const char *segname, const char *sectname) { + section_t *section = NULL; + segment_command_t *segment = NULL; + + int i = 0; + + segment = macho_kit_get_segment_by_name(header, segname); + if (!segment) + goto finish; + + section = (section_t *)((addr_t)segment + sizeof(segment_command_t)); + for (i = 0; i < segment->nsects; ++i) { + if (!strncmp(section->sectname, sectname, sizeof(section->sectname))) { + break; + } + section += 1; + } + if (i == segment->nsects) { + section = NULL; + } + +finish: + return section; +} \ No newline at end of file diff --git a/app/src/main/cpp/Dobby/builtin-plugin/SupervisorCallMonitor/misc_utility.h b/app/src/main/cpp/Dobby/builtin-plugin/SupervisorCallMonitor/misc_utility.h new file mode 100644 index 0000000..1c356c0 --- /dev/null +++ b/app/src/main/cpp/Dobby/builtin-plugin/SupervisorCallMonitor/misc_utility.h @@ -0,0 +1,28 @@ +#pragma once + +#include +typedef uintptr_t addr_t; + +#include +#include +#include + +#if defined(__LP64__) +typedef struct mach_header_64 mach_header_t; +typedef struct segment_command_64 segment_command_t; +typedef struct section_64 section_t; +typedef struct nlist_64 nlist_t; +#define LC_SEGMENT_ARCH_DEPENDENT LC_SEGMENT_64 +#else +typedef struct mach_header mach_header_t; +typedef struct segment_command segment_command_t; +typedef struct section section_t; +typedef struct nlist nlist_t; +#define LC_SEGMENT_ARCH_DEPENDENT LC_SEGMENT +#endif + +// get macho segment by segment name +segment_command_t *macho_kit_get_segment_by_name(mach_header_t *mach_header, const char *segname); + +// get macho section by segment name and section name +section_t *macho_kit_get_section_by_name(mach_header_t *mach_header, const char *segname, const char *sectname); diff --git a/app/src/main/cpp/Dobby/builtin-plugin/SupervisorCallMonitor/sensitive_api_monitor.cc b/app/src/main/cpp/Dobby/builtin-plugin/SupervisorCallMonitor/sensitive_api_monitor.cc new file mode 100644 index 0000000..6ab0765 --- /dev/null +++ b/app/src/main/cpp/Dobby/builtin-plugin/SupervisorCallMonitor/sensitive_api_monitor.cc @@ -0,0 +1,95 @@ +#include "dobby/dobby_internal.h" + +#include +#include +#include + +#include "SupervisorCallMonitor/supervisor_call_monitor.h" +#include "misc-helper/async_logger.h" + +#define PT_DENY_ATTACH 31 + +static void sensitive_api_handler(DobbyRegisterContext *ctx, const InterceptEntry *info) { + char buffer[256] = {0}; + int syscall_rum = ctx->general.regs.x16; + if (syscall_rum == 0) { + syscall_rum = (int)ctx->general.x[0]; + if (syscall_rum == SYS_ptrace) { + int request = ctx->general.x[1]; + if (request == PT_DENY_ATTACH) { + ctx->general.x[1] = 0; + // INFO_LOG("syscall svc ptrace deny"); + } + } + if (syscall_rum == SYS_exit) { + // INFO_LOG("syscall svc exit"); + } + } else if (syscall_rum > 0) { + if (syscall_rum == SYS_ptrace) { + int request = ctx->general.x[0]; + if (request == PT_DENY_ATTACH) { + ctx->general.x[0] = 0; + // INFO_LOG("svc ptrace deny"); + } + } + if (syscall_rum == SYS_exit) { + // INFO_LOG("svc exit"); + } + } + async_logger_print(buffer); +} + +static int get_func_svc_offset(addr_t func_addr) { + typedef int32_t arm64_instr_t; + for (int i = 0; i < 8; i++) { + arm64_instr_t *insn = (arm64_instr_t *)func_addr + i; + if (*insn == 0xd4001001) { + return i * sizeof(arm64_instr_t); + } + } + return 0; +} + +#include +__typeof(sysctl) *orig_sysctl; +int fake_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp, size_t newlen) { + struct kinfo_proc *info = NULL; + int ret = orig_sysctl(name, namelen, oldp, oldlenp, newp, newlen); + if (name[0] == CTL_KERN && name[1] == KERN_PROC && name[2] == KERN_PROC_PID) { + info = (struct kinfo_proc *)oldp; + info->kp_proc.p_flag &= ~(P_TRACED); + } + return ret; +} + +void supervisor_call_monitor_register_sensitive_api_handler() { + char *sensitive_func_array[] = {"ptrace", "exit"}; + size_t count = sizeof(sensitive_func_array) / sizeof(char *); + for (size_t i = 0; i < count; i++) { + + addr_t func_addr = 0; + + char func_name[64] = {0}; + sprintf(func_name, "__%s", sensitive_func_array[i]); + func_addr = (addr_t)DobbySymbolResolver("libsystem_kernel.dylib", func_name); + if (func_addr == 0) { + func_addr = (addr_t)DobbySymbolResolver("libsystem_kernel.dylib", sensitive_func_array[i]); + } + if (func_addr == 0) { + INFO_LOG("not found func %s", sensitive_func_array[i]); + continue; + } + int func_svc_offset = get_func_svc_offset(func_addr); + if (func_svc_offset == 0) { + INFO_LOG("not found svc %s", sensitive_func_array[i]); + continue; + } + addr_t func_svc_addr = func_addr + func_svc_offset; + supervisor_call_monitor_register_svc(func_svc_addr); + } + + // =============== + DobbyHook((void *)sysctl, (void *)fake_sysctl, (void **)&orig_sysctl); + + supervisor_call_monitor_register_handler(sensitive_api_handler); +} diff --git a/app/src/main/cpp/Dobby/builtin-plugin/SupervisorCallMonitor/supervisor_call_monitor.cc b/app/src/main/cpp/Dobby/builtin-plugin/SupervisorCallMonitor/supervisor_call_monitor.cc new file mode 100644 index 0000000..c97b111 --- /dev/null +++ b/app/src/main/cpp/Dobby/builtin-plugin/SupervisorCallMonitor/supervisor_call_monitor.cc @@ -0,0 +1,138 @@ +#include "SupervisorCallMonitor/misc_utility.h" +#include "dobby/dobby_internal.h" +#include "PlatformUtil/ProcessRuntimeUtility.h" + +#include "misc-helper/async_logger.h" + +#include +std::vector *g_supervisor_call_handlers; + +static const char *fast_get_main_app_bundle_udid() { + static char *main_app_bundle_udid = NULL; + if (main_app_bundle_udid) + return main_app_bundle_udid; + + auto main = ProcessRuntimeUtility::GetProcessModuleMap()[0]; + char main_binary_path[2048] = {0}; + if (realpath(main.path, main_binary_path) == NULL) + return NULL; + + char *bundle_udid_ndx = main_binary_path + strlen("/private/var/containers/Bundle/Application/"); + main_app_bundle_udid = (char *)malloc(36 + 1); + strncpy(main_app_bundle_udid, bundle_udid_ndx, 36); + main_app_bundle_udid[36] = 0; + return main_app_bundle_udid; +} + +static void common_supervisor_call_monitor_handler(DobbyRegisterContext *ctx, const InterceptEntry *info) { + if (g_supervisor_call_handlers == NULL) { + return; + } + for (auto handler : *g_supervisor_call_handlers) { + handler(ctx, info); + } +} + +void supervisor_call_monitor_register_handler(DBICallTy handler) { + if (g_supervisor_call_handlers == NULL) { + g_supervisor_call_handlers = new std::vector(); + } + g_supervisor_call_handlers->push_back(handler); +} + +std::vector *g_svc_addr_array; + +void supervisor_call_monitor_register_svc(addr_t svc_addr) { + if (g_svc_addr_array == NULL) { + g_svc_addr_array = new std::vector(); + } + + if (g_svc_addr_array) { + auto iter = g_svc_addr_array->begin(); + for (; iter != g_svc_addr_array->end(); iter++) { + if (*iter == svc_addr) + return; + } + } + + g_svc_addr_array->push_back(svc_addr); + DobbyInstrument((void *)svc_addr, common_supervisor_call_monitor_handler); + DLOG(2, "register supervisor_call_monitor at %p", svc_addr); +} + +void supervisor_call_monitor_register_image(void *header) { + auto text_section = macho_kit_get_section_by_name((mach_header_t *)header, "__TEXT", "__text"); + + addr_t insn_addr = (addr_t)header + (addr_t)text_section->offset; + addr_t insn_addr_end = insn_addr + text_section->size; + + for (; insn_addr < insn_addr_end; insn_addr += sizeof(uint32_t)) { + if (*(uint32_t *)insn_addr == 0xd4001001) { + supervisor_call_monitor_register_svc((addr_t)insn_addr); + } + } +} + +void supervisor_call_monitor_register_main_app() { + const char *main_bundle_udid = fast_get_main_app_bundle_udid(); + auto module_map = ProcessRuntimeUtility::GetProcessModuleMap(); + for (auto module : module_map) { + if (strstr(module.path, main_bundle_udid)) { + INFO_LOG("[supervisor_call_monitor] %s", module.path); + supervisor_call_monitor_register_image((void *)module.load_address); + } + } +} + +extern "C" int __shared_region_check_np(uint64_t *startaddress); + +struct dyld_cache_header *shared_cache_get_load_addr() { + static struct dyld_cache_header *shared_cache_load_addr = 0; + if (shared_cache_load_addr) + return shared_cache_load_addr; +#if 0 + if (syscall(294, &shared_cache_load_addr) == 0) { +#else + // FIXME: + if (__shared_region_check_np((uint64_t *)&shared_cache_load_addr) != 0) { +#endif + shared_cache_load_addr = 0; +} +return shared_cache_load_addr; +} +void supervisor_call_monitor_register_system_kernel() { + auto libsystem = ProcessRuntimeUtility::GetProcessModule("libsystem_kernel.dylib"); + addr_t libsystem_header = (addr_t)libsystem.load_address; + auto text_section = macho_kit_get_section_by_name((mach_header_t *)libsystem_header, "__TEXT", "__text"); + + addr_t shared_cache_load_addr = (addr_t)shared_cache_get_load_addr(); + addr_t insn_addr = shared_cache_load_addr + (addr_t)text_section->offset; + addr_t insn_addr_end = insn_addr + text_section->size; + + addr_t write_svc_addr = (addr_t)DobbySymbolResolver("libsystem_kernel.dylib", "write"); + write_svc_addr += 4; + + addr_t __psynch_mutexwait_svc_addr = (addr_t)DobbySymbolResolver("libsystem_kernel.dylib", "__psynch_mutexwait"); + __psynch_mutexwait_svc_addr += 4; + + for (; insn_addr < insn_addr_end; insn_addr += sizeof(uint32_t)) { + if (*(uint32_t *)insn_addr == 0xd4001001) { + if (insn_addr == write_svc_addr) + continue; + + if (insn_addr == __psynch_mutexwait_svc_addr) + continue; + supervisor_call_monitor_register_svc((addr_t)insn_addr); + } + } +} + +void supervisor_call_monitor_init() { + // create logger file + char logger_path[1024] = {0}; + sprintf(logger_path, "%s%s", getenv("HOME"), "/Documents/svc_monitor.txt"); + INFO_LOG("HOME: %s", logger_path); + async_logger_init(logger_path); + + dobby_enable_near_branch_trampoline(); +} diff --git a/app/src/main/cpp/Dobby/builtin-plugin/SupervisorCallMonitor/supervisor_call_monitor.h b/app/src/main/cpp/Dobby/builtin-plugin/SupervisorCallMonitor/supervisor_call_monitor.h new file mode 100644 index 0000000..45bde0a --- /dev/null +++ b/app/src/main/cpp/Dobby/builtin-plugin/SupervisorCallMonitor/supervisor_call_monitor.h @@ -0,0 +1,24 @@ +#pragma once + +#include +typedef uintptr_t addr_t; + +#include "dobby.h" + +void supervisor_call_monitor_init(); + +void supervisor_call_monitor_register_handler(DBICallTy handler); + +void supervisor_call_monitor_register_svc(addr_t svc_addr); + +void supervisor_call_monitor_register_image(void *header); + +void supervisor_call_monitor_register_main_app(); + +void supervisor_call_monitor_register_system_kernel(); + +void supervisor_call_monitor_register_syscall_call_log_handler(); + +void supervisor_call_monitor_register_mach_syscall_call_log_handler(); + +void supervisor_call_monitor_register_sensitive_api_handler(); \ No newline at end of file diff --git a/app/src/main/cpp/Dobby/builtin-plugin/SupervisorCallMonitor/system_call_log_handler.cc b/app/src/main/cpp/Dobby/builtin-plugin/SupervisorCallMonitor/system_call_log_handler.cc new file mode 100644 index 0000000..d1ca013 --- /dev/null +++ b/app/src/main/cpp/Dobby/builtin-plugin/SupervisorCallMonitor/system_call_log_handler.cc @@ -0,0 +1,98 @@ +#include "dobby/dobby_internal.h" + +#include + +#include "misc-helper/async_logger.h" +#include "PlatformUtil/ProcessRuntimeUtility.h" +#include "SupervisorCallMonitor/misc_utility.h" +#include "SupervisorCallMonitor/supervisor_call_monitor.h" + +#include "XnuInternal/syscalls.c" + +static const char *syscall_num_to_str(int num) { + return syscallnames[num]; +} + +static addr_t getCallFirstArg(DobbyRegisterContext *ctx) { + addr_t result; +#if defined(_M_X64) || defined(__x86_64__) +#if defined(_WIN32) + result = ctx->general.regs.rcx; +#else + result = ctx->general.regs.rdi; +#endif +#elif defined(__arm64__) || defined(__aarch64__) + result = ctx->general.regs.x0; +#elif defined(__arm__) + result = ctx->general.regs.r0; +#else +#error "Not Support Architecture." +#endif + return result; +} + +static addr_t getRealLr(DobbyRegisterContext *ctx) { + addr_t closure_trampoline_reserved_stack = ctx->sp - sizeof(addr_t); + return *(addr_t *)closure_trampoline_reserved_stack; +} + +static addr_t fast_get_caller_from_main_binary(DobbyRegisterContext *ctx) { + static addr_t text_section_start = 0, text_section_end = 0; + static addr_t slide = 0; + if (text_section_start == 0 || text_section_end == 0) { + auto main = ProcessRuntimeUtility::GetProcessModule(""); + addr_t main_header = (addr_t)main.load_address; + + auto text_segment = macho_kit_get_segment_by_name((mach_header_t *)main_header, "__TEXT"); + slide = main_header - text_segment->vmaddr; + + auto text_section = macho_kit_get_section_by_name((mach_header_t *)main_header, "__TEXT", "__text"); + text_section_start = main_header + (addr_t)text_section->offset; + text_section_end = text_section_start + text_section->size; + } + + if (ctx == NULL) + return 0; + + addr_t lr = getRealLr(ctx); + if (lr > text_section_start && lr < text_section_end) + return lr - slide; + +#define MAX_STACK_ITERATE_LEVEL 8 + addr_t fp = ctx->fp; + if (fp == 0) + return 0; + for (int i = 0; i < MAX_STACK_ITERATE_LEVEL; i++) { + addr_t lr = *(addr_t *)(fp + sizeof(addr_t)); + if (lr > text_section_start && lr < text_section_end) + return lr - slide; + fp = *(addr_t *)fp; + if (fp == 0) + return 0; + } + return 0; +} + +static void syscall_log_handler(DobbyRegisterContext *ctx, const InterceptEntry *info) { + addr_t caller = fast_get_caller_from_main_binary(ctx); + if (caller == 0) + return; + + char buffer[2048] = {0}; + int syscall_rum = ctx->general.regs.x16; + if (syscall_rum == 0) { + syscall_rum = (int)getCallFirstArg(ctx); + sprintf(buffer, "[syscall svc-%d] %s\n", syscall_rum, syscall_num_to_str(syscall_rum)); + } else if (syscall_rum > 0) { + sprintf(buffer, "[svc-%d] %s\n", syscall_rum, syscall_num_to_str(syscall_rum)); + if (syscall_rum == 5) { + sprintf(buffer, "[svc-%d] %s:%s\n", syscall_rum, syscall_num_to_str(syscall_rum), (char *)ctx->general.regs.x0); + } + } + async_logger_print(buffer); +} + +void supervisor_call_monitor_register_syscall_call_log_handler() { + fast_get_caller_from_main_binary(NULL); + supervisor_call_monitor_register_handler(syscall_log_handler); +} \ No newline at end of file diff --git a/app/src/main/cpp/Dobby/builtin-plugin/SupervisorCallMonitor/test_supervisor_call_monitor.cc b/app/src/main/cpp/Dobby/builtin-plugin/SupervisorCallMonitor/test_supervisor_call_monitor.cc new file mode 100644 index 0000000..394a8c8 --- /dev/null +++ b/app/src/main/cpp/Dobby/builtin-plugin/SupervisorCallMonitor/test_supervisor_call_monitor.cc @@ -0,0 +1,16 @@ + +#include "dobby/dobby_internal.h" + +#include "SupervisorCallMonitor/supervisor_call_monitor.h" + +#if 1 +__attribute__((constructor)) static void ctor() { + log_set_level(2); + log_switch_to_syslog(); + + supervisor_call_monitor_init(); + supervisor_call_monitor_register_main_app(); + supervisor_call_monitor_register_syscall_call_log_handler(); + supervisor_call_monitor_register_mach_syscall_call_log_handler(); +} +#endif \ No newline at end of file diff --git a/app/src/main/cpp/Dobby/builtin-plugin/SymbolResolver/CMakeLists.txt b/app/src/main/cpp/Dobby/builtin-plugin/SymbolResolver/CMakeLists.txt new file mode 100644 index 0000000..2bf6a6a --- /dev/null +++ b/app/src/main/cpp/Dobby/builtin-plugin/SymbolResolver/CMakeLists.txt @@ -0,0 +1,57 @@ +set(SOURCE_FILE_LIST) + +if (NOT DEFINED DOBBY_DIR) + message(FATAL_ERROR "DOBBY_DIR must be set!") +endif () + +if (SYSTEM.Darwin AND (NOT DOBBY_BUILD_KERNEL_MODE)) + set(SOURCE_FILE_LIST ${SOURCE_FILE_LIST} + ${CMAKE_CURRENT_SOURCE_DIR}/macho/macho_ctx.cc + ${CMAKE_CURRENT_SOURCE_DIR}/macho/shared_cache_ctx.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/macho/dobby_symbol_resolver.cc + + + ${DOBBY_DIR}/source/Backend/UserMode/PlatformUtil/Darwin/ProcessRuntimeUtility.cc + ) +endif () +if (SYSTEM.Darwin AND DOBBY_BUILD_KERNEL_MODE) + set(SOURCE_FILE_LIST ${SOURCE_FILE_LIST} + ${CMAKE_CURRENT_SOURCE_DIR}/macho/dobby_symbol_resolver.cc + + ${DOBBY_DIR}/source/Backend/KernelMode/PlatformUtil/Darwin/ProcessRuntimeUtility.cc + ) +endif () +if (SYSTEM.Linux OR SYSTEM.Android) + set(SOURCE_FILE_LIST ${SOURCE_FILE_LIST} + ${CMAKE_CURRENT_SOURCE_DIR}/elf/dobby_symbol_resolver.cc + + ${DOBBY_DIR}/source/Backend/UserMode/PlatformUtil/Linux/ProcessRuntimeUtility.cc + ) +endif () +if (SYSTEM.Windows) + set(SOURCE_FILE_LIST ${SOURCE_FILE_LIST} + ${CMAKE_CURRENT_SOURCE_DIR}/pe/dobby_symbol_resolver.cc + + ${DOBBY_DIR}/source/Backend/UserMode/PlatformUtil/Windows/ProcessRuntimeUtility.cc + ) +endif () + +add_library(macho_ctx_kit + macho/macho_ctx.h + macho/macho_ctx.cc + ) + +add_library(shared_cache_ctx_kit + macho/shared_cache_ctx.h + macho/shared_cache_ctx.cpp + ) + +add_library(dobby_symbol_resolver + ${SOURCE_FILE_LIST} + ) + + +include_directories( + . +) + diff --git a/app/src/main/cpp/Dobby/builtin-plugin/SymbolResolver/dobby_symbol_resolver.h b/app/src/main/cpp/Dobby/builtin-plugin/SymbolResolver/dobby_symbol_resolver.h new file mode 100644 index 0000000..22dee3c --- /dev/null +++ b/app/src/main/cpp/Dobby/builtin-plugin/SymbolResolver/dobby_symbol_resolver.h @@ -0,0 +1,15 @@ +#pragma once + +#if defined(BUILDING_INTERNAL) +#include "macho/dobby_symbol_resolver_priv.h" +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +void *DobbySymbolResolver(const char *image_name, const char *symbol_name); + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/app/src/main/cpp/Dobby/builtin-plugin/SymbolResolver/elf/dobby_symbol_resolver.cc b/app/src/main/cpp/Dobby/builtin-plugin/SymbolResolver/elf/dobby_symbol_resolver.cc new file mode 100644 index 0000000..bf45ea9 --- /dev/null +++ b/app/src/main/cpp/Dobby/builtin-plugin/SymbolResolver/elf/dobby_symbol_resolver.cc @@ -0,0 +1,238 @@ +#include "SymbolResolver/dobby_symbol_resolver.h" +#include "dobby/common.h" + +#include +#include +#include +#include + +#include "mmap_file_util.h" + +#include "PlatformUtil/ProcessRuntimeUtility.h" + +#include + +#undef LOG_TAG +#define LOG_TAG "DobbySymbolResolver" + +typedef struct elf_ctx { + void *header; + + uintptr_t load_bias; + + ElfW(Shdr) * sym_sh_; + ElfW(Shdr) * dynsym_sh_; + + const char *strtab_; + ElfW(Sym) * symtab_; + + const char *dynstrtab_; + ElfW(Sym) * dynsymtab_; + + size_t nbucket_; + size_t nchain_; + uint32_t *bucket_; + uint32_t *chain_; + + size_t gnu_nbucket_; + uint32_t *gnu_bucket_; + uint32_t *gnu_chain_; + uint32_t gnu_maskwords_; + uint32_t gnu_shift2_; + ElfW(Addr) * gnu_bloom_filter_; +} elf_ctx_t; + +static void get_syms(ElfW(Ehdr) * header, ElfW(Sym) * *symtab_ptr, char **strtab_ptr, int *count_ptr) { + ElfW(Shdr) *section_header = NULL; + section_header = (ElfW(Shdr) *)((addr_t)header + header->e_shoff); + + ElfW(Shdr) *section_strtab_section_header = NULL; + section_strtab_section_header = (ElfW(Shdr) *)((addr_t)section_header + header->e_shstrndx * header->e_shentsize); + char *section_strtab = NULL; + section_strtab = (char *)((addr_t)header + section_strtab_section_header->sh_offset); + + for (int i = 0; i < header->e_shnum; ++i) { + const char *section_name = (const char *)(section_strtab + section_header->sh_name); + if (section_header->sh_type == SHT_SYMTAB && strcmp(section_name, ".symtab") == 0) { + *symtab_ptr = (ElfW(Sym) *)((addr_t)header + section_header->sh_offset); + *count_ptr = section_header->sh_size / sizeof(ElfW(Sym)); + } + + if (section_header->sh_type == SHT_STRTAB && strcmp(section_name, ".strtab") == 0) { + *strtab_ptr = (char *)((addr_t)header + section_header->sh_offset); + } + section_header = (ElfW(Shdr) *)((addr_t)section_header + header->e_shentsize); + } +} + +int elf_ctx_init(elf_ctx_t *ctx, void *header_) { + ElfW(Ehdr) *ehdr = (ElfW(Ehdr) *)header_; + ctx->header = ehdr; + + ElfW(Addr) ehdr_addr = (ElfW(Addr))ehdr; + + // Handle dynamic segment + { + ElfW(Addr) addr = 0; + ElfW(Dyn) *dyn = NULL; + ElfW(Phdr) *phdr = reinterpret_cast(ehdr_addr + ehdr->e_phoff); + for (size_t i = 0; i < ehdr->e_phnum; i++) { + if (phdr[i].p_type == PT_DYNAMIC) { + dyn = reinterpret_cast(ehdr_addr + phdr[i].p_offset); + } else if (phdr[i].p_type == PT_LOAD) { + addr = ehdr_addr + phdr[i].p_offset - phdr[i].p_vaddr; + if (ctx->load_bias == 0) + ctx->load_bias = ehdr_addr - (phdr[i].p_vaddr - phdr[i].p_offset); + } else if (phdr[i].p_type == PT_PHDR) { + ctx->load_bias = (ElfW(Addr))phdr - phdr[i].p_vaddr; + } + } +// ctx->load_bias = +#if 0 + const char *strtab = nullptr; + ElfW(Sym) *symtab = nullptr; + for (ElfW(Dyn) *d = dyn; d->d_tag != DT_NULL; ++d) { + if (d->d_tag == DT_STRTAB) { + strtab = reinterpret_cast(addr + d->d_un.d_ptr); + } else if (d->d_tag == DT_SYMTAB) { + symtab = reinterpret_cast(addr + d->d_un.d_ptr); + } + } +#endif + } + + // Handle section + { + ElfW(Shdr) * dynsym_sh, *dynstr_sh; + ElfW(Shdr) * sym_sh, *str_sh; + + ElfW(Shdr) *shdr = reinterpret_cast(ehdr_addr + ehdr->e_shoff); + + ElfW(Shdr) *shstr_sh = NULL; + shstr_sh = &shdr[ehdr->e_shstrndx]; + char *shstrtab = NULL; + shstrtab = (char *)((addr_t)ehdr_addr + shstr_sh->sh_offset); + + for (size_t i = 0; i < ehdr->e_shnum; i++) { + if (shdr[i].sh_type == SHT_SYMTAB) { + sym_sh = &shdr[i]; + ctx->sym_sh_ = sym_sh; + ctx->symtab_ = (ElfW(Sym) *)(ehdr_addr + shdr[i].sh_offset); + } else if (shdr[i].sh_type == SHT_STRTAB && strcmp(shstrtab + shdr[i].sh_name, ".strtab") == 0) { + str_sh = &shdr[i]; + ctx->strtab_ = (const char *)(ehdr_addr + shdr[i].sh_offset); + } else if (shdr[i].sh_type == SHT_DYNSYM) { + dynsym_sh = &shdr[i]; + ctx->dynsym_sh_ = dynsym_sh; + ctx->dynsymtab_ = (ElfW(Sym) *)(ehdr_addr + shdr[i].sh_offset); + } else if (shdr[i].sh_type == SHT_STRTAB && strcmp(shstrtab + shdr[i].sh_name, ".dynstr") == 0) { + dynstr_sh = &shdr[i]; + ctx->dynstrtab_ = (const char *)(ehdr_addr + shdr[i].sh_offset); + } + } + } + + return 0; +} + +static void *iterate_symbol_table_impl(const char *symbol_name, ElfW(Sym) * symtab, const char *strtab, int count) { + for (int i = 0; i < count; ++i) { + ElfW(Sym) *sym = symtab + i; + const char *symbol_name_ = strtab + sym->st_name; + if (strcmp(symbol_name_, symbol_name) == 0) { + return (void *)sym->st_value; + } + } + return NULL; +} + +void *elf_ctx_iterate_symbol_table(elf_ctx_t *ctx, const char *symbol_name) { + void *result = NULL; + if (ctx->symtab_ && ctx->strtab_) { + size_t count = ctx->sym_sh_->sh_size / sizeof(ElfW(Sym)); + result = iterate_symbol_table_impl(symbol_name, ctx->symtab_, ctx->strtab_, count); + if (result) + return result; + } + + if (ctx->dynsymtab_ && ctx->dynstrtab_) { + size_t count = ctx->dynsym_sh_->sh_size / sizeof(ElfW(Sym)); + result = iterate_symbol_table_impl(symbol_name, ctx->dynsymtab_, ctx->dynstrtab_, count); + if (result) + return result; + } + return NULL; +} + +void *resolve_elf_internal_symbol(const char *library_name, const char *symbol_name) { + void *result = NULL; + + if (library_name) { + RuntimeModule module = ProcessRuntimeUtility::GetProcessModule(library_name); + + if (module.load_address) { + auto mmapFileMng = MmapFileManager(module.path); + auto file_mem = mmapFileMng.map(); + + elf_ctx_t ctx; + memset(&ctx, 0, sizeof(elf_ctx_t)); + if (file_mem) { + elf_ctx_init(&ctx, file_mem); + result = elf_ctx_iterate_symbol_table(&ctx, symbol_name); + } + + if (result) + result = (void *)((addr_t)result + (addr_t)module.load_address - ((addr_t)file_mem - (addr_t)ctx.load_bias)); + } + } + + if (!result) { + auto ProcessModuleMap = ProcessRuntimeUtility::GetProcessModuleMap(); + for (auto module : ProcessModuleMap) { + + if (module.load_address) { + auto mmapFileMng = MmapFileManager(module.path); + auto file_mem = mmapFileMng.map(); + + elf_ctx_t ctx; + memset(&ctx, 0, sizeof(elf_ctx_t)); + if (file_mem) { + elf_ctx_init(&ctx, file_mem); + result = elf_ctx_iterate_symbol_table(&ctx, symbol_name); + } + + if (result) + result = (void *)((addr_t)result + (addr_t)module.load_address - ((addr_t)file_mem - (addr_t)ctx.load_bias)); + } + + if (result) + break; + } + } + return result; +} + +// impl at "android_restriction.cc" +extern std::vector linker_get_solist(); + +PUBLIC void *DobbySymbolResolver(const char *image_name, const char *symbol_name_pattern) { + void *result = NULL; + +#if 0 + auto solist = linker_get_solist(); + for (auto soinfo : solist) { + uintptr_t handle = linker_soinfo_to_handle(soinfo); + if (image_name == NULL || strstr(linker_soinfo_get_realpath(soinfo), image_name) != 0) { + result = dlsym((void *)handle, symbol_name_pattern); + if (result) + return result; + } + } +#endif + result = dlsym(RTLD_DEFAULT, symbol_name_pattern); + if (result) + return result; + + result = resolve_elf_internal_symbol(image_name, symbol_name_pattern); + return result; +} \ No newline at end of file diff --git a/app/src/main/cpp/Dobby/builtin-plugin/SymbolResolver/macho/dobby_symbol_resolver.cc b/app/src/main/cpp/Dobby/builtin-plugin/SymbolResolver/macho/dobby_symbol_resolver.cc new file mode 100644 index 0000000..5fe236c --- /dev/null +++ b/app/src/main/cpp/Dobby/builtin-plugin/SymbolResolver/macho/dobby_symbol_resolver.cc @@ -0,0 +1,116 @@ +#include "dobby_symbol_resolver.h" +#include "macho/dobby_symbol_resolver_priv.h" + +#include "dobby/common.h" + +#include +#include + +#include "PlatformUtil/ProcessRuntimeUtility.h" + +#include "macho_ctx.h" +#include "shared_cache_ctx.h" + +#if defined(BUILDING_KERNEL) +#else + +#include +#include + +#endif + +#undef LOG_TAG +#define LOG_TAG "DobbySymbolResolver" + +PUBLIC void *DobbySymbolResolver(const char *image_name, const char *symbol_name_pattern) { + uintptr_t result = 0; + auto modules = ProcessRuntimeUtility::GetProcessModuleMap(); + + for (auto iter = modules.begin(); iter != modules.end(); iter++) { + auto module = *iter; + + // image filter + if (image_name && !strstr(module.path, image_name)) + continue; + + // dyld in shared cached at new os version + // ignore dyld, as some functions as own implementation in dyld + if (!image_name && strstr(module.path, "dyld")) + continue; + + auto header = (mach_header_t *)module.load_address; + if (header == nullptr) + continue; + +#if 0 + DEBUG_LOG("resolve image: %s", module.path); +#endif + + nlist_t *symtab = NULL; + uint32_t symtab_count = 0; + char *strtab = NULL; + +#if !defined(BUILDING_KERNEL) +#if defined(__arm__) || defined(__aarch64__) + static int shared_cache_ctx_init_once = 0; + static shared_cache_ctx_t shared_cache_ctx; + if (shared_cache_ctx_init_once == 0) { + shared_cache_ctx_init_once = 1; + shared_cache_ctx_init(&shared_cache_ctx); + shared_cache_load_symbols(&shared_cache_ctx); + } + if (shared_cache_ctx.mmap_shared_cache) { + // shared cache library + if (shared_cache_is_contain(&shared_cache_ctx, (addr_t)header, 0)) { + shared_cache_get_symbol_table(&shared_cache_ctx, header, &symtab, &symtab_count, &strtab); + } + } + if (symtab && strtab) { + result = macho_iterate_symbol_table((char *)symbol_name_pattern, symtab, symtab_count, strtab); + } + if (result) { + result = result + shared_cache_ctx.runtime_slide; + return (void *)result; + } +#endif +#endif + + result = macho_symbol_resolve(header, symbol_name_pattern); + if (result) { + return (void *)result; + } + } + +#if !defined(BUILDING_KERNEL) + mach_header_t *dyld_header = NULL; + if (image_name != NULL && strcmp(image_name, "dyld") == 0) { + // task info + task_dyld_info_data_t task_dyld_info; + mach_msg_type_number_t count = TASK_DYLD_INFO_COUNT; + if (task_info(mach_task_self(), TASK_DYLD_INFO, (task_info_t)&task_dyld_info, &count)) { + return NULL; + } + + // get dyld load address + const struct dyld_all_image_infos *infos = + (struct dyld_all_image_infos *)(uintptr_t)task_dyld_info.all_image_info_addr; + dyld_header = (mach_header_t *)infos->dyldImageLoadAddress; + macho_ctx_t ctx; + macho_ctx_init(&ctx, dyld_header, true); + result = (uintptr_t)macho_ctx_symbol_resolve(&ctx, symbol_name_pattern); + + bool is_dyld_in_cache = ((mach_header_t *)dyld_header)->flags & MH_DYLIB_IN_CACHE; + if (!is_dyld_in_cache && result == 0) { + result = macho_file_symbol_resolve(dyld_header->cputype, dyld_header->cpusubtype, "/usr/lib/dyld", + (char *)symbol_name_pattern); + result += (uintptr_t)dyld_header; + } + } +#endif + + if (result == 0) { + DEBUG_LOG("symbol resolver failed: %s", symbol_name_pattern); + } + + return (void *)result; +} diff --git a/app/src/main/cpp/Dobby/builtin-plugin/SymbolResolver/macho/dobby_symbol_resolver_priv.h b/app/src/main/cpp/Dobby/builtin-plugin/SymbolResolver/macho/dobby_symbol_resolver_priv.h new file mode 100644 index 0000000..c6b4244 --- /dev/null +++ b/app/src/main/cpp/Dobby/builtin-plugin/SymbolResolver/macho/dobby_symbol_resolver_priv.h @@ -0,0 +1,6 @@ +#include +#include +#include + +#include "macho_ctx.h" + diff --git a/app/src/main/cpp/Dobby/builtin-plugin/SymbolResolver/macho/macho_ctx.cc b/app/src/main/cpp/Dobby/builtin-plugin/SymbolResolver/macho/macho_ctx.cc new file mode 100644 index 0000000..05b55a8 --- /dev/null +++ b/app/src/main/cpp/Dobby/builtin-plugin/SymbolResolver/macho/macho_ctx.cc @@ -0,0 +1,419 @@ +#include "macho_ctx.h" + +#include "string.h" +#include "SymbolResolver/mmap_file_util.h" + +#include +#include +#include +#include + +#define ASSERT(x) + +void macho_ctx_init(macho_ctx_t *ctx, mach_header_t *header, bool is_runtime_mode) { + memset(ctx, 0, sizeof(macho_ctx_t)); + + ctx->is_runtime_mode = is_runtime_mode; + + ctx->header = header; + segment_command_t *curr_seg_cmd; + segment_command_t *text_segment = 0, *text_exec_segment = 0, *data_segment = 0, *data_const_segment = 0, + *linkedit_segment = 0; + struct symtab_command *symtab_cmd = 0; + struct dysymtab_command *dysymtab_cmd = 0; + struct dyld_info_command *dyld_info_cmd = 0; + struct linkedit_data_command *exports_trie_cmd = 0; + struct linkedit_data_command *chained_fixups_cmd = NULL; + + curr_seg_cmd = (segment_command_t *)((uintptr_t)header + sizeof(mach_header_t)); + for (int i = 0; i < header->ncmds; i++) { + if (curr_seg_cmd->cmd == LC_SEGMENT_ARCH_DEPENDENT) { + // BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB and REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB + ctx->segments[ctx->segments_count++] = curr_seg_cmd; + + if (strcmp(curr_seg_cmd->segname, "__LINKEDIT") == 0) { + linkedit_segment = curr_seg_cmd; + } else if (strcmp(curr_seg_cmd->segname, "__DATA") == 0) { + data_segment = curr_seg_cmd; + } else if (strcmp(curr_seg_cmd->segname, "__DATA_CONST") == 0) { + data_const_segment = curr_seg_cmd; + } else if (strcmp(curr_seg_cmd->segname, "__TEXT") == 0) { + text_segment = curr_seg_cmd; + } else if (strcmp(curr_seg_cmd->segname, "__TEXT_EXEC") == 0) { + text_exec_segment = curr_seg_cmd; + } + } else if (curr_seg_cmd->cmd == LC_SYMTAB) { + symtab_cmd = (struct symtab_command *)curr_seg_cmd; + } else if (curr_seg_cmd->cmd == LC_DYSYMTAB) { + dysymtab_cmd = (struct dysymtab_command *)curr_seg_cmd; + } else if (curr_seg_cmd->cmd == LC_DYLD_INFO || curr_seg_cmd->cmd == LC_DYLD_INFO_ONLY) { + dyld_info_cmd = (struct dyld_info_command *)curr_seg_cmd; + } else if (curr_seg_cmd->cmd == LC_DYLD_EXPORTS_TRIE) { + exports_trie_cmd = (struct linkedit_data_command *)curr_seg_cmd; + } else if (curr_seg_cmd->cmd == LC_DYLD_CHAINED_FIXUPS) { + chained_fixups_cmd = (struct linkedit_data_command *)curr_seg_cmd; + } + curr_seg_cmd = (segment_command_t *)((uintptr_t)curr_seg_cmd + curr_seg_cmd->cmdsize); + } + + uintptr_t slide = (uintptr_t)header - (uintptr_t)text_segment->vmaddr; + uintptr_t linkedit_base = (uintptr_t)slide + linkedit_segment->vmaddr - linkedit_segment->fileoff; + if (is_runtime_mode == false) { + // as mmap, all segment is close + uintptr_t linkedit_segment_vmaddr = linkedit_segment->fileoff; + linkedit_base = (uintptr_t)slide + linkedit_segment_vmaddr - linkedit_segment->fileoff; + } + + ctx->text_seg = text_segment; + ctx->text_exec_seg = text_exec_segment; + ctx->data_seg = data_segment; + ctx->data_const_seg = data_const_segment; + ctx->linkedit_seg = linkedit_segment; + + ctx->symtab_cmd = symtab_cmd; + ctx->dysymtab_cmd = dysymtab_cmd; + ctx->dyld_info_cmd = dyld_info_cmd; + ctx->exports_trie_cmd = exports_trie_cmd; + ctx->chained_fixups_cmd = chained_fixups_cmd; + + ctx->slide = slide; + ctx->linkedit_base = linkedit_base; + + ctx->symtab = (nlist_t *)(ctx->linkedit_base + ctx->symtab_cmd->symoff); + ctx->strtab = (char *)(ctx->linkedit_base + ctx->symtab_cmd->stroff); + ctx->indirect_symtab = (uint32_t *)(ctx->linkedit_base + ctx->dysymtab_cmd->indirectsymoff); +} + +uintptr_t macho_iterate_symbol_table(char *symbol_name_pattern, nlist_t *symtab, uint32_t symtab_count, char *strtab) { + for (uint32_t i = 0; i < symtab_count; i++) { + if (symtab[i].n_value) { + uint32_t strtab_offset = symtab[i].n_un.n_strx; + char *symbol_name = strtab + strtab_offset; +#if 0 + printf("> %s", symbol_name); +#endif + if (strcmp(symbol_name_pattern, symbol_name) == 0) { + return symtab[i].n_value; + } + if (symbol_name[0] == '_') { + if (strcmp(symbol_name_pattern, &symbol_name[1]) == 0) { + return symtab[i].n_value; + } + } + } + } + return 0; +} + +uintptr_t macho_ctx_iterate_symbol_table(macho_ctx_t *ctx, const char *symbol_name_pattern) { + nlist_t *symtab = ctx->symtab; + uint32_t symtab_count = ctx->symtab_cmd->nsyms; + char *strtab = ctx->strtab; + + for (uint32_t i = 0; i < symtab_count; i++) { + if (symtab[i].n_value) { + uint32_t strtab_offset = symtab[i].n_un.n_strx; + char *symbol_name = strtab + strtab_offset; +#if 0 + printf("> %s", symbol_name); +#endif + if (strcmp(symbol_name_pattern, symbol_name) == 0) { + return symtab[i].n_value; + } + if (symbol_name[0] == '_') { + if (strcmp(symbol_name_pattern, &symbol_name[1]) == 0) { + return symtab[i].n_value; + } + } + } + } + return 0; +} + +uintptr_t read_uleb128(const uint8_t **pp, const uint8_t *end) { + uint8_t *p = (uint8_t *)*pp; + uint64_t result = 0; + int bit = 0; + do { + if (p == end) + ASSERT(p == end); + + uint64_t slice = *p & 0x7f; + + if (bit > 63) + ASSERT(bit > 63); + else { + result |= (slice << bit); + bit += 7; + } + } while (*p++ & 0x80); + + *pp = p; + + return (uintptr_t)result; +} + +intptr_t read_sleb128(const uint8_t **pp, const uint8_t *end) { + uint8_t *p = (uint8_t *)*pp; + + int64_t result = 0; + int bit = 0; + uint8_t byte; + do { + if (p == end) + ASSERT(p == end); + byte = *p++; + result |= (((int64_t)(byte & 0x7f)) << bit); + bit += 7; + } while (byte & 0x80); + // sign extend negative numbers + if ((byte & 0x40) != 0) + result |= (~0ULL) << bit; + + *pp = p; + + return (intptr_t)result; +} + +// dyld +// bool MachOLoaded::findExportedSymbol +// MachOLoaded::trieWalk +uint8_t *tail_walk(const uint8_t *start, const uint8_t *end, const char *symbol) { + uint32_t visitedNodeOffsets[128]; + int visitedNodeOffsetCount = 0; + visitedNodeOffsets[visitedNodeOffsetCount++] = 0; + const uint8_t *p = start; + while (p < end) { + uint64_t terminalSize = *p++; + if (terminalSize > 127) { + // except for re-export-with-rename, all terminal sizes fit in one byte + --p; + terminalSize = read_uleb128(&p, end); + } + if ((*symbol == '\0') && (terminalSize != 0)) { + return (uint8_t *)p; + } + const uint8_t *children = p + terminalSize; + if (children > end) { + // diag.error("malformed trie node, terminalSize=0x%llX extends past end of trie\n", terminalSize); + return NULL; + } + uint8_t childrenRemaining = *children++; + p = children; + uint64_t nodeOffset = 0; + + for (; childrenRemaining > 0; --childrenRemaining) { + const char *ss = symbol; + bool wrongEdge = false; + // scan whole edge to get to next edge + // if edge is longer than target symbol name, don't read past end of symbol name + char c = *p; + while (c != '\0') { + if (!wrongEdge) { + if (c != *ss) + wrongEdge = true; + ++ss; + } + ++p; + c = *p; + } + if (wrongEdge) { + // advance to next child + ++p; // skip over zero terminator + // skip over uleb128 until last byte is found + while ((*p & 0x80) != 0) + ++p; + ++p; // skip over last byte of uleb128 + if (p > end) { + // diag.error("malformed trie node, child node extends past end of trie\n"); + return nullptr; + } + } else { + // the symbol so far matches this edge (child) + // so advance to the child's node + ++p; + nodeOffset = read_uleb128(&p, end); + if ((nodeOffset == 0) || (&start[nodeOffset] > end)) { + // diag.error("malformed trie child, nodeOffset=0x%llX out of range\n", nodeOffset); + return nullptr; + } + symbol = ss; + break; + } + } + + if (nodeOffset != 0) { + if (nodeOffset > (uint64_t)(end - start)) { + // diag.error("malformed trie child, nodeOffset=0x%llX out of range\n", nodeOffset); + return NULL; + } + for (int i = 0; i < visitedNodeOffsetCount; ++i) { + if (visitedNodeOffsets[i] == nodeOffset) { + // diag.error("malformed trie child, cycle to nodeOffset=0x%llX\n", nodeOffset); + return NULL; + } + } + visitedNodeOffsets[visitedNodeOffsetCount++] = (uint32_t)nodeOffset; + p = &start[nodeOffset]; + } else + p = end; + } + return NULL; +} + +uintptr_t macho_ctx_iterate_exported_symbol(macho_ctx_t *ctx, const char *symbol_name, uint64_t *out_flags) { + if (ctx->text_seg == NULL || ctx->linkedit_seg == NULL) { + return 0; + } + + struct dyld_info_command *dyld_info_cmd = ctx->dyld_info_cmd; + struct linkedit_data_command *exports_trie_cmd = ctx->exports_trie_cmd; + if (exports_trie_cmd == NULL && dyld_info_cmd == NULL) + return 0; + + uint32_t trieFileOffset = dyld_info_cmd ? dyld_info_cmd->export_off : exports_trie_cmd->dataoff; + uint32_t trieFileSize = dyld_info_cmd ? dyld_info_cmd->export_size : exports_trie_cmd->datasize; + + void *exports = (void *)(ctx->linkedit_base + trieFileOffset); + if (exports == NULL) + return 0; + + uint8_t *exports_start = (uint8_t *)exports; + uint8_t *exports_end = exports_start + trieFileSize; + uint8_t *node = (uint8_t *)tail_walk(exports_start, exports_end, symbol_name); + if (node == NULL) + return 0; + const uint8_t *p = node; + const uintptr_t flags = read_uleb128(&p, exports_end); + if (out_flags) + *out_flags = flags; + if (flags & EXPORT_SYMBOL_FLAGS_REEXPORT) { + const uint64_t ordinal = read_uleb128(&p, exports_end); + const char *importedName = (const char *)p; + if (importedName[0] == '\0') { + importedName = symbol_name; + return 0; + } + // trick + // printf("reexported symbol: %s\n", importedName); + return (uintptr_t)importedName; + } + uint64_t trieValue = read_uleb128(&p, exports_end); + return trieValue; +#if 0 + if (off == (void *)0) { + if (symbol_name[0] != '_' && strlen(&symbol_name[1]) >= 1) { + char _symbol_name[1024] = {0}; + _symbol_name[0] = '_'; + strcpy(&_symbol_name[1], symbol_name); + off = (void *)walk_exported_trie((const uint8_t *)exports, (const uint8_t *)exports + trieFileSize, _symbol_name); + } + } +#endif +} + +uintptr_t macho_ctx_symbol_resolve_options(macho_ctx_t *ctx, const char *symbol_name_pattern, + resolve_symbol_type_t type) { + if (type & RESOLVE_SYMBOL_TYPE_SYMBOL_TABLE) { + uintptr_t result = macho_ctx_iterate_symbol_table(ctx, symbol_name_pattern); + if (result) { + result = result + (ctx->is_runtime_mode ? ctx->slide : 0); + return result; + } + } + + if (type & RESOLVE_SYMBOL_TYPE_EXPORTED) { + // binary exported table(uleb128) + uint64_t flags; + uintptr_t result = macho_ctx_iterate_exported_symbol(ctx, symbol_name_pattern, &flags); + if (result) { + switch (flags & EXPORT_SYMBOL_FLAGS_KIND_MASK) { + case EXPORT_SYMBOL_FLAGS_KIND_REGULAR: { + result += (uintptr_t)ctx->header; + } break; + case EXPORT_SYMBOL_FLAGS_KIND_THREAD_LOCAL: { + result += (uintptr_t)ctx->header; + } break; + case EXPORT_SYMBOL_FLAGS_KIND_ABSOLUTE: { + } break; + default: + break; + } + return result; + } + } + return 0; +} + +uintptr_t macho_ctx_symbol_resolve(macho_ctx_t *ctx, const char *symbol_name_pattern) { + return macho_ctx_symbol_resolve_options(ctx, symbol_name_pattern, RESOLVE_SYMBOL_TYPE_ALL); +} + +uintptr_t macho_symbol_resolve_options(mach_header_t *header, const char *symbol_name_pattern, + resolve_symbol_type_t type) { + macho_ctx_t ctx; + macho_ctx_init(&ctx, header, true); + return macho_ctx_symbol_resolve_options(&ctx, symbol_name_pattern, type); +} + +uintptr_t macho_symbol_resolve(mach_header_t *header, const char *symbol_name_pattern) { + return macho_symbol_resolve_options(header, symbol_name_pattern, RESOLVE_SYMBOL_TYPE_ALL); +} + +uintptr_t macho_file_memory_symbol_resolve(cpu_type_t in_cputype, cpu_subtype_t in_cpusubtype, const uint8_t *file_mem, + char *symbol_name_pattern) { + + mach_header_t *header = (mach_header_t *)file_mem; + struct fat_header *fh = (struct fat_header *)file_mem; + if (fh->magic == OSSwapBigToHostInt32(FAT_MAGIC)) { + const struct fat_arch *archs = (struct fat_arch *)(((uintptr_t)fh) + sizeof(fat_header)); + mach_header_t *header_arm64 = NULL; + mach_header_t *header_arm64e = NULL; + mach_header_t *header_x64 = NULL; + for (size_t i = 0; i < OSSwapBigToHostInt32(fh->nfat_arch); i++) { + uint64_t offset; + uint64_t len; + cpu_type_t cputype = (cpu_type_t)OSSwapBigToHostInt32(archs[i].cputype); + cpu_subtype_t cpusubtype = (cpu_subtype_t)OSSwapBigToHostInt32(archs[i].cpusubtype); + offset = OSSwapBigToHostInt32(archs[i].offset); + len = OSSwapBigToHostInt32(archs[i].size); + if (cputype == CPU_TYPE_X86_64) { + header_x64 = (mach_header_t *)&file_mem[offset]; + } else if (cputype == CPU_TYPE_ARM64 && (cpusubtype & ~CPU_SUBTYPE_MASK) == CPU_SUBTYPE_ARM64E) { + header_arm64e = (mach_header_t *)&file_mem[offset]; + } else if (cputype == CPU_TYPE_ARM64) { + header_arm64 = (mach_header_t *)&file_mem[offset]; + } + + if ((cputype == in_cputype) && ((cpusubtype & in_cpusubtype) == in_cpusubtype)) { + header = (mach_header_t *)&file_mem[offset]; + break; + } + } + + if (header == (mach_header_t *)file_mem) { + if (in_cputype == 0 && in_cpusubtype == 0) { +#if defined(__arm64__) || defined(__aarch64__) + header = header_arm64e ? header_arm64e : header_arm64; +#else + header = header_x64; +#endif + } + } + } + + macho_ctx_t ctx; + macho_ctx_init(&ctx, header, false); + return macho_ctx_symbol_resolve_options(&ctx, symbol_name_pattern, RESOLVE_SYMBOL_TYPE_SYMBOL_TABLE); +} + +uintptr_t macho_file_symbol_resolve(cpu_type_t cpu, cpu_subtype_t subtype, const char *file, + char *symbol_name_pattern) { + MmapFileManager mng(file); + auto mmap_buffer = mng.map(); + if (!mmap_buffer) { + return 0; + } + + return macho_file_memory_symbol_resolve(cpu, subtype, mmap_buffer, symbol_name_pattern); +} diff --git a/app/src/main/cpp/Dobby/builtin-plugin/SymbolResolver/macho/macho_ctx.h b/app/src/main/cpp/Dobby/builtin-plugin/SymbolResolver/macho/macho_ctx.h new file mode 100644 index 0000000..e41d1cc --- /dev/null +++ b/app/src/main/cpp/Dobby/builtin-plugin/SymbolResolver/macho/macho_ctx.h @@ -0,0 +1,89 @@ +#pragma once + +#include +#include +#include +#include + +#if defined(__LP64__) +typedef struct mach_header_64 mach_header_t; +typedef struct segment_command_64 segment_command_t; +typedef struct section_64 section_t; +typedef struct nlist_64 nlist_t; +#define LC_SEGMENT_ARCH_DEPENDENT LC_SEGMENT_64 +#else +typedef struct mach_header mach_header_t; +typedef struct segment_command segment_command_t; +typedef struct section section_t; +typedef struct nlist nlist_t; +#define LC_SEGMENT_ARCH_DEPENDENT LC_SEGMENT +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct macho_ctx { + bool is_runtime_mode; + + mach_header_t *header; + + uintptr_t slide; + uintptr_t linkedit_base; + + segment_command_t *segments[64]; + int segments_count; + + segment_command_t *text_seg; + segment_command_t *data_seg; + segment_command_t *text_exec_seg; + segment_command_t *data_const_seg; + segment_command_t *linkedit_seg; + + struct symtab_command *symtab_cmd; + struct dysymtab_command *dysymtab_cmd; + struct dyld_info_command *dyld_info_cmd; + struct linkedit_data_command *exports_trie_cmd; + struct linkedit_data_command *chained_fixups_cmd; + + nlist_t *symtab; + char *strtab; + uint32_t *indirect_symtab; +} macho_ctx_t; + +intptr_t read_sleb128(const uint8_t **pp, const uint8_t *end); + +uintptr_t read_uleb128(const uint8_t **pp, const uint8_t *end); + +void macho_ctx_init(macho_ctx_t *ctx, mach_header_t *header, bool is_runtime_mode); + +uintptr_t macho_ctx_iterate_symbol_table(macho_ctx_t *ctx, const char *symbol_name_pattern); + +uintptr_t macho_ctx_iterate_exported_symbol(macho_ctx_t *ctx, const char *symbol_name, uint64_t *out_flags); + +typedef enum { + RESOLVE_SYMBOL_TYPE_SYMBOL_TABLE = 1 << 0, + RESOLVE_SYMBOL_TYPE_EXPORTED = 1 << 1, + RESOLVE_SYMBOL_TYPE_ALL = RESOLVE_SYMBOL_TYPE_SYMBOL_TABLE | RESOLVE_SYMBOL_TYPE_EXPORTED +} resolve_symbol_type_t; + +uintptr_t macho_ctx_symbol_resolve_options(macho_ctx_t *ctx, const char *symbol_name_pattern, + resolve_symbol_type_t type); + +uintptr_t macho_ctx_symbol_resolve(macho_ctx_t *ctx, const char *symbol_name_pattern); + +uintptr_t macho_symbol_resolve_options(mach_header_t *header, const char *symbol_name_pattern, + resolve_symbol_type_t type); + +uintptr_t macho_symbol_resolve(mach_header_t *header, const char *symbol_name_pattern); + +uintptr_t macho_iterate_symbol_table(char *name_pattern, nlist_t *symtab, uint32_t symtab_count, char *strtab); + +uintptr_t macho_file_memory_symbol_resolve(cpu_type_t cpu, cpu_subtype_t subtype, const uint8_t *file_mem, + char *symbol_name_pattern); + +uintptr_t macho_file_symbol_resolve(cpu_type_t cpu, cpu_subtype_t subtype, const char *file, char *symbol_name_pattern); + +#ifdef __cplusplus +} +#endif diff --git a/app/src/main/cpp/Dobby/builtin-plugin/SymbolResolver/macho/shared-cache/dyld_cache_format.h b/app/src/main/cpp/Dobby/builtin-plugin/SymbolResolver/macho/shared-cache/dyld_cache_format.h new file mode 100644 index 0000000..9209293 --- /dev/null +++ b/app/src/main/cpp/Dobby/builtin-plugin/SymbolResolver/macho/shared-cache/dyld_cache_format.h @@ -0,0 +1,560 @@ +/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*- + * + * Copyright (c) 2006-2015 Apple Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ +#ifndef __DYLD_CACHE_FORMAT__ +#define __DYLD_CACHE_FORMAT__ + +#include +#include +#include + + +struct dyld_cache_header +{ + char magic[16]; // e.g. "dyld_v0 i386" + uint32_t mappingOffset; // file offset to first dyld_cache_mapping_info + uint32_t mappingCount; // number of dyld_cache_mapping_info entries + uint32_t imagesOffsetOld; // UNUSED: moved to imagesOffset to prevent older dsc_extarctors from crashing + uint32_t imagesCountOld; // UNUSED: moved to imagesCount to prevent older dsc_extarctors from crashing + uint64_t dyldBaseAddress; // base address of dyld when cache was built + uint64_t codeSignatureOffset; // file offset of code signature blob + uint64_t codeSignatureSize; // size of code signature blob (zero means to end of file) + uint64_t slideInfoOffsetUnused; // unused. Used to be file offset of kernel slid info + uint64_t slideInfoSizeUnused; // unused. Used to be size of kernel slid info + uint64_t localSymbolsOffset; // file offset of where local symbols are stored + uint64_t localSymbolsSize; // size of local symbols information + uint8_t uuid[16]; // unique value for each shared cache file + uint64_t cacheType; // 0 for development, 1 for production, 2 for multi-cache + uint32_t branchPoolsOffset; // file offset to table of uint64_t pool addresses + uint32_t branchPoolsCount; // number of uint64_t entries + uint64_t dyldInCacheMH; // (unslid) address of mach_header of dyld in cache + uint64_t dyldInCacheEntry; // (unslid) address of entry point (_dyld_start) of dyld in cache + uint64_t imagesTextOffset; // file offset to first dyld_cache_image_text_info + uint64_t imagesTextCount; // number of dyld_cache_image_text_info entries + uint64_t patchInfoAddr; // (unslid) address of dyld_cache_patch_info + uint64_t patchInfoSize; // Size of all of the patch information pointed to via the dyld_cache_patch_info + uint64_t otherImageGroupAddrUnused; // unused + uint64_t otherImageGroupSizeUnused; // unused + uint64_t progClosuresAddr; // (unslid) address of list of program launch closures + uint64_t progClosuresSize; // size of list of program launch closures + uint64_t progClosuresTrieAddr; // (unslid) address of trie of indexes into program launch closures + uint64_t progClosuresTrieSize; // size of trie of indexes into program launch closures + uint32_t platform; // platform number (macOS=1, etc) + uint32_t formatVersion : 8, // dyld3::closure::kFormatVersion + dylibsExpectedOnDisk : 1, // dyld should expect the dylib exists on disk and to compare inode/mtime to see if cache is valid + simulator : 1, // for simulator of specified platform + locallyBuiltCache : 1, // 0 for B&I built cache, 1 for locally built cache + builtFromChainedFixups : 1, // some dylib in cache was built using chained fixups, so patch tables must be used for overrides + padding : 20; // TBD + uint64_t sharedRegionStart; // base load address of cache if not slid + uint64_t sharedRegionSize; // overall size required to map the cache and all subCaches, if any + uint64_t maxSlide; // runtime slide of cache can be between zero and this value + uint64_t dylibsImageArrayAddr; // (unslid) address of ImageArray for dylibs in this cache + uint64_t dylibsImageArraySize; // size of ImageArray for dylibs in this cache + uint64_t dylibsTrieAddr; // (unslid) address of trie of indexes of all cached dylibs + uint64_t dylibsTrieSize; // size of trie of cached dylib paths + uint64_t otherImageArrayAddr; // (unslid) address of ImageArray for dylibs and bundles with dlopen closures + uint64_t otherImageArraySize; // size of ImageArray for dylibs and bundles with dlopen closures + uint64_t otherTrieAddr; // (unslid) address of trie of indexes of all dylibs and bundles with dlopen closures + uint64_t otherTrieSize; // size of trie of dylibs and bundles with dlopen closures + uint32_t mappingWithSlideOffset; // file offset to first dyld_cache_mapping_and_slide_info + uint32_t mappingWithSlideCount; // number of dyld_cache_mapping_and_slide_info entries + uint64_t dylibsPBLStateArrayAddrUnused; // unused + uint64_t dylibsPBLSetAddr; // (unslid) address of PrebuiltLoaderSet of all cached dylibs + uint64_t programsPBLSetPoolAddr; // (unslid) address of pool of PrebuiltLoaderSet for each program + uint64_t programsPBLSetPoolSize; // size of pool of PrebuiltLoaderSet for each program + uint64_t programTrieAddr; // (unslid) address of trie mapping program path to PrebuiltLoaderSet + uint32_t programTrieSize; + uint32_t osVersion; // OS Version of dylibs in this cache for the main platform + uint32_t altPlatform; // e.g. iOSMac on macOS + uint32_t altOsVersion; // e.g. 14.0 for iOSMac + uint64_t swiftOptsOffset; // VM offset from cache_header* to Swift optimizations header + uint64_t swiftOptsSize; // size of Swift optimizations header + uint32_t subCacheArrayOffset; // file offset to first dyld_subcache_entry + uint32_t subCacheArrayCount; // number of subCache entries + uint8_t symbolFileUUID[16]; // unique value for the shared cache file containing unmapped local symbols + uint64_t rosettaReadOnlyAddr; // (unslid) address of the start of where Rosetta can add read-only/executable data + uint64_t rosettaReadOnlySize; // maximum size of the Rosetta read-only/executable region + uint64_t rosettaReadWriteAddr; // (unslid) address of the start of where Rosetta can add read-write data + uint64_t rosettaReadWriteSize; // maximum size of the Rosetta read-write region + uint32_t imagesOffset; // file offset to first dyld_cache_image_info + uint32_t imagesCount; // number of dyld_cache_image_info entries + uint32_t cacheSubType; // 0 for development, 1 for production, when cacheType is multi-cache(2) + uint64_t objcOptsOffset; // VM offset from cache_header* to ObjC optimizations header + uint64_t objcOptsSize; // size of ObjC optimizations header + uint64_t cacheAtlasOffset; // VM offset from cache_header* to embedded cache atlas for process introspection + uint64_t cacheAtlasSize; // size of embedded cache atlas + uint64_t dynamicDataOffset; // VM offset from cache_header* to the location of dyld_cache_dynamic_data_header + uint64_t dynamicDataMaxSize; // maximum size of space reserved from dynamic data +}; + +// Uncomment this and check the build errors for the current mapping offset to check against when adding new fields. +// template class A { int x[-size]; }; A a; + + +struct dyld_cache_mapping_info { + uint64_t address; + uint64_t size; + uint64_t fileOffset; + uint32_t maxProt; + uint32_t initProt; +}; + +// Contains the flags for the dyld_cache_mapping_and_slide_info flgs field +enum { + DYLD_CACHE_MAPPING_AUTH_DATA = 1 << 0U, + DYLD_CACHE_MAPPING_DIRTY_DATA = 1 << 1U, + DYLD_CACHE_MAPPING_CONST_DATA = 1 << 2U, + DYLD_CACHE_MAPPING_TEXT_STUBS = 1 << 3U, + DYLD_CACHE_DYNAMIC_CONFIG_DATA = 1 << 4U, +}; + +struct dyld_cache_mapping_and_slide_info { + uint64_t address; + uint64_t size; + uint64_t fileOffset; + uint64_t slideInfoFileOffset; + uint64_t slideInfoFileSize; + uint64_t flags; + uint32_t maxProt; + uint32_t initProt; +}; + +struct dyld_cache_image_info +{ + uint64_t address; + uint64_t modTime; + uint64_t inode; + uint32_t pathFileOffset; + uint32_t pad; +}; + +struct dyld_cache_image_info_extra +{ + uint64_t exportsTrieAddr; // address of trie in unslid cache + uint64_t weakBindingsAddr; + uint32_t exportsTrieSize; + uint32_t weakBindingsSize; + uint32_t dependentsStartArrayIndex; + uint32_t reExportsStartArrayIndex; +}; + + +struct dyld_cache_accelerator_info +{ + uint32_t version; // currently 1 + uint32_t imageExtrasCount; // does not include aliases + uint32_t imagesExtrasOffset; // offset into this chunk of first dyld_cache_image_info_extra + uint32_t bottomUpListOffset; // offset into this chunk to start of 16-bit array of sorted image indexes + uint32_t dylibTrieOffset; // offset into this chunk to start of trie containing all dylib paths + uint32_t dylibTrieSize; // size of trie containing all dylib paths + uint32_t initializersOffset; // offset into this chunk to start of initializers list + uint32_t initializersCount; // size of initializers list + uint32_t dofSectionsOffset; // offset into this chunk to start of DOF sections list + uint32_t dofSectionsCount; // size of initializers list + uint32_t reExportListOffset; // offset into this chunk to start of 16-bit array of re-exports + uint32_t reExportCount; // size of re-exports + uint32_t depListOffset; // offset into this chunk to start of 16-bit array of dependencies (0x8000 bit set if upward) + uint32_t depListCount; // size of dependencies + uint32_t rangeTableOffset; // offset into this chunk to start of ss + uint32_t rangeTableCount; // size of dependencies + uint64_t dyldSectionAddr; // address of libdyld's __dyld section in unslid cache +}; + +struct dyld_cache_accelerator_initializer +{ + uint32_t functionOffset; // address offset from start of cache mapping + uint32_t imageIndex; +}; + +struct dyld_cache_range_entry +{ + uint64_t startAddress; // unslid address of start of region + uint32_t size; + uint32_t imageIndex; +}; + +struct dyld_cache_accelerator_dof +{ + uint64_t sectionAddress; // unslid address of start of region + uint32_t sectionSize; + uint32_t imageIndex; +}; + +struct dyld_cache_image_text_info +{ + uuid_t uuid; + uint64_t loadAddress; // unslid address of start of __TEXT + uint32_t textSegmentSize; + uint32_t pathOffset; // offset from start of cache file +}; + + +// The rebasing info is to allow the kernel to lazily rebase DATA pages of the +// dyld shared cache. Rebasing is adding the slide to interior pointers. +struct dyld_cache_slide_info +{ + uint32_t version; // currently 1 + uint32_t toc_offset; + uint32_t toc_count; + uint32_t entries_offset; + uint32_t entries_count; + uint32_t entries_size; // currently 128 + // uint16_t toc[toc_count]; + // entrybitmap entries[entries_count]; +}; + +struct dyld_cache_slide_info_entry { + uint8_t bits[4096/(8*4)]; // 128-byte bitmap +}; + + +// The version 2 of the slide info uses a different compression scheme. Since +// only interior pointers (pointers that point within the cache) are rebased +// (slid), we know the possible range of the pointers and thus know there are +// unused bits in each pointer. We use those bits to form a linked list of +// locations needing rebasing in each page. +// +// Definitions: +// +// pageIndex = (pageAddress - startOfAllDataAddress)/info->page_size +// pageStarts[] = info + info->page_starts_offset +// pageExtras[] = info + info->page_extras_offset +// valueMask = ~(info->delta_mask) +// deltaShift = __builtin_ctzll(info->delta_mask) - 2 +// +// There are three cases: +// +// 1) pageStarts[pageIndex] == DYLD_CACHE_SLIDE_PAGE_ATTR_NO_REBASE +// The page contains no values that need rebasing. +// +// 2) (pageStarts[pageIndex] & DYLD_CACHE_SLIDE_PAGE_ATTR_EXTRA) == 0 +// All rebase locations are in one linked list. The offset of the first +// rebase location in the page is pageStarts[pageIndex] * 4. +// +// 3) pageStarts[pageIndex] & DYLD_CACHE_SLIDE_PAGE_ATTR_EXTRA +// Multiple linked lists are needed for all rebase locations in a page. +// The pagesExtras array contains 2 or more entries each of which is the +// start of a new linked list in the page. The first is at: +// extrasStartIndex = (pageStarts[pageIndex] & 0x3FFF) +// The next is at extrasStartIndex+1. The last is denoted by +// having the high bit (DYLD_CACHE_SLIDE_PAGE_ATTR_END) of the pageExtras[] +// set. +// +// For 64-bit architectures, there is always enough free bits to encode all +// possible deltas. The info->delta_mask field shows where the delta is located +// in the pointer. That value must be masked off (valueMask) before the slide +// is added to the pointer. +// +// For 32-bit architectures, there are only three bits free (the three most +// significant bits). To extract the delta, you must first subtract value_add +// from the pointer value, then AND with delta_mask, then shift by deltaShift. +// That still leaves a maximum delta to the next rebase location of 28 bytes. +// To reduce the number or chains needed, an optimization was added. Turns +// out zero is common in the DATA region. A zero can be turned into a +// non-rebasing entry in the linked list. The can be done because nothing +// in the shared cache should point out of its dylib to the start of the shared +// cache. +// +// The code for processing a linked list (chain) is: +// +// uint32_t delta = 1; +// while ( delta != 0 ) { +// uint8_t* loc = pageStart + pageOffset; +// uintptr_t rawValue = *((uintptr_t*)loc); +// delta = ((rawValue & deltaMask) >> deltaShift); +// uintptr_t newValue = (rawValue & valueMask); +// if ( newValue != 0 ) { +// newValue += valueAdd; +// newValue += slideAmount; +// } +// *((uintptr_t*)loc) = newValue; +// pageOffset += delta; +// } +// +// +struct dyld_cache_slide_info2 +{ + uint32_t version; // currently 2 + uint32_t page_size; // currently 4096 (may also be 16384) + uint32_t page_starts_offset; + uint32_t page_starts_count; + uint32_t page_extras_offset; + uint32_t page_extras_count; + uint64_t delta_mask; // which (contiguous) set of bits contains the delta to the next rebase location + uint64_t value_add; + //uint16_t page_starts[page_starts_count]; + //uint16_t page_extras[page_extras_count]; +}; +#define DYLD_CACHE_SLIDE_PAGE_ATTRS 0xC000 // high bits of uint16_t are flags +#define DYLD_CACHE_SLIDE_PAGE_ATTR_EXTRA 0x8000 // index is into extras array (not starts array) +#define DYLD_CACHE_SLIDE_PAGE_ATTR_NO_REBASE 0x4000 // page has no rebasing +#define DYLD_CACHE_SLIDE_PAGE_ATTR_END 0x8000 // last chain entry for page + + + +// The version 3 of the slide info uses a different compression scheme. Since +// only interior pointers (pointers that point within the cache) are rebased +// (slid), we know the possible range of the pointers and thus know there are +// unused bits in each pointer. We use those bits to form a linked list of +// locations needing rebasing in each page. +// +// Definitions: +// +// pageIndex = (pageAddress - startOfAllDataAddress)/info->page_size +// pageStarts[] = info + info->page_starts_offset +// +// There are two cases: +// +// 1) pageStarts[pageIndex] == DYLD_CACHE_SLIDE_V3_PAGE_ATTR_NO_REBASE +// The page contains no values that need rebasing. +// +// 2) otherwise... +// All rebase locations are in one linked list. The offset of the first +// rebase location in the page is pageStarts[pageIndex]. +// +// A pointer is one of of the variants in dyld_cache_slide_pointer3 +// +// The code for processing a linked list (chain) is: +// +// uint32_t delta = pageStarts[pageIndex]; +// dyld_cache_slide_pointer3* loc = pageStart; +// do { +// loc += delta; +// delta = loc->offsetToNextPointer; +// if ( loc->auth.authenticated ) { +// newValue = loc->offsetFromSharedCacheBase + results->slide + auth_value_add; +// newValue = sign_using_the_various_bits(newValue); +// } +// else { +// uint64_t value51 = loc->pointerValue; +// uint64_t top8Bits = value51 & 0x0007F80000000000ULL; +// uint64_t bottom43Bits = value51 & 0x000007FFFFFFFFFFULL; +// uint64_t targetValue = ( top8Bits << 13 ) | bottom43Bits; +// newValue = targetValue + results->slide; +// } +// loc->raw = newValue; +// } while (delta != 0); +// +// +struct dyld_cache_slide_info3 +{ + uint32_t version; // currently 3 + uint32_t page_size; // currently 4096 (may also be 16384) + uint32_t page_starts_count; + uint64_t auth_value_add; + uint16_t page_starts[/* page_starts_count */]; +}; + +#define DYLD_CACHE_SLIDE_V3_PAGE_ATTR_NO_REBASE 0xFFFF // page has no rebasing + +union dyld_cache_slide_pointer3 +{ + uint64_t raw; + struct { + uint64_t pointerValue : 51, + offsetToNextPointer : 11, + unused : 2; + } plain; + + struct { + uint64_t offsetFromSharedCacheBase : 32, + diversityData : 16, + hasAddressDiversity : 1, + key : 2, + offsetToNextPointer : 11, + unused : 1, + authenticated : 1; // = 1; + } auth; +}; + + + +// The version 4 of the slide info is optimized for 32-bit caches up to 1GB. +// Since only interior pointers (pointers that point within the cache) are rebased +// (slid), we know the possible range of the pointers takes 30 bits. That +// gives us two bits to use to chain to the next rebase. +// +// Definitions: +// +// pageIndex = (pageAddress - startOfAllDataAddress)/info->page_size +// pageStarts[] = info + info->page_starts_offset +// pageExtras[] = info + info->page_extras_offset +// valueMask = ~(info->delta_mask) +// deltaShift = __builtin_ctzll(info->delta_mask) - 2 +// +// There are three cases: +// +// 1) pageStarts[pageIndex] == DYLD_CACHE_SLIDE4_PAGE_NO_REBASE +// The page contains no values that need rebasing. +// +// 2) (pageStarts[pageIndex] & DYLD_CACHE_SLIDE4_PAGE_USE_EXTRA) == 0 +// All rebase locations are in one linked list. The offset of the first +// rebase location in the page is pageStarts[pageIndex] * 4. +// +// 3) pageStarts[pageIndex] & DYLD_CACHE_SLIDE4_PAGE_USE_EXTRA +// Multiple chains are needed for all rebase locations in a page. +// The pagesExtras array contains 2 or more entries each of which is the +// start of a new chain in the page. The first is at: +// extrasStartIndex = (pageStarts[pageIndex] & DYLD_CACHE_SLIDE4_PAGE_INDEX) +// The next is at extrasStartIndex+1. The last is denoted by +// having the high bit (DYLD_CACHE_SLIDE4_PAGE_EXTRA_END) of the pageExtras[]. +// +// For 32-bit architectures, there are only two bits free (the two most +// significant bits). To extract the delta, you must first subtract value_add +// from the pointer value, then AND with delta_mask, then shift by deltaShift. +// That still leaves a maximum delta to the next rebase location of 12 bytes. +// To reduce the number or chains needed, an optimization was added. Turns +// most of the non-rebased data are small values and can be co-opt'ed into +// being used in the chain. The can be done because nothing +// in the shared cache should point to the first 64KB which are in the shared +// cache header information. So if the resulting pointer points to the +// start of the cache +/-32KB, then it is actually a small number that should +// not be rebased, but just reconstituted. +// +// The code for processing a linked list (chain) is: +// +// uint32_t delta = 1; +// while ( delta != 0 ) { +// uint8_t* loc = pageStart + pageOffset; +// uint32_t rawValue = *((uint32_t*)loc); +// delta = ((rawValue & deltaMask) >> deltaShift); +// uintptr_t newValue = (rawValue & valueMask); +// if ( (newValue & 0xFFFF8000) == 0 ) { +// // small positive non-pointer, use as-is +// } +// else if ( (newValue & 0x3FFF8000) == 0x3FFF8000 ) { +// // small negative non-pointer +// newValue |= 0xC0000000; +// } +// else { +// // pointer that needs rebasing +// newValue += valueAdd; +// newValue += slideAmount; +// } +// *((uint32_t*)loc) = newValue; +// pageOffset += delta; +// } +// +// +struct dyld_cache_slide_info4 +{ + uint32_t version; // currently 4 + uint32_t page_size; // currently 4096 (may also be 16384) + uint32_t page_starts_offset; + uint32_t page_starts_count; + uint32_t page_extras_offset; + uint32_t page_extras_count; + uint64_t delta_mask; // which (contiguous) set of bits contains the delta to the next rebase location (0xC0000000) + uint64_t value_add; // base address of cache + //uint16_t page_starts[page_starts_count]; + //uint16_t page_extras[page_extras_count]; +}; +#define DYLD_CACHE_SLIDE4_PAGE_NO_REBASE 0xFFFF // page has no rebasing +#define DYLD_CACHE_SLIDE4_PAGE_INDEX 0x7FFF // mask of page_starts[] values +#define DYLD_CACHE_SLIDE4_PAGE_USE_EXTRA 0x8000 // index is into extras array (not a chain start offset) +#define DYLD_CACHE_SLIDE4_PAGE_EXTRA_END 0x8000 // last chain entry for page + + +struct dyld_cache_local_symbols_info +{ + uint32_t nlistOffset; // offset into this chunk of nlist entries + uint32_t nlistCount; // count of nlist entries + uint32_t stringsOffset; // offset into this chunk of string pool + uint32_t stringsSize; // byte count of string pool + uint32_t entriesOffset; // offset into this chunk of array of dyld_cache_local_symbols_entry + uint32_t entriesCount; // number of elements in dyld_cache_local_symbols_entry array +}; + +struct dyld_cache_local_symbols_entry +{ + uint32_t dylibOffset; // offset in cache file of start of dylib + uint32_t nlistStartIndex; // start index of locals for this dylib + uint32_t nlistCount; // number of local symbols for this dylib +}; + +struct dyld_cache_local_symbols_entry_64 +{ + uint64_t dylibOffset; // offset in cache buffer of start of dylib + uint32_t nlistStartIndex; // start index of locals for this dylib + uint32_t nlistCount; // number of local symbols for this dylib +}; + +struct dyld_subcache_entry_v1 +{ + uint8_t uuid[16]; // The UUID of the subCache file + uint64_t cacheVMOffset; // The offset of this subcache from the main cache base address +}; + +struct dyld_subcache_entry +{ + uint8_t uuid[16]; // The UUID of the subCache file + uint64_t cacheVMOffset; // The offset of this subcache from the main cache base address + char fileSuffix[32]; // The file name suffix of the subCache file e.g. ".25.data", ".03.development" +}; + +// This struct is a small piece of dynamic data that can be included in the shared region, and contains configuration +// data about the shared cache in use by the process. It is located +struct dyld_cache_dynamic_data_header +{ + char magic[16]; // e.g. "dyld_data v0" + uint64_t fsId; // The fsid_t of the shared cache being used by a process + uint64_t fsObjId; // The fs_obj_id_t of the shared cache being used by a process +}; + +// This is the location of the macOS shared cache on macOS 11.0 and later +#define MACOSX_MRM_DYLD_SHARED_CACHE_DIR "/System/Library/dyld/" + +// This is old define for the old location of the dyld cache +#define MACOSX_DYLD_SHARED_CACHE_DIR MACOSX_MRM_DYLD_SHARED_CACHE_DIR + +#define IPHONE_DYLD_SHARED_CACHE_DIR "/System/Library/Caches/com.apple.dyld/" + +#define DRIVERKIT_DYLD_SHARED_CACHE_DIR "/System/DriverKit/System/Library/dyld/" + +#if !TARGET_OS_SIMULATOR + #define DYLD_SHARED_CACHE_BASE_NAME "dyld_shared_cache_" +#else + #define DYLD_SHARED_CACHE_BASE_NAME "dyld_sim_shared_cache_" +#endif +#define DYLD_SHARED_CACHE_DEVELOPMENT_EXT ".development" + +#define DYLD_SHARED_CACHE_DYNAMIC_DATA_MAGIC "dyld_data v0" + +static const char* cryptexPrefixes[] = { + "/System/Volumes/Preboot/Cryptexes/OS/", + "/private/preboot/Cryptexes/OS/", + "/System/Cryptexes/OS" +}; + +static const uint64_t kDyldSharedCacheTypeDevelopment = 0; +static const uint64_t kDyldSharedCacheTypeProduction = 1; +static const uint64_t kDyldSharedCacheTypeUniversal = 2; + + + + + +#endif // __DYLD_CACHE_FORMAT__ + + diff --git a/app/src/main/cpp/Dobby/builtin-plugin/SymbolResolver/macho/shared_cache_ctx.cpp b/app/src/main/cpp/Dobby/builtin-plugin/SymbolResolver/macho/shared_cache_ctx.cpp new file mode 100644 index 0000000..2c9db23 --- /dev/null +++ b/app/src/main/cpp/Dobby/builtin-plugin/SymbolResolver/macho/shared_cache_ctx.cpp @@ -0,0 +1,183 @@ +#include "shared_cache_ctx.h" + +#include +#include +#include + +#include "logging/logging.h" + +#include "mmap_file_util.h" + +typedef uintptr_t addr_t; + +extern "C" { +extern const char *dyld_shared_cache_file_path(); +extern int __shared_region_check_np(uint64_t *startaddress); +} + +const char *shared_cache_get_file_path() { + return dyld_shared_cache_file_path(); +} + +struct dyld_cache_header *shared_cache_get_load_addr() { + addr_t shared_cache_base = 0; + if (__shared_region_check_np((uint64_t *)&shared_cache_base) != 0) { + WARN_LOG("__shared_region_check_np failed"); + } + + if (shared_cache_base) + return (struct dyld_cache_header *)shared_cache_base; + + // task info + task_dyld_info_data_t task_dyld_info; + mach_msg_type_number_t count = TASK_DYLD_INFO_COUNT; + kern_return_t ret = task_info(mach_task_self(), TASK_DYLD_INFO, (task_info_t)&task_dyld_info, &count); + if (ret != KERN_SUCCESS) { + ERROR_LOG("task_info failed, ret: %d", ret); + return NULL; + } + + // get dyld load address + auto *infos = (struct dyld_all_image_infos *)(uintptr_t)task_dyld_info.all_image_info_addr; + auto *shared_cache = (struct dyld_cache_header *)infos->sharedCacheBaseAddress; + return shared_cache; +} + +int shared_cache_load_symbols(shared_cache_ctx_t *ctx) { + uint64_t localSymbolsOffset = 0; + + bool latest_shared_cache_format = true; + + const char *shared_cache_path = shared_cache_get_file_path(); + char shared_cache_symbols_path[4096] = {0}; + { + strcat(shared_cache_symbols_path, shared_cache_path); + strcat(shared_cache_symbols_path, ".symbols"); + } + + auto mmapSharedCacheSymbolsMng = new MmapFileManager(shared_cache_symbols_path); + auto mmap_buffer = mmapSharedCacheSymbolsMng->map(); + if (mmap_buffer) { // iphoneos >= 15.0, which has .symbols file + ctx->mmap_shared_cache = (struct dyld_cache_header *)mmap_buffer; + + localSymbolsOffset = ctx->mmap_shared_cache->localSymbolsOffset; + } else { + // iphoneos < 15.0, which has no .symbols file + auto mmapSharedCacheMng = new MmapFileManager(shared_cache_symbols_path); + + auto runtime_shared_cache = ctx->runtime_shared_cache; + uint64_t mmap_length = runtime_shared_cache->localSymbolsSize; + uint64_t mmap_offset = runtime_shared_cache->localSymbolsOffset; + + if (mmap_length == 0) + return -1; + + auto mmap_buffer = mmapSharedCacheMng->map_options(mmap_length, mmap_offset); + if (!mmap_buffer) { + return -1; + } + + // fake shared cache header + auto mmap_shared_cache = + (struct dyld_cache_header *)((addr_t)mmap_buffer - runtime_shared_cache->localSymbolsOffset); + ctx->mmap_shared_cache = mmap_shared_cache; + + localSymbolsOffset = runtime_shared_cache->localSymbolsOffset; + + latest_shared_cache_format = false; + } + ctx->latest_shared_cache_format = latest_shared_cache_format; + + { + auto mmap_shared_cache = ctx->mmap_shared_cache; + auto localInfo = (struct dyld_cache_local_symbols_info *)((char *)mmap_shared_cache + localSymbolsOffset); + ctx->local_symbols_info = localInfo; + + if (ctx->latest_shared_cache_format) { + auto localEntries_64 = (struct dyld_cache_local_symbols_entry_64 *)((char *)localInfo + localInfo->entriesOffset); + ctx->local_symbols_entries_64 = localEntries_64; + } else { + auto localEntries = (struct dyld_cache_local_symbols_entry *)((char *)localInfo + localInfo->entriesOffset); + ctx->local_symbols_entries = localEntries; + } + + ctx->symtab = (nlist_t *)((char *)localInfo + localInfo->nlistOffset); + ctx->strtab = ((char *)localInfo) + localInfo->stringsOffset; + } + + return 0; +} + +int shared_cache_ctx_init(shared_cache_ctx_t *ctx) { + memset(ctx, 0, sizeof(shared_cache_ctx_t)); + + auto runtime_shared_cache = shared_cache_get_load_addr(); + if (!runtime_shared_cache) { + return -1; + } + ctx->runtime_shared_cache = runtime_shared_cache; + + // shared cache slide + auto mappings = + (struct dyld_cache_mapping_info *)((char *)runtime_shared_cache + runtime_shared_cache->mappingOffset); + uintptr_t slide = (uintptr_t)runtime_shared_cache - (uintptr_t)(mappings[0].address); + ctx->runtime_slide = slide; + + return 0; +} + +// refer: dyld +bool shared_cache_is_contain(shared_cache_ctx_t *ctx, addr_t addr, size_t length) { + struct dyld_cache_header *runtime_shared_cache; + if (ctx) { + runtime_shared_cache = ctx->runtime_shared_cache; + } else { + runtime_shared_cache = shared_cache_get_load_addr(); + } + + addr_t region_start = runtime_shared_cache->sharedRegionStart + ctx->runtime_slide; + addr_t region_end = region_start + runtime_shared_cache->sharedRegionSize; + if (addr >= region_start && addr < region_end) + return true; + + return false; +} + +int shared_cache_get_symbol_table(shared_cache_ctx_t *ctx, mach_header_t *image_header, nlist_t **out_symtab, + uint32_t *out_symtab_count, char **out_strtab) { + uint64_t textOffsetInCache = (uint64_t)image_header - (uint64_t)ctx->runtime_shared_cache; + + nlist_t *localNlists = NULL; + uint32_t localNlistCount = 0; + const char *localStrings = NULL; + + const uint32_t entriesCount = ctx->local_symbols_info->entriesCount; + for (uint32_t i = 0; i < entriesCount; ++i) { + if (ctx->latest_shared_cache_format) { + if (ctx->local_symbols_entries_64[i].dylibOffset == textOffsetInCache) { + uint32_t localNlistStart = ctx->local_symbols_entries_64[i].nlistStartIndex; + localNlistCount = ctx->local_symbols_entries_64[i].nlistCount; + localNlists = &ctx->symtab[localNlistStart]; + break; + } + } else { + if (ctx->local_symbols_entries[i].dylibOffset == textOffsetInCache) { + uint32_t localNlistStart = ctx->local_symbols_entries[i].nlistStartIndex; + localNlistCount = ctx->local_symbols_entries[i].nlistCount; + localNlists = &ctx->symtab[localNlistStart]; + break; + } + } + +#if 0 + static struct dyld_cache_image_info *imageInfos = NULL; + imageInfos = (struct dyld_cache_image_info *)((addr_t)g_mmap_shared_cache + g_mmap_shared_cache->imagesOffset); + char *image_name = (char *)g_mmap_shared_cache + imageInfos[i].pathFileOffset; + INFO_LOG("dyld image: %s", image_name); +#endif + } + *out_symtab = localNlists; + *out_symtab_count = (uint32_t)localNlistCount; + *out_strtab = (char *)ctx->strtab; + return 0; +} \ No newline at end of file diff --git a/app/src/main/cpp/Dobby/builtin-plugin/SymbolResolver/macho/shared_cache_ctx.h b/app/src/main/cpp/Dobby/builtin-plugin/SymbolResolver/macho/shared_cache_ctx.h new file mode 100644 index 0000000..a17fdc5 --- /dev/null +++ b/app/src/main/cpp/Dobby/builtin-plugin/SymbolResolver/macho/shared_cache_ctx.h @@ -0,0 +1,45 @@ +#include +#include +#include + +#include "shared-cache/dyld_cache_format.h" + +#if defined(__LP64__) +typedef struct mach_header_64 mach_header_t; +typedef struct segment_command_64 segment_command_t; +typedef struct section_64 section_t; +typedef struct nlist_64 nlist_t; +#define LC_SEGMENT_ARCH_DEPENDENT LC_SEGMENT_64 +#else +typedef struct mach_header mach_header_t; +typedef struct segment_command segment_command_t; +typedef struct section section_t; +typedef struct nlist nlist_t; +#define LC_SEGMENT_ARCH_DEPENDENT LC_SEGMENT +#endif + +typedef uintptr_t addr_t; + +typedef struct shared_cache_ctx { + struct dyld_cache_header *runtime_shared_cache; + struct dyld_cache_header *mmap_shared_cache; + + uintptr_t runtime_slide; + + bool latest_shared_cache_format; + struct dyld_cache_local_symbols_info *local_symbols_info; + struct dyld_cache_local_symbols_entry *local_symbols_entries; + struct dyld_cache_local_symbols_entry_64 *local_symbols_entries_64; + + nlist_t *symtab; + char *strtab; +} shared_cache_ctx_t; + +int shared_cache_ctx_init(shared_cache_ctx_t *ctx); + +int shared_cache_load_symbols(shared_cache_ctx_t *ctx); + +bool shared_cache_is_contain(shared_cache_ctx_t *ctx, addr_t addr, size_t length); + +int shared_cache_get_symbol_table(shared_cache_ctx_t *ctx, mach_header_t *image_header, nlist_t **out_symtab, + uint32_t *out_symtab_count, char **out_strtab); \ No newline at end of file diff --git a/app/src/main/cpp/Dobby/builtin-plugin/SymbolResolver/mmap_file_util.h b/app/src/main/cpp/Dobby/builtin-plugin/SymbolResolver/mmap_file_util.h new file mode 100644 index 0000000..6439274 --- /dev/null +++ b/app/src/main/cpp/Dobby/builtin-plugin/SymbolResolver/mmap_file_util.h @@ -0,0 +1,64 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include + +class MmapFileManager { + const char *file_; + uint8_t *mmap_buffer_; + size_t mmap_buffer_size_; + +public: + explicit MmapFileManager(const char *file) : file_(file), mmap_buffer_(nullptr) { + } + + ~MmapFileManager() { + if (mmap_buffer_) { + munmap((void *)mmap_buffer_, mmap_buffer_size_); + } + } + + uint8_t *map() { + size_t file_size = 0; + { + struct stat s; + int rt = stat(file_, &s); + if (rt != 0) { + // printf("mmap %s failed\n", file_); + return NULL; + } + file_size = s.st_size; + } + + return map_options(file_size, 0); + } + + uint8_t *map_options(size_t _size, off_t _off) { + if (!mmap_buffer_) { + int fd = open(file_, O_RDONLY, 0); + if (fd < 0) { + // printf("%s open failed\n", file_); + return NULL; + } + + // auto align + auto mmap_buffer = (uint8_t *)mmap(0, _size, PROT_READ | PROT_WRITE, MAP_FILE | MAP_PRIVATE, fd, _off); + if (mmap_buffer == MAP_FAILED) { + // printf("mmap %s failed\n", file_); + return NULL; + } + + close(fd); + + mmap_buffer_ = mmap_buffer; + mmap_buffer_size_ = _size; + } + return mmap_buffer_; + } +}; diff --git a/app/src/main/cpp/Dobby/builtin-plugin/SymbolResolver/pe/dobby_symbol_resolver.cc b/app/src/main/cpp/Dobby/builtin-plugin/SymbolResolver/pe/dobby_symbol_resolver.cc new file mode 100644 index 0000000..e1d0502 --- /dev/null +++ b/app/src/main/cpp/Dobby/builtin-plugin/SymbolResolver/pe/dobby_symbol_resolver.cc @@ -0,0 +1,26 @@ +#include "SymbolResolver/dobby_symbol_resolver.h" +#include "dobby/common.h" + +#include + +#include +#include + +#include "PlatformUtil/ProcessRuntimeUtility.h" + +#include + +#undef LOG_TAG +#define LOG_TAG "DobbySymbolResolver" + +PUBLIC void *DobbySymbolResolver(const char *image_name, const char *symbol_name_pattern) { + void *result = NULL; + + HMODULE hMod = LoadLibraryExA(image_name, NULL, DONT_RESOLVE_DLL_REFERENCES); + result = GetProcAddress(hMod, symbol_name_pattern); + if (result) + return result; + + //result = resolve_elf_internal_symbol(image_name, symbol_name_pattern); + return result; +} \ No newline at end of file diff --git a/app/src/main/cpp/Dobby/cmake/Macros.cmake b/app/src/main/cpp/Dobby/cmake/Macros.cmake new file mode 100644 index 0000000..5774bef --- /dev/null +++ b/app/src/main/cpp/Dobby/cmake/Macros.cmake @@ -0,0 +1,3 @@ +macro(SET_OPTION option value) + set(${option} ${value} CACHE INTERNAL "" FORCE) +endmacro() \ No newline at end of file diff --git a/app/src/main/cpp/Dobby/cmake/Util.cmake b/app/src/main/cpp/Dobby/cmake/Util.cmake new file mode 100644 index 0000000..6a722a2 --- /dev/null +++ b/app/src/main/cpp/Dobby/cmake/Util.cmake @@ -0,0 +1,19 @@ +# Check files list exist +function(check_files_exist CHECK_FILES) + foreach(file ${CHECK_FILES}) + if(NOT EXISTS "${file}") + message(FATAL_ERROR "${file} NOT EXISTS!") + endif() + endforeach() +endfunction(check_files_exist CHECK_FILES) + +# Search suffix files +function(search_suffix_files suffix INPUT_VARIABLE OUTPUT_VARIABLE) + set(ResultFiles ) + foreach(filePath ${${INPUT_VARIABLE}}) + # message(STATUS "[*] searching *.${suffix} from ${filePath}") + file(GLOB files ${filePath}/*.${suffix}) + set(ResultFiles ${ResultFiles} ${files}) + endforeach() + set(${OUTPUT_VARIABLE} ${ResultFiles} PARENT_SCOPE) +endfunction() diff --git a/app/src/main/cpp/Dobby/cmake/auto_source_group.cmake b/app/src/main/cpp/Dobby/cmake/auto_source_group.cmake new file mode 100644 index 0000000..f563836 --- /dev/null +++ b/app/src/main/cpp/Dobby/cmake/auto_source_group.cmake @@ -0,0 +1,32 @@ +function (auto_source_group _folder _base _pattern) + if (ARGC GREATER 3) + set(_exclude ${ARGN}) + else () + set(_exclude) + endif () + file (GLOB _files RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}/ ${_folder}/*) + set (folder_files) + foreach (_fname ${_files}) + if (IS_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/${_fname}) + auto_source_group ("${_fname}" "${_base}" "${_pattern}" "${_exclude}") + elseif (_fname MATCHES ${_pattern}) + if(_exclude) + if (NOT _fname MATCHES ${_exclude}) + set(folder_files ${folder_files} ${_fname}) + endif () + else () + set(folder_files ${folder_files} ${_fname}) + endif () + endif () + endforeach () + + string(REPLACE "./" "" _folder2 ${_folder}) + string(REPLACE "/" "\\" _folder2 ${_folder2}) + if (_folder2 STREQUAL ".") + source_group(${_base} FILES ${folder_files}) + else () + source_group(${_base}\\${_folder2} FILES ${folder_files}) + endif () + + set(AUTO_FILES_RESULT ${AUTO_FILES_RESULT} ${folder_files} PARENT_SCOPE) +endfunction () \ No newline at end of file diff --git a/app/src/main/cpp/Dobby/cmake/build_environment_check.cmake b/app/src/main/cpp/Dobby/cmake/build_environment_check.cmake new file mode 100644 index 0000000..9e7a67f --- /dev/null +++ b/app/src/main/cpp/Dobby/cmake/build_environment_check.cmake @@ -0,0 +1,86 @@ +if(__BUILD_ENVIRONMENT_CHECK) + return() +endif() +set(__BUILD_ENVIRONMENT_CHECK TRUE) + +message(STATUS "") +message(STATUS "********* build environment check ***********") + + +# The Compiler ID +if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "AppleClang") + set(COMPILER.Clang 1) +elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") + set(COMPILER.Gcc 1) +elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Intel") +elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") + set(COMPILER.MSVC 1) +else() + message (FATAL_ERROR "Compiler ${CMAKE_CXX_COMPILER_ID} not configured") +endif() +message(STATUS "\tCompiler: \t ${CMAKE_CXX_COMPILER_ID}") + +if(MSVC) + string(TOLOWER ${MSVC_CXX_ARCHITECTURE_ID} CMAKE_SYSTEM_PROCESSOR) + set(CMAKE_SYSTEM_PROCESSOR ${MSVC_CXX_ARCHITECTURE_ID}) +endif() + + +if(BUILDING_SILICON) + set(CMAKE_SYSTEM_PROCESSOR ${CMAKE_OSX_ARCHITECTURES}) +endif() + +string(TOLOWER ${CMAKE_SYSTEM_PROCESSOR} CMAKE_SYSTEM_PROCESSOR) + +# The Processor +if(CMAKE_SYSTEM_PROCESSOR MATCHES "amd64.*|x86_64.*|AMD64.*|x64.*") + set(PROCESSOR.X86_64 1) +elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "i686.*|i386.*|x86.*|amd64.*|AMD64.*") + set(PROCESSOR.X86 1) +elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^arm64.*") + set(PROCESSOR.AARCH64 1) +elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(aarch64.*|AARCH64.*)") + set(PROCESSOR.AARCH64 1) +elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(arm.*|ARM.*)") + set(PROCESSOR.ARM 1) +elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(powerpc|ppc)64le") + message(STATUS "NOT SUPPORT ${CMAKE_SYSTEM_PROCESSOR}") + set(PROCESSOR.PPC64LE 1) +elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(powerpc|ppc)64") + message(STATUS "NOT SUPPORT ${CMAKE_SYSTEM_PROCESSOR}") + set(PROCESSOR.PPC64 1) +else() + message (FATAL_ERROR "Processor ${CMAKE_SYSTEM_PROCESSOR} not configured") +endif() +message(STATUS "\tProcessor:\t ${CMAKE_SYSTEM_PROCESSOR}") + +# The System +if(CMAKE_SYSTEM_NAME MATCHES "^Android") + set(SYSTEM.Android 1) +elseif(CMAKE_SYSTEM_NAME MATCHES "^Windows") + set(SYSTEM.Windows 1) +elseif(CMAKE_SYSTEM_NAME MATCHES "^Linux") + set(SYSTEM.Linux 1) +elseif(CMAKE_SYSTEM_NAME MATCHES "^iOS") + set(SYSTEM.iOS 1) + set(SYSTEM.Darwin 1) +elseif(CMAKE_SYSTEM_NAME MATCHES "^macOS") + set(SYSTEM.macOS 1) + set(SYSTEM.Darwin 1) +elseif(CMAKE_SYSTEM_NAME MATCHES "^Darwin") + if(PROCESSOR.AARCH64 OR PROCESSOR.ARM) + set(CMAKE_SYSTEM_NAME "iOS or Silicon") + set(SYSTEM.iOS 1) + set(SYSTEM.Silicon 1) + elseif(PROCESSOR.X86 OR PROCESSOR.X86_64) + set(CMAKE_SYSTEM_NAME "macOS") + set(SYSTEM.macOS 1) + endif() + set(SYSTEM.Darwin 1) +else() + message (FATAL_ERROR "System ${CMAKE_SYSTEM_NAME} not configured") +endif() +message(STATUS "\tSystem: \t ${CMAKE_SYSTEM_NAME}") + +message(STATUS "***************************************") +message(STATUS "") diff --git a/app/src/main/cpp/Dobby/cmake/compiler_and_linker.cmake b/app/src/main/cpp/Dobby/cmake/compiler_and_linker.cmake new file mode 100644 index 0000000..9fc1754 --- /dev/null +++ b/app/src/main/cpp/Dobby/cmake/compiler_and_linker.cmake @@ -0,0 +1,55 @@ +# :< You Shall Not Pass! +if (0) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Werror") +endif () + +set(linker_flags "") +if (NOT DOBBY_DEBUG) + set(linker_flags "${linker_flags} -Wl,-x -Wl,-S") +endif () + +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fno-rtti -fno-exceptions") + +if (SYSTEM.Darwin) + # set(compiler_flags "${compiler_flags} -nostdinc++") +elseif (SYSTEM.Android) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fomit-frame-pointer") + if (NOT DOBBY_DEBUG) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -ffunction-sections -fdata-sections") + set(linker_flags "${linker_flags} -Wl,--gc-sections -Wl,--exclude-libs,ALL") + endif () +elseif (SYSTEM.Linux) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC") + if (COMPILER.Clang) + if (PROCESSOR.ARM) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} --target=armv7-unknown-linux-gnueabihf") + elseif (PROCESSOR.ARM64) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} --target=aarch64-unknown-linux-gnu") + elseif (PROCESSOR.X86) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} --target=i686-unknown-linux-gnu") + elseif (PROCESSOR.X86_64) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} --target=x86_64-unknown-linux-gnu") + endif () + endif () +elseif (SYSTEM.Windows) +endif () + +if (NOT DOBBY_DEBUG) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O3") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fno-rtti -fvisibility=hidden -fvisibility-inlines-hidden") +endif () + +if (PROCESSOR.ARM) + set(CMAKE_ASM_FLAGS "${CMAKE_ASM_FLAGS} -arch armv7 -x assembler-with-cpp") +elseif (PROCESSOR.AARCH64) + set(CMAKE_ASM_FLAGS "${CMAKE_ASM_FLAGS} -arch arm64 -x assembler-with-cpp") +endif () + +# sync cxx with c flags +set(CMAKE_CXX_FLAGS "${CMAKE_C_FLAGS} ${CMAKE_CXX_FLAGS}") + +message(STATUS "CMAKE_C_COMPILER: ${CMAKE_C_COMPILER}") +message(STATUS "CMAKE_CXX_COMPILER: ${CMAKE_CXX_COMPILER}") +message(STATUS "CMAKE_C_FLAGS: ${CMAKE_C_FLAGS}") +message(STATUS "CMAKE_CXX_FLAGS: ${CMAKE_CXX_FLAGS}") +message(STATUS "CMAKE_SHARED_LINKER_FLAGS: ${CMAKE_SHARED_LINKER_FLAGS}") diff --git a/app/src/main/cpp/Dobby/cmake/dobby.xcode.source.cmake b/app/src/main/cpp/Dobby/cmake/dobby.xcode.source.cmake new file mode 100644 index 0000000..64fb0e0 --- /dev/null +++ b/app/src/main/cpp/Dobby/cmake/dobby.xcode.source.cmake @@ -0,0 +1,94 @@ +set(dobby.SOURCE_FILE_LIST + # cpu + source/core/arch/CpuFeature.cc + source/core/arch/CpuRegister.cc + + # cpu - x86 + source/core/arch/x86/cpu-x86.cc + + # assembler + source/core/assembler/assembler.cc + source/core/assembler/assembler-arm.cc + source/core/assembler/assembler-arm64.cc + source/core/assembler/assembler-ia32.cc + source/core/assembler/assembler-x64.cc + + # codegen + source/core/codegen/codegen-arm.cc + source/core/codegen/codegen-arm64.cc + source/core/codegen/codegen-ia32.cc + source/core/codegen/codegen-x64.cc + + # executable memory - code buffer + source/MemoryAllocator/CodeBuffer/CodeBufferBase.cc + source/MemoryAllocator/CodeBuffer/code-buffer-x86.cc + + # executable memory + source/MemoryAllocator/AssemblyCodeBuilder.cc + source/MemoryAllocator/MemoryArena.cc + + # instruction relocation + source/InstructionRelocation/arm/InstructionRelocationARM.cc + source/InstructionRelocation/arm64/InstructionRelocationARM64.cc + source/InstructionRelocation/x86/X86InstructionRelocation.cc + source/InstructionRelocation/x64/InstructionRelocationX64.cc + + source/InstructionRelocation/x86/x86_insn_decode/x86_insn_decode.c + + # intercept routing + source/InterceptRouting/InterceptRouting.cpp + + # intercept routing trampoline + source/TrampolineBridge/Trampoline/arm/trampoline-arm.cc + source/TrampolineBridge/Trampoline/arm64/trampoline-arm64.cc + source/TrampolineBridge/Trampoline/x86/trampoline-x86.cc + source/TrampolineBridge/Trampoline/x64/trampoline-x64.cc + + # intercept routing plugin (buildin) + source/InterceptRouting/Routing/FunctionInlineReplace/function-inline-replace.cc + source/InterceptRouting/Routing/FunctionInlineReplace/FunctionInlineReplaceExport.cc + + # plugin register + source/InterceptRouting/RoutingPlugin/RoutingPlugin.cc + + # unified interface + + # platform util + source/UserMode/PlatformUtil/${platform2}/ProcessRuntimeUtility.cc + + # user mode - platform interface + source/UserMode/UnifiedInterface/platform-${platform1}.cc + + # user mode - executable memory + source/UserMode/ExecMemory/code-patch-tool-${platform1}.cc + source/UserMode/ExecMemory/clear-cache-tool-all.c + + # main + source/dobby.cpp + source/Interceptor.cpp + source/InterceptEntry.cpp + ) + +if(FunctionWrapper OR DynamicBinaryInstrument) + set(dobby.SOURCE_FILE_LIST ${dobby.SOURCE_FILE_LIST} + # closure trampoline bridge + source/TrampolineBridge/ClosureTrampolineBridge/common_bridge_handler.cc + + source/TrampolineBridge/ClosureTrampolineBridge/arm/helper-arm.cc + source/TrampolineBridge/ClosureTrampolineBridge/arm/closure-bridge-arm.cc + source/TrampolineBridge/ClosureTrampolineBridge/arm/ClosureTrampolineARM.cc + + source/TrampolineBridge/ClosureTrampolineBridge/arm64/helper-arm64.cc + source/TrampolineBridge/ClosureTrampolineBridge/arm64/closure-bridge-arm64.cc + source/TrampolineBridge/ClosureTrampolineBridge/arm64/ClosureTrampolineARM64.cc + + source/TrampolineBridge/ClosureTrampolineBridge/x64/helper-x64.cc + source/TrampolineBridge/ClosureTrampolineBridge/x64/closure-bridge-x64.cc + source/TrampolineBridge/ClosureTrampolineBridge/x64/ClosureTrampolineX64.cc + + # user mode - multi thread support + source/UserMode/MultiThreadSupport/ThreadSupport.cpp + source/UserMode/Thread/PlatformThread.cc + source/UserMode/Thread/platform-thread-${platform1}.cc + ) +endif() \ No newline at end of file diff --git a/app/src/main/cpp/Dobby/cmake/platform/platform-darwin.cmake b/app/src/main/cpp/Dobby/cmake/platform/platform-darwin.cmake new file mode 100644 index 0000000..826c418 --- /dev/null +++ b/app/src/main/cpp/Dobby/cmake/platform/platform-darwin.cmake @@ -0,0 +1,30 @@ +# set(CMAKE_BUILD_WITH_INSTALL_NAME_DIR TRUE) +set(CMAKE_INSTALL_NAME_DIR "@rpath") +set(CMAKE_SHARED_LIBRARY_RUNTIME_C_FLAG "-Wl,-rpath,") +add_library(DobbyX ${DOBBY_LIBRARY_TYPE} ${dobby.HEADER_FILE_LIST} ${dobby.SOURCE_FILE_LIST} ${logging.SOURCE_FILE_LIST} ${misc_helper.SOURCE_FILE_LIST} ${dobby.plugin.SOURCE_FILE_LIST}) + +set_target_properties(DobbyX + PROPERTIES + LINK_FLAGS "${linker_flags}" + COMPILE_FLAGS "${compiler_flags}" + ) + +# set framework property +set_target_properties(DobbyX PROPERTIES + FRAMEWORK TRUE + FRAMEWORK_VERSION A + MACOSX_FRAMEWORK_IDENTIFIER "com.dobby.dobby" + # MACOSX_FRAMEWORK_INFO_PLIST Info.plist + VERSION 1.0.0 # current version + SOVERSION 1.0.0 # compatibility version + PUBLIC_HEADER include/dobby.h + XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY "Apple Development" + ) + +if ((SYSTEM.Darwin AND BUILDING_PLUGIN) AND (NOT DOBBY_BUILD_KERNEL_MODE)) +add_subdirectory(builtin-plugin/Dyld2HideLibrary) +add_subdirectory(builtin-plugin/ObjcRuntimeHook) +if (PROCESSOR.AARCH64) + add_subdirectory(builtin-plugin/SupervisorCallMonitor) +endif () +endif() \ No newline at end of file diff --git a/app/src/main/cpp/Dobby/cmake/xcode_generator_helper.cmake b/app/src/main/cpp/Dobby/cmake/xcode_generator_helper.cmake new file mode 100644 index 0000000..243593d --- /dev/null +++ b/app/src/main/cpp/Dobby/cmake/xcode_generator_helper.cmake @@ -0,0 +1,9 @@ +if(CMAKE_GENERATOR STREQUAL Xcode) + message(STATUS "[*] Detect Xcode Project") + set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_DEBUG ${CMAKE_BINARY_DIR}/build/Debug) + set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_RELEASE ${CMAKE_BINARY_DIR}/build/Release) + set(CMAKE_LIBRARY_OUTPUT_DIRECTORY_DEBUG ${CMAKE_BINARY_DIR}/build/Debug) + set(CMAKE_LIBRARY_OUTPUT_DIRECTORY_RELEASE ${CMAKE_BINARY_DIR}/build/Release) + set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG ${CMAKE_BINARY_DIR}/build/Debug) + set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE ${CMAKE_BINARY_DIR}/build/Release) +endif() \ No newline at end of file diff --git a/app/src/main/cpp/Dobby/docs/compile.md b/app/src/main/cpp/Dobby/docs/compile.md new file mode 100644 index 0000000..002dba4 --- /dev/null +++ b/app/src/main/cpp/Dobby/docs/compile.md @@ -0,0 +1,89 @@ +# Build + +## CMake build options + +``` +option(DOBBY_GENERATE_SHARED "Build shared library" ON) + +option(DOBBY_DEBUG "Enable debug logging" OFF) + +option(NearBranch "Enable near branch trampoline" ON) + +option(FullFloatingPointRegisterPack "Save and pack all floating-point registers" OFF) + +option(Plugin.SymbolResolver "Enable symbol resolver" ON) + +option(Plugin.ImportTableReplace "Enable import table replace " OFF) + +option(Plugin.Android.BionicLinkerUtil "Enable android bionic linker util" OFF) + +option(DOBBY_BUILD_EXAMPLE "Build example" OFF) + +option(DOBBY_BUILD_TEST "Build test" OFF) +``` + +## Build with `scripts/platform_builder.py` + +#### Build for iphoneos + +```shell +python3 scripts/platform_builder.py --platform=iphoneos --arch=all +``` + +#### Build for macos + +``` +python3 scripts/platform_builder.py --platform=macos --arch=all +``` + +#### Build for linux + +``` +# prepare and download cmake/llvm +sh scripts/setup_linux_cross_compile.sh +python3 scripts/platform_builder.py --platform=linux --arch=all --cmake_dir=$HOME/opt/cmake-3.25.2 --llvm_dir=$HOME/opt/llvm-15.0.6 +``` + +#### Build for android + +``` +# prepare and download cmake/llvm/ndk +sh scripts/setup_linux_cross_compile.sh +python3 scripts/platform_builder.py --platform=android --arch=all --cmake_dir=$HOME/opt/cmake-3.25.2 --llvm_dir=$HOME/opt/llvm-15.0.6 --android_ndk_dir=$HOME/opt/ndk-r25b +``` + +## Build with CMake + +#### Build for host + +```shell +cd Dobby && mkdir cmake-build-host && cd cmake-build-host +cmake .. +make -j4 +``` + +## Build with Android Studio CMake + +``` +if(NOT TARGET dobby) +set(DOBBY_DIR /Users/jmpews/Workspace/Project.wrk/Dobby) +macro(SET_OPTION option value) + set(${option} ${value} CACHE INTERNAL "" FORCE) +endmacro() +SET_OPTION(DOBBY_DEBUG OFF) +SET_OPTION(DOBBY_GENERATE_SHARED OFF) +add_subdirectory(${DOBBY_DIR} dobby) +get_property(DOBBY_INCLUDE_DIRECTORIES + TARGET dobby + PROPERTY INCLUDE_DIRECTORIES) +include_directories( + . + ${DOBBY_INCLUDE_DIRECTORIES} + $ +) +endif() + +add_library(native-lib SHARED + ${DOBBY_DIR}/examples/socket_example.cc + native-lib.cpp) +``` diff --git a/app/src/main/cpp/Dobby/examples/CMakeLists.txt b/app/src/main/cpp/Dobby/examples/CMakeLists.txt new file mode 100644 index 0000000..b461a1c --- /dev/null +++ b/app/src/main/cpp/Dobby/examples/CMakeLists.txt @@ -0,0 +1,18 @@ +add_executable(socket_example + main.cc + socket_example.cc + ) + +target_link_libraries(socket_example + dobby + logging + ) + + +add_library(socket_example_lib SHARED + socket_example.cc + ) + +target_link_libraries(socket_example_lib + dobby + ) \ No newline at end of file diff --git a/app/src/main/cpp/Dobby/examples/main.cc b/app/src/main/cpp/Dobby/examples/main.cc new file mode 100644 index 0000000..33eeddf --- /dev/null +++ b/app/src/main/cpp/Dobby/examples/main.cc @@ -0,0 +1,14 @@ +#include +#include +#include +#include +#include +#include + +int main(int argc, char const *argv[]) { + + std::cout << "Start..." << std::endl; + + sleep(100); + return 0; +} \ No newline at end of file diff --git a/app/src/main/cpp/Dobby/examples/socket_example.cc b/app/src/main/cpp/Dobby/examples/socket_example.cc new file mode 100644 index 0000000..1377fa3 --- /dev/null +++ b/app/src/main/cpp/Dobby/examples/socket_example.cc @@ -0,0 +1,212 @@ +#include "dobby.h" + +#include "logging/logging.h" + +#include +#include +#include +#include +#include + +#include +#include +#include + +std::map *func_map; + +// clang-format off +const char *func_array[] = { +// "__loader_dlopen", + + "dlsym", + "dlclose", + + "open", + "write", + "read", + "close", + + "socket", + "connect", + "bind", + "listen", + "accept", + "send", + "recv", + + // "pthread_create" +}; + +const char *func_short_array[] = { + "accept", +}; +// clang-format on + +#define pac_strip(symbol) +#if defined(__APPLE__) && __arm64e__ +#if __has_feature(ptrauth_calls) +#define pac_strip(symbol) +//#define pac_strip(symbol) *(void **)&symbol = (void *)ptrauth_sign_unauthenticated((void *)symbol, ptrauth_key_asia, 0) +#endif +#endif + +#define install_hook(name, fn_ret_t, fn_args_t...) \ + fn_ret_t (*orig_##name)(fn_args_t); \ + fn_ret_t fake_##name(fn_args_t); \ + /* __attribute__((constructor)) */ static void install_hook_##name() { \ + void *sym_addr = DobbySymbolResolver(NULL, #name); \ + DobbyHook(sym_addr, (dobby_dummy_func_t)fake_##name, (dobby_dummy_func_t *)&orig_##name); \ + pac_strip(orig_##name); \ + printf("install hook %s:%p:%p\n", #name, sym_addr, orig_##name); \ + } \ + fn_ret_t fake_##name(fn_args_t) + +install_hook(pthread_create, int, pthread_t *thread, const pthread_attr_t *attrs, void *(*start_routine)(void *), + void *arg, unsigned int create_flags) { + INFO_LOG("pthread_create: %p", start_routine); + return orig_pthread_create(thread, attrs, start_routine, arg, create_flags); +} + +void common_handler(void *address, DobbyRegisterContext *ctx) { + auto iter = func_map->find(address); + if (iter != func_map->end()) { + INFO_LOG("func %s:%p invoke", iter->second, iter->first); + } +} + +uint64_t socket_demo_server(void *ctx); + +uint64_t socket_demo_client(void *ctx); + +#if 1 + +__attribute__((constructor)) static void ctor() { + logger_set_options(0, 0, 0, LOG_LEVEL_DEBUG, false, false); + + void *func = NULL; + func_map = new std::map(); + for (int i = 0; i < sizeof(func_array) / sizeof(char *); ++i) { + func = DobbySymbolResolver(NULL, func_array[i]); + if (func == NULL) { + INFO_LOG("func %s not resolve", func_array[i]); + continue; + } + func_map->insert(std::pair(func, func_array[i])); + } + + for (auto iter = func_map->begin(), e = func_map->end(); iter != e; iter++) { + bool is_short = false; + for (int i = 0; i < sizeof(func_short_array) / sizeof(char *); ++i) { + if (strcmp(func_short_array[i], iter->second) == 0) { + is_short = true; + break; + } + } + if (is_short) { + dobby_enable_near_branch_trampoline(); + DobbyInstrument(iter->first, common_handler); + dobby_disable_near_branch_trampoline(); + } else { + DobbyInstrument(iter->first, common_handler); + } + } + +#if defined(__APPLE__) + // DobbyImportTableReplace(NULL, "_pthread_create", (void *)fake_pthread_create, (void **)&orig_pthread_create); +#endif + + // install_hook_pthread_create(); + + pthread_t socket_server; + pthread_create(&socket_server, NULL, (void *(*)(void *))socket_demo_server, NULL); + + usleep(10000); + pthread_t socket_client; + pthread_create(&socket_client, NULL, (void *(*)(void *))socket_demo_client, NULL); + + // pthread_join(socket_client, 0); + // pthread_join(socket_server, 0); +} + +#include +#include +#include + +#define PORT 49494 + +uint64_t socket_demo_server(void *ctx) { + int server_fd, new_socket; + struct sockaddr_in address; + int opt = 1; + int addrlen = sizeof(address); + char buffer[1024] = {0}; + char *hello = "Hello from server"; + + if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1) { + ERROR_LOG("socket failed: %s", strerror(errno)); + return -1; + } + + if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt))) { + ERROR_LOG("setsockopt: %s", strerror(errno)); + return -1; + } + + address.sin_family = AF_INET; + address.sin_port = htons(PORT); + address.sin_addr.s_addr = INADDR_ANY; + + if (bind(server_fd, (struct sockaddr *)&address, sizeof(address)) < 0) { + ERROR_LOG("bind failed: %s", strerror(errno)); + return -1; + } + if (listen(server_fd, 3) < 0) { + ERROR_LOG("listen failed: %s", strerror(errno)); + return -1; + } + if ((new_socket = accept(server_fd, (struct sockaddr *)&address, (socklen_t *)&addrlen)) < 0) { + ERROR_LOG("accept failed: %s", strerror(errno)); + return -1; + } + + int ret = recv(new_socket, buffer, 1024, 0); + INFO_LOG("[server] %s", buffer); + + send(new_socket, hello, strlen(hello), 0); + INFO_LOG("[server] Hello message sent"); + return 0; +} + +uint64_t socket_demo_client(void *ctx) { + int sock = 0; + struct sockaddr_in serv_addr; + char *hello = "Hello from client"; + char buffer[1024] = {0}; + if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) { + ERROR_LOG("socket failed"); + return -1; + } + + serv_addr.sin_family = AF_INET; + serv_addr.sin_port = htons(PORT); + + // Convert IPv4 and IPv6 addresses from text to binary form + if (inet_pton(AF_INET, "127.0.0.1", &serv_addr.sin_addr) <= 0) { + ERROR_LOG("inet_pton failed"); + return -1; + } + + if (connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) { + ERROR_LOG("connect failed"); + return -1; + } + + send(sock, hello, strlen(hello), 0); + INFO_LOG("[client] Hello message sent"); + + int ret = recv(sock, buffer, 1024, 0); + INFO_LOG("[client] %s", buffer); + return 0; +} + +#endif diff --git a/app/src/main/cpp/Dobby/external/TINYSTL/README b/app/src/main/cpp/Dobby/external/TINYSTL/README new file mode 100644 index 0000000..b6d5879 --- /dev/null +++ b/app/src/main/cpp/Dobby/external/TINYSTL/README @@ -0,0 +1 @@ +ref: https://github.com/mendsley/tinystl \ No newline at end of file diff --git a/app/src/main/cpp/Dobby/external/TINYSTL/algorithm.h b/app/src/main/cpp/Dobby/external/TINYSTL/algorithm.h new file mode 100644 index 0000000..7b9637e --- /dev/null +++ b/app/src/main/cpp/Dobby/external/TINYSTL/algorithm.h @@ -0,0 +1 @@ +#pragma once \ No newline at end of file diff --git a/app/src/main/cpp/Dobby/external/TINYSTL/allocator.h b/app/src/main/cpp/Dobby/external/TINYSTL/allocator.h new file mode 100644 index 0000000..685d98c --- /dev/null +++ b/app/src/main/cpp/Dobby/external/TINYSTL/allocator.h @@ -0,0 +1,49 @@ +/*- + * Copyright 2012-2018 Matthew Endsley + * All rights reserved + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted providing that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef TINYSTL_ALLOCATOR_H +#define TINYSTL_ALLOCATOR_H + +#include + +namespace tinystl { + + struct allocator { + static void* static_allocate(size_t bytes) { + return operator new(bytes); + } + + static void static_deallocate(void* ptr, size_t /*bytes*/) { + operator delete(ptr); + } + }; +} + +#ifndef TINYSTL_ALLOCATOR +# define TINYSTL_ALLOCATOR ::tinystl::allocator +#endif + +#endif diff --git a/app/src/main/cpp/Dobby/external/TINYSTL/buffer.h b/app/src/main/cpp/Dobby/external/TINYSTL/buffer.h new file mode 100644 index 0000000..7ec5d19 --- /dev/null +++ b/app/src/main/cpp/Dobby/external/TINYSTL/buffer.h @@ -0,0 +1,310 @@ +/*- + * Copyright 2012-2018 Matthew Endsley + * All rights reserved + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted providing that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef TINYSTL_BUFFER_H +#define TINYSTL_BUFFER_H + +#include +#include +#include + +namespace tinystl { + + template + struct buffer { + T* first; + T* last; + T* capacity; + }; + + template + static inline void buffer_destroy_range_traits(T* first, T* last, pod_traits) { + for (; first < last; ++first) + first->~T(); + } + + template + static inline void buffer_destroy_range_traits(T*, T*, pod_traits) { + } + + template + static inline void buffer_destroy_range(T* first, T* last) { + buffer_destroy_range_traits(first, last, pod_traits()); + } + + template + static inline void buffer_fill_urange_traits(T* first, T* last, pod_traits) { + for (; first < last; ++first) + new(placeholder(), first) T(); + } + + template + static inline void buffer_fill_urange_traits(T* first, T* last, pod_traits) { + for (; first < last; ++first) + *first = T(); + } + + template + static inline void buffer_fill_urange_traits(T* first, T* last, const T& value, pod_traits) { + for (; first < last; ++first) + new(placeholder(), first) T(value); + } + + template + static inline void buffer_fill_urange_traits(T* first, T* last, const T& value, pod_traits) { + for (; first < last; ++first) + *first = value; + } + + template + static inline void buffer_move_urange_traits(T* dest, T* first, T* last, pod_traits) { + for (T* it = first; it != last; ++it, ++dest) + move_construct(dest, *it); + buffer_destroy_range(first, last); + } + + template + static inline void buffer_move_urange_traits(T* dest, T* first, T* last, pod_traits) { + for (; first != last; ++first, ++dest) + *dest = *first; + } + + template + static inline void buffer_bmove_urange_traits(T* dest, T* first, T* last, pod_traits) { + dest += (last - first); + for (T* it = last; it != first; --it, --dest) { + move_construct(dest - 1, *(it - 1)); + buffer_destroy_range(it - 1, it); + } + } + + template + static inline void buffer_bmove_urange_traits(T* dest, T* first, T* last, pod_traits) { + dest += (last - first); + for (T* it = last; it != first; --it, --dest) + *(dest - 1) = *(it - 1); + } + + template + static inline void buffer_move_urange(T* dest, T* first, T* last) { + buffer_move_urange_traits(dest, first, last, pod_traits()); + } + + template + static inline void buffer_bmove_urange(T* dest, T* first, T* last) { + buffer_bmove_urange_traits(dest, first, last, pod_traits()); + } + + template + static inline void buffer_fill_urange(T* first, T* last) { + buffer_fill_urange_traits(first, last, pod_traits()); + } + + template + static inline void buffer_fill_urange(T* first, T* last, const T& value) { + buffer_fill_urange_traits(first, last, value, pod_traits()); + } + + template + static inline void buffer_init(buffer* b) { + b->first = b->last = b->capacity = 0; + } + + template + static inline void buffer_destroy(buffer* b) { + buffer_destroy_range(b->first, b->last); + Alloc::static_deallocate(b->first, (size_t)((char*)b->capacity - (char*)b->first)); + } + + template + static inline void buffer_reserve(buffer* b, size_t capacity) { + if (b->first + capacity <= b->capacity) + return; + + typedef T* pointer; + const size_t size = (size_t)(b->last - b->first); + pointer newfirst = (pointer)Alloc::static_allocate(sizeof(T) * capacity); + buffer_move_urange(newfirst, b->first, b->last); + Alloc::static_deallocate(b->first, sizeof(T) * capacity); + + b->first = newfirst; + b->last = newfirst + size; + b->capacity = newfirst + capacity; + } + + template + static inline void buffer_resize(buffer* b, size_t size) { + buffer_reserve(b, size); + + buffer_fill_urange(b->last, b->first + size); + buffer_destroy_range(b->first + size, b->last); + b->last = b->first + size; + } + + template + static inline void buffer_resize(buffer* b, size_t size, const T& value) { + buffer_reserve(b, size); + + buffer_fill_urange(b->last, b->first + size, value); + buffer_destroy_range(b->first + size, b->last); + b->last = b->first + size; + } + + template + static inline void buffer_shrink_to_fit(buffer* b) { + if (b->capacity != b->last) { + if (b->last == b->first) { + const size_t capacity = (size_t)(b->capacity - b->first); + Alloc::static_deallocate(b->first, sizeof(T)*capacity); + b->capacity = b->first = b->last = nullptr; + } else { + const size_t capacity = (size_t)(b->capacity - b->first); + const size_t size = (size_t)(b->last - b->first); + T* newfirst = (T*)Alloc::static_allocate(sizeof(T) * size); + buffer_move_urange(newfirst, b->first, b->last); + Alloc::static_deallocate(b->first, sizeof(T) * capacity); + b->first = newfirst; + b->last = newfirst + size; + b->capacity = b->last; + } + } + } + + template + static inline void buffer_clear(buffer* b) { + buffer_destroy_range(b->first, b->last); + b->last = b->first; + } + + template + static inline T* buffer_insert_common(buffer* b, T* where, size_t count) { + const size_t offset = (size_t)(where - b->first); + const size_t newsize = (size_t)((b->last - b->first) + count); + if (b->first + newsize > b->capacity) + buffer_reserve(b, (newsize * 3) / 2); + + where = b->first + offset; + + if (where != b->last) + buffer_bmove_urange(where + count, where, b->last); + + b->last = b->first + newsize; + + return where; + } + + template + static inline void buffer_insert(buffer* b, T* where, const Param* first, const Param* last) { + typedef const char* pointer; + const size_t count = last - first; + const bool frombuf = ((pointer)b->first <= (pointer)first && (pointer)b->last >= (pointer)last); + size_t offset; + if (frombuf) { + offset = (pointer)first - (pointer)b->first; + if ((pointer)where <= (pointer)first) + offset += count * sizeof(T); + where = buffer_insert_common(b, where, count); + first = (Param*)((pointer)b->first + offset); + last = first + count; + } + else { + where = buffer_insert_common(b, where, count); + } + for (; first != last; ++first, ++where) + new(placeholder(), where) T(*first); + } + + template + static inline void buffer_insert(buffer* b, T* where, size_t count) { + where = buffer_insert_common(b, where, count); + for (T* end = where+count; where != end; ++where) + new(placeholder(), where) T(); + } + + template + static inline void buffer_append(buffer* b, const Param* param) { + if (b->capacity != b->last) { + new(placeholder(), b->last) T(*param); + ++b->last; + } else { + buffer_insert(b, b->last, param, param + 1); + } + } + + template + static inline void buffer_append(buffer* b) { + if (b->capacity != b->last) { + new(placeholder(), b->last) T(); + ++b->last; + } else { + buffer_insert(b, b->last, 1); + } + } + + template + static inline T* buffer_erase(buffer* b, T* first, T* last) { + typedef T* pointer; + const size_t count = (last - first); + for (pointer it = last, end = b->last, dest = first; it != end; ++it, ++dest) + move(*dest, *it); + + buffer_destroy_range(b->last - count, b->last); + + b->last -= count; + return first; + } + + template + static inline T* buffer_erase_unordered(buffer* b, T* first, T* last) { + typedef T* pointer; + const size_t count = (last - first); + const size_t tail = (b->last - last); + pointer it = b->last - ((count < tail) ? count : tail); + for (pointer end = b->last, dest = first; it != end; ++it, ++dest) + move(*dest, *it); + + buffer_destroy_range(b->last - count, b->last); + + b->last -= count; + return first; + } + + template + static inline void buffer_swap(buffer* b, buffer* other) { + typedef T* pointer; + const pointer tfirst = b->first, tlast = b->last, tcapacity = b->capacity; + b->first = other->first, b->last = other->last, b->capacity = other->capacity; + other->first = tfirst, other->last = tlast, other->capacity = tcapacity; + } + + template + static inline void buffer_move(buffer* dst, buffer* src) { + dst->first = src->first, dst->last = src->last, dst->capacity = src->capacity; + src->first = src->last = src->capacity = nullptr; + } +} + +#endif //TINYSTL_BUFFER_H diff --git a/app/src/main/cpp/Dobby/external/TINYSTL/hash.h b/app/src/main/cpp/Dobby/external/TINYSTL/hash.h new file mode 100644 index 0000000..c03b326 --- /dev/null +++ b/app/src/main/cpp/Dobby/external/TINYSTL/hash.h @@ -0,0 +1,53 @@ +/*- + * Copyright 2012-2018 Matthew Endsley + * All rights reserved + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted providing that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef TINYSTL_STRINGHASH_H +#define TINYSTL_STRINGHASH_H + +#include + +namespace tinystl { + + static inline size_t hash_string(const char* str, size_t len) { + // Implementation of sdbm a public domain string hash from Ozan Yigit + // see: http://www.eecs.harvard.edu/margo/papers/usenix91/paper.ps + + size_t hash = 0; + typedef const char* pointer; + for (pointer it = str, end = str + len; it != end; ++it) + hash = *it + (hash << 6) + (hash << 16) - hash; + + return hash; + } + + template + inline size_t hash(const T& value) { + const size_t asint = (size_t)value; + return hash_string((const char*)&asint, sizeof(asint)); + } +} + +#endif diff --git a/app/src/main/cpp/Dobby/external/TINYSTL/hash_base.h b/app/src/main/cpp/Dobby/external/TINYSTL/hash_base.h new file mode 100644 index 0000000..30f449b --- /dev/null +++ b/app/src/main/cpp/Dobby/external/TINYSTL/hash_base.h @@ -0,0 +1,292 @@ +/*- + * Copyright 2012-2018 Matthew Endsley + * All rights reserved + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted providing that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef TINYSTL_HASH_BASE_H +#define TINYSTL_HASH_BASE_H + +#include +#include + +namespace tinystl { + + template + struct pair { + pair(); + pair(const pair& other); + pair(pair&& other); + pair(const Key& key, const Value& value); + pair(Key&& key, Value&& value); + + pair& operator=(const pair& other); + pair& operator=(pair&& other); + + Key first; + Value second; + }; + + template + inline pair::pair() { + } + + template + inline pair::pair(const pair& other) + : first(other.first) + , second(other.second) + { + } + + template + inline pair::pair(pair&& other) + : first(static_cast(other.first)) + , second(static_cast(other.second)) + { + } + + template + inline pair::pair(const Key& key, const Value& value) + : first(key) + , second(value) + { + } + + template + inline pair::pair(Key&& key, Value&& value) + : first(static_cast(key)) + , second(static_cast(value)) + { + } + + template + inline pair& pair::operator=(const pair& other) { + first = other.first; + second = other.second; + return *this; + } + + template + inline pair& pair::operator=(pair&& other) { + first = static_cast(other.first); + second = static_cast(other.second); + return *this; + } + + template + static inline pair::type, typename remove_reference::type> + make_pair(Key&& key, Value&& value) { + return pair::type, typename remove_reference::type>( + static_cast(key) + , static_cast(value) + ); + } + + + template + struct unordered_hash_node { + unordered_hash_node(const Key& key, const Value& value); + unordered_hash_node(Key&& key, Value&& value); + + const Key first; + Value second; + unordered_hash_node* next; + unordered_hash_node* prev; + + private: + unordered_hash_node& operator=(const unordered_hash_node&); + }; + + template + inline unordered_hash_node::unordered_hash_node(const Key& key, const Value& value) + : first(key) + , second(value) + { + } + + template + inline unordered_hash_node::unordered_hash_node(Key&& key, Value&& value) + : first(static_cast(key)) + , second(static_cast(value)) + { + } + + template + struct unordered_hash_node { + explicit unordered_hash_node(const Key& key); + explicit unordered_hash_node(Key&& key); + + const Key first; + unordered_hash_node* next; + unordered_hash_node* prev; + + private: + unordered_hash_node& operator=(const unordered_hash_node&); + }; + + template + inline unordered_hash_node::unordered_hash_node(const Key& key) + : first(key) + { + } + + template + inline unordered_hash_node::unordered_hash_node(Key&& key) + : first(static_cast(key)) + { + } + + template + static inline void unordered_hash_node_insert(unordered_hash_node* node, size_t hash, unordered_hash_node** buckets, size_t nbuckets) { + size_t bucket = hash & (nbuckets - 1); + + unordered_hash_node* it = buckets[bucket + 1]; + node->next = it; + if (it) { + node->prev = it->prev; + it->prev = node; + if (node->prev) + node->prev->next = node; + } else { + size_t newbucket = bucket; + while (newbucket && !buckets[newbucket]) + --newbucket; + + unordered_hash_node* prev = buckets[newbucket]; + while (prev && prev->next) + prev = prev->next; + + node->prev = prev; + if (prev) + prev->next = node; + } + + // propagate node through buckets + for (; it == buckets[bucket]; --bucket) { + buckets[bucket] = node; + if (!bucket) + break; + } + } + + template + static inline void unordered_hash_node_erase(const unordered_hash_node* where, size_t hash, unordered_hash_node** buckets, size_t nbuckets) { + size_t bucket = hash & (nbuckets - 1); + + unordered_hash_node* next = where->next; + for (; buckets[bucket] == where; --bucket) { + buckets[bucket] = next; + if (!bucket) + break; + } + + if (where->prev) + where->prev->next = where->next; + if (next) + next->prev = where->prev; + } + + template + struct unordered_hash_iterator { + Node* operator->() const; + Node& operator*() const; + Node* node; + }; + + template + struct unordered_hash_iterator { + + unordered_hash_iterator() {} + unordered_hash_iterator(unordered_hash_iterator other) + : node(other.node) + { + } + + const Node* operator->() const; + const Node& operator*() const; + const Node* node; + }; + + template + struct unordered_hash_iterator > { + const Key* operator->() const; + const Key& operator*() const; + unordered_hash_node* node; + }; + + template + static inline bool operator==(const unordered_hash_iterator& lhs, const unordered_hash_iterator& rhs) { + return lhs.node == rhs.node; + } + + template + static inline bool operator!=(const unordered_hash_iterator& lhs, const unordered_hash_iterator& rhs) { + return lhs.node != rhs.node; + } + + template + static inline void operator++(unordered_hash_iterator& lhs) { + lhs.node = lhs.node->next; + } + + template + inline Node* unordered_hash_iterator::operator->() const { + return node; + } + + template + inline Node& unordered_hash_iterator::operator*() const { + return *node; + } + + template + inline const Node* unordered_hash_iterator::operator->() const { + return node; + } + + template + inline const Node& unordered_hash_iterator::operator*() const { + return *node; + } + + template + inline const Key* unordered_hash_iterator >::operator->() const { + return &node->first; + } + + template + inline const Key& unordered_hash_iterator >::operator*() const { + return node->first; + } + + template + static inline Node unordered_hash_find(const Key& key, Node* buckets, size_t nbuckets) { + const size_t bucket = hash(key) & (nbuckets - 2); + for (Node it = buckets[bucket], end = buckets[bucket+1]; it != end; it = it->next) + if (it->first == key) + return it; + + return 0; + } +} +#endif diff --git a/app/src/main/cpp/Dobby/external/TINYSTL/new.h b/app/src/main/cpp/Dobby/external/TINYSTL/new.h new file mode 100644 index 0000000..5f8a6f7 --- /dev/null +++ b/app/src/main/cpp/Dobby/external/TINYSTL/new.h @@ -0,0 +1,43 @@ +/*- + * Copyright 2012-2018 Matthew Endsley + * All rights reserved + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted providing that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef TINYSTL_NEW_H +#define TINYSTL_NEW_H + +#include + +namespace tinystl { + + struct placeholder {}; +} + +inline void* operator new(size_t, tinystl::placeholder, void* ptr) { + return ptr; +} + +inline void operator delete(void*, tinystl::placeholder, void*) throw() {} + +#endif diff --git a/app/src/main/cpp/Dobby/external/TINYSTL/stddef.h b/app/src/main/cpp/Dobby/external/TINYSTL/stddef.h new file mode 100644 index 0000000..a31dd34 --- /dev/null +++ b/app/src/main/cpp/Dobby/external/TINYSTL/stddef.h @@ -0,0 +1,43 @@ +/*- + * Copyright 2012-2018 Matthew Endsley + * All rights reserved + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted providing that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef TINYSTL_STDDEF_H +#define TINYSTL_STDDEF_H + +#if defined(_WIN64) + typedef long long unsigned int size_t; + typedef long long int ptrdiff_t; +#elif defined(_WIN32) + typedef unsigned int size_t; + typedef int ptrdiff_t; +#elif defined (__linux__) && defined(__SIZE_TYPE__) && defined(__PTRDIFF_TYPE__) + typedef __SIZE_TYPE__ size_t; + typedef __PTRDIFF_TYPE__ ptrdiff_t; +#else +# include +#endif + +#endif diff --git a/app/src/main/cpp/Dobby/external/TINYSTL/string.h b/app/src/main/cpp/Dobby/external/TINYSTL/string.h new file mode 100644 index 0000000..3fe45d1 --- /dev/null +++ b/app/src/main/cpp/Dobby/external/TINYSTL/string.h @@ -0,0 +1,295 @@ +/*- + * Copyright 2012-2018 Matthew Endsley + * All rights reserved + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted providing that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef TINYSTL_STRING_H +#define TINYSTL_STRING_H + +#include +#include +#include + +namespace tinystl { + + template + class basic_string { + public: + basic_string(); + basic_string(const basic_string& other); + basic_string(basic_string&& other); + basic_string(const char* sz); + basic_string(const char* sz, size_t len); + ~basic_string(); + + basic_string& operator=(const basic_string& other); + basic_string& operator=(basic_string&& other); + + const char* c_str() const; + size_t size() const; + + void reserve(size_t size); + void resize(size_t size); + + void clear(); + void append(const char* first, const char* last); + void assign(const char* s, size_t n); + + void shrink_to_fit(); + void swap(basic_string& other); + + private: + typedef char* pointer; + pointer m_first; + pointer m_last; + pointer m_capacity; + + static const size_t c_nbuffer = 12; + char m_buffer[12]; + }; + + template + inline basic_string::basic_string() + : m_first(m_buffer) + , m_last(m_buffer) + , m_capacity(m_buffer + c_nbuffer) + { + resize(0); + } + + template + inline basic_string::basic_string(const basic_string& other) + : m_first(m_buffer) + , m_last(m_buffer) + , m_capacity(m_buffer + c_nbuffer) + { + reserve(other.size()); + append(other.m_first, other.m_last); + } + + template + inline basic_string::basic_string(basic_string&& other) + { + if (other.m_first == other.m_buffer) { + m_first = m_buffer; + m_last = m_buffer; + m_capacity = m_buffer + c_nbuffer; + reserve(other.size()); + append(other.m_first, other.m_last); + } else { + m_first = other.m_first; + m_last = other.m_last; + m_capacity = other.m_capacity; + } + other.m_first = other.m_last = other.m_buffer; + other.m_capacity = other.m_buffer + c_nbuffer; + other.resize(0); + } + + template + inline basic_string::basic_string(const char* sz) + : m_first(m_buffer) + , m_last(m_buffer) + , m_capacity(m_buffer + c_nbuffer) + { + size_t len = 0; + for (const char* it = sz; *it; ++it) + ++len; + + reserve(len); + append(sz, sz + len); + } + + template + inline basic_string::basic_string(const char* sz, size_t len) + : m_first(m_buffer) + , m_last(m_buffer) + , m_capacity(m_buffer + c_nbuffer) + { + reserve(len); + append(sz, sz + len); + } + + template + inline basic_string::~basic_string() { + if (m_first != m_buffer) + allocator::static_deallocate(m_first, m_capacity - m_first); + } + + template + inline basic_string& basic_string::operator=(const basic_string& other) { + basic_string(other).swap(*this); + return *this; + } + + template + inline basic_string& basic_string::operator=(basic_string&& other) { + basic_string(static_cast(other)).swap(*this); + return *this; + } + + template + inline const char* basic_string::c_str() const { + return m_first; + } + + template + inline size_t basic_string::size() const + { + return (size_t)(m_last - m_first); + } + + template + inline void basic_string::reserve(size_t capacity) { + if (m_first + capacity + 1 <= m_capacity) + return; + + const size_t size = (size_t)(m_last - m_first); + + pointer newfirst = (pointer)allocator::static_allocate(capacity + 1); + for (pointer it = m_first, newit = newfirst, end = m_last; it != end; ++it, ++newit) + *newit = *it; + if (m_first != m_buffer) + allocator::static_deallocate(m_first, m_capacity - m_first); + + m_first = newfirst; + m_last = newfirst + size; + m_capacity = m_first + capacity; + } + + template + inline void basic_string::resize(size_t size) { + const size_t prevSize = m_last-m_first; + reserve(size); + if (size > prevSize) + for (pointer it = m_last, end = m_first + size + 1; it < end; ++it) + *it = 0; + else if (m_last != m_first) + m_first[size] = 0; + + m_last = m_first + size; + } + + template + inline void basic_string::clear() { + resize(0); + } + + template + inline void basic_string::append(const char* first, const char* last) { + const size_t newsize = (size_t)((m_last - m_first) + (last - first) + 1); + if (m_first + newsize > m_capacity) + reserve((newsize * 3) / 2); + + for (; first != last; ++m_last, ++first) + *m_last = *first; + *m_last = 0; + } + + template + inline void basic_string::assign(const char* sz, size_t n) { + clear(); + append(sz, sz+n); + } + + template + inline void basic_string::shrink_to_fit() { + if (m_first == m_buffer) { + } else if (m_last == m_first) { + const size_t capacity = (size_t)(m_capacity - m_first); + if (capacity) + allocator::static_deallocate(m_first, capacity+1); + m_capacity = m_first; + } else if (m_capacity != m_last) { + const size_t size = (size_t)(m_last - m_first); + char* newfirst = (pointer)allocator::static_allocate(size+1); + for (pointer in = m_first, out = newfirst; in != m_last + 1; ++in, ++out) + *out = *in; + if (m_first != m_capacity) + allocator::static_deallocate(m_first, m_capacity+1-m_first); + m_first = newfirst; + m_last = newfirst+size; + m_capacity = m_last; + } + } + + template + inline void basic_string::swap(basic_string& other) { + const pointer tfirst = m_first, tlast = m_last, tcapacity = m_capacity; + m_first = other.m_first, m_last = other.m_last, m_capacity = other.m_capacity; + other.m_first = tfirst, other.m_last = tlast, other.m_capacity = tcapacity; + + char tbuffer[c_nbuffer]; + + if (m_first == other.m_buffer) + for (pointer it = other.m_buffer, end = m_last, out = tbuffer; it != end; ++it, ++out) + *out = *it; + + if (other.m_first == m_buffer) { + other.m_last = other.m_last - other.m_first + other.m_buffer; + other.m_first = other.m_buffer; + other.m_capacity = other.m_buffer + c_nbuffer; + + for (pointer it = other.m_first, end = other.m_last, in = m_buffer; it != end; ++it, ++in) + *it = *in; + *other.m_last = 0; + } + + if (m_first == other.m_buffer) { + m_last = m_last - m_first + m_buffer; + m_first = m_buffer; + m_capacity = m_buffer + c_nbuffer; + + for (pointer it = m_first, end = m_last, in = tbuffer; it != end; ++it, ++in) + *it = *in; + *m_last = 0; + } + } + + template + inline bool operator==(const basic_string& lhs, const basic_string& rhs) { + typedef const char* pointer; + + const size_t lsize = lhs.size(), rsize = rhs.size(); + if (lsize != rsize) + return false; + + pointer lit = lhs.c_str(), rit = rhs.c_str(); + pointer lend = lit + lsize; + while (lit != lend) + if (*lit++ != *rit++) + return false; + + return true; + } + + template + static inline size_t hash(const basic_string& value) { + return hash_string(value.c_str(), value.size()); + } + + typedef basic_string string; +} + +#endif diff --git a/app/src/main/cpp/Dobby/external/TINYSTL/string_view.h b/app/src/main/cpp/Dobby/external/TINYSTL/string_view.h new file mode 100644 index 0000000..fabc633 --- /dev/null +++ b/app/src/main/cpp/Dobby/external/TINYSTL/string_view.h @@ -0,0 +1,147 @@ +/*- + * Copyright 2012-1017 Matthew Endsley + * All rights reserved + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted providing that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef TINYSTL_STRING_VIEW_H +#define TINYSTL_STRING_VIEW_H + +#include + +namespace tinystl { + + class string_view + { + public: + typedef char value_type; + typedef char* pointer; + typedef const char* const_pointer; + typedef char& reference; + typedef const char& const_reference; + typedef const_pointer iterator; + typedef const_pointer const_iterator; + typedef size_t size_type; + typedef ptrdiff_t difference_type; + + static constexpr size_type npos = size_type(-1); + + constexpr string_view(); + constexpr string_view(const char* s, size_type count); + constexpr string_view(const char* s); + constexpr string_view(const string_view&) = default; + string_view& operator=(const string_view&) = default; + + constexpr const char* data() const; + constexpr char operator[](size_type pos) const; + constexpr size_type size() const; + constexpr bool empty() const; + constexpr iterator begin() const; + constexpr const_iterator cbegin() const; + constexpr iterator end() const; + constexpr const_iterator cend() const; + constexpr string_view substr(size_type pos = 0, size_type count = npos) const; + constexpr void swap(string_view& v); + + private: + string_view(decltype(nullptr)) = delete; + + static constexpr size_type strlen(const char*); + + const char* m_str; + size_type m_size; + }; + + constexpr string_view::string_view() + : m_str(nullptr) + , m_size(0) + { + } + + constexpr string_view::string_view(const char* s, size_type count) + : m_str(s) + , m_size(count) + { + } + + constexpr string_view::string_view(const char* s) + : m_str(s) + , m_size(strlen(s)) + { + } + + constexpr const char* string_view::data() const { + return m_str; + } + + constexpr char string_view::operator[](size_type pos) const { + return m_str[pos]; + } + + constexpr string_view::size_type string_view::size() const { + return m_size; + } + + constexpr bool string_view::empty() const { + return 0 == m_size; + } + + constexpr string_view::iterator string_view::begin() const { + return m_str; + } + + constexpr string_view::const_iterator string_view::cbegin() const { + return m_str; + } + + constexpr string_view::iterator string_view::end() const { + return m_str + m_size; + } + + constexpr string_view::const_iterator string_view::cend() const { + return m_str + m_size; + } + + constexpr string_view string_view::substr(size_type pos, size_type count) const { + return string_view(m_str + pos, npos == count ? m_size - pos : count); + } + + constexpr void string_view::swap(string_view& v) { + const char* strtmp = m_str; + size_type sizetmp = m_size; + m_str = v.m_str; + m_size = v.m_size; + v.m_str = strtmp; + v.m_size = sizetmp; + } + + constexpr string_view::size_type string_view::strlen(const char* s) { + for (size_t len = 0; ; ++len) { + if (0 == s[len]) { + return len; + } + } + } +} + +#endif // TINYSTL_STRING_VIEW_H diff --git a/app/src/main/cpp/Dobby/external/TINYSTL/traits.h b/app/src/main/cpp/Dobby/external/TINYSTL/traits.h new file mode 100644 index 0000000..84574ee --- /dev/null +++ b/app/src/main/cpp/Dobby/external/TINYSTL/traits.h @@ -0,0 +1,100 @@ +/*- + * Copyright 2012-2018 Matthew Endsley + * All rights reserved + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted providing that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef TINYSTL_TRAITS_H +#define TINYSTL_TRAITS_H + +#include + +#if defined(__GNUC__) +# define TINYSTL_TRY_POD_OPTIMIZATION(t) __is_pod(t) +#elif defined(_MSC_VER) +# define TINYSTL_TRY_POD_OPTIMIZATION(t) (!__is_class(t) || __is_pod(t)) +#else +# define TINYSTL_TRY_POD_OPTIMIZATION(t) false +#endif + +namespace tinystl { + template struct pod_traits {}; + + template struct swap_holder; + + template + static inline void move_impl(T& a, T& b, ...) { + a = b; + } + + template + static inline void move_impl(T& a, T& b, T*, swap_holder* = 0) { + a.swap(b); + } + + template + static inline void move(T& a, T&b) { + move_impl(a, b, (T*)0); + } + + template + static inline void move_construct_impl(T* a, T& b, ...) { + new(placeholder(), a) T(b); + } + + template + static inline void move_construct_impl(T* a, T& b, void*, swap_holder* = 0) { + // If your type T does not have a default constructor, simply insert: + // struct tinystl_nomove_construct; + // in the class definition + new(placeholder(), a) T; + a->swap(b); + } + + template + static inline void move_construct_impl(T* a, T& b, T*, typename T::tinystl_nomove_construct* = 0) { + new(placeholder(), a) T(b); + } + + template + static inline void move_construct(T* a, T& b) { + move_construct_impl(a, b, (T*)0); + } + + template + struct remove_reference { + typedef T type; + }; + + template + struct remove_reference { + typedef T type; + }; + + template + struct remove_reference { + typedef T type; + }; +} + +#endif diff --git a/app/src/main/cpp/Dobby/external/TINYSTL/unordered_map.h b/app/src/main/cpp/Dobby/external/TINYSTL/unordered_map.h new file mode 100644 index 0000000..4be6a78 --- /dev/null +++ b/app/src/main/cpp/Dobby/external/TINYSTL/unordered_map.h @@ -0,0 +1,289 @@ +/*- + * Copyright 2012-2018 Matthew Endsley + * All rights reserved + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted providing that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef TINYSTL_UNORDERED_MAP_H +#define TINYSTL_UNORDERED_MAP_H + +#include +#include +#include +#include + +namespace tinystl { + + template + class unordered_map { + public: + unordered_map(); + unordered_map(const unordered_map& other); + unordered_map(unordered_map&& other); + ~unordered_map(); + + unordered_map& operator=(const unordered_map& other); + unordered_map& operator=(unordered_map&& other); + + typedef pair value_type; + + typedef unordered_hash_iterator > const_iterator; + typedef unordered_hash_iterator > iterator; + + iterator begin(); + iterator end(); + + const_iterator begin() const; + const_iterator end() const; + + void clear(); + bool empty() const; + size_t size() const; + + const_iterator find(const Key& key) const; + iterator find(const Key& key); + pair insert(const pair& p); + pair emplace(pair&& p); + void erase(const_iterator where); + + Value& operator[](const Key& key); + + void swap(unordered_map& other); + + private: + + void rehash(size_t nbuckets); + + typedef unordered_hash_node* pointer; + + size_t m_size; + tinystl::buffer m_buckets; + }; + + template + inline unordered_map::unordered_map() + : m_size(0) + { + buffer_init(&m_buckets); + buffer_resize(&m_buckets, 9, 0); + } + + template + inline unordered_map::unordered_map(const unordered_map& other) + : m_size(other.m_size) + { + const size_t nbuckets = (size_t)(other.m_buckets.last - other.m_buckets.first); + buffer_init(&m_buckets); + buffer_resize(&m_buckets, nbuckets, 0); + + for (pointer it = *other.m_buckets.first; it; it = it->next) { + unordered_hash_node* newnode = new(placeholder(), Alloc::static_allocate(sizeof(unordered_hash_node))) unordered_hash_node(it->first, it->second); + newnode->next = newnode->prev = 0; + + unordered_hash_node_insert(newnode, hash(it->first), m_buckets.first, nbuckets - 1); + } + } + + template + inline unordered_map::unordered_map(unordered_map&& other) + : m_size(other.m_size) + { + buffer_move(&m_buckets, &other.m_buckets); + other.m_size = 0; + } + + template + inline unordered_map::~unordered_map() { + if (m_buckets.first != m_buckets.last) + clear(); + buffer_destroy(&m_buckets); + } + + template + inline unordered_map& unordered_map::operator=(const unordered_map& other) { + unordered_map(other).swap(*this); + return *this; + } + + template + inline unordered_map& unordered_map::operator=(unordered_map&& other) { + unordered_map(static_cast(other)).swap(*this); + return *this; + } + + template + inline typename unordered_map::iterator unordered_map::begin() { + iterator it; + it.node = *m_buckets.first; + return it; + } + + template + inline typename unordered_map::iterator unordered_map::end() { + iterator it; + it.node = 0; + return it; + } + + template + inline typename unordered_map::const_iterator unordered_map::begin() const { + const_iterator cit; + cit.node = *m_buckets.first; + return cit; + } + + template + inline typename unordered_map::const_iterator unordered_map::end() const { + const_iterator cit; + cit.node = 0; + return cit; + } + + template + inline bool unordered_map::empty() const { + return m_size == 0; + } + + template + inline size_t unordered_map::size() const { + return m_size; + } + + template + inline void unordered_map::clear() { + pointer it = *m_buckets.first; + while (it) { + const pointer next = it->next; + it->~unordered_hash_node(); + Alloc::static_deallocate(it, sizeof(unordered_hash_node)); + + it = next; + } + + m_buckets.last = m_buckets.first; + buffer_resize(&m_buckets, 9, 0); + m_size = 0; + } + + template + inline typename unordered_map::iterator unordered_map::find(const Key& key) { + iterator result; + result.node = unordered_hash_find(key, m_buckets.first, (size_t)(m_buckets.last - m_buckets.first)); + return result; + } + + template + inline typename unordered_map::const_iterator unordered_map::find(const Key& key) const { + iterator result; + result.node = unordered_hash_find(key, m_buckets.first, (size_t)(m_buckets.last - m_buckets.first)); + return result; + } + + template + inline void unordered_map::rehash(size_t nbuckets) { + if (m_size + 1 > 4 * nbuckets) { + pointer root = *m_buckets.first; + + const size_t newnbuckets = ((size_t)(m_buckets.last - m_buckets.first) - 1) * 8; + m_buckets.last = m_buckets.first; + buffer_resize(&m_buckets, newnbuckets + 1, 0); + unordered_hash_node** buckets = m_buckets.first; + + while (root) { + const pointer next = root->next; + root->next = root->prev = 0; + unordered_hash_node_insert(root, hash(root->first), buckets, newnbuckets); + root = next; + } + } + } + + template + inline pair::iterator, bool> unordered_map::insert(const pair& p) { + pair result; + result.second = false; + + result.first = find(p.first); + if (result.first.node != 0) + return result; + + unordered_hash_node* newnode = new(placeholder(), Alloc::static_allocate(sizeof(unordered_hash_node))) unordered_hash_node(p.first, p.second); + newnode->next = newnode->prev = 0; + + const size_t nbuckets = (size_t)(m_buckets.last - m_buckets.first); + unordered_hash_node_insert(newnode, hash(p.first), m_buckets.first, nbuckets - 1); + + ++m_size; + rehash(nbuckets); + + result.first.node = newnode; + result.second = true; + return result; + } + + template + inline pair::iterator, bool> unordered_map::emplace(pair&& p) { + pair result; + result.second = false; + + result.first = find(p.first); + if (result.first.node != 0) + return result; + + const size_t keyhash = hash(p.first); + unordered_hash_node* newnode = new(placeholder(), Alloc::static_allocate(sizeof(unordered_hash_node))) unordered_hash_node(static_cast(p.first), static_cast(p.second)); + newnode->next = newnode->prev = 0; + + const size_t nbuckets = (size_t)(m_buckets.last - m_buckets.first); + unordered_hash_node_insert(newnode, keyhash, m_buckets.first, nbuckets - 1); + + ++m_size; + rehash(nbuckets); + + result.first.node = newnode; + result.second = true; + return result; + } + + template + inline void unordered_map::erase(const_iterator where) { + unordered_hash_node_erase(where.node, hash(where->first), m_buckets.first, (size_t)(m_buckets.last - m_buckets.first) - 1); + + where->~unordered_hash_node(); + Alloc::static_deallocate((void*)where.node, sizeof(unordered_hash_node)); + --m_size; + } + + template + inline Value& unordered_map::operator[](const Key& key) { + return insert(pair(key, Value())).first->second; + } + + template + inline void unordered_map::swap(unordered_map& other) { + size_t tsize = other.m_size; + other.m_size = m_size, m_size = tsize; + buffer_swap(&m_buckets, &other.m_buckets); + } +} +#endif diff --git a/app/src/main/cpp/Dobby/external/TINYSTL/unordered_set.h b/app/src/main/cpp/Dobby/external/TINYSTL/unordered_set.h new file mode 100644 index 0000000..450fbc5 --- /dev/null +++ b/app/src/main/cpp/Dobby/external/TINYSTL/unordered_set.h @@ -0,0 +1,265 @@ +/*- + * Copyright 2012-2018 Matthew Endsley + * All rights reserved + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted providing that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef TINYSTL_UNORDERED_SET_H +#define TINYSTL_UNORDERED_SET_H + +#include +#include +#include +#include + +namespace tinystl { + + template + class unordered_set { + public: + unordered_set(); + unordered_set(const unordered_set& other); + unordered_set(unordered_set&& other); + ~unordered_set(); + + unordered_set& operator=(const unordered_set& other); + unordered_set& operator=(unordered_set&& other); + + typedef unordered_hash_iterator > const_iterator; + typedef const_iterator iterator; + + iterator begin() const; + iterator end() const; + + void clear(); + bool empty() const; + size_t size() const; + + iterator find(const Key& key) const; + pair insert(const Key& key); + pair emplace(Key&& key); + void erase(iterator where); + size_t erase(const Key& key); + + void swap(unordered_set& other); + + private: + + void rehash(size_t nbuckets); + + typedef unordered_hash_node* pointer; + + size_t m_size; + tinystl::buffer m_buckets; + }; + + template + inline unordered_set::unordered_set() + : m_size(0) + { + buffer_init(&m_buckets); + buffer_resize(&m_buckets, 9, 0); + } + + template + inline unordered_set::unordered_set(const unordered_set& other) + : m_size(other.m_size) + { + const size_t nbuckets = (size_t)(other.m_buckets.last - other.m_buckets.first); + buffer_init(&m_buckets); + buffer_resize(&m_buckets, nbuckets, 0); + + for (pointer it = *other.m_buckets.first; it; it = it->next) { + unordered_hash_node* newnode = new(placeholder(), Alloc::static_allocate(sizeof(unordered_hash_node))) unordered_hash_node(*it); + newnode->next = newnode->prev = 0; + unordered_hash_node_insert(newnode, hash(it->first), m_buckets.first, nbuckets - 1); + } + } + + template + inline unordered_set::unordered_set(unordered_set&& other) + : m_size(other.m_size) + { + buffer_move(&m_buckets, &other.m_buckets); + other.m_size = 0; + } + + template + inline unordered_set::~unordered_set() { + if (m_buckets.first != m_buckets.last) + clear(); + buffer_destroy(&m_buckets); + } + + template + inline unordered_set& unordered_set::operator=(const unordered_set& other) { + unordered_set(other).swap(*this); + return *this; + } + + template + inline unordered_set& unordered_set::operator=(unordered_set&& other) { + unordered_set(static_cast(other)).swap(*this); + return *this; + } + + template + inline typename unordered_set::iterator unordered_set::begin() const { + iterator cit; + cit.node = *m_buckets.first; + return cit; + } + + template + inline typename unordered_set::iterator unordered_set::end() const { + iterator cit; + cit.node = 0; + return cit; + } + + template + inline bool unordered_set::empty() const { + return m_size == 0; + } + + template + inline size_t unordered_set::size() const { + return m_size; + } + + template + inline void unordered_set::clear() { + pointer it = *m_buckets.first; + while (it) { + const pointer next = it->next; + it->~unordered_hash_node(); + Alloc::static_deallocate(it, sizeof(unordered_hash_node)); + + it = next; + } + + m_buckets.last = m_buckets.first; + buffer_resize(&m_buckets, 9, 0); + m_size = 0; + } + + template + inline typename unordered_set::iterator unordered_set::find(const Key& key) const { + iterator result; + result.node = unordered_hash_find(key, m_buckets.first, (size_t)(m_buckets.last - m_buckets.first)); + return result; + } + + template + inline void unordered_set::rehash(size_t nbuckets) { + if (m_size + 1 > 4 * nbuckets) { + pointer root = *m_buckets.first; + + const size_t newnbuckets = ((size_t)(m_buckets.last - m_buckets.first) - 1) * 8; + m_buckets.last = m_buckets.first; + buffer_resize(&m_buckets, newnbuckets + 1, 0); + unordered_hash_node** buckets = m_buckets.first; + + while (root) { + const pointer next = root->next; + root->next = root->prev = 0; + unordered_hash_node_insert(root, hash(root->first), buckets, newnbuckets); + root = next; + } + } + } + + template + inline pair::iterator, bool> unordered_set::insert(const Key& key) { + pair result; + result.second = false; + + result.first = find(key); + if (result.first.node != 0) + return result; + + unordered_hash_node* newnode = new(placeholder(), Alloc::static_allocate(sizeof(unordered_hash_node))) unordered_hash_node(key); + newnode->next = newnode->prev = 0; + + const size_t nbuckets = (size_t)(m_buckets.last - m_buckets.first); + unordered_hash_node_insert(newnode, hash(key), m_buckets.first, nbuckets - 1); + + ++m_size; + rehash(nbuckets); + + result.first.node = newnode; + result.second = true; + return result; + } + + template + inline pair::iterator, bool> unordered_set::emplace(Key&& key) { + pair result; + result.second = false; + + result.first = find(key); + if (result.first.node != 0) + return result; + + const size_t keyhash = hash(key); + unordered_hash_node* newnode = new(placeholder(), Alloc::static_allocate(sizeof(unordered_hash_node))) unordered_hash_node(static_cast(key)); + newnode->next = newnode->prev = 0; + + const size_t nbuckets = (size_t)(m_buckets.last - m_buckets.first); + unordered_hash_node_insert(newnode, keyhash, m_buckets.first, nbuckets - 1); + + ++m_size; + rehash(nbuckets); + + result.first.node = newnode; + result.second = true; + return result; + } + + template + inline void unordered_set::erase(iterator where) { + unordered_hash_node_erase(where.node, hash(where.node->first), m_buckets.first, (size_t)(m_buckets.last - m_buckets.first) - 1); + + where.node->~unordered_hash_node(); + Alloc::static_deallocate((void*)where.node, sizeof(unordered_hash_node)); + --m_size; + } + + template + inline size_t unordered_set::erase(const Key& key) { + const iterator it = find(key); + if (it.node == 0) + return 0; + + erase(it); + return 1; + } + + template + void unordered_set::swap(unordered_set& other) { + size_t tsize = other.m_size; + other.m_size = m_size, m_size = tsize; + buffer_swap(&m_buckets, &other.m_buckets); + } +} +#endif diff --git a/app/src/main/cpp/Dobby/external/TINYSTL/vector.h b/app/src/main/cpp/Dobby/external/TINYSTL/vector.h new file mode 100644 index 0000000..6e3b0e1 --- /dev/null +++ b/app/src/main/cpp/Dobby/external/TINYSTL/vector.h @@ -0,0 +1,353 @@ +/*- + * Copyright 2012-2018 Matthew Endsley + * All rights reserved + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted providing that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef TINYSTL_VECTOR_H +#define TINYSTL_VECTOR_H + +#include +#include +#include +#include + +namespace tinystl { +template class vector { + using iterator = T *; + +public: + vector(); + vector(const vector &other); + vector(vector &&other); + vector(size_t size); + vector(size_t size, const T &value); + vector(const T *first, const T *last); + ~vector(); + + vector &operator=(const vector &other); + vector &operator=(vector &&other); + + void assign(const T *first, const T *last); + + const T *data() const; + T *data(); + size_t size() const; + size_t capacity() const; + bool empty() const; + + T &operator[](size_t idx); + const T &operator[](size_t idx) const; + + const T &front() const; + T &front(); + const T &back() const; + T &back(); + + void resize(size_t size); + void resize(size_t size, const T &value); + void clear(); + void reserve(size_t capacity); + + void push_back(const T &t); + void pop_back(); + + void emplace_back(); + template void emplace_back(const Param ¶m); + + void shrink_to_fit(); + + void swap(vector &other); + + typedef T value_type; + + iterator begin(); + iterator end(); + + typedef const T *const_iterator; + const_iterator begin() const; + const_iterator end() const; + + void insert(iterator where); + void insert(iterator where, const T &value); + void insert(iterator where, const T *first, const T *last); + + template void emplace(iterator where, const Param ¶m); + + iterator erase(iterator where); + iterator erase(iterator first, iterator last); + + iterator erase_unordered(iterator where); + iterator erase_unordered(iterator first, iterator last); + + iterator find(const T &other) const; + void sort(int (*compare)(const T &elem0, const T &elem1)); + void sort(unsigned begin, unsigned end, int (*compare)(const T &elem0, const T &elem1)); + +private: + int partition(int (*compare)(const T &elem0, const T &elem1), int p, int r); + void quick_sort(int (*compare)(const T &elem0, const T &elem1), int p, int r); + +private: + buffer m_buffer; +}; + +template inline vector::vector() { + buffer_init(&m_buffer); +} + +template inline vector::vector(const vector &other) { + buffer_init(&m_buffer); + buffer_reserve(&m_buffer, other.size()); + buffer_insert(&m_buffer, m_buffer.last, other.m_buffer.first, other.m_buffer.last); +} + +template inline vector::vector(vector &&other) { + buffer_move(&m_buffer, &other.m_buffer); +} + +template inline vector::vector(size_t size) { + buffer_init(&m_buffer); + buffer_resize(&m_buffer, size); +} + +template inline vector::vector(size_t size, const T &value) { + buffer_init(&m_buffer); + buffer_resize(&m_buffer, size, value); +} + +template inline vector::vector(const T *first, const T *last) { + buffer_init(&m_buffer); + buffer_insert(&m_buffer, m_buffer.last, first, last); +} + +template inline vector::~vector() { + buffer_destroy(&m_buffer); +} + +template inline vector &vector::operator=(const vector &other) { + vector(other).swap(*this); + return *this; +} + +template vector &vector::operator=(vector &&other) { + buffer_destroy(&m_buffer); + buffer_move(&m_buffer, &other.m_buffer); + return *this; +} + +template inline void vector::assign(const T *first, const T *last) { + buffer_clear(&m_buffer); + buffer_insert(&m_buffer, m_buffer.last, first, last); +} + +template inline const T *vector::data() const { + return m_buffer.first; +} + +template inline T *vector::data() { + return m_buffer.first; +} + +template inline size_t vector::size() const { + return (size_t)(m_buffer.last - m_buffer.first); +} + +template inline size_t vector::capacity() const { + return (size_t)(m_buffer.capacity - m_buffer.first); +} + +template inline bool vector::empty() const { + return m_buffer.last == m_buffer.first; +} + +template inline T &vector::operator[](size_t idx) { + return m_buffer.first[idx]; +} + +template inline const T &vector::operator[](size_t idx) const { + return m_buffer.first[idx]; +} + +template inline const T &vector::front() const { + return m_buffer.first[0]; +} + +template inline T &vector::front() { + return m_buffer.first[0]; +} + +template inline const T &vector::back() const { + return m_buffer.last[-1]; +} + +template inline T &vector::back() { + return m_buffer.last[-1]; +} + +template inline void vector::resize(size_t size) { + buffer_resize(&m_buffer, size); +} + +template inline void vector::resize(size_t size, const T &value) { + buffer_resize(&m_buffer, size, value); +} + +template inline void vector::clear() { + buffer_clear(&m_buffer); +} + +template inline void vector::reserve(size_t capacity) { + buffer_reserve(&m_buffer, capacity); +} + +template inline void vector::push_back(const T &t) { + buffer_append(&m_buffer, &t); +} + +template inline void vector::emplace_back() { + buffer_append(&m_buffer); +} + +template +template +inline void vector::emplace_back(const Param ¶m) { + buffer_append(&m_buffer, ¶m); +} + +template inline void vector::pop_back() { + buffer_erase(&m_buffer, m_buffer.last - 1, m_buffer.last); +} + +template inline void vector::shrink_to_fit() { + buffer_shrink_to_fit(&m_buffer); +} + +template inline void vector::swap(vector &other) { + buffer_swap(&m_buffer, &other.m_buffer); +} + +template inline typename vector::iterator vector::begin() { + return m_buffer.first; +} + +template inline typename vector::iterator vector::end() { + return m_buffer.last; +} + +template inline typename vector::const_iterator vector::begin() const { + return m_buffer.first; +} + +template inline typename vector::const_iterator vector::end() const { + return m_buffer.last; +} + +template inline void vector::insert(typename vector::iterator where) { + buffer_insert(&m_buffer, where, 1); +} + +template inline void vector::insert(iterator where, const T &value) { + buffer_insert(&m_buffer, where, &value, &value + 1); +} + +template +inline void vector::insert(iterator where, const T *first, const T *last) { + buffer_insert(&m_buffer, where, first, last); +} + +template +inline typename vector::iterator vector::erase(iterator where) { + return buffer_erase(&m_buffer, where, where + 1); +} + +template +inline typename vector::iterator vector::erase(iterator first, iterator last) { + return buffer_erase(&m_buffer, first, last); +} + +template +inline typename vector::iterator vector::erase_unordered(iterator where) { + return buffer_erase_unordered(&m_buffer, where, where + 1); +} + +template +inline typename vector::iterator vector::erase_unordered(iterator first, iterator last) { + return buffer_erase_unordered(&m_buffer, first, last); +} + +template +template +void vector::emplace(typename vector::iterator where, const Param ¶m) { + buffer_insert(&m_buffer, where, ¶m, ¶m + 1); +} + +template +inline typename vector::iterator vector::find(const T &other) const { + for (unsigned i = 0; i < size(); ++i) + if (m_buffer.first[i] == other) + return &m_buffer.first[i]; + + return m_buffer.last; +} + +template +inline int vector::partition(int (*compare)(const T &elem0, const T &elem1), int p, int r) { + T tmp, pivot = m_buffer.first[p]; + int left = p; + + for (int i = p + 1; i <= r; i++) { + if (compare(m_buffer.first[i], pivot) < 0) { + left++; + tmp = m_buffer.first[i]; + m_buffer.first[i] = m_buffer.first[left]; + m_buffer.first[left] = tmp; + } + } + tmp = m_buffer.first[p]; + m_buffer.first[p] = m_buffer.first[left]; + m_buffer.first[left] = tmp; + return left; +} + +template +inline void vector::quick_sort(int (*compare)(const T &elem0, const T &elem1), int p, int r) { + if (p < r) { + int q = partition(compare, p, r); + quick_sort(compare, p, q - 1); + quick_sort(compare, q + 1, r); + } +} + +template +inline void vector::sort(int (*compare)(const T &elem0, const T &elem1)) { + quick_sort(compare, 0, (int)size() - 1); +} + +template +inline void vector::sort(unsigned begin, unsigned end, int (*compare)(const T &elem0, const T &elem1)) { + quick_sort(compare, (int)begin, (int)end); +} +} // namespace tinystl + +#endif // TINYSTL_VECTOR_H diff --git a/app/src/main/cpp/Dobby/external/deprecated/misc-helper/CMakeLists.txt b/app/src/main/cpp/Dobby/external/deprecated/misc-helper/CMakeLists.txt new file mode 100644 index 0000000..fca13b6 --- /dev/null +++ b/app/src/main/cpp/Dobby/external/deprecated/misc-helper/CMakeLists.txt @@ -0,0 +1,18 @@ +include_directories(.) + +if(NOT DOBBY_BUILD_KERNEL_MODE) + set(SOURCE_FILE_LIST + ${CMAKE_CURRENT_SOURCE_DIR}/variable_cache.c + ${CMAKE_CURRENT_SOURCE_DIR}/async_logger.cc + ${CMAKE_CURRENT_SOURCE_DIR}/format_printer.cc + ) +else() + set(SOURCE_FILE_LIST + ${CMAKE_CURRENT_SOURCE_DIR}/format_printer.cc + ) +endif() + +add_library(misc_helper + ${SOURCE_FILE_LIST} + ${SOURCE_HEADER_LIST} +) \ No newline at end of file diff --git a/app/src/main/cpp/Dobby/external/deprecated/misc-helper/async_logger.cc b/app/src/main/cpp/Dobby/external/deprecated/misc-helper/async_logger.cc new file mode 100644 index 0000000..49b11cb --- /dev/null +++ b/app/src/main/cpp/Dobby/external/deprecated/misc-helper/async_logger.cc @@ -0,0 +1,65 @@ +#include +#include +#include +#include + +#include + +#include +#include +#include + +#define aync_logger_buffer_size (20 * 1024 * 1024) +int async_logger_buffer_cursor = 0; +char async_logger_buffer[aync_logger_buffer_size]; + +static pthread_mutex_t async_logger_mutex = PTHREAD_MUTEX_INITIALIZER; + +static int output_fd = -1; + +void async_logger_print(char *str) { + pthread_mutex_lock(&async_logger_mutex); +#if 0 + { + write(STDOUT_FILENO, str, strlen(str) + 1); + } +#endif + memcpy(async_logger_buffer + async_logger_buffer_cursor, str, strlen(str)); + async_logger_buffer_cursor += strlen(str); + pthread_mutex_unlock(&async_logger_mutex); + return; +} + +static void *async_logger_print_impl(void *ctx) { + while (1) { + pthread_mutex_lock(&async_logger_mutex); + if (async_logger_buffer_cursor > 0) { + write(output_fd, async_logger_buffer, async_logger_buffer_cursor); + async_logger_buffer_cursor = 0; + } + pthread_mutex_unlock(&async_logger_mutex); + sleep(1); + } +} + +void async_logger_init(char *logger_path) { + static int async_logger_initialized = 0; + if (async_logger_initialized) + return; + async_logger_initialized = 1; + + // init stdout write lock + pthread_mutex_t write_mutex; + pthread_mutex_init(&write_mutex, NULL); + + output_fd = STDOUT_FILENO; + if (logger_path) { + int fd = open(logger_path, O_CREAT | O_WRONLY | O_TRUNC, 0644); + output_fd = fd; + } + + // init async logger + pthread_mutex_init(&async_logger_mutex, NULL); + pthread_t async_logger_thread; + int ret = pthread_create(&async_logger_thread, NULL, async_logger_print_impl, NULL); +} diff --git a/app/src/main/cpp/Dobby/external/deprecated/misc-helper/deprecated/pthread_helper.cc b/app/src/main/cpp/Dobby/external/deprecated/misc-helper/deprecated/pthread_helper.cc new file mode 100644 index 0000000..bc080f6 --- /dev/null +++ b/app/src/main/cpp/Dobby/external/deprecated/misc-helper/deprecated/pthread_helper.cc @@ -0,0 +1,129 @@ +#include "pthread_helper.h" +#include +#ifdef _WIN32 + +typedef void (*windows_thread)(void *); + +int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine)(void *), void *arg) { + uintptr_t handle = _beginthread((windows_thread)start_routine, 0, arg); + thread->handle = (HANDLE)handle; + if (thread->handle == (HANDLE)-1) { + return 1; + } else { + return 0; + } +} + +int pthread_detach(pthread_t thread) { + /* Do nothing */ + return 0; +} + +void pthread_exit(void *value_ptr) { + _endthread(); +} + +int pthread_join(pthread_t thread, void **value_ptr) { + DWORD retvalue = WaitForSingleObject(thread.handle, INFINITE); + if (retvalue == WAIT_OBJECT_0) { + return 0; + } else { + return EINVAL; + } +} + +pthread_t pthread_self(void) { + pthread_t pt; + pt.handle = GetCurrentThread(); + return pt; +} + +int pthread_cancel(pthread_t thread) { + fprintf(stderr, "DO NOT USE THIS FUNCTION. pthread_cancel\n"); + abort(); + return 0; +} + +/* --------------------- MUTEX --------------------*/ + +int pthread_mutexattr_destroy(pthread_mutexattr_t *attr) { + /* do nothing */ + return 0; +} + +int pthread_mutexattr_init(pthread_mutexattr_t *attr) { + /* do nothing */ + return 0; +} + +int pthread_mutex_destroy(pthread_mutex_t *mutex) { + return !CloseHandle(mutex->handle); +} + +int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr) { + HANDLE handle = CreateMutex(NULL, FALSE, NULL); + if (handle != NULL) { + mutex->handle = handle; + return 0; + } else { + return 1; + } +} + +int pthread_mutex_lock(pthread_mutex_t *mutex) { + DWORD retvalue = WaitForSingleObject(mutex->handle, INFINITE); + if (retvalue == WAIT_OBJECT_0) { + return 0; + } else { + return EINVAL; + } +} + +int pthread_mutex_trylock(pthread_mutex_t *mutex) { + DWORD retvalue = WaitForSingleObject(mutex->handle, 0); + if (retvalue == WAIT_OBJECT_0) { + return 0; + } else if (retvalue == WAIT_TIMEOUT) { + return EBUSY; + } else { + return EINVAL; + } +} + +int pthread_mutex_unlock(pthread_mutex_t *mutex) { + return !ReleaseMutex(mutex->handle); +} + +/* ------------------- Thead Specific Data ------------------ */ + +int pthread_key_create(pthread_key_t *key, void (*destr_function)(void *)) { + DWORD dkey = TlsAlloc(); + if (dkey != 0xFFFFFFFF) { + *key = dkey; + return 0; + } else { + return EAGAIN; + } +} + +int pthread_key_delete(pthread_key_t key) { + if (TlsFree(key)) { + return 0; + } else { + return EINVAL; + } +} + +int pthread_setspecific(pthread_key_t key, const void *pointer) { + if (TlsSetValue(key, (LPVOID)pointer)) { + return 0; + } else { + return EINVAL; + } +} + +void *pthread_getspecific(pthread_key_t key) { + return TlsGetValue(key); +} + +#endif \ No newline at end of file diff --git a/app/src/main/cpp/Dobby/external/deprecated/misc-helper/deprecated/pthread_helper.h b/app/src/main/cpp/Dobby/external/deprecated/misc-helper/deprecated/pthread_helper.h new file mode 100644 index 0000000..3ed01f6 --- /dev/null +++ b/app/src/main/cpp/Dobby/external/deprecated/misc-helper/deprecated/pthread_helper.h @@ -0,0 +1,85 @@ +/* + * light weight pthread compatible library for Windows + * (C) 2009 Okamura Yasunobu + * + * WARNING This library does NOT support all future of pthread + * + */ + +#ifndef CROSS_THREAD_H +#define CROSS_THREAD_H + +#ifdef _WIN32 + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include + +typedef struct pthread_tag { + HANDLE handle; +} pthread_t; + +typedef struct pthread_mutex_tag { + HANDLE handle; +} pthread_mutex_t; + +/* stub */ +typedef struct pthread_attr_tag { + int attr; +} pthread_attr_t; + +typedef struct pthread_mutexattr_tag { + int attr; +} pthread_mutexattr_t; + +typedef DWORD pthread_key_t; + +/* ignore attribute */ +int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine)(void *), void *arg); + +/* ignore value_ptr */ +void pthread_exit(void *value_ptr); + +/* ignore value_ptr */ +int pthread_join(pthread_t thread, void **value_ptr); + +pthread_t pthread_self(void); + +/* do nothing */ +int pthread_detach(pthread_t thread); + +/* DO NOT USE */ +int pthread_cancel(pthread_t thread); + +int pthread_mutexattr_destroy(pthread_mutexattr_t *attr); /* do nothing */ +int pthread_mutexattr_init(pthread_mutexattr_t *attr); /* do nothing */ + +int pthread_mutex_destroy(pthread_mutex_t *mutex); +int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr); +int pthread_mutex_lock(pthread_mutex_t *mutex); +int pthread_mutex_trylock(pthread_mutex_t *mutex); +int pthread_mutex_unlock(pthread_mutex_t *mutex); + +/* ignore deconstructor */ +int pthread_key_create(pthread_key_t *key, void (*destr_function)(void *)); +int pthread_key_delete(pthread_key_t key); +int pthread_setspecific(pthread_key_t key, const void *pointer); +void *pthread_getspecific(pthread_key_t key); + +#define sleep(num) Sleep(1000 * (num)) + +#ifdef __cplusplus +} +#endif + +#else +#include +#include +#define Sleep(num) usleep(num * 1000) +#endif + +#endif /* CROSS_THREAD_H */ diff --git a/app/src/main/cpp/Dobby/external/deprecated/misc-helper/deprecated/unistd_helper.h b/app/src/main/cpp/Dobby/external/deprecated/misc-helper/deprecated/unistd_helper.h new file mode 100644 index 0000000..d990fa3 --- /dev/null +++ b/app/src/main/cpp/Dobby/external/deprecated/misc-helper/deprecated/unistd_helper.h @@ -0,0 +1,30 @@ +#ifdef _WIN32 + +#include +#define open _open +#define read _read +#define O_RDONLY _O_RDONLY +#define O_WRONLY _O_WRONLY +#define O_CREAT _O_CREAT +#define O_TRUNC _O_TRUNC + +#define ssize_t int + +#define STDIN_FILENO 0 +#define STDOUT_FILENO 1 +#define STDERR_FILENO 2 +/* should be in some equivalent to */ +typedef __int8 int8_t; +typedef __int16 int16_t; +typedef __int32 int32_t; +typedef __int64 int64_t; +typedef unsigned __int8 uint8_t; +typedef unsigned __int16 uint16_t; +typedef unsigned __int32 uint32_t; +typedef unsigned __int64 uint64_t; + +#else + +#include + +#endif \ No newline at end of file diff --git a/app/src/main/cpp/Dobby/external/deprecated/misc-helper/format_printer.cc b/app/src/main/cpp/Dobby/external/deprecated/misc-helper/format_printer.cc new file mode 100644 index 0000000..47c8b8f --- /dev/null +++ b/app/src/main/cpp/Dobby/external/deprecated/misc-helper/format_printer.cc @@ -0,0 +1,11 @@ +#include "misc-helper/format_printer.h" + +void hexdump(const uint8_t *bytes, size_t len) { + size_t ix; + for (ix = 0; ix < len; ++ix) { + if (ix != 0 && !(ix % 16)) + LOG_FUNCTION_IMPL(0, "\n"); + LOG_FUNCTION_IMPL(0, "%02X ", bytes[ix]); + } + LOG_FUNCTION_IMPL(0, "\n"); +} diff --git a/app/src/main/cpp/Dobby/external/deprecated/misc-helper/misc-helper/async_logger.h b/app/src/main/cpp/Dobby/external/deprecated/misc-helper/misc-helper/async_logger.h new file mode 100644 index 0000000..03e0d4e --- /dev/null +++ b/app/src/main/cpp/Dobby/external/deprecated/misc-helper/misc-helper/async_logger.h @@ -0,0 +1,8 @@ +#ifndef ASYNC_LOGGER_H +#define ASYNC_LOGGER_H + +void async_logger_print(char *str); + +void async_logger_init(char *logger_path); + +#endif \ No newline at end of file diff --git a/app/src/main/cpp/Dobby/external/deprecated/misc-helper/misc-helper/format_printer.h b/app/src/main/cpp/Dobby/external/deprecated/misc-helper/misc-helper/format_printer.h new file mode 100644 index 0000000..1123908 --- /dev/null +++ b/app/src/main/cpp/Dobby/external/deprecated/misc-helper/misc-helper/format_printer.h @@ -0,0 +1,3 @@ +#include "dobby/common.h" + +void hexdump(const uint8_t *bytes, size_t len); \ No newline at end of file diff --git a/app/src/main/cpp/Dobby/external/deprecated/misc-helper/misc-helper/variable_cache.h b/app/src/main/cpp/Dobby/external/deprecated/misc-helper/misc-helper/variable_cache.h new file mode 100644 index 0000000..bf490fd --- /dev/null +++ b/app/src/main/cpp/Dobby/external/deprecated/misc-helper/misc-helper/variable_cache.h @@ -0,0 +1,17 @@ +#ifndef VARIABLE_CACHE_H +#define VARIABLE_CACHE_H + +#include + +#define cache_set stash +void cache_set(const char *name, uint64_t value); + +#define cache_get(x) cache(x) +#define assert_cache(x) (assert(cache(x)), cache(x)) +uint64_t cache_get(const char *name); + +int serialized_to_file(const char *filepath); + +int unserialized_from_file(const char *filepath); + +#endif diff --git a/app/src/main/cpp/Dobby/external/deprecated/misc-helper/variable_cache.c b/app/src/main/cpp/Dobby/external/deprecated/misc-helper/variable_cache.c new file mode 100644 index 0000000..895a2cb --- /dev/null +++ b/app/src/main/cpp/Dobby/external/deprecated/misc-helper/variable_cache.c @@ -0,0 +1,118 @@ +#include "misc-helper/variable_cache.h" + +#include +#include +#include + +#include +#include "deprecated/unistd_helper.h" + +#include + +typedef struct queue_entry_t { + struct queue_entry *next; + struct queue_entry *prev; +} queue_entry_t; + +/* TODO: add a property or attribute indicate not serialized */ +typedef struct var_entry_t { + queue_entry_t entry_; + char key[128]; + uint64_t value; +} var_entry_t; + +var_entry_t *root = NULL; + +static var_entry_t *cache_get_entry_internal(const char *name) { + var_entry_t *entry; + entry = root; + while (entry != NULL) { + if (strcmp(name, entry->key) == 0) { + return entry; + } + entry = (var_entry_t *)entry->entry_.next; + } + return NULL; +} + +void cache_set(const char *name, uint64_t value) { + var_entry_t *entry = cache_get_entry_internal(name); + if (entry) { + entry->value = value; + return; + } + + entry = (var_entry_t *)malloc(sizeof(var_entry_t)); + strcpy(entry->key, name); + entry->value = value; + + entry->entry_.next = (struct queue_entry *)root; + root = entry; +} + +uint64_t cache_get(const char *name) { + var_entry_t *entry = cache_get_entry_internal(name); + if (entry) { + return entry->value; + } + return 0; +} + +typedef struct entry_block { + int key_length; + int value_length; +} entry_block_t; + +int serialized_to_file(const char *filepath) { + int fd = open(filepath, O_WRONLY | O_CREAT | O_TRUNC, 0660); + if (fd == -1) { + printf("open %s failed: %s\n", filepath, strerror(errno)); + return -1; + } + + var_entry_t *entry; + entry = root; + while (entry != NULL) { + entry_block_t block = {0}; + { + block.key_length = strlen(entry->key) + 1; + block.value_length = sizeof(uint64_t); + write(fd, &block, sizeof(block)); + } + + write(fd, entry->key, block.key_length); + write(fd, &entry->value, block.value_length); + + entry = (var_entry_t *)entry->entry_.next; + } + close(fd); + return 0; +} + +int unserialized_from_file(const char *filepath) { + int fd = open(filepath, O_RDONLY); + if (fd == -1) { + printf("open %s failed: %s\n", filepath, strerror(errno)); + return -1; + } + + entry_block_t block = {0}; + while (read(fd, &block, sizeof(block)) > 0) { + char key[128] = {0}; + uint64_t value = 0; + + read(fd, (void *)&key, block.key_length); + read(fd, (void *)&value, block.value_length); + + { + var_entry_t *entry = (var_entry_t *)malloc(sizeof(var_entry_t)); + strcpy(entry->key, key); + entry->value = value; + + entry->entry_.next = (struct queue_entry *)root; + root = entry; + } + } + + return 0; +} diff --git a/app/src/main/cpp/Dobby/external/logging/CMakeLists.txt b/app/src/main/cpp/Dobby/external/logging/CMakeLists.txt new file mode 100644 index 0000000..a11dfa9 --- /dev/null +++ b/app/src/main/cpp/Dobby/external/logging/CMakeLists.txt @@ -0,0 +1,15 @@ +include_directories(.) + +if(NOT DOBBY_BUILD_KERNEL_MODE) + set(SOURCE_FILE_LIST + ${CMAKE_CURRENT_SOURCE_DIR}/logging.cc + ) +else() + set(SOURCE_FILE_LIST + ${CMAKE_CURRENT_SOURCE_DIR}/kernel_logging.cc + ) +endif() +add_library(logging + ${SOURCE_FILE_LIST} + ${SOURCE_HEADER_LIST} +) \ No newline at end of file diff --git a/app/src/main/cpp/Dobby/external/logging/kernel_logging.cc b/app/src/main/cpp/Dobby/external/logging/kernel_logging.cc new file mode 100644 index 0000000..996f9f9 --- /dev/null +++ b/app/src/main/cpp/Dobby/external/logging/kernel_logging.cc @@ -0,0 +1,28 @@ +#include "logging/logging.h" + +#include +#include "utility_macro.h" + +#if defined(BUILDING_KERNEL) +#define abort() +#else +#include +#endif + +static int _log_level = 1; +PUBLIC void log_set_level(int level) { + _log_level = level; +} + +PUBLIC int log_internal_impl(int level, const char *fmt, ...) { + if (level < _log_level) + return 0; + + va_list ap; + va_start(ap, fmt); + + vprintf(fmt, ap); + + va_end(ap); + return 0; +} diff --git a/app/src/main/cpp/Dobby/external/logging/logging.cc b/app/src/main/cpp/Dobby/external/logging/logging.cc new file mode 100644 index 0000000..fb57c0e --- /dev/null +++ b/app/src/main/cpp/Dobby/external/logging/logging.cc @@ -0,0 +1,137 @@ +#include "logging/logging.h" + +#include +#include +#include +#include +#include +#include + +#if defined(__linux__) || defined(__APPLE__) +#include +#include +#include +#include +#include +#endif + +#if defined(__APPLE__) +#include +#include +#include +#include +#include +#include "./priv_headers/_simple.h" +#endif + +#if defined(_WIN32) +#define PUBLIC +#else +#define PUBLIC __attribute__((visibility("default"))) +#define INTERNAL __attribute__((visibility("internal"))) +#endif + +#if defined(__ANDROID__) +#include +#endif + +#pragma clang diagnostic ignored "-Wformat" + +Logger *Logger::g_logger = nullptr; + +void Logger::logv(LogLevel level, const char *_fmt, va_list ap) { + if (level < log_level_) + return; + + char fmt_buffer[4096] = {0}; + + if (log_tag_ != nullptr) { + snprintf(fmt_buffer + strlen(fmt_buffer), sizeof(fmt_buffer) - strlen(fmt_buffer), "%s ", log_tag_); + } + + if (enable_time_tag_) { + time_t now = time(NULL); + struct tm *tm = localtime(&now); + snprintf(fmt_buffer + strlen(fmt_buffer), sizeof(fmt_buffer) - strlen(fmt_buffer), "%04d-%02d-%02d %02d:%02d:%02d ", + tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec); + } + + snprintf(fmt_buffer + strlen(fmt_buffer), sizeof(fmt_buffer) - strlen(fmt_buffer), "%s\n", _fmt); + + if (enable_syslog_) { +#if defined(__APPLE__) + extern void *_os_log_default; + static void (*os_log_with_args)(void *oslog, char type, const char *format, va_list args, void *ret_addr) = 0; + if (!os_log_with_args) + os_log_with_args = (__typeof(os_log_with_args))dlsym((void *)-2, "os_log_with_args"); + // os_log_with_args(&_os_log_default, 0x10, fmt_buffer, ap, (void *)&os_log_with_args); + vsyslog(LOG_ALERT, fmt_buffer, ap); + + static int _logDescriptor = 0; + if (_logDescriptor == 0) { + _logDescriptor = socket(AF_UNIX, SOCK_DGRAM, 0); + if (_logDescriptor != -1) { + fcntl(_logDescriptor, F_SETFD, FD_CLOEXEC); + struct sockaddr_un addr; + addr.sun_family = AF_UNIX; + strncpy(addr.sun_path, _PATH_LOG, sizeof(addr.sun_path)); + if (connect(_logDescriptor, (struct sockaddr *)&addr, sizeof(addr)) == -1) { + close(_logDescriptor); + _logDescriptor = -1; + ERROR_LOG("Failed to connect to syslogd: %s", strerror(errno)); + } + } + } + if (_logDescriptor > 0) { + vdprintf(_logDescriptor, fmt_buffer, ap); + } +#elif defined(_POSIX_VERSION) + vsyslog(LOG_ERR, fmt_buffer, ap); +#endif + } + + if (log_file_ != nullptr) { + char buffer[0x4000] = {0}; + vsnprintf(buffer, sizeof(buffer) - 1, fmt_buffer, ap); +#if defined(USER_CXX_FILESTREAM) + log_file_stream_->write(buffer, strlen(buffer)); + log_file_stream_->flush(); +#else + fwrite(buffer, strlen(buffer), 1, log_file_stream_); + fflush(log_file_stream_); +#endif + } + + if (1 || !enable_syslog_ && log_file_ == nullptr) { +#if defined(__ANDROID__) + __android_log_vprint(ANDROID_LOG_INFO, NULL, fmt_buffer, ap); +#else + vprintf(fmt_buffer, ap); +#endif + } +} + +#pragma clang diagnostic warning "-Wformat" + +void *logger_create(const char *tag, const char *file, LogLevel level, bool enable_time_tag, bool enable_syslog) { + Logger *logger = new Logger(tag, file, level, enable_time_tag, enable_syslog); + return logger; +} + +void logger_set_options(void *logger, const char *tag, const char *file, LogLevel level, bool enable_time_tag, + bool enable_syslog) { + if (logger == nullptr) { + logger = Logger::Shared(); + } + ((Logger *)logger)->setOptions(tag, file, level, enable_time_tag, enable_syslog); +} + +void logger_log_impl(void *logger, LogLevel level, const char *fmt, ...) { + if (logger == nullptr) { + logger = Logger::Shared(); + } + va_list ap; + va_start(ap, fmt); + ((Logger *)logger)->logv(level, fmt, ap); + va_end(ap); +} \ No newline at end of file diff --git a/app/src/main/cpp/Dobby/external/logging/logging/check_logging.h b/app/src/main/cpp/Dobby/external/logging/logging/check_logging.h new file mode 100644 index 0000000..571c2c7 --- /dev/null +++ b/app/src/main/cpp/Dobby/external/logging/logging/check_logging.h @@ -0,0 +1,87 @@ + +#ifndef CHECK_LOGGING_H_ +#define CHECK_LOGGING_H_ + +#include "logging.h" + +#define CHECK_WITH_MSG(condition, message) \ + do { \ + if (!(condition)) { \ + FATAL_LOG("Check failed: %s.\n", message); \ + } \ + } while (0) +#define CHECK(condition) CHECK_WITH_MSG(condition, #condition) + +#ifdef LOGGING_DEBUG + +#define DCHECK_WITH_MSG(condition, message) \ + do { \ + if (!(condition)) { \ + FATAL_LOG("%s", message); \ + } \ + } while (0) +#define DCHECK(condition) DCHECK_WITH_MSG(condition, #condition) + +// Helper macro for binary operators. +// Don't use this macro directly in your code, use CHECK_EQ et al below. +#define CHECK_OP(name, op, lhs, rhs) \ + do { \ + if (!(lhs op rhs)) { \ + FATAL_LOG(" Check failed: %s.\n", #lhs " " #op " " #rhs); \ + } \ + } while (0) + +#define DCHECK_OP(name, op, lhs, rhs) \ + do { \ + if (!((lhs)op(rhs))) { \ + FATAL_LOG("%s", ""); \ + } \ + } while (0) + +#else + +// Make all CHECK functions discard their log strings to reduce code +// bloat for official release builds. +#define CHECK_OP(name, op, lhs, rhs) \ + do { \ + bool _cond = lhs op rhs; \ + CHECK_WITH_MSG(_cond, #lhs " " #op " " #rhs "\n"); \ + } while (0) + +#define DCHECK_WITH_MSG(condition, msg) void(0); + +#endif + +#define CHECK_EQ(lhs, rhs) CHECK_OP(EQ, ==, lhs, rhs) +#define CHECK_NE(lhs, rhs) CHECK_OP(NE, !=, lhs, rhs) +#define CHECK_LE(lhs, rhs) CHECK_OP(LE, <=, lhs, rhs) +#define CHECK_LT(lhs, rhs) CHECK_OP(LT, <, lhs, rhs) +#define CHECK_GE(lhs, rhs) CHECK_OP(GE, >=, lhs, rhs) +#define CHECK_GT(lhs, rhs) CHECK_OP(GT, >, lhs, rhs) +#define CHECK_NULL(val) CHECK((val) == NULL) +#define CHECK_NOT_NULL(val) CHECK((val) != NULL) + +#ifdef LOGGING_DEBUG +#define DCHECK_EQ(lhs, rhs) DCHECK_OP(EQ, ==, lhs, rhs) +#define DCHECK_NE(lhs, rhs) DCHECK_OP(NE, !=, lhs, rhs) +#define DCHECK_GT(lhs, rhs) DCHECK_OP(GT, >, lhs, rhs) +#define DCHECK_GE(lhs, rhs) DCHECK_OP(GE, >=, lhs, rhs) +#define DCHECK_LT(lhs, rhs) DCHECK_OP(LT, <, lhs, rhs) +#define DCHECK_LE(lhs, rhs) DCHECK_OP(LE, <=, lhs, rhs) +#define DCHECK_NULL(val) DCHECK((val) == nullptr) +#define DCHECK_NOT_NULL(val) DCHECK((val) != nullptr) +#define DCHECK_IMPLIES(lhs, rhs) DCHECK_WITH_MSG(!(lhs) || (rhs), #lhs " implies " #rhs) +#else +#define DCHECK(condition) ((void)0) +#define DCHECK_EQ(v1, v2) ((void)0) +#define DCHECK_NE(v1, v2) ((void)0) +#define DCHECK_GT(v1, v2) ((void)0) +#define DCHECK_GE(v1, v2) ((void)0) +#define DCHECK_LT(v1, v2) ((void)0) +#define DCHECK_LE(v1, v2) ((void)0) +#define DCHECK_NULL(val) ((void)0) +#define DCHECK_NOT_NULL(val) ((void)0) +#define DCHECK_IMPLIES(v1, v2) ((void)0) +#endif + +#endif diff --git a/app/src/main/cpp/Dobby/external/logging/logging/logging.h b/app/src/main/cpp/Dobby/external/logging/logging/logging.h new file mode 100644 index 0000000..99ec360 --- /dev/null +++ b/app/src/main/cpp/Dobby/external/logging/logging/logging.h @@ -0,0 +1,204 @@ +#pragma once + +#include +#include +#include +#include + +#define LOG_TAG NULL + +typedef enum { + LOG_LEVEL_DEBUG = 0, + LOG_LEVEL_INFO = 1, + LOG_LEVEL_WARN = 2, + LOG_LEVEL_ERROR = 3, + LOG_LEVEL_FATAL = 4 +} LogLevel; + +#ifdef __cplusplus + +#if defined(USE_CXX_FILESTREAM) +#include +#endif + +class Logger { +public: + const char *log_tag_; + + const char *log_file_; +#if defined(USE_CXX_FILESTREAM) + std::fstream *log_file_stream_; +#else + FILE *log_file_stream_; +#endif + + LogLevel log_level_; + + bool enable_time_tag_; + + bool enable_syslog_; + + static Logger *g_logger; + static Logger *Shared() { + if (g_logger == nullptr) { + g_logger = new Logger(); + } + return g_logger; + } + + Logger() { + log_tag_ = nullptr; + log_file_ = nullptr; + log_level_ = LOG_LEVEL_DEBUG; + enable_time_tag_ = false; + enable_syslog_ = false; + } + + Logger(const char *tag, const char *file, LogLevel level, bool enable_time_tag, bool enable_syslog) { + setTag(tag); + setLogFile(file); + setLogLevel(level); + enable_time_tag_ = enable_time_tag; + enable_syslog_ = enable_syslog; + } + + void setOptions(const char *tag, const char *file, LogLevel level, bool enable_time_tag, bool enable_syslog) { + if (tag) + setTag(tag); + if (file) + setLogFile(file); + setLogLevel(level); + enable_time_tag_ = enable_time_tag; + enable_syslog_ = enable_syslog; + } + + void setTag(const char *tag) { + log_tag_ = tag; + } + + void setLogFile(const char *file) { + log_file_ = file; +#if defined(USE_CXX_FILESTREAM) + log_file_stream_ = new std::fstream(); + log_file_stream_->open(log_file_, std::ios::out | std::ios::app); +#else + log_file_stream_ = fopen(log_file_, "a"); +#endif + } + + void setLogLevel(LogLevel level) { + log_level_ = level; + } + + void enableTimeTag() { + enable_time_tag_ = true; + } + + void enableSyslog() { + enable_syslog_ = true; + } + + void logv(LogLevel level, const char *fmt, va_list ap); + + void log(LogLevel level, const char *fmt, ...) { + va_list ap; + va_start(ap, fmt); + logv(level, fmt, ap); + va_end(ap); + } + + void debug(const char *fmt, ...) { + va_list ap; + va_start(ap, fmt); + logv(LOG_LEVEL_DEBUG, fmt, ap); + va_end(ap); + } + + void info(const char *fmt, ...) { + va_list ap; + va_start(ap, fmt); + logv(LOG_LEVEL_INFO, fmt, ap); + va_end(ap); + } + + void warn(const char *fmt, ...) { + va_list ap; + va_start(ap, fmt); + logv(LOG_LEVEL_WARN, fmt, ap); + va_end(ap); + } + + void error(const char *fmt, ...) { + va_list ap; + va_start(ap, fmt); + logv(LOG_LEVEL_ERROR, fmt, ap); + va_end(ap); + } + + void fatal(const char *fmt, ...) { + va_list ap; + va_start(ap, fmt); + logv(LOG_LEVEL_FATAL, fmt, ap); + va_end(ap); + } +}; + +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(DOBBY_LOGGING_DISABLE) +#define LOG_FUNCTION_IMPL(...) +#else +#if !defined(LOG_FUNCTION_IMPL) +#define LOG_FUNCTION_IMPL logger_log_impl +#endif +#endif + +void *logger_create(const char *tag, const char *file, LogLevel level, bool enable_time_tag, bool enable_syslog); +void logger_set_options(void *logger, const char *tag, const char *file, LogLevel level, bool enable_time_tag, + bool enable_syslog); +void logger_log_impl(void *logger, LogLevel level, const char *fmt, ...); + +#ifdef __cplusplus +} +#endif + +#define LOG(level, fmt, ...) \ + do { \ + if (LOG_TAG) \ + LOG_FUNCTION_IMPL(NULL, level, "[%s] " fmt, LOG_TAG, ##__VA_ARGS__); \ + else \ + LOG_FUNCTION_IMPL(NULL, level, fmt, ##__VA_ARGS__); \ + } while (0) + +#define DEBUG_LOG(fmt, ...) \ + do { \ + LOG(LOG_LEVEL_DEBUG, fmt, ##__VA_ARGS__); \ + } while (0) + +#define INFO_LOG(fmt, ...) \ + do { \ + LOG(LOG_LEVEL_INFO, fmt, ##__VA_ARGS__); \ + } while (0) + +#define WARN_LOG(fmt, ...) \ + do { \ + LOG(LOG_LEVEL_WARN, fmt, ##__VA_ARGS__); \ + } while (0) + +#define ERROR_LOG(fmt, ...) \ + do { \ + LOG(LOG_LEVEL_ERROR, "[!] [%s:%d:%s]" fmt, __FILE__, __LINE__, __func__, ##__VA_ARGS__); \ + } while (0) + +#define FATAL_LOG(fmt, ...) \ + do { \ + LOG(LOG_LEVEL_FATAL, "[!] [%s:%d:%s]" fmt, __FILE__, __LINE__, __func__, ##__VA_ARGS__); \ + abort(); \ + } while (0) + +#define UNIMPLEMENTED() FATAL_LOG("%s\n", "unimplemented code!!!") +#define UNREACHABLE() FATAL_LOG("%s\n", "unreachable code!!!") \ No newline at end of file diff --git a/app/src/main/cpp/Dobby/external/logging/priv_headers/_simple.h b/app/src/main/cpp/Dobby/external/logging/priv_headers/_simple.h new file mode 100644 index 0000000..2ae8384 --- /dev/null +++ b/app/src/main/cpp/Dobby/external/logging/priv_headers/_simple.h @@ -0,0 +1,162 @@ +/* + * Copyright (c) 2006, 2010, 2013 Apple Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +#ifndef _SYSTEM_SIMPLE_H_ +#define _SYSTEM_SIMPLE_H_ + +#include +#include + +#include + +typedef void *_SIMPLE_STRING; +typedef const char *_esc_func(unsigned char); + +__BEGIN_DECLS +/* + * A simplified vfprintf variant. The format string is interpreted with + * arguments from the va_list, and the results are written to the given + * file descriptor. + */ +void _simple_vdprintf(int __fd, const char *__fmt, va_list __ap) __printflike(2, 0); + +/* + * A simplified fprintf variant. The format string is interpreted with + * arguments from the variable argument list, and the results are written + * to the given file descriptor. + */ +void _simple_dprintf(int __fd, const char *__fmt, ...) __printflike(2, 3); + +/* + * A simplified string allocate routine. Pass the opaque pointer to structure + * to _simple_*sprintf() routines. Use _simple_string() to retrieve the + * current string (the string is guaranteed to be null terminated only on + * the call to _simple_string()). Use _simple_sfree() to free the structure + * and string memory. + */ +_SIMPLE_STRING _simple_salloc(void); + +/* + * The format string is interpreted with arguments from the va_list, and the + * results are appended to the string maintained by the opaque structure, as + * returned by a previous call to _simple_salloc(). Non-zero is returned on + * out-of-memory error. + */ +int _simple_vsprintf(_SIMPLE_STRING __b, const char *__fmt, va_list __ap) __printflike(2, 0); + +/* + * The format string is interpreted with arguments from the variable argument + * list, and the results are appended to the string maintained by the opaque + * structure, as returned by a previous call to _simple_salloc(). Non-zero is + * returned on out-of-memory error. + */ +int _simple_sprintf(_SIMPLE_STRING __b, const char *__fmt, ...) __printflike(2, 3); + +/* + * Like _simple_vsprintf(), except __esc is a function to call on each + * character; the function returns NULL if the character should be passed + * as is, otherwise, the returned character string is used instead. + */ +int _simple_vesprintf(_SIMPLE_STRING __b, _esc_func __esc, const char *__fmt, va_list __ap) __printflike(3, 0); + +/* + * Like _simple_sprintf(), except __esc is a function to call on each + * character; the function returns NULL if the character should be passed + * as is, otherwise, the returned character string is used instead. + */ +int _simple_esprintf(_SIMPLE_STRING __b, _esc_func __esc, const char *__fmt, ...) __printflike(3, 4); + +/* + * Return the null terminated string from the opaque structure, as returned + * by a previous call to _simple_salloc(). + */ +char *_simple_string(_SIMPLE_STRING __b); + +/* + * Reposition the pointer to the first null in the buffer. After a call to + * _simple_string, the buffer can be modified, and shrunk. + */ +void _simple_sresize(_SIMPLE_STRING __b); + +/* + * Append the null-terminated string to the string associated with the opaque + * structure. Non-zero is returned on out-of-memory error. + */ +int _simple_sappend(_SIMPLE_STRING __b, const char *__str); + +/* + * Like _simple_sappend(), except __esc is a function to call on each + * character; the function returns NULL if the character should be passed + * as is, otherwise, the returned character string is used instead. + */ +int _simple_esappend(_SIMPLE_STRING __b, _esc_func __esc, const char *__str); + +/* + * Write the string associated with the opaque structure to the file descriptor. + */ +void _simple_put(_SIMPLE_STRING __b, int __fd); + +/* + * Write the string associated with the opaque structure and a trailing newline, + * to the file descriptor. + */ +void _simple_putline(_SIMPLE_STRING __b, int __fd); + +/* + * Free the opaque structure, and the associated string. + */ +void _simple_sfree(_SIMPLE_STRING __b); + +/* + * Simplified ASL log interface; does not use malloc. Unfortunately, this + * requires knowledge of the format used by ASL. + */ +#ifndef ASL_LEVEL_DEBUG +#define ASL_LEVEL_EMERG 0 +#define ASL_LEVEL_ALERT 1 +#define ASL_LEVEL_CRIT 2 +#define ASL_LEVEL_ERR 3 +#define ASL_LEVEL_WARNING 4 +#define ASL_LEVEL_NOTICE 5 +#define ASL_LEVEL_INFO 6 +#define ASL_LEVEL_DEBUG 7 +#endif + +void _simple_asl_log(int __level, const char *__facility, const char *__message); +void _simple_asl_log_prog(int level, const char *facility, const char *message, const char *progname); + +__OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_7_0) +_SIMPLE_STRING _simple_asl_msg_new(void); + +__OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_7_0) +void _simple_asl_msg_set(_SIMPLE_STRING __b, const char *__key, const char *__val); + +__OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_7_0) +void _simple_asl_send(_SIMPLE_STRING __b); + +__OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_7_0) +const char *_simple_getenv(const char *envp[], const char *var); + +__END_DECLS + +#endif /* _SYSTEM_SIMPLE_H_ */ diff --git a/app/src/main/cpp/Dobby/external/osbase/CMakeLists.txt b/app/src/main/cpp/Dobby/external/osbase/CMakeLists.txt new file mode 100644 index 0000000..ef7ce40 --- /dev/null +++ b/app/src/main/cpp/Dobby/external/osbase/CMakeLists.txt @@ -0,0 +1,3 @@ +add_library(osbase STATIC + ${PROJECT_SOURCE_DIR}/source/Backend/UserMode/UnifiedInterface/platform-posix.cc + ) \ No newline at end of file diff --git a/app/src/main/cpp/Dobby/include/dobby.h b/app/src/main/cpp/Dobby/include/dobby.h new file mode 100644 index 0000000..745b798 --- /dev/null +++ b/app/src/main/cpp/Dobby/include/dobby.h @@ -0,0 +1,152 @@ +#ifndef dobby_h +#define dobby_h + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +typedef uintptr_t addr_t; +typedef uint32_t addr32_t; +typedef uint64_t addr64_t; + +typedef void *dobby_dummy_func_t; +typedef void *asm_func_t; + +#if defined(__arm__) +typedef struct { + uint32_t dummy_0; + uint32_t dummy_1; + + uint32_t dummy_2; + uint32_t sp; + + union { + uint32_t r[13]; + struct { + uint32_t r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, r12; + } regs; + } general; + + uint32_t lr; +} DobbyRegisterContext; +#elif defined(__arm64__) || defined(__aarch64__) +#define ARM64_TMP_REG_NDX_0 17 + +typedef union _FPReg { + __int128_t q; + struct { + double d1; + double d2; + } d; + struct { + float f1; + float f2; + float f3; + float f4; + } f; +} FPReg; + +// register context +typedef struct { + uint64_t dmmpy_0; // dummy placeholder + uint64_t sp; + + uint64_t dmmpy_1; // dummy placeholder + union { + uint64_t x[29]; + struct { + uint64_t x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, + x23, x24, x25, x26, x27, x28; + } regs; + } general; + + uint64_t fp; + uint64_t lr; + + union { + FPReg q[32]; + struct { + FPReg q0, q1, q2, q3, q4, q5, q6, q7; + // [!!! READ ME !!!] + // for Arm64, can't access q8 - q31, unless you enable full floating-point register pack + FPReg q8, q9, q10, q11, q12, q13, q14, q15, q16, q17, q18, q19, q20, q21, q22, q23, q24, q25, q26, q27, q28, q29, + q30, q31; + } regs; + } floating; +} DobbyRegisterContext; +#elif defined(_M_IX86) || defined(__i386__) +typedef struct _RegisterContext { + uint32_t dummy_0; + uint32_t esp; + + uint32_t dummy_1; + uint32_t flags; + + union { + struct { + uint32_t eax, ebx, ecx, edx, ebp, esp, edi, esi; + } regs; + } general; + +} DobbyRegisterContext; +#elif defined(_M_X64) || defined(__x86_64__) +typedef struct { + uint64_t dummy_0; + uint64_t rsp; + + union { + struct { + uint64_t rax, rbx, rcx, rdx, rbp, rsp, rdi, rsi, r8, r9, r10, r11, r12, r13, r14, r15; + } regs; + } general; + + uint64_t dummy_1; + uint64_t flags; +} DobbyRegisterContext; +#endif + +#define install_hook_name(name, fn_ret_t, fn_args_t...) \ + static fn_ret_t fake_##name(fn_args_t); \ + static fn_ret_t (*orig_##name)(fn_args_t); \ + /* __attribute__((constructor)) */ static void install_hook_##name(void *sym_addr) { \ + DobbyHook(sym_addr, (dobby_dummy_func_t)fake_##name, (dobby_dummy_func_t *)&orig_##name); \ + return; \ + } \ + fn_ret_t fake_##name(fn_args_t) + +// memory code patch +int DobbyCodePatch(void *address, uint8_t *buffer, uint32_t buffer_size); + +// function inline hook +int DobbyHook(void *address, dobby_dummy_func_t replace_func, dobby_dummy_func_t *origin_func); + +// dynamic binary instruction instrument +// for Arm64, can't access q8 - q31, unless enable full floating-point register pack +typedef void (*dobby_instrument_callback_t)(void *address, DobbyRegisterContext *ctx); +int DobbyInstrument(void *address, dobby_instrument_callback_t pre_handler); + +// destroy and restore code patch +int DobbyDestroy(void *address); + +const char *DobbyGetVersion(); + +// symbol resolver +void *DobbySymbolResolver(const char *image_name, const char *symbol_name); + +// import table replace +int DobbyImportTableReplace(char *image_name, char *symbol_name, dobby_dummy_func_t fake_func, + dobby_dummy_func_t *orig_func); + +// for arm, Arm64, try use b xxx instead of ldr absolute indirect branch +// for x86, x64, always use absolute indirect jump +void dobby_enable_near_branch_trampoline(); +void dobby_disable_near_branch_trampoline(); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/app/src/main/cpp/Dobby/scripts/Dockerfile b/app/src/main/cpp/Dobby/scripts/Dockerfile new file mode 100644 index 0000000..149f448 --- /dev/null +++ b/app/src/main/cpp/Dobby/scripts/Dockerfile @@ -0,0 +1,10 @@ +FROM ubuntu:focal + +ARG DEBIAN_FRONTEND='noninteractive' + +RUN apt-key adv --keyserver 'keyserver.ubuntu.com' --recv-key 'C99B11DEB97541F0' && + apt-add-repository -y -u 'https://cli.github.com/packages' && + apt-add-repository 'deb https://apt.kitware.com/ubuntu/ focal main' + +ADD setup_linux_cross_compile.sh /root/setup_linux_cross_compile.sh +RUN sh /root/setup_linux_cross_compile.sh diff --git a/app/src/main/cpp/Dobby/scripts/platform_builder.py b/app/src/main/cpp/Dobby/scripts/platform_builder.py new file mode 100644 index 0000000..b31b4c9 --- /dev/null +++ b/app/src/main/cpp/Dobby/scripts/platform_builder.py @@ -0,0 +1,242 @@ +import os +import pipes +import re +import shutil +import subprocess +import sys +import logging + +import argparse + +platforms = { + "macos": ["x86_64", "arm64", "arm64e"], + "iphoneos": ["arm64", "arm64e"], + "linux": ["x86", "x86_64", "arm", "arm64"], + "android": ["x86", "x86_64", "armeabi-v7a", "arm64-v8a"] +} + + +class PlatformBuilder(object): + cmake_args = list() + cmake_build_type = "Release" + cmake_build_verbose = False + cmake_build_dir = "" + + library_build_type = "static" + + project_dir = "" + output_dir = "" + + shared_output_name = "" + static_output_name = "" + + platform = "" + arch = "" + + def __init__(self, project_dir, library_build_type, platform, arch): + self.project_dir = project_dir + self.library_build_type = library_build_type + self.platform = platform + self.arch = arch + + self.cmake_build_dir = f"{self.project_dir}/build/cmake-build-{platform}-{arch}" + self.output_dir = f"{self.project_dir}/build/{platform}/{arch}" + + self.cmake = "cmake" if PlatformBuilder.cmake_dir is None else f"{PlatformBuilder.cmake_dir}/bin/cmake" + self.clang = "clang" if PlatformBuilder.llvm_dir is None else f"{PlatformBuilder.llvm_dir}/bin/clang" + self.clangxx = "clang++" if PlatformBuilder.llvm_dir is None else f"{PlatformBuilder.llvm_dir}/bin/clang++" + + self.setup_common_args() + + def cmake_generate_build_system(self): + cmake_cmd_options = ["-S {}".format(self.project_dir), "-B {}".format(self.cmake_build_dir)] + cmd = [f"{self.cmake}"] + cmake_cmd_options + self.cmake_args + # subprocess.run(cmd, check=True) + cmd_line = " ".join(cmd) + print(cmd_line) + os.system(cmd_line) + + def setup_common_args(self): + self.cmake_args += [f"-DCMAKE_C_COMPILER={self.clang}", f"-DCMAKE_CXX_COMPILER={self.clangxx}"] + + self.cmake_args += ["-DCMAKE_BUILD_TYPE={}".format(self.cmake_build_type)] + + if self.library_build_type == "shared": + pass + # self.cmake_args += ["-DDOBBY_GENERATE_SHARED=ON"] + elif self.library_build_type == "static": + pass + # self.cmake_args += ["-DDOBBY_GENERATE_SHARED=OFF"] + + def build(self): + subprocess.run(["mkdir", "-p", "{}".format(self.output_dir)], check=True) + self.cmake_generate_build_system() + + subprocess.run("cmake --build . --clean-first --target dobby --target dobby_static -- -j8", cwd=self.cmake_build_dir, shell=True, check=True) + + os.system(f"mkdir -p {self.output_dir}") + os.system(f"cp {self.cmake_build_dir}/{self.shared_output_name} {self.output_dir}") + os.system(f"cp {self.cmake_build_dir}/{self.static_output_name} {self.output_dir}") + + +class WindowsPlatformBuilder(PlatformBuilder): + + def __init__(self, project_dir, library_build_type, platform, arch): + super().__init__(project_dir, library_build_type, platform, arch) + + if self.library_build_type == "shared": + self.output_name = "libdobby.dll" + else: + self.output_name = "libdobby.lib" + + triples = { + "x86": "i686-pc-windows-msvc", + "x64": "x86_64-pc-windows-msvc", + # "arm": "arm-pc-windows-msvc", + "arm64": "arm64-pc-windows-msvc", + } + + # self.cmake_args += ["--target {}".format(triples[arch])] + self.cmake_args += [ + "-DCMAKE_SYSTEM_PROCESSOR={}".format(arch), + ] + + +class LinuxPlatformBuilder(PlatformBuilder): + + def __init__(self, project_dir, library_build_type, arch): + super().__init__(project_dir, library_build_type, "linux", arch) + + self.shared_output_name = "libdobby.so" + self.static_output_name = "libdobby.a" + + targets = { + "x86": "i686-linux-gnu", + "x86_64": "x86_64-linux-gnu", + "arm": "arm-linux-gnueabi", + "aarch64": "aarch64-linux-gnu", + } + + # self.cmake_args += ["--target={}".format(targets[arch])] + self.cmake_args += [ + "-DCMAKE_SYSTEM_NAME=Linux", + "-DCMAKE_SYSTEM_PROCESSOR={}".format(arch), + ] + + +class AndroidPlatformBuilder(PlatformBuilder): + + def __init__(self, android_nkd_dir, project_dir, library_build_type, arch): + super().__init__(project_dir, library_build_type, "android", arch) + + self.shared_output_name = "libdobby.so" + self.static_output_name = "libdobby.a" + + android_api_level = 21 + if arch == "armeabi-v7a" or arch == "x86": + android_api_level = 19 + + self.cmake_args += [ + "-DCMAKE_SYSTEM_NAME=Android", f"-DCMAKE_ANDROID_NDK={android_nkd_dir}", f"-DCMAKE_ANDROID_ARCH_ABI={arch}", + f"-DCMAKE_SYSTEM_VERSION={android_api_level}" + ] + + +class DarwinPlatformBuilder(PlatformBuilder): + + def __init__(self, project_dir, library_build_type, platform, arch): + super().__init__(project_dir, library_build_type, platform, arch) + + self.cmake_args += [ + "-DCMAKE_OSX_ARCHITECTURES={}".format(arch), + "-DCMAKE_SYSTEM_PROCESSOR={}".format(arch), + ] + + if platform == "macos": + self.cmake_args += ["-DCMAKE_SYSTEM_NAME=Darwin"] + elif platform == "iphoneos": + self.cmake_args += ["-DCMAKE_SYSTEM_NAME=iOS", "-DCMAKE_OSX_DEPLOYMENT_TARGET=9.3"] + + self.shared_output_name = "libdobby.dylib" + self.static_output_name = "libdobby.a" + + @classmethod + def lipo_create_fat(cls, project_dir, platform, output_name): + files = list() + archs = platforms[platform] + for arch in archs: + file = f"{project_dir}/build/{platform}/{arch}/{output_name}" + files.append(file) + + fat_output_dir = f"{project_dir}/build/{platform}/universal" + subprocess.run(["mkdir", "-p", "{}".format(fat_output_dir)], check=True) + cmd = ["lipo", "-create"] + files + ["-output", f"{fat_output_dir}/{output_name}"] + subprocess.run(cmd, check=True) + + +if __name__ == "__main__": + parser = argparse.ArgumentParser() + parser.add_argument("--platform", type=str, required=True) + parser.add_argument("--arch", type=str, required=True) + parser.add_argument("--library_build_type", type=str, default="static") + parser.add_argument("--android_ndk_dir", type=str) + parser.add_argument("--cmake_dir", type=str) + parser.add_argument("--llvm_dir", type=str) + args = parser.parse_args() + + logging.basicConfig(level=logging.INFO, format="%(asctime)s - %(levelname)s - %(message)s") + + platform = args.platform + arch = args.arch + library_build_type = args.library_build_type + + PlatformBuilder.cmake_dir = args.cmake_dir + PlatformBuilder.llvm_dir = args.llvm_dir + + project_dir = os.path.dirname(os.path.dirname(os.path.realpath(__file__))) + logging.info("project dir: {}".format(project_dir)) + if not os.path.exists(f"{project_dir}/CMakeLists.txt"): + logging.error("Please run this script in Dobby project root directory") + sys.exit(1) + + if platform not in platforms: + logging.error("invalid platform {}".format(platform)) + sys.exit(-1) + + if arch != "all" and arch not in platforms[platform]: + logging.error("invalid arch {} for platform {}".format(arch, platform)) + sys.exit(-1) + + if platform == "android": + if args.android_ndk_dir is None: + logging.error("ndk dir is required for android platform") + sys.exit(-1) + + archs = list() + if arch == "all": + archs = platforms[platform] + else: + archs.append(arch) + logging.info("build platform: {}, archs: {}".format(platform, archs)) + + builder: PlatformBuilder = None + for arch_ in archs: + if platform == "macos": + builder = DarwinPlatformBuilder(project_dir, library_build_type, platform, arch_) + elif platform == "iphoneos": + builder = DarwinPlatformBuilder(project_dir, library_build_type, platform, arch_) + elif platform == "android": + builder = AndroidPlatformBuilder(args.android_ndk_dir, project_dir, library_build_type, arch_) + elif platform == "linux": + builder = LinuxPlatformBuilder(project_dir, library_build_type, arch_) + else: + logging.error("invalid platform {}".format(platform)) + sys.exit(-1) + logging.info( + f"build platform: {platform}, arch: {arch_}, cmake_build_dir: {builder.cmake_build_dir}, output_dir: {builder.output_dir}" + ) + builder.build() + + if platform in ["iphoneos", "macos"] and arch == "all": + DarwinPlatformBuilder.lipo_create_fat(project_dir, platform, builder.shared_output_name) + DarwinPlatformBuilder.lipo_create_fat(project_dir, platform, builder.static_output_name) diff --git a/app/src/main/cpp/Dobby/scripts/setup_linux_cross_compile.sh b/app/src/main/cpp/Dobby/scripts/setup_linux_cross_compile.sh new file mode 100644 index 0000000..e2034b6 --- /dev/null +++ b/app/src/main/cpp/Dobby/scripts/setup_linux_cross_compile.sh @@ -0,0 +1,61 @@ +#!/bin/sh + +set -x +set -e + +# sudo dpkg --add-architecture armhf +# sudo dpkg --add-architecture i386 +# sudo dpkg --add-architecture arm64 +# sudo apt-get -y update +# sudo apt-get -y dist-upgrade +# sudo apt-get -y install git build-essential libssl-dev pkg-config unzip gcc-multilib +# sudo apt-get -y install libc6-armhf-cross libc6-dev-armhf-cross gcc-arm-linux-gnueabihf libssl-dev:armhf +# sudo apt-get -y install libc6-i386-cross libc6-dev-i386-cross gcc-i686-linux-gnu libssl-dev:i386 +# sudo apt-get -y install libc6-arm64-cross libc6-dev-arm64-cross gcc-aarch64-linux-gnu libssl-dev:arm64 + +sudo apt-get -y update +sudo apt-get -y install aptitude +sudo apt-get -f -y install \ + apt-utils \ + binutils \ + build-essential \ + curl \ + wget \ + unzip \ + gcc-multilib \ + g++-multilib \ + make \ + zsh + +sudo apt-get -f -y install gcc g++ libc6-dev +sudo apt-get -f -y install gcc-i686-linux-gnu g++-i686-linux-gnu +sudo apt-get -f -y install gcc-arm-linux-gnueabihf g++-arm-linux-gnueabihf +sudo apt-get -f -y install gcc-aarch64-linux-gnu g++-aarch64-linux-gnu + +mkdir -p ~/opt + +cd ~/opt +CMAKE_VERSION=3.25.2 +CMAKE_DOWNLOAD_PACKAGE=cmake-$CMAKE_VERSION-linux-x86_64 +wget https://github.com/Kitware/CMake/releases/download/v$CMAKE_VERSION/$CMAKE_DOWNLOAD_PACKAGE.tar.gz && + tar -zxf $CMAKE_DOWNLOAD_PACKAGE.tar.gz >/dev/null && + mv $CMAKE_DOWNLOAD_PACKAGE cmake-$CMAKE_VERSION +CMAKE_HOME=~/opt/cmake-$CMAKE_VERSION + +cd ~/opt +LLVM_VERSION=15.0.6 +LLVM_DOWNLOAD_PACKAGE=clang+llvm-$LLVM_VERSION-x86_64-linux-gnu-ubuntu-18.04 +wget https://github.com/llvm/llvm-project/releases/download/llvmorg-$LLVM_VERSION/$LLVM_DOWNLOAD_PACKAGE.tar.xz && + tar -xf $LLVM_DOWNLOAD_PACKAGE.tar.xz >/dev/null && + mv $LLVM_DOWNLOAD_PACKAGE llvm-$LLVM_VERSION +LLVM_HOME=~/opt/llvm-$LLVM_VERSION + +cd ~/opt +NDK_VERSION=r25b +NDK_DOWNLOAD_PACKAGE=android-ndk-$NDK_VERSION-linux +NDK_DOWNLOAD_UNZIP_PACKAGE=android-ndk-$NDK_VERSION +wget https://dl.google.com/android/repository/$NDK_DOWNLOAD_PACKAGE.zip && + unzip -q $NDK_DOWNLOAD_PACKAGE.zip >/dev/null && + mv $NDK_DOWNLOAD_UNZIP_PACKAGE ndk-$NDK_VERSION && + rm $NDK_DOWNLOAD_PACKAGE.zip +ANDROID_NDK_HOME=~/opt/android-ndk-$NDK_VERSION diff --git a/app/src/main/cpp/Dobby/scripts/setup_macos_cross_compile.sh b/app/src/main/cpp/Dobby/scripts/setup_macos_cross_compile.sh new file mode 100644 index 0000000..fb904b0 --- /dev/null +++ b/app/src/main/cpp/Dobby/scripts/setup_macos_cross_compile.sh @@ -0,0 +1,22 @@ +#!/bin/sh + +set -x +set -e + +mkdir -p ~/opt + +cd ~/opt +CMAKE_VERSION=3.25.2 +CMAKE_DOWNLOAD_PACKAGE=cmake-$CMAKE_VERSION-macos-universal +wget https://github.com/Kitware/CMake/releases/download/v$CMAKE_VERSION/$CMAKE_DOWNLOAD_PACKAGE.tar.gz && + tar -zxf $CMAKE_DOWNLOAD_PACKAGE.tar.gz >/dev/null && + mv $CMAKE_DOWNLOAD_PACKAGE cmake-$CMAKE_VERSION +CMAKE_HOME=~/opt/cmake-$CMAKE_VERSION + +cd ~/opt +LLVM_VERSION=15.0.6 +LLVM_DOWNLOAD_PACKAGE=clang+llvm-$LLVM_VERSION-x86_64-apple-darwin +wget https://github.com/llvm/llvm-project/releases/download/llvmorg-$LLVM_VERSION/$LLVM_DOWNLOAD_PACKAGE.tar.xz && + tar -xf $LLVM_DOWNLOAD_PACKAGE.tar.xz >/dev/null && + mv $LLVM_DOWNLOAD_PACKAGE llvm-$LLVM_VERSION +LLVM_HOME=~/opt/llvm-$LLVM_VERSION diff --git a/app/src/main/cpp/Dobby/source/Backend/KernelMode/ExecMemory/clear-cache-tool-all.c b/app/src/main/cpp/Dobby/source/Backend/KernelMode/ExecMemory/clear-cache-tool-all.c new file mode 100644 index 0000000..495257f --- /dev/null +++ b/app/src/main/cpp/Dobby/source/Backend/KernelMode/ExecMemory/clear-cache-tool-all.c @@ -0,0 +1,3 @@ +void ClearCache(void *start, void *end) { + return; +} diff --git a/app/src/main/cpp/Dobby/source/Backend/KernelMode/ExecMemory/code-patch-tool-darwin.cc b/app/src/main/cpp/Dobby/source/Backend/KernelMode/ExecMemory/code-patch-tool-darwin.cc new file mode 100644 index 0000000..636c413 --- /dev/null +++ b/app/src/main/cpp/Dobby/source/Backend/KernelMode/ExecMemory/code-patch-tool-darwin.cc @@ -0,0 +1,57 @@ +#include "dobby/dobby_internal.h" + +#include "PlatformUnifiedInterface/ExecMemory/ClearCacheTool.h" + +#include +#include +#include +#include + +#undef max +#undef min +#include + +#define DobbySymbolResolverAuth(o_var, name) \ + do { \ + static void *func_ptr = nullptr; \ + if (func_ptr == nullptr) { \ + func_ptr = DobbySymbolResolver(nullptr, name); \ + if (func_ptr) { \ + func_ptr = ptrauth_strip((void *)func_ptr, ptrauth_key_asia); \ + func_ptr = ptrauth_sign_unauthenticated(func_ptr, ptrauth_key_asia, 0); \ + } \ + } \ + o_var = (typeof(o_var))func_ptr; \ + } while (0); + +#define KERN_RETURN_ERROR(kr, failure) \ + do { \ + if (kr != KERN_SUCCESS) { \ + ERROR_LOG("mach error: %d", kr); \ + return failure; \ + } \ + } while (0); + +PUBLIC int DobbyCodePatch(void *address, uint8_t *buffer, uint32_t buffer_size) { + if (address == nullptr || buffer == nullptr || buffer_size == 0) { + ERROR_LOG("invalid argument"); + return kMemoryOperationError; + } + + kern_return_t kr; + + { + paddr_t dst_paddr = pmap_kit_kvtophys(kernel_pmap, (vaddr_t)address); + paddr_t src_paddr = pmap_kit_kvtophys(kernel_pmap, (vaddr_t)buffer); + pmap_kit_bcopy_phys((addr_t)buffer, dst_paddr, buffer_size, cppvPsnk); + DEBUG_LOG("bcopy_phys: src: %p, dst: %p", src_paddr, dst_paddr); + + pmap_kit_kva_to_pte(kernel_pmap, (vaddr_t)address); + pmap_kit_set_perm(kernel_pmap, (vaddr_t)address, (vaddr_t)address + PAGE_SIZE, VM_PROT_READ | VM_PROT_EXECUTE); + + if (memcmp(address, buffer, buffer_size)) + return kMemoryOperationError; + } + + return 0; +} diff --git a/app/src/main/cpp/Dobby/source/Backend/KernelMode/PlatformUtil/Darwin/ProcessRuntimeUtility.cc b/app/src/main/cpp/Dobby/source/Backend/KernelMode/PlatformUtil/Darwin/ProcessRuntimeUtility.cc new file mode 100644 index 0000000..3635c7b --- /dev/null +++ b/app/src/main/cpp/Dobby/source/Backend/KernelMode/PlatformUtil/Darwin/ProcessRuntimeUtility.cc @@ -0,0 +1,133 @@ +#include "PlatformUtil/ProcessRuntimeUtility.h" + +#include + +typedef struct _loaded_kext_summary { + char name[KMOD_MAX_NAME]; + uuid_t uuid; + uint64_t address; + uint64_t size; + uint64_t version; + uint32_t loadTag; + uint32_t flags; + uint64_t reference_list; + uint64_t text_exec_address; + size_t text_exec_size; +} OSKextLoadedKextSummary; +typedef struct _loaded_kext_summary_header { + uint32_t version; + uint32_t entry_size; + uint32_t numSummaries; + uint32_t reserved; /* explicit alignment for gdb */ + OSKextLoadedKextSummary summaries[0]; +} OSKextLoadedKextSummaryHeader; + +#undef min +#undef max +#include +#include + +#include +#if defined(__LP64__) +typedef struct mach_header_64 mach_header_t; +typedef struct segment_command_64 segment_command_t; +typedef struct section_64 section_t; +typedef struct nlist_64 nlist_t; +#define LC_SEGMENT_ARCH_DEPENDENT LC_SEGMENT_64 +#else +typedef struct mach_header mach_header_t; +typedef struct segment_command segment_command_t; +typedef struct section section_t; +typedef struct nlist nlist_t; +#define LC_SEGMENT_ARCH_DEPENDENT LC_SEGMENT +#endif + +// Generate the name for an offset. +#define KERN_PARAM_OFFSET(type_, member_) __##type_##__##member_##__offset_ +#define KERN_STRUCT_OFFSET KERN_PARAM_OFFSET + +struct vm_map_links { + struct vm_map_entry *prev; + struct vm_map_entry *next; + vm_map_offset_t start; + vm_map_offset_t end; +}; + +struct vm_map_header { + struct vm_map_links links; + uint8_t placeholder_[]; +}; + +static inline vm_map_offset_t vme_start(vm_map_entry_t entry) { + uint KERN_STRUCT_OFFSET(vm_map_entry, links) = 0; + return ((vm_map_header *)((addr_t)entry + KERN_STRUCT_OFFSET(vm_map_entry, links)))->links.start; +} +static inline vm_map_entry_t vm_map_to_entry(vm_map_t map) { + return nullptr; +} +static inline vm_map_entry_t vm_map_first_entry(vm_map_t map) { + uint KERN_STRUCT_OFFSET(vm_map, hdr) = 4; + return ((vm_map_header *)((addr_t)map + KERN_STRUCT_OFFSET(vm_map, hdr)))->links.next; +} + +// --- + +static tinystl::vector regions; +const tinystl::vector &ProcessRuntimeUtility::GetProcessMemoryLayout() { + return regions; +} + +// --- + +#include + +extern "C" void *kernel_info_load_base(); +; + +tinystl::vector modules; +const tinystl::vector *ProcessRuntimeUtility::GetProcessModuleMap() { + modules.clear(); + + // brute force kernel base ? so rude :) + static void *kernel_base = nullptr; + static OSKextLoadedKextSummaryHeader *_gLoadedKextSummaries = nullptr; + if (kernel_base == nullptr) { + kernel_base = kernel_info_load_base(); + if (kernel_base == nullptr) { + ERROR_LOG("kernel base not found"); + return &modules; + } + DEBUG_LOG("kernel base at: %p", kernel_base); + + extern void *DobbyMachOSymbolResolver(void *header_, const char *symbol_name); + OSKextLoadedKextSummaryHeader **_gLoadedKextSummariesPtr; + _gLoadedKextSummariesPtr = + (typeof(_gLoadedKextSummariesPtr))DobbyMachOSymbolResolver(kernel_base, "_gLoadedKextSummaries"); + if (_gLoadedKextSummariesPtr == nullptr) { + ERROR_LOG("failed resolve gLoadedKextSummaries symbol"); + return &modules; + } + _gLoadedKextSummaries = *_gLoadedKextSummariesPtr; + DEBUG_LOG("gLoadedKextSummaries at: %p", _gLoadedKextSummaries); + } + + // only kernel + RuntimeModule module = {0}; + strncpy(module.path, "kernel", sizeof(module.path) - 1); + module.load_address = (void *)kernel_base; + modules.push_back(module); + + // kext + for (int i = 0; i < _gLoadedKextSummaries->numSummaries; ++i) { + strncpy(module.path, _gLoadedKextSummaries->summaries[i].name, sizeof(module.path) - 1); + module.load_address = (void *)_gLoadedKextSummaries->summaries[i].address; + modules.push_back(module); + } + + return &modules; +} + +RuntimeModule ProcessRuntimeUtility::GetProcessModule(const char *name) { + const tinystl::vector *modules = GetProcessModuleMap(); + return RuntimeModule{0}; +} diff --git a/app/src/main/cpp/Dobby/source/Backend/KernelMode/PlatformUtil/ProcessRuntimeUtility.h b/app/src/main/cpp/Dobby/source/Backend/KernelMode/PlatformUtil/ProcessRuntimeUtility.h new file mode 100644 index 0000000..af2df8e --- /dev/null +++ b/app/src/main/cpp/Dobby/source/Backend/KernelMode/PlatformUtil/ProcessRuntimeUtility.h @@ -0,0 +1,25 @@ +#pragma once + +#include "PlatformUnifiedInterface/MemoryAllocator.h" + +#include "UnifiedInterface/platform.h" + +typedef struct _RuntimeModule { + char path[1024]; + void *load_address; +} RuntimeModule; + +struct MemRegion : MemRange { + MemoryPermission permission; + MemRegion(addr_t addr, size_t size, MemoryPermission perm) : MemRange(addr, size), permission(perm) { + } +}; + +class ProcessRuntimeUtility { +public: + static const tinystl::vector &GetProcessMemoryLayout(); + + static const tinystl::vector *GetProcessModuleMap(); + + static RuntimeModule GetProcessModule(const char *name); +}; \ No newline at end of file diff --git a/app/src/main/cpp/Dobby/source/Backend/KernelMode/UnifiedInterface/exec_mem_placeholder.asm b/app/src/main/cpp/Dobby/source/Backend/KernelMode/UnifiedInterface/exec_mem_placeholder.asm new file mode 100644 index 0000000..137da1e --- /dev/null +++ b/app/src/main/cpp/Dobby/source/Backend/KernelMode/UnifiedInterface/exec_mem_placeholder.asm @@ -0,0 +1,10 @@ +#include + +#define PAGE_SHIFT 14 +.align PAGE_SHIFT + + .globl EXT(kernel_executable_memory_placeholder) +EXT(kernel_executable_memory_placeholder): +.rept 0x4000/4 +.long 0x41414141 +.endr \ No newline at end of file diff --git a/app/src/main/cpp/Dobby/source/Backend/KernelMode/UnifiedInterface/platform-darwin.cc b/app/src/main/cpp/Dobby/source/Backend/KernelMode/UnifiedInterface/platform-darwin.cc new file mode 100644 index 0000000..f0c217d --- /dev/null +++ b/app/src/main/cpp/Dobby/source/Backend/KernelMode/UnifiedInterface/platform-darwin.cc @@ -0,0 +1,106 @@ +#include "UnifiedInterface/platform.h" + +#include +#include +#include +#include + +// ================================================================ +// base :: OSMemory + +static int GetProtectionFromMemoryPermission(MemoryPermission access) { + switch (access) { + case MemoryPermission::kNoAccess: + return PROT_NONE; + case MemoryPermission::kRead: + return PROT_READ; + case MemoryPermission::kReadWrite: + return PROT_READ | PROT_WRITE; + case MemoryPermission::kReadWriteExecute: + return PROT_READ | PROT_WRITE | PROT_EXEC; + case MemoryPermission::kReadExecute: + return PROT_READ | PROT_EXEC; + } + UNREACHABLE(); +} + +int OSMemory::PageSize() { + return static_cast(0x4000); +} + +void *OSMemory::Allocate(size_t size, MemoryPermission access) { + return OSMemory::Allocate(size, access, nullptr); +} + +extern "C" void *kernel_executable_memory_placeholder; +void *OSMemory::Allocate(size_t size, MemoryPermission access, void *fixed_address) { + int prot = GetProtectionFromMemoryPermission(access); + + void *addr = nullptr; + int flags = VM_FLAGS_ANYWHERE; + if (fixed_address != nullptr) { + flags = VM_FLAGS_FIXED; + addr = fixed_address; + } + + // fixme: wire at pmap + if (prot & PROT_EXEC || prot == PROT_NONE) { + addr = &kernel_executable_memory_placeholder; + } else { + kern_return_t ret = mach_vm_allocate(kernel_map, (mach_vm_address_t *)&addr, size, flags); + if (ret != KERN_SUCCESS) { + panic("mach_vm_allocate"); + return nullptr; + } + ret = vm_map_wire(kernel_map, (mach_vm_address_t)addr, (mach_vm_address_t)addr + size, PROT_NONE, false); + if (ret != KERN_SUCCESS) { + panic("vm_map_wire"); + return nullptr; + } + + // make fault before at rw prot + bzero(addr, size); + { memcpy(addr, "AAAAAAAA", 8); } + + if (access == kNoAccess) { + access = kReadExecute; + } + if (!OSMemory::SetPermission((void *)addr, size, access)) { + OSMemory::Free(addr, size); + return nullptr; + } + + { + if (memcmp(addr, "AAAAAAAA", 8) != 0) { + return nullptr; + } + } + } + + return addr; +} + +bool OSMemory::Free(void *address, size_t size) { + DCHECK_EQ(0, reinterpret_cast(address) % PageSize()); + DCHECK_EQ(0, size % PageSize()); + + auto ret = mach_vm_deallocate(kernel_map, (mach_vm_address_t)address, size); + return ret == KERN_SUCCESS; +} + +bool OSMemory::Release(void *address, size_t size) { + DCHECK_EQ(0, reinterpret_cast(address) % PageSize()); + DCHECK_EQ(0, size % PageSize()); + + auto ret = mach_vm_deallocate(kernel_map, (mach_vm_address_t)address, size); + return ret == KERN_SUCCESS; +} + +bool OSMemory::SetPermission(void *address, size_t size, MemoryPermission access) { + DCHECK_EQ(0, reinterpret_cast(address) % PageSize()); + DCHECK_EQ(0, size % PageSize()); + + int prot = GetProtectionFromMemoryPermission(access); + auto ret = mach_vm_protect(kernel_map, (mach_vm_address_t)address, size, false, prot); + return ret == KERN_SUCCESS; +} diff --git a/app/src/main/cpp/Dobby/source/Backend/KernelMode/UnifiedInterface/platform.h b/app/src/main/cpp/Dobby/source/Backend/KernelMode/UnifiedInterface/platform.h new file mode 100644 index 0000000..5d8a879 --- /dev/null +++ b/app/src/main/cpp/Dobby/source/Backend/KernelMode/UnifiedInterface/platform.h @@ -0,0 +1,26 @@ +#ifndef PLATFORM_INTERFACE_COMMON_PLATFORM_H +#define PLATFORM_INTERFACE_COMMON_PLATFORM_H + +#include "dobby/common.h" + +// ================================================================ +// base :: OSMemory + +enum MemoryPermission { kNoAccess, kRead, kReadWrite, kReadWriteExecute, kReadExecute }; + +class OSMemory { +public: + static int PageSize(); + + static void *Allocate(size_t size, MemoryPermission access); + + static void *Allocate(size_t size, MemoryPermission access, void *fixed_address); + + static bool Free(void *address, size_t size); + + static bool Release(void *address, size_t size); + + static bool SetPermission(void *address, size_t size, MemoryPermission access); +}; + +#endif diff --git a/app/src/main/cpp/Dobby/source/Backend/UserMode/ExecMemory/clear-cache-tool-all.c b/app/src/main/cpp/Dobby/source/Backend/UserMode/ExecMemory/clear-cache-tool-all.c new file mode 100644 index 0000000..413ef48 --- /dev/null +++ b/app/src/main/cpp/Dobby/source/Backend/UserMode/ExecMemory/clear-cache-tool-all.c @@ -0,0 +1,145 @@ +//===-- clear_cache.c - Implement __clear_cache ---------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include +#include +#include + +#if __APPLE__ +#include +#endif + +#if defined(_WIN32) +// Forward declare Win32 APIs since the GCC mode driver does not handle the +// newer SDKs as well as needed. +uint32_t FlushInstructionCache(uintptr_t hProcess, void *lpBaseAddress, uintptr_t dwSize); +uintptr_t GetCurrentProcess(void); +#endif + +// The compiler generates calls to __clear_cache() when creating +// trampoline functions on the stack for use with nested functions. +// It is expected to invalidate the instruction cache for the +// specified range. + +void _clear_cache(void *start, void *end) { +#if __i386__ || __x86_64__ || defined(_M_IX86) || defined(_M_X64) +// Intel processors have a unified instruction and data cache +// so there is nothing to do +#elif defined(_WIN32) && (defined(__arm__) || defined(__aarch64__)) + FlushInstructionCache(GetCurrentProcess(), start, end - start); +#elif defined(__arm__) && !defined(__APPLE__) +#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) + struct arm_sync_icache_args arg; + + arg.addr = (uintptr_t)start; + arg.len = (uintptr_t)end - (uintptr_t)start; + + sysarch(ARM_SYNC_ICACHE, &arg); +#elif defined(__linux__) +// We used to include asm/unistd.h for the __ARM_NR_cacheflush define, but +// it also brought many other unused defines, as well as a dependency on +// kernel headers to be installed. +// +// This value is stable at least since Linux 3.13 and should remain so for +// compatibility reasons, warranting it's re-definition here. +#define __ARM_NR_cacheflush 0x0f0002 + register int start_reg __asm("r0") = (int)(intptr_t)start; + const register int end_reg __asm("r1") = (int)(intptr_t)end; + const register int flags __asm("r2") = 0; + const register int syscall_nr __asm("r7") = __ARM_NR_cacheflush; + __asm __volatile("svc 0x0" : "=r"(start_reg) : "r"(syscall_nr), "r"(start_reg), "r"(end_reg), "r"(flags)); + assert(start_reg == 0 && "Cache flush syscall failed."); +#else + compilerrt_abort(); +#endif +#elif defined(__linux__) && defined(__mips__) + const uintptr_t start_int = (uintptr_t)start; + const uintptr_t end_int = (uintptr_t)end; + syscall(__NR_cacheflush, start, (end_int - start_int), BCACHE); +#elif defined(__mips__) && defined(__OpenBSD__) + cacheflush(start, (uintptr_t)end - (uintptr_t)start, BCACHE); +#elif defined(__aarch64__) && !defined(__APPLE__) + uint64_t xstart = (uint64_t)(uintptr_t)start; + uint64_t xend = (uint64_t)(uintptr_t)end; + + // Get Cache Type Info. + static uint64_t ctr_el0 = 0; + if (ctr_el0 == 0) + __asm __volatile("mrs %0, ctr_el0" : "=r"(ctr_el0)); + + // The DC and IC instructions must use 64-bit registers so we don't use + // uintptr_t in case this runs in an IPL32 environment. + uint64_t addr; + + // If CTR_EL0.IDC is set, data cache cleaning to the point of unification + // is not required for instruction to data coherence. + if (((ctr_el0 >> 28) & 0x1) == 0x0) { + const size_t dcache_line_size = 4 << ((ctr_el0 >> 16) & 15); + for (addr = xstart & ~(dcache_line_size - 1); addr < xend; addr += dcache_line_size) + __asm __volatile("dc cvau, %0" ::"r"(addr)); + } + __asm __volatile("dsb ish"); + + // If CTR_EL0.DIC is set, instruction cache invalidation to the point of + // unification is not required for instruction to data coherence. + if (((ctr_el0 >> 29) & 0x1) == 0x0) { + const size_t icache_line_size = 4 << ((ctr_el0 >> 0) & 15); + for (addr = xstart & ~(icache_line_size - 1); addr < xend; addr += icache_line_size) + __asm __volatile("ic ivau, %0" ::"r"(addr)); + __asm __volatile("dsb ish"); + } + __asm __volatile("isb sy"); +#elif defined(__powerpc64__) + const size_t line_size = 32; + const size_t len = (uintptr_t)end - (uintptr_t)start; + + const uintptr_t mask = ~(line_size - 1); + const uintptr_t start_line = ((uintptr_t)start) & mask; + const uintptr_t end_line = ((uintptr_t)start + len + line_size - 1) & mask; + + for (uintptr_t line = start_line; line < end_line; line += line_size) + __asm__ volatile("dcbf 0, %0" : : "r"(line)); + __asm__ volatile("sync"); + + for (uintptr_t line = start_line; line < end_line; line += line_size) + __asm__ volatile("icbi 0, %0" : : "r"(line)); + __asm__ volatile("isync"); +#elif defined(__sparc__) + const size_t dword_size = 8; + const size_t len = (uintptr_t)end - (uintptr_t)start; + + const uintptr_t mask = ~(dword_size - 1); + const uintptr_t start_dword = ((uintptr_t)start) & mask; + const uintptr_t end_dword = ((uintptr_t)start + len + dword_size - 1) & mask; + + for (uintptr_t dword = start_dword; dword < end_dword; dword += dword_size) + __asm__ volatile("flush %0" : : "r"(dword)); +#elif defined(__riscv) && defined(__linux__) + // See: arch/riscv/include/asm/cacheflush.h, arch/riscv/kernel/sys_riscv.c + register void *start_reg __asm("a0") = start; + const register void *end_reg __asm("a1") = end; + // "0" means that we clear cache for all threads (SYS_RISCV_FLUSH_ICACHE_ALL) + const register long flags __asm("a2") = 0; + const register long syscall_nr __asm("a7") = __NR_riscv_flush_icache; + __asm __volatile("ecall" : "=r"(start_reg) : "r"(start_reg), "r"(end_reg), "r"(flags), "r"(syscall_nr)); + assert(start_reg == 0 && "Cache flush syscall failed."); +#else +#if __APPLE__ + // On Darwin, sys_icache_invalidate() provides this functionality + sys_icache_invalidate(start, end - start); +#elif defined(__ve__) + __asm__ volatile("fencec 2"); +#else + compilerrt_abort(); +#endif +#endif +} + +void ClearCache(void *start, void *end) { + return _clear_cache(start, end); +} diff --git a/app/src/main/cpp/Dobby/source/Backend/UserMode/ExecMemory/clear-cache-tool/clear-cache-tool-arm-dummy.cc b/app/src/main/cpp/Dobby/source/Backend/UserMode/ExecMemory/clear-cache-tool/clear-cache-tool-arm-dummy.cc new file mode 100644 index 0000000..abe26c4 --- /dev/null +++ b/app/src/main/cpp/Dobby/source/Backend/UserMode/ExecMemory/clear-cache-tool/clear-cache-tool-arm-dummy.cc @@ -0,0 +1,53 @@ +#ifndef USER_MODE_CLEAR_CACHE_TOOL_H +#define USER_MODE_CLEAR_CACHE_TOOL_H + +#include "core/arch/Cpu.h" + +#include "PlatformInterface/globals.h" + +#if !HOST_OS_IOS +#include // for cache flushing. +#endif + +void CpuFeatures::FlushICache(void *startp, void *endp) { + +#if HOST_OS_IOS + // Precompilation never patches code so there should be no I cache flushes. + CpuFeatures::ClearCache(startp, endp); + +#else + + register uint32_t beg asm("r0") = reinterpret_cast(startp); + register uint32_t end asm("r1") = reinterpret_cast(endp); + register uint32_t flg asm("r2") = 0; + +#ifdef __clang__ + // This variant of the asm avoids a constant pool entry, which can be + // problematic when LTO'ing. It is also slightly shorter. + register uint32_t scno asm("r7") = __ARM_NR_cacheflush; + + asm volatile("svc 0\n" : : "r"(beg), "r"(end), "r"(flg), "r"(scno) : "memory"); +#else + // Use a different variant of the asm with GCC because some versions doesn't + // support r7 as an asm input. + asm volatile( + // This assembly works for both ARM and Thumb targets. + + // Preserve r7; it is callee-saved, and GCC uses it as a frame pointer for + // Thumb targets. + " push {r7}\n" + // r0 = beg + // r1 = end + // r2 = flags (0) + " ldr r7, =%c[scno]\n" // r7 = syscall number + " svc 0\n" + + " pop {r7}\n" + : + : "r"(beg), "r"(end), "r"(flg), [scno] "i"(__ARM_NR_cacheflush) + : "memory"); +#endif +#endif +} + +#endif \ No newline at end of file diff --git a/app/src/main/cpp/Dobby/source/Backend/UserMode/ExecMemory/clear-cache-tool/clear-cache-tool-arm64-dummy.cc b/app/src/main/cpp/Dobby/source/Backend/UserMode/ExecMemory/clear-cache-tool/clear-cache-tool-arm64-dummy.cc new file mode 100644 index 0000000..60580a5 --- /dev/null +++ b/app/src/main/cpp/Dobby/source/Backend/UserMode/ExecMemory/clear-cache-tool/clear-cache-tool-arm64-dummy.cc @@ -0,0 +1,103 @@ +#ifndef USER_MODE_CLEAR_CACHE_TOOL_ARM64_H +#define USER_MODE_CLEAR_CACHE_TOOL_ARM64_H + +#include "core/arch/Cpu.h" + +#include "PlatformInterface/globals.h" + +class CacheLineSizes { +public: + CacheLineSizes() { + // Copy the content of the cache type register to a core register. + __asm__ __volatile__("mrs %x[ctr], ctr_el0" // NOLINT + : [ctr] "=r"(cache_type_register_)); + } + + uint32_t icache_line_size() const { + return ExtractCacheLineSize(0); + } + uint32_t dcache_line_size() const { + return ExtractCacheLineSize(16); + } + +private: + uint32_t ExtractCacheLineSize(int cache_line_size_shift) const { + // The cache type register holds the size of cache lines in words as a + // power of two. + return 4 << ((cache_type_register_ >> cache_line_size_shift) & 0xF); + } + + uint32_t cache_type_register_; +}; + +void CpuFeatures::FlushICache(void *startp, void *endp) { + // The code below assumes user space cache operations are allowed. The goal + // of this routine is to make sure the code generated is visible to the I + // side of the CPU. + +#if HOST_OS_IOS + // Precompilation never patches code so there should be no I cache flushes. + CpuFeatures::ClearCache(startp, endp); +#else + uintptr_t start = reinterpret_cast(startp); + // Sizes will be used to generate a mask big enough to cover a pointer. + CacheLineSizes sizes; + uintptr_t dsize = sizes.dcache_line_size(); + uintptr_t isize = sizes.icache_line_size(); + // Cache line sizes are always a power of 2. + uintptr_t dstart = start & ~(dsize - 1); + uintptr_t istart = start & ~(isize - 1); + uintptr_t end = reinterpret_cast(endp); + + __asm__ __volatile__( // NOLINT + // Clean every line of the D cache containing the target data. + "0: \n\t" + // dc : Data Cache maintenance + // c : Clean + // i : Invalidate + // va : by (Virtual) Address + // c : to the point of Coherency + // See ARM DDI 0406B page B2-12 for more information. + // We would prefer to use "cvau" (clean to the point of unification) here + // but we use "civac" to work around Cortex-A53 errata 819472, 826319, + // 827319 and 824069. + "dc civac, %[dline] \n\t" + "add %[dline], %[dline], %[dsize] \n\t" + "cmp %[dline], %[end] \n\t" + "b.lt 0b \n\t" + // Barrier to make sure the effect of the code above is visible to the rest + // of the world. + // dsb : Data Synchronisation Barrier + // ish : Inner SHareable domain + // The point of unification for an Inner Shareable shareability domain is + // the point by which the instruction and data caches of all the processors + // in that Inner Shareable shareability domain are guaranteed to see the + // same copy of a memory location. See ARM DDI 0406B page B2-12 for more + // information. + "dsb ish \n\t" + // Invalidate every line of the I cache containing the target data. + "1: \n\t" + // ic : instruction cache maintenance + // i : invalidate + // va : by address + // u : to the point of unification + "ic ivau, %[iline] \n\t" + "add %[iline], %[iline], %[isize] \n\t" + "cmp %[iline], %[end] \n\t" + "b.lt 1b \n\t" + // Barrier to make sure the effect of the code above is visible to the rest + // of the world. + "dsb ish \n\t" + // Barrier to ensure any prefetching which happened before this code is + // discarded. + // isb : Instruction Synchronisation Barrier + "isb \n\t" + : [dline] "+r"(dstart), [iline] "+r"(istart) + : [dsize] "r"(dsize), [isize] "r"(isize), [end] "r"(end) + // This code does not write to memory but without the dependency gcc might + // move this code before the code is generated. + : "cc", "memory"); // NOLINT +#endif +} + +#endif diff --git a/app/src/main/cpp/Dobby/source/Backend/UserMode/ExecMemory/code-patch-tool-darwin.cc b/app/src/main/cpp/Dobby/source/Backend/UserMode/ExecMemory/code-patch-tool-darwin.cc new file mode 100644 index 0000000..f277d72 --- /dev/null +++ b/app/src/main/cpp/Dobby/source/Backend/UserMode/ExecMemory/code-patch-tool-darwin.cc @@ -0,0 +1,172 @@ +#include "dobby/dobby_internal.h" + +#include "PlatformUnifiedInterface/ExecMemory/ClearCacheTool.h" + +#include + +#include +#include "UnifiedInterface/platform-darwin/mach_vm.h" + +#if defined(__APPLE__) +#include +#include +#endif + +#define KERN_RETURN_ERROR(kr, failure) \ + do { \ + if (kr != KERN_SUCCESS) { \ + ERROR_LOG("mach error: %s", mach_error_string(kr)); \ + return failure; \ + } \ + } while (0); + +#include + +#if defined(TARGET_ARCH_ARM64) +#define SYS_mprotect 74 +int mprotect_impl(void *addr, size_t len, int prot) { + int ret = 0; + __asm__ __volatile__("mov x16, %[_SYS_mprotect]\n" + "svc 0x80\n" + "mov %w[_ret], w0\n" + "add %w[_ret], %w[_ret], #0x0\n" + : [_ret] "=r"(ret) + : [_SYS_mprotect] "n"(SYS_mprotect) + :); + return ret; +} +#endif + +PUBLIC int DobbyCodePatch(void *address, uint8_t *buffer, uint32_t buffer_size) { + if (address == nullptr || buffer == nullptr || buffer_size == 0) { + ERROR_LOG("invalid argument"); + return -1; + } + + size_t page_size = PAGE_SIZE; + addr_t patch_page = ALIGN_FLOOR(address, page_size); + + // cross over page + if ((addr_t)address + buffer_size > patch_page + page_size) { + void *address_a = address; + uint8_t *buffer_a = buffer; + uint32_t buffer_size_a = (patch_page + page_size - (addr_t)address); + auto ret = DobbyCodePatch(address_a, buffer_a, buffer_size_a); + if (ret == -1) { + return ret; + } + + void *address_b = (void *)((addr_t)address + buffer_size_a); + uint8_t *buffer_b = buffer + buffer_size_a; + uint32_t buffer_size_b = buffer_size - buffer_size_a; + ret = DobbyCodePatch(address_b, buffer_b, buffer_size_b); + return ret; + } + + addr_t remap_dest_page = patch_page; + mach_vm_address_t remap_dummy_page = 0; + + auto self_task = mach_task_self(); + kern_return_t kr; + + int orig_prot = 0; + int orig_max_prot = 0; + int share_mode = 0; + int is_enable_remap = -1; + if (is_enable_remap == -1) { + auto get_region_info = [&](addr_t region_start) -> void { + vm_region_submap_info_64 region_submap_info; + mach_msg_type_number_t count = VM_REGION_SUBMAP_INFO_COUNT_64; + mach_vm_address_t addr = region_start; + mach_vm_size_t size = 0; + natural_t depth = 0; + while (1) { + kr = mach_vm_region_recurse(mach_task_self(), (mach_vm_address_t *)&addr, (mach_vm_size_t *)&size, &depth, + (vm_region_recurse_info_t)®ion_submap_info, &count); + if (region_submap_info.is_submap) { + depth++; + } else { + orig_prot = region_submap_info.protection; + orig_max_prot = region_submap_info.max_protection; + share_mode = region_submap_info.share_mode; + return; + } + } + }; + get_region_info(remap_dest_page); + if (orig_max_prot != 5 && share_mode != 2) { + is_enable_remap = 1; + } else { + is_enable_remap = 0; + DEBUG_LOG("code patch %p won't use remap", address); + } + } + if (is_enable_remap == 1) { + addr_t remap_dummy_page = 0; + { + kr = mach_vm_allocate(self_task, (mach_vm_address_t *)&remap_dummy_page, page_size, VM_FLAGS_ANYWHERE); + KERN_RETURN_ERROR(kr, -1); + + memcpy((void *)remap_dummy_page, (void *)patch_page, page_size); + + int offset = (int)((addr_t)address - patch_page); + memcpy((void *)(remap_dummy_page + offset), buffer, buffer_size); + + kr = mach_vm_protect(self_task, remap_dummy_page, page_size, false, VM_PROT_READ | VM_PROT_EXECUTE); + KERN_RETURN_ERROR(kr, -1); + } + + vm_prot_t prot, max_prot; + kr = mach_vm_remap(self_task, (mach_vm_address_t *)&remap_dest_page, page_size, 0, + VM_FLAGS_OVERWRITE | VM_FLAGS_FIXED, self_task, remap_dummy_page, true, &prot, &max_prot, + VM_INHERIT_COPY); + KERN_RETURN_ERROR(kr, -1); + + kr = mach_vm_deallocate(self_task, remap_dummy_page, page_size); + KERN_RETURN_ERROR(kr, -1); + } else { + + if (0) { + { + auto kr = mach_vm_allocate(self_task, &remap_dummy_page, page_size, VM_FLAGS_ANYWHERE); + KERN_RETURN_ERROR(kr, -1); + + kr = mach_vm_deallocate(self_task, remap_dummy_page, page_size); + KERN_RETURN_ERROR(kr, -1); + } + + vm_prot_t prot, max_prot; + kr = mach_vm_remap(self_task, &remap_dummy_page, page_size, 0, VM_FLAGS_ANYWHERE, self_task, remap_dest_page, + false, &prot, &max_prot, VM_INHERIT_SHARE); + KERN_RETURN_ERROR(kr, -1); + + kr = mach_vm_protect(self_task, remap_dummy_page, page_size, false, VM_PROT_READ | VM_PROT_WRITE); + // the kr always return KERN_PROTECTION_FAILURE + kr = KERN_PROTECTION_FAILURE; + + memcpy((void *)(remap_dummy_page + ((uint64_t)address - remap_dest_page)), buffer, buffer_size); + } + + static __typeof(vm_protect) *vm_protect_impl = nullptr; + if (vm_protect_impl == nullptr) { + vm_protect_impl = (__typeof(vm_protect) *)DobbySymbolResolver("dyld", "vm_protect"); + if (vm_protect_impl == nullptr) { + vm_protect_impl = (__typeof(vm_protect) *)DobbySymbolResolver("libsystem_kernel.dylib", "_vm_protect"); + } + vm_protect_impl = (__typeof(vm_protect) *)pac_sign((void *)vm_protect_impl); + } + { + kr = vm_protect_impl(self_task, remap_dest_page, page_size, false, VM_PROT_READ | VM_PROT_WRITE | VM_PROT_COPY); + KERN_RETURN_ERROR(kr, -1); + + memcpy((void *)(patch_page + ((uint64_t)address - remap_dest_page)), buffer, buffer_size); + + kr = vm_protect_impl(self_task, remap_dest_page, page_size, false, orig_prot); + KERN_RETURN_ERROR(kr, -1); + } + } + + ClearCache(address, (void *)((addr_t)address + buffer_size)); + + return 0; +} diff --git a/app/src/main/cpp/Dobby/source/Backend/UserMode/ExecMemory/code-patch-tool-posix.cc b/app/src/main/cpp/Dobby/source/Backend/UserMode/ExecMemory/code-patch-tool-posix.cc new file mode 100644 index 0000000..bfe7361 --- /dev/null +++ b/app/src/main/cpp/Dobby/source/Backend/UserMode/ExecMemory/code-patch-tool-posix.cc @@ -0,0 +1,37 @@ + +#include "dobby/dobby_internal.h" +#include "core/arch/Cpu.h" + +#include +#include +#include + +#if !defined(__APPLE__) +PUBLIC int DobbyCodePatch(void *address, uint8_t *buffer, uint32_t buffer_size) { +#if defined(__ANDROID__) || defined(__linux__) + int page_size = (int)sysconf(_SC_PAGESIZE); + uintptr_t patch_page = ALIGN_FLOOR(address, page_size); + uintptr_t patch_end_page = ALIGN_FLOOR((uintptr_t)address + buffer_size, page_size); + + // change page permission as rwx + mprotect((void *)patch_page, page_size, PROT_READ | PROT_WRITE | PROT_EXEC); + if (patch_page != patch_end_page) { + mprotect((void *)patch_end_page, page_size, PROT_READ | PROT_WRITE | PROT_EXEC); + } + + // patch buffer + memcpy(address, buffer, buffer_size); + + // restore page permission + mprotect((void *)patch_page, page_size, PROT_READ | PROT_EXEC); + if (patch_page != patch_end_page) { + mprotect((void *)patch_end_page, page_size, PROT_READ | PROT_EXEC); + } + + addr_t clear_start_ = (addr_t)address; + ClearCache((void *)clear_start_, (void *)(clear_start_ + buffer_size)); +#endif + return 0; +} + +#endif \ No newline at end of file diff --git a/app/src/main/cpp/Dobby/source/Backend/UserMode/ExecMemory/code-patch-tool-windows.cc b/app/src/main/cpp/Dobby/source/Backend/UserMode/ExecMemory/code-patch-tool-windows.cc new file mode 100644 index 0000000..471a467 --- /dev/null +++ b/app/src/main/cpp/Dobby/source/Backend/UserMode/ExecMemory/code-patch-tool-windows.cc @@ -0,0 +1,27 @@ +#include "dobby/dobby_internal.h" + +#include + +using namespace zz; + +PUBLIC int DobbyCodePatch(void *address, uint8_t *buffer, uint32_t buffer_size) { + DWORD oldProtect; + int page_size; + + // Get page size + SYSTEM_INFO si; + GetSystemInfo(&si); + page_size = si.dwPageSize; + + void *addressPageAlign = (void *)ALIGN(address, page_size); + + if (!VirtualProtect(addressPageAlign, page_size, PAGE_EXECUTE_READWRITE, &oldProtect)) + return kMemoryOperationError; + + memcpy(address, buffer, buffer_size); + + if (!VirtualProtect(addressPageAlign, page_size, oldProtect, &oldProtect)) + return kMemoryOperationError; + + return 0; +} diff --git a/app/src/main/cpp/Dobby/source/Backend/UserMode/ExecMemory/substrated/mach_interface_support/substrated.defs b/app/src/main/cpp/Dobby/source/Backend/UserMode/ExecMemory/substrated/mach_interface_support/substrated.defs new file mode 100644 index 0000000..3871f7a --- /dev/null +++ b/app/src/main/cpp/Dobby/source/Backend/UserMode/ExecMemory/substrated/mach_interface_support/substrated.defs @@ -0,0 +1,27 @@ +/* + * Regenerate with: + * + * $(xcrun --sdk macosx -f mig) \ + * -isysroot $(xcrun --sdk macosx --show-sdk-path) \ + * -sheader substratedserver.h \ + * -server substratedserver.c \ + * -header substratedclient.h \ + * -user substratedclient.c \ + * substrated.defs + */ + +subsystem substrated 9000; + +#include +#include + +routine substrated_mark(server + : mach_port_t; + task + : vm_task_entry_t; + source_address + : mach_vm_address_t; + source_size + : mach_vm_size_t; + inout target_address + : mach_vm_address_t); diff --git a/app/src/main/cpp/Dobby/source/Backend/UserMode/MultiThreadSupport/ThreadSupport.cpp b/app/src/main/cpp/Dobby/source/Backend/UserMode/MultiThreadSupport/ThreadSupport.cpp new file mode 100644 index 0000000..30be99c --- /dev/null +++ b/app/src/main/cpp/Dobby/source/Backend/UserMode/MultiThreadSupport/ThreadSupport.cpp @@ -0,0 +1,22 @@ +#include "MultiThreadSupport/ThreadSupport.h" + +using namespace zz; + +OSThread::LocalStorageKey ThreadSupport::thread_callstack_key_ = 0; + +// Get current CallStack +CallStack *ThreadSupport::CurrentThreadCallStack() { + + // TODO: __attribute__((destructor)) is better ? + if (!thread_callstack_key_) { + thread_callstack_key_ = OSThread::CreateThreadLocalKey(); + } + + if (OSThread::HasThreadLocal(thread_callstack_key_)) { + return static_cast(OSThread::GetThreadLocal(thread_callstack_key_)); + } else { + CallStack *callstack = new CallStack(); + OSThread::SetThreadLocal(thread_callstack_key_, callstack); + return callstack; + } +} diff --git a/app/src/main/cpp/Dobby/source/Backend/UserMode/MultiThreadSupport/ThreadSupport.h b/app/src/main/cpp/Dobby/source/Backend/UserMode/MultiThreadSupport/ThreadSupport.h new file mode 100644 index 0000000..ed02a79 --- /dev/null +++ b/app/src/main/cpp/Dobby/source/Backend/UserMode/MultiThreadSupport/ThreadSupport.h @@ -0,0 +1,63 @@ +#ifndef USER_MODE_MULTI_THREAD_SUPPORT_H +#define USER_MODE_MULTI_THREAD_SUPPORT_H + +#include +#include + +#include "dobby/dobby_internal.h" + +#include "source/Backend/UserMode/Thread/PlatformThread.h" + +// StackFrame base in CallStack +typedef struct _StackFrame { + // context between `pre_call` and `post_call` + std::map kv_context; + // origin function ret address + void *orig_ret; +} StackFrame; + +// (thead) CallStack base in thread +typedef struct _CallStack { + tinystl::vector stackframes; +} CallStack; + +// ThreadSupport base on vm_core, support mutipl platforms. +class ThreadSupport { +public: + // Push stack frame + static void PushStackFrame(StackFrame *stackframe) { + CallStack *callstack = ThreadSupport::CurrentThreadCallStack(); + callstack->stackframes.push_back(stackframe); + } + + // Pop stack frame + static StackFrame *PopStackFrame() { + CallStack *callstack = ThreadSupport::CurrentThreadCallStack(); + StackFrame *stackframe = callstack->stackframes.back(); + callstack->stackframes.pop_back(); + return stackframe; + } + + // ===== + static void SetStackFrameContextValue(StackFrame *stackframe, char *key, void *value) { + std::map *kv_context = &stackframe->kv_context; + kv_context->insert(std::pair(key, value)); + }; + + static void *GetStackFrameContextValue(StackFrame *stackframe, char *key) { + std::map kv_context = stackframe->kv_context; + std::map::iterator it; + it = kv_context.find(key); + if (it != kv_context.end()) { + return (void *)it->second; + } + return NULL; + }; + + static CallStack *CurrentThreadCallStack(); + +private: + static zz::OSThread::LocalStorageKey thread_callstack_key_; +}; + +#endif diff --git a/app/src/main/cpp/Dobby/source/Backend/UserMode/PlatformUtil/Darwin/ProcessRuntimeUtility.cc b/app/src/main/cpp/Dobby/source/Backend/UserMode/PlatformUtil/Darwin/ProcessRuntimeUtility.cc new file mode 100644 index 0000000..1046221 --- /dev/null +++ b/app/src/main/cpp/Dobby/source/Backend/UserMode/PlatformUtil/Darwin/ProcessRuntimeUtility.cc @@ -0,0 +1,139 @@ +#include "dobby/dobby_internal.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "UnifiedInterface/platform-darwin/mach_vm.h" +#include "PlatformUtil/ProcessRuntimeUtility.h" + +static bool memory_region_comparator(MemRegion a, MemRegion b) { + return (a.start < b.start); +} + +tinystl::vector regions; + +const tinystl::vector &ProcessRuntimeUtility::GetProcessMemoryLayout() { + regions.clear(); + + vm_region_submap_info_64 region_submap_info; + mach_msg_type_number_t count = VM_REGION_SUBMAP_INFO_COUNT_64; + mach_vm_address_t addr = 0; + mach_vm_size_t size = 0; + natural_t depth = 0; + while (true) { + count = VM_REGION_SUBMAP_INFO_COUNT_64; + kern_return_t kr = mach_vm_region_recurse(mach_task_self(), (mach_vm_address_t *)&addr, (mach_vm_size_t *)&size, + &depth, (vm_region_recurse_info_t)®ion_submap_info, &count); + if (kr != KERN_SUCCESS) { + if (kr == KERN_INVALID_ADDRESS) { + break; + } else { + break; + } + } + + if (region_submap_info.is_submap) { + depth++; + } else { + MemoryPermission permission; + if ((region_submap_info.protection & PROT_READ) && (region_submap_info.protection & PROT_WRITE)) { + permission = MemoryPermission::kReadWrite; + } else if ((region_submap_info.protection & PROT_READ) == region_submap_info.protection) { + permission = MemoryPermission::kRead; + } else if ((region_submap_info.protection & PROT_READ) && (region_submap_info.protection & PROT_EXEC)) { + permission = MemoryPermission::kReadExecute; + } else { + permission = MemoryPermission::kNoAccess; + } +#if 0 + DEBUG_LOG("%p --- %p", addr, addr + size); +#endif + MemRegion region = MemRegion(addr, size, permission); + regions.push_back(region); + addr += size; + } + } + + // std::sort(ProcessMemoryLayout.begin(), ProcessMemoryLayout.end(), memory_region_comparator); + + return regions; +} + +static tinystl::vector *modules; + +const tinystl::vector &ProcessRuntimeUtility::GetProcessModuleMap() { + if (modules == nullptr) { + modules = new tinystl::vector(); + } + modules->clear(); + + kern_return_t kr; + task_dyld_info_data_t task_dyld_info; + mach_msg_type_number_t count = TASK_DYLD_INFO_COUNT; + kr = task_info(mach_task_self_, TASK_DYLD_INFO, (task_info_t)&task_dyld_info, &count); + if (kr != KERN_SUCCESS) { + return *modules; + } + + struct dyld_all_image_infos *infos = (struct dyld_all_image_infos *)task_dyld_info.all_image_info_addr; + const struct dyld_image_info *infoArray = infos->infoArray; + uint32_t infoArrayCount = infos->infoArrayCount; + + RuntimeModule module = {0}; + strncpy(module.path, "dummy-placeholder-module", sizeof(module.path) - 1); + module.load_address = 0; + modules->push_back(module); + + strncpy(module.path, infos->dyldPath, sizeof(module.path) - 1); + module.load_address = (void *)infos->dyldImageLoadAddress; + modules->push_back(module); + + for (int i = 0; i < infoArrayCount; ++i) { + const struct dyld_image_info *info = &infoArray[i]; + + { + strncpy(module.path, info->imageFilePath, sizeof(module.path) - 1); + module.load_address = (void *)info->imageLoadAddress; + modules->push_back(module); + } + } + + modules->sort([](const RuntimeModule &a, const RuntimeModule &b) -> int { return a.load_address < b.load_address; }); + + return *modules; +} + +RuntimeModule ProcessRuntimeUtility::GetProcessModule(const char *name) { + auto modules = GetProcessModuleMap(); + for (auto module : modules) { + if (strstr(module.path, name) != 0) { + return module; + } + } + return RuntimeModule{0}; +} diff --git a/app/src/main/cpp/Dobby/source/Backend/UserMode/PlatformUtil/Linux/ProcessRuntimeUtility.cc b/app/src/main/cpp/Dobby/source/Backend/UserMode/PlatformUtil/Linux/ProcessRuntimeUtility.cc new file mode 100644 index 0000000..862c29f --- /dev/null +++ b/app/src/main/cpp/Dobby/source/Backend/UserMode/PlatformUtil/Linux/ProcessRuntimeUtility.cc @@ -0,0 +1,237 @@ +#include "PlatformUtil/ProcessRuntimeUtility.h" + +#include +#include +#include +#include + +#include +#include + +#include +#include + +#define LINE_MAX 2048 + +// ================================================================ +// GetProcessMemoryLayout + +static bool memory_region_comparator(MemRange a, MemRange b) { + return (a.start < b.start); +} + +tinystl::vector regions; +const tinystl::vector &ProcessRuntimeUtility::GetProcessMemoryLayout() { + regions.clear(); + + FILE *fp = fopen("/proc/self/maps", "r"); + if (fp == nullptr) + return regions; + + while (!feof(fp)) { + char line_buffer[LINE_MAX + 1]; + fgets(line_buffer, LINE_MAX, fp); + + // ignore the rest of characters + if (strlen(line_buffer) == LINE_MAX && line_buffer[LINE_MAX] != '\n') { + // Entry not describing executable data. Skip to end of line to set up + // reading the next entry. + int c; + do { + c = getc(fp); + } while ((c != EOF) && (c != '\n')); + if (c == EOF) + break; + } + + addr_t region_start, region_end; + addr_t region_offset; + char permissions[5] = {'\0'}; // Ensure NUL-terminated string. + uint8_t dev_major = 0; + uint8_t dev_minor = 0; + long inode = 0; + int path_index = 0; + + // Sample format from man 5 proc: + // + // address perms offset dev inode pathname + // 08048000-08056000 r-xp 00000000 03:0c 64593 /usr/sbin/gpm + // + // The final %n term captures the offset in the input string, which is used + // to determine the path name. It *does not* increment the return value. + // Refer to man 3 sscanf for details. + if (sscanf(line_buffer, + "%" PRIxPTR "-%" PRIxPTR " %4c " + "%" PRIxPTR " %hhx:%hhx %ld %n", + ®ion_start, ®ion_end, permissions, ®ion_offset, &dev_major, &dev_minor, &inode, + &path_index) < 7) { + ERROR_LOG("/proc/self/maps parse failed!"); + fclose(fp); + return regions; + } + + MemoryPermission permission; + if (permissions[0] == 'r' && permissions[1] == 'w') { + permission = MemoryPermission::kReadWrite; + } else if (permissions[0] == 'r' && permissions[2] == 'x') { + permission = MemoryPermission::kReadExecute; + } else if (permissions[0] == 'r' && permissions[1] == 'w' && permissions[2] == 'x') { + permission = MemoryPermission::kReadWriteExecute; + } else { + permission = MemoryPermission::kNoAccess; + } + +#if 0 + DEBUG_LOG("%p --- %p", region_start, region_end); +#endif + + MemRegion region = MemRegion(region_start, region_end - region_start, permission); + regions.push_back(region); + } + std::sort(regions.begin(), regions.end(), memory_region_comparator); + + fclose(fp); + return regions; +} + +// ================================================================ +// GetProcessModuleMap + +static tinystl::vector *modules; +static tinystl::vector &get_process_map_with_proc_maps() { + if (modules == nullptr) { + modules = new tinystl::vector(); + } + + FILE *fp = fopen("/proc/self/maps", "r"); + if (fp == nullptr) + return *modules; + + while (!feof(fp)) { + char line_buffer[LINE_MAX + 1]; + fgets(line_buffer, LINE_MAX, fp); + + // ignore the rest of characters + if (strlen(line_buffer) == LINE_MAX && line_buffer[LINE_MAX] != '\n') { + // Entry not describing executable data. Skip to end of line to set up + // reading the next entry. + int c; + do { + c = getc(fp); + } while ((c != EOF) && (c != '\n')); + if (c == EOF) + break; + } + + addr_t region_start, region_end; + addr_t region_offset; + char permissions[5] = {'\0'}; // Ensure NUL-terminated string. + uint8_t dev_major = 0; + uint8_t dev_minor = 0; + long inode = 0; + int path_index = 0; + + // Sample format from man 5 proc: + // + // address perms offset dev inode pathname + // 08048000-08056000 r-xp 00000000 03:0c 64593 /usr/sbin/gpm + // + // The final %n term captures the offset in the input string, which is used + // to determine the path name. It *does not* increment the return value. + // Refer to man 3 sscanf for details. + if (sscanf(line_buffer, + "%" PRIxPTR "-%" PRIxPTR " %4c " + "%" PRIxPTR " %hhx:%hhx %ld %n", + ®ion_start, ®ion_end, permissions, ®ion_offset, &dev_major, &dev_minor, &inode, + &path_index) < 7) { + ERROR_LOG("/proc/self/maps parse failed!"); + fclose(fp); + return *modules; + } + + // check header section permission + if (strcmp(permissions, "r--p") != 0 && strcmp(permissions, "r-xp") != 0) + continue; + + // check elf magic number + ElfW(Ehdr) *header = (ElfW(Ehdr) *)region_start; + if (memcmp(header->e_ident, ELFMAG, SELFMAG) != 0) { + continue; + } + + char *path_buffer = line_buffer + path_index; + if (*path_buffer == 0 || *path_buffer == '\n' || *path_buffer == '[') + continue; + RuntimeModule module; + + // strip + if (path_buffer[strlen(path_buffer) - 1] == '\n') { + path_buffer[strlen(path_buffer) - 1] = 0; + } + strncpy(module.path, path_buffer, sizeof(module.path) - 1); + module.load_address = (void *)region_start; + modules->push_back(module); + +#if 0 + DEBUG_LOG("module: %s", module.path); +#endif + } + + fclose(fp); + return *modules; +} + +#if defined(__LP64__) +static tinystl::vector get_process_map_with_linker_iterator() { + tinystl::vector ProcessModuleMap; + + static int (*dl_iterate_phdr_ptr)(int (*)(struct dl_phdr_info *, size_t, void *), void *); + dl_iterate_phdr_ptr = (__typeof(dl_iterate_phdr_ptr))dlsym(RTLD_DEFAULT, "dl_iterate_phdr"); + if (dl_iterate_phdr_ptr == NULL) { + return ProcessModuleMap; + } + + dl_iterate_phdr_ptr( + [](dl_phdr_info *info, size_t size, void *data) { + RuntimeModule module = {0}; + if (info->dlpi_name && info->dlpi_name[0] == '/') + strcpy(module.path, info->dlpi_name); + + module.load_address = (void *)info->dlpi_addr; + for (size_t i = 0; i < info->dlpi_phnum; ++i) { + if (info->dlpi_phdr[i].p_type == PT_LOAD) { + uintptr_t load_bias = (info->dlpi_phdr[i].p_vaddr - info->dlpi_phdr[i].p_offset); + module.load_address = (void *)((addr_t)module.load_address + load_bias); + break; + } + } + + // push to vector + auto ProcessModuleMap = reinterpret_cast *>(data); + ProcessModuleMap->push_back(module); + return 0; + }, + (void *)&ProcessModuleMap); + + return ProcessModuleMap; +} +#endif + +const tinystl::vector &ProcessRuntimeUtility::GetProcessModuleMap() { +#if defined(__LP64__) && 0 + // TODO: won't resolve main binary + return get_process_map_with_linker_iterator(); +#else + return get_process_map_with_proc_maps(); +#endif +} + +RuntimeModule ProcessRuntimeUtility::GetProcessModule(const char *name) { + auto modules = GetProcessModuleMap(); + for (auto module : modules) { + if (strstr(module.path, name) != 0) { + return module; + } + } + return RuntimeModule{0}; +} \ No newline at end of file diff --git a/app/src/main/cpp/Dobby/source/Backend/UserMode/PlatformUtil/ProcessRuntimeUtility.h b/app/src/main/cpp/Dobby/source/Backend/UserMode/PlatformUtil/ProcessRuntimeUtility.h new file mode 100644 index 0000000..f861d7a --- /dev/null +++ b/app/src/main/cpp/Dobby/source/Backend/UserMode/PlatformUtil/ProcessRuntimeUtility.h @@ -0,0 +1,26 @@ +#pragma once + +#include "PlatformUnifiedInterface/MemoryAllocator.h" + +#include "UnifiedInterface/platform.h" + +typedef struct _RuntimeModule { + char path[1024]; + void *load_address; +} RuntimeModule; + +struct MemRegion : MemRange { + MemoryPermission permission; + + MemRegion(addr_t addr, size_t size, MemoryPermission perm) : MemRange(addr, size), permission(perm) { + } +}; + +class ProcessRuntimeUtility { +public: + static const tinystl::vector &GetProcessMemoryLayout(); + + static const tinystl::vector &GetProcessModuleMap(); + + static RuntimeModule GetProcessModule(const char *name); +}; \ No newline at end of file diff --git a/app/src/main/cpp/Dobby/source/Backend/UserMode/PlatformUtil/Windows/ProcessRuntimeUtility.cc b/app/src/main/cpp/Dobby/source/Backend/UserMode/PlatformUtil/Windows/ProcessRuntimeUtility.cc new file mode 100644 index 0000000..632bfc5 --- /dev/null +++ b/app/src/main/cpp/Dobby/source/Backend/UserMode/PlatformUtil/Windows/ProcessRuntimeUtility.cc @@ -0,0 +1,81 @@ +#include "PlatformUtil/ProcessRuntimeUtility.h" + +#include + +#include + +#define LINE_MAX 2048 + +// ================================================================ +// GetProcessMemoryLayout + +static bool memory_region_comparator(MemRange a, MemRange b) { + return (a.address > b.address); +} + +// https://gist.github.com/jedwardsol/9d4fe1fd806043a5767affbd200088ca + +tinystl::vector ProcessMemoryLayout; +tinystl::vector ProcessRuntimeUtility::GetProcessMemoryLayout() { + if (!ProcessMemoryLayout.empty()) { + ProcessMemoryLayout.clear(); + } + + char *address{nullptr}; + MEMORY_BASIC_INFORMATION region; + + while (VirtualQuery(address, ®ion, sizeof(region))) { + address += region.RegionSize; + if (!(region.State & (MEM_COMMIT | MEM_RESERVE))) { + continue; + } + + MemoryPermission permission = MemoryPermission::kNoAccess; + auto mask = PAGE_GUARD | PAGE_NOCACHE | PAGE_WRITECOMBINE; + switch (region.Protect & ~mask) { + case PAGE_NOACCESS: + case PAGE_READONLY: + break; + + case PAGE_EXECUTE: + case PAGE_EXECUTE_READ: + permission = MemoryPermission::kReadExecute; + break; + + case PAGE_READWRITE: + case PAGE_WRITECOPY: + permission = MemoryPermission::kReadWrite; + break; + + case PAGE_EXECUTE_READWRITE: + case PAGE_EXECUTE_WRITECOPY: + permission = MemoryPermission::kReadWriteExecute; + break; + } + + ProcessMemoryLayout.push_back(MemRange{(void *)region.BaseAddress, region.RegionSize, permission}); + } + return ProcessMemoryLayout; +} + +// ================================================================ +// GetProcessModuleMap + +tinystl::vector ProcessModuleMap; + +tinystl::vector ProcessRuntimeUtility::GetProcessModuleMap() { + if (!ProcessMemoryLayout.empty()) { + ProcessMemoryLayout.clear(); + } + return ProcessModuleMap; +} + +RuntimeModule ProcessRuntimeUtility::GetProcessModule(const char *name) { + tinystl::vector ProcessModuleMap = GetProcessModuleMap(); + for (auto module : ProcessModuleMap) { + if (strstr(module.path, name) != 0) { + return module; + } + } + return RuntimeModule{0}; +} \ No newline at end of file diff --git a/app/src/main/cpp/Dobby/source/Backend/UserMode/Thread/PlatformThread.cc b/app/src/main/cpp/Dobby/source/Backend/UserMode/Thread/PlatformThread.cc new file mode 100644 index 0000000..827d125 --- /dev/null +++ b/app/src/main/cpp/Dobby/source/Backend/UserMode/Thread/PlatformThread.cc @@ -0,0 +1,19 @@ +#include "./PlatformThread.h" + +namespace zz { +int OSThread::GetThreadLocalInt(LocalStorageKey key) { + return static_cast(reinterpret_cast(GetThreadLocal(key))); +} + +void OSThread::SetThreadLocalInt(LocalStorageKey key, int value) { + SetThreadLocal(key, reinterpret_cast(static_cast(value))); +} + +bool OSThread::HasThreadLocal(LocalStorageKey key) { + return GetThreadLocal(key) != nullptr; +} + +void *OSThread::GetExistingThreadLocal(LocalStorageKey key) { + return GetThreadLocal(key); +} +} // namespace zz \ No newline at end of file diff --git a/app/src/main/cpp/Dobby/source/Backend/UserMode/Thread/PlatformThread.h b/app/src/main/cpp/Dobby/source/Backend/UserMode/Thread/PlatformThread.h new file mode 100644 index 0000000..5a46c6c --- /dev/null +++ b/app/src/main/cpp/Dobby/source/Backend/UserMode/Thread/PlatformThread.h @@ -0,0 +1,32 @@ +#pragma once + +#include "dobby/common.h" + +namespace zz { + +class OSThread { +public: + typedef int LocalStorageKey; + + static int GetCurrentProcessId(); + + static int GetCurrentThreadId(); + + static LocalStorageKey CreateThreadLocalKey(); + + static void DeleteThreadLocalKey(LocalStorageKey key); + + static void *GetThreadLocal(LocalStorageKey key); + + static int GetThreadLocalInt(LocalStorageKey key); + + static void SetThreadLocal(LocalStorageKey key, void *value); + + static void SetThreadLocalInt(LocalStorageKey key, int value); + + static bool HasThreadLocal(LocalStorageKey key); + + static void *GetExistingThreadLocal(LocalStorageKey key); +}; + +} // namespace zz \ No newline at end of file diff --git a/app/src/main/cpp/Dobby/source/Backend/UserMode/Thread/platform-thread-posix.cc b/app/src/main/cpp/Dobby/source/Backend/UserMode/Thread/platform-thread-posix.cc new file mode 100644 index 0000000..486618c --- /dev/null +++ b/app/src/main/cpp/Dobby/source/Backend/UserMode/Thread/platform-thread-posix.cc @@ -0,0 +1,71 @@ +#include "Thread/PlatformThread.h" + +#include // getpid +#include // pthread +#include + +using namespace zz; + +int OSThread::GetCurrentProcessId() { + return static_cast(getpid()); +} + +int OSThread::GetCurrentThreadId() { +#if defined(__APPLE__) + return static_cast(pthread_mach_thread_np(pthread_self())); +#elif defined(__ANDROID__) + return static_cast(gettid()); +#elif defined(__linux__) + return static_cast(syscall(__NR_gettid)); +#else + return static_cast(reinterpret_cast(pthread_self())); +#endif +} + +static OSThread::LocalStorageKey PthreadKeyToLocalKey(pthread_key_t pthread_key) { +#if defined(__cygwin__) + // We need to cast pthread_key_t to OSThread::LocalStorageKey in two steps + // because pthread_key_t is a pointer type on Cygwin. This will probably not + // work on 64-bit platforms, but Cygwin doesn't support 64-bit anyway. + assert(sizeof(OSThread::LocalStorageKey) == sizeof(pthread_key_t)); + intptr_t ptr_key = reinterpret_cast(pthread_key); + return static_cast(ptr_key); +#else + return static_cast(pthread_key); +#endif +} + +static pthread_key_t LocalKeyToPthreadKey(OSThread::LocalStorageKey local_key) { +#if defined(__cygwin__) + assert(sizeof(OSThread::LocalStorageKey) == sizeof(pthread_key_t)); + intptr_t ptr_key = static_cast(local_key); + return reinterpret_cast(ptr_key); +#else + return static_cast(local_key); +#endif +} + +OSThread::LocalStorageKey OSThread::CreateThreadLocalKey() { + pthread_key_t key; + int result = pthread_key_create(&key, nullptr); + DCHECK_EQ(0, result); + LocalStorageKey local_key = PthreadKeyToLocalKey(key); + return local_key; +} + +void OSThread::DeleteThreadLocalKey(LocalStorageKey key) { + pthread_key_t pthread_key = LocalKeyToPthreadKey(key); + int result = pthread_key_delete(pthread_key); + DCHECK_EQ(0, result); +} + +void *OSThread::GetThreadLocal(LocalStorageKey key) { + pthread_key_t pthread_key = LocalKeyToPthreadKey(key); + return pthread_getspecific(pthread_key); +} + +void OSThread::SetThreadLocal(LocalStorageKey key, void *value) { + pthread_key_t pthread_key = LocalKeyToPthreadKey(key); + int result = pthread_setspecific(pthread_key, value); + DCHECK_EQ(0, result); +} diff --git a/app/src/main/cpp/Dobby/source/Backend/UserMode/Thread/platform-thread-windows.cc b/app/src/main/cpp/Dobby/source/Backend/UserMode/Thread/platform-thread-windows.cc new file mode 100644 index 0000000..1428bb0 --- /dev/null +++ b/app/src/main/cpp/Dobby/source/Backend/UserMode/Thread/platform-thread-windows.cc @@ -0,0 +1,25 @@ +#include "PlatformThread.h" + +using namespace zz; + +int OSThread::GetCurrentProcessId() { + return 0; +} + +int OSThread::GetCurrentThreadId() { + return 0; +} + +OSThread::LocalStorageKey OSThread::CreateThreadLocalKey() { + return 0; +} + +void OSThread::DeleteThreadLocalKey(LocalStorageKey key) { +} + +void *OSThread::GetThreadLocal(LocalStorageKey key) { + return NULL; +} + +void OSThread::SetThreadLocal(LocalStorageKey key, void *value) { +} diff --git a/app/src/main/cpp/Dobby/source/Backend/UserMode/UnifiedInterface/platform-darwin/mach_vm.h b/app/src/main/cpp/Dobby/source/Backend/UserMode/UnifiedInterface/platform-darwin/mach_vm.h new file mode 100644 index 0000000..a9cab32 --- /dev/null +++ b/app/src/main/cpp/Dobby/source/Backend/UserMode/UnifiedInterface/platform-darwin/mach_vm.h @@ -0,0 +1,933 @@ +#ifndef _mach_vm_user_ +#define _mach_vm_user_ + +/* Module mach_vm */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* BEGIN MIG_STRNCPY_ZEROFILL CODE */ + +#if defined(__has_include) +#if __has_include() +#ifndef USING_MIG_STRNCPY_ZEROFILL +#define USING_MIG_STRNCPY_ZEROFILL +#endif +#ifndef __MIG_STRNCPY_ZEROFILL_FORWARD_TYPE_DECLS__ +#define __MIG_STRNCPY_ZEROFILL_FORWARD_TYPE_DECLS__ +#ifdef __cplusplus +extern "C" { +#endif +extern int mig_strncpy_zerofill(char *dest, const char *src, int len) __attribute__((weak_import)); +#ifdef __cplusplus +} +#endif +#endif /* __MIG_STRNCPY_ZEROFILL_FORWARD_TYPE_DECLS__ */ +#endif /* __has_include() */ +#endif /* __has_include */ + +/* END MIG_STRNCPY_ZEROFILL CODE */ + +#ifdef AUTOTEST +#ifndef FUNCTION_PTR_T +#define FUNCTION_PTR_T +typedef void (*function_ptr_t)(mach_port_t, char *, mach_msg_type_number_t); +typedef struct { + char *name; + function_ptr_t function; +} function_table_entry; +typedef function_table_entry *function_table_t; +#endif /* FUNCTION_PTR_T */ +#endif /* AUTOTEST */ + +#ifndef mach_vm_MSG_COUNT +#define mach_vm_MSG_COUNT 20 +#endif /* mach_vm_MSG_COUNT */ + +#include +#include +#include +#include + +#ifdef __BeforeMigUserHeader +__BeforeMigUserHeader +#endif /* __BeforeMigUserHeader */ + +#include + + __BEGIN_DECLS + +/* Routine mach_vm_allocate */ +#ifdef mig_external + mig_external +#else +extern +#endif /* mig_external */ + kern_return_t + mach_vm_allocate(vm_map_t target, mach_vm_address_t *address, mach_vm_size_t size, int flags); + +/* Routine mach_vm_deallocate */ +#ifdef mig_external +mig_external +#else +extern +#endif /* mig_external */ + kern_return_t + mach_vm_deallocate(vm_map_t target, mach_vm_address_t address, mach_vm_size_t size); + +/* Routine mach_vm_protect */ +#ifdef mig_external +mig_external +#else +extern +#endif /* mig_external */ + kern_return_t + mach_vm_protect(vm_map_t target_task, mach_vm_address_t address, mach_vm_size_t size, boolean_t set_maximum, + vm_prot_t new_protection); + +/* Routine mach_vm_inherit */ +#ifdef mig_external +mig_external +#else +extern +#endif /* mig_external */ + kern_return_t + mach_vm_inherit(vm_map_t target_task, mach_vm_address_t address, mach_vm_size_t size, vm_inherit_t new_inheritance); + +/* Routine mach_vm_read */ +#ifdef mig_external +mig_external +#else +extern +#endif /* mig_external */ + kern_return_t + mach_vm_read(vm_map_t target_task, mach_vm_address_t address, mach_vm_size_t size, vm_offset_t *data, + mach_msg_type_number_t *dataCnt); + +/* Routine mach_vm_read_list */ +#ifdef mig_external +mig_external +#else +extern +#endif /* mig_external */ + kern_return_t + mach_vm_read_list(vm_map_t target_task, mach_vm_read_entry_t data_list, natural_t count); + +/* Routine mach_vm_write */ +#ifdef mig_external +mig_external +#else +extern +#endif /* mig_external */ + kern_return_t + mach_vm_write(vm_map_t target_task, mach_vm_address_t address, vm_offset_t data, mach_msg_type_number_t dataCnt); + +/* Routine mach_vm_copy */ +#ifdef mig_external +mig_external +#else +extern +#endif /* mig_external */ + kern_return_t + mach_vm_copy(vm_map_t target_task, mach_vm_address_t source_address, mach_vm_size_t size, + mach_vm_address_t dest_address); + +/* Routine mach_vm_read_overwrite */ +#ifdef mig_external +mig_external +#else +extern +#endif /* mig_external */ + kern_return_t + mach_vm_read_overwrite(vm_map_t target_task, mach_vm_address_t address, mach_vm_size_t size, mach_vm_address_t data, + mach_vm_size_t *outsize); + +/* Routine mach_vm_msync */ +#ifdef mig_external +mig_external +#else +extern +#endif /* mig_external */ + kern_return_t + mach_vm_msync(vm_map_t target_task, mach_vm_address_t address, mach_vm_size_t size, vm_sync_t sync_flags); + +/* Routine mach_vm_behavior_set */ +#ifdef mig_external +mig_external +#else +extern +#endif /* mig_external */ + kern_return_t + mach_vm_behavior_set(vm_map_t target_task, mach_vm_address_t address, mach_vm_size_t size, + vm_behavior_t new_behavior); + +/* Routine mach_vm_map */ +#ifdef mig_external +mig_external +#else +extern +#endif /* mig_external */ + kern_return_t + mach_vm_map(vm_map_t target_task, mach_vm_address_t *address, mach_vm_size_t size, mach_vm_offset_t mask, int flags, + mem_entry_name_port_t object, memory_object_offset_t offset, boolean_t copy, vm_prot_t curr_protection, + vm_prot_t max_protection, vm_inherit_t inheritance); + +/* Routine mach_vm_machine_attribute */ +#ifdef mig_external +mig_external +#else +extern +#endif /* mig_external */ + kern_return_t + mach_vm_machine_attribute(vm_map_t target_task, mach_vm_address_t address, mach_vm_size_t size, + vm_machine_attribute_t attribute, vm_machine_attribute_val_t *value); + +/* Routine mach_vm_remap */ +#ifdef mig_external +mig_external +#else +extern +#endif /* mig_external */ + kern_return_t + mach_vm_remap(vm_map_t target_task, mach_vm_address_t *target_address, mach_vm_size_t size, mach_vm_offset_t mask, + int flags, vm_map_t src_task, mach_vm_address_t src_address, boolean_t copy, + vm_prot_t *curr_protection, vm_prot_t *max_protection, vm_inherit_t inheritance); + +/* Routine mach_vm_page_query */ +#ifdef mig_external +mig_external +#else +extern +#endif /* mig_external */ + kern_return_t + mach_vm_page_query(vm_map_t target_map, mach_vm_offset_t offset, integer_t *disposition, integer_t *ref_count); + +/* Routine mach_vm_region_recurse */ +#ifdef mig_external +mig_external +#else +extern +#endif /* mig_external */ + kern_return_t + mach_vm_region_recurse(vm_map_t target_task, mach_vm_address_t *address, mach_vm_size_t *size, + natural_t *nesting_depth, vm_region_recurse_info_t info, mach_msg_type_number_t *infoCnt); + +/* Routine mach_vm_region */ +#ifdef mig_external +mig_external +#else +extern +#endif /* mig_external */ + kern_return_t + mach_vm_region(vm_map_t target_task, mach_vm_address_t *address, mach_vm_size_t *size, vm_region_flavor_t flavor, + vm_region_info_t info, mach_msg_type_number_t *infoCnt, mach_port_t *object_name); + +/* Routine _mach_make_memory_entry */ +#ifdef mig_external +mig_external +#else +extern +#endif /* mig_external */ + kern_return_t + _mach_make_memory_entry(vm_map_t target_task, memory_object_size_t *size, memory_object_offset_t offset, + vm_prot_t permission, mem_entry_name_port_t *object_handle, + mem_entry_name_port_t parent_handle); + +/* Routine mach_vm_purgable_control */ +#ifdef mig_external +mig_external +#else +extern +#endif /* mig_external */ + kern_return_t + mach_vm_purgable_control(vm_map_t target_task, mach_vm_address_t address, vm_purgable_t control, int *state); + +/* Routine mach_vm_page_info */ +#ifdef mig_external +mig_external +#else +extern +#endif /* mig_external */ + kern_return_t + mach_vm_page_info(vm_map_t target_task, mach_vm_address_t address, vm_page_info_flavor_t flavor, + vm_page_info_t info, mach_msg_type_number_t *infoCnt); + +__END_DECLS + +/********************** Caution **************************/ +/* The following data types should be used to calculate */ +/* maximum message sizes only. The actual message may be */ +/* smaller, and the position of the arguments within the */ +/* message layout may vary from what is presented here. */ +/* For example, if any of the arguments are variable- */ +/* sized, and less than the maximum is sent, the data */ +/* will be packed tight in the actual message to reduce */ +/* the presence of holes. */ +/********************** Caution **************************/ + +/* typedefs for all requests */ + +#ifndef __Request__mach_vm_subsystem__defined +#define __Request__mach_vm_subsystem__defined + +#ifdef __MigPackStructs +#pragma pack(4) +#endif +typedef struct { + mach_msg_header_t Head; + NDR_record_t NDR; + mach_vm_address_t address; + mach_vm_size_t size; + int flags; +} __Request__mach_vm_allocate_t __attribute__((unused)); +#ifdef __MigPackStructs +#pragma pack() +#endif + +#ifdef __MigPackStructs +#pragma pack(4) +#endif +typedef struct { + mach_msg_header_t Head; + NDR_record_t NDR; + mach_vm_address_t address; + mach_vm_size_t size; +} __Request__mach_vm_deallocate_t __attribute__((unused)); +#ifdef __MigPackStructs +#pragma pack() +#endif + +#ifdef __MigPackStructs +#pragma pack(4) +#endif +typedef struct { + mach_msg_header_t Head; + NDR_record_t NDR; + mach_vm_address_t address; + mach_vm_size_t size; + boolean_t set_maximum; + vm_prot_t new_protection; +} __Request__mach_vm_protect_t __attribute__((unused)); +#ifdef __MigPackStructs +#pragma pack() +#endif + +#ifdef __MigPackStructs +#pragma pack(4) +#endif +typedef struct { + mach_msg_header_t Head; + NDR_record_t NDR; + mach_vm_address_t address; + mach_vm_size_t size; + vm_inherit_t new_inheritance; +} __Request__mach_vm_inherit_t __attribute__((unused)); +#ifdef __MigPackStructs +#pragma pack() +#endif + +#ifdef __MigPackStructs +#pragma pack(4) +#endif +typedef struct { + mach_msg_header_t Head; + NDR_record_t NDR; + mach_vm_address_t address; + mach_vm_size_t size; +} __Request__mach_vm_read_t __attribute__((unused)); +#ifdef __MigPackStructs +#pragma pack() +#endif + +#ifdef __MigPackStructs +#pragma pack(4) +#endif +typedef struct { + mach_msg_header_t Head; + NDR_record_t NDR; + mach_vm_read_entry_t data_list; + natural_t count; +} __Request__mach_vm_read_list_t __attribute__((unused)); +#ifdef __MigPackStructs +#pragma pack() +#endif + +#ifdef __MigPackStructs +#pragma pack(4) +#endif +typedef struct { + mach_msg_header_t Head; + /* start of the kernel processed data */ + mach_msg_body_t msgh_body; + mach_msg_ool_descriptor_t data; + /* end of the kernel processed data */ + NDR_record_t NDR; + mach_vm_address_t address; + mach_msg_type_number_t dataCnt; +} __Request__mach_vm_write_t __attribute__((unused)); +#ifdef __MigPackStructs +#pragma pack() +#endif + +#ifdef __MigPackStructs +#pragma pack(4) +#endif +typedef struct { + mach_msg_header_t Head; + NDR_record_t NDR; + mach_vm_address_t source_address; + mach_vm_size_t size; + mach_vm_address_t dest_address; +} __Request__mach_vm_copy_t __attribute__((unused)); +#ifdef __MigPackStructs +#pragma pack() +#endif + +#ifdef __MigPackStructs +#pragma pack(4) +#endif +typedef struct { + mach_msg_header_t Head; + NDR_record_t NDR; + mach_vm_address_t address; + mach_vm_size_t size; + mach_vm_address_t data; +} __Request__mach_vm_read_overwrite_t __attribute__((unused)); +#ifdef __MigPackStructs +#pragma pack() +#endif + +#ifdef __MigPackStructs +#pragma pack(4) +#endif +typedef struct { + mach_msg_header_t Head; + NDR_record_t NDR; + mach_vm_address_t address; + mach_vm_size_t size; + vm_sync_t sync_flags; +} __Request__mach_vm_msync_t __attribute__((unused)); +#ifdef __MigPackStructs +#pragma pack() +#endif + +#ifdef __MigPackStructs +#pragma pack(4) +#endif +typedef struct { + mach_msg_header_t Head; + NDR_record_t NDR; + mach_vm_address_t address; + mach_vm_size_t size; + vm_behavior_t new_behavior; +} __Request__mach_vm_behavior_set_t __attribute__((unused)); +#ifdef __MigPackStructs +#pragma pack() +#endif + +#ifdef __MigPackStructs +#pragma pack(4) +#endif +typedef struct { + mach_msg_header_t Head; + /* start of the kernel processed data */ + mach_msg_body_t msgh_body; + mach_msg_port_descriptor_t object; + /* end of the kernel processed data */ + NDR_record_t NDR; + mach_vm_address_t address; + mach_vm_size_t size; + mach_vm_offset_t mask; + int flags; + memory_object_offset_t offset; + boolean_t copy; + vm_prot_t curr_protection; + vm_prot_t max_protection; + vm_inherit_t inheritance; +} __Request__mach_vm_map_t __attribute__((unused)); +#ifdef __MigPackStructs +#pragma pack() +#endif + +#ifdef __MigPackStructs +#pragma pack(4) +#endif +typedef struct { + mach_msg_header_t Head; + NDR_record_t NDR; + mach_vm_address_t address; + mach_vm_size_t size; + vm_machine_attribute_t attribute; + vm_machine_attribute_val_t value; +} __Request__mach_vm_machine_attribute_t __attribute__((unused)); +#ifdef __MigPackStructs +#pragma pack() +#endif + +#ifdef __MigPackStructs +#pragma pack(4) +#endif +typedef struct { + mach_msg_header_t Head; + /* start of the kernel processed data */ + mach_msg_body_t msgh_body; + mach_msg_port_descriptor_t src_task; + /* end of the kernel processed data */ + NDR_record_t NDR; + mach_vm_address_t target_address; + mach_vm_size_t size; + mach_vm_offset_t mask; + int flags; + mach_vm_address_t src_address; + boolean_t copy; + vm_inherit_t inheritance; +} __Request__mach_vm_remap_t __attribute__((unused)); +#ifdef __MigPackStructs +#pragma pack() +#endif + +#ifdef __MigPackStructs +#pragma pack(4) +#endif +typedef struct { + mach_msg_header_t Head; + NDR_record_t NDR; + mach_vm_offset_t offset; +} __Request__mach_vm_page_query_t __attribute__((unused)); +#ifdef __MigPackStructs +#pragma pack() +#endif + +#ifdef __MigPackStructs +#pragma pack(4) +#endif +typedef struct { + mach_msg_header_t Head; + NDR_record_t NDR; + mach_vm_address_t address; + natural_t nesting_depth; + mach_msg_type_number_t infoCnt; +} __Request__mach_vm_region_recurse_t __attribute__((unused)); +#ifdef __MigPackStructs +#pragma pack() +#endif + +#ifdef __MigPackStructs +#pragma pack(4) +#endif +typedef struct { + mach_msg_header_t Head; + NDR_record_t NDR; + mach_vm_address_t address; + vm_region_flavor_t flavor; + mach_msg_type_number_t infoCnt; +} __Request__mach_vm_region_t __attribute__((unused)); +#ifdef __MigPackStructs +#pragma pack() +#endif + +#ifdef __MigPackStructs +#pragma pack(4) +#endif +typedef struct { + mach_msg_header_t Head; + /* start of the kernel processed data */ + mach_msg_body_t msgh_body; + mach_msg_port_descriptor_t parent_handle; + /* end of the kernel processed data */ + NDR_record_t NDR; + memory_object_size_t size; + memory_object_offset_t offset; + vm_prot_t permission; +} __Request___mach_make_memory_entry_t __attribute__((unused)); +#ifdef __MigPackStructs +#pragma pack() +#endif + +#ifdef __MigPackStructs +#pragma pack(4) +#endif +typedef struct { + mach_msg_header_t Head; + NDR_record_t NDR; + mach_vm_address_t address; + vm_purgable_t control; + int state; +} __Request__mach_vm_purgable_control_t __attribute__((unused)); +#ifdef __MigPackStructs +#pragma pack() +#endif + +#ifdef __MigPackStructs +#pragma pack(4) +#endif +typedef struct { + mach_msg_header_t Head; + NDR_record_t NDR; + mach_vm_address_t address; + vm_page_info_flavor_t flavor; + mach_msg_type_number_t infoCnt; +} __Request__mach_vm_page_info_t __attribute__((unused)); +#ifdef __MigPackStructs +#pragma pack() +#endif +#endif /* !__Request__mach_vm_subsystem__defined */ + +/* union of all requests */ + +#ifndef __RequestUnion__mach_vm_subsystem__defined +#define __RequestUnion__mach_vm_subsystem__defined +union __RequestUnion__mach_vm_subsystem { + __Request__mach_vm_allocate_t Request_mach_vm_allocate; + __Request__mach_vm_deallocate_t Request_mach_vm_deallocate; + __Request__mach_vm_protect_t Request_mach_vm_protect; + __Request__mach_vm_inherit_t Request_mach_vm_inherit; + __Request__mach_vm_read_t Request_mach_vm_read; + __Request__mach_vm_read_list_t Request_mach_vm_read_list; + __Request__mach_vm_write_t Request_mach_vm_write; + __Request__mach_vm_copy_t Request_mach_vm_copy; + __Request__mach_vm_read_overwrite_t Request_mach_vm_read_overwrite; + __Request__mach_vm_msync_t Request_mach_vm_msync; + __Request__mach_vm_behavior_set_t Request_mach_vm_behavior_set; + __Request__mach_vm_map_t Request_mach_vm_map; + __Request__mach_vm_machine_attribute_t Request_mach_vm_machine_attribute; + __Request__mach_vm_remap_t Request_mach_vm_remap; + __Request__mach_vm_page_query_t Request_mach_vm_page_query; + __Request__mach_vm_region_recurse_t Request_mach_vm_region_recurse; + __Request__mach_vm_region_t Request_mach_vm_region; + __Request___mach_make_memory_entry_t Request__mach_make_memory_entry; + __Request__mach_vm_purgable_control_t Request_mach_vm_purgable_control; + __Request__mach_vm_page_info_t Request_mach_vm_page_info; +}; +#endif /* !__RequestUnion__mach_vm_subsystem__defined */ +/* typedefs for all replies */ + +#ifndef __Reply__mach_vm_subsystem__defined +#define __Reply__mach_vm_subsystem__defined + +#ifdef __MigPackStructs +#pragma pack(4) +#endif +typedef struct { + mach_msg_header_t Head; + NDR_record_t NDR; + kern_return_t RetCode; + mach_vm_address_t address; +} __Reply__mach_vm_allocate_t __attribute__((unused)); +#ifdef __MigPackStructs +#pragma pack() +#endif + +#ifdef __MigPackStructs +#pragma pack(4) +#endif +typedef struct { + mach_msg_header_t Head; + NDR_record_t NDR; + kern_return_t RetCode; +} __Reply__mach_vm_deallocate_t __attribute__((unused)); +#ifdef __MigPackStructs +#pragma pack() +#endif + +#ifdef __MigPackStructs +#pragma pack(4) +#endif +typedef struct { + mach_msg_header_t Head; + NDR_record_t NDR; + kern_return_t RetCode; +} __Reply__mach_vm_protect_t __attribute__((unused)); +#ifdef __MigPackStructs +#pragma pack() +#endif + +#ifdef __MigPackStructs +#pragma pack(4) +#endif +typedef struct { + mach_msg_header_t Head; + NDR_record_t NDR; + kern_return_t RetCode; +} __Reply__mach_vm_inherit_t __attribute__((unused)); +#ifdef __MigPackStructs +#pragma pack() +#endif + +#ifdef __MigPackStructs +#pragma pack(4) +#endif +typedef struct { + mach_msg_header_t Head; + /* start of the kernel processed data */ + mach_msg_body_t msgh_body; + mach_msg_ool_descriptor_t data; + /* end of the kernel processed data */ + NDR_record_t NDR; + mach_msg_type_number_t dataCnt; +} __Reply__mach_vm_read_t __attribute__((unused)); +#ifdef __MigPackStructs +#pragma pack() +#endif + +#ifdef __MigPackStructs +#pragma pack(4) +#endif +typedef struct { + mach_msg_header_t Head; + NDR_record_t NDR; + kern_return_t RetCode; + mach_vm_read_entry_t data_list; +} __Reply__mach_vm_read_list_t __attribute__((unused)); +#ifdef __MigPackStructs +#pragma pack() +#endif + +#ifdef __MigPackStructs +#pragma pack(4) +#endif +typedef struct { + mach_msg_header_t Head; + NDR_record_t NDR; + kern_return_t RetCode; +} __Reply__mach_vm_write_t __attribute__((unused)); +#ifdef __MigPackStructs +#pragma pack() +#endif + +#ifdef __MigPackStructs +#pragma pack(4) +#endif +typedef struct { + mach_msg_header_t Head; + NDR_record_t NDR; + kern_return_t RetCode; +} __Reply__mach_vm_copy_t __attribute__((unused)); +#ifdef __MigPackStructs +#pragma pack() +#endif + +#ifdef __MigPackStructs +#pragma pack(4) +#endif +typedef struct { + mach_msg_header_t Head; + NDR_record_t NDR; + kern_return_t RetCode; + mach_vm_size_t outsize; +} __Reply__mach_vm_read_overwrite_t __attribute__((unused)); +#ifdef __MigPackStructs +#pragma pack() +#endif + +#ifdef __MigPackStructs +#pragma pack(4) +#endif +typedef struct { + mach_msg_header_t Head; + NDR_record_t NDR; + kern_return_t RetCode; +} __Reply__mach_vm_msync_t __attribute__((unused)); +#ifdef __MigPackStructs +#pragma pack() +#endif + +#ifdef __MigPackStructs +#pragma pack(4) +#endif +typedef struct { + mach_msg_header_t Head; + NDR_record_t NDR; + kern_return_t RetCode; +} __Reply__mach_vm_behavior_set_t __attribute__((unused)); +#ifdef __MigPackStructs +#pragma pack() +#endif + +#ifdef __MigPackStructs +#pragma pack(4) +#endif +typedef struct { + mach_msg_header_t Head; + NDR_record_t NDR; + kern_return_t RetCode; + mach_vm_address_t address; +} __Reply__mach_vm_map_t __attribute__((unused)); +#ifdef __MigPackStructs +#pragma pack() +#endif + +#ifdef __MigPackStructs +#pragma pack(4) +#endif +typedef struct { + mach_msg_header_t Head; + NDR_record_t NDR; + kern_return_t RetCode; + vm_machine_attribute_val_t value; +} __Reply__mach_vm_machine_attribute_t __attribute__((unused)); +#ifdef __MigPackStructs +#pragma pack() +#endif + +#ifdef __MigPackStructs +#pragma pack(4) +#endif +typedef struct { + mach_msg_header_t Head; + NDR_record_t NDR; + kern_return_t RetCode; + mach_vm_address_t target_address; + vm_prot_t curr_protection; + vm_prot_t max_protection; +} __Reply__mach_vm_remap_t __attribute__((unused)); +#ifdef __MigPackStructs +#pragma pack() +#endif + +#ifdef __MigPackStructs +#pragma pack(4) +#endif +typedef struct { + mach_msg_header_t Head; + NDR_record_t NDR; + kern_return_t RetCode; + integer_t disposition; + integer_t ref_count; +} __Reply__mach_vm_page_query_t __attribute__((unused)); +#ifdef __MigPackStructs +#pragma pack() +#endif + +#ifdef __MigPackStructs +#pragma pack(4) +#endif +typedef struct { + mach_msg_header_t Head; + NDR_record_t NDR; + kern_return_t RetCode; + mach_vm_address_t address; + mach_vm_size_t size; + natural_t nesting_depth; + mach_msg_type_number_t infoCnt; + int info[19]; +} __Reply__mach_vm_region_recurse_t __attribute__((unused)); +#ifdef __MigPackStructs +#pragma pack() +#endif + +#ifdef __MigPackStructs +#pragma pack(4) +#endif +typedef struct { + mach_msg_header_t Head; + /* start of the kernel processed data */ + mach_msg_body_t msgh_body; + mach_msg_port_descriptor_t object_name; + /* end of the kernel processed data */ + NDR_record_t NDR; + mach_vm_address_t address; + mach_vm_size_t size; + mach_msg_type_number_t infoCnt; + int info[10]; +} __Reply__mach_vm_region_t __attribute__((unused)); +#ifdef __MigPackStructs +#pragma pack() +#endif + +#ifdef __MigPackStructs +#pragma pack(4) +#endif +typedef struct { + mach_msg_header_t Head; + /* start of the kernel processed data */ + mach_msg_body_t msgh_body; + mach_msg_port_descriptor_t object_handle; + /* end of the kernel processed data */ + NDR_record_t NDR; + memory_object_size_t size; +} __Reply___mach_make_memory_entry_t __attribute__((unused)); +#ifdef __MigPackStructs +#pragma pack() +#endif + +#ifdef __MigPackStructs +#pragma pack(4) +#endif +typedef struct { + mach_msg_header_t Head; + NDR_record_t NDR; + kern_return_t RetCode; + int state; +} __Reply__mach_vm_purgable_control_t __attribute__((unused)); +#ifdef __MigPackStructs +#pragma pack() +#endif + +#ifdef __MigPackStructs +#pragma pack(4) +#endif +typedef struct { + mach_msg_header_t Head; + NDR_record_t NDR; + kern_return_t RetCode; + mach_msg_type_number_t infoCnt; + int info[32]; +} __Reply__mach_vm_page_info_t __attribute__((unused)); +#ifdef __MigPackStructs +#pragma pack() +#endif +#endif /* !__Reply__mach_vm_subsystem__defined */ + +/* union of all replies */ + +#ifndef __ReplyUnion__mach_vm_subsystem__defined +#define __ReplyUnion__mach_vm_subsystem__defined +union __ReplyUnion__mach_vm_subsystem { + __Reply__mach_vm_allocate_t Reply_mach_vm_allocate; + __Reply__mach_vm_deallocate_t Reply_mach_vm_deallocate; + __Reply__mach_vm_protect_t Reply_mach_vm_protect; + __Reply__mach_vm_inherit_t Reply_mach_vm_inherit; + __Reply__mach_vm_read_t Reply_mach_vm_read; + __Reply__mach_vm_read_list_t Reply_mach_vm_read_list; + __Reply__mach_vm_write_t Reply_mach_vm_write; + __Reply__mach_vm_copy_t Reply_mach_vm_copy; + __Reply__mach_vm_read_overwrite_t Reply_mach_vm_read_overwrite; + __Reply__mach_vm_msync_t Reply_mach_vm_msync; + __Reply__mach_vm_behavior_set_t Reply_mach_vm_behavior_set; + __Reply__mach_vm_map_t Reply_mach_vm_map; + __Reply__mach_vm_machine_attribute_t Reply_mach_vm_machine_attribute; + __Reply__mach_vm_remap_t Reply_mach_vm_remap; + __Reply__mach_vm_page_query_t Reply_mach_vm_page_query; + __Reply__mach_vm_region_recurse_t Reply_mach_vm_region_recurse; + __Reply__mach_vm_region_t Reply_mach_vm_region; + __Reply___mach_make_memory_entry_t Reply__mach_make_memory_entry; + __Reply__mach_vm_purgable_control_t Reply_mach_vm_purgable_control; + __Reply__mach_vm_page_info_t Reply_mach_vm_page_info; +}; +#endif /* !__RequestUnion__mach_vm_subsystem__defined */ + +#ifndef subsystem_to_name_map_mach_vm +#define subsystem_to_name_map_mach_vm \ + {"mach_vm_allocate", 4800}, {"mach_vm_deallocate", 4801}, {"mach_vm_protect", 4802}, {"mach_vm_inherit", 4803}, \ + {"mach_vm_read", 4804}, {"mach_vm_read_list", 4805}, {"mach_vm_write", 4806}, {"mach_vm_copy", 4807}, \ + {"mach_vm_read_overwrite", 4808}, {"mach_vm_msync", 4809}, {"mach_vm_behavior_set", 4810}, \ + {"mach_vm_map", 4811}, {"mach_vm_machine_attribute", 4812}, {"mach_vm_remap", 4813}, \ + {"mach_vm_page_query", 4814}, {"mach_vm_region_recurse", 4815}, {"mach_vm_region", 4816}, \ + {"_mach_make_memory_entry", 4817}, {"mach_vm_purgable_control", 4818}, { \ + "mach_vm_page_info", 4819 \ + } +#endif + +#ifdef __AfterMigUserHeader +__AfterMigUserHeader +#endif /* __AfterMigUserHeader */ + +#endif /* _mach_vm_user_ */ diff --git a/app/src/main/cpp/Dobby/source/Backend/UserMode/UnifiedInterface/platform-posix.cc b/app/src/main/cpp/Dobby/source/Backend/UserMode/UnifiedInterface/platform-posix.cc new file mode 100644 index 0000000..f7928e5 --- /dev/null +++ b/app/src/main/cpp/Dobby/source/Backend/UserMode/UnifiedInterface/platform-posix.cc @@ -0,0 +1,183 @@ +#include +#include +#include +#include + +#if defined(__DragonFly__) || defined(__FreeBSD__) || defined(__OpenBSD__) +#include // for pthread_set_name_np +#endif + +#include // for sched_yield +#include +#include +#include + +#include +#include +#include +#include +#include + +#if defined(__APPLE__) || defined(__DragonFly__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) +#include // NOLINT, for sysctl +#endif + +#include "logging/logging.h" +#include "logging/check_logging.h" +#include "UnifiedInterface/platform.h" + +#if defined(__APPLE__) +#include +#include +#include +#endif + +#if defined(ANDROID) && !defined(ANDROID_LOG_STDOUT) +#define ANDROID_LOG_TAG "Dobby" + +#include + +#endif + +#include + +#if defined(__APPLE__) +const int kMmapFd = VM_MAKE_TAG(255); +#else +const int kMmapFd = -1; +#endif + +const int kMmapFdOffset = 0; + +using namespace base; + +typedef struct thread_handle_t { + pthread_t thread; +} thread_handle_t; + +void ThreadInterface::SetName(const char *name) { +#if defined(__DragonFly__) || defined(__FreeBSD__) || defined(__OpenBSD__) + pthread_set_name_np(pthread_self(), name); +#elif defined(__APPLE__) + pthread_setname_np(name); +#endif +} + +int ThreadInterface::CurrentId() { +#if defined(__APPLE__) + mach_port_t port = mach_thread_self(); + mach_port_deallocate(mach_task_self(), port); + return port; +#elif defined(_POSIX_VERSION) + return syscall(__NR_gettid); +#endif +} + +static void *thread_handler_wrapper(void *ctx) { + ThreadInterface::Delegate *d = (ThreadInterface::Delegate *)ctx; + d->ThreadMain(); + return nullptr; +} + +bool ThreadInterface::Create(ThreadInterface::Delegate *delegate, ThreadHandle *handle) { + thread_handle_t *handle_impl = new thread_handle_t; + + int err = 0; + err = pthread_create(&(handle_impl->thread), nullptr, thread_handler_wrapper, delegate); + if (err != 0) { + ERROR_LOG("pthread create failed"); + return false; + } + return true; +} + +OSThread::OSThread(const char *name) { + strncpy(name_, name, sizeof(name_) -1); +} + +bool OSThread::Start() { + if (ThreadInterface::Create(this, &handle_) == false) { + return false; + } + return true; +} + +static int GetProtectionFromMemoryPermission(MemoryPermission access) { + switch (access) { + case MemoryPermission::kNoAccess: + return PROT_NONE; + case MemoryPermission::kRead: + return PROT_READ; + case MemoryPermission::kReadWrite: + return PROT_READ | PROT_WRITE; + case MemoryPermission::kReadWriteExecute: + return PROT_READ | PROT_WRITE | PROT_EXEC; + case MemoryPermission::kReadExecute: + return PROT_READ | PROT_EXEC; + } + UNREACHABLE(); +} + +int OSMemory::PageSize() { + return static_cast(sysconf(_SC_PAGESIZE)); +} + +void *OSMemory::Allocate(size_t size, MemoryPermission access) { + return OSMemory::Allocate(size, access, nullptr); +} + +void *OSMemory::Allocate(size_t size, MemoryPermission access, void *fixed_address) { + int prot = GetProtectionFromMemoryPermission(access); + + int flags = MAP_PRIVATE | MAP_ANONYMOUS; + if (fixed_address != nullptr) { + flags = flags | MAP_FIXED; + } + void *result = mmap(fixed_address, size, prot, flags, kMmapFd, kMmapFdOffset); + if (result == MAP_FAILED) + return nullptr; + + return result; +} + +bool OSMemory::Free(void *address, size_t size) { + DCHECK_EQ(0, reinterpret_cast(address) % PageSize()); + DCHECK_EQ(0, size % PageSize()); + + return munmap(address, size) == 0; +} + +bool OSMemory::Release(void *address, size_t size) { + DCHECK_EQ(0, reinterpret_cast(address) % PageSize()); + DCHECK_EQ(0, size % PageSize()); + + return munmap(address, size) == 0; +} + +bool OSMemory::SetPermission(void *address, size_t size, MemoryPermission access) { + DCHECK_EQ(0, reinterpret_cast(address) % PageSize()); + DCHECK_EQ(0, size % PageSize()); + + int prot = GetProtectionFromMemoryPermission(access); + int ret = mprotect(address, size, prot); + if (ret) { + ERROR_LOG("OSMemory::SetPermission: %s\n", ((const char *)strerror(errno))); + } + + return ret == 0; +} + +void OSPrint::Print(const char *format, ...) { + va_list args; + va_start(args, format); + VPrint(format, args); + va_end(args); +} + +void OSPrint::VPrint(const char *format, va_list args) { +#if defined(ANDROID) && !defined(ANDROID_LOG_STDOUT) + __android_log_vprint(ANDROID_LOG_INFO, ANDROID_LOG_TAG, format, args); +#else + vprintf(format, args); +#endif +} diff --git a/app/src/main/cpp/Dobby/source/Backend/UserMode/UnifiedInterface/platform-windows.cc b/app/src/main/cpp/Dobby/source/Backend/UserMode/UnifiedInterface/platform-windows.cc new file mode 100644 index 0000000..fd36108 --- /dev/null +++ b/app/src/main/cpp/Dobby/source/Backend/UserMode/UnifiedInterface/platform-windows.cc @@ -0,0 +1,86 @@ +#include + +#include + +#include "logging/logging.h" +#include "logging/check_logging.h" +#include "UnifiedInterface/platform.h" + +int GetProtectionFromMemoryPermission(MemoryPermission access) { + if (kReadWriteExecute == access) + return PAGE_EXECUTE_READWRITE; + else if (kReadExecute == access) + return PAGE_EXECUTE_READ; +} + +int OSMemory::AllocPageSize() { + static int lastRet = -1; + if (lastRet == -1) { + SYSTEM_INFO si; + GetSystemInfo(&si); + lastRet = si.dwAllocationGranularity; // should be used with VirtualAlloc(MEM_RESERVE) + } + return lastRet; +} + +int OSMemory::PageSize() { + static int lastRet = -1; + if (lastRet == -1) { + SYSTEM_INFO si; + GetSystemInfo(&si); + lastRet = si.dwPageSize; // should be used with VirtualAlloc(MEM_RESERVE) + } + return lastRet; +} + +void *OSMemory::Allocate(void *address, int size, MemoryPermission access) { + DCHECK_EQ(0, reinterpret_cast(address) % AllocPageSize()); + DCHECK_EQ(0, size % PageSize()); + + void *result = VirtualAlloc(address, size, MEM_COMMIT | MEM_RESERVE, PAGE_NOACCESS); + OSMemory::SetPermission(result, size, kReadWriteExecute); + if (result == nullptr) + return nullptr; + + // TODO: if need align + void *aligned_base = result; + return static_cast(aligned_base); +} + +// static +bool OSMemory::Free(void *address, const int size) { + DCHECK_EQ(0, reinterpret_cast(address) % PageSize()); + DCHECK_EQ(0, size % PageSize()); + + return VirtualFree(address, size, MEM_RELEASE); +} + +bool OSMemory::Release(void *address, int size) { + DCHECK_EQ(0, reinterpret_cast(address) % PageSize()); + DCHECK_EQ(0, size % PageSize()); + + return OSMemory::Free(address, size); +} + +bool OSMemory::SetPermission(void *address, int size, MemoryPermission access) { + DCHECK_EQ(0, reinterpret_cast(address) % PageSize()); + DCHECK_EQ(0, size % PageSize()); + + int prot = GetProtectionFromMemoryPermission(access); + + DWORD oldProtect; + return VirtualProtect(address, size, prot, &oldProtect); +} + +// ===== + +void OSPrint::Print(const char *format, ...) { + va_list args; + va_start(args, format); + VPrint(format, args); + va_end(args); +} + +void OSPrint::VPrint(const char *format, va_list args) { + vprintf(format, args); +} diff --git a/app/src/main/cpp/Dobby/source/Backend/UserMode/UnifiedInterface/platform.h b/app/src/main/cpp/Dobby/source/Backend/UserMode/UnifiedInterface/platform.h new file mode 100644 index 0000000..62bfe8f --- /dev/null +++ b/app/src/main/cpp/Dobby/source/Backend/UserMode/UnifiedInterface/platform.h @@ -0,0 +1,83 @@ +#pragma once + +#include +#include + +namespace base { + +class ThreadLocalStorageInterface { + using LocalStorageKey = int32_t; + + static LocalStorageKey CreateThreadLocalKey(); + + static void DeleteThreadLocalKey(LocalStorageKey key); + + static void *GetThreadLocal(LocalStorageKey key); + + static int GetThreadLocalInt(LocalStorageKey key) { + return static_cast(reinterpret_cast(GetThreadLocal(key))); + } + + static void SetThreadLocal(LocalStorageKey key, void *value); + + static void SetThreadLocalInt(LocalStorageKey key, int value) { + SetThreadLocal(key, reinterpret_cast(static_cast(value))); + } + + static bool HasThreadLocal(LocalStorageKey key) { + return GetThreadLocal(key) != nullptr; + } +}; + +typedef void *ThreadHandle; + +class ThreadInterface { +public: + class Delegate { + public: + virtual void ThreadMain() = 0; + }; + +public: + static bool Create(Delegate *delegate, ThreadHandle *handle); + + static int CurrentId(); + + static void SetName(const char *); +}; +} // namespace base + +class OSThread : public base::ThreadInterface, public base::ThreadInterface::Delegate { + base::ThreadHandle handle_; + + char name_[256]; + +public: + OSThread(const char *name); + + bool Start(); +}; + +enum MemoryPermission { kNoAccess, kRead, kReadWrite, kReadWriteExecute, kReadExecute }; + +class OSMemory { +public: + static int PageSize(); + + static void *Allocate(size_t size, MemoryPermission access); + + static void *Allocate(size_t size, MemoryPermission access, void *fixed_address); + + static bool Free(void *address, size_t size); + + static bool Release(void *address, size_t size); + + static bool SetPermission(void *address, size_t size, MemoryPermission access); +}; + +class OSPrint { +public: + static void Print(const char *format, ...); + + static void VPrint(const char *format, va_list args); +}; \ No newline at end of file diff --git a/app/src/main/cpp/Dobby/source/Backend/UserMode/UnifiedInterface/semaphore.cc b/app/src/main/cpp/Dobby/source/Backend/UserMode/UnifiedInterface/semaphore.cc new file mode 100644 index 0000000..b454c6e --- /dev/null +++ b/app/src/main/cpp/Dobby/source/Backend/UserMode/UnifiedInterface/semaphore.cc @@ -0,0 +1,160 @@ +// Copyright 2013 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "src/base/platform/semaphore.h" + +#if V8_OS_MACOSX +#include +#endif + +#include + +#include "src/base/logging.h" +#include "src/base/platform/elapsed-timer.h" +#include "src/base/platform/time.h" + +namespace v8 { +namespace base { + +#if V8_OS_MACOSX + +Semaphore::Semaphore(int count) { + native_handle_ = dispatch_semaphore_create(count); + DCHECK(native_handle_); +} + +Semaphore::~Semaphore() { + dispatch_release(native_handle_); +} + +void Semaphore::Signal() { + dispatch_semaphore_signal(native_handle_); +} + +void Semaphore::Wait() { + dispatch_semaphore_wait(native_handle_, DISPATCH_TIME_FOREVER); +} + +bool Semaphore::WaitFor(const TimeDelta &rel_time) { + dispatch_time_t timeout = dispatch_time(DISPATCH_TIME_NOW, rel_time.InNanoseconds()); + return dispatch_semaphore_wait(native_handle_, timeout) == 0; +} + +#elif V8_OS_POSIX + +Semaphore::Semaphore(int count) { + DCHECK_GE(count, 0); + int result = sem_init(&native_handle_, 0, count); + DCHECK_EQ(0, result); + USE(result); +} + +Semaphore::~Semaphore() { + int result = sem_destroy(&native_handle_); + DCHECK_EQ(0, result); + USE(result); +} + +void Semaphore::Signal() { + int result = sem_post(&native_handle_); + // This check may fail with 0) { + // sem_timedwait in glibc prior to 2.3.4 returns the errno instead of -1. + errno = result; + result = -1; + } +#endif + if (result == -1 && errno == ETIMEDOUT) { + // Timed out while waiting for semaphore. + return false; + } + // Signal caused spurious wakeup. + DCHECK_EQ(-1, result); + DCHECK_EQ(EINTR, errno); + } +} + +#elif V8_OS_WIN + +Semaphore::Semaphore(int count) { + DCHECK_GE(count, 0); + native_handle_ = ::CreateSemaphoreA(nullptr, count, 0x7FFFFFFF, nullptr); + DCHECK_NOT_NULL(native_handle_); +} + +Semaphore::~Semaphore() { + BOOL result = CloseHandle(native_handle_); + DCHECK(result); + USE(result); +} + +void Semaphore::Signal() { + LONG dummy; + BOOL result = ReleaseSemaphore(native_handle_, 1, &dummy); + DCHECK(result); + USE(result); +} + +void Semaphore::Wait() { + DWORD result = WaitForSingleObject(native_handle_, INFINITE); + DCHECK(result == WAIT_OBJECT_0); + USE(result); +} + +bool Semaphore::WaitFor(const TimeDelta &rel_time) { + TimeTicks now = TimeTicks::Now(); + TimeTicks end = now + rel_time; + while (true) { + int64_t msec = (end - now).InMilliseconds(); + if (msec >= static_cast(INFINITE)) { + DWORD result = WaitForSingleObject(native_handle_, INFINITE - 1); + if (result == WAIT_OBJECT_0) { + return true; + } + DCHECK(result == WAIT_TIMEOUT); + now = TimeTicks::Now(); + } else { + DWORD result = WaitForSingleObject(native_handle_, (msec < 0) ? 0 : static_cast(msec)); + if (result == WAIT_TIMEOUT) { + return false; + } + DCHECK(result == WAIT_OBJECT_0); + return true; + } + } +} + +#endif // V8_OS_MACOSX + +} // namespace base +} // namespace v8 diff --git a/app/src/main/cpp/Dobby/source/Backend/UserMode/UnifiedInterface/semaphore.h b/app/src/main/cpp/Dobby/source/Backend/UserMode/UnifiedInterface/semaphore.h new file mode 100644 index 0000000..cff4cd4 --- /dev/null +++ b/app/src/main/cpp/Dobby/source/Backend/UserMode/UnifiedInterface/semaphore.h @@ -0,0 +1,98 @@ +// Copyright 2013 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef V8_BASE_PLATFORM_SEMAPHORE_H_ +#define V8_BASE_PLATFORM_SEMAPHORE_H_ + +#include "src/base/base-export.h" +#include "src/base/lazy-instance.h" +#if V8_OS_WIN +#include "src/base/win32-headers.h" +#endif + +#if V8_OS_MACOSX +#include // NOLINT +#elif V8_OS_POSIX +#include // NOLINT +#endif + +namespace v8 { +namespace base { + +// Forward declarations. +class TimeDelta; + +// ---------------------------------------------------------------------------- +// Semaphore +// +// A semaphore object is a synchronization object that maintains a count. The +// count is decremented each time a thread completes a wait for the semaphore +// object and incremented each time a thread signals the semaphore. When the +// count reaches zero, threads waiting for the semaphore blocks until the +// count becomes non-zero. + +class V8_BASE_EXPORT Semaphore final { +public: + explicit Semaphore(int count); + ~Semaphore(); + + // Increments the semaphore counter. + void Signal(); + + // Decrements the semaphore counter if it is positive, or blocks until it + // becomes positive and then decrements the counter. + void Wait(); + + // Like Wait() but returns after rel_time time has passed. If the timeout + // happens the return value is false and the counter is unchanged. Otherwise + // the semaphore counter is decremented and true is returned. + bool WaitFor(const TimeDelta &rel_time) V8_WARN_UNUSED_RESULT; + +#if V8_OS_MACOSX + using NativeHandle = dispatch_semaphore_t; +#elif V8_OS_POSIX + using NativeHandle = sem_t; +#elif V8_OS_WIN + using NativeHandle = HANDLE; +#endif + + NativeHandle &native_handle() { + return native_handle_; + } + const NativeHandle &native_handle() const { + return native_handle_; + } + +private: + NativeHandle native_handle_; + + DISALLOW_COPY_AND_ASSIGN(Semaphore); +}; + +// POD Semaphore initialized lazily (i.e. the first time Pointer() is called). +// Usage: +// // The following semaphore starts at 0. +// static LazySemaphore<0>::type my_semaphore = LAZY_SEMAPHORE_INITIALIZER; +// +// void my_function() { +// // Do something with my_semaphore.Pointer(). +// } +// + +template struct CreateSemaphoreTrait { + static Semaphore *Create() { + return new Semaphore(N); + } +}; + +template struct LazySemaphore { + using typename LazyDynamicInstance, ThreadSafeInitOnceTrait>::type; +}; + +#define LAZY_SEMAPHORE_INITIALIZER LAZY_DYNAMIC_INSTANCE_INITIALIZER + +} // namespace base +} // namespace v8 + +#endif // V8_BASE_PLATFORM_SEMAPHORE_H_ diff --git a/app/src/main/cpp/Dobby/source/InstructionRelocation/InstructionRelocation.h b/app/src/main/cpp/Dobby/source/InstructionRelocation/InstructionRelocation.h new file mode 100644 index 0000000..079fc78 --- /dev/null +++ b/app/src/main/cpp/Dobby/source/InstructionRelocation/InstructionRelocation.h @@ -0,0 +1,5 @@ +#include "dobby/dobby_internal.h" + +void GenRelocateCode(void *buffer, CodeMemBlock *origin, CodeMemBlock *relocated, bool branch); + +void GenRelocateCodeAndBranch(void *buffer, CodeMemBlock *origin, CodeMemBlock *relocated); diff --git a/app/src/main/cpp/Dobby/source/InstructionRelocation/arm/InstructionRelocationARM.cc b/app/src/main/cpp/Dobby/source/InstructionRelocation/arm/InstructionRelocationARM.cc new file mode 100644 index 0000000..1e8f15e --- /dev/null +++ b/app/src/main/cpp/Dobby/source/InstructionRelocation/arm/InstructionRelocationARM.cc @@ -0,0 +1,895 @@ +#include "platform_detect_macro.h" + +#if defined(TARGET_ARCH_ARM) + +#include "dobby/dobby_internal.h" + +#include "InstructionRelocation/arm/InstructionRelocationARM.h" + +#include "core/arch/arm/registers-arm.h" +#include "core/assembler/assembler-arm.h" +#include "core/codegen/codegen-arm.h" + +using namespace zz; +using namespace zz::arm; + +typedef struct { + addr_t mapped_addr; + + bool thumb_mode; + + uint8_t *buffer; + uint8_t *buffer_cursor; + size_t buffer_size; + + addr_t src_vmaddr; + addr_t dst_vmaddr; + + CodeMemBlock *relocated; + CodeBuffer *relocated_buffer; + + ExecuteState start_state; + ExecuteState curr_state; + Assembler *curr_assembler; + ThumbTurboAssembler *thumb_assembler; + TurboAssembler *arm_assembler; + + tinystl::unordered_map execute_state_map; + + tinystl::unordered_map relocated_offset_map; + + tinystl::unordered_map label_map; +} relo_ctx_t; + +// --- + +addr_t relo_cur_src_vmaddr(relo_ctx_t *ctx) { + int relocated_len = ctx->buffer_cursor - ctx->buffer; + if (ctx->curr_state == zz::arm::ARMExecuteState) { + return ctx->src_vmaddr + relocated_len + ARM_PC_OFFSET; + } else { + return ctx->src_vmaddr + relocated_len + Thumb_PC_OFFSET; + } +} + +static bool is_thumb2(uint32_t insn) { + uint16_t insn1, insn2; + insn1 = insn & 0x0000ffff; + insn2 = (insn & 0xffff0000) >> 16; + // refer: Top level T32 instruction set encoding + uint32_t op0 = bits(insn1, 13, 15); + uint32_t op1 = bits(insn1, 11, 12); + + if (op0 == 0b111 && op1 != 0b00) { + return true; + } + return false; +} + +bool check_execute_state_changed(relo_ctx_t *ctx, addr_t insn_addr) { + for (auto iter = ctx->execute_state_map.begin(); iter != ctx->execute_state_map.end(); ++iter) { + addr_t execute_state_changed_pc = iter->first; + auto state = iter->second; + if (execute_state_changed_pc == insn_addr) { + return true; + } + } + return false; +} + +static inline int32_t SignExtend(unsigned x, int M, int N) { +#if 1 + char sign_bit = bit(x, M - 1); + unsigned sign_mask = 0 - sign_bit; + x |= ((sign_mask >> M) << M); +#else + x = (long)((long)x << (N - M)) >> (N - M); +#endif + return (int32_t)x; +} + +enum arm_shift_type { arm_shift_lsl, arm_shift_lsr, arm_shift_asr, arm_shift_ror, arm_shift_rrx }; + +uint32_t arm_shift_c(uint32_t val, uint32_t shift_type, uint32_t shift_count, uint32_t carry_in, uint32_t *carry_out) { + if (shift_count == 0) + return val; + uint32_t r_val; + uint32_t carry = carry_in; + switch (shift_type) { + case arm_shift_lsl: + r_val = val; + r_val = r_val << shift_count; + carry = (r_val >> 32) & 0x1; + val = r_val; + break; + case arm_shift_lsr: + r_val = val; + r_val = r_val >> (shift_count - 1); + carry = r_val & 0x1; + val = (r_val >> 1); + break; + case arm_shift_asr: + r_val = val; + if (val & 0x80000000) { + r_val |= 0xFFFFFFFF00000000ULL; + } + r_val = r_val >> (shift_count - 1); + carry = r_val & 0x1; + val = (r_val >> 1); + break; + case arm_shift_ror: + val = (val >> (shift_count % 32)) | (val << (32 - (shift_count % 32))); + carry = (val >> 31); + break; + case arm_shift_rrx: + carry = val & 0x1; + val = (carry_in << 31) | (val >> 1); + break; + break; + } + return val; +} + +uint32_t arm_expand_imm_c(uint32_t imm12) { + uint32_t unrotated_value = bits(imm12, 0, 7); + return arm_shift_c(unrotated_value, arm_shift_ror, 2 * bits(imm12, 8, 11), 0, 0); +} + +uint32_t A32ExpandImm(uint32_t imm12) { + return arm_expand_imm_c(imm12); +} + +static void ARMRelocateSingleInsn(relo_ctx_t *ctx, int32_t insn) { + auto turbo_assembler_ = static_cast(ctx->curr_assembler); +#define _ turbo_assembler_-> + + bool is_insn_relocated = false; + + // top level encoding + uint32_t cond, op0, op1; + cond = bits(insn, 28, 31); + op0 = bits(insn, 25, 27); + op1 = bit(insn, 4); + // Load/Store Word, Unsigned byte (immediate, literal) + if (cond != 0b1111 && op0 == 0b010) { + uint32_t P, U, o2, W, o1, Rn, Rt, imm12; + P = bit(insn, 24); + U = bit(insn, 23); + W = bit(insn, 21); + imm12 = bits(insn, 0, 11); + Rn = bits(insn, 16, 19); + Rt = bits(insn, 12, 15); + o1 = bit(insn, 20); + o2 = bit(insn, 22); + uint32_t P_W = (P << 1) | W; + do { + // LDR (literal) + DEBUG_LOG("%d:relo at %p", ctx->relocated_offset_map.size(), relo_cur_src_vmaddr(ctx)); + if (o1 == 1 && o2 == 0 && P_W != 0b01 && Rn == 0b1111) { + goto load_literal_fix_scheme; + } + if (o1 == 1 && o2 == 1 && P_W != 0b01 && Rn == 0b1111) { + goto load_literal_fix_scheme; + } + break; + load_literal_fix_scheme: + addr32_t dst_vmaddr = 0; + if (U == 0b1) + dst_vmaddr = relo_cur_src_vmaddr(ctx) + imm12; + else + dst_vmaddr = relo_cur_src_vmaddr(ctx) - imm12; + Register regRt = Register::R(Rt); + + auto label = RelocLabel::withData(dst_vmaddr); + _ AppendRelocLabel(label); + + if (regRt.code() == pc.code()) { + _ Ldr(VOLATILE_REGISTER, label); + _ ldr(regRt, MemOperand(VOLATILE_REGISTER)); + } else { + _ Ldr(regRt, label); + _ ldr(regRt, MemOperand(regRt)); + } + + is_insn_relocated = true; + } while (0); + } + + // Data-processing and miscellaneous instructions + if (cond != 0b1111 && (op0 & 0b110) == 0b000) { + uint32_t op0, op1, op2, op3, op4; + op0 = bit(insn, 25); + // Data-processing immediate + if (op0 == 1) { + uint32_t op0, op1; + op0 = bits(insn, 23, 24); + op1 = bits(insn, 20, 21); + // Integer Data Processing (two register and immediate) + if ((op0 & 0b10) == 0b00) { + DEBUG_LOG("%d:relo at %p", ctx->relocated_offset_map.size(), relo_cur_src_vmaddr(ctx)); + + uint32_t opc, S, Rn; + opc = bits(insn, 21, 23); + S = bit(insn, 20); + Rn = bits(insn, 16, 19); + + uint32_t dst_vmaddr = -1; + int Rd = bits(insn, 12, 15); + int imm12 = bits(insn, 0, 11); + uint32_t imm = arm_expand_imm_c(imm12); + if (opc == 0b010 && S == 0b0 && Rn == 0b1111) { // ADR - A2 variant + dst_vmaddr = relo_cur_src_vmaddr(ctx) - imm; + } else if (opc == 0b100 && S == 0b0 && Rn == 0b1111) { // ADR - A1 variant + dst_vmaddr = relo_cur_src_vmaddr(ctx) + imm; + } + + if (dst_vmaddr != -1) { + Register regRd = Register::R(Rd); + auto dst_label = RelocLabel::withData(dst_vmaddr); + _ AppendRelocLabel(dst_label); + + _ Ldr(regRd, dst_label); + + is_insn_relocated = true; + } + } + } + } + + // Branch, branch with link, and block data transfer + if ((op0 & 0b110) == 0b100) { + uint32_t cond, op0; + cond = bits(insn, 28, 31); + op0 = bit(insn, 25); + // Branch (immediate) on page F4-4034 + if (op0 == 1) { + DEBUG_LOG("%d:relo at %p", ctx->relocated_offset_map.size(), relo_cur_src_vmaddr(ctx)); + + uint32_t H = 0, imm24 = 0; + H = bit(insn, 24); + imm24 = bits(insn, 0, 23); + int32_t label = SignExtend(imm24 << 2, 2 + 24, 32); + uint32_t dst_vmaddr = relo_cur_src_vmaddr(ctx) + label; + bool branch_link; + if (cond != 0b1111 && H == 0) { // B + branch_link = false; + } else if (cond != 0b1111 && H == 1) { // BL, BLX (immediate) - A1 on page F5-4135 + branch_link = true; + } else if (cond == 0b1111) { // BL, BLX (immediate) - A2 on page F5-4135 + branch_link = true; + cond = AL; + dst_vmaddr |= 1; + } else + UNREACHABLE(); + + if (branch_link) + _ bl((Condition)cond, 0); // goto [dst_vmaddr] + else + _ b((Condition)cond, 0); // goto [dst_vmaddr] + _ b(4); // goto [rest_flow] + // [dst_vmaddr] + _ ldr(pc, MemOperand(pc, -4)); + _ EmitAddress(dst_vmaddr); + // [rest_flow] + _ mov(r8, r8); + + is_insn_relocated = true; + } + } + + // if the insn do not needed relocate, just rewrite the origin + if (!is_insn_relocated) { + _ EmitARMInst(insn); + } +} + +// relocate thumb-1 instructions +static void Thumb1RelocateSingleInsn(relo_ctx_t *ctx, int16_t insn) { + auto turbo_assembler_ = static_cast(ctx->curr_assembler); +#define _ turbo_assembler_-> + + bool is_insn_relocated = false; + + _ AlignThumbNop(); + + uint32_t op = 0, rt = 0, rm = 0, rn = 0, rd = 0, shift = 0, cond = 0; + int32_t offset = 0; + + int32_t op0 = 0, op1 = 0; + op0 = bits(insn, 10, 15); + // Special data instructions and branch and exchange on page F3-3942 + if (op0 == 0b010001) { + op0 = bits(insn, 8, 9); + // Add, subtract, compare, move (two high registers) + if (op0 != 0b11) { + int rs = bits(insn, 3, 6); + // rs is PC register + if (rs == 15) { + DEBUG_LOG("%d:relo at %p", ctx->relocated_offset_map.size(), + relo_cur_src_vmaddr(ctx)); + + thumb1_inst_t rewrite_inst = insn; + set_bits(rewrite_inst, 3, 6, VOLATILE_REGISTER.code()); + + auto label = ThumbRelocLabelEntry::withData(relo_cur_src_vmaddr(ctx), false); + _ AppendRelocLabel(label); + + _ T2_Ldr(VOLATILE_REGISTER, label); + _ EmitInt16(rewrite_inst); + + is_insn_relocated = true; + } + } + + // Branch and exchange + if (op0 == 0b11) { + int32_t L = bit(insn, 7); + rm = bits(insn, 3, 6); + // BX + if (L == 0b0) { + if (rm == pc.code()) { + DEBUG_LOG("%d:relo at %p", ctx->relocated_offset_map.size(), relo_cur_src_vmaddr(ctx)); + + addr_t dst_vmaddr = relo_cur_src_vmaddr(ctx); + auto label = ThumbRelocLabelEntry::withData(dst_vmaddr, true); + _ AppendRelocLabel(label); + + _ T2_Ldr(pc, label); + + ctx->execute_state_map[dst_vmaddr] = ARMExecuteState; + + is_insn_relocated = true; + } + } + // BLX + if (L == 0b1) { + if (rm == pc.code()) { + DEBUG_LOG("%d:relo at %p", ctx->relocated_offset_map.size(), relo_cur_src_vmaddr(ctx)); + + addr_t dst_vmaddr = relo_cur_src_vmaddr(ctx); + auto label = ThumbRelocLabelEntry::withData(dst_vmaddr, true); + _ AppendRelocLabel(label); + + _ t2_bl(4); + _ t2_b(4); // goto [rest flow] + _ T2_Ldr(pc, label); // goto [dst_vmaddr] + // [rest flow] + + ctx->execute_state_map[dst_vmaddr] = ARMExecuteState; + + is_insn_relocated = true; + } + } + } + } + + // LDR (literal) - T1 variant on page F5-4243 + // ldr literal + if ((insn & 0xf800) == 0x4800) { + DEBUG_LOG("%d:relo at %p", ctx->relocated_offset_map.size(), relo_cur_src_vmaddr(ctx)); + + uint32_t imm8 = bits(insn, 0, 7); + uint32_t imm = imm8 << 2; + addr_t dst_vmaddr = relo_cur_src_vmaddr(ctx) + imm; + dst_vmaddr = ALIGN_FLOOR(dst_vmaddr, 4); + rt = bits(insn, 8, 10); + + auto label = ThumbRelocLabelEntry::withData(dst_vmaddr, false); + _ AppendRelocLabel(label); + + _ T2_Ldr(Register::R(rt), label); + _ t2_ldr(Register::R(rt), MemOperand(Register::R(rt), 0)); + + is_insn_relocated = true; + } + + // Add PC/SP (immediate) on page F3-3939 + // adr + if ((insn & 0xf800) == 0xa000) { + DEBUG_LOG("%d:relo at %p", ctx->relocated_offset_map.size(), relo_cur_src_vmaddr(ctx)); + + rd = bits(insn, 8, 10); + uint32_t imm8 = bits(insn, 0, 7); + int32_t imm32 = imm8 << 2; + addr_t dst_vmaddr = relo_cur_src_vmaddr(ctx) + imm32; + + auto label = ThumbRelocLabelEntry::withData(dst_vmaddr, false); + _ AppendRelocLabel(label); + + _ T2_Ldr(Register::R(rd), label); + + is_insn_relocated = true; + } + + // Conditional branch, and Supervisor Call on page F3-3946 + // b + if ((insn & 0xf000) == 0xd000) { + DEBUG_LOG("%d:relo at %p", ctx->relocated_offset_map.size(), relo_cur_src_vmaddr(ctx)); + + uint16_t cond = bits(insn, 8, 11); + // cond != 111x + if (cond >= 0b1110) { + UNREACHABLE(); + } + uint32_t imm8 = bits(insn, 0, 7); + int32_t imm = SignExtend(imm8 << 1, 8 + 1, 32); + addr_t dst_vmaddr = relo_cur_src_vmaddr(ctx) + imm; + dst_vmaddr |= 1; + + auto label = ThumbRelocLabelEntry::withData(dst_vmaddr, true); + _ AppendRelocLabel(label); + + thumb1_inst_t b_cond_insn = 0xe000; + set_bits(b_cond_insn, 8, 11, cond); + _ EmitInt16(b_cond_insn | (4 >> 1)); + _ t1_nop(); // align + _ t2_b(4); + _ T2_Ldr(pc, label); + + is_insn_relocated = true; + } + + // Miscellaneous 16-bit instructions on page F3-3943 + // CBNZ, CBZ + if ((insn & 0xf500) == 0xb100) { + DEBUG_LOG("%d:relo at %p", ctx->relocated_offset_map.size(), relo_cur_src_vmaddr(ctx)); + + uint32_t imm5 = bits(insn, 3, 7); + uint32_t i = bit(insn, 9); + uint32_t imm = (i << 6) | (imm5 << 1); + addr_t dst_vmaddr = relo_cur_src_vmaddr(ctx) + imm; + + rn = bits(insn, 0, 2); + + auto label = ThumbRelocLabelEntry::withData(dst_vmaddr + 1, true); + _ AppendRelocLabel(label); + + imm5 = bits(0x4, 1, 5); + set_bits(insn, 3, 7, imm5); + i = bit(0x4, 6); + set_bit(insn, 9, i); + _ EmitInt16(insn); + _ t1_nop(); // align + _ t2_b(4); // goto [rest flow] + _ T2_Ldr(pc, label); + // [rest flow] + + is_insn_relocated = true; + } + + // F3.1 + // T32 instruction set encoding + // b + if ((insn & 0xf800) == 0xe000) { + DEBUG_LOG("%d:relo at %p", ctx->relocated_offset_map.size(), relo_cur_src_vmaddr(ctx)); + + uint32_t imm11 = bits(insn, 0, 10); + int32_t imm = SignExtend(imm11 << 1, 11 + 1, 32); + addr_t dst_vmaddr = relo_cur_src_vmaddr(ctx) + imm; + + auto label = ThumbRelocLabelEntry::withData(dst_vmaddr + 1, true); + _ AppendRelocLabel(label); + + _ T2_Ldr(pc, label); + + is_insn_relocated = true; + } + + // if the insn do not needed relocate, just rewrite the origin + if (!is_insn_relocated) { +#if 0 + if (relo_cur_src_vmaddr(ctx) % Thumb2_INST_LEN) + _ t1_nop(); +#endif + _ EmitInt16(insn); + } +} + +static void Thumb2RelocateSingleInsn(relo_ctx_t *ctx, thumb1_inst_t insn1, thumb1_inst_t insn2) { + auto turbo_assembler_ = static_cast(ctx->curr_assembler); +#define _ turbo_assembler_-> + + bool is_insn_relocated = false; + + // if (turbo_assembler->pc_offset() % 4) { + // _ t1_nop(); + // } + + _ AlignThumbNop(); + + // Branches and miscellaneous control on page F3-3979 + if ((insn1 & 0xf800) == 0xf000 && (insn2 & 0x8000) == 0x8000) { + uint32_t op1 = 0, op3 = 0; + op1 = bits(insn1, 6, 9); + op3 = bits(insn2, 12, 14); + + // B - T3 variant on page F5-4118 + if (((op1 & 0b1110) != 0b1110) && ((op3 & 0b101) == 0b000)) { + DEBUG_LOG("%d:relo at %p", ctx->relocated_offset_map.size(), relo_cur_src_vmaddr(ctx)); + + uint32_t S = bit(insn1, 10); + uint32_t J1 = bit(insn2, 13); + uint32_t J2 = bit(insn2, 11); + uint32_t imm6 = bits(insn1, 0, 5); + uint32_t imm11 = bits(insn2, 0, 10); + + int32_t imm = + SignExtend((S << 20) | (J2 << 19) | (J1 << 18) | (imm6 << 12) | (imm11 << 1), 1 + 1 + 1 + 6 + 11 + 1, 32); + addr_t dst_vmaddr = relo_cur_src_vmaddr(ctx) + imm; + dst_vmaddr |= 1; + + uint32_t cond = bits(insn1, 6, 9); + thumb1_inst_t b_cond_insn = 0xe000; + set_bits(b_cond_insn, 8, 11, cond); + _ EmitInt16(b_cond_insn | (4 >> 1)); + _ t1_nop(); // align + _ t2_b(8); + _ t2_ldr(pc, MemOperand(pc, 0)); + _ EmitAddress(dst_vmaddr); + + is_insn_relocated = true; + } + + // B - T4 variant on page F5-4118 + if ((op3 & 0b101) == 0b001) { + DEBUG_LOG("%d:relo at %p", ctx->relocated_offset_map.size(), relo_cur_src_vmaddr(ctx)); + + uint32_t S = bit(insn1, 10); + uint32_t J1 = bit(insn2, 13); + uint32_t J2 = bit(insn2, 11); + uint32_t imm10 = bits(insn1, 0, 9); + uint32_t imm11 = bits(insn2, 0, 10); + uint32_t i1 = !(J1 ^ S); + uint32_t i2 = !(J2 ^ S); + + int32_t imm = + SignExtend((S << 24) | (i1 << 23) | (i2 << 22) | (imm10 << 12) | (imm11 << 1), 1 + 1 + 1 + 10 + 11 + 1, 32); + addr_t dst_vmaddr = relo_cur_src_vmaddr(ctx) + imm; + dst_vmaddr |= 1; + + _ t2_ldr(pc, MemOperand(pc, 0)); + _ EmitAddress(dst_vmaddr); + + is_insn_relocated = true; + } + + // BL, BLX (immediate) - T1 variant on page F5-4135 + if ((op3 & 0b101) == 0b101) { + DEBUG_LOG("%d:relo at %p", ctx->relocated_offset_map.size(), relo_cur_src_vmaddr(ctx)); + + uint32_t S = bit(insn1, 10); + uint32_t J1 = bit(insn2, 13); + uint32_t J2 = bit(insn2, 11); + uint32_t i1 = !(J1 ^ S); + uint32_t i2 = !(J2 ^ S); + uint32_t imm11 = bits(insn2, 0, 10); + uint32_t imm10 = bits(insn1, 0, 9); + int32_t imm = + SignExtend((S << 24) | (i1 << 23) | (i2 << 22) | (imm10 << 12) | (imm11 << 1), 1 + 1 + 1 + 10 + 11 + 1, 32); + addr_t dst_vmaddr = relo_cur_src_vmaddr(ctx) + imm; + dst_vmaddr |= 1; + + _ t2_bl(4); + _ t2_b(8); + _ t2_ldr(pc, MemOperand(pc, 0)); + _ EmitAddress(dst_vmaddr); + + is_insn_relocated = true; + } + + // BL, BLX (immediate) - T2 variant on page F5-4136 + if ((op3 & 0b101) == 0b100) { + DEBUG_LOG("%d:relo at %p", ctx->relocated_offset_map.size(), relo_cur_src_vmaddr(ctx)); + + uint32_t S = bit(insn1, 10); + uint32_t J1 = bit(insn2, 13); + uint32_t J2 = bit(insn2, 11); + uint32_t i1 = !(J1 ^ S); + uint32_t i2 = !(J2 ^ S); + uint32_t imm10h = bits(insn1, 0, 9); + uint32_t imm10l = bits(insn2, 1, 10); + int32_t imm = + SignExtend((S << 24) | (i1 << 23) | (i2 << 22) | (imm10h << 12) | (imm10l << 2), 1 + 1 + 1 + 10 + 10 + 1, 32); + addr_t dst_vmaddr = relo_cur_src_vmaddr(ctx); + dst_vmaddr = ALIGN_FLOOR(dst_vmaddr, 4); + dst_vmaddr += imm; + + _ t2_bl(4); + _ t2_b(8); + _ t2_ldr(pc, MemOperand(pc, 0)); + _ EmitAddress(dst_vmaddr); + + is_insn_relocated = true; + } + } + + // Data-processing (plain binary immediate) on page F3-3983 + if ((insn1 & (0xfa10)) == 0xf200 & (insn2 & 0x8000) == 0) { + uint32_t op0 = 0, op1 = 0; + op0 = bit(insn1, 8); + op1 = bits(insn2, 5, 6); + + // Data-processing (simple immediate) + if (op0 == 0 && (op1 & 0b10) == 0b00) { + int o1 = bit(insn1, 7); + int o2 = bit(insn1, 5); + int rn = bits(insn1, 0, 3); + + // ADR + if (((o1 == 0 && o2 == 0) || (o1 == 1 && o2 == 1)) && rn == 0b1111) { + uint32_t i = bit(insn1, 10); + uint32_t imm3 = bits(insn2, 12, 14); + uint32_t imm8 = bits(insn2, 0, 7); + uint32_t rd = bits(insn2, 8, 11); + uint32_t imm = (i << 11) | (imm3 << 8) | imm8; + + addr_t dst_vmaddr = 0; + if (o1 == 0 && o2 == 0) { // ADR - T3 on page F5-4098 + dst_vmaddr = relo_cur_src_vmaddr(ctx) + imm; + } else if (o1 == 1 && o2 == 1) { // ADR - T2 on page F5-4097 + dst_vmaddr = relo_cur_src_vmaddr(ctx) - imm; + } else { + UNREACHABLE(); + } + + _ t2_ldr(Register::R(rd), MemOperand(pc, 4)); + _ t2_b(0); + _ EmitAddress(dst_vmaddr); + + is_insn_relocated = true; + } + } + } + + // Load/store single on page F3-3988 + // Load, unsigned (literal) on page F3-3992 + // Load, signed (literal) on page F3-3996 + // LDR literal (T2) + if ((insn1 & 0xff7f) == 0xf85f) { + uint32_t U = bit(insn1, 7); + uint32_t imm12 = bits(insn2, 0, 11); + uint16_t rt = bits(insn2, 12, 15); + + uint32_t imm = imm12; + + addr_t dst_vmaddr = 0; + if (U == 1) { + dst_vmaddr = relo_cur_src_vmaddr(ctx) + imm; + } else { + dst_vmaddr = relo_cur_src_vmaddr(ctx) - imm; + } + + Register regRt = Register::R(rt); + + _ t2_ldr(regRt, MemOperand(pc, 8)); + _ t2_ldr(regRt, MemOperand(regRt, 0)); + _ t2_b(4); + _ EmitAddress(dst_vmaddr); + + is_insn_relocated = true; + } + + // if the insn not needed relocate, just rewrite the origin + if (!is_insn_relocated) { +#if 0 + if (relo_cur_src_vmaddr(ctx) % Thumb2_INST_LEN) + _ t1_nop(); +#endif + _ EmitInt16(insn1); + _ EmitInt16(insn2); + } +} + +void gen_arm_relocate_code(relo_ctx_t *ctx) { + +#undef _ +#define _ turbo_assembler_-> + auto turbo_assembler_ = static_cast(ctx->curr_assembler); +#define _ turbo_assembler_-> + + auto relocated_buffer = turbo_assembler_->GetCodeBuffer(); + + DEBUG_LOG("[arm] ARM relocate %d start >>>>>", ctx->buffer_size); + + while (ctx->buffer_cursor < ctx->buffer + ctx->buffer_size) { + uint32_t orig_off = ctx->buffer_cursor - ctx->buffer; + uint32_t relocated_off = relocated_buffer->GetBufferSize(); + ctx->relocated_offset_map[orig_off] = relocated_off; + + arm_inst_t insn = *(arm_inst_t *)ctx->buffer_cursor; + + int last_relo_offset = turbo_assembler_->GetCodeBuffer()->GetBufferSize(); + + ARMRelocateSingleInsn(ctx, insn); + DEBUG_LOG("[arm] Relocate arm insn: 0x%x", insn); + + // move to next instruction + ctx->buffer_cursor += ARM_INST_LEN; + + // execute state changed + addr32_t next_insn_addr = relo_cur_src_vmaddr(ctx) - ARM_PC_OFFSET; + if (check_execute_state_changed(ctx, next_insn_addr)) { + break; + } + } + + bool is_relocate_interrupted = ctx->buffer_cursor < ctx->buffer + ctx->buffer_size; + if (is_relocate_interrupted) { + turbo_assembler_->SetExecuteState(ThumbExecuteState); + } +} + +void gen_thumb_relocate_code(relo_ctx_t *ctx) { + int relocated_insn_count = 0; + + auto turbo_assembler_ = static_cast(ctx->curr_assembler); +#define _ turbo_assembler_-> + + auto relocated_buffer = turbo_assembler_->GetCodeBuffer(); + + DEBUG_LOG("[arm] Thumb relocate %d start >>>>>", ctx->buffer_size); + + while (ctx->buffer_cursor < ctx->buffer + ctx->buffer_size) { + uint32_t orig_off = ctx->buffer_cursor - ctx->buffer; + uint32_t relocated_off = relocated_buffer->GetBufferSize(); + ctx->relocated_offset_map[orig_off] = relocated_off; + + // align nop + _ t1_nop(); + + thumb2_inst_t insn = *(thumb2_inst_t *)ctx->buffer_cursor; + + int last_relo_offset = relocated_buffer->GetBufferSize(); + if (is_thumb2(insn)) { + Thumb2RelocateSingleInsn(ctx, (uint16_t)insn, (uint16_t)(insn >> 16)); + DEBUG_LOG("[arm] Relocate thumb2 insn: 0x%x", insn); + } else { + Thumb1RelocateSingleInsn(ctx, (uint16_t)insn); + DEBUG_LOG("[arm] Relocate thumb1 insn: 0x%x", (uint16_t)insn); + } + + // Move to next instruction + if (is_thumb2(insn)) { + ctx->buffer_cursor += Thumb2_INST_LEN; + } else { + ctx->buffer_cursor += Thumb1_INST_LEN; + } + + // execute state changed + addr32_t next_insn_addr = relo_cur_src_vmaddr(ctx) - Thumb_PC_OFFSET; + if (check_execute_state_changed(ctx, next_insn_addr)) { + break; + } + } + + // .thumb1 bx pc + // .thumb1 mov r8, r8 + // .arm ldr pc, [pc, #-4] + + bool is_relocate_interrupted = ctx->buffer_cursor < ctx->buffer + ctx->buffer_size; + if (is_relocate_interrupted) { + turbo_assembler_->SetExecuteState(ARMExecuteState); + } +} + +void GenRelocateCode(void *buffer, CodeMemBlock *origin, CodeMemBlock *relocated, bool branch) { + relo_ctx_t ctx; + + if ((addr_t)buffer % 2) { + ctx.start_state = ThumbExecuteState; + ctx.curr_state = ThumbExecuteState; + // remove thumb address flag + buffer = (void *)((addr_t)buffer - 1); + } else { + ctx.start_state = ARMExecuteState; + ctx.curr_state = ARMExecuteState; + } + + ctx.buffer = ctx.buffer_cursor = (uint8_t *)buffer; + ctx.buffer_size = origin->size; + + ctx.src_vmaddr = (addr_t)origin->addr; + ctx.dst_vmaddr = 0; + + auto *relocated_buffer = new CodeBuffer(); + ctx.relocated_buffer = relocated_buffer; + + ThumbTurboAssembler thumb_turbo_assembler_(0, ctx.relocated_buffer); +#define thumb_ thumb_turbo_assembler_. + TurboAssembler arm_turbo_assembler_(0, ctx.relocated_buffer); +#define arm_ arm_turbo_assembler_. + + if (ctx.start_state == ThumbExecuteState) + ctx.curr_assembler = &thumb_turbo_assembler_; + else + ctx.curr_assembler = &arm_turbo_assembler_; + +relocate_remain: + if (ctx.curr_state == ThumbExecuteState) { + ctx.curr_assembler = &thumb_turbo_assembler_; + gen_thumb_relocate_code(&ctx); + if (thumb_turbo_assembler_.GetExecuteState() == ARMExecuteState) { + // translate interrupt as execute state changed + bool is_translate_interrupted = ctx.buffer_cursor < ctx.buffer + ctx.buffer_size; + if (is_translate_interrupted) { + // add nop to align ARM + if (thumb_turbo_assembler_.pc_offset() % 4) + thumb_turbo_assembler_.t1_nop(); + goto relocate_remain; + } + } + } else { + ctx.curr_assembler = &arm_turbo_assembler_; + gen_arm_relocate_code(&ctx); + if (arm_turbo_assembler_.GetExecuteState() == ThumbExecuteState) { + bool is_translate_interrupted = ctx.buffer_cursor < ctx.buffer + ctx.buffer_size; + // translate interrupt as execute state changed + if (is_translate_interrupted) { + goto relocate_remain; + } + } + } + + // update origin + int new_origin_len = (addr_t)ctx.buffer_cursor - (addr_t)ctx.buffer; + origin->reset(origin->addr, new_origin_len); + + // TODO: if last insn is unlink branch, skip + if (branch) { + if (ctx.curr_state == ThumbExecuteState) { + // branch to the rest of instructions + thumb_ AlignThumbNop(); + thumb_ t2_ldr(pc, MemOperand(pc, 0)); + // get the real branch address + thumb_ EmitAddress(origin->addr + origin->size + THUMB_ADDRESS_FLAG); + } else { + // branch to the rest of instructions + CodeGen codegen(&arm_turbo_assembler_); + // get the real branch address + codegen.LiteralLdrBranch(origin->addr + origin->size); + } + } + + // fixup the insn branch into trampoline(has been modified) + arm_turbo_assembler_.RelocLabelFixup(&ctx.relocated_offset_map); + thumb_turbo_assembler_.RelocLabelFixup(&ctx.relocated_offset_map); + + // realize all the pseudo data label + thumb_turbo_assembler_.RelocBind(); + arm_turbo_assembler_.RelocBind(); + + // generate executable code + { + // assembler without specific memory address + auto relocated_mem = MemoryAllocator::SharedAllocator()->allocateExecMemory(relocated_buffer->GetBufferSize()); + if (relocated_mem == nullptr) + return; + + thumb_turbo_assembler_.SetRealizedAddress((void *)relocated_mem); + arm_turbo_assembler_.SetRealizedAddress((void *)relocated_mem); + + AssemblyCode *code = NULL; + code = AssemblyCodeBuilder::FinalizeFromTurboAssembler(ctx.curr_assembler); + relocated->reset(code->addr, code->size); + } + + // thumb + if (ctx.start_state == ThumbExecuteState) { + // add thumb address flag + relocated->reset(relocated->addr + THUMB_ADDRESS_FLAG, relocated->size); + } + + // clean + { + thumb_turbo_assembler_.ClearCodeBuffer(); + arm_turbo_assembler_.ClearCodeBuffer(); + + delete relocated_buffer; + } +} + +void GenRelocateCodeAndBranch(void *buffer, CodeMemBlock *origin, CodeMemBlock *relocated) { + GenRelocateCode(buffer, origin, relocated, true); +} + +#endif diff --git a/app/src/main/cpp/Dobby/source/InstructionRelocation/arm/InstructionRelocationARM.h b/app/src/main/cpp/Dobby/source/InstructionRelocation/arm/InstructionRelocationARM.h new file mode 100644 index 0000000..ed289aa --- /dev/null +++ b/app/src/main/cpp/Dobby/source/InstructionRelocation/arm/InstructionRelocationARM.h @@ -0,0 +1,307 @@ +#pragma once +#include "dobby/dobby_internal.h" + +#include "core/arch/arm/constants-arm.h" +#include "core/assembler/assembler-arm.h" + +namespace zz { +namespace arm { + +// thumb1/thumb2 pseudo label type, only support Thumb1-Ldr | Thumb2-Ldr +enum ref_label_type_t { kThumb1Ldr, kThumb2LiteralLdr }; + +// custom thumb pseudo label for thumb/thumb2 +class ThumbPseudoLabel : public AssemblerPseudoLabel { +public: + ThumbPseudoLabel(addr_t addr) : AssemblerPseudoLabel(addr) { + } + + // fix the instruction which not link to the label yet. + void link_confused_instructions(CodeBuffer *buffer) { + CodeBuffer *_buffer; + if (buffer) + _buffer = buffer; + + for (auto &ref_label_insn : ref_label_insns_) { + // instruction offset to label + thumb2_inst_t insn = _buffer->LoadThumb2Inst(ref_label_insn.pc_offset); + thumb1_inst_t insn1 = _buffer->LoadThumb1Inst(ref_label_insn.pc_offset); + thumb1_inst_t insn2 = _buffer->LoadThumb1Inst(ref_label_insn.pc_offset + sizeof(thumb1_inst_t)); + + switch (ref_label_insn.link_type) { + case kThumb1Ldr: { + UNREACHABLE(); + } break; + case kThumb2LiteralLdr: { + int64_t pc = ref_label_insn.pc_offset + Thumb_PC_OFFSET; + assert(pc % 4 == 0); + int32_t imm12 = pos() - pc; + + if (imm12 > 0) { + set_bit(insn1, 7, 1); + } else { + set_bit(insn1, 7, 0); + imm12 = -imm12; + } + set_bits(insn2, 0, 11, imm12); + _buffer->RewriteThumb1Inst(ref_label_insn.pc_offset, insn1); + _buffer->RewriteThumb1Inst(ref_label_insn.pc_offset + Thumb1_INST_LEN, insn2); + + DEBUG_LOG("[thumb label link] insn offset %d link offset %d", ref_label_insn.pc_offset, imm12); + } break; + default: + UNREACHABLE(); + break; + } + } + } +}; + +class ThumbRelocLabelEntry : public ThumbPseudoLabel, public RelocLabel { +public: + ThumbRelocLabelEntry(bool is_pc_register) : RelocLabel(), ThumbPseudoLabel(0), is_pc_register_(is_pc_register) { + } + + template static ThumbRelocLabelEntry *withData(T value, bool is_pc_register) { + auto label = new ThumbRelocLabelEntry(is_pc_register); + label->setData(value); + return label; + } + + bool is_pc_register() { + return is_pc_register_; + } + +private: + bool is_pc_register_; +}; + +// --- + +class ThumbAssembler : public Assembler { +public: + ThumbAssembler(void *address) : Assembler(address) { + this->SetExecuteState(ThumbExecuteState); + } + + ThumbAssembler(void *address, CodeBuffer *buffer) : Assembler(address, buffer) { + this->SetExecuteState(ThumbExecuteState); + } + + void EmitInt16(int16_t val) { + buffer_->Emit16(val); + } + + void Emit2Int16(int16_t val1, int16_t val2) { + EmitInt16(val1); + EmitInt16(val2); + } + + void EmitAddress(uint32_t value) { + buffer_->Emit32(value); + } + + // ===== + void t1_nop() { + EmitInt16(0xbf00); + } + void t1_b(int32_t imm) { + ASSERT(CheckSignLength(imm, 12)); + ASSERT(CheckAlign(imm, 2)); + + int32_t imm11 = bits(imm >> 1, 0, 10); + EmitInt16(0xe000 | imm11); + } + + // ===== + void t2_b(uint32_t imm) { + EmitThumb2Branch(AL, imm, false); + } + void t2_bl(uint32_t imm) { + EmitThumb2Branch(AL, imm, true); + } + void t2_blx(uint32_t imm) { + UNIMPLEMENTED(); + } + + // ===== + void t2_ldr(Register dst, const MemOperand &src) { + // WARNNING: literal ldr, base = ALIGN(pc, 4) + EmitThumb2LoadStore(true, dst, src); + } + +private: + void EmitThumb2LoadLiteral(Register rt, const MemOperand x) { + bool add = true; + uint32_t U, imm12; + int32_t offset = x.offset(); + +#if 0 + // literal ldr, base = ALIGN(pc, 4) + if (rt.Is(pc)) { + // TODO: convert to `GetRealizedAddress()` ??? + addr_t curr_pc = pc_offset() + (addr_t)GetRealizedAddress(); + if (curr_pc % 4) { + t1_nop(); + } + } +#endif + + if (offset > 0) { + U = B7; + imm12 = offset; + } else { + U = 0; + imm12 = -offset; + } + EmitInt16(0xf85f | U); + EmitInt16(0x0 | (rt.code() << 12) | imm12); + } + void EmitThumb2LoadStore(bool load, Register rt, const MemOperand x) { + if (x.rn().Is(pc)) { + EmitThumb2LoadLiteral(rt, x); + return; + } + + bool index, add, wback; + if (x.IsRegisterOffset() && x.offset() >= 0) { + index = true, add = true, wback = false; + uint32_t imm12 = x.offset(); + EmitInt16(0xf8d0 | (x.rn().code() << 0)); + EmitInt16(0x0 | (rt.code() << 12) | imm12); + } else { + // use bit accelerate + uint32_t P = 0, W = 0, U = 0; + uint32_t imm8 = x.offset() > 0 ? x.offset() : -x.offset(); + U = x.offset() > 0 ? 0 : B9; + if (x.IsPostIndex()) { + P = 0, W = B8; + } else if (x.IsPreIndex()) { + P = B10, W = B8; + } + index = (P == B10); + add = (U == B9); + wback = (W == B8); + EmitInt16(0xf850 | (x.rn().code() << 0)); + EmitInt16(0x0800 | (rt.code() << 12) | P | U | W | imm8); + } + } + + void EmitThumb2Branch(Condition cond, int32_t imm, bool link) { + uint32_t operand = imm >> 1; + ASSERT(CheckSignLength(operand, 25)); + ASSERT(CheckAlign(operand, 2)); + + uint32_t signbit = (imm >> 31) & 0x1; + uint32_t i1 = (operand >> 22) & 0x1; + uint32_t i2 = (operand >> 21) & 0x1; + uint32_t imm10 = (operand >> 11) & 0x03ff; + uint32_t imm11 = operand & 0x07ff; + uint32_t j1 = (!(i1 ^ signbit)); + uint32_t j2 = (!(i2 ^ signbit)); + + if (cond != AL) { + UNIMPLEMENTED(); + } + + EmitInt16(0xf000 | LeftShift(signbit, 1, 10) | LeftShift(imm10, 10, 0)); + if (link) { + // Not use LeftShift(1, 1, 14), and use B14 for accelerate + EmitInt16(0x9000 | LeftShift(j1, 1, 13) | (LeftShift(j2, 1, 11)) | LeftShift(imm11, 11, 0) | B14); + } else { + EmitInt16(0x9000 | LeftShift(j1, 1, 13) | (LeftShift(j2, 1, 11)) | LeftShift(imm11, 11, 0)); + } + } +}; + +// --- + +class ThumbTurboAssembler : public ThumbAssembler { +public: + ThumbTurboAssembler(void *address) : ThumbAssembler(address) { + } + + ThumbTurboAssembler(void *address, CodeBuffer *buffer) : ThumbAssembler(address, buffer) { + } + + ~ThumbTurboAssembler() { + } + + void T1_Ldr(Register rt, ThumbPseudoLabel *label) { + UNREACHABLE(); + +// t1_ldr: rt can't be PC register +// === +#if 0 + if (label->is_bound()) { + const int64_t dest = label->pos() - buffer_.Size(); + ldr(rt, MemOperand(pc, dest)); + } else { + // record this ldr, and fix later. + label->link_to(buffer_.Size(), ThumbPseudoLabel::kThumb1Ldr); + ldr(rt, MemOperand(pc, 0)); + } +#endif + } + + void T2_Ldr(Register rt, ThumbPseudoLabel *label) { + if (label->pos()) { + int offset = label->pos() - buffer_->GetBufferSize(); + t2_ldr(rt, MemOperand(pc, offset)); + } else { + // record this ldr, and fix later. + label->link_to(kThumb2LiteralLdr, buffer_->GetBufferSize()); + t2_ldr(rt, MemOperand(pc, 0)); + } + } + + void AlignThumbNop() { + addr32_t pc = this->GetCodeBuffer()->GetBufferSize() + (uintptr_t)GetRealizedAddress(); + if (pc % Thumb2_INST_LEN) { + t1_nop(); + } else { + } + } + + // --- + + void PseudoBind(ThumbPseudoLabel *label) { + const addr_t bound_pc = buffer_->GetBufferSize(); + label->bind_to(bound_pc); + // If some instructions have been wrote, before the label bound, we need link these `confused` instructions + if (label->has_confused_instructions()) { + label->link_confused_instructions(GetCodeBuffer()); + } + } + + void RelocBind() { + for (auto *data_label : data_labels_) { + PseudoBind(data_label); + reinterpret_cast(buffer_)->EmitBuffer(data_label->data_, data_label->data_size_); + } + } + + void AppendRelocLabel(ThumbRelocLabelEntry *label) { + data_labels_.push_back(label); + } + + void RelocLabelFixup(tinystl::unordered_map *relocated_offset_map) { + for (auto *data_label : data_labels_) { + auto val = data_label->data(); + auto iter = relocated_offset_map->find(val); + if (iter != relocated_offset_map->end()) { + data_label->fixupData(iter->second); + } + } + } + +private: + tinystl::vector data_labels_; +}; + +#if 0 +void GenRelocateCodeAndBranch(void *buffer, CodeMemBlock *origin, CodeMemBlock *relocated); +#endif + +} // namespace arm +} // namespace zz diff --git a/app/src/main/cpp/Dobby/source/InstructionRelocation/arm64/InstructionRelocationARM64.cc b/app/src/main/cpp/Dobby/source/InstructionRelocation/arm64/InstructionRelocationARM64.cc new file mode 100644 index 0000000..899ac9e --- /dev/null +++ b/app/src/main/cpp/Dobby/source/InstructionRelocation/arm64/InstructionRelocationARM64.cc @@ -0,0 +1,366 @@ +#include "platform_detect_macro.h" + +#if defined(TARGET_ARCH_ARM64) + +#include "InstructionRelocation/arm64/InstructionRelocationARM64.h" + +#include "dobby/dobby_internal.h" + +#include "core/arch/arm64/registers-arm64.h" +#include "core/assembler/assembler-arm64.h" +#include "core/codegen/codegen-arm64.h" + +#include "inst_constants.h" +#include "inst_decode_encode_kit.h" + +using namespace zz::arm64; + +#if defined(DOBBY_DEBUG) +#define debug_nop() _ nop() +#else +#define debug_nop() +#endif + +#define arm64_trunc_page(x) ((x) & (~(0x1000 - 1))) +#define arm64_round_page(x) trunc_page((x) + (0x1000 - 1)) + +typedef struct { + addr_t mapped_addr; + + uint8_t *buffer; + uint8_t *buffer_cursor; + size_t buffer_size; + + addr_t src_vmaddr; + addr_t dst_vmaddr; + + CodeMemBlock *origin; + CodeMemBlock *relocated; + + tinystl::unordered_map relocated_offset_map; + + tinystl::unordered_map label_map; + +} relo_ctx_t; + +// --- + +addr_t relo_cur_src_vmaddr(relo_ctx_t *ctx) { + return ctx->src_vmaddr + (ctx->buffer_cursor - ctx->buffer); +} + +addr_t relo_cur_dst_vmaddr(relo_ctx_t *ctx, TurboAssembler *assembler) { + return ctx->dst_vmaddr + assembler->GetCodeBuffer()->GetBufferSize(); +} + +addr_t relo_src_offset_to_vmaddr(relo_ctx_t *ctx, off_t offset) { + return ctx->src_vmaddr + offset; +} + +addr_t relo_dst_offset_to_vmaddr(relo_ctx_t *ctx, off_t offset) { + return ctx->dst_vmaddr + offset; +} + +// --- + +#if 0 +bool has_relo_label_at(relo_ctx_t *ctx, addr_t addr) { + if (ctx->label_map.count(addr)) { + return true; + } + return false; +} + +AssemblerPseudoLabel *relo_label_create_or_get(relo_ctx_t *ctx, addr_t addr) { + if (!ctx->label_map.count(addr)) { + auto *label = new AssemblerPseudoLabel(addr); + ctx->label_map[addr] = label; + } + return ctx->label_map[addr]; +} + +int64_t relo_label_link_offset(relo_ctx_t *ctx, pcrel_type_t pcrel_type, int64_t offset) { + auto is_offset_undefined = [ctx](int64_t offset) -> bool { + if (ctx->buffer_cursor + offset < ctx->buffer || ctx->buffer_cursor + offset > ctx->buffer + ctx->buffer_size) { + return true; + } + return false; + }; + + auto is_offset_uninitialized = [ctx](int64_t offset) -> bool { + if (ctx->buffer_cursor + offset > ctx->buffer && ctx->buffer_cursor + offset < ctx->buffer + ctx->buffer_size) { + if (!ctx->relocated_offset_map.count(ctx->buffer_cursor + offset - ctx->buffer_cursor)) + return true; + } + return false; + }; + + addr_t label_vmaddr = relo_cur_src_vmaddr(ctx) + offset; + if (pcrel_type == RELO_ARM64_RELOC_PAGE21) { + label_vmaddr = arm64_trunc_page(label_vmaddr); + } + + auto *label = relo_label_create_or_get(ctx, label_vmaddr); + if (is_offset_undefined(offset)) { // pc relative target is beyond our scope + label->link_to(AssemblerPseudoLabel::kLabelImm19, relo_cur_src_vmaddr(ctx), (addr_t)ctx->buffer_cursor - ctx->mapped_addr); + return 0; + } else if (is_offset_uninitialized(offset)) { // pc relative target is in our control, but not handle yet + label->link_to(AssemblerPseudoLabel::kLabelImm19, relo_cur_src_vmaddr(ctx), (addr_t)ctx->buffer_cursor - ctx->mapped_addr); + return 0; + } else { // pc relative target is already handled + off_t off = ctx->buffer_cursor + offset - ctx->buffer; + off_t relocated_off = label->pos(); + int64_t new_offset = relo_dst_offset_to_vmaddr(ctx, relocated_off) - relo_src_offset_to_vmaddr(ctx, off); + return new_offset; + } +} +#endif + +// --- + +static inline bool inst_is_b_bl(uint32_t instr) { + return (instr & UnconditionalBranchFixedMask) == UnconditionalBranchFixed; +} + +static inline bool inst_is_ldr_literal(uint32_t instr) { + return ((instr & LoadRegLiteralFixedMask) == LoadRegLiteralFixed); +} + +static inline bool inst_is_adr(uint32_t instr) { + return (instr & PCRelAddressingFixedMask) == PCRelAddressingFixed && (instr & PCRelAddressingMask) == ADR; +} + +static inline bool inst_is_adrp(uint32_t instr) { + return (instr & PCRelAddressingFixedMask) == PCRelAddressingFixed && (instr & PCRelAddressingMask) == ADRP; +} + +static inline bool inst_is_b_cond(uint32_t instr) { + return (instr & ConditionalBranchFixedMask) == ConditionalBranchFixed; +} + +static inline bool inst_is_compare_b(uint32_t instr) { + return (instr & CompareBranchFixedMask) == CompareBranchFixed; +} + +static inline bool inst_is_test_b(uint32_t instr) { + return (instr & TestBranchFixedMask) == TestBranchFixed; +} + +// --- + +int relo_relocate(relo_ctx_t *ctx, bool branch) { + int relocated_insn_count = 0; + + TurboAssembler turbo_assembler_(0); +#define _ turbo_assembler_. + + auto relocated_buffer = turbo_assembler_.GetCodeBuffer(); + + while (ctx->buffer_cursor < ctx->buffer + ctx->buffer_size) { + uint32_t orig_off = ctx->buffer_cursor - ctx->buffer; + uint32_t relocated_off = relocated_buffer->GetBufferSize(); + ctx->relocated_offset_map[orig_off] = relocated_off; + +#if 0 + addr_t inst_vmaddr = 0; + inst_vmaddr = relo_cur_src_vmaddr(ctx); + if (has_relo_label_at(ctx, inst_vmaddr)) { + auto *label = relo_label_create_or_get(ctx, inst_vmaddr); + label->bind_to(inst_vmaddr); + } +#endif + + arm64_inst_t inst = *(arm64_inst_t *)ctx->buffer_cursor; + if (inst_is_b_bl(inst)) { + DEBUG_LOG("%d:relo at %p", relocated_insn_count++, relo_cur_src_vmaddr(ctx)); + + int64_t offset = decode_imm26_offset(inst); + addr_t dst_vmaddr = relo_cur_src_vmaddr(ctx) + offset; + + auto dst_label = RelocLabel::withData(dst_vmaddr); + _ AppendRelocLabel(dst_label); + + { + _ Ldr(TMP_REG_0, dst_label); + if ((inst & UnconditionalBranchMask) == BL) { + _ blr(TMP_REG_0); + } else { + _ br(TMP_REG_0); + } + } + + } else if (inst_is_ldr_literal(inst)) { + DEBUG_LOG("%d:relo at %p", relocated_insn_count++, relo_cur_src_vmaddr(ctx)); + + int64_t offset = decode_imm19_offset(inst); + addr_t dst_vmaddr = relo_cur_src_vmaddr(ctx) + offset; + + int rt = decode_rt(inst); + char opc = bits(inst, 30, 31); + + { + _ Mov(TMP_REG_0, dst_vmaddr); + if (opc == 0b00) + _ ldr(W(rt), MemOperand(TMP_REG_0, 0)); + else if (opc == 0b01) + _ ldr(X(rt), MemOperand(TMP_REG_0, 0)); + else { + UNIMPLEMENTED(); + } + } + } else if (inst_is_adr(inst)) { + DEBUG_LOG("%d:relo at %p", relocated_insn_count++, relo_cur_src_vmaddr(ctx)); + + int64_t offset = decode_immhi_immlo_offset(inst); + addr_t dst_vmaddr = relo_cur_src_vmaddr(ctx) + offset; + + int rd = decode_rd(inst); + + { + _ Mov(X(rd), dst_vmaddr); + ; + } + } else if (inst_is_adrp(inst)) { + DEBUG_LOG("%d:relo at %p", relocated_insn_count++, relo_cur_src_vmaddr(ctx)); + + int64_t offset = decode_immhi_immlo_zero12_offset(inst); + addr_t dst_vmaddr = relo_cur_src_vmaddr(ctx) + offset; + dst_vmaddr = arm64_trunc_page(dst_vmaddr); + + int rd = decode_rd(inst); + + { + _ Mov(X(rd), dst_vmaddr); + ; + } + } else if (inst_is_b_cond(inst)) { + DEBUG_LOG("%d:relo at %p", relocated_insn_count++, relo_cur_src_vmaddr(ctx)); + + int64_t offset = decode_imm19_offset(inst); + addr_t dst_vmaddr = relo_cur_src_vmaddr(ctx) + offset; + + arm64_inst_t branch_instr = inst; + { + char cond = bits(inst, 0, 3); + cond = cond ^ 1; + set_bits(branch_instr, 0, 3, cond); + + int64_t offset = 4 * 3; + uint32_t imm19 = offset >> 2; + set_bits(branch_instr, 5, 23, imm19); + } + + auto dst_label = RelocLabel::withData(dst_vmaddr); + _ AppendRelocLabel(dst_label); + + { + _ Emit(branch_instr); + { + _ Ldr(TMP_REG_0, dst_label); + _ br(TMP_REG_0); + } + } + } else if (inst_is_compare_b(inst)) { + DEBUG_LOG("%d:relo at %p", relocated_insn_count++, relo_cur_src_vmaddr(ctx)); + + int64_t offset = decode_imm19_offset(inst); + addr_t dst_vmaddr = relo_cur_src_vmaddr(ctx) + offset; + + arm64_inst_t branch_instr = inst; + { + char op = bit(inst, 24); + op = op ^ 1; + set_bit(branch_instr, 24, op); + + int64_t offset = 4 * 3; + uint32_t imm19 = offset >> 2; + set_bits(branch_instr, 5, 23, imm19); + } + + auto dst_label = RelocLabel::withData(dst_vmaddr); + _ AppendRelocLabel(dst_label); + + { + _ Emit(branch_instr); + { + _ Ldr(TMP_REG_0, dst_label); + _ br(TMP_REG_0); + } + } + } else if (inst_is_test_b(inst)) { + DEBUG_LOG("%d:relo at %p", relocated_insn_count++, relo_cur_src_vmaddr(ctx)); + + int64_t offset = decode_imm14_offset(inst); + addr_t dst_vmaddr = relo_cur_src_vmaddr(ctx) + offset; + + arm64_inst_t branch_instr = inst; + { + char op = bit(inst, 24); + op = op ^ 1; + set_bit(branch_instr, 24, op); + + int64_t offset = 4 * 3; + uint32_t imm14 = offset >> 2; + set_bits(branch_instr, 5, 18, imm14); + } + + auto dst_label = RelocLabel::withData(dst_vmaddr); + _ AppendRelocLabel(dst_label); + + { + _ Emit(branch_instr); + { + _ Ldr(TMP_REG_0, dst_label); + _ br(TMP_REG_0); + } + } + } else { + _ Emit(inst); + } + + ctx->buffer_cursor += sizeof(arm64_inst_t); + } +#undef _ + + // update origin + int new_origin_len = (addr_t)ctx->buffer_cursor - (addr_t)ctx->buffer; + ctx->origin->reset(ctx->origin->addr, new_origin_len); + + // TODO: if last instr is unlink branch, ignore it + if (branch) { + CodeGen codegen(&turbo_assembler_); + codegen.LiteralLdrBranch(ctx->origin->addr + ctx->origin->size); + } + + // Bind all labels + turbo_assembler_.RelocBind(); + + // Generate executable code + { + auto code = AssemblyCodeBuilder::FinalizeFromTurboAssembler(&turbo_assembler_); + ctx->relocated = code; + } + return 0; +} + +void GenRelocateCode(void *buffer, CodeMemBlock *origin, CodeMemBlock *relocated, bool branch) { + relo_ctx_t ctx = {0}; + + ctx.buffer = ctx.buffer_cursor = (uint8_t *)buffer; + ctx.buffer_size = origin->size; + + ctx.src_vmaddr = (addr_t)origin->addr; + ctx.dst_vmaddr = (addr_t)relocated->addr; + + ctx.origin = origin; + + relo_relocate(&ctx, branch); + + relocated->reset(ctx.relocated->addr, ctx.relocated->size); +} + +void GenRelocateCodeAndBranch(void *buffer, CodeMemBlock *origin, CodeMemBlock *relocated) { + GenRelocateCode(buffer, origin, relocated, true); +} + +#endif diff --git a/app/src/main/cpp/Dobby/source/InstructionRelocation/arm64/InstructionRelocationARM64.h b/app/src/main/cpp/Dobby/source/InstructionRelocation/arm64/InstructionRelocationARM64.h new file mode 100644 index 0000000..226d3ad --- /dev/null +++ b/app/src/main/cpp/Dobby/source/InstructionRelocation/arm64/InstructionRelocationARM64.h @@ -0,0 +1,13 @@ +#pragma once + +#include "dobby/dobby_internal.h" + +#include "core/arch/arm64/constants-arm64.h" + +#if 0 +namespace zz { +namespace arm64 { +void GenRelocateCodeAndBranch(void *buffer, CodeMemBlock *origin, CodeMemBlock *relocated); +} // namespace arm64 +} // namespace zz +#endif \ No newline at end of file diff --git a/app/src/main/cpp/Dobby/source/InstructionRelocation/arm64/inst_constants.h b/app/src/main/cpp/Dobby/source/InstructionRelocation/arm64/inst_constants.h new file mode 100644 index 0000000..228a952 --- /dev/null +++ b/app/src/main/cpp/Dobby/source/InstructionRelocation/arm64/inst_constants.h @@ -0,0 +1,49 @@ +#pragma once + +#if 0 +enum LoadRegLiteralOp { + LoadRegLiteralFixed = 0x18000000, + LoadRegLiteralFixedMask = 0x3B000000, + LoadRegLiteralMask = 0xFF000000, +}; + +// PC relative addressing. +enum PCRelAddressingOp { + PCRelAddressingFixed = 0x10000000, + PCRelAddressingFixedMask = 0x1F000000, + PCRelAddressingMask = 0x9F000000, + ADR = PCRelAddressingFixed | 0x00000000, + ADRP = PCRelAddressingFixed | 0x80000000 +}; + +// Unconditional branch. +enum UnconditionalBranchOp { + UnconditionalBranchFixed = 0x14000000, + UnconditionalBranchFixedMask = 0x7C000000, + UnconditionalBranchMask = 0xFC000000, + + B = UnconditionalBranchFixed | 0x00000000, + BL = UnconditionalBranchFixed | 0x80000000 +}; +#endif + +// Compare and branch. +enum CompareBranchOp { + CompareBranchFixed = 0x34000000, + CompareBranchFixedMask = 0x7E000000, + CompareBranchMask = 0xFF000000, +}; + +// Conditional branch. +enum ConditionalBranchOp { + ConditionalBranchFixed = 0x54000000, + ConditionalBranchFixedMask = 0xFE000000, + ConditionalBranchMask = 0xFF000010, +}; + +// Test and branch. +enum TestBranchOp { + TestBranchFixed = 0x36000000, + TestBranchFixedMask = 0x7E000000, + TestBranchMask = 0x7F000000, +}; \ No newline at end of file diff --git a/app/src/main/cpp/Dobby/source/InstructionRelocation/arm64/inst_decode_encode_kit.h b/app/src/main/cpp/Dobby/source/InstructionRelocation/arm64/inst_decode_encode_kit.h new file mode 100644 index 0000000..cfae889 --- /dev/null +++ b/app/src/main/cpp/Dobby/source/InstructionRelocation/arm64/inst_decode_encode_kit.h @@ -0,0 +1,110 @@ +#pragma once + +#include "dobby/common.h" + +static inline int64_t SignExtend(unsigned long x, int M, int N) { +#if 1 + char sign_bit = bit(x, M - 1); + unsigned long sign_mask = 0 - sign_bit; + x |= ((sign_mask >> M) << M); +#else + x = (long)((long)x << (N - M)) >> (N - M); +#endif + return (int64_t)x; +} + +static inline int64_t decode_imm14_offset(uint32_t instr) { + int64_t offset; + { + int64_t imm14 = bits(instr, 5, 18); + offset = (imm14 << 2); + } + offset = SignExtend(offset, 2 + 14, 64); + return offset; +} +static inline uint32_t encode_imm14_offset(uint32_t instr, int64_t offset) { + uint32_t imm14 = bits((offset >> 2), 0, 13); + set_bits(instr, 5, 18, imm14); + return instr; +} + +static inline int64_t decode_imm19_offset(uint32_t instr) { + int64_t offset; + { + int64_t imm19 = bits(instr, 5, 23); + offset = (imm19 << 2); + } + offset = SignExtend(offset, 2 + 19, 64); + return offset; +} + +static inline uint32_t encode_imm19_offset(uint32_t instr, int64_t offset) { + uint32_t imm19 = bits((offset >> 2), 0, 18); + set_bits(instr, 5, 23, imm19); + return instr; +} + +static inline int64_t decode_imm26_offset(uint32_t instr) { + int64_t offset; + { + int64_t imm26 = bits(instr, 0, 25); + offset = (imm26 << 2); + } + offset = SignExtend(offset, 2 + 26, 64); + return offset; +} +static inline uint32_t encode_imm26_offset(uint32_t instr, int64_t offset) { + uint32_t imm26 = bits((offset >> 2), 0, 25); + set_bits(instr, 0, 25, imm26); + return instr; +} + +static inline int64_t decode_immhi_immlo_offset(uint32_t instr) { + typedef uint32_t instr_t; + struct { + instr_t Rd : 5; // Destination register + instr_t immhi : 19; // 19-bit upper immediate + instr_t dummy_0 : 5; // Must be 10000 == 0x10 + instr_t immlo : 2; // 2-bit lower immediate + instr_t op : 1; // 0 = ADR, 1 = ADRP + } instr_decode; + + *(instr_t *)&instr_decode = instr; + + int64_t imm = instr_decode.immlo + (instr_decode.immhi << 2); + imm = SignExtend(imm, 2 + 19, 64); + return imm; +} +static inline uint32_t encode_immhi_immlo_offset(uint32_t instr, int64_t offset) { + struct { + uint32_t Rd : 5; // Destination register + uint32_t immhi : 19; // 19-bit upper immediate + uint32_t dummy_0 : 5; // Must be 10000 == 0x10 + uint32_t immlo : 2; // 2-bit lower immediate + uint32_t op : 1; // 0 = ADR, 1 = ADRP + } instr_decode; + + *(uint32_t *)&instr_decode = instr; + instr_decode.immlo = bits(offset, 0, 2); + instr_decode.immhi = bits(offset, 2, 2 + 19); + + return *(uint32_t *)&instr_decode; +} + +static inline int64_t decode_immhi_immlo_zero12_offset(uint32_t instr) { + int64_t imm = decode_immhi_immlo_offset(instr); + imm = imm << 12; + return imm; +} +static inline uint32_t encode_immhi_immlo_zero12_offset(uint32_t instr, int64_t offset) { + offset = (offset >> 12); + return encode_immhi_immlo_offset(instr, offset); +} + +static inline int decode_rt(uint32_t instr) { + return bits(instr, 0, 4); +} + +static inline int decode_rd(uint32_t instr) { + return bits(instr, 0, 4); +} \ No newline at end of file diff --git a/app/src/main/cpp/Dobby/source/InstructionRelocation/x64/InstructionRelocationX64.cc b/app/src/main/cpp/Dobby/source/InstructionRelocation/x64/InstructionRelocationX64.cc new file mode 100644 index 0000000..d9d78fd --- /dev/null +++ b/app/src/main/cpp/Dobby/source/InstructionRelocation/x64/InstructionRelocationX64.cc @@ -0,0 +1,79 @@ +#include "platform_detect_macro.h" + +#if defined(TARGET_ARCH_X64) + +#include "dobby/dobby_internal.h" + +#include "InstructionRelocation/x64/InstructionRelocationX64.h" +#include "InstructionRelocation/x86/x86_insn_decode/x86_insn_decode.h" + +#include "core/arch/x64/registers-x64.h" +#include "core/assembler/assembler-x64.h" +#include "core/codegen/codegen-x64.h" + +using namespace zz::x64; + +int GenRelocateCodeFixed(void *buffer, CodeMemBlock *origin, CodeMemBlock *relocated, bool branch) { + TurboAssembler turbo_assembler_(0); + // Set fixed executable code chunk address + turbo_assembler_.SetRealizedAddress((void *)relocated->addr); +#define _ turbo_assembler_. +#define __ turbo_assembler_.GetCodeBuffer()-> + + auto curr_orig_ip = (addr64_t)origin->addr; + auto curr_relo_ip = (addr64_t)relocated->addr; + + auto buffer_cursor = (uint8_t *)buffer; + + int predefined_relocate_size = origin->size; + + while ((buffer_cursor < ((uint8_t *)buffer + predefined_relocate_size))) { + x86_insn_decode_t insn = {0}; + memset(&insn, 0, sizeof(insn)); + GenRelocateSingleX86Insn(curr_orig_ip, curr_relo_ip, buffer_cursor, &turbo_assembler_, + turbo_assembler_.GetCodeBuffer(), insn, 64); + + // go next + curr_orig_ip += insn.length; + buffer_cursor += insn.length; + curr_relo_ip = (addr64_t)relocated->addr + turbo_assembler_.ip_offset(); + } + + // jmp to the origin rest instructions + if (branch) { + CodeGen codegen(&turbo_assembler_); + // TODO: 6 == jmp [RIP + disp32] instruction size + addr64_t stub_addr = curr_relo_ip + 6; + codegen.JmpNearIndirect(stub_addr); + turbo_assembler_.GetCodeBuffer()->Emit64(curr_orig_ip); + } + + // update origin + int new_origin_len = curr_orig_ip - (addr_t)origin->addr; + origin->reset(origin->addr, new_origin_len); + + int relo_len = turbo_assembler_.GetCodeBuffer()->GetBufferSize(); + if (relo_len > relocated->size) { + DEBUG_LOG("pre-alloc code chunk not enough"); + return -1; + } + + // generate executable code + { + auto code = AssemblyCodeBuilder::FinalizeFromTurboAssembler(&turbo_assembler_); + relocated->reset(code->addr, code->size); + delete code; + } + + return 0; +} + +void GenRelocateCodeAndBranch(void *buffer, CodeMemBlock *origin, CodeMemBlock *relocated) { + GenRelocateCode(buffer, origin, relocated, true); +} + +void GenRelocateCode(void *buffer, CodeMemBlock *origin, CodeMemBlock *relocated, bool branch) { + GenRelocateCodeX86Shared(buffer, origin, relocated, branch); +} + +#endif diff --git a/app/src/main/cpp/Dobby/source/InstructionRelocation/x64/InstructionRelocationX64.h b/app/src/main/cpp/Dobby/source/InstructionRelocation/x64/InstructionRelocationX64.h new file mode 100644 index 0000000..bad483c --- /dev/null +++ b/app/src/main/cpp/Dobby/source/InstructionRelocation/x64/InstructionRelocationX64.h @@ -0,0 +1,9 @@ +#pragma once + +#include "dobby/common.h" + +#include "core/arch/x64/constants-x64.h" + +#include "MemoryAllocator/AssemblyCodeBuilder.h" + +#include "InstructionRelocation/x86/InstructionRelocationX86Shared.h" diff --git a/app/src/main/cpp/Dobby/source/InstructionRelocation/x86/InstructionRelocationX86.cc b/app/src/main/cpp/Dobby/source/InstructionRelocation/x86/InstructionRelocationX86.cc new file mode 100644 index 0000000..2e84552 --- /dev/null +++ b/app/src/main/cpp/Dobby/source/InstructionRelocation/x86/InstructionRelocationX86.cc @@ -0,0 +1,80 @@ +#include "platform_detect_macro.h" + +#if defined(TARGET_ARCH_IA32) + +#include "dobby/dobby_internal.h" + +#include "InstructionRelocation/x86/InstructionRelocationX86.h" +#include "InstructionRelocation/x86/x86_insn_decode/x86_insn_decode.h" + +#include "core/arch/x86/registers-x86.h" +#include "core/assembler/assembler-ia32.h" +#include "core/codegen/codegen-ia32.h" + +using namespace zz::x86; + +int GenRelocateCodeFixed(void *buffer, CodeMemBlock *origin, CodeMemBlock *relocated, bool branch) { + TurboAssembler turbo_assembler_(0); + // Set fixed executable code chunk address + turbo_assembler_.SetRealizedAddress((void *)relocated->addr); +#define _ turbo_assembler_. +#define __ turbo_assembler_.GetCodeBuffer()-> + + auto curr_orig_ip = (addr32_t)origin->addr; + auto curr_relo_ip = (addr32_t)relocated->addr; + + uint8_t *buffer_cursor = (uint8_t *)buffer; + + x86_options_t conf = {0}; + conf.mode = 32; + + int predefined_relocate_size = origin->size; + + while ((buffer_cursor < ((uint8_t *)buffer + predefined_relocate_size))) { + x86_insn_decode_t insn = {0}; + memset(&insn, 0, sizeof(insn)); + GenRelocateSingleX86Insn(curr_orig_ip, curr_relo_ip, buffer_cursor, &turbo_assembler_, + turbo_assembler_.GetCodeBuffer(), insn, 64); + + // go next + curr_orig_ip += insn.length; + buffer_cursor += insn.length; + curr_relo_ip = (addr32_t)relocated->addr + turbo_assembler_.ip_offset(); + } + + // jmp to the origin rest instructions + if (branch) { + CodeGen codegen(&turbo_assembler_); + addr32_t stub_addr = curr_relo_ip + 6; + codegen.JmpNear(curr_orig_ip); + } + + // update origin + int new_origin_len = curr_orig_ip - (addr_t)origin->addr; + origin->reset(origin->addr, new_origin_len); + + int relo_len = turbo_assembler_.GetCodeBuffer()->GetBufferSize(); + if (relo_len > relocated->size) { + DEBUG_LOG("pre-alloc code chunk not enough"); + return -1; + } + + // generate executable code + { + auto code = AssemblyCodeBuilder::FinalizeFromTurboAssembler(&turbo_assembler_); + relocated->reset(code->addr, code->size); + delete code; + } + + return 0; +} + +void GenRelocateCodeAndBranch(void *buffer, CodeMemBlock *origin, CodeMemBlock *relocated) { + GenRelocateCode(buffer, origin, relocated, true); +} + +void GenRelocateCode(void *buffer, CodeMemBlock *origin, CodeMemBlock *relocated, bool branch) { + GenRelocateCodeX86Shared(buffer, origin, relocated, branch); +} + +#endif diff --git a/app/src/main/cpp/Dobby/source/InstructionRelocation/x86/InstructionRelocationX86.h b/app/src/main/cpp/Dobby/source/InstructionRelocation/x86/InstructionRelocationX86.h new file mode 100644 index 0000000..b554e48 --- /dev/null +++ b/app/src/main/cpp/Dobby/source/InstructionRelocation/x86/InstructionRelocationX86.h @@ -0,0 +1,9 @@ +#pragma once + +#include "dobby/common.h" + +#include "core/arch/x86/constants-x86.h" + +#include "MemoryAllocator/AssemblyCodeBuilder.h" + +#include "InstructionRelocation/x86/InstructionRelocationX86Shared.h" diff --git a/app/src/main/cpp/Dobby/source/InstructionRelocation/x86/InstructionRelocationX86Shared.cc b/app/src/main/cpp/Dobby/source/InstructionRelocation/x86/InstructionRelocationX86Shared.cc new file mode 100644 index 0000000..7df7038 --- /dev/null +++ b/app/src/main/cpp/Dobby/source/InstructionRelocation/x86/InstructionRelocationX86Shared.cc @@ -0,0 +1,218 @@ +#include "platform_detect_macro.h" + +#if defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_X64) + +#include "dobby/dobby_internal.h" + +#include "InstructionRelocation/x86/InstructionRelocationX86.h" +#include "InstructionRelocation/x86/x86_insn_decode/x86_insn_decode.h" +#include "MemoryAllocator/NearMemoryAllocator.h" + +using namespace zz::x86; + +// x64 jmp absolute address +inline void codegen_x64_jmp_absolute_addr(CodeBufferBase *buffer, addr_t target) { + // jmp *(rip) + buffer->Emit8(0xFF); + buffer->Emit8(0x25); // ModR/M: 00 100 101 + buffer->Emit32(0x00); + // .long target + buffer->Emit64(target); +} + +// simple impl for ReloLabel +inline void emit_rel32_label(CodeBufferBase *buffer, uint32_t last_offset, addr_t curr_relo_ip, addr_t orig_dst_ip) { + addr_t curr_offset = buffer->GetBufferSize(); + uint32_t relo_insn_len = curr_offset + sizeof(uint32_t) - last_offset; + addr_t relo_ip = curr_relo_ip + relo_insn_len; + int32_t new_offset = orig_dst_ip - relo_ip; + buffer->Emit32(new_offset); +} + +int GenRelocateSingleX86Insn(addr_t curr_orig_ip, addr_t curr_relo_ip, uint8_t *buffer_cursor, AssemblerBase *assembler, + CodeBufferBase *code_buffer, x86_insn_decode_t &insn, int8_t mode) { +#define __ code_buffer-> + + int relocated_insn_len = -1; + + x86_options_t conf = {0}; + conf.mode = mode; + + // decode x86/x64 insn + x86_insn_decode(&insn, (uint8_t *)buffer_cursor, &conf); + + // x86 ip register == next instruction address + curr_orig_ip = curr_orig_ip + insn.length; + + auto last_relo_offset = code_buffer->GetBufferSize(); + + static auto x86_insn_encode_start = 0; + static auto x86_insn_encoded_len = 0; + auto x86_insn_encode_begin = [&] { x86_insn_encode_start = code_buffer->GetBufferSize(); }; + auto x86_insn_encode_end = [&] { x86_insn_encoded_len = code_buffer->GetBufferSize() - x86_insn_encode_start; }; + + if (insn.primary_opcode >= 0x70 && insn.primary_opcode <= 0x7F) { // jcc rel8 + DEBUG_LOG("[x86 relo] %p: jc rel8", buffer_cursor); + + int8_t offset = insn.immediate; + addr_t orig_dst_ip = curr_orig_ip + offset; +#if defined(TARGET_ARCH_IA32) + uint8_t opcode = 0x80 | (insn.primary_opcode & 0x0f); + + x86_insn_encode_begin(); + __ Emit8(0x0F); + __ Emit8(opcode); + emit_rel32_label(code_buffer, x86_insn_encode_start, curr_relo_ip, orig_dst_ip); +#else + // jcc_true stage 1 + const uint8_t label_jcc_cond_true_stage2 = 2; + __ Emit8(insn.primary_opcode); + __ Emit8(label_jcc_cond_true_stage2); + + // jcc_false + const uint8_t label_cond_false = 6 + 8; + __ Emit8(0xEB); + __ Emit8(label_cond_false); + + // jcc_true stage 2, jmp to orig dst + codegen_x64_jmp_absolute_addr(code_buffer, orig_dst_ip); +#endif + + } else if (mode == 64 && (insn.flags & X86_INSN_DECODE_FLAG_IP_RELATIVE) && + (insn.operands[1].mem.base == RIP)) { // RIP + DEBUG_LOG("[x86 relo] %p: rip", buffer_cursor); + + int32_t orig_disp = insn.operands[1].mem.disp; + addr_t orig_dst_ip = curr_orig_ip + orig_disp; + + addr_t rip_insn_seq_addr = 0; + { + + uint32_t jmp_near_range = (uint32_t)2 * 1024 * 1024 * 1024; + auto rip_insn_seq = (addr_t)NearMemoryAllocator::SharedAllocator()->allocateNearExecMemory( + insn.length + 6 + 8, orig_dst_ip, jmp_near_range); + + rip_insn_seq_addr = rip_insn_seq; + } + + // jmp *(rip) => jmp to [rip insn seq] + x86_insn_encode_begin(); + __ Emit8(0xFF); + __ Emit8(0x25); // ModR/M: 00 100 101 + __ Emit32(0); + __ Emit64(rip_insn_seq_addr); + x86_insn_encode_end(); + + { + auto rip_insn_seq_buffer = CodeBufferBase(); +#define ___ rip_insn_seq_buffer. + + auto rip_insn_req_ip = rip_insn_seq_addr; + rip_insn_req_ip = rip_insn_req_ip + insn.length; // next insn addr + int32_t new_disp = (int32_t)(orig_dst_ip - rip_insn_req_ip); + + // keep orig insn opcode + ___ EmitBuffer(buffer_cursor, insn.displacement_offset); + ___ Emit32(new_disp); + // keep orig insn immediate + if (insn.immediate_offset) { + ___ EmitBuffer((buffer_cursor + insn.immediate_offset), insn.length - insn.immediate_offset); + } + + // jmp *(rip) => back to relo process + auto relo_next_ip = curr_relo_ip + x86_insn_encoded_len; + codegen_x64_jmp_absolute_addr(&rip_insn_seq_buffer, relo_next_ip); + + DobbyCodePatch((void *)rip_insn_seq_addr, rip_insn_seq_buffer.GetBuffer(), rip_insn_seq_buffer.GetBufferSize()); + } + + } else if (insn.primary_opcode == 0xEB) { // jmp rel8 + DEBUG_LOG("[x86 relo] %p: jmp rel8", buffer_cursor); + + int8_t offset = insn.immediate; + addr_t orig_dst_ip = curr_orig_ip + offset; + +#if defined(TARGET_ARCH_IA32) + x86_insn_encode_begin(); + __ Emit8(0xE9); + emit_rel32_label(code_buffer, x86_insn_encode_start, curr_relo_ip, orig_dst_ip); +#else + // jmp *(rip) + codegen_x64_jmp_absolute_addr(code_buffer, orig_dst_ip); +#endif + } else if (insn.primary_opcode == 0xE8 || insn.primary_opcode == 0xE9) { // call or jmp rel32 + DEBUG_LOG("[x86 relo] %p:jmp or call rel32", buffer_cursor); + + int32_t offset = insn.immediate; + addr_t orig_dst_ip = curr_orig_ip + offset; + + assert(insn.immediate_offset == 1); + +#if defined(TARGET_ARCH_IA32) + x86_insn_encode_begin(); + + __ EmitBuffer(buffer_cursor, insn.immediate_offset); + emit_rel32_label(code_buffer, x86_insn_encode_start, curr_relo_ip, orig_dst_ip); +#else + __ Emit8(0xFF); + if (insn.primary_opcode == 0xE8) { + // call *(rip + 2) + __ Emit8(0x15); // ModR/M: 00 010 101 + __ Emit32(2); + + // jmp 8 + __ Emit8(0xEB); + __ Emit8(0x08); + + // dst + __ Emit64(orig_dst_ip); + } else { + // jmp *(rip) + __ Emit8(0x25); // ModR/M: 00 100 101 + __ Emit32(0); + + // dst + __ Emit64(orig_dst_ip); + } +#endif + } else if (insn.primary_opcode >= 0xE0 && insn.primary_opcode <= 0xE2) { // LOOPNZ/LOOPZ/LOOP/JECXZ + // LOOP/LOOPcc + UNIMPLEMENTED(); + } else if (insn.primary_opcode == 0xE3) { + // JCXZ JCEXZ JCRXZ + UNIMPLEMENTED(); + } else { + __ EmitBuffer(buffer_cursor, insn.length); + } + + // insn -> relocated insn + { + int relo_offset = code_buffer->GetBufferSize(); + int relo_len = relo_offset - last_relo_offset; + DEBUG_LOG("insn -> relocated insn: %d -> %d", insn.length, relo_len); + } + return relocated_insn_len; +} + +void GenRelocateCodeX86Shared(void *buffer, CodeMemBlock *origin, CodeMemBlock *relocated, bool branch) { + int expected_relocated_mem_size = 32; +x86_try_again: + if (!relocated->addr) { + auto relocated_mem = MemoryAllocator::SharedAllocator()->allocateExecMemory(expected_relocated_mem_size); + if (relocated_mem == nullptr) { + return; + } + relocated->reset((addr_t)relocated_mem, expected_relocated_mem_size); + } + + int ret = GenRelocateCodeFixed(buffer, origin, relocated, branch); + if (ret != 0) { + const int step_size = 16; + expected_relocated_mem_size += step_size; + relocated->reset(0, 0); + + goto x86_try_again; + } +} + +#endif diff --git a/app/src/main/cpp/Dobby/source/InstructionRelocation/x86/InstructionRelocationX86Shared.h b/app/src/main/cpp/Dobby/source/InstructionRelocation/x86/InstructionRelocationX86Shared.h new file mode 100644 index 0000000..249d75b --- /dev/null +++ b/app/src/main/cpp/Dobby/source/InstructionRelocation/x86/InstructionRelocationX86Shared.h @@ -0,0 +1,14 @@ +#pragma once + +#include "dobby/common.h" + +#include "MemoryAllocator/AssemblyCodeBuilder.h" + +#include "x86_insn_decode/x86_insn_decode.h" + +int GenRelocateCodeFixed(void *buffer, CodeMemBlock *origin, CodeMemBlock *relocated, bool branch); + +void GenRelocateCodeX86Shared(void *buffer, CodeMemBlock *origin, CodeMemBlock *relocated, bool branch); + +int GenRelocateSingleX86Insn(addr_t curr_orig_ip, addr_t curr_relo_ip, uint8_t *buffer_cursor, AssemblerBase *assembler, + CodeBufferBase *code_buffer, x86_insn_decode_t &insn, int8_t mode); \ No newline at end of file diff --git a/app/src/main/cpp/Dobby/source/InstructionRelocation/x86/deprecated/Ia32Disassembler.cc b/app/src/main/cpp/Dobby/source/InstructionRelocation/x86/deprecated/Ia32Disassembler.cc new file mode 100644 index 0000000..f1bb1ae --- /dev/null +++ b/app/src/main/cpp/Dobby/source/InstructionRelocation/x86/deprecated/Ia32Disassembler.cc @@ -0,0 +1,388 @@ +#include +#include + +#include "logging/logging.h" + +enum SegmentPrefix { + kCs = 0x2e, + kSs = 0x36, + kDs = 0x3e, + kEs = 0x26, + kFs = 0x64, + kGs = 0x65, +}; + +bool supports_rex_ = false; + +void DecodeInstruction(uint8_t *instr) { + bool have_prefixes = true; + uint8_t prefix[4] = {0, 0, 0, 0}; + + // decode legacy prefix + do { + switch (*instr) { + // Group 1 - lock and repeat prefixes: + case 0xF0: + case 0xF2: + case 0xF3: + prefix[0] = *instr; + break; + // Group 2 - segment override prefixes: + case kCs: + case kSs: + case kDs: + case kEs: + case kFs: + case kGs: + prefix[1] = *instr; + break; + // Group 3 - operand size override: + case 0x66: + prefix[2] = *instr; + break; + // Group 4 - address size override: + case 0x67: + prefix[3] = *instr; + break; + default: + have_prefixes = false; + break; + } + if (have_prefixes) { + instr++; + } + } while (have_prefixes); + + // x64 rex + uint8_t rex = (supports_rex_ && (*instr >= 0x40) && (*instr <= 0x4F)) ? *instr : 0; + if (rex != 0) { + instr++; + } + + bool has_modrm = false; + bool reg_is_opcode = false; + + size_t immediate_bytes = 0; + +#define OpEn_MR \ + do { \ + has_modrm = true; \ + } while (0); \ + break; + +#define OpEn_RM \ + do { \ + has_modrm = true; \ + } while (0); \ + break; + +#define OpEn_I(immediate_size) \ + do { \ + immediate_bytes = immediate_size; \ + } while (0); \ + break; + +#define OpEn_RMI(immediate_size) \ + do { \ + immediate_bytes = immediate_size; \ + } while (0); \ + break; + +#define OpEn_O \ + do { \ + reg_is_opcode = true; \ + } while (0); \ + break; + +#define OpEn_D \ + do { \ + reg_is_opcode = true; \ + } while (0); \ + break; + +#define OpEn_ZO \ + do { \ + reg_is_opcode = true; \ + } while (0); \ + break; + +#define Op_Prefix \ + do { \ + reg_is_opcode = true; \ + } while (0); \ + break; + +#define UnImplOpcode \ + do { \ + DEBUG_LOG("opcode unreachable"); \ + } while (0); \ + break; + + typedef enum { + MR, + } OpEnTy; + + // decode opcode + switch (*instr) { + case 0x00: + OpEn_MR; + case 0x01: + OpEn_MR; + case 0x02: + OpEn_RM; + case 0x03: + OpEn_RM; + case 0x04: + OpEn_I(8); + case 0x05: + OpEn_I(16 | 32); + + case 0x06: + case 0x07: + UnImplOpcode; + + case 0x08: + OpEn_MR; + case 0x09: + OpEn_MR; + case 0x0a: + OpEn_RM; + case 0x0b: + OpEn_RM; + case 0x0c: + OpEn_I(8); + case 0x0d: + OpEn_I(16 | 32); + + case 0x0e: + case 0x0f: + UnImplOpcode; + + case 0x10: + OpEn_MR; + case 0x11: + OpEn_MR; + case 0x12: + OpEn_RM; + case 0x13: + OpEn_RM; + case 0x14: + OpEn_I(8); + case 0x15: + OpEn_I(16 | 32); + + case 0x16: + case 0x17: + UnImplOpcode; + + case 0x18: + OpEn_MR; + case 0x19: + OpEn_MR; + case 0x1a: + OpEn_RM; + case 0x1b: + OpEn_RM; + case 0x1c: + OpEn_I(8); + case 0x1d: + OpEn_I(16 | 32); + + case 0x1e: + case 0x1f: + UnImplOpcode; + + case 0x20: + OpEn_MR; + case 0x21: + OpEn_MR; + case 0x22: + OpEn_RM; + case 0x23: + OpEn_RM; + case 0x24: + OpEn_I(8); + case 0x25: + OpEn_I(16 | 32); + + case 0x26: + case 0x27: + UnImplOpcode; + + case 0x28: + OpEn_MR; + case 0x29: + OpEn_MR; + case 0x2a: + OpEn_RM; + case 0x2b: + OpEn_RM; + case 0x2c: + OpEn_I(8); + case 0x2d: + OpEn_I(16 | 32); + + case 0x2e: + case 0x2f: + UnImplOpcode; + + case 0x30: + OpEn_MR; + case 0x31: + OpEn_MR; + case 0x32: + OpEn_RM; + case 0x33: + OpEn_RM; + case 0x34: + OpEn_I(8); + case 0x35: + OpEn_I(16 | 32); + + case 0x36: + case 0x37: + UnImplOpcode; + + case 0x38: + OpEn_MR; + case 0x39: + OpEn_MR; + case 0x3a: + OpEn_RM; + case 0x3b: + OpEn_RM; + case 0x3c: + OpEn_I(8); + case 0x3d: + OpEn_I(16 | 32); + + case 0x40: + case 0x41: + case 0x42: + case 0x43: + case 0x44: + case 0x45: + case 0x46: + case 0x47: + case 0x48: + case 0x49: + case 0x4a: + case 0x4b: + case 0x4c: + case 0x4d: + case 0x4e: + case 0x4f: + UnImplOpcode; + + case 0x50: + case 0x51: + case 0x52: + case 0x53: + case 0x54: + case 0x55: + case 0x56: + case 0x57: + case 0x58: + case 0x59: + case 0x5A: + case 0x5B: + case 0x5C: + case 0x5D: + case 0x5E: + case 0x5F: + OpEn_O; + + case 0x60: + case 0x61: + case 0x62: + UnImplOpcode; + + case 0x63: + if ((rex & REX_W) != 0) { + OpEn_RM; + }; + break; + + case 0x64: + case 0x65: + case 0x66: + case 0x67: + Op_Prefix; + + case 0x68: + OpEn_I(16 | 32); + + case 0x69: + OpEn_RMI(16 | 32); + + case 0x6a: + OpEn_I(8); + + case 0x6b: + OpEn_RMI(8); + + case 0x70: + case 0x71: + case 0x72: + case 0x73: + case 0x74: + case 0x75: + case 0x76: + case 0x77: + case 0x78: + case 0x79: + case 0x7A: + case 0x7B: + case 0x7C: + case 0x7D: + case 0x7E: + case 0x7F: + OpEn_D; + + case 0x80: + case 0x81: + case 0x82: + case 0x83: + case 0x84: + case 0x85: + UnImplOpcode; + + case 0x86: + case 0x87: + OpEn_RM; + + case 0x88: + case 0x89: + case 0x8a: + case 0x8b: + OpEn_RM; + + case 0x8c: + case 0x8d: + case 0x8e: + case 0x8f: + case 0x90: + case 0x91: + case 0x92: + case 0x93: + case 0x94: + case 0x95: + case 0x96: + case 0x97: + case 0x98: + case 0x99: + case 0x9a: + case 0x9b: + case 0x9c: + UnImplOpcode; + + case 0x9d: + OpEn_ZO; + + case 0x0f: + DecodeExtendedOpcode + } +} + +void DecodeExtendedOpcode(uint8_t *instr) { +} \ No newline at end of file diff --git a/app/src/main/cpp/Dobby/source/InstructionRelocation/x86/deprecated/X86OpcodoDecodeTable.cc b/app/src/main/cpp/Dobby/source/InstructionRelocation/x86/deprecated/X86OpcodoDecodeTable.cc new file mode 100644 index 0000000..800badf --- /dev/null +++ b/app/src/main/cpp/Dobby/source/InstructionRelocation/x86/deprecated/X86OpcodoDecodeTable.cc @@ -0,0 +1,604 @@ +#include "platform_detect_macro.h" +#if defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_X64) + +#include "./X86OpcodoDecodeTable.h" + +// clang-format on + +#define _xUnknownOpHanlder -1, -1, OpSz_0, ImmSz_0, _UnknownOpHanlder +void _UnknownOpHanlder(InstrMnemonic *instr, addr_t p) { + // printf("Unknown Operand\n"); + return; +} + +#define _xInvalidOpHanlder -1, -1, OpSz_0, ImmSz_0, _InValidOpHanlder +void _InValidOpHanlder(InstrMnemonic *instr, addr_t p) { + // printf("Invalid Operand\n"); + return; +} + +inline void _ContinueDispatch(InstrMnemonic *instr, addr_t p) { + OpcodeDecodeItem *item = &OpcodeDecodeTable[*(unsigned char *)p]; + item->DecodeHandler(instr, p); +} + +// ===== Decode LegacyPrefix and REXPrefix ===== + +// clang-format off +#define _xDecodePrefix_0F 1, OpEn_NONE, OpSz_0, ImmSz_0, _DecodeLegacyPrefix +#define _xDecodePrefix_66 1, OpEn_NONE, OpSz_0, ImmSz_0, _DecodePrefix_66 +#define _xDecodePrefix_67 1, OpEn_NONE, OpSz_0, ImmSz_0, _DecodeLegacyPrefix +#define _xDecodeREXPrefix 1, OpEn_NONE, OpSz_0, ImmSz_0, _DecodeREXPrefix +#define _xDecodePrefix 1, OpEn_NONE, OpSz_0, ImmSz_0, _DecodeLegacyPrefix +#define _xDecodeSegPrefix 1, OpEn_NONE, OpSz_0, ImmSz_0, _DecodeLegacyPrefix +// clang-format on + +void _DecodeREXPrefix(InstrMnemonic *instr, addr_t p) { + instr->instr.REX = *(byte_t *)p; + instr->len++; + instr->OperandSz = OpSz_64; + + _ContinueDispatch(instr, p + 1); // continue decode +} + +void _DecodeLegacyPrefix(InstrMnemonic *instr, addr_t p) { + instr->instr.prefix = *(byte_t *)p; + instr->len++; + + _ContinueDispatch(instr, p + 1); // continue decode +} + +void _DecodePrefix_66(InstrMnemonic *instr, addr_t p) { + instr->OperandSz = OpSz_16; + _DecodeLegacyPrefix(instr, p); +} + +// ===== Decode Opcode ===== + +static void _DecodeOp(InstrMnemonic *instr, addr_t p) { + instr->instr.opcode1 = *(byte_t *)p; + instr->len++; +} + +static void _DecodeOpExtraOp(InstrMnemonic *instr, addr_t p) { + _DecodeOp(instr, p); +} + +static void _DecodeOpWithReg(InstrMnemonic *instr, addr_t p) { + _DecodeOp(instr, p); +} + +#define _xDecodeOpEn_ZO 1, OpEn_ZO, OpSz_0, ImmSz_0, _DecodeOpEn_ZO +void _DecodeOpEn_ZO(InstrMnemonic *instr, addr_t p) { + _DecodeOp(instr, p); +} + +#define _xDecodeOpEn_O 1, OpEn_O, OpSz_0, ImmSz_0, _DecodeOpEn_O +void _DecodeOpEn_O(InstrMnemonic *instr, addr_t p) { + _DecodeOpWithReg(instr, p); +} + +// ===== Decode Operand ===== + +// ===== Decode ModRM Operand ===== + +#define REX_W(byte) ((byte & 0b00001000) >> 3) +#define REX_R(byte) ((byte & 0b00000100) >> 2) +#define REX_X(byte) ((byte & 0b00000010) >> 1) +#define REX_B(byte) ((byte & 0b00000001) >> 0) + +#define ModRM_Mod(byte) ((byte & 0b11000000) >> 6) +#define ModRM_RegOpcode(byte) ((byte & 0b00111000) >> 3) +#define ModRM_RM(byte) (byte & 0b00000111) + +#define SIB_Scale(sib) ((sib & 0b11000000) >> 6) +#define SIB_Index(sib) ((sib & 0b00111000) >> 3) +#define SIB_Base(sib) ((sib & 0b00000111) >> 0) + +#define REX_SIB_Base(rex, sib) ((REX_B(rex) << 3) | SIB_Base(sib)) + +void _DecodeDisplacement8(InstrMnemonic *instr, addr_t p) { + *(byte_t *)&instr->instr.Displacement = *(byte_t *)p; + instr->len += 1; +} + +void _DecodeDisplacement32(InstrMnemonic *instr, addr_t p) { + instr->instr.DisplacementOffset = instr->len; + *(dword *)&instr->instr.Displacement = *(byte_t *)p; + instr->len += 4; +} + +void _DecodeSIB(InstrMnemonic *instr, addr_t p) { + instr->instr.SIB = *(byte_t *)p; + instr->len++; +} + +void _DecodeModRM(InstrMnemonic *instr, addr_t p) { + int init_len = instr->len; + + instr->instr.ModRM = *(byte_t *)p; + instr->len++; + +#if defined(_M_X64) || defined(__x86_64__) + if (ModRM_Mod(instr->instr.ModRM) == 0b00 && ModRM_RM(instr->instr.ModRM) == 0b101) { + // RIP-Relative Addressing + instr->flag = instr->flag | kIPRelativeAddress; + _DecodeDisplacement32(instr, p + (instr->len - init_len)); + return; + } +#endif + + // Addressing Forms with the SIB Byte + if (ModRM_Mod(instr->instr.ModRM) != 0b11 && ModRM_RM(instr->instr.ModRM) == 0b100) { + _DecodeSIB(instr, p + (instr->len - init_len)); + } + + // [REG] + if (ModRM_Mod(instr->instr.ModRM) == 0b00) { + if (ModRM_RM(instr->instr.ModRM) == 0b101) { + _DecodeDisplacement32(instr, p + (instr->len - init_len)); + return; + } + } + + // [REG+disp8} + if (ModRM_Mod(instr->instr.ModRM) == 0b01) { + _DecodeDisplacement8(instr, p + (instr->len - init_len)); + return; + } + + // [REG+disp32} + if (ModRM_Mod(instr->instr.ModRM) == 0b10) { + _DecodeDisplacement32(instr, p + (instr->len - init_len)); + return; + } + + // REG + if (ModRM_Mod(instr->instr.ModRM) == 0b11) { + } +} + +void _DecodeOpEn_M(InstrMnemonic *instr, addr_t p) { + _DecodeOp(instr, p); + _DecodeModRM(instr, p + 1); +} + +void _DecodeOpEn_RM(InstrMnemonic *instr, addr_t p) { + _DecodeOp(instr, p); + _DecodeModRM(instr, p + 1); +} + +void _DecodeOpEn_MR(InstrMnemonic *instr, addr_t p) { + _DecodeOp(instr, p); + _DecodeModRM(instr, p + 1); +} + +void _DecodeOpEn_M1(InstrMnemonic *instr, addr_t p) { + _DecodeOp(instr, p); + _DecodeModRM(instr, p + 1); +} + +void _DecodeOpEn_MC(InstrMnemonic *instr, addr_t p) { + _DecodeOp(instr, p); + _DecodeModRM(instr, p + 1); +} + +// ===== Decode Immediate Operand ===== + +void _DecodeImmedite(InstrMnemonic *instr, addr_t p, int sz) { + + instr->instr.ImmediateOffset = instr->len; + + OpcodeDecodeItem *item = &OpcodeDecodeTable[instr->instr.opcode1]; + if (sz == ImmSz_0) { + sz = item->ImmediteSz; + if (sz == (ImmSz_16 | ImmSz_32)) { + if (instr->instr.prefix == 0x66) { + sz = ImmSz_16; + } else { + sz = ImmSz_32; // Default Immedite Size + } + } + } + + if (sz == ImmSz_8) { + *(byte_t *)&instr->instr.Immediate = *(byte_t *)p; + instr->len += 1; + } else if (sz == ImmSz_16) { + *(word *)&instr->instr.Immediate = *(dword *)p; + instr->len += 2; + } else if (sz == ImmSz_32) { + *(dword *)&instr->instr.Immediate = *(dword *)p; + instr->len += 4; + } +} + +void _DecodeOpEn_I(InstrMnemonic *instr, addr_t p) { + _DecodeOp(instr, p); + _DecodeImmedite(instr, p + 1, instr->ImmediteSz); +} + +void _DecodeOpEn_OI(InstrMnemonic *instr, addr_t p) { + _DecodeOpWithReg(instr, p); + _DecodeImmedite(instr, p + 1, instr->ImmediteSz); +} + +void _DecodeOpEn_D(InstrMnemonic *instr, addr_t p) { + _DecodeOp(instr, p); + _DecodeImmedite(instr, p + 1, instr->ImmediteSz); +} + +// ===== Decode ModRM Immediate Operand ===== + +void _DecodeOpEn_RMI(InstrMnemonic *instr, addr_t p) { + _DecodeOp(instr, p); + _DecodeModRM(instr, p + 1); + _DecodeImmedite(instr, p + 2, instr->ImmediteSz); +} + +void _DecodeOpEn_MI(InstrMnemonic *instr, addr_t p) { + _DecodeOpExtraOp(instr, p); + _DecodeModRM(instr, p + 1); + _DecodeImmedite(instr, p + 2, instr->ImmediteSz); +} + +// ===== Decode Specific Opcode ===== + +#define _xDecodeOpC8 1, 0, OpSz_0, ImmSz_0, _DecodeOpC8 +void _DecodeOpC8(InstrMnemonic *instr, addr_t p) { + _DecodeOp(instr, p); + + instr->len = instr->len + 2 + 1; +} + +// http://ref.x86asm.net/coder.html#x04 +OpcodeDecodeItem OpcodeDecodeTable[257] = { + + {0x00, 2, OpEn_MR, OpSz_8, ImmSz_0, _DecodeOpEn_MR}, + {0x01, 2, OpEn_MR, OpSz_16 | OpSz_32, ImmSz_0, _DecodeOpEn_MR}, + {0x02, 2, OpEn_RM, OpSz_8, ImmSz_0, _DecodeOpEn_RM}, + {0x03, 2, OpEn_RM, OpSz_16 | OpSz_32, ImmSz_0, _DecodeOpEn_RM}, + {0x04, 1, OpEn_I, OpSz_0, ImmSz_8, _DecodeOpEn_I}, + {0x05, 1, OpEn_I, OpSz_16 | OpSz_32, ImmSz_16 | ImmSz_32, _DecodeOpEn_I}, +#if defined(_M_X64) || defined(__x86_64__) + {0x06, _xInvalidOpHanlder}, + {0x07, _xInvalidOpHanlder}, +#else + {0x06, _xDecodeOpEn_ZO}, + {0x07, _xDecodeOpEn_ZO}, +#endif + {0x08, 2, OpEn_MR, OpSz_8, ImmSz_0, _DecodeOpEn_MR}, + {0x09, 2, OpEn_MR, OpSz_16 | OpSz_32, ImmSz_0, _DecodeOpEn_MR}, + {0x0A, 2, OpEn_RM, OpSz_8, ImmSz_0, _DecodeOpEn_RM}, + {0x0B, 2, OpEn_RM, OpSz_16 | OpSz_32, ImmSz_0, _DecodeOpEn_RM}, + {0x0C, 1, OpEn_I, OpSz_0, ImmSz_8, _DecodeOpEn_I}, + {0x0D, 1, OpEn_I, OpSz_16 | OpSz_32, ImmSz_16 | ImmSz_32, _DecodeOpEn_I}, +#if defined(_M_X64) || defined(__x86_64__) + {0x0E, _xInvalidOpHanlder}, +#else + {0x0E, _xDecodeOpEn_ZO}, +#endif + {0x0F, _xDecodePrefix_0F}, + {0x10, 2, OpEn_MR, OpSz_8, ImmSz_0, _DecodeOpEn_MR}, + {0x11, 2, OpEn_MR, OpSz_16 | OpSz_32, ImmSz_0, _DecodeOpEn_MR}, + {0x12, 2, OpEn_RM, OpSz_8, ImmSz_0, _DecodeOpEn_RM}, + {0x13, 2, OpEn_RM, OpSz_16 | OpSz_32, ImmSz_0, _DecodeOpEn_RM}, + {0x14, 1, OpEn_I, OpSz_0, ImmSz_8, _DecodeOpEn_I}, + {0x15, 1, OpEn_I, OpSz_16 | OpSz_32, ImmSz_16 | ImmSz_32, _DecodeOpEn_I}, +#if defined(_M_X64) || defined(__x86_64__) + {0x16, _xInvalidOpHanlder}, + {0x17, _xInvalidOpHanlder}, +#else + {0x16, _xDecodeOpEn_ZO}, + {0x17, _xDecodeOpEn_ZO}, +#endif + {0x18, 2, OpEn_MR, OpSz_8, ImmSz_0, _DecodeOpEn_MR}, + {0x19, 2, OpEn_MR, OpSz_16 | OpSz_32, ImmSz_0, _DecodeOpEn_MR}, + {0x1A, 2, OpEn_RM, OpSz_8, ImmSz_0, _DecodeOpEn_RM}, + {0x1B, 2, OpEn_RM, OpSz_16 | OpSz_32, ImmSz_0, _DecodeOpEn_RM}, + {0x1C, 1, OpEn_I, OpSz_0, ImmSz_8, _DecodeOpEn_I}, + {0x1D, 1, OpEn_I, OpSz_16 | OpSz_32, ImmSz_16 | ImmSz_32, _DecodeOpEn_I}, +#if defined(_M_X64) || defined(__x86_64__) + {0x1E, _xInvalidOpHanlder}, + {0x1F, _xInvalidOpHanlder}, +#else + {0x1E, _xDecodeOpEn_ZO}, + {0x1F, _xDecodeOpEn_ZO}, +#endif + {0x20, 2, OpEn_MR, OpSz_8, ImmSz_0, _DecodeOpEn_MR}, + {0x21, 2, OpEn_MR, OpSz_16 | OpSz_32, ImmSz_0, _DecodeOpEn_MR}, + {0x22, 2, OpEn_RM, OpSz_8, ImmSz_0, _DecodeOpEn_RM}, + {0x23, 2, OpEn_RM, OpSz_16 | OpSz_32, ImmSz_0, _DecodeOpEn_RM}, + {0x24, 1, OpEn_I, OpSz_0, ImmSz_8, _DecodeOpEn_I}, + {0x25, 1, OpEn_I, OpSz_16 | OpSz_32, ImmSz_16 | ImmSz_32, _DecodeOpEn_I}, + {0x26, _xDecodeSegPrefix}, +#if defined(_M_X64) || defined(__x86_64__) + {0x27, _xInvalidOpHanlder}, +#else + {0x27, _xDecodeOpEn_ZO}, +#endif + {0x28, 2, OpEn_MR, OpSz_8, ImmSz_0, _DecodeOpEn_MR}, + {0x29, 2, OpEn_MR, OpSz_16 | OpSz_32, ImmSz_0, _DecodeOpEn_MR}, + {0x2A, 2, OpEn_RM, OpSz_8, ImmSz_0, _DecodeOpEn_RM}, + {0x2B, 2, OpEn_RM, OpSz_16 | OpSz_32, ImmSz_0, _DecodeOpEn_RM}, + {0x2C, 1, OpEn_I, OpSz_0, ImmSz_8, _DecodeOpEn_I}, + {0x2D, 1, OpEn_I, OpSz_16 | OpSz_32, ImmSz_16 | ImmSz_32, _DecodeOpEn_I}, + {0x2E, _xDecodeSegPrefix}, +#if defined(_M_X64) || defined(__x86_64__) + {0x2F, _xInvalidOpHanlder}, +#else + {0x2F, _xDecodeOpEn_ZO}, +#endif + {0x30, 2, OpEn_MR, OpSz_8, ImmSz_0, _DecodeOpEn_MR}, + {0x31, 2, OpEn_MR, OpSz_16 | OpSz_32, ImmSz_0, _DecodeOpEn_MR}, + {0x32, 2, OpEn_RM, OpSz_8, ImmSz_0, _DecodeOpEn_RM}, + {0x33, 2, OpEn_RM, OpSz_16 | OpSz_32, ImmSz_0, _DecodeOpEn_RM}, + {0x34, 1, OpEn_I, OpSz_0, ImmSz_8, _DecodeOpEn_I}, + {0x35, 1, OpEn_I, OpSz_16 | OpSz_32, ImmSz_16 | ImmSz_32, _DecodeOpEn_I}, + {0x36, _xDecodeSegPrefix}, +#if defined(_M_X64) || defined(__x86_64__) + {0x37, _xInvalidOpHanlder}, +#else + {0x37, _xDecodeOpEn_ZO}, +#endif + {0x38, 2, OpEn_MR, OpSz_8, ImmSz_0, _DecodeOpEn_MR}, + {0x39, 2, OpEn_MR, OpSz_16 | OpSz_32, ImmSz_0, _DecodeOpEn_MR}, + {0x3A, 2, OpEn_RM, OpSz_8, ImmSz_0, _DecodeOpEn_RM}, + {0x3B, 2, OpEn_RM, OpSz_16 | OpSz_32, ImmSz_0, _DecodeOpEn_RM}, + {0x3C, 1, OpEn_I, OpSz_0, ImmSz_8, _DecodeOpEn_I}, + {0x3D, 1, OpEn_I, OpSz_16 | OpSz_32, ImmSz_16 | ImmSz_32, _DecodeOpEn_I}, + {0x3E, _xDecodeSegPrefix}, +#if defined(_M_X64) || defined(__x86_64__) + {0x3F, _xInvalidOpHanlder}, +#else + {0x3F, _xDecodeOpEn_ZO}, +#endif +#if defined(_M_X64) || defined(__x86_64__) // For REX Prefix + {0x40, _xDecodeREXPrefix}, + {0x41, _xDecodeREXPrefix}, + {0x42, _xDecodeREXPrefix}, + {0x43, _xDecodeREXPrefix}, + {0x44, _xDecodeREXPrefix}, + {0x45, _xDecodeREXPrefix}, + {0x46, _xDecodeREXPrefix}, + {0x47, _xDecodeREXPrefix}, + {0x48, _xDecodeREXPrefix}, + {0x49, _xDecodeREXPrefix}, + {0x4A, _xDecodeREXPrefix}, + {0x4B, _xDecodeREXPrefix}, + {0x4C, _xDecodeREXPrefix}, + {0x4D, _xDecodeREXPrefix}, + {0x4E, _xDecodeREXPrefix}, + {0x4F, _xDecodeREXPrefix}, +#else + {0x40, _xDecodeOpEn_O}, + {0x41, _xDecodeOpEn_O}, + {0x42, _xDecodeOpEn_O}, + {0x43, _xDecodeOpEn_O}, + {0x44, _xDecodeOpEn_O}, + {0x45, _xDecodeOpEn_O}, + {0x46, _xDecodeOpEn_O}, + {0x47, _xDecodeOpEn_O}, + {0x48, _xDecodeOpEn_O}, + {0x49, _xDecodeOpEn_O}, + {0x4A, _xDecodeOpEn_O}, + {0x4B, _xDecodeOpEn_O}, + {0x4C, _xDecodeOpEn_O}, + {0x4D, _xDecodeOpEn_O}, + {0x4E, _xDecodeOpEn_O}, + {0x4F, _xDecodeOpEn_O}, +#endif + {0x50, _xDecodeOpEn_O}, + {0x51, _xDecodeOpEn_O}, + {0x52, _xDecodeOpEn_O}, + {0x53, _xDecodeOpEn_O}, + {0x54, _xDecodeOpEn_O}, + {0x55, _xDecodeOpEn_O}, + {0x56, _xDecodeOpEn_O}, + {0x57, _xDecodeOpEn_O}, + {0x58, _xDecodeOpEn_O}, + {0x59, _xDecodeOpEn_O}, + {0x5A, _xDecodeOpEn_O}, + {0x5B, _xDecodeOpEn_O}, + {0x5C, _xDecodeOpEn_O}, + {0x5D, _xDecodeOpEn_O}, + {0x5E, _xDecodeOpEn_O}, + {0x5F, _xDecodeOpEn_O}, +#if defined(_M_X64) || defined(__x86_64__) + {0x60, _xInvalidOpHanlder}, + {0x61, _xInvalidOpHanlder}, + {0x62, _xInvalidOpHanlder}, +#else + {0x60, _xDecodeOpEn_ZO}, + {0x61, _xDecodeOpEn_ZO}, + {0x62, 2, OpEn_RM, OpSz_16 | OpSz_32, ImmSz_0, _DecodeOpEn_RM}, +#endif + {0x63, 2, OpEn_RM, OpSz_16 | OpSz_32, ImmSz_0, _DecodeOpEn_RM}, + {0x64, _xDecodeSegPrefix}, + {0x65, _xDecodeSegPrefix}, + {0x66, _xDecodePrefix_66}, + {0x67, _xDecodePrefix_67}, + {0x68, 1, OpEn_I, OpSz_16 | OpSz_32, ImmSz_16 | ImmSz_32, _DecodeOpEn_I}, + {0x69, 2, OpEn_RMI, OpSz_16 | OpSz_32, ImmSz_16 | ImmSz_32, _DecodeOpEn_RMI}, + {0x6A, 1, OpEn_I, OpSz_0, ImmSz_8, _DecodeOpEn_I}, + {0x6B, 1, OpEn_RMI, OpSz_16 | OpSz_32, ImmSz_8, _DecodeOpEn_RMI}, + {0x6C, _xDecodeOpEn_ZO}, + {0x6D, _xDecodeOpEn_ZO}, + {0x6E, _xDecodeOpEn_ZO}, + {0x6F, _xDecodeOpEn_ZO}, + {0x70, 1, OpEn_D, OpSz_0, ImmSz_8, _DecodeOpEn_D}, + {0x71, 1, OpEn_D, OpSz_0, ImmSz_8, _DecodeOpEn_D}, + {0x72, 1, OpEn_D, OpSz_0, ImmSz_8, _DecodeOpEn_D}, + {0x73, 1, OpEn_D, OpSz_0, ImmSz_8, _DecodeOpEn_D}, + {0x74, 1, OpEn_D, OpSz_0, ImmSz_8, _DecodeOpEn_D}, + {0x75, 1, OpEn_D, OpSz_0, ImmSz_8, _DecodeOpEn_D}, + {0x76, 1, OpEn_D, OpSz_0, ImmSz_8, _DecodeOpEn_D}, + {0x77, 1, OpEn_D, OpSz_0, ImmSz_8, _DecodeOpEn_D}, + {0x78, 1, OpEn_D, OpSz_0, ImmSz_8, _DecodeOpEn_D}, + {0x79, 1, OpEn_D, OpSz_0, ImmSz_8, _DecodeOpEn_D}, + {0x7A, 1, OpEn_D, OpSz_0, ImmSz_8, _DecodeOpEn_D}, + {0x7B, 1, OpEn_D, OpSz_0, ImmSz_8, _DecodeOpEn_D}, + {0x7C, 1, OpEn_D, OpSz_0, ImmSz_8, _DecodeOpEn_D}, + {0x7D, 1, OpEn_D, OpSz_0, ImmSz_8, _DecodeOpEn_D}, + {0x7E, 1, OpEn_D, OpSz_0, ImmSz_8, _DecodeOpEn_D}, + {0x7F, 1, OpEn_D, OpSz_0, ImmSz_8, _DecodeOpEn_D}, + {0x80, 2, OpEn_MI, OpSz_8, ImmSz_8, _DecodeOpEn_MI}, + {0x81, 2, OpEn_MI, OpSz_16 | OpSz_32, ImmSz_16 | ImmSz_32, _DecodeOpEn_MI}, +#if defined(_M_X64) || defined(__x86_64__) + {0x82, _xInvalidOpHanlder}, +#else + {0x82, _xUnknownOpHanlder}, +#endif + {0x83, 2, OpEn_MI, OpSz_16 | OpSz_32, ImmSz_8, _DecodeOpEn_MI}, + {0x84, 2, OpEn_MR, OpSz_8, ImmSz_0, _DecodeOpEn_MR}, + {0x85, 2, OpEn_MR, OpSz_16 | OpSz_32, ImmSz_0, _DecodeOpEn_MR}, + {0x86, 2, OpEn_RM, OpSz_16 | OpSz_32, ImmSz_0, _DecodeOpEn_RM}, + {0x87, 2, OpEn_RM, OpSz_16 | OpSz_32, ImmSz_0, _DecodeOpEn_RM}, + {0x88, 2, OpEn_MR, OpSz_8, ImmSz_0, _DecodeOpEn_MR}, + {0x89, 2, OpEn_MR, OpSz_16 | OpSz_32, ImmSz_0, _DecodeOpEn_MR}, + {0x8A, 2, OpEn_RM, OpSz_16 | OpSz_32, ImmSz_0, _DecodeOpEn_RM}, + {0x8B, 2, OpEn_RM, OpSz_16 | OpSz_32, ImmSz_0, _DecodeOpEn_RM}, + {0x8C, 2, OpEn_MR, OpSz_16 | OpSz_32, ImmSz_0, _DecodeOpEn_MR}, + {0x8D, 2, OpEn_RM, OpSz_16 | OpSz_32, ImmSz_0, _DecodeOpEn_RM}, + {0x8E, 2, OpEn_RM, OpSz_16 | OpSz_32, ImmSz_0, _DecodeOpEn_RM}, + {0x8F, 2, OpEn_M, OpSz_16 | OpSz_32, ImmSz_0, _DecodeOpEn_M}, + {0x90, _xDecodeOpEn_ZO}, + {0x91, _xInvalidOpHanlder}, + {0x92, _xInvalidOpHanlder}, + {0x93, _xInvalidOpHanlder}, + {0x94, _xInvalidOpHanlder}, + {0x95, _xInvalidOpHanlder}, + {0x96, _xInvalidOpHanlder}, + {0x97, _xInvalidOpHanlder}, + {0x98, _xDecodeOpEn_ZO}, + {0x99, _xDecodeOpEn_ZO}, +#if defined(_M_X64) || defined(__x86_64__) + {0x9A, _xInvalidOpHanlder}, +#else + {0x9A, _xDecodeOpEn_ZO}, +#endif + {0x9B, _xDecodeOpEn_ZO}, + {0x9C, _xDecodeOpEn_ZO}, + {0x9D, _xDecodeOpEn_ZO}, + {0x9E, _xDecodeOpEn_ZO}, + {0x9F, _xDecodeOpEn_ZO}, + {0xA0, _xUnknownOpHanlder}, + {0xA1, _xUnknownOpHanlder}, + {0xA2, _xUnknownOpHanlder}, + {0xA3, _xUnknownOpHanlder}, + {0xA4, _xDecodeOpEn_ZO}, + {0xA5, _xDecodeOpEn_ZO}, + {0xA6, _xDecodeOpEn_ZO}, + {0xA7, _xDecodeOpEn_ZO}, + {0xA8, 1, OpEn_I, OpSz_0, ImmSz_8, _DecodeOpEn_I}, + {0xA9, 1, OpEn_I, OpSz_16 | OpSz_32, ImmSz_16 | ImmSz_32, _DecodeOpEn_I}, + {0xAA, _xDecodeOpEn_ZO}, + {0xAB, _xDecodeOpEn_ZO}, + {0xAC, _xDecodeOpEn_ZO}, + {0xAD, _xDecodeOpEn_ZO}, + {0xAE, _xDecodeOpEn_ZO}, + {0xAF, _xDecodeOpEn_ZO}, +#undef SAME_ITEM_LAZY +#define SAME_ITEM_LAZY 1, OpEn_OI, OpSz_0, ImmSz_8, _DecodeOpEn_OI + {0xB0, SAME_ITEM_LAZY}, + {0xB1, SAME_ITEM_LAZY}, + {0xB2, SAME_ITEM_LAZY}, + {0xB3, SAME_ITEM_LAZY}, + {0xB4, SAME_ITEM_LAZY}, + {0xB5, SAME_ITEM_LAZY}, + {0xB6, SAME_ITEM_LAZY}, + {0xB7, SAME_ITEM_LAZY}, +#undef SAME_ITEM_LAZY +#define SAME_ITEM_LAZY 1, OpEn_OI, OpSz_16 | OpSz_32, ImmSz_16 | ImmSz_32, _DecodeOpEn_OI + {0xB8, SAME_ITEM_LAZY}, + {0xB9, SAME_ITEM_LAZY}, + {0xBA, SAME_ITEM_LAZY}, + {0xBB, SAME_ITEM_LAZY}, + {0xBC, SAME_ITEM_LAZY}, + {0xBD, SAME_ITEM_LAZY}, + {0xBE, SAME_ITEM_LAZY}, + {0xBF, SAME_ITEM_LAZY}, + {0xC0, 2, OpEn_MI, OpSz_8, ImmSz_8, _DecodeOpEn_MI}, + {0xC1, 2, OpEn_MI, OpSz_16 | OpSz_32, ImmSz_16 | ImmSz_32, _DecodeOpEn_MI}, + {0xC2, 1, OpEn_I, OpSz_0, ImmSz_16, _DecodeOpEn_I}, + {0xC3, _xDecodeOpEn_ZO}, + {0xC4, _xInvalidOpHanlder}, + {0xC5, _xInvalidOpHanlder}, + {0xC6, _xUnknownOpHanlder}, + {0xC7, 2, OpEn_MI, OpSz_16 | OpSz_32, ImmSz_16 | ImmSz_32, _DecodeOpEn_MI}, + {0xC8, _xDecodeOpC8}, + {0xC9, _xDecodeOpEn_ZO}, + {0xCA, 1, OpEn_I, OpSz_0, ImmSz_16, _DecodeOpEn_I}, + {0xCB, _xDecodeOpEn_ZO}, + {0xCC, _xDecodeOpEn_ZO}, + {0xCD, 1, OpEn_I, OpSz_0, ImmSz_8, _DecodeOpEn_I}, +#if defined(_M_X64) || defined(__x86_64__) + {0xCE, _xInvalidOpHanlder}, +#else + {0xCE, _xDecodeOpEn_ZO}, +#endif + {0xCF, _xDecodeOpEn_ZO}, + {0xD0, 1, OpEn_M1, OpSz_8, ImmSz_0, _DecodeOpEn_M1}, + {0xD1, 1, OpEn_M1, OpSz_16 | OpSz_32, ImmSz_0, _DecodeOpEn_M1}, + {0xD2, 1, OpEn_MC, OpSz_8, ImmSz_0, _DecodeOpEn_MC}, + {0xD3, 1, OpEn_MC, OpSz_16 | OpSz_32, ImmSz_0, _DecodeOpEn_MC}, +#if defined(_M_X64) || defined(__x86_64__) + {0xD4, _xInvalidOpHanlder}, + {0xD5, _xInvalidOpHanlder}, +#else + {0xD4, 1, OpEn_I, OpSz_0, ImmSz_8, _DecodeOpEn_I}, + {0xD5, 1, OpEn_I, OpSz_0, ImmSz_8, _DecodeOpEn_I}, +#endif + {0xD6, _xInvalidOpHanlder}, + {0xD7, _xDecodeOpEn_ZO}, + {0xD8, _xUnknownOpHanlder}, + {0xD9, _xUnknownOpHanlder}, + {0xDA, _xUnknownOpHanlder}, + {0xDB, _xUnknownOpHanlder}, + {0xDC, _xUnknownOpHanlder}, + {0xDD, _xUnknownOpHanlder}, + {0xDE, _xUnknownOpHanlder}, + {0xDF, _xUnknownOpHanlder}, + {0xE0, 1, OpEn_D, OpSz_0, ImmSz_8, _DecodeOpEn_D}, + {0xE1, 1, OpEn_D, OpSz_0, ImmSz_8, _DecodeOpEn_D}, + {0xE2, 1, OpEn_D, OpSz_0, ImmSz_8, _DecodeOpEn_D}, + {0xE3, 1, OpEn_D, OpSz_0, ImmSz_8, _DecodeOpEn_D}, + {0xE4, 1, OpEn_I, OpSz_0, ImmSz_8, _DecodeOpEn_I}, + {0xE5, 1, OpEn_I, OpSz_0, ImmSz_8, _DecodeOpEn_I}, + {0xE6, 1, OpEn_I, OpSz_0, ImmSz_8, _DecodeOpEn_I}, + {0xE7, 1, OpEn_I, OpSz_0, ImmSz_8, _DecodeOpEn_I}, + {0xE8, 1, OpEn_I, OpSz_16 | OpSz_32, ImmSz_16 | ImmSz_32, _DecodeOpEn_I}, + {0xE9, 1, OpEn_I, OpSz_16 | OpSz_32, ImmSz_16 | ImmSz_32, _DecodeOpEn_I}, +#if defined(_M_X64) || defined(__x86_64__) + {0xEA, _xInvalidOpHanlder}, +#else + {0xEA, _xUnknownOpHanlder}, +#endif + {0xEB, 1, OpEn_I, OpSz_0, ImmSz_8, _DecodeOpEn_I}, + {0xEC, _xDecodeOpEn_ZO}, + {0xED, _xDecodeOpEn_ZO}, + {0xEE, _xDecodeOpEn_ZO}, + {0xEF, _xDecodeOpEn_ZO}, + {0xF0, _xDecodePrefix}, + {0xF1, _xDecodeOpEn_ZO}, + {0xF2, _xDecodeOpEn_ZO}, +#ifdef DETOURS_X86 + {0xF3, _CopyF3}, +#else + {0xF3, _xDecodeOpEn_ZO}, +#endif + {0xF4, _xDecodeOpEn_ZO}, + {0xF5, _xDecodeOpEn_ZO}, + {0xF6, 2, OpEn_MI, OpSz_8, ImmSz_8, _DecodeOpEn_MI}, + {0xF7, 2, OpEn_MI, OpSz_16 | OpSz_32, ImmSz_16 | ImmSz_32, _DecodeOpEn_MI}, + {0xF8, _xDecodeOpEn_ZO}, + {0xF9, _xDecodeOpEn_ZO}, + {0xFA, _xDecodeOpEn_ZO}, + {0xFB, _xDecodeOpEn_ZO}, + {0xFC, _xDecodeOpEn_ZO}, + {0xFD, _xDecodeOpEn_ZO}, + {0xFE, 2, OpEn_M, OpSz_8, ImmSz_0, _DecodeOpEn_M}, + {0xFF, 2, OpEn_M, OpSz_16 | OpSz_32, ImmSz_0, _DecodeOpEn_M}, + {0, 0, 0, 0, 0}}; + +#endif \ No newline at end of file diff --git a/app/src/main/cpp/Dobby/source/InstructionRelocation/x86/deprecated/X86OpcodoDecodeTable.h b/app/src/main/cpp/Dobby/source/InstructionRelocation/x86/deprecated/X86OpcodoDecodeTable.h new file mode 100644 index 0000000..778fdb3 --- /dev/null +++ b/app/src/main/cpp/Dobby/source/InstructionRelocation/x86/deprecated/X86OpcodoDecodeTable.h @@ -0,0 +1,142 @@ +#ifndef X86_OPCODE_DECODE_TABLE_H +#define X86_OPCODE_DECODE_TABLE_H + +#ifndef __addr_t_defined +#define __addr_t_defined +typedef unsigned long long addr_t; +#endif + +#ifndef __byte_defined +#define __byte_defined +typedef unsigned char byte_t; +#endif + +#ifndef __uint_defined +#define __uint_defined +typedef unsigned int uint; +#endif + +#ifndef __word_defined +#define __word_defined +typedef short word; +#endif + +#ifndef __dword_defined +#define __dword_defined +typedef int dword; +#endif + +enum OpcodeType { OpTy_Op1, OpTy_RegInOp1, OpTy_Op1ExtraOp }; + +struct Instr { + byte_t prefix; + + byte_t REX; + + union { + byte_t opcode[3]; + struct { + byte_t opcode1; + byte_t opcode2; + byte_t opcode3; + }; + }; + + union { + byte_t ModRM; + struct { + byte_t Mod : 2; + byte_t RegOpcode : 3; + byte_t RM : 3; + }; + }; + + union { + byte_t SIB; + struct { + byte_t base : 2; + byte_t index : 3; + byte_t scale : 3; + }; + }; + + byte_t Displacement[4]; + int DisplacementOffset; + + byte_t Immediate[4]; + int ImmediateOffset; +}; + +// clang-format off +enum OperandSize { + OpSz_0 = 0, + OpSz_8=1, + OpSz_16=2, + OpSz_32=4, + OpSz_64=8 +}; + +enum ImmediteSize { + ImmSz_0 = 0, + ImmSz_8=1, + ImmSz_16=2, + ImmSz_32=4, + ImmSz_64=8 +}; + +enum InstrFlag { + kNoFlag = 0, + kIPRelativeAddress = 1 +}; +// clang-format on + +struct InstrMnemonic { + uint len; + + int flag; + + OperandSize OperandSz; + + ImmediteSize ImmediteSz; + + struct Instr instr; +}; + +struct OpcodeDecodeItem { + unsigned char opcode; + + int FixedSize; + + int OpEn; + + int OperandSz; + + int ImmediteSz; + + void (*DecodeHandler)(InstrMnemonic *, addr_t); +}; + +// clang-format off +enum OperandEncodingType { + OpEn_NONE =0, + OpEn_ZO, + OpEn_M, + OpEn_I, + OpEn_D, + OpEn_O, + OpEn_RM, + OpEn_MR, + OpEn_MI, + OpEn_OI, + OpEn_M1, + OpEn_MC, + OpEn_RMI +}; + +// clang-format on + +extern OpcodeDecodeItem OpcodeDecodeTable[257]; + +void _DecodePrefix(InstrMnemonic *instr, addr_t p); + +#endif diff --git a/app/src/main/cpp/Dobby/source/InstructionRelocation/x86/x86_insn_decode/build_config.h b/app/src/main/cpp/Dobby/source/InstructionRelocation/x86/x86_insn_decode/build_config.h new file mode 100644 index 0000000..6206267 --- /dev/null +++ b/app/src/main/cpp/Dobby/source/InstructionRelocation/x86/x86_insn_decode/build_config.h @@ -0,0 +1,144 @@ +#ifndef BUILD_CONFIG_H +#define BUILD_CONFIG_H + +#if defined(__APPLE__) +// only include TargetConditions after testing ANDROID as some android builds +// on mac don't have this header available and it's not needed unless the target +// is really mac/ios. +#include +#define OS_MACOSX 1 +#if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE +#define OS_IOS 1 +#endif // defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE +#elif defined(__linux__) +#define OS_LINUX 1 +// include a system header to pull in features.h for glibc/uclibc macros. +#include +#if defined(__GLIBC__) && !defined(__UCLIBC__) +// we really are using glibc, not uClibc pretending to be glibc +#define LIBC_GLIBC 1 +#endif +#elif defined(_WIN32) +#define OS_WIN 1 +#elif defined(__Fuchsia__) +#define OS_FUCHSIA 1 +#elif defined(__FreeBSD__) +#define OS_FREEBSD 1 +#elif defined(__NetBSD__) +#define OS_NETBSD 1 +#elif defined(__OpenBSD__) +#define OS_OPENBSD 1 +#elif defined(__sun) +#define OS_SOLARIS 1 +#elif defined(__QNXNTO__) +#define OS_QNX 1 +#elif defined(_AIX) +#define OS_AIX 1 +#elif defined(__asmjs__) || defined(__wasm__) +#define OS_ASMJS +#else +#error Please add support for your platform in build/build_config.h +#endif +// NOTE: Adding a new port? Please follow +// https://chromium.googlesource.com/chromium/src/+/master/docs/new_port_policy.md + +// For access to standard BSD features, use OS_BSD instead of a +// more specific macro. +#if defined(OS_FREEBSD) || defined(OS_NETBSD) || defined(OS_OPENBSD) +#define OS_BSD 1 +#endif + +// For access to standard POSIXish features, use OS_POSIX instead of a +// more specific macro. +#if defined(OS_AIX) || defined(OS_ANDROID) || defined(OS_ASMJS) || defined(OS_FREEBSD) || defined(OS_LINUX) || \ + defined(OS_MACOSX) || defined(OS_NACL) || defined(OS_NETBSD) || defined(OS_OPENBSD) || defined(OS_QNX) || \ + defined(OS_SOLARIS) +#define OS_POSIX 1 +#endif + +// Compiler detection. Note: clang masquerades as GCC on POSIX and as MSVC on +// Windows. +#if defined(__GNUC__) +#define COMPILER_GCC 1 +#elif defined(_MSC_VER) +#define COMPILER_MSVC 1 +#else +#error Please add support for your compiler in build/build_config.h +#endif + +// Processor architecture detection. For more info on what's defined, see: +// http://msdn.microsoft.com/en-us/library/b0084kay.aspx +// http://www.agner.org/optimize/calling_conventions.pdf +// or with gcc, run: "echo | gcc -E -dM -" +#if defined(_M_X64) || defined(__x86_64__) +#define ARCH_CPU_X86_FAMILY 1 +#define ARCH_CPU_X86_64 1 +#define ARCH_CPU_64_BITS 1 +#define ARCH_CPU_LITTLE_ENDIAN 1 +#elif defined(_M_IX86) || defined(__i386__) +#define ARCH_CPU_X86_FAMILY 1 +#define ARCH_CPU_X86 1 +#define ARCH_CPU_32_BITS 1 +#define ARCH_CPU_LITTLE_ENDIAN 1 +#elif defined(__s390x__) +#define ARCH_CPU_S390_FAMILY 1 +#define ARCH_CPU_S390X 1 +#define ARCH_CPU_64_BITS 1 +#define ARCH_CPU_BIG_ENDIAN 1 +#elif defined(__s390__) +#define ARCH_CPU_S390_FAMILY 1 +#define ARCH_CPU_S390 1 +#define ARCH_CPU_31_BITS 1 +#define ARCH_CPU_BIG_ENDIAN 1 +#elif (defined(__PPC64__) || defined(__PPC__)) && defined(__BIG_ENDIAN__) +#define ARCH_CPU_PPC64_FAMILY 1 +#define ARCH_CPU_PPC64 1 +#define ARCH_CPU_64_BITS 1 +#define ARCH_CPU_BIG_ENDIAN 1 +#elif defined(__PPC64__) +#define ARCH_CPU_PPC64_FAMILY 1 +#define ARCH_CPU_PPC64 1 +#define ARCH_CPU_64_BITS 1 +#define ARCH_CPU_LITTLE_ENDIAN 1 +#elif defined(__ARMEL__) +#define ARCH_CPU_ARM_FAMILY 1 +#define ARCH_CPU_ARMEL 1 +#define ARCH_CPU_32_BITS 1 +#define ARCH_CPU_LITTLE_ENDIAN 1 +#elif defined(__aarch64__) || defined(_M_ARM64) +#define ARCH_CPU_ARM_FAMILY 1 +#define ARCH_CPU_ARM64 1 +#define ARCH_CPU_64_BITS 1 +#define ARCH_CPU_LITTLE_ENDIAN 1 +#elif defined(__pnacl__) || defined(__asmjs__) || defined(__wasm__) +#define ARCH_CPU_32_BITS 1 +#define ARCH_CPU_LITTLE_ENDIAN 1 +#elif defined(__MIPSEL__) +#if defined(__LP64__) +#define ARCH_CPU_MIPS_FAMILY 1 +#define ARCH_CPU_MIPS64EL 1 +#define ARCH_CPU_64_BITS 1 +#define ARCH_CPU_LITTLE_ENDIAN 1 +#else +#define ARCH_CPU_MIPS_FAMILY 1 +#define ARCH_CPU_MIPSEL 1 +#define ARCH_CPU_32_BITS 1 +#define ARCH_CPU_LITTLE_ENDIAN 1 +#endif +#elif defined(__MIPSEB__) +#if defined(__LP64__) +#define ARCH_CPU_MIPS_FAMILY 1 +#define ARCH_CPU_MIPS64 1 +#define ARCH_CPU_64_BITS 1 +#define ARCH_CPU_BIG_ENDIAN 1 +#else +#define ARCH_CPU_MIPS_FAMILY 1 +#define ARCH_CPU_MIPS 1 +#define ARCH_CPU_32_BITS 1 +#define ARCH_CPU_BIG_ENDIAN 1 +#endif +#else +#error Please add support for your architecture in build/build_config.h +#endif + +#endif \ No newline at end of file diff --git a/app/src/main/cpp/Dobby/source/InstructionRelocation/x86/x86_insn_decode/x86_insn_decode.c b/app/src/main/cpp/Dobby/source/InstructionRelocation/x86/x86_insn_decode/x86_insn_decode.c new file mode 100644 index 0000000..5b8fc32 --- /dev/null +++ b/app/src/main/cpp/Dobby/source/InstructionRelocation/x86/x86_insn_decode/x86_insn_decode.c @@ -0,0 +1,564 @@ +#include "platform_detect_macro.h" +#if defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_X64) + +#include "x86_insn_decode.h" + +#include "logging/logging.h" + +#define REX_W(byte) ((byte & 0b00001000) >> 3) +#define REX_R(byte) ((byte & 0b00000100) >> 2) +#define REX_X(byte) ((byte & 0b00000010) >> 1) +#define REX_B(byte) ((byte & 0b00000001) >> 0) + +#define ModRM_Mod(byte) ((byte & 0b11000000) >> 6) +#define ModRM_RegOpcode(byte) ((byte & 0b00111000) >> 3) +#define ModRM_RM(byte) (byte & 0b00000111) + +#define SIB_Scale(sib) ((sib & 0b11000000) >> 6) +#define SIB_Index(sib) ((sib & 0b00111000) >> 3) +#define SIB_Base(sib) ((sib & 0b00000111) >> 0) + +#if 0 +/* Build an encoding specification from scratch. */ +#define SPEC_MAKE(op, opr1, opr2, opr3, opr4) \ + ((uint64_t)(uint16_t)(int16_t)(op) | ((uint64_t)(opr1) << 16) | ((uint64_t)(opr2) << 24) | \ + ((uint64_t)(opr3) << 32) | ((uint64_t)(opr4) << 40)) + +/* Get the operation in an encoding specification. */ +#define SPEC_INSN(spec) ((int16_t)((spec)&0xffff)) + +/* Get the given operand (zero-based) in an encoding specification. */ +#define SPEC_OPERAND(spec, i) ((uint8_t)(((spec) >> (16 + (i)*8)) & 0xff)) + +/* Get the operands part of an encoding specification. */ +#define SPEC_OPERANDS(spec) ((spec)&0xffffffffffff0000ULL) + +/* Merges two encoding specifications. */ +#define SPEC_MERGE(spec1, spec2) ((spec1) | (spec2)) + +#define OP4(insn, oper1, oper2, oper3, oper4) SPEC_MAKE(I_##insn, O_##oper1, O_##oper2, O_##oper3, O_##oper4) +#define OP3(insn, oper1, oper2, oper3) OP4(insn, oper1, oper2, oper3, NONE) +#define OP2(insn, oper1, oper2) OP3(insn, oper1, oper2, NONE) +#define OP1(insn, oper1) OP2(insn, oper1, NONE) +#define OP0(insn) OP1(insn, NONE) +#define OP_EMPTY OP0(NONE) +#define OP_EMPTY_4 OP_EMPTY, OP_EMPTY, OP_EMPTY, OP_EMPTY +#define OP_EMPTY_8 OP_EMPTY_4, OP_EMPTY_4 +#endif + +#define op3_flag(x, f, o0, o1, o2) \ + { \ + .name = #x, .flags = (f), .operands[0] = {.data = #o0}, .operands[1] = {.data = #o1}, \ + .operands[2] = {.data = #o2}, \ + } +#define op2_flag(x, f, o0, o1) op3_flag(x, f, o0, o1, __) +#define op1_flag(x, f, o0) op2_flag(x, f, o0, __) +#define op0_flag(x, f) op1_flag(x, f, __) + +#define op3f op3_flag +#define op2f op2_flag +#define op1f op1_flag +#define op0f op0_flag + +#define op3(x, o0, o1, o2) op3f(x, 0, o0, o1, o2) +#define op2(x, o0, o1) op2f(x, 0, o0, o1) +#define op1(x, o0) op1f(x, 0, o0) +#define op0(x) op0f(x, 0) + +/* Opcode extension in modrm byte reg field. */ +#define foreach_x86_insn_modrm_reg_group \ + _(1) _(1a) _(2) _(3) _(4) _(5) _(6) _(7) _(8) _(9) _(10) _(11) _(12) _(13) _(14) _(15) _(16) _(p) +#define foreach_x86_insn_sse_group \ + _(10) _(28) _(50) _(58) _(60) _(68) _(70) _(78) _(c0) _(d0) _(d8) _(e0) _(e8) _(f0) _(f8) +enum { + X86_INSN_GROUP_START = 0, + +#define _(x) X86_INSN_MODRM_REG_GROUP_##x, + foreach_x86_insn_modrm_reg_group +#undef _ + + X86_INSN_SSE_GROUP_START = 19, +#define _(x) X86_INSN_SSE_GROUP_##x, + foreach_x86_insn_sse_group +#undef _ + + X86_INSN_GROUP_END = 35 +}; + +#define X86_INSN_GROUP_END_MASK ((1 << 6) - 1) +#define X86_INSN_FLAG_SET_GROUP(n) ((n) << 5) +#define X86_INSN_FLAG_GET_GROUP(f) (((f) >> 5) & X86_INSN_GROUP_END_MASK) + +enum { +#define _(x) X86_INSN_FLAG_MODRM_REG_GROUP_##x = X86_INSN_FLAG_SET_GROUP(X86_INSN_MODRM_REG_GROUP_##x), + foreach_x86_insn_modrm_reg_group +#undef _ + +#define _(x) X86_INSN_FLAG_SSE_GROUP_##x = X86_INSN_FLAG_SET_GROUP(X86_INSN_SSE_GROUP_##x), + foreach_x86_insn_sse_group +#undef _ +}; + +// clang-format off + +#define foreach_x86_operand_combine(x, op1_type, op2_type) op2(x, Eb, Gb), op2(x, Ev, Gv), op2(x, Gb, Eb), op2(x, Gv, Ev), op2(x, AL, Ib), op2(x, AX, Iz) + +#define foreach_x86_gp_reg _(AX) _(CX) _(DX) _(BX) _(SP) _(BP) _(SI) _(DI) + +#define foreach_x86_condition _(o) _(no) _(b) _(nb) _(z) _(nz) _(be) _(nbe) _(s) _(ns) _(p) _(np) _(l) _(nl) _(le) _(nle) + +// clang-format on + +#include "./x86_opcode_one_byte.c" +#include "./x86_opcode_two_byte.c" + +typedef struct { + x86_insn_spec_t insns[8]; +} x86_insn_group8_t; + +#include "./x86_opcode_modrm_reg_group.c" +#include "./x86_opcode_sse_group.c" + +#include "./x86_insn_reader.c" + +static x86_insn_prefix_t x86_insn_decode_prefix(x86_insn_reader_t *rd, x86_insn_decode_t *insn, x86_options_t *conf) { + /* Decode each byte until the byte is not a prefix or is an REX prefix, + * because an REX prefix is required to immediately preceed the opcode. + */ + x86_insn_prefix_t insn_prefix = 0; + for (;;) { + uint8_t c = peek_byte(rd); + x86_insn_prefix_t t = 0; + + /* Check for REX prefix if we're in 64-bit mode. */ + if (conf->mode == 64) { + if (c >= 0x40 && c <= 0x4f) { + uint8_t rex = read_byte(rd); + + if (REX_W(rex)) { + insn->flags |= X86_INSN_DECODE_FLAG_OPERAND_SIZE_64; + } + + insn->rex = rex; + + break; + } + } + + /* Check for legacy prefixes. */ + switch (c) { + case 0xF0: + t = INSN_PREFIX_LOCK; + break; + case 0xF2: + t = INSN_PREFIX_REPNE; + break; + case 0xF3: + t = INSN_PREFIX_REPE; + break; + case 0x2E: + t = INSN_PREFIX_CS; + break; + case 0x36: + t = INSN_PREFIX_SS; + break; + case 0x3E: + t = INSN_PREFIX_DS; + break; + case 0x26: + t = INSN_PREFIX_ES; + break; + case 0x64: + t = INSN_PREFIX_FS; + break; + case 0x65: + t = INSN_PREFIX_GS; + break; + case 0x66: + t = INSN_PREFIX_OPERAND_SIZE; + break; + case 0x67: + t = INSN_PREFIX_ADDRESS_SIZE; + break; + } + if (t == 0) + break; + + /* Consume 1 byte. */ + read_byte(rd); + insn_prefix |= t; + } + + return insn_prefix; +} + +int x86_insn_has_modrm_byte(x86_insn_spec_t *insn) { + int i; + for (i = 0; i < sizeof(insn->operands) / sizeof(x86_insn_operand_spec_t); i++) + switch (insn->operands[i].code) { + case 'G': + case 'E': + case 'M': + case 'R': + return 1; + } + return 0; +} + +int x86_insn_immediate_type(x86_insn_spec_t *insn) { + int i; + for (i = 0; i < sizeof(insn->operands); i++) { + switch (insn->operands[i].code) { + case 'J': + case 'I': + case 'O': + return insn->operands[i].type; + } + } + return 0; +} + +int x86_insn_has_immediate(x86_insn_spec_t *insn) { + int i; + for (i = 0; i < sizeof(insn->operands) / sizeof(x86_insn_operand_spec_t); i++) { + switch (insn->operands[i].code) { + case 'J': + case 'I': + case 'O': + return 1; + } + } + return 0; +} + +static uint8_t *x86_insn_decode_number(x86_insn_reader_t *rd, uint8_t number_bits, int64_t *out_number) { + int64_t disp = 0; + switch (number_bits) { + case 64: + disp = read_uint64(rd); + break; + case 32: + disp = read_uint32(rd); + break; + case 16: + disp = read_uint16(rd); + break; + case 8: + disp = read_uint8(rd); + break; + default: + UNREACHABLE(); + } + + *out_number = disp; + return NULL; +} + +void x86_insn_decode_modrm_sib(x86_insn_reader_t *rd, x86_insn_decode_t *insn, x86_options_t *conf) { + uint8_t mod, rm, reg; + + x86_insn_modrm_t modrm; + modrm.byte = read_byte(rd); + insn->modrm = modrm; + + mod = modrm.mode; + rm = (uint8_t)((REX_B(insn->rex) << 3) | modrm.rm); + reg = (uint8_t)((REX_R(insn->rex) << 3) | modrm.reg); + + x86_insn_operand_t *reg_op = &insn->operands[0]; + x86_insn_operand_t *mem_op = &insn->operands[1]; + + reg_op->reg = reg; + + if (mod == 3) { + mem_op->reg = rm; + return; + } + + uint8_t disp_bits = -1; + + insn->flags |= X86_INSN_DECODE_FLAG_IS_ADDRESS; + + uint8_t effective_address_bits; + if (conf->mode == 64) + effective_address_bits = (insn->prefix & INSN_PREFIX_ADDRESS_SIZE) ? 32 : 64; + else if (conf->mode == 32) + effective_address_bits = (insn->prefix & INSN_PREFIX_ADDRESS_SIZE) ? 16 : 32; + else { + ERROR_LOG("16-bit address mode not supported"); + } + + if (effective_address_bits == 32 || effective_address_bits == 64) { + mem_op->mem.base = rm; + + insn->flags |= X86_INSN_DECODE_FLAG_HAS_BASE; + + if (mod == 0 && (rm & 7) == 5) { + insn->flags = X86_INSN_DECODE_FLAG_IP_RELATIVE; + mem_op->mem.base = RIP; + disp_bits = 32; + } else if (mod == 0) { + disp_bits = 0; + } else if (mod == 1) { + disp_bits = 8; + } else if (mod == 2) { + disp_bits = 32; + } else { + disp_bits = 0; + } + + uint8_t has_sib = 0; + if ((rm & 7) == 4) { + ASSERT(modrm.rm == (rm & 7)); + has_sib = 1; + } + + if (has_sib) { + x86_insn_sib_t sib = {0}; + sib.byte = read_byte(rd); + insn->sib = sib; + + uint8_t base = (uint8_t)(sib.base | (REX_B(insn->rex) << 3)); + uint8_t index = (uint8_t)(sib.index | (REX_X(insn->rex) << 3)); + uint8_t scale = (uint8_t)(1 << sib.log2_scale); + + insn->flags |= X86_INSN_DECODE_FLAG_HAS_BASE; + + if (sib.index != X86_INSN_GP_REG_SP) { + insn->flags |= X86_INSN_DECODE_FLAG_HAS_INDEX; + } + + insn->operands[1].mem.base = base; + insn->operands[1].mem.index = index; + insn->operands[1].mem.scale = scale; + + if (sib.index == X86_INSN_GP_REG_SP) { + insn->operands[1].mem.index = RNone; + insn->operands[1].mem.scale = 0; + } + + // for 64 bit + if (effective_address_bits == 64) { + if (mem_op->mem.base == RBP || mem_op->mem.base == R13) { + if (mod == 0) { + mem_op->mem.base = RNone; + } + if (mod == 1) { + disp_bits = 8; + } else { + disp_bits = 32; + } + } + + if (sib.index != X86_INSN_GP_REG_SP) { + insn->flags |= X86_INSN_DECODE_FLAG_HAS_INDEX; + } + } + + // for 32 bit + if (effective_address_bits == 32) { + if (mem_op->mem.base == RBP) { + if (mod == 0) { + mem_op->mem.base = RNone; + } + if (mod == 1) { + disp_bits = 8; + } else { + disp_bits = 32; + } + } + } + } + } + + // for 16 bit + if (effective_address_bits == 16) { + switch (modrm.mode) { + case 0: + if (modrm.rm == 6) { + /* [disp16] */ + disp_bits = 16; + break; + } + /* fall through */ + case 1: + case 2: + switch (modrm.rm) { + case 0: /* [bx + si/di] */ + case 1: + mem_op->mem.base = X86_INSN_GP_REG_BX; + mem_op->mem.index = X86_INSN_GP_REG_SI + (modrm.rm & 1); + insn->flags |= X86_INSN_DECODE_FLAG_HAS_BASE | X86_INSN_DECODE_FLAG_HAS_INDEX; + break; + + case 2: /* [bp + si/di] */ + case 3: + mem_op->mem.base = X86_INSN_GP_REG_BP; + mem_op->mem.index = X86_INSN_GP_REG_SI + (modrm.rm & 1); + insn->flags |= X86_INSN_DECODE_FLAG_HAS_BASE | X86_INSN_DECODE_FLAG_HAS_INDEX; + break; + + case 4: /* [si/di] */ + case 5: + mem_op->mem.base = X86_INSN_GP_REG_SI + (modrm.rm & 1); + insn->flags |= X86_INSN_DECODE_FLAG_HAS_BASE; + break; + + case 6: /* [bp + disp] */ + mem_op->mem.base = X86_INSN_GP_REG_BP; + insn->flags |= X86_INSN_DECODE_FLAG_HAS_BASE; + break; + + case 7: /* [bx + disp] */ + mem_op->mem.base = X86_INSN_GP_REG_BX; + insn->flags |= X86_INSN_DECODE_FLAG_HAS_BASE; + break; + } + + if (modrm.mode != 0) + disp_bits = modrm.mode == 1 ? 8 : 16; + break; + } + } + + if (disp_bits != 0) { + // update displacement offset + insn->displacement_offset = (uint8_t)reader_offset(rd); + + int64_t disp; + x86_insn_decode_number(rd, disp_bits, &disp); + mem_op->mem.disp = disp; + } +} + +/* Decodes the opcode of an instruction and returns its encoding + * specification. + */ +static void x86_insn_decode_opcode(x86_insn_reader_t *rd, x86_insn_decode_t *insn, x86_options_t *conf) { + uint8_t opcode = read_byte(rd); + + x86_insn_spec_t insn_spec; + if (opcode == 0x0f) { + opcode = read_byte(rd); + insn_spec = x86_opcode_map_two_byte[opcode]; + } else { + insn_spec = x86_opcode_map_one_byte[opcode]; + } + + // check sse group + if (X86_INSN_FLAG_GET_GROUP(insn_spec.flags) > X86_INSN_SSE_GROUP_START) { + UNIMPLEMENTED(); + } + + if (X86_INSN_FLAG_GET_GROUP(insn_spec.flags) > X86_INSN_GROUP_START && + X86_INSN_FLAG_GET_GROUP(insn_spec.flags) < X86_INSN_SSE_GROUP_START) { + // get group index + int group_ndx = X86_INSN_FLAG_GET_GROUP(insn_spec.flags); + + // get gp insn index in group + x86_insn_modrm_t modrm; + modrm.byte = peek_byte(rd); + int insn_ndx = modrm.reg; + + // get insn in group + x86_insn_spec_t *group_insn = NULL; + group_insn = &x86_insn_modrm_reg_groups[group_ndx].insns[insn_ndx]; + + // update the insn spec + insn_spec.name = group_insn->name; + insn_spec.flags = group_insn->flags; + } + + insn->primary_opcode = opcode; + insn->insn_spec = insn_spec; +} + +uint8_t x86_insn_imm_bits(x86_insn_spec_t *insn, uint8_t operand_bits) { + uint8_t imm_bits = 0; + switch (x86_insn_immediate_type(insn)) { + case 'b': + imm_bits = 8; + break; + case 'w': + imm_bits = 16; + break; + case 'd': + imm_bits = 32; + break; + case 'q': + imm_bits = 64; + break; + + case 'z': + imm_bits = operand_bits; + if (imm_bits == 64) + imm_bits = 32; + break; + + case 'v': + imm_bits = operand_bits; + break; + + default: + imm_bits = 0; + break; + } + + return imm_bits; +} + +void x86_insn_decode_immediate(x86_insn_reader_t *rd, x86_insn_decode_t *insn, x86_options_t *conf) { + uint8_t effective_operand_bits; + if (conf->mode == 64 || conf->mode == 32) { + effective_operand_bits = (insn->prefix & INSN_PREFIX_OPERAND_SIZE) ? 16 : 32; + } + effective_operand_bits = (insn->prefix & INSN_PREFIX_OPERAND_SIZE) ? 16 : 32; + + if (insn->flags & X86_INSN_DECODE_FLAG_OPERAND_SIZE_64) + effective_operand_bits = 64; + + if (conf->mode == 64 && insn->insn_spec.flags & X86_INSN_SPEC_DEFAULT_64_BIT) + effective_operand_bits = 64; + + int64_t immediate = 0; + uint8_t imm_bits = x86_insn_imm_bits(&insn->insn_spec, effective_operand_bits); + if (imm_bits == 0) + return; + + // update immediate offset + insn->immediate_offset = (uint8_t)reader_offset(rd); + + x86_insn_decode_number(rd, imm_bits, &immediate); + insn->immediate = immediate; +} + +void x86_insn_decode(x86_insn_decode_t *insn, uint8_t *buffer, x86_options_t *conf) { + // init reader + x86_insn_reader_t rd; + init_reader(&rd, buffer, buffer + 15); + + // decode prefix + insn->prefix = x86_insn_decode_prefix(&rd, insn, conf); + + // decode insn specp/x in + x86_insn_decode_opcode(&rd, insn, conf); + + if (x86_insn_has_modrm_byte(&insn->insn_spec)) { + // decode insn modrm sib (operand register, disp) + x86_insn_decode_modrm_sib(&rd, insn, conf); + } + + if (x86_insn_has_immediate(&insn->insn_spec)) { + // decode insn immeidate + x86_insn_decode_immediate(&rd, insn, conf); + } + +#if 1 + DEBUG_LOG("[x86 insn] %s", insn->insn_spec.name); +#endif + + // set insn length + insn->length = rd.buffer_cursor - rd.buffer; +} + +#endif \ No newline at end of file diff --git a/app/src/main/cpp/Dobby/source/InstructionRelocation/x86/x86_insn_decode/x86_insn_decode.h b/app/src/main/cpp/Dobby/source/InstructionRelocation/x86/x86_insn_decode/x86_insn_decode.h new file mode 100644 index 0000000..b08ee9b --- /dev/null +++ b/app/src/main/cpp/Dobby/source/InstructionRelocation/x86/x86_insn_decode/x86_insn_decode.h @@ -0,0 +1,200 @@ +#ifndef X86_INSN_DECODE_H +#define X86_INSN_DECODE_H + +#include +#include "dobby/common.h" + +typedef enum { + X86_INSN_SPEC_DEFAULT_64_BIT = 1 << 0, +} x86_insn_spec_flag_t; + +typedef enum { + X86_INSN_DECODE_FLAG_HAS_BASE = 1 << 0, + + X86_INSN_DECODE_FLAG_HAS_INDEX = 1 << 1, + + X86_INSN_DECODE_FLAG_IS_ADDRESS = 1 << 2, + + X86_INSN_DECODE_FLAG_IP_RELATIVE = 1 << 3, + + X86_INSN_DECODE_FLAG_OPERAND_SIZE_64 = 1 << 4, +} x86_insn_decode_flag_t; + +typedef enum { + INSN_PREFIX_NONE = 0, + + /* Group 1: lock and repeat prefixes */ + INSN_PREFIX_GROUP1 = 0x07, + INSN_PREFIX_LOCK = 0x01, /* F0 */ + INSN_PREFIX_REPNZ = 0x02, /* F2 */ + INSN_PREFIX_REPNE = INSN_PREFIX_REPNZ, + INSN_PREFIX_REP = 0x04, /* F3 */ + INSN_PREFIX_REPZ = INSN_PREFIX_REP, + INSN_PREFIX_REPE = INSN_PREFIX_REPZ, + + /* Group 2: segment override or branch hints */ + INSN_PREFIX_GROUP2 = 0x01f8, + INSN_PREFIX_ES = 0x0008, /* 26 */ + INSN_PREFIX_CS = 0x0010, /* 2E */ + INSN_PREFIX_SS = 0x0020, /* 36 */ + INSN_PREFIX_DS = 0x0040, /* 3E */ + INSN_PREFIX_FS = 0x0080, /* 64 */ + INSN_PREFIX_GS = 0x0100, /* 65 */ + INSN_PREFIX_BRANCH_TAKEN = INSN_PREFIX_CS, /* 2E */ + INSN_PREFIX_BRANCH_NOT_TAKEN = INSN_PREFIX_DS, /* 3E */ + + /* Group 3: operand-size override */ + INSN_PREFIX_OPERAND_SIZE = 0x0200, /* 66 */ + + /* Group 4: address-size override */ + INSN_PREFIX_ADDRESS_SIZE = 0x0400 /* 67 */ +} x86_insn_prefix_t; + +typedef union { + struct { + uint8_t code; + uint8_t type; + }; + uint8_t data[2]; +} x86_insn_operand_spec_t; + +typedef struct { + // insn name + char *name; + + // insn max 3 operands + x86_insn_operand_spec_t operands[3]; + + // insn flag + uint16_t flags; +#define X86_INSN_FLAG_SET_SSE_GROUP(n) ((n) << 5) +#define X86_INSN_FLAG_GET_SSE_GROUP(f) (((f) >> 5) & 0x1f) +#define X86_INSN_FLAG_SET_MODRM_REG_GROUP(n) (((n)&0x3f) << 10) +#define X86_INSN_FLAG_GET_MODRM_REG_GROUP(f) (((f) >> 10) & 0x3f) +} x86_insn_spec_t; + +#define foreach_x86_gp_register _(AX) _(CX) _(DX) _(BX) _(SP) _(BP) _(SI) _(DI) + +typedef enum { +#define _(r) X86_INSN_GP_REG_##r, + foreach_x86_gp_register +#undef _ +} x86_insn_gp_register_t; + +typedef enum { + RNone = 0, + RAX, + RBX, + RCX, + RDX, + RDI, + RSI, + RBP, + RSP, + R8, + R9, + R10, + R11, + R12, + R13, + R14, + R15, + RIP +} x86_ia32e_register_t; + +typedef union { + struct { + uint8_t rm : 3; + uint8_t reg : 3; + uint8_t mode : 2; + }; + uint8_t byte; +} x86_insn_modrm_t; + +typedef union { + struct { + uint8_t base : 3; + uint8_t index : 3; + uint8_t log2_scale : 2; + }; + uint8_t byte; +} x86_insn_sib_t; + +typedef struct { + uint8_t reg; + + struct { + uint8_t base; + uint8_t index; + uint8_t scale; + uint32_t disp; + } mem; +} x86_insn_operand_t; + +typedef struct x86_insn_decode_t { + // insn flag + uint32_t flags; + + // insn length + uint32_t length; + + // insn displacement offset + uint8_t displacement_offset; + + // insn immediate offset + uint8_t immediate_offset; + + // Registers in instruction + // [0] is modrm reg field + // [1] is base reg + // [2] is index reg + // union { + // struct { + // uint8_t modrm_reg; + // uint8_t op_base_reg; + // uint8_t op_index_reg; + // }; + // uint8_t regs[3]; + // }; + + x86_insn_operand_t operands[3]; + + struct { // insn field combine + // insn prefix + x86_insn_prefix_t prefix; + + // insn rex + uint8_t rex; + + // insn primary opcode + uint8_t primary_opcode; + + // insn modrm + x86_insn_modrm_t modrm; + + // insn sib + x86_insn_sib_t sib; + + // insn operand imm + int64_t immediate; + }; + + // insn pre-spec + x86_insn_spec_t insn_spec; +} x86_insn_decode_t; + +typedef struct x86_options_t { + int mode; /* 16, 32 or 64 bit */ +} x86_options_t; + +#ifdef __cplusplus +extern "C" { +#endif + +void x86_insn_decode(x86_insn_decode_t *insn, uint8_t *buffer, x86_options_t *conf); + +#ifdef __cplusplus +} +#endif + +#endif \ No newline at end of file diff --git a/app/src/main/cpp/Dobby/source/InstructionRelocation/x86/x86_insn_decode/x86_insn_reader.c b/app/src/main/cpp/Dobby/source/InstructionRelocation/x86/x86_insn_decode/x86_insn_reader.c new file mode 100644 index 0000000..214c060 --- /dev/null +++ b/app/src/main/cpp/Dobby/source/InstructionRelocation/x86/x86_insn_decode/x86_insn_reader.c @@ -0,0 +1,87 @@ +/* Specialized instruction reader. */ +typedef struct x86_insn_reader_t { + const unsigned char *prefix; /* pointer to beginning of instruction */ + const unsigned char *opcode; /* pointer to opcode */ + const unsigned char *modrm; /* pointer to modrm byte */ + + unsigned char buffer[20]; /* buffer used when few bytes left */ + const unsigned char *buffer_cursor; /* pointer to buffer_cursor of insn + 1 */ +} x86_insn_reader_t; + +/* Initializes a bytecode reader to read code from a given part of memory. */ +static void init_reader(x86_insn_reader_t *rd, const unsigned char *begin, const unsigned char *buffer_cursor) { + if (buffer_cursor - begin < sizeof(rd->buffer)) { + memset(rd->buffer, 0xcc, sizeof(rd->buffer)); /* debug token */ + memcpy(rd->buffer, begin, buffer_cursor - begin); + rd->prefix = rd->buffer; + } else { + rd->prefix = begin; + } + rd->opcode = rd->modrm = rd->buffer_cursor = rd->prefix; +} + +uint32_t reader_offset(x86_insn_reader_t *rd) { + return rd->buffer_cursor - rd->buffer; +} + +static uint8_t peek_byte(const x86_insn_reader_t *rd) { + return *rd->buffer_cursor; +} + +#define read_uint8 read_byte +static uint8_t read_byte(x86_insn_reader_t *rd) { + DEBUG_LOG("[x86 insn reader] %p - 1", rd->buffer_cursor); + + const unsigned char *p = rd->buffer_cursor; + rd->buffer_cursor++; + return *p; +} + +#define read_uint16 read_word +static uint16_t read_word(x86_insn_reader_t *rd) { + DEBUG_LOG("[x86 insn reader] %p - 2", rd->buffer_cursor); + + const unsigned char *p = rd->buffer_cursor; + rd->buffer_cursor += 2; + return (uint16_t)((uint16_t)p[0] | ((uint16_t)p[1] << 8)); +} + +#define read_uint32 read_dword +static uint32_t read_dword(x86_insn_reader_t *rd) { + DEBUG_LOG("[x86 insn reader] %p - 4", rd->buffer_cursor); + + const unsigned char *p = rd->buffer_cursor; + rd->buffer_cursor += 4; + return (uint32_t)p[0] | ((uint32_t)p[1] << 8) | ((uint32_t)p[2] << 16) | ((uint32_t)p[3] << 24); +} + +#define read_uint64 read_qword +static uint64_t read_qword(x86_insn_reader_t *rd) { + DEBUG_LOG("[x86 insn reader] %p - 8", rd->buffer_cursor); + + uint64_t *p = (uint64_t *)rd->buffer_cursor; + rd->buffer_cursor += 4; + return p[0]; +} + +static uint32_t read_imm(x86_insn_reader_t *rd, int size) { + DEBUG_LOG("[x86 insn reader] %p", rd->buffer_cursor); + + return (size == 8) ? read_byte(rd) : (size == 16) ? read_word(rd) : (size == 32) ? read_dword(rd) : 0; +} + +static unsigned char read_modrm(x86_insn_reader_t *rd) { + if (rd->buffer_cursor == rd->modrm) + rd->buffer_cursor++; + return *rd->modrm; +} + +/* Marks the next byte as ModR/M. */ +static void continue_modrm(x86_insn_reader_t *rd) { + rd->modrm = rd->buffer_cursor; +} + +/* Marks the next byte as opcode. */ +static void continue_opcode(x86_insn_reader_t *rd) { + rd->modrm = rd->opcode = rd->buffer_cursor; +} diff --git a/app/src/main/cpp/Dobby/source/InstructionRelocation/x86/x86_insn_decode/x86_opcode_modrm_reg_group.c b/app/src/main/cpp/Dobby/source/InstructionRelocation/x86/x86_insn_decode/x86_opcode_modrm_reg_group.c new file mode 100644 index 0000000..352ea1a --- /dev/null +++ b/app/src/main/cpp/Dobby/source/InstructionRelocation/x86/x86_insn_decode/x86_opcode_modrm_reg_group.c @@ -0,0 +1,218 @@ +/* Escape groups are indexed by modrm reg field. */ +static x86_insn_group8_t x86_insn_modrm_reg_groups[] = { + [X86_INSN_MODRM_REG_GROUP_1].insns = + { + op0(add), + op0(or), + op0(adc), + op0(sbb), + op0(and), + op0(sub), + op0(xor), + op0(cmp), + }, + + [X86_INSN_MODRM_REG_GROUP_1a].insns = + { + op0f(pop, X86_INSN_SPEC_DEFAULT_64_BIT), + op0(bad), + op0(bad), + op0(bad), + op0(bad), + op0(bad), + op0(bad), + op0(bad), + }, + + [X86_INSN_MODRM_REG_GROUP_2].insns = + { + op0(rol), + op0(ror), + op0(rcl), + op0(rcr), + op0(shl), + op0(shr), + op0(sal), + op0(sar), + }, + + [X86_INSN_MODRM_REG_GROUP_3].insns = + { + op0(test), + op0(test), + op0(not ), + op0(neg), + op0(mul), + op0(imul), + op0(div), + op0(idiv), + }, + + [X86_INSN_MODRM_REG_GROUP_4].insns = + { + op0(inc), + op0(dec), + op0(bad), + op0(bad), + op0(bad), + op0(bad), + op0(bad), + op0(bad), + }, + + [X86_INSN_MODRM_REG_GROUP_5].insns = + { + op1(inc, Ev), + op1(dec, Ev), + op1f(call, X86_INSN_SPEC_DEFAULT_64_BIT, Ev), + op1(call, Mp), + op1f(jmp, X86_INSN_SPEC_DEFAULT_64_BIT, Ev), + op1(jmp, Mp), + op1f(push, X86_INSN_SPEC_DEFAULT_64_BIT, Ev), + op0(bad), + }, + + [X86_INSN_MODRM_REG_GROUP_6].insns = + { + op1(sldt, Ev), + op1(str, Ev), + op1(lldt, Ev), + op1(ltr, Ev), + op1(verr, Ev), + op1(verw, Ev), + op0(bad), + op0(bad), + }, + + [X86_INSN_MODRM_REG_GROUP_7].insns = + { + op1(sgdt, Mv), + op1(sidt, Mv), + op1(lgdt, Mv), + op1(lidt, Mv), + op1(smsw, Ev), + op0(bad), + op1(lmsw, Ew), + op1(invlpg, Mv), + }, + + [X86_INSN_MODRM_REG_GROUP_8].insns = + { + op0(bad), + op0(bad), + op0(bad), + op0(bad), + op2(bt, Ev, Ib), + op2(bts, Ev, Ib), + op2(btr, Ev, Ib), + op2(btc, Ev, Ib), + }, + + [X86_INSN_MODRM_REG_GROUP_9].insns = + { + op0(bad), + op1(cmpxchg, Mx), + op0(bad), + op0(bad), + op0(bad), + op0(bad), + op0(bad), + op0(bad), + }, + + [X86_INSN_MODRM_REG_GROUP_10].insns = + { + op0(bad), + op0(bad), + op0(bad), + op0(bad), + op0(bad), + op0(bad), + op0(bad), + op0(bad), + }, + + [X86_INSN_MODRM_REG_GROUP_11].insns = + { + op0(mov), + op0(bad), + op0(bad), + op0(bad), + op0(bad), + op0(bad), + op0(bad), + op0(bad), + }, + + [X86_INSN_MODRM_REG_GROUP_12].insns = + { + op0(bad), + op0(bad), + op2(psrlw, Rm, Ib), + op0(bad), + op2(psraw, Rm, Ib), + op0(bad), + op2(psllw, Rm, Ib), + op0(bad), + }, + + [X86_INSN_MODRM_REG_GROUP_13].insns = + { + op0(bad), + op0(bad), + op2(psrld, Rm, Ib), + op0(bad), + op2(psrad, Rm, Ib), + op0(bad), + op2(pslld, Rm, Ib), + op0(bad), + }, + + [X86_INSN_MODRM_REG_GROUP_14].insns = + { + op0(bad), + op0(bad), + op2(psrlq, Rm, Ib), + op0f(bad, 0), + op0(bad), + op0(bad), + op2(psllq, Rm, Ib), + op0f(bad, 0), + }, + + [X86_INSN_MODRM_REG_GROUP_15].insns = + { + op1(fxsave, Mv), + op1(fxrstor, Mv), + op1(ldmxcsr, Mv), + op1(stmxcsr, Mv), + op0(bad), + op1(lfence, Mv), + op1(mfence, Mv), + op1(sfence, Mv), + }, + + [X86_INSN_MODRM_REG_GROUP_16].insns = + { + op1(prefetch_nta, Mv), + op1(prefetch_t0, Mv), + op1(prefetch_t1, Mv), + op1(prefetch_t2, Mv), + op1(prefetch_nop, Mv), + op1(prefetch_nop, Mv), + op1(prefetch_nop, Mv), + op1(prefetch_nop, Mv), + }, + + [X86_INSN_MODRM_REG_GROUP_p].insns = + { + op1(prefetch_exclusive, Mv), + op1(prefetch_modified, Mv), + op1(prefetch_nop, Mv), + op1(prefetch_modified, Mv), + op1(prefetch_nop, Mv), + op1(prefetch_nop, Mv), + op1(prefetch_nop, Mv), + op1(prefetch_nop, Mv), + }, +}; diff --git a/app/src/main/cpp/Dobby/source/InstructionRelocation/x86/x86_insn_decode/x86_opcode_one_byte.c b/app/src/main/cpp/Dobby/source/InstructionRelocation/x86/x86_insn_decode/x86_opcode_one_byte.c new file mode 100644 index 0000000..44b1462 --- /dev/null +++ b/app/src/main/cpp/Dobby/source/InstructionRelocation/x86/x86_insn_decode/x86_opcode_one_byte.c @@ -0,0 +1,215 @@ +// clang-format off +static x86_insn_spec_t x86_opcode_map_one_byte[256] = { + /* 0x00 */ + foreach_x86_operand_combine(add, op_dst, op_src), + op0(push_es), + op0f(pop_es, X86_INSN_SPEC_DEFAULT_64_BIT), + foreach_x86_operand_combine(or, op_dst, op_src), + op0f(push_cs, X86_INSN_SPEC_DEFAULT_64_BIT), + op0(escape_two_byte), + + /* 0x10 */ + foreach_x86_operand_combine(adc, op_dst, op_src), + op0(push_ss), + op0(pop_ss), + foreach_x86_operand_combine(sbb, op_dst, op_src), + op0(push_ds), + op0(pop_ds), + + /* 0x20 */ + foreach_x86_operand_combine(and, op_dst, op_src), + op0(segment_es), + op0(daa), + foreach_x86_operand_combine(sub, op_dst, op_src), + op0(segment_cs), + op0(das), + + /* 0x30 */ + foreach_x86_operand_combine(xor, op_dst, op_src), + op0(segment_ss), + op0(aaa), + foreach_x86_operand_combine(cmp, op_src, op_src), + op0(segment_ds), + op0(aas), + +/* 0x40 */ +#define _(r) op1(inc, r), + foreach_x86_gp_reg +#undef _ +#define _(r) op1(dec, r), + foreach_x86_gp_reg +#undef _ + +/* 0x50 */ +#define _(r) op1f(push, X86_INSN_SPEC_DEFAULT_64_BIT, r), + foreach_x86_gp_reg +#undef _ +#define _(r) op1f(pop, X86_INSN_SPEC_DEFAULT_64_BIT, r), + foreach_x86_gp_reg +#undef _ + + /* 0x60 */ + op0(pusha), + op0(popa), + op2(bound, Gv, Ma), + op2(movsxd, Gv, Ed), + op0(segment_fs), + op0(segment_gs), + op0(operand_type), + op0(address_size), + op1f(push, X86_INSN_SPEC_DEFAULT_64_BIT, Iz), + op3(imul, Gv, Ev, Iz), + op1f(push, X86_INSN_SPEC_DEFAULT_64_BIT, Ib), + op3(imul, Gv, Ev, Ib), + op1(insb, DX), + op1(insw, DX), + op1(outsb, DX), + op1(outsw, DX), + +/* 0x70 */ +#define _(x) op1(j##x, Jb), + foreach_x86_condition +#undef _ + + /* 0x80 */ + op2f(modrm_group_1, X86_INSN_FLAG_MODRM_REG_GROUP_1, Eb, Ib), + op2f(modrm_group_1, X86_INSN_FLAG_MODRM_REG_GROUP_1, Ev, Iz), + op2f(modrm_group_1, X86_INSN_FLAG_MODRM_REG_GROUP_1, Eb, Ib), + op2f(modrm_group_1, X86_INSN_FLAG_MODRM_REG_GROUP_1, Ev, Ib), + op2(test, Eb, Gb), + op2(test, Ev, Gv), + op2(xchg, Eb, Gb), + op2(xchg, Ev, Gv), + op2(mov, Eb, Gb), + op2(mov, Ev, Gv), + op2(mov, Gb, Eb), + op2(mov, Gv, Ev), + op2(mov, Ev, Sw), + op2(lea, Gv, Ev), + op2(mov, Sw, Ew), + op1f(modrm_group_1a, X86_INSN_FLAG_MODRM_REG_GROUP_1a, Ev), + + /* 0x90 */ + op0(nop), + op1(xchg, CX), + op1(xchg, DX), + op1(xchg, BX), + op1(xchg, SP), + op1(xchg, BP), + op1(xchg, SI), + op1(xchg, DI), + op0(cbw), + op0(cwd), + op1(call, Ap), + op0(wait), + op0(pushf), + op0(popf), + op0(sahf), + op0(lahf), + + /* 0xa0 */ + op2(mov, AL, Ob), + op2(mov, AX, Ov), + op2(mov, Ob, AL), + op2(mov, Ov, AX), + op0(movsb), + op0(movsw), + op0(cmpsb), + op0(cmpsw), + op2(test, AL, Ib), + op2(test, AX, Iz), + op1(stosb, AL), + op1(stosw, AX), + op1(lodsb, AL), + op1(lodsw, AX), + op1(scasb, AL), + op1(scasw, AX), + + /* 0xb0 */ + op2(mov, AL, Ib), + op2(mov, CL, Ib), + op2(mov, DL, Ib), + op2(mov, BL, Ib), + op2(mov, AH, Ib), + op2(mov, CH, Ib), + op2(mov, DH, Ib), + op2(mov, BH, Ib), +#define _(r) op2(mov, r, Iv), + foreach_x86_gp_reg +#undef _ + + /* 0xc0 */ + op2f(modrm_group_2, X86_INSN_FLAG_MODRM_REG_GROUP_2, Eb, Ib), + op2f(modrm_group_2, X86_INSN_FLAG_MODRM_REG_GROUP_2, Ev, Ib), + op1(ret, Iw), + op0(ret), + op2(les, Gz, Mp), + op2(lds, Gz, Mp), + op2f(modrm_group_11, X86_INSN_FLAG_MODRM_REG_GROUP_11, Eb, Ib), + op2f(modrm_group_11, X86_INSN_FLAG_MODRM_REG_GROUP_11, Ev, Iz), + op2(enter, Iw, Ib), + op0(leave), + op1(ret, Iw), + op0(ret), + op0(int3), + op1(int, Ib), + op0(into), + op0(iret), + + /* 0xd0 */ + op2f(modrm_group_2, X86_INSN_FLAG_MODRM_REG_GROUP_2, Eb, 1b), + op2f(modrm_group_2, X86_INSN_FLAG_MODRM_REG_GROUP_2, Ev, 1b), + op2f(modrm_group_2, X86_INSN_FLAG_MODRM_REG_GROUP_2, Eb, CL), + op2f(modrm_group_2, X86_INSN_FLAG_MODRM_REG_GROUP_2, Ev, CL), + op0(aam), + op0(aad), + op0(salc), + op0(xlat), + /* FIXME x87 */ + op0(bad), + op0(bad), + op0(bad), + op0(bad), + op0(bad), + op0(bad), + op0(bad), + op0(bad), + + /* 0xe0 */ + op1(loopnz, Jb), + op1(loopz, Jb), + op1(loop, Jb), + op1(jcxz, Jb), + op2(in, AL, Ib), + op2(in, AX, Ib), + op2(out, Ib, AL), + op2(out, Ib, AX), + op1f(call, X86_INSN_SPEC_DEFAULT_64_BIT, Jz), + op1f(jmp, X86_INSN_SPEC_DEFAULT_64_BIT, Jz), + op1(jmp, Ap), + op1(jmp, Jb), + op2(in, AL, DX), + op2(in, AX, DX), + op2(out, DX, AL), + op2(out, DX, AX), + + /* 0xf0 */ + op0(lock), + op0(int1), + op0(repne), + op0(rep), + op0(hlt), + op0(cmc), + op0f(modrm_group_3, X86_INSN_FLAG_MODRM_REG_GROUP_3), + op0f(modrm_group_3, X86_INSN_FLAG_MODRM_REG_GROUP_3), + op0(clc), + op0(stc), + op0(cli), + op0(sti), + op0(cld), + op0(std), + op1f(modrm_group_4, X86_INSN_FLAG_MODRM_REG_GROUP_4, Eb), + op0f(modrm_group_5, X86_INSN_FLAG_MODRM_REG_GROUP_5), +}; + +// clang-format on \ No newline at end of file diff --git a/app/src/main/cpp/Dobby/source/InstructionRelocation/x86/x86_insn_decode/x86_opcode_sse_group.c b/app/src/main/cpp/Dobby/source/InstructionRelocation/x86/x86_insn_decode/x86_opcode_sse_group.c new file mode 100644 index 0000000..8e56a9b --- /dev/null +++ b/app/src/main/cpp/Dobby/source/InstructionRelocation/x86/x86_insn_decode/x86_opcode_sse_group.c @@ -0,0 +1,545 @@ +static x86_insn_group8_t x86_insn_sse_groups_repz[] = { + [X86_INSN_SSE_GROUP_10].insns = + { + op2(movss, Gx, Ex), + op2(movss, Ex, Gx), + op2(movsldup, Gx, Ex), + op0(bad), + op0(bad), + op0(bad), + op2(movshdup, Gx, Ex), + op0(bad), + }, + + [X86_INSN_SSE_GROUP_28].insns = + { + op0(bad), + op0(bad), + op2(cvtsi2ss, Gx, Ev), + op0(bad), + op2(cvttss2si, Gv, Ex), + op2(cvtss2si, Gv, Ex), + op0(bad), + op0(bad), + }, + + [X86_INSN_SSE_GROUP_50].insns = + { + op0(bad), + op2(sqrtss, Gx, Ex), + op2(rsqrtps, Gx, Ex), + op2(rcpss, Gx, Ex), + op0(bad), + op0(bad), + op0(bad), + op0(bad), + }, + + [X86_INSN_SSE_GROUP_58].insns = + { + op2(addss, Gx, Ex), + op2(mulss, Gx, Ex), + op2(cvtss2sd, Gx, Ex), + op2(cvttps2dq, Gx, Ex), + op2(subss, Gx, Ex), + op2(minss, Gx, Ex), + op2(divss, Gx, Ex), + op2(maxss, Gx, Ex), + }, + + [X86_INSN_SSE_GROUP_60].insns = + { + op0(bad), + op0(bad), + op0(bad), + op0(bad), + op0(bad), + op0(bad), + op0(bad), + op0(bad), + }, + + [X86_INSN_SSE_GROUP_68].insns = + { + op0(bad), + op0(bad), + op0(bad), + op0(bad), + op0(bad), + op0(bad), + op0(bad), + op2(movdqu, Gx, Ex), + }, + + [X86_INSN_SSE_GROUP_70].insns = + { + op3(pshufhw, Gx, Ex, Ib), + op0(bad), + op0(bad), + op0(bad), + op0(bad), + op0(bad), + op0(bad), + op0(bad), + }, + + [X86_INSN_SSE_GROUP_78].insns = + { + op0(bad), + op0(bad), + op0(bad), + op0(bad), + op0(bad), + op0(bad), + op2(movq, Gx, Ex), + op2(movdqu, Ex, Gx), + }, + + [X86_INSN_SSE_GROUP_c0].insns = + { + op0(bad), + op0(bad), + op3(cmpss, Gx, Ex, Ib), + op0(bad), + op0(bad), + op0(bad), + op0(bad), + op0(bad), + }, + + [X86_INSN_SSE_GROUP_d0].insns = + { + op0(bad), + op0(bad), + op0(bad), + op0(bad), + op0(bad), + op0(bad), + op2(movq2dq, Gx, Em), + op0(bad), + }, + + [X86_INSN_SSE_GROUP_d8].insns = + { + op0(bad), + op0(bad), + op0(bad), + op0(bad), + op0(bad), + op0(bad), + op0(bad), + op0(bad), + }, + + [X86_INSN_SSE_GROUP_e0].insns = + { + op0(bad), + op0(bad), + op0(bad), + op0(bad), + op0(bad), + op0(bad), + op2(cvtdq2pd, Gx, Ex), + op0(bad), + }, + + [X86_INSN_SSE_GROUP_e8].insns = + { + op0(bad), + op0(bad), + op0(bad), + op0(bad), + op0(bad), + op0(bad), + op0(bad), + op0(bad), + }, + + [X86_INSN_SSE_GROUP_f0].insns = + { + op0(bad), + op0(bad), + op0(bad), + op0(bad), + op0(bad), + op0(bad), + op0(bad), + op0(bad), + }, + + [X86_INSN_SSE_GROUP_f8].insns = + { + op0(bad), + op0(bad), + op0(bad), + op0(bad), + op0(bad), + op0(bad), + op0(bad), + op0(bad), + }, +}; + +static x86_insn_group8_t x86_insn_sse_groups_operand_size[] = { + [X86_INSN_SSE_GROUP_10].insns = + { + op2(movupd, Gx, Ex), + op2(movupd, Ex, Gx), + op2(movlpd, Gx, Ex), + op2(movlpd, Ex, Gx), + op2(unpcklpd, Gx, Ex), + op2(unpckhpd, Gx, Ex), + op2(movhpd, Gx, Mx), + op2(movhpd, Mx, Gx), + }, + + [X86_INSN_SSE_GROUP_28].insns = + { + op2(movapd, Gx, Ex), + op2(movapd, Ex, Gx), + op2(cvtpi2pd, Gx, Ex), + op2(movntpd, Mx, Gx), + op2(cvttpd2pi, Gx, Mx), + op2(cvtpd2pi, Gx, Mx), + op2(ucomisd, Gx, Ex), + op2(comisd, Gx, Ex), + }, + + [X86_INSN_SSE_GROUP_50].insns = + { + op2(movmskpd, Gd, Rx), + op2(sqrtpd, Gx, Ex), + op0(bad), + op0(bad), + op2(andpd, Gx, Ex), + op2(andnpd, Gx, Ex), + op2(orpd, Gx, Ex), + op2(xorpd, Gx, Ex), + }, + + [X86_INSN_SSE_GROUP_58].insns = + { + op2(addpd, Gx, Ex), + op2(mulpd, Gx, Ex), + op2(cvtpd2ps, Gx, Ex), + op2(cvtps2dq, Gx, Ex), + op2(subpd, Gx, Ex), + op2(minpd, Gx, Ex), + op2(divpd, Gx, Ex), + op2(maxpd, Gx, Ex), + }, + + [X86_INSN_SSE_GROUP_60].insns = + { + op2(punpcklbw, Gx, Ex), + op2(punpcklwd, Gx, Ex), + op2(punpckldq, Gx, Ex), + op2(packsswb, Gx, Ex), + op2(pcmpgtb, Gx, Ex), + op2(pcmpgtw, Gx, Ex), + op2(pcmpgtd, Gx, Ex), + op2(packuswb, Gx, Ex), + }, + + [X86_INSN_SSE_GROUP_68].insns = + { + op2(punpckhbw, Gx, Ex), + op2(punpckhwd, Gx, Ex), + op2(punpckhdq, Gx, Ex), + op2(packssdw, Gx, Ex), + op2(punpcklqdq, Gx, Ex), + op2(punpckhqdq, Gx, Ex), + op2(movd, Gx, Ev), + op2(movdqa, Gx, Ex), + }, + + [X86_INSN_SSE_GROUP_70].insns = + { + op3(pshufd, Gx, Ex, Ib), + op0f(modrm_group_12, X86_INSN_FLAG_MODRM_REG_GROUP_12), + op0f(modrm_group_13, X86_INSN_FLAG_MODRM_REG_GROUP_13), + op0f(modrm_group_14, X86_INSN_FLAG_MODRM_REG_GROUP_14), + op2(pcmpeqb, Gx, Ex), + op2(pcmpeqw, Gx, Ex), + op2(pcmpeqd, Gx, Ex), + op0(bad), + }, + + [X86_INSN_SSE_GROUP_78].insns = + { + op0(bad), + op0(bad), + op0(bad), + op0(bad), + op2(haddpd, Gx, Ex), + op2(hsubpd, Gx, Ex), + op2(movd, Ev, Gx), + op2(movdqa, Ex, Gx), + }, + + [X86_INSN_SSE_GROUP_c0].insns = + { + op0(bad), + op0(bad), + op3(cmppd, Gx, Ex, Ib), + op0(bad), + op3(pinsrw, Gx, Ew, Ib), + op3(pextrw, Gd, Gx, Ib), + op3(shufpd, Gx, Ex, Ib), + op0(bad), + }, + + [X86_INSN_SSE_GROUP_d0].insns = + { + op2(addsubpd, Gx, Ex), + op2(psrlw, Gx, Ex), + op2(psrld, Gx, Ex), + op2(psrlq, Gx, Ex), + op2(paddq, Gx, Ex), + op2(pmullw, Gx, Ex), + op2(movq, Ex, Gx), + op2(pmovmskb, Gd, Rx), + }, + + [X86_INSN_SSE_GROUP_d8].insns = + { + op2(psubusb, Gx, Ex), + op2(psubusw, Gx, Ex), + op2(pminub, Gx, Ex), + op2(pand, Gx, Ex), + op2(paddusb, Gx, Ex), + op2(paddusw, Gx, Ex), + op2(pmaxub, Gx, Ex), + op2(pandn, Gx, Ex), + }, + + [X86_INSN_SSE_GROUP_e0].insns = + { + op2(pavgb, Gx, Ex), + op2(psraw, Gx, Ex), + op2(psrad, Gx, Ex), + op2(pavgw, Gx, Ex), + op2(pmulhuw, Gx, Ex), + op2(pmulhw, Gx, Ex), + op2(cvttpd2dq, Gx, Ex), + op2(movntdq, Mx, Gx), + }, + + [X86_INSN_SSE_GROUP_e8].insns = + { + op2(psubsb, Gx, Ex), + op2(psubsw, Gx, Ex), + op2(pminsw, Gx, Ex), + op2(por, Gx, Ex), + op2(paddsb, Gx, Ex), + op2(paddsw, Gx, Ex), + op2(pmaxsw, Gx, Ex), + op2(pxor, Gx, Ex), + }, + + [X86_INSN_SSE_GROUP_f0].insns = + { + op0(bad), + op2(psllw, Gx, Ex), + op2(pslld, Gx, Ex), + op2(psllq, Gx, Ex), + op2(pmuludq, Gx, Ex), + op2(pmaddwd, Gx, Ex), + op2(psadbw, Gx, Ex), + op2(maskmovdqu, Gx, Ex), + }, + + [X86_INSN_SSE_GROUP_f8].insns = + { + op2(psubb, Gx, Ex), + op2(psubw, Gx, Ex), + op2(psubd, Gx, Ex), + op2(psubq, Gx, Ex), + op2(paddb, Gx, Ex), + op2(paddw, Gx, Ex), + op2(paddd, Gx, Ex), + op0(bad), + }, +}; + +static x86_insn_group8_t x86_insn_sse_groups_repnz[] = { + [X86_INSN_SSE_GROUP_10].insns = + { + op2(movsd, Gx, Ex), + op2(movsd, Ex, Gx), + op2(movddup, Gx, Ex), + op0(bad), + op0(bad), + op0(bad), + op0(bad), + op0(bad), + }, + + [X86_INSN_SSE_GROUP_28].insns = + { + op0(bad), + op0(bad), + op2(cvtsi2sd, Gx, Ev), + op0(bad), + op2(cvttsd2si, Gv, Ex), + op2(cvtsd2si, Gv, Ex), + op0(bad), + op0(bad), + }, + + [X86_INSN_SSE_GROUP_50].insns = + { + op0(bad), + op2(sqrtsd, Gx, Ex), + op0(bad), + op0(bad), + op0(bad), + op0(bad), + op0(bad), + op0(bad), + }, + + [X86_INSN_SSE_GROUP_58].insns = + { + op2(addsd, Gx, Ex), + op2(mulsd, Gx, Ex), + op2(cvtsd2ss, Gx, Ex), + op0(bad), + op2(subsd, Gx, Ex), + op2(minsd, Gx, Ex), + op2(divsd, Gx, Ex), + op2(maxsd, Gx, Ex), + }, + + [X86_INSN_SSE_GROUP_60].insns = + { + op0(bad), + op0(bad), + op0(bad), + op0(bad), + op0(bad), + op0(bad), + op0(bad), + op0(bad), + }, + + [X86_INSN_SSE_GROUP_68].insns = + { + op0(bad), + op0(bad), + op0(bad), + op0(bad), + op0(bad), + op0(bad), + op0(bad), + op0(bad), + }, + + [X86_INSN_SSE_GROUP_70].insns = + { + op3(pshuflw, Gx, Ex, Ib), + op0(bad), + op0(bad), + op0(bad), + op0(bad), + op0(bad), + op0(bad), + op0(bad), + }, + + [X86_INSN_SSE_GROUP_78].insns = + { + op0(bad), + op0(bad), + op0(bad), + op0(bad), + op2(haddps, Gx, Ex), + op2(hsubps, Gx, Ex), + op0(bad), + op0(bad), + }, + + [X86_INSN_SSE_GROUP_c0].insns = + { + op0(bad), + op0(bad), + op3(cmpsd, Gx, Ex, Ib), + op0(bad), + op0(bad), + op0(bad), + op0(bad), + op0(bad), + }, + + [X86_INSN_SSE_GROUP_d0].insns = + { + op2(addsubps, Gx, Ex), + op0(bad), + op0(bad), + op0(bad), + op0(bad), + op0(bad), + op2(movdq2q, Gm, Ex), + op0(bad), + }, + + [X86_INSN_SSE_GROUP_d8].insns = + { + op0(bad), + op0(bad), + op0(bad), + op0(bad), + op0(bad), + op0(bad), + op0(bad), + op0(bad), + }, + + [X86_INSN_SSE_GROUP_e0].insns = + { + op0(bad), + op0(bad), + op0(bad), + op0(bad), + op0(bad), + op0(bad), + op2(cvtpd2dq, Gx, Ex), + op0(bad), + }, + + [X86_INSN_SSE_GROUP_e8].insns = + { + op0(bad), + op0(bad), + op0(bad), + op0(bad), + op0(bad), + op0(bad), + op0(bad), + op0(bad), + }, + + [X86_INSN_SSE_GROUP_f0].insns = + { + op2(lddqu, Gx, Mx), + op0(bad), + op0(bad), + op0(bad), + op0(bad), + op0(bad), + op0(bad), + op0(bad), + }, + + [X86_INSN_SSE_GROUP_f8].insns = + { + op0(bad), + op0(bad), + op0(bad), + op0(bad), + op0(bad), + op0(bad), + op0(bad), + op0(bad), + }, +}; \ No newline at end of file diff --git a/app/src/main/cpp/Dobby/source/InstructionRelocation/x86/x86_insn_decode/x86_opcode_two_byte.c b/app/src/main/cpp/Dobby/source/InstructionRelocation/x86/x86_insn_decode/x86_opcode_two_byte.c new file mode 100644 index 0000000..900d0b3 --- /dev/null +++ b/app/src/main/cpp/Dobby/source/InstructionRelocation/x86/x86_insn_decode/x86_opcode_two_byte.c @@ -0,0 +1,249 @@ + +// clang-format off +static x86_insn_spec_t x86_opcode_map_two_byte[256] = { + /* 0x00 */ + op0f(modrm_group_6, X86_INSN_FLAG_MODRM_REG_GROUP_6), + op0f(modrm_group_7, X86_INSN_FLAG_MODRM_REG_GROUP_7), + op2(lar, Gv, Ew), + op2(lsl, Gv, Ew), + op0(bad), + op0(syscall), + op0(clts), + op0(sysret), + op0(invd), + op0(wbinvd), + op0(bad), + op0(ud2), + op0(bad), + op0f(modrm_group_p, X86_INSN_FLAG_MODRM_REG_GROUP_p), + op0(femms), + op0(escape_3dnow), + + /* 0x10 */ + op2f(movups, X86_INSN_FLAG_SSE_GROUP_10, Gx, Ex), + op2f(movups, X86_INSN_FLAG_SSE_GROUP_10, Ex, Gx), + op2f(movlps, X86_INSN_FLAG_SSE_GROUP_10, Ex, Gx), + op2f(movlps, X86_INSN_FLAG_SSE_GROUP_10, Gx, Ex), + op2f(unpcklps, X86_INSN_FLAG_SSE_GROUP_10, Gx, Ex), + op2f(unpckhps, X86_INSN_FLAG_SSE_GROUP_10, Gx, Ex), + op2f(movhps, X86_INSN_FLAG_SSE_GROUP_10, Ex, Gx), + op2f(movhps, X86_INSN_FLAG_SSE_GROUP_10, Gx, Ex), + op0f(modrm_group_16, X86_INSN_FLAG_MODRM_REG_GROUP_16), + op0(nop), + op0(nop), + op0(nop), + op0(nop), + op0(nop), + op0(nop), + op0(nop), + + /* 0x20 */ + op2(mov, Rv, Cv), + op2(mov, Rv, Dv), + op2(mov, Cv, Rv), + op2(mov, Dv, Rv), + op0(bad), + op0(bad), + op0(bad), + op0(bad), + op2f(movaps, X86_INSN_FLAG_SSE_GROUP_28, Gx, Ex), + op2f(movaps, X86_INSN_FLAG_SSE_GROUP_28, Ex, Gx), + op2f(cvtpi2ps, X86_INSN_FLAG_SSE_GROUP_28, Gx, Ex), + op2f(movntps, X86_INSN_FLAG_SSE_GROUP_28, Mx, Gx), + op2f(cvttps2pi, X86_INSN_FLAG_SSE_GROUP_28, Gx, Ex), + op2f(cvtps2pi, X86_INSN_FLAG_SSE_GROUP_28, Gx, Ex), + op2f(ucomiss, X86_INSN_FLAG_SSE_GROUP_28, Gx, Ex), + op2f(comiss, X86_INSN_FLAG_SSE_GROUP_28, Gx, Ex), + + /* 0x30 */ + op0(wrmsr), + op0(rdtsc), + op0(rdmsr), + op0(rdpmc), + op0(sysenter), + op0(sysexit), + op0(bad), + op0(bad), + op0(bad), + op0(bad), + op0(bad), + op0(bad), + op0(bad), + op0(bad), + op0(bad), + op0(bad), + +/* 0x40 */ +#define _(x) op2(cmov##x, Gv, Ev), + foreach_x86_condition +#undef _ + + /* 0x50 */ + op2f(movmskps, X86_INSN_FLAG_SSE_GROUP_50, Gd, Rx), + op2f(sqrtps, X86_INSN_FLAG_SSE_GROUP_50, Gx, Ex), + op2f(rsqrtps, X86_INSN_FLAG_SSE_GROUP_50, Gx, Ex), + op2f(rcpps, X86_INSN_FLAG_SSE_GROUP_50, Gx, Ex), + op2f(andps, X86_INSN_FLAG_SSE_GROUP_50, Gx, Ex), + op2f(andnps, X86_INSN_FLAG_SSE_GROUP_50, Gx, Ex), + op2f(orps, X86_INSN_FLAG_SSE_GROUP_50, Gx, Ex), + op2f(xorps, X86_INSN_FLAG_SSE_GROUP_50, Gx, Ex), + op2f(addps, X86_INSN_FLAG_SSE_GROUP_58, Gx, Ex), + op2f(mulps, X86_INSN_FLAG_SSE_GROUP_58, Gx, Ex), + op2f(cvtps2pd, X86_INSN_FLAG_SSE_GROUP_58, Gx, Ex), + op2f(cvtdq2ps, X86_INSN_FLAG_SSE_GROUP_58, Gx, Ex), + op2f(subps, X86_INSN_FLAG_SSE_GROUP_58, Gx, Ex), + op2f(minps, X86_INSN_FLAG_SSE_GROUP_58, Gx, Ex), + op2f(divps, X86_INSN_FLAG_SSE_GROUP_58, Gx, Ex), + op2f(maxps, X86_INSN_FLAG_SSE_GROUP_58, Gx, Ex), + + /* 0x60 */ + op2f(punpcklbw, X86_INSN_FLAG_SSE_GROUP_60, Gm, Em), + op2f(punpcklwd, X86_INSN_FLAG_SSE_GROUP_60, Gm, Em), + op2f(punpckldq, X86_INSN_FLAG_SSE_GROUP_60, Gm, Em), + op2f(packsswb, X86_INSN_FLAG_SSE_GROUP_60, Gm, Em), + op2f(pcmpgtb, X86_INSN_FLAG_SSE_GROUP_60, Gm, Em), + op2f(pcmpgtw, X86_INSN_FLAG_SSE_GROUP_60, Gm, Em), + op2f(pcmpgtd, X86_INSN_FLAG_SSE_GROUP_60, Gm, Em), + op2f(packuswb, X86_INSN_FLAG_SSE_GROUP_60, Gm, Em), + op2f(punpckhbw, X86_INSN_FLAG_SSE_GROUP_68, Gm, Em), + op2f(punpckhwd, X86_INSN_FLAG_SSE_GROUP_68, Gm, Em), + op2f(punpckhdq, X86_INSN_FLAG_SSE_GROUP_68, Gm, Em), + op2f(packssdw, X86_INSN_FLAG_SSE_GROUP_68, Gm, Em), + op0f(bad, X86_INSN_FLAG_SSE_GROUP_68), + op0f(bad, X86_INSN_FLAG_SSE_GROUP_68), + op2f(movd, X86_INSN_FLAG_SSE_GROUP_68, Gm, Em), + op2f(movq, X86_INSN_FLAG_SSE_GROUP_68, Gm, Em), + + /* 0x70 */ + op3f(pshufw, X86_INSN_FLAG_SSE_GROUP_70, Gm, Em, Ib), + op0f(modrm_group_12, X86_INSN_FLAG_MODRM_REG_GROUP_12), + op0f(modrm_group_13, X86_INSN_FLAG_MODRM_REG_GROUP_13), + op0f(modrm_group_14, X86_INSN_FLAG_MODRM_REG_GROUP_14), + op2f(pcmpeqb, X86_INSN_FLAG_SSE_GROUP_70, Gm, Em), + op2f(pcmpeqw, X86_INSN_FLAG_SSE_GROUP_70, Gm, Em), + op2f(pcmpeqd, X86_INSN_FLAG_SSE_GROUP_70, Gm, Em), + op0f(emms, X86_INSN_FLAG_SSE_GROUP_70), + op0f(bad, X86_INSN_FLAG_SSE_GROUP_78), + op0f(bad, X86_INSN_FLAG_SSE_GROUP_78), + op0f(bad, X86_INSN_FLAG_SSE_GROUP_78), + op0f(bad, X86_INSN_FLAG_SSE_GROUP_78), + op0f(bad, X86_INSN_FLAG_SSE_GROUP_78), + op0f(bad, X86_INSN_FLAG_SSE_GROUP_78), + op2f(movd, X86_INSN_FLAG_SSE_GROUP_78, Em, Gm), + op2f(movq, X86_INSN_FLAG_SSE_GROUP_78, Em, Gm), + +/* 0x80 */ +#define _(x) op1(jmp##x, Jz), + foreach_x86_condition +#undef _ + +/* 0x90 */ +#define _(x) op1(set##x, Eb), + foreach_x86_condition +#undef _ + + /* 0xa0 */ + op0(push_fs), + op0(pop_fs), + op0(cpuid), + op2(bt, Ev, Gv), + op3(shld, Ev, Gv, Ib), + op3(shld, Ev, Gv, CL), + op0(bad), + op0(bad), + op0(push_gs), + op0(pop_gs), + op0(rsm), + op2(bts, Ev, Gv), + op3(shrd, Ev, Gv, Ib), + op3(shrd, Ev, Gv, CL), + op0f(modrm_group_15, X86_INSN_FLAG_MODRM_REG_GROUP_15), + op2(imul, Gv, Ev), + + /* 0xb0 */ + op2(cmpxchg, Eb, Gb), + op2(cmpxchg, Ev, Gv), + op2(lss, Gz, Mp), + op2(btr, Ev, Gv), + op2(lfs, Gz, Mp), + op2(lgs, Gz, Mp), + op2(movzbl, Gv, Eb), + op2(movzwl, Gv, Ew), + op0(bad), + op0f(modrm_group_10, X86_INSN_FLAG_MODRM_REG_GROUP_10), + op2f(modrm_group_8, X86_INSN_FLAG_MODRM_REG_GROUP_8, Ev, Ib), + op2(btc, Ev, Gv), + op2(bsf, Gv, Ev), + op2(bsr, Gv, Ev), + op2(movsx, Gv, Eb), + op2(movsx, Gv, Ew), + + /* 0xc0 */ + op2(xadd, Eb, Gb), + op2(xadd, Ev, Gv), + op3f(cmpps, X86_INSN_FLAG_SSE_GROUP_c0, Gx, Ex, Ib), + op2(movnti, Mv, Gv), + op3f(pinsrw, X86_INSN_FLAG_SSE_GROUP_c0, Gm, Ew, Ib), + op3f(pextrw, X86_INSN_FLAG_SSE_GROUP_c0, Gd, Rm, Ib), + op3f(shufps, X86_INSN_FLAG_SSE_GROUP_c0, Gx, Ex, Ib), + op1f(modrm_group_9, X86_INSN_FLAG_MODRM_REG_GROUP_9, Mx), +#define _(r) op1(bswap, r), + foreach_x86_gp_reg +#undef _ + + /* 0xd0 */ + op0f(bad, X86_INSN_FLAG_SSE_GROUP_d0), + op2f(psrlw, X86_INSN_FLAG_SSE_GROUP_d0, Gm, Em), + op2f(psrld, X86_INSN_FLAG_SSE_GROUP_d0, Gm, Em), + op2f(psrlq, X86_INSN_FLAG_SSE_GROUP_d0, Gm, Em), + op2f(paddq, X86_INSN_FLAG_SSE_GROUP_d0, Gm, Em), + op2f(pmullw, X86_INSN_FLAG_SSE_GROUP_d0, Gm, Em), + op0f(bad, X86_INSN_FLAG_SSE_GROUP_d0), + op2f(pmovmskb, X86_INSN_FLAG_SSE_GROUP_d0, Gd, Rm), + op2f(psubusb, X86_INSN_FLAG_SSE_GROUP_d8, Gm, Em), + op2f(psubusw, X86_INSN_FLAG_SSE_GROUP_d8, Gm, Em), + op2f(pminub, X86_INSN_FLAG_SSE_GROUP_d8, Gm, Em), + op2f(pand, X86_INSN_FLAG_SSE_GROUP_d8, Gm, Em), + op2f(paddusb, X86_INSN_FLAG_SSE_GROUP_d8, Gm, Em), + op2f(paddusw, X86_INSN_FLAG_SSE_GROUP_d8, Gm, Em), + op2f(pmaxub, X86_INSN_FLAG_SSE_GROUP_d8, Gm, Em), + op2f(pandn, X86_INSN_FLAG_SSE_GROUP_d8, Gm, Em), + + /* 0xe0 */ + op2f(pavgb, X86_INSN_FLAG_SSE_GROUP_e0, Gm, Em), + op2f(psraw, X86_INSN_FLAG_SSE_GROUP_e0, Gm, Em), + op2f(psrad, X86_INSN_FLAG_SSE_GROUP_e0, Gm, Em), + op2f(pavgw, X86_INSN_FLAG_SSE_GROUP_e0, Gm, Em), + op2f(pmulhuw, X86_INSN_FLAG_SSE_GROUP_e0, Gm, Em), + op2f(pmulhw, X86_INSN_FLAG_SSE_GROUP_e0, Gm, Em), + op2f(bad, X86_INSN_FLAG_SSE_GROUP_e0, Gm, Em), + op2f(movntq, X86_INSN_FLAG_SSE_GROUP_e0, Mm, Gm), + op2f(psubsb, X86_INSN_FLAG_SSE_GROUP_e8, Gm, Em), + op2f(psubsw, X86_INSN_FLAG_SSE_GROUP_e8, Gm, Em), + op2f(pminsw, X86_INSN_FLAG_SSE_GROUP_e8, Gm, Em), + op2f(por, X86_INSN_FLAG_SSE_GROUP_e8, Gm, Em), + op2f(paddsb, X86_INSN_FLAG_SSE_GROUP_e8, Gm, Em), + op2f(paddsw, X86_INSN_FLAG_SSE_GROUP_e8, Gm, Em), + op2f(pmaxsw, X86_INSN_FLAG_SSE_GROUP_e8, Gm, Em), + op2f(pxor, X86_INSN_FLAG_SSE_GROUP_e8, Gm, Em), + + /* 0xf0 */ + op0f(bad, X86_INSN_FLAG_SSE_GROUP_f0), + op2f(psllw, X86_INSN_FLAG_SSE_GROUP_f0, Gm, Em), + op2f(pslld, X86_INSN_FLAG_SSE_GROUP_f0, Gm, Em), + op2f(psllq, X86_INSN_FLAG_SSE_GROUP_f0, Gm, Em), + op2f(pmuludq, X86_INSN_FLAG_SSE_GROUP_f0, Gm, Em), + op2f(pmaddwd, X86_INSN_FLAG_SSE_GROUP_f0, Gm, Em), + op2f(psadbw, X86_INSN_FLAG_SSE_GROUP_f0, Gm, Em), + op2f(maskmovq, X86_INSN_FLAG_SSE_GROUP_f0, Gm, Em), + op2f(psubb, X86_INSN_FLAG_SSE_GROUP_f8, Gm, Em), + op2f(psubw, X86_INSN_FLAG_SSE_GROUP_f8, Gm, Em), + op2f(psubd, X86_INSN_FLAG_SSE_GROUP_f8, Gm, Em), + op2f(psubq, X86_INSN_FLAG_SSE_GROUP_f8, Gm, Em), + op2f(paddb, X86_INSN_FLAG_SSE_GROUP_f8, Gm, Em), + op2f(paddw, X86_INSN_FLAG_SSE_GROUP_f8, Gm, Em), + op2f(paddd, X86_INSN_FLAG_SSE_GROUP_f8, Gm, Em), + op0f(bad, X86_INSN_FLAG_SSE_GROUP_f8), +}; + +// clang-format on \ No newline at end of file diff --git a/app/src/main/cpp/Dobby/source/InterceptEntry.cpp b/app/src/main/cpp/Dobby/source/InterceptEntry.cpp new file mode 100644 index 0000000..9a84405 --- /dev/null +++ b/app/src/main/cpp/Dobby/source/InterceptEntry.cpp @@ -0,0 +1,16 @@ +#include "InterceptEntry.h" +#include "Interceptor.h" + +InterceptEntry::InterceptEntry(InterceptEntryType type, addr_t address) { + this->type = type; + +#if defined(TARGET_ARCH_ARM) + if (address % 2) { + address -= 1; + this->thumb_mode = true; + } +#endif + + this->patched_addr = address; + this->id = Interceptor::SharedInstance()->count(); +} \ No newline at end of file diff --git a/app/src/main/cpp/Dobby/source/InterceptEntry.h b/app/src/main/cpp/Dobby/source/InterceptEntry.h new file mode 100644 index 0000000..2955635 --- /dev/null +++ b/app/src/main/cpp/Dobby/source/InterceptEntry.h @@ -0,0 +1,30 @@ +#pragma once + +#include +#include "dobby/common.h" + +typedef enum { kFunctionInlineHook, kInstructionInstrument } InterceptEntryType; + +class InterceptRouting; + +typedef struct InterceptEntry { + uint32_t id; + InterceptEntryType type; + InterceptRouting *routing; + + union { + addr_t addr; + addr_t patched_addr; + }; + uint32_t patched_size; + + addr_t relocated_addr; + uint32_t relocated_size; + + uint8_t origin_insns[256]; + uint32_t origin_insn_size; + + bool thumb_mode; + + InterceptEntry(InterceptEntryType type, addr_t address); +} InterceptEntry; \ No newline at end of file diff --git a/app/src/main/cpp/Dobby/source/InterceptRouting/InterceptRouting.cpp b/app/src/main/cpp/Dobby/source/InterceptRouting/InterceptRouting.cpp new file mode 100644 index 0000000..5299e62 --- /dev/null +++ b/app/src/main/cpp/Dobby/source/InterceptRouting/InterceptRouting.cpp @@ -0,0 +1,97 @@ +#include "dobby/dobby_internal.h" + +#include "InterceptRouting/InterceptRouting.h" +#include "InterceptRouting/RoutingPlugin/RoutingPlugin.h" + +using namespace zz; + +void log_hex_format(uint8_t *buffer, uint32_t buffer_size) { + char output[1024] = {0}; + for (int i = 0; i < buffer_size && i < sizeof(output); i++) { + snprintf(output + strlen(output), 3, "%02x ", *((uint8_t *)buffer + i)); + } + DEBUG_LOG("%s", output); +}; + +void InterceptRouting::Prepare() { +} + +// generate relocated code +bool InterceptRouting::GenerateRelocatedCode() { + uint32_t tramp_size = GetTrampolineBuffer()->GetBufferSize(); + origin_ = new CodeMemBlock(entry_->patched_addr, tramp_size); + relocated_ = new CodeMemBlock(); + + auto buffer = (void *)entry_->patched_addr; +#if defined(TARGET_ARCH_ARM) + if (entry_->thumb_mode) { + buffer = (void *)((addr_t)buffer + 1); + } +#endif + GenRelocateCodeAndBranch(buffer, origin_, relocated_); + if (relocated_->size == 0) { + ERROR_LOG("[insn relocate]] failed"); + return false; + } + + // set the relocated instruction address + entry_->relocated_addr = relocated_->addr; + + // save original prologue + memcpy((void *)entry_->origin_insns, (void *)origin_->addr, origin_->size); + entry_->origin_insn_size = origin_->size; + + // log + DEBUG_LOG("[insn relocate] origin %p - %d", origin_->addr, origin_->size); + log_hex_format((uint8_t *)origin_->addr, origin_->size); + + DEBUG_LOG("[insn relocate] relocated %p - %d", relocated_->addr, relocated_->size); + log_hex_format((uint8_t *)relocated_->addr, relocated_->size); + + return true; +} + +bool InterceptRouting::GenerateTrampolineBuffer(addr_t src, addr_t dst) { + // if near branch trampoline plugin enabled + if (RoutingPluginManager::near_branch_trampoline) { + auto plugin = static_cast(RoutingPluginManager::near_branch_trampoline); + if (plugin->GenerateTrampolineBuffer(this, src, dst) == false) { + DEBUG_LOG("Failed enable near branch trampoline plugin"); + } + } + + if (GetTrampolineBuffer() == nullptr) { + auto tramp_buffer = GenerateNormalTrampolineBuffer(src, dst); + SetTrampolineBuffer(tramp_buffer); + } + return true; +} + +// active routing, patch origin instructions as trampoline +void InterceptRouting::Active() { + auto ret = DobbyCodePatch((void *)entry_->patched_addr, trampoline_buffer_->GetBuffer(), + trampoline_buffer_->GetBufferSize()); + if (ret == -1) { + ERROR_LOG("[intercept routing] active failed"); + return; + } + DEBUG_LOG("[intercept routing] active"); +} + +void InterceptRouting::Commit() { + this->Active(); +} + +#if 0 +int InterceptRouting::PredefinedTrampolineSize() { +#if __arm64__ + return 12; +#elif __arm__ + return 8; +#endif +} +#endif + +InterceptEntry *InterceptRouting::GetInterceptEntry() { + return entry_; +}; diff --git a/app/src/main/cpp/Dobby/source/InterceptRouting/InterceptRouting.h b/app/src/main/cpp/Dobby/source/InterceptRouting/InterceptRouting.h new file mode 100644 index 0000000..e21ca32 --- /dev/null +++ b/app/src/main/cpp/Dobby/source/InterceptRouting/InterceptRouting.h @@ -0,0 +1,62 @@ +#pragma once + +#include "InterceptEntry.h" +#include "MemoryAllocator/AssemblyCodeBuilder.h" +#include "InstructionRelocation/InstructionRelocation.h" +#include "TrampolineBridge/Trampoline/Trampoline.h" + +class InterceptRouting { +public: + explicit InterceptRouting(InterceptEntry *entry) : entry_(entry) { + entry->routing = this; + + origin_ = nullptr; + relocated_ = nullptr; + + trampoline_ = nullptr; + trampoline_buffer_ = nullptr; + trampoline_target_ = 0; + } + + virtual void DispatchRouting() = 0; + + virtual void Prepare(); + + virtual void Active(); + + void Commit(); + + InterceptEntry *GetInterceptEntry(); + + void SetTrampolineBuffer(CodeBufferBase *buffer) { + trampoline_buffer_ = buffer; + } + + CodeBufferBase *GetTrampolineBuffer() { + return trampoline_buffer_; + } + + void SetTrampolineTarget(addr_t address) { + trampoline_target_ = address; + } + + addr_t GetTrampolineTarget() { + return trampoline_target_; + } + +protected: + bool GenerateRelocatedCode(); + + bool GenerateTrampolineBuffer(addr_t src, addr_t dst); + +protected: + InterceptEntry *entry_; + + CodeMemBlock *origin_; + CodeMemBlock *relocated_; + + CodeMemBlock *trampoline_; + // trampoline buffer before active + CodeBufferBase *trampoline_buffer_; + addr_t trampoline_target_; +}; diff --git a/app/src/main/cpp/Dobby/source/InterceptRouting/Routing/FunctionInlineHook/FunctionInlineHook.cc b/app/src/main/cpp/Dobby/source/InterceptRouting/Routing/FunctionInlineHook/FunctionInlineHook.cc new file mode 100644 index 0000000..8694f01 --- /dev/null +++ b/app/src/main/cpp/Dobby/source/InterceptRouting/Routing/FunctionInlineHook/FunctionInlineHook.cc @@ -0,0 +1,52 @@ +#include "dobby/dobby_internal.h" + +#include "Interceptor.h" +#include "InterceptRouting/Routing/FunctionInlineHook/FunctionInlineHookRouting.h" + +PUBLIC int DobbyHook(void *address, dobby_dummy_func_t replace_func, dobby_dummy_func_t *origin_func) { + if (!address) { + ERROR_LOG("function address is 0x0"); + return -1; + } + +#if defined(__APPLE__) && defined(__arm64__) + address = pac_strip(address); + replace_func = pac_strip(replace_func); +#endif + +#if defined(ANDROID) + void *page_align_address = (void *)ALIGN_FLOOR(address, OSMemory::PageSize()); + if (!OSMemory::SetPermission(page_align_address, OSMemory::PageSize(), kReadExecute)) { + return -1; + } +#endif + + DEBUG_LOG("----- [DobbyHook:%p] -----", address); + + // check if already register + auto entry = Interceptor::SharedInstance()->find((addr_t)address); + if (entry) { + ERROR_LOG("%p already been hooked.", address); + return -1; + } + + entry = new InterceptEntry(kFunctionInlineHook, (addr_t)address); + + auto *routing = new FunctionInlineHookRouting(entry, replace_func); + routing->Prepare(); + routing->DispatchRouting(); + + // set origin func entry with as relocated instructions + if (origin_func) { + *origin_func = (dobby_dummy_func_t)entry->relocated_addr; +#if defined(__APPLE__) && defined(__arm64__) + *origin_func = pac_sign(*origin_func); +#endif + } + + routing->Commit(); + + Interceptor::SharedInstance()->add(entry); + + return 0; +} diff --git a/app/src/main/cpp/Dobby/source/InterceptRouting/Routing/FunctionInlineHook/FunctionInlineHookRouting.h b/app/src/main/cpp/Dobby/source/InterceptRouting/Routing/FunctionInlineHook/FunctionInlineHookRouting.h new file mode 100644 index 0000000..65722c2 --- /dev/null +++ b/app/src/main/cpp/Dobby/source/InterceptRouting/Routing/FunctionInlineHook/FunctionInlineHookRouting.h @@ -0,0 +1,22 @@ +#pragma once + +#include "dobby/dobby_internal.h" + +#include "InterceptRouting/InterceptRouting.h" + +#include "TrampolineBridge/ClosureTrampolineBridge/ClosureTrampoline.h" + +class FunctionInlineHookRouting : public InterceptRouting { +public: + FunctionInlineHookRouting(InterceptEntry *entry, dobby_dummy_func_t replace_func) : InterceptRouting(entry) { + this->replace_func = replace_func; + } + + void DispatchRouting() override; + +private: + void BuildRouting(); + +private: + dobby_dummy_func_t replace_func; +}; diff --git a/app/src/main/cpp/Dobby/source/InterceptRouting/Routing/FunctionInlineHook/RoutingImpl.cc b/app/src/main/cpp/Dobby/source/InterceptRouting/Routing/FunctionInlineHook/RoutingImpl.cc new file mode 100644 index 0000000..4408d55 --- /dev/null +++ b/app/src/main/cpp/Dobby/source/InterceptRouting/Routing/FunctionInlineHook/RoutingImpl.cc @@ -0,0 +1,22 @@ +#include "dobby/dobby_internal.h" +#include "InterceptRouting/Routing/FunctionInlineHook/FunctionInlineHookRouting.h" + +void FunctionInlineHookRouting::BuildRouting() { + SetTrampolineTarget((addr_t)replace_func); + + // generate trampoline buffer, run before GenerateRelocatedCode + addr_t from = entry_->patched_addr; +#if defined(TARGET_ARCH_ARM) + if (entry_->thumb_mode) + from += 1; +#endif + addr_t to = GetTrampolineTarget(); + GenerateTrampolineBuffer(from, to); +} + +void FunctionInlineHookRouting::DispatchRouting() { + BuildRouting(); + + // generate relocated code which size == trampoline size + GenerateRelocatedCode(); +} diff --git a/app/src/main/cpp/Dobby/source/InterceptRouting/Routing/FunctionWrapper/FunctionWrapperExport.cc b/app/src/main/cpp/Dobby/source/InterceptRouting/Routing/FunctionWrapper/FunctionWrapperExport.cc new file mode 100644 index 0000000..20232b0 --- /dev/null +++ b/app/src/main/cpp/Dobby/source/InterceptRouting/Routing/FunctionWrapper/FunctionWrapperExport.cc @@ -0,0 +1,27 @@ +#include "dobby/dobby_internal.h" + +#include "logging/logging.h" + +#include "Interceptor.h" +#include "InterceptRouting/InterceptRouting.h" + +#include "function-wrapper.h" + +PUBLIC int DobbyWrap(void *function_address, PreCallTy pre_call, PostCallTy post_call) { + DEBUG_LOG("Initialize 'DobbyWrap' hook at %p", function_address); + + Interceptor *interceptor = Interceptor::SharedInstance(); + + InterceptEntry *entry = new InterceptEntry(); + entry->id = interceptor->entries->getCount(); + entry->type = kFunctionWrapper; + entry->function_address = function_address; + + FunctionWrapperRouting *routing = new FunctionWrapperRouting(entry); + routing->DispatchRouting(); + interceptor->addHookEntry(entry); + routing->Commit(); + + DEBUG_LOG("Finalize %p", function_address); + return 0; +} diff --git a/app/src/main/cpp/Dobby/source/InterceptRouting/Routing/FunctionWrapper/function-wrapper.cc b/app/src/main/cpp/Dobby/source/InterceptRouting/Routing/FunctionWrapper/function-wrapper.cc new file mode 100644 index 0000000..6a8a294 --- /dev/null +++ b/app/src/main/cpp/Dobby/source/InterceptRouting/Routing/FunctionWrapper/function-wrapper.cc @@ -0,0 +1,38 @@ +#include "dobby/dobby_internal.h" + +#include "TrampolineBridge/ClosureTrampolineBridge/ClosureTrampoline.h" + +#include "intercept_routing_handler.h" + +#include "function-wrapper.h" + +void FunctionWrapperRouting::DispatchRouting() { + Prepare(); + BuildPreCallRouting(); + BuildPostCallRouting(); +} + +// Add pre_call(prologue) handler before running the origin function, +void FunctionWrapperRouting::BuildPreCallRouting() { + // create closure trampoline jump to prologue_routing_dispath with the `entry_` data + ClosureTrampolineEntry *cte = ClosureTrampoline::CreateClosureTrampoline(entry_, (void *)prologue_routing_dispatch); + this->prologue_dispatch_bridge = cte->address; + + DEBUG_LOG("Create pre call closure trampoline to 'prologue_routing_dispatch' at %p", cte->address); +} + +// Add post_call(epilogue) handler before `Return` of the origin function, as implementation is replace the origin +// `Return Address` of the function. +void FunctionWrapperRouting::BuildPostCallRouting() { + // create closure trampoline jump to prologue_routing_dispath with the `entry_` data + ClosureTrampolineEntry *closure_trampoline_entry; + // format trampoline + closure_trampoline_entry = ClosureTrampoline::CreateClosureTrampoline(entry_, (void *)epilogue_routing_dispatch); + DEBUG_LOG("Create post call closure trampoline to 'prologue_routing_dispatch' at %p", + closure_trampoline_entry->address); + + this->SetTrampolineTarget(closure_trampoline_entry->address); + this->epilogue_dispatch_bridge = closure_trampoline_entry->address; + + GenerateTrampolineBuffer(entry_->target_address, GetTrampolineTarget()); +} \ No newline at end of file diff --git a/app/src/main/cpp/Dobby/source/InterceptRouting/Routing/FunctionWrapper/function-wrapper.h b/app/src/main/cpp/Dobby/source/InterceptRouting/Routing/FunctionWrapper/function-wrapper.h new file mode 100644 index 0000000..362b750 --- /dev/null +++ b/app/src/main/cpp/Dobby/source/InterceptRouting/Routing/FunctionWrapper/function-wrapper.h @@ -0,0 +1,40 @@ +#ifndef FUNCTION_WRAPPER_H +#define FUNCTION_WRAPPER_H + +#include "dobby/dobby_internal.h" + +#include "TrampolineBridge/ClosureTrampolineBridge/ClosureTrampoline.h" +#include "InterceptRouting/InterceptRouting.h" +#include "Interceptor.h" + +#if TARGET_ARCH_IA32 +#elif TARGET_ARCH_X64 +#include "InterceptRouting/x64/X64InterceptRouting.h" +#elif TARGET_ARCH_ARM64 +#include "InterceptRouting/arm64/ARM64InterceptRouting.h" +#elif TARGET_ARCH_ARM +#else +#error "unsupported architecture" +#endif + +class FunctionWrapperRouting : public InterceptRouting { +public: + FunctionWrapperRouting(InterceptEntry *entry) : InterceptRouting(entry) { + } + + void DispatchRouting(); + + void *GetTrampolineTarget(); + +private: + void BuildPreCallRouting(); + + void BuildPostCallRouting(); + +private: + void *prologue_dispatch_bridge; + + void *epilogue_dispatch_bridge; +}; + +#endif diff --git a/app/src/main/cpp/Dobby/source/InterceptRouting/Routing/FunctionWrapper/intercept_routing_handler.cc b/app/src/main/cpp/Dobby/source/InterceptRouting/Routing/FunctionWrapper/intercept_routing_handler.cc new file mode 100644 index 0000000..55de2fb --- /dev/null +++ b/app/src/main/cpp/Dobby/source/InterceptRouting/Routing/FunctionWrapper/intercept_routing_handler.cc @@ -0,0 +1,79 @@ + +#include "dobby/dobby_internal.h" + +#include "logging/logging.h" + +#include "intercept_routing_handler.h" + +#include "function-wrapper.h" +#include "intercept_routing_handler.h" + +#include "MultiThreadSupport/ThreadSupport.h" + +#include "TrampolineBridge/ClosureTrampolineBridge/common_bridge_handler.h" + +void pre_call_forward_handler(DobbyRegisterContext *ctx, InterceptEntry *entry) { + FunctionWrapperRouting *routing = (FunctionWrapperRouting *)entry->routing; + + StackFrame *stackframe = new StackFrame(); + // create stack frame as common variable between pre_call and post_call + ThreadSupport::PushStackFrame(stackframe); + + // run the `pre_call` before execute origin function which has been relocated(fixed) + if (routing->pre_call) { + PreCallTy pre_call; + InterceptEntry entry; + entry.hook_id = entry->id; + entry.target_address = entry->target_address; + pre_call = routing->pre_call; + // run the pre_call with the power of accessing all registers + (*pre_call)(ctx, (const InterceptEntry *)&entry); + } + + // save the origin ret address, and use in `post_call_forword_handler` + stackframe->orig_ret = get_func_ret_address(ctx); + + // set the prologue bridge next hop address with the patched instructions has been relocated + set_routing_bridge_next_hop(ctx, entry->relocated_origin_function); + + // replace the function ret address with our epilogue_routing_dispatch + set_func_ret_address(ctx, entry->epilogue_dispatch_bridge); +} + +void post_call_forward_handler(DobbyRegisterContext *ctx, InterceptEntry *entry) { + FunctionWrapperRouting *routing = (FunctionWrapperRouting *)entry->routing; + + // pop stack frame as common variable between pre_call and post_call + StackFrame *stackframe = ThreadSupport::PopStackFrame(); + + // run the `post_call`, and access all the register value, as the origin function done, + if (routing->post_call) { + PostCallTy post_call; + InterceptEntry entry; + entry.hook_id = entry->id; + entry.target_address = entry->target_address; + post_call = routing->post_call; + + // run the post_call with the power of accessing all registers + (*post_call)(ctx, (const InterceptEntry *)&entry); + } + + // set epilogue bridge next hop address with origin ret address, restore the call. + set_routing_bridge_next_hop(ctx, stackframe->orig_ret); +} + +// run the user handler **before run the origin-instructions(which have been relocated)** +void prologue_routing_dispatch(DobbyRegisterContext *ctx, ClosureTrampolineEntry *closure_trampoline_entry) { + DEBUG_LOG("Catch prologue dispatch"); + InterceptEntry *entry = static_cast(closure_trampoline_entry->carry_data); + pre_call_forward_handler(ctx, entry); + return; +} + +// run the user handler **before the function return** by replace the lr register +void epilogue_routing_dispatch(DobbyRegisterContext *ctx, ClosureTrampolineEntry *closure_trampoline_entry) { + DEBUG_LOG("Catch epilogue dispatch"); + InterceptEntry *entry = static_cast(closure_trampoline_entry->carry_data); + post_call_forward_handler(ctx, entry); + return; +} \ No newline at end of file diff --git a/app/src/main/cpp/Dobby/source/InterceptRouting/Routing/FunctionWrapper/intercept_routing_handler.h b/app/src/main/cpp/Dobby/source/InterceptRouting/Routing/FunctionWrapper/intercept_routing_handler.h new file mode 100644 index 0000000..6aaea3f --- /dev/null +++ b/app/src/main/cpp/Dobby/source/InterceptRouting/Routing/FunctionWrapper/intercept_routing_handler.h @@ -0,0 +1,27 @@ +#ifndef FUNCTION_WRAPPER_INTERCEPT_ROUTING_HANDLER_H +#define FUNCTION_WRAPPER_INTERCEPT_ROUTING_HANDLER_H + +#include "TrampolineBridge/ClosureTrampolineBridge/ClosureTrampoline.h" +#include "Interceptor.h" +#include "dobby/dobby_internal.h" + +#ifdef __cplusplus +extern "C" { +#endif //__cplusplus + +// Dispatch the routing befor running the origin function +void prologue_routing_dispatch(DobbyRegisterContext *ctx, ClosureTrampolineEntry *entry); + +// Dispatch the routing before the function return . (as it's implementation by relpace `return address` in the stack +// ,or LR register) +void epilogue_routing_dispatch(DobbyRegisterContext *ctx, ClosureTrampolineEntry *entry); + +void pre_call_forward_handler(DobbyRegisterContext *ctx, InterceptEntry *entry); + +void post_call_forward_handler(DobbyRegisterContext *ctx, InterceptEntry *entry); + +#ifdef __cplusplus +} +#endif //__cplusplus + +#endif \ No newline at end of file diff --git a/app/src/main/cpp/Dobby/source/InterceptRouting/Routing/InstructionInstrument/InstructionInstrument.cc b/app/src/main/cpp/Dobby/source/InterceptRouting/Routing/InstructionInstrument/InstructionInstrument.cc new file mode 100644 index 0000000..9c28ca3 --- /dev/null +++ b/app/src/main/cpp/Dobby/source/InterceptRouting/Routing/InstructionInstrument/InstructionInstrument.cc @@ -0,0 +1,42 @@ +#include "dobby/dobby_internal.h" + +#include "Interceptor.h" +#include "InterceptRouting/InterceptRouting.h" +#include "InterceptRouting/Routing/InstructionInstrument/InstructionInstrumentRouting.h" + +PUBLIC int DobbyInstrument(void *address, dobby_instrument_callback_t pre_handler) { + if (!address) { + ERROR_LOG("address is 0x0.\n"); + return -1; + } + +#if defined(__APPLE__) && defined(__arm64__) + address = pac_strip(address); +#endif + +#if defined(ANDROID) + void *page_align_address = (void *)ALIGN_FLOOR(address, OSMemory::PageSize()); + if (!OSMemory::SetPermission(page_align_address, OSMemory::PageSize(), kReadExecute)) { + return -1; + } +#endif + + DEBUG_LOG("\n\n----- [DobbyInstrument:%p] -----", address); + + auto entry = Interceptor::SharedInstance()->find((addr_t)address); + if (entry) { + ERROR_LOG("%s already been instrumented.", address); + return -1; + } + + entry = new InterceptEntry(kInstructionInstrument, (addr_t)address); + + auto routing = new InstructionInstrumentRouting(entry, pre_handler, nullptr); + routing->Prepare(); + routing->DispatchRouting(); + routing->Commit(); + + Interceptor::SharedInstance()->add(entry); + + return 0; +} diff --git a/app/src/main/cpp/Dobby/source/InterceptRouting/Routing/InstructionInstrument/InstructionInstrumentRouting.h b/app/src/main/cpp/Dobby/source/InterceptRouting/Routing/InstructionInstrument/InstructionInstrumentRouting.h new file mode 100644 index 0000000..60a9a2e --- /dev/null +++ b/app/src/main/cpp/Dobby/source/InterceptRouting/Routing/InstructionInstrument/InstructionInstrumentRouting.h @@ -0,0 +1,30 @@ +#pragma once + +#include "dobby/dobby_internal.h" + +#include "InterceptRouting/InterceptRouting.h" + +#include "TrampolineBridge/ClosureTrampolineBridge/ClosureTrampoline.h" + +class InstructionInstrumentRouting : public InterceptRouting { +public: + InstructionInstrumentRouting(InterceptEntry *entry, dobby_instrument_callback_t pre_handler, + dobby_instrument_callback_t post_handler) + : InterceptRouting(entry) { + this->prologue_dispatch_bridge = nullptr; + this->pre_handler = pre_handler; + this->post_handler = post_handler; + } + + void DispatchRouting() override; + +private: + void BuildRouting(); + +public: + dobby_instrument_callback_t pre_handler; + dobby_instrument_callback_t post_handler; + +private: + void *prologue_dispatch_bridge; +}; diff --git a/app/src/main/cpp/Dobby/source/InterceptRouting/Routing/InstructionInstrument/RoutingImpl.cc b/app/src/main/cpp/Dobby/source/InterceptRouting/Routing/InstructionInstrument/RoutingImpl.cc new file mode 100644 index 0000000..bd12545 --- /dev/null +++ b/app/src/main/cpp/Dobby/source/InterceptRouting/Routing/InstructionInstrument/RoutingImpl.cc @@ -0,0 +1,40 @@ + +#include "dobby/dobby_internal.h" + +#include "TrampolineBridge/ClosureTrampolineBridge/ClosureTrampoline.h" + +#include "InterceptRouting/Routing/InstructionInstrument/InstructionInstrumentRouting.h" +#include "InterceptRouting/Routing/InstructionInstrument/instrument_routing_handler.h" + +// create closure trampoline jump to prologue_routing_dispatch with the `entry_` data +void InstructionInstrumentRouting::BuildRouting() { + void *handler = (void *)instrument_routing_dispatch; +#if defined(__APPLE__) && defined(__arm64__) + handler = pac_strip(handler); +#endif + auto closure_trampoline = ClosureTrampoline::CreateClosureTrampoline(entry_, handler); + this->SetTrampolineTarget((addr_t)closure_trampoline->address); + DEBUG_LOG("[closure trampoline] closure trampoline: %p, data: %p", closure_trampoline->address, entry_); + + // generate trampoline buffer, before `GenerateRelocatedCode` + addr_t from = entry_->patched_addr; +#if defined(TARGET_ARCH_ARM) + if (entry_->thumb_mode) + from += 1; +#endif + addr_t to = GetTrampolineTarget(); + GenerateTrampolineBuffer(from, to); +} + +void InstructionInstrumentRouting::DispatchRouting() { + BuildRouting(); + + // generate relocated code which size == trampoline size + GenerateRelocatedCode(); +} + +#if 0 +void *InstructionInstrumentRouting::GetTrampolineTarget() { + return this->prologue_dispatch_bridge; +} +#endif diff --git a/app/src/main/cpp/Dobby/source/InterceptRouting/Routing/InstructionInstrument/instrument_routing_handler.cc b/app/src/main/cpp/Dobby/source/InterceptRouting/Routing/InstructionInstrument/instrument_routing_handler.cc new file mode 100644 index 0000000..3e38122 --- /dev/null +++ b/app/src/main/cpp/Dobby/source/InterceptRouting/Routing/InstructionInstrument/instrument_routing_handler.cc @@ -0,0 +1,21 @@ +#include "dobby/dobby_internal.h" + +#include "InterceptRouting/Routing/InstructionInstrument/InstructionInstrumentRouting.h" +#include "InterceptRouting/Routing/InstructionInstrument/instrument_routing_handler.h" + +#include "TrampolineBridge/ClosureTrampolineBridge/common_bridge_handler.h" + +void instrument_forward_handler(InterceptEntry *entry, DobbyRegisterContext *ctx) { + auto routing = static_cast(entry->routing); + if (routing->pre_handler) { + auto handler = (dobby_instrument_callback_t)routing->pre_handler; + (*handler)((void *)entry->patched_addr, ctx); + } + + // set prologue bridge next hop address as relocated instructions + set_routing_bridge_next_hop(ctx, (void *)entry->relocated_addr); +} + +void instrument_routing_dispatch(InterceptEntry *entry, DobbyRegisterContext *ctx) { + instrument_forward_handler(entry, ctx); +} diff --git a/app/src/main/cpp/Dobby/source/InterceptRouting/Routing/InstructionInstrument/instrument_routing_handler.h b/app/src/main/cpp/Dobby/source/InterceptRouting/Routing/InstructionInstrument/instrument_routing_handler.h new file mode 100644 index 0000000..640bfec --- /dev/null +++ b/app/src/main/cpp/Dobby/source/InterceptRouting/Routing/InstructionInstrument/instrument_routing_handler.h @@ -0,0 +1,7 @@ +#pragma once + +#include "dobby/dobby_internal.h" + +extern "C" { +void instrument_routing_dispatch(InterceptEntry *entry, DobbyRegisterContext *ctx); +} \ No newline at end of file diff --git a/app/src/main/cpp/Dobby/source/InterceptRouting/RoutingPlugin/NearBranchTrampoline/NearBranchTrampoline.cc b/app/src/main/cpp/Dobby/source/InterceptRouting/RoutingPlugin/NearBranchTrampoline/NearBranchTrampoline.cc new file mode 100644 index 0000000..fab0a12 --- /dev/null +++ b/app/src/main/cpp/Dobby/source/InterceptRouting/RoutingPlugin/NearBranchTrampoline/NearBranchTrampoline.cc @@ -0,0 +1,50 @@ +#include "InterceptRouting/RoutingPlugin/NearBranchTrampoline/NearBranchTrampoline.h" + +#include "dobby/dobby_internal.h" + +#include "MemoryAllocator/NearMemoryAllocator.h" + +#include "InterceptRouting/RoutingPlugin/RoutingPlugin.h" + +using namespace zz; + +PUBLIC void dobby_enable_near_branch_trampoline() { + RoutingPluginInterface *plugin = new NearBranchTrampolinePlugin; + RoutingPluginManager::registerPlugin("near_branch_trampoline", plugin); + RoutingPluginManager::near_branch_trampoline = plugin; +} + +PUBLIC void dobby_disable_near_branch_trampoline() { + NearBranchTrampolinePlugin *plugin = (NearBranchTrampolinePlugin *)RoutingPluginManager::near_branch_trampoline; + delete plugin; + RoutingPluginManager::near_branch_trampoline = NULL; +} + +#if 0 +int NearBranchTrampolinePlugin::PredefinedTrampolineSize() { +#if __arm64__ + return 4; +#elif __arm__ + return 4; +#endif +} +#endif + +extern CodeBufferBase *GenerateNearTrampolineBuffer(InterceptRouting *routing, addr_t from, addr_t to); +bool NearBranchTrampolinePlugin::GenerateTrampolineBuffer(InterceptRouting *routing, addr_t src, addr_t dst) { + CodeBufferBase *trampoline_buffer; + trampoline_buffer = GenerateNearTrampolineBuffer(routing, src, dst); + if (trampoline_buffer == NULL) + return false; + routing->SetTrampolineBuffer(trampoline_buffer); + return true; +} + +// generate trampoline, patch the original entry +bool NearBranchTrampolinePlugin::Active(InterceptRouting *routing) { + addr_t src, dst; + InterceptEntry *entry = routing->GetInterceptEntry(); + src = (addr_t)entry->patched_addr; + dst = (addr_t)routing->GetTrampolineTarget(); + return true; +} diff --git a/app/src/main/cpp/Dobby/source/InterceptRouting/RoutingPlugin/NearBranchTrampoline/NearBranchTrampoline.h b/app/src/main/cpp/Dobby/source/InterceptRouting/RoutingPlugin/NearBranchTrampoline/NearBranchTrampoline.h new file mode 100644 index 0000000..58bee51 --- /dev/null +++ b/app/src/main/cpp/Dobby/source/InterceptRouting/RoutingPlugin/NearBranchTrampoline/NearBranchTrampoline.h @@ -0,0 +1,15 @@ +#pragma once + +#include "dobby/dobby_internal.h" + +#include "InterceptRouting/RoutingPlugin/RoutingPlugin.h" + +class NearBranchTrampolinePlugin : public RoutingPluginInterface { + bool Prepare(InterceptRouting *routing) { + return false; + }; + + bool Active(InterceptRouting *routing); + + bool GenerateTrampolineBuffer(InterceptRouting *routing, addr_t src, addr_t dst); +}; diff --git a/app/src/main/cpp/Dobby/source/InterceptRouting/RoutingPlugin/NearBranchTrampoline/near_trampoline_arm64.cc b/app/src/main/cpp/Dobby/source/InterceptRouting/RoutingPlugin/NearBranchTrampoline/near_trampoline_arm64.cc new file mode 100644 index 0000000..4b16c92 --- /dev/null +++ b/app/src/main/cpp/Dobby/source/InterceptRouting/RoutingPlugin/NearBranchTrampoline/near_trampoline_arm64.cc @@ -0,0 +1,81 @@ +#include "platform_detect_macro.h" +#if defined(TARGET_ARCH_ARM64) + +#include "dobby/dobby_internal.h" + +#include "core/assembler/assembler-arm64.h" +#include "core/codegen/codegen-arm64.h" + +#include "MemoryAllocator/NearMemoryAllocator.h" +#include "InstructionRelocation/arm64/InstructionRelocationARM64.h" +#include "InterceptRouting/RoutingPlugin/RoutingPlugin.h" + +using namespace zz::arm64; + +#define ARM64_B_XXX_RANGE ((1 << 25) << 2) // signed + +// If BranchType is B_Branch and the branch_range of `B` is not enough +// build the transfer to forward the b branch +static AssemblyCode *GenerateFastForwardTrampoline(addr_t src, addr_t dst) { + TurboAssembler turbo_assembler_(nullptr); +#define _ turbo_assembler_. + + // [adrp + add + br branch] + auto tramp_size = 3 * 4; + auto tramp_mem = NearMemoryAllocator::SharedAllocator()->allocateNearExecMemory(tramp_size, src, ARM64_B_XXX_RANGE); + if (tramp_mem == nullptr) { + ERROR_LOG("search near code block failed"); + return nullptr; + } + + // Use adrp + add branch + uint64_t distance = llabs((int64_t)(tramp_mem - dst)); + uint64_t adrp_range = ((uint64_t)1 << (2 + 19 + 12 - 1)); + if (distance < adrp_range) { + // use adrp + add + br branch == (3 * 4) trampoline size + _ AdrpAdd(TMP_REG_0, (uint64_t)tramp_mem, dst); + _ br(TMP_REG_0); + DEBUG_LOG("forward trampoline use [adrp, add, br]"); + } else { + // use mov + br == (4 * 5) trampoline size + _ Mov(TMP_REG_0, dst); + _ br(TMP_REG_0); + DEBUG_LOG("forward trampoline use [mov, br]"); + + auto tramp_size = turbo_assembler_.GetCodeBuffer()->GetBufferSize(); + tramp_mem = NearMemoryAllocator::SharedAllocator()->allocateNearExecMemory(tramp_size, src, ARM64_B_XXX_RANGE); + if (tramp_mem == nullptr) { + ERROR_LOG("Can't found near code chunk"); + return nullptr; + } + } + + turbo_assembler_.SetRealizedAddress((void *)tramp_mem); + + AssemblyCode *code = nullptr; + code = AssemblyCodeBuilder::FinalizeFromTurboAssembler(&turbo_assembler_); + return code; +} + +CodeBufferBase *GenerateNearTrampolineBuffer(InterceptRouting *routing, addr_t src, addr_t dst) { + CodeBufferBase *result = nullptr; + + TurboAssembler turbo_assembler_((void *)src); +#define _ turbo_assembler_. + + // branch to trampoline_target directly + if (llabs((long long)dst - (long long)src) < ARM64_B_XXX_RANGE) { + _ b(dst - src); + } else { + auto fast_forward_trampoline = GenerateFastForwardTrampoline(src, dst); + if (!fast_forward_trampoline) + return nullptr; + _ b(fast_forward_trampoline->addr - src); + } + + // free the original trampoline + result = turbo_assembler_.GetCodeBuffer()->Copy(); + return result; +} + +#endif diff --git a/app/src/main/cpp/Dobby/source/InterceptRouting/RoutingPlugin/RoutingPlugin.cc b/app/src/main/cpp/Dobby/source/InterceptRouting/RoutingPlugin/RoutingPlugin.cc new file mode 100644 index 0000000..e6e8ffd --- /dev/null +++ b/app/src/main/cpp/Dobby/source/InterceptRouting/RoutingPlugin/RoutingPlugin.cc @@ -0,0 +1,11 @@ +#include "InterceptRouting/RoutingPlugin/RoutingPlugin.h" + +tinystl::vector RoutingPluginManager::plugins; + +RoutingPluginInterface *RoutingPluginManager::near_branch_trampoline = NULL; + +void RoutingPluginManager::registerPlugin(const char *name, RoutingPluginInterface *plugin) { + DEBUG_LOG("register %s plugin", name); + + RoutingPluginManager::plugins.push_back(plugin); +} diff --git a/app/src/main/cpp/Dobby/source/InterceptRouting/RoutingPlugin/RoutingPlugin.h b/app/src/main/cpp/Dobby/source/InterceptRouting/RoutingPlugin/RoutingPlugin.h new file mode 100644 index 0000000..17ac97e --- /dev/null +++ b/app/src/main/cpp/Dobby/source/InterceptRouting/RoutingPlugin/RoutingPlugin.h @@ -0,0 +1,30 @@ +#pragma once + +#include "dobby/dobby_internal.h" + +#include "InterceptRouting/InterceptRouting.h" + +class RoutingPluginInterface { +public: + // @Return: if false will continue to iter next plugin + virtual bool Prepare(InterceptRouting *routing) = 0; + + // @Return: if false will continue to iter next plugin + virtual bool Active(InterceptRouting *routing) = 0; + + // @Return: if false will continue to iter next plugin + virtual bool GenerateTrampolineBuffer(InterceptRouting *routing, addr_t src, addr_t dst) = 0; + +private: + char name_[256]; +}; + +class RoutingPluginManager { +public: + static void registerPlugin(const char *name, RoutingPluginInterface *plugin); + +public: + static tinystl::vector plugins; + + static RoutingPluginInterface *near_branch_trampoline; +}; diff --git a/app/src/main/cpp/Dobby/source/Interceptor.cpp b/app/src/main/cpp/Dobby/source/Interceptor.cpp new file mode 100644 index 0000000..7cfe113 --- /dev/null +++ b/app/src/main/cpp/Dobby/source/Interceptor.cpp @@ -0,0 +1,40 @@ +#include "Interceptor.h" + +Interceptor *Interceptor::instance = nullptr; + +Interceptor *Interceptor::SharedInstance() { + if (Interceptor::instance == nullptr) { + Interceptor::instance = new Interceptor(); + } + return Interceptor::instance; +} + +InterceptEntry *Interceptor::find(addr_t addr) { + for (auto *entry : entries) { + if (entry->patched_addr == addr) { + return entry; + } + } + return nullptr; +} + +void Interceptor::add(InterceptEntry *entry) { + entries.push_back(entry); +} + +void Interceptor::remove(addr_t addr) { + for (auto iter = entries.begin(); iter != entries.end(); iter++) { + if ((*iter)->patched_addr == addr) { + entries.erase(iter); + break; + } + } +} + +const InterceptEntry *Interceptor::getEntry(int i) { + return entries[i]; +} + +int Interceptor::count() { + return entries.size(); +} diff --git a/app/src/main/cpp/Dobby/source/Interceptor.h b/app/src/main/cpp/Dobby/source/Interceptor.h new file mode 100644 index 0000000..467a229 --- /dev/null +++ b/app/src/main/cpp/Dobby/source/Interceptor.h @@ -0,0 +1,25 @@ +#pragma once + +#include "dobby/dobby_internal.h" +#include "InterceptEntry.h" + +class Interceptor { +public: + static Interceptor *SharedInstance(); + +public: + InterceptEntry *find(addr_t addr); + + void remove(addr_t addr); + + void add(InterceptEntry *entry); + + const InterceptEntry *getEntry(int i); + + int count(); + +private: + static Interceptor *instance; + + tinystl::vector entries; +}; \ No newline at end of file diff --git a/app/src/main/cpp/Dobby/source/MemoryAllocator/AssemblyCodeBuilder.cc b/app/src/main/cpp/Dobby/source/MemoryAllocator/AssemblyCodeBuilder.cc new file mode 100644 index 0000000..f0bffea --- /dev/null +++ b/app/src/main/cpp/Dobby/source/MemoryAllocator/AssemblyCodeBuilder.cc @@ -0,0 +1,34 @@ +#include "MemoryAllocator/AssemblyCodeBuilder.h" + +#include "dobby/dobby_internal.h" +#include "PlatformUnifiedInterface/ExecMemory/CodePatchTool.h" + +AssemblyCode *AssemblyCodeBuilder::FinalizeFromTurboAssembler(AssemblerBase *assembler) { + auto buffer = (CodeBufferBase *)assembler->GetCodeBuffer(); + auto realized_addr = (addr_t)assembler->GetRealizedAddress(); +#if defined(TEST_WITH_UNICORN) + // impl: unicorn emulator map memory + realized_addr = 0; +#endif + if (!realized_addr) { + size_t buffer_size = 0; + buffer_size = buffer->GetBufferSize(); +#if TARGET_ARCH_ARM + // extra bytes for align needed + buffer_size += 4; +#endif + + auto block = MemoryAllocator::SharedAllocator()->allocateExecBlock(buffer_size); + if (block == nullptr) + return nullptr; + + realized_addr = block->addr; + assembler->SetRealizedAddress((void *)realized_addr); + } + + // Realize the buffer code to the executable memory address, remove the external label, etc + DobbyCodePatch((void *)realized_addr, buffer->GetBuffer(), buffer->GetBufferSize()); + + auto block = new AssemblyCode(realized_addr, buffer->GetBufferSize()); + return block; +} \ No newline at end of file diff --git a/app/src/main/cpp/Dobby/source/MemoryAllocator/AssemblyCodeBuilder.h b/app/src/main/cpp/Dobby/source/MemoryAllocator/AssemblyCodeBuilder.h new file mode 100644 index 0000000..d704c56 --- /dev/null +++ b/app/src/main/cpp/Dobby/source/MemoryAllocator/AssemblyCodeBuilder.h @@ -0,0 +1,14 @@ +#pragma once + +#include "PlatformUnifiedInterface/MemoryAllocator.h" + +#include "core/assembler/assembler.h" + +using namespace zz; + +using AssemblyCode = CodeMemBlock; + +class AssemblyCodeBuilder { +public: + static AssemblyCode *FinalizeFromTurboAssembler(AssemblerBase *assembler); +}; diff --git a/app/src/main/cpp/Dobby/source/MemoryAllocator/CodeBuffer/CodeBufferBase.cc b/app/src/main/cpp/Dobby/source/MemoryAllocator/CodeBuffer/CodeBufferBase.cc new file mode 100644 index 0000000..eab9622 --- /dev/null +++ b/app/src/main/cpp/Dobby/source/MemoryAllocator/CodeBuffer/CodeBufferBase.cc @@ -0,0 +1,53 @@ +#include "MemoryAllocator/CodeBuffer/CodeBufferBase.h" + +CodeBufferBase *CodeBufferBase::Copy() { + CodeBufferBase *result = new CodeBufferBase(); + result->EmitBuffer(GetBuffer(), GetBufferSize()); + return result; +} + +void CodeBufferBase::Emit8(uint8_t data) { + Emit(data); +} + +void CodeBufferBase::Emit16(uint16_t data) { + Emit(data); +} + +void CodeBufferBase::Emit32(uint32_t data) { + Emit(data); +} + +void CodeBufferBase::Emit64(uint64_t data) { + Emit(data); +} + +void CodeBufferBase::EmitBuffer(uint8_t *buffer, int buffer_size) { + buffer_.insert(buffer_.end(), buffer, buffer + buffer_size); +} + +uint8_t *CodeBufferBase::GetBuffer() { + return buffer_.data(); +} + +size_t CodeBufferBase::GetBufferSize() { + return buffer_.size(); +} + +#if 0 // Template Advanced won't enable even in userspace +template T CodeBufferBase::Load(int offset) { + return *reinterpret_cast(buffer + offset); +} + +template void CodeBufferBase::Store(int offset, T value) { + *reinterpret_cast(buffer + offset) = value; +} + +template void CodeBufferBase::Emit(T value) { + // Ensure the free space enough for the template T value + ensureCapacity(sizeof(T) + GetBufferSize()); + + *reinterpret_cast(buffer_cursor) = value; + buffer_cursor += sizeof(T); +} +#endif diff --git a/app/src/main/cpp/Dobby/source/MemoryAllocator/CodeBuffer/CodeBufferBase.h b/app/src/main/cpp/Dobby/source/MemoryAllocator/CodeBuffer/CodeBufferBase.h new file mode 100644 index 0000000..61b5889 --- /dev/null +++ b/app/src/main/cpp/Dobby/source/MemoryAllocator/CodeBuffer/CodeBufferBase.h @@ -0,0 +1,40 @@ +#pragma once + +#include "dobby/common.h" + +class CodeBufferBase { +public: + CodeBufferBase() { + } + +public: + virtual CodeBufferBase *Copy(); + + void Emit8(uint8_t data); + + void Emit16(uint16_t data); + + void Emit32(uint32_t data); + + void Emit64(uint64_t data); + + template T Load(int offset) { + return *(T *)(buffer_.data() + offset); + } + + template void Store(int offset, T value) { + *(T *)(buffer_.data() + offset) = value; + } + + template void Emit(T value) { + EmitBuffer((uint8_t *)&value, sizeof(value)); + } + + void EmitBuffer(uint8_t *buffer, int len); + + uint8_t *GetBuffer(); + size_t GetBufferSize(); + +private: + tinystl::vector buffer_; +}; diff --git a/app/src/main/cpp/Dobby/source/MemoryAllocator/CodeBuffer/code-buffer-arm.h b/app/src/main/cpp/Dobby/source/MemoryAllocator/CodeBuffer/code-buffer-arm.h new file mode 100644 index 0000000..0255947 --- /dev/null +++ b/app/src/main/cpp/Dobby/source/MemoryAllocator/CodeBuffer/code-buffer-arm.h @@ -0,0 +1,59 @@ +#ifndef CODE_BUFFER_ARM_H +#define CODE_BUFFER_ARM_H + +#include "MemoryAllocator/CodeBuffer/CodeBufferBase.h" + +typedef int32_t arm_inst_t; +typedef int16_t thumb1_inst_t; +typedef int32_t thumb2_inst_t; + +class CodeBuffer : public CodeBufferBase { + enum ExecuteState { ARMExecuteState, ThumbExecuteState }; + +public: + CodeBuffer() : CodeBufferBase() { + } + +public: + arm_inst_t LoadARMInst(uint32_t offset) { + return *reinterpret_cast(GetBuffer() + offset); + } + + thumb1_inst_t LoadThumb1Inst(uint32_t offset) { + return *reinterpret_cast(GetBuffer() + offset); + } + + thumb2_inst_t LoadThumb2Inst(uint32_t offset) { + return *reinterpret_cast(GetBuffer() + offset); + } + + void RewriteAddr(uint32_t offset, addr32_t addr) { + memcpy(GetBuffer() + offset, &addr, sizeof(addr)); + } + + void RewriteARMInst(uint32_t offset, arm_inst_t instr) { + *reinterpret_cast(GetBuffer() + offset) = instr; + } + + void RewriteThumb1Inst(uint32_t offset, thumb1_inst_t instr) { + *reinterpret_cast(GetBuffer() + offset) = instr; + } + + void RewriteThumb2Inst(uint32_t offset, thumb2_inst_t instr) { + memcpy(GetBuffer() + offset, &instr, sizeof(instr)); + } + + void EmitARMInst(arm_inst_t instr) { + Emit(instr); + } + + void EmitThumb1Inst(thumb1_inst_t instr) { + Emit(instr); + } + + void EmitThumb2Inst(thumb2_inst_t instr) { + Emit(instr); + } +}; + +#endif \ No newline at end of file diff --git a/app/src/main/cpp/Dobby/source/MemoryAllocator/CodeBuffer/code-buffer-arm64.h b/app/src/main/cpp/Dobby/source/MemoryAllocator/CodeBuffer/code-buffer-arm64.h new file mode 100644 index 0000000..266e10b --- /dev/null +++ b/app/src/main/cpp/Dobby/source/MemoryAllocator/CodeBuffer/code-buffer-arm64.h @@ -0,0 +1,24 @@ +#ifndef CODE_BUFFER_ARM64_H +#define CODE_BUFFER_ARM64_H + +#include "MemoryAllocator/CodeBuffer/CodeBufferBase.h" + +typedef int32_t arm64_inst_t; + +class CodeBuffer : public CodeBufferBase { + +public: + CodeBuffer() : CodeBufferBase() { + } + +public: + arm64_inst_t LoadInst(uint32_t offset) { + return *reinterpret_cast(GetBuffer() + offset); + } + + void RewriteInst(uint32_t offset, arm64_inst_t instr) { + *reinterpret_cast(GetBuffer() + offset) = instr; + } +}; + +#endif diff --git a/app/src/main/cpp/Dobby/source/MemoryAllocator/CodeBuffer/code-buffer-x64.h b/app/src/main/cpp/Dobby/source/MemoryAllocator/CodeBuffer/code-buffer-x64.h new file mode 100644 index 0000000..913ee8a --- /dev/null +++ b/app/src/main/cpp/Dobby/source/MemoryAllocator/CodeBuffer/code-buffer-x64.h @@ -0,0 +1,17 @@ +#ifndef CODE_BUFFER_X64_H +#define CODE_BUFFER_X64_H + +#include "MemoryAllocator/CodeBuffer/CodeBufferBase.h" + +class CodeBuffer : public CodeBufferBase { +public: + CodeBuffer() : CodeBufferBase() { + } + +public: + void FixBindLabel(int offset, int32_t disp) { + Store(offset, disp); + } +}; + +#endif \ No newline at end of file diff --git a/app/src/main/cpp/Dobby/source/MemoryAllocator/CodeBuffer/code-buffer-x86.cc b/app/src/main/cpp/Dobby/source/MemoryAllocator/CodeBuffer/code-buffer-x86.cc new file mode 100644 index 0000000..e7e0734 --- /dev/null +++ b/app/src/main/cpp/Dobby/source/MemoryAllocator/CodeBuffer/code-buffer-x86.cc @@ -0,0 +1,18 @@ +#include "platform_detect_macro.h" +#if defined(TARGET_ARCH_IA32) + +#include "MemoryAllocator/CodeBuffer/code-buffer-x86.h" + +void CodeBuffer::Emit32(int32_t data) { + ensureCapacity(GetBufferSize() + sizeof(int32_t)); + *reinterpret_cast(getCursor()) = data; + buffer_cursor += sizeof(int32_t); + return; +} + +void CodeBuffer::FixBindLabel(int offset, int32_t disp) { + *reinterpret_cast(buffer + offset) = disp; + return; +} + +#endif \ No newline at end of file diff --git a/app/src/main/cpp/Dobby/source/MemoryAllocator/CodeBuffer/code-buffer-x86.h b/app/src/main/cpp/Dobby/source/MemoryAllocator/CodeBuffer/code-buffer-x86.h new file mode 100644 index 0000000..43b2f35 --- /dev/null +++ b/app/src/main/cpp/Dobby/source/MemoryAllocator/CodeBuffer/code-buffer-x86.h @@ -0,0 +1,12 @@ +#pragma once + +#include "MemoryAllocator/CodeBuffer/CodeBufferBase.h" + +class CodeBuffer : public CodeBufferBase { +public: + CodeBuffer() : CodeBufferBase() { + } + +public: + void FixBindLabel(int offset, int32_t disp); +}; \ No newline at end of file diff --git a/app/src/main/cpp/Dobby/source/MemoryAllocator/CodeBuffer/code_buffer_arm.h b/app/src/main/cpp/Dobby/source/MemoryAllocator/CodeBuffer/code_buffer_arm.h new file mode 100644 index 0000000..0fe8346 --- /dev/null +++ b/app/src/main/cpp/Dobby/source/MemoryAllocator/CodeBuffer/code_buffer_arm.h @@ -0,0 +1,56 @@ +#pragma once + +#include "MemoryAllocator/CodeBuffer/CodeBufferBase.h" + +typedef int32_t arm_inst_t; +typedef int16_t thumb1_inst_t; +typedef int32_t thumb2_inst_t; + +class CodeBuffer : public CodeBufferBase { + enum ExecuteState { ARMExecuteState, ThumbExecuteState }; + +public: + CodeBuffer() : CodeBufferBase() { + } + +public: + arm_inst_t LoadARMInst(uint32_t offset) { + return *reinterpret_cast(GetBuffer() + offset); + } + + thumb1_inst_t LoadThumb1Inst(uint32_t offset) { + return *reinterpret_cast(GetBuffer() + offset); + } + + thumb2_inst_t LoadThumb2Inst(uint32_t offset) { + return *reinterpret_cast(GetBuffer() + offset); + } + + void RewriteAddr(uint32_t offset, addr32_t addr) { + memcpy(GetBuffer() + offset, &addr, sizeof(addr)); + } + + void RewriteARMInst(uint32_t offset, arm_inst_t instr) { + *reinterpret_cast(GetBuffer() + offset) = instr; + } + + void RewriteThumb1Inst(uint32_t offset, thumb1_inst_t instr) { + *reinterpret_cast(GetBuffer() + offset) = instr; + } + + void RewriteThumb2Inst(uint32_t offset, thumb2_inst_t instr) { + memcpy(GetBuffer() + offset, &instr, sizeof(instr)); + } + + void EmitARMInst(arm_inst_t instr) { + Emit(instr); + } + + void EmitThumb1Inst(thumb1_inst_t instr) { + Emit(instr); + } + + void EmitThumb2Inst(thumb2_inst_t instr) { + Emit(instr); + } +}; \ No newline at end of file diff --git a/app/src/main/cpp/Dobby/source/MemoryAllocator/CodeBuffer/code_buffer_arm64.h b/app/src/main/cpp/Dobby/source/MemoryAllocator/CodeBuffer/code_buffer_arm64.h new file mode 100644 index 0000000..4c8d803 --- /dev/null +++ b/app/src/main/cpp/Dobby/source/MemoryAllocator/CodeBuffer/code_buffer_arm64.h @@ -0,0 +1,21 @@ +#pragma once + +#include "MemoryAllocator/CodeBuffer/CodeBufferBase.h" + +typedef int32_t arm64_inst_t; + +class CodeBuffer : public CodeBufferBase { + +public: + CodeBuffer() : CodeBufferBase() { + } + +public: + arm64_inst_t LoadInst(uint32_t offset) { + return *reinterpret_cast(GetBuffer() + offset); + } + + void RewriteInst(uint32_t offset, arm64_inst_t instr) { + *reinterpret_cast(GetBuffer() + offset) = instr; + } +}; \ No newline at end of file diff --git a/app/src/main/cpp/Dobby/source/MemoryAllocator/CodeBuffer/code_buffer_x64.h b/app/src/main/cpp/Dobby/source/MemoryAllocator/CodeBuffer/code_buffer_x64.h new file mode 100644 index 0000000..d80dfb8 --- /dev/null +++ b/app/src/main/cpp/Dobby/source/MemoryAllocator/CodeBuffer/code_buffer_x64.h @@ -0,0 +1,14 @@ +#pragma once + +#include "MemoryAllocator/CodeBuffer/CodeBufferBase.h" + +class CodeBuffer : public CodeBufferBase { +public: + CodeBuffer() : CodeBufferBase() { + } + +public: + void FixBindLabel(int offset, int32_t disp) { + Store(offset, disp); + } +}; \ No newline at end of file diff --git a/app/src/main/cpp/Dobby/source/MemoryAllocator/CodeBuffer/code_buffer_x86.h b/app/src/main/cpp/Dobby/source/MemoryAllocator/CodeBuffer/code_buffer_x86.h new file mode 100644 index 0000000..d80dfb8 --- /dev/null +++ b/app/src/main/cpp/Dobby/source/MemoryAllocator/CodeBuffer/code_buffer_x86.h @@ -0,0 +1,14 @@ +#pragma once + +#include "MemoryAllocator/CodeBuffer/CodeBufferBase.h" + +class CodeBuffer : public CodeBufferBase { +public: + CodeBuffer() : CodeBufferBase() { + } + +public: + void FixBindLabel(int offset, int32_t disp) { + Store(offset, disp); + } +}; \ No newline at end of file diff --git a/app/src/main/cpp/Dobby/source/MemoryAllocator/MemoryAllocator.cc b/app/src/main/cpp/Dobby/source/MemoryAllocator/MemoryAllocator.cc new file mode 100644 index 0000000..13ff04a --- /dev/null +++ b/app/src/main/cpp/Dobby/source/MemoryAllocator/MemoryAllocator.cc @@ -0,0 +1,106 @@ +#include "dobby/dobby_internal.h" + +#include "PlatformUnifiedInterface/MemoryAllocator.h" + +MemBlock *MemoryArena::allocMemBlock(size_t size) { + // insufficient memory + if (this->end - this->cursor_addr < size) { + return nullptr; + } + + auto result = new MemBlock(cursor_addr, size); + cursor_addr += size; + return result; +} + +MemoryAllocator *MemoryAllocator::shared_allocator = nullptr; +MemoryAllocator *MemoryAllocator::SharedAllocator() { + if (MemoryAllocator::shared_allocator == nullptr) { + MemoryAllocator::shared_allocator = new MemoryAllocator(); + } + return MemoryAllocator::shared_allocator; +} + +CodeMemoryArena *MemoryAllocator::allocateCodeMemoryArena(uint32_t size) { + CHECK_EQ(size % OSMemory::PageSize(), 0); + uint32_t arena_size = size; + auto arena_addr = OSMemory::Allocate(arena_size, kNoAccess); + OSMemory::SetPermission(arena_addr, arena_size, kReadExecute); + + auto result = new CodeMemoryArena((addr_t)arena_addr, (size_t)arena_size); + code_arenas.push_back(result); + return result; +} + +CodeMemBlock *MemoryAllocator::allocateExecBlock(uint32_t size) { + CodeMemBlock *block = nullptr; + for (auto iter = code_arenas.begin(); iter != code_arenas.end(); iter++) { + auto arena = static_cast(*iter); + block = arena->allocMemBlock(size); + if (block) + break; + } + if (!block) { + // allocate new arena + auto arena_size = ALIGN_CEIL(size, OSMemory::PageSize()); + auto arena = allocateCodeMemoryArena(arena_size); + block = arena->allocMemBlock(size); + CHECK_NOT_NULL(block); + } + + DEBUG_LOG("[memory allocator] allocate exec memory at: %p, size: %p", block->addr, block->size); + return block; +} + +uint8_t *MemoryAllocator::allocateExecMemory(uint32_t size) { + auto block = allocateExecBlock(size); + return (uint8_t *)block->addr; +} +uint8_t *MemoryAllocator::allocateExecMemory(uint8_t *buffer, uint32_t buffer_size) { + auto mem = allocateExecMemory(buffer_size); + auto ret = DobbyCodePatch(mem, buffer, buffer_size); + CHECK_EQ(ret, 0); + return mem; +} + +DataMemoryArena *MemoryAllocator::allocateDataMemoryArena(uint32_t size) { + DataMemoryArena *result = nullptr; + + uint32_t buffer_size = ALIGN_CEIL(size, OSMemory::PageSize()); + void *buffer = OSMemory::Allocate(buffer_size, kNoAccess); + OSMemory::SetPermission(buffer, buffer_size, kReadWrite); + + result = new DataMemoryArena((addr_t)buffer, (size_t)buffer_size); + data_arenas.push_back(result); + return result; +} + +DataMemBlock *MemoryAllocator::allocateDataBlock(uint32_t size) { + CodeMemBlock *block = nullptr; + for (auto iter = data_arenas.begin(); iter != data_arenas.end(); iter++) { + auto arena = static_cast(*iter); + block = arena->allocMemBlock(size); + if (block) + break; + } + if (!block) { + // allocate new arena + auto arena = allocateCodeMemoryArena(size); + block = arena->allocMemBlock(size); + CHECK_NOT_NULL(block); + } + + DEBUG_LOG("[memory allocator] allocate data memory at: %p, size: %p", block->addr, block->size); + return block; +} + +uint8_t *MemoryAllocator::allocateDataMemory(uint32_t size) { + auto block = allocateDataBlock(size); + return (uint8_t *)block->addr; +} + +uint8_t *MemoryAllocator::allocateDataMemory(uint8_t *buffer, uint32_t buffer_size) { + auto mem = allocateDataMemory(buffer_size); + memcpy(mem, buffer, buffer_size); + return mem; +} diff --git a/app/src/main/cpp/Dobby/source/MemoryAllocator/NearMemoryAllocator.cc b/app/src/main/cpp/Dobby/source/MemoryAllocator/NearMemoryAllocator.cc new file mode 100644 index 0000000..27b5cf7 --- /dev/null +++ b/app/src/main/cpp/Dobby/source/MemoryAllocator/NearMemoryAllocator.cc @@ -0,0 +1,235 @@ +#include "NearMemoryAllocator.h" + +#include "dobby/dobby_internal.h" + +#include "PlatformUtil/ProcessRuntimeUtility.h" + +using namespace zz; + +#define KB (1024uLL) +#define MB (1024uLL * KB) +#define GB (1024uLL * MB) + +#if defined(WIN32) +static const void *memmem(const void *haystack, size_t haystacklen, const void *needle, size_t needlelen) { + if (!haystack || !needle) { + return haystack; + } else { + const char *h = (const char *)haystack; + const char *n = (const char *)needle; + size_t l = needlelen; + const char *r = h; + while (l && (l <= haystacklen)) { + if (*n++ != *h++) { + r = h; + n = (const char *)needle; + l = needlelen; + } else { + --l; + } + --haystacklen; + } + return l ? nullptr : r; + } +} +#endif + +#define min(a, b) (((a) < (b)) ? (a) : (b)) +#define max(a, b) (((a) > (b)) ? (a) : (b)) + +NearMemoryAllocator *NearMemoryAllocator::shared_allocator = nullptr; +NearMemoryAllocator *NearMemoryAllocator::SharedAllocator() { + if (NearMemoryAllocator::shared_allocator == nullptr) { + NearMemoryAllocator::shared_allocator = new NearMemoryAllocator(); + } + return NearMemoryAllocator::shared_allocator; +} + +MemBlock *NearMemoryAllocator::allocateNearBlockFromDefaultAllocator(uint32_t size, addr_t pos, size_t search_range, + bool executable) { + addr_t min_valid_addr, max_valid_addr; + min_valid_addr = pos - search_range; + max_valid_addr = pos + search_range; + + auto allocateFromDefaultArena = [&](MemoryArena *arena, uint32_t size) -> addr_t { + addr_t unused_mem_start = arena->cursor_addr; + addr_t unused_mem_end = arena->addr + arena->size; + + // check if unused region total out of search range + if (unused_mem_end < min_valid_addr || unused_mem_start > max_valid_addr) + return 0; + + unused_mem_start = max(unused_mem_start, min_valid_addr); + unused_mem_end = min(unused_mem_end, max_valid_addr); + + // check if invalid + if (unused_mem_start >= unused_mem_end) + return 0; + + // check if has sufficient memory + if (unused_mem_end - unused_mem_start < size) + return 0; + + DEBUG_LOG("[near memory allocator] unused memory from default allocator %p(%p), within pos: %p, serach_range: %p", + unused_mem_start, size, pos, search_range); + return unused_mem_start; + }; + + MemoryArena *arena = nullptr; + addr_t unused_mem = 0; + if (executable) { + for (auto iter = default_allocator->code_arenas.begin(); iter != default_allocator->code_arenas.end(); iter++) { + arena = *iter; + unused_mem = allocateFromDefaultArena(arena, size); + if (!unused_mem) + continue; + + break; + } + } else { + for (auto iter = default_allocator->data_arenas.begin(); iter != default_allocator->data_arenas.end(); iter++) { + arena = *iter; + unused_mem = allocateFromDefaultArena(arena, size); + if (unused_mem) + continue; + } + } + + if (!unused_mem) + return nullptr; + + // skip placeholder block + // FIXME: allocate the placeholder but mark it as freed + auto placeholder_block_size = unused_mem - arena->cursor_addr; + arena->allocMemBlock(placeholder_block_size); + + auto block = arena->allocMemBlock(size); + return block; +} + +MemBlock *NearMemoryAllocator::allocateNearBlockFromUnusedRegion(uint32_t size, addr_t pos, size_t search_range, + bool executable) { + + addr_t min_valid_addr, max_valid_addr; + min_valid_addr = pos - search_range; + max_valid_addr = pos + search_range; + + auto check_has_sufficient_memory_between_region = [&](MemRegion region, MemRegion next_region, + uint32_t size) -> addr_t { + addr_t unused_mem_start = region.start + region.size; + addr_t unused_mem_end = next_region.start; + + // check if unused region total out of search range + if (unused_mem_end < min_valid_addr || unused_mem_start > max_valid_addr) + return 0; + + // align + unused_mem_start = ALIGN_FLOOR(unused_mem_start, 4); + + unused_mem_start = max(unused_mem_start, min_valid_addr); + unused_mem_end = min(unused_mem_end, max_valid_addr); + + // check if invalid + if (unused_mem_start >= unused_mem_end) + return 0; + + // check if has sufficient memory + if (unused_mem_end - unused_mem_start < size) + return 0; + + DEBUG_LOG("[near memory allocator] unused memory from unused region %p(%p), within pos: %p, serach_range: %p", + unused_mem_start, size, pos, search_range); + return unused_mem_start; + }; + + addr_t unused_mem = 0; + auto regions = ProcessRuntimeUtility::GetProcessMemoryLayout(); + for (size_t i = 0; i + 1 < regions.size(); i++) { + unused_mem = check_has_sufficient_memory_between_region(regions[i], regions[i + 1], size); + if (unused_mem == 0) + continue; + break; + } + + if (!unused_mem) + return nullptr; + + auto unused_arena_first_page_addr = (addr_t)ALIGN_FLOOR(unused_mem, OSMemory::PageSize()); + auto unused_arena_end_page_addr = ALIGN_FLOOR(unused_mem + size, OSMemory::PageSize()); + auto unused_arena_size = unused_arena_end_page_addr - unused_arena_first_page_addr + OSMemory::PageSize(); + auto unused_arena_addr = unused_arena_first_page_addr; + + if (OSMemory::Allocate(unused_arena_size, kNoAccess, (void *)unused_arena_addr) == nullptr) { + ERROR_LOG("[near memory allocator] allocate fixed page failed %p", unused_arena_addr); + return nullptr; + } + + auto register_near_arena = [&](addr_t arena_addr, size_t arena_size) -> MemoryArena * { + MemoryArena *arena = nullptr; + if (executable) { + arena = new CodeMemoryArena(arena_addr, arena_size); + default_allocator->code_arenas.push_back(arena); + } else { + arena = new DataMemoryArena(arena_addr, arena_size); + default_allocator->data_arenas.push_back(arena); + } + OSMemory::SetPermission((void *)arena->addr, arena->size, executable ? kReadExecute : kReadWrite); + return arena; + }; + + auto unused_arena = register_near_arena(unused_arena_addr, unused_arena_size); + + // skip placeholder block + // FIXME: allocate the placeholder but mark it as freed + auto placeholder_block_size = unused_mem - unused_arena->cursor_addr; + unused_arena->allocMemBlock(placeholder_block_size); + + auto block = unused_arena->allocMemBlock(size); + return block; +} + +MemBlock *NearMemoryAllocator::allocateNearBlock(uint32_t size, addr_t pos, size_t search_range, bool executable) { + MemBlock *result = nullptr; + result = allocateNearBlockFromDefaultAllocator(size, pos, search_range, executable); + if (!result) { + result = allocateNearBlockFromUnusedRegion(size, pos, search_range, executable); + } + + if (!result) { + ERROR_LOG("[near memory allocator] allocate near block failed (%p, %p, %p)", size, pos, search_range); + } + return result; +} + +uint8_t *NearMemoryAllocator::allocateNearExecMemory(uint32_t size, addr_t pos, size_t search_range) { + auto block = allocateNearBlock(size, pos, search_range, true); + if (!block) + return nullptr; + + DEBUG_LOG("[near memory allocator] allocate exec memory at: %p, size: %p", block->addr, block->size); + return (uint8_t *)block->addr; +} + +uint8_t *NearMemoryAllocator::allocateNearExecMemory(uint8_t *buffer, uint32_t buffer_size, addr_t pos, + size_t search_range) { + auto mem = allocateNearExecMemory(buffer_size, pos, search_range); + auto ret = DobbyCodePatch(mem, buffer, buffer_size); + CHECK_EQ(ret, 0); + return mem; +} + +uint8_t *NearMemoryAllocator::allocateNearDataMemory(uint32_t size, addr_t pos, size_t search_range) { + auto block = allocateNearBlock(size, pos, search_range, false); + if (!block) + return nullptr; + + DEBUG_LOG("[near memory allocator] allocate data memory at: %p, size: %p", block->addr, block->size); + return (uint8_t *)block->addr; +} + +uint8_t *NearMemoryAllocator::allocateNearDataMemory(uint8_t *buffer, uint32_t buffer_size, addr_t pos, + size_t search_range) { + auto mem = allocateNearExecMemory(buffer_size, pos, search_range); + memcpy(mem, buffer, buffer_size); + return mem; +} diff --git a/app/src/main/cpp/Dobby/source/MemoryAllocator/NearMemoryAllocator.h b/app/src/main/cpp/Dobby/source/MemoryAllocator/NearMemoryAllocator.h new file mode 100644 index 0000000..701cba8 --- /dev/null +++ b/app/src/main/cpp/Dobby/source/MemoryAllocator/NearMemoryAllocator.h @@ -0,0 +1,30 @@ +#pragma once + +#include "PlatformUnifiedInterface/MemoryAllocator.h" + +#include "dobby/common.h" + +class NearMemoryAllocator { +public: + MemoryAllocator *default_allocator; + NearMemoryAllocator() { + default_allocator = MemoryAllocator::SharedAllocator(); + } + +private: + static NearMemoryAllocator *shared_allocator; + +public: + static NearMemoryAllocator *SharedAllocator(); + +public: + MemBlock *allocateNearBlock(uint32_t size, addr_t pos, size_t search_range, bool executable); + MemBlock *allocateNearBlockFromDefaultAllocator(uint32_t size, addr_t pos, size_t search_range, bool executable); + MemBlock *allocateNearBlockFromUnusedRegion(uint32_t size, addr_t pos, size_t search_range, bool executable); + + uint8_t *allocateNearExecMemory(uint32_t size, addr_t pos, size_t search_range); + uint8_t *allocateNearExecMemory(uint8_t *buffer, uint32_t buffer_size, addr_t pos, size_t search_range); + + uint8_t *allocateNearDataMemory(uint32_t size, addr_t pos, size_t search_range); + uint8_t *allocateNearDataMemory(uint8_t *buffer, uint32_t buffer_size, addr_t pos, size_t search_range); +}; \ No newline at end of file diff --git a/app/src/main/cpp/Dobby/source/PlatformUnifiedInterface/ExecMemory/ClearCacheTool.h b/app/src/main/cpp/Dobby/source/PlatformUnifiedInterface/ExecMemory/ClearCacheTool.h new file mode 100644 index 0000000..ee407cb --- /dev/null +++ b/app/src/main/cpp/Dobby/source/PlatformUnifiedInterface/ExecMemory/ClearCacheTool.h @@ -0,0 +1,11 @@ +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +void ClearCache(void *start, void *end); + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/app/src/main/cpp/Dobby/source/PlatformUnifiedInterface/ExecMemory/CodePatchTool.h b/app/src/main/cpp/Dobby/source/PlatformUnifiedInterface/ExecMemory/CodePatchTool.h new file mode 100644 index 0000000..410f0d8 --- /dev/null +++ b/app/src/main/cpp/Dobby/source/PlatformUnifiedInterface/ExecMemory/CodePatchTool.h @@ -0,0 +1,3 @@ +#pragma once + +int DobbyCodePatch(void *address, uint8_t *buffer, uint32_t buffer_size); \ No newline at end of file diff --git a/app/src/main/cpp/Dobby/source/PlatformUnifiedInterface/MemoryAllocator.h b/app/src/main/cpp/Dobby/source/PlatformUnifiedInterface/MemoryAllocator.h new file mode 100644 index 0000000..56da2e5 --- /dev/null +++ b/app/src/main/cpp/Dobby/source/PlatformUnifiedInterface/MemoryAllocator.h @@ -0,0 +1,101 @@ +#pragma once + +#include "dobby/common.h" + +struct MemRange { + addr_t start; + addr_t end; + size_t size; + + MemRange(addr_t start, size_t size) : start(start), end(0), size(size) { + end = start + size; + } + + void reset(addr_t start, size_t size) { + this->start = start; + this->size = size; + end = start + size; + } +}; + +struct MemBlock : MemRange { + addr_t addr; + + MemBlock() : MemRange(0, 0), addr(0) { + } + + MemBlock(addr_t addr, size_t size) : MemRange(addr, size), addr(addr) { + } + + void reset(addr_t addr, size_t size) { + MemRange::reset(addr, size); + this->addr = addr; + } +}; + +struct MemoryArena : MemRange { + addr_t addr; + addr_t cursor_addr; + + tinystl::vector memory_blocks; + + MemoryArena(addr_t addr, size_t size) : MemRange(addr, size), addr(addr), cursor_addr(addr) { + } + + virtual MemBlock *allocMemBlock(size_t size); +}; + +using CodeMemBlock = MemBlock; +using CodeMemoryArena = MemoryArena; + +#if 0 +struct CodeMemoryArena : MemoryArena { + CodeMemoryArena(addr_t addr, size_t size) : MemoryArena(addr, size) { + } + + CodeMemBlock *allocateCodeMemBlock(size_t size) { + return allocMemBlock(size); + } +}; +#endif + +using DataMemBlock = MemBlock; +using DataMemoryArena = MemoryArena; + +#if 0 +struct DataMemoryArena : MemoryArena { +public: + DataMemoryArena(addr_t addr, size_t size) : MemoryArena(addr, size) { + } + + DataMemBlock *allocateDataMemBlock(size_t size) { + return allocMemBlock(size); + } +}; +#endif + +class NearMemoryAllocator; +class MemoryAllocator { + friend class NearMemoryAllocator; + +private: + tinystl::vector code_arenas; + tinystl::vector data_arenas; + +private: + static MemoryAllocator *shared_allocator; + +public: + static MemoryAllocator *SharedAllocator(); + +public: + CodeMemoryArena *allocateCodeMemoryArena(uint32_t size); + CodeMemBlock *allocateExecBlock(uint32_t size); + uint8_t *allocateExecMemory(uint32_t size); + uint8_t *allocateExecMemory(uint8_t *buffer, uint32_t buffer_size); + + DataMemoryArena *allocateDataMemoryArena(uint32_t size); + DataMemBlock *allocateDataBlock(uint32_t size); + uint8_t *allocateDataMemory(uint32_t size); + uint8_t *allocateDataMemory(uint8_t *buffer, uint32_t buffer_size); +}; \ No newline at end of file diff --git a/app/src/main/cpp/Dobby/source/TrampolineBridge/ClosureTrampolineBridge/ClosureTrampoline.h b/app/src/main/cpp/Dobby/source/TrampolineBridge/ClosureTrampolineBridge/ClosureTrampoline.h new file mode 100644 index 0000000..160ba0a --- /dev/null +++ b/app/src/main/cpp/Dobby/source/TrampolineBridge/ClosureTrampolineBridge/ClosureTrampoline.h @@ -0,0 +1,39 @@ +#pragma once + +#include "dobby/dobby_internal.h" + +#ifdef ENABLE_CLOSURE_TRAMPOLINE_TEMPLATE +#ifdef __cplusplus +extern "C" { +#endif //__cplusplus +void closure_trampoline_template(); +void closure_bridge_template(); +#ifdef __cplusplus +} +#endif //__cplusplus +#endif + +#ifdef __cplusplus +extern "C" { +#endif //__cplusplus + +typedef struct { + void *address; + int size; + void *carry_handler; + void *carry_data; +} ClosureTrampolineEntry; + +asm_func_t get_closure_bridge(); + +#ifdef __cplusplus +} +#endif //__cplusplus + +class ClosureTrampoline { +private: + static tinystl::vector *trampolines_; + +public: + static ClosureTrampolineEntry *CreateClosureTrampoline(void *carry_data, void *carry_handler); +}; diff --git a/app/src/main/cpp/Dobby/source/TrampolineBridge/ClosureTrampolineBridge/arm/ClosureTrampolineARM.cc b/app/src/main/cpp/Dobby/source/TrampolineBridge/ClosureTrampolineBridge/arm/ClosureTrampolineARM.cc new file mode 100644 index 0000000..76e2ea2 --- /dev/null +++ b/app/src/main/cpp/Dobby/source/TrampolineBridge/ClosureTrampolineBridge/arm/ClosureTrampolineARM.cc @@ -0,0 +1,49 @@ +#include "platform_detect_macro.h" +#if defined(TARGET_ARCH_ARM) + +#include "dobby/dobby_internal.h" + +#include "core/assembler/assembler-arm.h" + +#include "TrampolineBridge/ClosureTrampolineBridge/ClosureTrampoline.h" + +using namespace zz; +using namespace zz::arm; + +ClosureTrampolineEntry *ClosureTrampoline::CreateClosureTrampoline(void *carry_data, void *carry_handler) { + ClosureTrampolineEntry *tramp_entry = nullptr; + tramp_entry = new ClosureTrampolineEntry; + +#ifdef ENABLE_CLOSURE_TRAMPOLINE_TEMPLATE +#define CLOSURE_TRAMPOLINE_SIZE (7 * 4) + // use closure trampoline template code, find the executable memory and patch it. + auto code = AssemblyCodeBuilder::FinalizeCodeFromAddress(closure_trampoline_template, CLOSURE_TRAMPOLINE_SIZE); +#else +// use assembler and codegen modules instead of template_code +#include "TrampolineBridge/ClosureTrampolineBridge/ClosureTrampoline.h" +#define _ turbo_assembler_. + TurboAssembler turbo_assembler_(0); + + AssemblerPseudoLabel entry_label(0); + AssemblerPseudoLabel forward_bridge_label(0); + + _ Ldr(r12, &entry_label); + _ Ldr(pc, &forward_bridge_label); + _ PseudoBind(&entry_label); + _ EmitAddress((uint32_t)(uintptr_t)tramp_entry); + _ PseudoBind(&forward_bridge_label); + _ EmitAddress((uint32_t)(uintptr_t)get_closure_bridge()); + + auto closure_tramp = AssemblyCodeBuilder::FinalizeFromTurboAssembler(&turbo_assembler_); + tramp_entry->address = (void *)closure_tramp->addr; + tramp_entry->size = closure_tramp->size; + tramp_entry->carry_data = carry_data; + tramp_entry->carry_handler = carry_handler; + + delete closure_tramp; + + return tramp_entry; +#endif +} + +#endif \ No newline at end of file diff --git a/app/src/main/cpp/Dobby/source/TrampolineBridge/ClosureTrampolineBridge/arm/closure_bridge_arm.cc b/app/src/main/cpp/Dobby/source/TrampolineBridge/ClosureTrampolineBridge/arm/closure_bridge_arm.cc new file mode 100644 index 0000000..e41500d --- /dev/null +++ b/app/src/main/cpp/Dobby/source/TrampolineBridge/ClosureTrampolineBridge/arm/closure_bridge_arm.cc @@ -0,0 +1,90 @@ +#include "platform_detect_macro.h" +#if defined(TARGET_ARCH_ARM) + +#include "dobby/dobby_internal.h" + +#include "core/assembler/assembler-arm.h" + +#include "TrampolineBridge/ClosureTrampolineBridge/common_bridge_handler.h" + +using namespace zz; +using namespace zz::arm; + +static asm_func_t closure_bridge = nullptr; + +asm_func_t get_closure_bridge() { + + // if already initialized, just return. + if (closure_bridge) + return closure_bridge; + +// check if enable the inline-assembly closure_bridge_template +#if ENABLE_CLOSURE_BRIDGE_TEMPLATE + extern void closure_bridge_tempate(); + closure_bridge = closure_bridge_template; +// otherwise, use the Assembler build the closure_bridge +#else +#define _ turbo_assembler_. + TurboAssembler turbo_assembler_(0); + + _ sub(sp, sp, Operand(14 * 4)); + _ str(lr, MemOperand(sp, 13 * 4)); + _ str(r12, MemOperand(sp, 12 * 4)); + _ str(r11, MemOperand(sp, 11 * 4)); + _ str(r10, MemOperand(sp, 10 * 4)); + _ str(r9, MemOperand(sp, 9 * 4)); + _ str(r8, MemOperand(sp, 8 * 4)); + _ str(r7, MemOperand(sp, 7 * 4)); + _ str(r6, MemOperand(sp, 6 * 4)); + _ str(r5, MemOperand(sp, 5 * 4)); + _ str(r4, MemOperand(sp, 4 * 4)); + _ str(r3, MemOperand(sp, 3 * 4)); + _ str(r2, MemOperand(sp, 2 * 4)); + _ str(r1, MemOperand(sp, 1 * 4)); + _ str(r0, MemOperand(sp, 0 * 4)); + + // store sp + _ add(r0, sp, Operand(14 * 4)); + _ sub(sp, sp, Operand(8)); + _ str(r0, MemOperand(sp, 4)); + + // stack align + _ sub(sp, sp, Operand(8)); + + _ mov(r0, Operand(sp)); + _ mov(r1, Operand(r12)); + _ CallFunction(ExternalReference((void *)common_closure_bridge_handler)); + + // stack align + _ add(sp, sp, Operand(8)); + + // restore sp placeholder stack + _ add(sp, sp, Operand(8)); + + _ ldr(r0, MemOperand(sp, 4, PostIndex)); + _ ldr(r1, MemOperand(sp, 4, PostIndex)); + _ ldr(r2, MemOperand(sp, 4, PostIndex)); + _ ldr(r3, MemOperand(sp, 4, PostIndex)); + _ ldr(r4, MemOperand(sp, 4, PostIndex)); + _ ldr(r5, MemOperand(sp, 4, PostIndex)); + _ ldr(r6, MemOperand(sp, 4, PostIndex)); + _ ldr(r7, MemOperand(sp, 4, PostIndex)); + _ ldr(r8, MemOperand(sp, 4, PostIndex)); + _ ldr(r9, MemOperand(sp, 4, PostIndex)); + _ ldr(r10, MemOperand(sp, 4, PostIndex)); + _ ldr(r11, MemOperand(sp, 4, PostIndex)); + _ ldr(r12, MemOperand(sp, 4, PostIndex)); + _ ldr(lr, MemOperand(sp, 4, PostIndex)); + + // auto switch A32 & T32 with `least significant bit`, refer `docs/A32_T32_states_switch.md` + _ mov(pc, Operand(r12)); + + auto code = AssemblyCodeBuilder::FinalizeFromTurboAssembler(&turbo_assembler_); + closure_bridge = (asm_func_t)code->addr; + + DEBUG_LOG("[closure bridge] closure bridge at %p", closure_bridge); +#endif + return closure_bridge; +} + +#endif diff --git a/app/src/main/cpp/Dobby/source/TrampolineBridge/ClosureTrampolineBridge/arm/dummy/closure-bridge-template-arm.cc b/app/src/main/cpp/Dobby/source/TrampolineBridge/ClosureTrampolineBridge/arm/dummy/closure-bridge-template-arm.cc new file mode 100644 index 0000000..8e41525 --- /dev/null +++ b/app/src/main/cpp/Dobby/source/TrampolineBridge/ClosureTrampolineBridge/arm/dummy/closure-bridge-template-arm.cc @@ -0,0 +1,65 @@ +// .section __TEXT,__text,regular,pure_instructions +// .ios_version_min 11, 0 + +#if defined(ENABLE_CLOSURE_BRIDGE_TEMPLATE) + +#if defined(__WIN32__) || defined(__APPLE__) +#define cdecl(s) "_" s +#else +#define cdecl(s) s +#endif + +#define xASM(x) __asm(x) + +__attribute__((naked)) void closure_bridge_template() { + xASM(".arm"); + xASM("sub sp, sp, #(14*4)"); + xASM("str lr, [sp, #(13*4)]"); + xASM("str r12, [sp, #(12*4)]"); + xASM("str r11, [sp, #(11*4)]"); + xASM("str r10, [sp, #(10*4)]"); + xASM("str r9, [sp, #(9*4)]"); + xASM("str r8, [sp, #(8*4)]"); + xASM("str r7, [sp, #(7*4)]"); + xASM("str r6, [sp, #(6*4)]"); + xASM("str r5, [sp, #(5*4)]"); + xASM("str r4, [sp, #(4*4)]"); + xASM("str r3, [sp, #(3*4)]"); + xASM("str r2, [sp, #(2*4)]"); + xASM("str r1, [sp, #(1*4)]"); + xASM("str r0, [sp, #(0*4)]"); + + // dummy align + xASM("sub sp, sp, #8"); + + xASM("mov r0, sp"); + xASM("mov r1, r12"); + xASM("bl " cdecl("common_closure_bridge_handler")); + + // dummy align + xASM("add sp, sp, #8"); + + xASM("ldr r0, [sp], #4"); + xASM("ldr r1, [sp], #4"); + xASM("ldr r2, [sp], #4"); + xASM("ldr r3, [sp], #4"); + xASM("ldr r4, [sp], #4"); + xASM("ldr r5, [sp], #4"); + xASM("ldr r6, [sp], #4"); + xASM("ldr r7, [sp], #4"); + xASM("ldr r8, [sp], #4"); + xASM("ldr r9, [sp], #4"); + xASM("ldr r10, [sp], #4"); + xASM("ldr r11, [sp], #4"); + xASM("ldr r12, [sp], #4"); + xASM("ldr lr, [sp], #4"); + +#if 1 + xASM("str r12, [sp, #-4]"); + xASM("ldr pc, [sp, #-4]"); +#else + xASM("mov pc, r12"); +#endif +} + +#endif \ No newline at end of file diff --git a/app/src/main/cpp/Dobby/source/TrampolineBridge/ClosureTrampolineBridge/arm/dummy/closure-trampoline-template-arm.S b/app/src/main/cpp/Dobby/source/TrampolineBridge/ClosureTrampolineBridge/arm/dummy/closure-trampoline-template-arm.S new file mode 100644 index 0000000..5be6ac8 --- /dev/null +++ b/app/src/main/cpp/Dobby/source/TrampolineBridge/ClosureTrampolineBridge/arm/dummy/closure-trampoline-template-arm.S @@ -0,0 +1,34 @@ +// .section __TEXT,__text,regular,pure_instructions + +#if defined(ENABLE_CLOSURE_BRIDGE_TEMPLATE) + +#if defined(__WIN32__) || defined(__APPLE__) +#define cdecl(s) _##s +#else +#define cdecl(s) s +#endif + +.align 4 + +#if !defined(ENABLE_CLOSURE_TRAMPOLINE_CARRY_OBJECT_PTR) + +// closure trampoline carray the object pointer, and fetch required members at the runtime assembly code. +// #include "TrampolineBridge/ClosureTrampolineBridge/ClosureTrampoline.h" +// #define OFFSETOF(TYPE, ELEMENT) ((size_t)&(((TYPE *)0)->ELEMENT)) +#define OFFSETOF_ClourseTrampolineEntry_carry_data 4 +#define OFFSETOF_ClourseTrampolineEntry_carry_handler 0 + .globl + cdecl(closure_trampoline_template) cdecl(closure_trampoline_template) + : ldr r12, +ClourseTrampolineEntryPtr ldr pc, [ r12, #0 ] ClourseTrampolineEntryPtr :.long 0 + +#else + + ; +closure trampoline just carray the required members from the object..globl cdecl(closure_trampoline_template) + cdecl(closure_trampoline_template) + : ldr r12, += carry_data ldr pc, = carry_handler carry_data :.long 0 carry_handler :.long 0 +#endif + +#endif \ No newline at end of file diff --git a/app/src/main/cpp/Dobby/source/TrampolineBridge/ClosureTrampolineBridge/arm/helper_arm.cc b/app/src/main/cpp/Dobby/source/TrampolineBridge/ClosureTrampolineBridge/arm/helper_arm.cc new file mode 100644 index 0000000..bf2123d --- /dev/null +++ b/app/src/main/cpp/Dobby/source/TrampolineBridge/ClosureTrampolineBridge/arm/helper_arm.cc @@ -0,0 +1,13 @@ +#include "platform_detect_macro.h" +#if defined(TARGET_ARCH_ARM) + +#include "dobby/dobby_internal.h" + +void set_routing_bridge_next_hop(DobbyRegisterContext *ctx, void *address) { + *reinterpret_cast(&ctx->general.regs.r12) = address; +} + +void get_routing_bridge_next_hop(DobbyRegisterContext *ctx, void *address) { +} + +#endif \ No newline at end of file diff --git a/app/src/main/cpp/Dobby/source/TrampolineBridge/ClosureTrampolineBridge/arm64/ClosureTrampolineARM64.cc b/app/src/main/cpp/Dobby/source/TrampolineBridge/ClosureTrampolineBridge/arm64/ClosureTrampolineARM64.cc new file mode 100644 index 0000000..9dfc44c --- /dev/null +++ b/app/src/main/cpp/Dobby/source/TrampolineBridge/ClosureTrampolineBridge/arm64/ClosureTrampolineARM64.cc @@ -0,0 +1,63 @@ +#include "platform_detect_macro.h" +#if defined(TARGET_ARCH_ARM64) + +#include "dobby/dobby_internal.h" + +#include "core/assembler/assembler-arm64.h" + +#include "TrampolineBridge/ClosureTrampolineBridge/ClosureTrampoline.h" + +using namespace zz; +using namespace zz::arm64; + +// // tips +// _ ldr(TMP_REG_1, OFFSETOF(ClosureTrampolineEntry, carry_data)); +// _ ldr(TMP_REG_0, OFFSETOF(ClosureTrampolineEntry, carry_handler)); + +// use assembler and codegen modules instead of template_code +ClosureTrampolineEntry *ClosureTrampoline::CreateClosureTrampoline(void *carry_data, void *carry_handler) { + ClosureTrampolineEntry *tramp_entry = nullptr; + tramp_entry = new ClosureTrampolineEntry; + +#define _ turbo_assembler_. + TurboAssembler turbo_assembler_(0); + + AssemblerPseudoLabel entry_label(0); + AssemblerPseudoLabel forward_bridge_label(0); + + // prologue: alloc stack, store lr + _ sub(SP, SP, 2 * 8); + _ str(x30, MemOperand(SP, 8)); + + // store data at stack + _ Ldr(TMP_REG_0, &entry_label); + _ str(TMP_REG_0, MemOperand(SP, 0)); + + _ Ldr(TMP_REG_0, &forward_bridge_label); + _ blr(TMP_REG_0); + + // epilogue: release stack(won't restore lr) + _ ldr(x30, MemOperand(SP, 8)); + _ add(SP, SP, 2 * 8); + + // branch to next hop + _ br(TMP_REG_0); + + _ PseudoBind(&entry_label); + _ EmitInt64((uint64_t)tramp_entry); + _ PseudoBind(&forward_bridge_label); + _ EmitInt64((uint64_t)get_closure_bridge()); + + auto closure_tramp = AssemblyCodeBuilder::FinalizeFromTurboAssembler(static_cast(&turbo_assembler_)); + + tramp_entry->address = (void *)closure_tramp->addr; + tramp_entry->size = closure_tramp->size; + tramp_entry->carry_data = carry_data; + tramp_entry->carry_handler = carry_handler; + + delete closure_tramp; + + return tramp_entry; +} + +#endif diff --git a/app/src/main/cpp/Dobby/source/TrampolineBridge/ClosureTrampolineBridge/arm64/closure_bridge_arm64.cc b/app/src/main/cpp/Dobby/source/TrampolineBridge/ClosureTrampolineBridge/arm64/closure_bridge_arm64.cc new file mode 100644 index 0000000..5e1bc0e --- /dev/null +++ b/app/src/main/cpp/Dobby/source/TrampolineBridge/ClosureTrampolineBridge/arm64/closure_bridge_arm64.cc @@ -0,0 +1,159 @@ +#include "platform_detect_macro.h" +#if defined(TARGET_ARCH_ARM64) + +#include "dobby/dobby_internal.h" + +#include "core/assembler/assembler.h" +#include "core/assembler/assembler-arm64.h" + +#include "TrampolineBridge/ClosureTrampolineBridge/common_bridge_handler.h" + +using namespace zz; +using namespace zz::arm64; + +static asm_func_t closure_bridge = nullptr; + +asm_func_t get_closure_bridge() { + // if already initialized, just return. + if (closure_bridge) + return closure_bridge; + +// check if enable the inline-assembly closure_bridge_template +#if ENABLE_CLOSURE_BRIDGE_TEMPLATE + extern void closure_bridge_tempate(); + closure_bridge = closure_bridge_template; +// otherwise, use the Assembler build the closure_bridge +#else +#define _ turbo_assembler_. +#define MEM(reg, offset) MemOperand(reg, offset) + TurboAssembler turbo_assembler_(0); + +#if defined(FULL_FLOATING_POINT_REGISTER_PACK) + + _ sub(SP, SP, 24 * 16); + _ stp(Q(30), Q(31), MEM(SP, 22 * 16)); + _ stp(Q(28), Q(29), MEM(SP, 20 * 16)); + _ stp(Q(26), Q(27), MEM(SP, 18 * 16)); + _ stp(Q(24), Q(25), MEM(SP, 16 * 16)); + _ stp(Q(22), Q(23), MEM(SP, 14 * 16)); + _ stp(Q(20), Q(21), MEM(SP, 12 * 16)); + _ stp(Q(18), Q(19), MEM(SP, 10 * 16)); + _ stp(Q(16), Q(17), MEM(SP, 8 * 16)); + _ stp(Q(14), Q(15), MEM(SP, 6 * 16)); + _ stp(Q(12), Q(13), MEM(SP, 4 * 16)); + _ stp(Q(10), Q(11), MEM(SP, 2 * 16)); + _ stp(Q(8), Q(9), MEM(SP, 0 * 16)); + +#endif + + // save {q0-q7} + _ sub(SP, SP, 8 * 16); + _ stp(Q(6), Q(7), MEM(SP, 6 * 16)); + _ stp(Q(4), Q(5), MEM(SP, 4 * 16)); + _ stp(Q(2), Q(3), MEM(SP, 2 * 16)); + _ stp(Q(0), Q(1), MEM(SP, 0 * 16)); + + // save {x1-x30} + _ sub(SP, SP, 30 * 8); + _ stp(X(29), X(30), MEM(SP, 28 * 8)); + _ stp(X(27), X(28), MEM(SP, 26 * 8)); + _ stp(X(25), X(26), MEM(SP, 24 * 8)); + _ stp(X(23), X(24), MEM(SP, 22 * 8)); + _ stp(X(21), X(22), MEM(SP, 20 * 8)); + _ stp(X(19), X(20), MEM(SP, 18 * 8)); + _ stp(X(17), X(18), MEM(SP, 16 * 8)); + _ stp(X(15), X(16), MEM(SP, 14 * 8)); + _ stp(X(13), X(14), MEM(SP, 12 * 8)); + _ stp(X(11), X(12), MEM(SP, 10 * 8)); + _ stp(X(9), X(10), MEM(SP, 8 * 8)); + _ stp(X(7), X(8), MEM(SP, 6 * 8)); + _ stp(X(5), X(6), MEM(SP, 4 * 8)); + _ stp(X(3), X(4), MEM(SP, 2 * 8)); + _ stp(X(1), X(2), MEM(SP, 0 * 8)); + + // save {x0} + _ sub(SP, SP, 2 * 8); + _ str(x0, MEM(SP, 8)); + + // calculate original sp + _ add(TMP_REG_0, SP, 2 * 8); // closure trampoline reserved + _ add(TMP_REG_0, TMP_REG_0, 2 * 8 + 30 * 8 + 8 * 16); // x0, x1-x30, q0-q7 reserved +#if defined(FULL_FLOATING_POINT_REGISTER_PACK) + _ add(TMP_REG_0, TMP_REG_0, 24 * 16); // q8-q31 reserved +#endif + + // alloc stack, store original sp + _ sub(SP, SP, 2 * 8); + _ str(TMP_REG_0, MEM(SP, 8)); + +#if defined(FULL_FLOATING_POINT_REGISTER_PACK) +#define REGISTER_CONTEXT_SIZE (sizeof(DobbyRegisterContext)) +#else +#define REGISTER_CONTEXT_SIZE (sizeof(DobbyRegisterContext) - 24 * 16) +#endif + // create function arm64 call convention + _ mov(x0, SP); // arg1: register context + // load package(closure trampoline entry reserved) + _ ldr(x1, MEM(SP, REGISTER_CONTEXT_SIZE + 0)); // arg2: closure trampoline entry + _ CallFunction(ExternalReference((void *)common_closure_bridge_handler)); + + // restore sp placeholder stack + _ add(SP, SP, 2 * 8); + + // restore {x0} + _ ldr(X(0), MEM(SP, 8)); + _ add(SP, SP, 2 * 8); + +#define MEM_EXT(reg, offset, addrmode) MemOperand(reg, offset, addrmode) + // restore {x1-x30} + _ ldp(X(1), X(2), MEM_EXT(SP, 16, PostIndex)); + _ ldp(X(3), X(4), MEM_EXT(SP, 16, PostIndex)); + _ ldp(X(5), X(6), MEM_EXT(SP, 16, PostIndex)); + _ ldp(X(7), X(8), MEM_EXT(SP, 16, PostIndex)); + _ ldp(X(9), X(10), MEM_EXT(SP, 16, PostIndex)); + _ ldp(X(11), X(12), MEM_EXT(SP, 16, PostIndex)); + _ ldp(X(13), X(14), MEM_EXT(SP, 16, PostIndex)); + _ ldp(X(15), X(16), MEM_EXT(SP, 16, PostIndex)); + _ ldp(X(17), X(18), MEM_EXT(SP, 16, PostIndex)); + _ ldp(X(19), X(20), MEM_EXT(SP, 16, PostIndex)); + _ ldp(X(21), X(22), MEM_EXT(SP, 16, PostIndex)); + _ ldp(X(23), X(24), MEM_EXT(SP, 16, PostIndex)); + _ ldp(X(25), X(26), MEM_EXT(SP, 16, PostIndex)); + _ ldp(X(27), X(28), MEM_EXT(SP, 16, PostIndex)); + _ ldp(X(29), X(30), MEM_EXT(SP, 16, PostIndex)); + + // restore {q0-q7} + _ ldp(Q(0), Q(1), MEM_EXT(SP, 32, PostIndex)); + _ ldp(Q(2), Q(3), MEM_EXT(SP, 32, PostIndex)); + _ ldp(Q(4), Q(5), MEM_EXT(SP, 32, PostIndex)); + _ ldp(Q(6), Q(7), MEM_EXT(SP, 32, PostIndex)); + +#if defined(FULL_FLOATING_POINT_REGISTER_PACK) + _ ldp(Q(8), Q(9), MEM_EXT(SP, 32, PostIndex)); + _ ldp(Q(10), Q(11), MEM_EXT(SP, 32, PostIndex)); + _ ldp(Q(12), Q(13), MEM_EXT(SP, 32, PostIndex)); + _ ldp(Q(14), Q(15), MEM_EXT(SP, 32, PostIndex)); + _ ldp(Q(16), Q(17), MEM_EXT(SP, 32, PostIndex)); + _ ldp(Q(18), Q(19), MEM_EXT(SP, 32, PostIndex)); + _ ldp(Q(20), Q(21), MEM_EXT(SP, 32, PostIndex)); + _ ldp(Q(22), Q(23), MEM_EXT(SP, 32, PostIndex)); + _ ldp(Q(24), Q(25), MEM_EXT(SP, 32, PostIndex)); + _ ldp(Q(26), Q(27), MEM_EXT(SP, 32, PostIndex)); + _ ldp(Q(28), Q(29), MEM_EXT(SP, 32, PostIndex)); + _ ldp(Q(30), Q(31), MEM_EXT(SP, 32, PostIndex)); +#endif + + // _ brk(0); // for debug + + // return to closure trampoline, but TMP_REG_0, had been modified with next hop address + _ ret(); // AKA br x30 + + auto code = AssemblyCodeBuilder::FinalizeFromTurboAssembler(&turbo_assembler_); + closure_bridge = (asm_func_t)code->addr; + + DEBUG_LOG("[closure bridge] closure bridge at %p", closure_bridge); +#endif + return closure_bridge; +} + +#endif diff --git a/app/src/main/cpp/Dobby/source/TrampolineBridge/ClosureTrampolineBridge/arm64/dummy/closure-bridge-template-arm64.c b/app/src/main/cpp/Dobby/source/TrampolineBridge/ClosureTrampolineBridge/arm64/dummy/closure-bridge-template-arm64.c new file mode 100644 index 0000000..ee5323e --- /dev/null +++ b/app/src/main/cpp/Dobby/source/TrampolineBridge/ClosureTrampolineBridge/arm64/dummy/closure-bridge-template-arm64.c @@ -0,0 +1,103 @@ +#if defined(ENABLE_CLOSURE_BRIDGE_TEMPLATE) + +#if defined(__WIN32__) || defined(__APPLE__) +#define xcdecl(s) "_" s +#else +#define xcdecl(s) s +#endif + +#define xASM(x) __asm(x) + +__attribute__((naked)) void closure_bridge_template() { + // DO NOT USE prologue + // x29 == fp, x30 == lr + // xASM("stp x29, x30, [sp, #-16]!"); + // xASM("mov x29, sp"); + + // save {q0-q7} + xASM("sub sp, sp, #(8*16)"); + xASM("stp q6, q7, [sp, #(6*16)]"); + xASM("stp q4, q5, [sp, #(4*16)]"); + xASM("stp q2, q3, [sp, #(2*16)]"); + xASM("stp q0, q1, [sp, #(0*16)]"); + + // save {x1-x30} + xASM("sub sp, sp, #(30*8)"); + // stp fp, lr, [sp, #(28*8)]"); + xASM("stp x29, x30, [sp, #(28*8)]"); + xASM("stp x27, x28, [sp, #(26*8)]"); + xASM("stp x25, x26, [sp, #(24*8)]"); + xASM("stp x23, x24, [sp, #(22*8)]"); + xASM("stp x21, x22, [sp, #(20*8)]"); + xASM("stp x19, x20, [sp, #(18*8)]"); + xASM("stp x17, x18, [sp, #(16*8)]"); + xASM("stp x15, x16, [sp, #(14*8)]"); + xASM("stp x13, x14, [sp, #(12*8)]"); + xASM("stp x11, x12, [sp, #(10*8)]"); + xASM("stp x9, x10, [sp, #(8*8)]"); + xASM("stp x7, x8, [sp, #(6*8)]"); + xASM("stp x5, x6, [sp, #(4*8)]"); + xASM("stp x3, x4, [sp, #(2*8)]"); + xASM("stp x1, x2, [sp, #(0*8)]"); + +#if 1 + // save {x0} + xASM("sub sp, sp, #(2*8)"); + xASM("str x0, [sp, #8]"); +#else + // save {x0, sp} + // save x0 and reserve sp, but this is trick + xASM("sub sp, sp, #(2*8)"); + xASM("str x0, [sp, #8]"); + // save origin sp + xASM("add x1, sp, #0x190"); + xASM("str x1, [sp, #0]"); +#endif + + // ======= Jump to UnifiedInterface Bridge Handle ======= + + // prepare args + // @x0: data_address + // @x1: DobbyRegisterContext stack address + xASM("mov x0, sp"); + xASM("mov x1, x14"); + xASM("bl " xcdecl("common_closure_bridge_handler")); + + // ======= DobbyRegisterContext Restore ======= + // restore x0 + xASM("ldr x0, [sp, #8]"); + xASM("add sp, sp, #(2*8)"); + + // restore {x1-x30} + xASM("ldp x1, x2, [sp], #16"); + xASM("ldp x3, x4, [sp], #16"); + xASM("ldp x5, x6, [sp], #16"); + xASM("ldp x7, x8, [sp], #16"); + xASM("ldp x9, x10, [sp], #16"); + xASM("ldp x11, x12, [sp], #16"); + xASM("ldp x13, x14, [sp], #16"); + xASM("ldp x15, x16, [sp], #16"); + xASM("ldp x17, x18, [sp], #16"); + xASM("ldp x19, x20, [sp], #16"); + xASM("ldp x21, x22, [sp], #16"); + xASM("ldp x23, x24, [sp], #16"); + xASM("ldp x25, x26, [sp], #16"); + xASM("ldp x27, x28, [sp], #16"); + // ldp fp, lr, [sp], #16"); + xASM("ldp x29, x30, [sp], #16"); + + // restore {q0-q7} + xASM("ldp q0, q1, [sp], #32"); + xASM("ldp q2, q3, [sp], #32"); + xASM("ldp q4, q5, [sp], #32"); + xASM("ldp q6, q7, [sp], #32"); + + // DO NOT USE epilog + // x29 == fp, x30 == lr + // xASM("mov sp, x29"); + // xASM("ldp x29, x30, [sp], #16"); + + xASM("br x15"); +}; + +#endif \ No newline at end of file diff --git a/app/src/main/cpp/Dobby/source/TrampolineBridge/ClosureTrampolineBridge/arm64/dummy/closure-trampoline-template-arm64.S b/app/src/main/cpp/Dobby/source/TrampolineBridge/ClosureTrampolineBridge/arm64/dummy/closure-trampoline-template-arm64.S new file mode 100644 index 0000000..2d54868 --- /dev/null +++ b/app/src/main/cpp/Dobby/source/TrampolineBridge/ClosureTrampolineBridge/arm64/dummy/closure-trampoline-template-arm64.S @@ -0,0 +1,36 @@ +// .section __TEXT,__text,regular,pure_instructions + +#if defined(ENABLE_CLOSURE_BRIDGE_TEMPLATE) + +#if defined(__WIN32__) || defined(__APPLE__) +#define cdecl(s) _##s +#else +#define cdecl(s) s +#endif + +.align 4 + +#if !defined(ENABLE_CLOSURE_TRAMPOLINE_CARRY_OBJECT_PTR) + +// closure trampoline carray the object pointer, and fetch required members at the runtime assembly code. +// #include "TrampolineBridge/ClosureTrampolineBridge/ClosureTrampoline.h" +// #define OFFSETOF(TYPE, ELEMENT) ((size_t)&(((TYPE *)0)->ELEMENT)) +#define OFFSETOF_ClourseTrampolineEntry_carry_data 8 +#define OFFSETOF_ClourseTrampolineEntry_carry_handler 0 + .globl + cdecl(closure_trampoline_template) cdecl(closure_trampoline_template) + : ldr x17, +ClourseTrampolineEntryPtr ldr x16, OFFSETOF_ClourseTrampolineEntry_carry_data ldr x17, +OFFSETOF_ClourseTrampolineEntry_carry_handler br x17 ClourseTrampolineEntryPtr :.long 0.long 0 + +#else + + ; +closure trampoline just carray the required members from the object..globl cdecl(closure_trampoline_template) + cdecl(closure_trampoline_template) + : ldr x16, += carry_data ldr x17, = carry_handler br x17 carry_data :.long 0.long 0 carry_handler :.long 0.long 0 + +#endif + +#endif \ No newline at end of file diff --git a/app/src/main/cpp/Dobby/source/TrampolineBridge/ClosureTrampolineBridge/arm64/dummy/dynamic-closure-trampoline-template-arm64.S b/app/src/main/cpp/Dobby/source/TrampolineBridge/ClosureTrampolineBridge/arm64/dummy/dynamic-closure-trampoline-template-arm64.S new file mode 100644 index 0000000..a52032f --- /dev/null +++ b/app/src/main/cpp/Dobby/source/TrampolineBridge/ClosureTrampolineBridge/arm64/dummy/dynamic-closure-trampoline-template-arm64.S @@ -0,0 +1,33 @@ +// .section __TEXT,__text,regular,pure_instructions + +// For iOS, we can't allocate executable memory, but we can use `remap` doing some trick. +// For details, please refer `libffi` + +#if defined(ENABLE_CLOSURE_BRIDGE_TEMPLATE) + +#if defined(__WIN32__) || defined(__APPLE__) +#define cdecl(s) _##s +#else +#define cdecl(s) s +#endif + +#define PAGE_MAX_SIZE 4096 +#define PAGE_MAX_SHIFT 14 + +.align PAGE_MAX_SHIFT.globl cdecl(dynamic_closure_trampoline_table_page) cdecl(dynamic_closure_trampoline_table_page) + :.rept(PAGE_MAX_SIZE - 4 * 4) / + 8 // sub dynamic_closure_trampoline_forward size + adr x16, +#0 b cdecl(dynamic_closure_trampoline_forward) + .endr + + cdecl(dynamic_closure_trampoline_forward) + : sub x16, +x16, #0x4000 // [DynamicClosureTrampoline **] + ldr x16, +[ x16, #0 ] // [DynamicClosureTrampoline *] + ldr x17, +[ x16, #0 ] // trampolineTo + br x17 + +#endif \ No newline at end of file diff --git a/app/src/main/cpp/Dobby/source/TrampolineBridge/ClosureTrampolineBridge/arm64/helper_arm64.cc b/app/src/main/cpp/Dobby/source/TrampolineBridge/ClosureTrampolineBridge/arm64/helper_arm64.cc new file mode 100644 index 0000000..c0046d4 --- /dev/null +++ b/app/src/main/cpp/Dobby/source/TrampolineBridge/ClosureTrampolineBridge/arm64/helper_arm64.cc @@ -0,0 +1,17 @@ +#include "platform_detect_macro.h" +#if defined(TARGET_ARCH_ARM64) + +#include "core/assembler/assembler-arm64.h" + +#include "dobby/dobby_internal.h" + +using namespace zz::arm64; + +void set_routing_bridge_next_hop(DobbyRegisterContext *ctx, void *address) { + *reinterpret_cast(&ctx->general.x[TMP_REG_0.code()]) = address; +} + +void get_routing_bridge_next_hop(DobbyRegisterContext *ctx, void *address) { +} + +#endif diff --git a/app/src/main/cpp/Dobby/source/TrampolineBridge/ClosureTrampolineBridge/common_bridge_handler.cc b/app/src/main/cpp/Dobby/source/TrampolineBridge/ClosureTrampolineBridge/common_bridge_handler.cc new file mode 100644 index 0000000..b1be02a --- /dev/null +++ b/app/src/main/cpp/Dobby/source/TrampolineBridge/ClosureTrampolineBridge/common_bridge_handler.cc @@ -0,0 +1,22 @@ +#include "logging/logging.h" + +#include "TrampolineBridge/ClosureTrampolineBridge/common_bridge_handler.h" + +PUBLIC void common_closure_bridge_handler(DobbyRegisterContext *ctx, ClosureTrampolineEntry *entry) { + DEBUG_LOG("common bridge handler: carry data: %p, carry handler: %p", (InterceptEntry *)entry->carry_data, + entry->carry_handler); + + typedef void (*routing_handler_t)(InterceptEntry *, DobbyRegisterContext *); + auto routing_handler = (routing_handler_t)entry->carry_handler; + +#if defined(__APPLE__) && __arm64e__ +#if __has_feature(ptrauth_calls) + uint64_t discriminator = 0; + // discriminator = __builtin_ptrauth_type_discriminator(__typeof(routing_handler)); + routing_handler = (__typeof(routing_handler))__builtin_ptrauth_sign_unauthenticated((void *)routing_handler, + ptrauth_key_asia, discriminator); +#endif +#endif + + routing_handler((InterceptEntry *)entry->carry_data, ctx); +} diff --git a/app/src/main/cpp/Dobby/source/TrampolineBridge/ClosureTrampolineBridge/common_bridge_handler.h b/app/src/main/cpp/Dobby/source/TrampolineBridge/ClosureTrampolineBridge/common_bridge_handler.h new file mode 100644 index 0000000..c02eca3 --- /dev/null +++ b/app/src/main/cpp/Dobby/source/TrampolineBridge/ClosureTrampolineBridge/common_bridge_handler.h @@ -0,0 +1,17 @@ +#ifndef CLOSURE_TRAMPOLINE_COMMON_HANDLER_H +#define CLOSURE_TRAMPOLINE_COMMON_HANDLER_H + +#include "dobby/dobby_internal.h" + +#include "Interceptor.h" +#include "TrampolineBridge/ClosureTrampolineBridge/ClosureTrampoline.h" + +extern "C" { +void common_closure_bridge_handler(DobbyRegisterContext *ctx, ClosureTrampolineEntry *entry); +} + +void get_routing_bridge_next_hop(DobbyRegisterContext *ctx, void *address); + +void set_routing_bridge_next_hop(DobbyRegisterContext *ctx, void *address); + +#endif \ No newline at end of file diff --git a/app/src/main/cpp/Dobby/source/TrampolineBridge/ClosureTrampolineBridge/x64/ClosureTrampolineX64.cc b/app/src/main/cpp/Dobby/source/TrampolineBridge/ClosureTrampolineBridge/x64/ClosureTrampolineX64.cc new file mode 100644 index 0000000..f3abb2d --- /dev/null +++ b/app/src/main/cpp/Dobby/source/TrampolineBridge/ClosureTrampolineBridge/x64/ClosureTrampolineX64.cc @@ -0,0 +1,45 @@ +#include "platform_detect_macro.h" +#if defined(TARGET_ARCH_X64) + +#include "dobby/dobby_internal.h" + +#include "core/assembler/assembler-x64.h" + +#include "TrampolineBridge/ClosureTrampolineBridge/ClosureTrampoline.h" + +using namespace zz; +using namespace zz::x64; + +ClosureTrampolineEntry *ClosureTrampoline::CreateClosureTrampoline(void *carry_data, void *carry_handler) { + ClosureTrampolineEntry *tramp_entry = nullptr; + tramp_entry = new ClosureTrampolineEntry; + + auto tramp_size = 32; + auto tramp_mem = MemoryAllocator::SharedAllocator()->allocateExecMemory(tramp_size); + if (tramp_mem == nullptr) { + return nullptr; + } +#define _ turbo_assembler_. +#define __ turbo_assembler_.GetCodeBuffer()-> + TurboAssembler turbo_assembler_(0); + + uint8_t *push_rip_6 = (uint8_t *)"\xff\x35\x06\x00\x00\x00"; + uint8_t *jmp_rip_8 = (uint8_t *)"\xff\x25\x08\x00\x00\x00"; + + __ EmitBuffer(push_rip_6, 6); + __ EmitBuffer(jmp_rip_8, 6); + __ Emit64((uint64_t)tramp_entry); + __ Emit64((uint64_t)get_closure_bridge()); + + tramp_entry->address = tramp_mem; + tramp_entry->size = tramp_size; + tramp_entry->carry_data = carry_data; + tramp_entry->carry_handler = carry_handler; + + auto closure_tramp_buffer = static_cast(turbo_assembler_.GetCodeBuffer()); + DobbyCodePatch(tramp_mem, (uint8_t *)closure_tramp_buffer->GetBuffer(), closure_tramp_buffer->GetBufferSize()); + + return tramp_entry; +} + +#endif \ No newline at end of file diff --git a/app/src/main/cpp/Dobby/source/TrampolineBridge/ClosureTrampolineBridge/x64/closure_bridge_x64.cc b/app/src/main/cpp/Dobby/source/TrampolineBridge/ClosureTrampolineBridge/x64/closure_bridge_x64.cc new file mode 100644 index 0000000..c0c5ffc --- /dev/null +++ b/app/src/main/cpp/Dobby/source/TrampolineBridge/ClosureTrampolineBridge/x64/closure_bridge_x64.cc @@ -0,0 +1,141 @@ +#include "platform_detect_macro.h" +#if defined(TARGET_ARCH_X64) + +#include "dobby/dobby_internal.h" + +#include "core/assembler/assembler-x64.h" + +#include "TrampolineBridge/ClosureTrampolineBridge/common_bridge_handler.h" + +using namespace zz; +using namespace zz::x64; + +static asm_func_t closure_bridge = nullptr; + +asm_func_t get_closure_bridge() { + // if already initialized, just return. + if (closure_bridge) + return closure_bridge; + +// Check if enable the inline-assembly closure_bridge_template +#if ENABLE_CLOSURE_BRIDGE_TEMPLATE + + extern void closure_bridge_tempate(); + closure_bridge = closure_bridge_template; + +#else + +// otherwise, use the Assembler build the closure_bridge +#define _ turbo_assembler_. +#define __ turbo_assembler_.GetCodeBuffer()-> + + uint8_t *pushfq = (uint8_t *)"\x9c"; + uint8_t *popfq = (uint8_t *)"\x9d"; + + TurboAssembler turbo_assembler_(0); + + // save flags register + __ EmitBuffer(pushfq, 1); + // align rsp 16-byte + _ sub(rsp, Immediate(8, 32)); + + // general register + _ sub(rsp, Immediate(16 * 8, 32)); + _ mov(Address(rsp, 8 * 0), rax); + _ mov(Address(rsp, 8 * 1), rbx); + _ mov(Address(rsp, 8 * 2), rcx); + _ mov(Address(rsp, 8 * 3), rdx); + _ mov(Address(rsp, 8 * 4), rbp); + _ mov(Address(rsp, 8 * 5), rsp); + _ mov(Address(rsp, 8 * 6), rdi); + _ mov(Address(rsp, 8 * 7), rsi); + _ mov(Address(rsp, 8 * 8), r8); + _ mov(Address(rsp, 8 * 9), r9); + _ mov(Address(rsp, 8 * 10), r10); + _ mov(Address(rsp, 8 * 11), r11); + _ mov(Address(rsp, 8 * 12), r12); + _ mov(Address(rsp, 8 * 13), r13); + _ mov(Address(rsp, 8 * 14), r14); + _ mov(Address(rsp, 8 * 15), r15); + + // save origin sp + _ mov(rax, rsp); + _ add(rax, Immediate(8 + 8 + 8 + 16 * 8, 32)); + _ sub(rsp, Immediate(2 * 8, 32)); + _ mov(Address(rsp, 8), rax); + + // ======= Jump to UnifiedInterface Bridge Handle ======= + + // prepare args + // @rdi: data_address + // @rsi: DobbyRegisterContext stack address + _ mov(rdi, rsp); + _ mov(rsi, Address(rsp, 8 + 8 + 16 * 8 + 2 * 8)); + + // [!!!] As we can't detect the sp is aligned or not, check if need stack align + { + // mov rax, rsp + __ EmitBuffer((uint8_t *)"\x48\x89\xE0", 3); + // and rax, 0xF + __ EmitBuffer((uint8_t *)"\x48\x83\xE0\x0F", 4); + // cmp rax, 0x0 + __ EmitBuffer((uint8_t *)"\x48\x83\xF8\x00", 4); + // jnz [stack_align_call_bridge] + __ EmitBuffer((uint8_t *)"\x75\x15", 2); + } + + // LABEL: call_bridge + _ CallFunction(ExternalReference((void *)common_closure_bridge_handler)); + + // jmp [restore_stack_register] + __ EmitBuffer((uint8_t *)"\xE9\x12\x00\x00\x00", 5); + + // LABEL: stack_align_call_bridge + // push rax + __ EmitBuffer((uint8_t *)"\x50", 1); + _ CallFunction(ExternalReference((void *)common_closure_bridge_handler)); + // pop rax + __ EmitBuffer((uint8_t *)"\x58", 1); + + // ======= DobbyRegisterContext Restore ======= + + // restore sp placeholder stack + _ add(rsp, Immediate(2 * 8, 32)); + + // general register + _ pop(rax); + _ pop(rbx); + _ pop(rcx); + _ pop(rdx); + _ pop(rbp); + _ add(rsp, Immediate(8, 32)); // => pop rsp + _ pop(rdi); + _ pop(rsi); + _ pop(r8); + _ pop(r9); + _ pop(r10); + _ pop(r11); + _ pop(r12); + _ pop(r13); + _ pop(r14); + _ pop(r15); + + // align rsp 16-byte + _ add(rsp, Immediate(8, 32)); + // restore flags register + __ EmitBuffer(popfq, 1); + + // trick: use the 'carry_data' stack(remain at closure trampoline) placeholder, as the return address + _ ret(); + + _ RelocBind(); + + auto code = AssemblyCodeBuilder::FinalizeFromTurboAssembler(&turbo_assembler_); + closure_bridge = (asm_func_t)code->addr; + + DEBUG_LOG("[closure bridge] closure bridge at %p", closure_bridge); +#endif + return closure_bridge; +} + +#endif diff --git a/app/src/main/cpp/Dobby/source/TrampolineBridge/ClosureTrampolineBridge/x64/dummy/closure-bridge-template-x64.c b/app/src/main/cpp/Dobby/source/TrampolineBridge/ClosureTrampolineBridge/x64/dummy/closure-bridge-template-x64.c new file mode 100644 index 0000000..d59dcdc --- /dev/null +++ b/app/src/main/cpp/Dobby/source/TrampolineBridge/ClosureTrampolineBridge/x64/dummy/closure-bridge-template-x64.c @@ -0,0 +1,70 @@ +#if defined(ENABLE_CLOSURE_BRIDGE_TEMPLATE) + +#if defined(__WIN32__) || defined(__APPLE__) +#define xcdecl(s) "_" s +#else +#define xcdecl(s) s +#endif + +#define xASM(x) __asm(x) + +__attribute__((naked)) void closure_bridge_template() { + // flags register + xASM("pushfq"); + + // general register + xASM("sub rsp, #(16*8)"); + xASM("mov [rsp+16*0], rax"); + xASM("mov [rsp+16*1], rbx"); + xASM("mov [rsp+16*2], rcx"); + xASM("mov [rsp+16*3], rdx"); + xASM("mov [rsp+16*4], rbp"); + xASM("mov [rsp+16*5], rsp"); + xASM("mov [rsp+16*6], rdi"); + xASM("mov [rsp+16*7], rsi"); + xASM("mov [rsp+16*8], r8"); + xASM("mov [rsp+16*9], r9"); + xASM("mov [rsp+16*10], r10"); + xASM("mov [rsp+16*11], r11"); + xASM("mov [rsp+16*12], r12"); + xASM("mov [rsp+16*13], r13"); + xASM("mov [rsp+16*14], r14"); + xASM("mov [rsp+16*15], r15"); + + // ======= Jump to UnifiedInterface Bridge Handle ======= + + // prepare args + // @rdi: data_address + // @rsi: DobbyRegisterContext stack address + xASM("mov rdi, rsp"); + xASM("mov rsi, [rsp-16*8]"); + xASM("call " xcdecl("common_closure_bridge_handler")); + + // ======= DobbyRegisterContext Restore ======= + + // general register + xASM("pop r15"); + xASM("pop r14"); + xASM("pop r13"); + xASM("pop r12"); + xASM("pop r11"); + xASM("pop r10"); + xASM("pop r9"); + xASM("pop r8"); + xASM("pop rsi"); + xASM("pop rdi"); + xASM("pop rsp"); + xASM("pop rbp"); + xASM("pop rdx"); + xASM("pop rcx"); + xASM("pop rbx"); + xASM("pop rax"); + + // flags register + xASM("popfq"); + + // trick: use the 'carry_data' placeholder, as the return address + xASM("ret"); +}; + +#endif \ No newline at end of file diff --git a/app/src/main/cpp/Dobby/source/TrampolineBridge/ClosureTrampolineBridge/x64/dummy/closure-trampoline-template-x64.S b/app/src/main/cpp/Dobby/source/TrampolineBridge/ClosureTrampolineBridge/x64/dummy/closure-trampoline-template-x64.S new file mode 100644 index 0000000..c544dc8 --- /dev/null +++ b/app/src/main/cpp/Dobby/source/TrampolineBridge/ClosureTrampolineBridge/x64/dummy/closure-trampoline-template-x64.S @@ -0,0 +1,17 @@ +#if defined(ENABLE_CLOSURE_BRIDGE_TEMPLATE) + +#if defined(__WIN32__) || defined(__APPLE__) +#define cdecl(s) _##s +#else +#define cdecl(s) s +#endif + +.align 4 + + ; +closure trampoline just carray the required members from the object. + .globl + cdecl(closure_trampoline_template) cdecl(closure_trampoline_template) + : push[rip + 6 + 6] jmp[rip + 6 + 8] carry_data :.long 0.long 0 carry_handler :.long 0.long 0 + +#endif diff --git a/app/src/main/cpp/Dobby/source/TrampolineBridge/ClosureTrampolineBridge/x64/helper_x64.cc b/app/src/main/cpp/Dobby/source/TrampolineBridge/ClosureTrampolineBridge/x64/helper_x64.cc new file mode 100644 index 0000000..1f59357 --- /dev/null +++ b/app/src/main/cpp/Dobby/source/TrampolineBridge/ClosureTrampolineBridge/x64/helper_x64.cc @@ -0,0 +1,17 @@ +#include "platform_detect_macro.h" +#if defined(TARGET_ARCH_X64) + +#include "dobby/dobby_internal.h" + +void set_routing_bridge_next_hop(DobbyRegisterContext *ctx, void *address) { + addr_t rsp = ctx->rsp; + + // ClosureTrampolineEntry reserved stack + addr_t entry_placeholder_stack_addr = rsp - 8; + *(addr_t *)entry_placeholder_stack_addr = (addr_t)address; +} + +void get_routing_bridge_next_hop(DobbyRegisterContext *ctx, void *address) { +} + +#endif \ No newline at end of file diff --git a/app/src/main/cpp/Dobby/source/TrampolineBridge/ClosureTrampolineBridge/x86/ClosureTrampolineX86.cc b/app/src/main/cpp/Dobby/source/TrampolineBridge/ClosureTrampolineBridge/x86/ClosureTrampolineX86.cc new file mode 100644 index 0000000..c29b190 --- /dev/null +++ b/app/src/main/cpp/Dobby/source/TrampolineBridge/ClosureTrampolineBridge/x86/ClosureTrampolineX86.cc @@ -0,0 +1,44 @@ +#include "platform_detect_macro.h" +#if defined(TARGET_ARCH_IA32) + +#include "dobby/dobby_internal.h" + +#include "core/assembler/assembler-ia32.h" + +#include "TrampolineBridge/ClosureTrampolineBridge/ClosureTrampoline.h" + +using namespace zz; +using namespace zz::x86; + +ClosureTrampolineEntry *ClosureTrampoline::CreateClosureTrampoline(void *carry_data, void *carry_handler) { + ClosureTrampolineEntry *tramp_entry = nullptr; + tramp_entry = new ClosureTrampolineEntry; + + auto tramp_size = 32; + auto tramp_mem = MemoryAllocator::SharedAllocator()->allocateExecMemory(tramp_size); + if (tramp_mem == nullptr) { + return nullptr; + } + +#define _ turbo_assembler_. +#define __ turbo_assembler_.GetCodeBuffer()-> + TurboAssembler turbo_assembler_(tramp_mem); + + int32_t offset = (int32_t)((uintptr_t)get_closure_bridge() - ((uintptr_t)tramp_mem + 18)); + + _ sub(esp, Immediate(4, 32)); + _ mov(Address(esp, 4 * 0), Immediate((int32_t)(uintptr_t)tramp_entry, 32)); + _ jmp(Immediate(offset, 32)); + + tramp_entry->address = tramp_mem; + tramp_entry->size = tramp_size; + tramp_entry->carry_data = carry_data; + tramp_entry->carry_handler = carry_handler; + + auto closure_tramp_buffer = static_cast(turbo_assembler_.GetCodeBuffer()); + DobbyCodePatch(tramp_mem, (uint8_t *)closure_tramp_buffer->GetBuffer(), closure_tramp_buffer->GetBufferSize()); + + return tramp_entry; +} + +#endif \ No newline at end of file diff --git a/app/src/main/cpp/Dobby/source/TrampolineBridge/ClosureTrampolineBridge/x86/closure_bridge_x86.cc b/app/src/main/cpp/Dobby/source/TrampolineBridge/ClosureTrampolineBridge/x86/closure_bridge_x86.cc new file mode 100644 index 0000000..acc940a --- /dev/null +++ b/app/src/main/cpp/Dobby/source/TrampolineBridge/ClosureTrampolineBridge/x86/closure_bridge_x86.cc @@ -0,0 +1,112 @@ +#include "platform_detect_macro.h" +#if defined(TARGET_ARCH_IA32) + +#include "dobby/dobby_internal.h" + +#include "core/assembler/assembler-ia32.h" + +#include "TrampolineBridge/ClosureTrampolineBridge/common_bridge_handler.h" + +using namespace zz; +using namespace zz::x86; + +static asm_func_t closure_bridge = NULL; + +asm_func_t get_closure_bridge() { + // if already initialized, just return. + if (closure_bridge) + return closure_bridge; + +// Check if enable the inline-assembly closure_bridge_template +#if ENABLE_CLOSURE_BRIDGE_TEMPLATE + + extern void closure_bridge_tempate(); + closure_bridge = closure_bridge_template; + +#else + +// otherwise, use the Assembler build the closure_bridge +#define _ turbo_assembler_. +#define __ turbo_assembler_.GetCodeBuffer()-> + + auto pushfd = (uint8_t *)"\x9c"; + auto popfd = (uint8_t *)"\x9d"; + + TurboAssembler turbo_assembler_(0); + + // general register + _ sub(esp, Immediate(8 * 4, 32)); + _ mov(Address(esp, 4 * 0), eax); + _ mov(Address(esp, 4 * 1), ebx); + _ mov(Address(esp, 4 * 2), ecx); + _ mov(Address(esp, 4 * 3), edx); + _ mov(Address(esp, 4 * 4), ebp); + _ mov(Address(esp, 4 * 5), esp); + _ mov(Address(esp, 4 * 6), edi); + _ mov(Address(esp, 4 * 7), esi); + + // save flags register + __ EmitBuffer(pushfd, 1); + _ pop(eax); + { // save to stack + _ sub(esp, Immediate(2 * 4, 32)); + _ mov(Address(esp, 4), eax); + } + + // save origin sp + _ mov(eax, esp); + _ add(eax, Immediate(8 * 4 + 2 * 4 + 4, 32)); + { // save to stack + _ sub(esp, Immediate(2 * 4, 32)); + _ mov(Address(esp, 4), eax); + } + + // ======= Jump to UnifiedInterface Bridge Handle ======= + + // prepare args + _ sub(esp, Immediate(2 * 4, 32)); + _ mov(eax, Address(esp, 8 * 4 + 2 * 4 + 2 * 4 + 2 * 4)); + _ mov(Address(esp, 4), eax); + _ mov(eax, esp); + _ add(eax, Immediate(2 * 4, 32)); + _ mov(Address(esp, 0), eax); + + // LABEL: call_bridge + _ CallFunction(ExternalReference((void *)common_closure_bridge_handler)); + + // ======= DobbyRegisterContext Restore ======= + + // restore argument reserved stack + _ add(esp, Immediate(2 * 4, 32)); + + // restore sp placeholder stack + _ add(esp, Immediate(2 * 4, 32)); + + _ add(esp, Immediate(4, 32)); + // restore flags register + __ EmitBuffer(popfd, 1); + + // general register + _ pop(eax); + _ pop(ebx); + _ pop(ecx); + _ pop(edx); + _ pop(ebp); + _ add(esp, Immediate(4, 32)); // => pop rsp + _ pop(edi); + _ pop(esi); + + // trick: use the 'carry_data' stack(remain at closure trampoline) placeholder, as the return address + _ ret(); + + _ RelocBind(); + + auto code = AssemblyCodeBuilder::FinalizeFromTurboAssembler(&turbo_assembler_); + closure_bridge = (asm_func_t)code->addr; + + DEBUG_LOG("[closure bridge] closure bridge at %p", closure_bridge); +#endif + return closure_bridge; +} + +#endif \ No newline at end of file diff --git a/app/src/main/cpp/Dobby/source/TrampolineBridge/ClosureTrampolineBridge/x86/helper_x86.cc b/app/src/main/cpp/Dobby/source/TrampolineBridge/ClosureTrampolineBridge/x86/helper_x86.cc new file mode 100644 index 0000000..3dac41c --- /dev/null +++ b/app/src/main/cpp/Dobby/source/TrampolineBridge/ClosureTrampolineBridge/x86/helper_x86.cc @@ -0,0 +1,16 @@ +#include "platform_detect_macro.h" +#if defined(TARGET_ARCH_IA32) + +#include "dobby/dobby_internal.h" + +void set_routing_bridge_next_hop(DobbyRegisterContext *ctx, void *address) { + addr_t esp = ctx->esp; + + addr_t entry_placeholder_stack_addr = esp - 4; + *(addr_t *)entry_placeholder_stack_addr = (addr_t)address; +} + +void get_routing_bridge_next_hop(DobbyRegisterContext *ctx, void *address) { +} + +#endif \ No newline at end of file diff --git a/app/src/main/cpp/Dobby/source/TrampolineBridge/Trampoline/Trampoline.h b/app/src/main/cpp/Dobby/source/TrampolineBridge/Trampoline/Trampoline.h new file mode 100644 index 0000000..53f3779 --- /dev/null +++ b/app/src/main/cpp/Dobby/source/TrampolineBridge/Trampoline/Trampoline.h @@ -0,0 +1,5 @@ +#pragma once + +#include "MemoryAllocator/AssemblyCodeBuilder.h" + +CodeBufferBase *GenerateNormalTrampolineBuffer(addr_t from, addr_t to); \ No newline at end of file diff --git a/app/src/main/cpp/Dobby/source/TrampolineBridge/Trampoline/arm/trampoline_arm.cc b/app/src/main/cpp/Dobby/source/TrampolineBridge/Trampoline/arm/trampoline_arm.cc new file mode 100644 index 0000000..c8c9033 --- /dev/null +++ b/app/src/main/cpp/Dobby/source/TrampolineBridge/Trampoline/arm/trampoline_arm.cc @@ -0,0 +1,62 @@ +#include "platform_detect_macro.h" + +#if defined(TARGET_ARCH_ARM) + +#include "dobby/dobby_internal.h" + +#include "core/assembler/assembler-arm.h" +#include "core/codegen/codegen-arm.h" + +#include "InstructionRelocation/arm/InstructionRelocationARM.h" +#include "MemoryAllocator/NearMemoryAllocator.h" +#include "InterceptRouting/RoutingPlugin/RoutingPlugin.h" + +using namespace zz::arm; + +static CodeBufferBase *generate_arm_trampoline(addr32_t from, addr32_t to) { + TurboAssembler turbo_assembler_((void *)from); +#define _ turbo_assembler_. + + CodeGen codegen(&turbo_assembler_); + codegen.LiteralLdrBranch(to); + + return turbo_assembler_.GetCodeBuffer()->Copy(); +} + +CodeBufferBase *generate_thumb_trampoline(addr32_t from, addr32_t to) { + ThumbTurboAssembler thumb_turbo_assembler_((void *)from); +#undef _ +#define _ thumb_turbo_assembler_. + + _ AlignThumbNop(); + _ t2_ldr(pc, MemOperand(pc, 0)); + _ EmitAddress(to); + + return thumb_turbo_assembler_.GetCodeBuffer()->Copy(); +} + +CodeBufferBase *GenerateNormalTrampolineBuffer(addr_t from, addr_t to) { + enum ExecuteState { ARMExecuteState, ThumbExecuteState }; + + // set instruction running state + ExecuteState execute_state_; + execute_state_ = ARMExecuteState; + if ((addr_t)from % 2) { + execute_state_ = ThumbExecuteState; + } + + if (execute_state_ == ARMExecuteState) { + return generate_arm_trampoline(from, to); + } else { + // Check if needed pc align, (relative pc instructions needed 4 align) + from = from - THUMB_ADDRESS_FLAG; + return generate_thumb_trampoline(from, to); + } + return NULL; +} + +CodeBufferBase *GenerateNearTrampolineBuffer(InterceptRouting *routing, addr_t src, addr_t dst) { + return NULL; +} + +#endif \ No newline at end of file diff --git a/app/src/main/cpp/Dobby/source/TrampolineBridge/Trampoline/arm64/trampoline_arm64.cc b/app/src/main/cpp/Dobby/source/TrampolineBridge/Trampoline/arm64/trampoline_arm64.cc new file mode 100644 index 0000000..66eb63c --- /dev/null +++ b/app/src/main/cpp/Dobby/source/TrampolineBridge/Trampoline/arm64/trampoline_arm64.cc @@ -0,0 +1,41 @@ +#include "platform_detect_macro.h" +#if defined(TARGET_ARCH_ARM64) + +#include "dobby/dobby_internal.h" + +#include "core/assembler/assembler-arm64.h" +#include "core/codegen/codegen-arm64.h" + +#include "MemoryAllocator/NearMemoryAllocator.h" +#include "InstructionRelocation/arm64/InstructionRelocationARM64.h" +#include "InterceptRouting/RoutingPlugin/RoutingPlugin.h" + +using namespace zz::arm64; + +CodeBufferBase *GenerateNormalTrampolineBuffer(addr_t from, addr_t to) { + TurboAssembler turbo_assembler_((void *)from); +#define _ turbo_assembler_. + + uint64_t distance = llabs((int64_t)(from - to)); + uint64_t adrp_range = ((uint64_t)1 << (2 + 19 + 12 - 1)); + if (distance < adrp_range) { + // adrp, add, br + _ AdrpAdd(TMP_REG_0, from, to); + _ br(TMP_REG_0); + DEBUG_LOG("[trampoline] use [adrp, add, br]"); + } else { + // ldr, br, branch-address + CodeGen codegen(&turbo_assembler_); + codegen.LiteralLdrBranch((uint64_t)to); + DEBUG_LOG("[trampoline] use [ldr, br, #label]"); + } +#undef _ + + // Bind all labels + turbo_assembler_.RelocBind(); + + auto result = turbo_assembler_.GetCodeBuffer()->Copy(); + return result; +} + +#endif diff --git a/app/src/main/cpp/Dobby/source/TrampolineBridge/Trampoline/x64/trampoline_x64.cc b/app/src/main/cpp/Dobby/source/TrampolineBridge/Trampoline/x64/trampoline_x64.cc new file mode 100644 index 0000000..53afd43 --- /dev/null +++ b/app/src/main/cpp/Dobby/source/TrampolineBridge/Trampoline/x64/trampoline_x64.cc @@ -0,0 +1,54 @@ +#include "platform_detect_macro.h" + +#if defined(TARGET_ARCH_X64) + +#include "dobby/dobby_internal.h" + +#include "core/assembler/assembler-x64.h" +#include "core/codegen/codegen-x64.h" + +#include "InstructionRelocation/x64/InstructionRelocationX64.h" + +#include "MemoryAllocator/NearMemoryAllocator.h" +#include "InterceptRouting/RoutingPlugin/RoutingPlugin.h" + +using namespace zz::x64; + +static addr_t allocate_indirect_stub(addr_t jmp_insn_addr) { + uint32_t jmp_near_range = (uint32_t)2 * 1024 * 1024 * 1024; + auto stub_addr = (addr_t)NearMemoryAllocator::SharedAllocator()->allocateNearDataMemory(sizeof(void *), jmp_insn_addr, + jmp_near_range); + if (stub_addr == 0) { + ERROR_LOG("Not found near forward stub"); + return 0; + } + + DEBUG_LOG("forward stub: %p", stub_addr); + return stub_addr; +} + +CodeBufferBase *GenerateNormalTrampolineBuffer(addr_t from, addr_t to) { + TurboAssembler turbo_assembler_((void *)from); +#define _ turbo_assembler_. + + // allocate forward stub + auto jump_near_next_insn_addr = from + 6; + addr_t forward_stub = allocate_indirect_stub(jump_near_next_insn_addr); + if (forward_stub == 0) + return nullptr; + + *(addr_t *)forward_stub = to; + + CodeGen codegen(&turbo_assembler_); + codegen.JmpNearIndirect((addr_t)forward_stub); + + auto buffer = turbo_assembler_.GetCodeBuffer()->Copy(); + return buffer; +} + +CodeBufferBase *GenerateNearTrampolineBuffer(InterceptRouting *routing, addr_t src, addr_t dst) { + DEBUG_LOG("x64 near branch trampoline enable default"); + return nullptr; +} + +#endif \ No newline at end of file diff --git a/app/src/main/cpp/Dobby/source/TrampolineBridge/Trampoline/x86/trampoline_x86.cc b/app/src/main/cpp/Dobby/source/TrampolineBridge/Trampoline/x86/trampoline_x86.cc new file mode 100644 index 0000000..50b4641 --- /dev/null +++ b/app/src/main/cpp/Dobby/source/TrampolineBridge/Trampoline/x86/trampoline_x86.cc @@ -0,0 +1,33 @@ +#include "platform_detect_macro.h" +#if defined(TARGET_ARCH_IA32) + +#include "dobby/dobby_internal.h" + +#include "core/assembler/assembler-ia32.h" +#include "core/codegen/codegen-ia32.h" + +#include "InstructionRelocation/x86/InstructionRelocationX86.h" + +#include "MemoryAllocator/NearMemoryAllocator.h" +#include "InterceptRouting/RoutingPlugin/RoutingPlugin.h" + +using namespace zz::x86; + +CodeBufferBase *GenerateNormalTrampolineBuffer(addr_t from, addr_t to) { + TurboAssembler turbo_assembler_((void *)from); +#define _ turbo_assembler_. + + CodeGen codegen(&turbo_assembler_); + codegen.JmpNear((uint32_t)to); + + CodeBufferBase *result = NULL; + result = turbo_assembler_.GetCodeBuffer()->Copy(); + return result; +} + +CodeBufferBase *GenerateNearTrampolineBuffer(InterceptRouting *routing, addr_t src, addr_t dst) { + DEBUG_LOG("x86 near branch trampoline enable default"); + return NULL; +} + +#endif \ No newline at end of file diff --git a/app/src/main/cpp/Dobby/source/core/arch/Cpu.cc b/app/src/main/cpp/Dobby/source/core/arch/Cpu.cc new file mode 100644 index 0000000..0716361 --- /dev/null +++ b/app/src/main/cpp/Dobby/source/core/arch/Cpu.cc @@ -0,0 +1,5 @@ + +#include "core/arch/Cpu.h" +#include "core/arch/CpuUtils.h" + +#include "xnucxx/LiteMemOpt.h" diff --git a/app/src/main/cpp/Dobby/source/core/arch/Cpu.h b/app/src/main/cpp/Dobby/source/core/arch/Cpu.h new file mode 100644 index 0000000..e0361a7 --- /dev/null +++ b/app/src/main/cpp/Dobby/source/core/arch/Cpu.h @@ -0,0 +1,7 @@ +#ifndef CORE_ARCH_CPU_H +#define CORE_ARCH_CPU_H + +#include "CpuRegister.h" +#include "CpuFeature.h" + +#endif diff --git a/app/src/main/cpp/Dobby/source/core/arch/CpuFeature.cc b/app/src/main/cpp/Dobby/source/core/arch/CpuFeature.cc new file mode 100644 index 0000000..d29f176 --- /dev/null +++ b/app/src/main/cpp/Dobby/source/core/arch/CpuFeature.cc @@ -0,0 +1,7 @@ + +#include "core/arch/CpuFeature.h" +#include "logging/logging.h" + +void CpuFeatures::ClearCache(void *start, void *end) { + UNIMPLEMENTED(); +} \ No newline at end of file diff --git a/app/src/main/cpp/Dobby/source/core/arch/CpuFeature.h b/app/src/main/cpp/Dobby/source/core/arch/CpuFeature.h new file mode 100644 index 0000000..adb50ae --- /dev/null +++ b/app/src/main/cpp/Dobby/source/core/arch/CpuFeature.h @@ -0,0 +1,19 @@ +#ifndef CORE_ARCH_CPU_FEATURE_H +#define CORE_ARCH_CPU_FEATURE_H + +#include "dobby/common.h" + +class CpuFeatures { +private: + static void FlushICache(void *start, size_t size) { + ClearCache(start, (void *)((addr_t)start + size)); + } + + static void FlushICache(void *start, void *end) { + ClearCache(start, end); + } + + static void ClearCache(void *start, void *end); +}; + +#endif diff --git a/app/src/main/cpp/Dobby/source/core/arch/CpuRegister.cc b/app/src/main/cpp/Dobby/source/core/arch/CpuRegister.cc new file mode 100644 index 0000000..3617e4e --- /dev/null +++ b/app/src/main/cpp/Dobby/source/core/arch/CpuRegister.cc @@ -0,0 +1,10 @@ + +#include "CpuRegister.h" + +constexpr RegisterBase RegisterBase::from_code(int code) { + return RegisterBase{code}; +} + +constexpr RegisterBase RegisterBase::no_reg() { + return RegisterBase{0}; +} \ No newline at end of file diff --git a/app/src/main/cpp/Dobby/source/core/arch/CpuRegister.h b/app/src/main/cpp/Dobby/source/core/arch/CpuRegister.h new file mode 100644 index 0000000..e12aff4 --- /dev/null +++ b/app/src/main/cpp/Dobby/source/core/arch/CpuRegister.h @@ -0,0 +1,25 @@ +#ifndef CORE_ARCH_CPU_REGISTER_H +#define CORE_ARCH_CPU_REGISTER_H + +class RegisterBase { +public: + static constexpr RegisterBase from_code(int code); + + static constexpr RegisterBase no_reg(); + + virtual bool Is(const RegisterBase ®) const { + return (reg.reg_code_ == this->reg_code_); + } + + int code() const { + return reg_code_; + }; + +protected: + explicit constexpr RegisterBase(int code) : reg_code_(code) { + } + + int reg_code_; +}; + +#endif diff --git a/app/src/main/cpp/Dobby/source/core/arch/CpuUtils.h b/app/src/main/cpp/Dobby/source/core/arch/CpuUtils.h new file mode 100644 index 0000000..3942363 --- /dev/null +++ b/app/src/main/cpp/Dobby/source/core/arch/CpuUtils.h @@ -0,0 +1,17 @@ +#ifndef CPU_UTILITY_H +#define CPU_UTILITY_H + +/* Define the default attributes for the functions in this file. */ +#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__)) + +#if defined(__i386__) || defined(__x86_64__) +static __inline__ void __DEFAULT_FN_ATTRS __cpuid(int __info[4], int __level) { + __asm__("cpuid" : "=a"(__info[0]), "=b"(__info[1]), "=c"(__info[2]), "=d"(__info[3]) : "a"(__level)); +} + +static __inline__ void __DEFAULT_FN_ATTRS __cpuidex(int __info[4], int __level, int __ecx) { + __asm__("cpuid" : "=a"(__info[0]), "=b"(__info[1]), "=c"(__info[2]), "=d"(__info[3]) : "a"(__level), "c"(__ecx)); +} +#endif + +#endif diff --git a/app/src/main/cpp/Dobby/source/core/arch/arm/constants-arm.h b/app/src/main/cpp/Dobby/source/core/arch/arm/constants-arm.h new file mode 100644 index 0000000..b326d34 --- /dev/null +++ b/app/src/main/cpp/Dobby/source/core/arch/arm/constants-arm.h @@ -0,0 +1,70 @@ +#ifndef CORE_ARCH_CONSTANTS_ARM_H +#define CORE_ARCH_CONSTANTS_ARM_H + +enum AddrMode { Offset = 0, PreIndex = 1, PostIndex = 2 }; + +enum Condition { + EQ = 0, // equal + NE = 1, // not equal + CS = 2, // carry set/unsigned higher or same + CC = 3, // carry clear/unsigned lower + MI = 4, // minus/negative + PL = 5, // plus/positive or zero + VS = 6, // overflow + VC = 7, // no overflow + HI = 8, // unsigned higher + LS = 9, // unsigned lower or same + GE = 10, // signed greater than or equal + LT = 11, // signed less than + GT = 12, // signed greater than + LE = 13, // signed less than or equal + AL = 14, // always (unconditional) + +}; + +enum Shift { + LSL = 0, // Logical shift left + LSR = 1, // Logical shift right + ASR = 2, // Arithmetic shift right + ROR = 3, // Rotate right +}; + +enum { + B0 = 1 << 0, + B4 = 1 << 4, + B5 = 1 << 5, + B6 = 1 << 6, + B7 = 1 << 7, + B8 = 1 << 8, + B9 = 1 << 9, + B10 = 1 << 10, + B12 = 1 << 12, + B14 = 1 << 14, + B15 = 1 << 15, + B16 = 1 << 16, + B17 = 1 << 17, + B18 = 1 << 18, + B19 = 1 << 19, + B20 = 1 << 20, + B21 = 1 << 21, + B22 = 1 << 22, + B23 = 1 << 23, + B24 = 1 << 24, + B25 = 1 << 25, + B26 = 1 << 26, + B27 = 1 << 27, + B28 = 1 << 28, +}; + +enum InstructionFields { + // Registers. + kRdShift = 12, + kRtShift = 12, + kRmShift = 10, + kRnShift = 16, + + // Condition + kConditionShift = 28, +}; + +#endif \ No newline at end of file diff --git a/app/src/main/cpp/Dobby/source/core/arch/arm/registers-arm.h b/app/src/main/cpp/Dobby/source/core/arch/arm/registers-arm.h new file mode 100644 index 0000000..88b7c2e --- /dev/null +++ b/app/src/main/cpp/Dobby/source/core/arch/arm/registers-arm.h @@ -0,0 +1,58 @@ +#ifndef ARCH_ARM_REGISTERS +#define ARCH_ARM_REGISTERS + +#include "core/arch/arm/constants-arm.h" +#include "core/arch/Cpu.h" + +namespace zz { +namespace arm { + +#define GENERAL_REGISTERS(V) \ + V(r0) V(r1) V(r2) V(r3) V(r4) V(r5) V(r6) V(r7) V(r8) V(r9) V(r10) V(r11) V(r12) V(sp) V(lr) V(pc) + +enum RegisterCode { +#define REGISTER_CODE(R) kRegCode_##R, + GENERAL_REGISTERS(REGISTER_CODE) +#undef REGISTER_CODE + kRegAfterLast +}; + +class Register : public RegisterBase { +public: + explicit constexpr Register(int code) : RegisterBase(code) { + } + + static constexpr Register Create(int code) { + return Register(code); + } + + static constexpr Register R(int code) { + return Register(code); + } + + bool Is(const Register ®) const { + return (reg.reg_code_ == this->reg_code_); + } + + bool IsValid() const { + return (reg_code_ != 0); + } + + int code() const { + return reg_code_; + } + +private: +}; + +typedef Register CPURegister; + +#define DECLARE_REGISTER(R) constexpr Register R = Register::Create(kRegCode_##R); +GENERAL_REGISTERS(DECLARE_REGISTER) +#undef DECLARE_REGISTER + +constexpr Register no_reg = Register::Create(0); + +} // namespace arm +} // namespace zz +#endif \ No newline at end of file diff --git a/app/src/main/cpp/Dobby/source/core/arch/arm64/constants-arm64.h b/app/src/main/cpp/Dobby/source/core/arch/arm64/constants-arm64.h new file mode 100644 index 0000000..e72a6ed --- /dev/null +++ b/app/src/main/cpp/Dobby/source/core/arch/arm64/constants-arm64.h @@ -0,0 +1,387 @@ +#ifndef CORE_ARCH_CONSTANTS_ARM64_H +#define CORE_ARCH_CONSTANTS_ARM64_H + +#include "dobby/common.h" + +enum Shift { NO_SHIFT = -1, LSL = 0x0, LSR = 0x1, ASR = 0x2, ROR = 0x3, MSL = 0x4 }; + +enum Extend { NO_EXTEND = -1, UXTB = 0, UXTH = 1, UXTW = 2, UXTX = 3, SXTB = 4, SXTH = 5, SXTW = 6, SXTX = 7 }; + +enum AddrMode { Offset, PreIndex, PostIndex }; + +enum FlagsUpdate { SetFlags = 1, LeaveFlags = 0 }; + +enum InstructionFields { + + // Registers. + kRdShift = 0, + kRdBits = 5, + kRnShift = 5, + kRnBits = 5, + kRaShift = 10, + kRaBits = 5, + kRmShift = 16, + kRmBits = 5, + kRtShift = 0, + kRtBits = 5, + kRt2Shift = 10, + kRt2Bits = 5, + kRsShift = 16, + kRsBits = 5, + +}; + +#define OP(op) op +#define OP_W(op) op##_w +#define OP_X(op) op##_x +#define OP_B(op) op##_b +#define OP_H(op) op##_h +#define OP_S(op) op##_s +#define OP_D(op) op##_d +#define OP_Q(op) op##_q + +#define OPT(op, attribute) op##_##attribute +#define OPT_W(op, attribute) op##_w_##attribute +#define OPT_X(op, attribute) op##_x_##attribute +#define OPT_B(op, attribute) op##_b_##attribute +#define OPT_H(op, attribute) op##_h_##attribute +#define OPT_S(op, attribute) op##_s_##attribute +#define OPT_D(op, attribute) op##_d_##attribute +#define OPT_Q(op, attribute) op##_q_##attribute + +// ===== + +// Exception. +enum ExceptionOp { + ExceptionFixed = 0xD4000000, + ExceptionFMask = 0xFF000000, + ExceptionMask = 0xFFE0001F, + + HLT = ExceptionFixed | 0x00400000, + BRK = ExceptionFixed | 0x00200000, + SVC = ExceptionFixed | 0x00000001, + HVC = ExceptionFixed | 0x00000002, + SMC = ExceptionFixed | 0x00000003, + DCPS1 = ExceptionFixed | 0x00A00001, + DCPS2 = ExceptionFixed | 0x00A00002, + DCPS3 = ExceptionFixed | 0x00A00003 +}; + +// ===== + +// Unconditional branch. +enum UnconditionalBranchOp { + UnconditionalBranchFixed = 0x14000000, + UnconditionalBranchFixedMask = 0x7C000000, + UnconditionalBranchMask = 0xFC000000, + + B = UnconditionalBranchFixed | 0x00000000, + BL = UnconditionalBranchFixed | 0x80000000 +}; + +// ===== + +// Unconditional branch to register. +enum UnconditionalBranchToRegisterOp { + UnconditionalBranchToRegisterFixed = 0xD6000000, + UnconditionalBranchToRegisterFixedMask = 0xFE000000, + UnconditionalBranchToRegisterMask = 0xFFFFFC1F, + + BR = UnconditionalBranchToRegisterFixed | 0x001F0000, + BLR = UnconditionalBranchToRegisterFixed | 0x003F0000, + RET = UnconditionalBranchToRegisterFixed | 0x005F0000 +}; + +// ===== + +enum LoadRegLiteralOp { + LoadRegLiteralFixed = 0x18000000, + LoadRegLiteralFixedMask = 0x3B000000, + LoadRegLiteralMask = 0xFF000000, + +#define LoadRegLiteralSub(opc, V) LoadRegLiteralFixed | LeftShift(opc, 2, 30) | LeftShift(V, 1, 26) + OPT_W(LDR, literal) = LoadRegLiteralSub(0b00, 0), + OPT_X(LDR, literal) = LoadRegLiteralSub(0b01, 0), + OPT(LDRSW, literal) = LoadRegLiteralSub(0b10, 0), + OPT(PRFM, literal) = LoadRegLiteralSub(0b11, 0), + OPT_S(LDR, literal) = LoadRegLiteralSub(0b00, 1), + OPT_D(LDR, literal) = LoadRegLiteralSub(0b01, 1), + OPT_Q(LDR, literal) = LoadRegLiteralSub(0b10, 1), +}; + +// ===== + +// clang-format off +#define LOAD_STORE_OP_LIST(V) \ + V(OP_W(STRB), 0b00, 0, 0b00), \ + V(OP_W(LDRB), 0b00, 0, 0b01), \ + V(OP_X(LDRSB), 0b00, 0, 0b10), \ + V(OP_W(LDRSB), 0b00, 0, 0b11), \ + V(OP_B(STR), 0b00, 1, 0b00), \ + V(OP_B(LDR), 0b00, 1, 0b01), \ + V(OP_Q(STR), 0b00, 1, 0b10), \ + V(OP_Q(LDR), 0b00, 1, 0b11), \ + V(OP_W(STRH), 0b01, 0, 0b00), \ + V(OP_W(LDRH), 0b01, 0, 0b01), \ + V(OP_X(LDRSH), 0b01, 0, 0b10), \ + V(OP_W(LDRSH), 0b01, 0, 0b11), \ + V(OP_H(STR), 0b01, 1, 0b00), \ + V(OP_H(LDR), 0b01, 1, 0b01), \ + V(OP_W(STR), 0b10, 0, 0b00), \ + V(OP_W(LDR), 0b10, 0, 0b01), \ + V(OP(LDRSW), 0b10, 0, 0b10), \ + V(OP_S(STR), 0b10, 1, 0b00), \ + V(OP_S(LDR), 0b10, 1, 0b01), \ + V(OP_X(STR), 0b11, 0, 0b00), \ + V(OP_X(LDR), 0b11, 0, 0b01), \ + V(OP(PRFM), 0b11, 0, 0b10), \ + V(OP_D(STR), 0b11, 1, 0b00), \ + V(OP_D(LDR), 0b11, 1, 0b01), +// clang-format on + +// Load/store +enum LoadStoreOp { +#define LoadStoreOpSub(size, V, opc) LeftShift(size, 2, 30) | LeftShift(V, 1, 26) | LeftShift(opc, 2, 22) +#define LOAD_STORE(opname, size, V, opc) OP(opname) = LoadStoreOpSub(size, V, opc) + LOAD_STORE_OP_LIST(LOAD_STORE) +#undef LOAD_STORE +}; + +// Load/store register offset. +enum LoadStoreRegisterOffsetOp { + LoadStoreRegisterOffsetFixed = 0x38200800, + LoadStoreRegisterOffsetFixedMask = 0x3B200C00, + LoadStoreRegisterOffsetMask = 0xFFE00C00, + +#define LoadStoreRegisterOffsetOpSub(size, V, opc) \ + LoadStoreRegisterOffsetFixed | LeftShift(size, 2, 30) | LeftShift(V, 1, 26) | LeftShift(opc, 2, 22) +#define LOAD_STORE_REGISTER_OFFSET(opname, size, V, opc) \ + OPT(opname, register) = LoadStoreRegisterOffsetOpSub(size, V, opc) + LOAD_STORE_OP_LIST(LOAD_STORE_REGISTER_OFFSET) +#undef LOAD_STORE_REGISTER_OFFSET +}; + +// Load/store register (unscaled immediate) +enum LoadStoreUnscaledOffsetOp { + LoadStoreUnscaledOffsetFixed = 0x38000000, + LoadStoreUnscaledOffsetFixedMask = 0x3B200C00, + LoadStoreUnscaledOffsetMask = 0xFFE00C00, + +#define LoadStoreUnscaledOffsetOpSub(size, V, opc) \ + LoadStoreUnscaledOffsetFixed | LeftShift(size, 2, 30) | LeftShift(V, 1, 26) | LeftShift(opc, 2, 22) +#define LOAD_STORE_UNSCALED(opname, size, V, opc) OPT(opname, unscaled) = LoadStoreUnscaledOffsetOpSub(size, V, opc) + LOAD_STORE_OP_LIST(LOAD_STORE_UNSCALED) +#undef LOAD_STORE_UNSCALED +}; + +// Load/store unsigned offset. +enum LoadStoreUnsignedOffset { + LoadStoreUnsignedOffsetFixed = 0x39000000, + LoadStoreUnsignedOffsetFixedMask = 0x3B000000, + LoadStoreUnsignedOffsetMask = 0xFFC00000, + +#define LoadStoreUnsignedOffsetSub(size, V, opc) \ + LoadStoreUnsignedOffsetFixed | LeftShift(size, 2, 30) | LeftShift(V, 1, 26) | LeftShift(opc, 2, 22) +#define LOAD_STORE_UNSIGNED_OFFSET(opname, size, V, opc) \ + OPT(opname, unsigned) = LoadStoreUnsignedOffsetSub(size, V, opc) + LOAD_STORE_OP_LIST(LOAD_STORE_UNSIGNED_OFFSET) +#undef LOAD_STORE_UNSIGNED_OFFSET +}; + +// ===== + +// clang-format off +#define LOAD_STORE_PAIR_OP_LIST(V) \ + V(OP_W(STP), 0b00, 0, 0), \ + V(OP_W(LDP), 0b00, 0, 1), \ + V(OP_S(STP), 0b00, 1, 0), \ + V(OP_S(LDP), 0b00, 1, 1), \ + V(OP(LDPSW), 0b01, 0, 1), \ + V(OP_D(STP), 0b01, 1, 0), \ + V(OP_D(LDP), 0b01, 1, 1), \ + V(OP_X(STP), 0b10, 0, 0), \ + V(OP_X(LDP), 0b10, 0, 1), \ + V(OP_Q(STP), 0b10, 1, 0), \ + V(OP_Q(LDP), 0b10, 1, 1) +// clang-format on + +enum LoadStorePairOp { +#define LoadStorePairOpSub(opc, V, L) LeftShift(opc, 2, 30) | LeftShift(V, 1, 26) | LeftShift(L, 1, 22) +#define LOAD_STORE_PAIR(opname, opc, V, L) OP(opname) = LoadStorePairOpSub(opc, V, L) + LOAD_STORE_PAIR_OP_LIST(LOAD_STORE_PAIR) +#undef LOAD_STORE_PAIR +}; + +enum LoadStorePairOffsetOp { + LoadStorePairOffsetFixed = 0x29000000, + LoadStorePairOffsetFixedMask = 0x3B800000, + LoadStorePairOffsetMask = 0xFFC00000, + +#define LoadStorePairOffsetOpSub(opc, V, L) \ + LoadStorePairOffsetFixed | LeftShift(opc, 2, 30) | LeftShift(V, 1, 26) | LeftShift(L, 1, 22) +#define LOAD_STORE_PAIR_OFFSET(opname, opc, V, L) OPT(opname, offset) = LoadStorePairOffsetOpSub(opc, V, L) + LOAD_STORE_PAIR_OP_LIST(LOAD_STORE_PAIR_OFFSET) +#undef LOAD_STORE_PAIR_OFFSET +}; + +enum LoadStorePairPostIndexOp { + LoadStorePairPostIndexFixed = 0x28800000, + LoadStorePairPostIndexFixedMask = 0x3B800000, + LoadStorePairPostIndexMask = 0xFFC00000, + +#define LoadStorePairPostOpSub(opc, V, L) \ + LoadStorePairPostIndexFixed | LeftShift(opc, 2, 30) | LeftShift(V, 1, 26) | LeftShift(L, 1, 22) +#define LOAD_STORE_PAIR_POST_INDEX(opname, opc, V, L) OPT(opname, post) = LoadStorePairPostOpSub(opc, V, L) + LOAD_STORE_PAIR_OP_LIST(LOAD_STORE_PAIR_POST_INDEX) +#undef LOAD_STORE_PAIR_POST_INDEX +}; + +enum LoadStorePairPreIndexOp { + LoadStorePairPreIndexFixed = 0x29800000, + LoadStorePairPreIndexFixedMask = 0x3B800000, + LoadStorePairPreIndexMask = 0xFFC00000, + +#define LoadStorePairPreOpSub(opc, V, L) \ + LoadStorePairPreIndexFixed | LeftShift(opc, 2, 30) | LeftShift(V, 1, 26) | LeftShift(L, 1, 22) +#define LOAD_STORE_PAIR_PRE_INDEX(opname, opc, V, L) OPT(opname, pre) = LoadStorePairPreOpSub(opc, V, L) + LOAD_STORE_PAIR_OP_LIST(LOAD_STORE_PAIR_PRE_INDEX) +#undef LOAD_STORE_PAIR_PRE_INDEX +}; + +// ===== + +// Generic fields. +enum GenericInstrField { SixtyFourBits = 0x80000000, ThirtyTwoBits = 0x00000000, FP32 = 0x00000000, FP64 = 0x00400000 }; + +// Generic utils +// #define sf(rd) (rd.Is64Bits() ? SixtyFourBits : ThirtyTwoBits) + +// ===== + +// Move wide immediate. +enum MoveWideImmediateOp { + MoveWideImmediateFixed = 0x12800000, + MoveWideImmediateFixedMask = 0x1F800000, + MoveWideImmediateMask = 0xFF800000, + + OP(MOVN) = 0x00000000, + OP(MOVZ) = 0x40000000, + OP(MOVK) = 0x60000000, + +#define MoveWideImmediateOpSub(sf, opc) MoveWideImmediateFixed | LeftShift(sf, 1, 31) | LeftShift(opc, 2, 29) + OP_W(MOVN) = MoveWideImmediateFixed | MOVN, + OP_X(MOVN) = MoveWideImmediateFixed | MOVN | SixtyFourBits, + OP_W(MOVZ) = MoveWideImmediateFixed | MOVZ, + OP_X(MOVZ) = MoveWideImmediateFixed | MOVZ | SixtyFourBits, + OP_W(MOVK) = MoveWideImmediateFixed | MOVK, + OP_X(MOVK) = MoveWideImmediateFixed | MOVK | SixtyFourBits +}; + +// ===== + +enum AddSubImmediateOp { + AddSubImmediateFixed = 0x11000000, + AddSubImmediateFixedMask = 0x1F000000, + AddSubImmediateMask = 0xFF000000, + +#define AddSubImmediateOpSub(sf, op, S) \ + AddSubImmediateFixed | LeftShift(sf, 1, 31) | LeftShift(op, 1, 30) | LeftShift(S, 1, 29) + OPT_W(ADD, imm) = AddSubImmediateOpSub(0, 0, 0), + OPT_W(ADDS, imm) = AddSubImmediateOpSub(0, 0, 1), + OPT_W(SUB, imm) = AddSubImmediateOpSub(0, 1, 0), + OPT_W(SUBS, imm) = AddSubImmediateOpSub(0, 1, 1), + OPT_X(ADD, imm) = AddSubImmediateOpSub(1, 0, 0), + OPT_X(ADDS, imm) = AddSubImmediateOpSub(1, 0, 1), + OPT_X(SUB, imm) = AddSubImmediateOpSub(1, 1, 0), + OPT_X(SUBS, imm) = AddSubImmediateOpSub(1, 1, 1) +}; + +enum AddSubShiftedOp { + AddSubShiftedFixed = 0x0B000000, + AddSubShiftedFixedMask = 0x1F200000, + AddSubShiftedMask = 0xFF200000, + +#define AddSubShiftedOpSub(sf, op, S) \ + AddSubShiftedFixed | LeftShift(sf, 1, 31) | LeftShift(op, 1, 30) | LeftShift(S, 1, 29) + OPT_W(ADD, shift) = AddSubShiftedOpSub(0, 0, 0), + OPT_W(ADDS, shift) = AddSubShiftedOpSub(0, 0, 1), + OPT_W(SUB, shift) = AddSubShiftedOpSub(0, 1, 0), + OPT_W(SUBS, shift) = AddSubShiftedOpSub(0, 1, 1), + OPT_X(ADD, shift) = AddSubShiftedOpSub(1, 0, 0), + OPT_X(ADDS, shift) = AddSubShiftedOpSub(1, 0, 1), + OPT_X(SUB, shift) = AddSubShiftedOpSub(1, 1, 0), + OPT_X(SUBS, shift) = AddSubShiftedOpSub(1, 1, 1) +}; + +enum AddSubExtendedOp { + AddSubExtendedFixed = 0x0B200000, + AddSubExtendedFixedMask = 0x1F200000, + AddSubExtendedMask = 0xFFE00000, + +#define AddSubExtendedOpSub(sf, op, S) \ + AddSubExtendedFixed | LeftShift(sf, 1, 31) | LeftShift(op, 1, 30) | LeftShift(S, 1, 29) + OPT_W(ADD, extend) = AddSubExtendedOpSub(0, 0, 0), + OPT_W(ADDS, extend) = AddSubExtendedOpSub(0, 0, 1), + OPT_W(SUB, extend) = AddSubExtendedOpSub(0, 1, 0), + OPT_W(SUBS, extend) = AddSubExtendedOpSub(0, 1, 1), + OPT_X(ADD, extend) = AddSubExtendedOpSub(1, 0, 0), + OPT_X(ADDS, extend) = AddSubExtendedOpSub(1, 0, 1), + OPT_X(SUB, extend) = AddSubExtendedOpSub(1, 1, 0), + OPT_X(SUBS, extend) = AddSubExtendedOpSub(1, 1, 1) +}; + +// ===== + +// Logical (immediate and shifted register). +enum LogicalOp { + LogicalOpMask = 0x60200000, + NOT = 0x00200000, + AND = 0x00000000, + BIC = AND | NOT, + ORR = 0x20000000, + ORN = ORR | NOT, + EOR = 0x40000000, + EON = EOR | NOT, + ANDS = 0x60000000, + BICS = ANDS | NOT +}; + +// Logical immediate. +enum LogicalImmediateOp { + LogicalImmediateFixed = 0x12000000, + LogicalImmediateFixedMask = 0x1F800000, + LogicalImmediateMask = 0xFF800000, + +#define W_X_OP(opname, combine_fields) \ + OPT_W(opname, imm) = LogicalImmediateFixed | combine_fields | ThirtyTwoBits, \ + OPT_X(opname, imm) = LogicalImmediateFixed | combine_fields | SixtyFourBits +#define W_X_OP_LIST(V) V(AND, AND), V(ORR, ORR), V(EOR, EOR), V(ANDS, ANDS) +#undef W_X_OP +#undef W_X_OP_LIST +}; + +// Logical shifted register. +enum LogicalShiftedOp { + LogicalShiftedFixed = 0x0A000000, + LogicalShiftedFixedMask = 0x1F000000, + LogicalShiftedMask = 0xFF200000, + +#define W_X_OP(opname, combine_fields) \ + OPT_W(opname, shift) = LogicalShiftedFixed | combine_fields | ThirtyTwoBits, \ + OPT_X(opname, shift) = LogicalShiftedFixed | combine_fields | SixtyFourBits +#define W_X_OP_LIST(V) \ + V(AND, AND), V(BIC, BIC), V(ORR, ORR), V(ORN, ORN), V(EOR, EOR), V(EON, EON), V(ANDS, ANDS), V(BICS, BICS) +#undef W_X_OP +#undef W_X_OP_LIST +}; + +// PC relative addressing. +enum PCRelAddressingOp { + PCRelAddressingFixed = 0x10000000, + PCRelAddressingFixedMask = 0x1F000000, + PCRelAddressingMask = 0x9F000000, + ADR = PCRelAddressingFixed | 0x00000000, + ADRP = PCRelAddressingFixed | 0x80000000 +}; + +#endif diff --git a/app/src/main/cpp/Dobby/source/core/arch/arm64/registers-arm64.h b/app/src/main/cpp/Dobby/source/core/arch/arm64/registers-arm64.h new file mode 100644 index 0000000..84a6d6b --- /dev/null +++ b/app/src/main/cpp/Dobby/source/core/arch/arm64/registers-arm64.h @@ -0,0 +1,142 @@ +#ifndef ARCH_ARM64_REGISTERS +#define ARCH_ARM64_REGISTERS + +#include "core/arch/arm64/constants-arm64.h" +#include "core/arch/Cpu.h" + +namespace zz { +namespace arm64 { + +class CPURegister : RegisterBase { +public: + enum RegisterType { + kRegister_32, + kRegister_W = kRegister_32, + kRegister_64, + kRegister_X = kRegister_64, + kRegister, + + kVRegister, + kSIMD_FP_Register_8, + kSIMD_FP_Register_B = kSIMD_FP_Register_8, + kSIMD_FP_Register_16, + kSIMD_FP_Register_H = kSIMD_FP_Register_16, + kSIMD_FP_Register_32, + kSIMD_FP_Register_S = kSIMD_FP_Register_32, + kSIMD_FP_Register_64, + kSIMD_FP_Register_D = kSIMD_FP_Register_64, + kSIMD_FP_Register_128, + kSIMD_FP_Register_Q = kSIMD_FP_Register_128, + + kInvalid + }; + + constexpr CPURegister(int code, int size, RegisterType type) : RegisterBase(code), reg_size_(size), reg_type_(type) { + } + + static constexpr CPURegister Create(int code, int size, RegisterType type) { + return CPURegister(code, size, type); + } + + // ===== + + static constexpr CPURegister X(int code) { + return CPURegister(code, 64, kRegister_64); + } + + static constexpr CPURegister W(int code) { + return CPURegister(code, 32, kRegister_32); + } + + static constexpr CPURegister Q(int code) { + return CPURegister(code, 128, kSIMD_FP_Register_128); + } + + static constexpr CPURegister InvalidRegister() { + return CPURegister(0, 0, kInvalid); + } + + // ===== + + bool Is(const CPURegister ®) const { + return (reg.reg_code_ == this->reg_code_); + } + + bool Is64Bits() const { + return reg_size_ == 64; + } + + bool IsRegister() const { + return reg_type_ < kRegister; + } + + bool IsVRegister() const { + return reg_type_ > kVRegister; + } + + // ===== + + RegisterType type() const { + return reg_type_; + } + + int32_t code() const { + return reg_code_; + }; + +private: + RegisterType reg_type_; + int reg_size_; +}; + +typedef CPURegister Register; +typedef CPURegister VRegister; + +// clang-format off +#define GENERAL_REGISTER_CODE_LIST(R) \ + R(0) R(1) R(2) R(3) R(4) R(5) R(6) R(7) \ + R(8) R(9) R(10) R(11) R(12) R(13) R(14) R(15) \ + R(16) R(17) R(18) R(19) R(20) R(21) R(22) R(23) \ + R(24) R(25) R(26) R(27) R(28) R(29) R(30) R(31) + +#define DEFINE_REGISTER(register_class, name, ...) constexpr register_class name = register_class::Create(__VA_ARGS__) + +#define DEFINE_REGISTERS(N) \ + DEFINE_REGISTER(Register, w##N, N, 32, CPURegister::kRegister_32); \ + DEFINE_REGISTER(Register, x##N, N, 64, CPURegister::kRegister_64); + GENERAL_REGISTER_CODE_LIST(DEFINE_REGISTERS) +#undef DEFINE_REGISTERS + +#define DEFINE_VREGISTERS(N) \ + DEFINE_REGISTER(VRegister, b##N, N, 8, CPURegister::kSIMD_FP_Register_8); \ + DEFINE_REGISTER(VRegister, h##N, N, 16, CPURegister::kSIMD_FP_Register_16); \ + DEFINE_REGISTER(VRegister, s##N, N, 32, CPURegister::kSIMD_FP_Register_32); \ + DEFINE_REGISTER(VRegister, d##N, N, 64, CPURegister::kSIMD_FP_Register_64); \ + DEFINE_REGISTER(VRegister, q##N, N, 128, CPURegister::kSIMD_FP_Register_128); \ +GENERAL_REGISTER_CODE_LIST(DEFINE_VREGISTERS) +#undef DEFINE_VREGISTERS + +#undef DEFINE_REGISTER +// clang-format on + +// ===== + +constexpr Register wzr = w31; +constexpr Register xzr = x31; + +constexpr Register SP = x31; +constexpr Register wSP = w31; +constexpr Register FP = x29; +constexpr Register wFP = w29; +constexpr Register LR = x30; +constexpr Register wLR = w30; + +} // namespace arm64 +} // namespace zz + +#define W(code) CPURegister::W(code) +#define X(code) CPURegister::X(code) +#define Q(code) CPURegister::Q(code) +#define InvalidRegister CPURegister::InvalidRegister() + +#endif diff --git a/app/src/main/cpp/Dobby/source/core/arch/x64/constants-x64.h b/app/src/main/cpp/Dobby/source/core/arch/x64/constants-x64.h new file mode 100644 index 0000000..d72f44f --- /dev/null +++ b/app/src/main/cpp/Dobby/source/core/arch/x64/constants-x64.h @@ -0,0 +1,21 @@ +#ifndef CORE_ARCH_CONSTANTS_X64_H +#define CORE_ARCH_CONSTANTS_X64_H + +namespace zz { +namespace x64 { + +enum ScaleFactor { + TIMES_1 = 0, + TIMES_2 = 1, + TIMES_4 = 2, + TIMES_8 = 3, + TIMES_16 = 4, + TIMES_HALF_WORD_SIZE = sizeof(void *) / 2 - 1 +}; + +enum RexBits { REX_NONE = 0, REX_B = 1 << 0, REX_X = 1 << 1, REX_R = 1 << 2, REX_W = 1 << 3, REX_PREFIX = 1 << 6 }; + +} // namespace x64 +} // namespace zz + +#endif \ No newline at end of file diff --git a/app/src/main/cpp/Dobby/source/core/arch/x64/registers-x64.h b/app/src/main/cpp/Dobby/source/core/arch/x64/registers-x64.h new file mode 100644 index 0000000..4c7c612 --- /dev/null +++ b/app/src/main/cpp/Dobby/source/core/arch/x64/registers-x64.h @@ -0,0 +1,244 @@ +#ifndef ARCH_X64_REGISTERS +#define ARCH_X64_REGISTERS + +#include "core/arch/x64/constants-x64.h" +#include "core/arch/Cpu.h" + +namespace zz { +namespace x64 { + +#define GENERAL_REGISTERS(V) \ + V(rax) \ + V(rcx) \ + V(rdx) \ + V(rbx) \ + V(rsp) \ + V(rbp) \ + V(rsi) \ + V(rdi) \ + V(r8) \ + V(r9) \ + V(r10) \ + V(r11) \ + V(r12) \ + V(r13) \ + V(r14) \ + V(r15) + +#define GENERAL_32_REGISTERS(V) \ + V(eax) \ + V(ecx) \ + V(edx) \ + V(ebx) \ + V(esp) \ + V(ebp) \ + V(esi) \ + V(edi) + +#define GENERAL_16_REGISTERS(V) \ + V(ax) \ + V(cx) \ + V(dx) \ + V(bx) \ + V(sp) \ + V(bp) \ + V(si) \ + V(di) + +#define GENERAL_8H_REGISTERS(V) \ + V(ah) \ + V(ch) \ + V(dh) \ + V(bh) + +#define GENERAL_8L_REGISTERS(V) \ + V(al) \ + V(cl) \ + V(dl) \ + V(bl) + +// clang-format off +enum RegisterCode { +#define REGISTER_CODE(R) kRegCode_##R, + kRegisterCodeStart8L = -1, + GENERAL_8L_REGISTERS(REGISTER_CODE) + kRegisterCodeStart8H = -1, + GENERAL_8H_REGISTERS(REGISTER_CODE) + kRegisterCodeStart16 = -1, + GENERAL_16_REGISTERS(REGISTER_CODE) + kRegisterCodeStart32 = -1, + GENERAL_32_REGISTERS(REGISTER_CODE) + kRegisterCodeStart64 = -1, + GENERAL_REGISTERS(REGISTER_CODE) +#undef REGISTER_CODE + kRegAfterLast +}; +// clang-format on + +class CPURegister : public RegisterBase { +public: + enum RegisterType { kDefault, kInvalid }; + + constexpr CPURegister(int code, int size, RegisterType type) : RegisterBase(code), reg_size_(size), reg_type_(type) { + } + + static constexpr CPURegister Create(int code, int size, RegisterType type) { + return CPURegister(code, size, type); + } + + static constexpr CPURegister from_code(int code) { + return CPURegister(code, 0, kDefault); + } + + static constexpr CPURegister InvalidRegister() { + return CPURegister(0, 0, kInvalid); + } + + bool Is64Bits() const { + return reg_size_ == 64; + } + + RegisterType type() const { + return reg_type_; + } + +public: + bool is_byte_register() const { + return reg_code_ <= 3; + } + + // Return the high bit of the register code as a 0 or 1. Used often + // when constructing the REX prefix byte. + int high_bit() const { + return reg_code_ >> 3; + } + + // Return the 3 low bits of the register code. Used when encoding registers + // in modR/M, SIB, and opcode bytes. + int low_bits() const { + return reg_code_ & 0x7; + } + + int size() { + return reg_size_; + } + +private: + RegisterType reg_type_; + int reg_size_; +}; + +typedef CPURegister Register; + +#define DECLARE_REGISTER(R) constexpr Register R = Register::Create(kRegCode_##R, 64, CPURegister::kDefault); +GENERAL_REGISTERS(DECLARE_REGISTER) +#undef DECLARE_REGISTER + +#define DECLARE_REGISTER(R) constexpr Register R = Register::Create(kRegCode_##R, 8, CPURegister::kDefault); +GENERAL_8H_REGISTERS(DECLARE_REGISTER) +#undef DECLARE_REGISTER + +#define DECLARE_REGISTER(R) constexpr Register R = Register::Create(kRegCode_##R, 8, CPURegister::kDefault); +GENERAL_8L_REGISTERS(DECLARE_REGISTER) +#undef DECLARE_REGISTER + +#define DECLARE_REGISTER(R) constexpr Register R = Register::Create(kRegCode_##R, 16, CPURegister::kDefault); +GENERAL_16_REGISTERS(DECLARE_REGISTER) +#undef DECLARE_REGISTER + +#define DECLARE_REGISTER(R) constexpr Register R = Register::Create(kRegCode_##R, 32, CPURegister::kDefault); +GENERAL_32_REGISTERS(DECLARE_REGISTER) +#undef DECLARE_REGISTER + +#ifdef _WIN64 +// Windows calling convention +constexpr Register arg_reg_1 = rcx; +constexpr Register arg_reg_2 = rdx; +constexpr Register arg_reg_3 = r8; +constexpr Register arg_reg_4 = r9; +#else +// AMD64 calling convention +constexpr Register arg_reg_1 = rdi; +constexpr Register arg_reg_2 = rsi; +constexpr Register arg_reg_3 = rdx; +constexpr Register arg_reg_4 = rcx; +#endif // _WIN64 + +#define DOUBLE_REGISTERS(V) \ + V(xmm0) \ + V(xmm1) \ + V(xmm2) \ + V(xmm3) \ + V(xmm4) \ + V(xmm5) \ + V(xmm6) \ + V(xmm7) \ + V(xmm8) \ + V(xmm9) \ + V(xmm10) \ + V(xmm11) \ + V(xmm12) \ + V(xmm13) \ + V(xmm14) \ + V(xmm15) + +#define FLOAT_REGISTERS DOUBLE_REGISTERS +#define SIMD128_REGISTERS DOUBLE_REGISTERS + +constexpr bool kPadArguments = false; +constexpr bool kSimpleFPAliasing = true; +constexpr bool kSimdMaskRegisters = false; + +enum DoubleRegisterCode { +#define REGISTER_CODE(R) kDoubleCode_##R, + DOUBLE_REGISTERS(REGISTER_CODE) +#undef REGISTER_CODE + kDoubleAfterLast +}; + +class XMMRegister : public RegisterBase { +public: + enum RegisterType { kInvalid }; + + constexpr XMMRegister(int code) : RegisterBase(code) { + } + + static constexpr XMMRegister Create(int code) { + return XMMRegister(code); + } + + static constexpr XMMRegister InvalidRegister() { + return XMMRegister(0); + } + +public: + // Return the high bit of the register code as a 0 or 1. Used often + // when constructing the REX prefix byte. + int high_bit() const { + return reg_code_ >> 3; + } + // Return the 3 low bits of the register code. Used when encoding registers + // in modR/M, SIB, and opcode bytes. + int low_bits() const { + return reg_code_ & 0x7; + } + +private: +}; + +typedef XMMRegister FloatRegister; + +typedef XMMRegister DoubleRegister; + +typedef XMMRegister Simd128Register; + +typedef XMMRegister FPURegister; + +#define DECLARE_REGISTER(R) constexpr DoubleRegister R = DoubleRegister::Create(kDoubleCode_##R); +DOUBLE_REGISTERS(DECLARE_REGISTER) +#undef DECLARE_REGISTER + +} // namespace x64 +} // namespace zz + +#endif diff --git a/app/src/main/cpp/Dobby/source/core/arch/x86/constants-x86.h b/app/src/main/cpp/Dobby/source/core/arch/x86/constants-x86.h new file mode 100644 index 0000000..a243a76 --- /dev/null +++ b/app/src/main/cpp/Dobby/source/core/arch/x86/constants-x86.h @@ -0,0 +1,19 @@ +#ifndef CORE_ARCH_CONSTANTS_X86_H +#define CORE_ARCH_CONSTANTS_X86_H + +namespace zz { +namespace x86 { + +enum ScaleFactor { + TIMES_1 = 0, + TIMES_2 = 1, + TIMES_4 = 2, + TIMES_8 = 3, + TIMES_16 = 4, + TIMES_HALF_WORD_SIZE = sizeof(void *) / 2 - 1 +}; + +} // namespace x86 +} // namespace zz + +#endif \ No newline at end of file diff --git a/app/src/main/cpp/Dobby/source/core/arch/x86/cpu-x86.cc b/app/src/main/cpp/Dobby/source/core/arch/x86/cpu-x86.cc new file mode 100644 index 0000000..d700581 --- /dev/null +++ b/app/src/main/cpp/Dobby/source/core/arch/x86/cpu-x86.cc @@ -0,0 +1,10 @@ +#include "platform_detect_macro.h" +#if defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_X64) + +#include "cpu-x86.h" + +X86CpuInfo::X86CpuInfo() { + +} + +#endif \ No newline at end of file diff --git a/app/src/main/cpp/Dobby/source/core/arch/x86/cpu-x86.h b/app/src/main/cpp/Dobby/source/core/arch/x86/cpu-x86.h new file mode 100644 index 0000000..68fd62c --- /dev/null +++ b/app/src/main/cpp/Dobby/source/core/arch/x86/cpu-x86.h @@ -0,0 +1,120 @@ +#ifndef CORE_ARCH_CPU_X86_H +#define CORE_ARCH_CPU_X86_H + +#include "core/arch/Cpu.h" + +class X86CpuInfo { + +public: + X86CpuInfo(); + +public: + // General features + bool has_fpu() const { + return has_fpu_; + } + int icache_line_size() const { + return icache_line_size_; + } + int dcache_line_size() const { + return dcache_line_size_; + } + + static const int UNKNOWN_CACHE_LINE_SIZE = 0; + + // x86 features + bool has_cmov() const { + return has_cmov_; + } + bool has_sahf() const { + return has_sahf_; + } + bool has_mmx() const { + return has_mmx_; + } + bool has_sse() const { + return has_sse_; + } + bool has_sse2() const { + return has_sse2_; + } + bool has_sse3() const { + return has_sse3_; + } + bool has_ssse3() const { + return has_ssse3_; + } + bool has_sse41() const { + return has_sse41_; + } + bool has_sse42() const { + return has_sse42_; + } + bool has_osxsave() const { + return has_osxsave_; + } + bool has_avx() const { + return has_avx_; + } + bool has_fma3() const { + return has_fma3_; + } + bool has_bmi1() const { + return has_bmi1_; + } + bool has_bmi2() const { + return has_bmi2_; + } + bool has_lzcnt() const { + return has_lzcnt_; + } + bool has_popcnt() const { + return has_popcnt_; + } + bool is_atom() const { + return is_atom_; + } + +private: + char vendor_[13]; + + // General features + int icache_line_size_; + int dcache_line_size_; + bool has_fpu_; + + // x86 features + bool has_cmov_; + bool has_sahf_; + bool has_mmx_; + bool has_sse_; + bool has_sse2_; + bool has_sse3_; + bool has_ssse3_; + bool has_sse41_; + bool has_sse42_; + bool has_osxsave_; + bool has_avx_; + bool has_fma3_; + bool has_bmi1_; + bool has_bmi2_; + bool has_lzcnt_; + bool has_popcnt_; + bool is_atom_; +}; + +class X86CpuFeatures : public CpuFeatures { +public: + static bool sse2_supported() { + return X86CpuInfo().has_sse2(); + } + static bool sse4_1_supported() { + return X86CpuInfo().has_sse41(); + } + +private: + static bool sse2_supported_; + static bool sse4_1_supported_; +}; + +#endif \ No newline at end of file diff --git a/app/src/main/cpp/Dobby/source/core/arch/x86/registers-x86.h b/app/src/main/cpp/Dobby/source/core/arch/x86/registers-x86.h new file mode 100644 index 0000000..65b06b2 --- /dev/null +++ b/app/src/main/cpp/Dobby/source/core/arch/x86/registers-x86.h @@ -0,0 +1,124 @@ +#ifndef ARCH_IA32_REGISTERS +#define ARCH_IA32_REGISTERS + +#include "core/arch/x86/constants-x86.h" +#include "core/arch/Cpu.h" + +namespace zz { +namespace x86 { + +#define GENERAL_REGISTERS(V) \ + V(eax) \ + V(ecx) \ + V(edx) \ + V(ebx) \ + V(esp) \ + V(ebp) \ + V(esi) \ + V(edi) + +enum RegisterCode { +#define REGISTER_CODE(R) kRegCode_##R, + GENERAL_REGISTERS(REGISTER_CODE) +#undef REGISTER_CODE + kRegAfterLast +}; + +class CPURegister : public RegisterBase { +public: + enum RegisterType { kDefault, kInvalid }; + + constexpr CPURegister(int code, int size, RegisterType type) : RegisterBase(code), reg_size_(size), reg_type_(type) { + } + + static constexpr CPURegister Create(int code, int size, RegisterType type) { + return CPURegister(code, size, type); + } + + static constexpr CPURegister from_code(int code) { + return CPURegister(code, 0, kDefault); + } + + static constexpr CPURegister InvalidRegister() { + return CPURegister(0, 0, kInvalid); + } + + RegisterType type() const { + return reg_type_; + } + +public: + bool is_byte_register() const { + return reg_code_ <= 3; + } + + int size() { + return reg_size_; + } + +private: + RegisterType reg_type_; + int reg_size_; +}; + +typedef CPURegister Register; + +#define DEFINE_REGISTER(R) constexpr Register R = Register::Create(kRegCode_##R, 32, CPURegister::kDefault); +GENERAL_REGISTERS(DEFINE_REGISTER) +#undef DEFINE_REGISTER + +#define DOUBLE_REGISTERS(V) \ + V(xmm0) \ + V(xmm1) \ + V(xmm2) \ + V(xmm3) \ + V(xmm4) \ + V(xmm5) \ + V(xmm6) \ + V(xmm7) + +#define FLOAT_REGISTERS DOUBLE_REGISTERS +#define SIMD128_REGISTERS DOUBLE_REGISTERS + +constexpr bool kPadArguments = false; +constexpr bool kSimpleFPAliasing = true; +constexpr bool kSimdMaskRegisters = false; + +enum DoubleRegisterCode { +#define REGISTER_CODE(R) kDoubleCode_##R, + DOUBLE_REGISTERS(REGISTER_CODE) +#undef REGISTER_CODE + kDoubleAfterLast +}; + +class XMMRegister : public RegisterBase { +public: + enum RegisterType { kInvalid }; + + constexpr XMMRegister(int code) : RegisterBase(code) { + } + + static constexpr XMMRegister Create(int code) { + return XMMRegister(code); + } + + static constexpr XMMRegister InvalidRegister() { + return XMMRegister(0); + } + +private: +}; + +typedef XMMRegister FloatRegister; +typedef XMMRegister DoubleRegister; +typedef XMMRegister Simd128Register; +typedef XMMRegister FPURegister; + +#define DEFINE_REGISTER(R) constexpr DoubleRegister R = DoubleRegister::Create(kDoubleCode_##R); +DOUBLE_REGISTERS(DEFINE_REGISTER) +#undef DEFINE_REGISTER + +} // namespace x86 +} // namespace zz + +#endif diff --git a/app/src/main/cpp/Dobby/source/core/assembler/AssemblerPseudoLabel.h b/app/src/main/cpp/Dobby/source/core/assembler/AssemblerPseudoLabel.h new file mode 100644 index 0000000..8774774 --- /dev/null +++ b/app/src/main/cpp/Dobby/source/core/assembler/AssemblerPseudoLabel.h @@ -0,0 +1,85 @@ +#pragma once + +#include "MemoryAllocator/CodeBuffer/CodeBufferBase.h" + +class Label { +public: + Label(addr_t addr) : pos_(addr) { + } + +protected: + addr_t pos_; +}; + +class AssemblerPseudoLabel : public Label { +public: + typedef struct { + int link_type; + size_t pc_offset; + addr_t vmaddr_; + } ref_label_insn_t; + +public: + AssemblerPseudoLabel(addr_t addr) : Label(addr) { + ref_label_insns_.reserve(4); + + bind_to(addr); + } + + bool has_confused_instructions() { + return ref_label_insns_.size(); + } + + void link_confused_instructions(); + + void link_confused_instructions(CodeBufferBase *buffer_); + + void link_to(int link_type, uint32_t pc_offset) { + ref_label_insn_t insn; + insn.link_type = link_type; + insn.pc_offset = pc_offset; + ref_label_insns_.push_back(insn); + } + +public: + addr_t pos() { + return pos_; + }; + + void bind_to(addr_t addr) { + pos_ = addr; + } + +protected: + tinystl::vector ref_label_insns_; +}; + +struct RelocLabel : public AssemblerPseudoLabel { +public: + RelocLabel() : AssemblerPseudoLabel(0) { + memset(data_, 0, sizeof(data_)); + data_size_ = 0; + } + + template static RelocLabel *withData(T value) { + auto label = new RelocLabel(); + label->setData(value); + return label; + } + + template T data() { + return *(T *)data_; + } + + template void setData(T value) { + data_size_ = sizeof(T); + memcpy(data_, &value, data_size_); + } + + template void fixupData(T value) { + *(T *)data_ = value; + } + + uint8_t data_[8]; + int data_size_; +}; \ No newline at end of file diff --git a/app/src/main/cpp/Dobby/source/core/assembler/assembler-arch.h b/app/src/main/cpp/Dobby/source/core/assembler/assembler-arch.h new file mode 100644 index 0000000..23ae9c3 --- /dev/null +++ b/app/src/main/cpp/Dobby/source/core/assembler/assembler-arch.h @@ -0,0 +1,28 @@ +#ifndef CORE_ASSEMBLER_ARCH_H +#define CORE_ASSEMBLER_ARCH_H + +#include "src/assembler.h" + +#if 0 +#if TARGET_ARCH_IA32 +#include "src/ia32/assembler-ia32.h" +#elif TARGET_ARCH_X64 +#include "src/x64/assembler-x64.h" +#elif TARGET_ARCH_ARM64 +#include "src/arm64/assembler-arm64.h" +#elif TARGET_ARCH_ARM +#include "src/arm/assembler-arm.h" +#elif TARGET_ARCH_PPC +#include "src/ppc/assembler-ppc.h" +#elif TARGET_ARCH_MIPS +#include "src/mips/assembler-mips.h" +#elif TARGET_ARCH_MIPS64 +#include "src/mips64/assembler-mips64.h" +#elif TARGET_ARCH_S390 +#include "src/s390/assembler-s390.h" +#else +#error Unknown architecture. +#endif +#endif + +#endif diff --git a/app/src/main/cpp/Dobby/source/core/assembler/assembler-arm.cc b/app/src/main/cpp/Dobby/source/core/assembler/assembler-arm.cc new file mode 100644 index 0000000..138db0c --- /dev/null +++ b/app/src/main/cpp/Dobby/source/core/assembler/assembler-arm.cc @@ -0,0 +1,41 @@ +#include "platform_detect_macro.h" +#if TARGET_ARCH_ARM + +#include "core/assembler/assembler-arm.h" + +void AssemblerPseudoLabel::link_confused_instructions(CodeBufferBase *buffer) { + CodeBuffer *_buffer = (CodeBuffer *)buffer; + + for (auto &ref_label_insn : ref_label_insns_) { + arm_inst_t inst = _buffer->LoadARMInst(ref_label_insn.pc_offset); + if (ref_label_insn.link_type == kLdrLiteral) { + int64_t pc = ref_label_insn.pc_offset + ARM_PC_OFFSET; + assert(pc % 4 == 0); + int32_t imm12 = pos() - pc; + if (imm12 > 0) { + set_bit(inst, 23, 1); + } else { + set_bit(inst, 23, 0); + imm12 = -imm12; + } + set_bits(inst, 0, 11, imm12); + } + _buffer->RewriteARMInst(ref_label_insn.pc_offset, inst); + } +} + +namespace zz { +namespace arm { + +void Assembler::EmitARMInst(arm_inst_t instr) { + buffer_->EmitARMInst(instr); +} + +void Assembler::EmitAddress(uint32_t value) { + buffer_->Emit32(value); +} + +} // namespace arm +} // namespace zz + +#endif diff --git a/app/src/main/cpp/Dobby/source/core/assembler/assembler-arm.h b/app/src/main/cpp/Dobby/source/core/assembler/assembler-arm.h new file mode 100644 index 0000000..46e080a --- /dev/null +++ b/app/src/main/cpp/Dobby/source/core/assembler/assembler-arm.h @@ -0,0 +1,354 @@ +#pragma once + +#include "dobby/common.h" + +#include "core/arch/arm/constants-arm.h" +#include "core/arch/arm/registers-arm.h" +#include "core/assembler/assembler.h" + +#include "MemoryAllocator/CodeBuffer/code_buffer_arm.h" + +enum ref_label_type_t { kLdrLiteral }; + +namespace zz { +namespace arm { + +// ARM design had a 3-stage pipeline (fetch-decode-execute) +#define ARM_PC_OFFSET 8 +#define Thumb_PC_OFFSET 4 + +// define instruction length +#define ARM_INST_LEN 4 +#define Thumb1_INST_LEN 2 +#define Thumb2_INST_LEN 4 + +// Thumb instructions address is odd +#define THUMB_ADDRESS_FLAG 1 + +constexpr Register TMP_REG_0 = r12; + +constexpr Register VOLATILE_REGISTER = r12; + +#define Rd(rd) (rd.code() << kRdShift) +#define Rt(rt) (rt.code() << kRtShift) +#define Rn(rn) (rn.code() << kRnShift) +#define Rm(rm) (rm.code() << kRmShift) + +// --- + +class Operand { + friend class OpEncode; + +public: + Operand(int immediate) : imm_(immediate), rm_(no_reg), shift_(LSL), shift_imm_(0), rs_(no_reg) { + } + + Operand(Register rm) : imm_(0), rm_(rm), shift_(LSL), shift_imm_(0), rs_(no_reg) { + } + + Operand(Register rm, Shift shift, uint32_t shift_imm) + : imm_(0), rm_(rm), shift_(shift), shift_imm_(shift_imm), rs_(no_reg) { + } + + Operand(Register rm, Shift shift, Register rs) : imm_(0), rm_(rm), shift_(shift), shift_imm_(0), rs_(rs) { + } + +public: + int GetImmediate() const { + return imm_; + } + +private: + Register rm_; + Register rs_; + + Shift shift_; + int shift_imm_; + + int imm_; + +private: + friend class EncodeUtility; +}; + +// --- + +class MemOperand { + friend class OpEncode; + +public: + MemOperand(Register rn, int32_t offset = 0, AddrMode addrmode = Offset) + : rn_(rn), offset_(offset), rm_(no_reg), shift_(LSL), shift_imm_(0), addrmode_(addrmode) { + } + + MemOperand(Register rn, Register rm, AddrMode addrmode = Offset) + : rn_(rn), offset_(0), rm_(rm), shift_(LSL), shift_imm_(0), addrmode_(addrmode) { + } + + MemOperand(Register rn, Register rm, Shift shift, uint32_t shift_imm, AddrMode addrmode = Offset) + : rn_(rn), offset_(0), rm_(rm), shift_(shift), shift_imm_(shift_imm), addrmode_(addrmode) { + } + + const Register &rn() const { + return rn_; + } + const Register &rm() const { + return rm_; + } + int32_t offset() const { + return offset_; + } + + bool IsImmediateOffset() const { + return (addrmode_ == Offset); + } + bool IsRegisterOffset() const { + return (addrmode_ == Offset); + } + bool IsPreIndex() const { + return addrmode_ == PreIndex; + } + bool IsPostIndex() const { + return addrmode_ == PostIndex; + } + +private: + Register rn_; // base + Register rm_; // register offset + + int32_t offset_; // valid if rm_ == no_reg + + Shift shift_; + uint32_t shift_imm_; // valid if rm_ != no_reg && rs_ == no_reg + + AddrMode addrmode_; // bits P, U, and W +}; + +// --- + +class OpEncode { +public: + static uint32_t MemOperand(const MemOperand operand) { + uint32_t encoding = 0; + if (operand.rm_.IsValid()) { + UNREACHABLE(); + } + + // sign + uint32_t U = 0; + if (operand.offset_ >= 0) { + U = (1 << 23); + } + encoding |= U; + + // offset + encoding |= bits(abs(operand.offset_), 0, 11); + + // addr mode + uint32_t P, W; + if (operand.addrmode_ == Offset) { + P = 1; + W = 0; + } else if (operand.addrmode_ == PostIndex) { + P = 0; + W = 0; + } else if (operand.addrmode_ == PreIndex) { + P = 1; + W = 1; + } + encoding |= ((P << 24) | (W << 21)); + + // rn + encoding |= Rn(operand.rn_); + + return encoding; + } + + static uint32_t Operand(const Operand operand) { + uint32_t encoding = 0; + if (operand.rm_.IsValid()) { + encoding = static_cast(operand.rm_.code()); + } else { + encoding = operand.GetImmediate(); + } + + return encoding; + } +}; + +// --- + +enum ExecuteState { ARMExecuteState, ThumbExecuteState }; + +class Assembler : public AssemblerBase { +private: + ExecuteState execute_state_; + +public: + Assembler(void *address) : AssemblerBase(address) { + execute_state_ = ARMExecuteState; + buffer_ = new CodeBuffer(); + } + + // shared_ptr is better choice + // but we can't use it at kernelspace + Assembler(void *address, CodeBuffer *buffer) : AssemblerBase(address) { + execute_state_ = ARMExecuteState; + buffer_ = buffer; + } + + void ClearCodeBuffer() { + buffer_ = NULL; + } + +public: + void SetExecuteState(ExecuteState state) { + execute_state_ = state; + } + ExecuteState GetExecuteState() { + return execute_state_; + } + + void SetRealizedAddress(void *address) { + DCHECK_EQ(0, reinterpret_cast(address) % 4); + AssemblerBase::SetRealizedAddress(address); + } + + void EmitARMInst(arm_inst_t instr); + + void EmitAddress(uint32_t value); + +public: + void sub(Register rd, Register rn, const Operand &operand) { + uint32_t encoding = B25 | B22; + add_sub(encoding, AL, rd, rn, operand); + } + + void add(Register rd, Register rn, const Operand &operand) { + uint32_t encoding = B25 | B23; + add_sub(encoding, AL, rd, rn, operand); + } + + void add_sub(uint32_t encoding, Condition cond, Register rd, Register rn, const Operand &operand) { + encoding |= (cond << kConditionShift); + + uint32_t imm = operand.GetImmediate(); + encoding |= imm; + + encoding |= Rd(rd); + + encoding |= Rn(rn); + + buffer_->EmitARMInst(encoding); + } + + void ldr(Register rt, const MemOperand &operand) { + uint32_t encoding = B20 | B26; + load_store(encoding, AL, rt, operand); + } + + void str(Register rt, const MemOperand &operand) { + uint32_t encoding = B26; + load_store(encoding, AL, rt, operand); + } + + void load_store(uint32_t encoding, Condition cond, Register rt, const MemOperand &operand) { + encoding |= (cond << kConditionShift); + encoding |= Rt(rt) | OpEncode::MemOperand(operand); + buffer_->EmitARMInst(encoding); + } + + void mov(Register rd, const Operand &operand) { + mov(AL, rd, operand); + } + + void mov(Condition cond, Register rd, const Operand &operand) { + uint32_t encoding = 0x01a00000; + encoding |= (cond << kConditionShift); + encoding |= Rd(rd) | OpEncode::Operand(operand); + buffer_->EmitARMInst(encoding); + } + + // Branch instructions. + void b(int branch_offset) { + b(AL, branch_offset); + } + void b(Condition cond, int branch_offset) { + uint32_t encoding = 0xa000000; + encoding |= (cond << kConditionShift); + uint32_t imm24 = bits(branch_offset >> 2, 0, 23); + encoding |= imm24; + buffer_->EmitARMInst(encoding); + } + + void bl(int branch_offset) { + bl(AL, branch_offset); + } + void bl(Condition cond, int branch_offset) { + uint32_t encoding = 0xb000000; + encoding |= (cond << kConditionShift); + uint32_t imm24 = bits(branch_offset >> 2, 0, 23); + encoding |= imm24; + buffer_->EmitARMInst(encoding); + } + + void blx(int branch_offset) { + UNIMPLEMENTED(); + } + void blx(Register target, Condition cond = AL) { + UNIMPLEMENTED(); + } + void bx(Register target, Condition cond = AL) { + UNIMPLEMENTED(); + } + +}; // namespace arm + +// --- + +class TurboAssembler : public Assembler { +public: + TurboAssembler(void *address) : Assembler(address) { + } + + ~TurboAssembler() { + } + + TurboAssembler(void *address, CodeBuffer *buffer) : Assembler(address, buffer) { + } + + void Ldr(Register rt, AssemblerPseudoLabel *label) { + if (label->pos()) { + int offset = label->pos() - buffer_->GetBufferSize(); + ldr(rt, MemOperand(pc, offset)); + } else { + // record this ldr, and fix later. + label->link_to(kLdrLiteral, buffer_->GetBufferSize()); + ldr(rt, MemOperand(pc, 0)); + } + } + + void CallFunction(ExternalReference function) { + // trick: use bl to replace lr register + bl(0); + b(4); + ldr(pc, MemOperand(pc, -4)); + buffer_->Emit32((uint32_t)(uintptr_t)function.address()); + } + + void Move32Immeidate(Register rd, const Operand &x, Condition cond = AL) { + } + + void RelocLabelFixup(tinystl::unordered_map *relocated_offset_map) { + for (auto *data_label : data_labels_) { + auto val = data_label->data(); + auto iter = relocated_offset_map->find(val); + if (iter != relocated_offset_map->end()) { + data_label->fixupData(iter->second); + } + } + } +}; + +} // namespace arm +} // namespace zz \ No newline at end of file diff --git a/app/src/main/cpp/Dobby/source/core/assembler/assembler-arm64.cc b/app/src/main/cpp/Dobby/source/core/assembler/assembler-arm64.cc new file mode 100644 index 0000000..e52fdc6 --- /dev/null +++ b/app/src/main/cpp/Dobby/source/core/assembler/assembler-arm64.cc @@ -0,0 +1,25 @@ +#include "platform_detect_macro.h" +#if TARGET_ARCH_ARM64 + +#include "core/assembler/assembler-arm64.h" + +void AssemblerPseudoLabel::link_confused_instructions(CodeBufferBase *buffer_) { + auto buffer = (CodeBuffer *)buffer_; + + for (auto &ref_label_insn : ref_label_insns_) { + int64_t fixup_offset = pos() - ref_label_insn.pc_offset; + + arm64_inst_t inst = buffer->LoadInst(ref_label_insn.pc_offset); + arm64_inst_t new_inst = 0; + + if (ref_label_insn.link_type == kLabelImm19) { + new_inst = encode_imm19_offset(inst, fixup_offset); + } + + buffer->RewriteInst(ref_label_insn.pc_offset, new_inst); + } +} + +using namespace zz::arm64; + +#endif diff --git a/app/src/main/cpp/Dobby/source/core/assembler/assembler-arm64.h b/app/src/main/cpp/Dobby/source/core/assembler/assembler-arm64.h new file mode 100644 index 0000000..70c5309 --- /dev/null +++ b/app/src/main/cpp/Dobby/source/core/assembler/assembler-arm64.h @@ -0,0 +1,560 @@ +#pragma once + +#include "dobby/dobby_internal.h" + +#include "core/arch/arm64/constants-arm64.h" +#include "core/arch/arm64/registers-arm64.h" +#include "core/assembler/assembler.h" + +#include "MemoryAllocator/CodeBuffer/code_buffer_arm64.h" + +#include "InstructionRelocation/arm64/inst_decode_encode_kit.h" + +static inline uint16_t Low16Bits(uint32_t value) { + return static_cast(value & 0xffff); +} + +static inline uint16_t High16Bits(uint32_t value) { + return static_cast(value >> 16); +} + +static inline uint32_t Low32Bits(uint64_t value) { + return static_cast(value); +} + +static inline uint32_t High32Bits(uint64_t value) { + return static_cast(value >> 32); +} + +enum ref_label_type_t { kLabelImm19 }; + +namespace zz { +namespace arm64 { + +constexpr Register TMP_REG_0 = X(ARM64_TMP_REG_NDX_0); + +#define Rd(rd) (rd.code() << kRdShift) +#define Rt(rt) (rt.code() << kRtShift) +#define Rt2(rt) (rt.code() << kRt2Shift) +#define Rn(rn) (rn.code() << kRnShift) +#define Rm(rm) (rm.code() << kRmShift) + +// --- + +class Operand { +public: + inline explicit Operand(int64_t imm) + : immediate_(imm), reg_(InvalidRegister), shift_(NO_SHIFT), extend_(NO_EXTEND), shift_extent_imm_(0) { + } + inline Operand(Register reg, Shift shift = LSL, int32_t shift_imm = 0) + : immediate_(0), reg_(reg), shift_(shift), extend_(NO_EXTEND), shift_extent_imm_(shift_imm) { + } + inline Operand(Register reg, Extend extend, int32_t shift_imm = 0) + : immediate_(0), reg_(reg), shift_(NO_SHIFT), extend_(extend), shift_extent_imm_(shift_imm) { + } + + bool IsImmediate() const { + return reg_.Is(InvalidRegister); + } + bool IsShiftedRegister() const { + return /* reg_.IsValid() && */ (shift_ != NO_SHIFT); + } + bool IsExtendedRegister() const { + return /* reg_.IsValid() && */ (extend_ != NO_EXTEND); + } + + Register reg() const { + DCHECK((IsShiftedRegister() || IsExtendedRegister())); + return reg_; + } + int64_t Immediate() const { + return immediate_; + } + Shift shift() const { + DCHECK(IsShiftedRegister()); + return shift_; + } + Extend extend() const { + DCHECK(IsExtendedRegister()); + return extend_; + } + int32_t shift_extend_imm() const { + return shift_extent_imm_; + } + +private: + int64_t immediate_; + + Register reg_; + + Shift shift_; + Extend extend_; + int32_t shift_extent_imm_; +}; + +// --- + +class MemOperand { +public: + inline explicit MemOperand(Register base, int64_t offset = 0, AddrMode addrmode = Offset) + : base_(base), regoffset_(InvalidRegister), offset_(offset), addrmode_(addrmode), shift_(NO_SHIFT), + extend_(NO_EXTEND), shift_extend_imm_(0) { + } + + inline explicit MemOperand(Register base, Register regoffset, Extend extend, unsigned extend_imm) + : base_(base), regoffset_(regoffset), offset_(0), addrmode_(Offset), shift_(NO_SHIFT), extend_(extend), + shift_extend_imm_(extend_imm) { + } + + inline explicit MemOperand(Register base, Register regoffset, Shift shift = LSL, unsigned shift_imm = 0) + : base_(base), regoffset_(regoffset), offset_(0), addrmode_(Offset), shift_(shift), extend_(NO_EXTEND), + shift_extend_imm_(shift_imm) { + } + + inline explicit MemOperand(Register base, const Operand &offset, AddrMode addrmode = Offset) + : base_(base), regoffset_(InvalidRegister), addrmode_(addrmode) { + if (offset.IsShiftedRegister()) { + regoffset_ = offset.reg(); + shift_ = offset.shift(); + shift_extend_imm_ = offset.shift_extend_imm(); + + extend_ = NO_EXTEND; + offset_ = 0; + } else if (offset.IsExtendedRegister()) { + regoffset_ = offset.reg(); + extend_ = offset.extend(); + shift_extend_imm_ = offset.shift_extend_imm(); + + shift_ = NO_SHIFT; + offset_ = 0; + } + } + + const Register &base() const { + return base_; + } + const Register ®offset() const { + return regoffset_; + } + int64_t offset() const { + return offset_; + } + AddrMode addrmode() const { + return addrmode_; + } + Shift shift() const { + return shift_; + } + Extend extend() const { + return extend_; + } + unsigned shift_extend_imm() const { + return shift_extend_imm_; + } + + bool IsImmediateOffset() const { + return (addrmode_ == Offset); + } + bool IsRegisterOffset() const { + return (addrmode_ == Offset); + } + bool IsPreIndex() const { + return addrmode_ == PreIndex; + } + bool IsPostIndex() const { + return addrmode_ == PostIndex; + } + +private: + Register base_; + Register regoffset_; + + int64_t offset_; + + Shift shift_; + Extend extend_; + uint32_t shift_extend_imm_; + + AddrMode addrmode_; +}; + +// --- + +class OpEncode { +public: + static int32_t sf(const Register ®, int32_t op) { + return (op | sf(reg)); + } + + // register operation size, 32 bits or 64 bits + static int32_t sf(const Register ®) { + if (reg.Is64Bits()) + return LeftShift(1, 1, 31); + return 0; + } + + static int32_t V(const Register ®, int32_t op) { + return (op | V(reg)); + } + + // register type, SIMD_FD register or general register + static int32_t V(const Register ®) { + if (reg.IsVRegister()) + return LeftShift(1, 1, 26); + return 0; + } + + // load or store + static int32_t L(bool load_or_store) { + if (load_or_store) { + return LeftShift(1, 1, 22); + } + return 0; + } + + // shift type + static int32_t shift(Shift shift) { + return LeftShift(shift, 2, 22); + } + + // LogicalImmeidate + static int32_t EncodeLogicalImmediate(const Register &rd, const Register &rn, const Operand &operand) { + int64_t imm = operand.Immediate(); + int32_t N, imms, immr; + immr = bits(imm, 0, 5); + imms = bits(imm, 6, 11); + N = bit(imm, 12); + + return (sf(rd) | LeftShift(immr, 6, 16) | LeftShift(imms, 6, 10) | Rd(rd) | Rn(rn)); + } + + // LogicalShift + static int32_t EncodeLogicalShift(const Register &rd, const Register &rn, const Operand &operand) { + return (sf(rd) | shift(operand.shift()) | Rm(operand.reg()) | LeftShift(operand.shift_extend_imm(), 6, 10) | + Rn(rn) | Rd(rd)); + } + + // LoadStore + static int32_t LoadStorePair(LoadStorePairOp op, CPURegister rt, CPURegister rt2, const MemOperand &addr) { + int32_t scale = 2; + int32_t opc = 0; + int imm7; + opc = bits(op, 30, 31); + if (rt.IsRegister()) { + scale += bit(opc, 1); + } else if (rt.IsVRegister()) { + scale += opc; + } + + imm7 = (int)(addr.offset() >> scale); + return LeftShift(imm7, 7, 15); + } + + // scale + static int32_t scale(int32_t op) { + int scale = 0; + if ((op & LoadStoreUnsignedOffsetFixed) == LoadStoreUnsignedOffsetFixed) { + scale = bits(op, 30, 31); + } + return scale; + } +}; + +// --- + +class Assembler : public AssemblerBase { +public: + Assembler(void *address) : AssemblerBase(address) { + buffer_ = new CodeBuffer(); + } + + ~Assembler() { + if (buffer_) + delete buffer_; + buffer_ = NULL; + } + +public: + void SetRealizedAddress(void *address) { + DCHECK_EQ(0, reinterpret_cast(address) % 4); + AssemblerBase::SetRealizedAddress(address); + } + + void Emit(uint32_t value) { + buffer_->Emit32(value); + } + + void EmitInt64(int64_t value) { + buffer_->Emit64(value); + } + + void bind(Label *label); + + void nop() { + Emit(0xD503201F); + } + + void brk(int code) { + Emit(BRK | LeftShift(code, 16, 5)); + } + + void ret() { + Emit(0xD65F03C0); + } + + void adrp(const Register &rd, int64_t imm) { + DCHECK(rd.Is64Bits()); + DCHECK((abs(imm) >> 12) < (1 << 21)); + + uint32_t immlo = LeftShift(bits(imm >> 12, 0, 1), 2, 29); + uint32_t immhi = LeftShift(bits(imm >> 12, 2, 20), 19, 5); + Emit(ADRP | Rd(rd) | immlo | immhi); + } + + void add(const Register &rd, const Register &rn, int64_t imm) { + if (rd.Is64Bits() && rn.Is64Bits()) + AddSubImmediate(rd, rn, Operand(imm), OPT_X(ADD, imm)); + else + AddSubImmediate(rd, rn, Operand(imm), OPT_W(ADD, imm)); + } + + void adds(const Register &rd, const Register &rn, int64_t imm) { + UNREACHABLE(); + } + void sub(const Register &rd, const Register &rn, int64_t imm) { + if (rd.Is64Bits() && rn.Is64Bits()) + AddSubImmediate(rd, rn, Operand(imm), OPT_X(SUB, imm)); + else + AddSubImmediate(rd, rn, Operand(imm), OPT_W(SUB, imm)); + } + void subs(const Register &rd, const Register &rn, int64_t imm) { + UNREACHABLE(); + } + + void b(int64_t imm) { + int32_t imm26 = bits(imm >> 2, 0, 25); + + Emit(B | imm26); + } + + void b(Label *label) { + int offset = LinkAndGetByteOffsetTo(label); + b(offset); + } + + void br(Register rn) { + Emit(BR | Rn(rn)); + } + + void blr(Register rn) { + Emit(BLR | Rn(rn)); + } + + void ldr(Register rt, int64_t imm) { + LoadRegLiteralOp op; + switch (rt.type()) { + case CPURegister::kRegister_32: + op = OPT_W(LDR, literal); + break; + case CPURegister::kRegister_X: + op = OPT_X(LDR, literal); + break; + case CPURegister::kSIMD_FP_Register_S: + op = OPT_S(LDR, literal); + break; + case CPURegister::kSIMD_FP_Register_D: + op = OPT_D(LDR, literal); + break; + case CPURegister::kSIMD_FP_Register_Q: + op = OPT_Q(LDR, literal); + break; + default: + UNREACHABLE(); + break; + } + EmitLoadRegLiteral(op, rt, imm); + } + + void ldr(const CPURegister &rt, const MemOperand &src) { + LoadStore(OP_X(LDR), rt, src); + } + + void str(const CPURegister &rt, const MemOperand &src) { + LoadStore(OP_X(STR), rt, src); + } + + void ldp(const Register &rt, const Register &rt2, const MemOperand &src) { + if (rt.type() == Register::kSIMD_FP_Register_128) { + LoadStorePair(OP_Q(LDP), rt, rt2, src); + } else if (rt.type() == Register::kRegister_X) { + LoadStorePair(OP_X(LDP), rt, rt2, src); + } else { + UNREACHABLE(); + } + } + + void stp(const Register &rt, const Register &rt2, const MemOperand &dst) { + if (rt.type() == Register::kSIMD_FP_Register_128) { + LoadStorePair(OP_Q(STP), rt, rt2, dst); + } else if (rt.type() == Register::kRegister_X) { + LoadStorePair(OP_X(STP), rt, rt2, dst); + } else { + UNREACHABLE(); + } + } + + void mov(const Register &rd, const Register &rn) { + if ((rd.Is(SP)) || (rn.Is(SP))) { + add(rd, rn, 0); + } else { + if (rd.Is64Bits()) + orr(rd, xzr, Operand(rn)); + else + orr(rd, wzr, Operand(rn)); + } + } + void movk(const Register &rd, uint64_t imm, int shift = -1) { + // Move and keep. + MoveWide(rd, imm, shift, MOVK); + } + void movn(const Register &rd, uint64_t imm, int shift = -1) { + // Move with non-zero. + MoveWide(rd, imm, shift, MOVN); + } + void movz(const Register &rd, uint64_t imm, int shift = -1) { + // Move with zero. + MoveWide(rd, imm, shift, MOVZ); + } + + void orr(const Register &rd, const Register &rn, const Operand &operand) { + Logical(rd, rn, operand, ORR); + } + +private: + // label helpers. + static constexpr int kStartOfLabelLinkChain = 0; + int LinkAndGetByteOffsetTo(Label *label); + + // load helpers. + void EmitLoadRegLiteral(LoadRegLiteralOp op, CPURegister rt, int64_t imm) { + const int32_t encoding = op | LeftShift(imm, 26, 5) | Rt(rt); + Emit(encoding); + } + + void LoadStore(LoadStoreOp op, CPURegister rt, const MemOperand &addr) { + int64_t imm12 = addr.offset(); + if (addr.IsImmediateOffset()) { + // TODO: check Scaled ??? + imm12 = addr.offset() >> OpEncode::scale(LoadStoreUnsignedOffsetFixed | op); + Emit(LoadStoreUnsignedOffsetFixed | op | LeftShift(imm12, 12, 10) | Rn(addr.base()) | Rt(rt)); + } else if (addr.IsRegisterOffset()) { + UNREACHABLE(); + } else { + // pre-index & post-index + UNREACHABLE(); + } + } + + void LoadStorePair(LoadStorePairOp op, CPURegister rt, CPURegister rt2, const MemOperand &addr) { + int32_t combine_fields_op = OpEncode::LoadStorePair(op, rt, rt2, addr) | Rt2(rt2) | Rn(addr.base()) | Rt(rt); + int32_t addrmodeop; + + if (addr.IsImmediateOffset()) { + addrmodeop = LoadStorePairOffsetFixed; + } else { + if (addr.IsPreIndex()) { + addrmodeop = LoadStorePairPreIndexFixed; + } else { + addrmodeop = LoadStorePairPostIndexFixed; + } + } + Emit(op | addrmodeop | combine_fields_op); + } + + void MoveWide(Register rd, uint64_t imm, int shift, MoveWideImmediateOp op) { + if (shift > 0) + shift /= 16; + else + shift = 0; + + int32_t imm16 = LeftShift(imm, 16, 5); + Emit(MoveWideImmediateFixed | op | OpEncode::sf(rd) | LeftShift(shift, 2, 21) | imm16 | Rd(rd)); + } + + void AddSubImmediate(const Register &rd, const Register &rn, const Operand &operand, AddSubImmediateOp op) { + if (operand.IsImmediate()) { + int64_t immediate = operand.Immediate(); + int32_t imm12 = LeftShift(immediate, 12, 10); + Emit(op | Rd(rd) | Rn(rn) | imm12); + } else { + UNREACHABLE(); + } + } + + void Logical(const Register &rd, const Register &rn, const Operand &operand, LogicalOp op) { + if (operand.IsImmediate()) { + LogicalImmediate(rd, rn, operand, op); + } else { + LogicalShift(rd, rn, operand, op); + } + } + void LogicalImmediate(const Register &rd, const Register &rn, const Operand &operand, LogicalOp op) { + int32_t combine_fields_op = OpEncode::EncodeLogicalImmediate(rd, rn, operand); + Emit(op | combine_fields_op); + } + void LogicalShift(const Register &rd, const Register &rn, const Operand &operand, LogicalOp op) { + int32_t combine_fields_op = OpEncode::EncodeLogicalShift(rd, rn, operand); + Emit(op | LogicalShiftedFixed | combine_fields_op); + } +}; + +// --- + +class TurboAssembler : public Assembler { +public: + TurboAssembler(void *address) : Assembler(address) { + } + + ~TurboAssembler() { + } + + void CallFunction(ExternalReference function) { + Mov(TMP_REG_0, (uint64_t)function.address()); + blr(TMP_REG_0); + } + + void Ldr(Register rt, AssemblerPseudoLabel *label) { + if (label->pos()) { + int offset = label->pos() - buffer_->GetBufferSize(); + ldr(rt, offset); + } else { + label->link_to(kLabelImm19, buffer_->GetBufferSize()); + ldr(rt, 0); + } + } + + void Mov(Register rd, uint64_t imm) { + const uint32_t w0 = Low32Bits(imm); + const uint32_t w1 = High32Bits(imm); + const uint16_t h0 = Low16Bits(w0); + const uint16_t h1 = High16Bits(w0); + const uint16_t h2 = Low16Bits(w1); + const uint16_t h3 = High16Bits(w1); + movz(rd, h0, 0); + movk(rd, h1, 16); + movk(rd, h2, 32); + movk(rd, h3, 48); + } + + void AdrpAdd(Register rd, uint64_t from, uint64_t to) { + uint64_t from_PAGE = ALIGN(from, 0x1000); + uint64_t to_PAGE = ALIGN(to, 0x1000); + uint64_t to_PAGEOFF = (uint64_t)to % 0x1000; + + adrp(rd, to_PAGE - from_PAGE); + add(rd, rd, to_PAGEOFF); + } +}; + +} // namespace arm64 +} // namespace zz \ No newline at end of file diff --git a/app/src/main/cpp/Dobby/source/core/assembler/assembler-ia32.cc b/app/src/main/cpp/Dobby/source/core/assembler/assembler-ia32.cc new file mode 100644 index 0000000..12af8ed --- /dev/null +++ b/app/src/main/cpp/Dobby/source/core/assembler/assembler-ia32.cc @@ -0,0 +1,34 @@ +#include "platform_detect_macro.h" +#if TARGET_ARCH_IA32 + +#include "core/assembler/assembler-ia32.h" + +using namespace zz::x86; + +void Assembler::jmp(Immediate imm) { + buffer_->Emit8(0xE9); + buffer_->Emit32((int)imm.value()); +} + +addr32_t TurboAssembler::CurrentIP() { + return pc_offset() + (addr_t)realized_addr_; +} + +void AssemblerPseudoLabel::link_confused_instructions(CodeBufferBase *buffer) { + auto _buffer = (CodeBuffer *)buffer; + + for (auto &ref_label_insn : ref_label_insns_) { + int64_t new_offset = pos() - ref_label_insn.pc_offset; + + if (ref_label_insn.link_type == kDisp32_off_7) { + // why 7 ? + // use `call` and `pop` get the runtime ip register + // but the ip register not the real call next insn + // it need add two insn length == 7 + int disp32_fix_pos = ref_label_insn.pc_offset - sizeof(int32_t); + _buffer->FixBindLabel(disp32_fix_pos, new_offset + 7); + } + } +} + +#endif \ No newline at end of file diff --git a/app/src/main/cpp/Dobby/source/core/assembler/assembler-ia32.h b/app/src/main/cpp/Dobby/source/core/assembler/assembler-ia32.h new file mode 100644 index 0000000..19474a3 --- /dev/null +++ b/app/src/main/cpp/Dobby/source/core/assembler/assembler-ia32.h @@ -0,0 +1,456 @@ +#pragma once + +#include "dobby/common.h" + +#include "core/arch/x86/registers-x86.h" +#include "core/assembler/assembler.h" + +#include "MemoryAllocator/CodeBuffer/code_buffer_x86.h" + +#define IsInt8(imm) (-128 <= imm && imm <= 127) + +enum ref_label_type_t { kDisp32_off_7 }; + +namespace zz { +namespace x86 { + +constexpr Register VOLATILE_REGISTER = eax; + +#define ModRM_Mod(byte) ((byte & 0b11000000) >> 6) +#define ModRM_RegOpcode(byte) ((byte & 0b00111000) >> 3) +#define ModRM_RM(byte) (byte & 0b00000111) + +typedef union _ModRM { + byte_t ModRM; + struct { + byte_t RM : 3; + byte_t RegOpcode : 3; + byte_t Mod : 2; + }; +} ModRM; + +// --- + +class Immediate { +public: + explicit Immediate(int32_t imm) : value_(imm), value_size_(32) { + if ((int32_t)(int8_t)imm == imm) { + value_size_ = 8; + } else if ((int32_t)(int16_t)imm == imm) { + value_size_ = 16; + } else { + value_size_ = 32; + } + } + + explicit Immediate(int32_t imm, int size) : value_(imm), value_size_(size) { + } + + int32_t value() const { + return value_; + } + + int size() const { + return value_size_; + } + +private: + const int32_t value_; + + int value_size_; +}; + +// --- + +class Operand { +public: + // [base] + Operand(Register base); + + // [base + disp/r] + Operand(Register base, int32_t disp); + + // [base + index*scale + disp/r] + Operand(Register base, Register index, ScaleFactor scale, int32_t disp); + + // [index*scale + disp/r] + Operand(Register index, ScaleFactor scale, int32_t disp); + +public: // Getter and Setter + uint8_t modrm() { + return (encoding_at(0)); + } + + uint8_t mod() const { + return (encoding_at(0) >> 6) & 3; + } + + Register rm() const { + return Register::from_code(encoding_at(0) & 7); + } + + ScaleFactor scale() const { + return static_cast((encoding_at(1) >> 6) & 3); + } + + Register index() const { + return Register::from_code((encoding_at(1) >> 3) & 7); + } + + Register base() const { + return Register::from_code(encoding_at(1) & 7); + } + + int8_t disp8() const { + ASSERT(length_ >= 2); + return static_cast(encoding_[length_ - 1]); + } + + int32_t disp32() const { + ASSERT(length_ >= 5); + return static_cast(encoding_[length_ - 4]); + } + +protected: + Operand() : length_(0) { + } + + void SetModRM(int mod, Register rm) { + ASSERT((mod & ~3) == 0); + encoding_[0] = (mod << 6) | rm.code(); + length_ = 1; + } + + void SetSIB(ScaleFactor scale, Register index, Register base) { + ASSERT(length_ == 1); + ASSERT((scale & ~3) == 0); + encoding_[1] = (scale << 6) | (index.code() << 3) | base.code(); + length_ = 2; + } + + void SetDisp8(int8_t disp) { + ASSERT(length_ == 1 || length_ == 2); + encoding_[length_++] = static_cast(disp); + } + + void SetDisp32(int32_t disp) { + ASSERT(length_ == 1 || length_ == 2); + *(int32_t *)&encoding_[length_] = disp; + length_ += sizeof(disp); + } + +private: + // explicit Operand(Register reg) : rex_(REX_NONE) { SetModRM(3, reg); } + + // Get the operand encoding byte at the given index. + uint8_t encoding_at(intptr_t index) const { + ASSERT(index >= 0 && index < length_); + return encoding_[index]; + } + +public: + uint8_t length_; + uint8_t encoding_[6]; +}; + +// --- + +class Address : public Operand { +public: + Address(Register base, int32_t disp) { + int base_ = base.code(); + int ebp_ = ebp.code(); + int esp_ = esp.code(); + if ((disp == 0) && (base_ != ebp_)) { + SetModRM(0, base); + if (base_ == esp_) + SetSIB(TIMES_1, esp, base); + } else if (disp >= -128 && disp <= 127) { + SetModRM(1, base); + if (base_ == esp_) + SetSIB(TIMES_1, esp, base); + SetDisp8(disp); + } else { + SetModRM(2, base); + if (base_ == esp_) + SetSIB(TIMES_1, esp, base); + SetDisp32(disp); + } + } + + // This addressing mode does not exist. + Address(Register base, Register r); + + Address(Register index, ScaleFactor scale, int32_t disp) { + ASSERT(index.code() != rsp.code()); // Illegal addressing mode. + SetModRM(0, esp); + SetSIB(scale, index, ebp); + SetDisp32(disp); + } + + // This addressing mode does not exist. + Address(Register index, ScaleFactor scale, Register r); + + Address(Register base, Register index, ScaleFactor scale, int32_t disp) { + ASSERT(index.code() != rsp.code()); // Illegal addressing mode. + int rbp_ = ebp.code(); + if ((disp == 0) && ((base.code() & 7) != rbp_)) { + SetModRM(0, esp); + SetSIB(scale, index, base); + } else if (disp >= -128 && disp <= 127) { + SetModRM(1, esp); + SetSIB(scale, index, base); + SetDisp8(disp); + } else { + SetModRM(2, esp); + SetSIB(scale, index, base); + SetDisp32(disp); + } + } + + // This addressing mode does not exist. + Address(Register base, Register index, ScaleFactor scale, Register r); + +private: + Address(Register base, int32_t disp, bool fixed) { + ASSERT(fixed); + + SetModRM(2, base); + if (base.code() == esp.code()) { + SetSIB(TIMES_1, esp, base); + } + SetDisp32(disp); + } +}; + +// --- + +class Assembler : public AssemblerBase { +public: + Assembler(void *address) : AssemblerBase(address) { + buffer_ = new CodeBuffer(); + } + ~Assembler() { + if (buffer_) + delete buffer_; + buffer_ = NULL; + } + +public: + void Emit1(byte_t val) { + buffer_->Emit8(val); + } + + void Emit(int32_t value) { + buffer_->Emit32(value); + } + + // --- + + void EmitImmediate(Immediate imm, int imm_size) { + if (imm_size == 8) { + buffer_->Emit8((uint8_t)imm.value()); + } else if (imm_size == 32) { + buffer_->Emit32((uint32_t)imm.value()); + } else { + UNREACHABLE(); + } + } + + // --- + + // ATTENTION: + // ModR/M == 8 registers and 24 addressing mode + + void Emit_OpEn_Register_MemOperand(Register dst, Address &operand) { + EmitModRM_Update_Register(operand.modrm(), dst); + buffer_->EmitBuffer(&operand.encoding_[1], operand.length_ - 1); + } + + void Emit_OpEn_Register_RegOperand(Register dst, Register src) { + EmitModRM_Register_Register(dst, src); + } + + void Emit_OpEn_MemOperand_Immediate(uint8_t extra_opcode, Address &operand, Immediate imm) { + EmitModRM_Update_ExtraOpcode(operand.modrm(), extra_opcode); + buffer_->EmitBuffer(&operand.encoding_[1], operand.length_ - 1); + EmitImmediate(imm, imm.size()); + } + + void Emit_OpEn_RegOperand_Immediate(uint8_t extra_opcode, Register reg, Immediate imm) { + EmitModRM_ExtraOpcode_Register(extra_opcode, reg); + EmitImmediate(imm, imm.size()); + } + + void Emit_OpEn_MemOperand(uint8_t extra_opcode, Address &operand) { + EmitModRM_Update_ExtraOpcode(operand.modrm(), extra_opcode); + buffer_->EmitBuffer(&operand.encoding_[1], operand.length_ - 1); + } + + void Emit_OpEn_RegOperand(uint8_t extra_opcode, Register reg) { + EmitModRM_ExtraOpcode_Register(extra_opcode, reg); + } + + // Encoding: OI + void Emit_OpEn_OpcodeRegister_Immediate(uint8_t opcode, Register dst, Immediate imm) { + EmitOpcode_Register(opcode, dst); + EmitImmediate(imm, imm.size()); + } + + // --- + + inline void EmitModRM(uint8_t Mod, uint8_t RegOpcode, uint8_t RM) { + uint8_t ModRM = 0; + ModRM |= Mod << 6; + ModRM |= RegOpcode << 3; + ModRM |= RM; + Emit1(ModRM); + } + + void EmitModRM_ExtraOpcode_Register(uint8_t extra_opcode, Register reg) { + EmitModRM(0b11, extra_opcode, reg.code()); + } + + void EmitModRM_Register_Register(Register reg1, Register reg2) { + EmitModRM(0b11, reg1.code(), reg2.code()); + } + + // update operand's ModRM + void EmitModRM_Update_Register(uint8_t modRM, Register reg) { + EmitModRM(ModRM_Mod(modRM), reg.code(), ModRM_RM(modRM)); + } + + // update operand's ModRM + void EmitModRM_Update_ExtraOpcode(uint8_t modRM, uint8_t extra_opcode) { + EmitModRM(ModRM_Mod(modRM), extra_opcode, ModRM_RM(modRM)); + } + + // --- + + void EmitOpcode(uint8_t opcode) { + Emit1(opcode); + } + + void EmitOpcode_Register(uint8_t opcode, Register reg) { + EmitOpcode(opcode | reg.code()); + } + + // --- + + void pushfq() { + Emit1(0x9C); + } + + void jmp(Immediate imm); + + void sub(Register dst, Immediate imm) { + DCHECK_EQ(dst.size(), 32); + + EmitOpcode(0x81); + + Emit_OpEn_RegOperand_Immediate(0x5, dst, imm); + } + + void add(Register dst, Immediate imm) { + DCHECK_EQ(dst.size(), 32); + + EmitOpcode(0x81); + + Emit_OpEn_RegOperand_Immediate(0x0, dst, imm); + } + + // MOV RAX, 0x320 + // 48 c7 c0 20 03 00 00 (MI encoding) + // 48 b8 20 03 00 00 00 00 00 00 (OI encoding) + void mov(Register dst, const Immediate imm) { + Emit_OpEn_OpcodeRegister_Immediate(0xb8, dst, imm); + } + + void mov(Address dst, const Immediate imm) { + EmitOpcode(0xc7); + + Emit_OpEn_MemOperand_Immediate(0x0, dst, imm); + } + + void mov(Register dst, Address src) { + EmitOpcode(0x8B); + + Emit_OpEn_Register_MemOperand(dst, src); + } + + void mov(Address dst, Register src) { + EmitOpcode(0x89); + + Emit_OpEn_Register_MemOperand(src, dst); + } + + void mov(Register dst, Register src) { + Emit1(0x8B); + + Emit_OpEn_Register_RegOperand(dst, src); + } + + void call(Address operand) { + EmitOpcode(0xFF); + + Emit_OpEn_MemOperand(0x2, operand); + } + + void call(Immediate imm) { + EmitOpcode(0xe8); + + EmitImmediate(imm, imm.size()); + } + + void call(Register reg) { + EmitOpcode(0xFF); + + Emit_OpEn_RegOperand(0x2, reg); + } + + void pop(Register reg) { + EmitOpcode_Register(0x58, reg); + } + + void push(Register reg) { + EmitOpcode_Register(0x50, reg); + } + + void ret() { + EmitOpcode(0xc3); + } + void nop() { + EmitOpcode(0x90); + } +}; + +class TurboAssembler : public Assembler { +public: + TurboAssembler(void *address) : Assembler(address) { + } + + ~TurboAssembler() { + } + + addr32_t CurrentIP(); + + void CallFunction(ExternalReference function) { + nop(); + MovRipToRegister(VOLATILE_REGISTER); + call(Address(VOLATILE_REGISTER, INT32_MAX)); + { + auto label = RelocLabel::withData(function.address()); + label->link_to(kDisp32_off_7, ip_offset()); + AppendRelocLabel(label); + } + nop(); + } + + void MovRipToRegister(Register dst) { + call(Immediate(0, 32)); + pop(dst); + } +}; + +} // namespace x86 +} // namespace zz \ No newline at end of file diff --git a/app/src/main/cpp/Dobby/source/core/assembler/assembler-x64.cc b/app/src/main/cpp/Dobby/source/core/assembler/assembler-x64.cc new file mode 100644 index 0000000..8441a11 --- /dev/null +++ b/app/src/main/cpp/Dobby/source/core/assembler/assembler-x64.cc @@ -0,0 +1,34 @@ +#include "platform_detect_macro.h" +#if defined(TARGET_ARCH_X64) + +#include "core/assembler/assembler-x64.h" + +using namespace zz::x64; + +void AssemblerPseudoLabel::link_confused_instructions(CodeBufferBase *buffer) { + CodeBuffer *_buffer = (CodeBuffer *)buffer; + + for (auto &ref_label_insn : ref_label_insns_) { + int64_t new_offset = pos() - ref_label_insn.pc_offset; + + if (ref_label_insn.link_type == kDisp32_off_9) { + // why 9 ? + // use `call` and `pop` get the runtime ip register + // but the ip register not the real call next insn + // it need add two insn length == 9 + int disp32_fix_pos = ref_label_insn.pc_offset - sizeof(int32_t); + _buffer->FixBindLabel(disp32_fix_pos, new_offset + 9); + } + } +} + +void Assembler::jmp(Immediate imm) { + buffer_->Emit8(0xE9); + buffer_->Emit32((int)imm.value()); +} + +addr64_t TurboAssembler::CurrentIP() { + return pc_offset() + (addr_t)realized_addr_; +} + +#endif \ No newline at end of file diff --git a/app/src/main/cpp/Dobby/source/core/assembler/assembler-x64.h b/app/src/main/cpp/Dobby/source/core/assembler/assembler-x64.h new file mode 100644 index 0000000..f94d94d --- /dev/null +++ b/app/src/main/cpp/Dobby/source/core/assembler/assembler-x64.h @@ -0,0 +1,596 @@ +#pragma once + +#include "dobby/common.h" + +#include "core/arch/x64/registers-x64.h" +#include "core/assembler/assembler.h" + +#include "MemoryAllocator/CodeBuffer/code_buffer_x64.h" + +#define IsInt8(imm) (-128 <= imm && imm <= 127) + +enum ref_label_type_t { kDisp32_off_9 }; + +namespace zz { +namespace x64 { + +constexpr Register VOLATILE_REGISTER = r11; + +#define ModRM_Mod(byte) ((byte & 0b11000000) >> 6) +#define ModRM_RegOpcode(byte) ((byte & 0b00111000) >> 3) +#define ModRM_RM(byte) (byte & 0b00000111) + +typedef union _ModRM { + byte_t ModRM; + struct { + byte_t RM : 3; + byte_t RegOpcode : 3; + byte_t Mod : 2; + }; +} ModRM; + +// --- + +class Immediate { +public: + explicit Immediate(int64_t imm) : value_(imm), value_size_(64) { + if ((int64_t)(int8_t)imm == imm) { + value_size_ = 8; + } else if ((int64_t)(int16_t)imm == imm) { + value_size_ = 8; + } else if ((int64_t)(int32_t)imm == imm) { + value_size_ = 32; + } else { + value_size_ = 64; + } + } + + explicit Immediate(int64_t imm, int size) : value_(imm), value_size_(size) { + } + + int64_t value() const { + return value_; + } + + int size() const { + return value_size_; + } + +private: + const int64_t value_; + + int value_size_; +}; + +// --- + +class Operand { +public: + // [base] + Operand(Register base); + + // [base + disp/r] + Operand(Register base, int32_t disp); + + // [base + index*scale + disp/r] + Operand(Register base, Register index, ScaleFactor scale, int32_t disp); + + // [index*scale + disp/r] + Operand(Register index, ScaleFactor scale, int32_t disp); + +public: // Getter and Setter + uint8_t rex() const { + return rex_; + } + + inline uint8_t rex_b() const { + return (rex_ & REX_B); + } + + inline uint8_t rex_x() const { + return (rex_ & REX_X); + } + + inline uint8_t rex_r() const { + return (rex_ & REX_R); + } + + inline uint8_t rex_w() const { + return (rex_ & REX_W); + } + + uint8_t modrm() { + return (encoding_at(0)); + } + + uint8_t mod() const { + return (encoding_at(0) >> 6) & 3; + } + + Register rm() const { + int rm_rex = rex_b() << 3; + return Register::from_code(rm_rex + (encoding_at(0) & 7)); + } + + ScaleFactor scale() const { + return static_cast((encoding_at(1) >> 6) & 3); + } + + Register index() const { + int index_rex = rex_x() << 2; + return Register::from_code(index_rex + ((encoding_at(1) >> 3) & 7)); + } + + Register base() const { + int base_rex = rex_b() << 3; + return Register::from_code(base_rex + (encoding_at(1) & 7)); + } + + int8_t disp8() const { + ASSERT(length_ >= 2); + return static_cast(encoding_[length_ - 1]); + } + + int32_t disp32() const { + ASSERT(length_ >= 5); + return static_cast(encoding_[length_ - 4]); + } + +protected: + Operand() : length_(0), rex_(REX_NONE) { + } // Needed by subclass Address. + + void SetModRM(int mod, Register rm) { + ASSERT((mod & ~3) == 0); + + if ((rm.code() > 7) && !((rm.Is(r12)) && (mod != 3))) { + rex_ |= REX_B; + } + encoding_[0] = (mod << 6) | (rm.code() & 7); + length_ = 1; + } + + void SetSIB(ScaleFactor scale, Register index, Register base) { + ASSERT(length_ == 1); + ASSERT((scale & ~3) == 0); + + if (base.code() > 7) { + ASSERT((rex_ & REX_B) == 0); // Must not have REX.B already set. + rex_ |= REX_B; + } + if (index.code() > 7) + rex_ |= REX_X; + + encoding_[1] = (scale << 6) | ((index.code() & 7) << 3) | (base.code() & 7); + length_ = 2; + } + + void SetDisp8(int8_t disp) { + ASSERT(length_ == 1 || length_ == 2); + + encoding_[length_++] = static_cast(disp); + } + + void SetDisp32(int32_t disp) { + ASSERT(length_ == 1 || length_ == 2); + + *(int32_t *)&encoding_[length_] = disp; + length_ += sizeof(disp); + } + +private: + // explicit Operand(Register reg) : rex_(REX_NONE) { SetModRM(3, reg); } + + // Get the operand encoding byte at the given index. + uint8_t encoding_at(intptr_t index) const { + ASSERT(index >= 0 && index < length_); + return encoding_[index]; + } + +public: + uint8_t length_; + uint8_t rex_; + uint8_t encoding_[6]; +}; + +// --- + +class Address : public Operand { +public: + Address(Register base, int32_t disp) { + int base_ = base.code(); + int rbp_ = rbp.code(); + int rsp_ = rsp.code(); + if ((disp == 0) && ((base_ & 7) != rbp_)) { + SetModRM(0, base); + if ((base_ & 7) == rsp_) { + SetSIB(TIMES_1, rsp, base); + } + } else if (IsInt8(disp)) { + SetModRM(1, base); + if ((base_ & 7) == rsp_) { + SetSIB(TIMES_1, rsp, base); + } + SetDisp8(disp); + } else { + SetModRM(2, base); + if ((base_ & 7) == rsp_) { + SetSIB(TIMES_1, rsp, base); + } + SetDisp32(disp); + } + } + + // This addressing mode does not exist. + Address(Register base, Register r); + + Address(Register index, ScaleFactor scale, int32_t disp) { + ASSERT(index.code() != rsp.code()); // Illegal addressing mode. + SetModRM(0, rsp); + SetSIB(scale, index, rbp); + SetDisp32(disp); + } + + // This addressing mode does not exist. + Address(Register index, ScaleFactor scale, Register r); + + Address(Register base, Register index, ScaleFactor scale, int32_t disp) { + ASSERT(index.code() != rsp.code()); // Illegal addressing mode. + int rbp_ = rbp.code(); + if ((disp == 0) && ((base.code() & 7) != rbp_)) { + SetModRM(0, rsp); + SetSIB(scale, index, base); + } else if (IsInt8(disp)) { + SetModRM(1, rsp); + SetSIB(scale, index, base); + SetDisp8(disp); + } else { + SetModRM(2, rsp); + SetSIB(scale, index, base); + SetDisp32(disp); + } + } + + // This addressing mode does not exist. + Address(Register base, Register index, ScaleFactor scale, Register r); + +private: + Address(Register base, int32_t disp, bool fixed) { + ASSERT(fixed); + + SetModRM(2, base); + if ((base.code() & 7) == rsp.code()) { + SetSIB(TIMES_1, rsp, base); + } + SetDisp32(disp); + } +}; + +// --- + +class Assembler : public AssemblerBase { +public: + Assembler(void *address) : AssemblerBase(address) { + buffer_ = new CodeBuffer(); + } + ~Assembler() { + if (buffer_) + delete buffer_; + buffer_ = NULL; + } + +public: + void Emit1(byte_t val) { + buffer_->Emit8(val); + } + + void Emit(int32_t value) { + buffer_->Emit32(value); + } + + void EmitInt64(int64_t value) { + buffer_->Emit64(value); + } + + // --- + + // refer android_art + uint8_t EmitOptionalRex(bool force, bool w, bool r, bool x, bool b) { + // REX.WRXB + // W - 64-bit operand + // R - MODRM.reg + // X - SIB.index + // B - MODRM.rm/SIB.base + + uint8_t rex = force ? 0x40 : 0; + if (w) { + rex |= 0x48; // REX.W000 + } + if (r) { + rex |= 0x44; // REX.0R00 + } + if (x) { + rex |= 0x42; // REX.00X0 + } + if (b) { + rex |= 0x41; // REX.000B + } + if (rex != 0) { + return rex; + } + return 0; + } + + void Emit_64REX(uint8_t extra) { + uint8_t rex = EmitOptionalRex(false, true, false, false, false); + rex |= extra; + if (rex) + Emit1(rex); + } + + void EmitREX_ExtraRegister(Register reg) { + uint8_t rex = EmitOptionalRex(false, reg.size() == 64, reg.code() > 7, false, reg.code() > 7); + if (rex) + Emit1(rex); + } + + void EmitREX_Register(Register reg) { + uint8_t rex = EmitOptionalRex(false, reg.size() == 64, reg.code() > 7, false, false); + if (rex) + Emit1(rex); + } + + void EmitREX_Register_Operand(Register reg, Operand &operand) { + if (reg.size() != 64) + UNIMPLEMENTED(); + uint8_t rex = operand.rex(); + rex |= EmitOptionalRex(true, reg.size() == 64, reg.code() > 7, false, false); + if (rex != 0) { + Emit1(rex); + } + } + + void EmitREX_Operand(Operand &operand) { + uint8_t rex = operand.rex(); + rex |= REX_PREFIX; + if (rex != 0) { + Emit1(rex); + } + } + + // --- + + void EmitImmediate(Immediate imm, int imm_size) { + if (imm_size == 8) { + buffer_->Emit8((uint8_t)imm.value()); + } else if (imm_size == 32) { + buffer_->Emit32((uint32_t)imm.value()); + } else if (imm_size == 64) { + buffer_->Emit64((uint64_t)imm.value()); + } else { + UNREACHABLE(); + } + } + + // --- + + // ATTENTION: + // ModR/M == 8 registers and 24 addressing mode + + void Emit_OpEn_Register_MemOperand(Register dst, Address &operand) { + EmitModRM_Update_Register(operand.modrm(), dst); + buffer_->EmitBuffer(&operand.encoding_[1], operand.length_ - 1); + } + + void Emit_OpEn_Register_RegOperand(Register dst, Register src) { + EmitModRM_Register_Register(dst, src); + } + + void Emit_OpEn_MemOperand_Immediate(uint8_t extra_opcode, Address &operand, Immediate imm) { + EmitModRM_Update_ExtraOpcode(operand.modrm(), extra_opcode); + buffer_->EmitBuffer(&operand.encoding_[1], operand.length_ - 1); + EmitImmediate(imm, imm.size()); + } + + void Emit_OpEn_RegOperand_Immediate(uint8_t extra_opcode, Register reg, Immediate imm) { + EmitModRM_ExtraOpcode_Register(extra_opcode, reg); + EmitImmediate(imm, imm.size()); + } + + void Emit_OpEn_MemOperand(uint8_t extra_opcode, Address &operand) { + EmitModRM_Update_ExtraOpcode(operand.modrm(), extra_opcode); + buffer_->EmitBuffer(&operand.encoding_[1], operand.length_ - 1); + } + + void Emit_OpEn_RegOperand(uint8_t extra_opcode, Register reg) { + EmitModRM_ExtraOpcode_Register(extra_opcode, reg); + } + + // Encoding: OI + void Emit_OpEn_OpcodeRegister_Immediate(uint8_t opcode, Register dst, Immediate imm) { + EmitOpcode_Register(opcode, dst); + EmitImmediate(imm, imm.size()); + } + + // --- + + inline void EmitModRM(uint8_t Mod, uint8_t RegOpcode, uint8_t RM) { + uint8_t ModRM = 0; + ModRM |= Mod << 6; + ModRM |= RegOpcode << 3; + ModRM |= RM; + Emit1(ModRM); + } + + void EmitModRM_ExtraOpcode_Register(uint8_t extra_opcode, Register reg) { + EmitModRM(0b11, extra_opcode, reg.code()); + } + + void EmitModRM_Register_Register(Register reg1, Register reg2) { + EmitModRM(0b11, reg1.code(), reg2.code()); + } + + // update operand's ModRM + void EmitModRM_Update_Register(uint8_t modRM, Register reg) { + EmitModRM(ModRM_Mod(modRM), reg.low_bits(), ModRM_RM(modRM)); + } + + // update operand's ModRM + void EmitModRM_Update_ExtraOpcode(uint8_t modRM, uint8_t extra_opcode) { + EmitModRM(ModRM_Mod(modRM), extra_opcode, ModRM_RM(modRM)); + } + + // --- + + void EmitOpcode(uint8_t opcode) { + Emit1(opcode); + } + + void EmitOpcode_Register(uint8_t opcode, Register reg) { + EmitOpcode(opcode | reg.low_bits()); + } + + // --- + + void pushfq() { + Emit1(0x9C); + } + + void jmp(Immediate imm); + + void sub(Register dst, Immediate imm) { + EmitREX_Register(dst); + + EmitOpcode(0x81); + + Emit_OpEn_RegOperand_Immediate(0x5, dst, imm); + } + + void add(Register dst, Immediate imm) { + EmitREX_Register(dst); + + EmitOpcode(0x81); + + Emit_OpEn_RegOperand_Immediate(0x0, dst, imm); + } + + // MOV RAX, 0x320 + // 48 c7 c0 20 03 00 00 (MI encoding) + // 48 b8 20 03 00 00 00 00 00 00 (OI encoding) + void mov(Register dst, const Immediate imm) { + EmitREX_Register(dst); + + Emit_OpEn_OpcodeRegister_Immediate(0xb8, dst, imm); + } + + void mov(Address dst, const Immediate imm) { + EmitREX_Operand(dst); + + EmitOpcode(0xc7); + + Emit_OpEn_MemOperand_Immediate(0x0, dst, imm); + } + + void mov(Register dst, Address src) { + EmitREX_Register(dst); + + EmitOpcode(0x8B); + + Emit_OpEn_Register_MemOperand(dst, src); + } + + void mov(Address dst, Register src) { + EmitREX_Register_Operand(src, dst); + + EmitOpcode(0x89); + + Emit_OpEn_Register_MemOperand(src, dst); + } + + void mov(Register dst, Register src) { + EmitREX_Register(dst); + + Emit1(0x8B); + + Emit_OpEn_Register_RegOperand(dst, src); + } + + void call(Address operand) { + EmitREX_Operand(operand); + + EmitOpcode(0xFF); + + Emit_OpEn_MemOperand(0x2, operand); + } + + void call(Immediate imm) { + EmitOpcode(0xe8); + + EmitImmediate(imm, imm.size()); + } + + void call(Register reg) { + EmitREX_Register(reg); + + EmitOpcode(0xFF); + + Emit_OpEn_RegOperand(0x2, reg); + } + + void pop(Register reg) { + EmitREX_ExtraRegister(reg); + + EmitOpcode_Register(0x58, reg); + } + + void push(Register reg) { + EmitREX_ExtraRegister(reg); + + EmitOpcode_Register(0x50, reg); + } + + void ret() { + EmitOpcode(0xc3); + } + void nop() { + EmitOpcode(0x90); + } +}; + +// --- + +class TurboAssembler : public Assembler { +public: + TurboAssembler(void *address) : Assembler(address) { + } + + ~TurboAssembler() { + } + + addr64_t CurrentIP(); + + void CallFunction(ExternalReference function) { +#if 0 + mov(r11, Immediate((int64_t)function.address(), 64)); + call(r11); +#endif + + nop(); + MovRipToRegister(VOLATILE_REGISTER); + call(Address(VOLATILE_REGISTER, INT32_MAX)); + { + auto label = RelocLabel::withData((uint64_t)function.address()); + label->link_to(kDisp32_off_9, ip_offset()); + this->AppendRelocLabel(label); + } + nop(); + } + + void MovRipToRegister(Register dst) { + call(Immediate(0, 32)); + pop(dst); + } +}; + +} // namespace x64 +} // namespace zz diff --git a/app/src/main/cpp/Dobby/source/core/assembler/assembler-x86-shared.cc b/app/src/main/cpp/Dobby/source/core/assembler/assembler-x86-shared.cc new file mode 100644 index 0000000..e81e063 --- /dev/null +++ b/app/src/main/cpp/Dobby/source/core/assembler/assembler-x86-shared.cc @@ -0,0 +1,17 @@ +#include "platform_detect_macro.h" +#if defined(TARGET_ARCH_X64) || defined(TARGET_ARCH_IA32) + +#include "core/assembler/assembler-x86-shared.h" + +using namespace zz::x86shared; + +void Assembler::jmp(Immediate imm) { + buffer_->Emit8(0xE9); + buffer_->Emit32((int)imm.value()); +} + +uint64_t TurboAssembler::CurrentIP() { + return pc_offset() + (addr_t)realized_addr_; +} + +#endif \ No newline at end of file diff --git a/app/src/main/cpp/Dobby/source/core/assembler/assembler-x86-shared.h b/app/src/main/cpp/Dobby/source/core/assembler/assembler-x86-shared.h new file mode 100644 index 0000000..2dcd87c --- /dev/null +++ b/app/src/main/cpp/Dobby/source/core/assembler/assembler-x86-shared.h @@ -0,0 +1,707 @@ +#pragma once + +#include "dobby/common.h" + +#include "core/arch/x64/registers-x64.h" +#include "core/assembler/assembler.h" + +#include "MemoryAllocator/CodeBuffer/code_buffer_x64.h" + +#include "xnucxx/LiteMutableArray.h" +#include "xnucxx/LiteIterator.h" + +#define IsInt8(imm) (-128 <= imm && imm <= 127) + +namespace zz { +namespace x86shared { + +using namespace x64; + +constexpr Register VOLATILE_REGISTER = r11; + +// ================================================================ +// AssemblerPseudoLabel + +class AssemblerPseudoLabel : public Label { +public: + enum PseudoLabelType { kDisp32_off_9 }; + + typedef struct _PseudoLabelInstruction { + int position_; + PseudoLabelType type_; + } PseudoLabelInstruction; + +public: + AssemblerPseudoLabel(void) { + instructions_.initWithCapacity(8); + } + ~AssemblerPseudoLabel(void) { + for (size_t i = 0; i < instructions_.getCount(); i++) { + PseudoLabelInstruction *item = (PseudoLabelInstruction *)instructions_.getObject(i); + delete item; + } + + instructions_.release(); + } + + bool has_confused_instructions() { + return instructions_.getCount() > 0; + } + + void link_confused_instructions(CodeBuffer *buffer = nullptr) { + if (!buffer) + UNREACHABLE(); + CodeBuffer *_buffer = buffer; + + for (size_t i = 0; i < instructions_.getCount(); i++) { + PseudoLabelInstruction *instruction = (PseudoLabelInstruction *)instructions_.getObject(i); + + int32_t offset = pos() - instruction->position_; + + switch (instruction->type_) { + case kDisp32_off_9: { + int disp32_fix_pos = instruction->position_ - sizeof(int32_t); + _buffer->FixBindLabel(disp32_fix_pos, offset + 9); + } break; + default: + UNREACHABLE(); + break; + } + } + }; + + void link_to(int pos, PseudoLabelType type) { + PseudoLabelInstruction *instruction = new PseudoLabelInstruction; + instruction->position_ = pos; + instruction->type_ = type; + instructions_.pushObject((LiteObject *)instruction); + } + +private: + LiteMutableArray instructions_; +}; + +class RelocLabel : public AssemblerPseudoLabel { +public: + explicit RelocLabel(uint64_t data) : data_size_(0) { + data_ = data; + } + + uint64_t data() { + return data_; + } + +private: + uint64_t data_; + + int data_size_; +}; + +#define ModRM_Mod(byte) ((byte & 0b11000000) >> 6) +#define ModRM_RegOpcode(byte) ((byte & 0b00111000) >> 3) +#define ModRM_RM(byte) (byte & 0b00000111) + +typedef union _ModRM { + byte_t ModRM; + struct { + byte_t RM : 3; + byte_t RegOpcode : 3; + byte_t Mod : 2; + }; +} ModRM; + +// ================================================================ +// Immediate + +class Immediate { +public: + explicit Immediate(int64_t imm) : value_(imm), value_size_(64) { + if ((int64_t)(int8_t)imm == imm) { + value_size_ = 8; + } else if ((int64_t)(int16_t)imm == imm) { + value_size_ = 8; + } else if ((int64_t)(int32_t)imm == imm) { + value_size_ = 32; + } else { + value_size_ = 64; + } + } + + explicit Immediate(int64_t imm, int size) : value_(imm), value_size_(size) { + } + + int64_t value() const { + return value_; + } + + int size() const { + return value_size_; + } + +private: + const int64_t value_; + + int value_size_; +}; + +// ================================================================ +// Operand + +class Operand { +public: + // [base] + Operand(Register base); + + // [base + disp/r] + Operand(Register base, int32_t disp); + + // [base + index*scale + disp/r] + Operand(Register base, Register index, ScaleFactor scale, int32_t disp); + + // [index*scale + disp/r] + Operand(Register index, ScaleFactor scale, int32_t disp); + +public: // Getter and Setter + uint8_t rex() const { + return rex_; + } + + inline uint8_t rex_b() const { + return (rex_ & REX_B); + } + + inline uint8_t rex_x() const { + return (rex_ & REX_X); + } + + inline uint8_t rex_r() const { + return (rex_ & REX_R); + } + + inline uint8_t rex_w() const { + return (rex_ & REX_W); + } + + uint8_t modrm() { + return (encoding_at(0)); + } + + uint8_t mod() const { + return (encoding_at(0) >> 6) & 3; + } + + Register rm() const { + int rm_rex = rex_b() << 3; + return Register::from_code(rm_rex + (encoding_at(0) & 7)); + } + + ScaleFactor scale() const { + return static_cast((encoding_at(1) >> 6) & 3); + } + + Register index() const { + int index_rex = rex_x() << 2; + return Register::from_code(index_rex + ((encoding_at(1) >> 3) & 7)); + } + + Register base() const { + int base_rex = rex_b() << 3; + return Register::from_code(base_rex + (encoding_at(1) & 7)); + } + + int8_t disp8() const { + ASSERT(length_ >= 2); + return static_cast(encoding_[length_ - 1]); + } + + int32_t disp32() const { + ASSERT(length_ >= 5); + return static_cast(encoding_[length_ - 4]); + } + +protected: + Operand() : length_(0), rex_(REX_NONE) { + } // Needed by subclass Address. + + void SetModRM(int mod, Register rm) { + ASSERT((mod & ~3) == 0); + + if ((rm.code() > 7) && !((rm.Is(r12)) && (mod != 3))) { + rex_ |= REX_B; + } + encoding_[0] = (mod << 6) | (rm.code() & 7); + length_ = 1; + } + + void SetSIB(ScaleFactor scale, Register index, Register base) { + ASSERT(length_ == 1); + ASSERT((scale & ~3) == 0); + + if (base.code() > 7) { + ASSERT((rex_ & REX_B) == 0); // Must not have REX.B already set. + rex_ |= REX_B; + } + if (index.code() > 7) + rex_ |= REX_X; + encoding_[1] = (scale << 6) | ((index.code() & 7) << 3) | (base.code() & 7); + length_ = 2; + } + + void SetDisp8(int8_t disp) { + ASSERT(length_ == 1 || length_ == 2); + + encoding_[length_++] = static_cast(disp); + } + + void SetDisp32(int32_t disp) { + ASSERT(length_ == 1 || length_ == 2); + + *(int32_t *)&encoding_[length_] = disp; + length_ += sizeof(disp); + } + +private: + // explicit Operand(Register reg) : rex_(REX_NONE) { SetModRM(3, reg); } + + // Get the operand encoding byte at the given index. + uint8_t encoding_at(intptr_t index) const { + ASSERT(index >= 0 && index < length_); + return encoding_[index]; + } + +public: + uint8_t length_; + uint8_t rex_; + uint8_t encoding_[6]; +}; + +// ================================================================ +// Address + +class Address : public Operand { +public: + Address(Register base, int32_t disp) { + int base_ = base.code(); + int rbp_ = rbp.code(); + int rsp_ = rsp.code(); + if ((disp == 0) && ((base_ & 7) != rbp_)) { + SetModRM(0, base); + if ((base_ & 7) == rsp_) { + SetSIB(TIMES_1, rsp, base); + } + } else if (IsInt8(disp)) { + SetModRM(1, base); + if ((base_ & 7) == rsp_) { + SetSIB(TIMES_1, rsp, base); + } + SetDisp8(disp); + } else { + SetModRM(2, base); + if ((base_ & 7) == rsp_) { + SetSIB(TIMES_1, rsp, base); + } + SetDisp32(disp); + } + } + + // This addressing mode does not exist. + Address(Register base, Register r); + + Address(Register index, ScaleFactor scale, int32_t disp) { + ASSERT(index.code() != rsp.code()); // Illegal addressing mode. + SetModRM(0, rsp); + SetSIB(scale, index, rbp); + SetDisp32(disp); + } + + // This addressing mode does not exist. + Address(Register index, ScaleFactor scale, Register r); + + Address(Register base, Register index, ScaleFactor scale, int32_t disp) { + ASSERT(index.code() != rsp.code()); // Illegal addressing mode. + int rbp_ = rbp.code(); + if ((disp == 0) && ((base.code() & 7) != rbp_)) { + SetModRM(0, rsp); + SetSIB(scale, index, base); + } else if (IsInt8(disp)) { + SetModRM(1, rsp); + SetSIB(scale, index, base); + SetDisp8(disp); + } else { + SetModRM(2, rsp); + SetSIB(scale, index, base); + SetDisp32(disp); + } + } + + // This addressing mode does not exist. + Address(Register base, Register index, ScaleFactor scale, Register r); + +private: + Address(Register base, int32_t disp, bool fixed) { + ASSERT(fixed); + SetModRM(2, base); + if ((base.code() & 7) == rsp.code()) { + SetSIB(TIMES_1, rsp, base); + } + SetDisp32(disp); + } +}; + +// ================================================================ +// Assembler + +class Assembler : public AssemblerBase { +public: + Assembler(void *address, int mode) : AssemblerBase(address) : mode_(mode) { + buffer_ = new CodeBuffer(); + } + ~Assembler() { + if (buffer_) + delete buffer_; + buffer_ = NULL + } + +public: + void Emit1(byte_t val) { + buffer_->Emit8(val); + } + + void Emit(int32_t value) { + buffer_->Emit32(value); + } + + void EmitInt64(int64_t value) { + buffer_->Emit64(value); + } + + void EmitAddr(uint64_t addr) { + if (mode == 64) { + EmitInt64(int64_t)addr); + } else { + EmitI((int32_t)addr); + } + } + + // ================================================================ + // REX + + // refer android_art + uint8_t EmitOptionalRex(bool force, bool w, bool r, bool x, bool b) { + // REX.WRXB + // W - 64-bit operand + // R - MODRM.reg + // X - SIB.index + // B - MODRM.rm/SIB.base + + uint8_t rex = force ? 0x40 : 0; + if (w) { + rex |= 0x48; // REX.W000 + } + if (r) { + rex |= 0x44; // REX.0R00 + } + if (x) { + rex |= 0x42; // REX.00X0 + } + if (b) { + rex |= 0x41; // REX.000B + } + if (rex != 0) { + return rex; + } + return 0; + } + + void Emit_64REX(uint8_t extra) { + uint8_t rex = EmitOptionalRex(false, true, false, false, false); + rex |= extra; + if (rex) + Emit1(rex); + } + + void EmitREX_ExtraRegister(Register reg) { + uint8_t rex = EmitOptionalRex(false, reg.size() == 64, reg.code() > 7, false, reg.code() > 7); + if (rex) + Emit1(rex); + } + + void EmitREX_Register(Register reg) { + uint8_t rex = EmitOptionalRex(false, reg.size() == 64, reg.code() > 7, false, false); + if (rex) + Emit1(rex); + } + + void EmitREX_Register_Operand(Register reg, Operand &operand) { + if (reg.size() != 64) + UNIMPLEMENTED(); + uint8_t rex = operand.rex(); + rex |= EmitOptionalRex(true, reg.size() == 64, reg.code() > 7, false, false); + if (rex != 0) { + Emit1(rex); + } + } + + void EmitREX_Operand(Operand &operand) { + uint8_t rex = operand.rex(); + rex |= REX_PREFIX; + if (rex != 0) { + Emit1(rex); + } + } + + // ================================================================ + // Immediate + + void EmitImmediate(Immediate imm, int imm_size) { + if (imm_size == 8) { + buffer_->Emit8((uint8_t)imm.value()); + } else if (imm_size == 32) { + buffer_->Emit32((uint32_t)imm.value()); + } else if (imm_size == 64) { + buffer_->Emit64((uint64_t)imm.value()); + } else { + UNREACHABLE(); + } + } + + // ================================================================ + // Operand Encoding + + // ATTENTION: + // ModR/M == 8 registers and 24 addressing mode + + // RM or MR + void Emit_OpEn_Register_MemOperand(Register dst, Address &operand) { + EmitModRM_Update_Register(operand.modrm(), dst); + buffer_->EmitBuffer(&operand.encoding_[1], operand.length_ - 1); + } + void Emit_OpEn_Register_RegOperand(Register dst, Register src) { + EmitModRM_Register_Register(dst, src); + } + + void Emit_OpEn_MemOperand_Immediate(uint8_t extra_opcode, Address &operand, Immediate imm) { + } + void Emit_OpEn_RegOperand_Immediate(uint8_t extra_opcode, Register reg, Immediate imm) { + EmitModRM_ExtraOpcode_Register(extra_opcode, reg); + EmitImmediate(imm, imm.size()); + } + + void Emit_OpEn_MemOperand(uint8_t extra_opcode, Address &operand) { + EmitModRM_Update_ExtraOpcode(operand.modrm(), extra_opcode); + buffer_->EmitBuffer(&operand.encoding_[1], operand.length_ - 1); + } + void Emit_OpEn_RegOperand(uint8_t extra_opcode, Register reg) { + EmitModRM_ExtraOpcode_Register(extra_opcode, reg); + } + + // Encoding: OI + void Emit_OpEn_OpcodeRegister_Immediate(uint8_t opcode, Register dst, Immediate imm) { + EmitOpcode_Register(opcode, dst); + EmitImmediate(imm, imm.size()); + } + + // ================================================================ + // ModRM + + inline void EmitModRM(uint8_t Mod, uint8_t RegOpcode, uint8_t RM) { + uint8_t ModRM = 0; + ModRM |= Mod << 6; + ModRM |= RegOpcode << 3; + ModRM |= RM; + Emit1(ModRM); + } + + void EmitModRM_ExtraOpcode_Register(uint8_t extra_opcode, Register reg) { + EmitModRM(0b11, extra_opcode, reg.code()); + } + + void EmitModRM_Register_Register(Register reg1, Register reg2) { + EmitModRM(0b11, reg1.code(), reg2.code()); + } + + // update operand's ModRM + void EmitModRM_Update_Register(uint8_t modRM, Register reg) { + EmitModRM(ModRM_Mod(modRM), reg.low_bits(), ModRM_RM(modRM)); + } + + // update operand's ModRM + void EmitModRM_Update_ExtraOpcode(uint8_t modRM, uint8_t extra_opcode) { + EmitModRM(ModRM_Mod(modRM), extra_opcode, ModRM_RM(modRM)); + } + + // ================================================================ + // Opcode + void EmitOpcode(uint8_t opcode) { + Emit1(opcode); + } + + void EmitOpcode_Register(uint8_t opcode, Register reg) { + EmitOpcode(opcode | reg.low_bits()); + } + + // ================================================================ + // Instruction + + void pushfq() { + Emit1(0x9C); + } + + void jmp(Immediate imm); + + void sub(Register dst, Immediate imm) { + EmitREX_Register(dst); + EmitOpcode(0x81); + Emit_OpEn_RegOperand_Immediate(0x5, dst, imm); + } + + void add(Register dst, Immediate imm) { + EmitREX_Register(dst); + EmitOpcode(0x81); + Emit_OpEn_RegOperand_Immediate(0x0, dst, imm); + } + + // MOV RAX, 0x320 + // 48 c7 c0 20 03 00 00 (MI encoding) + // 48 b8 20 03 00 00 00 00 00 00 (OI encoding) + void mov(Register dst, const Immediate imm) { + EmitREX_Register(dst); + + // OI encoding + Emit_OpEn_OpcodeRegister_Immediate(0xb8, dst, imm); + } + + void mov(Register dst, Address src) { + EmitREX_Register(dst); + + EmitOpcode(0x8B); + + Emit_OpEn_Register_MemOperand(dst, src); + } + + void mov(Address dst, Register src) { + EmitREX_Register_Operand(src, dst); + EmitOpcode(0x89); + Emit_OpEn_Register_MemOperand(src, dst); + } + + void mov(Register dst, Register src) { + EmitREX_Register(dst); + + Emit1(0x8B); + + Emit_OpEn_Register_RegOperand(dst, src); + } + + void call(Address operand) { + EmitREX_Operand(operand); + + EmitOpcode(0xFF); + + Emit_OpEn_MemOperand(0x2, operand); + } + + void call(Immediate imm) { + EmitOpcode(0xe8); + EmitImmediate(imm, imm.size()); + } + + void call(Register reg) { + EmitREX_Register(reg); + EmitOpcode(0xFF); + Emit_OpEn_RegOperand(0x2, reg); + } + + void pop(Register reg) { + EmitREX_ExtraRegister(reg); + EmitOpcode_Register(0x58, reg); + } + + void push(Register reg) { + EmitREX_ExtraRegister(reg); + EmitOpcode_Register(0x50, reg); + } + + void ret() { + EmitOpcode(0xc3); + } + void nop() { + EmitOpcode(0x90); + } + +private: + int mode_; +}; + +// ================================================================ +// TurboAssembler + +class TurboAssembler : public Assembler { +public: + TurboAssembler(void *address, int mode) : Assembler(address, mode) { + data_labels_ = NULL; + } + + addr64_t CurrentIP(); + + void CallFunction(ExternalReference function) { +#if 0 + mov(r11, Immediate((int64_t)function.address(), 64)); + call(r11); +#endif + + nop(); + MovRipToRegister(VOLATILE_REGISTER); + call(Address(VOLATILE_REGISTER, INT32_MAX)); + { + RelocLabel *addrLabel = new RelocLabel((uint64_t)function.address()); + addrLabel->link_to(ip_offset(), AssemblerPseudoLabel::kDisp32_off_9); + this->AppendRelocLabel(addrLabel); + } + nop(); + } + + void MovRipToRegister(Register dst) { + call(Immediate(0, 32)); + pop(dst); + } + + // ================================================================ + // RelocLabel + + void PseudoBind(AssemblerPseudoLabel *label) { + const addr_t bound_pc = buffer_->GetBufferSize(); + label->bind_to(bound_pc); + // If some instructions have been wrote, before the label bound, we need link these `confused` instructions + if (label->has_confused_instructions()) { + label->link_confused_instructions(reinterpret_cast(this->GetCodeBuffer())); + } + } + + void RelocBind() { + if (data_labels_ == NULL) + return; + for (size_t i = 0; i < data_labels_->getCount(); i++) { + RelocLabel *label = (RelocLabel *)data_labels_->getObject(i); + PseudoBind(label); + EmitAddr(label->data()); + } + } + + void AppendRelocLabel(RelocLabel *label) { + if (data_labels_ == NULL) { + data_labels_ = new LiteMutableArray(8); + } + data_labels_->pushObject((LiteObject *)label); + } + + LiteMutableArray *GetLabels() { + return data_labels_; + } + +private: + LiteMutableArray *data_labels_; +}; + +} // namespace x86shared +} // namespace zz \ No newline at end of file diff --git a/app/src/main/cpp/Dobby/source/core/assembler/assembler.cc b/app/src/main/cpp/Dobby/source/core/assembler/assembler.cc new file mode 100644 index 0000000..30192bf --- /dev/null +++ b/app/src/main/cpp/Dobby/source/core/assembler/assembler.cc @@ -0,0 +1,64 @@ +#include "core/assembler/assembler.h" +#include "logging/logging.h" + +namespace zz { + +const void *ExternalReference::address() { + return address_; +} + +AssemblerBase::AssemblerBase(void *address) { + realized_addr_ = address; + buffer_ = nullptr; +} + +AssemblerBase::~AssemblerBase() { + buffer_ = nullptr; +} + +size_t AssemblerBase::ip_offset() const { + return reinterpret_cast(buffer_)->GetBufferSize(); +} + +size_t AssemblerBase::pc_offset() const { + return reinterpret_cast(buffer_)->GetBufferSize(); +} + +CodeBuffer *AssemblerBase::GetCodeBuffer() { + return buffer_; +} + +void AssemblerBase::PseudoBind(AssemblerPseudoLabel *label) { + auto pc_offset = reinterpret_cast(buffer_)->GetBufferSize(); + label->bind_to(pc_offset); + if (label->has_confused_instructions()) { + label->link_confused_instructions(reinterpret_cast(buffer_)); + } +} + +void AssemblerBase::RelocBind() { + for (auto *data_label : data_labels_) { + PseudoBind(data_label); + reinterpret_cast(buffer_)->EmitBuffer(data_label->data_, data_label->data_size_); + } +} + +void AssemblerBase::AppendRelocLabel(RelocLabel *label) { + data_labels_.push_back(label); +} + +void AssemblerBase::SetRealizedAddress(void *address) { + realized_addr_ = address; +} + +void *AssemblerBase::GetRealizedAddress() { + return realized_addr_; +} + +void AssemblerBase::FlushICache(addr_t start, int size) { +} + +void AssemblerBase::FlushICache(addr_t start, addr_t end) { +} + +} // namespace zz diff --git a/app/src/main/cpp/Dobby/source/core/assembler/assembler.h b/app/src/main/cpp/Dobby/source/core/assembler/assembler.h new file mode 100644 index 0000000..e3e22df --- /dev/null +++ b/app/src/main/cpp/Dobby/source/core/assembler/assembler.h @@ -0,0 +1,74 @@ +#pragma once + +#include "MemoryAllocator/CodeBuffer/CodeBufferBase.h" + +#include "AssemblerPseudoLabel.h" + +class CodeBuffer; + +namespace zz { + +class ExternalReference { +public: + explicit ExternalReference(void *address) : address_(address) { +#if defined(__APPLE__) && __arm64e__ + address_ = pac_strip((void *)address_); +#endif + } + + const void *address(); + +private: + const void *address_; +}; + +class AssemblerBase { +public: + explicit AssemblerBase(void *address); + + ~AssemblerBase(); + + size_t ip_offset() const; + + size_t pc_offset() const; + + CodeBuffer *GetCodeBuffer(); + + void PseudoBind(AssemblerPseudoLabel *label); + + void RelocBind(); + + void AppendRelocLabel(RelocLabel *label); + +protected: + tinystl::vector data_labels_; + +public: + virtual void *GetRealizedAddress(); + + virtual void SetRealizedAddress(void *address); + + static void FlushICache(addr_t start, int size); + + static void FlushICache(addr_t start, addr_t end); + +protected: + CodeBuffer *buffer_; + + void *realized_addr_; +}; + +} // namespace zz + +#if 0 +#include "globals.h" +#if TARGET_ARCH_ARM +#include "core/assembler/assembler-arm.h" +#elif TARGET_ARCH_ARM64 +#include "core/assembler/assembler-arm64.h" +#elif TARGET_ARCH_X64 +#include "core/assembler/assembler-x64.h" +#else +#error "unsupported architecture" +#endif +#endif \ No newline at end of file diff --git a/app/src/main/cpp/Dobby/source/core/codegen/codegen-arm.cc b/app/src/main/cpp/Dobby/source/core/codegen/codegen-arm.cc new file mode 100644 index 0000000..926d901 --- /dev/null +++ b/app/src/main/cpp/Dobby/source/core/codegen/codegen-arm.cc @@ -0,0 +1,19 @@ +#include "platform_detect_macro.h" +#if defined(TARGET_ARCH_ARM) + +#include "core/codegen/codegen-arm.h" + +namespace zz { +namespace arm { + +void CodeGen::LiteralLdrBranch(uint32_t address) { + TurboAssembler *turbo_assembler_ = reinterpret_cast(this->assembler_); +#define _ turbo_assembler_-> + _ ldr(pc, MemOperand(pc, -4)); + turbo_assembler_->GetCodeBuffer()->Emit32((addr_t)address); +} + +} // namespace arm +} // namespace zz + +#endif \ No newline at end of file diff --git a/app/src/main/cpp/Dobby/source/core/codegen/codegen-arm.h b/app/src/main/cpp/Dobby/source/core/codegen/codegen-arm.h new file mode 100644 index 0000000..9f87202 --- /dev/null +++ b/app/src/main/cpp/Dobby/source/core/codegen/codegen-arm.h @@ -0,0 +1,22 @@ +#ifndef CORE_CODEGEN_ARM_H +#define CORE_CODEGEN_ARM_H + +#include "core/codegen/codegen.h" +#include "core/assembler/assembler.h" +#include "core/assembler/assembler-arm.h" + +namespace zz { +namespace arm { + +class CodeGen : public CodeGenBase { +public: + CodeGen(TurboAssembler *turbo_assembler) : CodeGenBase(turbo_assembler) { + } + + void LiteralLdrBranch(uint32_t address); +}; + +} // namespace arm +} // namespace zz + +#endif \ No newline at end of file diff --git a/app/src/main/cpp/Dobby/source/core/codegen/codegen-arm64.cc b/app/src/main/cpp/Dobby/source/core/codegen/codegen-arm64.cc new file mode 100644 index 0000000..8e82718 --- /dev/null +++ b/app/src/main/cpp/Dobby/source/core/codegen/codegen-arm64.cc @@ -0,0 +1,26 @@ +#include "platform_detect_macro.h" +#if defined(TARGET_ARCH_ARM64) + +#include "dobby/dobby_internal.h" +#include "core/codegen/codegen-arm64.h" + +namespace zz { +namespace arm64 { + +void CodeGen::LiteralLdrBranch(uint64_t address) { + auto turbo_assembler_ = reinterpret_cast(this->assembler_); +#define _ turbo_assembler_-> + + auto label = RelocLabel::withData(address); + turbo_assembler_->AppendRelocLabel(label); + + _ Ldr(TMP_REG_0, label); + _ br(TMP_REG_0); + +#undef _ +} + +} // namespace arm64 +} // namespace zz + +#endif diff --git a/app/src/main/cpp/Dobby/source/core/codegen/codegen-arm64.h b/app/src/main/cpp/Dobby/source/core/codegen/codegen-arm64.h new file mode 100644 index 0000000..99dafb3 --- /dev/null +++ b/app/src/main/cpp/Dobby/source/core/codegen/codegen-arm64.h @@ -0,0 +1,21 @@ +#ifndef CORE_CODEGEN_ARM64_H +#define CORE_CODEGEN_ARM64_H + +#include "core/codegen/codegen.h" +#include "core/assembler/assembler.h" +#include "core/assembler/assembler-arm64.h" + +namespace zz { +namespace arm64 { + +class CodeGen : public CodeGenBase { +public: + CodeGen(TurboAssembler *turbo_assembler) : CodeGenBase(turbo_assembler) { + } + void LiteralLdrBranch(uint64_t address); +}; + +} // namespace arm64 +} // namespace zz + +#endif \ No newline at end of file diff --git a/app/src/main/cpp/Dobby/source/core/codegen/codegen-ia32.cc b/app/src/main/cpp/Dobby/source/core/codegen/codegen-ia32.cc new file mode 100644 index 0000000..821137f --- /dev/null +++ b/app/src/main/cpp/Dobby/source/core/codegen/codegen-ia32.cc @@ -0,0 +1,23 @@ +#include "platform_detect_macro.h" +#if defined(TARGET_ARCH_IA32) + +#include "core/codegen/codegen-ia32.h" + +namespace zz { +namespace x86 { + +void CodeGen::JmpNear(uint32_t address) { + TurboAssembler *turbo_assembler_ = reinterpret_cast(this->assembler_); +#define _ turbo_assembler_-> +#define __ turbo_assembler_->GetCodeBuffer()-> + uint32_t currIP = turbo_assembler_->CurrentIP() + 5; + int32_t offset = (int32_t)(address - currIP); + + __ Emit8(0xe9); + __ Emit32(offset); +} + +} // namespace x86 +} // namespace zz + +#endif \ No newline at end of file diff --git a/app/src/main/cpp/Dobby/source/core/codegen/codegen-ia32.h b/app/src/main/cpp/Dobby/source/core/codegen/codegen-ia32.h new file mode 100644 index 0000000..5ad42bc --- /dev/null +++ b/app/src/main/cpp/Dobby/source/core/codegen/codegen-ia32.h @@ -0,0 +1,22 @@ +#ifndef CORE_CODEGEN_X86_H +#define CORE_CODEGEN_X86_H + +#include "core/codegen/codegen.h" +#include "core/assembler/assembler.h" +#include "core/assembler/assembler-ia32.h" + +namespace zz { +namespace x86 { + +class CodeGen : public CodeGenBase { +public: + CodeGen(TurboAssembler *turbo_assembler) : CodeGenBase(turbo_assembler) { + } + + void JmpNear(uint32_t address); +}; + +} // namespace x86 +} // namespace zz + +#endif \ No newline at end of file diff --git a/app/src/main/cpp/Dobby/source/core/codegen/codegen-x64.cc b/app/src/main/cpp/Dobby/source/core/codegen/codegen-x64.cc new file mode 100644 index 0000000..ad6d660 --- /dev/null +++ b/app/src/main/cpp/Dobby/source/core/codegen/codegen-x64.cc @@ -0,0 +1,25 @@ +#include "platform_detect_macro.h" +#if defined(TARGET_ARCH_X64) + +#include "core/codegen/codegen-x64.h" + +namespace zz { +namespace x64 { + +void CodeGen::JmpNearIndirect(addr_t forward_stub_addr) { + TurboAssembler *turbo_assembler_ = reinterpret_cast(this->assembler_); +#define _ turbo_assembler_-> +#define __ turbo_assembler_->GetCodeBuffer()-> + uint64_t currIP = turbo_assembler_->CurrentIP() + 6; + int32_t offset = (int32_t)(forward_stub_addr - currIP); + + // jmp *(rip + disp32) + __ Emit8(0xFF); + __ Emit8(0x25); // ModR/M: 00 100 101 + __ Emit32(offset); +} + +} // namespace x64 +} // namespace zz + +#endif \ No newline at end of file diff --git a/app/src/main/cpp/Dobby/source/core/codegen/codegen-x64.h b/app/src/main/cpp/Dobby/source/core/codegen/codegen-x64.h new file mode 100644 index 0000000..5fbbc1f --- /dev/null +++ b/app/src/main/cpp/Dobby/source/core/codegen/codegen-x64.h @@ -0,0 +1,22 @@ +#ifndef CORE_CODEGEN_X64_H +#define CORE_CODEGEN_X64_H + +#include "core/codegen/codegen.h" +#include "core/assembler/assembler.h" +#include "core/assembler/assembler-x64.h" + +namespace zz { +namespace x64 { + +class CodeGen : public CodeGenBase { +public: + CodeGen(TurboAssembler *turbo_assembler) : CodeGenBase(turbo_assembler) { + } + + void JmpNearIndirect(addr_t forward_stub_addr); +}; + +} // namespace x64 +} // namespace zz + +#endif \ No newline at end of file diff --git a/app/src/main/cpp/Dobby/source/core/codegen/codegen.h b/app/src/main/cpp/Dobby/source/core/codegen/codegen.h new file mode 100644 index 0000000..e75d193 --- /dev/null +++ b/app/src/main/cpp/Dobby/source/core/codegen/codegen.h @@ -0,0 +1,17 @@ +#ifndef CORE_CODEGEN_H +#define CORE_CODEGEN_H + +#include "core/assembler/assembler.h" + +using namespace zz; + +class CodeGenBase { +public: + CodeGenBase(AssemblerBase *assembler) : assembler_(assembler) { + } + +protected: + AssemblerBase *assembler_; +}; + +#endif \ No newline at end of file diff --git a/app/src/main/cpp/Dobby/source/core/emulator/dummy.cc b/app/src/main/cpp/Dobby/source/core/emulator/dummy.cc new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/cpp/Dobby/source/dobby.cpp b/app/src/main/cpp/Dobby/source/dobby.cpp new file mode 100644 index 0000000..c843796 --- /dev/null +++ b/app/src/main/cpp/Dobby/source/dobby.cpp @@ -0,0 +1,31 @@ +#include "dobby/dobby_internal.h" +#include "Interceptor.h" + +__attribute__((constructor)) static void ctor() { + DEBUG_LOG("================================"); + DEBUG_LOG("Dobby"); + DEBUG_LOG("dobby in debug log mode, disable with cmake flag \"-DDOBBY_DEBUG=OFF\""); + DEBUG_LOG("================================"); +} + +PUBLIC const char *DobbyGetVersion() { + return __DOBBY_BUILD_VERSION__; +} + +PUBLIC int DobbyDestroy(void *address) { +#if defined(TARGET_ARCH_ARM) + if ((addr_t)address % 2) { + address = (void *)((addr_t)address - 1); + } +#endif + auto entry = Interceptor::SharedInstance()->find((addr_t)address); + if (entry) { + uint8_t *buffer = entry->origin_insns; + uint32_t buffer_size = entry->origin_insn_size; + DobbyCodePatch(address, buffer, buffer_size); + Interceptor::SharedInstance()->remove((addr_t)address); + return 0; + } + + return -1; +} diff --git a/app/src/main/cpp/Dobby/source/dobby/common.h b/app/src/main/cpp/Dobby/source/dobby/common.h new file mode 100644 index 0000000..94d897b --- /dev/null +++ b/app/src/main/cpp/Dobby/source/dobby/common.h @@ -0,0 +1,11 @@ +#pragma once + +#include "dobby.h" +#include "dobby/types.h" +#include "dobby/platform_features.h" +#include "dobby/platform_detect_macro.h" +#include "dobby/utility_macro.h" +#include "dobby/pac_kit.h" + +#include "logging/logging.h" +#include "logging/check_logging.h" \ No newline at end of file diff --git a/app/src/main/cpp/Dobby/source/dobby/dobby_internal.h b/app/src/main/cpp/Dobby/source/dobby/dobby_internal.h new file mode 100644 index 0000000..26e9912 --- /dev/null +++ b/app/src/main/cpp/Dobby/source/dobby/dobby_internal.h @@ -0,0 +1,13 @@ +#pragma once + +#include "dobby/common.h" + +#include "UnifiedInterface/platform.h" + +#include "PlatformUnifiedInterface/MemoryAllocator.h" +#include "PlatformUnifiedInterface/ExecMemory/CodePatchTool.h" +#include "PlatformUnifiedInterface/ExecMemory/ClearCacheTool.h" + +#include "MemoryAllocator/AssemblyCodeBuilder.h" + +#include "InterceptRouting/InterceptRouting.h" \ No newline at end of file diff --git a/app/src/main/cpp/Dobby/source/dobby/kernel_mode_header.h b/app/src/main/cpp/Dobby/source/dobby/kernel_mode_header.h new file mode 100644 index 0000000..66d7a1a --- /dev/null +++ b/app/src/main/cpp/Dobby/source/dobby/kernel_mode_header.h @@ -0,0 +1,57 @@ +#pragma once + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef void *vm_map_entry_t; +extern vm_map_t kernel_map; + +typedef void *pmap_paddr_t; +struct pmap; +typedef struct pmap *pmap_t; +extern pmap_t kernel_pmap; + +extern task_t kernel_task; + +#ifdef __cplusplus +} +#endif + +// ----- pmap ----- + +typedef void *pmap_paddr_t; +struct pmap; +typedef struct pmap *pmap_t; + +typedef uint64_t vaddr_t; +typedef uint64_t paddr_t; + +struct pmap; +typedef struct pmap *pmap_t; + +#ifdef __cplusplus +extern "C" { +#endif + +extern pmap_t kernel_pmap; + +void pmap_kit_init(); + +paddr_t pmap_kit_kvtophys(pmap_t pmap, vaddr_t va); + +int pmap_kit_set_perm(pmap_t pmap, vaddr_t start, vaddr_t end, unsigned int prot); + +#define cppvPsnk 1 +#define cppvPsrc 2 +void pmap_kit_bcopy_phys(paddr_t src, paddr_t dst, size_t size, int flags); + +typedef uint64_t pt_entry_t; +pt_entry_t pmap_kit_kva_to_pte(pmap_t pmap, vaddr_t va); + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/app/src/main/cpp/Dobby/source/dobby/pac_kit.h b/app/src/main/cpp/Dobby/source/dobby/pac_kit.h new file mode 100644 index 0000000..68b5d5d --- /dev/null +++ b/app/src/main/cpp/Dobby/source/dobby/pac_kit.h @@ -0,0 +1,31 @@ +#pragma once + +#include + +#if defined(__arm64e__) && __has_feature(ptrauth_calls) +#include +#endif + +static inline void *pac_strip(void *addr) { + if (addr == NULL) { + return NULL; + } +#if __has_feature(ptrauth_calls) + addr = ptrauth_strip(addr, ptrauth_key_asia); +#endif + return addr; +} + +static inline void *pac_sign(void *addr) { + if (addr == NULL) { + return NULL; + } +#if __has_feature(ptrauth_calls) + addr = ptrauth_sign_unauthenticated((void *)addr, ptrauth_key_asia, 0); +#endif + return addr; +} + +static inline void *pac_strip_and_sign(void *addr) { + return pac_sign(pac_strip(addr)); +} \ No newline at end of file diff --git a/app/src/main/cpp/Dobby/source/dobby/platform_detect_macro.h b/app/src/main/cpp/Dobby/source/dobby/platform_detect_macro.h new file mode 100644 index 0000000..300c759 --- /dev/null +++ b/app/src/main/cpp/Dobby/source/dobby/platform_detect_macro.h @@ -0,0 +1,15 @@ +#pragma once + +#if !defined(DISABLE_ARCH_DETECT) +#if defined(__arm__) +#define TARGET_ARCH_ARM 1 +#elif defined(__arm64__) || defined(__aarch64__) +#define TARGET_ARCH_ARM64 1 +#elif defined(_M_IX86) || defined(__i386__) +#define TARGET_ARCH_IA32 1 +#elif defined(_M_X64) || defined(__x86_64__) +#define TARGET_ARCH_X64 1 +#else +#error Target architecture was not detected as supported by Dobby +#endif +#endif diff --git a/app/src/main/cpp/Dobby/source/dobby/platform_features.h b/app/src/main/cpp/Dobby/source/dobby/platform_features.h new file mode 100644 index 0000000..94d8abe --- /dev/null +++ b/app/src/main/cpp/Dobby/source/dobby/platform_features.h @@ -0,0 +1,51 @@ +#pragma once + +#if defined(__APPLE__) && __arm64e__ +#if __has_feature(ptrauth_calls) +#include +#endif +#endif + +#if defined(BUILDING_KERNEL) +#include +#include +#include +#include +#include +#include +#include +#else +#include +#include +#include +#include +#include +#include +#include +#include +#if defined(__linux__) || defined(__APPLE__) +#include +#include +#endif +#endif + +#if defined(BUILDING_KERNEL) +#include "kernel_mode_header.h" +#endif + +#if defined(BUILDING_KERNEL) +#define abs(a) ((a) < 0 ? -(a) : (a)) +#define llabs(a) (((long long)a) < 0 ? -((long long)a) : ((long long)a)) +#define min(a, b) (((a) < (b)) ? (a) : (b)) +#define max(a, b) (((a) > (b)) ? (a) : (b)) +#ifdef __cplusplus +#define abs(a) ((a) < 0 ? -(a) : (a)) +#endif +#else +#ifdef __cplusplus +// #include "TINYSTL/vector.h" +// #include "TINYSTL/unordered_map.h" +#include "TINYSTL/vector.h" +#include "TINYSTL/unordered_map.h" +#endif +#endif \ No newline at end of file diff --git a/app/src/main/cpp/Dobby/source/dobby/types.h b/app/src/main/cpp/Dobby/source/dobby/types.h new file mode 100644 index 0000000..f67546e --- /dev/null +++ b/app/src/main/cpp/Dobby/source/dobby/types.h @@ -0,0 +1,10 @@ +#pragma once + +#include + +typedef unsigned char byte_t; +typedef unsigned int uint; + +#ifndef NULL +#define NULL 0 +#endif diff --git a/app/src/main/cpp/Dobby/source/dobby/utility_macro.h b/app/src/main/cpp/Dobby/source/dobby/utility_macro.h new file mode 100644 index 0000000..a6c567c --- /dev/null +++ b/app/src/main/cpp/Dobby/source/dobby/utility_macro.h @@ -0,0 +1,62 @@ +#pragma once + +// offset of struct member +#define OFFSETOF(TYPE, ELEMENT) ((size_t) & (((TYPE *)0)->ELEMENT)) + +// assert +#define ASSERT(X) + +// left/right shift +#define LeftShift(a, b, c) ((a & ((1 << b) - 1)) << c) +#define RightShift(a, b, c) ((a >> c) & ((1 << b) - 1)) + +// align +#ifndef ALIGN +#define ALIGN ALIGN_FLOOR +#endif +#define ALIGN_FLOOR(address, range) ((uintptr_t)address & ~((uintptr_t)range - 1)) +#define ALIGN_CEIL(address, range) (((uintptr_t)address + (uintptr_t)range - 1) & ~((uintptr_t)range - 1)) + +// borrow from gdb, refer: binutils-gdb/gdb/arch/arm.h +#define submask(x) ((1L << ((x) + 1)) - 1) +#define bits(obj, st, fn) (((obj) >> (st)) & submask((fn) - (st))) +#define bit(obj, st) (((obj) >> (st)) & 1) +#define sbits(obj, st, fn) ((long)(bits(obj, st, fn) | ((long)bit(obj, fn) * ~submask(fn - st)))) + +// make it easy +#define set_bit(obj, st, bit) obj = (((~(1 << st)) & obj) | (bit << st)) +#define set_bits(obj, st, fn, bits) obj = (((~(submask(fn - st) << st)) & obj) | (bits << st)) + +// definition to expand macro then apply to pragma message +// #pragma message(VAR_NAME_VALUE(HOST_OS_IOS)) +#define VALUE_TO_STRING(x) #x +#define VALUE(x) VALUE_TO_STRING(x) +#define VAR_NAME_VALUE(var) #var "=" VALUE(var) + +// format print +#ifdef __LP64__ +#define __PRI_64_prefix "l" +#define __PRI_PTR_prefix "l" +#else +#define __PRI_64_prefix "ll" +#define __PRI_PTR_prefix +#endif +#define PRIxPTR __PRI_PTR_prefix "x" /* uintptr_t */ + +// deprecated declared +#if defined(__GNUC__) || defined(__clang__) +#define DEPRECATED __attribute__((deprecated)) +#elif defined(_MSC_VER) +#define DEPRECATED __declspec(deprecated) +#else +#pragma message("WARNING: You need to implement DEPRECATED for this compiler") +#define DEPRECATED +#endif + +// export method +#if defined(_WIN32) +#define PUBLIC +#else +#define PUBLIC __attribute__((visibility("default"))) +#define INTERNAL __attribute__((visibility("internal"))) +#endif \ No newline at end of file diff --git a/app/src/main/cpp/Dobby/tests/CMakeLists.txt b/app/src/main/cpp/Dobby/tests/CMakeLists.txt new file mode 100644 index 0000000..8cb2454 --- /dev/null +++ b/app/src/main/cpp/Dobby/tests/CMakeLists.txt @@ -0,0 +1,120 @@ + +find_package(PkgConfig REQUIRED) +pkg_check_modules(CAPSTONE REQUIRED capstone) +message(STATUS "Capstone libraries: " ${CAPSTONE_LIBRARY_DIRS}) +message(STATUS "Capstone includes: " ${CAPSTONE_INCLUDE_DIRS}) + +pkg_check_modules(UNICORN REQUIRED unicorn) +message(STATUS "unicorn libraries: " ${UNICORN_LIBRARY_DIRS}) +message(STATUS "unicorn includes: " ${UNICORN_INCLUDE_DIRS}) + +get_property(DOBBY_SOURCE_FILE_LIST + TARGET dobby + PROPERTY SOURCES) + +set(DOBBY_SOURCES) +foreach (path ${DOBBY_SOURCE_FILE_LIST}) + if (NOT path MATCHES "^/") + list(APPEND DOBBY_SOURCES ${DOBBY_DIR}/${path}) + else () + list(APPEND DOBBY_SOURCES ${path}) + endif () +endforeach () + + +add_executable(test_insn_relo_arm64 + test_insn_relo_arm64.cpp + UniconEmulator.cpp + ${DOBBY_SOURCES} + ) + +target_compile_definitions(test_insn_relo_arm64 PUBLIC + LOGGING_DEBUG=1 + DISABLE_ARCH_DETECT=1 + TARGET_ARCH_ARM64=1 + TEST_WITH_UNICORN=1 + ) + +target_include_directories(test_insn_relo_arm64 PUBLIC + ${CAPSTONE_INCLUDE_DIRS} + ${UNICORN_INCLUDE_DIRS} + ) + +target_link_directories(test_insn_relo_arm64 PUBLIC + ${CAPSTONE_LIBRARY_DIRS} + ${UNICORN_LIBRARY_DIRS} + ) + +target_link_libraries(test_insn_relo_arm64 PUBLIC + ${CAPSTONE_LIBRARIES} + ${UNICORN_LIBRARIES} + ) + +# --- + +add_executable(test_insn_relo_arm + test_insn_relo_arm.cpp + UniconEmulator.cpp + ${DOBBY_SOURCES} + ) + +target_compile_definitions(test_insn_relo_arm PUBLIC + LOGGING_DEBUG=1 + DISABLE_ARCH_DETECT=1 + TARGET_ARCH_ARM=1 + TEST_WITH_UNICORN=1 + ) + +target_include_directories(test_insn_relo_arm PUBLIC + ${CAPSTONE_INCLUDE_DIRS} + ${UNICORN_INCLUDE_DIRS} + ) + +target_link_directories(test_insn_relo_arm PUBLIC + ${CAPSTONE_LIBRARY_DIRS} + ${UNICORN_LIBRARY_DIRS} + ) + +target_link_libraries(test_insn_relo_arm PUBLIC + ${CAPSTONE_LIBRARIES} + ${UNICORN_LIBRARIES} + ) + +# --- + +add_executable(test_insn_relo_x64 + test_insn_relo_x64.cpp + UniconEmulator.cpp + ${DOBBY_SOURCES} + ) + +target_compile_definitions(test_insn_relo_x64 PUBLIC + LOGGING_DEBUG=1 + DISABLE_ARCH_DETECT=1 + TARGET_ARCH_X64=1 + TEST_WITH_UNICORN=1 + # TARGET_ARCH_IA32=1 + ) + +target_include_directories(test_insn_relo_x64 PUBLIC + ${CAPSTONE_INCLUDE_DIRS} + ${UNICORN_INCLUDE_DIRS} + ) + +target_link_directories(test_insn_relo_x64 PUBLIC + ${CAPSTONE_LIBRARY_DIRS} + ${UNICORN_LIBRARY_DIRS} + ) + +target_link_libraries(test_insn_relo_x64 PUBLIC + ${CAPSTONE_LIBRARIES} + ${UNICORN_LIBRARIES} + ) + +# --- + +add_executable(test_native + test_native.cpp) + +target_link_libraries(test_native + dobby) \ No newline at end of file diff --git a/app/src/main/cpp/Dobby/tests/UniconEmulator.cpp b/app/src/main/cpp/Dobby/tests/UniconEmulator.cpp new file mode 100644 index 0000000..a0848ca --- /dev/null +++ b/app/src/main/cpp/Dobby/tests/UniconEmulator.cpp @@ -0,0 +1,219 @@ +#include "UniconEmulator.h" +#include "PlatformUnifiedInterface/MemoryAllocator.h" +#include "InstructionRelocation/InstructionRelocation.h" + +// align +#ifndef ALIGN +#define ALIGN ALIGN_FLOOR +#endif +#define ALIGN_FLOOR(address, range) ((uintptr_t)address & ~((uintptr_t)range - 1)) +#define ALIGN_CEIL(address, range) (((uintptr_t)address + (uintptr_t)range - 1) & ~((uintptr_t)range - 1)) + +std::string g_arch = ""; + +void set_global_arch(std::string arch) { + g_arch = arch; +} + +std::unordered_map CapstoneDisassembler::instances_; + +CapstoneDisassembler *CapstoneDisassembler::Get(const std::string &arch) { + if (instances_.count(arch) == 0) { + cs_err err = CS_ERR_OK; + csh csh_; + if (arch == "arm") { + err = cs_open(CS_ARCH_ARM, CS_MODE_ARM, &csh_); + } else if (arch == "thumb") { + err = cs_open(CS_ARCH_ARM, CS_MODE_THUMB, &csh_); + } else if (arch == "arm64") { + err = cs_open(CS_ARCH_ARM64, CS_MODE_ARM, &csh_); + } else if (arch == "x86_64") { + err = cs_open(CS_ARCH_X86, CS_MODE_64, &csh_); + } else if (arch == "x86") { + err = cs_open(CS_ARCH_X86, CS_MODE_32, &csh_); + } + + auto instance = new CapstoneDisassembler(arch, csh_); + instances_[arch] = instance; + } + return instances_[arch]; +} + +CapstoneDisassembler::CapstoneDisassembler(const std::string &arch, csh csh_) : arch_(arch), csh_(csh_) { +} + +CapstoneDisassembler::~CapstoneDisassembler() { + cs_close((csh *)&csh_); +} + +void CapstoneDisassembler::disassemble(uintptr_t addr, char *buffer, size_t buffer_size) { + cs_insn *insns; + + size_t count = cs_disasm(csh_, (uint8_t *)buffer, buffer_size, addr, 0, &insns); + for (size_t i = 0; i < count; ++i) { + auto &insn = insns[i]; + if (arch_ == "thumb") { + printf("%s %p: %s %s // thumb-%d\n", "-", insn.address, insn.mnemonic, insn.op_str, insn.size / 2); + } else { + printf("%s %p: %s %s\n", "-", insn.address, insn.mnemonic, insn.op_str); + } + } + cs_free(insns, count); +} + +static void hook_trace_insn(uc_engine *uc, uint64_t address, uint32_t size, void *user_data) { + auto emu = (UniconEmulator *)user_data; + + uc_err err; + char insn_bytes[16]; + err = uc_mem_read(uc, address, insn_bytes, size); + assert(err == UC_ERR_OK); + + if (address >= emu->end_) { + emu->stop(); + return; + } + + if ((emu->arch_ == "arm" || emu->arch_ == "thumb") && emu->isThumb()) { + CapstoneDisassembler::Get("thumb")->disassemble(address, (char *)insn_bytes, size); + } else { + CapstoneDisassembler::Get(g_arch)->disassemble(address, (char *)insn_bytes, size); + } +} + +static void hook_unmapped(uc_engine *uc, uc_mem_type type, uint64_t address, int size, int64_t value, void *user_data) { + printf(">>> Unmapped memory access at %p, data size = %p, data value = %p\n", address, size, value); + auto emu = (UniconEmulator *)user_data; + emu->setUnmappedAddr(address); + emu->stop(); +} + +void dump_regions(uc_engine *uc) { + uc_mem_region *regions; + uint32_t region_count; + uc_mem_regions(uc, ®ions, ®ion_count); + for (int i = 0; i < region_count; ++i) { + auto ®ion = regions[i]; + printf("region: %p - %p\n", region.begin, region.end); + } +} + +UniconEmulator::UniconEmulator(const std::string &arch) { + uc_err err = UC_ERR_OK; + if (arch == "arm" || arch == "thumb") { + err = uc_open(UC_ARCH_ARM, UC_MODE_ARM, &uc_); + } else if (arch == "arm64") { + err = uc_open(UC_ARCH_ARM64, UC_MODE_ARM, &uc_); + } else if (arch == "x86_64") { + err = uc_open(UC_ARCH_X86, UC_MODE_64, &uc_); + } else if (arch == "x86") { + err = uc_open(UC_ARCH_X86, UC_MODE_32, &uc_); + } + assert(err == UC_ERR_OK); + + arch_ = arch; + + uc_hook hook_trace_insn_handle; + uc_hook_add(uc_, &hook_trace_insn_handle, UC_HOOK_CODE, (void *)hook_trace_insn, this, 1, 0); + + uc_hook hook_unmapped_handle; + uc_hook_add(uc_, &hook_unmapped_handle, UC_HOOK_MEM_UNMAPPED, (void *)hook_unmapped, this, 1, 0); +} + +void UniconEmulator::mapMemory(uintptr_t addr, char *buffer, size_t buffer_size) { + uc_err err = UC_ERR_OK; + uintptr_t map_addr = ALIGN_FLOOR(addr, 0x1000); + size_t map_size = ALIGN_CEIL(buffer_size, 0x1000); + err = uc_mem_map(uc_, map_addr, map_size, UC_PROT_ALL); + assert(err == UC_ERR_OK); + err = uc_mem_write(uc_, addr, buffer, buffer_size); + assert(err == UC_ERR_OK); +} + +void *UniconEmulator::readRegister(int regId) { + void *value = nullptr; + uc_reg_read(uc_, regId, &value); + return value; +} + +void UniconEmulator::writeRegister(int regNdx, void *value) { + uc_reg_write(uc_, regNdx, (void *)&value); +} + +void UniconEmulator::start(uintptr_t addr, uintptr_t end) { + uc_err err; + if (g_arch == "thumb") { + addr |= 1; + } + err = uc_emu_start(uc_, addr, end, 0, 0); + if (err == UC_ERR_FETCH_UNMAPPED || err == UC_ERR_READ_UNMAPPED || err == UC_ERR_WRITE_UNMAPPED) + err = UC_ERR_OK; + assert(err == UC_ERR_OK); +} + +void UniconEmulator::emulate(uintptr_t addr, uintptr_t end, char *buffer, size_t buffer_size) { + uc_err err; + mapMemory(addr, buffer, buffer_size); + writeRegister(UC_ARM_REG_PC, (void *)addr); + + if (end == 0) + end = addr + buffer_size; + + start_ = addr; + end_ = end; + + start(addr, end); +} + +void check_insn_relo(char *buffer, size_t buffer_size, bool check_fault_addr, int check_reg_id, + void (^callback)(UniconEmulator *orig, UniconEmulator *relo), uintptr_t relo_stop_size) { + auto *orig_ue = new UniconEmulator(g_arch); + auto *relo_ue = new UniconEmulator(g_arch); + + addr_t orig_addr = 0x100014000; + addr_t relocate_addr = 0x100024000; + + if (g_arch == "arm" || g_arch == "thumb") { + orig_addr = 0x10014000; + relocate_addr = 0x10024000; + } + + // auto dism = CapstoneDisassembler::Get("arm64"); + // dism->disassemble((uintptr_t)orig_addr, buffer, buffer_size); + // printf("\n"); + + auto origin = new CodeMemBlock(orig_addr, buffer_size); + auto relocated = new CodeMemBlock(relocate_addr, 0x1000); + if (g_arch == "thumb") { + origin->reset(origin->addr + 1, origin->size); + } + + GenRelocateCode(buffer, origin, relocated, false); + + if (g_arch == "thumb") { + orig_ue->writeRegister(UC_ARM_REG_CPSR, (void *)0x20); + relo_ue->writeRegister(UC_ARM_REG_CPSR, (void *)0x20); + } + orig_ue->emulate(orig_addr, 0, buffer, buffer_size); + if (g_arch == "thumb") { + relocated->addr -= 1; + } + if (relo_stop_size == 0) { + relo_stop_size = relocated->size; + } + relo_ue->emulate(relocate_addr, relocate_addr + relo_stop_size, (char *)relocated->addr, relocated->size); + + // dism->disassemble((uintptr_t)relocate_addr, (char *)relocated->addr, relocated->size); + // printf("\n"); + + if (check_fault_addr) { + assert(orig_ue->getFaultAddr() == relo_ue->getFaultAddr()); + } else if (check_reg_id != -1) { + assert(orig_ue->readRegister(check_reg_id) == relo_ue->readRegister(check_reg_id)); + } else if (callback) { + callback(orig_ue, relo_ue); + } + + delete orig_ue; + delete relo_ue; +} diff --git a/app/src/main/cpp/Dobby/tests/UniconEmulator.h b/app/src/main/cpp/Dobby/tests/UniconEmulator.h new file mode 100644 index 0000000..414618b --- /dev/null +++ b/app/src/main/cpp/Dobby/tests/UniconEmulator.h @@ -0,0 +1,73 @@ +#pragma once + +#include +#include + +#include +#include + +class CapstoneDisassembler { +public: + void disassemble(uintptr_t addr, char *buffer, size_t buffer_size); + + static CapstoneDisassembler *Get(const std::string &arch); + +private: + CapstoneDisassembler(const std::string &arch, csh csh_); + + ~CapstoneDisassembler(); + +private: + std::string arch_; + csh csh_; + + static std::unordered_map instances_; +}; + +class UniconEmulator { +public: + UniconEmulator(const std::string &arch); + + void mapMemory(uintptr_t addr, char *buffer, size_t buffer_size); + + void *readRegister(int regId); + + void writeRegister(int regId, void *value); + + void start(uintptr_t addr, uintptr_t end); + + void stop() { + uc_emu_stop(uc_); + } + + void emulate(uintptr_t addr, uintptr_t end, char *buffer, size_t buffer_size); + + void setUnmappedAddr(uintptr_t addr) { + unmapped_addr_ = addr; + } + + intptr_t getFaultAddr() { + return unmapped_addr_; + } + + bool isThumb() { + void *reg_value = readRegister(UC_ARM_REG_CPSR); + return (intptr_t)reg_value & 0x20; + } + + void reset(); + +public: + std::string arch_; + uintptr_t start_, end_; + +private: + uc_err err_; + uc_engine *uc_; + uintptr_t unmapped_addr_; +}; + +void set_global_arch(std::string arch); + +void check_insn_relo(char *buffer, size_t buffer_size, bool check_fault_addr, int check_reg_id, + void (^callback)(UniconEmulator *orig, UniconEmulator *relo), uintptr_t relo_stop_size = 0); \ No newline at end of file diff --git a/app/src/main/cpp/Dobby/tests/test_insn_decoder_x86.cpp b/app/src/main/cpp/Dobby/tests/test_insn_decoder_x86.cpp new file mode 100644 index 0000000..20e0fb9 --- /dev/null +++ b/app/src/main/cpp/Dobby/tests/test_insn_decoder_x86.cpp @@ -0,0 +1,267 @@ +#include "InstructionRelocation/InstructionRelocation.h" +#include "InstructionRelocation/arm64/InstructionRelocationARM64.h" + +#include +#include + +#include + +class CapstoneDisassembler { +public: + void disassemble(uintptr_t addr, char *buffer, size_t buffer_szie); + + static CapstoneDisassembler *Get(const std::string &arch); + +private: + CapstoneDisassembler(const std::string &arch, csh csh_); + + ~CapstoneDisassembler(); + +private: + csh csh_; + + static CapstoneDisassembler *instance_; +}; + +CapstoneDisassembler *CapstoneDisassembler::instance_ = nullptr; + +CapstoneDisassembler *CapstoneDisassembler::Get(const std::string &arch) { + if (instance_ == nullptr) { + cs_err err = CS_ERR_OK; + csh csh_; + if (arch == "arm") { + err = cs_open(CS_ARCH_ARM, CS_MODE_ARM, &csh_); + } else if (arch == "arm64") { + err = cs_open(CS_ARCH_ARM64, CS_MODE_ARM, &csh_); + } else if (arch == "x86_64") { + err = cs_open(CS_ARCH_X86, CS_MODE_64, &csh_); + } else if (arch == "x86") { + err = cs_open(CS_ARCH_X86, CS_MODE_32, &csh_); + } + instance_ = new CapstoneDisassembler(arch, csh_); + } + return instance_; +} + +CapstoneDisassembler::CapstoneDisassembler(const std::string &arch, csh csh_) : csh_(csh_) { +} + +CapstoneDisassembler::~CapstoneDisassembler() { + cs_close((csh *)&csh_); +} + +void CapstoneDisassembler::disassemble(uintptr_t addr, char *buffer, size_t buffer_size) { + cs_insn *insns; + + size_t count = cs_disasm(csh_, (uint8_t *)buffer, buffer_size, addr, 0, &insns); + for (size_t i = 0; i < count; ++i) { + auto &insn = insns[i]; + printf("%s %p: %s %s\n", "-", insn.address, insn.mnemonic, insn.op_str); + } + cs_free(insns, count); +} + +class UniconEmulator { +public: + UniconEmulator(const std::string &arch); + + void mapMemory(uintptr_t addr, char *buffer, size_t buffer_size); + + void *readRegister(int regId); + + void writeRegister(int regId, void *value); + + void start(uintptr_t addr, uintptr_t end); + + void stop() { + uc_emu_stop(uc_); + } + + void emulate(uintptr_t addr, char *buffer, size_t buffer_size); + + void setUnmappedAddr(uintptr_t addr) { + unmapped_addr_ = addr; + } + + intptr_t getFaultAddr() { + return unmapped_addr_; + } + + void reset(); + +private: +private: + uc_err err_; + uc_engine *uc_; + uintptr_t unmapped_addr_; +}; + +static void hook_trace_insn(uc_engine *uc, uint64_t address, uint32_t size, void *user_data) { + auto emu = (UniconEmulator *)user_data; + uc_err err; + char insn_bytes[16]; + err = uc_mem_read(uc, address, insn_bytes, size); + assert(err == UC_ERR_OK); + CapstoneDisassembler::Get("arm64")->disassemble(address, (char *)insn_bytes, size); +} + +static void hook_unmapped(uc_engine *uc, uc_mem_type type, uint64_t address, int size, int64_t value, void *user_data) { + printf(">>> Unmapped memory access at %p, data size = %p, data value = %p\n", address, size, value); + auto emu = (UniconEmulator *)user_data; + emu->setUnmappedAddr(address); + emu->stop(); +} + +void dump_regions(uc_engine *uc) { + uc_mem_region *regions; + uint32_t region_count; + uc_mem_regions(uc, ®ions, ®ion_count); + for (int i = 0; i < region_count; ++i) { + auto ®ion = regions[i]; + printf("region: %p - %p\n", region.begin, region.end); + } +} + +UniconEmulator::UniconEmulator(const std::string &arch) { + uc_err err = UC_ERR_OK; + if (arch == "arm") { + err = uc_open(UC_ARCH_ARM, UC_MODE_ARM, &uc_); + } else if (arch == "arm64") { + err = uc_open(UC_ARCH_ARM64, UC_MODE_ARM, &uc_); + } else if (arch == "x86_64") { + err = uc_open(UC_ARCH_X86, UC_MODE_64, &uc_); + } else if (arch == "x86") { + err = uc_open(UC_ARCH_X86, UC_MODE_32, &uc_); + } + assert(err == UC_ERR_OK); + + uc_hook hook_trace_insn_handle; + uc_hook_add(uc_, &hook_trace_insn_handle, UC_HOOK_CODE, (void *)hook_trace_insn, this, 1, 0); + + uc_hook hook_unmapped_handle; + uc_hook_add(uc_, &hook_unmapped_handle, UC_HOOK_MEM_UNMAPPED, (void *)hook_unmapped, this, 1, 0); +} + +void UniconEmulator::mapMemory(uintptr_t addr, char *buffer, size_t buffer_size) { + uc_err err = UC_ERR_OK; + uintptr_t map_addr = ALIGN_FLOOR(addr, 0x1000); + size_t map_size = ALIGN_CEIL(buffer_size, 0x1000); + err = uc_mem_map(uc_, map_addr, map_size, UC_PROT_ALL); + assert(err == UC_ERR_OK); + err = uc_mem_write(uc_, addr, buffer, buffer_size); + assert(err == UC_ERR_OK); +} + +void *UniconEmulator::readRegister(int regId) { + void *value = nullptr; + uc_reg_read(uc_, regId, &value); + return value; +} + +void UniconEmulator::writeRegister(int regNdx, void *value) { + uc_reg_write(uc_, regNdx, (void *)&value); +} + +void UniconEmulator::start(uintptr_t addr, uintptr_t end) { + uc_err err; + err = uc_emu_start(uc_, addr, end, 0, 0); + if (err == UC_ERR_FETCH_UNMAPPED || err == UC_ERR_READ_UNMAPPED || err == UC_ERR_WRITE_UNMAPPED) + err = UC_ERR_OK; + assert(err == UC_ERR_OK); +} + +void UniconEmulator::emulate(uintptr_t addr, char *buffer, size_t buffer_size) { + uc_err err; + mapMemory(addr, buffer, buffer_size); + writeRegister(UC_ARM_REG_PC, (void *)addr); + start(addr, addr + buffer_size); +} + +void check_insn_relo(char *buffer, size_t buffer_size, bool check_fault_addr, int check_reg_id, + void (^callback)(UniconEmulator *orig, UniconEmulator *relo)) { + auto *orig_ue = new UniconEmulator("arm64"); + auto *relo_ue = new UniconEmulator("arm64"); + + addr_t orig_addr = 0x100004000; + addr_t relocate_addr = 0x200004000; + + // auto dism = CapstoneDisassembler::Get("arm64"); + // dism->disassemble((uintptr_t)orig_addr, buffer, buffer_size); + // printf("\n"); + + auto origin = new CodeMemBlock(orig_addr, buffer_size); + auto relocated = new CodeMemBlock(); + + GenRelocateCode(buffer, origin, relocated, false); + + orig_ue->emulate(orig_addr, buffer, buffer_size); + relo_ue->emulate(relocate_addr, (char *)relocated->addr, relocated->size); + + // dism->disassemble((uintptr_t)relocate_addr, (char *)relocated->addr, relocated->size); + // printf("\n"); + + if (check_fault_addr) { + assert(orig_ue->getFaultAddr() == relo_ue->getFaultAddr()); + } else if (check_reg_id != -1) { + assert(orig_ue->readRegister(check_reg_id) == relo_ue->readRegister(check_reg_id)); + } else if (callback) { + callback(orig_ue, relo_ue); + } + + delete orig_ue; + delete relo_ue; +} + +int main() { + // b #-0x4000 + check_insn_relo("\x00\xf0\xff\x17", 4, true, -1, nullptr); + // b #0x4000 + check_insn_relo("\x00\x10\x00\x14", 4, true, -1, nullptr); + + // bl #-0x4000 + check_insn_relo("\x00\xf0\xff\x97", 4, true, -1, nullptr); + // bl #0x4000 + check_insn_relo("\x00\x10\x00\x94", 4, true, -1, nullptr); + + // mov x0, #0 + // cbz x0, #-0x4000 + check_insn_relo("\x00\x00\x80\xd2\x00\x00\xfe\xb4", 8, true, -1, nullptr); + // mov x0, #0 + // cbz x0, #0x4000 + check_insn_relo("\x00\x00\x80\xd2\x00\x00\x02\xb4", 8, true, -1, nullptr); + + // ldr x0, #-0x4000 + check_insn_relo("\x00\x00\xfe\x58", 4, true, -1, nullptr); + // ldr x0, #0x4000 + check_insn_relo("\x00\x00\x02\x58", 4, true, -1, nullptr); + + // adr x0, #-0x4000 + check_insn_relo("\x00\x00\xfe\x10", 4, false, UC_ARM64_REG_X0, nullptr); + // adr x0, #0x4000 + check_insn_relo("\x00\x00\x02\x10", 4, false, UC_ARM64_REG_X0, nullptr); + + // adrp x0, #-0x4000 + check_insn_relo("\xe0\xff\xff\x90", 4, false, UC_ARM64_REG_X0, nullptr); + // adrp x0, #0x4000 + check_insn_relo("\x20\x00\x00\x90", 4, false, UC_ARM64_REG_X0, nullptr); + + // mov x0, #0 + // cmp x0, #0 + // b.eq #-0x4000 + check_insn_relo("\x00\x00\x80\xd2\x1f\x00\x00\xf1\x00\x00\xfe\x54", 12, true, -1, nullptr); + // mov x0, #0 + // cmp x0, #0 + // b.eq #0x4000 + check_insn_relo("\x00\x00\x80\xd2\x1f\x00\x00\xf1\x00\x00\x02\x54", 12, true, -1, nullptr); + + // mov x0, #0xb + // tbz w0, 2, #-0x4000 + check_insn_relo("\x60\x01\x80\xd2\x00\x00\x16\x36", 8, true, -1, nullptr); + // mov x0, #0xb + + // mov x0, #0xb + // tbz w0, 2, #0x4000 + check_insn_relo("\x60\x01\x80\xd2\x00\x00\x12\x36", 8, true, -1, nullptr); + + return 0; +} diff --git a/app/src/main/cpp/Dobby/tests/test_insn_relo_arm.cpp b/app/src/main/cpp/Dobby/tests/test_insn_relo_arm.cpp new file mode 100644 index 0000000..43dd16c --- /dev/null +++ b/app/src/main/cpp/Dobby/tests/test_insn_relo_arm.cpp @@ -0,0 +1,116 @@ +#include "InstructionRelocation/InstructionRelocation.h" + +#include "UniconEmulator.h" + +void check_insn_relo_arm(char *buffer, size_t buffer_size, bool check_fault_addr, int check_reg_id, + void (^callback)(UniconEmulator *orig, UniconEmulator *relo)) { + __attribute__((aligned(4))) char code[64] = {0}; + memcpy(code, buffer, buffer_size); + check_insn_relo(code, buffer_size, check_fault_addr, check_reg_id, callback); +} + +void check_insn_relo_thumb(char *buffer, size_t buffer_size, bool check_fault_addr, int check_reg_id, + void (^callback)(UniconEmulator *orig, UniconEmulator *relo), uintptr_t relo_stop_size = 0) { + __attribute__((aligned(4))) char code[64] = {0}; + memcpy(code, buffer, buffer_size); + check_insn_relo(code, buffer_size, check_fault_addr, check_reg_id, callback, relo_stop_size); +} + +int main() { + log_set_level(0); + set_global_arch("arm"); + + // ldr r0, [pc, #-0x20] + __attribute__((aligned(4))) char *code_0 = "\x20\x00\x1f\xe5"; + check_insn_relo(code_0, 4, true, -1, nullptr); + + // ldr r0, [pc, #0x20] + __attribute__((aligned(4))) char *code_1 = "\x20\x00\x9f\xe5"; + check_insn_relo(code_1, 4, false, -1, ^(UniconEmulator *orig, UniconEmulator *relo) { + assert(relo->getFaultAddr() == 0x10014028); + }); + + // add r0, pc, #-0x4000 + check_insn_relo_arm("\x01\x09\x4f\xe2", 4, false, UC_ARM_REG_R0, nullptr); + // add r0, pc, #0x4000 + check_insn_relo_arm("\x01\x09\x8f\xe2", 4, false, UC_ARM_REG_R0, nullptr); + + // b #-0x4000 + check_insn_relo_arm("\xfe\xef\xff\xea", 4, true, -1, nullptr); + // b #0x4000 + check_insn_relo_arm("\xfe\x0f\x00\xea", 4, true, -1, nullptr); + + // bl #-0x4000 + check_insn_relo_arm("\xfe\xef\xff\xeb", 4, true, -1, nullptr); + // blx #0x4000 + check_insn_relo_arm("\xfe\x0f\x00\xfa", 4, true, -1, nullptr); + + set_global_arch("thumb"); + + // cmp r0, pc + check_insn_relo_thumb("\x78\x45", 2, false, -1, ^(UniconEmulator *orig, UniconEmulator *relo) { + assert(relo->readRegister(UC_ARM_REG_R12) == (void *)0x10014004); + }); + + // adr r0, #0x20 + check_insn_relo_thumb("\x08\xa0", 2, false, UC_ARM_REG_R0, nullptr, 8); + + // bx pc + check_insn_relo_thumb("\x78\x47", 2, false, UC_ARM_REG_PC, nullptr); + // blx pc + check_insn_relo_thumb("\xf8\x47", 2, false, UC_ARM_REG_PC, nullptr); + + // ldr r0, [pc, #8] + check_insn_relo_thumb("\x02\x48", 2, false, -1, ^(UniconEmulator *orig, UniconEmulator *relo) { + assert(relo->getFaultAddr() == 0x1001400c); + }); + + // b #-8 + check_insn_relo_thumb("\xfa\xe7", 2, true, -1, nullptr); + // b #8 + check_insn_relo_thumb("\x02\xe0", 2, false, -1, ^(UniconEmulator *orig, UniconEmulator *relo) { + assert(relo->getFaultAddr() == 0x10014008); + }); + + // mov r0, 0 + // cbz r0, #8 + check_insn_relo_thumb("\x4f\xf0\x00\x00" + "\x10\xb1", + 6, false, -1, ^(UniconEmulator *orig, UniconEmulator *relo) { + assert(relo->getFaultAddr() == 0x1001400c); + }); + + set_global_arch("thumb"); + + // cmp r0, r0 + // beq.w #-0x4000 + check_insn_relo_thumb("\x80\x42" + "\x3c\xf4\x00\xa8", + 6, true, -1, nullptr); + // cmp r0, r0 + // beq.w #0x4000 + check_insn_relo_thumb("\x80\x42" + "\x04\xf0\x00\x80", + 6, true, -1, nullptr); + + // bl #-0x4000 + check_insn_relo_thumb("\xfb\xf7\xfe\xff", 4, true, -1, nullptr); + // blx #0x4000 + check_insn_relo_thumb("\x03\xf0\xfe\xef", 4, true, -1, nullptr); + + // adr r0, #-0x512 + check_insn_relo_thumb("\xaf\xf2\x12\x50", 4, false, UC_ARM_REG_R0, nullptr); + // adr r0, #0x512 + check_insn_relo_thumb("\x0f\xf2\x12\x50", 4, false, UC_ARM_REG_R0, nullptr); + + // ldr r0, [pc, #-0x512] + check_insn_relo_thumb("\x5f\xf8\x12\x05", 4, true, -1, nullptr, 0xc); + // ldr r0, [pc, #0x512] + check_insn_relo_thumb( + "\xdf\xf8\x12\x05", 4, false, -1, + ^(UniconEmulator *orig, UniconEmulator *relo) { + assert(relo->getFaultAddr() == 0x10014000 + 0x512 + 4); + }, + 0xc); + return 0; +} diff --git a/app/src/main/cpp/Dobby/tests/test_insn_relo_arm64.cpp b/app/src/main/cpp/Dobby/tests/test_insn_relo_arm64.cpp new file mode 100644 index 0000000..d76aee6 --- /dev/null +++ b/app/src/main/cpp/Dobby/tests/test_insn_relo_arm64.cpp @@ -0,0 +1,97 @@ +/* + +test_b: +b #-0x4000 +b #0x4000 + +test_bl: +bl #-0x4000 +bl #0x4000 + +test_cbz: +cbz x0, #-0x4000 +cbz x0, #0x4000 + +test_ldr_liberal: +ldr x0, #-0x4000 +ldr x0, #0x4000 + +test_adr: +adr x0, #-0x4000 +adr x0, #0x4000 + +test_adrp: +adrp x0, #-0x4000 +adrp x0, #0x4000 + +test_b_cond: +b.eq #-0x4000 +b.eq #0x4000 + +test_tbz: +tbz x0, #0, #-0x4000 +tbz x0, #0, #0x4000 + +*/ + +// clang -arch arm64 code_arm64.asm -o code_arm64.o + +#include "InstructionRelocation/InstructionRelocation.h" + +#include "UniconEmulator.h" + +int main() { + set_global_arch("arm64"); + + // b #-0x4000 + check_insn_relo("\x00\xf0\xff\x17", 4, true, -1, nullptr); + // b #0x4000 + check_insn_relo("\x00\x10\x00\x14", 4, true, -1, nullptr); + + // bl #-0x4000 + check_insn_relo("\x00\xf0\xff\x97", 4, true, -1, nullptr); + // bl #0x4000 + check_insn_relo("\x00\x10\x00\x94", 4, true, -1, nullptr); + + // mov x0, #0 + // cbz x0, #-0x4000 + check_insn_relo("\x00\x00\x80\xd2\x00\x00\xfe\xb4", 8, true, -1, nullptr); + // mov x0, #0 + // cbz x0, #0x4000 + check_insn_relo("\x00\x00\x80\xd2\x00\x00\x02\xb4", 8, true, -1, nullptr); + + // ldr x0, #-0x4000 + check_insn_relo("\x00\x00\xfe\x58", 4, true, -1, nullptr); + // ldr x0, #0x4000 + check_insn_relo("\x00\x00\x02\x58", 4, true, -1, nullptr); + + // adr x0, #-0x4000 + check_insn_relo("\x00\x00\xfe\x10", 4, false, UC_ARM64_REG_X0, nullptr); + // adr x0, #0x4000 + check_insn_relo("\x00\x00\x02\x10", 4, false, UC_ARM64_REG_X0, nullptr); + + // adrp x0, #-0x4000 + check_insn_relo("\xe0\xff\xff\x90", 4, false, UC_ARM64_REG_X0, nullptr); + // adrp x0, #0x4000 + check_insn_relo("\x20\x00\x00\x90", 4, false, UC_ARM64_REG_X0, nullptr); + + // mov x0, #0 + // cmp x0, #0 + // b.eq #-0x4000 + check_insn_relo("\x00\x00\x80\xd2\x1f\x00\x00\xf1\x00\x00\xfe\x54", 12, true, -1, nullptr); + // mov x0, #0 + // cmp x0, #0 + // b.eq #0x4000 + check_insn_relo("\x00\x00\x80\xd2\x1f\x00\x00\xf1\x00\x00\x02\x54", 12, true, -1, nullptr); + + // mov x0, #0xb + // tbz w0, 2, #-0x4000 + check_insn_relo("\x60\x01\x80\xd2\x00\x00\x16\x36", 8, true, -1, nullptr); + // mov x0, #0xb + + // mov x0, #0xb + // tbz w0, 2, #0x4000 + check_insn_relo("\x60\x01\x80\xd2\x00\x00\x12\x36", 8, true, -1, nullptr); + + return 0; +} diff --git a/app/src/main/cpp/Dobby/tests/test_insn_relo_x64.cpp b/app/src/main/cpp/Dobby/tests/test_insn_relo_x64.cpp new file mode 100644 index 0000000..f9db59d --- /dev/null +++ b/app/src/main/cpp/Dobby/tests/test_insn_relo_x64.cpp @@ -0,0 +1,38 @@ +#include "InstructionRelocation/InstructionRelocation.h" + +#include "UniconEmulator.h" + +int main() { + log_set_level(0); + set_global_arch("x86_64"); + + + // cmp eax, eax + // jz -0x20 + check_insn_relo("\x39\xc0\x74\xdc", 4, false, UC_X86_REG_IP, nullptr); + // cmp eax, eax + // jz 0x20 + check_insn_relo("\x39\xc0\x74\x1c", 4, false, UC_X86_REG_IP, nullptr); + + // jmp -0x20 + check_insn_relo("\xeb\xde", 2, false, UC_X86_REG_IP, nullptr); + // jmp 0x20 + check_insn_relo("\xeb\x1e", 2, false, UC_X86_REG_IP, nullptr); + + + // jmp -0x4000 + check_insn_relo("\xe9\xfb\xbf\xff\xff", 4, false, UC_X86_REG_IP, nullptr); + // jmp 0x4000 + check_insn_relo("\xe9\xfb\x3f\x00\x00", 4, false, UC_X86_REG_IP, nullptr); + + // lea rax, [rip] + check_insn_relo("\x48\x8d\x05\x00\x00\x00\x00", 7, false, UC_X86_REG_RAX, nullptr); + + // lea rax, [rip + 0x4000] + check_insn_relo("\x48\x8d\x05\x00\x40\x00\x00", 7, false, UC_X86_REG_RAX, nullptr); + + // mov rax, [rip + 0x4000] + check_insn_relo("\x48\x8b\x05\x00\x40\x00\x00", 7, true, -1, nullptr); + + return 0; +} diff --git a/app/src/main/cpp/Dobby/tests/test_native.cpp b/app/src/main/cpp/Dobby/tests/test_native.cpp new file mode 100644 index 0000000..21f84a9 --- /dev/null +++ b/app/src/main/cpp/Dobby/tests/test_native.cpp @@ -0,0 +1,30 @@ +#include "dobby.h" + +#include +#include + +#define LOG(fmt, ...) printf("[test_native] " fmt, ##__VA_ARGS__) + +void test_execve() { + char *argv[] = {NULL}; + char *envp[] = {NULL}; + + LOG("test execve"); + + DobbyInstrument(DobbySymbolResolver(0, "_execve"), [](void *, DobbyRegisterContext *ctx) { + LOG("execve: %s", (char *)ctx->general.regs.rdi); + return; + }); + + execve("ls", argv, envp); + + return; +} + +int main(int argc, char *argv[]) { + log_set_level(0); + + test_execve(); + + return 0; +} diff --git a/app/src/main/cpp/libcxx b/app/src/main/cpp/libcxx deleted file mode 160000 index 12c8f4e..0000000 --- a/app/src/main/cpp/libcxx +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 12c8f4e93f196a700137e983dcceeac43cf807f2 diff --git a/app/src/main/cpp/libcxx/arm64-v8a.a b/app/src/main/cpp/libcxx/arm64-v8a.a new file mode 100644 index 0000000..4cb0dd5 Binary files /dev/null and b/app/src/main/cpp/libcxx/arm64-v8a.a differ diff --git a/app/src/main/cpp/libcxx/armeabi-v7a.a b/app/src/main/cpp/libcxx/armeabi-v7a.a new file mode 100644 index 0000000..9587228 Binary files /dev/null and b/app/src/main/cpp/libcxx/armeabi-v7a.a differ diff --git a/app/src/main/cpp/libcxx/include/CMakeLists.txt b/app/src/main/cpp/libcxx/include/CMakeLists.txt new file mode 100644 index 0000000..a12aa1d --- /dev/null +++ b/app/src/main/cpp/libcxx/include/CMakeLists.txt @@ -0,0 +1,934 @@ +set(files + __algorithm/adjacent_find.h + __algorithm/all_of.h + __algorithm/any_of.h + __algorithm/binary_search.h + __algorithm/clamp.h + __algorithm/comp.h + __algorithm/comp_ref_type.h + __algorithm/copy.h + __algorithm/copy_backward.h + __algorithm/copy_if.h + __algorithm/copy_move_common.h + __algorithm/copy_n.h + __algorithm/count.h + __algorithm/count_if.h + __algorithm/equal.h + __algorithm/equal_range.h + __algorithm/fill.h + __algorithm/fill_n.h + __algorithm/find.h + __algorithm/find_end.h + __algorithm/find_first_of.h + __algorithm/find_if.h + __algorithm/find_if_not.h + __algorithm/for_each.h + __algorithm/for_each_n.h + __algorithm/generate.h + __algorithm/generate_n.h + __algorithm/half_positive.h + __algorithm/in_found_result.h + __algorithm/in_fun_result.h + __algorithm/in_in_out_result.h + __algorithm/in_in_result.h + __algorithm/in_out_out_result.h + __algorithm/in_out_result.h + __algorithm/includes.h + __algorithm/inplace_merge.h + __algorithm/is_heap.h + __algorithm/is_heap_until.h + __algorithm/is_partitioned.h + __algorithm/is_permutation.h + __algorithm/is_sorted.h + __algorithm/is_sorted_until.h + __algorithm/iter_swap.h + __algorithm/iterator_operations.h + __algorithm/lexicographical_compare.h + __algorithm/lower_bound.h + __algorithm/make_heap.h + __algorithm/make_projected.h + __algorithm/max.h + __algorithm/max_element.h + __algorithm/merge.h + __algorithm/min.h + __algorithm/min_element.h + __algorithm/min_max_result.h + __algorithm/minmax.h + __algorithm/minmax_element.h + __algorithm/mismatch.h + __algorithm/move.h + __algorithm/move_backward.h + __algorithm/next_permutation.h + __algorithm/none_of.h + __algorithm/nth_element.h + __algorithm/partial_sort.h + __algorithm/partial_sort_copy.h + __algorithm/partition.h + __algorithm/partition_copy.h + __algorithm/partition_point.h + __algorithm/pop_heap.h + __algorithm/prev_permutation.h + __algorithm/push_heap.h + __algorithm/ranges_adjacent_find.h + __algorithm/ranges_all_of.h + __algorithm/ranges_any_of.h + __algorithm/ranges_binary_search.h + __algorithm/ranges_clamp.h + __algorithm/ranges_copy.h + __algorithm/ranges_copy_backward.h + __algorithm/ranges_copy_if.h + __algorithm/ranges_copy_n.h + __algorithm/ranges_count.h + __algorithm/ranges_count_if.h + __algorithm/ranges_equal.h + __algorithm/ranges_equal_range.h + __algorithm/ranges_fill.h + __algorithm/ranges_fill_n.h + __algorithm/ranges_find.h + __algorithm/ranges_find_end.h + __algorithm/ranges_find_first_of.h + __algorithm/ranges_find_if.h + __algorithm/ranges_find_if_not.h + __algorithm/ranges_for_each.h + __algorithm/ranges_for_each_n.h + __algorithm/ranges_generate.h + __algorithm/ranges_generate_n.h + __algorithm/ranges_includes.h + __algorithm/ranges_inplace_merge.h + __algorithm/ranges_is_heap.h + __algorithm/ranges_is_heap_until.h + __algorithm/ranges_is_partitioned.h + __algorithm/ranges_is_permutation.h + __algorithm/ranges_is_sorted.h + __algorithm/ranges_is_sorted_until.h + __algorithm/ranges_iterator_concept.h + __algorithm/ranges_lexicographical_compare.h + __algorithm/ranges_lower_bound.h + __algorithm/ranges_make_heap.h + __algorithm/ranges_max.h + __algorithm/ranges_max_element.h + __algorithm/ranges_merge.h + __algorithm/ranges_min.h + __algorithm/ranges_min_element.h + __algorithm/ranges_minmax.h + __algorithm/ranges_minmax_element.h + __algorithm/ranges_mismatch.h + __algorithm/ranges_move.h + __algorithm/ranges_move_backward.h + __algorithm/ranges_next_permutation.h + __algorithm/ranges_none_of.h + __algorithm/ranges_nth_element.h + __algorithm/ranges_partial_sort.h + __algorithm/ranges_partial_sort_copy.h + __algorithm/ranges_partition.h + __algorithm/ranges_partition_copy.h + __algorithm/ranges_partition_point.h + __algorithm/ranges_pop_heap.h + __algorithm/ranges_prev_permutation.h + __algorithm/ranges_push_heap.h + __algorithm/ranges_remove.h + __algorithm/ranges_remove_copy.h + __algorithm/ranges_remove_copy_if.h + __algorithm/ranges_remove_if.h + __algorithm/ranges_replace.h + __algorithm/ranges_replace_copy.h + __algorithm/ranges_replace_copy_if.h + __algorithm/ranges_replace_if.h + __algorithm/ranges_reverse.h + __algorithm/ranges_reverse_copy.h + __algorithm/ranges_rotate.h + __algorithm/ranges_rotate_copy.h + __algorithm/ranges_sample.h + __algorithm/ranges_search.h + __algorithm/ranges_search_n.h + __algorithm/ranges_set_difference.h + __algorithm/ranges_set_intersection.h + __algorithm/ranges_set_symmetric_difference.h + __algorithm/ranges_set_union.h + __algorithm/ranges_shuffle.h + __algorithm/ranges_sort.h + __algorithm/ranges_sort_heap.h + __algorithm/ranges_stable_partition.h + __algorithm/ranges_stable_sort.h + __algorithm/ranges_swap_ranges.h + __algorithm/ranges_transform.h + __algorithm/ranges_unique.h + __algorithm/ranges_unique_copy.h + __algorithm/ranges_upper_bound.h + __algorithm/remove.h + __algorithm/remove_copy.h + __algorithm/remove_copy_if.h + __algorithm/remove_if.h + __algorithm/replace.h + __algorithm/replace_copy.h + __algorithm/replace_copy_if.h + __algorithm/replace_if.h + __algorithm/reverse.h + __algorithm/reverse_copy.h + __algorithm/rotate.h + __algorithm/rotate_copy.h + __algorithm/sample.h + __algorithm/search.h + __algorithm/search_n.h + __algorithm/set_difference.h + __algorithm/set_intersection.h + __algorithm/set_symmetric_difference.h + __algorithm/set_union.h + __algorithm/shift_left.h + __algorithm/shift_right.h + __algorithm/shuffle.h + __algorithm/sift_down.h + __algorithm/sort.h + __algorithm/sort_heap.h + __algorithm/stable_partition.h + __algorithm/stable_sort.h + __algorithm/swap_ranges.h + __algorithm/transform.h + __algorithm/uniform_random_bit_generator_adaptor.h + __algorithm/unique.h + __algorithm/unique_copy.h + __algorithm/unwrap_iter.h + __algorithm/unwrap_range.h + __algorithm/upper_bound.h + __assert + __availability + __bit/bit_cast.h + __bit/bit_ceil.h + __bit/bit_floor.h + __bit/bit_log2.h + __bit/bit_width.h + __bit/blsr.h + __bit/byteswap.h + __bit/countl.h + __bit/countr.h + __bit/endian.h + __bit/has_single_bit.h + __bit/popcount.h + __bit/rotate.h + __bit_reference + __bsd_locale_defaults.h + __bsd_locale_fallbacks.h + __charconv/chars_format.h + __charconv/from_chars_result.h + __charconv/tables.h + __charconv/to_chars_base_10.h + __charconv/to_chars_result.h + __chrono/calendar.h + __chrono/convert_to_timespec.h + __chrono/convert_to_tm.h + __chrono/day.h + __chrono/duration.h + __chrono/file_clock.h + __chrono/formatter.h + __chrono/hh_mm_ss.h + __chrono/high_resolution_clock.h + __chrono/literals.h + __chrono/month.h + __chrono/month_weekday.h + __chrono/monthday.h + __chrono/ostream.h + __chrono/parser_std_format_spec.h + __chrono/statically_widen.h + __chrono/steady_clock.h + __chrono/system_clock.h + __chrono/time_point.h + __chrono/weekday.h + __chrono/year.h + __chrono/year_month.h + __chrono/year_month_day.h + __chrono/year_month_weekday.h + __compare/common_comparison_category.h + __compare/compare_partial_order_fallback.h + __compare/compare_strong_order_fallback.h + __compare/compare_three_way.h + __compare/compare_three_way_result.h + __compare/compare_weak_order_fallback.h + __compare/is_eq.h + __compare/ordering.h + __compare/partial_order.h + __compare/strong_order.h + __compare/synth_three_way.h + __compare/three_way_comparable.h + __compare/weak_order.h + __concepts/arithmetic.h + __concepts/assignable.h + __concepts/boolean_testable.h + __concepts/class_or_enum.h + __concepts/common_reference_with.h + __concepts/common_with.h + __concepts/constructible.h + __concepts/convertible_to.h + __concepts/copyable.h + __concepts/derived_from.h + __concepts/destructible.h + __concepts/different_from.h + __concepts/equality_comparable.h + __concepts/invocable.h + __concepts/movable.h + __concepts/predicate.h + __concepts/regular.h + __concepts/relation.h + __concepts/same_as.h + __concepts/semiregular.h + __concepts/swappable.h + __concepts/totally_ordered.h + __config + __coroutine/coroutine_handle.h + __coroutine/coroutine_traits.h + __coroutine/noop_coroutine_handle.h + __coroutine/trivial_awaitables.h + __debug + __debug_utils/randomize_range.h + __errc + __expected/bad_expected_access.h + __expected/expected.h + __expected/unexpect.h + __expected/unexpected.h + __filesystem/copy_options.h + __filesystem/directory_entry.h + __filesystem/directory_iterator.h + __filesystem/directory_options.h + __filesystem/file_status.h + __filesystem/file_time_type.h + __filesystem/file_type.h + __filesystem/filesystem_error.h + __filesystem/operations.h + __filesystem/path.h + __filesystem/path_iterator.h + __filesystem/perm_options.h + __filesystem/perms.h + __filesystem/recursive_directory_iterator.h + __filesystem/space_info.h + __filesystem/u8path.h + __format/buffer.h + __format/concepts.h + __format/container_adaptor.h + __format/enable_insertable.h + __format/escaped_output_table.h + __format/extended_grapheme_cluster_table.h + __format/format_arg.h + __format/format_arg_store.h + __format/format_args.h + __format/format_context.h + __format/format_error.h + __format/format_functions.h + __format/format_fwd.h + __format/format_parse_context.h + __format/format_string.h + __format/format_to_n_result.h + __format/formatter.h + __format/formatter_bool.h + __format/formatter_char.h + __format/formatter_floating_point.h + __format/formatter_integer.h + __format/formatter_integral.h + __format/formatter_output.h + __format/formatter_pointer.h + __format/formatter_string.h + __format/formatter_tuple.h + __format/parser_std_format_spec.h + __format/range_default_formatter.h + __format/range_formatter.h + __format/unicode.h + __functional/binary_function.h + __functional/binary_negate.h + __functional/bind.h + __functional/bind_back.h + __functional/bind_front.h + __functional/binder1st.h + __functional/binder2nd.h + __functional/boyer_moore_searcher.h + __functional/compose.h + __functional/default_searcher.h + __functional/function.h + __functional/hash.h + __functional/identity.h + __functional/invoke.h + __functional/is_transparent.h + __functional/mem_fn.h + __functional/mem_fun_ref.h + __functional/not_fn.h + __functional/operations.h + __functional/perfect_forward.h + __functional/pointer_to_binary_function.h + __functional/pointer_to_unary_function.h + __functional/ranges_operations.h + __functional/reference_wrapper.h + __functional/unary_function.h + __functional/unary_negate.h + __functional/unwrap_ref.h + __functional/weak_result_type.h + __fwd/array.h + __fwd/get.h + __fwd/hash.h + __fwd/memory_resource.h + __fwd/pair.h + __fwd/span.h + __fwd/string.h + __fwd/string_view.h + __fwd/subrange.h + __fwd/tuple.h + __hash_table + __ios/fpos.h + __iterator/access.h + __iterator/advance.h + __iterator/back_insert_iterator.h + __iterator/bounded_iter.h + __iterator/common_iterator.h + __iterator/concepts.h + __iterator/counted_iterator.h + __iterator/data.h + __iterator/default_sentinel.h + __iterator/distance.h + __iterator/empty.h + __iterator/erase_if_container.h + __iterator/front_insert_iterator.h + __iterator/incrementable_traits.h + __iterator/indirectly_comparable.h + __iterator/insert_iterator.h + __iterator/istream_iterator.h + __iterator/istreambuf_iterator.h + __iterator/iter_move.h + __iterator/iter_swap.h + __iterator/iterator.h + __iterator/iterator_traits.h + __iterator/iterator_with_data.h + __iterator/mergeable.h + __iterator/move_iterator.h + __iterator/move_sentinel.h + __iterator/next.h + __iterator/ostream_iterator.h + __iterator/ostreambuf_iterator.h + __iterator/permutable.h + __iterator/prev.h + __iterator/projected.h + __iterator/readable_traits.h + __iterator/reverse_access.h + __iterator/reverse_iterator.h + __iterator/segmented_iterator.h + __iterator/size.h + __iterator/sortable.h + __iterator/unreachable_sentinel.h + __iterator/wrap_iter.h + __locale + __mbstate_t.h + __memory/addressof.h + __memory/align.h + __memory/allocate_at_least.h + __memory/allocation_guard.h + __memory/allocator.h + __memory/allocator_arg_t.h + __memory/allocator_destructor.h + __memory/allocator_traits.h + __memory/assume_aligned.h + __memory/auto_ptr.h + __memory/builtin_new_allocator.h + __memory/compressed_pair.h + __memory/concepts.h + __memory/construct_at.h + __memory/destruct_n.h + __memory/pointer_traits.h + __memory/ranges_construct_at.h + __memory/ranges_uninitialized_algorithms.h + __memory/raw_storage_iterator.h + __memory/shared_ptr.h + __memory/swap_allocator.h + __memory/temp_value.h + __memory/temporary_buffer.h + __memory/uninitialized_algorithms.h + __memory/unique_ptr.h + __memory/uses_allocator.h + __memory/uses_allocator_construction.h + __memory/voidify.h + __memory_resource/memory_resource.h + __memory_resource/monotonic_buffer_resource.h + __memory_resource/polymorphic_allocator.h + __memory_resource/pool_options.h + __memory_resource/synchronized_pool_resource.h + __memory_resource/unsynchronized_pool_resource.h + __mutex_base + __node_handle + __numeric/accumulate.h + __numeric/adjacent_difference.h + __numeric/exclusive_scan.h + __numeric/gcd_lcm.h + __numeric/inclusive_scan.h + __numeric/inner_product.h + __numeric/iota.h + __numeric/midpoint.h + __numeric/partial_sum.h + __numeric/reduce.h + __numeric/transform_exclusive_scan.h + __numeric/transform_inclusive_scan.h + __numeric/transform_reduce.h + __random/bernoulli_distribution.h + __random/binomial_distribution.h + __random/cauchy_distribution.h + __random/chi_squared_distribution.h + __random/clamp_to_integral.h + __random/default_random_engine.h + __random/discard_block_engine.h + __random/discrete_distribution.h + __random/exponential_distribution.h + __random/extreme_value_distribution.h + __random/fisher_f_distribution.h + __random/gamma_distribution.h + __random/generate_canonical.h + __random/geometric_distribution.h + __random/independent_bits_engine.h + __random/is_seed_sequence.h + __random/is_valid.h + __random/knuth_b.h + __random/linear_congruential_engine.h + __random/log2.h + __random/lognormal_distribution.h + __random/mersenne_twister_engine.h + __random/negative_binomial_distribution.h + __random/normal_distribution.h + __random/piecewise_constant_distribution.h + __random/piecewise_linear_distribution.h + __random/poisson_distribution.h + __random/random_device.h + __random/ranlux.h + __random/seed_seq.h + __random/shuffle_order_engine.h + __random/student_t_distribution.h + __random/subtract_with_carry_engine.h + __random/uniform_int_distribution.h + __random/uniform_random_bit_generator.h + __random/uniform_real_distribution.h + __random/weibull_distribution.h + __ranges/access.h + __ranges/all.h + __ranges/as_rvalue_view.h + __ranges/common_view.h + __ranges/concepts.h + __ranges/copyable_box.h + __ranges/counted.h + __ranges/dangling.h + __ranges/data.h + __ranges/drop_view.h + __ranges/drop_while_view.h + __ranges/elements_view.h + __ranges/empty.h + __ranges/empty_view.h + __ranges/enable_borrowed_range.h + __ranges/enable_view.h + __ranges/filter_view.h + __ranges/iota_view.h + __ranges/istream_view.h + __ranges/join_view.h + __ranges/lazy_split_view.h + __ranges/non_propagating_cache.h + __ranges/owning_view.h + __ranges/range_adaptor.h + __ranges/rbegin.h + __ranges/ref_view.h + __ranges/rend.h + __ranges/reverse_view.h + __ranges/single_view.h + __ranges/size.h + __ranges/split_view.h + __ranges/subrange.h + __ranges/take_view.h + __ranges/take_while_view.h + __ranges/transform_view.h + __ranges/view_interface.h + __ranges/views.h + __ranges/zip_view.h + __split_buffer + __std_stream + __string/char_traits.h + __string/extern_template_lists.h + __support/android/locale_bionic.h + __support/fuchsia/xlocale.h + __support/ibm/gettod_zos.h + __support/ibm/locale_mgmt_zos.h + __support/ibm/nanosleep.h + __support/ibm/xlocale.h + __support/musl/xlocale.h + __support/newlib/xlocale.h + __support/openbsd/xlocale.h + __support/solaris/floatingpoint.h + __support/solaris/wchar.h + __support/solaris/xlocale.h + __support/win32/locale_win32.h + __support/xlocale/__nop_locale_mgmt.h + __support/xlocale/__posix_l_fallback.h + __support/xlocale/__strtonum_fallback.h + __thread/poll_with_backoff.h + __thread/timed_backoff_policy.h + __threading_support + __tree + __tuple_dir/apply_cv.h + __tuple_dir/make_tuple_types.h + __tuple_dir/pair_like.h + __tuple_dir/sfinae_helpers.h + __tuple_dir/tuple_element.h + __tuple_dir/tuple_indices.h + __tuple_dir/tuple_like.h + __tuple_dir/tuple_like_ext.h + __tuple_dir/tuple_size.h + __tuple_dir/tuple_types.h + __type_traits/add_const.h + __type_traits/add_cv.h + __type_traits/add_lvalue_reference.h + __type_traits/add_pointer.h + __type_traits/add_rvalue_reference.h + __type_traits/add_volatile.h + __type_traits/aligned_storage.h + __type_traits/aligned_union.h + __type_traits/alignment_of.h + __type_traits/apply_cv.h + __type_traits/can_extract_key.h + __type_traits/common_reference.h + __type_traits/common_type.h + __type_traits/conditional.h + __type_traits/conjunction.h + __type_traits/copy_cv.h + __type_traits/copy_cvref.h + __type_traits/decay.h + __type_traits/dependent_type.h + __type_traits/disjunction.h + __type_traits/enable_if.h + __type_traits/extent.h + __type_traits/has_unique_object_representation.h + __type_traits/has_virtual_destructor.h + __type_traits/integral_constant.h + __type_traits/is_abstract.h + __type_traits/is_aggregate.h + __type_traits/is_allocator.h + __type_traits/is_always_bitcastable.h + __type_traits/is_arithmetic.h + __type_traits/is_array.h + __type_traits/is_assignable.h + __type_traits/is_base_of.h + __type_traits/is_bounded_array.h + __type_traits/is_callable.h + __type_traits/is_char_like_type.h + __type_traits/is_class.h + __type_traits/is_compound.h + __type_traits/is_const.h + __type_traits/is_constant_evaluated.h + __type_traits/is_constructible.h + __type_traits/is_convertible.h + __type_traits/is_copy_assignable.h + __type_traits/is_copy_constructible.h + __type_traits/is_core_convertible.h + __type_traits/is_default_constructible.h + __type_traits/is_destructible.h + __type_traits/is_empty.h + __type_traits/is_enum.h + __type_traits/is_final.h + __type_traits/is_floating_point.h + __type_traits/is_function.h + __type_traits/is_fundamental.h + __type_traits/is_implicitly_default_constructible.h + __type_traits/is_integral.h + __type_traits/is_literal_type.h + __type_traits/is_member_function_pointer.h + __type_traits/is_member_object_pointer.h + __type_traits/is_member_pointer.h + __type_traits/is_move_assignable.h + __type_traits/is_move_constructible.h + __type_traits/is_nothrow_assignable.h + __type_traits/is_nothrow_constructible.h + __type_traits/is_nothrow_convertible.h + __type_traits/is_nothrow_copy_assignable.h + __type_traits/is_nothrow_copy_constructible.h + __type_traits/is_nothrow_default_constructible.h + __type_traits/is_nothrow_destructible.h + __type_traits/is_nothrow_move_assignable.h + __type_traits/is_nothrow_move_constructible.h + __type_traits/is_null_pointer.h + __type_traits/is_object.h + __type_traits/is_pod.h + __type_traits/is_pointer.h + __type_traits/is_polymorphic.h + __type_traits/is_primary_template.h + __type_traits/is_reference.h + __type_traits/is_reference_wrapper.h + __type_traits/is_referenceable.h + __type_traits/is_same.h + __type_traits/is_scalar.h + __type_traits/is_scoped_enum.h + __type_traits/is_signed.h + __type_traits/is_signed_integer.h + __type_traits/is_specialization.h + __type_traits/is_standard_layout.h + __type_traits/is_swappable.h + __type_traits/is_trivial.h + __type_traits/is_trivially_assignable.h + __type_traits/is_trivially_constructible.h + __type_traits/is_trivially_copy_assignable.h + __type_traits/is_trivially_copy_constructible.h + __type_traits/is_trivially_copyable.h + __type_traits/is_trivially_default_constructible.h + __type_traits/is_trivially_destructible.h + __type_traits/is_trivially_move_assignable.h + __type_traits/is_trivially_move_constructible.h + __type_traits/is_unbounded_array.h + __type_traits/is_union.h + __type_traits/is_unsigned.h + __type_traits/is_unsigned_integer.h + __type_traits/is_valid_expansion.h + __type_traits/is_void.h + __type_traits/is_volatile.h + __type_traits/lazy.h + __type_traits/make_32_64_or_128_bit.h + __type_traits/make_const_lvalue_ref.h + __type_traits/make_signed.h + __type_traits/make_unsigned.h + __type_traits/maybe_const.h + __type_traits/nat.h + __type_traits/negation.h + __type_traits/noexcept_move_assign_container.h + __type_traits/promote.h + __type_traits/rank.h + __type_traits/remove_all_extents.h + __type_traits/remove_const.h + __type_traits/remove_const_ref.h + __type_traits/remove_cv.h + __type_traits/remove_cvref.h + __type_traits/remove_extent.h + __type_traits/remove_pointer.h + __type_traits/remove_reference.h + __type_traits/remove_volatile.h + __type_traits/result_of.h + __type_traits/strip_signature.h + __type_traits/type_identity.h + __type_traits/type_list.h + __type_traits/underlying_type.h + __type_traits/void_t.h + __undef_macros + __utility/as_const.h + __utility/auto_cast.h + __utility/cmp.h + __utility/convert_to_integral.h + __utility/declval.h + __utility/exception_guard.h + __utility/exchange.h + __utility/forward.h + __utility/forward_like.h + __utility/in_place.h + __utility/integer_sequence.h + __utility/move.h + __utility/pair.h + __utility/piecewise_construct.h + __utility/priority_tag.h + __utility/rel_ops.h + __utility/swap.h + __utility/to_underlying.h + __utility/unreachable.h + __variant/monostate.h + __verbose_abort + algorithm + any + array + atomic + barrier + bit + bitset + cassert + ccomplex + cctype + cerrno + cfenv + cfloat + charconv + chrono + cinttypes + ciso646 + climits + clocale + cmath + codecvt + compare + complex + complex.h + concepts + condition_variable + coroutine + csetjmp + csignal + cstdarg + cstdbool + cstddef + cstdint + cstdio + cstdlib + cstring + ctgmath + ctime + ctype.h + cuchar + cwchar + cwctype + deque + errno.h + exception + execution + expected + experimental/__config + experimental/__memory + experimental/algorithm + experimental/coroutine + experimental/deque + experimental/forward_list + experimental/functional + experimental/iterator + experimental/list + experimental/map + experimental/memory_resource + experimental/propagate_const + experimental/regex + experimental/set + experimental/simd + experimental/string + experimental/type_traits + experimental/unordered_map + experimental/unordered_set + experimental/utility + experimental/vector + ext/__hash + ext/hash_map + ext/hash_set + fenv.h + filesystem + float.h + format + forward_list + fstream + functional + future + initializer_list + inttypes.h + iomanip + ios + iosfwd + iostream + istream + iterator + latch + libcxx.imp + limits + limits.h + list + locale + locale.h + map + math.h + memory + memory_resource + mutex + new + numbers + numeric + optional + ostream + queue + random + ranges + ratio + regex + scoped_allocator + semaphore + set + setjmp.h + shared_mutex + source_location + span + sstream + stack + stdatomic.h + stdbool.h + stddef.h + stdexcept + stdint.h + stdio.h + stdlib.h + streambuf + string + string.h + string_view + strstream + system_error + tgmath.h + thread + tuple + type_traits + typeindex + typeinfo + uchar.h + unordered_map + unordered_set + utility + valarray + variant + vector + version + wchar.h + wctype.h + ) + +foreach(feature LIBCXX_ENABLE_FILESYSTEM LIBCXX_ENABLE_LOCALIZATION LIBCXX_ENABLE_FSTREAM LIBCXX_ENABLE_THREADS LIBCXX_ENABLE_WIDE_CHARACTERS) + if (NOT ${${feature}}) + set(requires_${feature} "requires LIBCXX_CONFIGURED_WITHOUT_SUPPORT_FOR_THIS_HEADER") + endif() +endforeach() + +configure_file("__config_site.in" "${LIBCXX_GENERATED_INCLUDE_TARGET_DIR}/__config_site" @ONLY) +configure_file("module.modulemap.in" "${LIBCXX_GENERATED_INCLUDE_DIR}/module.modulemap" @ONLY) + +set(_all_includes "${LIBCXX_GENERATED_INCLUDE_TARGET_DIR}/__config_site" + "${LIBCXX_GENERATED_INCLUDE_DIR}/module.modulemap") +foreach(f ${files}) + set(src "${CMAKE_CURRENT_SOURCE_DIR}/${f}") + set(dst "${LIBCXX_GENERATED_INCLUDE_DIR}/${f}") + add_custom_command(OUTPUT ${dst} + DEPENDS ${src} + COMMAND ${CMAKE_COMMAND} -E copy_if_different ${src} ${dst} + COMMENT "Copying CXX header ${f}") + list(APPEND _all_includes "${dst}") +endforeach() + +add_custom_target(generate-cxx-headers ALL DEPENDS ${_all_includes}) + +add_library(cxx-headers INTERFACE) +target_link_libraries(cxx-headers INTERFACE libcxx-abi-headers) +add_dependencies(cxx-headers generate-cxx-headers) +target_include_directories(cxx-headers INTERFACE ${LIBCXX_GENERATED_INCLUDE_DIR} + ${LIBCXX_GENERATED_INCLUDE_TARGET_DIR}) + +if (LIBCXX_INSTALL_HEADERS) + foreach(file ${files}) + get_filename_component(dir ${file} DIRECTORY) + install(FILES ${file} + DESTINATION "${LIBCXX_INSTALL_INCLUDE_DIR}/${dir}" + COMPONENT cxx-headers + PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ + ) + endforeach() + + # Install the generated __config_site file to the per-target include dir. + install(FILES "${LIBCXX_GENERATED_INCLUDE_TARGET_DIR}/__config_site" + DESTINATION "${LIBCXX_INSTALL_INCLUDE_TARGET_DIR}" + PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ + COMPONENT cxx-headers) + + # Install the generated modulemap file to the generic include dir. + install(FILES "${LIBCXX_GENERATED_INCLUDE_DIR}/module.modulemap" + DESTINATION "${LIBCXX_INSTALL_INCLUDE_DIR}" + PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ + COMPONENT cxx-headers) + + if (NOT CMAKE_CONFIGURATION_TYPES) + add_custom_target(install-cxx-headers + DEPENDS cxx-headers + COMMAND "${CMAKE_COMMAND}" + -DCMAKE_INSTALL_COMPONENT=cxx-headers + -P "${CMAKE_BINARY_DIR}/cmake_install.cmake") + # Stripping is a no-op for headers + add_custom_target(install-cxx-headers-stripped DEPENDS install-cxx-headers) + endif() +endif() diff --git a/app/src/main/cpp/libcxx/include/__algorithm/adjacent_find.h b/app/src/main/cpp/libcxx/include/__algorithm/adjacent_find.h new file mode 100644 index 0000000..30df4a9 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/adjacent_find.h @@ -0,0 +1,53 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_ADJACENT_FIND_H +#define _LIBCPP___ALGORITHM_ADJACENT_FIND_H + +#include <__algorithm/comp.h> +#include <__algorithm/iterator_operations.h> +#include <__config> +#include <__iterator/iterator_traits.h> +#include <__utility/move.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +template +_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Iter +__adjacent_find(_Iter __first, _Sent __last, _BinaryPredicate&& __pred) { + if (__first == __last) + return __first; + _Iter __i = __first; + while (++__i != __last) { + if (__pred(*__first, *__i)) + return __first; + __first = __i; + } + return __i; +} + +template +_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator +adjacent_find(_ForwardIterator __first, _ForwardIterator __last, _BinaryPredicate __pred) { + return std::__adjacent_find(std::move(__first), std::move(__last), __pred); +} + +template +_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator +adjacent_find(_ForwardIterator __first, _ForwardIterator __last) { + return std::adjacent_find(std::move(__first), std::move(__last), __equal_to()); +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ALGORITHM_ADJACENT_FIND_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/all_of.h b/app/src/main/cpp/libcxx/include/__algorithm/all_of.h new file mode 100644 index 0000000..284c34f --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/all_of.h @@ -0,0 +1,32 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_ALL_OF_H +#define _LIBCPP___ALGORITHM_ALL_OF_H + +#include <__config> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +template +_LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 bool +all_of(_InputIterator __first, _InputIterator __last, _Predicate __pred) { + for (; __first != __last; ++__first) + if (!__pred(*__first)) + return false; + return true; +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ALGORITHM_ALL_OF_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/any_of.h b/app/src/main/cpp/libcxx/include/__algorithm/any_of.h new file mode 100644 index 0000000..fe08828 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/any_of.h @@ -0,0 +1,32 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_ANY_OF_H +#define _LIBCPP___ALGORITHM_ANY_OF_H + +#include <__config> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +template +_LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 bool +any_of(_InputIterator __first, _InputIterator __last, _Predicate __pred) { + for (; __first != __last; ++__first) + if (__pred(*__first)) + return true; + return false; +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ALGORITHM_ANY_OF_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/binary_search.h b/app/src/main/cpp/libcxx/include/__algorithm/binary_search.h new file mode 100644 index 0000000..8f958c2 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/binary_search.h @@ -0,0 +1,46 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_BINARY_SEARCH_H +#define _LIBCPP___ALGORITHM_BINARY_SEARCH_H + +#include <__algorithm/comp.h> +#include <__algorithm/comp_ref_type.h> +#include <__algorithm/lower_bound.h> +#include <__config> +#include <__iterator/iterator_traits.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +template +_LIBCPP_NODISCARD_EXT inline +_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 +bool +binary_search(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value, _Compare __comp) +{ + __first = std::lower_bound<_ForwardIterator, _Tp, __comp_ref_type<_Compare> >(__first, __last, __value, __comp); + return __first != __last && !__comp(__value, *__first); +} + +template +_LIBCPP_NODISCARD_EXT inline +_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 +bool +binary_search(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value) +{ + return std::binary_search(__first, __last, __value, + __less::value_type, _Tp>()); +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ALGORITHM_BINARY_SEARCH_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/clamp.h b/app/src/main/cpp/libcxx/include/__algorithm/clamp.h new file mode 100644 index 0000000..30ddbdc --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/clamp.h @@ -0,0 +1,46 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_CLAMP_H +#define _LIBCPP___ALGORITHM_CLAMP_H + +#include <__algorithm/comp.h> +#include <__assert> +#include <__config> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 14 +template +_LIBCPP_NODISCARD_EXT inline +_LIBCPP_INLINE_VISIBILITY constexpr +const _Tp& +clamp(const _Tp& __v, const _Tp& __lo, const _Tp& __hi, _Compare __comp) +{ + _LIBCPP_ASSERT(!__comp(__hi, __lo), "Bad bounds passed to std::clamp"); + return __comp(__v, __lo) ? __lo : __comp(__hi, __v) ? __hi : __v; + +} + +template +_LIBCPP_NODISCARD_EXT inline +_LIBCPP_INLINE_VISIBILITY constexpr +const _Tp& +clamp(const _Tp& __v, const _Tp& __lo, const _Tp& __hi) +{ + return _VSTD::clamp(__v, __lo, __hi, __less<_Tp>()); +} +#endif + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ALGORITHM_CLAMP_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/comp.h b/app/src/main/cpp/libcxx/include/__algorithm/comp.h new file mode 100644 index 0000000..af8eb7b --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/comp.h @@ -0,0 +1,66 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_COMP_H +#define _LIBCPP___ALGORITHM_COMP_H + +#include <__config> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +struct __equal_to { + template + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 bool operator()(const _T1& __x, const _T2& __y) const { + return __x == __y; + } +}; + +template +struct __less +{ + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 + bool operator()(const _T1& __x, const _T1& __y) const {return __x < __y;} + + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 + bool operator()(const _T1& __x, const _T2& __y) const {return __x < __y;} + + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 + bool operator()(const _T2& __x, const _T1& __y) const {return __x < __y;} + + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 + bool operator()(const _T2& __x, const _T2& __y) const {return __x < __y;} +}; + +template +struct __less<_T1, _T1> +{ + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 + bool operator()(const _T1& __x, const _T1& __y) const {return __x < __y;} +}; + +template +struct __less +{ + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 + bool operator()(const _T1& __x, const _T1& __y) const {return __x < __y;} +}; + +template +struct __less<_T1, const _T1> +{ + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 + bool operator()(const _T1& __x, const _T1& __y) const {return __x < __y;} +}; + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ALGORITHM_COMP_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/comp_ref_type.h b/app/src/main/cpp/libcxx/include/__algorithm/comp_ref_type.h new file mode 100644 index 0000000..f2338e1 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/comp_ref_type.h @@ -0,0 +1,79 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_COMP_REF_TYPE_H +#define _LIBCPP___ALGORITHM_COMP_REF_TYPE_H + +#include <__config> +#include <__debug> +#include <__utility/declval.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +template +struct __debug_less +{ + _Compare &__comp_; + _LIBCPP_CONSTEXPR_SINCE_CXX14 + __debug_less(_Compare& __c) : __comp_(__c) {} + + template + _LIBCPP_CONSTEXPR_SINCE_CXX14 + bool operator()(const _Tp& __x, const _Up& __y) + { + bool __r = __comp_(__x, __y); + if (__r) + __do_compare_assert(0, __y, __x); + return __r; + } + + template + _LIBCPP_CONSTEXPR_SINCE_CXX14 + bool operator()(_Tp& __x, _Up& __y) + { + bool __r = __comp_(__x, __y); + if (__r) + __do_compare_assert(0, __y, __x); + return __r; + } + + template + _LIBCPP_CONSTEXPR_SINCE_CXX14 + inline _LIBCPP_INLINE_VISIBILITY + decltype((void)std::declval<_Compare&>()( + std::declval<_LHS &>(), std::declval<_RHS &>())) + __do_compare_assert(int, _LHS & __l, _RHS & __r) { + _LIBCPP_DEBUG_ASSERT(!__comp_(__l, __r), + "Comparator does not induce a strict weak ordering"); + (void)__l; + (void)__r; + } + + template + _LIBCPP_CONSTEXPR_SINCE_CXX14 + inline _LIBCPP_INLINE_VISIBILITY + void __do_compare_assert(long, _LHS &, _RHS &) {} +}; + +// Pass the comparator by lvalue reference. Or in debug mode, using a +// debugging wrapper that stores a reference. +#ifdef _LIBCPP_ENABLE_DEBUG_MODE +template +using __comp_ref_type = __debug_less<_Comp>; +#else +template +using __comp_ref_type = _Comp&; +#endif + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ALGORITHM_COMP_REF_TYPE_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/copy.h b/app/src/main/cpp/libcxx/include/__algorithm/copy.h new file mode 100644 index 0000000..193a6df --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/copy.h @@ -0,0 +1,126 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_COPY_H +#define _LIBCPP___ALGORITHM_COPY_H + +#include <__algorithm/copy_move_common.h> +#include <__algorithm/iterator_operations.h> +#include <__algorithm/min.h> +#include <__config> +#include <__iterator/segmented_iterator.h> +#include <__type_traits/common_type.h> +#include <__utility/move.h> +#include <__utility/pair.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + +_LIBCPP_BEGIN_NAMESPACE_STD + +template +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_InIter, _OutIter> __copy(_InIter, _Sent, _OutIter); + +template +struct __copy_loop { + template + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_InIter, _OutIter> + operator()(_InIter __first, _Sent __last, _OutIter __result) const { + while (__first != __last) { + *__result = *__first; + ++__first; + ++__result; + } + + return std::make_pair(std::move(__first), std::move(__result)); + } + + template ::value, int> = 0> + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_InIter, _OutIter> + operator()(_InIter __first, _InIter __last, _OutIter __result) const { + using _Traits = __segmented_iterator_traits<_InIter>; + auto __sfirst = _Traits::__segment(__first); + auto __slast = _Traits::__segment(__last); + if (__sfirst == __slast) { + auto __iters = std::__copy<_AlgPolicy>(_Traits::__local(__first), _Traits::__local(__last), std::move(__result)); + return std::make_pair(__last, std::move(__iters.second)); + } + + __result = std::__copy<_AlgPolicy>(_Traits::__local(__first), _Traits::__end(__sfirst), std::move(__result)).second; + ++__sfirst; + while (__sfirst != __slast) { + __result = + std::__copy<_AlgPolicy>(_Traits::__begin(__sfirst), _Traits::__end(__sfirst), std::move(__result)).second; + ++__sfirst; + } + __result = + std::__copy<_AlgPolicy>(_Traits::__begin(__sfirst), _Traits::__local(__last), std::move(__result)).second; + return std::make_pair(__last, std::move(__result)); + } + + template ::value && + !__is_segmented_iterator<_InIter>::value && __is_segmented_iterator<_OutIter>::value, + int> = 0> + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_InIter, _OutIter> + operator()(_InIter __first, _InIter __last, _OutIter __result) { + using _Traits = __segmented_iterator_traits<_OutIter>; + using _DiffT = typename common_type<__iter_diff_t<_InIter>, __iter_diff_t<_OutIter> >::type; + + if (__first == __last) + return std::make_pair(std::move(__first), std::move(__result)); + + auto __local_first = _Traits::__local(__result); + auto __segment_iterator = _Traits::__segment(__result); + while (true) { + auto __local_last = _Traits::__end(__segment_iterator); + auto __size = std::min<_DiffT>(__local_last - __local_first, __last - __first); + auto __iters = std::__copy<_AlgPolicy>(__first, __first + __size, __local_first); + __first = std::move(__iters.first); + + if (__first == __last) + return std::make_pair(std::move(__first), _Traits::__compose(__segment_iterator, std::move(__iters.second))); + + __local_first = _Traits::__begin(++__segment_iterator); + } + } +}; + +struct __copy_trivial { + // At this point, the iterators have been unwrapped so any `contiguous_iterator` has been unwrapped to a pointer. + template ::value, int> = 0> + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_In*, _Out*> + operator()(_In* __first, _In* __last, _Out* __result) const { + return std::__copy_trivial_impl(__first, __last, __result); + } +}; + +template +pair<_InIter, _OutIter> inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 +__copy(_InIter __first, _Sent __last, _OutIter __result) { + return std::__dispatch_copy_or_move<_AlgPolicy, __copy_loop<_AlgPolicy>, __copy_trivial>( + std::move(__first), std::move(__last), std::move(__result)); +} + +template +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 _OutputIterator +copy(_InputIterator __first, _InputIterator __last, _OutputIterator __result) { + return std::__copy<_ClassicAlgPolicy>(__first, __last, __result).second; +} + +_LIBCPP_END_NAMESPACE_STD + +_LIBCPP_POP_MACROS + +#endif // _LIBCPP___ALGORITHM_COPY_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/copy_backward.h b/app/src/main/cpp/libcxx/include/__algorithm/copy_backward.h new file mode 100644 index 0000000..bb2a432 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/copy_backward.h @@ -0,0 +1,143 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_COPY_BACKWARD_H +#define _LIBCPP___ALGORITHM_COPY_BACKWARD_H + +#include <__algorithm/copy_move_common.h> +#include <__algorithm/iterator_operations.h> +#include <__algorithm/min.h> +#include <__config> +#include <__iterator/segmented_iterator.h> +#include <__type_traits/common_type.h> +#include <__type_traits/is_copy_constructible.h> +#include <__utility/move.h> +#include <__utility/pair.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + +_LIBCPP_BEGIN_NAMESPACE_STD + +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_InIter, _OutIter> +__copy_backward(_InIter __first, _Sent __last, _OutIter __result); + +template +struct __copy_backward_loop { + template + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_InIter, _OutIter> + operator()(_InIter __first, _Sent __last, _OutIter __result) const { + auto __last_iter = _IterOps<_AlgPolicy>::next(__first, __last); + auto __original_last_iter = __last_iter; + + while (__first != __last_iter) { + *--__result = *--__last_iter; + } + + return std::make_pair(std::move(__original_last_iter), std::move(__result)); + } + + template ::value, int> = 0> + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_InIter, _OutIter> + operator()(_InIter __first, _InIter __last, _OutIter __result) const { + using _Traits = __segmented_iterator_traits<_InIter>; + auto __sfirst = _Traits::__segment(__first); + auto __slast = _Traits::__segment(__last); + if (__sfirst == __slast) { + auto __iters = + std::__copy_backward<_AlgPolicy>(_Traits::__local(__first), _Traits::__local(__last), std::move(__result)); + return std::make_pair(__last, __iters.second); + } + + __result = + std::__copy_backward<_AlgPolicy>(_Traits::__begin(__slast), _Traits::__local(__last), std::move(__result)) + .second; + --__slast; + while (__sfirst != __slast) { + __result = + std::__copy_backward<_AlgPolicy>(_Traits::__begin(__slast), _Traits::__end(__slast), std::move(__result)) + .second; + --__slast; + } + __result = std::__copy_backward<_AlgPolicy>(_Traits::__local(__first), _Traits::__end(__slast), std::move(__result)) + .second; + return std::make_pair(__last, std::move(__result)); + } + + template ::value && + !__is_segmented_iterator<_InIter>::value && __is_segmented_iterator<_OutIter>::value, + int> = 0> + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_InIter, _OutIter> + operator()(_InIter __first, _InIter __last, _OutIter __result) { + using _Traits = __segmented_iterator_traits<_OutIter>; + auto __orig_last = __last; + auto __segment_iterator = _Traits::__segment(__result); + + // When the range contains no elements, __result might not be a valid iterator + if (__first == __last) + return std::make_pair(__first, __result); + + auto __local_last = _Traits::__local(__result); + while (true) { + using _DiffT = typename common_type<__iter_diff_t<_InIter>, __iter_diff_t<_OutIter> >::type; + + auto __local_first = _Traits::__begin(__segment_iterator); + auto __size = std::min<_DiffT>(__local_last - __local_first, __last - __first); + auto __iter = std::__copy_backward<_AlgPolicy>(__last - __size, __last, __local_last).second; + __last -= __size; + + if (__first == __last) + return std::make_pair(std::move(__orig_last), _Traits::__compose(__segment_iterator, std::move(__iter))); + --__segment_iterator; + __local_last = _Traits::__end(__segment_iterator); + } + } +}; + +struct __copy_backward_trivial { + // At this point, the iterators have been unwrapped so any `contiguous_iterator` has been unwrapped to a pointer. + template ::value, int> = 0> + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_In*, _Out*> + operator()(_In* __first, _In* __last, _Out* __result) const { + return std::__copy_backward_trivial_impl(__first, __last, __result); + } +}; + +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_BidirectionalIterator1, _BidirectionalIterator2> +__copy_backward(_BidirectionalIterator1 __first, _Sentinel __last, _BidirectionalIterator2 __result) { + return std::__dispatch_copy_or_move<_AlgPolicy, __copy_backward_loop<_AlgPolicy>, __copy_backward_trivial>( + std::move(__first), std::move(__last), std::move(__result)); +} + +template +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 +_BidirectionalIterator2 +copy_backward(_BidirectionalIterator1 __first, _BidirectionalIterator1 __last, + _BidirectionalIterator2 __result) +{ + static_assert(std::is_copy_constructible<_BidirectionalIterator1>::value && + std::is_copy_constructible<_BidirectionalIterator1>::value, "Iterators must be copy constructible."); + + return std::__copy_backward<_ClassicAlgPolicy>( + std::move(__first), std::move(__last), std::move(__result)).second; +} + +_LIBCPP_END_NAMESPACE_STD + +_LIBCPP_POP_MACROS + +#endif // _LIBCPP___ALGORITHM_COPY_BACKWARD_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/copy_if.h b/app/src/main/cpp/libcxx/include/__algorithm/copy_if.h new file mode 100644 index 0000000..a5938b8 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/copy_if.h @@ -0,0 +1,39 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_COPY_IF_H +#define _LIBCPP___ALGORITHM_COPY_IF_H + +#include <__config> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +template +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 +_OutputIterator +copy_if(_InputIterator __first, _InputIterator __last, + _OutputIterator __result, _Predicate __pred) +{ + for (; __first != __last; ++__first) + { + if (__pred(*__first)) + { + *__result = *__first; + ++__result; + } + } + return __result; +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ALGORITHM_COPY_IF_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/copy_move_common.h b/app/src/main/cpp/libcxx/include/__algorithm/copy_move_common.h new file mode 100644 index 0000000..b88c149 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/copy_move_common.h @@ -0,0 +1,163 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_COPY_MOVE_COMMON_H +#define _LIBCPP___ALGORITHM_COPY_MOVE_COMMON_H + +#include <__algorithm/iterator_operations.h> +#include <__algorithm/unwrap_iter.h> +#include <__algorithm/unwrap_range.h> +#include <__config> +#include <__iterator/iterator_traits.h> +#include <__memory/pointer_traits.h> +#include <__type_traits/enable_if.h> +#include <__type_traits/is_always_bitcastable.h> +#include <__type_traits/is_constant_evaluated.h> +#include <__type_traits/is_copy_constructible.h> +#include <__type_traits/is_trivially_assignable.h> +#include <__type_traits/is_trivially_copyable.h> +#include <__type_traits/is_volatile.h> +#include <__utility/move.h> +#include <__utility/pair.h> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +// Type traits. + +template +struct __can_lower_copy_assignment_to_memmove { + static const bool value = + // If the types are always bitcastable, it's valid to do a bitwise copy between them. + __is_always_bitcastable<_From, _To>::value && + // Reject conversions that wouldn't be performed by the regular built-in assignment (e.g. between arrays). + is_trivially_assignable<_To&, const _From&>::value && + // `memmove` doesn't accept `volatile` pointers, make sure the optimization SFINAEs away in that case. + !is_volatile<_From>::value && + !is_volatile<_To>::value; +}; + +template +struct __can_lower_move_assignment_to_memmove { + static const bool value = + __is_always_bitcastable<_From, _To>::value && + is_trivially_assignable<_To&, _From&&>::value && + !is_volatile<_From>::value && + !is_volatile<_To>::value; +}; + +// `memmove` algorithms implementation. + +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_In*, _Out*> +__copy_trivial_impl(_In* __first, _In* __last, _Out* __result) { + const size_t __n = static_cast(__last - __first); + ::__builtin_memmove(__result, __first, __n * sizeof(_Out)); + + return std::make_pair(__last, __result + __n); +} + +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_In*, _Out*> +__copy_backward_trivial_impl(_In* __first, _In* __last, _Out* __result) { + const size_t __n = static_cast(__last - __first); + __result -= __n; + + ::__builtin_memmove(__result, __first, __n * sizeof(_Out)); + + return std::make_pair(__last, __result); +} + +// Iterator unwrapping and dispatching to the correct overload. + +template +struct __overload : _F1, _F2 { + using _F1::operator(); + using _F2::operator(); +}; + +template +struct __can_rewrap : false_type {}; + +template +struct __can_rewrap<_InIter, + _Sent, + _OutIter, + // Note that sentinels are always copy-constructible. + __enable_if_t< is_copy_constructible<_InIter>::value && + is_copy_constructible<_OutIter>::value > > : true_type {}; + +template ::value, int> = 0> +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 pair<_InIter, _OutIter> +__unwrap_and_dispatch(_InIter __first, _Sent __last, _OutIter __out_first) { + auto __range = std::__unwrap_range(__first, std::move(__last)); + auto __result = _Algorithm()(std::move(__range.first), std::move(__range.second), std::__unwrap_iter(__out_first)); + return std::make_pair(std::__rewrap_range<_Sent>(std::move(__first), std::move(__result.first)), + std::__rewrap_iter(std::move(__out_first), std::move(__result.second))); +} + +template ::value, int> = 0> +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 pair<_InIter, _OutIter> +__unwrap_and_dispatch(_InIter __first, _Sent __last, _OutIter __out_first) { + return _Algorithm()(std::move(__first), std::move(__last), std::move(__out_first)); +} + +template +struct __can_copy_without_conversion : false_type {}; + +template +struct __can_copy_without_conversion< + _IterOps, + _InValue, + _OutIter, + __enable_if_t >::value> > : true_type {}; + +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 pair<_InIter, _OutIter> +__dispatch_copy_or_move(_InIter __first, _Sent __last, _OutIter __out_first) { +#ifdef _LIBCPP_COMPILER_GCC + // GCC doesn't support `__builtin_memmove` during constant evaluation. + if (__libcpp_is_constant_evaluated()) { + return std::__unwrap_and_dispatch<_NaiveAlgorithm>(std::move(__first), std::move(__last), std::move(__out_first)); + } +#else + // In Clang, `__builtin_memmove` only supports fully trivially copyable types (just having trivial copy assignment is + // insufficient). Also, conversions are not supported. + if (__libcpp_is_constant_evaluated()) { + using _InValue = typename _IterOps<_AlgPolicy>::template __value_type<_InIter>; + if (!is_trivially_copyable<_InValue>::value || + !__can_copy_without_conversion<_IterOps<_AlgPolicy>, _InValue, _OutIter>::value) { + return std::__unwrap_and_dispatch<_NaiveAlgorithm>(std::move(__first), std::move(__last), std::move(__out_first)); + } + } +#endif // _LIBCPP_COMPILER_GCC + + using _Algorithm = __overload<_NaiveAlgorithm, _OptimizedAlgorithm>; + return std::__unwrap_and_dispatch<_Algorithm>(std::move(__first), std::move(__last), std::move(__out_first)); +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ALGORITHM_COPY_MOVE_COMMON_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/copy_n.h b/app/src/main/cpp/libcxx/include/__algorithm/copy_n.h new file mode 100644 index 0000000..b08bbdf --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/copy_n.h @@ -0,0 +1,67 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_COPY_N_H +#define _LIBCPP___ALGORITHM_COPY_N_H + +#include <__algorithm/copy.h> +#include <__config> +#include <__iterator/iterator_traits.h> +#include <__utility/convert_to_integral.h> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +template +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 +typename enable_if +< + __is_cpp17_input_iterator<_InputIterator>::value && + !__is_cpp17_random_access_iterator<_InputIterator>::value, + _OutputIterator +>::type +copy_n(_InputIterator __first, _Size __orig_n, _OutputIterator __result) +{ + typedef decltype(_VSTD::__convert_to_integral(__orig_n)) _IntegralSize; + _IntegralSize __n = __orig_n; + if (__n > 0) + { + *__result = *__first; + ++__result; + for (--__n; __n > 0; --__n) + { + ++__first; + *__result = *__first; + ++__result; + } + } + return __result; +} + +template +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 +typename enable_if +< + __is_cpp17_random_access_iterator<_InputIterator>::value, + _OutputIterator +>::type +copy_n(_InputIterator __first, _Size __orig_n, _OutputIterator __result) +{ + typedef typename iterator_traits<_InputIterator>::difference_type difference_type; + typedef decltype(_VSTD::__convert_to_integral(__orig_n)) _IntegralSize; + _IntegralSize __n = __orig_n; + return _VSTD::copy(__first, __first + difference_type(__n), __result); +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ALGORITHM_COPY_N_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/count.h b/app/src/main/cpp/libcxx/include/__algorithm/count.h new file mode 100644 index 0000000..6c8c7fd --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/count.h @@ -0,0 +1,35 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_COUNT_H +#define _LIBCPP___ALGORITHM_COUNT_H + +#include <__config> +#include <__iterator/iterator_traits.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +template +_LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 + typename iterator_traits<_InputIterator>::difference_type + count(_InputIterator __first, _InputIterator __last, const _Tp& __value) { + typename iterator_traits<_InputIterator>::difference_type __r(0); + for (; __first != __last; ++__first) + if (*__first == __value) + ++__r; + return __r; +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ALGORITHM_COUNT_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/count_if.h b/app/src/main/cpp/libcxx/include/__algorithm/count_if.h new file mode 100644 index 0000000..b96521f --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/count_if.h @@ -0,0 +1,35 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_COUNT_IF_H +#define _LIBCPP___ALGORITHM_COUNT_IF_H + +#include <__config> +#include <__iterator/iterator_traits.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +template +_LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 + typename iterator_traits<_InputIterator>::difference_type + count_if(_InputIterator __first, _InputIterator __last, _Predicate __pred) { + typename iterator_traits<_InputIterator>::difference_type __r(0); + for (; __first != __last; ++__first) + if (__pred(*__first)) + ++__r; + return __r; +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ALGORITHM_COUNT_IF_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/equal.h b/app/src/main/cpp/libcxx/include/__algorithm/equal.h new file mode 100644 index 0000000..cf37f46 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/equal.h @@ -0,0 +1,86 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_EQUAL_H +#define _LIBCPP___ALGORITHM_EQUAL_H + +#include <__algorithm/comp.h> +#include <__config> +#include <__iterator/distance.h> +#include <__iterator/iterator_traits.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +template +_LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 bool +equal(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2, _BinaryPredicate __pred) { + for (; __first1 != __last1; ++__first1, (void)++__first2) + if (!__pred(*__first1, *__first2)) + return false; + return true; +} + +template +_LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 bool +equal(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2) { + return std::equal(__first1, __last1, __first2, __equal_to()); +} + +#if _LIBCPP_STD_VER > 11 +template +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 bool +__equal(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2, _InputIterator2 __last2, + _BinaryPredicate __pred, input_iterator_tag, input_iterator_tag) { + for (; __first1 != __last1 && __first2 != __last2; ++__first1, (void)++__first2) + if (!__pred(*__first1, *__first2)) + return false; + return __first1 == __last1 && __first2 == __last2; +} + +template +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 bool +__equal(_RandomAccessIterator1 __first1, _RandomAccessIterator1 __last1, _RandomAccessIterator2 __first2, + _RandomAccessIterator2 __last2, _BinaryPredicate __pred, random_access_iterator_tag, + random_access_iterator_tag) { + if (_VSTD::distance(__first1, __last1) != _VSTD::distance(__first2, __last2)) + return false; + return _VSTD::equal<_RandomAccessIterator1, _RandomAccessIterator2, + _BinaryPredicate&>(__first1, __last1, __first2, __pred); +} + +template +_LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 bool +equal(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2, _InputIterator2 __last2, + _BinaryPredicate __pred) { + return _VSTD::__equal<_BinaryPredicate&>( + __first1, __last1, __first2, __last2, __pred, typename iterator_traits<_InputIterator1>::iterator_category(), + typename iterator_traits<_InputIterator2>::iterator_category()); +} + +template +_LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 bool +equal(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2, _InputIterator2 __last2) { + return std::__equal( + __first1, + __last1, + __first2, + __last2, + __equal_to(), + typename iterator_traits<_InputIterator1>::iterator_category(), + typename iterator_traits<_InputIterator2>::iterator_category()); +} +#endif + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ALGORITHM_EQUAL_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/equal_range.h b/app/src/main/cpp/libcxx/include/__algorithm/equal_range.h new file mode 100644 index 0000000..2075b03 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/equal_range.h @@ -0,0 +1,87 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_EQUAL_RANGE_H +#define _LIBCPP___ALGORITHM_EQUAL_RANGE_H + +#include <__algorithm/comp.h> +#include <__algorithm/comp_ref_type.h> +#include <__algorithm/half_positive.h> +#include <__algorithm/iterator_operations.h> +#include <__algorithm/lower_bound.h> +#include <__algorithm/upper_bound.h> +#include <__config> +#include <__functional/identity.h> +#include <__functional/invoke.h> +#include <__iterator/advance.h> +#include <__iterator/distance.h> +#include <__iterator/iterator_traits.h> +#include <__iterator/next.h> +#include <__type_traits/is_callable.h> +#include <__type_traits/is_copy_constructible.h> +#include <__utility/move.h> +#include <__utility/pair.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_Iter, _Iter> +__equal_range(_Iter __first, _Sent __last, const _Tp& __value, _Compare&& __comp, _Proj&& __proj) { + auto __len = _IterOps<_AlgPolicy>::distance(__first, __last); + _Iter __end = _IterOps<_AlgPolicy>::next(__first, __last); + while (__len != 0) { + auto __half_len = std::__half_positive(__len); + _Iter __mid = _IterOps<_AlgPolicy>::next(__first, __half_len); + if (std::__invoke(__comp, std::__invoke(__proj, *__mid), __value)) { + __first = ++__mid; + __len -= __half_len + 1; + } else if (std::__invoke(__comp, __value, std::__invoke(__proj, *__mid))) { + __end = __mid; + __len = __half_len; + } else { + _Iter __mp1 = __mid; + return pair<_Iter, _Iter>( + std::__lower_bound_impl<_AlgPolicy>(__first, __mid, __value, __comp, __proj), + std::__upper_bound<_AlgPolicy>(++__mp1, __end, __value, __comp, __proj)); + } + } + return pair<_Iter, _Iter>(__first, __first); +} + +template +_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_ForwardIterator, _ForwardIterator> +equal_range(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value, _Compare __comp) { + static_assert(__is_callable<_Compare, decltype(*__first), const _Tp&>::value, + "The comparator has to be callable"); + static_assert(is_copy_constructible<_ForwardIterator>::value, + "Iterator has to be copy constructible"); + return std::__equal_range<_ClassicAlgPolicy>( + std::move(__first), + std::move(__last), + __value, + static_cast<__comp_ref_type<_Compare> >(__comp), + std::__identity()); +} + +template +_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_ForwardIterator, _ForwardIterator> +equal_range(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value) { + return std::equal_range( + std::move(__first), + std::move(__last), + __value, + __less::value_type, _Tp>()); +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ALGORITHM_EQUAL_RANGE_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/fill.h b/app/src/main/cpp/libcxx/include/__algorithm/fill.h new file mode 100644 index 0000000..76cf4a1 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/fill.h @@ -0,0 +1,52 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_FILL_H +#define _LIBCPP___ALGORITHM_FILL_H + +#include <__algorithm/fill_n.h> +#include <__config> +#include <__iterator/iterator_traits.h> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +// fill isn't specialized for std::memset, because the compiler already optimizes the loop to a call to std::memset. + +template +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 +void +__fill(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value, forward_iterator_tag) +{ + for (; __first != __last; ++__first) + *__first = __value; +} + +template +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 +void +__fill(_RandomAccessIterator __first, _RandomAccessIterator __last, const _Tp& __value, random_access_iterator_tag) +{ + _VSTD::fill_n(__first, __last - __first, __value); +} + +template +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 +void +fill(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value) +{ + _VSTD::__fill(__first, __last, __value, typename iterator_traits<_ForwardIterator>::iterator_category()); +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ALGORITHM_FILL_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/fill_n.h b/app/src/main/cpp/libcxx/include/__algorithm/fill_n.h new file mode 100644 index 0000000..fe58c8d --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/fill_n.h @@ -0,0 +1,45 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_FILL_N_H +#define _LIBCPP___ALGORITHM_FILL_N_H + +#include <__config> +#include <__iterator/iterator_traits.h> +#include <__utility/convert_to_integral.h> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +// fill_n isn't specialized for std::memset, because the compiler already optimizes the loop to a call to std::memset. + +template +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 +_OutputIterator +__fill_n(_OutputIterator __first, _Size __n, const _Tp& __value) +{ + for (; __n > 0; ++__first, (void) --__n) + *__first = __value; + return __first; +} + +template +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 +_OutputIterator +fill_n(_OutputIterator __first, _Size __n, const _Tp& __value) +{ + return _VSTD::__fill_n(__first, _VSTD::__convert_to_integral(__n), __value); +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ALGORITHM_FILL_N_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/find.h b/app/src/main/cpp/libcxx/include/__algorithm/find.h new file mode 100644 index 0000000..e51dc9b --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/find.h @@ -0,0 +1,32 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_FIND_H +#define _LIBCPP___ALGORITHM_FIND_H + +#include <__config> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +template +_LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 _InputIterator +find(_InputIterator __first, _InputIterator __last, const _Tp& __value) { + for (; __first != __last; ++__first) + if (*__first == __value) + break; + return __first; +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ALGORITHM_FIND_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/find_end.h b/app/src/main/cpp/libcxx/include/__algorithm/find_end.h new file mode 100644 index 0000000..e2fee6b --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/find_end.h @@ -0,0 +1,227 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_FIND_END_OF_H +#define _LIBCPP___ALGORITHM_FIND_END_OF_H + +#include <__algorithm/comp.h> +#include <__algorithm/iterator_operations.h> +#include <__algorithm/search.h> +#include <__config> +#include <__functional/identity.h> +#include <__iterator/advance.h> +#include <__iterator/iterator_traits.h> +#include <__iterator/next.h> +#include <__iterator/reverse_iterator.h> +#include <__utility/pair.h> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +template < + class _AlgPolicy, + class _Iter1, + class _Sent1, + class _Iter2, + class _Sent2, + class _Pred, + class _Proj1, + class _Proj2> +_LIBCPP_HIDE_FROM_ABI inline _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_Iter1, _Iter1> __find_end_impl( + _Iter1 __first1, + _Sent1 __last1, + _Iter2 __first2, + _Sent2 __last2, + _Pred& __pred, + _Proj1& __proj1, + _Proj2& __proj2, + forward_iterator_tag, + forward_iterator_tag) { + // modeled after search algorithm + _Iter1 __match_first = _IterOps<_AlgPolicy>::next(__first1, __last1); // __last1 is the "default" answer + _Iter1 __match_last = __match_first; + if (__first2 == __last2) + return pair<_Iter1, _Iter1>(__match_last, __match_last); + while (true) { + while (true) { + if (__first1 == __last1) // if source exhausted return last correct answer (or __last1 if never found) + return pair<_Iter1, _Iter1>(__match_first, __match_last); + if (std::__invoke(__pred, std::__invoke(__proj1, *__first1), std::__invoke(__proj2, *__first2))) + break; + ++__first1; + } + // *__first1 matches *__first2, now match elements after here + _Iter1 __m1 = __first1; + _Iter2 __m2 = __first2; + while (true) { + if (++__m2 == __last2) { // Pattern exhaused, record answer and search for another one + __match_first = __first1; + __match_last = ++__m1; + ++__first1; + break; + } + if (++__m1 == __last1) // Source exhausted, return last answer + return pair<_Iter1, _Iter1>(__match_first, __match_last); + // mismatch, restart with a new __first + if (!std::__invoke(__pred, std::__invoke(__proj1, *__m1), std::__invoke(__proj2, *__m2))) + { + ++__first1; + break; + } // else there is a match, check next elements + } + } +} + +template < + class _IterOps, + class _Pred, + class _Iter1, + class _Sent1, + class _Iter2, + class _Sent2, + class _Proj1, + class _Proj2> +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Iter1 __find_end( + _Iter1 __first1, + _Sent1 __sent1, + _Iter2 __first2, + _Sent2 __sent2, + _Pred& __pred, + _Proj1& __proj1, + _Proj2& __proj2, + bidirectional_iterator_tag, + bidirectional_iterator_tag) { + auto __last1 = _IterOps::next(__first1, __sent1); + auto __last2 = _IterOps::next(__first2, __sent2); + // modeled after search algorithm (in reverse) + if (__first2 == __last2) + return __last1; // Everything matches an empty sequence + _Iter1 __l1 = __last1; + _Iter2 __l2 = __last2; + --__l2; + while (true) { + // Find last element in sequence 1 that matchs *(__last2-1), with a mininum of loop checks + while (true) { + if (__first1 == __l1) // return __last1 if no element matches *__first2 + return __last1; + if (std::__invoke(__pred, std::__invoke(__proj1, *--__l1), std::__invoke(__proj2, *__l2))) + break; + } + // *__l1 matches *__l2, now match elements before here + _Iter1 __m1 = __l1; + _Iter2 __m2 = __l2; + while (true) { + if (__m2 == __first2) // If pattern exhausted, __m1 is the answer (works for 1 element pattern) + return __m1; + if (__m1 == __first1) // Otherwise if source exhaused, pattern not found + return __last1; + + // if there is a mismatch, restart with a new __l1 + if (!std::__invoke(__pred, std::__invoke(__proj1, *--__m1), std::__invoke(__proj2, *--__m2))) + { + break; + } // else there is a match, check next elements + } + } +} + +template < + class _AlgPolicy, + class _Pred, + class _Iter1, + class _Sent1, + class _Iter2, + class _Sent2, + class _Proj1, + class _Proj2> +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _Iter1 __find_end( + _Iter1 __first1, + _Sent1 __sent1, + _Iter2 __first2, + _Sent2 __sent2, + _Pred& __pred, + _Proj1& __proj1, + _Proj2& __proj2, + random_access_iterator_tag, + random_access_iterator_tag) { + typedef typename iterator_traits<_Iter1>::difference_type _D1; + auto __last1 = _IterOps<_AlgPolicy>::next(__first1, __sent1); + auto __last2 = _IterOps<_AlgPolicy>::next(__first2, __sent2); + // Take advantage of knowing source and pattern lengths. Stop short when source is smaller than pattern + auto __len2 = __last2 - __first2; + if (__len2 == 0) + return __last1; + auto __len1 = __last1 - __first1; + if (__len1 < __len2) + return __last1; + const _Iter1 __s = __first1 + _D1(__len2 - 1); // End of pattern match can't go before here + _Iter1 __l1 = __last1; + _Iter2 __l2 = __last2; + --__l2; + while (true) { + while (true) { + if (__s == __l1) + return __last1; + if (std::__invoke(__pred, std::__invoke(__proj1, *--__l1), std::__invoke(__proj2, *__l2))) + break; + } + _Iter1 __m1 = __l1; + _Iter2 __m2 = __l2; + while (true) { + if (__m2 == __first2) + return __m1; + // no need to check range on __m1 because __s guarantees we have enough source + if (!std::__invoke(__pred, std::__invoke(__proj1, *--__m1), std::__invoke(*--__m2))) { + break; + } + } + } +} + +template +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 +_ForwardIterator1 __find_end_classic(_ForwardIterator1 __first1, _ForwardIterator1 __last1, + _ForwardIterator2 __first2, _ForwardIterator2 __last2, + _BinaryPredicate& __pred) { + auto __proj = __identity(); + return std::__find_end_impl<_ClassicAlgPolicy>( + __first1, + __last1, + __first2, + __last2, + __pred, + __proj, + __proj, + typename iterator_traits<_ForwardIterator1>::iterator_category(), + typename iterator_traits<_ForwardIterator2>::iterator_category()) + .first; +} + +template +_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 +_ForwardIterator1 find_end(_ForwardIterator1 __first1, _ForwardIterator1 __last1, + _ForwardIterator2 __first2, _ForwardIterator2 __last2, + _BinaryPredicate __pred) { + return std::__find_end_classic(__first1, __last1, __first2, __last2, __pred); +} + +template +_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 +_ForwardIterator1 find_end(_ForwardIterator1 __first1, _ForwardIterator1 __last1, + _ForwardIterator2 __first2, _ForwardIterator2 __last2) { + return std::find_end(__first1, __last1, __first2, __last2, __equal_to()); +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ALGORITHM_FIND_END_OF_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/find_first_of.h b/app/src/main/cpp/libcxx/include/__algorithm/find_first_of.h new file mode 100644 index 0000000..12f0109 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/find_first_of.h @@ -0,0 +1,52 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_FIND_FIRST_OF_H +#define _LIBCPP___ALGORITHM_FIND_FIRST_OF_H + +#include <__algorithm/comp.h> +#include <__config> +#include <__iterator/iterator_traits.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +template +_LIBCPP_HIDE_FROM_ABI +_LIBCPP_CONSTEXPR_SINCE_CXX14 _ForwardIterator1 __find_first_of_ce(_ForwardIterator1 __first1, + _ForwardIterator1 __last1, + _ForwardIterator2 __first2, + _ForwardIterator2 __last2, + _BinaryPredicate&& __pred) { + for (; __first1 != __last1; ++__first1) + for (_ForwardIterator2 __j = __first2; __j != __last2; ++__j) + if (__pred(*__first1, *__j)) + return __first1; + return __last1; +} + +template +_LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator1 +find_first_of(_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2, + _ForwardIterator2 __last2, _BinaryPredicate __pred) { + return _VSTD::__find_first_of_ce(__first1, __last1, __first2, __last2, __pred); +} + +template +_LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator1 find_first_of( + _ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2, _ForwardIterator2 __last2) { + return std::__find_first_of_ce(__first1, __last1, __first2, __last2, __equal_to()); +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ALGORITHM_FIND_FIRST_OF_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/find_if.h b/app/src/main/cpp/libcxx/include/__algorithm/find_if.h new file mode 100644 index 0000000..f4ef3ac --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/find_if.h @@ -0,0 +1,32 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_FIND_IF_H +#define _LIBCPP___ALGORITHM_FIND_IF_H + +#include <__config> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +template +_LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 _InputIterator +find_if(_InputIterator __first, _InputIterator __last, _Predicate __pred) { + for (; __first != __last; ++__first) + if (__pred(*__first)) + break; + return __first; +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ALGORITHM_FIND_IF_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/find_if_not.h b/app/src/main/cpp/libcxx/include/__algorithm/find_if_not.h new file mode 100644 index 0000000..96c159c --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/find_if_not.h @@ -0,0 +1,32 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_FIND_IF_NOT_H +#define _LIBCPP___ALGORITHM_FIND_IF_NOT_H + +#include <__config> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +template +_LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 _InputIterator +find_if_not(_InputIterator __first, _InputIterator __last, _Predicate __pred) { + for (; __first != __last; ++__first) + if (!__pred(*__first)) + break; + return __first; +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ALGORITHM_FIND_IF_NOT_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/for_each.h b/app/src/main/cpp/libcxx/include/__algorithm/for_each.h new file mode 100644 index 0000000..6564f31 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/for_each.h @@ -0,0 +1,32 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_FOR_EACH_H +#define _LIBCPP___ALGORITHM_FOR_EACH_H + +#include <__config> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +template +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 _Function for_each(_InputIterator __first, + _InputIterator __last, + _Function __f) { + for (; __first != __last; ++__first) + __f(*__first); + return __f; +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ALGORITHM_FOR_EACH_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/for_each_n.h b/app/src/main/cpp/libcxx/include/__algorithm/for_each_n.h new file mode 100644 index 0000000..38d204a --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/for_each_n.h @@ -0,0 +1,43 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_FOR_EACH_N_H +#define _LIBCPP___ALGORITHM_FOR_EACH_N_H + +#include <__config> +#include <__utility/convert_to_integral.h> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 14 + +template +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 _InputIterator for_each_n(_InputIterator __first, + _Size __orig_n, + _Function __f) { + typedef decltype(_VSTD::__convert_to_integral(__orig_n)) _IntegralSize; + _IntegralSize __n = __orig_n; + while (__n > 0) { + __f(*__first); + ++__first; + --__n; + } + return __first; +} + +#endif + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ALGORITHM_FOR_EACH_N_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/generate.h b/app/src/main/cpp/libcxx/include/__algorithm/generate.h new file mode 100644 index 0000000..48e21b5 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/generate.h @@ -0,0 +1,31 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_GENERATE_H +#define _LIBCPP___ALGORITHM_GENERATE_H + +#include <__config> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +template +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 +void +generate(_ForwardIterator __first, _ForwardIterator __last, _Generator __gen) +{ + for (; __first != __last; ++__first) + *__first = __gen(); +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ALGORITHM_GENERATE_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/generate_n.h b/app/src/main/cpp/libcxx/include/__algorithm/generate_n.h new file mode 100644 index 0000000..4525998 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/generate_n.h @@ -0,0 +1,36 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_GENERATE_N_H +#define _LIBCPP___ALGORITHM_GENERATE_N_H + +#include <__config> +#include <__utility/convert_to_integral.h> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +template +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 +_OutputIterator +generate_n(_OutputIterator __first, _Size __orig_n, _Generator __gen) +{ + typedef decltype(_VSTD::__convert_to_integral(__orig_n)) _IntegralSize; + _IntegralSize __n = __orig_n; + for (; __n > 0; ++__first, (void) --__n) + *__first = __gen(); + return __first; +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ALGORITHM_GENERATE_N_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/half_positive.h b/app/src/main/cpp/libcxx/include/__algorithm/half_positive.h new file mode 100644 index 0000000..74aede2 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/half_positive.h @@ -0,0 +1,49 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_HALF_POSITIVE_H +#define _LIBCPP___ALGORITHM_HALF_POSITIVE_H + +#include <__config> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +// Perform division by two quickly for positive integers (llvm.org/PR39129) + +template +_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR +typename enable_if +< + is_integral<_Integral>::value, + _Integral +>::type +__half_positive(_Integral __value) +{ + return static_cast<_Integral>(static_cast<__make_unsigned_t<_Integral> >(__value) / 2); +} + +template +_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR +typename enable_if +< + !is_integral<_Tp>::value, + _Tp +>::type +__half_positive(_Tp __value) +{ + return __value / 2; +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ALGORITHM_HALF_POSITIVE_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/in_found_result.h b/app/src/main/cpp/libcxx/include/__algorithm/in_found_result.h new file mode 100644 index 0000000..3134d6e --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/in_found_result.h @@ -0,0 +1,49 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_IN_FOUND_RESULT_H +#define _LIBCPP___ALGORITHM_IN_FOUND_RESULT_H + +#include <__concepts/convertible_to.h> +#include <__config> +#include <__utility/move.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if _LIBCPP_STD_VER > 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace ranges { +template +struct in_found_result { + _LIBCPP_NO_UNIQUE_ADDRESS _InIter1 in; + bool found; + + template + requires convertible_to + _LIBCPP_HIDE_FROM_ABI constexpr operator in_found_result<_InIter2>() const & { + return {in, found}; + } + + template + requires convertible_to<_InIter1, _InIter2> + _LIBCPP_HIDE_FROM_ABI constexpr operator in_found_result<_InIter2>() && { + return {std::move(in), found}; + } +}; +} // namespace ranges + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER > 17 + +#endif // _LIBCPP___ALGORITHM_IN_FOUND_RESULT_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/in_fun_result.h b/app/src/main/cpp/libcxx/include/__algorithm/in_fun_result.h new file mode 100644 index 0000000..3cbb9e1 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/in_fun_result.h @@ -0,0 +1,49 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_IN_FUN_RESULT_H +#define _LIBCPP___ALGORITHM_IN_FUN_RESULT_H + +#include <__concepts/convertible_to.h> +#include <__config> +#include <__utility/move.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 17 + +namespace ranges { +template +struct in_fun_result { + _LIBCPP_NO_UNIQUE_ADDRESS _InIter1 in; + _LIBCPP_NO_UNIQUE_ADDRESS _Func1 fun; + + template + requires convertible_to && convertible_to + _LIBCPP_HIDE_FROM_ABI constexpr operator in_fun_result<_InIter2, _Func2>() const & { + return {in, fun}; + } + + template + requires convertible_to<_InIter1, _InIter2> && convertible_to<_Func1, _Func2> + _LIBCPP_HIDE_FROM_ABI constexpr operator in_fun_result<_InIter2, _Func2>() && { + return {std::move(in), std::move(fun)}; + } +}; +} // namespace ranges + +#endif // _LIBCPP_STD_VER > 17 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ALGORITHM_IN_FUN_RESULT_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/in_in_out_result.h b/app/src/main/cpp/libcxx/include/__algorithm/in_in_out_result.h new file mode 100644 index 0000000..3e747be --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/in_in_out_result.h @@ -0,0 +1,56 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_IN_IN_OUT_RESULT_H +#define _LIBCPP___ALGORITHM_IN_IN_OUT_RESULT_H + +#include <__concepts/convertible_to.h> +#include <__config> +#include <__utility/move.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 17 + +namespace ranges { + +template +struct in_in_out_result { + _LIBCPP_NO_UNIQUE_ADDRESS _InIter1 in1; + _LIBCPP_NO_UNIQUE_ADDRESS _InIter2 in2; + _LIBCPP_NO_UNIQUE_ADDRESS _OutIter1 out; + + template + requires convertible_to + && convertible_to && convertible_to + _LIBCPP_HIDE_FROM_ABI constexpr + operator in_in_out_result<_InIter3, _InIter4, _OutIter2>() const& { + return {in1, in2, out}; + } + + template + requires convertible_to<_InIter1, _InIter3> + && convertible_to<_InIter2, _InIter4> && convertible_to<_OutIter1, _OutIter2> + _LIBCPP_HIDE_FROM_ABI constexpr + operator in_in_out_result<_InIter3, _InIter4, _OutIter2>() && { + return {std::move(in1), std::move(in2), std::move(out)}; + } +}; + +} // namespace ranges + +#endif // _LIBCPP_STD_VER > 17 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ALGORITHM_IN_IN_OUT_RESULT_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/in_in_result.h b/app/src/main/cpp/libcxx/include/__algorithm/in_in_result.h new file mode 100644 index 0000000..2098c18 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/in_in_result.h @@ -0,0 +1,53 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_IN_IN_RESULT_H +#define _LIBCPP___ALGORITHM_IN_IN_RESULT_H + +#include <__concepts/convertible_to.h> +#include <__config> +#include <__utility/move.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 17 + +namespace ranges { + +template +struct in_in_result { + _LIBCPP_NO_UNIQUE_ADDRESS _InIter1 in1; + _LIBCPP_NO_UNIQUE_ADDRESS _InIter2 in2; + + template + requires convertible_to && convertible_to + _LIBCPP_HIDE_FROM_ABI constexpr + operator in_in_result<_InIter3, _InIter4>() const & { + return {in1, in2}; + } + + template + requires convertible_to<_InIter1, _InIter3> && convertible_to<_InIter2, _InIter4> + _LIBCPP_HIDE_FROM_ABI constexpr + operator in_in_result<_InIter3, _InIter4>() && { + return {std::move(in1), std::move(in2)}; + } +}; + +} // namespace ranges + +#endif // _LIBCPP_STD_VER > 17 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ALGORITHM_IN_IN_RESULT_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/in_out_out_result.h b/app/src/main/cpp/libcxx/include/__algorithm/in_out_out_result.h new file mode 100644 index 0000000..4046eee --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/in_out_out_result.h @@ -0,0 +1,54 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_IN_OUT_OUT_RESULT_H +#define _LIBCPP___ALGORITHM_IN_OUT_OUT_RESULT_H + +#include <__concepts/convertible_to.h> +#include <__config> +#include <__utility/move.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 17 + +namespace ranges { +template +struct in_out_out_result { + _LIBCPP_NO_UNIQUE_ADDRESS _InIter1 in; + _LIBCPP_NO_UNIQUE_ADDRESS _OutIter1 out1; + _LIBCPP_NO_UNIQUE_ADDRESS _OutIter2 out2; + + template + requires convertible_to + && convertible_to && convertible_to + _LIBCPP_HIDE_FROM_ABI constexpr + operator in_out_out_result<_InIter2, _OutIter3, _OutIter4>() const& { + return {in, out1, out2}; + } + + template + requires convertible_to<_InIter1, _InIter2> + && convertible_to<_OutIter1, _OutIter3> && convertible_to<_OutIter2, _OutIter4> + _LIBCPP_HIDE_FROM_ABI constexpr + operator in_out_out_result<_InIter2, _OutIter3, _OutIter4>() && { + return {std::move(in), std::move(out1), std::move(out2)}; + } +}; +} // namespace ranges + +#endif // _LIBCPP_STD_VER > 17 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ALGORITHM_IN_OUT_OUT_RESULT_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/in_out_result.h b/app/src/main/cpp/libcxx/include/__algorithm/in_out_result.h new file mode 100644 index 0000000..7f5a027 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/in_out_result.h @@ -0,0 +1,53 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_IN_OUT_RESULT_H +#define _LIBCPP___ALGORITHM_IN_OUT_RESULT_H + +#include <__concepts/convertible_to.h> +#include <__config> +#include <__utility/move.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 17 + +namespace ranges { + +template +struct in_out_result { + _LIBCPP_NO_UNIQUE_ADDRESS _InIter1 in; + _LIBCPP_NO_UNIQUE_ADDRESS _OutIter1 out; + + template + requires convertible_to && convertible_to + _LIBCPP_HIDE_FROM_ABI + constexpr operator in_out_result<_InIter2, _OutIter2>() const & { + return {in, out}; + } + + template + requires convertible_to<_InIter1, _InIter2> && convertible_to<_OutIter1, _OutIter2> + _LIBCPP_HIDE_FROM_ABI + constexpr operator in_out_result<_InIter2, _OutIter2>() && { + return {std::move(in), std::move(out)}; + } +}; + +} // namespace ranges + +#endif // _LIBCPP_STD_VER > 17 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ALGORITHM_IN_OUT_RESULT_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/includes.h b/app/src/main/cpp/libcxx/include/__algorithm/includes.h new file mode 100644 index 0000000..cc39f27 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/includes.h @@ -0,0 +1,75 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_INCLUDES_H +#define _LIBCPP___ALGORITHM_INCLUDES_H + +#include <__algorithm/comp.h> +#include <__algorithm/comp_ref_type.h> +#include <__config> +#include <__functional/identity.h> +#include <__functional/invoke.h> +#include <__iterator/iterator_traits.h> +#include <__type_traits/is_callable.h> +#include <__utility/move.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool +__includes(_Iter1 __first1, _Sent1 __last1, _Iter2 __first2, _Sent2 __last2, + _Comp&& __comp, _Proj1&& __proj1, _Proj2&& __proj2) { + for (; __first2 != __last2; ++__first1) { + if (__first1 == __last1 || std::__invoke( + __comp, std::__invoke(__proj2, *__first2), std::__invoke(__proj1, *__first1))) + return false; + if (!std::__invoke(__comp, std::__invoke(__proj1, *__first1), std::__invoke(__proj2, *__first2))) + ++__first2; + } + return true; +} + +template +_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool includes( + _InputIterator1 __first1, + _InputIterator1 __last1, + _InputIterator2 __first2, + _InputIterator2 __last2, + _Compare __comp) { + static_assert(__is_callable<_Compare, decltype(*__first1), decltype(*__first2)>::value, + "Comparator has to be callable"); + + return std::__includes( + std::move(__first1), + std::move(__last1), + std::move(__first2), + std::move(__last2), + static_cast<__comp_ref_type<_Compare> >(__comp), + __identity(), + __identity()); +} + +template +_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool +includes(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2, _InputIterator2 __last2) { + return std::includes( + std::move(__first1), + std::move(__last1), + std::move(__first2), + std::move(__last2), + __less::value_type, + typename iterator_traits<_InputIterator2>::value_type>()); +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ALGORITHM_INCLUDES_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/inplace_merge.h b/app/src/main/cpp/libcxx/include/__algorithm/inplace_merge.h new file mode 100644 index 0000000..5bbefc9 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/inplace_merge.h @@ -0,0 +1,257 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_INPLACE_MERGE_H +#define _LIBCPP___ALGORITHM_INPLACE_MERGE_H + +#include <__algorithm/comp.h> +#include <__algorithm/comp_ref_type.h> +#include <__algorithm/iterator_operations.h> +#include <__algorithm/lower_bound.h> +#include <__algorithm/min.h> +#include <__algorithm/move.h> +#include <__algorithm/rotate.h> +#include <__algorithm/upper_bound.h> +#include <__config> +#include <__functional/identity.h> +#include <__iterator/advance.h> +#include <__iterator/distance.h> +#include <__iterator/iterator_traits.h> +#include <__iterator/reverse_iterator.h> +#include <__memory/destruct_n.h> +#include <__memory/temporary_buffer.h> +#include <__memory/unique_ptr.h> +#include <__utility/pair.h> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + +_LIBCPP_BEGIN_NAMESPACE_STD + +template +class __invert // invert the sense of a comparison +{ +private: + _Predicate __p_; +public: + _LIBCPP_INLINE_VISIBILITY __invert() {} + + _LIBCPP_INLINE_VISIBILITY + explicit __invert(_Predicate __p) : __p_(__p) {} + + template + _LIBCPP_INLINE_VISIBILITY + bool operator()(const _T1& __x) {return !__p_(__x);} + + template + _LIBCPP_INLINE_VISIBILITY + bool operator()(const _T1& __x, const _T2& __y) {return __p_(__y, __x);} +}; + +template +_LIBCPP_HIDE_FROM_ABI +void __half_inplace_merge(_InputIterator1 __first1, _Sent1 __last1, + _InputIterator2 __first2, _Sent2 __last2, + _OutputIterator __result, _Compare&& __comp) +{ + for (; __first1 != __last1; ++__result) + { + if (__first2 == __last2) + { + std::__move<_AlgPolicy>(__first1, __last1, __result); + return; + } + + if (__comp(*__first2, *__first1)) + { + *__result = _IterOps<_AlgPolicy>::__iter_move(__first2); + ++__first2; + } + else + { + *__result = _IterOps<_AlgPolicy>::__iter_move(__first1); + ++__first1; + } + } + // __first2 through __last2 are already in the right spot. +} + +template +_LIBCPP_HIDE_FROM_ABI +void __buffered_inplace_merge( + _BidirectionalIterator __first, + _BidirectionalIterator __middle, + _BidirectionalIterator __last, + _Compare&& __comp, + typename iterator_traits<_BidirectionalIterator>::difference_type __len1, + typename iterator_traits<_BidirectionalIterator>::difference_type __len2, + typename iterator_traits<_BidirectionalIterator>::value_type* __buff) { + typedef typename iterator_traits<_BidirectionalIterator>::value_type value_type; + __destruct_n __d(0); + unique_ptr __h2(__buff, __d); + if (__len1 <= __len2) + { + value_type* __p = __buff; + for (_BidirectionalIterator __i = __first; __i != __middle; __d.template __incr(), (void) ++__i, (void) ++__p) + ::new ((void*)__p) value_type(_IterOps<_AlgPolicy>::__iter_move(__i)); + std::__half_inplace_merge<_AlgPolicy>(__buff, __p, __middle, __last, __first, __comp); + } + else + { + value_type* __p = __buff; + for (_BidirectionalIterator __i = __middle; __i != __last; __d.template __incr(), (void) ++__i, (void) ++__p) + ::new ((void*)__p) value_type(_IterOps<_AlgPolicy>::__iter_move(__i)); + typedef __unconstrained_reverse_iterator<_BidirectionalIterator> _RBi; + typedef __unconstrained_reverse_iterator _Rv; + typedef __invert<_Compare> _Inverted; + std::__half_inplace_merge<_AlgPolicy>(_Rv(__p), _Rv(__buff), + _RBi(__middle), _RBi(__first), + _RBi(__last), _Inverted(__comp)); + } +} + +template +void __inplace_merge( + _BidirectionalIterator __first, + _BidirectionalIterator __middle, + _BidirectionalIterator __last, + _Compare&& __comp, + typename iterator_traits<_BidirectionalIterator>::difference_type __len1, + typename iterator_traits<_BidirectionalIterator>::difference_type __len2, + typename iterator_traits<_BidirectionalIterator>::value_type* __buff, + ptrdiff_t __buff_size) { + using _Ops = _IterOps<_AlgPolicy>; + + typedef typename iterator_traits<_BidirectionalIterator>::difference_type difference_type; + while (true) + { + // if __middle == __last, we're done + if (__len2 == 0) + return; + if (__len1 <= __buff_size || __len2 <= __buff_size) + return std::__buffered_inplace_merge<_AlgPolicy> + (__first, __middle, __last, __comp, __len1, __len2, __buff); + // shrink [__first, __middle) as much as possible (with no moves), returning if it shrinks to 0 + for (; true; ++__first, (void) --__len1) + { + if (__len1 == 0) + return; + if (__comp(*__middle, *__first)) + break; + } + // __first < __middle < __last + // *__first > *__middle + // partition [__first, __m1) [__m1, __middle) [__middle, __m2) [__m2, __last) such that + // all elements in: + // [__first, __m1) <= [__middle, __m2) + // [__middle, __m2) < [__m1, __middle) + // [__m1, __middle) <= [__m2, __last) + // and __m1 or __m2 is in the middle of its range + _BidirectionalIterator __m1; // "median" of [__first, __middle) + _BidirectionalIterator __m2; // "median" of [__middle, __last) + difference_type __len11; // distance(__first, __m1) + difference_type __len21; // distance(__middle, __m2) + // binary search smaller range + if (__len1 < __len2) + { // __len >= 1, __len2 >= 2 + __len21 = __len2 / 2; + __m2 = __middle; + _Ops::advance(__m2, __len21); + __m1 = std::__upper_bound<_AlgPolicy>(__first, __middle, *__m2, __comp, std::__identity()); + __len11 = _Ops::distance(__first, __m1); + } + else + { + if (__len1 == 1) + { // __len1 >= __len2 && __len2 > 0, therefore __len2 == 1 + // It is known *__first > *__middle + _Ops::iter_swap(__first, __middle); + return; + } + // __len1 >= 2, __len2 >= 1 + __len11 = __len1 / 2; + __m1 = __first; + _Ops::advance(__m1, __len11); + __m2 = std::lower_bound(__middle, __last, *__m1, __comp); + __len21 = _Ops::distance(__middle, __m2); + } + difference_type __len12 = __len1 - __len11; // distance(__m1, __middle) + difference_type __len22 = __len2 - __len21; // distance(__m2, __last) + // [__first, __m1) [__m1, __middle) [__middle, __m2) [__m2, __last) + // swap middle two partitions + __middle = std::__rotate<_AlgPolicy>(__m1, __middle, __m2).first; + // __len12 and __len21 now have swapped meanings + // merge smaller range with recursive call and larger with tail recursion elimination + if (__len11 + __len21 < __len12 + __len22) + { + std::__inplace_merge<_AlgPolicy>( + __first, __m1, __middle, __comp, __len11, __len21, __buff, __buff_size); + __first = __middle; + __middle = __m2; + __len1 = __len12; + __len2 = __len22; + } + else + { + std::__inplace_merge<_AlgPolicy>( + __middle, __m2, __last, __comp, __len12, __len22, __buff, __buff_size); + __last = __middle; + __middle = __m1; + __len1 = __len11; + __len2 = __len21; + } + } +} + +template +_LIBCPP_HIDE_FROM_ABI +void +__inplace_merge(_BidirectionalIterator __first, _BidirectionalIterator __middle, _BidirectionalIterator __last, + _Compare&& __comp) +{ + typedef typename iterator_traits<_BidirectionalIterator>::value_type value_type; + typedef typename iterator_traits<_BidirectionalIterator>::difference_type difference_type; + difference_type __len1 = _IterOps<_AlgPolicy>::distance(__first, __middle); + difference_type __len2 = _IterOps<_AlgPolicy>::distance(__middle, __last); + difference_type __buf_size = _VSTD::min(__len1, __len2); +// TODO: Remove the use of std::get_temporary_buffer +_LIBCPP_SUPPRESS_DEPRECATED_PUSH + pair __buf = _VSTD::get_temporary_buffer(__buf_size); +_LIBCPP_SUPPRESS_DEPRECATED_POP + unique_ptr __h(__buf.first); + return std::__inplace_merge<_AlgPolicy>( + std::move(__first), std::move(__middle), std::move(__last), __comp, __len1, __len2, __buf.first, __buf.second); +} + +template +inline _LIBCPP_HIDE_FROM_ABI void inplace_merge( + _BidirectionalIterator __first, _BidirectionalIterator __middle, _BidirectionalIterator __last, _Compare __comp) { + std::__inplace_merge<_ClassicAlgPolicy>( + std::move(__first), std::move(__middle), std::move(__last), static_cast<__comp_ref_type<_Compare> >(__comp)); +} + +template +inline _LIBCPP_HIDE_FROM_ABI +void +inplace_merge(_BidirectionalIterator __first, _BidirectionalIterator __middle, _BidirectionalIterator __last) +{ + std::inplace_merge(std::move(__first), std::move(__middle), std::move(__last), + __less::value_type>()); +} + +_LIBCPP_END_NAMESPACE_STD + +_LIBCPP_POP_MACROS + +#endif // _LIBCPP___ALGORITHM_INPLACE_MERGE_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/is_heap.h b/app/src/main/cpp/libcxx/include/__algorithm/is_heap.h new file mode 100644 index 0000000..2dcb4a2 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/is_heap.h @@ -0,0 +1,44 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_IS_HEAP_H +#define _LIBCPP___ALGORITHM_IS_HEAP_H + +#include <__algorithm/comp.h> +#include <__algorithm/comp_ref_type.h> +#include <__algorithm/is_heap_until.h> +#include <__config> +#include <__iterator/iterator_traits.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +template +_LIBCPP_NODISCARD_EXT inline +_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 +bool +is_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp) +{ + return std::__is_heap_until(__first, __last, static_cast<__comp_ref_type<_Compare> >(__comp)) == __last; +} + +template +_LIBCPP_NODISCARD_EXT inline +_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 +bool +is_heap(_RandomAccessIterator __first, _RandomAccessIterator __last) +{ + return _VSTD::is_heap(__first, __last, __less::value_type>()); +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ALGORITHM_IS_HEAP_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/is_heap_until.h b/app/src/main/cpp/libcxx/include/__algorithm/is_heap_until.h new file mode 100644 index 0000000..6ed4cb2 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/is_heap_until.h @@ -0,0 +1,66 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_IS_HEAP_UNTIL_H +#define _LIBCPP___ALGORITHM_IS_HEAP_UNTIL_H + +#include <__algorithm/comp.h> +#include <__algorithm/comp_ref_type.h> +#include <__config> +#include <__iterator/iterator_traits.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _RandomAccessIterator +__is_heap_until(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare&& __comp) +{ + typedef typename iterator_traits<_RandomAccessIterator>::difference_type difference_type; + difference_type __len = __last - __first; + difference_type __p = 0; + difference_type __c = 1; + _RandomAccessIterator __pp = __first; + while (__c < __len) + { + _RandomAccessIterator __cp = __first + __c; + if (__comp(*__pp, *__cp)) + return __cp; + ++__c; + ++__cp; + if (__c == __len) + return __last; + if (__comp(*__pp, *__cp)) + return __cp; + ++__p; + ++__pp; + __c = 2 * __p + 1; + } + return __last; +} + +template +_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _RandomAccessIterator +is_heap_until(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp) +{ + return std::__is_heap_until(__first, __last, static_cast<__comp_ref_type<_Compare> >(__comp)); +} + +template +_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _RandomAccessIterator +is_heap_until(_RandomAccessIterator __first, _RandomAccessIterator __last) +{ + return _VSTD::__is_heap_until(__first, __last, __less::value_type>()); +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ALGORITHM_IS_HEAP_UNTIL_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/is_partitioned.h b/app/src/main/cpp/libcxx/include/__algorithm/is_partitioned.h new file mode 100644 index 0000000..ab59d3c --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/is_partitioned.h @@ -0,0 +1,38 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_IS_PARTITIONED_H +#define _LIBCPP___ALGORITHM_IS_PARTITIONED_H + +#include <__config> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +template +_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool +is_partitioned(_InputIterator __first, _InputIterator __last, _Predicate __pred) +{ + for (; __first != __last; ++__first) + if (!__pred(*__first)) + break; + if ( __first == __last ) + return true; + ++__first; + for (; __first != __last; ++__first) + if (__pred(*__first)) + return false; + return true; +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ALGORITHM_IS_PARTITIONED_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/is_permutation.h b/app/src/main/cpp/libcxx/include/__algorithm/is_permutation.h new file mode 100644 index 0000000..0054456 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/is_permutation.h @@ -0,0 +1,238 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_IS_PERMUTATION_H +#define _LIBCPP___ALGORITHM_IS_PERMUTATION_H + +#include <__algorithm/comp.h> +#include <__algorithm/iterator_operations.h> +#include <__config> +#include <__functional/identity.h> +#include <__functional/invoke.h> +#include <__iterator/concepts.h> +#include <__iterator/distance.h> +#include <__iterator/iterator_traits.h> +#include <__iterator/next.h> +#include <__utility/move.h> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +template +struct _ConstTimeDistance : false_type {}; + +#if _LIBCPP_STD_VER > 17 + +template +struct _ConstTimeDistance<_Iter1, _Sent1, _Iter2, _Sent2, __enable_if_t< + sized_sentinel_for<_Sent1, _Iter1> && + sized_sentinel_for<_Sent2, _Iter2> +>> : true_type {}; + +#else + +template +struct _ConstTimeDistance<_Iter1, _Iter1, _Iter2, _Iter2, __enable_if_t< + is_same::iterator_category, random_access_iterator_tag>::value && + is_same::iterator_category, random_access_iterator_tag>::value +> > : true_type {}; + +#endif // _LIBCPP_STD_VER > 17 + +// Internal functions + +// For each element in [f1, l1) see if there are the same number of equal elements in [f2, l2) +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool +__is_permutation_impl(_Iter1 __first1, _Sent1 __last1, _Iter2 __first2, _Sent2 __last2, + _Pred&& __pred, _Proj1&& __proj1, _Proj2&& __proj2) { + using _D1 = __iter_diff_t<_Iter1>; + + for (auto __i = __first1; __i != __last1; ++__i) { + // Have we already counted the number of *__i in [f1, l1)? + auto __match = __first1; + for (; __match != __i; ++__match) { + if (std::__invoke(__pred, std::__invoke(__proj1, *__match), std::__invoke(__proj1, *__i))) + break; + } + + if (__match == __i) { + // Count number of *__i in [f2, l2) + _D1 __c2 = 0; + for (auto __j = __first2; __j != __last2; ++__j) { + if (std::__invoke(__pred, std::__invoke(__proj1, *__i), std::__invoke(__proj2, *__j))) + ++__c2; + } + if (__c2 == 0) + return false; + + // Count number of *__i in [__i, l1) (we can start with 1) + _D1 __c1 = 1; + for (auto __j = _IterOps<_AlgPolicy>::next(__i); __j != __last1; ++__j) { + if (std::__invoke(__pred, std::__invoke(__proj1, *__i), std::__invoke(__proj1, *__j))) + ++__c1; + } + if (__c1 != __c2) + return false; + } + } + + return true; +} + +// 2+1 iterators, predicate. Not used by range algorithms. +template +_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool +__is_permutation(_ForwardIterator1 __first1, _Sentinel1 __last1, _ForwardIterator2 __first2, + _BinaryPredicate&& __pred) { + // Shorten sequences as much as possible by lopping of any equal prefix. + for (; __first1 != __last1; ++__first1, (void)++__first2) { + if (!__pred(*__first1, *__first2)) + break; + } + + if (__first1 == __last1) + return true; + + // __first1 != __last1 && *__first1 != *__first2 + using _D1 = __iter_diff_t<_ForwardIterator1>; + _D1 __l1 = _IterOps<_AlgPolicy>::distance(__first1, __last1); + if (__l1 == _D1(1)) + return false; + auto __last2 = _IterOps<_AlgPolicy>::next(__first2, __l1); + + return std::__is_permutation_impl<_AlgPolicy>( + std::move(__first1), std::move(__last1), std::move(__first2), std::move(__last2), + __pred, __identity(), __identity()); +} + +// 2+2 iterators, predicate, non-constant time `distance`. +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool +__is_permutation(_Iter1 __first1, _Sent1 __last1, _Iter2 __first2, _Sent2 __last2, + _Pred&& __pred, _Proj1&& __proj1, _Proj2&& __proj2, + /*_ConstTimeDistance=*/false_type) { + // Shorten sequences as much as possible by lopping of any equal prefix. + while (__first1 != __last1 && __first2 != __last2) { + if (!std::__invoke(__pred, std::__invoke(__proj1, *__first1), std::__invoke(__proj2, *__first2))) + break; + ++__first1; + ++__first2; + } + + if (__first1 == __last1) + return __first2 == __last2; + if (__first2 == __last2) // Second range is shorter + return false; + + using _D1 = __iter_diff_t<_Iter1>; + _D1 __l1 = _IterOps<_AlgPolicy>::distance(__first1, __last1); + + using _D2 = __iter_diff_t<_Iter2>; + _D2 __l2 = _IterOps<_AlgPolicy>::distance(__first2, __last2); + if (__l1 != __l2) + return false; + + return std::__is_permutation_impl<_AlgPolicy>( + std::move(__first1), std::move(__last1), std::move(__first2), std::move(__last2), + __pred, __proj1, __proj2); +} + +// 2+2 iterators, predicate, specialization for constant-time `distance` call. +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool +__is_permutation(_Iter1 __first1, _Sent1 __last1, _Iter2 __first2, _Sent2 __last2, + _Pred&& __pred, _Proj1&& __proj1, _Proj2&& __proj2, + /*_ConstTimeDistance=*/true_type) { + if (std::distance(__first1, __last1) != std::distance(__first2, __last2)) + return false; + return std::__is_permutation<_AlgPolicy>( + std::move(__first1), std::move(__last1), std::move(__first2), std::move(__last2), + __pred, __proj1, __proj2, + /*_ConstTimeDistance=*/false_type()); +} + +// 2+2 iterators, predicate +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool +__is_permutation(_Iter1 __first1, _Sent1 __last1, _Iter2 __first2, _Sent2 __last2, + _Pred&& __pred, _Proj1&& __proj1, _Proj2&& __proj2) { + return std::__is_permutation<_AlgPolicy>( + std::move(__first1), std::move(__last1), std::move(__first2), std::move(__last2), + __pred, __proj1, __proj2, + _ConstTimeDistance<_Iter1, _Sent1, _Iter2, _Sent2>()); +} + +// Public interface + +// 2+1 iterators, predicate +template +_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool +is_permutation(_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2, + _BinaryPredicate __pred) { + static_assert(__is_callable<_BinaryPredicate, decltype(*__first1), decltype(*__first2)>::value, + "The predicate has to be callable"); + + return std::__is_permutation<_ClassicAlgPolicy>( + std::move(__first1), std::move(__last1), std::move(__first2), __pred); +} + +// 2+1 iterators +template +_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool +is_permutation(_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2) { + return std::is_permutation(__first1, __last1, __first2, __equal_to()); +} + +#if _LIBCPP_STD_VER > 11 + +// 2+2 iterators +template +_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool is_permutation( + _ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2, _ForwardIterator2 __last2) { + return std::__is_permutation<_ClassicAlgPolicy>( + std::move(__first1), + std::move(__last1), + std::move(__first2), + std::move(__last2), + __equal_to(), + __identity(), + __identity()); +} + +// 2+2 iterators, predicate +template +_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool +is_permutation(_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2, + _ForwardIterator2 __last2, _BinaryPredicate __pred) { + static_assert(__is_callable<_BinaryPredicate, decltype(*__first1), decltype(*__first2)>::value, + "The predicate has to be callable"); + + return std::__is_permutation<_ClassicAlgPolicy>( + std::move(__first1), std::move(__last1), std::move(__first2), std::move(__last2), + __pred, __identity(), __identity()); +} + +#endif // _LIBCPP_STD_VER > 11 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ALGORITHM_IS_PERMUTATION_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/is_sorted.h b/app/src/main/cpp/libcxx/include/__algorithm/is_sorted.h new file mode 100644 index 0000000..bf44f45 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/is_sorted.h @@ -0,0 +1,44 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_IS_SORTED_H +#define _LIBCPP___ALGORITHM_IS_SORTED_H + +#include <__algorithm/comp.h> +#include <__algorithm/comp_ref_type.h> +#include <__algorithm/is_sorted_until.h> +#include <__config> +#include <__iterator/iterator_traits.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +template +_LIBCPP_NODISCARD_EXT inline +_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 +bool +is_sorted(_ForwardIterator __first, _ForwardIterator __last, _Compare __comp) +{ + return _VSTD::__is_sorted_until<__comp_ref_type<_Compare> >(__first, __last, __comp) == __last; +} + +template +_LIBCPP_NODISCARD_EXT inline +_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 +bool +is_sorted(_ForwardIterator __first, _ForwardIterator __last) +{ + return _VSTD::is_sorted(__first, __last, __less::value_type>()); +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ALGORITHM_IS_SORTED_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/is_sorted_until.h b/app/src/main/cpp/libcxx/include/__algorithm/is_sorted_until.h new file mode 100644 index 0000000..b668300 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/is_sorted_until.h @@ -0,0 +1,56 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_IS_SORTED_UNTIL_H +#define _LIBCPP___ALGORITHM_IS_SORTED_UNTIL_H + +#include <__algorithm/comp.h> +#include <__algorithm/comp_ref_type.h> +#include <__config> +#include <__iterator/iterator_traits.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator +__is_sorted_until(_ForwardIterator __first, _ForwardIterator __last, _Compare __comp) +{ + if (__first != __last) + { + _ForwardIterator __i = __first; + while (++__i != __last) + { + if (__comp(*__i, *__first)) + return __i; + __first = __i; + } + } + return __last; +} + +template +_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator +is_sorted_until(_ForwardIterator __first, _ForwardIterator __last, _Compare __comp) +{ + return _VSTD::__is_sorted_until<__comp_ref_type<_Compare> >(__first, __last, __comp); +} + +template +_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator +is_sorted_until(_ForwardIterator __first, _ForwardIterator __last) +{ + return _VSTD::is_sorted_until(__first, __last, __less::value_type>()); +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ALGORITHM_IS_SORTED_UNTIL_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/iter_swap.h b/app/src/main/cpp/libcxx/include/__algorithm/iter_swap.h new file mode 100644 index 0000000..44422b5 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/iter_swap.h @@ -0,0 +1,32 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_ITER_SWAP_H +#define _LIBCPP___ALGORITHM_ITER_SWAP_H + +#include <__config> +#include <__utility/declval.h> +#include <__utility/swap.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +template +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 void iter_swap(_ForwardIterator1 __a, + _ForwardIterator2 __b) + // _NOEXCEPT_(_NOEXCEPT_(swap(*__a, *__b))) + _NOEXCEPT_(_NOEXCEPT_(swap(*std::declval<_ForwardIterator1>(), *std::declval<_ForwardIterator2>()))) { + swap(*__a, *__b); +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ALGORITHM_ITER_SWAP_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/iterator_operations.h b/app/src/main/cpp/libcxx/include/__algorithm/iterator_operations.h new file mode 100644 index 0000000..bd3e6f1 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/iterator_operations.h @@ -0,0 +1,175 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_ITERATOR_OPERATIONS_H +#define _LIBCPP___ALGORITHM_ITERATOR_OPERATIONS_H + +#include <__algorithm/iter_swap.h> +#include <__algorithm/ranges_iterator_concept.h> +#include <__config> +#include <__iterator/advance.h> +#include <__iterator/distance.h> +#include <__iterator/incrementable_traits.h> +#include <__iterator/iter_move.h> +#include <__iterator/iter_swap.h> +#include <__iterator/iterator_traits.h> +#include <__iterator/next.h> +#include <__iterator/prev.h> +#include <__iterator/readable_traits.h> +#include <__type_traits/enable_if.h> +#include <__type_traits/is_reference.h> +#include <__type_traits/is_same.h> +#include <__type_traits/remove_cvref.h> +#include <__utility/declval.h> +#include <__utility/forward.h> +#include <__utility/move.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +template struct _IterOps; + +#if _LIBCPP_STD_VER > 17 +struct _RangeAlgPolicy {}; + +template <> +struct _IterOps<_RangeAlgPolicy> { + + template + using __value_type = iter_value_t<_Iter>; + + template + using __iterator_category = ranges::__iterator_concept<_Iter>; + + template + using __difference_type = iter_difference_t<_Iter>; + + static constexpr auto advance = ranges::advance; + static constexpr auto distance = ranges::distance; + static constexpr auto __iter_move = ranges::iter_move; + static constexpr auto iter_swap = ranges::iter_swap; + static constexpr auto next = ranges::next; + static constexpr auto prev = ranges::prev; + static constexpr auto __advance_to = ranges::advance; +}; + +#endif + +struct _ClassicAlgPolicy {}; + +template <> +struct _IterOps<_ClassicAlgPolicy> { + + template + using __value_type = typename iterator_traits<_Iter>::value_type; + + template + using __iterator_category = typename iterator_traits<_Iter>::iterator_category; + + template + using __difference_type = typename iterator_traits<_Iter>::difference_type; + + // advance + template + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 + static void advance(_Iter& __iter, _Distance __count) { + std::advance(__iter, __count); + } + + // distance + template + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 + static typename iterator_traits<_Iter>::difference_type distance(_Iter __first, _Iter __last) { + return std::distance(__first, __last); + } + + template + using __deref_t = decltype(*std::declval<_Iter&>()); + + template + using __move_t = decltype(std::move(*std::declval<_Iter&>())); + + template + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 + static void __validate_iter_reference() { + static_assert(is_same<__deref_t<_Iter>, typename iterator_traits<__remove_cvref_t<_Iter> >::reference>::value, + "It looks like your iterator's `iterator_traits::reference` does not match the return type of " + "dereferencing the iterator, i.e., calling `*it`. This is undefined behavior according to [input.iterators] " + "and can lead to dangling reference issues at runtime, so we are flagging this."); + } + + // iter_move + template + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 static + // If the result of dereferencing `_Iter` is a reference type, deduce the result of calling `std::move` on it. Note + // that the C++03 mode doesn't support `decltype(auto)` as the return type. + __enable_if_t< + is_reference<__deref_t<_Iter> >::value, + __move_t<_Iter> > + __iter_move(_Iter&& __i) { + __validate_iter_reference<_Iter>(); + + return std::move(*std::forward<_Iter>(__i)); + } + + template + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 static + // If the result of dereferencing `_Iter` is a value type, deduce the return value of this function to also be a + // value -- otherwise, after `operator*` returns a temporary, this function would return a dangling reference to that + // temporary. Note that the C++03 mode doesn't support `auto` as the return type. + __enable_if_t< + !is_reference<__deref_t<_Iter> >::value, + __deref_t<_Iter> > + __iter_move(_Iter&& __i) { + __validate_iter_reference<_Iter>(); + + return *std::forward<_Iter>(__i); + } + + // iter_swap + template + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 + static void iter_swap(_Iter1&& __a, _Iter2&& __b) { + std::iter_swap(std::forward<_Iter1>(__a), std::forward<_Iter2>(__b)); + } + + // next + template + _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR_SINCE_CXX14 + _Iterator next(_Iterator, _Iterator __last) { + return __last; + } + + template + _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR_SINCE_CXX14 + __remove_cvref_t<_Iter> next(_Iter&& __it, + typename iterator_traits<__remove_cvref_t<_Iter> >::difference_type __n = 1) { + return std::next(std::forward<_Iter>(__it), __n); + } + + // prev + template + _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR_SINCE_CXX14 + __remove_cvref_t<_Iter> prev(_Iter&& __iter, + typename iterator_traits<__remove_cvref_t<_Iter> >::difference_type __n = 1) { + return std::prev(std::forward<_Iter>(__iter), __n); + } + + template + _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR_SINCE_CXX14 + void __advance_to(_Iter& __first, _Iter __last) { + __first = __last; + } +}; + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ALGORITHM_ITERATOR_OPERATIONS_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/lexicographical_compare.h b/app/src/main/cpp/libcxx/include/__algorithm/lexicographical_compare.h new file mode 100644 index 0000000..0a13c5d --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/lexicographical_compare.h @@ -0,0 +1,62 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_LEXICOGRAPHICAL_COMPARE_H +#define _LIBCPP___ALGORITHM_LEXICOGRAPHICAL_COMPARE_H + +#include <__algorithm/comp.h> +#include <__algorithm/comp_ref_type.h> +#include <__config> +#include <__iterator/iterator_traits.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool +__lexicographical_compare(_InputIterator1 __first1, _InputIterator1 __last1, + _InputIterator2 __first2, _InputIterator2 __last2, _Compare __comp) +{ + for (; __first2 != __last2; ++__first1, (void) ++__first2) + { + if (__first1 == __last1 || __comp(*__first1, *__first2)) + return true; + if (__comp(*__first2, *__first1)) + return false; + } + return false; +} + +template +_LIBCPP_NODISCARD_EXT inline +_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 +bool +lexicographical_compare(_InputIterator1 __first1, _InputIterator1 __last1, + _InputIterator2 __first2, _InputIterator2 __last2, _Compare __comp) +{ + return _VSTD::__lexicographical_compare<__comp_ref_type<_Compare> >(__first1, __last1, __first2, __last2, __comp); +} + +template +_LIBCPP_NODISCARD_EXT inline +_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 +bool +lexicographical_compare(_InputIterator1 __first1, _InputIterator1 __last1, + _InputIterator2 __first2, _InputIterator2 __last2) +{ + return _VSTD::lexicographical_compare(__first1, __last1, __first2, __last2, + __less::value_type, + typename iterator_traits<_InputIterator2>::value_type>()); +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ALGORITHM_LEXICOGRAPHICAL_COMPARE_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/lower_bound.h b/app/src/main/cpp/libcxx/include/__algorithm/lower_bound.h new file mode 100644 index 0000000..2648982 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/lower_bound.h @@ -0,0 +1,68 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_LOWER_BOUND_H +#define _LIBCPP___ALGORITHM_LOWER_BOUND_H + +#include <__algorithm/comp.h> +#include <__algorithm/half_positive.h> +#include <__algorithm/iterator_operations.h> +#include <__config> +#include <__functional/identity.h> +#include <__functional/invoke.h> +#include <__iterator/advance.h> +#include <__iterator/distance.h> +#include <__iterator/iterator_traits.h> +#include <__type_traits/is_callable.h> +#include <__type_traits/remove_reference.h> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 +_Iter __lower_bound_impl(_Iter __first, _Sent __last, const _Type& __value, _Comp& __comp, _Proj& __proj) { + auto __len = _IterOps<_AlgPolicy>::distance(__first, __last); + + while (__len != 0) { + auto __l2 = std::__half_positive(__len); + _Iter __m = __first; + _IterOps<_AlgPolicy>::advance(__m, __l2); + if (std::__invoke(__comp, std::__invoke(__proj, *__m), __value)) { + __first = ++__m; + __len -= __l2 + 1; + } else { + __len = __l2; + } + } + return __first; +} + +template +_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 +_ForwardIterator lower_bound(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value, _Compare __comp) { + static_assert(__is_callable<_Compare, decltype(*__first), const _Tp&>::value, + "The comparator has to be callable"); + auto __proj = std::__identity(); + return std::__lower_bound_impl<_ClassicAlgPolicy>(__first, __last, __value, __comp, __proj); +} + +template +_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 +_ForwardIterator lower_bound(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value) { + return std::lower_bound(__first, __last, __value, + __less::value_type, _Tp>()); +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ALGORITHM_LOWER_BOUND_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/make_heap.h b/app/src/main/cpp/libcxx/include/__algorithm/make_heap.h new file mode 100644 index 0000000..d66cfe2 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/make_heap.h @@ -0,0 +1,56 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_MAKE_HEAP_H +#define _LIBCPP___ALGORITHM_MAKE_HEAP_H + +#include <__algorithm/comp.h> +#include <__algorithm/comp_ref_type.h> +#include <__algorithm/iterator_operations.h> +#include <__algorithm/sift_down.h> +#include <__config> +#include <__iterator/iterator_traits.h> +#include <__utility/move.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +template +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 +void __make_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare&& __comp) { + __comp_ref_type<_Compare> __comp_ref = __comp; + + using difference_type = typename iterator_traits<_RandomAccessIterator>::difference_type; + difference_type __n = __last - __first; + if (__n > 1) { + // start from the first parent, there is no need to consider children + for (difference_type __start = (__n - 2) / 2; __start >= 0; --__start) { + std::__sift_down<_AlgPolicy>(__first, __comp_ref, __n, __first + __start); + } + } +} + +template +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 +void make_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp) { + std::__make_heap<_ClassicAlgPolicy>(std::move(__first), std::move(__last), __comp); +} + +template +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 +void make_heap(_RandomAccessIterator __first, _RandomAccessIterator __last) { + std::make_heap(std::move(__first), std::move(__last), + __less::value_type>()); +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ALGORITHM_MAKE_HEAP_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/make_projected.h b/app/src/main/cpp/libcxx/include/__algorithm/make_projected.h new file mode 100644 index 0000000..87d4d59 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/make_projected.h @@ -0,0 +1,126 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_MAKE_PROJECTED_H +#define _LIBCPP___ALGORITHM_MAKE_PROJECTED_H + +#include <__concepts/same_as.h> +#include <__config> +#include <__functional/identity.h> +#include <__functional/invoke.h> +#include <__type_traits/decay.h> +#include <__type_traits/enable_if.h> +#include <__type_traits/integral_constant.h> +#include <__type_traits/is_member_pointer.h> +#include <__type_traits/is_same.h> +#include <__utility/declval.h> +#include <__utility/forward.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +template +struct _ProjectedPred { + _Pred& __pred; // Can be a unary or a binary predicate. + _Proj& __proj; + + _LIBCPP_CONSTEXPR _ProjectedPred(_Pred& __pred_arg, _Proj& __proj_arg) : __pred(__pred_arg), __proj(__proj_arg) {} + + template + typename __invoke_of<_Pred&, + decltype(std::__invoke(std::declval<_Proj&>(), std::declval<_Tp>())) + >::type + _LIBCPP_CONSTEXPR operator()(_Tp&& __v) const { + return std::__invoke(__pred, std::__invoke(__proj, std::forward<_Tp>(__v))); + } + + template + typename __invoke_of<_Pred&, + decltype(std::__invoke(std::declval<_Proj&>(), std::declval<_T1>())), + decltype(std::__invoke(std::declval<_Proj&>(), std::declval<_T2>())) + >::type + _LIBCPP_CONSTEXPR operator()(_T1&& __lhs, _T2&& __rhs) const { + return std::__invoke(__pred, + std::__invoke(__proj, std::forward<_T1>(__lhs)), + std::__invoke(__proj, std::forward<_T2>(__rhs))); + } + +}; + +template +struct __can_use_pristine_comp : false_type {}; + +template +struct __can_use_pristine_comp<_Pred, _Proj, __enable_if_t< + !is_member_pointer::type>::value && ( +#if _LIBCPP_STD_VER > 17 + is_same::type, identity>::value || +#endif + is_same::type, __identity>::value + ) +> > : true_type {}; + +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR static +__enable_if_t< + !__can_use_pristine_comp<_Pred, _Proj>::value, + _ProjectedPred<_Pred, _Proj> +> +__make_projected(_Pred& __pred, _Proj& __proj) { + return _ProjectedPred<_Pred, _Proj>(__pred, __proj); +} + +// Avoid creating the functor and just use the pristine comparator -- for certain algorithms, this would enable +// optimizations that rely on the type of the comparator. Additionally, this results in less layers of indirection in +// the call stack when the comparator is invoked, even in an unoptimized build. +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR static +__enable_if_t< + __can_use_pristine_comp<_Pred, _Proj>::value, + _Pred& +> +__make_projected(_Pred& __pred, _Proj&) { + return __pred; +} + +_LIBCPP_END_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace ranges { + +template +_LIBCPP_HIDE_FROM_ABI constexpr static +decltype(auto) __make_projected_comp(_Comp& __comp, _Proj1& __proj1, _Proj2& __proj2) { + if constexpr (same_as, identity> && same_as, identity> && + !is_member_pointer_v>) { + // Avoid creating the lambda and just use the pristine comparator -- for certain algorithms, this would enable + // optimizations that rely on the type of the comparator. + return __comp; + + } else { + return [&](auto&& __lhs, auto&& __rhs) { + return std::invoke(__comp, + std::invoke(__proj1, std::forward(__lhs)), + std::invoke(__proj2, std::forward(__rhs))); + }; + } +} + +} // namespace ranges + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER > 17 + +#endif // _LIBCPP___ALGORITHM_MAKE_PROJECTED_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/max.h b/app/src/main/cpp/libcxx/include/__algorithm/max.h new file mode 100644 index 0000000..a08a3fc --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/max.h @@ -0,0 +1,71 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_MAX_H +#define _LIBCPP___ALGORITHM_MAX_H + +#include <__algorithm/comp.h> +#include <__algorithm/comp_ref_type.h> +#include <__algorithm/max_element.h> +#include <__config> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + +_LIBCPP_BEGIN_NAMESPACE_STD + +template +_LIBCPP_NODISCARD_EXT inline +_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 +const _Tp& +max(const _Tp& __a, const _Tp& __b, _Compare __comp) +{ + return __comp(__a, __b) ? __b : __a; +} + +template +_LIBCPP_NODISCARD_EXT inline +_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 +const _Tp& +max(const _Tp& __a, const _Tp& __b) +{ + return _VSTD::max(__a, __b, __less<_Tp>()); +} + +#ifndef _LIBCPP_CXX03_LANG + +template +_LIBCPP_NODISCARD_EXT inline +_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 +_Tp +max(initializer_list<_Tp> __t, _Compare __comp) +{ + return *_VSTD::__max_element<__comp_ref_type<_Compare> >(__t.begin(), __t.end(), __comp); +} + +template +_LIBCPP_NODISCARD_EXT inline +_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 +_Tp +max(initializer_list<_Tp> __t) +{ + return *_VSTD::max_element(__t.begin(), __t.end(), __less<_Tp>()); +} + +#endif // _LIBCPP_CXX03_LANG + +_LIBCPP_END_NAMESPACE_STD + +_LIBCPP_POP_MACROS + +#endif // _LIBCPP___ALGORITHM_MAX_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/max_element.h b/app/src/main/cpp/libcxx/include/__algorithm/max_element.h new file mode 100644 index 0000000..6ac3106 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/max_element.h @@ -0,0 +1,57 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_MAX_ELEMENT_H +#define _LIBCPP___ALGORITHM_MAX_ELEMENT_H + +#include <__algorithm/comp.h> +#include <__algorithm/comp_ref_type.h> +#include <__config> +#include <__iterator/iterator_traits.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +template +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _ForwardIterator +__max_element(_ForwardIterator __first, _ForwardIterator __last, _Compare __comp) +{ + static_assert(__is_cpp17_forward_iterator<_ForwardIterator>::value, + "std::max_element requires a ForwardIterator"); + if (__first != __last) + { + _ForwardIterator __i = __first; + while (++__i != __last) + if (__comp(*__first, *__i)) + __first = __i; + } + return __first; +} + +template +_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _ForwardIterator +max_element(_ForwardIterator __first, _ForwardIterator __last, _Compare __comp) +{ + return _VSTD::__max_element<__comp_ref_type<_Compare> >(__first, __last, __comp); +} + + +template +_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _ForwardIterator +max_element(_ForwardIterator __first, _ForwardIterator __last) +{ + return _VSTD::max_element(__first, __last, + __less::value_type>()); +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ALGORITHM_MAX_ELEMENT_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/merge.h b/app/src/main/cpp/libcxx/include/__algorithm/merge.h new file mode 100644 index 0000000..e54e430 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/merge.h @@ -0,0 +1,70 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_MERGE_H +#define _LIBCPP___ALGORITHM_MERGE_H + +#include <__algorithm/comp.h> +#include <__algorithm/comp_ref_type.h> +#include <__algorithm/copy.h> +#include <__config> +#include <__iterator/iterator_traits.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 +_OutputIterator +__merge(_InputIterator1 __first1, _InputIterator1 __last1, + _InputIterator2 __first2, _InputIterator2 __last2, _OutputIterator __result, _Compare __comp) +{ + for (; __first1 != __last1; ++__result) + { + if (__first2 == __last2) + return _VSTD::copy(__first1, __last1, __result); + if (__comp(*__first2, *__first1)) + { + *__result = *__first2; + ++__first2; + } + else + { + *__result = *__first1; + ++__first1; + } + } + return _VSTD::copy(__first2, __last2, __result); +} + +template +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 +_OutputIterator +merge(_InputIterator1 __first1, _InputIterator1 __last1, + _InputIterator2 __first2, _InputIterator2 __last2, _OutputIterator __result, _Compare __comp) +{ + return _VSTD::__merge<__comp_ref_type<_Compare> >(__first1, __last1, __first2, __last2, __result, __comp); +} + +template +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 +_OutputIterator +merge(_InputIterator1 __first1, _InputIterator1 __last1, + _InputIterator2 __first2, _InputIterator2 __last2, _OutputIterator __result) +{ + typedef typename iterator_traits<_InputIterator1>::value_type __v1; + typedef typename iterator_traits<_InputIterator2>::value_type __v2; + return _VSTD::merge(__first1, __last1, __first2, __last2, __result, __less<__v1, __v2>()); +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ALGORITHM_MERGE_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/min.h b/app/src/main/cpp/libcxx/include/__algorithm/min.h new file mode 100644 index 0000000..2882485 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/min.h @@ -0,0 +1,71 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_MIN_H +#define _LIBCPP___ALGORITHM_MIN_H + +#include <__algorithm/comp.h> +#include <__algorithm/comp_ref_type.h> +#include <__algorithm/min_element.h> +#include <__config> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + +_LIBCPP_BEGIN_NAMESPACE_STD + +template +_LIBCPP_NODISCARD_EXT inline +_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 +const _Tp& +min(const _Tp& __a, const _Tp& __b, _Compare __comp) +{ + return __comp(__b, __a) ? __b : __a; +} + +template +_LIBCPP_NODISCARD_EXT inline +_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 +const _Tp& +min(const _Tp& __a, const _Tp& __b) +{ + return _VSTD::min(__a, __b, __less<_Tp>()); +} + +#ifndef _LIBCPP_CXX03_LANG + +template +_LIBCPP_NODISCARD_EXT inline +_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 +_Tp +min(initializer_list<_Tp> __t, _Compare __comp) +{ + return *_VSTD::__min_element<__comp_ref_type<_Compare> >(__t.begin(), __t.end(), __comp); +} + +template +_LIBCPP_NODISCARD_EXT inline +_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 +_Tp +min(initializer_list<_Tp> __t) +{ + return *_VSTD::min_element(__t.begin(), __t.end(), __less<_Tp>()); +} + +#endif // _LIBCPP_CXX03_LANG + +_LIBCPP_END_NAMESPACE_STD + +_LIBCPP_POP_MACROS + +#endif // _LIBCPP___ALGORITHM_MIN_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/min_element.h b/app/src/main/cpp/libcxx/include/__algorithm/min_element.h new file mode 100644 index 0000000..c0706fe --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/min_element.h @@ -0,0 +1,70 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_MIN_ELEMENT_H +#define _LIBCPP___ALGORITHM_MIN_ELEMENT_H + +#include <__algorithm/comp.h> +#include <__algorithm/comp_ref_type.h> +#include <__config> +#include <__functional/identity.h> +#include <__functional/invoke.h> +#include <__iterator/iterator_traits.h> +#include <__type_traits/is_callable.h> +#include <__utility/move.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +template +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 +_Iter __min_element(_Iter __first, _Sent __last, _Comp __comp, _Proj& __proj) { + if (__first == __last) + return __first; + + _Iter __i = __first; + while (++__i != __last) + if (std::__invoke(__comp, std::__invoke(__proj, *__i), std::__invoke(__proj, *__first))) + __first = __i; + + return __first; +} + +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 +_Iter __min_element(_Iter __first, _Sent __last, _Comp __comp) { + auto __proj = __identity(); + return std::__min_element<_Comp>(std::move(__first), std::move(__last), __comp, __proj); +} + +template +_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _ForwardIterator +min_element(_ForwardIterator __first, _ForwardIterator __last, _Compare __comp) +{ + static_assert(__is_cpp17_forward_iterator<_ForwardIterator>::value, + "std::min_element requires a ForwardIterator"); + static_assert(__is_callable<_Compare, decltype(*__first), decltype(*__first)>::value, + "The comparator has to be callable"); + + return std::__min_element<__comp_ref_type<_Compare> >(std::move(__first), std::move(__last), __comp); +} + +template +_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _ForwardIterator +min_element(_ForwardIterator __first, _ForwardIterator __last) +{ + return _VSTD::min_element(__first, __last, + __less::value_type>()); +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ALGORITHM_MIN_ELEMENT_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/min_max_result.h b/app/src/main/cpp/libcxx/include/__algorithm/min_max_result.h new file mode 100644 index 0000000..4be3999 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/min_max_result.h @@ -0,0 +1,56 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_MIN_MAX_RESULT_H +#define _LIBCPP___ALGORITHM_MIN_MAX_RESULT_H + +#include <__concepts/convertible_to.h> +#include <__config> +#include <__utility/move.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 17 + +namespace ranges { + +template +struct min_max_result { + _LIBCPP_NO_UNIQUE_ADDRESS _T1 min; + _LIBCPP_NO_UNIQUE_ADDRESS _T1 max; + + template + requires convertible_to + _LIBCPP_HIDE_FROM_ABI constexpr operator min_max_result<_T2>() const & { + return {min, max}; + } + + template + requires convertible_to<_T1, _T2> + _LIBCPP_HIDE_FROM_ABI constexpr operator min_max_result<_T2>() && { + return {std::move(min), std::move(max)}; + } +}; + +} // namespace ranges + +#endif // _LIBCPP_STD_VER > 17 + +_LIBCPP_END_NAMESPACE_STD + +_LIBCPP_POP_MACROS + +#endif // _LIBCPP___ALGORITHM_MIN_MAX_RESULT_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/minmax.h b/app/src/main/cpp/libcxx/include/__algorithm/minmax.h new file mode 100644 index 0000000..6ef0a77 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/minmax.h @@ -0,0 +1,69 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_MINMAX_H +#define _LIBCPP___ALGORITHM_MINMAX_H + +#include <__algorithm/comp.h> +#include <__algorithm/minmax_element.h> +#include <__config> +#include <__functional/identity.h> +#include <__type_traits/is_callable.h> +#include <__utility/pair.h> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +template +_LIBCPP_NODISCARD_EXT inline +_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 +pair +minmax(const _Tp& __a, const _Tp& __b, _Compare __comp) +{ + return __comp(__b, __a) ? pair(__b, __a) : + pair(__a, __b); +} + +template +_LIBCPP_NODISCARD_EXT inline +_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 +pair +minmax(const _Tp& __a, const _Tp& __b) +{ + return std::minmax(__a, __b, __less<_Tp>()); +} + +#ifndef _LIBCPP_CXX03_LANG + +template +_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 +pair<_Tp, _Tp> minmax(initializer_list<_Tp> __t, _Compare __comp) { + static_assert(__is_callable<_Compare, _Tp, _Tp>::value, "The comparator has to be callable"); + __identity __proj; + auto __ret = std::__minmax_element_impl(__t.begin(), __t.end(), __comp, __proj); + return pair<_Tp, _Tp>(*__ret.first, *__ret.second); +} + +template +_LIBCPP_NODISCARD_EXT inline +_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 +pair<_Tp, _Tp> +minmax(initializer_list<_Tp> __t) +{ + return std::minmax(__t, __less<_Tp>()); +} + +#endif // _LIBCPP_CXX03_LANG + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ALGORITHM_MINMAX_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/minmax_element.h b/app/src/main/cpp/libcxx/include/__algorithm/minmax_element.h new file mode 100644 index 0000000..caa963e --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/minmax_element.h @@ -0,0 +1,101 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_MINMAX_ELEMENT_H +#define _LIBCPP___ALGORITHM_MINMAX_ELEMENT_H + +#include <__algorithm/comp.h> +#include <__config> +#include <__functional/identity.h> +#include <__iterator/iterator_traits.h> +#include <__utility/pair.h> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +template +class _MinmaxElementLessFunc { + _Comp& __comp_; + _Proj& __proj_; + +public: + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR + _MinmaxElementLessFunc(_Comp& __comp, _Proj& __proj) : __comp_(__comp), __proj_(__proj) {} + + template + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 + bool operator()(_Iter& __it1, _Iter& __it2) { + return std::__invoke(__comp_, std::__invoke(__proj_, *__it1), std::__invoke(__proj_, *__it2)); + } +}; + +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 +pair<_Iter, _Iter> __minmax_element_impl(_Iter __first, _Sent __last, _Comp& __comp, _Proj& __proj) { + auto __less = _MinmaxElementLessFunc<_Comp, _Proj>(__comp, __proj); + + pair<_Iter, _Iter> __result(__first, __first); + if (__first == __last || ++__first == __last) + return __result; + + if (__less(__first, __result.first)) + __result.first = __first; + else + __result.second = __first; + + while (++__first != __last) { + _Iter __i = __first; + if (++__first == __last) { + if (__less(__i, __result.first)) + __result.first = __i; + else if (!__less(__i, __result.second)) + __result.second = __i; + return __result; + } + + if (__less(__first, __i)) { + if (__less(__first, __result.first)) + __result.first = __first; + if (!__less(__i, __result.second)) + __result.second = __i; + } else { + if (__less(__i, __result.first)) + __result.first = __i; + if (!__less(__first, __result.second)) + __result.second = __first; + } + } + + return __result; +} + +template +_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 +pair<_ForwardIterator, _ForwardIterator> +minmax_element(_ForwardIterator __first, _ForwardIterator __last, _Compare __comp) { + static_assert(__is_cpp17_forward_iterator<_ForwardIterator>::value, + "std::minmax_element requires a ForwardIterator"); + static_assert(__is_callable<_Compare, decltype(*__first), decltype(*__first)>::value, + "The comparator has to be callable"); + auto __proj = __identity(); + return std::__minmax_element_impl(__first, __last, __comp, __proj); +} + +template +_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 +pair<_ForwardIterator, _ForwardIterator> minmax_element(_ForwardIterator __first, _ForwardIterator __last) { + return std::minmax_element(__first, __last, __less::value_type>()); +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ALGORITHM_MINMAX_ELEMENT_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/mismatch.h b/app/src/main/cpp/libcxx/include/__algorithm/mismatch.h new file mode 100644 index 0000000..600e2cd --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/mismatch.h @@ -0,0 +1,63 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_MISMATCH_H +#define _LIBCPP___ALGORITHM_MISMATCH_H + +#include <__algorithm/comp.h> +#include <__config> +#include <__iterator/iterator_traits.h> +#include <__utility/pair.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +template +_LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY + _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_InputIterator1, _InputIterator2> + mismatch(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2, _BinaryPredicate __pred) { + for (; __first1 != __last1; ++__first1, (void)++__first2) + if (!__pred(*__first1, *__first2)) + break; + return pair<_InputIterator1, _InputIterator2>(__first1, __first2); +} + +template +_LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY + _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_InputIterator1, _InputIterator2> + mismatch(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2) { + return std::mismatch(__first1, __last1, __first2, __equal_to()); +} + +#if _LIBCPP_STD_VER > 11 +template +_LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY + _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_InputIterator1, _InputIterator2> + mismatch(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2, _InputIterator2 __last2, + _BinaryPredicate __pred) { + for (; __first1 != __last1 && __first2 != __last2; ++__first1, (void)++__first2) + if (!__pred(*__first1, *__first2)) + break; + return pair<_InputIterator1, _InputIterator2>(__first1, __first2); +} + +template +_LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY + _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_InputIterator1, _InputIterator2> + mismatch(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2, _InputIterator2 __last2) { + return std::mismatch(__first1, __last1, __first2, __last2, __equal_to()); +} +#endif + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ALGORITHM_MISMATCH_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/move.h b/app/src/main/cpp/libcxx/include/__algorithm/move.h new file mode 100644 index 0000000..ac95bda --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/move.h @@ -0,0 +1,130 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_MOVE_H +#define _LIBCPP___ALGORITHM_MOVE_H + +#include <__algorithm/copy_move_common.h> +#include <__algorithm/iterator_operations.h> +#include <__algorithm/min.h> +#include <__config> +#include <__iterator/segmented_iterator.h> +#include <__type_traits/common_type.h> +#include <__type_traits/is_copy_constructible.h> +#include <__utility/move.h> +#include <__utility/pair.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + +_LIBCPP_BEGIN_NAMESPACE_STD + +template +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_InIter, _OutIter> +__move(_InIter __first, _Sent __last, _OutIter __result); + +template +struct __move_loop { + template + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_InIter, _OutIter> + operator()(_InIter __first, _Sent __last, _OutIter __result) const { + while (__first != __last) { + *__result = _IterOps<_AlgPolicy>::__iter_move(__first); + ++__first; + ++__result; + } + return std::make_pair(std::move(__first), std::move(__result)); + } + + template ::value, int> = 0> + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_InIter, _OutIter> + operator()(_InIter __first, _InIter __last, _OutIter __result) const { + using _Traits = __segmented_iterator_traits<_InIter>; + auto __sfirst = _Traits::__segment(__first); + auto __slast = _Traits::__segment(__last); + if (__sfirst == __slast) { + auto __iters = std::__move<_AlgPolicy>(_Traits::__local(__first), _Traits::__local(__last), std::move(__result)); + return std::make_pair(__last, std::move(__iters.second)); + } + + __result = std::__move<_AlgPolicy>(_Traits::__local(__first), _Traits::__end(__sfirst), std::move(__result)).second; + ++__sfirst; + while (__sfirst != __slast) { + __result = + std::__move<_AlgPolicy>(_Traits::__begin(__sfirst), _Traits::__end(__sfirst), std::move(__result)).second; + ++__sfirst; + } + __result = + std::__move<_AlgPolicy>(_Traits::__begin(__sfirst), _Traits::__local(__last), std::move(__result)).second; + return std::make_pair(__last, std::move(__result)); + } + + template ::value && + !__is_segmented_iterator<_InIter>::value && __is_segmented_iterator<_OutIter>::value, + int> = 0> + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_InIter, _OutIter> + operator()(_InIter __first, _InIter __last, _OutIter __result) { + using _Traits = __segmented_iterator_traits<_OutIter>; + using _DiffT = typename common_type<__iter_diff_t<_InIter>, __iter_diff_t<_OutIter> >::type; + + if (__first == __last) + return std::make_pair(std::move(__first), std::move(__result)); + + auto __local_first = _Traits::__local(__result); + auto __segment_iterator = _Traits::__segment(__result); + while (true) { + auto __local_last = _Traits::__end(__segment_iterator); + auto __size = std::min<_DiffT>(__local_last - __local_first, __last - __first); + auto __iters = std::__move<_AlgPolicy>(__first, __first + __size, __local_first); + __first = std::move(__iters.first); + + if (__first == __last) + return std::make_pair(std::move(__first), _Traits::__compose(__segment_iterator, std::move(__iters.second))); + + __local_first = _Traits::__begin(++__segment_iterator); + } + } +}; + +struct __move_trivial { + // At this point, the iterators have been unwrapped so any `contiguous_iterator` has been unwrapped to a pointer. + template ::value, int> = 0> + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_In*, _Out*> + operator()(_In* __first, _In* __last, _Out* __result) const { + return std::__copy_trivial_impl(__first, __last, __result); + } +}; + +template +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_InIter, _OutIter> +__move(_InIter __first, _Sent __last, _OutIter __result) { + return std::__dispatch_copy_or_move<_AlgPolicy, __move_loop<_AlgPolicy>, __move_trivial>( + std::move(__first), std::move(__last), std::move(__result)); +} + +template +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _OutputIterator +move(_InputIterator __first, _InputIterator __last, _OutputIterator __result) { + static_assert(is_copy_constructible<_InputIterator>::value, "Iterators has to be copy constructible."); + static_assert(is_copy_constructible<_OutputIterator>::value, "The output iterator has to be copy constructible."); + + return std::__move<_ClassicAlgPolicy>(std::move(__first), std::move(__last), std::move(__result)).second; +} + +_LIBCPP_END_NAMESPACE_STD + +_LIBCPP_POP_MACROS + +#endif // _LIBCPP___ALGORITHM_MOVE_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/move_backward.h b/app/src/main/cpp/libcxx/include/__algorithm/move_backward.h new file mode 100644 index 0000000..d4f013b --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/move_backward.h @@ -0,0 +1,139 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_MOVE_BACKWARD_H +#define _LIBCPP___ALGORITHM_MOVE_BACKWARD_H + +#include <__algorithm/copy_move_common.h> +#include <__algorithm/iterator_operations.h> +#include <__algorithm/min.h> +#include <__config> +#include <__iterator/segmented_iterator.h> +#include <__type_traits/common_type.h> +#include <__type_traits/is_copy_constructible.h> +#include <__utility/move.h> +#include <__utility/pair.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + +_LIBCPP_BEGIN_NAMESPACE_STD + +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_BidirectionalIterator1, _BidirectionalIterator2> +__move_backward(_BidirectionalIterator1 __first, _Sentinel __last, _BidirectionalIterator2 __result); + +template +struct __move_backward_loop { + template + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_InIter, _OutIter> + operator()(_InIter __first, _Sent __last, _OutIter __result) const { + auto __last_iter = _IterOps<_AlgPolicy>::next(__first, __last); + auto __original_last_iter = __last_iter; + + while (__first != __last_iter) { + *--__result = _IterOps<_AlgPolicy>::__iter_move(--__last_iter); + } + + return std::make_pair(std::move(__original_last_iter), std::move(__result)); + } + + template ::value, int> = 0> + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_InIter, _OutIter> + operator()(_InIter __first, _InIter __last, _OutIter __result) const { + using _Traits = __segmented_iterator_traits<_InIter>; + auto __sfirst = _Traits::__segment(__first); + auto __slast = _Traits::__segment(__last); + if (__sfirst == __slast) { + auto __iters = + std::__move_backward<_AlgPolicy>(_Traits::__local(__first), _Traits::__local(__last), std::move(__result)); + return std::make_pair(__last, __iters.second); + } + + __result = + std::__move_backward<_AlgPolicy>(_Traits::__begin(__slast), _Traits::__local(__last), std::move(__result)) + .second; + --__slast; + while (__sfirst != __slast) { + __result = + std::__move_backward<_AlgPolicy>(_Traits::__begin(__slast), _Traits::__end(__slast), std::move(__result)) + .second; + --__slast; + } + __result = std::__move_backward<_AlgPolicy>(_Traits::__local(__first), _Traits::__end(__slast), std::move(__result)) + .second; + return std::make_pair(__last, std::move(__result)); + } + + template ::value && + !__is_segmented_iterator<_InIter>::value && __is_segmented_iterator<_OutIter>::value, + int> = 0> + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_InIter, _OutIter> + operator()(_InIter __first, _InIter __last, _OutIter __result) { + using _Traits = __segmented_iterator_traits<_OutIter>; + using _DiffT = typename common_type<__iter_diff_t<_InIter>, __iter_diff_t<_OutIter> >::type; + + // When the range contains no elements, __result might not be a valid iterator + if (__first == __last) + return std::make_pair(__first, __result); + + auto __orig_last = __last; + + auto __local_last = _Traits::__local(__result); + auto __segment_iterator = _Traits::__segment(__result); + while (true) { + auto __local_first = _Traits::__begin(__segment_iterator); + auto __size = std::min<_DiffT>(__local_last - __local_first, __last - __first); + auto __iter = std::__move_backward<_AlgPolicy>(__last - __size, __last, __local_last).second; + __last -= __size; + + if (__first == __last) + return std::make_pair(std::move(__orig_last), _Traits::__compose(__segment_iterator, std::move(__iter))); + + __local_last = _Traits::__end(--__segment_iterator); + } + } +}; + +struct __move_backward_trivial { + // At this point, the iterators have been unwrapped so any `contiguous_iterator` has been unwrapped to a pointer. + template ::value, int> = 0> + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_In*, _Out*> + operator()(_In* __first, _In* __last, _Out* __result) const { + return std::__copy_backward_trivial_impl(__first, __last, __result); + } +}; + +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_BidirectionalIterator1, _BidirectionalIterator2> +__move_backward(_BidirectionalIterator1 __first, _Sentinel __last, _BidirectionalIterator2 __result) { + static_assert(std::is_copy_constructible<_BidirectionalIterator1>::value && + std::is_copy_constructible<_BidirectionalIterator1>::value, "Iterators must be copy constructible."); + + return std::__dispatch_copy_or_move<_AlgPolicy, __move_backward_loop<_AlgPolicy>, __move_backward_trivial>( + std::move(__first), std::move(__last), std::move(__result)); +} + +template +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 _BidirectionalIterator2 +move_backward(_BidirectionalIterator1 __first, _BidirectionalIterator1 __last, _BidirectionalIterator2 __result) { + return std::__move_backward<_ClassicAlgPolicy>(std::move(__first), std::move(__last), std::move(__result)).second; +} + +_LIBCPP_END_NAMESPACE_STD + +_LIBCPP_POP_MACROS + +#endif // _LIBCPP___ALGORITHM_MOVE_BACKWARD_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/next_permutation.h b/app/src/main/cpp/libcxx/include/__algorithm/next_permutation.h new file mode 100644 index 0000000..73e8b99 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/next_permutation.h @@ -0,0 +1,78 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_NEXT_PERMUTATION_H +#define _LIBCPP___ALGORITHM_NEXT_PERMUTATION_H + +#include <__algorithm/comp.h> +#include <__algorithm/comp_ref_type.h> +#include <__algorithm/iterator_operations.h> +#include <__algorithm/reverse.h> +#include <__config> +#include <__iterator/iterator_traits.h> +#include <__utility/move.h> +#include <__utility/pair.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_BidirectionalIterator, bool> +__next_permutation(_BidirectionalIterator __first, _Sentinel __last, _Compare&& __comp) +{ + using _Result = pair<_BidirectionalIterator, bool>; + + _BidirectionalIterator __last_iter = _IterOps<_AlgPolicy>::next(__first, __last); + _BidirectionalIterator __i = __last_iter; + if (__first == __last || __first == --__i) + return _Result(std::move(__last_iter), false); + + while (true) + { + _BidirectionalIterator __ip1 = __i; + if (__comp(*--__i, *__ip1)) + { + _BidirectionalIterator __j = __last_iter; + while (!__comp(*__i, *--__j)) + ; + _IterOps<_AlgPolicy>::iter_swap(__i, __j); + std::__reverse<_AlgPolicy>(__ip1, __last_iter); + return _Result(std::move(__last_iter), true); + } + if (__i == __first) + { + std::__reverse<_AlgPolicy>(__first, __last_iter); + return _Result(std::move(__last_iter), false); + } + } +} + +template +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 +bool +next_permutation(_BidirectionalIterator __first, _BidirectionalIterator __last, _Compare __comp) +{ + return std::__next_permutation<_ClassicAlgPolicy>( + std::move(__first), std::move(__last), static_cast<__comp_ref_type<_Compare> >(__comp)).second; +} + +template +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 +bool +next_permutation(_BidirectionalIterator __first, _BidirectionalIterator __last) +{ + return _VSTD::next_permutation(__first, __last, + __less::value_type>()); +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ALGORITHM_NEXT_PERMUTATION_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/none_of.h b/app/src/main/cpp/libcxx/include/__algorithm/none_of.h new file mode 100644 index 0000000..19357eb --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/none_of.h @@ -0,0 +1,32 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_NONE_OF_H +#define _LIBCPP___ALGORITHM_NONE_OF_H + +#include <__config> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +template +_LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 bool +none_of(_InputIterator __first, _InputIterator __last, _Predicate __pred) { + for (; __first != __last; ++__first) + if (__pred(*__first)) + return false; + return true; +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ALGORITHM_NONE_OF_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/nth_element.h b/app/src/main/cpp/libcxx/include/__algorithm/nth_element.h new file mode 100644 index 0000000..9fdfb2c --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/nth_element.h @@ -0,0 +1,258 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_NTH_ELEMENT_H +#define _LIBCPP___ALGORITHM_NTH_ELEMENT_H + +#include <__algorithm/comp.h> +#include <__algorithm/comp_ref_type.h> +#include <__algorithm/iterator_operations.h> +#include <__algorithm/sort.h> +#include <__config> +#include <__debug> +#include <__debug_utils/randomize_range.h> +#include <__iterator/iterator_traits.h> +#include <__utility/move.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 bool +__nth_element_find_guard(_RandomAccessIterator& __i, _RandomAccessIterator& __j, + _RandomAccessIterator __m, _Compare __comp) +{ + // manually guard downward moving __j against __i + while (true) { + if (__i == --__j) { + return false; + } + if (__comp(*__j, *__m)) { + return true; // found guard for downward moving __j, now use unguarded partition + } + } +} + +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 void +__nth_element(_RandomAccessIterator __first, _RandomAccessIterator __nth, _RandomAccessIterator __last, _Compare __comp) +{ + using _Ops = _IterOps<_AlgPolicy>; + + // _Compare is known to be a reference type + typedef typename iterator_traits<_RandomAccessIterator>::difference_type difference_type; + const difference_type __limit = 7; + while (true) + { + if (__nth == __last) + return; + difference_type __len = __last - __first; + switch (__len) + { + case 0: + case 1: + return; + case 2: + if (__comp(*--__last, *__first)) + _Ops::iter_swap(__first, __last); + return; + case 3: + { + _RandomAccessIterator __m = __first; + std::__sort3<_AlgPolicy, _Compare>(__first, ++__m, --__last, __comp); + return; + } + } + if (__len <= __limit) + { + std::__selection_sort<_AlgPolicy, _Compare>(__first, __last, __comp); + return; + } + // __len > __limit >= 3 + _RandomAccessIterator __m = __first + __len/2; + _RandomAccessIterator __lm1 = __last; + unsigned __n_swaps = std::__sort3<_AlgPolicy, _Compare>(__first, __m, --__lm1, __comp); + // *__m is median + // partition [__first, __m) < *__m and *__m <= [__m, __last) + // (this inhibits tossing elements equivalent to __m around unnecessarily) + _RandomAccessIterator __i = __first; + _RandomAccessIterator __j = __lm1; + // j points beyond range to be tested, *__lm1 is known to be <= *__m + // The search going up is known to be guarded but the search coming down isn't. + // Prime the downward search with a guard. + if (!__comp(*__i, *__m)) // if *__first == *__m + { + // *__first == *__m, *__first doesn't go in first part + if (_VSTD::__nth_element_find_guard<_Compare>(__i, __j, __m, __comp)) { + _Ops::iter_swap(__i, __j); + ++__n_swaps; + } else { + // *__first == *__m, *__m <= all other elements + // Partition instead into [__first, __i) == *__first and *__first < [__i, __last) + ++__i; // __first + 1 + __j = __last; + if (!__comp(*__first, *--__j)) { // we need a guard if *__first == *(__last-1) + while (true) { + if (__i == __j) { + return; // [__first, __last) all equivalent elements + } else if (__comp(*__first, *__i)) { + _Ops::iter_swap(__i, __j); + ++__n_swaps; + ++__i; + break; + } + ++__i; + } + } + // [__first, __i) == *__first and *__first < [__j, __last) and __j == __last - 1 + if (__i == __j) { + return; + } + while (true) { + while (!__comp(*__first, *__i)) + ++__i; + while (__comp(*__first, *--__j)) + ; + if (__i >= __j) + break; + _Ops::iter_swap(__i, __j); + ++__n_swaps; + ++__i; + } + // [__first, __i) == *__first and *__first < [__i, __last) + // The first part is sorted, + if (__nth < __i) { + return; + } + // __nth_element the second part + // _VSTD::__nth_element<_Compare>(__i, __nth, __last, __comp); + __first = __i; + continue; + } + } + ++__i; + // j points beyond range to be tested, *__lm1 is known to be <= *__m + // if not yet partitioned... + if (__i < __j) + { + // known that *(__i - 1) < *__m + while (true) + { + // __m still guards upward moving __i + while (__comp(*__i, *__m)) + ++__i; + // It is now known that a guard exists for downward moving __j + while (!__comp(*--__j, *__m)) + ; + if (__i >= __j) + break; + _Ops::iter_swap(__i, __j); + ++__n_swaps; + // It is known that __m != __j + // If __m just moved, follow it + if (__m == __i) + __m = __j; + ++__i; + } + } + // [__first, __i) < *__m and *__m <= [__i, __last) + if (__i != __m && __comp(*__m, *__i)) + { + _Ops::iter_swap(__i, __m); + ++__n_swaps; + } + // [__first, __i) < *__i and *__i <= [__i+1, __last) + if (__nth == __i) + return; + if (__n_swaps == 0) + { + // We were given a perfectly partitioned sequence. Coincidence? + if (__nth < __i) + { + // Check for [__first, __i) already sorted + __j = __m = __first; + while (true) { + if (++__j == __i) { + // [__first, __i) sorted + return; + } + if (__comp(*__j, *__m)) { + // not yet sorted, so sort + break; + } + __m = __j; + } + } + else + { + // Check for [__i, __last) already sorted + __j = __m = __i; + while (true) { + if (++__j == __last) { + // [__i, __last) sorted + return; + } + if (__comp(*__j, *__m)) { + // not yet sorted, so sort + break; + } + __m = __j; + } + } + } + // __nth_element on range containing __nth + if (__nth < __i) + { + // _VSTD::__nth_element<_Compare>(__first, __nth, __i, __comp); + __last = __i; + } + else + { + // _VSTD::__nth_element<_Compare>(__i+1, __nth, __last, __comp); + __first = ++__i; + } + } +} + +template +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 +void __nth_element_impl(_RandomAccessIterator __first, _RandomAccessIterator __nth, _RandomAccessIterator __last, + _Compare& __comp) { + if (__nth == __last) + return; + + std::__debug_randomize_range<_AlgPolicy>(__first, __last); + + std::__nth_element<_AlgPolicy, __comp_ref_type<_Compare> >(__first, __nth, __last, __comp); + + std::__debug_randomize_range<_AlgPolicy>(__first, __nth); + if (__nth != __last) { + std::__debug_randomize_range<_AlgPolicy>(++__nth, __last); + } +} + +template +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 +void nth_element(_RandomAccessIterator __first, _RandomAccessIterator __nth, _RandomAccessIterator __last, + _Compare __comp) { + std::__nth_element_impl<_ClassicAlgPolicy>(std::move(__first), std::move(__nth), std::move(__last), __comp); +} + +template +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 +void nth_element(_RandomAccessIterator __first, _RandomAccessIterator __nth, _RandomAccessIterator __last) { + std::nth_element(std::move(__first), std::move(__nth), std::move(__last), __less::value_type>()); +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ALGORITHM_NTH_ELEMENT_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/partial_sort.h b/app/src/main/cpp/libcxx/include/__algorithm/partial_sort.h new file mode 100644 index 0000000..e0812af --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/partial_sort.h @@ -0,0 +1,96 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_PARTIAL_SORT_H +#define _LIBCPP___ALGORITHM_PARTIAL_SORT_H + +#include <__algorithm/comp.h> +#include <__algorithm/comp_ref_type.h> +#include <__algorithm/iterator_operations.h> +#include <__algorithm/make_heap.h> +#include <__algorithm/sift_down.h> +#include <__algorithm/sort_heap.h> +#include <__config> +#include <__debug> +#include <__debug_utils/randomize_range.h> +#include <__iterator/iterator_traits.h> +#include <__utility/move.h> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 +_RandomAccessIterator __partial_sort_impl( + _RandomAccessIterator __first, _RandomAccessIterator __middle, _Sentinel __last, _Compare&& __comp) { + if (__first == __middle) { + return _IterOps<_AlgPolicy>::next(__middle, __last); + } + + std::__make_heap<_AlgPolicy>(__first, __middle, __comp); + + typename iterator_traits<_RandomAccessIterator>::difference_type __len = __middle - __first; + _RandomAccessIterator __i = __middle; + for (; __i != __last; ++__i) + { + if (__comp(*__i, *__first)) + { + _IterOps<_AlgPolicy>::iter_swap(__i, __first); + std::__sift_down<_AlgPolicy>(__first, __comp, __len, __first); + } + } + std::__sort_heap<_AlgPolicy>(std::move(__first), std::move(__middle), __comp); + + return __i; +} + +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 +_RandomAccessIterator __partial_sort(_RandomAccessIterator __first, _RandomAccessIterator __middle, _Sentinel __last, + _Compare& __comp) { + if (__first == __middle) + return _IterOps<_AlgPolicy>::next(__middle, __last); + + std::__debug_randomize_range<_AlgPolicy>(__first, __last); + + auto __last_iter = + std::__partial_sort_impl<_AlgPolicy>(__first, __middle, __last, static_cast<__comp_ref_type<_Compare> >(__comp)); + + std::__debug_randomize_range<_AlgPolicy>(__middle, __last); + + return __last_iter; +} + +template +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 +void +partial_sort(_RandomAccessIterator __first, _RandomAccessIterator __middle, _RandomAccessIterator __last, + _Compare __comp) +{ + static_assert(std::is_copy_constructible<_RandomAccessIterator>::value, "Iterators must be copy constructible."); + static_assert(std::is_copy_assignable<_RandomAccessIterator>::value, "Iterators must be copy assignable."); + + (void)std::__partial_sort<_ClassicAlgPolicy>(std::move(__first), std::move(__middle), std::move(__last), __comp); +} + +template +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 +void +partial_sort(_RandomAccessIterator __first, _RandomAccessIterator __middle, _RandomAccessIterator __last) +{ + _VSTD::partial_sort(__first, __middle, __last, + __less::value_type>()); +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ALGORITHM_PARTIAL_SORT_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/partial_sort_copy.h b/app/src/main/cpp/libcxx/include/__algorithm/partial_sort_copy.h new file mode 100644 index 0000000..1aba071 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/partial_sort_copy.h @@ -0,0 +1,88 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_PARTIAL_SORT_COPY_H +#define _LIBCPP___ALGORITHM_PARTIAL_SORT_COPY_H + +#include <__algorithm/comp.h> +#include <__algorithm/comp_ref_type.h> +#include <__algorithm/iterator_operations.h> +#include <__algorithm/make_heap.h> +#include <__algorithm/make_projected.h> +#include <__algorithm/sift_down.h> +#include <__algorithm/sort_heap.h> +#include <__config> +#include <__functional/identity.h> +#include <__functional/invoke.h> +#include <__iterator/iterator_traits.h> +#include <__type_traits/is_callable.h> +#include <__utility/move.h> +#include <__utility/pair.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_InputIterator, _RandomAccessIterator> +__partial_sort_copy(_InputIterator __first, _Sentinel1 __last, + _RandomAccessIterator __result_first, _Sentinel2 __result_last, + _Compare&& __comp, _Proj1&& __proj1, _Proj2&& __proj2) +{ + _RandomAccessIterator __r = __result_first; + auto&& __projected_comp = std::__make_projected(__comp, __proj2); + + if (__r != __result_last) + { + for (; __first != __last && __r != __result_last; ++__first, (void) ++__r) + *__r = *__first; + std::__make_heap<_AlgPolicy>(__result_first, __r, __projected_comp); + typename iterator_traits<_RandomAccessIterator>::difference_type __len = __r - __result_first; + for (; __first != __last; ++__first) + if (std::__invoke(__comp, std::__invoke(__proj1, *__first), std::__invoke(__proj2, *__result_first))) { + *__result_first = *__first; + std::__sift_down<_AlgPolicy>(__result_first, __projected_comp, __len, __result_first); + } + std::__sort_heap<_AlgPolicy>(__result_first, __r, __projected_comp); + } + + return pair<_InputIterator, _RandomAccessIterator>( + _IterOps<_AlgPolicy>::next(std::move(__first), std::move(__last)), std::move(__r)); +} + +template +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 +_RandomAccessIterator +partial_sort_copy(_InputIterator __first, _InputIterator __last, + _RandomAccessIterator __result_first, _RandomAccessIterator __result_last, _Compare __comp) +{ + static_assert(__is_callable<_Compare, decltype(*__first), decltype(*__result_first)>::value, + "Comparator has to be callable"); + + auto __result = std::__partial_sort_copy<_ClassicAlgPolicy>(__first, __last, __result_first, __result_last, + static_cast<__comp_ref_type<_Compare> >(__comp), __identity(), __identity()); + return __result.second; +} + +template +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 +_RandomAccessIterator +partial_sort_copy(_InputIterator __first, _InputIterator __last, + _RandomAccessIterator __result_first, _RandomAccessIterator __result_last) +{ + return _VSTD::partial_sort_copy(__first, __last, __result_first, __result_last, + __less::value_type>()); +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ALGORITHM_PARTIAL_SORT_COPY_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/partition.h b/app/src/main/cpp/libcxx/include/__algorithm/partition.h new file mode 100644 index 0000000..0e094bf --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/partition.h @@ -0,0 +1,98 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_PARTITION_H +#define _LIBCPP___ALGORITHM_PARTITION_H + +#include <__algorithm/iterator_operations.h> +#include <__config> +#include <__iterator/iterator_traits.h> +#include <__utility/move.h> +#include <__utility/pair.h> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_ForwardIterator, _ForwardIterator> +__partition_impl(_ForwardIterator __first, _Sentinel __last, _Predicate __pred, forward_iterator_tag) +{ + while (true) + { + if (__first == __last) + return std::make_pair(std::move(__first), std::move(__first)); + if (!__pred(*__first)) + break; + ++__first; + } + + _ForwardIterator __p = __first; + while (++__p != __last) + { + if (__pred(*__p)) + { + _IterOps<_AlgPolicy>::iter_swap(__first, __p); + ++__first; + } + } + return std::make_pair(std::move(__first), std::move(__p)); +} + +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_BidirectionalIterator, _BidirectionalIterator> +__partition_impl(_BidirectionalIterator __first, _Sentinel __sentinel, _Predicate __pred, + bidirectional_iterator_tag) +{ + _BidirectionalIterator __original_last = _IterOps<_AlgPolicy>::next(__first, __sentinel); + _BidirectionalIterator __last = __original_last; + + while (true) + { + while (true) + { + if (__first == __last) + return std::make_pair(std::move(__first), std::move(__original_last)); + if (!__pred(*__first)) + break; + ++__first; + } + do + { + if (__first == --__last) + return std::make_pair(std::move(__first), std::move(__original_last)); + } while (!__pred(*__last)); + _IterOps<_AlgPolicy>::iter_swap(__first, __last); + ++__first; + } +} + +template +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 +pair<_ForwardIterator, _ForwardIterator> __partition( + _ForwardIterator __first, _Sentinel __last, _Predicate&& __pred, _IterCategory __iter_category) { + return std::__partition_impl<__remove_cvref_t<_Predicate>&, _AlgPolicy>( + std::move(__first), std::move(__last), __pred, __iter_category); +} + +template +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 +_ForwardIterator +partition(_ForwardIterator __first, _ForwardIterator __last, _Predicate __pred) +{ + using _IterCategory = typename iterator_traits<_ForwardIterator>::iterator_category; + auto __result = std::__partition<_ClassicAlgPolicy>(std::move(__first), std::move(__last), __pred, _IterCategory()); + return __result.first; +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ALGORITHM_PARTITION_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/partition_copy.h b/app/src/main/cpp/libcxx/include/__algorithm/partition_copy.h new file mode 100644 index 0000000..ff8826a --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/partition_copy.h @@ -0,0 +1,47 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_PARTITION_COPY_H +#define _LIBCPP___ALGORITHM_PARTITION_COPY_H + +#include <__config> +#include <__iterator/iterator_traits.h> +#include <__utility/pair.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_OutputIterator1, _OutputIterator2> +partition_copy(_InputIterator __first, _InputIterator __last, + _OutputIterator1 __out_true, _OutputIterator2 __out_false, + _Predicate __pred) +{ + for (; __first != __last; ++__first) + { + if (__pred(*__first)) + { + *__out_true = *__first; + ++__out_true; + } + else + { + *__out_false = *__first; + ++__out_false; + } + } + return pair<_OutputIterator1, _OutputIterator2>(__out_true, __out_false); +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ALGORITHM_PARTITION_COPY_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/partition_point.h b/app/src/main/cpp/libcxx/include/__algorithm/partition_point.h new file mode 100644 index 0000000..6ede71a --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/partition_point.h @@ -0,0 +1,48 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_PARTITION_POINT_H +#define _LIBCPP___ALGORITHM_PARTITION_POINT_H + +#include <__algorithm/half_positive.h> +#include <__config> +#include <__iterator/advance.h> +#include <__iterator/distance.h> +#include <__iterator/iterator_traits.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator +partition_point(_ForwardIterator __first, _ForwardIterator __last, _Predicate __pred) +{ + typedef typename iterator_traits<_ForwardIterator>::difference_type difference_type; + difference_type __len = _VSTD::distance(__first, __last); + while (__len != 0) + { + difference_type __l2 = _VSTD::__half_positive(__len); + _ForwardIterator __m = __first; + _VSTD::advance(__m, __l2); + if (__pred(*__m)) + { + __first = ++__m; + __len -= __l2 + 1; + } + else + __len = __l2; + } + return __first; +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ALGORITHM_PARTITION_POINT_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/pop_heap.h b/app/src/main/cpp/libcxx/include/__algorithm/pop_heap.h new file mode 100644 index 0000000..94d32a4 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/pop_heap.h @@ -0,0 +1,73 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_POP_HEAP_H +#define _LIBCPP___ALGORITHM_POP_HEAP_H + +#include <__algorithm/comp.h> +#include <__algorithm/comp_ref_type.h> +#include <__algorithm/iterator_operations.h> +#include <__algorithm/push_heap.h> +#include <__algorithm/sift_down.h> +#include <__assert> +#include <__config> +#include <__iterator/iterator_traits.h> +#include <__utility/move.h> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +template +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 +void __pop_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare& __comp, + typename iterator_traits<_RandomAccessIterator>::difference_type __len) { + _LIBCPP_ASSERT(__len > 0, "The heap given to pop_heap must be non-empty"); + + __comp_ref_type<_Compare> __comp_ref = __comp; + + using value_type = typename iterator_traits<_RandomAccessIterator>::value_type; + if (__len > 1) { + value_type __top = _IterOps<_AlgPolicy>::__iter_move(__first); // create a hole at __first + _RandomAccessIterator __hole = std::__floyd_sift_down<_AlgPolicy>(__first, __comp_ref, __len); + --__last; + + if (__hole == __last) { + *__hole = std::move(__top); + } else { + *__hole = _IterOps<_AlgPolicy>::__iter_move(__last); + ++__hole; + *__last = std::move(__top); + std::__sift_up<_AlgPolicy>(__first, __hole, __comp_ref, __hole - __first); + } + } +} + +template +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 +void pop_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp) { + static_assert(std::is_copy_constructible<_RandomAccessIterator>::value, "Iterators must be copy constructible."); + static_assert(std::is_copy_assignable<_RandomAccessIterator>::value, "Iterators must be copy assignable."); + + typename iterator_traits<_RandomAccessIterator>::difference_type __len = __last - __first; + std::__pop_heap<_ClassicAlgPolicy>(std::move(__first), std::move(__last), __comp, __len); +} + +template +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 +void pop_heap(_RandomAccessIterator __first, _RandomAccessIterator __last) { + std::pop_heap(std::move(__first), std::move(__last), + __less::value_type>()); +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ALGORITHM_POP_HEAP_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/prev_permutation.h b/app/src/main/cpp/libcxx/include/__algorithm/prev_permutation.h new file mode 100644 index 0000000..0b86ab7 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/prev_permutation.h @@ -0,0 +1,79 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_PREV_PERMUTATION_H +#define _LIBCPP___ALGORITHM_PREV_PERMUTATION_H + +#include <__algorithm/comp.h> +#include <__algorithm/comp_ref_type.h> +#include <__algorithm/iterator_operations.h> +#include <__algorithm/reverse.h> +#include <__config> +#include <__iterator/iterator_traits.h> +#include <__utility/move.h> +#include <__utility/pair.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 +pair<_BidirectionalIterator, bool> +__prev_permutation(_BidirectionalIterator __first, _Sentinel __last, _Compare&& __comp) +{ + using _Result = pair<_BidirectionalIterator, bool>; + + _BidirectionalIterator __last_iter = _IterOps<_AlgPolicy>::next(__first, __last); + _BidirectionalIterator __i = __last_iter; + if (__first == __last || __first == --__i) + return _Result(std::move(__last_iter), false); + + while (true) + { + _BidirectionalIterator __ip1 = __i; + if (__comp(*__ip1, *--__i)) + { + _BidirectionalIterator __j = __last_iter; + while (!__comp(*--__j, *__i)) + ; + _IterOps<_AlgPolicy>::iter_swap(__i, __j); + std::__reverse<_AlgPolicy>(__ip1, __last_iter); + return _Result(std::move(__last_iter), true); + } + if (__i == __first) + { + std::__reverse<_AlgPolicy>(__first, __last_iter); + return _Result(std::move(__last_iter), false); + } + } +} + +template +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 +bool +prev_permutation(_BidirectionalIterator __first, _BidirectionalIterator __last, _Compare __comp) +{ + return std::__prev_permutation<_ClassicAlgPolicy>( + std::move(__first), std::move(__last), static_cast<__comp_ref_type<_Compare> >(__comp)).second; +} + +template +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 +bool +prev_permutation(_BidirectionalIterator __first, _BidirectionalIterator __last) +{ + return _VSTD::prev_permutation(__first, __last, + __less::value_type>()); +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ALGORITHM_PREV_PERMUTATION_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/push_heap.h b/app/src/main/cpp/libcxx/include/__algorithm/push_heap.h new file mode 100644 index 0000000..9068495 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/push_heap.h @@ -0,0 +1,77 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_PUSH_HEAP_H +#define _LIBCPP___ALGORITHM_PUSH_HEAP_H + +#include <__algorithm/comp.h> +#include <__algorithm/comp_ref_type.h> +#include <__algorithm/iterator_operations.h> +#include <__config> +#include <__iterator/iterator_traits.h> +#include <__utility/move.h> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 +void __sift_up(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare&& __comp, + typename iterator_traits<_RandomAccessIterator>::difference_type __len) { + using value_type = typename iterator_traits<_RandomAccessIterator>::value_type; + + if (__len > 1) { + __len = (__len - 2) / 2; + _RandomAccessIterator __ptr = __first + __len; + + if (__comp(*__ptr, *--__last)) { + value_type __t(_IterOps<_AlgPolicy>::__iter_move(__last)); + do { + *__last = _IterOps<_AlgPolicy>::__iter_move(__ptr); + __last = __ptr; + if (__len == 0) + break; + __len = (__len - 1) / 2; + __ptr = __first + __len; + } while (__comp(*__ptr, __t)); + + *__last = std::move(__t); + } + } +} + +template +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 +void __push_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare& __comp) { + typename iterator_traits<_RandomAccessIterator>::difference_type __len = __last - __first; + std::__sift_up<_AlgPolicy, __comp_ref_type<_Compare> >(std::move(__first), std::move(__last), __comp, __len); +} + +template +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 +void push_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp) { + static_assert(std::is_copy_constructible<_RandomAccessIterator>::value, "Iterators must be copy constructible."); + static_assert(std::is_copy_assignable<_RandomAccessIterator>::value, "Iterators must be copy assignable."); + + std::__push_heap<_ClassicAlgPolicy>(std::move(__first), std::move(__last), __comp); +} + +template +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 +void push_heap(_RandomAccessIterator __first, _RandomAccessIterator __last) { + std::push_heap(std::move(__first), std::move(__last), + __less::value_type>()); +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ALGORITHM_PUSH_HEAP_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/ranges_adjacent_find.h b/app/src/main/cpp/libcxx/include/__algorithm/ranges_adjacent_find.h new file mode 100644 index 0000000..d338d13 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/ranges_adjacent_find.h @@ -0,0 +1,78 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_RANGES_ADJACENT_FIND_H +#define _LIBCPP___ALGORITHM_RANGES_ADJACENT_FIND_H + +#include <__config> +#include <__functional/identity.h> +#include <__functional/invoke.h> +#include <__functional/ranges_operations.h> +#include <__iterator/concepts.h> +#include <__iterator/projected.h> +#include <__ranges/access.h> +#include <__ranges/concepts.h> +#include <__ranges/dangling.h> +#include <__utility/move.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if _LIBCPP_STD_VER > 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace ranges { +namespace __adjacent_find { +struct __fn { + + template + _LIBCPP_HIDE_FROM_ABI constexpr static + _Iter __adjacent_find_impl(_Iter __first, _Sent __last, _Pred& __pred, _Proj& __proj) { + if (__first == __last) + return __first; + + auto __i = __first; + while (++__i != __last) { + if (std::invoke(__pred, std::invoke(__proj, *__first), std::invoke(__proj, *__i))) + return __first; + __first = __i; + } + return __i; + } + + template _Sent, + class _Proj = identity, + indirect_binary_predicate, projected<_Iter, _Proj>> _Pred = ranges::equal_to> + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr + _Iter operator()(_Iter __first, _Sent __last, _Pred __pred = {}, _Proj __proj = {}) const { + return __adjacent_find_impl(std::move(__first), std::move(__last), __pred, __proj); + } + + template , _Proj>, + projected, _Proj>> _Pred = ranges::equal_to> + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr + borrowed_iterator_t<_Range> operator()(_Range&& __range, _Pred __pred = {}, _Proj __proj = {}) const { + return __adjacent_find_impl(ranges::begin(__range), ranges::end(__range), __pred, __proj); + } +}; +} // namespace __adjacent_find + +inline namespace __cpo { + inline constexpr auto adjacent_find = __adjacent_find::__fn{}; +} // namespace __cpo +} // namespace ranges + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER > 17 + +#endif // _LIBCPP___ALGORITHM_RANGES_ADJACENT_FIND_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/ranges_all_of.h b/app/src/main/cpp/libcxx/include/__algorithm/ranges_all_of.h new file mode 100644 index 0000000..e45c4e5 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/ranges_all_of.h @@ -0,0 +1,68 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_RANGES_ALL_OF_H +#define _LIBCPP___ALGORITHM_RANGES_ALL_OF_H + +#include <__config> +#include <__functional/identity.h> +#include <__functional/invoke.h> +#include <__iterator/concepts.h> +#include <__iterator/projected.h> +#include <__ranges/access.h> +#include <__ranges/concepts.h> +#include <__utility/move.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if _LIBCPP_STD_VER > 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace ranges { +namespace __all_of { +struct __fn { + + template + _LIBCPP_HIDE_FROM_ABI constexpr static + bool __all_of_impl(_Iter __first, _Sent __last, _Pred& __pred, _Proj& __proj) { + for (; __first != __last; ++__first) { + if (!std::invoke(__pred, std::invoke(__proj, *__first))) + return false; + } + return true; + } + + template _Sent, class _Proj = identity, + indirect_unary_predicate> _Pred> + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr + bool operator()(_Iter __first, _Sent __last, _Pred __pred, _Proj __proj = {}) const { + return __all_of_impl(std::move(__first), std::move(__last), __pred, __proj); + } + + template , _Proj>> _Pred> + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr + bool operator()(_Range&& __range, _Pred __pred, _Proj __proj = {}) const { + return __all_of_impl(ranges::begin(__range), ranges::end(__range), __pred, __proj); + } +}; +} // namespace __all_of + +inline namespace __cpo { + inline constexpr auto all_of = __all_of::__fn{}; +} // namespace __cpo +} // namespace ranges + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER > 17 + +#endif // _LIBCPP___ALGORITHM_RANGES_ALL_OF_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/ranges_any_of.h b/app/src/main/cpp/libcxx/include/__algorithm/ranges_any_of.h new file mode 100644 index 0000000..e7d1e72 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/ranges_any_of.h @@ -0,0 +1,68 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_RANGES_ANY_OF_H +#define _LIBCPP___ALGORITHM_RANGES_ANY_OF_H + +#include <__config> +#include <__functional/identity.h> +#include <__functional/invoke.h> +#include <__iterator/concepts.h> +#include <__iterator/projected.h> +#include <__ranges/access.h> +#include <__ranges/concepts.h> +#include <__utility/move.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if _LIBCPP_STD_VER > 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace ranges { +namespace __any_of { +struct __fn { + + template + _LIBCPP_HIDE_FROM_ABI constexpr static + bool __any_of_impl(_Iter __first, _Sent __last, _Pred& __pred, _Proj& __proj) { + for (; __first != __last; ++__first) { + if (std::invoke(__pred, std::invoke(__proj, *__first))) + return true; + } + return false; + } + + template _Sent, class _Proj = identity, + indirect_unary_predicate> _Pred> + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr + bool operator()(_Iter __first, _Sent __last, _Pred __pred = {}, _Proj __proj = {}) const { + return __any_of_impl(std::move(__first), std::move(__last), __pred, __proj); + } + + template , _Proj>> _Pred> + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr + bool operator()(_Range&& __range, _Pred __pred, _Proj __proj = {}) const { + return __any_of_impl(ranges::begin(__range), ranges::end(__range), __pred, __proj); + } +}; +} // namespace __any_of + +inline namespace __cpo { + inline constexpr auto any_of = __any_of::__fn{}; +} // namespace __cpo +} // namespace ranges + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER > 17 + +#endif // _LIBCPP___ALGORITHM_RANGES_ANY_OF_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/ranges_binary_search.h b/app/src/main/cpp/libcxx/include/__algorithm/ranges_binary_search.h new file mode 100644 index 0000000..b2a8977 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/ranges_binary_search.h @@ -0,0 +1,63 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_RANGES_BINARY_SEARCH_H +#define _LIBCPP___ALGORITHM_RANGES_BINARY_SEARCH_H + +#include <__algorithm/iterator_operations.h> +#include <__algorithm/lower_bound.h> +#include <__config> +#include <__functional/identity.h> +#include <__functional/invoke.h> +#include <__functional/ranges_operations.h> +#include <__iterator/concepts.h> +#include <__iterator/projected.h> +#include <__ranges/access.h> +#include <__ranges/concepts.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if _LIBCPP_STD_VER > 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace ranges { +namespace __binary_search { +struct __fn { + template _Sent, class _Type, class _Proj = identity, + indirect_strict_weak_order> _Comp = ranges::less> + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr + bool operator()(_Iter __first, _Sent __last, const _Type& __value, _Comp __comp = {}, _Proj __proj = {}) const { + auto __ret = std::__lower_bound_impl<_RangeAlgPolicy>(__first, __last, __value, __comp, __proj); + return __ret != __last && !std::invoke(__comp, __value, std::invoke(__proj, *__first)); + } + + template , _Proj>> _Comp = ranges::less> + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr + bool operator()(_Range&& __r, const _Type& __value, _Comp __comp = {}, _Proj __proj = {}) const { + auto __first = ranges::begin(__r); + auto __last = ranges::end(__r); + auto __ret = std::__lower_bound_impl<_RangeAlgPolicy>(__first, __last, __value, __comp, __proj); + return __ret != __last && !std::invoke(__comp, __value, std::invoke(__proj, *__first)); + } +}; +} // namespace __binary_search + +inline namespace __cpo { + inline constexpr auto binary_search = __binary_search::__fn{}; +} // namespace __cpo +} // namespace ranges + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER > 17 + +#endif // _LIBCPP___ALGORITHM_RANGES_BINARY_SEARCH_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/ranges_clamp.h b/app/src/main/cpp/libcxx/include/__algorithm/ranges_clamp.h new file mode 100644 index 0000000..09a97fc --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/ranges_clamp.h @@ -0,0 +1,65 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_RANGES_CLAMP_H +#define _LIBCPP___ALGORITHM_RANGES_CLAMP_H + +#include <__assert> +#include <__config> +#include <__functional/identity.h> +#include <__functional/invoke.h> +#include <__functional/ranges_operations.h> +#include <__iterator/concepts.h> +#include <__iterator/projected.h> +#include <__utility/forward.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if _LIBCPP_STD_VER > 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace ranges { +namespace __clamp { +struct __fn { + + template > _Comp = ranges::less> + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr + const _Type& operator()(const _Type& __value, + const _Type& __low, + const _Type& __high, + _Comp __comp = {}, + _Proj __proj = {}) const { + _LIBCPP_ASSERT(!bool(std::invoke(__comp, std::invoke(__proj, __high), std::invoke(__proj, __low))), + "Bad bounds passed to std::ranges::clamp"); + + if (std::invoke(__comp, std::invoke(__proj, __value), std::invoke(__proj, __low))) + return __low; + else if (std::invoke(__comp, std::invoke(__proj, __high), std::invoke(__proj, __value))) + return __high; + else + return __value; + } + +}; +} // namespace __clamp + +inline namespace __cpo { + inline constexpr auto clamp = __clamp::__fn{}; +} // namespace __cpo +} // namespace ranges + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER > 17 + +#endif // _LIBCPP___ALGORITHM_RANGES_CLAMP_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/ranges_copy.h b/app/src/main/cpp/libcxx/include/__algorithm/ranges_copy.h new file mode 100644 index 0000000..bb02c84 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/ranges_copy.h @@ -0,0 +1,67 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_RANGES_COPY_H +#define _LIBCPP___ALGORITHM_RANGES_COPY_H + +#include <__algorithm/copy.h> +#include <__algorithm/in_out_result.h> +#include <__algorithm/iterator_operations.h> +#include <__config> +#include <__functional/identity.h> +#include <__iterator/concepts.h> +#include <__ranges/access.h> +#include <__ranges/concepts.h> +#include <__ranges/dangling.h> +#include <__utility/move.h> +#include <__utility/pair.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if _LIBCPP_STD_VER > 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace ranges { + +template +using copy_result = in_out_result<_InIter, _OutIter>; + +namespace __copy { +struct __fn { + + template _Sent, weakly_incrementable _OutIter> + requires indirectly_copyable<_InIter, _OutIter> + _LIBCPP_HIDE_FROM_ABI constexpr + copy_result<_InIter, _OutIter> operator()(_InIter __first, _Sent __last, _OutIter __result) const { + auto __ret = std::__copy<_RangeAlgPolicy>(std::move(__first), std::move(__last), std::move(__result)); + return {std::move(__ret.first), std::move(__ret.second)}; + } + + template + requires indirectly_copyable, _OutIter> + _LIBCPP_HIDE_FROM_ABI constexpr + copy_result, _OutIter> operator()(_Range&& __r, _OutIter __result) const { + auto __ret = std::__copy<_RangeAlgPolicy>(ranges::begin(__r), ranges::end(__r), std::move(__result)); + return {std::move(__ret.first), std::move(__ret.second)}; + } +}; +} // namespace __copy + +inline namespace __cpo { + inline constexpr auto copy = __copy::__fn{}; +} // namespace __cpo +} // namespace ranges + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER > 17 + +#endif // _LIBCPP___ALGORITHM_RANGES_COPY_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/ranges_copy_backward.h b/app/src/main/cpp/libcxx/include/__algorithm/ranges_copy_backward.h new file mode 100644 index 0000000..f41af66 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/ranges_copy_backward.h @@ -0,0 +1,65 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_RANGES_COPY_BACKWARD_H +#define _LIBCPP___ALGORITHM_RANGES_COPY_BACKWARD_H + +#include <__algorithm/copy_backward.h> +#include <__algorithm/in_out_result.h> +#include <__algorithm/iterator_operations.h> +#include <__config> +#include <__iterator/concepts.h> +#include <__ranges/access.h> +#include <__ranges/concepts.h> +#include <__ranges/dangling.h> +#include <__utility/move.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if _LIBCPP_STD_VER > 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace ranges { + +template +using copy_backward_result = in_out_result<_Ip, _Op>; + +namespace __copy_backward { +struct __fn { + + template _Sent1, bidirectional_iterator _InIter2> + requires indirectly_copyable<_InIter1, _InIter2> + _LIBCPP_HIDE_FROM_ABI constexpr + copy_backward_result<_InIter1, _InIter2> operator()(_InIter1 __first, _Sent1 __last, _InIter2 __result) const { + auto __ret = std::__copy_backward<_RangeAlgPolicy>(std::move(__first), std::move(__last), std::move(__result)); + return {std::move(__ret.first), std::move(__ret.second)}; + } + + template + requires indirectly_copyable, _Iter> + _LIBCPP_HIDE_FROM_ABI constexpr + copy_backward_result, _Iter> operator()(_Range&& __r, _Iter __result) const { + auto __ret = std::__copy_backward<_RangeAlgPolicy>(ranges::begin(__r), ranges::end(__r), std::move(__result)); + return {std::move(__ret.first), std::move(__ret.second)}; + } +}; +} // namespace __copy_backward + +inline namespace __cpo { + inline constexpr auto copy_backward = __copy_backward::__fn{}; +} // namespace __cpo +} // namespace ranges + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER > 17 + +#endif // _LIBCPP___ALGORITHM_RANGES_COPY_BACKWARD_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/ranges_copy_if.h b/app/src/main/cpp/libcxx/include/__algorithm/ranges_copy_if.h new file mode 100644 index 0000000..dba41c3 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/ranges_copy_if.h @@ -0,0 +1,81 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_RANGES_COPY_IF_H +#define _LIBCPP___ALGORITHM_RANGES_COPY_IF_H + +#include <__algorithm/in_out_result.h> +#include <__config> +#include <__functional/identity.h> +#include <__functional/invoke.h> +#include <__iterator/concepts.h> +#include <__iterator/projected.h> +#include <__ranges/access.h> +#include <__ranges/concepts.h> +#include <__ranges/dangling.h> +#include <__utility/move.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if _LIBCPP_STD_VER > 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace ranges { + +template +using copy_if_result = in_out_result<_Ip, _Op>; + +namespace __copy_if { +struct __fn { + + template + _LIBCPP_HIDE_FROM_ABI static constexpr + copy_if_result <_InIter, _OutIter> + __copy_if_impl(_InIter __first, _Sent __last, _OutIter __result, _Pred& __pred, _Proj& __proj) { + for (; __first != __last; ++__first) { + if (std::invoke(__pred, std::invoke(__proj, *__first))) { + *__result = *__first; + ++__result; + } + } + return {std::move(__first), std::move(__result)}; + } + + template _Sent, weakly_incrementable _OutIter, class _Proj = identity, + indirect_unary_predicate> _Pred> + requires indirectly_copyable<_Iter, _OutIter> + _LIBCPP_HIDE_FROM_ABI constexpr + copy_if_result<_Iter, _OutIter> + operator()(_Iter __first, _Sent __last, _OutIter __result, _Pred __pred, _Proj __proj = {}) const { + return __copy_if_impl(std::move(__first), std::move(__last), std::move(__result), __pred, __proj); + } + + template , _Proj>> _Pred> + requires indirectly_copyable, _OutIter> + _LIBCPP_HIDE_FROM_ABI constexpr + copy_if_result, _OutIter> + operator()(_Range&& __r, _OutIter __result, _Pred __pred, _Proj __proj = {}) const { + return __copy_if_impl(ranges::begin(__r), ranges::end(__r), std::move(__result), __pred, __proj); + } +}; +} // namespace __copy_if + +inline namespace __cpo { + inline constexpr auto copy_if = __copy_if::__fn{}; +} // namespace __cpo +} // namespace ranges + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER > 17 + +#endif // _LIBCPP___ALGORITHM_RANGES_COPY_IF_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/ranges_copy_n.h b/app/src/main/cpp/libcxx/include/__algorithm/ranges_copy_n.h new file mode 100644 index 0000000..04bb80b --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/ranges_copy_n.h @@ -0,0 +1,77 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_RANGES_COPY_N_H +#define _LIBCPP___ALGORITHM_RANGES_COPY_N_H + +#include <__algorithm/copy.h> +#include <__algorithm/in_out_result.h> +#include <__algorithm/iterator_operations.h> +#include <__algorithm/ranges_copy.h> +#include <__config> +#include <__functional/identity.h> +#include <__iterator/concepts.h> +#include <__iterator/incrementable_traits.h> +#include <__iterator/unreachable_sentinel.h> +#include <__iterator/wrap_iter.h> +#include <__utility/move.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 17 + +namespace ranges { + +template +using copy_n_result = in_out_result<_Ip, _Op>; + +namespace __copy_n { +struct __fn { + + template + _LIBCPP_HIDE_FROM_ABI constexpr static + copy_n_result<_InIter, _OutIter> __go(_InIter __first, _DiffType __n, _OutIter __result) { + while (__n != 0) { + *__result = *__first; + ++__first; + ++__result; + --__n; + } + return {std::move(__first), std::move(__result)}; + } + + template + _LIBCPP_HIDE_FROM_ABI constexpr static + copy_n_result<_InIter, _OutIter> __go(_InIter __first, _DiffType __n, _OutIter __result) { + auto __ret = std::__copy<_RangeAlgPolicy>(__first, __first + __n, __result); + return {__ret.first, __ret.second}; + } + + template + requires indirectly_copyable<_Ip, _Op> + _LIBCPP_HIDE_FROM_ABI constexpr + copy_n_result<_Ip, _Op> operator()(_Ip __first, iter_difference_t<_Ip> __n, _Op __result) const { + return __go(std::move(__first), __n, std::move(__result)); + } +}; +} // namespace __copy_n + +inline namespace __cpo { + inline constexpr auto copy_n = __copy_n::__fn{}; +} // namespace __cpo +} // namespace ranges + +#endif // _LIBCPP_STD_VER > 17 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ALGORITHM_RANGES_COPY_N_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/ranges_count.h b/app/src/main/cpp/libcxx/include/__algorithm/ranges_count.h new file mode 100644 index 0000000..527dd06 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/ranges_count.h @@ -0,0 +1,62 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_RANGES_COUNT_H +#define _LIBCPP___ALGORITHM_RANGES_COUNT_H + +#include <__algorithm/ranges_count_if.h> +#include <__config> +#include <__functional/identity.h> +#include <__functional/ranges_operations.h> +#include <__iterator/concepts.h> +#include <__iterator/incrementable_traits.h> +#include <__iterator/iterator_traits.h> +#include <__iterator/projected.h> +#include <__ranges/access.h> +#include <__ranges/concepts.h> +#include <__utility/move.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if _LIBCPP_STD_VER > 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace ranges { +namespace __count { +struct __fn { + template _Sent, class _Type, class _Proj = identity> + requires indirect_binary_predicate, const _Type*> + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr + iter_difference_t<_Iter> operator()(_Iter __first, _Sent __last, const _Type& __value, _Proj __proj = {}) const { + auto __pred = [&](auto&& __e) { return __e == __value; }; + return ranges::__count_if_impl(std::move(__first), std::move(__last), __pred, __proj); + } + + template + requires indirect_binary_predicate, _Proj>, const _Type*> + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr + range_difference_t<_Range> operator()(_Range&& __r, const _Type& __value, _Proj __proj = {}) const { + auto __pred = [&](auto&& __e) { return __e == __value; }; + return ranges::__count_if_impl(ranges::begin(__r), ranges::end(__r), __pred, __proj); + } +}; +} // namespace __count + +inline namespace __cpo { + inline constexpr auto count = __count::__fn{}; +} // namespace __cpo +} // namespace ranges + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER > 17 + +#endif // _LIBCPP___ALGORITHM_RANGES_COUNT_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/ranges_count_if.h b/app/src/main/cpp/libcxx/include/__algorithm/ranges_count_if.h new file mode 100644 index 0000000..931618b --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/ranges_count_if.h @@ -0,0 +1,72 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_RANGES_COUNT_IF_H +#define _LIBCPP___ALGORITHM_RANGES_COUNT_IF_H + +#include <__config> +#include <__functional/identity.h> +#include <__functional/invoke.h> +#include <__functional/ranges_operations.h> +#include <__iterator/concepts.h> +#include <__iterator/incrementable_traits.h> +#include <__iterator/iterator_traits.h> +#include <__iterator/projected.h> +#include <__ranges/access.h> +#include <__ranges/concepts.h> +#include <__utility/move.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if _LIBCPP_STD_VER > 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace ranges { +template +_LIBCPP_HIDE_FROM_ABI constexpr +iter_difference_t<_Iter> __count_if_impl(_Iter __first, _Sent __last, + _Pred& __pred, _Proj& __proj) { + iter_difference_t<_Iter> __counter(0); + for (; __first != __last; ++__first) { + if (std::invoke(__pred, std::invoke(__proj, *__first))) + ++__counter; + } + return __counter; +} + +namespace __count_if { +struct __fn { + template _Sent, class _Proj = identity, + indirect_unary_predicate> _Predicate> + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr + iter_difference_t<_Iter> operator()(_Iter __first, _Sent __last, _Predicate __pred, _Proj __proj = {}) const { + return ranges::__count_if_impl(std::move(__first), std::move(__last), __pred, __proj); + } + + template , _Proj>> _Predicate> + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr + range_difference_t<_Range> operator()(_Range&& __r, _Predicate __pred, _Proj __proj = {}) const { + return ranges::__count_if_impl(ranges::begin(__r), ranges::end(__r), __pred, __proj); + } +}; +} // namespace __count_if + +inline namespace __cpo { + inline constexpr auto count_if = __count_if::__fn{}; +} // namespace __cpo +} // namespace ranges + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER > 17 + +#endif // _LIBCPP___ALGORITHM_RANGES_COUNT_IF_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/ranges_equal.h b/app/src/main/cpp/libcxx/include/__algorithm/ranges_equal.h new file mode 100644 index 0000000..3c417f0 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/ranges_equal.h @@ -0,0 +1,115 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_RANGES_EQUAL_H +#define _LIBCPP___ALGORITHM_RANGES_EQUAL_H + +#include <__config> +#include <__functional/identity.h> +#include <__functional/invoke.h> +#include <__functional/ranges_operations.h> +#include <__iterator/concepts.h> +#include <__iterator/distance.h> +#include <__iterator/indirectly_comparable.h> +#include <__ranges/access.h> +#include <__ranges/concepts.h> +#include <__utility/move.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if _LIBCPP_STD_VER > 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace ranges { +namespace __equal { +struct __fn { +private: + template + _LIBCPP_HIDE_FROM_ABI constexpr static + bool __equal_impl(_Iter1 __first1, _Sent1 __last1, + _Iter2 __first2, _Sent2 __last2, + _Pred& __pred, + _Proj1& __proj1, + _Proj2& __proj2) { + while (__first1 != __last1 && __first2 != __last2) { + if (!std::invoke(__pred, std::invoke(__proj1, *__first1), std::invoke(__proj2, *__first2))) + return false; + ++__first1; + ++__first2; + } + return __first1 == __last1 && __first2 == __last2; + } + +public: + + template _Sent1, + input_iterator _Iter2, sentinel_for<_Iter2> _Sent2, + class _Pred = ranges::equal_to, + class _Proj1 = identity, + class _Proj2 = identity> + requires indirectly_comparable<_Iter1, _Iter2, _Pred, _Proj1, _Proj2> + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr + bool operator()(_Iter1 __first1, _Sent1 __last1, + _Iter2 __first2, _Sent2 __last2, + _Pred __pred = {}, + _Proj1 __proj1 = {}, + _Proj2 __proj2 = {}) const { + if constexpr (sized_sentinel_for<_Sent1, _Iter1> && sized_sentinel_for<_Sent2, _Iter2>) { + if (__last1 - __first1 != __last2 - __first2) + return false; + } + return __equal_impl(std::move(__first1), std::move(__last1), + std::move(__first2), std::move(__last2), + __pred, + __proj1, + __proj2); + } + + template + requires indirectly_comparable, iterator_t<_Range2>, _Pred, _Proj1, _Proj2> + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr + bool operator()(_Range1&& __range1, + _Range2&& __range2, + _Pred __pred = {}, + _Proj1 __proj1 = {}, + _Proj2 __proj2 = {}) const { + if constexpr (sized_range<_Range1> && sized_range<_Range2>) { + if (ranges::distance(__range1) != ranges::distance(__range2)) + return false; + } + return __equal_impl(ranges::begin(__range1), ranges::end(__range1), + ranges::begin(__range2), ranges::end(__range2), + __pred, + __proj1, + __proj2); + return false; + } +}; +} // namespace __equal + +inline namespace __cpo { + inline constexpr auto equal = __equal::__fn{}; +} // namespace __cpo +} // namespace ranges + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER > 17 + +#endif // _LIBCPP___ALGORITHM_RANGES_EQUAL_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/ranges_equal_range.h b/app/src/main/cpp/libcxx/include/__algorithm/ranges_equal_range.h new file mode 100644 index 0000000..94dc058 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/ranges_equal_range.h @@ -0,0 +1,78 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM __project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_RANGES_EQUAL_RANGE_H +#define _LIBCPP___ALGORITHM_RANGES_EQUAL_RANGE_H + +#include <__algorithm/equal_range.h> +#include <__algorithm/iterator_operations.h> +#include <__config> +#include <__functional/identity.h> +#include <__functional/invoke.h> +#include <__functional/ranges_operations.h> +#include <__iterator/concepts.h> +#include <__iterator/iterator_traits.h> +#include <__iterator/projected.h> +#include <__ranges/access.h> +#include <__ranges/concepts.h> +#include <__ranges/dangling.h> +#include <__ranges/subrange.h> +#include <__utility/forward.h> +#include <__utility/move.h> +#include <__utility/pair.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if _LIBCPP_STD_VER > 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace ranges { +namespace __equal_range { + +struct __fn { + template < + forward_iterator _Iter, + sentinel_for<_Iter> _Sent, + class _Tp, + class _Proj = identity, + indirect_strict_weak_order> _Comp = ranges::less> + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr subrange<_Iter> + operator()(_Iter __first, _Sent __last, const _Tp& __value, _Comp __comp = {}, _Proj __proj = {}) const { + auto __ret = std::__equal_range<_RangeAlgPolicy>( + std::move(__first), std::move(__last), __value, __comp, __proj); + return {std::move(__ret.first), std::move(__ret.second)}; + } + + template < + forward_range _Range, + class _Tp, + class _Proj = identity, + indirect_strict_weak_order, _Proj>> _Comp = ranges::less> + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr borrowed_subrange_t<_Range> + operator()(_Range&& __range, const _Tp& __value, _Comp __comp = {}, _Proj __proj = {}) const { + auto __ret = std::__equal_range<_RangeAlgPolicy>( + ranges::begin(__range), ranges::end(__range), __value, __comp, __proj); + return {std::move(__ret.first), std::move(__ret.second)}; + } +}; + +} // namespace __equal_range + +inline namespace __cpo { + inline constexpr auto equal_range = __equal_range::__fn{}; +} // namespace __cpo +} // namespace ranges + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER > 17 + +#endif // _LIBCPP___ALGORITHM_RANGES_EQUAL_RANGE_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/ranges_fill.h b/app/src/main/cpp/libcxx/include/__algorithm/ranges_fill.h new file mode 100644 index 0000000..6ebc2bd --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/ranges_fill.h @@ -0,0 +1,59 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_RANGES_FILL_H +#define _LIBCPP___ALGORITHM_RANGES_FILL_H + +#include <__algorithm/ranges_fill_n.h> +#include <__config> +#include <__iterator/concepts.h> +#include <__ranges/access.h> +#include <__ranges/concepts.h> +#include <__ranges/dangling.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if _LIBCPP_STD_VER > 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace ranges { +namespace __fill { +struct __fn { + template _Iter, sentinel_for<_Iter> _Sent> + _LIBCPP_HIDE_FROM_ABI constexpr + _Iter operator()(_Iter __first, _Sent __last, const _Type& __value) const { + if constexpr(random_access_iterator<_Iter> && sized_sentinel_for<_Sent, _Iter>) { + return ranges::fill_n(__first, __last - __first, __value); + } else { + for (; __first != __last; ++__first) + *__first = __value; + return __first; + } + } + + template _Range> + _LIBCPP_HIDE_FROM_ABI constexpr + borrowed_iterator_t<_Range> operator()(_Range&& __range, const _Type& __value) const { + return (*this)(ranges::begin(__range), ranges::end(__range), __value); + } +}; +} // namespace __fill + +inline namespace __cpo { + inline constexpr auto fill = __fill::__fn{}; +} // namespace __cpo +} // namespace ranges + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER > 17 + +#endif // _LIBCPP___ALGORITHM_RANGES_FILL_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/ranges_fill_n.h b/app/src/main/cpp/libcxx/include/__algorithm/ranges_fill_n.h new file mode 100644 index 0000000..a2660e8 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/ranges_fill_n.h @@ -0,0 +1,48 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_RANGES_FILL_N_H +#define _LIBCPP___ALGORITHM_RANGES_FILL_N_H + +#include <__config> +#include <__iterator/concepts.h> +#include <__iterator/incrementable_traits.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if _LIBCPP_STD_VER > 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace ranges { +namespace __fill_n { +struct __fn { + template _Iter> + _LIBCPP_HIDE_FROM_ABI constexpr + _Iter operator()(_Iter __first, iter_difference_t<_Iter> __n, const _Type& __value) const { + for (; __n != 0; --__n) { + *__first = __value; + ++__first; + } + return __first; + } +}; +} // namespace __fill_n + +inline namespace __cpo { + inline constexpr auto fill_n = __fill_n::__fn{}; +} // namespace __cpo +} // namespace ranges + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER > 17 + +#endif // _LIBCPP___ALGORITHM_RANGES_FILL_N_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/ranges_find.h b/app/src/main/cpp/libcxx/include/__algorithm/ranges_find.h new file mode 100644 index 0000000..580c2a1 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/ranges_find.h @@ -0,0 +1,63 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_RANGES_FIND_H +#define _LIBCPP___ALGORITHM_RANGES_FIND_H + +#include <__algorithm/ranges_find_if.h> +#include <__config> +#include <__functional/identity.h> +#include <__functional/invoke.h> +#include <__functional/ranges_operations.h> +#include <__iterator/concepts.h> +#include <__iterator/projected.h> +#include <__ranges/access.h> +#include <__ranges/concepts.h> +#include <__ranges/dangling.h> +#include <__utility/forward.h> +#include <__utility/move.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if _LIBCPP_STD_VER > 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace ranges { +namespace __find { +struct __fn { + template _Sp, class _Tp, class _Proj = identity> + requires indirect_binary_predicate, const _Tp*> + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr + _Ip operator()(_Ip __first, _Sp __last, const _Tp& __value, _Proj __proj = {}) const { + auto __pred = [&](auto&& __e) { return std::forward(__e) == __value; }; + return ranges::__find_if_impl(std::move(__first), std::move(__last), __pred, __proj); + } + + template + requires indirect_binary_predicate, _Proj>, const _Tp*> + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr + borrowed_iterator_t<_Rp> operator()(_Rp&& __r, const _Tp& __value, _Proj __proj = {}) const { + auto __pred = [&](auto&& __e) { return std::forward(__e) == __value; }; + return ranges::__find_if_impl(ranges::begin(__r), ranges::end(__r), __pred, __proj); + } +}; +} // namespace __find + +inline namespace __cpo { + inline constexpr auto find = __find::__fn{}; +} // namespace __cpo +} // namespace ranges + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER > 17 + +#endif // _LIBCPP___ALGORITHM_RANGES_FIND_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/ranges_find_end.h b/app/src/main/cpp/libcxx/include/__algorithm/ranges_find_end.h new file mode 100644 index 0000000..ea36f4d --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/ranges_find_end.h @@ -0,0 +1,98 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_RANGES_FIND_END_H +#define _LIBCPP___ALGORITHM_RANGES_FIND_END_H + +#include <__algorithm/find_end.h> +#include <__algorithm/iterator_operations.h> +#include <__algorithm/ranges_iterator_concept.h> +#include <__config> +#include <__functional/identity.h> +#include <__functional/ranges_operations.h> +#include <__iterator/concepts.h> +#include <__iterator/indirectly_comparable.h> +#include <__iterator/iterator_traits.h> +#include <__ranges/access.h> +#include <__ranges/concepts.h> +#include <__ranges/subrange.h> +#include <__utility/pair.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if _LIBCPP_STD_VER > 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace ranges { +namespace __find_end { +struct __fn { + template _Sent1, + forward_iterator _Iter2, sentinel_for<_Iter2> _Sent2, + class _Pred = ranges::equal_to, + class _Proj1 = identity, + class _Proj2 = identity> + requires indirectly_comparable<_Iter1, _Iter2, _Pred, _Proj1, _Proj2> + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr + subrange<_Iter1> operator()(_Iter1 __first1, _Sent1 __last1, + _Iter2 __first2, _Sent2 __last2, + _Pred __pred = {}, + _Proj1 __proj1 = {}, + _Proj2 __proj2 = {}) const { + auto __ret = std::__find_end_impl<_RangeAlgPolicy>( + __first1, + __last1, + __first2, + __last2, + __pred, + __proj1, + __proj2, + __iterator_concept<_Iter1>(), + __iterator_concept<_Iter2>()); + return {__ret.first, __ret.second}; + } + + template + requires indirectly_comparable, iterator_t<_Range2>, _Pred, _Proj1, _Proj2> + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr + borrowed_subrange_t<_Range1> operator()(_Range1&& __range1, + _Range2&& __range2, + _Pred __pred = {}, + _Proj1 __proj1 = {}, + _Proj2 __proj2 = {}) const { + auto __ret = std::__find_end_impl<_RangeAlgPolicy>( + ranges::begin(__range1), + ranges::end(__range1), + ranges::begin(__range2), + ranges::end(__range2), + __pred, + __proj1, + __proj2, + __iterator_concept>(), + __iterator_concept>()); + return {__ret.first, __ret.second}; + } +}; +} // namespace __find_end + +inline namespace __cpo { + inline constexpr auto find_end = __find_end::__fn{}; +} // namespace __cpo +} // namespace ranges + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER > 17 + +#endif // _LIBCPP___ALGORITHM_RANGES_FIND_END_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/ranges_find_first_of.h b/app/src/main/cpp/libcxx/include/__algorithm/ranges_find_first_of.h new file mode 100644 index 0000000..9d66e75 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/ranges_find_first_of.h @@ -0,0 +1,101 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_RANGES_FIND_FIRST_OF_H +#define _LIBCPP___ALGORITHM_RANGES_FIND_FIRST_OF_H + +#include <__config> +#include <__functional/identity.h> +#include <__functional/invoke.h> +#include <__functional/ranges_operations.h> +#include <__iterator/concepts.h> +#include <__iterator/indirectly_comparable.h> +#include <__ranges/access.h> +#include <__ranges/concepts.h> +#include <__ranges/dangling.h> +#include <__utility/move.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if _LIBCPP_STD_VER > 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace ranges { +namespace __find_first_of { +struct __fn { + + template + _LIBCPP_HIDE_FROM_ABI constexpr static + _Iter1 __find_first_of_impl(_Iter1 __first1, _Sent1 __last1, + _Iter2 __first2, _Sent2 __last2, + _Pred& __pred, + _Proj1& __proj1, + _Proj2& __proj2) { + for (; __first1 != __last1; ++__first1) { + for (auto __j = __first2; __j != __last2; ++__j) { + if (std::invoke(__pred, std::invoke(__proj1, *__first1), std::invoke(__proj2, *__j))) + return __first1; + } + } + return __first1; + } + + template _Sent1, + forward_iterator _Iter2, sentinel_for<_Iter2> _Sent2, + class _Pred = ranges::equal_to, + class _Proj1 = identity, + class _Proj2 = identity> + requires indirectly_comparable<_Iter1, _Iter2, _Pred, _Proj1, _Proj2> + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr + _Iter1 operator()(_Iter1 __first1, _Sent1 __last1, + _Iter2 __first2, _Sent2 __last2, + _Pred __pred = {}, + _Proj1 __proj1 = {}, + _Proj2 __proj2 = {}) const { + return __find_first_of_impl(std::move(__first1), std::move(__last1), + std::move(__first2), std::move(__last2), + __pred, + __proj1, + __proj2); + } + + template + requires indirectly_comparable, iterator_t<_Range2>, _Pred, _Proj1, _Proj2> + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr + borrowed_iterator_t<_Range1> operator()(_Range1&& __range1, + _Range2&& __range2, + _Pred __pred = {}, + _Proj1 __proj1 = {}, + _Proj2 __proj2 = {}) const { + return __find_first_of_impl(ranges::begin(__range1), ranges::end(__range1), + ranges::begin(__range2), ranges::end(__range2), + __pred, + __proj1, + __proj2); + } + +}; +} // namespace __find_first_of + +inline namespace __cpo { + inline constexpr auto find_first_of = __find_first_of::__fn{}; +} // namespace __cpo +} // namespace ranges + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER > 17 + +#endif // _LIBCPP___ALGORITHM_RANGES_FIND_FIRST_OF_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/ranges_find_if.h b/app/src/main/cpp/libcxx/include/__algorithm/ranges_find_if.h new file mode 100644 index 0000000..45ce6e4 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/ranges_find_if.h @@ -0,0 +1,71 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_RANGES_FIND_IF_H +#define _LIBCPP___ALGORITHM_RANGES_FIND_IF_H + +#include <__config> +#include <__functional/identity.h> +#include <__functional/invoke.h> +#include <__functional/ranges_operations.h> +#include <__iterator/concepts.h> +#include <__iterator/projected.h> +#include <__ranges/access.h> +#include <__ranges/concepts.h> +#include <__ranges/dangling.h> +#include <__utility/move.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if _LIBCPP_STD_VER > 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace ranges { + +template +_LIBCPP_HIDE_FROM_ABI static constexpr +_Ip __find_if_impl(_Ip __first, _Sp __last, _Pred& __pred, _Proj& __proj) { + for (; __first != __last; ++__first) { + if (std::invoke(__pred, std::invoke(__proj, *__first))) + break; + } + return __first; +} + +namespace __find_if { +struct __fn { + + template _Sp, class _Proj = identity, + indirect_unary_predicate> _Pred> + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr + _Ip operator()(_Ip __first, _Sp __last, _Pred __pred, _Proj __proj = {}) const { + return ranges::__find_if_impl(std::move(__first), std::move(__last), __pred, __proj); + } + + template , _Proj>> _Pred> + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr + borrowed_iterator_t<_Rp> operator()(_Rp&& __r, _Pred __pred, _Proj __proj = {}) const { + return ranges::__find_if_impl(ranges::begin(__r), ranges::end(__r), __pred, __proj); + } +}; +} // namespace __find_if + +inline namespace __cpo { + inline constexpr auto find_if = __find_if::__fn{}; +} // namespace __cpo +} // namespace ranges + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER > 17 + +#endif // _LIBCPP___ALGORITHM_RANGES_FIND_IF_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/ranges_find_if_not.h b/app/src/main/cpp/libcxx/include/__algorithm/ranges_find_if_not.h new file mode 100644 index 0000000..3dd1213 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/ranges_find_if_not.h @@ -0,0 +1,63 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_RANGES_FIND_IF_NOT_H +#define _LIBCPP___ALGORITHM_RANGES_FIND_IF_NOT_H + +#include <__algorithm/ranges_find_if.h> +#include <__config> +#include <__functional/identity.h> +#include <__functional/invoke.h> +#include <__functional/ranges_operations.h> +#include <__iterator/concepts.h> +#include <__iterator/projected.h> +#include <__ranges/access.h> +#include <__ranges/concepts.h> +#include <__ranges/dangling.h> +#include <__utility/forward.h> +#include <__utility/move.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if _LIBCPP_STD_VER > 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace ranges { +namespace __find_if_not { +struct __fn { + template _Sp, class _Proj = identity, + indirect_unary_predicate> _Pred> + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr + _Ip operator()(_Ip __first, _Sp __last, _Pred __pred, _Proj __proj = {}) const { + auto __pred2 = [&](auto&& __e) { return !std::invoke(__pred, std::forward(__e)); }; + return ranges::__find_if_impl(std::move(__first), std::move(__last), __pred2, __proj); + } + + template , _Proj>> _Pred> + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr + borrowed_iterator_t<_Rp> operator()(_Rp&& __r, _Pred __pred, _Proj __proj = {}) const { + auto __pred2 = [&](auto&& __e) { return !std::invoke(__pred, std::forward(__e)); }; + return ranges::__find_if_impl(ranges::begin(__r), ranges::end(__r), __pred2, __proj); + } +}; +} // namespace __find_if_not + +inline namespace __cpo { + inline constexpr auto find_if_not = __find_if_not::__fn{}; +} // namespace __cpo +} // namespace ranges + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER > 17 + +#endif // _LIBCPP___ALGORITHM_RANGES_FIND_IF_NOT_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/ranges_for_each.h b/app/src/main/cpp/libcxx/include/__algorithm/ranges_for_each.h new file mode 100644 index 0000000..0c70c05 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/ranges_for_each.h @@ -0,0 +1,78 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_RANGES_FOR_EACH_H +#define _LIBCPP___ALGORITHM_RANGES_FOR_EACH_H + +#include <__algorithm/in_fun_result.h> +#include <__config> +#include <__functional/identity.h> +#include <__functional/invoke.h> +#include <__iterator/concepts.h> +#include <__iterator/projected.h> +#include <__ranges/access.h> +#include <__ranges/concepts.h> +#include <__ranges/dangling.h> +#include <__utility/move.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if _LIBCPP_STD_VER > 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace ranges { + +template +using for_each_result = in_fun_result<_Iter, _Func>; + +namespace __for_each { +struct __fn { +private: + template + _LIBCPP_HIDE_FROM_ABI constexpr static + for_each_result<_Iter, _Func> __for_each_impl(_Iter __first, _Sent __last, _Func& __func, _Proj& __proj) { + for (; __first != __last; ++__first) + std::invoke(__func, std::invoke(__proj, *__first)); + return {std::move(__first), std::move(__func)}; + } + +public: + template _Sent, + class _Proj = identity, + indirectly_unary_invocable> _Func> + _LIBCPP_HIDE_FROM_ABI constexpr + for_each_result<_Iter, _Func> operator()(_Iter __first, _Sent __last, _Func __func, _Proj __proj = {}) const { + return __for_each_impl(std::move(__first), std::move(__last), __func, __proj); + } + + template , _Proj>> _Func> + _LIBCPP_HIDE_FROM_ABI constexpr + for_each_result, _Func> operator()(_Range&& __range, + _Func __func, + _Proj __proj = {}) const { + return __for_each_impl(ranges::begin(__range), ranges::end(__range), __func, __proj); + } + +}; +} // namespace __for_each + +inline namespace __cpo { + inline constexpr auto for_each = __for_each::__fn{}; +} // namespace __cpo +} // namespace ranges + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER > 17 + +#endif // _LIBCPP___ALGORITHM_RANGES_FOR_EACH_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/ranges_for_each_n.h b/app/src/main/cpp/libcxx/include/__algorithm/ranges_for_each_n.h new file mode 100644 index 0000000..261816a --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/ranges_for_each_n.h @@ -0,0 +1,66 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_RANGES_FOR_EACH_N_H +#define _LIBCPP___ALGORITHM_RANGES_FOR_EACH_N_H + +#include <__algorithm/in_fun_result.h> +#include <__config> +#include <__functional/identity.h> +#include <__functional/invoke.h> +#include <__iterator/concepts.h> +#include <__iterator/incrementable_traits.h> +#include <__iterator/iterator_traits.h> +#include <__iterator/projected.h> +#include <__ranges/concepts.h> +#include <__utility/move.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if _LIBCPP_STD_VER > 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace ranges { + +template +using for_each_n_result = in_fun_result<_Iter, _Func>; + +namespace __for_each_n { +struct __fn { + + template > _Func> + _LIBCPP_HIDE_FROM_ABI constexpr + for_each_n_result<_Iter, _Func> operator()(_Iter __first, + iter_difference_t<_Iter> __count, + _Func __func, + _Proj __proj = {}) const { + while (__count-- > 0) { + std::invoke(__func, std::invoke(__proj, *__first)); + ++__first; + } + return {std::move(__first), std::move(__func)}; + } + +}; +} // namespace __for_each_n + +inline namespace __cpo { + inline constexpr auto for_each_n = __for_each_n::__fn{}; +} // namespace __cpo +} // namespace ranges + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER > 17 + +#endif // _LIBCPP___ALGORITHM_RANGES_FOR_EACH_N_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/ranges_generate.h b/app/src/main/cpp/libcxx/include/__algorithm/ranges_generate.h new file mode 100644 index 0000000..ae486ae --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/ranges_generate.h @@ -0,0 +1,73 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_RANGES_GENERATE_H +#define _LIBCPP___ALGORITHM_RANGES_GENERATE_H + +#include <__concepts/constructible.h> +#include <__concepts/invocable.h> +#include <__config> +#include <__functional/invoke.h> +#include <__iterator/concepts.h> +#include <__iterator/iterator_traits.h> +#include <__ranges/access.h> +#include <__ranges/concepts.h> +#include <__ranges/dangling.h> +#include <__utility/move.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if _LIBCPP_STD_VER > 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace ranges { +namespace __generate { + +struct __fn { + + template + _LIBCPP_HIDE_FROM_ABI constexpr + static _OutIter __generate_fn_impl(_OutIter __first, _Sent __last, _Func& __gen) { + for (; __first != __last; ++__first) { + *__first = __gen(); + } + + return __first; + } + + template _Sent, copy_constructible _Func> + requires invocable<_Func&> && indirectly_writable<_OutIter, invoke_result_t<_Func&>> + _LIBCPP_HIDE_FROM_ABI constexpr + _OutIter operator()(_OutIter __first, _Sent __last, _Func __gen) const { + return __generate_fn_impl(std::move(__first), std::move(__last), __gen); + } + + template + requires invocable<_Func&> && output_range<_Range, invoke_result_t<_Func&>> + _LIBCPP_HIDE_FROM_ABI constexpr + borrowed_iterator_t<_Range> operator()(_Range&& __range, _Func __gen) const { + return __generate_fn_impl(ranges::begin(__range), ranges::end(__range), __gen); + } + +}; + +} // namespace __generate + +inline namespace __cpo { + inline constexpr auto generate = __generate::__fn{}; +} // namespace __cpo +} // namespace ranges + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER > 17 + +#endif // _LIBCPP___ALGORITHM_RANGES_GENERATE_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/ranges_generate_n.h b/app/src/main/cpp/libcxx/include/__algorithm/ranges_generate_n.h new file mode 100644 index 0000000..e625e3a --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/ranges_generate_n.h @@ -0,0 +1,62 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_RANGES_GENERATE_N_H +#define _LIBCPP___ALGORITHM_RANGES_GENERATE_N_H + +#include <__concepts/constructible.h> +#include <__concepts/invocable.h> +#include <__config> +#include <__functional/identity.h> +#include <__functional/invoke.h> +#include <__iterator/concepts.h> +#include <__iterator/incrementable_traits.h> +#include <__iterator/iterator_traits.h> +#include <__ranges/access.h> +#include <__ranges/concepts.h> +#include <__utility/move.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if _LIBCPP_STD_VER > 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace ranges { +namespace __generate_n { + +struct __fn { + + template + requires invocable<_Func&> && indirectly_writable<_OutIter, invoke_result_t<_Func&>> + _LIBCPP_HIDE_FROM_ABI constexpr + _OutIter operator()(_OutIter __first, iter_difference_t<_OutIter> __n, _Func __gen) const { + for (; __n > 0; --__n) { + *__first = __gen(); + ++__first; + } + + return __first; + } + +}; + +} // namespace __generate_n + +inline namespace __cpo { + inline constexpr auto generate_n = __generate_n::__fn{}; +} // namespace __cpo +} // namespace ranges + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER > 17 + +#endif // _LIBCPP___ALGORITHM_RANGES_GENERATE_N_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/ranges_includes.h b/app/src/main/cpp/libcxx/include/__algorithm/ranges_includes.h new file mode 100644 index 0000000..8438117 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/ranges_includes.h @@ -0,0 +1,95 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_RANGES_INCLUDES_H +#define _LIBCPP___ALGORITHM_RANGES_INCLUDES_H + +#include <__algorithm/includes.h> +#include <__algorithm/make_projected.h> +#include <__config> +#include <__functional/identity.h> +#include <__functional/invoke.h> +#include <__functional/ranges_operations.h> +#include <__iterator/concepts.h> +#include <__iterator/iterator_traits.h> +#include <__iterator/projected.h> +#include <__ranges/access.h> +#include <__ranges/concepts.h> +#include <__utility/forward.h> +#include <__utility/move.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if _LIBCPP_STD_VER > 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace ranges { +namespace __includes { + +struct __fn { + template < + input_iterator _Iter1, + sentinel_for<_Iter1> _Sent1, + input_iterator _Iter2, + sentinel_for<_Iter2> _Sent2, + class _Proj1 = identity, + class _Proj2 = identity, + indirect_strict_weak_order, projected<_Iter2, _Proj2>> _Comp = ranges::less> + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr bool operator()( + _Iter1 __first1, + _Sent1 __last1, + _Iter2 __first2, + _Sent2 __last2, + _Comp __comp = {}, + _Proj1 __proj1 = {}, + _Proj2 __proj2 = {}) const { + return std::__includes( + std::move(__first1), + std::move(__last1), + std::move(__first2), + std::move(__last2), + std::move(__comp), + std::move(__proj1), + std::move(__proj2)); + } + + template < + input_range _Range1, + input_range _Range2, + class _Proj1 = identity, + class _Proj2 = identity, + indirect_strict_weak_order, _Proj1>, projected, _Proj2>> + _Comp = ranges::less> + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr bool operator()( + _Range1&& __range1, _Range2&& __range2, _Comp __comp = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const { + return std::__includes( + ranges::begin(__range1), + ranges::end(__range1), + ranges::begin(__range2), + ranges::end(__range2), + std::move(__comp), + std::move(__proj1), + std::move(__proj2)); + } +}; + +} // namespace __includes + +inline namespace __cpo { + inline constexpr auto includes = __includes::__fn{}; +} // namespace __cpo +} // namespace ranges + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER > 17 + +#endif // _LIBCPP___ALGORITHM_RANGES_INCLUDES_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/ranges_inplace_merge.h b/app/src/main/cpp/libcxx/include/__algorithm/ranges_inplace_merge.h new file mode 100644 index 0000000..88171a6 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/ranges_inplace_merge.h @@ -0,0 +1,85 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_RANGES_INPLACE_MERGE_H +#define _LIBCPP___ALGORITHM_RANGES_INPLACE_MERGE_H + +#include <__algorithm/inplace_merge.h> +#include <__algorithm/iterator_operations.h> +#include <__algorithm/make_projected.h> +#include <__config> +#include <__functional/identity.h> +#include <__functional/invoke.h> +#include <__functional/ranges_operations.h> +#include <__iterator/concepts.h> +#include <__iterator/iterator_traits.h> +#include <__iterator/next.h> +#include <__iterator/projected.h> +#include <__iterator/sortable.h> +#include <__ranges/access.h> +#include <__ranges/concepts.h> +#include <__ranges/dangling.h> +#include <__utility/forward.h> +#include <__utility/move.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if _LIBCPP_STD_VER > 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace ranges { +namespace __inplace_merge { + + struct __fn { + template + _LIBCPP_HIDE_FROM_ABI static constexpr auto + __inplace_merge_impl(_Iter __first, _Iter __middle, _Sent __last, _Comp&& __comp, _Proj&& __proj) { + auto __last_iter = ranges::next(__middle, __last); + std::__inplace_merge<_RangeAlgPolicy>( + std::move(__first), std::move(__middle), __last_iter, std::__make_projected(__comp, __proj)); + return __last_iter; + } + + template < + bidirectional_iterator _Iter, + sentinel_for<_Iter> _Sent, + class _Comp = ranges::less, + class _Proj = identity> + requires sortable<_Iter, _Comp, _Proj> + _LIBCPP_HIDE_FROM_ABI _Iter + operator()(_Iter __first, _Iter __middle, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) const { + return __inplace_merge_impl( + std::move(__first), std::move(__middle), std::move(__last), std::move(__comp), std::move(__proj)); + } + + template + requires sortable< + iterator_t<_Range>, + _Comp, + _Proj> _LIBCPP_HIDE_FROM_ABI borrowed_iterator_t<_Range> + operator()(_Range&& __range, iterator_t<_Range> __middle, _Comp __comp = {}, _Proj __proj = {}) const { + return __inplace_merge_impl( + ranges::begin(__range), std::move(__middle), ranges::end(__range), std::move(__comp), std::move(__proj)); + } + }; + +} // namespace __inplace_merge + +inline namespace __cpo { + inline constexpr auto inplace_merge = __inplace_merge::__fn{}; +} // namespace __cpo +} // namespace ranges + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER > 17 + +#endif // _LIBCPP___ALGORITHM_RANGES_INPLACE_MERGE_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/ranges_is_heap.h b/app/src/main/cpp/libcxx/include/__algorithm/ranges_is_heap.h new file mode 100644 index 0000000..a16c075 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/ranges_is_heap.h @@ -0,0 +1,74 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_RANGES_IS_HEAP_H +#define _LIBCPP___ALGORITHM_RANGES_IS_HEAP_H + +#include <__algorithm/is_heap_until.h> +#include <__algorithm/make_projected.h> +#include <__config> +#include <__functional/identity.h> +#include <__functional/ranges_operations.h> +#include <__iterator/concepts.h> +#include <__iterator/iterator_traits.h> +#include <__iterator/next.h> +#include <__iterator/projected.h> +#include <__ranges/access.h> +#include <__ranges/concepts.h> +#include <__utility/move.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if _LIBCPP_STD_VER > 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace ranges { +namespace __is_heap { + +struct __fn { + + template + _LIBCPP_HIDE_FROM_ABI constexpr + static bool __is_heap_fn_impl(_Iter __first, _Sent __last, _Comp& __comp, _Proj& __proj) { + auto __last_iter = ranges::next(__first, __last); + auto&& __projected_comp = std::__make_projected(__comp, __proj); + + auto __result = std::__is_heap_until(std::move(__first), std::move(__last_iter), __projected_comp); + return __result == __last; + } + + template _Sent, class _Proj = identity, + indirect_strict_weak_order> _Comp = ranges::less> + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr + bool operator()(_Iter __first, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) const { + return __is_heap_fn_impl(std::move(__first), std::move(__last), __comp, __proj); + } + + template , _Proj>> _Comp = ranges::less> + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr + bool operator()(_Range&& __range, _Comp __comp = {}, _Proj __proj = {}) const { + return __is_heap_fn_impl(ranges::begin(__range), ranges::end(__range), __comp, __proj); + } +}; + +} // namespace __is_heap + +inline namespace __cpo { + inline constexpr auto is_heap = __is_heap::__fn{}; +} // namespace __cpo +} // namespace ranges + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER > 17 + +#endif // _LIBCPP___ALGORITHM_RANGES_IS_HEAP_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/ranges_is_heap_until.h b/app/src/main/cpp/libcxx/include/__algorithm/ranges_is_heap_until.h new file mode 100644 index 0000000..8c8dac5 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/ranges_is_heap_until.h @@ -0,0 +1,75 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_RANGES_IS_HEAP_UNTIL_H +#define _LIBCPP___ALGORITHM_RANGES_IS_HEAP_UNTIL_H + +#include <__algorithm/is_heap_until.h> +#include <__algorithm/make_projected.h> +#include <__config> +#include <__functional/identity.h> +#include <__functional/ranges_operations.h> +#include <__iterator/concepts.h> +#include <__iterator/iterator_traits.h> +#include <__iterator/next.h> +#include <__iterator/projected.h> +#include <__ranges/access.h> +#include <__ranges/concepts.h> +#include <__ranges/dangling.h> +#include <__utility/move.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if _LIBCPP_STD_VER > 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace ranges { +namespace __is_heap_until { + +struct __fn { + + template + _LIBCPP_HIDE_FROM_ABI constexpr + static _Iter __is_heap_until_fn_impl(_Iter __first, _Sent __last, _Comp& __comp, _Proj& __proj) { + auto __last_iter = ranges::next(__first, __last); + auto&& __projected_comp = std::__make_projected(__comp, __proj); + + return std::__is_heap_until(std::move(__first), std::move(__last_iter), __projected_comp); + } + + template _Sent, class _Proj = identity, + indirect_strict_weak_order> _Comp = ranges::less> + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr + _Iter operator()(_Iter __first, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) const { + return __is_heap_until_fn_impl(std::move(__first), std::move(__last), __comp, __proj); + } + + template , _Proj>> _Comp = ranges::less> + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr + borrowed_iterator_t<_Range> operator()(_Range&& __range, _Comp __comp = {}, _Proj __proj = {}) const { + return __is_heap_until_fn_impl(ranges::begin(__range), ranges::end(__range), __comp, __proj); + } + +}; + +} // namespace __is_heap_until + +inline namespace __cpo { + inline constexpr auto is_heap_until = __is_heap_until::__fn{}; +} // namespace __cpo +} // namespace ranges + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER > 17 + +#endif // _LIBCPP___ALGORITHM_RANGES_IS_HEAP_UNTIL_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/ranges_is_partitioned.h b/app/src/main/cpp/libcxx/include/__algorithm/ranges_is_partitioned.h new file mode 100644 index 0000000..b903953 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/ranges_is_partitioned.h @@ -0,0 +1,81 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_RANGES_IS_PARTITIONED_H +#define _LIBCPP___ALGORITHM_RANGES_IS_PARTITIONED_H + +#include <__config> +#include <__functional/identity.h> +#include <__functional/invoke.h> +#include <__iterator/concepts.h> +#include <__iterator/indirectly_comparable.h> +#include <__iterator/projected.h> +#include <__ranges/access.h> +#include <__ranges/concepts.h> +#include <__utility/move.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if _LIBCPP_STD_VER > 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace ranges { +namespace __is_partitioned { +struct __fn { + + template + _LIBCPP_HIDE_FROM_ABI constexpr static + bool __is_parititioned_impl(_Iter __first, _Sent __last, _Pred& __pred, _Proj& __proj) { + for (; __first != __last; ++__first) { + if (!std::invoke(__pred, std::invoke(__proj, *__first))) + break; + } + + if (__first == __last) + return true; + ++__first; + + for (; __first != __last; ++__first) { + if (std::invoke(__pred, std::invoke(__proj, *__first))) + return false; + } + + return true; + } + + template _Sent, + class _Proj = identity, + indirect_unary_predicate> _Pred> + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr + bool operator()(_Iter __first, _Sent __last, _Pred __pred, _Proj __proj = {}) const { + return __is_parititioned_impl(std::move(__first), std::move(__last), __pred, __proj); + } + + template , _Proj>> _Pred> + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr + bool operator()(_Range&& __range, _Pred __pred, _Proj __proj = {}) const { + return __is_parititioned_impl(ranges::begin(__range), ranges::end(__range), __pred, __proj); + } +}; +} // namespace __is_partitioned + +inline namespace __cpo { + inline constexpr auto is_partitioned = __is_partitioned::__fn{}; +} // namespace __cpo +} // namespace ranges + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER > 17 + +#endif // _LIBCPP___ALGORITHM_RANGES_IS_PARTITIONED_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/ranges_is_permutation.h b/app/src/main/cpp/libcxx/include/__algorithm/ranges_is_permutation.h new file mode 100644 index 0000000..b617500 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/ranges_is_permutation.h @@ -0,0 +1,89 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_RANGES_IS_PERMUTATION_H +#define _LIBCPP___ALGORITHM_RANGES_IS_PERMUTATION_H + +#include <__algorithm/is_permutation.h> +#include <__algorithm/iterator_operations.h> +#include <__config> +#include <__functional/identity.h> +#include <__functional/ranges_operations.h> +#include <__iterator/concepts.h> +#include <__iterator/distance.h> +#include <__iterator/projected.h> +#include <__ranges/access.h> +#include <__ranges/concepts.h> +#include <__utility/move.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if _LIBCPP_STD_VER > 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace ranges { +namespace __is_permutation { +struct __fn { + + template + _LIBCPP_HIDE_FROM_ABI constexpr static + bool __is_permutation_func_impl(_Iter1 __first1, _Sent1 __last1, _Iter2 __first2, _Sent2 __last2, + _Pred& __pred, _Proj1& __proj1, _Proj2& __proj2) { + return std::__is_permutation<_RangeAlgPolicy>( + std::move(__first1), std::move(__last1), std::move(__first2), std::move(__last2), + __pred, __proj1, __proj2); + } + + template _Sent1, + forward_iterator _Iter2, sentinel_for<_Iter2> _Sent2, + class _Proj1 = identity, + class _Proj2 = identity, + indirect_equivalence_relation, + projected<_Iter2, _Proj2>> _Pred = ranges::equal_to> + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr + bool operator()(_Iter1 __first1, _Sent1 __last1, _Iter2 __first2, _Sent2 __last2, + _Pred __pred = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const { + return __is_permutation_func_impl( + std::move(__first1), std::move(__last1), std::move(__first2), std::move(__last2), + __pred, __proj1, __proj2); + } + + template , _Proj1>, projected, _Proj2>> _Pred = ranges::equal_to> + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr + bool operator()(_Range1&& __range1, _Range2&& __range2, + _Pred __pred = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const { + if constexpr (sized_range<_Range1> && sized_range<_Range2>) { + if (ranges::distance(__range1) != ranges::distance(__range2)) + return false; + } + + return __is_permutation_func_impl( + ranges::begin(__range1), ranges::end(__range1), ranges::begin(__range2), ranges::end(__range2), + __pred, __proj1, __proj2); + } +}; +} // namespace __is_permutation + +inline namespace __cpo { + inline constexpr auto is_permutation = __is_permutation::__fn{}; +} // namespace __cpo +} // namespace ranges + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER > 17 + +#endif // _LIBCPP___ALGORITHM_RANGES_IS_PERMUTATION_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/ranges_is_sorted.h b/app/src/main/cpp/libcxx/include/__algorithm/ranges_is_sorted.h new file mode 100644 index 0000000..ce3032f --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/ranges_is_sorted.h @@ -0,0 +1,61 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP__ALGORITHM_RANGES_IS_SORTED_H +#define _LIBCPP__ALGORITHM_RANGES_IS_SORTED_H + +#include <__algorithm/ranges_is_sorted_until.h> +#include <__config> +#include <__functional/identity.h> +#include <__functional/ranges_operations.h> +#include <__iterator/concepts.h> +#include <__iterator/projected.h> +#include <__ranges/access.h> +#include <__ranges/concepts.h> +#include <__utility/move.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if _LIBCPP_STD_VER > 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace ranges { +namespace __is_sorted { +struct __fn { + template _Sent, + class _Proj = identity, + indirect_strict_weak_order> _Comp = ranges::less> + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr + bool operator()(_Iter __first, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) const { + return ranges::__is_sorted_until_impl(std::move(__first), __last, __comp, __proj) == __last; + } + + template , _Proj>> _Comp = ranges::less> + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr + bool operator()(_Range&& __range, _Comp __comp = {}, _Proj __proj = {}) const { + auto __last = ranges::end(__range); + return ranges::__is_sorted_until_impl(ranges::begin(__range), __last, __comp, __proj) == __last; + } +}; +} // namespace __is_sorted + +inline namespace __cpo { + inline constexpr auto is_sorted = __is_sorted::__fn{}; +} // namespace __cpo +} // namespace ranges + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER > 17 + +#endif // _LIBCPP__ALGORITHM_RANGES_IS_SORTED_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/ranges_is_sorted_until.h b/app/src/main/cpp/libcxx/include/__algorithm/ranges_is_sorted_until.h new file mode 100644 index 0000000..17fc42e --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/ranges_is_sorted_until.h @@ -0,0 +1,76 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP__ALGORITHM_RANGES_IS_SORTED_UNTIL_H +#define _LIBCPP__ALGORITHM_RANGES_IS_SORTED_UNTIL_H + +#include <__config> +#include <__functional/identity.h> +#include <__functional/invoke.h> +#include <__functional/ranges_operations.h> +#include <__iterator/concepts.h> +#include <__iterator/projected.h> +#include <__ranges/access.h> +#include <__ranges/concepts.h> +#include <__ranges/dangling.h> +#include <__utility/move.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if _LIBCPP_STD_VER > 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace ranges { + +template +_LIBCPP_HIDE_FROM_ABI constexpr +_Iter __is_sorted_until_impl(_Iter __first, _Sent __last, _Comp& __comp, _Proj& __proj) { + if (__first == __last) + return __first; + auto __i = __first; + while (++__i != __last) { + if (std::invoke(__comp, std::invoke(__proj, *__i), std::invoke(__proj, *__first))) + return __i; + __first = __i; + } + return __i; +} + +namespace __is_sorted_until { +struct __fn { + template _Sent, + class _Proj = identity, + indirect_strict_weak_order> _Comp = ranges::less> + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr + _Iter operator()(_Iter __first, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) const { + return ranges::__is_sorted_until_impl(std::move(__first), std::move(__last), __comp, __proj); + } + + template , _Proj>> _Comp = ranges::less> + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr + borrowed_iterator_t<_Range> operator()(_Range&& __range, _Comp __comp = {}, _Proj __proj = {}) const { + return ranges::__is_sorted_until_impl(ranges::begin(__range), ranges::end(__range), __comp, __proj); + } +}; +} // namespace __is_sorted_until + +inline namespace __cpo { + inline constexpr auto is_sorted_until = __is_sorted_until::__fn{}; +} // namespace __cpo +} // namespace ranges + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER > 17 + +#endif // _LIBCPP__ALGORITHM_RANGES_IS_SORTED_UNTIL_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/ranges_iterator_concept.h b/app/src/main/cpp/libcxx/include/__algorithm/ranges_iterator_concept.h new file mode 100644 index 0000000..3ac6b31 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/ranges_iterator_concept.h @@ -0,0 +1,51 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_RANGES_ITERATOR_CONCEPT_H +#define _LIBCPP___ALGORITHM_RANGES_ITERATOR_CONCEPT_H + +#include <__config> +#include <__iterator/concepts.h> +#include <__iterator/iterator_traits.h> +#include <__type_traits/remove_cvref.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if _LIBCPP_STD_VER > 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace ranges { + +template +consteval auto __get_iterator_concept() { + using _Iter = __remove_cvref_t<_IterMaybeQualified>; + + if constexpr (contiguous_iterator<_Iter>) + return contiguous_iterator_tag(); + else if constexpr (random_access_iterator<_Iter>) + return random_access_iterator_tag(); + else if constexpr (bidirectional_iterator<_Iter>) + return bidirectional_iterator_tag(); + else if constexpr (forward_iterator<_Iter>) + return forward_iterator_tag(); + else if constexpr (input_iterator<_Iter>) + return input_iterator_tag(); +} + +template +using __iterator_concept = decltype(__get_iterator_concept<_Iter>()); + +} // namespace ranges +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER > 17 + +#endif // _LIBCPP___ALGORITHM_RANGES_ITERATOR_CONCEPT_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/ranges_lexicographical_compare.h b/app/src/main/cpp/libcxx/include/__algorithm/ranges_lexicographical_compare.h new file mode 100644 index 0000000..2972e32 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/ranges_lexicographical_compare.h @@ -0,0 +1,98 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_RANGES_LEXICOGRAPHICAL_COMPARE_H +#define _LIBCPP___ALGORITHM_RANGES_LEXICOGRAPHICAL_COMPARE_H + +#include <__config> +#include <__functional/identity.h> +#include <__functional/invoke.h> +#include <__functional/ranges_operations.h> +#include <__iterator/concepts.h> +#include <__iterator/projected.h> +#include <__ranges/access.h> +#include <__ranges/concepts.h> +#include <__utility/move.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if _LIBCPP_STD_VER > 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace ranges { +namespace __lexicographical_compare { +struct __fn { + + template + _LIBCPP_HIDE_FROM_ABI constexpr static + bool __lexicographical_compare_impl(_Iter1 __first1, _Sent1 __last1, + _Iter2 __first2, _Sent2 __last2, + _Comp& __comp, + _Proj1& __proj1, + _Proj2& __proj2) { + while (__first2 != __last2) { + if (__first1 == __last1 + || std::invoke(__comp, std::invoke(__proj1, *__first1), std::invoke(__proj2, *__first2))) + return true; + if (std::invoke(__comp, std::invoke(__proj2, *__first2), std::invoke(__proj1, *__first1))) + return false; + ++__first1; + ++__first2; + } + return false; + } + + template _Sent1, + input_iterator _Iter2, sentinel_for<_Iter2> _Sent2, + class _Proj1 = identity, + class _Proj2 = identity, + indirect_strict_weak_order, projected<_Iter2, _Proj2>> _Comp = ranges::less> + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr + bool operator()(_Iter1 __first1, _Sent1 __last1, + _Iter2 __first2, _Sent2 __last2, + _Comp __comp = {}, + _Proj1 __proj1 = {}, + _Proj2 __proj2 = {}) const { + return __lexicographical_compare_impl(std::move(__first1), std::move(__last1), + std::move(__first2), std::move(__last2), + __comp, + __proj1, + __proj2); + } + + template , _Proj1>, + projected, _Proj2>> _Comp = ranges::less> + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr + bool operator()(_Range1&& __range1, _Range2&& __range2, _Comp __comp = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const { + return __lexicographical_compare_impl(ranges::begin(__range1), ranges::end(__range1), + ranges::begin(__range2), ranges::end(__range2), + __comp, + __proj1, + __proj2); + } + +}; +} // namespace __lexicographical_compare + +inline namespace __cpo { + inline constexpr auto lexicographical_compare = __lexicographical_compare::__fn{}; +} // namespace __cpo +} // namespace ranges + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER > 17 + +#endif // _LIBCPP___ALGORITHM_RANGES_LEXICOGRAPHICAL_COMPARE_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/ranges_lower_bound.h b/app/src/main/cpp/libcxx/include/__algorithm/ranges_lower_bound.h new file mode 100644 index 0000000..78cbb6d --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/ranges_lower_bound.h @@ -0,0 +1,66 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_RANGES_LOWER_BOUND_H +#define _LIBCPP___ALGORITHM_RANGES_LOWER_BOUND_H + +#include <__algorithm/iterator_operations.h> +#include <__algorithm/lower_bound.h> +#include <__config> +#include <__functional/identity.h> +#include <__functional/invoke.h> +#include <__functional/ranges_operations.h> +#include <__iterator/advance.h> +#include <__iterator/concepts.h> +#include <__iterator/iterator_traits.h> +#include <__iterator/projected.h> +#include <__ranges/access.h> +#include <__ranges/concepts.h> +#include <__ranges/dangling.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if _LIBCPP_STD_VER > 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace ranges { + +namespace __lower_bound { +struct __fn { + template _Sent, class _Type, class _Proj = identity, + indirect_strict_weak_order> _Comp = ranges::less> + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr + _Iter operator()(_Iter __first, _Sent __last, const _Type& __value, _Comp __comp = {}, _Proj __proj = {}) const { + return std::__lower_bound_impl<_RangeAlgPolicy>(__first, __last, __value, __comp, __proj); + } + + template , _Proj>> _Comp = ranges::less> + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr + borrowed_iterator_t<_Range> operator()(_Range&& __r, + const _Type& __value, + _Comp __comp = {}, + _Proj __proj = {}) const { + return std::__lower_bound_impl<_RangeAlgPolicy>(ranges::begin(__r), ranges::end(__r), __value, __comp, __proj); + } +}; +} // namespace __lower_bound + +inline namespace __cpo { + inline constexpr auto lower_bound = __lower_bound::__fn{}; +} // namespace __cpo +} // namespace ranges + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER > 17 + +#endif // _LIBCPP___ALGORITHM_RANGES_LOWER_BOUND_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/ranges_make_heap.h b/app/src/main/cpp/libcxx/include/__algorithm/ranges_make_heap.h new file mode 100644 index 0000000..f25c7ab --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/ranges_make_heap.h @@ -0,0 +1,80 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_RANGES_MAKE_HEAP_H +#define _LIBCPP___ALGORITHM_RANGES_MAKE_HEAP_H + +#include <__algorithm/iterator_operations.h> +#include <__algorithm/make_heap.h> +#include <__algorithm/make_projected.h> +#include <__concepts/same_as.h> +#include <__config> +#include <__functional/identity.h> +#include <__functional/invoke.h> +#include <__functional/ranges_operations.h> +#include <__iterator/concepts.h> +#include <__iterator/iterator_traits.h> +#include <__iterator/next.h> +#include <__iterator/projected.h> +#include <__iterator/sortable.h> +#include <__ranges/access.h> +#include <__ranges/concepts.h> +#include <__ranges/dangling.h> +#include <__utility/forward.h> +#include <__utility/move.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if _LIBCPP_STD_VER > 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace ranges { +namespace __make_heap { + +struct __fn { + template + _LIBCPP_HIDE_FROM_ABI constexpr static + _Iter __make_heap_fn_impl(_Iter __first, _Sent __last, _Comp& __comp, _Proj& __proj) { + auto __last_iter = ranges::next(__first, __last); + + auto&& __projected_comp = std::__make_projected(__comp, __proj); + std::__make_heap<_RangeAlgPolicy>(std::move(__first), __last_iter, __projected_comp); + + return __last_iter; + } + + template _Sent, class _Comp = ranges::less, class _Proj = identity> + requires sortable<_Iter, _Comp, _Proj> + _LIBCPP_HIDE_FROM_ABI constexpr + _Iter operator()(_Iter __first, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) const { + return __make_heap_fn_impl(std::move(__first), std::move(__last), __comp, __proj); + } + + template + requires sortable, _Comp, _Proj> + _LIBCPP_HIDE_FROM_ABI constexpr + borrowed_iterator_t<_Range> operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const { + return __make_heap_fn_impl(ranges::begin(__r), ranges::end(__r), __comp, __proj); + } +}; + +} // namespace __make_heap + +inline namespace __cpo { + inline constexpr auto make_heap = __make_heap::__fn{}; +} // namespace __cpo +} // namespace ranges + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER > 17 + +#endif // _LIBCPP___ALGORITHM_RANGES_MAKE_HEAP_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/ranges_max.h b/app/src/main/cpp/libcxx/include/__algorithm/ranges_max.h new file mode 100644 index 0000000..55aef99 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/ranges_max.h @@ -0,0 +1,93 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_RANGES_MAX_H +#define _LIBCPP___ALGORITHM_RANGES_MAX_H + +#include <__algorithm/ranges_min_element.h> +#include <__assert> +#include <__concepts/copyable.h> +#include <__config> +#include <__functional/identity.h> +#include <__functional/invoke.h> +#include <__functional/ranges_operations.h> +#include <__iterator/concepts.h> +#include <__iterator/projected.h> +#include <__ranges/access.h> +#include <__ranges/concepts.h> +#include <__utility/move.h> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if _LIBCPP_STD_VER > 17 + +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace ranges { +namespace __max { +struct __fn { + template > _Comp = ranges::less> + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr + const _Tp& operator()(const _Tp& __a, const _Tp& __b, _Comp __comp = {}, _Proj __proj = {}) const { + return std::invoke(__comp, std::invoke(__proj, __a), std::invoke(__proj, __b)) ? __b : __a; + } + + template > _Comp = ranges::less> + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr + _Tp operator()(initializer_list<_Tp> __il, _Comp __comp = {}, _Proj __proj = {}) const { + _LIBCPP_ASSERT(__il.begin() != __il.end(), "initializer_list must contain at least one element"); + + auto __comp_lhs_rhs_swapped = [&](auto&& __lhs, auto&& __rhs) { return std::invoke(__comp, __rhs, __lhs); }; + return *ranges::__min_element_impl(__il.begin(), __il.end(), __comp_lhs_rhs_swapped, __proj); + } + + template , _Proj>> _Comp = ranges::less> + requires indirectly_copyable_storable, range_value_t<_Rp>*> + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr + range_value_t<_Rp> operator()(_Rp&& __r, _Comp __comp = {}, _Proj __proj = {}) const { + auto __first = ranges::begin(__r); + auto __last = ranges::end(__r); + + _LIBCPP_ASSERT(__first != __last, "range must contain at least one element"); + + if constexpr (forward_range<_Rp>) { + auto __comp_lhs_rhs_swapped = [&](auto&& __lhs, auto&& __rhs) { return std::invoke(__comp, __rhs, __lhs); }; + return *ranges::__min_element_impl(std::move(__first), std::move(__last), __comp_lhs_rhs_swapped, __proj); + } else { + range_value_t<_Rp> __result = *__first; + while (++__first != __last) { + if (std::invoke(__comp, std::invoke(__proj, __result), std::invoke(__proj, *__first))) + __result = *__first; + } + return __result; + } + } +}; +} // namespace __max + +inline namespace __cpo { + inline constexpr auto max = __max::__fn{}; +} // namespace __cpo +} // namespace ranges + +_LIBCPP_END_NAMESPACE_STD + +_LIBCPP_POP_MACROS + +#endif // _LIBCPP_STD_VER > 17 && + +#endif // _LIBCPP___ALGORITHM_RANGES_MAX_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/ranges_max_element.h b/app/src/main/cpp/libcxx/include/__algorithm/ranges_max_element.h new file mode 100644 index 0000000..490f320 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/ranges_max_element.h @@ -0,0 +1,61 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_RANGES_MAX_ELEMENT_H +#define _LIBCPP___ALGORITHM_RANGES_MAX_ELEMENT_H + +#include <__algorithm/ranges_min_element.h> +#include <__config> +#include <__functional/identity.h> +#include <__functional/invoke.h> +#include <__functional/ranges_operations.h> +#include <__iterator/concepts.h> +#include <__iterator/projected.h> +#include <__ranges/access.h> +#include <__ranges/concepts.h> +#include <__ranges/dangling.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if _LIBCPP_STD_VER > 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace ranges { +namespace __max_element { +struct __fn { + template _Sp, class _Proj = identity, + indirect_strict_weak_order> _Comp = ranges::less> + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr + _Ip operator()(_Ip __first, _Sp __last, _Comp __comp = {}, _Proj __proj = {}) const { + auto __comp_lhs_rhs_swapped = [&](auto&& __lhs, auto&& __rhs) { return std::invoke(__comp, __rhs, __lhs); }; + return ranges::__min_element_impl(__first, __last, __comp_lhs_rhs_swapped, __proj); + } + + template , _Proj>> _Comp = ranges::less> + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr + borrowed_iterator_t<_Rp> operator()(_Rp&& __r, _Comp __comp = {}, _Proj __proj = {}) const { + auto __comp_lhs_rhs_swapped = [&](auto&& __lhs, auto&& __rhs) { return std::invoke(__comp, __rhs, __lhs); }; + return ranges::__min_element_impl(ranges::begin(__r), ranges::end(__r), __comp_lhs_rhs_swapped, __proj); + } +}; +} // namespace __max_element + +inline namespace __cpo { + inline constexpr auto max_element = __max_element::__fn{}; +} // namespace __cpo +} // namespace ranges + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER > 17 + +#endif // _LIBCPP___ALGORITHM_RANGES_MAX_ELEMENT_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/ranges_merge.h b/app/src/main/cpp/libcxx/include/__algorithm/ranges_merge.h new file mode 100644 index 0000000..b36a05a --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/ranges_merge.h @@ -0,0 +1,142 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_RANGES_MERGE_H +#define _LIBCPP___ALGORITHM_RANGES_MERGE_H + +#include <__algorithm/in_in_out_result.h> +#include <__algorithm/ranges_copy.h> +#include <__config> +#include <__functional/identity.h> +#include <__functional/invoke.h> +#include <__functional/ranges_operations.h> +#include <__iterator/concepts.h> +#include <__iterator/mergeable.h> +#include <__ranges/access.h> +#include <__ranges/concepts.h> +#include <__ranges/dangling.h> +#include <__utility/move.h> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if _LIBCPP_STD_VER > 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace ranges { + +template +using merge_result = in_in_out_result<_InIter1, _InIter2, _OutIter>; + +namespace __merge { + +template < + class _InIter1, + class _Sent1, + class _InIter2, + class _Sent2, + class _OutIter, + class _Comp, + class _Proj1, + class _Proj2> +_LIBCPP_HIDE_FROM_ABI constexpr merge_result<__remove_cvref_t<_InIter1>, __remove_cvref_t<_InIter2>, __remove_cvref_t<_OutIter>> +__merge_impl( + _InIter1&& __first1, + _Sent1&& __last1, + _InIter2&& __first2, + _Sent2&& __last2, + _OutIter&& __result, + _Comp&& __comp, + _Proj1&& __proj1, + _Proj2&& __proj2) { + for (; __first1 != __last1 && __first2 != __last2; ++__result) { + if (std::invoke(__comp, std::invoke(__proj2, *__first2), std::invoke(__proj1, *__first1))) { + *__result = *__first2; + ++__first2; + } else { + *__result = *__first1; + ++__first1; + } + } + auto __ret1 = ranges::copy(std::move(__first1), std::move(__last1), std::move(__result)); + auto __ret2 = ranges::copy(std::move(__first2), std::move(__last2), std::move(__ret1.out)); + return {std::move(__ret1.in), std::move(__ret2.in), std::move(__ret2.out)}; +} + +struct __fn { + template < + input_iterator _InIter1, + sentinel_for<_InIter1> _Sent1, + input_iterator _InIter2, + sentinel_for<_InIter2> _Sent2, + weakly_incrementable _OutIter, + class _Comp = less, + class _Proj1 = identity, + class _Proj2 = identity> + requires mergeable<_InIter1, _InIter2, _OutIter, _Comp, _Proj1, _Proj2> + _LIBCPP_HIDE_FROM_ABI constexpr merge_result<_InIter1, _InIter2, _OutIter> operator()( + _InIter1 __first1, + _Sent1 __last1, + _InIter2 __first2, + _Sent2 __last2, + _OutIter __result, + _Comp __comp = {}, + _Proj1 __proj1 = {}, + _Proj2 __proj2 = {}) const { + return __merge::__merge_impl(__first1, __last1, __first2, __last2, __result, __comp, __proj1, __proj2); + } + + template < + input_range _Range1, + input_range _Range2, + weakly_incrementable _OutIter, + class _Comp = less, + class _Proj1 = identity, + class _Proj2 = identity> + requires mergeable< + iterator_t<_Range1>, + iterator_t<_Range2>, + _OutIter, + _Comp, + _Proj1, + _Proj2> + _LIBCPP_HIDE_FROM_ABI constexpr merge_result, borrowed_iterator_t<_Range2>, _OutIter> + operator()( + _Range1&& __range1, + _Range2&& __range2, + _OutIter __result, + _Comp __comp = {}, + _Proj1 __proj1 = {}, + _Proj2 __proj2 = {}) const { + return __merge::__merge_impl( + ranges::begin(__range1), + ranges::end(__range1), + ranges::begin(__range2), + ranges::end(__range2), + __result, + __comp, + __proj1, + __proj2); + } +}; + +} // namespace __merge + +inline namespace __cpo { + inline constexpr auto merge = __merge::__fn{}; +} // namespace __cpo +} // namespace ranges + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER > 17 + +#endif // _LIBCPP___ALGORITHM_RANGES_MERGE_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/ranges_min.h b/app/src/main/cpp/libcxx/include/__algorithm/ranges_min.h new file mode 100644 index 0000000..0e31f57 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/ranges_min.h @@ -0,0 +1,89 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_RANGES_MIN_H +#define _LIBCPP___ALGORITHM_RANGES_MIN_H + +#include <__algorithm/ranges_min_element.h> +#include <__assert> +#include <__concepts/copyable.h> +#include <__config> +#include <__functional/identity.h> +#include <__functional/invoke.h> +#include <__functional/ranges_operations.h> +#include <__iterator/concepts.h> +#include <__iterator/projected.h> +#include <__ranges/access.h> +#include <__ranges/concepts.h> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if _LIBCPP_STD_VER > 17 + +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace ranges { +namespace __min { +struct __fn { + template > _Comp = ranges::less> + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr + const _Tp& operator()(const _Tp& __a, const _Tp& __b, _Comp __comp = {}, _Proj __proj = {}) const { + return std::invoke(__comp, std::invoke(__proj, __b), std::invoke(__proj, __a)) ? __b : __a; + } + + template > _Comp = ranges::less> + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr + _Tp operator()(initializer_list<_Tp> __il, _Comp __comp = {}, _Proj __proj = {}) const { + _LIBCPP_ASSERT(__il.begin() != __il.end(), "initializer_list must contain at least one element"); + return *ranges::__min_element_impl(__il.begin(), __il.end(), __comp, __proj); + } + + template , _Proj>> _Comp = ranges::less> + requires indirectly_copyable_storable, range_value_t<_Rp>*> + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr + range_value_t<_Rp> operator()(_Rp&& __r, _Comp __comp = {}, _Proj __proj = {}) const { + auto __first = ranges::begin(__r); + auto __last = ranges::end(__r); + + _LIBCPP_ASSERT(__first != __last, "range must contain at least one element"); + + if constexpr (forward_range<_Rp>) { + return *ranges::__min_element_impl(__first, __last, __comp, __proj); + } else { + range_value_t<_Rp> __result = *__first; + while (++__first != __last) { + if (std::invoke(__comp, std::invoke(__proj, *__first), std::invoke(__proj, __result))) + __result = *__first; + } + return __result; + } + } +}; +} // namespace __min + +inline namespace __cpo { + inline constexpr auto min = __min::__fn{}; +} // namespace __cpo +} // namespace ranges + +_LIBCPP_END_NAMESPACE_STD + +_LIBCPP_POP_MACROS + +#endif // _LIBCPP_STD_VER > 17 && + +#endif // _LIBCPP___ALGORITHM_RANGES_MIN_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/ranges_min_element.h b/app/src/main/cpp/libcxx/include/__algorithm/ranges_min_element.h new file mode 100644 index 0000000..1751874 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/ranges_min_element.h @@ -0,0 +1,74 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_RANGES_MIN_ELEMENT_H +#define _LIBCPP___ALGORITHM_RANGES_MIN_ELEMENT_H + +#include <__config> +#include <__functional/identity.h> +#include <__functional/invoke.h> +#include <__functional/ranges_operations.h> +#include <__iterator/concepts.h> +#include <__iterator/projected.h> +#include <__ranges/access.h> +#include <__ranges/concepts.h> +#include <__ranges/dangling.h> +#include <__utility/forward.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if _LIBCPP_STD_VER > 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace ranges { + +// TODO(ranges): `ranges::min_element` can now simply delegate to `std::__min_element`. +template +_LIBCPP_HIDE_FROM_ABI static constexpr +_Ip __min_element_impl(_Ip __first, _Sp __last, _Comp& __comp, _Proj& __proj) { + if (__first == __last) + return __first; + + _Ip __i = __first; + while (++__i != __last) + if (std::invoke(__comp, std::invoke(__proj, *__i), std::invoke(__proj, *__first))) + __first = __i; + return __first; +} + +namespace __min_element { +struct __fn { + template _Sp, class _Proj = identity, + indirect_strict_weak_order> _Comp = ranges::less> + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr + _Ip operator()(_Ip __first, _Sp __last, _Comp __comp = {}, _Proj __proj = {}) const { + return ranges::__min_element_impl(__first, __last, __comp, __proj); + } + + template , _Proj>> _Comp = ranges::less> + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr + borrowed_iterator_t<_Rp> operator()(_Rp&& __r, _Comp __comp = {}, _Proj __proj = {}) const { + return ranges::__min_element_impl(ranges::begin(__r), ranges::end(__r), __comp, __proj); + } +}; +} // namespace __min_element + +inline namespace __cpo { + inline constexpr auto min_element = __min_element::__fn{}; +} // namespace __cpo +} // namespace ranges + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER > 17 + +#endif // _LIBCPP___ALGORITHM_RANGES_MIN_ELEMENT_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/ranges_minmax.h b/app/src/main/cpp/libcxx/include/__algorithm/ranges_minmax.h new file mode 100644 index 0000000..f82e005 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/ranges_minmax.h @@ -0,0 +1,134 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_RANGES_MINMAX_H +#define _LIBCPP___ALGORITHM_RANGES_MINMAX_H + +#include <__algorithm/min_max_result.h> +#include <__algorithm/minmax_element.h> +#include <__assert> +#include <__concepts/copyable.h> +#include <__config> +#include <__functional/identity.h> +#include <__functional/invoke.h> +#include <__functional/ranges_operations.h> +#include <__iterator/concepts.h> +#include <__iterator/projected.h> +#include <__ranges/access.h> +#include <__ranges/concepts.h> +#include <__utility/forward.h> +#include <__utility/move.h> +#include <__utility/pair.h> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if _LIBCPP_STD_VER > 17 + +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace ranges { +template +using minmax_result = min_max_result<_T1>; + +namespace __minmax { +struct __fn { + template > _Comp = ranges::less> + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr ranges::minmax_result + operator()(const _Type& __a, const _Type& __b, _Comp __comp = {}, _Proj __proj = {}) const { + if (std::invoke(__comp, std::invoke(__proj, __b), std::invoke(__proj, __a))) + return {__b, __a}; + return {__a, __b}; + } + + template > _Comp = ranges::less> + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr + ranges::minmax_result<_Type> operator()(initializer_list<_Type> __il, _Comp __comp = {}, _Proj __proj = {}) const { + _LIBCPP_ASSERT(__il.begin() != __il.end(), "initializer_list has to contain at least one element"); + auto __iters = std::__minmax_element_impl(__il.begin(), __il.end(), __comp, __proj); + return ranges::minmax_result<_Type> { *__iters.first, *__iters.second }; + } + + template , _Proj>> _Comp = ranges::less> + requires indirectly_copyable_storable, range_value_t<_Range>*> + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr + ranges::minmax_result> operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const { + auto __first = ranges::begin(__r); + auto __last = ranges::end(__r); + using _ValueT = range_value_t<_Range>; + + _LIBCPP_ASSERT(__first != __last, "range has to contain at least one element"); + + if constexpr (forward_range<_Range>) { + auto __result = std::__minmax_element_impl(__first, __last, __comp, __proj); + return {*__result.first, *__result.second}; + } else { + // input_iterators can't be copied, so the implementation for input_iterators has to store + // the values instead of a pointer to the correct values + auto __less = [&](auto&& __a, auto&& __b) -> bool { + return std::invoke(__comp, std::invoke(__proj, std::forward(__a)), + std::invoke(__proj, std::forward(__b))); + }; + + ranges::minmax_result<_ValueT> __result = {*__first, __result.min}; + if (__first == __last || ++__first == __last) + return __result; + + if (__less(*__first, __result.min)) + __result.min = *__first; + else + __result.max = *__first; + + while (++__first != __last) { + _ValueT __i = *__first; + if (++__first == __last) { + if (__less(__i, __result.min)) + __result.min = __i; + else if (!__less(__i, __result.max)) + __result.max = __i; + return __result; + } + + if (__less(*__first, __i)) { + if (__less(*__first, __result.min)) + __result.min = *__first; + if (!__less(__i, __result.max)) + __result.max = std::move(__i); + } else { + if (__less(__i, __result.min)) + __result.min = std::move(__i); + if (!__less(*__first, __result.max)) + __result.max = *__first; + } + } + return __result; + } + } +}; +} // namespace __minmax + +inline namespace __cpo { + inline constexpr auto minmax = __minmax::__fn{}; +} // namespace __cpo +} // namespace ranges + +_LIBCPP_END_NAMESPACE_STD + +_LIBCPP_POP_MACROS + +#endif // _LIBCPP_STD_VER > 17 + +#endif // _LIBCPP___ALGORITHM_RANGES_MINMAX_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/ranges_minmax_element.h b/app/src/main/cpp/libcxx/include/__algorithm/ranges_minmax_element.h new file mode 100644 index 0000000..6699f96 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/ranges_minmax_element.h @@ -0,0 +1,72 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_RANGES_MINMAX_ELEMENT_H +#define _LIBCPP___ALGORITHM_RANGES_MINMAX_ELEMENT_H + +#include <__algorithm/min_max_result.h> +#include <__algorithm/minmax_element.h> +#include <__config> +#include <__functional/identity.h> +#include <__functional/invoke.h> +#include <__functional/ranges_operations.h> +#include <__iterator/concepts.h> +#include <__iterator/projected.h> +#include <__ranges/access.h> +#include <__ranges/concepts.h> +#include <__ranges/dangling.h> +#include <__utility/forward.h> +#include <__utility/move.h> +#include <__utility/pair.h> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if _LIBCPP_STD_VER > 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace ranges { + +template +using minmax_element_result = min_max_result<_T1>; + +namespace __minmax_element { +struct __fn { + template _Sp, class _Proj = identity, + indirect_strict_weak_order> _Comp = ranges::less> + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr + ranges::minmax_element_result<_Ip> operator()(_Ip __first, _Sp __last, _Comp __comp = {}, _Proj __proj = {}) const { + auto __ret = std::__minmax_element_impl(std::move(__first), std::move(__last), __comp, __proj); + return {__ret.first, __ret.second}; + } + + template , _Proj>> _Comp = ranges::less> + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr + ranges::minmax_element_result> + operator()(_Rp&& __r, _Comp __comp = {}, _Proj __proj = {}) const { + auto __ret = std::__minmax_element_impl(ranges::begin(__r), ranges::end(__r), __comp, __proj); + return {__ret.first, __ret.second}; + } +}; +} // namespace __minmax_element + +inline namespace __cpo { + inline constexpr auto minmax_element = __minmax_element::__fn{}; +} // namespace __cpo + +} // namespace ranges + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER > 17 + +#endif // _LIBCPP___ALGORITHM_RANGES_MINMAX_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/ranges_mismatch.h b/app/src/main/cpp/libcxx/include/__algorithm/ranges_mismatch.h new file mode 100644 index 0000000..4fd0517 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/ranges_mismatch.h @@ -0,0 +1,85 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_RANGES_MISMATCH_H +#define _LIBCPP___ALGORITHM_RANGES_MISMATCH_H + +#include <__algorithm/in_in_result.h> +#include <__config> +#include <__functional/identity.h> +#include <__functional/invoke.h> +#include <__functional/ranges_operations.h> +#include <__iterator/concepts.h> +#include <__iterator/indirectly_comparable.h> +#include <__ranges/access.h> +#include <__ranges/concepts.h> +#include <__ranges/dangling.h> +#include <__utility/move.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 17 + +namespace ranges { + +template +using mismatch_result = in_in_result<_I1, _I2>; + +namespace __mismatch { +struct __fn { + template + static _LIBCPP_HIDE_FROM_ABI constexpr + mismatch_result<_I1, _I2> + __go(_I1 __first1, _S1 __last1, _I2 __first2, _S2 __last2, + _Pred& __pred, _Proj1& __proj1, _Proj2& __proj2) { + while (__first1 != __last1 && __first2 != __last2) { + if (!std::invoke(__pred, std::invoke(__proj1, *__first1), std::invoke(__proj2, *__first2))) + break; + ++__first1; + ++__first2; + } + return {std::move(__first1), std::move(__first2)}; + } + + template _S1, + input_iterator _I2, sentinel_for<_I2> _S2, + class _Pred = ranges::equal_to, class _Proj1 = identity, class _Proj2 = identity> + requires indirectly_comparable<_I1, _I2, _Pred, _Proj1, _Proj2> + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr + mismatch_result<_I1, _I2> operator()(_I1 __first1, _S1 __last1, _I2 __first2, _S2 __last2, + _Pred __pred = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const { + return __go(std::move(__first1), __last1, std::move(__first2), __last2, __pred, __proj1, __proj2); + } + + template + requires indirectly_comparable, iterator_t<_R2>, _Pred, _Proj1, _Proj2> + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr + mismatch_result, borrowed_iterator_t<_R2>> + operator()(_R1&& __r1, _R2&& __r2, _Pred __pred = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const { + return __go(ranges::begin(__r1), ranges::end(__r1), ranges::begin(__r2), ranges::end(__r2), + __pred, __proj1, __proj2); + } +}; +} // namespace __mismatch + +inline namespace __cpo { + constexpr inline auto mismatch = __mismatch::__fn{}; +} // namespace __cpo +} // namespace ranges + +#endif // _LIBCPP_STD_VER > 17 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ALGORITHM_RANGES_MISMATCH_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/ranges_move.h b/app/src/main/cpp/libcxx/include/__algorithm/ranges_move.h new file mode 100644 index 0000000..46a0970 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/ranges_move.h @@ -0,0 +1,71 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_RANGES_MOVE_H +#define _LIBCPP___ALGORITHM_RANGES_MOVE_H + +#include <__algorithm/in_out_result.h> +#include <__algorithm/iterator_operations.h> +#include <__algorithm/move.h> +#include <__config> +#include <__iterator/concepts.h> +#include <__ranges/access.h> +#include <__ranges/concepts.h> +#include <__ranges/dangling.h> +#include <__utility/move.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if _LIBCPP_STD_VER > 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace ranges { + +template +using move_result = in_out_result<_InIter, _OutIter>; + +namespace __move { +struct __fn { + + template + _LIBCPP_HIDE_FROM_ABI constexpr static + move_result<_InIter, _OutIter> __move_impl(_InIter __first, _Sent __last, _OutIter __result) { + auto __ret = std::__move<_RangeAlgPolicy>(std::move(__first), std::move(__last), std::move(__result)); + return {std::move(__ret.first), std::move(__ret.second)}; + } + + template _Sent, weakly_incrementable _OutIter> + requires indirectly_movable<_InIter, _OutIter> + _LIBCPP_HIDE_FROM_ABI constexpr + move_result<_InIter, _OutIter> operator()(_InIter __first, _Sent __last, _OutIter __result) const { + return __move_impl(std::move(__first), std::move(__last), std::move(__result)); + } + + template + requires indirectly_movable, _OutIter> + _LIBCPP_HIDE_FROM_ABI constexpr + move_result, _OutIter> operator()(_Range&& __range, _OutIter __result) const { + return __move_impl(ranges::begin(__range), ranges::end(__range), std::move(__result)); + } + +}; +} // namespace __move + +inline namespace __cpo { + inline constexpr auto move = __move::__fn{}; +} // namespace __cpo +} // namespace ranges + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER > 17 + +#endif // _LIBCPP___ALGORITHM_RANGES_MOVE_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/ranges_move_backward.h b/app/src/main/cpp/libcxx/include/__algorithm/ranges_move_backward.h new file mode 100644 index 0000000..d4e8eb1 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/ranges_move_backward.h @@ -0,0 +1,73 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_RANGES_MOVE_BACKWARD_H +#define _LIBCPP___ALGORITHM_RANGES_MOVE_BACKWARD_H + +#include <__algorithm/in_out_result.h> +#include <__algorithm/iterator_operations.h> +#include <__algorithm/move_backward.h> +#include <__config> +#include <__iterator/concepts.h> +#include <__iterator/iter_move.h> +#include <__iterator/next.h> +#include <__ranges/access.h> +#include <__ranges/concepts.h> +#include <__ranges/dangling.h> +#include <__utility/move.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if _LIBCPP_STD_VER > 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace ranges { + +template +using move_backward_result = in_out_result<_InIter, _OutIter>; + +namespace __move_backward { +struct __fn { + + template + _LIBCPP_HIDE_FROM_ABI constexpr static + move_backward_result<_InIter, _OutIter> __move_backward_impl(_InIter __first, _Sent __last, _OutIter __result) { + auto __ret = std::__move_backward<_RangeAlgPolicy>(std::move(__first), std::move(__last), std::move(__result)); + return {std::move(__ret.first), std::move(__ret.second)}; + } + + template _Sent, bidirectional_iterator _OutIter> + requires indirectly_movable<_InIter, _OutIter> + _LIBCPP_HIDE_FROM_ABI constexpr + move_backward_result<_InIter, _OutIter> operator()(_InIter __first, _Sent __last, _OutIter __result) const { + return __move_backward_impl(std::move(__first), std::move(__last), std::move(__result)); + } + + template + requires indirectly_movable, _Iter> + _LIBCPP_HIDE_FROM_ABI constexpr + move_backward_result, _Iter> operator()(_Range&& __range, _Iter __result) const { + return __move_backward_impl(ranges::begin(__range), ranges::end(__range), std::move(__result)); + } + +}; +} // namespace __move_backward + +inline namespace __cpo { + inline constexpr auto move_backward = __move_backward::__fn{}; +} // namespace __cpo +} // namespace ranges + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER > 17 + +#endif // _LIBCPP___ALGORITHM_RANGES_MOVE_BACKWARD_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/ranges_next_permutation.h b/app/src/main/cpp/libcxx/include/__algorithm/ranges_next_permutation.h new file mode 100644 index 0000000..6c8e8e1 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/ranges_next_permutation.h @@ -0,0 +1,73 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_RANGES_NEXT_PERMUTATION_H +#define _LIBCPP___ALGORITHM_RANGES_NEXT_PERMUTATION_H + +#include <__algorithm/in_found_result.h> +#include <__algorithm/iterator_operations.h> +#include <__algorithm/make_projected.h> +#include <__algorithm/next_permutation.h> +#include <__config> +#include <__functional/identity.h> +#include <__functional/ranges_operations.h> +#include <__iterator/concepts.h> +#include <__iterator/sortable.h> +#include <__ranges/access.h> +#include <__ranges/concepts.h> +#include <__ranges/dangling.h> +#include <__utility/move.h> +#include <__utility/pair.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if _LIBCPP_STD_VER > 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace ranges { + +template +using next_permutation_result = in_found_result<_InIter>; + +namespace __next_permutation { + +struct __fn { + template _Sent, class _Comp = ranges::less, class _Proj = identity> + requires sortable<_Iter, _Comp, _Proj> + _LIBCPP_HIDE_FROM_ABI constexpr next_permutation_result<_Iter> + operator()(_Iter __first, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) const { + auto __result = std::__next_permutation<_RangeAlgPolicy>( + std::move(__first), std::move(__last), std::__make_projected(__comp, __proj)); + return {std::move(__result.first), std::move(__result.second)}; + } + + template + requires sortable, _Comp, _Proj> + _LIBCPP_HIDE_FROM_ABI constexpr next_permutation_result> + operator()(_Range&& __range, _Comp __comp = {}, _Proj __proj = {}) const { + auto __result = std::__next_permutation<_RangeAlgPolicy>( + ranges::begin(__range), ranges::end(__range), std::__make_projected(__comp, __proj)); + return {std::move(__result.first), std::move(__result.second)}; + } +}; + +} // namespace __next_permutation + +inline namespace __cpo { +constexpr inline auto next_permutation = __next_permutation::__fn{}; +} // namespace __cpo +} // namespace ranges + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER > 17 + +#endif // _LIBCPP___ALGORITHM_RANGES_NEXT_PERMUTATION_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/ranges_none_of.h b/app/src/main/cpp/libcxx/include/__algorithm/ranges_none_of.h new file mode 100644 index 0000000..b39e570 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/ranges_none_of.h @@ -0,0 +1,68 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_RANGES_NONE_OF_H +#define _LIBCPP___ALGORITHM_RANGES_NONE_OF_H + +#include <__config> +#include <__functional/identity.h> +#include <__functional/invoke.h> +#include <__iterator/concepts.h> +#include <__iterator/projected.h> +#include <__ranges/access.h> +#include <__ranges/concepts.h> +#include <__utility/move.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if _LIBCPP_STD_VER > 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace ranges { +namespace __none_of { +struct __fn { + + template + _LIBCPP_HIDE_FROM_ABI constexpr static + bool __none_of_impl(_Iter __first, _Sent __last, _Pred& __pred, _Proj& __proj) { + for (; __first != __last; ++__first) { + if (std::invoke(__pred, std::invoke(__proj, *__first))) + return false; + } + return true; + } + + template _Sent, class _Proj = identity, + indirect_unary_predicate> _Pred> + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr + bool operator()(_Iter __first, _Sent __last, _Pred __pred = {}, _Proj __proj = {}) const { + return __none_of_impl(std::move(__first), std::move(__last), __pred, __proj); + } + + template , _Proj>> _Pred> + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr + bool operator()(_Range&& __range, _Pred __pred, _Proj __proj = {}) const { + return __none_of_impl(ranges::begin(__range), ranges::end(__range), __pred, __proj); + } +}; +} // namespace __none_of + +inline namespace __cpo { + inline constexpr auto none_of = __none_of::__fn{}; +} // namespace __cpo +} // namespace ranges + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER > 17 + +#endif // _LIBCPP___ALGORITHM_RANGES_NONE_OF_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/ranges_nth_element.h b/app/src/main/cpp/libcxx/include/__algorithm/ranges_nth_element.h new file mode 100644 index 0000000..d9ec4f1 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/ranges_nth_element.h @@ -0,0 +1,80 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_RANGES_NTH_ELEMENT_H +#define _LIBCPP___ALGORITHM_RANGES_NTH_ELEMENT_H + +#include <__algorithm/iterator_operations.h> +#include <__algorithm/make_projected.h> +#include <__algorithm/nth_element.h> +#include <__config> +#include <__functional/identity.h> +#include <__functional/invoke.h> +#include <__functional/ranges_operations.h> +#include <__iterator/concepts.h> +#include <__iterator/iterator_traits.h> +#include <__iterator/next.h> +#include <__iterator/projected.h> +#include <__iterator/sortable.h> +#include <__ranges/access.h> +#include <__ranges/concepts.h> +#include <__ranges/dangling.h> +#include <__utility/forward.h> +#include <__utility/move.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if _LIBCPP_STD_VER > 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace ranges { +namespace __nth_element { + +struct __fn { + template + _LIBCPP_HIDE_FROM_ABI constexpr static + _Iter __nth_element_fn_impl(_Iter __first, _Iter __nth, _Sent __last, _Comp& __comp, _Proj& __proj) { + auto __last_iter = ranges::next(__first, __last); + + auto&& __projected_comp = std::__make_projected(__comp, __proj); + std::__nth_element_impl<_RangeAlgPolicy>(std::move(__first), std::move(__nth), __last_iter, __projected_comp); + + return __last_iter; + } + + template _Sent, class _Comp = ranges::less, class _Proj = identity> + requires sortable<_Iter, _Comp, _Proj> + _LIBCPP_HIDE_FROM_ABI constexpr + _Iter operator()(_Iter __first, _Iter __nth, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) const { + return __nth_element_fn_impl(std::move(__first), std::move(__nth), std::move(__last), __comp, __proj); + } + + template + requires sortable, _Comp, _Proj> + _LIBCPP_HIDE_FROM_ABI constexpr + borrowed_iterator_t<_Range> operator()(_Range&& __r, iterator_t<_Range> __nth, _Comp __comp = {}, + _Proj __proj = {}) const { + return __nth_element_fn_impl(ranges::begin(__r), std::move(__nth), ranges::end(__r), __comp, __proj); + } +}; + +} // namespace __nth_element + +inline namespace __cpo { + inline constexpr auto nth_element = __nth_element::__fn{}; +} // namespace __cpo +} // namespace ranges + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER > 17 + +#endif // _LIBCPP___ALGORITHM_RANGES_NTH_ELEMENT_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/ranges_partial_sort.h b/app/src/main/cpp/libcxx/include/__algorithm/ranges_partial_sort.h new file mode 100644 index 0000000..3ea0a7f --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/ranges_partial_sort.h @@ -0,0 +1,78 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_RANGES_PARTIAL_SORT_H +#define _LIBCPP___ALGORITHM_RANGES_PARTIAL_SORT_H + +#include <__algorithm/iterator_operations.h> +#include <__algorithm/make_projected.h> +#include <__algorithm/partial_sort.h> +#include <__concepts/same_as.h> +#include <__config> +#include <__functional/identity.h> +#include <__functional/invoke.h> +#include <__functional/ranges_operations.h> +#include <__iterator/concepts.h> +#include <__iterator/iterator_traits.h> +#include <__iterator/next.h> +#include <__iterator/projected.h> +#include <__iterator/sortable.h> +#include <__ranges/access.h> +#include <__ranges/concepts.h> +#include <__ranges/dangling.h> +#include <__utility/forward.h> +#include <__utility/move.h> +#include <__utility/pair.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if _LIBCPP_STD_VER > 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace ranges { +namespace __partial_sort { + +struct __fn { + template + _LIBCPP_HIDE_FROM_ABI constexpr static + _Iter __partial_sort_fn_impl(_Iter __first, _Iter __middle, _Sent __last, _Comp& __comp, _Proj& __proj) { + auto&& __projected_comp = std::__make_projected(__comp, __proj); + return std::__partial_sort<_RangeAlgPolicy>(std::move(__first), std::move(__middle), __last, __projected_comp); + } + + template _Sent, class _Comp = ranges::less, class _Proj = identity> + requires sortable<_Iter, _Comp, _Proj> + _LIBCPP_HIDE_FROM_ABI constexpr + _Iter operator()(_Iter __first, _Iter __middle, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) const { + return __partial_sort_fn_impl(std::move(__first), std::move(__middle), std::move(__last), __comp, __proj); + } + + template + requires sortable, _Comp, _Proj> + _LIBCPP_HIDE_FROM_ABI constexpr + borrowed_iterator_t<_Range> operator()(_Range&& __r, iterator_t<_Range> __middle, _Comp __comp = {}, + _Proj __proj = {}) const { + return __partial_sort_fn_impl(ranges::begin(__r), std::move(__middle), ranges::end(__r), __comp, __proj); + } +}; + +} // namespace __partial_sort + +inline namespace __cpo { + inline constexpr auto partial_sort = __partial_sort::__fn{}; +} // namespace __cpo +} // namespace ranges + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER > 17 + +#endif // _LIBCPP___ALGORITHM_RANGES_PARTIAL_SORT_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/ranges_partial_sort_copy.h b/app/src/main/cpp/libcxx/include/__algorithm/ranges_partial_sort_copy.h new file mode 100644 index 0000000..212db55 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/ranges_partial_sort_copy.h @@ -0,0 +1,92 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_RANGES_PARTIAL_SORT_COPY_H +#define _LIBCPP___ALGORITHM_RANGES_PARTIAL_SORT_COPY_H + +#include <__algorithm/in_out_result.h> +#include <__algorithm/iterator_operations.h> +#include <__algorithm/make_projected.h> +#include <__algorithm/partial_sort_copy.h> +#include <__config> +#include <__functional/identity.h> +#include <__functional/ranges_operations.h> +#include <__iterator/concepts.h> +#include <__iterator/iterator_traits.h> +#include <__iterator/projected.h> +#include <__iterator/sortable.h> +#include <__ranges/access.h> +#include <__ranges/concepts.h> +#include <__ranges/dangling.h> +#include <__utility/move.h> +#include <__utility/pair.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if _LIBCPP_STD_VER > 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace ranges { + +template +using partial_sort_copy_result = in_out_result<_InIter, _OutIter>; + +namespace __partial_sort_copy { + +struct __fn { + + template _Sent1, + random_access_iterator _Iter2, sentinel_for<_Iter2> _Sent2, + class _Comp = ranges::less, class _Proj1 = identity, class _Proj2 = identity> + requires indirectly_copyable<_Iter1, _Iter2> && sortable<_Iter2, _Comp, _Proj2> && + indirect_strict_weak_order<_Comp, projected<_Iter1, _Proj1>, projected<_Iter2, _Proj2>> + _LIBCPP_HIDE_FROM_ABI constexpr + partial_sort_copy_result<_Iter1, _Iter2> + operator()(_Iter1 __first, _Sent1 __last, _Iter2 __result_first, _Sent2 __result_last, + _Comp __comp = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const { + auto __result = std::__partial_sort_copy<_RangeAlgPolicy>( + std::move(__first), std::move(__last), std::move(__result_first), std::move(__result_last), + __comp, __proj1, __proj2 + ); + return {std::move(__result.first), std::move(__result.second)}; + } + + template + requires indirectly_copyable, iterator_t<_Range2>> && + sortable, _Comp, _Proj2> && + indirect_strict_weak_order<_Comp, projected, _Proj1>, + projected, _Proj2>> + _LIBCPP_HIDE_FROM_ABI constexpr + partial_sort_copy_result, borrowed_iterator_t<_Range2>> + operator()(_Range1&& __range, _Range2&& __result_range, _Comp __comp = {}, + _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const { + auto __result = std::__partial_sort_copy<_RangeAlgPolicy>( + ranges::begin(__range), ranges::end(__range), ranges::begin(__result_range), ranges::end(__result_range), + __comp, __proj1, __proj2 + ); + return {std::move(__result.first), std::move(__result.second)}; + } + +}; + +} // namespace __partial_sort_copy + +inline namespace __cpo { + inline constexpr auto partial_sort_copy = __partial_sort_copy::__fn{}; +} // namespace __cpo +} // namespace ranges + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER > 17 + +#endif // _LIBCPP___ALGORITHM_RANGES_PARTIAL_SORT_COPY_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/ranges_partition.h b/app/src/main/cpp/libcxx/include/__algorithm/ranges_partition.h new file mode 100644 index 0000000..8b3aae5 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/ranges_partition.h @@ -0,0 +1,83 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_RANGES_PARTITION_H +#define _LIBCPP___ALGORITHM_RANGES_PARTITION_H + +#include <__algorithm/iterator_operations.h> +#include <__algorithm/make_projected.h> +#include <__algorithm/partition.h> +#include <__algorithm/ranges_iterator_concept.h> +#include <__config> +#include <__functional/identity.h> +#include <__functional/invoke.h> +#include <__functional/ranges_operations.h> +#include <__iterator/concepts.h> +#include <__iterator/iterator_traits.h> +#include <__iterator/permutable.h> +#include <__iterator/projected.h> +#include <__ranges/access.h> +#include <__ranges/concepts.h> +#include <__ranges/subrange.h> +#include <__utility/forward.h> +#include <__utility/move.h> +#include <__utility/pair.h> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if _LIBCPP_STD_VER > 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace ranges { +namespace __partition { + +struct __fn { + + template + _LIBCPP_HIDE_FROM_ABI static constexpr + subrange<__remove_cvref_t<_Iter>> __partition_fn_impl(_Iter&& __first, _Sent&& __last, _Pred&& __pred, _Proj&& __proj) { + auto&& __projected_pred = std::__make_projected(__pred, __proj); + auto __result = std::__partition<_RangeAlgPolicy>( + std::move(__first), std::move(__last), __projected_pred, __iterator_concept<_Iter>()); + + return {std::move(__result.first), std::move(__result.second)}; + } + + template _Sent, class _Proj = identity, + indirect_unary_predicate> _Pred> + _LIBCPP_HIDE_FROM_ABI constexpr + subrange<_Iter> operator()(_Iter __first, _Sent __last, _Pred __pred, _Proj __proj = {}) const { + return __partition_fn_impl(__first, __last, __pred, __proj); + } + + template , _Proj>> _Pred> + requires permutable> + _LIBCPP_HIDE_FROM_ABI constexpr + borrowed_subrange_t<_Range> operator()(_Range&& __range, _Pred __pred, _Proj __proj = {}) const { + return __partition_fn_impl(ranges::begin(__range), ranges::end(__range), __pred, __proj); + } + +}; + +} // namespace __partition + +inline namespace __cpo { + inline constexpr auto partition = __partition::__fn{}; +} // namespace __cpo +} // namespace ranges + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER > 17 + +#endif // _LIBCPP___ALGORITHM_RANGES_PARTITION_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/ranges_partition_copy.h b/app/src/main/cpp/libcxx/include/__algorithm/ranges_partition_copy.h new file mode 100644 index 0000000..e7a9a34 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/ranges_partition_copy.h @@ -0,0 +1,98 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_RANGES_PARTITION_COPY_H +#define _LIBCPP___ALGORITHM_RANGES_PARTITION_COPY_H + +#include <__algorithm/in_out_out_result.h> +#include <__config> +#include <__functional/identity.h> +#include <__functional/invoke.h> +#include <__iterator/concepts.h> +#include <__iterator/iterator_traits.h> +#include <__iterator/projected.h> +#include <__ranges/access.h> +#include <__ranges/concepts.h> +#include <__ranges/dangling.h> +#include <__utility/move.h> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if _LIBCPP_STD_VER > 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace ranges { + +template +using partition_copy_result = in_out_out_result<_InIter, _OutIter1, _OutIter2>; + +namespace __partition_copy { + +struct __fn { + + // TODO(ranges): delegate to the classic algorithm. + template + _LIBCPP_HIDE_FROM_ABI constexpr + static partition_copy_result< + __remove_cvref_t<_InIter>, __remove_cvref_t<_OutIter1>, __remove_cvref_t<_OutIter2> + > __partition_copy_fn_impl( _InIter&& __first, _Sent&& __last, _OutIter1&& __out_true, _OutIter2&& __out_false, + _Pred& __pred, _Proj& __proj) { + for (; __first != __last; ++__first) { + if (std::invoke(__pred, std::invoke(__proj, *__first))) { + *__out_true = *__first; + ++__out_true; + + } else { + *__out_false = *__first; + ++__out_false; + } + } + + return {std::move(__first), std::move(__out_true), std::move(__out_false)}; + } + + template _Sent, + weakly_incrementable _OutIter1, weakly_incrementable _OutIter2, + class _Proj = identity, indirect_unary_predicate> _Pred> + requires indirectly_copyable<_InIter, _OutIter1> && indirectly_copyable<_InIter, _OutIter2> + _LIBCPP_HIDE_FROM_ABI constexpr + partition_copy_result<_InIter, _OutIter1, _OutIter2> + operator()(_InIter __first, _Sent __last, _OutIter1 __out_true, _OutIter2 __out_false, + _Pred __pred, _Proj __proj = {}) const { + return __partition_copy_fn_impl( + std::move(__first), std::move(__last), std::move(__out_true), std::move(__out_false), __pred, __proj); + } + + template , _Proj>> _Pred> + requires indirectly_copyable, _OutIter1> && indirectly_copyable, _OutIter2> + _LIBCPP_HIDE_FROM_ABI constexpr + partition_copy_result, _OutIter1, _OutIter2> + operator()(_Range&& __range, _OutIter1 __out_true, _OutIter2 __out_false, _Pred __pred, _Proj __proj = {}) const { + return __partition_copy_fn_impl( + ranges::begin(__range), ranges::end(__range), std::move(__out_true), std::move(__out_false), __pred, __proj); + } + +}; + +} // namespace __partition_copy + +inline namespace __cpo { + inline constexpr auto partition_copy = __partition_copy::__fn{}; +} // namespace __cpo +} // namespace ranges + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER > 17 + +#endif // _LIBCPP___ALGORITHM_RANGES_PARTITION_COPY_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/ranges_partition_point.h b/app/src/main/cpp/libcxx/include/__algorithm/ranges_partition_point.h new file mode 100644 index 0000000..2bd118d --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/ranges_partition_point.h @@ -0,0 +1,88 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_RANGES_PARTITION_POINT_H +#define _LIBCPP___ALGORITHM_RANGES_PARTITION_POINT_H + +#include <__algorithm/half_positive.h> +#include <__config> +#include <__functional/identity.h> +#include <__functional/invoke.h> +#include <__iterator/concepts.h> +#include <__iterator/distance.h> +#include <__iterator/iterator_traits.h> +#include <__iterator/next.h> +#include <__iterator/projected.h> +#include <__ranges/access.h> +#include <__ranges/concepts.h> +#include <__ranges/dangling.h> +#include <__utility/move.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if _LIBCPP_STD_VER > 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace ranges { +namespace __partition_point { + +struct __fn { + + // TODO(ranges): delegate to the classic algorithm. + template + _LIBCPP_HIDE_FROM_ABI constexpr + static _Iter __partition_point_fn_impl(_Iter&& __first, _Sent&& __last, _Pred& __pred, _Proj& __proj) { + auto __len = ranges::distance(__first, __last); + + while (__len != 0) { + auto __half_len = std::__half_positive(__len); + auto __mid = ranges::next(__first, __half_len); + + if (std::invoke(__pred, std::invoke(__proj, *__mid))) { + __first = ++__mid; + __len -= __half_len + 1; + + } else { + __len = __half_len; + } + } + + return __first; + } + + template _Sent, class _Proj = identity, + indirect_unary_predicate> _Pred> + _LIBCPP_HIDE_FROM_ABI constexpr + _Iter operator()(_Iter __first, _Sent __last, _Pred __pred, _Proj __proj = {}) const { + return __partition_point_fn_impl(std::move(__first), std::move(__last), __pred, __proj); + } + + template , _Proj>> _Pred> + _LIBCPP_HIDE_FROM_ABI constexpr + borrowed_iterator_t<_Range> operator()(_Range&& __range, _Pred __pred, _Proj __proj = {}) const { + return __partition_point_fn_impl(ranges::begin(__range), ranges::end(__range), __pred, __proj); + } + +}; + +} // namespace __partition_point + +inline namespace __cpo { + inline constexpr auto partition_point = __partition_point::__fn{}; +} // namespace __cpo +} // namespace ranges + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER > 17 + +#endif // _LIBCPP___ALGORITHM_RANGES_PARTITION_POINT_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/ranges_pop_heap.h b/app/src/main/cpp/libcxx/include/__algorithm/ranges_pop_heap.h new file mode 100644 index 0000000..65beec8 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/ranges_pop_heap.h @@ -0,0 +1,81 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_RANGES_POP_HEAP_H +#define _LIBCPP___ALGORITHM_RANGES_POP_HEAP_H + +#include <__algorithm/iterator_operations.h> +#include <__algorithm/make_projected.h> +#include <__algorithm/pop_heap.h> +#include <__concepts/same_as.h> +#include <__config> +#include <__functional/identity.h> +#include <__functional/invoke.h> +#include <__functional/ranges_operations.h> +#include <__iterator/concepts.h> +#include <__iterator/iterator_traits.h> +#include <__iterator/next.h> +#include <__iterator/projected.h> +#include <__iterator/sortable.h> +#include <__ranges/access.h> +#include <__ranges/concepts.h> +#include <__ranges/dangling.h> +#include <__utility/forward.h> +#include <__utility/move.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if _LIBCPP_STD_VER > 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace ranges { +namespace __pop_heap { + +struct __fn { + template + _LIBCPP_HIDE_FROM_ABI constexpr static + _Iter __pop_heap_fn_impl(_Iter __first, _Sent __last, _Comp& __comp, _Proj& __proj) { + auto __last_iter = ranges::next(__first, __last); + auto __len = __last_iter - __first; + + auto&& __projected_comp = std::__make_projected(__comp, __proj); + std::__pop_heap<_RangeAlgPolicy>(std::move(__first), __last_iter, __projected_comp, __len); + + return __last_iter; + } + + template _Sent, class _Comp = ranges::less, class _Proj = identity> + requires sortable<_Iter, _Comp, _Proj> + _LIBCPP_HIDE_FROM_ABI constexpr + _Iter operator()(_Iter __first, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) const { + return __pop_heap_fn_impl(std::move(__first), std::move(__last), __comp, __proj); + } + + template + requires sortable, _Comp, _Proj> + _LIBCPP_HIDE_FROM_ABI constexpr + borrowed_iterator_t<_Range> operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const { + return __pop_heap_fn_impl(ranges::begin(__r), ranges::end(__r), __comp, __proj); + } +}; + +} // namespace __pop_heap + +inline namespace __cpo { + inline constexpr auto pop_heap = __pop_heap::__fn{}; +} // namespace __cpo +} // namespace ranges + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER > 17 + +#endif // _LIBCPP___ALGORITHM_RANGES_POP_HEAP_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/ranges_prev_permutation.h b/app/src/main/cpp/libcxx/include/__algorithm/ranges_prev_permutation.h new file mode 100644 index 0000000..6866d90 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/ranges_prev_permutation.h @@ -0,0 +1,77 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_RANGES_PREV_PERMUTATION_H +#define _LIBCPP___ALGORITHM_RANGES_PREV_PERMUTATION_H + +#include <__algorithm/in_found_result.h> +#include <__algorithm/iterator_operations.h> +#include <__algorithm/make_projected.h> +#include <__algorithm/prev_permutation.h> +#include <__config> +#include <__functional/identity.h> +#include <__functional/ranges_operations.h> +#include <__iterator/concepts.h> +#include <__iterator/sortable.h> +#include <__ranges/access.h> +#include <__ranges/concepts.h> +#include <__ranges/dangling.h> +#include <__utility/move.h> +#include <__utility/pair.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if _LIBCPP_STD_VER > 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace ranges { + +template +using prev_permutation_result = in_found_result<_InIter>; + +namespace __prev_permutation { + +struct __fn { + + template _Sent, + class _Comp = ranges::less, class _Proj = identity> + requires sortable<_Iter, _Comp, _Proj> + _LIBCPP_HIDE_FROM_ABI constexpr prev_permutation_result<_Iter> + operator()(_Iter __first, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) const { + auto __result = std::__prev_permutation<_RangeAlgPolicy>( + std::move(__first), std::move(__last), std::__make_projected(__comp, __proj)); + return {std::move(__result.first), std::move(__result.second)}; + } + + template + requires sortable, _Comp, _Proj> + _LIBCPP_HIDE_FROM_ABI constexpr prev_permutation_result> + operator()(_Range&& __range, _Comp __comp = {}, _Proj __proj = {}) const { + auto __result = std::__prev_permutation<_RangeAlgPolicy>( + ranges::begin(__range), ranges::end(__range), std::__make_projected(__comp, __proj)); + return {std::move(__result.first), std::move(__result.second)}; + } + +}; + +} // namespace __prev_permutation + +inline namespace __cpo { +constexpr inline auto prev_permutation = __prev_permutation::__fn{}; +} // namespace __cpo +} // namespace ranges + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER > 17 + +#endif // _LIBCPP___ALGORITHM_RANGES_PREV_PERMUTATION_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/ranges_push_heap.h b/app/src/main/cpp/libcxx/include/__algorithm/ranges_push_heap.h new file mode 100644 index 0000000..a1f4347 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/ranges_push_heap.h @@ -0,0 +1,80 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_RANGES_PUSH_HEAP_H +#define _LIBCPP___ALGORITHM_RANGES_PUSH_HEAP_H + +#include <__algorithm/iterator_operations.h> +#include <__algorithm/make_projected.h> +#include <__algorithm/push_heap.h> +#include <__concepts/same_as.h> +#include <__config> +#include <__functional/identity.h> +#include <__functional/invoke.h> +#include <__functional/ranges_operations.h> +#include <__iterator/concepts.h> +#include <__iterator/iterator_traits.h> +#include <__iterator/next.h> +#include <__iterator/projected.h> +#include <__iterator/sortable.h> +#include <__ranges/access.h> +#include <__ranges/concepts.h> +#include <__ranges/dangling.h> +#include <__utility/forward.h> +#include <__utility/move.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if _LIBCPP_STD_VER > 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace ranges { +namespace __push_heap { + +struct __fn { + template + _LIBCPP_HIDE_FROM_ABI constexpr static + _Iter __push_heap_fn_impl(_Iter __first, _Sent __last, _Comp& __comp, _Proj& __proj) { + auto __last_iter = ranges::next(__first, __last); + + auto&& __projected_comp = std::__make_projected(__comp, __proj); + std::__push_heap<_RangeAlgPolicy>(std::move(__first), __last_iter, __projected_comp); + + return __last_iter; + } + + template _Sent, class _Comp = ranges::less, class _Proj = identity> + requires sortable<_Iter, _Comp, _Proj> + _LIBCPP_HIDE_FROM_ABI constexpr + _Iter operator()(_Iter __first, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) const { + return __push_heap_fn_impl(std::move(__first), std::move(__last), __comp, __proj); + } + + template + requires sortable, _Comp, _Proj> + _LIBCPP_HIDE_FROM_ABI constexpr + borrowed_iterator_t<_Range> operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const { + return __push_heap_fn_impl(ranges::begin(__r), ranges::end(__r), __comp, __proj); + } +}; + +} // namespace __push_heap + +inline namespace __cpo { + inline constexpr auto push_heap = __push_heap::__fn{}; +} // namespace __cpo +} // namespace ranges + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER > 17 + +#endif // _LIBCPP___ALGORITHM_RANGES_PUSH_HEAP_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/ranges_remove.h b/app/src/main/cpp/libcxx/include/__algorithm/ranges_remove.h new file mode 100644 index 0000000..dd5c5fb --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/ranges_remove.h @@ -0,0 +1,64 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_RANGES_REMOVE_H +#define _LIBCPP___ALGORITHM_RANGES_REMOVE_H +#include <__config> + +#include <__algorithm/ranges_remove_if.h> +#include <__functional/identity.h> +#include <__functional/ranges_operations.h> +#include <__iterator/concepts.h> +#include <__iterator/permutable.h> +#include <__iterator/projected.h> +#include <__ranges/access.h> +#include <__ranges/concepts.h> +#include <__ranges/subrange.h> +#include <__utility/move.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if _LIBCPP_STD_VER > 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace ranges { +namespace __remove { +struct __fn { + + template _Sent, class _Type, class _Proj = identity> + requires indirect_binary_predicate, const _Type*> + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr + subrange<_Iter> operator()(_Iter __first, _Sent __last, const _Type& __value, _Proj __proj = {}) const { + auto __pred = [&](auto&& __other) { return __value == __other; }; + return ranges::__remove_if_impl(std::move(__first), std::move(__last), __pred, __proj); + } + + template + requires permutable> + && indirect_binary_predicate, _Proj>, const _Type*> + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr + borrowed_subrange_t<_Range> operator()(_Range&& __range, const _Type& __value, _Proj __proj = {}) const { + auto __pred = [&](auto&& __other) { return __value == __other; }; + return ranges::__remove_if_impl(ranges::begin(__range), ranges::end(__range), __pred, __proj); + } +}; +} // namespace __remove + +inline namespace __cpo { + inline constexpr auto remove = __remove::__fn{}; +} // namespace __cpo +} // namespace ranges + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER > 17 + +#endif // _LIBCPP___ALGORITHM_RANGES_REMOVE_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/ranges_remove_copy.h b/app/src/main/cpp/libcxx/include/__algorithm/ranges_remove_copy.h new file mode 100644 index 0000000..2102228 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/ranges_remove_copy.h @@ -0,0 +1,76 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_RANGES_REMOVE_COPY_H +#define _LIBCPP___ALGORITHM_RANGES_REMOVE_COPY_H + +#include <__algorithm/in_out_result.h> +#include <__algorithm/ranges_remove_copy_if.h> +#include <__config> +#include <__functional/identity.h> +#include <__functional/invoke.h> +#include <__functional/ranges_operations.h> +#include <__iterator/concepts.h> +#include <__iterator/projected.h> +#include <__ranges/access.h> +#include <__ranges/concepts.h> +#include <__ranges/dangling.h> +#include <__utility/move.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if _LIBCPP_STD_VER > 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace ranges { + +template +using remove_copy_result = in_out_result<_InIter, _OutIter>; + +namespace __remove_copy { + + struct __fn { + template _Sent, + weakly_incrementable _OutIter, + class _Type, + class _Proj = identity> + requires indirectly_copyable<_InIter, _OutIter> && + indirect_binary_predicate, const _Type*> + _LIBCPP_HIDE_FROM_ABI constexpr remove_copy_result<_InIter, _OutIter> + operator()(_InIter __first, _Sent __last, _OutIter __result, const _Type& __value, _Proj __proj = {}) const { + auto __pred = [&](auto&& __val) { return __value == __val; }; + return ranges::__remove_copy_if_impl(std::move(__first), std::move(__last), std::move(__result), __pred, __proj); + } + + template + requires indirectly_copyable, _OutIter> && + indirect_binary_predicate, _Proj>, const _Type*> + _LIBCPP_HIDE_FROM_ABI constexpr remove_copy_result, _OutIter> + operator()(_Range&& __range, _OutIter __result, const _Type& __value, _Proj __proj = {}) const { + auto __pred = [&](auto&& __val) { return __value == __val; }; + return ranges::__remove_copy_if_impl( + ranges::begin(__range), ranges::end(__range), std::move(__result), __pred, __proj); + } + }; + +} // namespace __remove_copy + +inline namespace __cpo { + inline constexpr auto remove_copy = __remove_copy::__fn{}; +} // namespace __cpo +} // namespace ranges + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER > 17 + +#endif // _LIBCPP___ALGORITHM_RANGES_REMOVE_COPY_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/ranges_remove_copy_if.h b/app/src/main/cpp/libcxx/include/__algorithm/ranges_remove_copy_if.h new file mode 100644 index 0000000..4fc6745 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/ranges_remove_copy_if.h @@ -0,0 +1,90 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_RANGES_REMOVE_COPY_IF_H +#define _LIBCPP___ALGORITHM_RANGES_REMOVE_COPY_IF_H + +#include <__algorithm/in_out_result.h> +#include <__algorithm/make_projected.h> +#include <__algorithm/remove_copy_if.h> +#include <__config> +#include <__functional/identity.h> +#include <__functional/invoke.h> +#include <__functional/ranges_operations.h> +#include <__iterator/concepts.h> +#include <__iterator/iterator_traits.h> +#include <__iterator/projected.h> +#include <__ranges/access.h> +#include <__ranges/concepts.h> +#include <__ranges/dangling.h> +#include <__utility/forward.h> +#include <__utility/move.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if _LIBCPP_STD_VER > 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace ranges { + +template +using remove_copy_if_result = in_out_result<_InIter, _OutIter>; + +template +_LIBCPP_HIDE_FROM_ABI constexpr in_out_result<_InIter, _OutIter> +__remove_copy_if_impl(_InIter __first, _Sent __last, _OutIter __result, _Pred& __pred, _Proj& __proj) { + for (; __first != __last; ++__first) { + if (!std::invoke(__pred, std::invoke(__proj, *__first))) { + *__result = *__first; + ++__result; + } + } + return {std::move(__first), std::move(__result)}; +} + +namespace __remove_copy_if { + + struct __fn { + template _Sent, + weakly_incrementable _OutIter, + class _Proj = identity, + indirect_unary_predicate> _Pred> + requires indirectly_copyable<_InIter, _OutIter> + _LIBCPP_HIDE_FROM_ABI constexpr remove_copy_if_result<_InIter, _OutIter> + operator()(_InIter __first, _Sent __last, _OutIter __result, _Pred __pred, _Proj __proj = {}) const { + return ranges::__remove_copy_if_impl(std::move(__first), std::move(__last), std::move(__result), __pred, __proj); + } + + template , _Proj>> _Pred> + requires indirectly_copyable, _OutIter> + _LIBCPP_HIDE_FROM_ABI constexpr remove_copy_if_result, _OutIter> + operator()(_Range&& __range, _OutIter __result, _Pred __pred, _Proj __proj = {}) const { + return ranges::__remove_copy_if_impl( + ranges::begin(__range), ranges::end(__range), std::move(__result), __pred, __proj); + } + }; + +} // namespace __remove_copy_if + +inline namespace __cpo { + inline constexpr auto remove_copy_if = __remove_copy_if::__fn{}; +} // namespace __cpo +} // namespace ranges + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER > 17 + +#endif // _LIBCPP___ALGORITHM_RANGES_REMOVE_COPY_IF_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/ranges_remove_if.h b/app/src/main/cpp/libcxx/include/__algorithm/ranges_remove_if.h new file mode 100644 index 0000000..1f17467 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/ranges_remove_if.h @@ -0,0 +1,85 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_RANGES_REMOVE_IF_H +#define _LIBCPP___ALGORITHM_RANGES_REMOVE_IF_H +#include <__config> + +#include <__algorithm/ranges_find_if.h> +#include <__functional/identity.h> +#include <__functional/invoke.h> +#include <__functional/ranges_operations.h> +#include <__iterator/concepts.h> +#include <__iterator/iter_move.h> +#include <__iterator/permutable.h> +#include <__iterator/projected.h> +#include <__ranges/access.h> +#include <__ranges/concepts.h> +#include <__ranges/subrange.h> +#include <__utility/move.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if _LIBCPP_STD_VER > 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace ranges { + +template +_LIBCPP_HIDE_FROM_ABI constexpr +subrange<_Iter> __remove_if_impl(_Iter __first, _Sent __last, _Pred& __pred, _Proj& __proj) { + auto __new_end = ranges::__find_if_impl(__first, __last, __pred, __proj); + if (__new_end == __last) + return {__new_end, __new_end}; + + _Iter __i = __new_end; + while (++__i != __last) { + if (!std::invoke(__pred, std::invoke(__proj, *__i))) { + *__new_end = ranges::iter_move(__i); + ++__new_end; + } + } + return {__new_end, __i}; +} + +namespace __remove_if { +struct __fn { + + template _Sent, + class _Proj = identity, + indirect_unary_predicate> _Pred> + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr + subrange<_Iter> operator()(_Iter __first, _Sent __last, _Pred __pred, _Proj __proj = {}) const { + return ranges::__remove_if_impl(std::move(__first), std::move(__last), __pred, __proj); + } + + template , _Proj>> _Pred> + requires permutable> + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr + borrowed_subrange_t<_Range> operator()(_Range&& __range, _Pred __pred, _Proj __proj = {}) const { + return ranges::__remove_if_impl(ranges::begin(__range), ranges::end(__range), __pred, __proj); + } + +}; +} // namespace __remove_if + +inline namespace __cpo { + inline constexpr auto remove_if = __remove_if::__fn{}; +} // namespace __cpo +} // namespace ranges + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER > 17 + +#endif // _LIBCPP___ALGORITHM_RANGES_REMOVE_IF_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/ranges_replace.h b/app/src/main/cpp/libcxx/include/__algorithm/ranges_replace.h new file mode 100644 index 0000000..8b12bea --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/ranges_replace.h @@ -0,0 +1,74 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_RANGES_REPLACE_H +#define _LIBCPP___ALGORITHM_RANGES_REPLACE_H + +#include <__algorithm/ranges_replace_if.h> +#include <__config> +#include <__functional/identity.h> +#include <__functional/ranges_operations.h> +#include <__iterator/concepts.h> +#include <__iterator/projected.h> +#include <__ranges/access.h> +#include <__ranges/concepts.h> +#include <__ranges/dangling.h> +#include <__utility/move.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if _LIBCPP_STD_VER > 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace ranges { +namespace __replace { +struct __fn { + + template _Sent, + class _Type1, + class _Type2, + class _Proj = identity> + requires indirectly_writable<_Iter, const _Type2&> + && indirect_binary_predicate, const _Type1*> + _LIBCPP_HIDE_FROM_ABI constexpr + _Iter operator()(_Iter __first, _Sent __last, + const _Type1& __old_value, + const _Type2& __new_value, + _Proj __proj = {}) const { + auto __pred = [&](const auto& __val) { return __val == __old_value; }; + return ranges::__replace_if_impl(std::move(__first), std::move(__last), __pred, __new_value, __proj); + } + + template + requires indirectly_writable, const _Type2&> + && indirect_binary_predicate, _Proj>, const _Type1*> + _LIBCPP_HIDE_FROM_ABI constexpr borrowed_iterator_t<_Range> + operator()(_Range&& __range, const _Type1& __old_value, const _Type2& __new_value, _Proj __proj = {}) const { + auto __pred = [&](auto&& __val) { return __val == __old_value; }; + return ranges::__replace_if_impl(ranges::begin(__range), ranges::end(__range), __pred, __new_value, __proj); + } + +}; +} // namespace __replace + +inline namespace __cpo { + inline constexpr auto replace = __replace::__fn{}; +} // namespace __cpo +} // namespace ranges + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER > 17 + +#endif // _LIBCPP___ALGORITHM_RANGES_REPLACE_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/ranges_replace_copy.h b/app/src/main/cpp/libcxx/include/__algorithm/ranges_replace_copy.h new file mode 100644 index 0000000..f87a236 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/ranges_replace_copy.h @@ -0,0 +1,91 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_RANGES_REPLACE_COPY_H +#define _LIBCPP___ALGORITHM_RANGES_REPLACE_COPY_H + +#include <__algorithm/in_out_result.h> +#include <__algorithm/ranges_replace_copy_if.h> +#include <__config> +#include <__functional/identity.h> +#include <__functional/invoke.h> +#include <__functional/ranges_operations.h> +#include <__iterator/concepts.h> +#include <__iterator/projected.h> +#include <__ranges/access.h> +#include <__ranges/concepts.h> +#include <__ranges/dangling.h> +#include <__utility/move.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if _LIBCPP_STD_VER > 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace ranges { + +template +using replace_copy_result = in_out_result<_InIter, _OutIter>; + +namespace __replace_copy { + + struct __fn { + template _Sent, + class _OldType, + class _NewType, + output_iterator _OutIter, + class _Proj = identity> + requires indirectly_copyable<_InIter, _OutIter> && + indirect_binary_predicate, const _OldType*> + _LIBCPP_HIDE_FROM_ABI constexpr replace_copy_result<_InIter, _OutIter> + operator()(_InIter __first, + _Sent __last, + _OutIter __result, + const _OldType& __old_value, + const _NewType& __new_value, + _Proj __proj = {}) const { + auto __pred = [&](const auto& __value) { return __value == __old_value; }; + return ranges::__replace_copy_if_impl( + std::move(__first), std::move(__last), std::move(__result), __pred, __new_value, __proj); + } + + template _OutIter, + class _Proj = identity> + requires indirectly_copyable, _OutIter> && + indirect_binary_predicate, _Proj>, const _OldType*> + _LIBCPP_HIDE_FROM_ABI constexpr replace_copy_result, _OutIter> + operator()(_Range&& __range, + _OutIter __result, + const _OldType& __old_value, + const _NewType& __new_value, + _Proj __proj = {}) const { + auto __pred = [&](const auto& __value) { return __value == __old_value; }; + return ranges::__replace_copy_if_impl( + ranges::begin(__range), ranges::end(__range), std::move(__result), __pred, __new_value, __proj); + } + }; + +} // namespace __replace_copy + +inline namespace __cpo { + inline constexpr auto replace_copy = __replace_copy::__fn{}; +} // namespace __cpo +} // namespace ranges + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER > 17 + +#endif // _LIBCPP___ALGORITHM_RANGES_REPLACE_COPY_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/ranges_replace_copy_if.h b/app/src/main/cpp/libcxx/include/__algorithm/ranges_replace_copy_if.h new file mode 100644 index 0000000..b8741ec --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/ranges_replace_copy_if.h @@ -0,0 +1,93 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_RANGES_REPLACE_COPY_IF_H +#define _LIBCPP___ALGORITHM_RANGES_REPLACE_COPY_IF_H + +#include <__algorithm/in_out_result.h> +#include <__config> +#include <__functional/identity.h> +#include <__functional/invoke.h> +#include <__iterator/concepts.h> +#include <__iterator/projected.h> +#include <__ranges/access.h> +#include <__ranges/concepts.h> +#include <__ranges/dangling.h> +#include <__utility/move.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if _LIBCPP_STD_VER > 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace ranges { + +template +using replace_copy_if_result = in_out_result<_InIter, _OutIter>; + +template +_LIBCPP_HIDE_FROM_ABI constexpr replace_copy_if_result<_InIter, _OutIter> __replace_copy_if_impl( + _InIter __first, _Sent __last, _OutIter __result, _Pred& __pred, const _Type& __new_value, _Proj& __proj) { + while (__first != __last) { + if (std::invoke(__pred, std::invoke(__proj, *__first))) + *__result = __new_value; + else + *__result = *__first; + + ++__first; + ++__result; + } + + return {std::move(__first), std::move(__result)}; +} + +namespace __replace_copy_if { + + struct __fn { + template _Sent, + class _Type, + output_iterator _OutIter, + class _Proj = identity, + indirect_unary_predicate> _Pred> + requires indirectly_copyable<_InIter, _OutIter> + _LIBCPP_HIDE_FROM_ABI constexpr replace_copy_if_result<_InIter, _OutIter> operator()( + _InIter __first, _Sent __last, _OutIter __result, _Pred __pred, const _Type& __new_value, _Proj __proj = {}) + const { + return ranges::__replace_copy_if_impl( + std::move(__first), std::move(__last), std::move(__result), __pred, __new_value, __proj); + } + + template _OutIter, + class _Proj = identity, + indirect_unary_predicate, _Proj>> _Pred> + requires indirectly_copyable, _OutIter> + _LIBCPP_HIDE_FROM_ABI constexpr replace_copy_if_result, _OutIter> + operator()(_Range&& __range, _OutIter __result, _Pred __pred, const _Type& __new_value, _Proj __proj = {}) const { + return ranges::__replace_copy_if_impl( + ranges::begin(__range), ranges::end(__range), std::move(__result), __pred, __new_value, __proj); + } + }; + +} // namespace __replace_copy_if + +inline namespace __cpo { + inline constexpr auto replace_copy_if = __replace_copy_if::__fn{}; +} // namespace __cpo +} // namespace ranges + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER > 17 + +#endif // _LIBCPP___ALGORITHM_RANGES_REPLACE_COPY_IF_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/ranges_replace_if.h b/app/src/main/cpp/libcxx/include/__algorithm/ranges_replace_if.h new file mode 100644 index 0000000..65be3c7 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/ranges_replace_if.h @@ -0,0 +1,77 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_RANGES_REPLACE_IF_H +#define _LIBCPP___ALGORITHM_RANGES_REPLACE_IF_H + +#include <__config> +#include <__functional/identity.h> +#include <__functional/invoke.h> +#include <__iterator/concepts.h> +#include <__iterator/projected.h> +#include <__ranges/access.h> +#include <__ranges/concepts.h> +#include <__ranges/dangling.h> +#include <__utility/move.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if _LIBCPP_STD_VER > 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace ranges { + +template +_LIBCPP_HIDE_FROM_ABI constexpr +_Iter __replace_if_impl(_Iter __first, _Sent __last, _Pred& __pred, const _Type& __new_value, _Proj& __proj) { + for (; __first != __last; ++__first) { + if (std::invoke(__pred, std::invoke(__proj, *__first))) + *__first = __new_value; + } + return __first; +} + +namespace __replace_if { +struct __fn { + + template _Sent, + class _Type, + class _Proj = identity, + indirect_unary_predicate> _Pred> + requires indirectly_writable<_Iter, const _Type&> + _LIBCPP_HIDE_FROM_ABI constexpr + _Iter operator()(_Iter __first, _Sent __last, _Pred __pred, const _Type& __new_value, _Proj __proj = {}) const { + return ranges::__replace_if_impl(std::move(__first), std::move(__last), __pred, __new_value, __proj); + } + + template , _Proj>> _Pred> + requires indirectly_writable, const _Type&> + _LIBCPP_HIDE_FROM_ABI constexpr borrowed_iterator_t<_Range> + operator()(_Range&& __range, _Pred __pred, const _Type& __new_value, _Proj __proj = {}) const { + return ranges::__replace_if_impl(ranges::begin(__range), ranges::end(__range), __pred, __new_value, __proj); + } + +}; +} // namespace __replace_if + +inline namespace __cpo { + inline constexpr auto replace_if = __replace_if::__fn{}; +} // namespace __cpo +} // namespace ranges + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER > 17 + +#endif // _LIBCPP___ALGORITHM_RANGES_REPLACE_IF_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/ranges_reverse.h b/app/src/main/cpp/libcxx/include/__algorithm/ranges_reverse.h new file mode 100644 index 0000000..e2a5d9a --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/ranges_reverse.h @@ -0,0 +1,83 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_RANGES_REVERSE_H +#define _LIBCPP___ALGORITHM_RANGES_REVERSE_H + +#include <__config> +#include <__iterator/concepts.h> +#include <__iterator/iter_swap.h> +#include <__iterator/next.h> +#include <__iterator/permutable.h> +#include <__ranges/access.h> +#include <__ranges/concepts.h> +#include <__ranges/dangling.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if _LIBCPP_STD_VER > 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace ranges { +namespace __reverse { +struct __fn { + + template _Sent> + requires permutable<_Iter> + _LIBCPP_HIDE_FROM_ABI constexpr + _Iter operator()(_Iter __first, _Sent __last) const { + if constexpr (random_access_iterator<_Iter>) { + if (__first == __last) + return __first; + + auto __end = ranges::next(__first, __last); + auto __ret = __end; + + while (__first < --__end) { + ranges::iter_swap(__first, __end); + ++__first; + } + return __ret; + } else { + auto __end = ranges::next(__first, __last); + auto __ret = __end; + + while (__first != __end) { + if (__first == --__end) + break; + + ranges::iter_swap(__first, __end); + ++__first; + } + return __ret; + } + } + + template + requires permutable> + _LIBCPP_HIDE_FROM_ABI constexpr + borrowed_iterator_t<_Range> operator()(_Range&& __range) const { + return (*this)(ranges::begin(__range), ranges::end(__range)); + } + +}; +} // namespace __reverse + +inline namespace __cpo { + inline constexpr auto reverse = __reverse::__fn{}; +} // namespace __cpo +} // namespace ranges + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER > 17 + +#endif // _LIBCPP___ALGORITHM_RANGES_REVERSE_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/ranges_reverse_copy.h b/app/src/main/cpp/libcxx/include/__algorithm/ranges_reverse_copy.h new file mode 100644 index 0000000..a84b1ad --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/ranges_reverse_copy.h @@ -0,0 +1,67 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_RANGES_REVERSE_COPY_H +#define _LIBCPP___ALGORITHM_RANGES_REVERSE_COPY_H + +#include <__algorithm/in_out_result.h> +#include <__algorithm/ranges_copy.h> +#include <__config> +#include <__iterator/concepts.h> +#include <__iterator/next.h> +#include <__iterator/reverse_iterator.h> +#include <__ranges/access.h> +#include <__ranges/concepts.h> +#include <__ranges/dangling.h> +#include <__ranges/subrange.h> +#include <__utility/move.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if _LIBCPP_STD_VER > 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace ranges { + +template +using reverse_copy_result = in_out_result<_InIter, _OutIter>; + +namespace __reverse_copy { +struct __fn { + + template _Sent, weakly_incrementable _OutIter> + requires indirectly_copyable<_InIter, _OutIter> + _LIBCPP_HIDE_FROM_ABI constexpr + reverse_copy_result<_InIter, _OutIter> operator()(_InIter __first, _Sent __last, _OutIter __result) const { + return (*this)(subrange(std::move(__first), std::move(__last)), std::move(__result)); + } + + template + requires indirectly_copyable, _OutIter> + _LIBCPP_HIDE_FROM_ABI constexpr + reverse_copy_result, _OutIter> operator()(_Range&& __range, _OutIter __result) const { + auto __ret = ranges::copy(std::__reverse_range(__range), std::move(__result)); + return {ranges::next(ranges::begin(__range), ranges::end(__range)), std::move(__ret.out)}; + } + +}; +} // namespace __reverse_copy + +inline namespace __cpo { + inline constexpr auto reverse_copy = __reverse_copy::__fn{}; +} // namespace __cpo +} // namespace ranges + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER > 17 + +#endif // _LIBCPP___ALGORITHM_RANGES_REVERSE_COPY_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/ranges_rotate.h b/app/src/main/cpp/libcxx/include/__algorithm/ranges_rotate.h new file mode 100644 index 0000000..91ed402 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/ranges_rotate.h @@ -0,0 +1,71 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_RANGES_ROTATE_H +#define _LIBCPP___ALGORITHM_RANGES_ROTATE_H + +#include <__algorithm/iterator_operations.h> +#include <__algorithm/ranges_iterator_concept.h> +#include <__algorithm/rotate.h> +#include <__config> +#include <__iterator/concepts.h> +#include <__iterator/iterator_traits.h> +#include <__iterator/permutable.h> +#include <__ranges/access.h> +#include <__ranges/concepts.h> +#include <__ranges/subrange.h> +#include <__utility/move.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if _LIBCPP_STD_VER > 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace ranges { +namespace __rotate { + +struct __fn { + + template + _LIBCPP_HIDE_FROM_ABI constexpr + static subrange<_Iter> __rotate_fn_impl(_Iter __first, _Iter __middle, _Sent __last) { + auto __ret = std::__rotate<_RangeAlgPolicy>( + std::move(__first), std::move(__middle), std::move(__last)); + return {std::move(__ret.first), std::move(__ret.second)}; + } + + template _Sent> + _LIBCPP_HIDE_FROM_ABI constexpr + subrange<_Iter> operator()(_Iter __first, _Iter __middle, _Sent __last) const { + return __rotate_fn_impl(std::move(__first), std::move(__middle), std::move(__last)); + } + + template + requires permutable> + _LIBCPP_HIDE_FROM_ABI constexpr + borrowed_subrange_t<_Range> operator()(_Range&& __range, iterator_t<_Range> __middle) const { + return __rotate_fn_impl(ranges::begin(__range), std::move(__middle), ranges::end(__range)); + } + +}; + +} // namespace __rotate + +inline namespace __cpo { + inline constexpr auto rotate = __rotate::__fn{}; +} // namespace __cpo +} // namespace ranges + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER > 17 + +#endif // _LIBCPP___ALGORITHM_RANGES_ROTATE_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/ranges_rotate_copy.h b/app/src/main/cpp/libcxx/include/__algorithm/ranges_rotate_copy.h new file mode 100644 index 0000000..52f403c --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/ranges_rotate_copy.h @@ -0,0 +1,68 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_RANGES_ROTATE_COPY_H +#define _LIBCPP___ALGORITHM_RANGES_ROTATE_COPY_H + +#include <__algorithm/in_out_result.h> +#include <__algorithm/ranges_copy.h> +#include <__config> +#include <__iterator/concepts.h> +#include <__iterator/reverse_iterator.h> +#include <__ranges/access.h> +#include <__ranges/concepts.h> +#include <__ranges/dangling.h> +#include <__utility/move.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if _LIBCPP_STD_VER > 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace ranges { + +template +using rotate_copy_result = in_out_result<_InIter, _OutIter>; + +namespace __rotate_copy { +struct __fn { + + template _Sent, weakly_incrementable _OutIter> + requires indirectly_copyable<_InIter, _OutIter> + _LIBCPP_HIDE_FROM_ABI constexpr + rotate_copy_result<_InIter, _OutIter> + operator()(_InIter __first, _InIter __middle, _Sent __last, _OutIter __result) const { + auto __res1 = ranges::copy(__middle, __last, std::move(__result)); + auto __res2 = ranges::copy(__first, __middle, std::move(__res1.out)); + return {std::move(__res1.in), std::move(__res2.out)}; + } + + template + requires indirectly_copyable, _OutIter> + _LIBCPP_HIDE_FROM_ABI constexpr + rotate_copy_result, _OutIter> + operator()(_Range&& __range, iterator_t<_Range> __middle, _OutIter __result) const { + return (*this)(ranges::begin(__range), std::move(__middle), ranges::end(__range), std::move(__result)); + } + +}; +} // namespace __rotate_copy + +inline namespace __cpo { + inline constexpr auto rotate_copy = __rotate_copy::__fn{}; +} // namespace __cpo +} // namespace ranges + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER > 17 + +#endif // _LIBCPP___ALGORITHM_RANGES_ROTATE_COPY_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/ranges_sample.h b/app/src/main/cpp/libcxx/include/__algorithm/ranges_sample.h new file mode 100644 index 0000000..a37cb64 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/ranges_sample.h @@ -0,0 +1,74 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_RANGES_SAMPLE_H +#define _LIBCPP___ALGORITHM_RANGES_SAMPLE_H + +#include <__algorithm/iterator_operations.h> +#include <__algorithm/sample.h> +#include <__algorithm/uniform_random_bit_generator_adaptor.h> +#include <__config> +#include <__iterator/concepts.h> +#include <__iterator/incrementable_traits.h> +#include <__iterator/iterator_traits.h> +#include <__random/uniform_random_bit_generator.h> +#include <__ranges/access.h> +#include <__ranges/concepts.h> +#include <__utility/forward.h> +#include <__utility/move.h> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if _LIBCPP_STD_VER > 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace ranges { +namespace __sample { + +struct __fn { + + template _Sent, weakly_incrementable _OutIter, class _Gen> + requires (forward_iterator<_Iter> || random_access_iterator<_OutIter>) && + indirectly_copyable<_Iter, _OutIter> && + uniform_random_bit_generator> + _LIBCPP_HIDE_FROM_ABI + _OutIter operator()(_Iter __first, _Sent __last, + _OutIter __out_first, iter_difference_t<_Iter> __n, _Gen&& __gen) const { + _ClassicGenAdaptor<_Gen> __adapted_gen(__gen); + return std::__sample<_RangeAlgPolicy>( + std::move(__first), std::move(__last), std::move(__out_first), __n, __adapted_gen); + } + + template + requires (forward_range<_Range> || random_access_iterator<_OutIter>) && + indirectly_copyable, _OutIter> && + uniform_random_bit_generator> + _LIBCPP_HIDE_FROM_ABI + _OutIter operator()(_Range&& __range, _OutIter __out_first, range_difference_t<_Range> __n, _Gen&& __gen) const { + return (*this)(ranges::begin(__range), ranges::end(__range), + std::move(__out_first), __n, std::forward<_Gen>(__gen)); + } + +}; + +} // namespace __sample + +inline namespace __cpo { + inline constexpr auto sample = __sample::__fn{}; +} // namespace __cpo +} // namespace ranges + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER > 17 + +#endif // _LIBCPP___ALGORITHM_RANGES_SAMPLE_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/ranges_search.h b/app/src/main/cpp/libcxx/include/__algorithm/ranges_search.h new file mode 100644 index 0000000..388d5af --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/ranges_search.h @@ -0,0 +1,135 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_RANGES_SEARCH_H +#define _LIBCPP___ALGORITHM_RANGES_SEARCH_H + +#include <__algorithm/iterator_operations.h> +#include <__algorithm/search.h> +#include <__config> +#include <__functional/identity.h> +#include <__functional/ranges_operations.h> +#include <__iterator/advance.h> +#include <__iterator/concepts.h> +#include <__iterator/distance.h> +#include <__iterator/indirectly_comparable.h> +#include <__ranges/access.h> +#include <__ranges/concepts.h> +#include <__ranges/size.h> +#include <__ranges/subrange.h> +#include <__utility/pair.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if _LIBCPP_STD_VER > 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace ranges { +namespace __search { +struct __fn { + template + _LIBCPP_HIDE_FROM_ABI static constexpr subrange<_Iter1> __ranges_search_impl( + _Iter1 __first1, + _Sent1 __last1, + _Iter2 __first2, + _Sent2 __last2, + _Pred& __pred, + _Proj1& __proj1, + _Proj2& __proj2) { + if constexpr (sized_sentinel_for<_Sent2, _Iter2>) { + auto __size2 = ranges::distance(__first2, __last2); + if (__size2 == 0) + return {__first1, __first1}; + + if constexpr (sized_sentinel_for<_Sent1, _Iter1>) { + auto __size1 = ranges::distance(__first1, __last1); + if (__size1 < __size2) { + ranges::advance(__first1, __last1); + return {__first1, __first1}; + } + + if constexpr (random_access_iterator<_Iter1> && random_access_iterator<_Iter2>) { + auto __ret = std::__search_random_access_impl<_RangeAlgPolicy>( + __first1, __last1, __first2, __last2, __pred, __proj1, __proj2, __size1, __size2); + return {__ret.first, __ret.second}; + } + } + } + + auto __ret = + std::__search_forward_impl<_RangeAlgPolicy>(__first1, __last1, __first2, __last2, __pred, __proj1, __proj2); + return {__ret.first, __ret.second}; + } + + template _Sent1, + forward_iterator _Iter2, sentinel_for<_Iter2> _Sent2, + class _Pred = ranges::equal_to, + class _Proj1 = identity, + class _Proj2 = identity> + requires indirectly_comparable<_Iter1, _Iter2, _Pred, _Proj1, _Proj2> + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr + subrange<_Iter1> operator()(_Iter1 __first1, _Sent1 __last1, + _Iter2 __first2, _Sent2 __last2, + _Pred __pred = {}, + _Proj1 __proj1 = {}, + _Proj2 __proj2 = {}) const { + return __ranges_search_impl(__first1, __last1, __first2, __last2, __pred, __proj1, __proj2); + } + + template + requires indirectly_comparable, iterator_t<_Range2>, _Pred, _Proj1, _Proj2> + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr + borrowed_subrange_t<_Range1> operator()(_Range1&& __range1, + _Range2&& __range2, + _Pred __pred = {}, + _Proj1 __proj1 = {}, + _Proj2 __proj2 = {}) const { + auto __first1 = ranges::begin(__range1); + if constexpr (sized_range<_Range2>) { + auto __size2 = ranges::size(__range2); + if (__size2 == 0) + return {__first1, __first1}; + if constexpr (sized_range<_Range1>) { + auto __size1 = ranges::size(__range1); + if (__size1 < __size2) { + ranges::advance(__first1, ranges::end(__range1)); + return {__first1, __first1}; + } + } + } + + return __ranges_search_impl( + ranges::begin(__range1), + ranges::end(__range1), + ranges::begin(__range2), + ranges::end(__range2), + __pred, + __proj1, + __proj2); + } + +}; +} // namespace __search + +inline namespace __cpo { + inline constexpr auto search = __search::__fn{}; +} // namespace __cpo +} // namespace ranges + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER > 17 + +#endif // _LIBCPP___ALGORITHM_RANGES_SEARCH_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/ranges_search_n.h b/app/src/main/cpp/libcxx/include/__algorithm/ranges_search_n.h new file mode 100644 index 0000000..56ec8f3 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/ranges_search_n.h @@ -0,0 +1,117 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_RANGES_SEARCH_N_H +#define _LIBCPP___ALGORITHM_RANGES_SEARCH_N_H + +#include <__algorithm/iterator_operations.h> +#include <__algorithm/search_n.h> +#include <__config> +#include <__functional/identity.h> +#include <__functional/ranges_operations.h> +#include <__iterator/advance.h> +#include <__iterator/concepts.h> +#include <__iterator/distance.h> +#include <__iterator/incrementable_traits.h> +#include <__iterator/indirectly_comparable.h> +#include <__iterator/iterator_traits.h> +#include <__ranges/access.h> +#include <__ranges/concepts.h> +#include <__ranges/size.h> +#include <__ranges/subrange.h> +#include <__utility/move.h> +#include <__utility/pair.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if _LIBCPP_STD_VER > 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace ranges { +namespace __search_n { +struct __fn { + + template + _LIBCPP_HIDE_FROM_ABI static constexpr subrange<_Iter1> __ranges_search_n_impl( + _Iter1 __first, _Sent1 __last, _SizeT __count, const _Type& __value, _Pred& __pred, _Proj& __proj) { + if (__count == 0) + return {__first, __first}; + + if constexpr (sized_sentinel_for<_Sent1, _Iter1>) { + auto __size = ranges::distance(__first, __last); + if (__size < __count) { + ranges::advance(__first, __last); + return {__first, __first}; + } + + if constexpr (random_access_iterator<_Iter1>) { + auto __ret = std::__search_n_random_access_impl<_RangeAlgPolicy>( + __first, __last, __count, __value, __pred, __proj, __size); + return {std::move(__ret.first), std::move(__ret.second)}; + } + } + + auto __ret = std::__search_n_forward_impl<_RangeAlgPolicy>(__first, __last, + __count, + __value, + __pred, + __proj); + return {std::move(__ret.first), std::move(__ret.second)}; + } + + template _Sent, + class _Type, + class _Pred = ranges::equal_to, + class _Proj = identity> + requires indirectly_comparable<_Iter, const _Type*, _Pred, _Proj> + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr + subrange<_Iter> operator()(_Iter __first, _Sent __last, + iter_difference_t<_Iter> __count, + const _Type& __value, + _Pred __pred = {}, + _Proj __proj = _Proj{}) const { + return __ranges_search_n_impl(__first, __last, __count, __value, __pred, __proj); + } + + template + requires indirectly_comparable, const _Type*, _Pred, _Proj> + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr + borrowed_subrange_t<_Range> operator()(_Range&& __range, + range_difference_t<_Range> __count, + const _Type& __value, + _Pred __pred = {}, + _Proj __proj = {}) const { + auto __first = ranges::begin(__range); + if (__count <= 0) + return {__first, __first}; + if constexpr (sized_range<_Range>) { + auto __size1 = ranges::size(__range); + if (__size1 < static_cast>(__count)) { + ranges::advance(__first, ranges::end(__range)); + return {__first, __first}; + } + } + + return __ranges_search_n_impl(ranges::begin(__range), ranges::end(__range), __count, __value, __pred, __proj); + } +}; +} // namespace __search_n + +inline namespace __cpo { + inline constexpr auto search_n = __search_n::__fn{}; +} // namespace __cpo +} // namespace ranges + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER > 17 + +#endif // _LIBCPP___ALGORITHM_RANGES_SEARCH_N_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/ranges_set_difference.h b/app/src/main/cpp/libcxx/include/__algorithm/ranges_set_difference.h new file mode 100644 index 0000000..607dd68 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/ranges_set_difference.h @@ -0,0 +1,106 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_RANGES_SET_DIFFERENCE_H +#define _LIBCPP___ALGORITHM_RANGES_SET_DIFFERENCE_H + +#include <__algorithm/in_out_result.h> +#include <__algorithm/iterator_operations.h> +#include <__algorithm/make_projected.h> +#include <__algorithm/set_difference.h> +#include <__config> +#include <__functional/identity.h> +#include <__functional/invoke.h> +#include <__functional/ranges_operations.h> +#include <__iterator/concepts.h> +#include <__iterator/mergeable.h> +#include <__ranges/access.h> +#include <__ranges/concepts.h> +#include <__ranges/dangling.h> +#include <__type_traits/decay.h> +#include <__utility/move.h> +#include <__utility/pair.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if _LIBCPP_STD_VER > 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace ranges { + +template +using set_difference_result = in_out_result<_InIter, _OutIter>; + +namespace __set_difference { + +struct __fn { + template < + input_iterator _InIter1, + sentinel_for<_InIter1> _Sent1, + input_iterator _InIter2, + sentinel_for<_InIter2> _Sent2, + weakly_incrementable _OutIter, + class _Comp = less, + class _Proj1 = identity, + class _Proj2 = identity> + requires mergeable<_InIter1, _InIter2, _OutIter, _Comp, _Proj1, _Proj2> + _LIBCPP_HIDE_FROM_ABI constexpr set_difference_result<_InIter1, _OutIter> operator()( + _InIter1 __first1, + _Sent1 __last1, + _InIter2 __first2, + _Sent2 __last2, + _OutIter __result, + _Comp __comp = {}, + _Proj1 __proj1 = {}, + _Proj2 __proj2 = {}) const { + auto __ret = std::__set_difference<_RangeAlgPolicy>( + __first1, __last1, __first2, __last2, __result, ranges::__make_projected_comp(__comp, __proj1, __proj2)); + return {std::move(__ret.first), std::move(__ret.second)}; + } + + template < + input_range _Range1, + input_range _Range2, + weakly_incrementable _OutIter, + class _Comp = less, + class _Proj1 = identity, + class _Proj2 = identity> + requires mergeable, iterator_t<_Range2>, _OutIter, _Comp, _Proj1, _Proj2> + _LIBCPP_HIDE_FROM_ABI constexpr set_difference_result, _OutIter> + operator()( + _Range1&& __range1, + _Range2&& __range2, + _OutIter __result, + _Comp __comp = {}, + _Proj1 __proj1 = {}, + _Proj2 __proj2 = {}) const { + auto __ret = std::__set_difference<_RangeAlgPolicy>( + ranges::begin(__range1), + ranges::end(__range1), + ranges::begin(__range2), + ranges::end(__range2), + __result, + ranges::__make_projected_comp(__comp, __proj1, __proj2)); + return {std::move(__ret.first), std::move(__ret.second)}; + } +}; + +} // namespace __set_difference + +inline namespace __cpo { + inline constexpr auto set_difference = __set_difference::__fn{}; +} // namespace __cpo +} // namespace ranges + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP___ALGORITHM_RANGES_SET_DIFFERENCE_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/ranges_set_intersection.h b/app/src/main/cpp/libcxx/include/__algorithm/ranges_set_intersection.h new file mode 100644 index 0000000..aa9fd24 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/ranges_set_intersection.h @@ -0,0 +1,117 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_RANGES_SET_INTERSECTION_H +#define _LIBCPP___ALGORITHM_RANGES_SET_INTERSECTION_H + +#include <__algorithm/in_in_out_result.h> +#include <__algorithm/iterator_operations.h> +#include <__algorithm/make_projected.h> +#include <__algorithm/set_intersection.h> +#include <__config> +#include <__functional/identity.h> +#include <__functional/invoke.h> +#include <__functional/ranges_operations.h> +#include <__iterator/concepts.h> +#include <__iterator/mergeable.h> +#include <__ranges/access.h> +#include <__ranges/concepts.h> +#include <__ranges/dangling.h> +#include <__utility/move.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if _LIBCPP_STD_VER > 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace ranges { + +template +using set_intersection_result = in_in_out_result<_InIter1, _InIter2, _OutIter>; + +namespace __set_intersection { + +struct __fn { + template < + input_iterator _InIter1, + sentinel_for<_InIter1> _Sent1, + input_iterator _InIter2, + sentinel_for<_InIter2> _Sent2, + weakly_incrementable _OutIter, + class _Comp = less, + class _Proj1 = identity, + class _Proj2 = identity> + requires mergeable<_InIter1, _InIter2, _OutIter, _Comp, _Proj1, _Proj2> + _LIBCPP_HIDE_FROM_ABI constexpr set_intersection_result<_InIter1, _InIter2, _OutIter> operator()( + _InIter1 __first1, + _Sent1 __last1, + _InIter2 __first2, + _Sent2 __last2, + _OutIter __result, + _Comp __comp = {}, + _Proj1 __proj1 = {}, + _Proj2 __proj2 = {}) const { + auto __ret = std::__set_intersection<_RangeAlgPolicy>( + std::move(__first1), + std::move(__last1), + std::move(__first2), + std::move(__last2), + std::move(__result), + ranges::__make_projected_comp(__comp, __proj1, __proj2)); + return {std::move(__ret.__in1_), std::move(__ret.__in2_), std::move(__ret.__out_)}; + } + + template < + input_range _Range1, + input_range _Range2, + weakly_incrementable _OutIter, + class _Comp = less, + class _Proj1 = identity, + class _Proj2 = identity> + requires mergeable< + iterator_t<_Range1>, + iterator_t<_Range2>, + _OutIter, + _Comp, + _Proj1, + _Proj2> + _LIBCPP_HIDE_FROM_ABI constexpr set_intersection_result, + borrowed_iterator_t<_Range2>, + _OutIter> + operator()( + _Range1&& __range1, + _Range2&& __range2, + _OutIter __result, + _Comp __comp = {}, + _Proj1 __proj1 = {}, + _Proj2 __proj2 = {}) const { + auto __ret = std::__set_intersection<_RangeAlgPolicy>( + ranges::begin(__range1), + ranges::end(__range1), + ranges::begin(__range2), + ranges::end(__range2), + std::move(__result), + ranges::__make_projected_comp(__comp, __proj1, __proj2)); + return {std::move(__ret.__in1_), std::move(__ret.__in2_), std::move(__ret.__out_)}; + } +}; + +} // namespace __set_intersection + +inline namespace __cpo { + inline constexpr auto set_intersection = __set_intersection::__fn{}; +} // namespace __cpo +} // namespace ranges + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP___ALGORITHM_RANGES_SET_INTERSECTION_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/ranges_set_symmetric_difference.h b/app/src/main/cpp/libcxx/include/__algorithm/ranges_set_symmetric_difference.h new file mode 100644 index 0000000..bc4a906 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/ranges_set_symmetric_difference.h @@ -0,0 +1,117 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_RANGES_SET_SYMMETRIC_DIFFERENCE_H +#define _LIBCPP___ALGORITHM_RANGES_SET_SYMMETRIC_DIFFERENCE_H + +#include <__algorithm/in_in_out_result.h> +#include <__algorithm/iterator_operations.h> +#include <__algorithm/make_projected.h> +#include <__algorithm/set_symmetric_difference.h> +#include <__config> +#include <__functional/identity.h> +#include <__functional/invoke.h> +#include <__functional/ranges_operations.h> +#include <__iterator/concepts.h> +#include <__iterator/mergeable.h> +#include <__ranges/access.h> +#include <__ranges/concepts.h> +#include <__ranges/dangling.h> +#include <__utility/move.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if _LIBCPP_STD_VER > 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace ranges { + +template +using set_symmetric_difference_result = in_in_out_result<_InIter1, _InIter2, _OutIter>; + +namespace __set_symmetric_difference { + +struct __fn { + template < + input_iterator _InIter1, + sentinel_for<_InIter1> _Sent1, + input_iterator _InIter2, + sentinel_for<_InIter2> _Sent2, + weakly_incrementable _OutIter, + class _Comp = ranges::less, + class _Proj1 = identity, + class _Proj2 = identity> + requires mergeable<_InIter1, _InIter2, _OutIter, _Comp, _Proj1, _Proj2> + _LIBCPP_HIDE_FROM_ABI constexpr set_symmetric_difference_result<_InIter1, _InIter2, _OutIter> operator()( + _InIter1 __first1, + _Sent1 __last1, + _InIter2 __first2, + _Sent2 __last2, + _OutIter __result, + _Comp __comp = {}, + _Proj1 __proj1 = {}, + _Proj2 __proj2 = {}) const { + auto __ret = std::__set_symmetric_difference<_RangeAlgPolicy>( + std::move(__first1), + std::move(__last1), + std::move(__first2), + std::move(__last2), + std::move(__result), + ranges::__make_projected_comp(__comp, __proj1, __proj2)); + return {std::move(__ret.__in1_), std::move(__ret.__in2_), std::move(__ret.__out_)}; + } + + template < + input_range _Range1, + input_range _Range2, + weakly_incrementable _OutIter, + class _Comp = ranges::less, + class _Proj1 = identity, + class _Proj2 = identity> + requires mergeable< + iterator_t<_Range1>, + iterator_t<_Range2>, + _OutIter, + _Comp, + _Proj1, + _Proj2> + _LIBCPP_HIDE_FROM_ABI constexpr set_symmetric_difference_result, + borrowed_iterator_t<_Range2>, + _OutIter> + operator()( + _Range1&& __range1, + _Range2&& __range2, + _OutIter __result, + _Comp __comp = {}, + _Proj1 __proj1 = {}, + _Proj2 __proj2 = {}) const { + auto __ret = std::__set_symmetric_difference<_RangeAlgPolicy>( + ranges::begin(__range1), + ranges::end(__range1), + ranges::begin(__range2), + ranges::end(__range2), + std::move(__result), + ranges::__make_projected_comp(__comp, __proj1, __proj2)); + return {std::move(__ret.__in1_), std::move(__ret.__in2_), std::move(__ret.__out_)}; + } +}; + +} // namespace __set_symmetric_difference + +inline namespace __cpo { + inline constexpr auto set_symmetric_difference = __set_symmetric_difference::__fn{}; +} // namespace __cpo +} // namespace ranges + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP___ALGORITHM_RANGES_SET_SYMMETRIC_DIFFERENCE_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/ranges_set_union.h b/app/src/main/cpp/libcxx/include/__algorithm/ranges_set_union.h new file mode 100644 index 0000000..f8cd45c --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/ranges_set_union.h @@ -0,0 +1,121 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_RANGES_SET_UNION_H +#define _LIBCPP___ALGORITHM_RANGES_SET_UNION_H + +#include <__algorithm/in_in_out_result.h> +#include <__algorithm/iterator_operations.h> +#include <__algorithm/make_projected.h> +#include <__algorithm/set_union.h> +#include <__config> +#include <__functional/identity.h> +#include <__functional/invoke.h> +#include <__functional/ranges_operations.h> +#include <__iterator/concepts.h> +#include <__iterator/iterator_traits.h> +#include <__iterator/mergeable.h> +#include <__iterator/projected.h> +#include <__ranges/access.h> +#include <__ranges/concepts.h> +#include <__ranges/dangling.h> +#include <__utility/forward.h> +#include <__utility/move.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if _LIBCPP_STD_VER > 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace ranges { + +template +using set_union_result = in_in_out_result<_InIter1, _InIter2, _OutIter>; + +namespace __set_union { + +struct __fn { + template < + input_iterator _InIter1, + sentinel_for<_InIter1> _Sent1, + input_iterator _InIter2, + sentinel_for<_InIter2> _Sent2, + weakly_incrementable _OutIter, + class _Comp = ranges::less, + class _Proj1 = identity, + class _Proj2 = identity> + requires mergeable<_InIter1, _InIter2, _OutIter, _Comp, _Proj1, _Proj2> + _LIBCPP_HIDE_FROM_ABI constexpr set_union_result<_InIter1, _InIter2, _OutIter> operator()( + _InIter1 __first1, + _Sent1 __last1, + _InIter2 __first2, + _Sent2 __last2, + _OutIter __result, + _Comp __comp = {}, + _Proj1 __proj1 = {}, + _Proj2 __proj2 = {}) const { + auto __ret = std::__set_union<_RangeAlgPolicy>( + std::move(__first1), + std::move(__last1), + std::move(__first2), + std::move(__last2), + std::move(__result), + ranges::__make_projected_comp(__comp, __proj1, __proj2)); + return {std::move(__ret.__in1_), std::move(__ret.__in2_), std::move(__ret.__out_)}; + } + + template < + input_range _Range1, + input_range _Range2, + weakly_incrementable _OutIter, + class _Comp = ranges::less, + class _Proj1 = identity, + class _Proj2 = identity> + requires mergeable< + iterator_t<_Range1>, + iterator_t<_Range2>, + _OutIter, + _Comp, + _Proj1, + _Proj2> + _LIBCPP_HIDE_FROM_ABI constexpr set_union_result, + borrowed_iterator_t<_Range2>, + _OutIter> + operator()( + _Range1&& __range1, + _Range2&& __range2, + _OutIter __result, + _Comp __comp = {}, + _Proj1 __proj1 = {}, + _Proj2 __proj2 = {}) const { + auto __ret = std::__set_union<_RangeAlgPolicy>( + ranges::begin(__range1), + ranges::end(__range1), + ranges::begin(__range2), + ranges::end(__range2), + std::move(__result), + ranges::__make_projected_comp(__comp, __proj1, __proj2)); + return {std::move(__ret.__in1_), std::move(__ret.__in2_), std::move(__ret.__out_)}; + } +}; + +} // namespace __set_union + +inline namespace __cpo { + inline constexpr auto set_union = __set_union::__fn{}; +} // namespace __cpo +} // namespace ranges + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER > 17 + +#endif // _LIBCPP___ALGORITHM_RANGES_SET_UNION_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/ranges_shuffle.h b/app/src/main/cpp/libcxx/include/__algorithm/ranges_shuffle.h new file mode 100644 index 0000000..a2f2c0e --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/ranges_shuffle.h @@ -0,0 +1,71 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_RANGES_SHUFFLE_H +#define _LIBCPP___ALGORITHM_RANGES_SHUFFLE_H + +#include <__algorithm/iterator_operations.h> +#include <__algorithm/shuffle.h> +#include <__algorithm/uniform_random_bit_generator_adaptor.h> +#include <__config> +#include <__functional/invoke.h> +#include <__functional/ranges_operations.h> +#include <__iterator/concepts.h> +#include <__iterator/iterator_traits.h> +#include <__iterator/next.h> +#include <__iterator/permutable.h> +#include <__random/uniform_random_bit_generator.h> +#include <__ranges/access.h> +#include <__ranges/concepts.h> +#include <__ranges/dangling.h> +#include <__utility/forward.h> +#include <__utility/move.h> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if _LIBCPP_STD_VER > 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace ranges { +namespace __shuffle { + +struct __fn { + + template _Sent, class _Gen> + requires permutable<_Iter> && uniform_random_bit_generator> + _LIBCPP_HIDE_FROM_ABI + _Iter operator()(_Iter __first, _Sent __last, _Gen&& __gen) const { + _ClassicGenAdaptor<_Gen> __adapted_gen(__gen); + return std::__shuffle<_RangeAlgPolicy>(std::move(__first), std::move(__last), __adapted_gen); + } + + template + requires permutable> && uniform_random_bit_generator> + _LIBCPP_HIDE_FROM_ABI + borrowed_iterator_t<_Range> operator()(_Range&& __range, _Gen&& __gen) const { + return (*this)(ranges::begin(__range), ranges::end(__range), std::forward<_Gen>(__gen)); + } + +}; + +} // namespace __shuffle + +inline namespace __cpo { + inline constexpr auto shuffle = __shuffle::__fn{}; +} // namespace __cpo +} // namespace ranges + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER > 17 + +#endif // _LIBCPP___ALGORITHM_RANGES_SHUFFLE_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/ranges_sort.h b/app/src/main/cpp/libcxx/include/__algorithm/ranges_sort.h new file mode 100644 index 0000000..32391df --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/ranges_sort.h @@ -0,0 +1,79 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_RANGES_SORT_H +#define _LIBCPP___ALGORITHM_RANGES_SORT_H + +#include <__algorithm/iterator_operations.h> +#include <__algorithm/make_projected.h> +#include <__algorithm/sort.h> +#include <__config> +#include <__functional/identity.h> +#include <__functional/invoke.h> +#include <__functional/ranges_operations.h> +#include <__iterator/concepts.h> +#include <__iterator/iterator_traits.h> +#include <__iterator/next.h> +#include <__iterator/projected.h> +#include <__iterator/sortable.h> +#include <__ranges/access.h> +#include <__ranges/concepts.h> +#include <__ranges/dangling.h> +#include <__utility/forward.h> +#include <__utility/move.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if _LIBCPP_STD_VER > 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace ranges { +namespace __sort { + +struct __fn { + template + _LIBCPP_HIDE_FROM_ABI constexpr static + _Iter __sort_fn_impl(_Iter __first, _Sent __last, _Comp& __comp, _Proj& __proj) { + auto __last_iter = ranges::next(__first, __last); + + auto&& __projected_comp = std::__make_projected(__comp, __proj); + std::__sort_impl<_RangeAlgPolicy>(std::move(__first), __last_iter, __projected_comp); + + return __last_iter; + } + + template _Sent, class _Comp = ranges::less, class _Proj = identity> + requires sortable<_Iter, _Comp, _Proj> + _LIBCPP_HIDE_FROM_ABI constexpr + _Iter operator()(_Iter __first, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) const { + return __sort_fn_impl(std::move(__first), std::move(__last), __comp, __proj); + } + + template + requires sortable, _Comp, _Proj> + _LIBCPP_HIDE_FROM_ABI constexpr + borrowed_iterator_t<_Range> operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const { + return __sort_fn_impl(ranges::begin(__r), ranges::end(__r), __comp, __proj); + } +}; + +} // namespace __sort + +inline namespace __cpo { + inline constexpr auto sort = __sort::__fn{}; +} // namespace __cpo +} // namespace ranges + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER > 17 + +#endif // _LIBCPP___ALGORITHM_RANGES_SORT_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/ranges_sort_heap.h b/app/src/main/cpp/libcxx/include/__algorithm/ranges_sort_heap.h new file mode 100644 index 0000000..9feb0f6 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/ranges_sort_heap.h @@ -0,0 +1,80 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_RANGES_SORT_HEAP_H +#define _LIBCPP___ALGORITHM_RANGES_SORT_HEAP_H + +#include <__algorithm/iterator_operations.h> +#include <__algorithm/make_projected.h> +#include <__algorithm/sort_heap.h> +#include <__concepts/same_as.h> +#include <__config> +#include <__functional/identity.h> +#include <__functional/invoke.h> +#include <__functional/ranges_operations.h> +#include <__iterator/concepts.h> +#include <__iterator/iterator_traits.h> +#include <__iterator/next.h> +#include <__iterator/projected.h> +#include <__iterator/sortable.h> +#include <__ranges/access.h> +#include <__ranges/concepts.h> +#include <__ranges/dangling.h> +#include <__utility/forward.h> +#include <__utility/move.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if _LIBCPP_STD_VER > 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace ranges { +namespace __sort_heap { + +struct __fn { + template + _LIBCPP_HIDE_FROM_ABI constexpr static + _Iter __sort_heap_fn_impl(_Iter __first, _Sent __last, _Comp& __comp, _Proj& __proj) { + auto __last_iter = ranges::next(__first, __last); + + auto&& __projected_comp = std::__make_projected(__comp, __proj); + std::__sort_heap<_RangeAlgPolicy>(std::move(__first), __last_iter, __projected_comp); + + return __last_iter; + } + + template _Sent, class _Comp = ranges::less, class _Proj = identity> + requires sortable<_Iter, _Comp, _Proj> + _LIBCPP_HIDE_FROM_ABI constexpr + _Iter operator()(_Iter __first, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) const { + return __sort_heap_fn_impl(std::move(__first), std::move(__last), __comp, __proj); + } + + template + requires sortable, _Comp, _Proj> + _LIBCPP_HIDE_FROM_ABI constexpr + borrowed_iterator_t<_Range> operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const { + return __sort_heap_fn_impl(ranges::begin(__r), ranges::end(__r), __comp, __proj); + } +}; + +} // namespace __sort_heap + +inline namespace __cpo { + inline constexpr auto sort_heap = __sort_heap::__fn{}; +} // namespace __cpo +} // namespace ranges + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER > 17 + +#endif // _LIBCPP___ALGORITHM_RANGES_SORT_HEAP_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/ranges_stable_partition.h b/app/src/main/cpp/libcxx/include/__algorithm/ranges_stable_partition.h new file mode 100644 index 0000000..c3469f1 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/ranges_stable_partition.h @@ -0,0 +1,88 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_RANGES_STABLE_PARTITION_H +#define _LIBCPP___ALGORITHM_RANGES_STABLE_PARTITION_H + +#include <__algorithm/iterator_operations.h> +#include <__algorithm/make_projected.h> +#include <__algorithm/ranges_iterator_concept.h> +#include <__algorithm/stable_partition.h> +#include <__config> +#include <__functional/identity.h> +#include <__functional/invoke.h> +#include <__functional/ranges_operations.h> +#include <__iterator/concepts.h> +#include <__iterator/iterator_traits.h> +#include <__iterator/next.h> +#include <__iterator/permutable.h> +#include <__iterator/projected.h> +#include <__ranges/access.h> +#include <__ranges/concepts.h> +#include <__ranges/dangling.h> +#include <__ranges/subrange.h> +#include <__utility/forward.h> +#include <__utility/move.h> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if _LIBCPP_STD_VER > 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace ranges { +namespace __stable_partition { + +struct __fn { + + template + _LIBCPP_HIDE_FROM_ABI static + subrange<__remove_cvref_t<_Iter>> __stable_partition_fn_impl( + _Iter&& __first, _Sent&& __last, _Pred&& __pred, _Proj&& __proj) { + auto __last_iter = ranges::next(__first, __last); + + auto&& __projected_pred = std::__make_projected(__pred, __proj); + auto __result = std::__stable_partition<_RangeAlgPolicy>( + std::move(__first), __last_iter, __projected_pred, __iterator_concept<_Iter>()); + + return {std::move(__result), std::move(__last_iter)}; + } + + template _Sent, class _Proj = identity, + indirect_unary_predicate> _Pred> + requires permutable<_Iter> + _LIBCPP_HIDE_FROM_ABI + subrange<_Iter> operator()(_Iter __first, _Sent __last, _Pred __pred, _Proj __proj = {}) const { + return __stable_partition_fn_impl(__first, __last, __pred, __proj); + } + + template , _Proj>> _Pred> + requires permutable> + _LIBCPP_HIDE_FROM_ABI + borrowed_subrange_t<_Range> operator()(_Range&& __range, _Pred __pred, _Proj __proj = {}) const { + return __stable_partition_fn_impl(ranges::begin(__range), ranges::end(__range), __pred, __proj); + } + +}; + +} // namespace __stable_partition + +inline namespace __cpo { + inline constexpr auto stable_partition = __stable_partition::__fn{}; +} // namespace __cpo +} // namespace ranges + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER > 17 + +#endif // _LIBCPP___ALGORITHM_RANGES_STABLE_PARTITION_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/ranges_stable_sort.h b/app/src/main/cpp/libcxx/include/__algorithm/ranges_stable_sort.h new file mode 100644 index 0000000..d3c48dd --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/ranges_stable_sort.h @@ -0,0 +1,79 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_RANGES_STABLE_SORT_H +#define _LIBCPP___ALGORITHM_RANGES_STABLE_SORT_H + +#include <__algorithm/iterator_operations.h> +#include <__algorithm/make_projected.h> +#include <__algorithm/stable_sort.h> +#include <__config> +#include <__functional/identity.h> +#include <__functional/invoke.h> +#include <__functional/ranges_operations.h> +#include <__iterator/concepts.h> +#include <__iterator/iterator_traits.h> +#include <__iterator/next.h> +#include <__iterator/projected.h> +#include <__iterator/sortable.h> +#include <__ranges/access.h> +#include <__ranges/concepts.h> +#include <__ranges/dangling.h> +#include <__utility/forward.h> +#include <__utility/move.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if _LIBCPP_STD_VER > 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace ranges { +namespace __stable_sort { + +struct __fn { + template + _LIBCPP_HIDE_FROM_ABI + static _Iter __stable_sort_fn_impl(_Iter __first, _Sent __last, _Comp& __comp, _Proj& __proj) { + auto __last_iter = ranges::next(__first, __last); + + auto&& __projected_comp = std::__make_projected(__comp, __proj); + std::__stable_sort_impl<_RangeAlgPolicy>(std::move(__first), __last_iter, __projected_comp); + + return __last_iter; + } + + template _Sent, class _Comp = ranges::less, class _Proj = identity> + requires sortable<_Iter, _Comp, _Proj> + _LIBCPP_HIDE_FROM_ABI + _Iter operator()(_Iter __first, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) const { + return __stable_sort_fn_impl(std::move(__first), std::move(__last), __comp, __proj); + } + + template + requires sortable, _Comp, _Proj> + _LIBCPP_HIDE_FROM_ABI + borrowed_iterator_t<_Range> operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const { + return __stable_sort_fn_impl(ranges::begin(__r), ranges::end(__r), __comp, __proj); + } +}; + +} // namespace __stable_sort + +inline namespace __cpo { + inline constexpr auto stable_sort = __stable_sort::__fn{}; +} // namespace __cpo +} // namespace ranges + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER > 17 + +#endif // _LIBCPP___ALGORITHM_RANGES_STABLE_SORT_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/ranges_swap_ranges.h b/app/src/main/cpp/libcxx/include/__algorithm/ranges_swap_ranges.h new file mode 100644 index 0000000..552fd55 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/ranges_swap_ranges.h @@ -0,0 +1,68 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_RANGES_SWAP_RANGES_H +#define _LIBCPP___ALGORITHM_RANGES_SWAP_RANGES_H + +#include <__algorithm/in_in_result.h> +#include <__algorithm/iterator_operations.h> +#include <__algorithm/swap_ranges.h> +#include <__config> +#include <__iterator/concepts.h> +#include <__iterator/iter_swap.h> +#include <__ranges/access.h> +#include <__ranges/concepts.h> +#include <__ranges/dangling.h> +#include <__utility/move.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if _LIBCPP_STD_VER > 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace ranges { + +template +using swap_ranges_result = in_in_result<_I1, _I2>; + +namespace __swap_ranges { +struct __fn { + template _S1, + input_iterator _I2, sentinel_for<_I2> _S2> + requires indirectly_swappable<_I1, _I2> + _LIBCPP_HIDE_FROM_ABI constexpr swap_ranges_result<_I1, _I2> + operator()(_I1 __first1, _S1 __last1, _I2 __first2, _S2 __last2) const { + auto __ret = std::__swap_ranges<_RangeAlgPolicy>( + std::move(__first1), std::move(__last1), std::move(__first2), std::move(__last2)); + return {std::move(__ret.first), std::move(__ret.second)}; + } + + template + requires indirectly_swappable, iterator_t<_R2>> + _LIBCPP_HIDE_FROM_ABI constexpr + swap_ranges_result, borrowed_iterator_t<_R2>> + operator()(_R1&& __r1, _R2&& __r2) const { + return operator()(ranges::begin(__r1), ranges::end(__r1), + ranges::begin(__r2), ranges::end(__r2)); + } +}; +} // namespace __swap_ranges + +inline namespace __cpo { + inline constexpr auto swap_ranges = __swap_ranges::__fn{}; +} // namespace __cpo +} // namespace ranges + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER > 17 + +#endif // _LIBCPP___ALGORITHM_RANGES_SWAP_RANGES_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/ranges_transform.h b/app/src/main/cpp/libcxx/include/__algorithm/ranges_transform.h new file mode 100644 index 0000000..c0981a0 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/ranges_transform.h @@ -0,0 +1,170 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_RANGES_TRANSFORM_H +#define _LIBCPP___ALGORITHM_RANGES_TRANSFORM_H + +#include <__algorithm/in_in_out_result.h> +#include <__algorithm/in_out_result.h> +#include <__concepts/constructible.h> +#include <__config> +#include <__functional/identity.h> +#include <__functional/invoke.h> +#include <__iterator/concepts.h> +#include <__iterator/projected.h> +#include <__ranges/access.h> +#include <__ranges/concepts.h> +#include <__ranges/dangling.h> +#include <__utility/move.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if _LIBCPP_STD_VER > 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace ranges { + +template +using unary_transform_result = in_out_result<_Ip, _Op>; + +template +using binary_transform_result = in_in_out_result<_I1, _I2, _O1>; + +namespace __transform { +struct __fn { +private: + template + _LIBCPP_HIDE_FROM_ABI static constexpr + unary_transform_result<_InIter, _OutIter> __unary(_InIter __first, _Sent __last, + _OutIter __result, + _Func& __operation, + _Proj& __projection) { + while (__first != __last) { + *__result = std::invoke(__operation, std::invoke(__projection, *__first)); + ++__first; + ++__result; + } + + return {std::move(__first), std::move(__result)}; + } + + template + _LIBCPP_HIDE_FROM_ABI static constexpr binary_transform_result<_InIter1, _InIter2, _OutIter> + __binary(_InIter1 __first1, _Sent1 __last1, + _InIter2 __first2, _Sent2 __last2, + _OutIter __result, + _Func& __binary_operation, + _Proj1& __projection1, + _Proj2& __projection2) { + while (__first1 != __last1 && __first2 != __last2) { + *__result = std::invoke(__binary_operation, std::invoke(__projection1, *__first1), + std::invoke(__projection2, *__first2)); + ++__first1; + ++__first2; + ++__result; + } + return {std::move(__first1), std::move(__first2), std::move(__result)}; + } +public: + template _Sent, + weakly_incrementable _OutIter, + copy_constructible _Func, + class _Proj = identity> + requires indirectly_writable<_OutIter, indirect_result_t<_Func&, projected<_InIter, _Proj>>> + _LIBCPP_HIDE_FROM_ABI constexpr + unary_transform_result<_InIter, _OutIter> operator()(_InIter __first, _Sent __last, + _OutIter __result, + _Func __operation, + _Proj __proj = {}) const { + return __unary(std::move(__first), std::move(__last), std::move(__result), __operation, __proj); + } + + template + requires indirectly_writable<_OutIter, indirect_result_t<_Func, projected, _Proj>>> + _LIBCPP_HIDE_FROM_ABI constexpr + unary_transform_result, _OutIter> operator()(_Range&& __range, + _OutIter __result, + _Func __operation, + _Proj __projection = {}) const { + return __unary(ranges::begin(__range), ranges::end(__range), std::move(__result), __operation, __projection); + } + + template _Sent1, + input_iterator _InIter2, sentinel_for<_InIter2> _Sent2, + weakly_incrementable _OutIter, + copy_constructible _Func, + class _Proj1 = identity, + class _Proj2 = identity> + requires indirectly_writable<_OutIter, indirect_result_t<_Func&, projected<_InIter1, _Proj1>, + projected<_InIter2, _Proj2>>> + _LIBCPP_HIDE_FROM_ABI constexpr + binary_transform_result<_InIter1, _InIter2, _OutIter> operator()(_InIter1 __first1, _Sent1 __last1, + _InIter2 __first2, _Sent2 __last2, + _OutIter __result, + _Func __binary_operation, + _Proj1 __projection1 = {}, + _Proj2 __projection2 = {}) const { + return __binary(std::move(__first1), std::move(__last1), + std::move(__first2), std::move(__last2), + std::move(__result), + __binary_operation, + __projection1, + __projection2); + } + + template + requires indirectly_writable<_OutIter, indirect_result_t<_Func&, projected, _Proj1>, + projected, _Proj2>>> + _LIBCPP_HIDE_FROM_ABI constexpr + binary_transform_result, borrowed_iterator_t<_Range2>, _OutIter> + operator()(_Range1&& __range1, + _Range2&& __range2, + _OutIter __result, + _Func __binary_operation, + _Proj1 __projection1 = {}, + _Proj2 __projection2 = {}) const { + return __binary(ranges::begin(__range1), ranges::end(__range1), + ranges::begin(__range2), ranges::end(__range2), + std::move(__result), + __binary_operation, + __projection1, + __projection2); + } + +}; +} // namespace __transform + +inline namespace __cpo { + inline constexpr auto transform = __transform::__fn{}; +} // namespace __cpo +} // namespace ranges + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER > 17 + +#endif // _LIBCPP___ALGORITHM_RANGES_TRANSFORM_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/ranges_unique.h b/app/src/main/cpp/libcxx/include/__algorithm/ranges_unique.h new file mode 100644 index 0000000..be427cc --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/ranges_unique.h @@ -0,0 +1,79 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_RANGES_UNIQUE_H +#define _LIBCPP___ALGORITHM_RANGES_UNIQUE_H + +#include <__algorithm/iterator_operations.h> +#include <__algorithm/make_projected.h> +#include <__algorithm/unique.h> +#include <__config> +#include <__functional/identity.h> +#include <__functional/invoke.h> +#include <__functional/ranges_operations.h> +#include <__iterator/concepts.h> +#include <__iterator/iterator_traits.h> +#include <__iterator/permutable.h> +#include <__iterator/projected.h> +#include <__ranges/access.h> +#include <__ranges/concepts.h> +#include <__ranges/dangling.h> +#include <__ranges/subrange.h> +#include <__utility/forward.h> +#include <__utility/move.h> +#include <__utility/pair.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if _LIBCPP_STD_VER > 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace ranges { +namespace __unique { + + struct __fn { + template < + permutable _Iter, + sentinel_for<_Iter> _Sent, + class _Proj = identity, + indirect_equivalence_relation> _Comp = ranges::equal_to> + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr subrange<_Iter> + operator()(_Iter __first, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) const { + auto __ret = std::__unique<_RangeAlgPolicy>( + std::move(__first), std::move(__last), std::__make_projected(__comp, __proj)); + return {std::move(__ret.first), std::move(__ret.second)}; + } + + template < + forward_range _Range, + class _Proj = identity, + indirect_equivalence_relation, _Proj>> _Comp = ranges::equal_to> + requires permutable> + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr borrowed_subrange_t<_Range> + operator()(_Range&& __range, _Comp __comp = {}, _Proj __proj = {}) const { + auto __ret = std::__unique<_RangeAlgPolicy>( + ranges::begin(__range), ranges::end(__range), std::__make_projected(__comp, __proj)); + return {std::move(__ret.first), std::move(__ret.second)}; + } + }; + +} // namespace __unique + +inline namespace __cpo { + inline constexpr auto unique = __unique::__fn{}; +} // namespace __cpo +} // namespace ranges + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER > 17 + +#endif // _LIBCPP___ALGORITHM_RANGES_UNIQUE_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/ranges_unique_copy.h b/app/src/main/cpp/libcxx/include/__algorithm/ranges_unique_copy.h new file mode 100644 index 0000000..3ad47b0 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/ranges_unique_copy.h @@ -0,0 +1,116 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_RANGES_UNIQUE_COPY_H +#define _LIBCPP___ALGORITHM_RANGES_UNIQUE_COPY_H + +#include <__algorithm/in_out_result.h> +#include <__algorithm/iterator_operations.h> +#include <__algorithm/make_projected.h> +#include <__algorithm/unique_copy.h> +#include <__concepts/same_as.h> +#include <__config> +#include <__functional/identity.h> +#include <__functional/invoke.h> +#include <__functional/ranges_operations.h> +#include <__iterator/concepts.h> +#include <__iterator/iterator_traits.h> +#include <__iterator/projected.h> +#include <__iterator/readable_traits.h> +#include <__ranges/access.h> +#include <__ranges/concepts.h> +#include <__ranges/dangling.h> +#include <__utility/forward.h> +#include <__utility/move.h> +#include <__utility/pair.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if _LIBCPP_STD_VER > 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace ranges { + +template +using unique_copy_result = in_out_result<_InIter, _OutIter>; + +namespace __unique_copy { + +template +concept __can_reread_from_output = (input_iterator<_OutIter> && same_as, iter_value_t<_OutIter>>); + +struct __fn { + template + static consteval auto __get_algo_tag() { + if constexpr (forward_iterator<_InIter>) { + return __unique_copy_tags::__reread_from_input_tag{}; + } else if constexpr (__can_reread_from_output<_InIter, _OutIter>) { + return __unique_copy_tags::__reread_from_output_tag{}; + } else if constexpr (indirectly_copyable_storable<_InIter, _OutIter>) { + return __unique_copy_tags::__read_from_tmp_value_tag{}; + } + } + + template + using __algo_tag_t = decltype(__get_algo_tag<_InIter, _OutIter>()); + + template _Sent, + weakly_incrementable _OutIter, + class _Proj = identity, + indirect_equivalence_relation> _Comp = ranges::equal_to> + requires indirectly_copyable<_InIter, _OutIter> && + (forward_iterator<_InIter> || + (input_iterator<_OutIter> && same_as, iter_value_t<_OutIter>>) || + indirectly_copyable_storable<_InIter, _OutIter>) + _LIBCPP_HIDE_FROM_ABI constexpr unique_copy_result<_InIter, _OutIter> + operator()(_InIter __first, _Sent __last, _OutIter __result, _Comp __comp = {}, _Proj __proj = {}) const { + auto __ret = std::__unique_copy<_RangeAlgPolicy>( + std::move(__first), + std::move(__last), + std::move(__result), + std::__make_projected(__comp, __proj), + __algo_tag_t<_InIter, _OutIter>()); + return {std::move(__ret.first), std::move(__ret.second)}; + } + + template , _Proj>> _Comp = ranges::equal_to> + requires indirectly_copyable, _OutIter> && + (forward_iterator> || + (input_iterator<_OutIter> && same_as, iter_value_t<_OutIter>>) || + indirectly_copyable_storable, _OutIter>) + _LIBCPP_HIDE_FROM_ABI constexpr unique_copy_result, _OutIter> + operator()(_Range&& __range, _OutIter __result, _Comp __comp = {}, _Proj __proj = {}) const { + auto __ret = std::__unique_copy<_RangeAlgPolicy>( + ranges::begin(__range), + ranges::end(__range), + std::move(__result), + std::__make_projected(__comp, __proj), + __algo_tag_t, _OutIter>()); + return {std::move(__ret.first), std::move(__ret.second)}; + } +}; + +} // namespace __unique_copy + +inline namespace __cpo { +inline constexpr auto unique_copy = __unique_copy::__fn{}; +} // namespace __cpo +} // namespace ranges + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER > 17 + +#endif // _LIBCPP___ALGORITHM_RANGES_UNIQUE_COPY_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/ranges_upper_bound.h b/app/src/main/cpp/libcxx/include/__algorithm/ranges_upper_bound.h new file mode 100644 index 0000000..a134080 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/ranges_upper_bound.h @@ -0,0 +1,75 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_RANGES_UPPER_BOUND_H +#define _LIBCPP___ALGORITHM_RANGES_UPPER_BOUND_H + +#include <__algorithm/iterator_operations.h> +#include <__algorithm/lower_bound.h> +#include <__config> +#include <__functional/identity.h> +#include <__functional/invoke.h> +#include <__functional/ranges_operations.h> +#include <__iterator/concepts.h> +#include <__iterator/projected.h> +#include <__ranges/access.h> +#include <__ranges/concepts.h> +#include <__ranges/dangling.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if _LIBCPP_STD_VER > 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace ranges { +namespace __upper_bound { +struct __fn { + template _Sent, class _Type, class _Proj = identity, + indirect_strict_weak_order> _Comp = ranges::less> + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr + _Iter operator()(_Iter __first, _Sent __last, const _Type& __value, _Comp __comp = {}, _Proj __proj = {}) const { + auto __comp_lhs_rhs_swapped = [&](const auto& __lhs, const auto& __rhs) { + return !std::invoke(__comp, __rhs, __lhs); + }; + + return std::__lower_bound_impl<_RangeAlgPolicy>(__first, __last, __value, __comp_lhs_rhs_swapped, __proj); + } + + template , _Proj>> _Comp = ranges::less> + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr + borrowed_iterator_t<_Range> operator()(_Range&& __r, + const _Type& __value, + _Comp __comp = {}, + _Proj __proj = {}) const { + auto __comp_lhs_rhs_swapped = [&](const auto& __lhs, const auto& __rhs) { + return !std::invoke(__comp, __rhs, __lhs); + }; + + return std::__lower_bound_impl<_RangeAlgPolicy>(ranges::begin(__r), + ranges::end(__r), + __value, + __comp_lhs_rhs_swapped, + __proj); + } +}; +} // namespace __upper_bound + +inline namespace __cpo { + inline constexpr auto upper_bound = __upper_bound::__fn{}; +} // namespace __cpo +} // namespace ranges + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER > 17 + +#endif // _LIBCPP___ALGORITHM_RANGES_UPPER_BOUND_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/remove.h b/app/src/main/cpp/libcxx/include/__algorithm/remove.h new file mode 100644 index 0000000..533e41b --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/remove.h @@ -0,0 +1,45 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_REMOVE_H +#define _LIBCPP___ALGORITHM_REMOVE_H + +#include <__algorithm/find.h> +#include <__algorithm/find_if.h> +#include <__config> +#include <__utility/move.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +template +_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator +remove(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value) +{ + __first = _VSTD::find(__first, __last, __value); + if (__first != __last) + { + _ForwardIterator __i = __first; + while (++__i != __last) + { + if (!(*__i == __value)) + { + *__first = _VSTD::move(*__i); + ++__first; + } + } + } + return __first; +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ALGORITHM_REMOVE_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/remove_copy.h b/app/src/main/cpp/libcxx/include/__algorithm/remove_copy.h new file mode 100644 index 0000000..ecba08a --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/remove_copy.h @@ -0,0 +1,38 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_REMOVE_COPY_H +#define _LIBCPP___ALGORITHM_REMOVE_COPY_H + +#include <__config> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +template +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 +_OutputIterator +remove_copy(_InputIterator __first, _InputIterator __last, _OutputIterator __result, const _Tp& __value) +{ + for (; __first != __last; ++__first) + { + if (!(*__first == __value)) + { + *__result = *__first; + ++__result; + } + } + return __result; +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ALGORITHM_REMOVE_COPY_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/remove_copy_if.h b/app/src/main/cpp/libcxx/include/__algorithm/remove_copy_if.h new file mode 100644 index 0000000..2f235fd --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/remove_copy_if.h @@ -0,0 +1,38 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_REMOVE_COPY_IF_H +#define _LIBCPP___ALGORITHM_REMOVE_COPY_IF_H + +#include <__config> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +template +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 +_OutputIterator +remove_copy_if(_InputIterator __first, _InputIterator __last, _OutputIterator __result, _Predicate __pred) +{ + for (; __first != __last; ++__first) + { + if (!__pred(*__first)) + { + *__result = *__first; + ++__result; + } + } + return __result; +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ALGORITHM_REMOVE_COPY_IF_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/remove_if.h b/app/src/main/cpp/libcxx/include/__algorithm/remove_if.h new file mode 100644 index 0000000..2735072 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/remove_if.h @@ -0,0 +1,44 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_REMOVE_IF_H +#define _LIBCPP___ALGORITHM_REMOVE_IF_H + +#include <__algorithm/find_if.h> +#include <__config> +#include <__utility/move.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +template +_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator +remove_if(_ForwardIterator __first, _ForwardIterator __last, _Predicate __pred) +{ + __first = _VSTD::find_if<_ForwardIterator, _Predicate&>(__first, __last, __pred); + if (__first != __last) + { + _ForwardIterator __i = __first; + while (++__i != __last) + { + if (!__pred(*__i)) + { + *__first = _VSTD::move(*__i); + ++__first; + } + } + } + return __first; +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ALGORITHM_REMOVE_IF_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/replace.h b/app/src/main/cpp/libcxx/include/__algorithm/replace.h new file mode 100644 index 0000000..ce62150 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/replace.h @@ -0,0 +1,32 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_REPLACE_H +#define _LIBCPP___ALGORITHM_REPLACE_H + +#include <__config> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +template +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 +void +replace(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __old_value, const _Tp& __new_value) +{ + for (; __first != __last; ++__first) + if (*__first == __old_value) + *__first = __new_value; +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ALGORITHM_REPLACE_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/replace_copy.h b/app/src/main/cpp/libcxx/include/__algorithm/replace_copy.h new file mode 100644 index 0000000..bebb14c --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/replace_copy.h @@ -0,0 +1,36 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_REPLACE_COPY_H +#define _LIBCPP___ALGORITHM_REPLACE_COPY_H + +#include <__config> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +template +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 +_OutputIterator +replace_copy(_InputIterator __first, _InputIterator __last, _OutputIterator __result, + const _Tp& __old_value, const _Tp& __new_value) +{ + for (; __first != __last; ++__first, (void) ++__result) + if (*__first == __old_value) + *__result = __new_value; + else + *__result = *__first; + return __result; +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ALGORITHM_REPLACE_COPY_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/replace_copy_if.h b/app/src/main/cpp/libcxx/include/__algorithm/replace_copy_if.h new file mode 100644 index 0000000..e1ddb52 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/replace_copy_if.h @@ -0,0 +1,36 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_REPLACE_COPY_IF_H +#define _LIBCPP___ALGORITHM_REPLACE_COPY_IF_H + +#include <__config> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +template +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 +_OutputIterator +replace_copy_if(_InputIterator __first, _InputIterator __last, _OutputIterator __result, + _Predicate __pred, const _Tp& __new_value) +{ + for (; __first != __last; ++__first, (void) ++__result) + if (__pred(*__first)) + *__result = __new_value; + else + *__result = *__first; + return __result; +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ALGORITHM_REPLACE_COPY_IF_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/replace_if.h b/app/src/main/cpp/libcxx/include/__algorithm/replace_if.h new file mode 100644 index 0000000..b3a3367 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/replace_if.h @@ -0,0 +1,32 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_REPLACE_IF_H +#define _LIBCPP___ALGORITHM_REPLACE_IF_H + +#include <__config> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +template +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 +void +replace_if(_ForwardIterator __first, _ForwardIterator __last, _Predicate __pred, const _Tp& __new_value) +{ + for (; __first != __last; ++__first) + if (__pred(*__first)) + *__first = __new_value; +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ALGORITHM_REPLACE_IF_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/reverse.h b/app/src/main/cpp/libcxx/include/__algorithm/reverse.h new file mode 100644 index 0000000..aa76951 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/reverse.h @@ -0,0 +1,65 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_REVERSE_H +#define _LIBCPP___ALGORITHM_REVERSE_H + +#include <__algorithm/iter_swap.h> +#include <__algorithm/iterator_operations.h> +#include <__config> +#include <__iterator/iterator_traits.h> +#include <__utility/move.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +template +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 +void +__reverse_impl(_BidirectionalIterator __first, _BidirectionalIterator __last, bidirectional_iterator_tag) +{ + while (__first != __last) + { + if (__first == --__last) + break; + _IterOps<_AlgPolicy>::iter_swap(__first, __last); + ++__first; + } +} + +template +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 +void +__reverse_impl(_RandomAccessIterator __first, _RandomAccessIterator __last, random_access_iterator_tag) +{ + if (__first != __last) + for (; __first < --__last; ++__first) + _IterOps<_AlgPolicy>::iter_swap(__first, __last); +} + +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 +void __reverse(_BidirectionalIterator __first, _Sentinel __last) { + using _IterCategory = typename _IterOps<_AlgPolicy>::template __iterator_category<_BidirectionalIterator>; + std::__reverse_impl<_AlgPolicy>(std::move(__first), std::move(__last), _IterCategory()); +} + +template +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 +void +reverse(_BidirectionalIterator __first, _BidirectionalIterator __last) +{ + std::__reverse<_ClassicAlgPolicy>(std::move(__first), std::move(__last)); +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ALGORITHM_REVERSE_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/reverse_copy.h b/app/src/main/cpp/libcxx/include/__algorithm/reverse_copy.h new file mode 100644 index 0000000..f4a0e97 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/reverse_copy.h @@ -0,0 +1,32 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_REVERSE_COPY_H +#define _LIBCPP___ALGORITHM_REVERSE_COPY_H + +#include <__config> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +template +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 +_OutputIterator +reverse_copy(_BidirectionalIterator __first, _BidirectionalIterator __last, _OutputIterator __result) +{ + for (; __first != __last; ++__result) + *__result = *--__last; + return __result; +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ALGORITHM_REVERSE_COPY_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/rotate.h b/app/src/main/cpp/libcxx/include/__algorithm/rotate.h new file mode 100644 index 0000000..8934ce0 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/rotate.h @@ -0,0 +1,221 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_ROTATE_H +#define _LIBCPP___ALGORITHM_ROTATE_H + +#include <__algorithm/iterator_operations.h> +#include <__algorithm/move.h> +#include <__algorithm/move_backward.h> +#include <__algorithm/swap_ranges.h> +#include <__config> +#include <__iterator/iterator_traits.h> +#include <__utility/move.h> +#include <__utility/pair.h> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _ForwardIterator +__rotate_left(_ForwardIterator __first, _ForwardIterator __last) +{ + typedef typename iterator_traits<_ForwardIterator>::value_type value_type; + using _Ops = _IterOps<_AlgPolicy>; + + value_type __tmp = _Ops::__iter_move(__first); + _ForwardIterator __lm1 = std::__move<_AlgPolicy>( + _Ops::next(__first), __last, __first).second; + *__lm1 = _VSTD::move(__tmp); + return __lm1; +} + +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _BidirectionalIterator +__rotate_right(_BidirectionalIterator __first, _BidirectionalIterator __last) +{ + typedef typename iterator_traits<_BidirectionalIterator>::value_type value_type; + using _Ops = _IterOps<_AlgPolicy>; + + _BidirectionalIterator __lm1 = _Ops::prev(__last); + value_type __tmp = _Ops::__iter_move(__lm1); + _BidirectionalIterator __fp1 = std::__move_backward<_AlgPolicy>(__first, __lm1, std::move(__last)).second; + *__first = _VSTD::move(__tmp); + return __fp1; +} + +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 _ForwardIterator +__rotate_forward(_ForwardIterator __first, _ForwardIterator __middle, _ForwardIterator __last) +{ + _ForwardIterator __i = __middle; + while (true) + { + _IterOps<_AlgPolicy>::iter_swap(__first, __i); + ++__first; + if (++__i == __last) + break; + if (__first == __middle) + __middle = __i; + } + _ForwardIterator __r = __first; + if (__first != __middle) + { + __i = __middle; + while (true) + { + _IterOps<_AlgPolicy>::iter_swap(__first, __i); + ++__first; + if (++__i == __last) + { + if (__first == __middle) + break; + __i = __middle; + } + else if (__first == __middle) + __middle = __i; + } + } + return __r; +} + +template +inline _LIBCPP_INLINE_VISIBILITY +_LIBCPP_CONSTEXPR_SINCE_CXX17 _Integral +__algo_gcd(_Integral __x, _Integral __y) +{ + do + { + _Integral __t = __x % __y; + __x = __y; + __y = __t; + } while (__y); + return __x; +} + +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 _RandomAccessIterator +__rotate_gcd(_RandomAccessIterator __first, _RandomAccessIterator __middle, _RandomAccessIterator __last) +{ + typedef typename iterator_traits<_RandomAccessIterator>::difference_type difference_type; + typedef typename iterator_traits<_RandomAccessIterator>::value_type value_type; + using _Ops = _IterOps<_AlgPolicy>; + + const difference_type __m1 = __middle - __first; + const difference_type __m2 = _Ops::distance(__middle, __last); + if (__m1 == __m2) + { + std::__swap_ranges<_AlgPolicy>(__first, __middle, __middle, __last); + return __middle; + } + const difference_type __g = _VSTD::__algo_gcd(__m1, __m2); + for (_RandomAccessIterator __p = __first + __g; __p != __first;) + { + value_type __t(_Ops::__iter_move(--__p)); + _RandomAccessIterator __p1 = __p; + _RandomAccessIterator __p2 = __p1 + __m1; + do + { + *__p1 = _Ops::__iter_move(__p2); + __p1 = __p2; + const difference_type __d = _Ops::distance(__p2, __last); + if (__m1 < __d) + __p2 += __m1; + else + __p2 = __first + (__m1 - __d); + } while (__p2 != __p); + *__p1 = _VSTD::move(__t); + } + return __first + __m2; +} + +template +inline _LIBCPP_INLINE_VISIBILITY +_LIBCPP_CONSTEXPR_SINCE_CXX14 _ForwardIterator +__rotate_impl(_ForwardIterator __first, _ForwardIterator __middle, _ForwardIterator __last, + _VSTD::forward_iterator_tag) +{ + typedef typename iterator_traits<_ForwardIterator>::value_type value_type; + if (is_trivially_move_assignable::value) + { + if (_IterOps<_AlgPolicy>::next(__first) == __middle) + return std::__rotate_left<_AlgPolicy>(__first, __last); + } + return std::__rotate_forward<_AlgPolicy>(__first, __middle, __last); +} + +template +inline _LIBCPP_INLINE_VISIBILITY +_LIBCPP_CONSTEXPR_SINCE_CXX14 _BidirectionalIterator +__rotate_impl(_BidirectionalIterator __first, _BidirectionalIterator __middle, _BidirectionalIterator __last, + bidirectional_iterator_tag) +{ + typedef typename iterator_traits<_BidirectionalIterator>::value_type value_type; + if (is_trivially_move_assignable::value) + { + if (_IterOps<_AlgPolicy>::next(__first) == __middle) + return std::__rotate_left<_AlgPolicy>(__first, __last); + if (_IterOps<_AlgPolicy>::next(__middle) == __last) + return std::__rotate_right<_AlgPolicy>(__first, __last); + } + return std::__rotate_forward<_AlgPolicy>(__first, __middle, __last); +} + +template +inline _LIBCPP_INLINE_VISIBILITY +_LIBCPP_CONSTEXPR_SINCE_CXX14 _RandomAccessIterator +__rotate_impl(_RandomAccessIterator __first, _RandomAccessIterator __middle, _RandomAccessIterator __last, + random_access_iterator_tag) +{ + typedef typename iterator_traits<_RandomAccessIterator>::value_type value_type; + if (is_trivially_move_assignable::value) + { + if (_IterOps<_AlgPolicy>::next(__first) == __middle) + return std::__rotate_left<_AlgPolicy>(__first, __last); + if (_IterOps<_AlgPolicy>::next(__middle) == __last) + return std::__rotate_right<_AlgPolicy>(__first, __last); + return std::__rotate_gcd<_AlgPolicy>(__first, __middle, __last); + } + return std::__rotate_forward<_AlgPolicy>(__first, __middle, __last); +} + +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 +pair<_Iterator, _Iterator> +__rotate(_Iterator __first, _Iterator __middle, _Sentinel __last) { + using _Ret = pair<_Iterator, _Iterator>; + _Iterator __last_iter = _IterOps<_AlgPolicy>::next(__middle, __last); + + if (__first == __middle) + return _Ret(__last_iter, __last_iter); + if (__middle == __last) + return _Ret(std::move(__first), std::move(__last_iter)); + + using _IterCategory = typename _IterOps<_AlgPolicy>::template __iterator_category<_Iterator>; + auto __result = std::__rotate_impl<_AlgPolicy>( + std::move(__first), std::move(__middle), __last_iter, _IterCategory()); + + return _Ret(std::move(__result), std::move(__last_iter)); +} + +template +inline _LIBCPP_INLINE_VISIBILITY +_LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator +rotate(_ForwardIterator __first, _ForwardIterator __middle, _ForwardIterator __last) +{ + return std::__rotate<_ClassicAlgPolicy>( + std::move(__first), std::move(__middle), std::move(__last)).first; +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ALGORITHM_ROTATE_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/rotate_copy.h b/app/src/main/cpp/libcxx/include/__algorithm/rotate_copy.h new file mode 100644 index 0000000..c154649 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/rotate_copy.h @@ -0,0 +1,31 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_ROTATE_COPY_H +#define _LIBCPP___ALGORITHM_ROTATE_COPY_H + +#include <__algorithm/copy.h> +#include <__config> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +template +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 +_OutputIterator +rotate_copy(_ForwardIterator __first, _ForwardIterator __middle, _ForwardIterator __last, _OutputIterator __result) +{ + return _VSTD::copy(__first, __middle, _VSTD::copy(__middle, __last, __result)); +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ALGORITHM_ROTATE_COPY_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/sample.h b/app/src/main/cpp/libcxx/include/__algorithm/sample.h new file mode 100644 index 0000000..f403ba6 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/sample.h @@ -0,0 +1,112 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_SAMPLE_H +#define _LIBCPP___ALGORITHM_SAMPLE_H + +#include <__algorithm/iterator_operations.h> +#include <__algorithm/min.h> +#include <__assert> +#include <__config> +#include <__iterator/distance.h> +#include <__iterator/iterator_traits.h> +#include <__random/uniform_int_distribution.h> +#include <__utility/move.h> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + +_LIBCPP_BEGIN_NAMESPACE_STD + +template +_LIBCPP_INLINE_VISIBILITY +_SampleIterator __sample(_PopulationIterator __first, + _PopulationSentinel __last, _SampleIterator __output_iter, + _Distance __n, + _UniformRandomNumberGenerator& __g, + input_iterator_tag) { + + _Distance __k = 0; + for (; __first != __last && __k < __n; ++__first, (void) ++__k) + __output_iter[__k] = *__first; + _Distance __sz = __k; + for (; __first != __last; ++__first, (void) ++__k) { + _Distance __r = uniform_int_distribution<_Distance>(0, __k)(__g); + if (__r < __sz) + __output_iter[__r] = *__first; + } + return __output_iter + _VSTD::min(__n, __k); +} + +template +_LIBCPP_INLINE_VISIBILITY +_SampleIterator __sample(_PopulationIterator __first, + _PopulationSentinel __last, _SampleIterator __output_iter, + _Distance __n, + _UniformRandomNumberGenerator& __g, + forward_iterator_tag) { + _Distance __unsampled_sz = _IterOps<_AlgPolicy>::distance(__first, __last); + for (__n = _VSTD::min(__n, __unsampled_sz); __n != 0; ++__first) { + _Distance __r = uniform_int_distribution<_Distance>(0, --__unsampled_sz)(__g); + if (__r < __n) { + *__output_iter++ = *__first; + --__n; + } + } + return __output_iter; +} + +template +_LIBCPP_INLINE_VISIBILITY +_SampleIterator __sample(_PopulationIterator __first, + _PopulationSentinel __last, _SampleIterator __output_iter, + _Distance __n, _UniformRandomNumberGenerator& __g) { + _LIBCPP_ASSERT(__n >= 0, "N must be a positive number."); + + using _PopIterCategory = typename _IterOps<_AlgPolicy>::template __iterator_category<_PopulationIterator>; + using _Difference = typename _IterOps<_AlgPolicy>::template __difference_type<_PopulationIterator>; + using _CommonType = typename common_type<_Distance, _Difference>::type; + + return std::__sample<_AlgPolicy>( + std::move(__first), std::move(__last), std::move(__output_iter), _CommonType(__n), + __g, _PopIterCategory()); +} + +#if _LIBCPP_STD_VER > 14 +template +inline _LIBCPP_INLINE_VISIBILITY +_SampleIterator sample(_PopulationIterator __first, + _PopulationIterator __last, _SampleIterator __output_iter, + _Distance __n, _UniformRandomNumberGenerator&& __g) { + static_assert(__is_cpp17_forward_iterator<_PopulationIterator>::value || + __is_cpp17_random_access_iterator<_SampleIterator>::value, + "SampleIterator must meet the requirements of RandomAccessIterator"); + + return std::__sample<_ClassicAlgPolicy>( + std::move(__first), std::move(__last), std::move(__output_iter), __n, __g); +} + +#endif // _LIBCPP_STD_VER > 14 + +_LIBCPP_END_NAMESPACE_STD + +_LIBCPP_POP_MACROS + +#endif // _LIBCPP___ALGORITHM_SAMPLE_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/search.h b/app/src/main/cpp/libcxx/include/__algorithm/search.h new file mode 100644 index 0000000..93771be --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/search.h @@ -0,0 +1,201 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_SEARCH_H +#define _LIBCPP___ALGORITHM_SEARCH_H + +#include <__algorithm/comp.h> +#include <__algorithm/iterator_operations.h> +#include <__config> +#include <__functional/identity.h> +#include <__iterator/advance.h> +#include <__iterator/concepts.h> +#include <__iterator/iterator_traits.h> +#include <__type_traits/is_callable.h> +#include <__utility/pair.h> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 +pair<_Iter1, _Iter1> __search_forward_impl(_Iter1 __first1, _Sent1 __last1, + _Iter2 __first2, _Sent2 __last2, + _Pred& __pred, + _Proj1& __proj1, + _Proj2& __proj2) { + if (__first2 == __last2) + return std::make_pair(__first1, __first1); // Everything matches an empty sequence + while (true) { + // Find first element in sequence 1 that matchs *__first2, with a mininum of loop checks + while (true) { + if (__first1 == __last1) { // return __last1 if no element matches *__first2 + _IterOps<_AlgPolicy>::__advance_to(__first1, __last1); + return std::make_pair(__first1, __first1); + } + if (std::__invoke(__pred, std::__invoke(__proj1, *__first1), std::__invoke(__proj2, *__first2))) + break; + ++__first1; + } + // *__first1 matches *__first2, now match elements after here + _Iter1 __m1 = __first1; + _Iter2 __m2 = __first2; + while (true) { + if (++__m2 == __last2) // If pattern exhausted, __first1 is the answer (works for 1 element pattern) + return std::make_pair(__first1, ++__m1); + if (++__m1 == __last1) { // Otherwise if source exhaused, pattern not found + return std::make_pair(__m1, __m1); + } + + // if there is a mismatch, restart with a new __first1 + if (!std::__invoke(__pred, std::__invoke(__proj1, *__m1), std::__invoke(__proj2, *__m2))) + { + ++__first1; + break; + } // else there is a match, check next elements + } + } +} + +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 +pair<_Iter1, _Iter1> __search_random_access_impl(_Iter1 __first1, _Sent1 __last1, + _Iter2 __first2, _Sent2 __last2, + _Pred& __pred, + _Proj1& __proj1, + _Proj2& __proj2, + _DiffT1 __size1, + _DiffT2 __size2) { + const _Iter1 __s = __first1 + __size1 - _DiffT1(__size2 - 1); // Start of pattern match can't go beyond here + + while (true) { + while (true) { + if (__first1 == __s) { + _IterOps<_AlgPolicy>::__advance_to(__first1, __last1); + return std::make_pair(__first1, __first1); + } + if (std::__invoke(__pred, std::__invoke(__proj1, *__first1), std::__invoke(__proj2, *__first2))) + break; + ++__first1; + } + + _Iter1 __m1 = __first1; + _Iter2 __m2 = __first2; + while (true) { + if (++__m2 == __last2) + return std::make_pair(__first1, __first1 + _DiffT1(__size2)); + ++__m1; // no need to check range on __m1 because __s guarantees we have enough source + if (!std::__invoke(__pred, std::__invoke(__proj1, *__m1), std::__invoke(__proj2, *__m2))) { + ++__first1; + break; + } + } + } +} + +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 +pair<_Iter1, _Iter1> __search_impl(_Iter1 __first1, _Sent1 __last1, + _Iter2 __first2, _Sent2 __last2, + _Pred& __pred, + _Proj1& __proj1, + _Proj2& __proj2, + __enable_if_t<__is_cpp17_random_access_iterator<_Iter1>::value + && __is_cpp17_random_access_iterator<_Iter2>::value>* = nullptr) { + + auto __size2 = __last2 - __first2; + if (__size2 == 0) + return std::make_pair(__first1, __first1); + + auto __size1 = __last1 - __first1; + if (__size1 < __size2) { + return std::make_pair(__last1, __last1); + } + + return std::__search_random_access_impl<_ClassicAlgPolicy>(__first1, __last1, + __first2, __last2, + __pred, + __proj1, + __proj2, + __size1, + __size2); +} + +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 +pair<_Iter1, _Iter1> __search_impl(_Iter1 __first1, _Sent1 __last1, + _Iter2 __first2, _Sent2 __last2, + _Pred& __pred, + _Proj1& __proj1, + _Proj2& __proj2, + __enable_if_t<__is_cpp17_forward_iterator<_Iter1>::value + && __is_cpp17_forward_iterator<_Iter2>::value + && !(__is_cpp17_random_access_iterator<_Iter1>::value + && __is_cpp17_random_access_iterator<_Iter2>::value)>* = nullptr) { + return std::__search_forward_impl<_ClassicAlgPolicy>(__first1, __last1, + __first2, __last2, + __pred, + __proj1, + __proj2); +} + +template +_LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 +_ForwardIterator1 search(_ForwardIterator1 __first1, _ForwardIterator1 __last1, + _ForwardIterator2 __first2, _ForwardIterator2 __last2, + _BinaryPredicate __pred) { + static_assert(__is_callable<_BinaryPredicate, decltype(*__first1), decltype(*__first2)>::value, + "BinaryPredicate has to be callable"); + auto __proj = __identity(); + return std::__search_impl(__first1, __last1, __first2, __last2, __pred, __proj, __proj).first; +} + +template +_LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 +_ForwardIterator1 search(_ForwardIterator1 __first1, _ForwardIterator1 __last1, + _ForwardIterator2 __first2, _ForwardIterator2 __last2) { + return std::search(__first1, __last1, __first2, __last2, __equal_to()); +} + +#if _LIBCPP_STD_VER > 14 +template +_LIBCPP_NODISCARD_EXT _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator +search(_ForwardIterator __f, _ForwardIterator __l, const _Searcher& __s) { + return __s(__f, __l).first; +} + +#endif + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ALGORITHM_SEARCH_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/search_n.h b/app/src/main/cpp/libcxx/include/__algorithm/search_n.h new file mode 100644 index 0000000..60a0735 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/search_n.h @@ -0,0 +1,181 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_SEARCH_N_H +#define _LIBCPP___ALGORITHM_SEARCH_N_H + +#include <__algorithm/comp.h> +#include <__algorithm/iterator_operations.h> +#include <__config> +#include <__functional/identity.h> +#include <__iterator/advance.h> +#include <__iterator/concepts.h> +#include <__iterator/distance.h> +#include <__iterator/iterator_traits.h> +#include <__ranges/concepts.h> +#include <__utility/convert_to_integral.h> +#include <__utility/pair.h> +#include // __convert_to_integral + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 +pair<_Iter, _Iter> __search_n_forward_impl(_Iter __first, _Sent __last, + _SizeT __count, + const _Type& __value, + _Pred& __pred, + _Proj& __proj) { + if (__count <= 0) + return std::make_pair(__first, __first); + while (true) { + // Find first element in sequence that matchs __value, with a mininum of loop checks + while (true) { + if (__first == __last) { // return __last if no element matches __value + _IterOps<_AlgPolicy>::__advance_to(__first, __last); + return std::make_pair(__first, __first); + } + if (std::__invoke(__pred, std::__invoke(__proj, *__first), __value)) + break; + ++__first; + } + // *__first matches __value, now match elements after here + _Iter __m = __first; + _SizeT __c(0); + while (true) { + if (++__c == __count) // If pattern exhausted, __first is the answer (works for 1 element pattern) + return std::make_pair(__first, ++__m); + if (++__m == __last) { // Otherwise if source exhaused, pattern not found + _IterOps<_AlgPolicy>::__advance_to(__first, __last); + return std::make_pair(__first, __first); + } + + // if there is a mismatch, restart with a new __first + if (!std::__invoke(__pred, std::__invoke(__proj, *__m), __value)) + { + __first = __m; + ++__first; + break; + } // else there is a match, check next elements + } + } +} + +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 +std::pair<_Iter, _Iter> __search_n_random_access_impl(_Iter __first, _Sent __last, + _SizeT __count, + const _Type& __value, + _Pred& __pred, + _Proj& __proj, + _DiffT __size1) { + using difference_type = typename iterator_traits<_Iter>::difference_type; + if (__count == 0) + return std::make_pair(__first, __first); + if (__size1 < static_cast<_DiffT>(__count)) { + _IterOps<_AlgPolicy>::__advance_to(__first, __last); + return std::make_pair(__first, __first); + } + + const auto __s = __first + __size1 - difference_type(__count - 1); // Start of pattern match can't go beyond here + while (true) { + // Find first element in sequence that matchs __value, with a mininum of loop checks + while (true) { + if (__first >= __s) { // return __last if no element matches __value + _IterOps<_AlgPolicy>::__advance_to(__first, __last); + return std::make_pair(__first, __first); + } + if (std::__invoke(__pred, std::__invoke(__proj, *__first), __value)) + break; + ++__first; + } + // *__first matches __value_, now match elements after here + auto __m = __first; + _SizeT __c(0); + while (true) { + if (++__c == __count) // If pattern exhausted, __first is the answer (works for 1 element pattern) + return std::make_pair(__first, __first + _DiffT(__count)); + ++__m; // no need to check range on __m because __s guarantees we have enough source + + // if there is a mismatch, restart with a new __first + if (!std::__invoke(__pred, std::__invoke(__proj, *__m), __value)) + { + __first = __m; + ++__first; + break; + } // else there is a match, check next elements + } + } +} + +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 +pair<_Iter, _Iter> __search_n_impl(_Iter __first, _Sent __last, + _DiffT __count, + const _Type& __value, + _Pred& __pred, + _Proj& __proj, + __enable_if_t<__is_cpp17_random_access_iterator<_Iter>::value>* = nullptr) { + return std::__search_n_random_access_impl<_ClassicAlgPolicy>(__first, __last, + __count, + __value, + __pred, + __proj, + __last - __first); +} + +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 +pair<_Iter1, _Iter1> __search_n_impl(_Iter1 __first, _Sent1 __last, + _DiffT __count, + const _Type& __value, + _Pred& __pred, + _Proj& __proj, + __enable_if_t<__is_cpp17_forward_iterator<_Iter1>::value + && !__is_cpp17_random_access_iterator<_Iter1>::value>* = nullptr) { + return std::__search_n_forward_impl<_ClassicAlgPolicy>(__first, __last, + __count, + __value, + __pred, + __proj); +} + +template +_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 +_ForwardIterator search_n(_ForwardIterator __first, _ForwardIterator __last, + _Size __count, + const _Tp& __value, + _BinaryPredicate __pred) { + static_assert(__is_callable<_BinaryPredicate, decltype(*__first), const _Tp&>::value, + "BinaryPredicate has to be callable"); + auto __proj = __identity(); + return std::__search_n_impl(__first, __last, std::__convert_to_integral(__count), __value, __pred, __proj).first; +} + +template +_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 +_ForwardIterator search_n(_ForwardIterator __first, _ForwardIterator __last, _Size __count, const _Tp& __value) { + return std::search_n(__first, __last, std::__convert_to_integral(__count), __value, __equal_to()); +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ALGORITHM_SEARCH_N_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/set_difference.h b/app/src/main/cpp/libcxx/include/__algorithm/set_difference.h new file mode 100644 index 0000000..cffdc8f --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/set_difference.h @@ -0,0 +1,81 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_SET_DIFFERENCE_H +#define _LIBCPP___ALGORITHM_SET_DIFFERENCE_H + +#include <__algorithm/comp.h> +#include <__algorithm/comp_ref_type.h> +#include <__algorithm/copy.h> +#include <__algorithm/iterator_operations.h> +#include <__config> +#include <__functional/identity.h> +#include <__functional/invoke.h> +#include <__iterator/iterator_traits.h> +#include <__utility/move.h> +#include <__utility/pair.h> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<__remove_cvref_t<_InIter1>, __remove_cvref_t<_OutIter> > +__set_difference( + _InIter1&& __first1, _Sent1&& __last1, _InIter2&& __first2, _Sent2&& __last2, _OutIter&& __result, _Comp&& __comp) { + while (__first1 != __last1 && __first2 != __last2) { + if (__comp(*__first1, *__first2)) { + *__result = *__first1; + ++__first1; + ++__result; + } else if (__comp(*__first2, *__first1)) { + ++__first2; + } else { + ++__first1; + ++__first2; + } + } + return std::__copy<_AlgPolicy>(std::move(__first1), std::move(__last1), std::move(__result)); +} + +template +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _OutputIterator set_difference( + _InputIterator1 __first1, + _InputIterator1 __last1, + _InputIterator2 __first2, + _InputIterator2 __last2, + _OutputIterator __result, + _Compare __comp) { + return std::__set_difference<_ClassicAlgPolicy, __comp_ref_type<_Compare> >( + __first1, __last1, __first2, __last2, __result, __comp) + .second; +} + +template +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _OutputIterator set_difference( + _InputIterator1 __first1, + _InputIterator1 __last1, + _InputIterator2 __first2, + _InputIterator2 __last2, + _OutputIterator __result) { + return std::__set_difference<_ClassicAlgPolicy>( + __first1, + __last1, + __first2, + __last2, + __result, + __less::value_type, + typename iterator_traits<_InputIterator2>::value_type>()).second; +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ALGORITHM_SET_DIFFERENCE_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/set_intersection.h b/app/src/main/cpp/libcxx/include/__algorithm/set_intersection.h new file mode 100644 index 0000000..9fa7799 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/set_intersection.h @@ -0,0 +1,99 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_SET_INTERSECTION_H +#define _LIBCPP___ALGORITHM_SET_INTERSECTION_H + +#include <__algorithm/comp.h> +#include <__algorithm/comp_ref_type.h> +#include <__algorithm/iterator_operations.h> +#include <__config> +#include <__iterator/iterator_traits.h> +#include <__iterator/next.h> +#include <__utility/move.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +template +struct __set_intersection_result { + _InIter1 __in1_; + _InIter2 __in2_; + _OutIter __out_; + + // need a constructor as C++03 aggregate init is hard + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 + __set_intersection_result(_InIter1&& __in_iter1, _InIter2&& __in_iter2, _OutIter&& __out_iter) + : __in1_(std::move(__in_iter1)), __in2_(std::move(__in_iter2)), __out_(std::move(__out_iter)) {} +}; + +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __set_intersection_result<_InIter1, _InIter2, _OutIter> +__set_intersection( + _InIter1 __first1, _Sent1 __last1, _InIter2 __first2, _Sent2 __last2, _OutIter __result, _Compare&& __comp) { + while (__first1 != __last1 && __first2 != __last2) { + if (__comp(*__first1, *__first2)) + ++__first1; + else { + if (!__comp(*__first2, *__first1)) { + *__result = *__first1; + ++__result; + ++__first1; + } + ++__first2; + } + } + + return __set_intersection_result<_InIter1, _InIter2, _OutIter>( + _IterOps<_AlgPolicy>::next(std::move(__first1), std::move(__last1)), + _IterOps<_AlgPolicy>::next(std::move(__first2), std::move(__last2)), + std::move(__result)); +} + +template +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _OutputIterator set_intersection( + _InputIterator1 __first1, + _InputIterator1 __last1, + _InputIterator2 __first2, + _InputIterator2 __last2, + _OutputIterator __result, + _Compare __comp) { + return std::__set_intersection<_ClassicAlgPolicy, __comp_ref_type<_Compare> >( + std::move(__first1), + std::move(__last1), + std::move(__first2), + std::move(__last2), + std::move(__result), + __comp) + .__out_; +} + +template +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _OutputIterator set_intersection( + _InputIterator1 __first1, + _InputIterator1 __last1, + _InputIterator2 __first2, + _InputIterator2 __last2, + _OutputIterator __result) { + return std::__set_intersection<_ClassicAlgPolicy>( + std::move(__first1), + std::move(__last1), + std::move(__first2), + std::move(__last2), + std::move(__result), + __less::value_type, + typename iterator_traits<_InputIterator2>::value_type>()) + .__out_; +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ALGORITHM_SET_INTERSECTION_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/set_symmetric_difference.h b/app/src/main/cpp/libcxx/include/__algorithm/set_symmetric_difference.h new file mode 100644 index 0000000..bcb0958 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/set_symmetric_difference.h @@ -0,0 +1,105 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_SET_SYMMETRIC_DIFFERENCE_H +#define _LIBCPP___ALGORITHM_SET_SYMMETRIC_DIFFERENCE_H + +#include <__algorithm/comp.h> +#include <__algorithm/comp_ref_type.h> +#include <__algorithm/copy.h> +#include <__algorithm/iterator_operations.h> +#include <__config> +#include <__iterator/iterator_traits.h> +#include <__utility/move.h> +#include <__utility/pair.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +template +struct __set_symmetric_difference_result { + _InIter1 __in1_; + _InIter2 __in2_; + _OutIter __out_; + + // need a constructor as C++03 aggregate init is hard + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 + __set_symmetric_difference_result(_InIter1&& __in_iter1, _InIter2&& __in_iter2, _OutIter&& __out_iter) + : __in1_(std::move(__in_iter1)), __in2_(std::move(__in_iter2)), __out_(std::move(__out_iter)) {} +}; + +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __set_symmetric_difference_result<_InIter1, _InIter2, _OutIter> +__set_symmetric_difference( + _InIter1 __first1, _Sent1 __last1, _InIter2 __first2, _Sent2 __last2, _OutIter __result, _Compare&& __comp) { + while (__first1 != __last1) { + if (__first2 == __last2) { + auto __ret1 = std::__copy<_AlgPolicy>(std::move(__first1), std::move(__last1), std::move(__result)); + return __set_symmetric_difference_result<_InIter1, _InIter2, _OutIter>( + std::move(__ret1.first), std::move(__first2), std::move((__ret1.second))); + } + if (__comp(*__first1, *__first2)) { + *__result = *__first1; + ++__result; + ++__first1; + } else { + if (__comp(*__first2, *__first1)) { + *__result = *__first2; + ++__result; + } else { + ++__first1; + } + ++__first2; + } + } + auto __ret2 = std::__copy<_AlgPolicy>(std::move(__first2), std::move(__last2), std::move(__result)); + return __set_symmetric_difference_result<_InIter1, _InIter2, _OutIter>( + std::move(__first1), std::move(__ret2.first), std::move((__ret2.second))); +} + +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _OutputIterator set_symmetric_difference( + _InputIterator1 __first1, + _InputIterator1 __last1, + _InputIterator2 __first2, + _InputIterator2 __last2, + _OutputIterator __result, + _Compare __comp) { + return std::__set_symmetric_difference<_ClassicAlgPolicy, __comp_ref_type<_Compare> >( + std::move(__first1), + std::move(__last1), + std::move(__first2), + std::move(__last2), + std::move(__result), + __comp) + .__out_; +} + +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _OutputIterator set_symmetric_difference( + _InputIterator1 __first1, + _InputIterator1 __last1, + _InputIterator2 __first2, + _InputIterator2 __last2, + _OutputIterator __result) { + return std::set_symmetric_difference( + std::move(__first1), + std::move(__last1), + std::move(__first2), + std::move(__last2), + std::move(__result), + __less::value_type, + typename iterator_traits<_InputIterator2>::value_type>()); +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ALGORITHM_SET_SYMMETRIC_DIFFERENCE_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/set_union.h b/app/src/main/cpp/libcxx/include/__algorithm/set_union.h new file mode 100644 index 0000000..4d154b8 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/set_union.h @@ -0,0 +1,101 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_SET_UNION_H +#define _LIBCPP___ALGORITHM_SET_UNION_H + +#include <__algorithm/comp.h> +#include <__algorithm/comp_ref_type.h> +#include <__algorithm/copy.h> +#include <__algorithm/iterator_operations.h> +#include <__config> +#include <__iterator/iterator_traits.h> +#include <__utility/move.h> +#include <__utility/pair.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +template +struct __set_union_result { + _InIter1 __in1_; + _InIter2 __in2_; + _OutIter __out_; + + // need a constructor as C++03 aggregate init is hard + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 + __set_union_result(_InIter1&& __in_iter1, _InIter2&& __in_iter2, _OutIter&& __out_iter) + : __in1_(std::move(__in_iter1)), __in2_(std::move(__in_iter2)), __out_(std::move(__out_iter)) {} +}; + +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __set_union_result<_InIter1, _InIter2, _OutIter> __set_union( + _InIter1 __first1, _Sent1 __last1, _InIter2 __first2, _Sent2 __last2, _OutIter __result, _Compare&& __comp) { + for (; __first1 != __last1; ++__result) { + if (__first2 == __last2) { + auto __ret1 = std::__copy<_AlgPolicy>(std::move(__first1), std::move(__last1), std::move(__result)); + return __set_union_result<_InIter1, _InIter2, _OutIter>( + std::move(__ret1.first), std::move(__first2), std::move((__ret1.second))); + } + if (__comp(*__first2, *__first1)) { + *__result = *__first2; + ++__first2; + } else { + if (!__comp(*__first1, *__first2)) { + ++__first2; + } + *__result = *__first1; + ++__first1; + } + } + auto __ret2 = std::__copy<_AlgPolicy>(std::move(__first2), std::move(__last2), std::move(__result)); + return __set_union_result<_InIter1, _InIter2, _OutIter>( + std::move(__first1), std::move(__ret2.first), std::move((__ret2.second))); +} + +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _OutputIterator set_union( + _InputIterator1 __first1, + _InputIterator1 __last1, + _InputIterator2 __first2, + _InputIterator2 __last2, + _OutputIterator __result, + _Compare __comp) { + return std::__set_union<_ClassicAlgPolicy, __comp_ref_type<_Compare> >( + std::move(__first1), + std::move(__last1), + std::move(__first2), + std::move(__last2), + std::move(__result), + __comp) + .__out_; +} + +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _OutputIterator set_union( + _InputIterator1 __first1, + _InputIterator1 __last1, + _InputIterator2 __first2, + _InputIterator2 __last2, + _OutputIterator __result) { + return std::set_union( + std::move(__first1), + std::move(__last1), + std::move(__first2), + std::move(__last2), + std::move(__result), + __less::value_type, + typename iterator_traits<_InputIterator2>::value_type>()); +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ALGORITHM_SET_UNION_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/shift_left.h b/app/src/main/cpp/libcxx/include/__algorithm/shift_left.h new file mode 100644 index 0000000..33f06d5 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/shift_left.h @@ -0,0 +1,56 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_SHIFT_LEFT_H +#define _LIBCPP___ALGORITHM_SHIFT_LEFT_H + +#include <__algorithm/move.h> +#include <__config> +#include <__iterator/iterator_traits.h> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 17 + +template +inline _LIBCPP_INLINE_VISIBILITY constexpr +_ForwardIterator +shift_left(_ForwardIterator __first, _ForwardIterator __last, + typename iterator_traits<_ForwardIterator>::difference_type __n) +{ + if (__n == 0) { + return __last; + } + + _ForwardIterator __m = __first; + if constexpr (__is_cpp17_random_access_iterator<_ForwardIterator>::value) { + if (__n >= __last - __first) { + return __first; + } + __m += __n; + } else { + for (; __n > 0; --__n) { + if (__m == __last) { + return __first; + } + ++__m; + } + } + return _VSTD::move(__m, __last, __first); +} + +#endif // _LIBCPP_STD_VER > 17 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ALGORITHM_SHIFT_LEFT_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/shift_right.h b/app/src/main/cpp/libcxx/include/__algorithm/shift_right.h new file mode 100644 index 0000000..14bc761 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/shift_right.h @@ -0,0 +1,102 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_SHIFT_RIGHT_H +#define _LIBCPP___ALGORITHM_SHIFT_RIGHT_H + +#include <__algorithm/move.h> +#include <__algorithm/move_backward.h> +#include <__algorithm/swap_ranges.h> +#include <__config> +#include <__iterator/iterator_traits.h> +#include <__utility/swap.h> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 17 + +template +inline _LIBCPP_INLINE_VISIBILITY constexpr +_ForwardIterator +shift_right(_ForwardIterator __first, _ForwardIterator __last, + typename iterator_traits<_ForwardIterator>::difference_type __n) +{ + if (__n == 0) { + return __first; + } + + if constexpr (__is_cpp17_random_access_iterator<_ForwardIterator>::value) { + decltype(__n) __d = __last - __first; + if (__n >= __d) { + return __last; + } + _ForwardIterator __m = __first + (__d - __n); + return _VSTD::move_backward(__first, __m, __last); + } else if constexpr (__is_cpp17_bidirectional_iterator<_ForwardIterator>::value) { + _ForwardIterator __m = __last; + for (; __n > 0; --__n) { + if (__m == __first) { + return __last; + } + --__m; + } + return _VSTD::move_backward(__first, __m, __last); + } else { + _ForwardIterator __ret = __first; + for (; __n > 0; --__n) { + if (__ret == __last) { + return __last; + } + ++__ret; + } + + // We have an __n-element scratch space from __first to __ret. + // Slide an __n-element window [__trail, __lead) from left to right. + // We're essentially doing swap_ranges(__first, __ret, __trail, __lead) + // over and over; but once __lead reaches __last we needn't bother + // to save the values of elements [__trail, __last). + + auto __trail = __first; + auto __lead = __ret; + while (__trail != __ret) { + if (__lead == __last) { + _VSTD::move(__first, __trail, __ret); + return __ret; + } + ++__trail; + ++__lead; + } + + _ForwardIterator __mid = __first; + while (true) { + if (__lead == __last) { + __trail = _VSTD::move(__mid, __ret, __trail); + _VSTD::move(__first, __mid, __trail); + return __ret; + } + swap(*__mid, *__trail); + ++__mid; + ++__trail; + ++__lead; + if (__mid == __ret) { + __mid = __first; + } + } + } +} + +#endif // _LIBCPP_STD_VER > 17 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ALGORITHM_SHIFT_RIGHT_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/shuffle.h b/app/src/main/cpp/libcxx/include/__algorithm/shuffle.h new file mode 100644 index 0000000..f7bce68 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/shuffle.h @@ -0,0 +1,175 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_SHUFFLE_H +#define _LIBCPP___ALGORITHM_SHUFFLE_H + +#include <__algorithm/iterator_operations.h> +#include <__config> +#include <__debug> +#include <__iterator/iterator_traits.h> +#include <__random/uniform_int_distribution.h> +#include <__utility/forward.h> +#include <__utility/move.h> +#include <__utility/swap.h> +#include +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + +_LIBCPP_BEGIN_NAMESPACE_STD + +class _LIBCPP_TYPE_VIS __libcpp_debug_randomizer { +public: + __libcpp_debug_randomizer() { + __state_ = __seed(); + __inc_ = __state_ + 0xda3e39cb94b95bdbULL; + __inc_ = (__inc_ << 1) | 1; + } + typedef uint_fast32_t result_type; + + static const result_type _Min = 0; + static const result_type _Max = 0xFFFFFFFF; + + _LIBCPP_HIDE_FROM_ABI result_type operator()() { + uint_fast64_t __oldstate = __state_; + __state_ = __oldstate * 6364136223846793005ULL + __inc_; + return __oldstate >> 32; + } + + static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR result_type min() { return _Min; } + static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR result_type max() { return _Max; } + +private: + uint_fast64_t __state_; + uint_fast64_t __inc_; + _LIBCPP_HIDE_FROM_ABI static uint_fast64_t __seed() { +#ifdef _LIBCPP_DEBUG_RANDOMIZE_UNSPECIFIED_STABILITY_SEED + return _LIBCPP_DEBUG_RANDOMIZE_UNSPECIFIED_STABILITY_SEED; +#else + static char __x; + return reinterpret_cast(&__x); +#endif + } +}; + +#if _LIBCPP_STD_VER <= 14 || defined(_LIBCPP_ENABLE_CXX17_REMOVED_RANDOM_SHUFFLE) \ + || defined(_LIBCPP_BUILDING_LIBRARY) +class _LIBCPP_TYPE_VIS __rs_default; + +_LIBCPP_FUNC_VIS __rs_default __rs_get(); + +class _LIBCPP_TYPE_VIS __rs_default +{ + static unsigned __c_; + + __rs_default(); +public: + typedef uint_fast32_t result_type; + + static const result_type _Min = 0; + static const result_type _Max = 0xFFFFFFFF; + + __rs_default(const __rs_default&); + ~__rs_default(); + + result_type operator()(); + + static _LIBCPP_CONSTEXPR result_type min() {return _Min;} + static _LIBCPP_CONSTEXPR result_type max() {return _Max;} + + friend _LIBCPP_FUNC_VIS __rs_default __rs_get(); +}; + +_LIBCPP_FUNC_VIS __rs_default __rs_get(); + +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_DEPRECATED_IN_CXX14 void +random_shuffle(_RandomAccessIterator __first, _RandomAccessIterator __last) +{ + typedef typename iterator_traits<_RandomAccessIterator>::difference_type difference_type; + typedef uniform_int_distribution _Dp; + typedef typename _Dp::param_type _Pp; + difference_type __d = __last - __first; + if (__d > 1) + { + _Dp __uid; + __rs_default __g = __rs_get(); + for (--__last, (void) --__d; __first < __last; ++__first, (void) --__d) + { + difference_type __i = __uid(__g, _Pp(0, __d)); + if (__i != difference_type(0)) + swap(*__first, *(__first + __i)); + } + } +} + +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_DEPRECATED_IN_CXX14 void +random_shuffle(_RandomAccessIterator __first, _RandomAccessIterator __last, +#ifndef _LIBCPP_CXX03_LANG + _RandomNumberGenerator&& __rand) +#else + _RandomNumberGenerator& __rand) +#endif +{ + typedef typename iterator_traits<_RandomAccessIterator>::difference_type difference_type; + difference_type __d = __last - __first; + if (__d > 1) + { + for (--__last; __first < __last; ++__first, (void) --__d) + { + difference_type __i = __rand(__d); + if (__i != difference_type(0)) + swap(*__first, *(__first + __i)); + } + } +} +#endif + +template +_LIBCPP_HIDE_FROM_ABI _RandomAccessIterator __shuffle( + _RandomAccessIterator __first, _Sentinel __last_sentinel, _UniformRandomNumberGenerator&& __g) { + typedef typename iterator_traits<_RandomAccessIterator>::difference_type difference_type; + typedef uniform_int_distribution _Dp; + typedef typename _Dp::param_type _Pp; + + auto __original_last = _IterOps<_AlgPolicy>::next(__first, __last_sentinel); + auto __last = __original_last; + difference_type __d = __last - __first; + if (__d > 1) + { + _Dp __uid; + for (--__last, (void) --__d; __first < __last; ++__first, (void) --__d) + { + difference_type __i = __uid(__g, _Pp(0, __d)); + if (__i != difference_type(0)) + _IterOps<_AlgPolicy>::iter_swap(__first, __first + __i); + } + } + + return __original_last; +} + +template +_LIBCPP_HIDE_FROM_ABI void +shuffle(_RandomAccessIterator __first, _RandomAccessIterator __last, _UniformRandomNumberGenerator&& __g) { + (void)std::__shuffle<_ClassicAlgPolicy>( + std::move(__first), std::move(__last), std::forward<_UniformRandomNumberGenerator>(__g)); +} + +_LIBCPP_END_NAMESPACE_STD + +_LIBCPP_POP_MACROS + +#endif // _LIBCPP___ALGORITHM_SHUFFLE_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/sift_down.h b/app/src/main/cpp/libcxx/include/__algorithm/sift_down.h new file mode 100644 index 0000000..e3972fb --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/sift_down.h @@ -0,0 +1,114 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_SIFT_DOWN_H +#define _LIBCPP___ALGORITHM_SIFT_DOWN_H + +#include <__algorithm/iterator_operations.h> +#include <__assert> +#include <__config> +#include <__iterator/iterator_traits.h> +#include <__utility/move.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 void +__sift_down(_RandomAccessIterator __first, _Compare&& __comp, + typename iterator_traits<_RandomAccessIterator>::difference_type __len, + _RandomAccessIterator __start) +{ + using _Ops = _IterOps<_AlgPolicy>; + + typedef typename iterator_traits<_RandomAccessIterator>::difference_type difference_type; + typedef typename iterator_traits<_RandomAccessIterator>::value_type value_type; + // left-child of __start is at 2 * __start + 1 + // right-child of __start is at 2 * __start + 2 + difference_type __child = __start - __first; + + if (__len < 2 || (__len - 2) / 2 < __child) + return; + + __child = 2 * __child + 1; + _RandomAccessIterator __child_i = __first + __child; + + if ((__child + 1) < __len && __comp(*__child_i, *(__child_i + difference_type(1)))) { + // right-child exists and is greater than left-child + ++__child_i; + ++__child; + } + + // check if we are in heap-order + if (__comp(*__child_i, *__start)) + // we are, __start is larger than its largest child + return; + + value_type __top(_Ops::__iter_move(__start)); + do + { + // we are not in heap-order, swap the parent with its largest child + *__start = _Ops::__iter_move(__child_i); + __start = __child_i; + + if ((__len - 2) / 2 < __child) + break; + + // recompute the child based off of the updated parent + __child = 2 * __child + 1; + __child_i = __first + __child; + + if ((__child + 1) < __len && __comp(*__child_i, *(__child_i + difference_type(1)))) { + // right-child exists and is greater than left-child + ++__child_i; + ++__child; + } + + // check if we are in heap-order + } while (!__comp(*__child_i, __top)); + *__start = _VSTD::move(__top); +} + +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _RandomAccessIterator +__floyd_sift_down(_RandomAccessIterator __first, _Compare&& __comp, + typename iterator_traits<_RandomAccessIterator>::difference_type __len) +{ + using difference_type = typename iterator_traits<_RandomAccessIterator>::difference_type; + _LIBCPP_ASSERT(__len >= 2, "shouldn't be called unless __len >= 2"); + + _RandomAccessIterator __hole = __first; + _RandomAccessIterator __child_i = __first; + difference_type __child = 0; + + while (true) { + __child_i += difference_type(__child + 1); + __child = 2 * __child + 1; + + if ((__child + 1) < __len && __comp(*__child_i, *(__child_i + difference_type(1)))) { + // right-child exists and is greater than left-child + ++__child_i; + ++__child; + } + + // swap __hole with its largest child + *__hole = _IterOps<_AlgPolicy>::__iter_move(__child_i); + __hole = __child_i; + + // if __hole is now a leaf, we're done + if (__child > (__len - 2) / 2) + return __hole; + } +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ALGORITHM_SIFT_DOWN_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/sort.h b/app/src/main/cpp/libcxx/include/__algorithm/sort.h new file mode 100644 index 0000000..a7d2d55 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/sort.h @@ -0,0 +1,1001 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_SORT_H +#define _LIBCPP___ALGORITHM_SORT_H + +#include <__algorithm/comp.h> +#include <__algorithm/comp_ref_type.h> +#include <__algorithm/iter_swap.h> +#include <__algorithm/iterator_operations.h> +#include <__algorithm/min_element.h> +#include <__algorithm/partial_sort.h> +#include <__algorithm/unwrap_iter.h> +#include <__assert> +#include <__bit/blsr.h> +#include <__bit/countl.h> +#include <__bit/countr.h> +#include <__config> +#include <__debug> +#include <__debug_utils/randomize_range.h> +#include <__functional/operations.h> +#include <__functional/ranges_operations.h> +#include <__iterator/iterator_traits.h> +#include <__memory/destruct_n.h> +#include <__memory/unique_ptr.h> +#include <__type_traits/conditional.h> +#include <__type_traits/is_arithmetic.h> +#include <__utility/move.h> +#include <__utility/pair.h> +#include +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +// Wraps an algorithm policy tag and a comparator in a single struct, used to pass the policy tag around without +// changing the number of template arguments (to keep the ABI stable). This is only used for the "range" policy tag. +// +// To create an object of this type, use `_WrapAlgPolicy::type` -- see the specialization below for the rationale. +template +struct _WrapAlgPolicy { + using type = _WrapAlgPolicy; + + using _AlgPolicy = _PolicyT; + using _Comp = _CompT; + _Comp& __comp; + + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 + _WrapAlgPolicy(_Comp& __c) : __comp(__c) {} +}; + +// Specialization for the "classic" policy tag that avoids creating a struct and simply defines an alias for the +// comparator. When unwrapping, a pristine comparator is always considered to have the "classic" tag attached. Passing +// the pristine comparator where possible allows using template instantiations from the dylib. +template +struct _WrapAlgPolicy<_PolicyT, _CompT, __enable_if_t::value> > { + using type = _CompT; +}; + +// Unwraps a pristine functor (e.g. `std::less`) as if it were wrapped using `_WrapAlgPolicy`. The policy tag is always +// set to "classic". +template +struct _UnwrapAlgPolicy { + using _AlgPolicy = _ClassicAlgPolicy; + using _Comp = _CompT; + + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 static + _Comp __get_comp(_Comp __comp) { return __comp; } +}; + +// Unwraps a `_WrapAlgPolicy` struct. +template +struct _UnwrapAlgPolicy<_WrapAlgPolicy<_Ts...> > { + using _Wrapped = _WrapAlgPolicy<_Ts...>; + using _AlgPolicy = typename _Wrapped::_AlgPolicy; + using _Comp = typename _Wrapped::_Comp; + + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 static + _Comp __get_comp(_Wrapped& __w) { return __w.__comp; } +}; + +// stable, 2-3 compares, 0-2 swaps + +template +_LIBCPP_HIDE_FROM_ABI +_LIBCPP_CONSTEXPR_SINCE_CXX14 unsigned __sort3(_ForwardIterator __x, _ForwardIterator __y, _ForwardIterator __z, + _Compare __c) { + using _Ops = _IterOps<_AlgPolicy>; + + unsigned __r = 0; + if (!__c(*__y, *__x)) // if x <= y + { + if (!__c(*__z, *__y)) // if y <= z + return __r; // x <= y && y <= z + // x <= y && y > z + _Ops::iter_swap(__y, __z); // x <= z && y < z + __r = 1; + if (__c(*__y, *__x)) // if x > y + { + _Ops::iter_swap(__x, __y); // x < y && y <= z + __r = 2; + } + return __r; // x <= y && y < z + } + if (__c(*__z, *__y)) // x > y, if y > z + { + _Ops::iter_swap(__x, __z); // x < y && y < z + __r = 1; + return __r; + } + _Ops::iter_swap(__x, __y); // x > y && y <= z + __r = 1; // x < y && x <= z + if (__c(*__z, *__y)) // if y > z + { + _Ops::iter_swap(__y, __z); // x <= y && y < z + __r = 2; + } + return __r; +} // x <= y && y <= z + +// stable, 3-6 compares, 0-5 swaps + +template +_LIBCPP_HIDE_FROM_ABI +unsigned __sort4(_ForwardIterator __x1, _ForwardIterator __x2, _ForwardIterator __x3, _ForwardIterator __x4, + _Compare __c) { + using _Ops = _IterOps<_AlgPolicy>; + unsigned __r = std::__sort3<_AlgPolicy, _Compare>(__x1, __x2, __x3, __c); + if (__c(*__x4, *__x3)) { + _Ops::iter_swap(__x3, __x4); + ++__r; + if (__c(*__x3, *__x2)) { + _Ops::iter_swap(__x2, __x3); + ++__r; + if (__c(*__x2, *__x1)) { + _Ops::iter_swap(__x1, __x2); + ++__r; + } + } + } + return __r; +} + +// stable, 4-10 compares, 0-9 swaps + +template +_LIBCPP_HIDDEN unsigned __sort5(_ForwardIterator __x1, _ForwardIterator __x2, _ForwardIterator __x3, + _ForwardIterator __x4, _ForwardIterator __x5, _WrappedComp __wrapped_comp) { + using _Unwrap = _UnwrapAlgPolicy<_WrappedComp>; + using _AlgPolicy = typename _Unwrap::_AlgPolicy; + using _Ops = _IterOps<_AlgPolicy>; + + using _Compare = typename _Unwrap::_Comp; + _Compare __c = _Unwrap::__get_comp(__wrapped_comp); + + unsigned __r = std::__sort4<_AlgPolicy, _Compare>(__x1, __x2, __x3, __x4, __c); + if (__c(*__x5, *__x4)) { + _Ops::iter_swap(__x4, __x5); + ++__r; + if (__c(*__x4, *__x3)) { + _Ops::iter_swap(__x3, __x4); + ++__r; + if (__c(*__x3, *__x2)) { + _Ops::iter_swap(__x2, __x3); + ++__r; + if (__c(*__x2, *__x1)) { + _Ops::iter_swap(__x1, __x2); + ++__r; + } + } + } + } + return __r; +} + +template +_LIBCPP_HIDE_FROM_ABI unsigned __sort5_wrap_policy( + _ForwardIterator __x1, _ForwardIterator __x2, _ForwardIterator __x3, _ForwardIterator __x4, _ForwardIterator __x5, + _Compare __c) { + using _WrappedComp = typename _WrapAlgPolicy<_AlgPolicy, _Compare>::type; + _WrappedComp __wrapped_comp(__c); + return std::__sort5<_WrappedComp, _ForwardIterator>( + std::move(__x1), std::move(__x2), std::move(__x3), std::move(__x4), std::move(__x5), __wrapped_comp); +} + +// The comparator being simple is a prerequisite for using the branchless optimization. +template +struct __is_simple_comparator : false_type {}; +template +struct __is_simple_comparator<__less<_Tp>&> : true_type {}; +template +struct __is_simple_comparator&> : true_type {}; +template +struct __is_simple_comparator&> : true_type {}; +#if _LIBCPP_STD_VER > 17 +template <> +struct __is_simple_comparator : true_type {}; +template <> +struct __is_simple_comparator : true_type {}; +#endif + +template ::value_type> +using __use_branchless_sort = + integral_constant::value && sizeof(_Tp) <= sizeof(void*) && + is_arithmetic<_Tp>::value && __is_simple_comparator<_Compare>::value>; + +namespace __detail { + +// Size in bits for the bitset in use. +enum { __block_size = sizeof(uint64_t) * 8 }; + +} // namespace __detail + +// Ensures that __c(*__x, *__y) is true by swapping *__x and *__y if necessary. +template +inline _LIBCPP_HIDE_FROM_ABI void __cond_swap(_RandomAccessIterator __x, _RandomAccessIterator __y, _Compare __c) { + // Note: this function behaves correctly even with proxy iterators (because it relies on `value_type`). + using value_type = typename iterator_traits<_RandomAccessIterator>::value_type; + bool __r = __c(*__x, *__y); + value_type __tmp = __r ? *__x : *__y; + *__y = __r ? *__y : *__x; + *__x = __tmp; +} + +// Ensures that *__x, *__y and *__z are ordered according to the comparator __c, +// under the assumption that *__y and *__z are already ordered. +template +inline _LIBCPP_HIDE_FROM_ABI void __partially_sorted_swap(_RandomAccessIterator __x, _RandomAccessIterator __y, + _RandomAccessIterator __z, _Compare __c) { + // Note: this function behaves correctly even with proxy iterators (because it relies on `value_type`). + using value_type = typename iterator_traits<_RandomAccessIterator>::value_type; + bool __r = __c(*__z, *__x); + value_type __tmp = __r ? *__z : *__x; + *__z = __r ? *__x : *__z; + __r = __c(__tmp, *__y); + *__x = __r ? *__x : *__y; + *__y = __r ? *__y : __tmp; +} + +template +inline _LIBCPP_HIDE_FROM_ABI __enable_if_t<__use_branchless_sort<_Compare, _RandomAccessIterator>::value, void> +__sort3_maybe_branchless(_RandomAccessIterator __x1, _RandomAccessIterator __x2, _RandomAccessIterator __x3, + _Compare __c) { + std::__cond_swap<_Compare>(__x2, __x3, __c); + std::__partially_sorted_swap<_Compare>(__x1, __x2, __x3, __c); +} + +template +inline _LIBCPP_HIDE_FROM_ABI __enable_if_t::value, void> +__sort3_maybe_branchless(_RandomAccessIterator __x1, _RandomAccessIterator __x2, _RandomAccessIterator __x3, + _Compare __c) { + std::__sort3<_AlgPolicy, _Compare>(__x1, __x2, __x3, __c); +} + +template +inline _LIBCPP_HIDE_FROM_ABI __enable_if_t<__use_branchless_sort<_Compare, _RandomAccessIterator>::value, void> +__sort4_maybe_branchless(_RandomAccessIterator __x1, _RandomAccessIterator __x2, _RandomAccessIterator __x3, + _RandomAccessIterator __x4, _Compare __c) { + std::__cond_swap<_Compare>(__x1, __x3, __c); + std::__cond_swap<_Compare>(__x2, __x4, __c); + std::__cond_swap<_Compare>(__x1, __x2, __c); + std::__cond_swap<_Compare>(__x3, __x4, __c); + std::__cond_swap<_Compare>(__x2, __x3, __c); +} + +template +inline _LIBCPP_HIDE_FROM_ABI __enable_if_t::value, void> +__sort4_maybe_branchless(_RandomAccessIterator __x1, _RandomAccessIterator __x2, _RandomAccessIterator __x3, + _RandomAccessIterator __x4, _Compare __c) { + std::__sort4<_AlgPolicy, _Compare>(__x1, __x2, __x3, __x4, __c); +} + +template +inline _LIBCPP_HIDE_FROM_ABI __enable_if_t<__use_branchless_sort<_Compare, _RandomAccessIterator>::value, void> +__sort5_maybe_branchless( + _RandomAccessIterator __x1, + _RandomAccessIterator __x2, + _RandomAccessIterator __x3, + _RandomAccessIterator __x4, + _RandomAccessIterator __x5, + _Compare __c) { + std::__cond_swap<_Compare>(__x1, __x2, __c); + std::__cond_swap<_Compare>(__x4, __x5, __c); + std::__partially_sorted_swap<_Compare>(__x3, __x4, __x5, __c); + std::__cond_swap<_Compare>(__x2, __x5, __c); + std::__partially_sorted_swap<_Compare>(__x1, __x3, __x4, __c); + std::__partially_sorted_swap<_Compare>(__x2, __x3, __x4, __c); +} + +template +inline _LIBCPP_HIDE_FROM_ABI __enable_if_t::value, void> +__sort5_maybe_branchless(_RandomAccessIterator __x1, _RandomAccessIterator __x2, _RandomAccessIterator __x3, + _RandomAccessIterator __x4, _RandomAccessIterator __x5, _Compare __c) { + std::__sort5_wrap_policy<_AlgPolicy, _Compare>(__x1, __x2, __x3, __x4, __x5, __c); +} + +// Assumes size > 0 +template +_LIBCPP_HIDE_FROM_ABI +_LIBCPP_CONSTEXPR_SINCE_CXX14 void __selection_sort(_BidirectionalIterator __first, _BidirectionalIterator __last, + _Compare __comp) { + _BidirectionalIterator __lm1 = __last; + for (--__lm1; __first != __lm1; ++__first) { + _BidirectionalIterator __i = std::__min_element<_Compare>(__first, __last, __comp); + if (__i != __first) + _IterOps<_AlgPolicy>::iter_swap(__first, __i); + } +} + +// Sort the iterator range [__first, __last) using the comparator __comp using +// the insertion sort algorithm. +template +_LIBCPP_HIDE_FROM_ABI +void __insertion_sort(_BidirectionalIterator __first, _BidirectionalIterator __last, _Compare __comp) { + using _Ops = _IterOps<_AlgPolicy>; + + typedef typename iterator_traits<_BidirectionalIterator>::value_type value_type; + if (__first == __last) + return; + _BidirectionalIterator __i = __first; + for (++__i; __i != __last; ++__i) { + _BidirectionalIterator __j = __i; + --__j; + if (__comp(*__i, *__j)) { + value_type __t(_Ops::__iter_move(__i)); + _BidirectionalIterator __k = __j; + __j = __i; + do { + *__j = _Ops::__iter_move(__k); + __j = __k; + } while (__j != __first && __comp(__t, *--__k)); + *__j = std::move(__t); + } + } +} + +// Sort the iterator range [__first, __last) using the comparator __comp using +// the insertion sort algorithm. Insertion sort has two loops, outer and inner. +// The implementation below has not bounds check (unguarded) for the inner loop. +// Assumes that there is an element in the position (__first - 1) and that each +// element in the input range is greater or equal to the element at __first - 1. +template +_LIBCPP_HIDE_FROM_ABI void +__insertion_sort_unguarded(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp) { + using _Ops = _IterOps<_AlgPolicy>; + typedef typename iterator_traits<_RandomAccessIterator>::difference_type difference_type; + typedef typename iterator_traits<_RandomAccessIterator>::value_type value_type; + if (__first == __last) + return; + for (_RandomAccessIterator __i = __first + difference_type(1); __i != __last; ++__i) { + _RandomAccessIterator __j = __i - difference_type(1); + if (__comp(*__i, *__j)) { + value_type __t(_Ops::__iter_move(__i)); + _RandomAccessIterator __k = __j; + __j = __i; + do { + *__j = _Ops::__iter_move(__k); + __j = __k; + } while (__comp(__t, *--__k)); // No need for bounds check due to the assumption stated above. + *__j = std::move(__t); + } + } +} + +template +_LIBCPP_HIDDEN bool __insertion_sort_incomplete( + _RandomAccessIterator __first, _RandomAccessIterator __last, _WrappedComp __wrapped_comp) { + using _Unwrap = _UnwrapAlgPolicy<_WrappedComp>; + using _AlgPolicy = typename _Unwrap::_AlgPolicy; + using _Ops = _IterOps<_AlgPolicy>; + + using _Compare = typename _Unwrap::_Comp; + _Compare __comp = _Unwrap::__get_comp(__wrapped_comp); + + typedef typename iterator_traits<_RandomAccessIterator>::difference_type difference_type; + switch (__last - __first) { + case 0: + case 1: + return true; + case 2: + if (__comp(*--__last, *__first)) + _Ops::iter_swap(__first, __last); + return true; + case 3: + std::__sort3_maybe_branchless<_AlgPolicy, _Compare>(__first, __first + difference_type(1), --__last, __comp); + return true; + case 4: + std::__sort4_maybe_branchless<_AlgPolicy, _Compare>( + __first, __first + difference_type(1), __first + difference_type(2), --__last, __comp); + return true; + case 5: + std::__sort5_maybe_branchless<_AlgPolicy, _Compare>( + __first, __first + difference_type(1), __first + difference_type(2), __first + difference_type(3), + --__last, __comp); + return true; + } + typedef typename iterator_traits<_RandomAccessIterator>::value_type value_type; + _RandomAccessIterator __j = __first + difference_type(2); + std::__sort3_maybe_branchless<_AlgPolicy, _Compare>(__first, __first + difference_type(1), __j, __comp); + const unsigned __limit = 8; + unsigned __count = 0; + for (_RandomAccessIterator __i = __j + difference_type(1); __i != __last; ++__i) { + if (__comp(*__i, *__j)) { + value_type __t(_Ops::__iter_move(__i)); + _RandomAccessIterator __k = __j; + __j = __i; + do { + *__j = _Ops::__iter_move(__k); + __j = __k; + } while (__j != __first && __comp(__t, *--__k)); + *__j = std::move(__t); + if (++__count == __limit) + return ++__i == __last; + } + __j = __i; + } + return true; +} + +template +_LIBCPP_HIDE_FROM_ABI +void __insertion_sort_move(_BidirectionalIterator __first1, _BidirectionalIterator __last1, + typename iterator_traits<_BidirectionalIterator>::value_type* __first2, _Compare __comp) { + using _Ops = _IterOps<_AlgPolicy>; + + typedef typename iterator_traits<_BidirectionalIterator>::value_type value_type; + if (__first1 != __last1) { + __destruct_n __d(0); + unique_ptr __h(__first2, __d); + value_type* __last2 = __first2; + ::new ((void*)__last2) value_type(_Ops::__iter_move(__first1)); + __d.template __incr(); + for (++__last2; ++__first1 != __last1; ++__last2) { + value_type* __j2 = __last2; + value_type* __i2 = __j2; + if (__comp(*__first1, *--__i2)) { + ::new ((void*)__j2) value_type(std::move(*__i2)); + __d.template __incr(); + for (--__j2; __i2 != __first2 && __comp(*__first1, *--__i2); --__j2) + *__j2 = std::move(*__i2); + *__j2 = _Ops::__iter_move(__first1); + } else { + ::new ((void*)__j2) value_type(_Ops::__iter_move(__first1)); + __d.template __incr(); + } + } + __h.release(); + } +} + +template +inline _LIBCPP_HIDE_FROM_ABI void __swap_bitmap_pos( + _RandomAccessIterator __first, _RandomAccessIterator __last, uint64_t& __left_bitset, uint64_t& __right_bitset) { + using _Ops = _IterOps<_AlgPolicy>; + typedef typename std::iterator_traits<_RandomAccessIterator>::difference_type difference_type; + // Swap one pair on each iteration as long as both bitsets have at least one + // element for swapping. + while (__left_bitset != 0 && __right_bitset != 0) { + difference_type tz_left = __libcpp_ctz(__left_bitset); + __left_bitset = __libcpp_blsr(__left_bitset); + difference_type tz_right = __libcpp_ctz(__right_bitset); + __right_bitset = __libcpp_blsr(__right_bitset); + _Ops::iter_swap(__first + tz_left, __last - tz_right); + } +} + +template ::value_type> +inline _LIBCPP_HIDE_FROM_ABI void +__populate_left_bitset(_RandomAccessIterator __first, _Compare __comp, _ValueType& __pivot, uint64_t& __left_bitset) { + // Possible vectorization. With a proper "-march" flag, the following loop + // will be compiled into a set of SIMD instructions. + _RandomAccessIterator __iter = __first; + for (int __j = 0; __j < __detail::__block_size;) { + bool __comp_result = !__comp(*__iter, __pivot); + __left_bitset |= (static_cast(__comp_result) << __j); + __j++; + ++__iter; + } +} + +template ::value_type> +inline _LIBCPP_HIDE_FROM_ABI void +__populate_right_bitset(_RandomAccessIterator __lm1, _Compare __comp, _ValueType& __pivot, uint64_t& __right_bitset) { + // Possible vectorization. With a proper "-march" flag, the following loop + // will be compiled into a set of SIMD instructions. + _RandomAccessIterator __iter = __lm1; + for (int __j = 0; __j < __detail::__block_size;) { + bool __comp_result = __comp(*__iter, __pivot); + __right_bitset |= (static_cast(__comp_result) << __j); + __j++; + --__iter; + } +} + +template ::value_type> +inline _LIBCPP_HIDE_FROM_ABI void __bitset_partition_partial_blocks( + _RandomAccessIterator& __first, + _RandomAccessIterator& __lm1, + _Compare __comp, + _ValueType& __pivot, + uint64_t& __left_bitset, + uint64_t& __right_bitset) { + typedef typename std::iterator_traits<_RandomAccessIterator>::difference_type difference_type; + difference_type __remaining_len = __lm1 - __first + 1; + difference_type __l_size; + difference_type __r_size; + if (__left_bitset == 0 && __right_bitset == 0) { + __l_size = __remaining_len / 2; + __r_size = __remaining_len - __l_size; + } else if (__left_bitset == 0) { + // We know at least one side is a full block. + __l_size = __remaining_len - __detail::__block_size; + __r_size = __detail::__block_size; + } else { // if (__right_bitset == 0) + __l_size = __detail::__block_size; + __r_size = __remaining_len - __detail::__block_size; + } + // Record the comparison outcomes for the elements currently on the left side. + if (__left_bitset == 0) { + _RandomAccessIterator __iter = __first; + for (int j = 0; j < __l_size; j++) { + bool __comp_result = !__comp(*__iter, __pivot); + __left_bitset |= (static_cast(__comp_result) << j); + ++__iter; + } + } + // Record the comparison outcomes for the elements currently on the right + // side. + if (__right_bitset == 0) { + _RandomAccessIterator __iter = __lm1; + for (int j = 0; j < __r_size; j++) { + bool __comp_result = __comp(*__iter, __pivot); + __right_bitset |= (static_cast(__comp_result) << j); + --__iter; + } + } + std::__swap_bitmap_pos<_AlgPolicy, _RandomAccessIterator>(__first, __lm1, __left_bitset, __right_bitset); + __first += (__left_bitset == 0) ? __l_size : 0; + __lm1 -= (__right_bitset == 0) ? __r_size : 0; +} + +template +inline _LIBCPP_HIDE_FROM_ABI void __swap_bitmap_pos_within( + _RandomAccessIterator& __first, _RandomAccessIterator& __lm1, uint64_t& __left_bitset, uint64_t& __right_bitset) { + using _Ops = _IterOps<_AlgPolicy>; + typedef typename std::iterator_traits<_RandomAccessIterator>::difference_type difference_type; + if (__left_bitset) { + // Swap within the left side. Need to find set positions in the reverse + // order. + while (__left_bitset != 0) { + difference_type __tz_left = __detail::__block_size - 1 - __libcpp_clz(__left_bitset); + __left_bitset &= (static_cast(1) << __tz_left) - 1; + _RandomAccessIterator it = __first + __tz_left; + if (it != __lm1) { + _Ops::iter_swap(it, __lm1); + } + --__lm1; + } + __first = __lm1 + difference_type(1); + } else if (__right_bitset) { + // Swap within the right side. Need to find set positions in the reverse + // order. + while (__right_bitset != 0) { + difference_type __tz_right = __detail::__block_size - 1 - __libcpp_clz(__right_bitset); + __right_bitset &= (static_cast(1) << __tz_right) - 1; + _RandomAccessIterator it = __lm1 - __tz_right; + if (it != __first) { + _Ops::iter_swap(it, __first); + } + ++__first; + } + } +} + +// Partition [__first, __last) using the comparator __comp. *__first has the +// chosen pivot. Elements that are equivalent are kept to the left of the +// pivot. Returns the iterator for the pivot and a bool value which is true if +// the provided range is already sorted, false otherwise. We assume that the +// length of the range is at least three elements. +// +// __bitset_partition uses bitsets for storing outcomes of the comparisons +// between the pivot and other elements. +template +_LIBCPP_HIDE_FROM_ABI std::pair<_RandomAccessIterator, bool> +__bitset_partition(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp) { + using _Ops = _IterOps<_AlgPolicy>; + typedef typename std::iterator_traits<_RandomAccessIterator>::value_type value_type; + typedef typename std::iterator_traits<_RandomAccessIterator>::difference_type difference_type; + _LIBCPP_ASSERT(__last - __first >= difference_type(3), ""); + + _RandomAccessIterator __begin = __first; + value_type __pivot(_Ops::__iter_move(__first)); + // Find the first element greater than the pivot. + if (__comp(__pivot, *(__last - difference_type(1)))) { + // Not guarded since we know the last element is greater than the pivot. + while (!__comp(__pivot, *++__first)) { + } + } else { + while (++__first < __last && !__comp(__pivot, *__first)) { + } + } + // Find the last element less than or equal to the pivot. + if (__first < __last) { + // It will be always guarded because __introsort will do the median-of-three + // before calling this. + while (__comp(__pivot, *--__last)) { + } + } + // If the first element greater than the pivot is at or after the + // last element less than or equal to the pivot, then we have covered the + // entire range without swapping elements. This implies the range is already + // partitioned. + bool __already_partitioned = __first >= __last; + if (!__already_partitioned) { + _Ops::iter_swap(__first, __last); + ++__first; + } + + // In [__first, __last) __last is not inclusive. From now on, it uses last + // minus one to be inclusive on both sides. + _RandomAccessIterator __lm1 = __last - difference_type(1); + uint64_t __left_bitset = 0; + uint64_t __right_bitset = 0; + + // Reminder: length = __lm1 - __first + 1. + while (__lm1 - __first >= 2 * __detail::__block_size - 1) { + // Record the comparison outcomes for the elements currently on the left + // side. + if (__left_bitset == 0) + std::__populate_left_bitset<_Compare>(__first, __comp, __pivot, __left_bitset); + // Record the comparison outcomes for the elements currently on the right + // side. + if (__right_bitset == 0) + std::__populate_right_bitset<_Compare>(__lm1, __comp, __pivot, __right_bitset); + // Swap the elements recorded to be the candidates for swapping in the + // bitsets. + std::__swap_bitmap_pos<_AlgPolicy, _RandomAccessIterator>(__first, __lm1, __left_bitset, __right_bitset); + // Only advance the iterator if all the elements that need to be moved to + // other side were moved. + __first += (__left_bitset == 0) ? difference_type(__detail::__block_size) : difference_type(0); + __lm1 -= (__right_bitset == 0) ? difference_type(__detail::__block_size) : difference_type(0); + } + // Now, we have a less-than a block worth of elements on at least one of the + // sides. + std::__bitset_partition_partial_blocks<_AlgPolicy, _Compare>( + __first, __lm1, __comp, __pivot, __left_bitset, __right_bitset); + // At least one the bitsets would be empty. For the non-empty one, we need to + // properly partition the elements that appear within that bitset. + std::__swap_bitmap_pos_within<_AlgPolicy>(__first, __lm1, __left_bitset, __right_bitset); + + // Move the pivot to its correct position. + _RandomAccessIterator __pivot_pos = __first - difference_type(1); + if (__begin != __pivot_pos) { + *__begin = _Ops::__iter_move(__pivot_pos); + } + *__pivot_pos = std::move(__pivot); + return std::make_pair(__pivot_pos, __already_partitioned); +} + +// Partition [__first, __last) using the comparator __comp. *__first has the +// chosen pivot. Elements that are equivalent are kept to the right of the +// pivot. Returns the iterator for the pivot and a bool value which is true if +// the provided range is already sorted, false otherwise. We assume that the +// length of the range is at least three elements. +template +_LIBCPP_HIDE_FROM_ABI std::pair<_RandomAccessIterator, bool> +__partition_with_equals_on_right(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp) { + using _Ops = _IterOps<_AlgPolicy>; + typedef typename iterator_traits<_RandomAccessIterator>::difference_type difference_type; + typedef typename std::iterator_traits<_RandomAccessIterator>::value_type value_type; + _LIBCPP_ASSERT(__last - __first >= difference_type(3), ""); + _RandomAccessIterator __begin = __first; + value_type __pivot(_Ops::__iter_move(__first)); + // Find the first element greater or equal to the pivot. It will be always + // guarded because __introsort will do the median-of-three before calling + // this. + while (__comp(*++__first, __pivot)) + ; + + // Find the last element less than the pivot. + if (__begin == __first - difference_type(1)) { + while (__first < __last && !__comp(*--__last, __pivot)) + ; + } else { + // Guarded. + while (!__comp(*--__last, __pivot)) + ; + } + + // If the first element greater than or equal to the pivot is at or after the + // last element less than the pivot, then we have covered the entire range + // without swapping elements. This implies the range is already partitioned. + bool __already_partitioned = __first >= __last; + // Go through the remaining elements. Swap pairs of elements (one to the + // right of the pivot and the other to left of the pivot) that are not on the + // correct side of the pivot. + while (__first < __last) { + _Ops::iter_swap(__first, __last); + while (__comp(*++__first, __pivot)) + ; + while (!__comp(*--__last, __pivot)) + ; + } + // Move the pivot to its correct position. + _RandomAccessIterator __pivot_pos = __first - difference_type(1); + if (__begin != __pivot_pos) { + *__begin = _Ops::__iter_move(__pivot_pos); + } + *__pivot_pos = std::move(__pivot); + return std::make_pair(__pivot_pos, __already_partitioned); +} + +// Similar to the above function. Elements equivalent to the pivot are put to +// the left of the pivot. Returns the iterator to the pivot element. +template +_LIBCPP_HIDE_FROM_ABI _RandomAccessIterator +__partition_with_equals_on_left(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp) { + using _Ops = _IterOps<_AlgPolicy>; + typedef typename iterator_traits<_RandomAccessIterator>::difference_type difference_type; + typedef typename std::iterator_traits<_RandomAccessIterator>::value_type value_type; + _RandomAccessIterator __begin = __first; + value_type __pivot(_Ops::__iter_move(__first)); + if (__comp(__pivot, *(__last - difference_type(1)))) { + // Guarded. + while (!__comp(__pivot, *++__first)) { + } + } else { + while (++__first < __last && !__comp(__pivot, *__first)) { + } + } + + if (__first < __last) { + // It will be always guarded because __introsort will do the + // median-of-three before calling this. + while (__comp(__pivot, *--__last)) { + } + } + while (__first < __last) { + _Ops::iter_swap(__first, __last); + while (!__comp(__pivot, *++__first)) + ; + while (__comp(__pivot, *--__last)) + ; + } + _RandomAccessIterator __pivot_pos = __first - difference_type(1); + if (__begin != __pivot_pos) { + *__begin = _Ops::__iter_move(__pivot_pos); + } + *__pivot_pos = std::move(__pivot); + return __first; +} + +// The main sorting function. Implements introsort combined with other ideas: +// - option of using block quick sort for partitioning, +// - guarded and unguarded insertion sort for small lengths, +// - Tuckey's ninther technique for computing the pivot, +// - check on whether partition was not required. +// The implementation is partly based on Orson Peters' pattern-defeating +// quicksort, published at: . +template +void __introsort(_RandomAccessIterator __first, + _RandomAccessIterator __last, + _Compare __comp, + typename iterator_traits<_RandomAccessIterator>::difference_type __depth, + bool __leftmost = true) { + using _Ops = _IterOps<_AlgPolicy>; + typedef typename iterator_traits<_RandomAccessIterator>::difference_type difference_type; + using _Comp_ref = __comp_ref_type<_Compare>; + // Upper bound for using insertion sort for sorting. + _LIBCPP_CONSTEXPR difference_type __limit = 24; + // Lower bound for using Tuckey's ninther technique for median computation. + _LIBCPP_CONSTEXPR difference_type __ninther_threshold = 128; + while (true) { + difference_type __len = __last - __first; + switch (__len) { + case 0: + case 1: + return; + case 2: + if (__comp(*--__last, *__first)) + _Ops::iter_swap(__first, __last); + return; + case 3: + std::__sort3_maybe_branchless<_AlgPolicy, _Compare>(__first, __first + difference_type(1), --__last, __comp); + return; + case 4: + std::__sort4_maybe_branchless<_AlgPolicy, _Compare>( + __first, __first + difference_type(1), __first + difference_type(2), --__last, __comp); + return; + case 5: + std::__sort5_maybe_branchless<_AlgPolicy, _Compare>( + __first, __first + difference_type(1), __first + difference_type(2), __first + difference_type(3), + --__last, __comp); + return; + } + // Use insertion sort if the length of the range is below the specified limit. + if (__len < __limit) { + if (__leftmost) { + std::__insertion_sort<_AlgPolicy, _Compare>(__first, __last, __comp); + } else { + std::__insertion_sort_unguarded<_AlgPolicy, _Compare>(__first, __last, __comp); + } + return; + } + if (__depth == 0) { + // Fallback to heap sort as Introsort suggests. + std::__partial_sort<_AlgPolicy, _Compare>(__first, __last, __last, __comp); + return; + } + --__depth; + { + difference_type __half_len = __len / 2; + // Use Tuckey's ninther technique or median of 3 for pivot selection + // depending on the length of the range being sorted. + if (__len > __ninther_threshold) { + std::__sort3<_AlgPolicy, _Compare>(__first, __first + __half_len, __last - difference_type(1), __comp); + std::__sort3<_AlgPolicy, _Compare>( + __first + difference_type(1), __first + (__half_len - 1), __last - difference_type(2), __comp); + std::__sort3<_AlgPolicy, _Compare>( + __first + difference_type(2), __first + (__half_len + 1), __last - difference_type(3), __comp); + std::__sort3<_AlgPolicy, _Compare>( + __first + (__half_len - 1), __first + __half_len, __first + (__half_len + 1), __comp); + _Ops::iter_swap(__first, __first + __half_len); + } else { + std::__sort3<_AlgPolicy, _Compare>(__first + __half_len, __first, __last - difference_type(1), __comp); + } + } + // The elements to the left of the current iterator range are already + // sorted. If the current iterator range to be sorted is not the + // leftmost part of the entire iterator range and the pivot is same as + // the highest element in the range to the left, then we know that all + // the elements in the range [first, pivot] would be equal to the pivot, + // assuming the equal elements are put on the left side when + // partitioned. This also means that we do not need to sort the left + // side of the partition. + if (!__leftmost && !__comp(*(__first - difference_type(1)), *__first)) { + __first = std::__partition_with_equals_on_left<_AlgPolicy, _RandomAccessIterator, _Comp_ref>( + __first, __last, _Comp_ref(__comp)); + continue; + } + // Use bitset partition only if asked for. + auto __ret = + _UseBitSetPartition + ? std::__bitset_partition<_AlgPolicy, _RandomAccessIterator, _Compare>(__first, __last, __comp) + : std::__partition_with_equals_on_right<_AlgPolicy, _RandomAccessIterator, _Compare>(__first, __last, __comp); + _RandomAccessIterator __i = __ret.first; + // [__first, __i) < *__i and *__i <= [__i+1, __last) + // If we were given a perfect partition, see if insertion sort is quick... + if (__ret.second) { + using _WrappedComp = typename _WrapAlgPolicy<_AlgPolicy, _Compare>::type; + _WrappedComp __wrapped_comp(__comp); + bool __fs = std::__insertion_sort_incomplete<_WrappedComp>(__first, __i, __wrapped_comp); + if (std::__insertion_sort_incomplete<_WrappedComp>(__i + difference_type(1), __last, __wrapped_comp)) { + if (__fs) + return; + __last = __i; + continue; + } else { + if (__fs) { + __first = ++__i; + continue; + } + } + } + // Sort the left partiton recursively and the right partition with tail recursion elimination. + std::__introsort<_AlgPolicy, _Compare, _RandomAccessIterator, _UseBitSetPartition>( + __first, __i, __comp, __depth, __leftmost); + __leftmost = false; + __first = ++__i; + } +} + +template +inline _LIBCPP_HIDE_FROM_ABI _Number __log2i(_Number __n) { + if (__n == 0) + return 0; + if (sizeof(__n) <= sizeof(unsigned)) + return sizeof(unsigned) * CHAR_BIT - 1 - __libcpp_clz(static_cast(__n)); + if (sizeof(__n) <= sizeof(unsigned long)) + return sizeof(unsigned long) * CHAR_BIT - 1 - __libcpp_clz(static_cast(__n)); + if (sizeof(__n) <= sizeof(unsigned long long)) + return sizeof(unsigned long long) * CHAR_BIT - 1 - __libcpp_clz(static_cast(__n)); + + _Number __log2 = 0; + while (__n > 1) { + __log2++; + __n >>= 1; + } + return __log2; +} + +template +_LIBCPP_HIDDEN void __sort(_RandomAccessIterator __first, _RandomAccessIterator __last, _WrappedComp __wrapped_comp) { + typedef typename iterator_traits<_RandomAccessIterator>::difference_type difference_type; + difference_type __depth_limit = 2 * std::__log2i(__last - __first); + + using _Unwrap = _UnwrapAlgPolicy<_WrappedComp>; + using _AlgPolicy = typename _Unwrap::_AlgPolicy; + using _Compare = typename _Unwrap::_Comp; + _Compare __comp = _Unwrap::__get_comp(__wrapped_comp); + // Only use bitset partitioning for arithmetic types. We should also check + // that the default comparator is in use so that we are sure that there are no + // branches in the comparator. + std::__introsort<_AlgPolicy, + _Compare, + _RandomAccessIterator, + __use_branchless_sort<_Compare, _RandomAccessIterator>::value>( + __first, __last, __comp, __depth_limit); +} + +template +inline _LIBCPP_INLINE_VISIBILITY void __sort(_Tp** __first, _Tp** __last, __less<_Tp*>&) { + __less __comp; + std::__sort<__less&, uintptr_t*>((uintptr_t*)__first, (uintptr_t*)__last, __comp); +} + +extern template _LIBCPP_FUNC_VIS void __sort<__less&, char*>(char*, char*, __less&); +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +extern template _LIBCPP_FUNC_VIS void __sort<__less&, wchar_t*>(wchar_t*, wchar_t*, __less&); +#endif +extern template _LIBCPP_FUNC_VIS void __sort<__less&, signed char*>(signed char*, signed char*, __less&); +extern template _LIBCPP_FUNC_VIS void __sort<__less&, unsigned char*>(unsigned char*, unsigned char*, __less&); +extern template _LIBCPP_FUNC_VIS void __sort<__less&, short*>(short*, short*, __less&); +extern template _LIBCPP_FUNC_VIS void __sort<__less&, unsigned short*>(unsigned short*, unsigned short*, __less&); +extern template _LIBCPP_FUNC_VIS void __sort<__less&, int*>(int*, int*, __less&); +extern template _LIBCPP_FUNC_VIS void __sort<__less&, unsigned*>(unsigned*, unsigned*, __less&); +extern template _LIBCPP_FUNC_VIS void __sort<__less&, long*>(long*, long*, __less&); +extern template _LIBCPP_FUNC_VIS void __sort<__less&, unsigned long*>(unsigned long*, unsigned long*, __less&); +extern template _LIBCPP_FUNC_VIS void __sort<__less&, long long*>(long long*, long long*, __less&); +extern template _LIBCPP_FUNC_VIS void __sort<__less&, unsigned long long*>(unsigned long long*, unsigned long long*, __less&); +extern template _LIBCPP_FUNC_VIS void __sort<__less&, float*>(float*, float*, __less&); +extern template _LIBCPP_FUNC_VIS void __sort<__less&, double*>(double*, double*, __less&); +extern template _LIBCPP_FUNC_VIS void __sort<__less&, long double*>(long double*, long double*, __less&); + +extern template _LIBCPP_FUNC_VIS bool __insertion_sort_incomplete<__less&, char*>(char*, char*, __less&); +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +extern template _LIBCPP_FUNC_VIS bool __insertion_sort_incomplete<__less&, wchar_t*>(wchar_t*, wchar_t*, __less&); +#endif +extern template _LIBCPP_FUNC_VIS bool __insertion_sort_incomplete<__less&, signed char*>(signed char*, signed char*, __less&); +extern template _LIBCPP_FUNC_VIS bool __insertion_sort_incomplete<__less&, unsigned char*>(unsigned char*, unsigned char*, __less&); +extern template _LIBCPP_FUNC_VIS bool __insertion_sort_incomplete<__less&, short*>(short*, short*, __less&); +extern template _LIBCPP_FUNC_VIS bool __insertion_sort_incomplete<__less&, unsigned short*>(unsigned short*, unsigned short*, __less&); +extern template _LIBCPP_FUNC_VIS bool __insertion_sort_incomplete<__less&, int*>(int*, int*, __less&); +extern template _LIBCPP_FUNC_VIS bool __insertion_sort_incomplete<__less&, unsigned*>(unsigned*, unsigned*, __less&); +extern template _LIBCPP_FUNC_VIS bool __insertion_sort_incomplete<__less&, long*>(long*, long*, __less&); +extern template _LIBCPP_FUNC_VIS bool __insertion_sort_incomplete<__less&, unsigned long*>(unsigned long*, unsigned long*, __less&); +extern template _LIBCPP_FUNC_VIS bool __insertion_sort_incomplete<__less&, long long*>(long long*, long long*, __less&); +extern template _LIBCPP_FUNC_VIS bool __insertion_sort_incomplete<__less&, unsigned long long*>(unsigned long long*, unsigned long long*, __less&); +extern template _LIBCPP_FUNC_VIS bool __insertion_sort_incomplete<__less&, float*>(float*, float*, __less&); +extern template _LIBCPP_FUNC_VIS bool __insertion_sort_incomplete<__less&, double*>(double*, double*, __less&); +extern template _LIBCPP_FUNC_VIS bool __insertion_sort_incomplete<__less&, long double*>(long double*, long double*, __less&); + +extern template _LIBCPP_FUNC_VIS unsigned __sort5<__less&, long double*>(long double*, long double*, long double*, long double*, long double*, __less&); + +template +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 +void __sort_impl(_RandomAccessIterator __first, _RandomAccessIterator __last, _Comp& __comp) { + std::__debug_randomize_range<_AlgPolicy>(__first, __last); + + using _Comp_ref = __comp_ref_type<_Comp>; + if (__libcpp_is_constant_evaluated()) { + std::__partial_sort<_AlgPolicy>(__first, __last, __last, __comp); + + } else { + using _WrappedComp = typename _WrapAlgPolicy<_AlgPolicy, _Comp_ref>::type; + _Comp_ref __comp_ref(__comp); + _WrappedComp __wrapped_comp(__comp_ref); + std::__sort<_WrappedComp>(std::__unwrap_iter(__first), std::__unwrap_iter(__last), __wrapped_comp); + } +} + +template +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 +void sort(_RandomAccessIterator __first, _RandomAccessIterator __last, _Comp __comp) { + std::__sort_impl<_ClassicAlgPolicy>(std::move(__first), std::move(__last), __comp); +} + +template +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 +void sort(_RandomAccessIterator __first, _RandomAccessIterator __last) { + std::sort(__first, __last, __less::value_type>()); +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ALGORITHM_SORT_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/sort_heap.h b/app/src/main/cpp/libcxx/include/__algorithm/sort_heap.h new file mode 100644 index 0000000..8249407 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/sort_heap.h @@ -0,0 +1,55 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_SORT_HEAP_H +#define _LIBCPP___ALGORITHM_SORT_HEAP_H + +#include <__algorithm/comp.h> +#include <__algorithm/comp_ref_type.h> +#include <__algorithm/iterator_operations.h> +#include <__algorithm/pop_heap.h> +#include <__config> +#include <__iterator/iterator_traits.h> +#include <__utility/move.h> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +template +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 +void __sort_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare&& __comp) { + __comp_ref_type<_Compare> __comp_ref = __comp; + + using difference_type = typename iterator_traits<_RandomAccessIterator>::difference_type; + for (difference_type __n = __last - __first; __n > 1; --__last, (void) --__n) + std::__pop_heap<_AlgPolicy>(__first, __last, __comp_ref, __n); +} + +template +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 +void sort_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp) { + static_assert(std::is_copy_constructible<_RandomAccessIterator>::value, "Iterators must be copy constructible."); + static_assert(std::is_copy_assignable<_RandomAccessIterator>::value, "Iterators must be copy assignable."); + + std::__sort_heap<_ClassicAlgPolicy>(std::move(__first), std::move(__last), __comp); +} + +template +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 +void sort_heap(_RandomAccessIterator __first, _RandomAccessIterator __last) { + std::sort_heap(std::move(__first), std::move(__last), + __less::value_type>()); +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ALGORITHM_SORT_HEAP_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/stable_partition.h b/app/src/main/cpp/libcxx/include/__algorithm/stable_partition.h new file mode 100644 index 0000000..a49de6d --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/stable_partition.h @@ -0,0 +1,329 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_STABLE_PARTITION_H +#define _LIBCPP___ALGORITHM_STABLE_PARTITION_H + +#include <__algorithm/iterator_operations.h> +#include <__algorithm/rotate.h> +#include <__config> +#include <__iterator/advance.h> +#include <__iterator/distance.h> +#include <__iterator/iterator_traits.h> +#include <__memory/destruct_n.h> +#include <__memory/temporary_buffer.h> +#include <__memory/unique_ptr.h> +#include <__utility/move.h> +#include <__utility/pair.h> +#include +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +template +_LIBCPP_HIDE_FROM_ABI _ForwardIterator +__stable_partition_impl(_ForwardIterator __first, _ForwardIterator __last, _Predicate __pred, + _Distance __len, _Pair __p, forward_iterator_tag __fit) +{ + using _Ops = _IterOps<_AlgPolicy>; + + // *__first is known to be false + // __len >= 1 + if (__len == 1) + return __first; + if (__len == 2) + { + _ForwardIterator __m = __first; + if (__pred(*++__m)) + { + _Ops::iter_swap(__first, __m); + return __m; + } + return __first; + } + if (__len <= __p.second) + { // The buffer is big enough to use + typedef typename iterator_traits<_ForwardIterator>::value_type value_type; + __destruct_n __d(0); + unique_ptr __h(__p.first, __d); + // Move the falses into the temporary buffer, and the trues to the front of the line + // Update __first to always point to the end of the trues + value_type* __t = __p.first; + ::new ((void*)__t) value_type(_Ops::__iter_move(__first)); + __d.template __incr(); + ++__t; + _ForwardIterator __i = __first; + while (++__i != __last) + { + if (__pred(*__i)) + { + *__first = _Ops::__iter_move(__i); + ++__first; + } + else + { + ::new ((void*)__t) value_type(_Ops::__iter_move(__i)); + __d.template __incr(); + ++__t; + } + } + // All trues now at start of range, all falses in buffer + // Move falses back into range, but don't mess up __first which points to first false + __i = __first; + for (value_type* __t2 = __p.first; __t2 < __t; ++__t2, (void) ++__i) + *__i = _Ops::__iter_move(__t2); + // __h destructs moved-from values out of the temp buffer, but doesn't deallocate buffer + return __first; + } + // Else not enough buffer, do in place + // __len >= 3 + _ForwardIterator __m = __first; + _Distance __len2 = __len / 2; // __len2 >= 2 + _Ops::advance(__m, __len2); + // recurse on [__first, __m), *__first know to be false + // F????????????????? + // f m l + _ForwardIterator __first_false = std::__stable_partition_impl<_AlgPolicy, _Predicate&>( + __first, __m, __pred, __len2, __p, __fit); + // TTTFFFFF?????????? + // f ff m l + // recurse on [__m, __last], except increase __m until *(__m) is false, *__last know to be true + _ForwardIterator __m1 = __m; + _ForwardIterator __second_false = __last; + _Distance __len_half = __len - __len2; + while (__pred(*__m1)) + { + if (++__m1 == __last) + goto __second_half_done; + --__len_half; + } + // TTTFFFFFTTTF?????? + // f ff m m1 l + __second_false = std::__stable_partition_impl<_AlgPolicy, _Predicate&>( + __m1, __last, __pred, __len_half, __p, __fit); +__second_half_done: + // TTTFFFFFTTTTTFFFFF + // f ff m sf l + return std::__rotate<_AlgPolicy>(__first_false, __m, __second_false).first; + // TTTTTTTTFFFFFFFFFF + // | +} + +template +_LIBCPP_HIDE_FROM_ABI _ForwardIterator +__stable_partition_impl(_ForwardIterator __first, _ForwardIterator __last, _Predicate __pred, + forward_iterator_tag) +{ + const unsigned __alloc_limit = 3; // might want to make this a function of trivial assignment + // Either prove all true and return __first or point to first false + while (true) + { + if (__first == __last) + return __first; + if (!__pred(*__first)) + break; + ++__first; + } + // We now have a reduced range [__first, __last) + // *__first is known to be false + typedef typename iterator_traits<_ForwardIterator>::difference_type difference_type; + typedef typename iterator_traits<_ForwardIterator>::value_type value_type; + difference_type __len = _IterOps<_AlgPolicy>::distance(__first, __last); + pair __p(0, 0); + unique_ptr __h; + if (__len >= __alloc_limit) + { +// TODO: Remove the use of std::get_temporary_buffer +_LIBCPP_SUPPRESS_DEPRECATED_PUSH + __p = _VSTD::get_temporary_buffer(__len); +_LIBCPP_SUPPRESS_DEPRECATED_POP + __h.reset(__p.first); + } + return std::__stable_partition_impl<_AlgPolicy, _Predicate&>( + std::move(__first), std::move(__last), __pred, __len, __p, forward_iterator_tag()); +} + +template +_BidirectionalIterator +__stable_partition_impl(_BidirectionalIterator __first, _BidirectionalIterator __last, _Predicate __pred, + _Distance __len, _Pair __p, bidirectional_iterator_tag __bit) +{ + using _Ops = _IterOps<_AlgPolicy>; + + // *__first is known to be false + // *__last is known to be true + // __len >= 2 + if (__len == 2) + { + _Ops::iter_swap(__first, __last); + return __last; + } + if (__len == 3) + { + _BidirectionalIterator __m = __first; + if (__pred(*++__m)) + { + _Ops::iter_swap(__first, __m); + _Ops::iter_swap(__m, __last); + return __last; + } + _Ops::iter_swap(__m, __last); + _Ops::iter_swap(__first, __m); + return __m; + } + if (__len <= __p.second) + { // The buffer is big enough to use + typedef typename iterator_traits<_BidirectionalIterator>::value_type value_type; + __destruct_n __d(0); + unique_ptr __h(__p.first, __d); + // Move the falses into the temporary buffer, and the trues to the front of the line + // Update __first to always point to the end of the trues + value_type* __t = __p.first; + ::new ((void*)__t) value_type(_Ops::__iter_move(__first)); + __d.template __incr(); + ++__t; + _BidirectionalIterator __i = __first; + while (++__i != __last) + { + if (__pred(*__i)) + { + *__first = _Ops::__iter_move(__i); + ++__first; + } + else + { + ::new ((void*)__t) value_type(_Ops::__iter_move(__i)); + __d.template __incr(); + ++__t; + } + } + // move *__last, known to be true + *__first = _Ops::__iter_move(__i); + __i = ++__first; + // All trues now at start of range, all falses in buffer + // Move falses back into range, but don't mess up __first which points to first false + for (value_type* __t2 = __p.first; __t2 < __t; ++__t2, (void) ++__i) + *__i = _Ops::__iter_move(__t2); + // __h destructs moved-from values out of the temp buffer, but doesn't deallocate buffer + return __first; + } + // Else not enough buffer, do in place + // __len >= 4 + _BidirectionalIterator __m = __first; + _Distance __len2 = __len / 2; // __len2 >= 2 + _Ops::advance(__m, __len2); + // recurse on [__first, __m-1], except reduce __m-1 until *(__m-1) is true, *__first know to be false + // F????????????????T + // f m l + _BidirectionalIterator __m1 = __m; + _BidirectionalIterator __first_false = __first; + _Distance __len_half = __len2; + while (!__pred(*--__m1)) + { + if (__m1 == __first) + goto __first_half_done; + --__len_half; + } + // F???TFFF?????????T + // f m1 m l + __first_false = std::__stable_partition_impl<_AlgPolicy, _Predicate&>( + __first, __m1, __pred, __len_half, __p, __bit); +__first_half_done: + // TTTFFFFF?????????T + // f ff m l + // recurse on [__m, __last], except increase __m until *(__m) is false, *__last know to be true + __m1 = __m; + _BidirectionalIterator __second_false = __last; + ++__second_false; + __len_half = __len - __len2; + while (__pred(*__m1)) + { + if (++__m1 == __last) + goto __second_half_done; + --__len_half; + } + // TTTFFFFFTTTF?????T + // f ff m m1 l + __second_false = std::__stable_partition_impl<_AlgPolicy, _Predicate&>( + __m1, __last, __pred, __len_half, __p, __bit); +__second_half_done: + // TTTFFFFFTTTTTFFFFF + // f ff m sf l + return std::__rotate<_AlgPolicy>(__first_false, __m, __second_false).first; + // TTTTTTTTFFFFFFFFFF + // | +} + +template +_LIBCPP_HIDE_FROM_ABI _BidirectionalIterator +__stable_partition_impl(_BidirectionalIterator __first, _BidirectionalIterator __last, _Predicate __pred, + bidirectional_iterator_tag) +{ + typedef typename iterator_traits<_BidirectionalIterator>::difference_type difference_type; + typedef typename iterator_traits<_BidirectionalIterator>::value_type value_type; + const difference_type __alloc_limit = 4; // might want to make this a function of trivial assignment + // Either prove all true and return __first or point to first false + while (true) + { + if (__first == __last) + return __first; + if (!__pred(*__first)) + break; + ++__first; + } + // __first points to first false, everything prior to __first is already set. + // Either prove [__first, __last) is all false and return __first, or point __last to last true + do + { + if (__first == --__last) + return __first; + } while (!__pred(*__last)); + // We now have a reduced range [__first, __last] + // *__first is known to be false + // *__last is known to be true + // __len >= 2 + difference_type __len = _IterOps<_AlgPolicy>::distance(__first, __last) + 1; + pair __p(0, 0); + unique_ptr __h; + if (__len >= __alloc_limit) + { +// TODO: Remove the use of std::get_temporary_buffer +_LIBCPP_SUPPRESS_DEPRECATED_PUSH + __p = _VSTD::get_temporary_buffer(__len); +_LIBCPP_SUPPRESS_DEPRECATED_POP + __h.reset(__p.first); + } + return std::__stable_partition_impl<_AlgPolicy, _Predicate&>( + std::move(__first), std::move(__last), __pred, __len, __p, bidirectional_iterator_tag()); +} + +template +_LIBCPP_HIDE_FROM_ABI +_ForwardIterator __stable_partition( + _ForwardIterator __first, _ForwardIterator __last, _Predicate&& __pred, _IterCategory __iter_category) { + return std::__stable_partition_impl<_AlgPolicy, __remove_cvref_t<_Predicate>&>( + std::move(__first), std::move(__last), __pred, __iter_category); +} + +template +inline _LIBCPP_INLINE_VISIBILITY +_ForwardIterator +stable_partition(_ForwardIterator __first, _ForwardIterator __last, _Predicate __pred) +{ + using _IterCategory = typename iterator_traits<_ForwardIterator>::iterator_category; + return std::__stable_partition<_ClassicAlgPolicy, _Predicate&>( + std::move(__first), std::move(__last), __pred, _IterCategory()); +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ALGORITHM_STABLE_PARTITION_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/stable_sort.h b/app/src/main/cpp/libcxx/include/__algorithm/stable_sort.h new file mode 100644 index 0000000..8e70978 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/stable_sort.h @@ -0,0 +1,247 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_STABLE_SORT_H +#define _LIBCPP___ALGORITHM_STABLE_SORT_H + +#include <__algorithm/comp.h> +#include <__algorithm/comp_ref_type.h> +#include <__algorithm/inplace_merge.h> +#include <__algorithm/iterator_operations.h> +#include <__algorithm/sort.h> +#include <__config> +#include <__iterator/iterator_traits.h> +#include <__memory/destruct_n.h> +#include <__memory/temporary_buffer.h> +#include <__memory/unique_ptr.h> +#include <__utility/move.h> +#include <__utility/pair.h> +#include +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +template +_LIBCPP_HIDE_FROM_ABI void +__merge_move_construct(_InputIterator1 __first1, _InputIterator1 __last1, + _InputIterator2 __first2, _InputIterator2 __last2, + typename iterator_traits<_InputIterator1>::value_type* __result, _Compare __comp) +{ + using _Ops = _IterOps<_AlgPolicy>; + + typedef typename iterator_traits<_InputIterator1>::value_type value_type; + __destruct_n __d(0); + unique_ptr __h(__result, __d); + for (; true; ++__result) + { + if (__first1 == __last1) + { + for (; __first2 != __last2; ++__first2, (void) ++__result, __d.template __incr()) + ::new ((void*)__result) value_type(_Ops::__iter_move(__first2)); + __h.release(); + return; + } + if (__first2 == __last2) + { + for (; __first1 != __last1; ++__first1, (void) ++__result, __d.template __incr()) + ::new ((void*)__result) value_type(_Ops::__iter_move(__first1)); + __h.release(); + return; + } + if (__comp(*__first2, *__first1)) + { + ::new ((void*)__result) value_type(_Ops::__iter_move(__first2)); + __d.template __incr(); + ++__first2; + } + else + { + ::new ((void*)__result) value_type(_Ops::__iter_move(__first1)); + __d.template __incr(); + ++__first1; + } + } +} + +template +_LIBCPP_HIDE_FROM_ABI void +__merge_move_assign(_InputIterator1 __first1, _InputIterator1 __last1, + _InputIterator2 __first2, _InputIterator2 __last2, + _OutputIterator __result, _Compare __comp) +{ + using _Ops = _IterOps<_AlgPolicy>; + + for (; __first1 != __last1; ++__result) + { + if (__first2 == __last2) + { + for (; __first1 != __last1; ++__first1, (void) ++__result) + *__result = _Ops::__iter_move(__first1); + return; + } + if (__comp(*__first2, *__first1)) + { + *__result = _Ops::__iter_move(__first2); + ++__first2; + } + else + { + *__result = _Ops::__iter_move(__first1); + ++__first1; + } + } + for (; __first2 != __last2; ++__first2, (void) ++__result) + *__result = _Ops::__iter_move(__first2); +} + +template +void +__stable_sort(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp, + typename iterator_traits<_RandomAccessIterator>::difference_type __len, + typename iterator_traits<_RandomAccessIterator>::value_type* __buff, ptrdiff_t __buff_size); + +template +void +__stable_sort_move(_RandomAccessIterator __first1, _RandomAccessIterator __last1, _Compare __comp, + typename iterator_traits<_RandomAccessIterator>::difference_type __len, + typename iterator_traits<_RandomAccessIterator>::value_type* __first2) +{ + using _Ops = _IterOps<_AlgPolicy>; + + typedef typename iterator_traits<_RandomAccessIterator>::value_type value_type; + switch (__len) + { + case 0: + return; + case 1: + ::new ((void*)__first2) value_type(_Ops::__iter_move(__first1)); + return; + case 2: + __destruct_n __d(0); + unique_ptr __h2(__first2, __d); + if (__comp(*--__last1, *__first1)) + { + ::new ((void*)__first2) value_type(_Ops::__iter_move(__last1)); + __d.template __incr(); + ++__first2; + ::new ((void*)__first2) value_type(_Ops::__iter_move(__first1)); + } + else + { + ::new ((void*)__first2) value_type(_Ops::__iter_move(__first1)); + __d.template __incr(); + ++__first2; + ::new ((void*)__first2) value_type(_Ops::__iter_move(__last1)); + } + __h2.release(); + return; + } + if (__len <= 8) + { + std::__insertion_sort_move<_AlgPolicy, _Compare>(__first1, __last1, __first2, __comp); + return; + } + typename iterator_traits<_RandomAccessIterator>::difference_type __l2 = __len / 2; + _RandomAccessIterator __m = __first1 + __l2; + std::__stable_sort<_AlgPolicy, _Compare>(__first1, __m, __comp, __l2, __first2, __l2); + std::__stable_sort<_AlgPolicy, _Compare>(__m, __last1, __comp, __len - __l2, __first2 + __l2, __len - __l2); + std::__merge_move_construct<_AlgPolicy, _Compare>(__first1, __m, __m, __last1, __first2, __comp); +} + +template +struct __stable_sort_switch +{ + static const unsigned value = 128*is_trivially_copy_assignable<_Tp>::value; +}; + +template +void +__stable_sort(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp, + typename iterator_traits<_RandomAccessIterator>::difference_type __len, + typename iterator_traits<_RandomAccessIterator>::value_type* __buff, ptrdiff_t __buff_size) +{ + typedef typename iterator_traits<_RandomAccessIterator>::value_type value_type; + typedef typename iterator_traits<_RandomAccessIterator>::difference_type difference_type; + switch (__len) + { + case 0: + case 1: + return; + case 2: + if (__comp(*--__last, *__first)) + _IterOps<_AlgPolicy>::iter_swap(__first, __last); + return; + } + if (__len <= static_cast(__stable_sort_switch::value)) + { + std::__insertion_sort<_AlgPolicy, _Compare>(__first, __last, __comp); + return; + } + typename iterator_traits<_RandomAccessIterator>::difference_type __l2 = __len / 2; + _RandomAccessIterator __m = __first + __l2; + if (__len <= __buff_size) + { + __destruct_n __d(0); + unique_ptr __h2(__buff, __d); + std::__stable_sort_move<_AlgPolicy, _Compare>(__first, __m, __comp, __l2, __buff); + __d.__set(__l2, (value_type*)nullptr); + std::__stable_sort_move<_AlgPolicy, _Compare>(__m, __last, __comp, __len - __l2, __buff + __l2); + __d.__set(__len, (value_type*)nullptr); + std::__merge_move_assign<_AlgPolicy, _Compare>( + __buff, __buff + __l2, __buff + __l2, __buff + __len, __first, __comp); +// _VSTD::__merge<_Compare>(move_iterator(__buff), +// move_iterator(__buff + __l2), +// move_iterator<_RandomAccessIterator>(__buff + __l2), +// move_iterator<_RandomAccessIterator>(__buff + __len), +// __first, __comp); + return; + } + std::__stable_sort<_AlgPolicy, _Compare>(__first, __m, __comp, __l2, __buff, __buff_size); + std::__stable_sort<_AlgPolicy, _Compare>(__m, __last, __comp, __len - __l2, __buff, __buff_size); + std::__inplace_merge<_AlgPolicy>(__first, __m, __last, __comp, __l2, __len - __l2, __buff, __buff_size); +} + +template +inline _LIBCPP_HIDE_FROM_ABI +void __stable_sort_impl(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare& __comp) { + using value_type = typename iterator_traits<_RandomAccessIterator>::value_type; + using difference_type = typename iterator_traits<_RandomAccessIterator>::difference_type; + + difference_type __len = __last - __first; + pair __buf(0, 0); + unique_ptr __h; + if (__len > static_cast(__stable_sort_switch::value)) { +// TODO: Remove the use of std::get_temporary_buffer +_LIBCPP_SUPPRESS_DEPRECATED_PUSH + __buf = std::get_temporary_buffer(__len); +_LIBCPP_SUPPRESS_DEPRECATED_POP + __h.reset(__buf.first); + } + + std::__stable_sort<_AlgPolicy, __comp_ref_type<_Compare> >(__first, __last, __comp, __len, __buf.first, __buf.second); +} + +template +inline _LIBCPP_HIDE_FROM_ABI +void stable_sort(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp) { + std::__stable_sort_impl<_ClassicAlgPolicy>(std::move(__first), std::move(__last), __comp); +} + +template +inline _LIBCPP_HIDE_FROM_ABI +void stable_sort(_RandomAccessIterator __first, _RandomAccessIterator __last) { + std::stable_sort(__first, __last, __less::value_type>()); +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ALGORITHM_STABLE_SORT_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/swap_ranges.h b/app/src/main/cpp/libcxx/include/__algorithm/swap_ranges.h new file mode 100644 index 0000000..5ce5ed8 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/swap_ranges.h @@ -0,0 +1,60 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_SWAP_RANGES_H +#define _LIBCPP___ALGORITHM_SWAP_RANGES_H + +#include <__algorithm/iterator_operations.h> +#include <__config> +#include <__utility/move.h> +#include <__utility/pair.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +// 2+2 iterators: the shorter size will be used. +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 +pair<_ForwardIterator1, _ForwardIterator2> +__swap_ranges(_ForwardIterator1 __first1, _Sentinel1 __last1, _ForwardIterator2 __first2, _Sentinel2 __last2) { + while (__first1 != __last1 && __first2 != __last2) { + _IterOps<_AlgPolicy>::iter_swap(__first1, __first2); + ++__first1; + ++__first2; + } + + return pair<_ForwardIterator1, _ForwardIterator2>(std::move(__first1), std::move(__first2)); +} + +// 2+1 iterators: size2 >= size1. +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 +pair<_ForwardIterator1, _ForwardIterator2> +__swap_ranges(_ForwardIterator1 __first1, _Sentinel1 __last1, _ForwardIterator2 __first2) { + while (__first1 != __last1) { + _IterOps<_AlgPolicy>::iter_swap(__first1, __first2); + ++__first1; + ++__first2; + } + + return pair<_ForwardIterator1, _ForwardIterator2>(std::move(__first1), std::move(__first2)); +} + +template +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator2 +swap_ranges(_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2) { + return std::__swap_ranges<_ClassicAlgPolicy>( + std::move(__first1), std::move(__last1), std::move(__first2)).second; +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ALGORITHM_SWAP_RANGES_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/transform.h b/app/src/main/cpp/libcxx/include/__algorithm/transform.h new file mode 100644 index 0000000..4722c15 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/transform.h @@ -0,0 +1,43 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_TRANSFORM_H +#define _LIBCPP___ALGORITHM_TRANSFORM_H + +#include <__config> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +template +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 +_OutputIterator +transform(_InputIterator __first, _InputIterator __last, _OutputIterator __result, _UnaryOperation __op) +{ + for (; __first != __last; ++__first, (void) ++__result) + *__result = __op(*__first); + return __result; +} + +template +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 +_OutputIterator +transform(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2, + _OutputIterator __result, _BinaryOperation __binary_op) +{ + for (; __first1 != __last1; ++__first1, (void) ++__first2, ++__result) + *__result = __binary_op(*__first1, *__first2); + return __result; +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ALGORITHM_TRANSFORM_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/uniform_random_bit_generator_adaptor.h b/app/src/main/cpp/libcxx/include/__algorithm/uniform_random_bit_generator_adaptor.h new file mode 100644 index 0000000..1e86074 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/uniform_random_bit_generator_adaptor.h @@ -0,0 +1,62 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_RANGES_UNIFORM_RANDOM_BIT_GENERATOR_ADAPTOR_H +#define _LIBCPP___ALGORITHM_RANGES_UNIFORM_RANDOM_BIT_GENERATOR_ADAPTOR_H + +#include <__config> +#include <__functional/invoke.h> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if _LIBCPP_STD_VER > 17 + +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + +_LIBCPP_BEGIN_NAMESPACE_STD + +// Range versions of random algorithms (e.g. `std::shuffle`) are less constrained than their classic counterparts. +// Range algorithms only require the given generator to satisfy the `std::uniform_random_bit_generator` concept. +// Classic algorithms require the given generator to meet the uniform random bit generator requirements; these +// requirements include satisfying `std::uniform_random_bit_generator` and add a requirement for the generator to +// provide a nested `result_type` typedef (see `[rand.req.urng]`). +// +// To be able to reuse classic implementations, make the given generator meet the classic requirements by wrapping +// it into an adaptor type that forwards all of its interface and adds the required typedef. +template +class _ClassicGenAdaptor { +private: + // The generator is not required to be copyable or movable, so it has to be stored as a reference. + _Gen& __gen_; + +public: + using result_type = invoke_result_t<_Gen&>; + + _LIBCPP_HIDE_FROM_ABI + static constexpr auto min() { return __remove_cvref_t<_Gen>::min(); } + _LIBCPP_HIDE_FROM_ABI + static constexpr auto max() { return __remove_cvref_t<_Gen>::max(); } + + _LIBCPP_HIDE_FROM_ABI + constexpr explicit _ClassicGenAdaptor(_Gen& __g) : __gen_(__g) {} + + _LIBCPP_HIDE_FROM_ABI + constexpr auto operator()() const { return __gen_(); } +}; + +_LIBCPP_END_NAMESPACE_STD + +_LIBCPP_POP_MACROS + +#endif // _LIBCPP_STD_VER > 17 + +#endif // _LIBCPP___ALGORITHM_RANGES_UNIFORM_RANDOM_BIT_GENERATOR_ADAPTOR_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/unique.h b/app/src/main/cpp/libcxx/include/__algorithm/unique.h new file mode 100644 index 0000000..1717a00 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/unique.h @@ -0,0 +1,59 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_UNIQUE_H +#define _LIBCPP___ALGORITHM_UNIQUE_H + +#include <__algorithm/adjacent_find.h> +#include <__algorithm/comp.h> +#include <__algorithm/iterator_operations.h> +#include <__config> +#include <__iterator/iterator_traits.h> +#include <__utility/move.h> +#include <__utility/pair.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +// unique + +template +_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 std::pair<_Iter, _Iter> +__unique(_Iter __first, _Sent __last, _BinaryPredicate&& __pred) { + __first = std::__adjacent_find(__first, __last, __pred); + if (__first != __last) { + // ... a a ? ... + // f i + _Iter __i = __first; + for (++__i; ++__i != __last;) + if (!__pred(*__first, *__i)) + *++__first = _IterOps<_AlgPolicy>::__iter_move(__i); + ++__first; + return std::pair<_Iter, _Iter>(std::move(__first), std::move(__i)); + } + return std::pair<_Iter, _Iter>(__first, __first); +} + +template +_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator +unique(_ForwardIterator __first, _ForwardIterator __last, _BinaryPredicate __pred) { + return std::__unique<_ClassicAlgPolicy>(std::move(__first), std::move(__last), __pred).first; +} + +template +_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator +unique(_ForwardIterator __first, _ForwardIterator __last) { + return std::unique(__first, __last, __equal_to()); +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ALGORITHM_UNIQUE_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/unique_copy.h b/app/src/main/cpp/libcxx/include/__algorithm/unique_copy.h new file mode 100644 index 0000000..81fcd50 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/unique_copy.h @@ -0,0 +1,122 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_UNIQUE_COPY_H +#define _LIBCPP___ALGORITHM_UNIQUE_COPY_H + +#include <__algorithm/comp.h> +#include <__algorithm/iterator_operations.h> +#include <__config> +#include <__iterator/iterator_traits.h> +#include <__type_traits/conditional.h> +#include <__type_traits/is_base_of.h> +#include <__type_traits/is_same.h> +#include <__utility/move.h> +#include <__utility/pair.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace __unique_copy_tags { + +struct __reread_from_input_tag {}; +struct __reread_from_output_tag {}; +struct __read_from_tmp_value_tag {}; + +} // namespace __unique_copy_tags + +template +_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pair<_InputIterator, _OutputIterator> +__unique_copy(_InputIterator __first, + _Sent __last, + _OutputIterator __result, + _BinaryPredicate&& __pred, + __unique_copy_tags::__read_from_tmp_value_tag) { + if (__first != __last) { + typename _IterOps<_AlgPolicy>::template __value_type<_InputIterator> __t(*__first); + *__result = __t; + ++__result; + while (++__first != __last) { + if (!__pred(__t, *__first)) { + __t = *__first; + *__result = __t; + ++__result; + } + } + } + return pair<_InputIterator, _OutputIterator>(std::move(__first), std::move(__result)); +} + +template +_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pair<_ForwardIterator, _OutputIterator> +__unique_copy(_ForwardIterator __first, + _Sent __last, + _OutputIterator __result, + _BinaryPredicate&& __pred, + __unique_copy_tags::__reread_from_input_tag) { + if (__first != __last) { + _ForwardIterator __i = __first; + *__result = *__i; + ++__result; + while (++__first != __last) { + if (!__pred(*__i, *__first)) { + *__result = *__first; + ++__result; + __i = __first; + } + } + } + return pair<_ForwardIterator, _OutputIterator>(std::move(__first), std::move(__result)); +} + +template +_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pair<_InputIterator, _InputAndOutputIterator> +__unique_copy(_InputIterator __first, + _Sent __last, + _InputAndOutputIterator __result, + _BinaryPredicate&& __pred, + __unique_copy_tags::__reread_from_output_tag) { + if (__first != __last) { + *__result = *__first; + while (++__first != __last) + if (!__pred(*__result, *__first)) + *++__result = *__first; + ++__result; + } + return pair<_InputIterator, _InputAndOutputIterator>(std::move(__first), std::move(__result)); +} + +template +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _OutputIterator +unique_copy(_InputIterator __first, _InputIterator __last, _OutputIterator __result, _BinaryPredicate __pred) { + using __algo_tag = __conditional_t< + is_base_of::iterator_category>::value, + __unique_copy_tags::__reread_from_input_tag, + __conditional_t< + is_base_of::iterator_category>::value && + is_same< typename iterator_traits<_InputIterator>::value_type, + typename iterator_traits<_OutputIterator>::value_type>::value, + __unique_copy_tags::__reread_from_output_tag, + __unique_copy_tags::__read_from_tmp_value_tag> >; + return std::__unique_copy<_ClassicAlgPolicy>( + std::move(__first), std::move(__last), std::move(__result), __pred, __algo_tag()) + .second; +} + +template +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _OutputIterator +unique_copy(_InputIterator __first, _InputIterator __last, _OutputIterator __result) { + return std::unique_copy(std::move(__first), std::move(__last), std::move(__result), __equal_to()); +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ALGORITHM_UNIQUE_COPY_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/unwrap_iter.h b/app/src/main/cpp/libcxx/include/__algorithm/unwrap_iter.h new file mode 100644 index 0000000..0f661e1 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/unwrap_iter.h @@ -0,0 +1,74 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_UNWRAP_ITER_H +#define _LIBCPP___ALGORITHM_UNWRAP_ITER_H + +#include <__config> +#include <__iterator/iterator_traits.h> +#include <__memory/pointer_traits.h> +#include <__type_traits/enable_if.h> +#include <__type_traits/is_copy_constructible.h> +#include <__utility/declval.h> +#include <__utility/move.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +// TODO: Change the name of __unwrap_iter_impl to something more appropriate +// The job of __unwrap_iter is to remove iterator wrappers (like reverse_iterator or __wrap_iter), +// to reduce the number of template instantiations and to enable pointer-based optimizations e.g. in std::copy. +// In debug mode, we don't do this. +// +// Some algorithms (e.g. std::copy, but not std::sort) need to convert an +// "unwrapped" result back into the original iterator type. Doing that is the job of __rewrap_iter. + +// Default case - we can't unwrap anything +template ::value> +struct __unwrap_iter_impl { + static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _Iter __rewrap(_Iter, _Iter __iter) { return __iter; } + static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _Iter __unwrap(_Iter __i) _NOEXCEPT { return __i; } +}; + +#ifndef _LIBCPP_ENABLE_DEBUG_MODE + +// It's a contiguous iterator, so we can use a raw pointer instead +template +struct __unwrap_iter_impl<_Iter, true> { + using _ToAddressT = decltype(std::__to_address(std::declval<_Iter>())); + + static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _Iter __rewrap(_Iter __orig_iter, _ToAddressT __unwrapped_iter) { + return __orig_iter + (__unwrapped_iter - std::__to_address(__orig_iter)); + } + + static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _ToAddressT __unwrap(_Iter __i) _NOEXCEPT { + return std::__to_address(__i); + } +}; + +#endif // !_LIBCPP_ENABLE_DEBUG_MODE + +template, + __enable_if_t::value, int> = 0> +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 +decltype(_Impl::__unwrap(std::declval<_Iter>())) __unwrap_iter(_Iter __i) _NOEXCEPT { + return _Impl::__unwrap(__i); +} + +template > +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _OrigIter __rewrap_iter(_OrigIter __orig_iter, _Iter __iter) _NOEXCEPT { + return _Impl::__rewrap(std::move(__orig_iter), std::move(__iter)); +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ALGORITHM_UNWRAP_ITER_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/unwrap_range.h b/app/src/main/cpp/libcxx/include/__algorithm/unwrap_range.h new file mode 100644 index 0000000..2c5d23e --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/unwrap_range.h @@ -0,0 +1,97 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_UNWRAP_RANGE_H +#define _LIBCPP___ALGORITHM_UNWRAP_RANGE_H + +#include <__algorithm/unwrap_iter.h> +#include <__concepts/constructible.h> +#include <__config> +#include <__iterator/concepts.h> +#include <__iterator/next.h> +#include <__utility/declval.h> +#include <__utility/move.h> +#include <__utility/pair.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +// __unwrap_range and __rewrap_range are used to unwrap ranges which may have different iterator and sentinel types. +// __unwrap_iter and __rewrap_iter don't work for this, because they assume that the iterator and sentinel have +// the same type. __unwrap_range tries to get two iterators and then forward to __unwrap_iter. + +#if _LIBCPP_STD_VER > 17 +template +struct __unwrap_range_impl { + _LIBCPP_HIDE_FROM_ABI static constexpr auto __unwrap(_Iter __first, _Sent __sent) + requires random_access_iterator<_Iter> && sized_sentinel_for<_Sent, _Iter> + { + auto __last = ranges::next(__first, __sent); + return pair{std::__unwrap_iter(std::move(__first)), std::__unwrap_iter(std::move(__last))}; + } + + _LIBCPP_HIDE_FROM_ABI static constexpr auto __unwrap(_Iter __first, _Sent __last) { + return pair{std::move(__first), std::move(__last)}; + } + + _LIBCPP_HIDE_FROM_ABI static constexpr auto + __rewrap(_Iter __orig_iter, decltype(std::__unwrap_iter(__orig_iter)) __iter) + requires random_access_iterator<_Iter> && sized_sentinel_for<_Sent, _Iter> + { + return std::__rewrap_iter(std::move(__orig_iter), std::move(__iter)); + } + + _LIBCPP_HIDE_FROM_ABI static constexpr auto __rewrap(const _Iter&, _Iter __iter) + requires (!(random_access_iterator<_Iter> && sized_sentinel_for<_Sent, _Iter>)) + { + return __iter; + } +}; + +template +struct __unwrap_range_impl<_Iter, _Iter> { + _LIBCPP_HIDE_FROM_ABI static constexpr auto __unwrap(_Iter __first, _Iter __last) { + return pair{std::__unwrap_iter(std::move(__first)), std::__unwrap_iter(std::move(__last))}; + } + + _LIBCPP_HIDE_FROM_ABI static constexpr auto + __rewrap(_Iter __orig_iter, decltype(std::__unwrap_iter(__orig_iter)) __iter) { + return std::__rewrap_iter(std::move(__orig_iter), std::move(__iter)); + } +}; + +template +_LIBCPP_HIDE_FROM_ABI constexpr auto __unwrap_range(_Iter __first, _Sent __last) { + return __unwrap_range_impl<_Iter, _Sent>::__unwrap(std::move(__first), std::move(__last)); +} + +template < + class _Sent, + class _Iter, + class _Unwrapped = decltype(std::__unwrap_range(std::declval<_Iter>(), std::declval<_Sent>()))> +_LIBCPP_HIDE_FROM_ABI constexpr _Iter __rewrap_range(_Iter __orig_iter, _Unwrapped __iter) { + return __unwrap_range_impl<_Iter, _Sent>::__rewrap(std::move(__orig_iter), std::move(__iter)); +} +#else // _LIBCPP_STD_VER > 17 +template ()))> +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR pair<_Unwrapped, _Unwrapped> __unwrap_range(_Iter __first, _Iter __last) { + return std::make_pair(std::__unwrap_iter(std::move(__first)), std::__unwrap_iter(std::move(__last))); +} + +template ()))> +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _Iter __rewrap_range(_Iter __orig_iter, _Unwrapped __iter) { + return std::__rewrap_iter(std::move(__orig_iter), std::move(__iter)); +} +#endif // _LIBCPP_STD_VER > 17 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ALGORITHM_UNWRAP_RANGE_H diff --git a/app/src/main/cpp/libcxx/include/__algorithm/upper_bound.h b/app/src/main/cpp/libcxx/include/__algorithm/upper_bound.h new file mode 100644 index 0000000..96552ce --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__algorithm/upper_bound.h @@ -0,0 +1,68 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_UPPER_BOUND_H +#define _LIBCPP___ALGORITHM_UPPER_BOUND_H + +#include <__algorithm/comp.h> +#include <__algorithm/half_positive.h> +#include <__algorithm/iterator_operations.h> +#include <__config> +#include <__functional/identity.h> +#include <__functional/invoke.h> +#include <__iterator/advance.h> +#include <__iterator/distance.h> +#include <__iterator/iterator_traits.h> +#include <__type_traits/is_copy_constructible.h> +#include <__utility/move.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Iter +__upper_bound(_Iter __first, _Sent __last, const _Tp& __value, _Compare&& __comp, _Proj&& __proj) { + auto __len = _IterOps<_AlgPolicy>::distance(__first, __last); + while (__len != 0) { + auto __half_len = std::__half_positive(__len); + auto __mid = _IterOps<_AlgPolicy>::next(__first, __half_len); + if (std::__invoke(__comp, __value, std::__invoke(__proj, *__mid))) + __len = __half_len; + else { + __first = ++__mid; + __len -= __half_len + 1; + } + } + return __first; +} + +template +_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator +upper_bound(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value, _Compare __comp) { + static_assert(is_copy_constructible<_ForwardIterator>::value, + "Iterator has to be copy constructible"); + return std::__upper_bound<_ClassicAlgPolicy>( + std::move(__first), std::move(__last), __value, std::move(__comp), std::__identity()); +} + +template +_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator +upper_bound(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value) { + return std::upper_bound( + std::move(__first), + std::move(__last), + __value, + __less<_Tp, typename iterator_traits<_ForwardIterator>::value_type>()); +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ALGORITHM_UPPER_BOUND_H diff --git a/app/src/main/cpp/libcxx/include/__assert b/app/src/main/cpp/libcxx/include/__assert new file mode 100644 index 0000000..9c0cd1b --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__assert @@ -0,0 +1,55 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ASSERT +#define _LIBCPP___ASSERT + +#include <__config> +#include <__verbose_abort> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +// TODO: Remove in LLVM 17. +#if defined(_LIBCPP_DEBUG) +# error "Defining _LIBCPP_DEBUG is not supported anymore. Please use _LIBCPP_ENABLE_DEBUG_MODE instead." +#endif + +// Automatically enable assertions when the debug mode is enabled. +#if defined(_LIBCPP_ENABLE_DEBUG_MODE) +# ifndef _LIBCPP_ENABLE_ASSERTIONS +# define _LIBCPP_ENABLE_ASSERTIONS 1 +# endif +#endif + +#ifndef _LIBCPP_ENABLE_ASSERTIONS +# define _LIBCPP_ENABLE_ASSERTIONS _LIBCPP_ENABLE_ASSERTIONS_DEFAULT +#endif + +#if _LIBCPP_ENABLE_ASSERTIONS != 0 && _LIBCPP_ENABLE_ASSERTIONS != 1 +# error "_LIBCPP_ENABLE_ASSERTIONS must be set to 0 or 1" +#endif + +#if _LIBCPP_ENABLE_ASSERTIONS +# define _LIBCPP_ASSERT(expression, message) \ + (__builtin_expect(static_cast(expression), 1) ? \ + (void)0 : \ + _LIBCPP_VERBOSE_ABORT("%s:%d: assertion %s failed: %s", __FILE__, __LINE__, #expression, message)) +#elif !defined(_LIBCPP_ASSERTIONS_DISABLE_ASSUME) && __has_builtin(__builtin_assume) +# define _LIBCPP_ASSERT(expression, message) \ + (_LIBCPP_DIAGNOSTIC_PUSH \ + _LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wassume") \ + __builtin_assume(static_cast(expression)) \ + _LIBCPP_DIAGNOSTIC_POP) +#else +# define _LIBCPP_ASSERT(expression, message) ((void)0) +#endif + +#endif // _LIBCPP___ASSERT diff --git a/app/src/main/cpp/libcxx/include/__availability b/app/src/main/cpp/libcxx/include/__availability new file mode 100644 index 0000000..6dfca3f --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__availability @@ -0,0 +1,288 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___AVAILABILITY +#define _LIBCPP___AVAILABILITY + +#include <__config> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +// Libc++ is shipped by various vendors. In particular, it is used as a system +// library on macOS, iOS and other Apple platforms. In order for users to be +// able to compile a binary that is intended to be deployed to an older version +// of a platform, Clang provides availability attributes [1]. These attributes +// can be placed on declarations and are used to describe the life cycle of a +// symbol in the library. +// +// The main goal is to ensure a compile-time error if a symbol that hasn't been +// introduced in a previously released library is used in a program that targets +// that previously released library. Normally, this would be a load-time error +// when one tries to launch the program against the older library. +// +// For example, the filesystem library was introduced in the dylib in macOS 10.15. +// If a user compiles on a macOS 10.15 host but targets macOS 10.13 with their +// program, the compiler would normally not complain (because the required +// declarations are in the headers), but the dynamic loader would fail to find +// the symbols when actually trying to launch the program on macOS 10.13. To +// turn this into a compile-time issue instead, declarations are annotated with +// when they were introduced, and the compiler can produce a diagnostic if the +// program references something that isn't available on the deployment target. +// +// This mechanism is general in nature, and any vendor can add their markup to +// the library (see below). Whenever a new feature is added that requires support +// in the shared library, a macro should be added below to mark this feature +// as unavailable. When vendors decide to ship the feature as part of their +// shared library, they can update the markup appropriately. +// +// Furthermore, many features in the standard library have corresponding +// feature-test macros. When a feature is made unavailable on some deployment +// target, a macro should be defined to signal that it is unavailable. That +// macro can then be picked up when feature-test macros are generated (see +// generate_feature_test_macro_components.py) to make sure that feature-test +// macros don't announce a feature as being implemented if it has been marked +// as unavailable. +// +// Note that this mechanism is disabled by default in the "upstream" libc++. +// Availability annotations are only meaningful when shipping libc++ inside +// a platform (i.e. as a system library), and so vendors that want them should +// turn those annotations on at CMake configuration time. +// +// [1]: https://clang.llvm.org/docs/AttributeReference.html#availability + + +// For backwards compatibility, allow users to define _LIBCPP_DISABLE_AVAILABILITY +// for a while. +#if defined(_LIBCPP_DISABLE_AVAILABILITY) +# if !defined(_LIBCPP_HAS_NO_VENDOR_AVAILABILITY_ANNOTATIONS) +# define _LIBCPP_HAS_NO_VENDOR_AVAILABILITY_ANNOTATIONS +# endif +#endif + +// Availability markup is disabled when building the library, or when the compiler +// doesn't support the proper attributes. +#if defined(_LIBCPP_BUILDING_LIBRARY) || \ + defined(_LIBCXXABI_BUILDING_LIBRARY) || \ + !__has_feature(attribute_availability_with_strict) || \ + !__has_feature(attribute_availability_in_templates) || \ + !__has_extension(pragma_clang_attribute_external_declaration) +# if !defined(_LIBCPP_HAS_NO_VENDOR_AVAILABILITY_ANNOTATIONS) +# define _LIBCPP_HAS_NO_VENDOR_AVAILABILITY_ANNOTATIONS +# endif +#endif + +#if defined(_LIBCPP_HAS_NO_VENDOR_AVAILABILITY_ANNOTATIONS) + + // This controls the availability of std::shared_mutex and std::shared_timed_mutex, + // which were added to the dylib later. +# define _LIBCPP_AVAILABILITY_SHARED_MUTEX +// # define _LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_shared_mutex +// # define _LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_shared_timed_mutex + + // These macros control the availability of std::bad_optional_access and + // other exception types. These were put in the shared library to prevent + // code bloat from every user program defining the vtable for these exception + // types. + // + // Note that when exceptions are disabled, the methods that normally throw + // these exceptions can be used even on older deployment targets, but those + // methods will abort instead of throwing. +# define _LIBCPP_AVAILABILITY_BAD_OPTIONAL_ACCESS +# define _LIBCPP_AVAILABILITY_BAD_VARIANT_ACCESS +# define _LIBCPP_AVAILABILITY_BAD_ANY_CAST + + // This controls the availability of std::uncaught_exceptions(). +# define _LIBCPP_AVAILABILITY_UNCAUGHT_EXCEPTIONS + + // This controls the availability of the sized version of ::operator delete, + // ::operator delete[], and their align_val_t variants, which were all added + // in C++17, and hence not present in early dylibs. +# define _LIBCPP_AVAILABILITY_SIZED_NEW_DELETE + + // This controls the availability of the std::future_error exception. + // + // Note that when exceptions are disabled, the methods that normally throw + // std::future_error can be used even on older deployment targets, but those + // methods will abort instead of throwing. +# define _LIBCPP_AVAILABILITY_FUTURE_ERROR + + // This controls the availability of std::type_info's vtable. + // I can't imagine how using std::type_info can work at all if + // this isn't supported. +# define _LIBCPP_AVAILABILITY_TYPEINFO_VTABLE + + // This controls the availability of std::locale::category members + // (e.g. std::locale::collate), which are defined in the dylib. +# define _LIBCPP_AVAILABILITY_LOCALE_CATEGORY + + // This controls the availability of atomic operations on std::shared_ptr + // (e.g. `std::atomic_store(std::shared_ptr)`), which require a shared + // lock table located in the dylib. +# define _LIBCPP_AVAILABILITY_ATOMIC_SHARED_PTR + + // These macros control the availability of all parts of that + // depend on something in the dylib. +# define _LIBCPP_AVAILABILITY_FILESYSTEM +# define _LIBCPP_AVAILABILITY_FILESYSTEM_PUSH +# define _LIBCPP_AVAILABILITY_FILESYSTEM_POP +// # define _LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_filesystem + + // This controls the availability of floating-point std::to_chars functions. + // These overloads were added later than the integer overloads. +# define _LIBCPP_AVAILABILITY_TO_CHARS_FLOATING_POINT + + // This controls the availability of the C++20 synchronization library, + // which requires shared library support for various operations + // (see libcxx/src/atomic.cpp). This includes , , + // , and notification functions on std::atomic. +# define _LIBCPP_AVAILABILITY_SYNC +// # define _LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_atomic_wait +// # define _LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_barrier +// # define _LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_latch +// # define _LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_semaphore + + // This controls the availability of the C++20 format library. + // The library is in development and not ABI stable yet. P2216 is + // retroactively accepted in C++20. This paper contains ABI breaking + // changes. +# define _LIBCPP_AVAILABILITY_FORMAT +// # define _LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_format + + // This controls whether the library claims to provide a default verbose + // termination function, and consequently whether the headers will try + // to use it when the mechanism isn't overriden at compile-time. +// # define _LIBCPP_HAS_NO_VERBOSE_ABORT_IN_LIBRARY + +#elif defined(__APPLE__) + +# define _LIBCPP_AVAILABILITY_SHARED_MUTEX \ + __attribute__((availability(macos,strict,introduced=10.12))) \ + __attribute__((availability(ios,strict,introduced=10.0))) \ + __attribute__((availability(tvos,strict,introduced=10.0))) \ + __attribute__((availability(watchos,strict,introduced=3.0))) +# if (defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 101200) || \ + (defined(__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ < 100000) || \ + (defined(__ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__ < 100000) || \ + (defined(__ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__ < 30000) +# define _LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_shared_mutex +# define _LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_shared_timed_mutex +# endif + + // Note: bad_optional_access & friends were not introduced in the matching + // macOS and iOS versions, so the version mismatch between macOS and others + // is intended. +# define _LIBCPP_AVAILABILITY_BAD_OPTIONAL_ACCESS \ + __attribute__((availability(macos,strict,introduced=10.13))) \ + __attribute__((availability(ios,strict,introduced=12.0))) \ + __attribute__((availability(tvos,strict,introduced=12.0))) \ + __attribute__((availability(watchos,strict,introduced=5.0))) +# define _LIBCPP_AVAILABILITY_BAD_VARIANT_ACCESS \ + _LIBCPP_AVAILABILITY_BAD_OPTIONAL_ACCESS +# define _LIBCPP_AVAILABILITY_BAD_ANY_CAST \ + _LIBCPP_AVAILABILITY_BAD_OPTIONAL_ACCESS + +# define _LIBCPP_AVAILABILITY_UNCAUGHT_EXCEPTIONS \ + __attribute__((availability(macos,strict,introduced=10.12))) \ + __attribute__((availability(ios,strict,introduced=10.0))) \ + __attribute__((availability(tvos,strict,introduced=10.0))) \ + __attribute__((availability(watchos,strict,introduced=3.0))) + +# define _LIBCPP_AVAILABILITY_SIZED_NEW_DELETE \ + __attribute__((availability(macos,strict,introduced=10.12))) \ + __attribute__((availability(ios,strict,introduced=10.0))) \ + __attribute__((availability(tvos,strict,introduced=10.0))) \ + __attribute__((availability(watchos,strict,introduced=3.0))) + +# define _LIBCPP_AVAILABILITY_FUTURE_ERROR \ + __attribute__((availability(ios,strict,introduced=6.0))) + +# define _LIBCPP_AVAILABILITY_TYPEINFO_VTABLE \ + __attribute__((availability(macos,strict,introduced=10.9))) \ + __attribute__((availability(ios,strict,introduced=7.0))) + +# define _LIBCPP_AVAILABILITY_LOCALE_CATEGORY \ + __attribute__((availability(macos,strict,introduced=10.9))) \ + __attribute__((availability(ios,strict,introduced=7.0))) + +# define _LIBCPP_AVAILABILITY_ATOMIC_SHARED_PTR \ + __attribute__((availability(macos,strict,introduced=10.9))) \ + __attribute__((availability(ios,strict,introduced=7.0))) + +# define _LIBCPP_AVAILABILITY_FILESYSTEM \ + __attribute__((availability(macos,strict,introduced=10.15))) \ + __attribute__((availability(ios,strict,introduced=13.0))) \ + __attribute__((availability(tvos,strict,introduced=13.0))) \ + __attribute__((availability(watchos,strict,introduced=6.0))) +# define _LIBCPP_AVAILABILITY_FILESYSTEM_PUSH \ + _Pragma("clang attribute push(__attribute__((availability(macos,strict,introduced=10.15))), apply_to=any(function,record))") \ + _Pragma("clang attribute push(__attribute__((availability(ios,strict,introduced=13.0))), apply_to=any(function,record))") \ + _Pragma("clang attribute push(__attribute__((availability(tvos,strict,introduced=13.0))), apply_to=any(function,record))") \ + _Pragma("clang attribute push(__attribute__((availability(watchos,strict,introduced=6.0))), apply_to=any(function,record))") +# define _LIBCPP_AVAILABILITY_FILESYSTEM_POP \ + _Pragma("clang attribute pop") \ + _Pragma("clang attribute pop") \ + _Pragma("clang attribute pop") \ + _Pragma("clang attribute pop") +# if (defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 101500) || \ + (defined(__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ < 130000) || \ + (defined(__ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__ < 130000) || \ + (defined(__ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__ < 60000) +# define _LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_filesystem +# endif + +# define _LIBCPP_AVAILABILITY_TO_CHARS_FLOATING_POINT \ + __attribute__((unavailable)) + +# define _LIBCPP_AVAILABILITY_SYNC \ + __attribute__((availability(macos,strict,introduced=11.0))) \ + __attribute__((availability(ios,strict,introduced=14.0))) \ + __attribute__((availability(tvos,strict,introduced=14.0))) \ + __attribute__((availability(watchos,strict,introduced=7.0))) +# if (defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 110000) || \ + (defined(__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ < 140000) || \ + (defined(__ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__ < 140000) || \ + (defined(__ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__ < 70000) +# define _LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_atomic_wait +# define _LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_barrier +# define _LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_latch +# define _LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_semaphore +# endif + +# define _LIBCPP_AVAILABILITY_FORMAT \ + __attribute__((unavailable)) +# define _LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_format + +# define _LIBCPP_HAS_NO_VERBOSE_ABORT_IN_LIBRARY + +#else + +// ...New vendors can add availability markup here... + +# error "It looks like you're trying to enable vendor availability markup, but you haven't defined the corresponding macros yet!" + +#endif + +// Define availability attributes that depend on _LIBCPP_NO_EXCEPTIONS. +// Those are defined in terms of the availability attributes above, and +// should not be vendor-specific. +#if defined(_LIBCPP_NO_EXCEPTIONS) +# define _LIBCPP_AVAILABILITY_FUTURE +# define _LIBCPP_AVAILABILITY_THROW_BAD_ANY_CAST +# define _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS +# define _LIBCPP_AVAILABILITY_THROW_BAD_VARIANT_ACCESS +#else +# define _LIBCPP_AVAILABILITY_FUTURE _LIBCPP_AVAILABILITY_FUTURE_ERROR +# define _LIBCPP_AVAILABILITY_THROW_BAD_ANY_CAST _LIBCPP_AVAILABILITY_BAD_ANY_CAST +# define _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS _LIBCPP_AVAILABILITY_BAD_OPTIONAL_ACCESS +# define _LIBCPP_AVAILABILITY_THROW_BAD_VARIANT_ACCESS _LIBCPP_AVAILABILITY_BAD_VARIANT_ACCESS +#endif + +#endif // _LIBCPP___AVAILABILITY diff --git a/app/src/main/cpp/libcxx/include/__bit/bit_cast.h b/app/src/main/cpp/libcxx/include/__bit/bit_cast.h new file mode 100644 index 0000000..2ca4120 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__bit/bit_cast.h @@ -0,0 +1,36 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___BIT_BIT_CAST_H +#define _LIBCPP___BIT_BIT_CAST_H + +#include <__config> +#include <__type_traits/is_trivially_copyable.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 17 + +template + requires(sizeof(_ToType) == sizeof(_FromType) && + is_trivially_copyable_v<_ToType> && + is_trivially_copyable_v<_FromType>) +_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr _ToType bit_cast(const _FromType& __from) noexcept { + return __builtin_bit_cast(_ToType, __from); +} + +#endif // _LIBCPP_STD_VER > 17 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___BIT_BIT_CAST_H diff --git a/app/src/main/cpp/libcxx/include/__bit/bit_ceil.h b/app/src/main/cpp/libcxx/include/__bit/bit_ceil.h new file mode 100644 index 0000000..a558d61 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__bit/bit_ceil.h @@ -0,0 +1,46 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___BIT_BIT_CEIL_H +#define _LIBCPP___BIT_BIT_CEIL_H + +#include <__assert> +#include <__bit/countl.h> +#include <__concepts/arithmetic.h> +#include <__config> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER >= 20 + +template <__libcpp_unsigned_integer _Tp> +_LIBCPP_HIDE_FROM_ABI constexpr _Tp bit_ceil(_Tp __t) noexcept { + if (__t < 2) + return 1; + const unsigned __n = numeric_limits<_Tp>::digits - std::countl_zero((_Tp)(__t - 1u)); + _LIBCPP_ASSERT(__n != numeric_limits<_Tp>::digits, "Bad input to bit_ceil"); + + if constexpr (sizeof(_Tp) >= sizeof(unsigned)) + return _Tp{1} << __n; + else { + const unsigned __extra = numeric_limits::digits - numeric_limits<_Tp>::digits; + const unsigned __retVal = 1u << (__n + __extra); + return (_Tp)(__retVal >> __extra); + } +} + +#endif // _LIBCPP_STD_VER >= 20 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___BIT_BIT_CEIL_H diff --git a/app/src/main/cpp/libcxx/include/__bit/bit_floor.h b/app/src/main/cpp/libcxx/include/__bit/bit_floor.h new file mode 100644 index 0000000..b2e3809 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__bit/bit_floor.h @@ -0,0 +1,34 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___BIT_BIT_FLOOR_H +#define _LIBCPP___BIT_BIT_FLOOR_H + +#include <__bit/bit_log2.h> +#include <__concepts/arithmetic.h> +#include <__config> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER >= 20 + +template <__libcpp_unsigned_integer _Tp> +_LIBCPP_HIDE_FROM_ABI constexpr _Tp bit_floor(_Tp __t) noexcept { + return __t == 0 ? 0 : _Tp{1} << std::__bit_log2(__t); +} + +#endif // _LIBCPP_STD_VER >= 20 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___BIT_BIT_FLOOR_H diff --git a/app/src/main/cpp/libcxx/include/__bit/bit_log2.h b/app/src/main/cpp/libcxx/include/__bit/bit_log2.h new file mode 100644 index 0000000..62936f6 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__bit/bit_log2.h @@ -0,0 +1,34 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___BIT_BIT_LOG2_H +#define _LIBCPP___BIT_BIT_LOG2_H + +#include <__bit/countl.h> +#include <__concepts/arithmetic.h> +#include <__config> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER >= 20 + +template <__libcpp_unsigned_integer _Tp> +_LIBCPP_HIDE_FROM_ABI constexpr _Tp __bit_log2(_Tp __t) noexcept { + return numeric_limits<_Tp>::digits - 1 - std::countl_zero(__t); +} + +#endif // _LIBCPP_STD_VER >= 20 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___BIT_BIT_LOG2_H diff --git a/app/src/main/cpp/libcxx/include/__bit/bit_width.h b/app/src/main/cpp/libcxx/include/__bit/bit_width.h new file mode 100644 index 0000000..4381f22 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__bit/bit_width.h @@ -0,0 +1,33 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___BIT_BIT_WIDTH_H +#define _LIBCPP___BIT_BIT_WIDTH_H + +#include <__bit/bit_log2.h> +#include <__concepts/arithmetic.h> +#include <__config> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if _LIBCPP_STD_VER >= 20 + +_LIBCPP_BEGIN_NAMESPACE_STD + +template <__libcpp_unsigned_integer _Tp> +_LIBCPP_HIDE_FROM_ABI constexpr int bit_width(_Tp __t) noexcept { + return __t == 0 ? 0 : std::__bit_log2(__t) + 1; +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER >= 20 + +#endif // _LIBCPP___BIT_BIT_WIDTH_H diff --git a/app/src/main/cpp/libcxx/include/__bit/blsr.h b/app/src/main/cpp/libcxx/include/__bit/blsr.h new file mode 100644 index 0000000..de991e9 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__bit/blsr.h @@ -0,0 +1,34 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___BIT_BLSR_H +#define _LIBCPP___BIT_BLSR_H + +#include <__config> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR unsigned __libcpp_blsr(unsigned __x) _NOEXCEPT { + return __x ^ (__x & -__x); +} + +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR unsigned long __libcpp_blsr(unsigned long __x) _NOEXCEPT { + return __x ^ (__x & -__x); +} + +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR unsigned long long __libcpp_blsr(unsigned long long __x) _NOEXCEPT { + return __x ^ (__x & -__x); +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___BIT_BLSR_H diff --git a/app/src/main/cpp/libcxx/include/__bit/byteswap.h b/app/src/main/cpp/libcxx/include/__bit/byteswap.h new file mode 100644 index 0000000..6fa8d48 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__bit/byteswap.h @@ -0,0 +1,55 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___BIT_BYTESWAP_H +#define _LIBCPP___BIT_BYTESWAP_H + +#include <__concepts/arithmetic.h> +#include <__config> +#include +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 20 + +template +_LIBCPP_HIDE_FROM_ABI constexpr _Tp byteswap(_Tp __val) noexcept { + + if constexpr (sizeof(_Tp) == 1) { + return __val; + } else if constexpr (sizeof(_Tp) == 2) { + return __builtin_bswap16(__val); + } else if constexpr (sizeof(_Tp) == 4) { + return __builtin_bswap32(__val); + } else if constexpr (sizeof(_Tp) == 8) { + return __builtin_bswap64(__val); +#ifndef _LIBCPP_HAS_NO_INT128 + } else if constexpr (sizeof(_Tp) == 16) { +#if __has_builtin(__builtin_bswap128) + return __builtin_bswap128(__val); +#else + return static_cast<_Tp>(byteswap(static_cast(__val))) << 64 | + static_cast<_Tp>(byteswap(static_cast(__val >> 64))); +#endif // __has_builtin(__builtin_bswap128) +#endif // _LIBCPP_HAS_NO_INT128 + } else { + static_assert(sizeof(_Tp) == 0, "byteswap is unimplemented for integral types of this size"); + } +} + +#endif // _LIBCPP_STD_VER > 20 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___BIT_BYTESWAP_H diff --git a/app/src/main/cpp/libcxx/include/__bit/countl.h b/app/src/main/cpp/libcxx/include/__bit/countl.h new file mode 100644 index 0000000..86eaee0 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__bit/countl.h @@ -0,0 +1,104 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___BIT_COUNTL_H +#define _LIBCPP___BIT_COUNTL_H + +#include <__bit/rotate.h> +#include <__concepts/arithmetic.h> +#include <__config> +#include <__type_traits/is_unsigned_integer.h> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + +_LIBCPP_BEGIN_NAMESPACE_STD + +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR +int __libcpp_clz(unsigned __x) _NOEXCEPT { return __builtin_clz(__x); } + +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR +int __libcpp_clz(unsigned long __x) _NOEXCEPT { return __builtin_clzl(__x); } + +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR +int __libcpp_clz(unsigned long long __x) _NOEXCEPT { return __builtin_clzll(__x); } + +# ifndef _LIBCPP_HAS_NO_INT128 +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR +int __libcpp_clz(__uint128_t __x) _NOEXCEPT { + // The function is written in this form due to C++ constexpr limitations. + // The algorithm: + // - Test whether any bit in the high 64-bits is set + // - No bits set: + // - The high 64-bits contain 64 leading zeros, + // - Add the result of the low 64-bits. + // - Any bits set: + // - The number of leading zeros of the input is the number of leading + // zeros in the high 64-bits. + return ((__x >> 64) == 0) + ? (64 + __builtin_clzll(static_cast(__x))) + : __builtin_clzll(static_cast(__x >> 64)); +} +# endif // _LIBCPP_HAS_NO_INT128 + +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 +int __countl_zero(_Tp __t) _NOEXCEPT +{ + static_assert(__libcpp_is_unsigned_integer<_Tp>::value, "__countl_zero requires an unsigned integer type"); + if (__t == 0) + return numeric_limits<_Tp>::digits; + + if (sizeof(_Tp) <= sizeof(unsigned int)) + return std::__libcpp_clz(static_cast(__t)) + - (numeric_limits::digits - numeric_limits<_Tp>::digits); + else if (sizeof(_Tp) <= sizeof(unsigned long)) + return std::__libcpp_clz(static_cast(__t)) + - (numeric_limits::digits - numeric_limits<_Tp>::digits); + else if (sizeof(_Tp) <= sizeof(unsigned long long)) + return std::__libcpp_clz(static_cast(__t)) + - (numeric_limits::digits - numeric_limits<_Tp>::digits); + else + { + int __ret = 0; + int __iter = 0; + const unsigned int __ulldigits = numeric_limits::digits; + while (true) { + __t = std::__rotr(__t, __ulldigits); + if ((__iter = std::__countl_zero(static_cast(__t))) != __ulldigits) + break; + __ret += __iter; + } + return __ret + __iter; + } +} + +#if _LIBCPP_STD_VER >= 20 + +template <__libcpp_unsigned_integer _Tp> +_LIBCPP_HIDE_FROM_ABI constexpr int countl_zero(_Tp __t) noexcept { + return std::__countl_zero(__t); +} + +template <__libcpp_unsigned_integer _Tp> +_LIBCPP_HIDE_FROM_ABI constexpr int countl_one(_Tp __t) noexcept { + return __t != numeric_limits<_Tp>::max() ? std::countl_zero(static_cast<_Tp>(~__t)) : numeric_limits<_Tp>::digits; +} + +#endif // _LIBCPP_STD_VER >= 20 + +_LIBCPP_END_NAMESPACE_STD + +_LIBCPP_POP_MACROS + +#endif // _LIBCPP___BIT_COUNTL_H diff --git a/app/src/main/cpp/libcxx/include/__bit/countr.h b/app/src/main/cpp/libcxx/include/__bit/countr.h new file mode 100644 index 0000000..d3ca5b6 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__bit/countr.h @@ -0,0 +1,70 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___BIT_COUNTR_H +#define _LIBCPP___BIT_COUNTR_H + +#include <__bit/rotate.h> +#include <__concepts/arithmetic.h> +#include <__config> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + +_LIBCPP_BEGIN_NAMESPACE_STD + +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR +int __libcpp_ctz(unsigned __x) _NOEXCEPT { return __builtin_ctz(__x); } + +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR +int __libcpp_ctz(unsigned long __x) _NOEXCEPT { return __builtin_ctzl(__x); } + +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR +int __libcpp_ctz(unsigned long long __x) _NOEXCEPT { return __builtin_ctzll(__x); } + +#if _LIBCPP_STD_VER >= 20 + +template <__libcpp_unsigned_integer _Tp> +_LIBCPP_HIDE_FROM_ABI constexpr int countr_zero(_Tp __t) noexcept { + if (__t == 0) + return numeric_limits<_Tp>::digits; + + if (sizeof(_Tp) <= sizeof(unsigned int)) + return std::__libcpp_ctz(static_cast(__t)); + else if (sizeof(_Tp) <= sizeof(unsigned long)) + return std::__libcpp_ctz(static_cast(__t)); + else if (sizeof(_Tp) <= sizeof(unsigned long long)) + return std::__libcpp_ctz(static_cast(__t)); + else { + int __ret = 0; + const unsigned int __ulldigits = numeric_limits::digits; + while (static_cast(__t) == 0uLL) { + __ret += __ulldigits; + __t >>= __ulldigits; + } + return __ret + std::__libcpp_ctz(static_cast(__t)); + } +} + +template <__libcpp_unsigned_integer _Tp> +_LIBCPP_HIDE_FROM_ABI constexpr int countr_one(_Tp __t) noexcept { + return __t != numeric_limits<_Tp>::max() ? std::countr_zero(static_cast<_Tp>(~__t)) : numeric_limits<_Tp>::digits; +} + +#endif // _LIBCPP_STD_VER >= 20 + +_LIBCPP_END_NAMESPACE_STD + +_LIBCPP_POP_MACROS + +#endif // _LIBCPP___BIT_COUNTR_H diff --git a/app/src/main/cpp/libcxx/include/__bit/endian.h b/app/src/main/cpp/libcxx/include/__bit/endian.h new file mode 100644 index 0000000..52635f2 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__bit/endian.h @@ -0,0 +1,38 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___BIT_ENDIAN_H +#define _LIBCPP___BIT_ENDIAN_H + +#include <__config> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if _LIBCPP_STD_VER >= 20 + +_LIBCPP_BEGIN_NAMESPACE_STD + +enum class endian { + little = 0xDEAD, + big = 0xFACE, +# if defined(_LIBCPP_LITTLE_ENDIAN) + native = little +# elif defined(_LIBCPP_BIG_ENDIAN) + native = big +# else + native = 0xCAFE +# endif +}; + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER >= 20 + +#endif // _LIBCPP___BIT_ENDIAN_H diff --git a/app/src/main/cpp/libcxx/include/__bit/has_single_bit.h b/app/src/main/cpp/libcxx/include/__bit/has_single_bit.h new file mode 100644 index 0000000..b89f599 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__bit/has_single_bit.h @@ -0,0 +1,37 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___BIT_HAS_SINGLE_BIT_H +#define _LIBCPP___BIT_HAS_SINGLE_BIT_H + +#include <__concepts/arithmetic.h> +#include <__config> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + +#if _LIBCPP_STD_VER >= 20 + +_LIBCPP_BEGIN_NAMESPACE_STD + +template <__libcpp_unsigned_integer _Tp> +_LIBCPP_HIDE_FROM_ABI constexpr bool has_single_bit(_Tp __t) noexcept { + return __t != 0 && (((__t & (__t - 1)) == 0)); +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER >= 20 + +_LIBCPP_POP_MACROS + +#endif // _LIBCPP___BIT_HAS_SINGLE_BIT_H diff --git a/app/src/main/cpp/libcxx/include/__bit/popcount.h b/app/src/main/cpp/libcxx/include/__bit/popcount.h new file mode 100644 index 0000000..33b94cf --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__bit/popcount.h @@ -0,0 +1,61 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___BIT_POPCOUNT_H +#define _LIBCPP___BIT_POPCOUNT_H + +#include <__bit/rotate.h> +#include <__concepts/arithmetic.h> +#include <__config> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + +_LIBCPP_BEGIN_NAMESPACE_STD + +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR +int __libcpp_popcount(unsigned __x) _NOEXCEPT { return __builtin_popcount(__x); } + +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR +int __libcpp_popcount(unsigned long __x) _NOEXCEPT { return __builtin_popcountl(__x); } + +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR +int __libcpp_popcount(unsigned long long __x) _NOEXCEPT { return __builtin_popcountll(__x); } + +#if _LIBCPP_STD_VER >= 20 + +template <__libcpp_unsigned_integer _Tp> +_LIBCPP_HIDE_FROM_ABI constexpr int popcount(_Tp __t) noexcept { + if (sizeof(_Tp) <= sizeof(unsigned int)) + return std::__libcpp_popcount(static_cast(__t)); + else if (sizeof(_Tp) <= sizeof(unsigned long)) + return std::__libcpp_popcount(static_cast(__t)); + else if (sizeof(_Tp) <= sizeof(unsigned long long)) + return std::__libcpp_popcount(static_cast(__t)); + else { + int __ret = 0; + while (__t != 0) { + __ret += std::__libcpp_popcount(static_cast(__t)); + __t >>= numeric_limits::digits; + } + return __ret; + } +} + +#endif // _LIBCPP_STD_VER >= 20 + +_LIBCPP_END_NAMESPACE_STD + +_LIBCPP_POP_MACROS + +#endif // _LIBCPP___BIT_POPCOUNT_H diff --git a/app/src/main/cpp/libcxx/include/__bit/rotate.h b/app/src/main/cpp/libcxx/include/__bit/rotate.h new file mode 100644 index 0000000..5aa7518 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__bit/rotate.h @@ -0,0 +1,53 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___BIT_ROTATE_H +#define _LIBCPP___BIT_ROTATE_H + +#include <__concepts/arithmetic.h> +#include <__config> +#include <__type_traits/is_unsigned_integer.h> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 +_Tp __rotr(_Tp __t, unsigned int __cnt) _NOEXCEPT +{ + static_assert(__libcpp_is_unsigned_integer<_Tp>::value, "__rotr requires an unsigned integer type"); + const unsigned int __dig = numeric_limits<_Tp>::digits; + if ((__cnt % __dig) == 0) + return __t; + return (__t >> (__cnt % __dig)) | (__t << (__dig - (__cnt % __dig))); +} + +#if _LIBCPP_STD_VER >= 20 + +template <__libcpp_unsigned_integer _Tp> +_LIBCPP_HIDE_FROM_ABI constexpr _Tp rotl(_Tp __t, unsigned int __cnt) noexcept { + const unsigned int __dig = numeric_limits<_Tp>::digits; + if ((__cnt % __dig) == 0) + return __t; + return (__t << (__cnt % __dig)) | (__t >> (__dig - (__cnt % __dig))); +} + +template <__libcpp_unsigned_integer _Tp> +_LIBCPP_HIDE_FROM_ABI constexpr _Tp rotr(_Tp __t, unsigned int __cnt) noexcept { + return std::__rotr(__t, __cnt); +} + +#endif // _LIBCPP_STD_VER >= 20 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___BIT_ROTATE_H diff --git a/app/src/main/cpp/libcxx/include/__bit_reference b/app/src/main/cpp/libcxx/include/__bit_reference new file mode 100644 index 0000000..2665749 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__bit_reference @@ -0,0 +1,1360 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___BIT_REFERENCE +#define _LIBCPP___BIT_REFERENCE + +#include <__algorithm/copy_n.h> +#include <__algorithm/fill_n.h> +#include <__algorithm/min.h> +#include <__bit/countr.h> +#include <__bit/popcount.h> +#include <__config> +#include <__iterator/iterator_traits.h> +#include <__memory/construct_at.h> +#include <__memory/pointer_traits.h> +#include +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + + +_LIBCPP_BEGIN_NAMESPACE_STD + +template class __bit_iterator; +template class __bit_const_reference; + +template +struct __has_storage_type +{ + static const bool value = false; +}; + +template ::value> +class __bit_reference +{ + typedef typename _Cp::__storage_type __storage_type; + typedef typename _Cp::__storage_pointer __storage_pointer; + + __storage_pointer __seg_; + __storage_type __mask_; + + friend typename _Cp::__self; + + friend class __bit_const_reference<_Cp>; + friend class __bit_iterator<_Cp, false>; +public: + using __container = typename _Cp::__self; + + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 + __bit_reference(const __bit_reference&) = default; + + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 operator bool() const _NOEXCEPT + {return static_cast(*__seg_ & __mask_);} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 bool operator ~() const _NOEXCEPT + {return !static_cast(*this);} + + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 + __bit_reference& operator=(bool __x) _NOEXCEPT + { + if (__x) + *__seg_ |= __mask_; + else + *__seg_ &= ~__mask_; + return *this; + } + +#if _LIBCPP_STD_VER > 20 + _LIBCPP_HIDE_FROM_ABI constexpr const __bit_reference& operator=(bool __x) const noexcept { + if (__x) + *__seg_ |= __mask_; + else + *__seg_ &= ~__mask_; + return *this; + } +#endif + + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 + __bit_reference& operator=(const __bit_reference& __x) _NOEXCEPT + {return operator=(static_cast(__x));} + + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 void flip() _NOEXCEPT {*__seg_ ^= __mask_;} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 __bit_iterator<_Cp, false> operator&() const _NOEXCEPT + {return __bit_iterator<_Cp, false>(__seg_, static_cast(std::__libcpp_ctz(__mask_)));} +private: + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 + explicit __bit_reference(__storage_pointer __s, __storage_type __m) _NOEXCEPT + : __seg_(__s), __mask_(__m) {} +}; + +template +class __bit_reference<_Cp, false> +{ +}; + +template +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 +void +swap(__bit_reference<_Cp> __x, __bit_reference<_Cp> __y) _NOEXCEPT +{ + bool __t = __x; + __x = __y; + __y = __t; +} + +template +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 +void +swap(__bit_reference<_Cp> __x, __bit_reference<_Dp> __y) _NOEXCEPT +{ + bool __t = __x; + __x = __y; + __y = __t; +} + +template +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 +void +swap(__bit_reference<_Cp> __x, bool& __y) _NOEXCEPT +{ + bool __t = __x; + __x = __y; + __y = __t; +} + +template +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 +void +swap(bool& __x, __bit_reference<_Cp> __y) _NOEXCEPT +{ + bool __t = __x; + __x = __y; + __y = __t; +} + +template +class __bit_const_reference +{ + typedef typename _Cp::__storage_type __storage_type; + typedef typename _Cp::__const_storage_pointer __storage_pointer; + + __storage_pointer __seg_; + __storage_type __mask_; + + friend typename _Cp::__self; + friend class __bit_iterator<_Cp, true>; +public: + _LIBCPP_INLINE_VISIBILITY + __bit_const_reference(const __bit_const_reference&) = default; + + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 + __bit_const_reference(const __bit_reference<_Cp>& __x) _NOEXCEPT + : __seg_(__x.__seg_), __mask_(__x.__mask_) {} + + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR operator bool() const _NOEXCEPT + {return static_cast(*__seg_ & __mask_);} + + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 __bit_iterator<_Cp, true> operator&() const _NOEXCEPT + {return __bit_iterator<_Cp, true>(__seg_, static_cast(std::__libcpp_ctz(__mask_)));} +private: + _LIBCPP_INLINE_VISIBILITY + _LIBCPP_CONSTEXPR + explicit __bit_const_reference(__storage_pointer __s, __storage_type __m) _NOEXCEPT + : __seg_(__s), __mask_(__m) {} + + __bit_const_reference& operator=(const __bit_const_reference&) = delete; +}; + +// find + +template +_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __bit_iterator<_Cp, _IsConst> +__find_bool_true(__bit_iterator<_Cp, _IsConst> __first, typename _Cp::size_type __n) +{ + typedef __bit_iterator<_Cp, _IsConst> _It; + typedef typename _It::__storage_type __storage_type; + const int __bits_per_word = _It::__bits_per_word; + // do first partial word + if (__first.__ctz_ != 0) + { + __storage_type __clz_f = static_cast<__storage_type>(__bits_per_word - __first.__ctz_); + __storage_type __dn = _VSTD::min(__clz_f, __n); + __storage_type __m = (~__storage_type(0) << __first.__ctz_) & (~__storage_type(0) >> (__clz_f - __dn)); + __storage_type __b = *__first.__seg_ & __m; + if (__b) + return _It(__first.__seg_, static_cast(_VSTD::__libcpp_ctz(__b))); + if (__n == __dn) + return __first + __n; + __n -= __dn; + ++__first.__seg_; + } + // do middle whole words + for (; __n >= __bits_per_word; ++__first.__seg_, __n -= __bits_per_word) + if (*__first.__seg_) + return _It(__first.__seg_, static_cast(_VSTD::__libcpp_ctz(*__first.__seg_))); + // do last partial word + if (__n > 0) + { + __storage_type __m = ~__storage_type(0) >> (__bits_per_word - __n); + __storage_type __b = *__first.__seg_ & __m; + if (__b) + return _It(__first.__seg_, static_cast(_VSTD::__libcpp_ctz(__b))); + } + return _It(__first.__seg_, static_cast(__n)); +} + +template +_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __bit_iterator<_Cp, _IsConst> +__find_bool_false(__bit_iterator<_Cp, _IsConst> __first, typename _Cp::size_type __n) +{ + typedef __bit_iterator<_Cp, _IsConst> _It; + typedef typename _It::__storage_type __storage_type; + const int __bits_per_word = _It::__bits_per_word; + // do first partial word + if (__first.__ctz_ != 0) + { + __storage_type __clz_f = static_cast<__storage_type>(__bits_per_word - __first.__ctz_); + __storage_type __dn = _VSTD::min(__clz_f, __n); + __storage_type __m = (~__storage_type(0) << __first.__ctz_) & (~__storage_type(0) >> (__clz_f - __dn)); + __storage_type __b = ~*__first.__seg_ & __m; + if (__b) + return _It(__first.__seg_, static_cast(_VSTD::__libcpp_ctz(__b))); + if (__n == __dn) + return __first + __n; + __n -= __dn; + ++__first.__seg_; + } + // do middle whole words + for (; __n >= __bits_per_word; ++__first.__seg_, __n -= __bits_per_word) + { + __storage_type __b = ~*__first.__seg_; + if (__b) + return _It(__first.__seg_, static_cast(_VSTD::__libcpp_ctz(__b))); + } + // do last partial word + if (__n > 0) + { + __storage_type __m = ~__storage_type(0) >> (__bits_per_word - __n); + __storage_type __b = ~*__first.__seg_ & __m; + if (__b) + return _It(__first.__seg_, static_cast(_VSTD::__libcpp_ctz(__b))); + } + return _It(__first.__seg_, static_cast(__n)); +} + +template +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 +__bit_iterator<_Cp, _IsConst> +find(__bit_iterator<_Cp, _IsConst> __first, __bit_iterator<_Cp, _IsConst> __last, const _Tp& __value) +{ + if (static_cast(__value)) + return _VSTD::__find_bool_true(__first, static_cast(__last - __first)); + return _VSTD::__find_bool_false(__first, static_cast(__last - __first)); +} + +// count + +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 typename __bit_iterator<_Cp, _IsConst>::difference_type +__count_bool_true(__bit_iterator<_Cp, _IsConst> __first, typename _Cp::size_type __n) +{ + typedef __bit_iterator<_Cp, _IsConst> _It; + typedef typename _It::__storage_type __storage_type; + typedef typename _It::difference_type difference_type; + const int __bits_per_word = _It::__bits_per_word; + difference_type __r = 0; + // do first partial word + if (__first.__ctz_ != 0) + { + __storage_type __clz_f = static_cast<__storage_type>(__bits_per_word - __first.__ctz_); + __storage_type __dn = _VSTD::min(__clz_f, __n); + __storage_type __m = (~__storage_type(0) << __first.__ctz_) & (~__storage_type(0) >> (__clz_f - __dn)); + __r = _VSTD::__libcpp_popcount(*__first.__seg_ & __m); + __n -= __dn; + ++__first.__seg_; + } + // do middle whole words + for (; __n >= __bits_per_word; ++__first.__seg_, __n -= __bits_per_word) + __r += _VSTD::__libcpp_popcount(*__first.__seg_); + // do last partial word + if (__n > 0) + { + __storage_type __m = ~__storage_type(0) >> (__bits_per_word - __n); + __r += _VSTD::__libcpp_popcount(*__first.__seg_ & __m); + } + return __r; +} + +template +_LIBCPP_HIDE_FROM_ABI typename __bit_iterator<_Cp, _IsConst>::difference_type +__count_bool_false(__bit_iterator<_Cp, _IsConst> __first, typename _Cp::size_type __n) +{ + typedef __bit_iterator<_Cp, _IsConst> _It; + typedef typename _It::__storage_type __storage_type; + typedef typename _It::difference_type difference_type; + const int __bits_per_word = _It::__bits_per_word; + difference_type __r = 0; + // do first partial word + if (__first.__ctz_ != 0) + { + __storage_type __clz_f = static_cast<__storage_type>(__bits_per_word - __first.__ctz_); + __storage_type __dn = _VSTD::min(__clz_f, __n); + __storage_type __m = (~__storage_type(0) << __first.__ctz_) & (~__storage_type(0) >> (__clz_f - __dn)); + __r = _VSTD::__libcpp_popcount(~*__first.__seg_ & __m); + __n -= __dn; + ++__first.__seg_; + } + // do middle whole words + for (; __n >= __bits_per_word; ++__first.__seg_, __n -= __bits_per_word) + __r += _VSTD::__libcpp_popcount(~*__first.__seg_); + // do last partial word + if (__n > 0) + { + __storage_type __m = ~__storage_type(0) >> (__bits_per_word - __n); + __r += _VSTD::__libcpp_popcount(~*__first.__seg_ & __m); + } + return __r; +} + +template +inline _LIBCPP_INLINE_VISIBILITY +typename __bit_iterator<_Cp, _IsConst>::difference_type +count(__bit_iterator<_Cp, _IsConst> __first, __bit_iterator<_Cp, _IsConst> __last, const _Tp& __value) +{ + if (static_cast(__value)) + return _VSTD::__count_bool_true(__first, static_cast(__last - __first)); + return _VSTD::__count_bool_false(__first, static_cast(__last - __first)); +} + +// fill_n + +template +_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void +__fill_n_false(__bit_iterator<_Cp, false> __first, typename _Cp::size_type __n) +{ + typedef __bit_iterator<_Cp, false> _It; + typedef typename _It::__storage_type __storage_type; + const int __bits_per_word = _It::__bits_per_word; + // do first partial word + if (__first.__ctz_ != 0) + { + __storage_type __clz_f = static_cast<__storage_type>(__bits_per_word - __first.__ctz_); + __storage_type __dn = _VSTD::min(__clz_f, __n); + __storage_type __m = (~__storage_type(0) << __first.__ctz_) & (~__storage_type(0) >> (__clz_f - __dn)); + *__first.__seg_ &= ~__m; + __n -= __dn; + ++__first.__seg_; + } + // do middle whole words + __storage_type __nw = __n / __bits_per_word; + std::fill_n(std::__to_address(__first.__seg_), __nw, 0); + __n -= __nw * __bits_per_word; + // do last partial word + if (__n > 0) + { + __first.__seg_ += __nw; + __storage_type __m = ~__storage_type(0) >> (__bits_per_word - __n); + *__first.__seg_ &= ~__m; + } +} + +template +_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void +__fill_n_true(__bit_iterator<_Cp, false> __first, typename _Cp::size_type __n) +{ + typedef __bit_iterator<_Cp, false> _It; + typedef typename _It::__storage_type __storage_type; + const int __bits_per_word = _It::__bits_per_word; + // do first partial word + if (__first.__ctz_ != 0) + { + __storage_type __clz_f = static_cast<__storage_type>(__bits_per_word - __first.__ctz_); + __storage_type __dn = _VSTD::min(__clz_f, __n); + __storage_type __m = (~__storage_type(0) << __first.__ctz_) & (~__storage_type(0) >> (__clz_f - __dn)); + *__first.__seg_ |= __m; + __n -= __dn; + ++__first.__seg_; + } + // do middle whole words + __storage_type __nw = __n / __bits_per_word; + // __storage_type is always an unsigned type, so -1 sets all bits + std::fill_n(std::__to_address(__first.__seg_), __nw, static_cast<__storage_type>(-1)); + __n -= __nw * __bits_per_word; + // do last partial word + if (__n > 0) + { + __first.__seg_ += __nw; + __storage_type __m = ~__storage_type(0) >> (__bits_per_word - __n); + *__first.__seg_ |= __m; + } +} + +template +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 +void +fill_n(__bit_iterator<_Cp, false> __first, typename _Cp::size_type __n, bool __value) +{ + if (__n > 0) + { + if (__value) + _VSTD::__fill_n_true(__first, __n); + else + _VSTD::__fill_n_false(__first, __n); + } +} + +// fill + +template +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 +void +fill(__bit_iterator<_Cp, false> __first, __bit_iterator<_Cp, false> __last, bool __value) +{ + _VSTD::fill_n(__first, static_cast(__last - __first), __value); +} + +// copy + +template +_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __bit_iterator<_Cp, false> +__copy_aligned(__bit_iterator<_Cp, _IsConst> __first, __bit_iterator<_Cp, _IsConst> __last, + __bit_iterator<_Cp, false> __result) +{ + typedef __bit_iterator<_Cp, _IsConst> _In; + typedef typename _In::difference_type difference_type; + typedef typename _In::__storage_type __storage_type; + const int __bits_per_word = _In::__bits_per_word; + difference_type __n = __last - __first; + if (__n > 0) + { + // do first word + if (__first.__ctz_ != 0) + { + unsigned __clz = __bits_per_word - __first.__ctz_; + difference_type __dn = _VSTD::min(static_cast(__clz), __n); + __n -= __dn; + __storage_type __m = (~__storage_type(0) << __first.__ctz_) & (~__storage_type(0) >> (__clz - __dn)); + __storage_type __b = *__first.__seg_ & __m; + *__result.__seg_ &= ~__m; + *__result.__seg_ |= __b; + __result.__seg_ += (__dn + __result.__ctz_) / __bits_per_word; + __result.__ctz_ = static_cast((__dn + __result.__ctz_) % __bits_per_word); + ++__first.__seg_; + // __first.__ctz_ = 0; + } + // __first.__ctz_ == 0; + // do middle words + __storage_type __nw = __n / __bits_per_word; + std::copy_n(std::__to_address(__first.__seg_), __nw, std::__to_address(__result.__seg_)); + __n -= __nw * __bits_per_word; + __result.__seg_ += __nw; + // do last word + if (__n > 0) + { + __first.__seg_ += __nw; + __storage_type __m = ~__storage_type(0) >> (__bits_per_word - __n); + __storage_type __b = *__first.__seg_ & __m; + *__result.__seg_ &= ~__m; + *__result.__seg_ |= __b; + __result.__ctz_ = static_cast(__n); + } + } + return __result; +} + +template +_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __bit_iterator<_Cp, false> +__copy_unaligned(__bit_iterator<_Cp, _IsConst> __first, __bit_iterator<_Cp, _IsConst> __last, + __bit_iterator<_Cp, false> __result) +{ + typedef __bit_iterator<_Cp, _IsConst> _In; + typedef typename _In::difference_type difference_type; + typedef typename _In::__storage_type __storage_type; + const int __bits_per_word = _In::__bits_per_word; + difference_type __n = __last - __first; + if (__n > 0) + { + // do first word + if (__first.__ctz_ != 0) + { + unsigned __clz_f = __bits_per_word - __first.__ctz_; + difference_type __dn = _VSTD::min(static_cast(__clz_f), __n); + __n -= __dn; + __storage_type __m = (~__storage_type(0) << __first.__ctz_) & (~__storage_type(0) >> (__clz_f - __dn)); + __storage_type __b = *__first.__seg_ & __m; + unsigned __clz_r = __bits_per_word - __result.__ctz_; + __storage_type __ddn = _VSTD::min<__storage_type>(__dn, __clz_r); + __m = (~__storage_type(0) << __result.__ctz_) & (~__storage_type(0) >> (__clz_r - __ddn)); + *__result.__seg_ &= ~__m; + if (__result.__ctz_ > __first.__ctz_) + *__result.__seg_ |= __b << (__result.__ctz_ - __first.__ctz_); + else + *__result.__seg_ |= __b >> (__first.__ctz_ - __result.__ctz_); + __result.__seg_ += (__ddn + __result.__ctz_) / __bits_per_word; + __result.__ctz_ = static_cast((__ddn + __result.__ctz_) % __bits_per_word); + __dn -= __ddn; + if (__dn > 0) + { + __m = ~__storage_type(0) >> (__bits_per_word - __dn); + *__result.__seg_ &= ~__m; + *__result.__seg_ |= __b >> (__first.__ctz_ + __ddn); + __result.__ctz_ = static_cast(__dn); + } + ++__first.__seg_; + // __first.__ctz_ = 0; + } + // __first.__ctz_ == 0; + // do middle words + unsigned __clz_r = __bits_per_word - __result.__ctz_; + __storage_type __m = ~__storage_type(0) << __result.__ctz_; + for (; __n >= __bits_per_word; __n -= __bits_per_word, ++__first.__seg_) + { + __storage_type __b = *__first.__seg_; + *__result.__seg_ &= ~__m; + *__result.__seg_ |= __b << __result.__ctz_; + ++__result.__seg_; + *__result.__seg_ &= __m; + *__result.__seg_ |= __b >> __clz_r; + } + // do last word + if (__n > 0) + { + __m = ~__storage_type(0) >> (__bits_per_word - __n); + __storage_type __b = *__first.__seg_ & __m; + __storage_type __dn = _VSTD::min(__n, static_cast(__clz_r)); + __m = (~__storage_type(0) << __result.__ctz_) & (~__storage_type(0) >> (__clz_r - __dn)); + *__result.__seg_ &= ~__m; + *__result.__seg_ |= __b << __result.__ctz_; + __result.__seg_ += (__dn + __result.__ctz_) / __bits_per_word; + __result.__ctz_ = static_cast((__dn + __result.__ctz_) % __bits_per_word); + __n -= __dn; + if (__n > 0) + { + __m = ~__storage_type(0) >> (__bits_per_word - __n); + *__result.__seg_ &= ~__m; + *__result.__seg_ |= __b >> __dn; + __result.__ctz_ = static_cast(__n); + } + } + } + return __result; +} + +template +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 +__bit_iterator<_Cp, false> +copy(__bit_iterator<_Cp, _IsConst> __first, __bit_iterator<_Cp, _IsConst> __last, __bit_iterator<_Cp, false> __result) +{ + if (__first.__ctz_ == __result.__ctz_) + return _VSTD::__copy_aligned(__first, __last, __result); + return _VSTD::__copy_unaligned(__first, __last, __result); +} + +// copy_backward + +template +_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __bit_iterator<_Cp, false> +__copy_backward_aligned(__bit_iterator<_Cp, _IsConst> __first, __bit_iterator<_Cp, _IsConst> __last, + __bit_iterator<_Cp, false> __result) +{ + typedef __bit_iterator<_Cp, _IsConst> _In; + typedef typename _In::difference_type difference_type; + typedef typename _In::__storage_type __storage_type; + const int __bits_per_word = _In::__bits_per_word; + difference_type __n = __last - __first; + if (__n > 0) + { + // do first word + if (__last.__ctz_ != 0) + { + difference_type __dn = _VSTD::min(static_cast(__last.__ctz_), __n); + __n -= __dn; + unsigned __clz = __bits_per_word - __last.__ctz_; + __storage_type __m = (~__storage_type(0) << (__last.__ctz_ - __dn)) & (~__storage_type(0) >> __clz); + __storage_type __b = *__last.__seg_ & __m; + *__result.__seg_ &= ~__m; + *__result.__seg_ |= __b; + __result.__ctz_ = static_cast(((-__dn & (__bits_per_word - 1)) + + __result.__ctz_) % __bits_per_word); + // __last.__ctz_ = 0 + } + // __last.__ctz_ == 0 || __n == 0 + // __result.__ctz_ == 0 || __n == 0 + // do middle words + __storage_type __nw = __n / __bits_per_word; + __result.__seg_ -= __nw; + __last.__seg_ -= __nw; + std::copy_n(std::__to_address(__last.__seg_), __nw, std::__to_address(__result.__seg_)); + __n -= __nw * __bits_per_word; + // do last word + if (__n > 0) + { + __storage_type __m = ~__storage_type(0) << (__bits_per_word - __n); + __storage_type __b = *--__last.__seg_ & __m; + *--__result.__seg_ &= ~__m; + *__result.__seg_ |= __b; + __result.__ctz_ = static_cast(-__n & (__bits_per_word - 1)); + } + } + return __result; +} + +template +_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __bit_iterator<_Cp, false> +__copy_backward_unaligned(__bit_iterator<_Cp, _IsConst> __first, __bit_iterator<_Cp, _IsConst> __last, + __bit_iterator<_Cp, false> __result) +{ + typedef __bit_iterator<_Cp, _IsConst> _In; + typedef typename _In::difference_type difference_type; + typedef typename _In::__storage_type __storage_type; + const int __bits_per_word = _In::__bits_per_word; + difference_type __n = __last - __first; + if (__n > 0) + { + // do first word + if (__last.__ctz_ != 0) + { + difference_type __dn = _VSTD::min(static_cast(__last.__ctz_), __n); + __n -= __dn; + unsigned __clz_l = __bits_per_word - __last.__ctz_; + __storage_type __m = (~__storage_type(0) << (__last.__ctz_ - __dn)) & (~__storage_type(0) >> __clz_l); + __storage_type __b = *__last.__seg_ & __m; + unsigned __clz_r = __bits_per_word - __result.__ctz_; + __storage_type __ddn = _VSTD::min(__dn, static_cast(__result.__ctz_)); + if (__ddn > 0) + { + __m = (~__storage_type(0) << (__result.__ctz_ - __ddn)) & (~__storage_type(0) >> __clz_r); + *__result.__seg_ &= ~__m; + if (__result.__ctz_ > __last.__ctz_) + *__result.__seg_ |= __b << (__result.__ctz_ - __last.__ctz_); + else + *__result.__seg_ |= __b >> (__last.__ctz_ - __result.__ctz_); + __result.__ctz_ = static_cast(((-__ddn & (__bits_per_word - 1)) + + __result.__ctz_) % __bits_per_word); + __dn -= __ddn; + } + if (__dn > 0) + { + // __result.__ctz_ == 0 + --__result.__seg_; + __result.__ctz_ = static_cast(-__dn & (__bits_per_word - 1)); + __m = ~__storage_type(0) << __result.__ctz_; + *__result.__seg_ &= ~__m; + __last.__ctz_ -= __dn + __ddn; + *__result.__seg_ |= __b << (__result.__ctz_ - __last.__ctz_); + } + // __last.__ctz_ = 0 + } + // __last.__ctz_ == 0 || __n == 0 + // __result.__ctz_ != 0 || __n == 0 + // do middle words + unsigned __clz_r = __bits_per_word - __result.__ctz_; + __storage_type __m = ~__storage_type(0) >> __clz_r; + for (; __n >= __bits_per_word; __n -= __bits_per_word) + { + __storage_type __b = *--__last.__seg_; + *__result.__seg_ &= ~__m; + *__result.__seg_ |= __b >> __clz_r; + *--__result.__seg_ &= __m; + *__result.__seg_ |= __b << __result.__ctz_; + } + // do last word + if (__n > 0) + { + __m = ~__storage_type(0) << (__bits_per_word - __n); + __storage_type __b = *--__last.__seg_ & __m; + __clz_r = __bits_per_word - __result.__ctz_; + __storage_type __dn = _VSTD::min(__n, static_cast(__result.__ctz_)); + __m = (~__storage_type(0) << (__result.__ctz_ - __dn)) & (~__storage_type(0) >> __clz_r); + *__result.__seg_ &= ~__m; + *__result.__seg_ |= __b >> (__bits_per_word - __result.__ctz_); + __result.__ctz_ = static_cast(((-__dn & (__bits_per_word - 1)) + + __result.__ctz_) % __bits_per_word); + __n -= __dn; + if (__n > 0) + { + // __result.__ctz_ == 0 + --__result.__seg_; + __result.__ctz_ = static_cast(-__n & (__bits_per_word - 1)); + __m = ~__storage_type(0) << __result.__ctz_; + *__result.__seg_ &= ~__m; + *__result.__seg_ |= __b << (__result.__ctz_ - (__bits_per_word - __n - __dn)); + } + } + } + return __result; +} + +template +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 +__bit_iterator<_Cp, false> +copy_backward(__bit_iterator<_Cp, _IsConst> __first, __bit_iterator<_Cp, _IsConst> __last, __bit_iterator<_Cp, false> __result) +{ + if (__last.__ctz_ == __result.__ctz_) + return _VSTD::__copy_backward_aligned(__first, __last, __result); + return _VSTD::__copy_backward_unaligned(__first, __last, __result); +} + +// move + +template +inline _LIBCPP_INLINE_VISIBILITY +__bit_iterator<_Cp, false> +move(__bit_iterator<_Cp, _IsConst> __first, __bit_iterator<_Cp, _IsConst> __last, __bit_iterator<_Cp, false> __result) +{ + return _VSTD::copy(__first, __last, __result); +} + +// move_backward + +template +inline _LIBCPP_INLINE_VISIBILITY +__bit_iterator<_Cp, false> +move_backward(__bit_iterator<_Cp, _IsConst> __first, __bit_iterator<_Cp, _IsConst> __last, __bit_iterator<_Cp, false> __result) +{ + return _VSTD::copy_backward(__first, __last, __result); +} + +// swap_ranges + +template +_LIBCPP_HIDE_FROM_ABI __bit_iterator<__C2, false> +__swap_ranges_aligned(__bit_iterator<__C1, false> __first, __bit_iterator<__C1, false> __last, + __bit_iterator<__C2, false> __result) +{ + typedef __bit_iterator<__C1, false> _I1; + typedef typename _I1::difference_type difference_type; + typedef typename _I1::__storage_type __storage_type; + const int __bits_per_word = _I1::__bits_per_word; + difference_type __n = __last - __first; + if (__n > 0) + { + // do first word + if (__first.__ctz_ != 0) + { + unsigned __clz = __bits_per_word - __first.__ctz_; + difference_type __dn = _VSTD::min(static_cast(__clz), __n); + __n -= __dn; + __storage_type __m = (~__storage_type(0) << __first.__ctz_) & (~__storage_type(0) >> (__clz - __dn)); + __storage_type __b1 = *__first.__seg_ & __m; + *__first.__seg_ &= ~__m; + __storage_type __b2 = *__result.__seg_ & __m; + *__result.__seg_ &= ~__m; + *__result.__seg_ |= __b1; + *__first.__seg_ |= __b2; + __result.__seg_ += (__dn + __result.__ctz_) / __bits_per_word; + __result.__ctz_ = static_cast((__dn + __result.__ctz_) % __bits_per_word); + ++__first.__seg_; + // __first.__ctz_ = 0; + } + // __first.__ctz_ == 0; + // do middle words + for (; __n >= __bits_per_word; __n -= __bits_per_word, ++__first.__seg_, ++__result.__seg_) + swap(*__first.__seg_, *__result.__seg_); + // do last word + if (__n > 0) + { + __storage_type __m = ~__storage_type(0) >> (__bits_per_word - __n); + __storage_type __b1 = *__first.__seg_ & __m; + *__first.__seg_ &= ~__m; + __storage_type __b2 = *__result.__seg_ & __m; + *__result.__seg_ &= ~__m; + *__result.__seg_ |= __b1; + *__first.__seg_ |= __b2; + __result.__ctz_ = static_cast(__n); + } + } + return __result; +} + +template +_LIBCPP_HIDE_FROM_ABI __bit_iterator<__C2, false> +__swap_ranges_unaligned(__bit_iterator<__C1, false> __first, __bit_iterator<__C1, false> __last, + __bit_iterator<__C2, false> __result) +{ + typedef __bit_iterator<__C1, false> _I1; + typedef typename _I1::difference_type difference_type; + typedef typename _I1::__storage_type __storage_type; + const int __bits_per_word = _I1::__bits_per_word; + difference_type __n = __last - __first; + if (__n > 0) + { + // do first word + if (__first.__ctz_ != 0) + { + unsigned __clz_f = __bits_per_word - __first.__ctz_; + difference_type __dn = _VSTD::min(static_cast(__clz_f), __n); + __n -= __dn; + __storage_type __m = (~__storage_type(0) << __first.__ctz_) & (~__storage_type(0) >> (__clz_f - __dn)); + __storage_type __b1 = *__first.__seg_ & __m; + *__first.__seg_ &= ~__m; + unsigned __clz_r = __bits_per_word - __result.__ctz_; + __storage_type __ddn = _VSTD::min<__storage_type>(__dn, __clz_r); + __m = (~__storage_type(0) << __result.__ctz_) & (~__storage_type(0) >> (__clz_r - __ddn)); + __storage_type __b2 = *__result.__seg_ & __m; + *__result.__seg_ &= ~__m; + if (__result.__ctz_ > __first.__ctz_) + { + unsigned __s = __result.__ctz_ - __first.__ctz_; + *__result.__seg_ |= __b1 << __s; + *__first.__seg_ |= __b2 >> __s; + } + else + { + unsigned __s = __first.__ctz_ - __result.__ctz_; + *__result.__seg_ |= __b1 >> __s; + *__first.__seg_ |= __b2 << __s; + } + __result.__seg_ += (__ddn + __result.__ctz_) / __bits_per_word; + __result.__ctz_ = static_cast((__ddn + __result.__ctz_) % __bits_per_word); + __dn -= __ddn; + if (__dn > 0) + { + __m = ~__storage_type(0) >> (__bits_per_word - __dn); + __b2 = *__result.__seg_ & __m; + *__result.__seg_ &= ~__m; + unsigned __s = __first.__ctz_ + __ddn; + *__result.__seg_ |= __b1 >> __s; + *__first.__seg_ |= __b2 << __s; + __result.__ctz_ = static_cast(__dn); + } + ++__first.__seg_; + // __first.__ctz_ = 0; + } + // __first.__ctz_ == 0; + // do middle words + __storage_type __m = ~__storage_type(0) << __result.__ctz_; + unsigned __clz_r = __bits_per_word - __result.__ctz_; + for (; __n >= __bits_per_word; __n -= __bits_per_word, ++__first.__seg_) + { + __storage_type __b1 = *__first.__seg_; + __storage_type __b2 = *__result.__seg_ & __m; + *__result.__seg_ &= ~__m; + *__result.__seg_ |= __b1 << __result.__ctz_; + *__first.__seg_ = __b2 >> __result.__ctz_; + ++__result.__seg_; + __b2 = *__result.__seg_ & ~__m; + *__result.__seg_ &= __m; + *__result.__seg_ |= __b1 >> __clz_r; + *__first.__seg_ |= __b2 << __clz_r; + } + // do last word + if (__n > 0) + { + __m = ~__storage_type(0) >> (__bits_per_word - __n); + __storage_type __b1 = *__first.__seg_ & __m; + *__first.__seg_ &= ~__m; + __storage_type __dn = _VSTD::min<__storage_type>(__n, __clz_r); + __m = (~__storage_type(0) << __result.__ctz_) & (~__storage_type(0) >> (__clz_r - __dn)); + __storage_type __b2 = *__result.__seg_ & __m; + *__result.__seg_ &= ~__m; + *__result.__seg_ |= __b1 << __result.__ctz_; + *__first.__seg_ |= __b2 >> __result.__ctz_; + __result.__seg_ += (__dn + __result.__ctz_) / __bits_per_word; + __result.__ctz_ = static_cast((__dn + __result.__ctz_) % __bits_per_word); + __n -= __dn; + if (__n > 0) + { + __m = ~__storage_type(0) >> (__bits_per_word - __n); + __b2 = *__result.__seg_ & __m; + *__result.__seg_ &= ~__m; + *__result.__seg_ |= __b1 >> __dn; + *__first.__seg_ |= __b2 << __dn; + __result.__ctz_ = static_cast(__n); + } + } + } + return __result; +} + +template +inline _LIBCPP_INLINE_VISIBILITY +__bit_iterator<__C2, false> +swap_ranges(__bit_iterator<__C1, false> __first1, __bit_iterator<__C1, false> __last1, + __bit_iterator<__C2, false> __first2) +{ + if (__first1.__ctz_ == __first2.__ctz_) + return _VSTD::__swap_ranges_aligned(__first1, __last1, __first2); + return _VSTD::__swap_ranges_unaligned(__first1, __last1, __first2); +} + +// rotate + +template +struct __bit_array +{ + typedef typename _Cp::difference_type difference_type; + typedef typename _Cp::__storage_type __storage_type; + typedef typename _Cp::__storage_pointer __storage_pointer; + typedef typename _Cp::iterator iterator; + static const unsigned __bits_per_word = _Cp::__bits_per_word; + static const unsigned _Np = 4; + + difference_type __size_; + __storage_type __word_[_Np]; + + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 static difference_type capacity() + {return static_cast(_Np * __bits_per_word);} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 explicit __bit_array(difference_type __s) : __size_(__s) { + if (__libcpp_is_constant_evaluated()) { + for (size_t __i = 0; __i != __bit_array<_Cp>::_Np; ++__i) + std::__construct_at(__word_ + __i, 0); + } + } + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 iterator begin() + { + return iterator(pointer_traits<__storage_pointer>::pointer_to(__word_[0]), 0); + } + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 iterator end() + { + return iterator(pointer_traits<__storage_pointer>::pointer_to(__word_[0]) + __size_ / __bits_per_word, + static_cast(__size_ % __bits_per_word)); + } +}; + +template +_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __bit_iterator<_Cp, false> +rotate(__bit_iterator<_Cp, false> __first, __bit_iterator<_Cp, false> __middle, __bit_iterator<_Cp, false> __last) +{ + typedef __bit_iterator<_Cp, false> _I1; + typedef typename _I1::difference_type difference_type; + difference_type __d1 = __middle - __first; + difference_type __d2 = __last - __middle; + _I1 __r = __first + __d2; + while (__d1 != 0 && __d2 != 0) + { + if (__d1 <= __d2) + { + if (__d1 <= __bit_array<_Cp>::capacity()) + { + __bit_array<_Cp> __b(__d1); + _VSTD::copy(__first, __middle, __b.begin()); + _VSTD::copy(__b.begin(), __b.end(), _VSTD::copy(__middle, __last, __first)); + break; + } + else + { + __bit_iterator<_Cp, false> __mp = _VSTD::swap_ranges(__first, __middle, __middle); + __first = __middle; + __middle = __mp; + __d2 -= __d1; + } + } + else + { + if (__d2 <= __bit_array<_Cp>::capacity()) + { + __bit_array<_Cp> __b(__d2); + _VSTD::copy(__middle, __last, __b.begin()); + _VSTD::copy_backward(__b.begin(), __b.end(), _VSTD::copy_backward(__first, __middle, __last)); + break; + } + else + { + __bit_iterator<_Cp, false> __mp = __first + __d2; + _VSTD::swap_ranges(__first, __mp, __middle); + __first = __mp; + __d1 -= __d2; + } + } + } + return __r; +} + +// equal + +template +_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool +__equal_unaligned(__bit_iterator<_Cp, _IC1> __first1, __bit_iterator<_Cp, _IC1> __last1, + __bit_iterator<_Cp, _IC2> __first2) +{ + typedef __bit_iterator<_Cp, _IC1> _It; + typedef typename _It::difference_type difference_type; + typedef typename _It::__storage_type __storage_type; + const int __bits_per_word = _It::__bits_per_word; + difference_type __n = __last1 - __first1; + if (__n > 0) + { + // do first word + if (__first1.__ctz_ != 0) + { + unsigned __clz_f = __bits_per_word - __first1.__ctz_; + difference_type __dn = _VSTD::min(static_cast(__clz_f), __n); + __n -= __dn; + __storage_type __m = (~__storage_type(0) << __first1.__ctz_) & (~__storage_type(0) >> (__clz_f - __dn)); + __storage_type __b = *__first1.__seg_ & __m; + unsigned __clz_r = __bits_per_word - __first2.__ctz_; + __storage_type __ddn = _VSTD::min<__storage_type>(__dn, __clz_r); + __m = (~__storage_type(0) << __first2.__ctz_) & (~__storage_type(0) >> (__clz_r - __ddn)); + if (__first2.__ctz_ > __first1.__ctz_) + { + if ((*__first2.__seg_ & __m) != (__b << (__first2.__ctz_ - __first1.__ctz_))) + return false; + } + else + { + if ((*__first2.__seg_ & __m) != (__b >> (__first1.__ctz_ - __first2.__ctz_))) + return false; + } + __first2.__seg_ += (__ddn + __first2.__ctz_) / __bits_per_word; + __first2.__ctz_ = static_cast((__ddn + __first2.__ctz_) % __bits_per_word); + __dn -= __ddn; + if (__dn > 0) + { + __m = ~__storage_type(0) >> (__bits_per_word - __dn); + if ((*__first2.__seg_ & __m) != (__b >> (__first1.__ctz_ + __ddn))) + return false; + __first2.__ctz_ = static_cast(__dn); + } + ++__first1.__seg_; + // __first1.__ctz_ = 0; + } + // __first1.__ctz_ == 0; + // do middle words + unsigned __clz_r = __bits_per_word - __first2.__ctz_; + __storage_type __m = ~__storage_type(0) << __first2.__ctz_; + for (; __n >= __bits_per_word; __n -= __bits_per_word, ++__first1.__seg_) + { + __storage_type __b = *__first1.__seg_; + if ((*__first2.__seg_ & __m) != (__b << __first2.__ctz_)) + return false; + ++__first2.__seg_; + if ((*__first2.__seg_ & ~__m) != (__b >> __clz_r)) + return false; + } + // do last word + if (__n > 0) + { + __m = ~__storage_type(0) >> (__bits_per_word - __n); + __storage_type __b = *__first1.__seg_ & __m; + __storage_type __dn = _VSTD::min(__n, static_cast(__clz_r)); + __m = (~__storage_type(0) << __first2.__ctz_) & (~__storage_type(0) >> (__clz_r - __dn)); + if ((*__first2.__seg_ & __m) != (__b << __first2.__ctz_)) + return false; + __first2.__seg_ += (__dn + __first2.__ctz_) / __bits_per_word; + __first2.__ctz_ = static_cast((__dn + __first2.__ctz_) % __bits_per_word); + __n -= __dn; + if (__n > 0) + { + __m = ~__storage_type(0) >> (__bits_per_word - __n); + if ((*__first2.__seg_ & __m) != (__b >> __dn)) + return false; + } + } + } + return true; +} + +template +_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool +__equal_aligned(__bit_iterator<_Cp, _IC1> __first1, __bit_iterator<_Cp, _IC1> __last1, + __bit_iterator<_Cp, _IC2> __first2) +{ + typedef __bit_iterator<_Cp, _IC1> _It; + typedef typename _It::difference_type difference_type; + typedef typename _It::__storage_type __storage_type; + const int __bits_per_word = _It::__bits_per_word; + difference_type __n = __last1 - __first1; + if (__n > 0) + { + // do first word + if (__first1.__ctz_ != 0) + { + unsigned __clz = __bits_per_word - __first1.__ctz_; + difference_type __dn = _VSTD::min(static_cast(__clz), __n); + __n -= __dn; + __storage_type __m = (~__storage_type(0) << __first1.__ctz_) & (~__storage_type(0) >> (__clz - __dn)); + if ((*__first2.__seg_ & __m) != (*__first1.__seg_ & __m)) + return false; + ++__first2.__seg_; + ++__first1.__seg_; + // __first1.__ctz_ = 0; + // __first2.__ctz_ = 0; + } + // __first1.__ctz_ == 0; + // __first2.__ctz_ == 0; + // do middle words + for (; __n >= __bits_per_word; __n -= __bits_per_word, ++__first1.__seg_, ++__first2.__seg_) + if (*__first2.__seg_ != *__first1.__seg_) + return false; + // do last word + if (__n > 0) + { + __storage_type __m = ~__storage_type(0) >> (__bits_per_word - __n); + if ((*__first2.__seg_ & __m) != (*__first1.__seg_ & __m)) + return false; + } + } + return true; +} + +template +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 +bool +equal(__bit_iterator<_Cp, _IC1> __first1, __bit_iterator<_Cp, _IC1> __last1, __bit_iterator<_Cp, _IC2> __first2) +{ + if (__first1.__ctz_ == __first2.__ctz_) + return _VSTD::__equal_aligned(__first1, __last1, __first2); + return _VSTD::__equal_unaligned(__first1, __last1, __first2); +} + +template +class __bit_iterator +{ +public: + typedef typename _Cp::difference_type difference_type; + typedef bool value_type; + typedef __bit_iterator pointer; +#ifndef _LIBCPP_ABI_BITSET_VECTOR_BOOL_CONST_SUBSCRIPT_RETURN_BOOL + typedef __conditional_t<_IsConst, __bit_const_reference<_Cp>, __bit_reference<_Cp> > reference; +#else + using reference = __conditional_t<_IsConst, bool, __bit_reference<_Cp> >; +#endif + typedef random_access_iterator_tag iterator_category; + +private: + typedef typename _Cp::__storage_type __storage_type; + typedef __conditional_t<_IsConst, typename _Cp::__const_storage_pointer, typename _Cp::__storage_pointer> + __storage_pointer; + static const unsigned __bits_per_word = _Cp::__bits_per_word; + + __storage_pointer __seg_; + unsigned __ctz_; + +public: + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 __bit_iterator() _NOEXCEPT +#if _LIBCPP_STD_VER > 11 + : __seg_(nullptr), __ctz_(0) +#endif + {} + + // When _IsConst=false, this is the copy constructor. + // It is non-trivial. Making it trivial would break ABI. + // When _IsConst=true, this is a converting constructor; + // the copy and move constructors are implicitly generated + // and trivial. + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 + __bit_iterator(const __bit_iterator<_Cp, false>& __it) _NOEXCEPT + : __seg_(__it.__seg_), __ctz_(__it.__ctz_) {} + + // When _IsConst=false, we have a user-provided copy constructor, + // so we must also provide a copy assignment operator because + // the implicit generation of a defaulted one is deprecated. + // When _IsConst=true, the assignment operators are + // implicitly generated and trivial. + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 + __bit_iterator& operator=(const _If<_IsConst, struct __private_nat, __bit_iterator>& __it) { + __seg_ = __it.__seg_; + __ctz_ = __it.__ctz_; + return *this; + } + + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 reference operator*() const _NOEXCEPT { + return __conditional_t<_IsConst, __bit_const_reference<_Cp>, __bit_reference<_Cp> >( + __seg_, __storage_type(1) << __ctz_); + } + + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 __bit_iterator& operator++() + { + if (__ctz_ != __bits_per_word-1) + ++__ctz_; + else + { + __ctz_ = 0; + ++__seg_; + } + return *this; + } + + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 __bit_iterator operator++(int) + { + __bit_iterator __tmp = *this; + ++(*this); + return __tmp; + } + + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 __bit_iterator& operator--() + { + if (__ctz_ != 0) + --__ctz_; + else + { + __ctz_ = __bits_per_word - 1; + --__seg_; + } + return *this; + } + + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 __bit_iterator operator--(int) + { + __bit_iterator __tmp = *this; + --(*this); + return __tmp; + } + + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 __bit_iterator& operator+=(difference_type __n) + { + if (__n >= 0) + __seg_ += (__n + __ctz_) / __bits_per_word; + else + __seg_ += static_cast(__n - __bits_per_word + __ctz_ + 1) + / static_cast(__bits_per_word); + __n &= (__bits_per_word - 1); + __ctz_ = static_cast((__n + __ctz_) % __bits_per_word); + return *this; + } + + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 __bit_iterator& operator-=(difference_type __n) + { + return *this += -__n; + } + + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 __bit_iterator operator+(difference_type __n) const + { + __bit_iterator __t(*this); + __t += __n; + return __t; + } + + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 __bit_iterator operator-(difference_type __n) const + { + __bit_iterator __t(*this); + __t -= __n; + return __t; + } + + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 + friend __bit_iterator operator+(difference_type __n, const __bit_iterator& __it) {return __it + __n;} + + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 + friend difference_type operator-(const __bit_iterator& __x, const __bit_iterator& __y) + {return (__x.__seg_ - __y.__seg_) * __bits_per_word + __x.__ctz_ - __y.__ctz_;} + + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 reference operator[](difference_type __n) const {return *(*this + __n);} + + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 friend bool operator==(const __bit_iterator& __x, const __bit_iterator& __y) + {return __x.__seg_ == __y.__seg_ && __x.__ctz_ == __y.__ctz_;} + + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 friend bool operator!=(const __bit_iterator& __x, const __bit_iterator& __y) + {return !(__x == __y);} + + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 friend bool operator<(const __bit_iterator& __x, const __bit_iterator& __y) + {return __x.__seg_ < __y.__seg_ || (__x.__seg_ == __y.__seg_ && __x.__ctz_ < __y.__ctz_);} + + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 friend bool operator>(const __bit_iterator& __x, const __bit_iterator& __y) + {return __y < __x;} + + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 friend bool operator<=(const __bit_iterator& __x, const __bit_iterator& __y) + {return !(__y < __x);} + + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 friend bool operator>=(const __bit_iterator& __x, const __bit_iterator& __y) + {return !(__x < __y);} + +private: + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 + explicit __bit_iterator(__storage_pointer __s, unsigned __ctz) _NOEXCEPT + : __seg_(__s), __ctz_(__ctz) {} + + friend typename _Cp::__self; + + friend class __bit_reference<_Cp>; + friend class __bit_const_reference<_Cp>; + friend class __bit_iterator<_Cp, true>; + template friend struct __bit_array; + template + _LIBCPP_CONSTEXPR_SINCE_CXX20 + friend void __fill_n_false(__bit_iterator<_Dp, false> __first, typename _Dp::size_type __n); + + template + _LIBCPP_CONSTEXPR_SINCE_CXX20 + friend void __fill_n_true(__bit_iterator<_Dp, false> __first, typename _Dp::size_type __n); + + template + _LIBCPP_CONSTEXPR_SINCE_CXX20 + friend __bit_iterator<_Dp, false> __copy_aligned(__bit_iterator<_Dp, _IC> __first, + __bit_iterator<_Dp, _IC> __last, + __bit_iterator<_Dp, false> __result); + template + _LIBCPP_CONSTEXPR_SINCE_CXX20 + friend __bit_iterator<_Dp, false> __copy_unaligned(__bit_iterator<_Dp, _IC> __first, + __bit_iterator<_Dp, _IC> __last, + __bit_iterator<_Dp, false> __result); + template + _LIBCPP_CONSTEXPR_SINCE_CXX20 + friend __bit_iterator<_Dp, false> copy(__bit_iterator<_Dp, _IC> __first, + __bit_iterator<_Dp, _IC> __last, + __bit_iterator<_Dp, false> __result); + template + _LIBCPP_CONSTEXPR_SINCE_CXX20 + friend __bit_iterator<_Dp, false> __copy_backward_aligned(__bit_iterator<_Dp, _IC> __first, + __bit_iterator<_Dp, _IC> __last, + __bit_iterator<_Dp, false> __result); + template + _LIBCPP_CONSTEXPR_SINCE_CXX20 + friend __bit_iterator<_Dp, false> __copy_backward_unaligned(__bit_iterator<_Dp, _IC> __first, + __bit_iterator<_Dp, _IC> __last, + __bit_iterator<_Dp, false> __result); + template + _LIBCPP_CONSTEXPR_SINCE_CXX20 + friend __bit_iterator<_Dp, false> copy_backward(__bit_iterator<_Dp, _IC> __first, + __bit_iterator<_Dp, _IC> __last, + __bit_iterator<_Dp, false> __result); + template friend __bit_iterator<__C2, false> __swap_ranges_aligned(__bit_iterator<__C1, false>, + __bit_iterator<__C1, false>, + __bit_iterator<__C2, false>); + template friend __bit_iterator<__C2, false> __swap_ranges_unaligned(__bit_iterator<__C1, false>, + __bit_iterator<__C1, false>, + __bit_iterator<__C2, false>); + template friend __bit_iterator<__C2, false> swap_ranges(__bit_iterator<__C1, false>, + __bit_iterator<__C1, false>, + __bit_iterator<__C2, false>); + template + _LIBCPP_CONSTEXPR_SINCE_CXX20 + friend __bit_iterator<_Dp, false> rotate(__bit_iterator<_Dp, false>, + __bit_iterator<_Dp, false>, + __bit_iterator<_Dp, false>); + template + _LIBCPP_CONSTEXPR_SINCE_CXX20 + friend bool __equal_aligned(__bit_iterator<_Dp, _IC1>, + __bit_iterator<_Dp, _IC1>, + __bit_iterator<_Dp, _IC2>); + template + _LIBCPP_CONSTEXPR_SINCE_CXX20 + friend bool __equal_unaligned(__bit_iterator<_Dp, _IC1>, + __bit_iterator<_Dp, _IC1>, + __bit_iterator<_Dp, _IC2>); + template + _LIBCPP_CONSTEXPR_SINCE_CXX20 + friend bool equal(__bit_iterator<_Dp, _IC1>, + __bit_iterator<_Dp, _IC1>, + __bit_iterator<_Dp, _IC2>); + template + _LIBCPP_CONSTEXPR_SINCE_CXX20 + friend __bit_iterator<_Dp, _IC> __find_bool_true(__bit_iterator<_Dp, _IC>, typename _Dp::size_type); + template + _LIBCPP_CONSTEXPR_SINCE_CXX20 + friend __bit_iterator<_Dp, _IC> __find_bool_false(__bit_iterator<_Dp, _IC>, typename _Dp::size_type); + template friend typename __bit_iterator<_Dp, _IC>::difference_type + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 + __count_bool_true(__bit_iterator<_Dp, _IC>, typename _Dp::size_type); + template friend typename __bit_iterator<_Dp, _IC>::difference_type + __count_bool_false(__bit_iterator<_Dp, _IC>, typename _Dp::size_type); +}; + +_LIBCPP_END_NAMESPACE_STD + +_LIBCPP_POP_MACROS + +#endif // _LIBCPP___BIT_REFERENCE diff --git a/app/src/main/cpp/libcxx/include/__bsd_locale_defaults.h b/app/src/main/cpp/libcxx/include/__bsd_locale_defaults.h new file mode 100644 index 0000000..4d99048 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__bsd_locale_defaults.h @@ -0,0 +1,36 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// The BSDs have lots of *_l functions. We don't want to define those symbols +// on other platforms though, for fear of conflicts with user code. So here, +// we will define the mapping from an internal macro to the real BSD symbol. +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___BSD_LOCALE_DEFAULTS_H +#define _LIBCPP___BSD_LOCALE_DEFAULTS_H + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#define __libcpp_mb_cur_max_l(loc) MB_CUR_MAX_L(loc) +#define __libcpp_btowc_l(ch, loc) btowc_l(ch, loc) +#define __libcpp_wctob_l(wch, loc) wctob_l(wch, loc) +#define __libcpp_wcsnrtombs_l(dst, src, nwc, len, ps, loc) wcsnrtombs_l(dst, src, nwc, len, ps, loc) +#define __libcpp_wcrtomb_l(src, wc, ps, loc) wcrtomb_l(src, wc, ps, loc) +#define __libcpp_mbsnrtowcs_l(dst, src, nms, len, ps, loc) mbsnrtowcs_l(dst, src, nms, len, ps, loc) +#define __libcpp_mbrtowc_l(pwc, s, n, ps, l) mbrtowc_l(pwc, s, n, ps, l) +#define __libcpp_mbtowc_l(pwc, pmb, max, l) mbtowc_l(pwc, pmb, max, l) +#define __libcpp_mbrlen_l(s, n, ps, l) mbrlen_l(s, n, ps, l) +#define __libcpp_localeconv_l(l) localeconv_l(l) +#define __libcpp_mbsrtowcs_l(dest, src, len, ps, l) mbsrtowcs_l(dest, src, len, ps, l) +#define __libcpp_snprintf_l(...) snprintf_l(__VA_ARGS__) +#define __libcpp_asprintf_l(...) asprintf_l(__VA_ARGS__) +#define __libcpp_sscanf_l(...) sscanf_l(__VA_ARGS__) + +#endif // _LIBCPP___BSD_LOCALE_DEFAULTS_H diff --git a/app/src/main/cpp/libcxx/include/__bsd_locale_fallbacks.h b/app/src/main/cpp/libcxx/include/__bsd_locale_fallbacks.h new file mode 100644 index 0000000..9abd7e7 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__bsd_locale_fallbacks.h @@ -0,0 +1,142 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// The BSDs have lots of *_l functions. This file provides reimplementations +// of those functions for non-BSD platforms. +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___BSD_LOCALE_FALLBACKS_H +#define _LIBCPP___BSD_LOCALE_FALLBACKS_H + +#include +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +inline _LIBCPP_INLINE_VISIBILITY +decltype(MB_CUR_MAX) __libcpp_mb_cur_max_l(locale_t __l) +{ + __libcpp_locale_guard __current(__l); + return MB_CUR_MAX; +} + +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +inline _LIBCPP_INLINE_VISIBILITY +wint_t __libcpp_btowc_l(int __c, locale_t __l) +{ + __libcpp_locale_guard __current(__l); + return btowc(__c); +} + +inline _LIBCPP_INLINE_VISIBILITY +int __libcpp_wctob_l(wint_t __c, locale_t __l) +{ + __libcpp_locale_guard __current(__l); + return wctob(__c); +} + +inline _LIBCPP_INLINE_VISIBILITY +size_t __libcpp_wcsnrtombs_l(char *__dest, const wchar_t **__src, size_t __nwc, + size_t __len, mbstate_t *__ps, locale_t __l) +{ + __libcpp_locale_guard __current(__l); + return wcsnrtombs(__dest, __src, __nwc, __len, __ps); +} + +inline _LIBCPP_INLINE_VISIBILITY +size_t __libcpp_wcrtomb_l(char *__s, wchar_t __wc, mbstate_t *__ps, locale_t __l) +{ + __libcpp_locale_guard __current(__l); + return wcrtomb(__s, __wc, __ps); +} + +inline _LIBCPP_INLINE_VISIBILITY +size_t __libcpp_mbsnrtowcs_l(wchar_t * __dest, const char **__src, size_t __nms, + size_t __len, mbstate_t *__ps, locale_t __l) +{ + __libcpp_locale_guard __current(__l); + return mbsnrtowcs(__dest, __src, __nms, __len, __ps); +} + +inline _LIBCPP_INLINE_VISIBILITY +size_t __libcpp_mbrtowc_l(wchar_t *__pwc, const char *__s, size_t __n, + mbstate_t *__ps, locale_t __l) +{ + __libcpp_locale_guard __current(__l); + return mbrtowc(__pwc, __s, __n, __ps); +} + +inline _LIBCPP_INLINE_VISIBILITY +int __libcpp_mbtowc_l(wchar_t *__pwc, const char *__pmb, size_t __max, locale_t __l) +{ + __libcpp_locale_guard __current(__l); + return mbtowc(__pwc, __pmb, __max); +} + +inline _LIBCPP_INLINE_VISIBILITY +size_t __libcpp_mbrlen_l(const char *__s, size_t __n, mbstate_t *__ps, locale_t __l) +{ + __libcpp_locale_guard __current(__l); + return mbrlen(__s, __n, __ps); +} +#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS + +inline _LIBCPP_INLINE_VISIBILITY +lconv *__libcpp_localeconv_l(locale_t __l) +{ + __libcpp_locale_guard __current(__l); + return localeconv(); +} + +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +inline _LIBCPP_INLINE_VISIBILITY +size_t __libcpp_mbsrtowcs_l(wchar_t *__dest, const char **__src, size_t __len, + mbstate_t *__ps, locale_t __l) +{ + __libcpp_locale_guard __current(__l); + return mbsrtowcs(__dest, __src, __len, __ps); +} +#endif + +inline _LIBCPP_ATTRIBUTE_FORMAT(__printf__, 4, 5) +int __libcpp_snprintf_l(char *__s, size_t __n, locale_t __l, const char *__format, ...) { + va_list __va; + va_start(__va, __format); + __libcpp_locale_guard __current(__l); + int __res = vsnprintf(__s, __n, __format, __va); + va_end(__va); + return __res; +} + +inline _LIBCPP_ATTRIBUTE_FORMAT(__printf__, 3, 4) +int __libcpp_asprintf_l(char **__s, locale_t __l, const char *__format, ...) { + va_list __va; + va_start(__va, __format); + __libcpp_locale_guard __current(__l); + int __res = vasprintf(__s, __format, __va); + va_end(__va); + return __res; +} + +inline _LIBCPP_ATTRIBUTE_FORMAT(__scanf__, 3, 4) +int __libcpp_sscanf_l(const char *__s, locale_t __l, const char *__format, ...) { + va_list __va; + va_start(__va, __format); + __libcpp_locale_guard __current(__l); + int __res = vsscanf(__s, __format, __va); + va_end(__va); + return __res; +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___BSD_LOCALE_FALLBACKS_H diff --git a/app/src/main/cpp/libcxx/include/__charconv/chars_format.h b/app/src/main/cpp/libcxx/include/__charconv/chars_format.h new file mode 100644 index 0000000..695bd87 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__charconv/chars_format.h @@ -0,0 +1,77 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___CHARCONV_CHARS_FORMAT_H +#define _LIBCPP___CHARCONV_CHARS_FORMAT_H + +#include <__config> +#include <__utility/to_underlying.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 14 + +enum class _LIBCPP_ENUM_VIS chars_format +{ + scientific = 0x1, + fixed = 0x2, + hex = 0x4, + general = fixed | scientific +}; + +inline _LIBCPP_INLINE_VISIBILITY constexpr chars_format +operator~(chars_format __x) { + return chars_format(~_VSTD::__to_underlying(__x)); +} + +inline _LIBCPP_INLINE_VISIBILITY constexpr chars_format +operator&(chars_format __x, chars_format __y) { + return chars_format(_VSTD::__to_underlying(__x) & + _VSTD::__to_underlying(__y)); +} + +inline _LIBCPP_INLINE_VISIBILITY constexpr chars_format +operator|(chars_format __x, chars_format __y) { + return chars_format(_VSTD::__to_underlying(__x) | + _VSTD::__to_underlying(__y)); +} + +inline _LIBCPP_INLINE_VISIBILITY constexpr chars_format +operator^(chars_format __x, chars_format __y) { + return chars_format(_VSTD::__to_underlying(__x) ^ + _VSTD::__to_underlying(__y)); +} + +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 chars_format& +operator&=(chars_format& __x, chars_format __y) { + __x = __x & __y; + return __x; +} + +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 chars_format& +operator|=(chars_format& __x, chars_format __y) { + __x = __x | __y; + return __x; +} + +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 chars_format& +operator^=(chars_format& __x, chars_format __y) { + __x = __x ^ __y; + return __x; +} + +#endif // _LIBCPP_STD_VER > 14 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___CHARCONV_CHARS_FORMAT_H diff --git a/app/src/main/cpp/libcxx/include/__charconv/from_chars_result.h b/app/src/main/cpp/libcxx/include/__charconv/from_chars_result.h new file mode 100644 index 0000000..05ffe14 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__charconv/from_chars_result.h @@ -0,0 +1,37 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___CHARCONV_FROM_CHARS_RESULT_H +#define _LIBCPP___CHARCONV_FROM_CHARS_RESULT_H + +#include <__config> +#include <__errc> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 14 + +struct _LIBCPP_TYPE_VIS from_chars_result +{ + const char* ptr; + errc ec; +# if _LIBCPP_STD_VER > 17 + _LIBCPP_HIDE_FROM_ABI friend bool operator==(const from_chars_result&, const from_chars_result&) = default; +# endif +}; + +#endif // _LIBCPP_STD_VER > 14 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___CHARCONV_FROM_CHARS_RESULT_H diff --git a/app/src/main/cpp/libcxx/include/__charconv/tables.h b/app/src/main/cpp/libcxx/include/__charconv/tables.h new file mode 100644 index 0000000..9b82440 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__charconv/tables.h @@ -0,0 +1,154 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___CHARCONV_TABLES +#define _LIBCPP___CHARCONV_TABLES + +#include <__config> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 14 + +namespace __itoa { + +inline constexpr char __base_2_lut[64] = { + '0', '0', '0', '0', '0', '0', '0', '1', '0', '0', '1', '0', '0', '0', '1', '1', '0', '1', '0', '0', '0', '1', + '0', '1', '0', '1', '1', '0', '0', '1', '1', '1', '1', '0', '0', '0', '1', '0', '0', '1', '1', '0', '1', '0', + '1', '0', '1', '1', '1', '1', '0', '0', '1', '1', '0', '1', '1', '1', '1', '0', '1', '1', '1', '1'}; + +inline constexpr char __base_8_lut[128] = { + '0', '0', '0', '1', '0', '2', '0', '3', '0', '4', '0', '5', '0', '6', '0', '7', '1', '0', '1', '1', '1', '2', + '1', '3', '1', '4', '1', '5', '1', '6', '1', '7', '2', '0', '2', '1', '2', '2', '2', '3', '2', '4', '2', '5', + '2', '6', '2', '7', '3', '0', '3', '1', '3', '2', '3', '3', '3', '4', '3', '5', '3', '6', '3', '7', '4', '0', + '4', '1', '4', '2', '4', '3', '4', '4', '4', '5', '4', '6', '4', '7', '5', '0', '5', '1', '5', '2', '5', '3', + '5', '4', '5', '5', '5', '6', '5', '7', '6', '0', '6', '1', '6', '2', '6', '3', '6', '4', '6', '5', '6', '6', + '6', '7', '7', '0', '7', '1', '7', '2', '7', '3', '7', '4', '7', '5', '7', '6', '7', '7'}; + +inline constexpr char __base_16_lut[512] = { + '0', '0', '0', '1', '0', '2', '0', '3', '0', '4', '0', '5', '0', '6', '0', '7', '0', '8', '0', '9', '0', 'a', '0', + 'b', '0', 'c', '0', 'd', '0', 'e', '0', 'f', '1', '0', '1', '1', '1', '2', '1', '3', '1', '4', '1', '5', '1', '6', + '1', '7', '1', '8', '1', '9', '1', 'a', '1', 'b', '1', 'c', '1', 'd', '1', 'e', '1', 'f', '2', '0', '2', '1', '2', + '2', '2', '3', '2', '4', '2', '5', '2', '6', '2', '7', '2', '8', '2', '9', '2', 'a', '2', 'b', '2', 'c', '2', 'd', + '2', 'e', '2', 'f', '3', '0', '3', '1', '3', '2', '3', '3', '3', '4', '3', '5', '3', '6', '3', '7', '3', '8', '3', + '9', '3', 'a', '3', 'b', '3', 'c', '3', 'd', '3', 'e', '3', 'f', '4', '0', '4', '1', '4', '2', '4', '3', '4', '4', + '4', '5', '4', '6', '4', '7', '4', '8', '4', '9', '4', 'a', '4', 'b', '4', 'c', '4', 'd', '4', 'e', '4', 'f', '5', + '0', '5', '1', '5', '2', '5', '3', '5', '4', '5', '5', '5', '6', '5', '7', '5', '8', '5', '9', '5', 'a', '5', 'b', + '5', 'c', '5', 'd', '5', 'e', '5', 'f', '6', '0', '6', '1', '6', '2', '6', '3', '6', '4', '6', '5', '6', '6', '6', + '7', '6', '8', '6', '9', '6', 'a', '6', 'b', '6', 'c', '6', 'd', '6', 'e', '6', 'f', '7', '0', '7', '1', '7', '2', + '7', '3', '7', '4', '7', '5', '7', '6', '7', '7', '7', '8', '7', '9', '7', 'a', '7', 'b', '7', 'c', '7', 'd', '7', + 'e', '7', 'f', '8', '0', '8', '1', '8', '2', '8', '3', '8', '4', '8', '5', '8', '6', '8', '7', '8', '8', '8', '9', + '8', 'a', '8', 'b', '8', 'c', '8', 'd', '8', 'e', '8', 'f', '9', '0', '9', '1', '9', '2', '9', '3', '9', '4', '9', + '5', '9', '6', '9', '7', '9', '8', '9', '9', '9', 'a', '9', 'b', '9', 'c', '9', 'd', '9', 'e', '9', 'f', 'a', '0', + 'a', '1', 'a', '2', 'a', '3', 'a', '4', 'a', '5', 'a', '6', 'a', '7', 'a', '8', 'a', '9', 'a', 'a', 'a', 'b', 'a', + 'c', 'a', 'd', 'a', 'e', 'a', 'f', 'b', '0', 'b', '1', 'b', '2', 'b', '3', 'b', '4', 'b', '5', 'b', '6', 'b', '7', + 'b', '8', 'b', '9', 'b', 'a', 'b', 'b', 'b', 'c', 'b', 'd', 'b', 'e', 'b', 'f', 'c', '0', 'c', '1', 'c', '2', 'c', + '3', 'c', '4', 'c', '5', 'c', '6', 'c', '7', 'c', '8', 'c', '9', 'c', 'a', 'c', 'b', 'c', 'c', 'c', 'd', 'c', 'e', + 'c', 'f', 'd', '0', 'd', '1', 'd', '2', 'd', '3', 'd', '4', 'd', '5', 'd', '6', 'd', '7', 'd', '8', 'd', '9', 'd', + 'a', 'd', 'b', 'd', 'c', 'd', 'd', 'd', 'e', 'd', 'f', 'e', '0', 'e', '1', 'e', '2', 'e', '3', 'e', '4', 'e', '5', + 'e', '6', 'e', '7', 'e', '8', 'e', '9', 'e', 'a', 'e', 'b', 'e', 'c', 'e', 'd', 'e', 'e', 'e', 'f', 'f', '0', 'f', + '1', 'f', '2', 'f', '3', 'f', '4', 'f', '5', 'f', '6', 'f', '7', 'f', '8', 'f', '9', 'f', 'a', 'f', 'b', 'f', 'c', + 'f', 'd', 'f', 'e', 'f', 'f'}; + +inline constexpr uint32_t __pow10_32[10] = { + UINT32_C(0), UINT32_C(10), UINT32_C(100), UINT32_C(1000), UINT32_C(10000), + UINT32_C(100000), UINT32_C(1000000), UINT32_C(10000000), UINT32_C(100000000), UINT32_C(1000000000)}; + +inline constexpr uint64_t __pow10_64[20] = {UINT64_C(0), + UINT64_C(10), + UINT64_C(100), + UINT64_C(1000), + UINT64_C(10000), + UINT64_C(100000), + UINT64_C(1000000), + UINT64_C(10000000), + UINT64_C(100000000), + UINT64_C(1000000000), + UINT64_C(10000000000), + UINT64_C(100000000000), + UINT64_C(1000000000000), + UINT64_C(10000000000000), + UINT64_C(100000000000000), + UINT64_C(1000000000000000), + UINT64_C(10000000000000000), + UINT64_C(100000000000000000), + UINT64_C(1000000000000000000), + UINT64_C(10000000000000000000)}; + +# ifndef _LIBCPP_HAS_NO_INT128 +inline constexpr int __pow10_128_offset = 0; +inline constexpr __uint128_t __pow10_128[40] = { + UINT64_C(0), + UINT64_C(10), + UINT64_C(100), + UINT64_C(1000), + UINT64_C(10000), + UINT64_C(100000), + UINT64_C(1000000), + UINT64_C(10000000), + UINT64_C(100000000), + UINT64_C(1000000000), + UINT64_C(10000000000), + UINT64_C(100000000000), + UINT64_C(1000000000000), + UINT64_C(10000000000000), + UINT64_C(100000000000000), + UINT64_C(1000000000000000), + UINT64_C(10000000000000000), + UINT64_C(100000000000000000), + UINT64_C(1000000000000000000), + UINT64_C(10000000000000000000), + __uint128_t(UINT64_C(10000000000000000000)) * UINT64_C(10), + __uint128_t(UINT64_C(10000000000000000000)) * UINT64_C(100), + __uint128_t(UINT64_C(10000000000000000000)) * UINT64_C(1000), + __uint128_t(UINT64_C(10000000000000000000)) * UINT64_C(10000), + __uint128_t(UINT64_C(10000000000000000000)) * UINT64_C(100000), + __uint128_t(UINT64_C(10000000000000000000)) * UINT64_C(1000000), + __uint128_t(UINT64_C(10000000000000000000)) * UINT64_C(10000000), + __uint128_t(UINT64_C(10000000000000000000)) * UINT64_C(100000000), + __uint128_t(UINT64_C(10000000000000000000)) * UINT64_C(1000000000), + __uint128_t(UINT64_C(10000000000000000000)) * UINT64_C(10000000000), + __uint128_t(UINT64_C(10000000000000000000)) * UINT64_C(100000000000), + __uint128_t(UINT64_C(10000000000000000000)) * UINT64_C(1000000000000), + __uint128_t(UINT64_C(10000000000000000000)) * UINT64_C(10000000000000), + __uint128_t(UINT64_C(10000000000000000000)) * UINT64_C(100000000000000), + __uint128_t(UINT64_C(10000000000000000000)) * UINT64_C(1000000000000000), + __uint128_t(UINT64_C(10000000000000000000)) * UINT64_C(10000000000000000), + __uint128_t(UINT64_C(10000000000000000000)) * UINT64_C(100000000000000000), + __uint128_t(UINT64_C(10000000000000000000)) * UINT64_C(1000000000000000000), + __uint128_t(UINT64_C(10000000000000000000)) * UINT64_C(10000000000000000000), + (__uint128_t(UINT64_C(10000000000000000000)) * UINT64_C(10000000000000000000)) * 10}; +# endif + +inline constexpr char __digits_base_10[200] = { + // clang-format off + '0', '0', '0', '1', '0', '2', '0', '3', '0', '4', '0', '5', '0', '6', '0', '7', '0', '8', '0', '9', + '1', '0', '1', '1', '1', '2', '1', '3', '1', '4', '1', '5', '1', '6', '1', '7', '1', '8', '1', '9', + '2', '0', '2', '1', '2', '2', '2', '3', '2', '4', '2', '5', '2', '6', '2', '7', '2', '8', '2', '9', + '3', '0', '3', '1', '3', '2', '3', '3', '3', '4', '3', '5', '3', '6', '3', '7', '3', '8', '3', '9', + '4', '0', '4', '1', '4', '2', '4', '3', '4', '4', '4', '5', '4', '6', '4', '7', '4', '8', '4', '9', + '5', '0', '5', '1', '5', '2', '5', '3', '5', '4', '5', '5', '5', '6', '5', '7', '5', '8', '5', '9', + '6', '0', '6', '1', '6', '2', '6', '3', '6', '4', '6', '5', '6', '6', '6', '7', '6', '8', '6', '9', + '7', '0', '7', '1', '7', '2', '7', '3', '7', '4', '7', '5', '7', '6', '7', '7', '7', '8', '7', '9', + '8', '0', '8', '1', '8', '2', '8', '3', '8', '4', '8', '5', '8', '6', '8', '7', '8', '8', '8', '9', + '9', '0', '9', '1', '9', '2', '9', '3', '9', '4', '9', '5', '9', '6', '9', '7', '9', '8', '9', '9'}; +// clang-format on + +} // namespace __itoa + +#endif // _LIBCPP_STD_VER > 14 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___CHARCONV_TABLES diff --git a/app/src/main/cpp/libcxx/include/__charconv/to_chars_base_10.h b/app/src/main/cpp/libcxx/include/__charconv/to_chars_base_10.h new file mode 100644 index 0000000..fc7fb76 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__charconv/to_chars_base_10.h @@ -0,0 +1,185 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___CHARCONV_TO_CHARS_BASE_10_H +#define _LIBCPP___CHARCONV_TO_CHARS_BASE_10_H + +#include <__algorithm/copy_n.h> +#include <__charconv/tables.h> +#include <__config> +#include +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 14 + +namespace __itoa { + +_LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI inline char* __append1(char* __first, uint32_t __value) noexcept { + *__first = '0' + static_cast(__value); + return __first + 1; +} + +_LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI inline char* __append2(char* __first, uint32_t __value) noexcept { + return std::copy_n(&__digits_base_10[__value * 2], 2, __first); +} + +_LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI inline char* __append3(char* __first, uint32_t __value) noexcept { + return __itoa::__append2(__itoa::__append1(__first, __value / 100), __value % 100); +} + +_LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI inline char* __append4(char* __first, uint32_t __value) noexcept { + return __itoa::__append2(__itoa::__append2(__first, __value / 100), __value % 100); +} + +_LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI inline char* __append5(char* __first, uint32_t __value) noexcept { + return __itoa::__append4(__itoa::__append1(__first, __value / 10000), __value % 10000); +} + +_LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI inline char* __append6(char* __first, uint32_t __value) noexcept { + return __itoa::__append4(__itoa::__append2(__first, __value / 10000), __value % 10000); +} + +_LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI inline char* __append7(char* __first, uint32_t __value) noexcept { + return __itoa::__append6(__itoa::__append1(__first, __value / 1000000), __value % 1000000); +} + +_LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI inline char* __append8(char* __first, uint32_t __value) noexcept { + return __itoa::__append6(__itoa::__append2(__first, __value / 1000000), __value % 1000000); +} + +_LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI inline char* __append9(char* __first, uint32_t __value) noexcept { + return __itoa::__append8(__itoa::__append1(__first, __value / 100000000), __value % 100000000); +} + +template +_LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI char* __append10(char* __first, _Tp __value) noexcept { + return __itoa::__append8(__itoa::__append2(__first, static_cast(__value / 100000000)), + static_cast(__value % 100000000)); +} + +_LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI inline char* __base_10_u32(char* __first, uint32_t __value) noexcept { + if (__value < 1000000) { + if (__value < 10000) { + if (__value < 100) { + // 0 <= __value < 100 + if (__value < 10) + return __itoa::__append1(__first, __value); + return __itoa::__append2(__first, __value); + } + // 100 <= __value < 10'000 + if (__value < 1000) + return __itoa::__append3(__first, __value); + return __itoa::__append4(__first, __value); + } + + // 10'000 <= __value < 1'000'000 + if (__value < 100000) + return __itoa::__append5(__first, __value); + return __itoa::__append6(__first, __value); + } + + // __value => 1'000'000 + if (__value < 100000000) { + // 1'000'000 <= __value < 100'000'000 + if (__value < 10000000) + return __itoa::__append7(__first, __value); + return __itoa::__append8(__first, __value); + } + + // 100'000'000 <= __value < max + if (__value < 1000000000) + return __itoa::__append9(__first, __value); + return __itoa::__append10(__first, __value); +} + +_LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI inline char* __base_10_u64(char* __buffer, uint64_t __value) noexcept { + if (__value <= UINT32_MAX) + return __itoa::__base_10_u32(__buffer, static_cast(__value)); + + // Numbers in the range UINT32_MAX <= val < 10'000'000'000 always contain 10 + // digits and are outputted after this if statement. + if (__value >= 10000000000) { + // This function properly deterimines the first non-zero leading digit. + __buffer = __itoa::__base_10_u32(__buffer, static_cast(__value / 10000000000)); + __value %= 10000000000; + } + return __itoa::__append10(__buffer, __value); +} + +# ifndef _LIBCPP_HAS_NO_INT128 +/// \returns 10^\a exp +/// +/// \pre \a exp [19, 39] +/// +/// \note The lookup table contains a partial set of exponents limiting the +/// range that can be used. However the range is sufficient for +/// \ref __base_10_u128. +_LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI inline __uint128_t __pow_10(int __exp) noexcept { + _LIBCPP_ASSERT(__exp >= __pow10_128_offset, "Index out of bounds"); + return __pow10_128[__exp - __pow10_128_offset]; +} + +_LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI inline char* __base_10_u128(char* __buffer, __uint128_t __value) noexcept { + _LIBCPP_ASSERT( + __value > numeric_limits::max(), "The optimizations for this algorithm fail when this isn't true."); + + // Unlike the 64 to 32 bit case the 128 bit case the "upper half" can't be + // stored in the "lower half". Instead we first need to handle the top most + // digits separately. + // + // Maximum unsigned values + // 64 bit 18'446'744'073'709'551'615 (20 digits) + // 128 bit 340'282'366'920'938'463'463'374'607'431'768'211'455 (39 digits) + // step 1 ^ ([0-1] digits) + // step 2 ^^^^^^^^^^^^^^^^^^^^^^^^^ ([0-19] digits) + // step 3 ^^^^^^^^^^^^^^^^^^^^^^^^^ (19 digits) + if (__value >= __itoa::__pow_10(38)) { + // step 1 + __buffer = __itoa::__append1(__buffer, static_cast(__value / __itoa::__pow_10(38))); + __value %= __itoa::__pow_10(38); + + // step 2 always 19 digits. + // They are handled here since leading zeros need to be appended to the buffer, + __buffer = __itoa::__append9(__buffer, static_cast(__value / __itoa::__pow_10(29))); + __value %= __itoa::__pow_10(29); + __buffer = __itoa::__append10(__buffer, static_cast(__value / __itoa::__pow_10(19))); + __value %= __itoa::__pow_10(19); + } + else { + // step 2 + // This version needs to determine the position of the leading non-zero digit. + __buffer = __base_10_u64(__buffer, static_cast(__value / __itoa::__pow_10(19))); + __value %= __itoa::__pow_10(19); + } + + // Step 3 + __buffer = __itoa::__append9(__buffer, static_cast(__value / 10000000000)); + __buffer = __itoa::__append10(__buffer, static_cast(__value % 10000000000)); + + return __buffer; +} +# endif +} // namespace __itoa + +#endif // _LIBCPP_STD_VER > 14 + +_LIBCPP_END_NAMESPACE_STD + +_LIBCPP_POP_MACROS + +#endif // _LIBCPP___CHARCONV_TO_CHARS_BASE_10_H diff --git a/app/src/main/cpp/libcxx/include/__charconv/to_chars_result.h b/app/src/main/cpp/libcxx/include/__charconv/to_chars_result.h new file mode 100644 index 0000000..2eb4098 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__charconv/to_chars_result.h @@ -0,0 +1,37 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___CHARCONV_TO_CHARS_RESULT_H +#define _LIBCPP___CHARCONV_TO_CHARS_RESULT_H + +#include <__config> +#include <__errc> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 14 + +struct _LIBCPP_TYPE_VIS to_chars_result +{ + char* ptr; + errc ec; +# if _LIBCPP_STD_VER > 17 + _LIBCPP_HIDE_FROM_ABI friend bool operator==(const to_chars_result&, const to_chars_result&) = default; +# endif +}; + +#endif // _LIBCPP_STD_VER > 14 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___CHARCONV_TO_CHARS_RESULT_H diff --git a/app/src/main/cpp/libcxx/include/__chrono/calendar.h b/app/src/main/cpp/libcxx/include/__chrono/calendar.h new file mode 100644 index 0000000..d3762a6 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__chrono/calendar.h @@ -0,0 +1,44 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___CHRONO_CALENDAR_H +#define _LIBCPP___CHRONO_CALENDAR_H + +#include <__chrono/duration.h> +#include <__chrono/time_point.h> +#include <__config> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if _LIBCPP_STD_VER > 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace chrono +{ + +struct local_t {}; +template +using local_time = time_point; +using local_seconds = local_time; +using local_days = local_time; + +struct last_spec { _LIBCPP_HIDE_FROM_ABI explicit last_spec() = default; }; +inline constexpr last_spec last{}; + + +} // namespace chrono + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER > 17 + +#endif // _LIBCPP___CHRONO_CALENDAR_H diff --git a/app/src/main/cpp/libcxx/include/__chrono/convert_to_timespec.h b/app/src/main/cpp/libcxx/include/__chrono/convert_to_timespec.h new file mode 100644 index 0000000..fab07f2 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__chrono/convert_to_timespec.h @@ -0,0 +1,56 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___CHRONO_CONVERT_TO_TIMESPEC_H +#define _LIBCPP___CHRONO_CONVERT_TO_TIMESPEC_H + +#include <__chrono/duration.h> +#include <__config> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + +_LIBCPP_BEGIN_NAMESPACE_STD + +// Convert a nanoseconds duration to the given TimeSpec type, which must have +// the same properties as std::timespec. +template +_LIBCPP_HIDE_FROM_ABI inline +_TimeSpec __convert_to_timespec(const chrono::nanoseconds& __ns) +{ + using namespace chrono; + seconds __s = duration_cast(__ns); + _TimeSpec __ts; + typedef decltype(__ts.tv_sec) __ts_sec; + const __ts_sec __ts_sec_max = numeric_limits<__ts_sec>::max(); + + if (__s.count() < __ts_sec_max) + { + __ts.tv_sec = static_cast<__ts_sec>(__s.count()); + __ts.tv_nsec = static_cast((__ns - __s).count()); + } + else + { + __ts.tv_sec = __ts_sec_max; + __ts.tv_nsec = 999999999; // (10^9 - 1) + } + + return __ts; +} + +_LIBCPP_END_NAMESPACE_STD + +_LIBCPP_POP_MACROS + +#endif // _LIBCPP___CHRONO_CONVERT_TO_TIMESPEC_H diff --git a/app/src/main/cpp/libcxx/include/__chrono/convert_to_tm.h b/app/src/main/cpp/libcxx/include/__chrono/convert_to_tm.h new file mode 100644 index 0000000..36846b3 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__chrono/convert_to_tm.h @@ -0,0 +1,127 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___CHRONO_CONVERT_TO_TM_H +#define _LIBCPP___CHRONO_CONVERT_TO_TM_H + +#include <__chrono/day.h> +#include <__chrono/duration.h> +#include <__chrono/hh_mm_ss.h> +#include <__chrono/month.h> +#include <__chrono/month_weekday.h> +#include <__chrono/monthday.h> +#include <__chrono/statically_widen.h> +#include <__chrono/system_clock.h> +#include <__chrono/time_point.h> +#include <__chrono/weekday.h> +#include <__chrono/year.h> +#include <__chrono/year_month.h> +#include <__chrono/year_month_day.h> +#include <__chrono/year_month_weekday.h> +#include <__concepts/same_as.h> +#include <__config> +#include <__memory/addressof.h> +#include +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 17 + +// Conerts a chrono date and weekday to a given _Tm type. +// +// This is an implementation detail for the function +// template +// _Tm __convert_to_tm(const _ChronoT& __value) +// +// This manually converts the two values to the proper type. It is possible to +// convert from sys_days to time_t and then to _Tm. But this leads to the Y2K +// bug when time_t is a 32-bit signed integer. Chrono considers years beyond +// the year 2038 valid, so instead do the transformation manually. +template + requires(same_as<_Date, chrono::year_month_day> || same_as<_Date, chrono::year_month_day_last>) +_LIBCPP_HIDE_FROM_ABI _Tm __convert_to_tm(const _Date& __date, chrono::weekday __weekday) { + _Tm __result = {}; +# ifdef __GLIBC__ + __result.tm_zone = "UTC"; +# endif + __result.tm_year = static_cast(__date.year()) - 1900; + __result.tm_mon = static_cast(__date.month()) - 1; + __result.tm_mday = static_cast(__date.day()); + __result.tm_wday = static_cast(__weekday.c_encoding()); + __result.tm_yday = + (static_cast(__date) - + static_cast(chrono::year_month_day{__date.year(), chrono::January, chrono::day{1}})) + .count(); + + return __result; +} + +// Convert a chrono (calendar) time point, or dururation to the given _Tm type, +// which must have the same properties as std::tm. +template +_LIBCPP_HIDE_FROM_ABI _Tm __convert_to_tm(const _ChronoT& __value) { + _Tm __result = {}; +# ifdef __GLIBC__ + __result.tm_zone = "UTC"; +# endif + + if constexpr (chrono::__is_duration<_ChronoT>::value) { + // [time.format]/6 + // ... However, if a flag refers to a "time of day" (e.g. %H, %I, %p, + // etc.), then a specialization of duration is interpreted as the time of + // day elapsed since midnight. + uint64_t __sec = chrono::duration_cast(__value).count(); + __sec %= 24 * 3600; + __result.tm_hour = __sec / 3600; + __sec %= 3600; + __result.tm_min = __sec / 60; + __result.tm_sec = __sec % 60; + } else if constexpr (same_as<_ChronoT, chrono::day>) + __result.tm_mday = static_cast(__value); + else if constexpr (same_as<_ChronoT, chrono::month>) + __result.tm_mon = static_cast(__value) - 1; + else if constexpr (same_as<_ChronoT, chrono::year>) + __result.tm_year = static_cast(__value) - 1900; + else if constexpr (same_as<_ChronoT, chrono::weekday>) + __result.tm_wday = __value.c_encoding(); + else if constexpr (same_as<_ChronoT, chrono::weekday_indexed> || same_as<_ChronoT, chrono::weekday_last>) + __result.tm_wday = __value.weekday().c_encoding(); + else if constexpr (same_as<_ChronoT, chrono::month_day>) { + __result.tm_mday = static_cast(__value.day()); + __result.tm_mon = static_cast(__value.month()) - 1; + } else if constexpr (same_as<_ChronoT, chrono::month_day_last>) { + __result.tm_mon = static_cast(__value.month()) - 1; + } else if constexpr (same_as<_ChronoT, chrono::month_weekday> || same_as<_ChronoT, chrono::month_weekday_last>) { + __result.tm_wday = __value.weekday_indexed().weekday().c_encoding(); + __result.tm_mon = static_cast(__value.month()) - 1; + } else if constexpr (same_as<_ChronoT, chrono::year_month>) { + __result.tm_year = static_cast(__value.year()) - 1900; + __result.tm_mon = static_cast(__value.month()) - 1; + } else if constexpr (same_as<_ChronoT, chrono::year_month_day> || same_as<_ChronoT, chrono::year_month_day_last>) { + return std::__convert_to_tm<_Tm>( + chrono::year_month_day{__value}, chrono::weekday{static_cast(__value)}); + } else if constexpr (same_as<_ChronoT, chrono::year_month_weekday> || + same_as<_ChronoT, chrono::year_month_weekday_last>) { + return std::__convert_to_tm<_Tm>(chrono::year_month_day{static_cast(__value)}, __value.weekday()); + } else + static_assert(sizeof(_ChronoT) == 0, "Add the missing type specialization"); + + return __result; +} + +#endif //if _LIBCPP_STD_VER > 17 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___CHRONO_CONVERT_TO_TM_H diff --git a/app/src/main/cpp/libcxx/include/__chrono/day.h b/app/src/main/cpp/libcxx/include/__chrono/day.h new file mode 100644 index 0000000..35ecfcf --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__chrono/day.h @@ -0,0 +1,84 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___CHRONO_DAY_H +#define _LIBCPP___CHRONO_DAY_H + +#include <__chrono/duration.h> +#include <__config> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if _LIBCPP_STD_VER > 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace chrono +{ + +class day { +private: + unsigned char __d_; +public: + _LIBCPP_HIDE_FROM_ABI day() = default; + _LIBCPP_HIDE_FROM_ABI explicit inline constexpr day(unsigned __val) noexcept : __d_(static_cast(__val)) {} + _LIBCPP_HIDE_FROM_ABI inline constexpr day& operator++() noexcept { ++__d_; return *this; } + _LIBCPP_HIDE_FROM_ABI inline constexpr day operator++(int) noexcept { day __tmp = *this; ++(*this); return __tmp; } + _LIBCPP_HIDE_FROM_ABI inline constexpr day& operator--() noexcept { --__d_; return *this; } + _LIBCPP_HIDE_FROM_ABI inline constexpr day operator--(int) noexcept { day __tmp = *this; --(*this); return __tmp; } + _LIBCPP_HIDE_FROM_ABI constexpr day& operator+=(const days& __dd) noexcept; + _LIBCPP_HIDE_FROM_ABI constexpr day& operator-=(const days& __dd) noexcept; + _LIBCPP_HIDE_FROM_ABI explicit inline constexpr operator unsigned() const noexcept { return __d_; } + _LIBCPP_HIDE_FROM_ABI inline constexpr bool ok() const noexcept { return __d_ >= 1 && __d_ <= 31; } + }; + + +_LIBCPP_HIDE_FROM_ABI inline constexpr +bool operator==(const day& __lhs, const day& __rhs) noexcept +{ return static_cast(__lhs) == static_cast(__rhs); } + +_LIBCPP_HIDE_FROM_ABI constexpr strong_ordering operator<=>(const day& __lhs, const day& __rhs) noexcept { + return static_cast(__lhs) <=> static_cast(__rhs); +} + +_LIBCPP_HIDE_FROM_ABI inline constexpr +day operator+ (const day& __lhs, const days& __rhs) noexcept +{ return day(static_cast(__lhs) + __rhs.count()); } + +_LIBCPP_HIDE_FROM_ABI inline constexpr +day operator+ (const days& __lhs, const day& __rhs) noexcept +{ return __rhs + __lhs; } + +_LIBCPP_HIDE_FROM_ABI inline constexpr +day operator- (const day& __lhs, const days& __rhs) noexcept +{ return __lhs + -__rhs; } + +_LIBCPP_HIDE_FROM_ABI inline constexpr +days operator-(const day& __lhs, const day& __rhs) noexcept +{ return days(static_cast(static_cast(__lhs)) - + static_cast(static_cast(__rhs))); } + +_LIBCPP_HIDE_FROM_ABI inline constexpr +day& day::operator+=(const days& __dd) noexcept +{ *this = *this + __dd; return *this; } + +_LIBCPP_HIDE_FROM_ABI inline constexpr +day& day::operator-=(const days& __dd) noexcept +{ *this = *this - __dd; return *this; } + +} // namespace chrono + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER > 17 + +#endif // _LIBCPP___CHRONO_DAY_H diff --git a/app/src/main/cpp/libcxx/include/__chrono/duration.h b/app/src/main/cpp/libcxx/include/__chrono/duration.h new file mode 100644 index 0000000..afcc38b --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__chrono/duration.h @@ -0,0 +1,622 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___CHRONO_DURATION_H +#define _LIBCPP___CHRONO_DURATION_H + +#include <__config> +#include <__type_traits/common_type.h> +#include <__type_traits/enable_if.h> +#include <__type_traits/is_convertible.h> +#include <__type_traits/is_floating_point.h> +#include +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace chrono +{ + +template > class _LIBCPP_TEMPLATE_VIS duration; + +template +struct __is_duration : false_type {}; + +template +struct __is_duration > : true_type {}; + +template +struct __is_duration > : true_type {}; + +template +struct __is_duration > : true_type {}; + +template +struct __is_duration > : true_type {}; + +} // namespace chrono + +template +struct _LIBCPP_TEMPLATE_VIS common_type, + chrono::duration<_Rep2, _Period2> > +{ + typedef chrono::duration::type, + typename __ratio_gcd<_Period1, _Period2>::type> type; +}; + +namespace chrono { + +// duration_cast + +template ::type, + bool = _Period::num == 1, + bool = _Period::den == 1> +struct __duration_cast; + +template +struct __duration_cast<_FromDuration, _ToDuration, _Period, true, true> +{ + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR + _ToDuration operator()(const _FromDuration& __fd) const + { + return _ToDuration(static_cast(__fd.count())); + } +}; + +template +struct __duration_cast<_FromDuration, _ToDuration, _Period, true, false> +{ + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR + _ToDuration operator()(const _FromDuration& __fd) const + { + typedef typename common_type::type _Ct; + return _ToDuration(static_cast( + static_cast<_Ct>(__fd.count()) / static_cast<_Ct>(_Period::den))); + } +}; + +template +struct __duration_cast<_FromDuration, _ToDuration, _Period, false, true> +{ + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR + _ToDuration operator()(const _FromDuration& __fd) const + { + typedef typename common_type::type _Ct; + return _ToDuration(static_cast( + static_cast<_Ct>(__fd.count()) * static_cast<_Ct>(_Period::num))); + } +}; + +template +struct __duration_cast<_FromDuration, _ToDuration, _Period, false, false> +{ + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR + _ToDuration operator()(const _FromDuration& __fd) const + { + typedef typename common_type::type _Ct; + return _ToDuration(static_cast( + static_cast<_Ct>(__fd.count()) * static_cast<_Ct>(_Period::num) + / static_cast<_Ct>(_Period::den))); + } +}; + +template +inline _LIBCPP_INLINE_VISIBILITY +_LIBCPP_CONSTEXPR +typename enable_if +< + __is_duration<_ToDuration>::value, + _ToDuration +>::type +duration_cast(const duration<_Rep, _Period>& __fd) +{ + return __duration_cast, _ToDuration>()(__fd); +} + +template +struct _LIBCPP_TEMPLATE_VIS treat_as_floating_point : is_floating_point<_Rep> {}; + +#if _LIBCPP_STD_VER > 14 +template +inline constexpr bool treat_as_floating_point_v = treat_as_floating_point<_Rep>::value; +#endif + +template +struct _LIBCPP_TEMPLATE_VIS duration_values +{ +public: + _LIBCPP_INLINE_VISIBILITY static _LIBCPP_CONSTEXPR _Rep zero() _NOEXCEPT {return _Rep(0);} + _LIBCPP_INLINE_VISIBILITY static _LIBCPP_CONSTEXPR _Rep max() _NOEXCEPT {return numeric_limits<_Rep>::max();} + _LIBCPP_INLINE_VISIBILITY static _LIBCPP_CONSTEXPR _Rep min() _NOEXCEPT {return numeric_limits<_Rep>::lowest();} +}; + +#if _LIBCPP_STD_VER > 14 +template +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR +typename enable_if +< + __is_duration<_ToDuration>::value, + _ToDuration +>::type +floor(const duration<_Rep, _Period>& __d) +{ + _ToDuration __t = chrono::duration_cast<_ToDuration>(__d); + if (__t > __d) + __t = __t - _ToDuration{1}; + return __t; +} + +template +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR +typename enable_if +< + __is_duration<_ToDuration>::value, + _ToDuration +>::type +ceil(const duration<_Rep, _Period>& __d) +{ + _ToDuration __t = chrono::duration_cast<_ToDuration>(__d); + if (__t < __d) + __t = __t + _ToDuration{1}; + return __t; +} + +template +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR +typename enable_if +< + __is_duration<_ToDuration>::value, + _ToDuration +>::type +round(const duration<_Rep, _Period>& __d) +{ + _ToDuration __lower = chrono::floor<_ToDuration>(__d); + _ToDuration __upper = __lower + _ToDuration{1}; + auto __lowerDiff = __d - __lower; + auto __upperDiff = __upper - __d; + if (__lowerDiff < __upperDiff) + return __lower; + if (__lowerDiff > __upperDiff) + return __upper; + return __lower.count() & 1 ? __upper : __lower; +} +#endif + +// duration + +template +class _LIBCPP_TEMPLATE_VIS duration +{ + static_assert(!__is_duration<_Rep>::value, "A duration representation can not be a duration"); + static_assert(__is_ratio<_Period>::value, "Second template parameter of duration must be a std::ratio"); + static_assert(_Period::num > 0, "duration period must be positive"); + + template + struct __no_overflow + { + private: + static const intmax_t __gcd_n1_n2 = __static_gcd<_R1::num, _R2::num>::value; + static const intmax_t __gcd_d1_d2 = __static_gcd<_R1::den, _R2::den>::value; + static const intmax_t __n1 = _R1::num / __gcd_n1_n2; + static const intmax_t __d1 = _R1::den / __gcd_d1_d2; + static const intmax_t __n2 = _R2::num / __gcd_n1_n2; + static const intmax_t __d2 = _R2::den / __gcd_d1_d2; + static const intmax_t max = -((intmax_t(1) << (sizeof(intmax_t) * CHAR_BIT - 1)) + 1); + + template + struct __mul // __overflow == false + { + static const intmax_t value = _Xp * _Yp; + }; + + template + struct __mul<_Xp, _Yp, true> + { + static const intmax_t value = 1; + }; + + public: + static const bool value = (__n1 <= max / __d2) && (__n2 <= max / __d1); + typedef ratio<__mul<__n1, __d2, !value>::value, + __mul<__n2, __d1, !value>::value> type; + }; + +public: + typedef _Rep rep; + typedef typename _Period::type period; +private: + rep __rep_; +public: + + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR +#ifndef _LIBCPP_CXX03_LANG + duration() = default; +#else + duration() {} +#endif + + template + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR + explicit duration(const _Rep2& __r, + typename enable_if + < + is_convertible::value && + (treat_as_floating_point::value || + !treat_as_floating_point<_Rep2>::value) + >::type* = nullptr) + : __rep_(__r) {} + + // conversions + template + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR + duration(const duration<_Rep2, _Period2>& __d, + typename enable_if + < + __no_overflow<_Period2, period>::value && ( + treat_as_floating_point::value || + (__no_overflow<_Period2, period>::type::den == 1 && + !treat_as_floating_point<_Rep2>::value)) + >::type* = nullptr) + : __rep_(chrono::duration_cast(__d).count()) {} + + // observer + + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR rep count() const {return __rep_;} + + // arithmetic + + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR typename common_type::type operator+() const {return typename common_type::type(*this);} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR typename common_type::type operator-() const {return typename common_type::type(-__rep_);} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX17 duration& operator++() {++__rep_; return *this;} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX17 duration operator++(int) {return duration(__rep_++);} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX17 duration& operator--() {--__rep_; return *this;} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX17 duration operator--(int) {return duration(__rep_--);} + + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX17 duration& operator+=(const duration& __d) {__rep_ += __d.count(); return *this;} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX17 duration& operator-=(const duration& __d) {__rep_ -= __d.count(); return *this;} + + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX17 duration& operator*=(const rep& __rhs) {__rep_ *= __rhs; return *this;} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX17 duration& operator/=(const rep& __rhs) {__rep_ /= __rhs; return *this;} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX17 duration& operator%=(const rep& __rhs) {__rep_ %= __rhs; return *this;} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX17 duration& operator%=(const duration& __rhs) {__rep_ %= __rhs.count(); return *this;} + + // special values + + _LIBCPP_INLINE_VISIBILITY static _LIBCPP_CONSTEXPR duration zero() _NOEXCEPT {return duration(duration_values::zero());} + _LIBCPP_INLINE_VISIBILITY static _LIBCPP_CONSTEXPR duration min() _NOEXCEPT {return duration(duration_values::min());} + _LIBCPP_INLINE_VISIBILITY static _LIBCPP_CONSTEXPR duration max() _NOEXCEPT {return duration(duration_values::max());} +}; + +typedef duration nanoseconds; +typedef duration microseconds; +typedef duration milliseconds; +typedef duration seconds; +typedef duration< long, ratio< 60> > minutes; +typedef duration< long, ratio<3600> > hours; +#if _LIBCPP_STD_VER > 17 +typedef duration< int, ratio_multiply, hours::period>> days; +typedef duration< int, ratio_multiply, days::period>> weeks; +typedef duration< int, ratio_multiply, days::period>> years; +typedef duration< int, ratio_divide>> months; +#endif +// Duration == + +template +struct __duration_eq +{ + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR + bool operator()(const _LhsDuration& __lhs, const _RhsDuration& __rhs) const + { + typedef typename common_type<_LhsDuration, _RhsDuration>::type _Ct; + return _Ct(__lhs).count() == _Ct(__rhs).count(); + } +}; + +template +struct __duration_eq<_LhsDuration, _LhsDuration> +{ + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR + bool operator()(const _LhsDuration& __lhs, const _LhsDuration& __rhs) const + {return __lhs.count() == __rhs.count();} +}; + +template +inline _LIBCPP_INLINE_VISIBILITY +_LIBCPP_CONSTEXPR +bool +operator==(const duration<_Rep1, _Period1>& __lhs, const duration<_Rep2, _Period2>& __rhs) +{ + return __duration_eq, duration<_Rep2, _Period2> >()(__lhs, __rhs); +} + +// Duration != + +template +inline _LIBCPP_INLINE_VISIBILITY +_LIBCPP_CONSTEXPR +bool +operator!=(const duration<_Rep1, _Period1>& __lhs, const duration<_Rep2, _Period2>& __rhs) +{ + return !(__lhs == __rhs); +} + +// Duration < + +template +struct __duration_lt +{ + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR + bool operator()(const _LhsDuration& __lhs, const _RhsDuration& __rhs) const + { + typedef typename common_type<_LhsDuration, _RhsDuration>::type _Ct; + return _Ct(__lhs).count() < _Ct(__rhs).count(); + } +}; + +template +struct __duration_lt<_LhsDuration, _LhsDuration> +{ + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR + bool operator()(const _LhsDuration& __lhs, const _LhsDuration& __rhs) const + {return __lhs.count() < __rhs.count();} +}; + +template +inline _LIBCPP_INLINE_VISIBILITY +_LIBCPP_CONSTEXPR +bool +operator< (const duration<_Rep1, _Period1>& __lhs, const duration<_Rep2, _Period2>& __rhs) +{ + return __duration_lt, duration<_Rep2, _Period2> >()(__lhs, __rhs); +} + +// Duration > + +template +inline _LIBCPP_INLINE_VISIBILITY +_LIBCPP_CONSTEXPR +bool +operator> (const duration<_Rep1, _Period1>& __lhs, const duration<_Rep2, _Period2>& __rhs) +{ + return __rhs < __lhs; +} + +// Duration <= + +template +inline _LIBCPP_INLINE_VISIBILITY +_LIBCPP_CONSTEXPR +bool +operator<=(const duration<_Rep1, _Period1>& __lhs, const duration<_Rep2, _Period2>& __rhs) +{ + return !(__rhs < __lhs); +} + +// Duration >= + +template +inline _LIBCPP_INLINE_VISIBILITY +_LIBCPP_CONSTEXPR +bool +operator>=(const duration<_Rep1, _Period1>& __lhs, const duration<_Rep2, _Period2>& __rhs) +{ + return !(__lhs < __rhs); +} + +// Duration + + +template +inline _LIBCPP_INLINE_VISIBILITY +_LIBCPP_CONSTEXPR +typename common_type, duration<_Rep2, _Period2> >::type +operator+(const duration<_Rep1, _Period1>& __lhs, const duration<_Rep2, _Period2>& __rhs) +{ + typedef typename common_type, duration<_Rep2, _Period2> >::type _Cd; + return _Cd(_Cd(__lhs).count() + _Cd(__rhs).count()); +} + +// Duration - + +template +inline _LIBCPP_INLINE_VISIBILITY +_LIBCPP_CONSTEXPR +typename common_type, duration<_Rep2, _Period2> >::type +operator-(const duration<_Rep1, _Period1>& __lhs, const duration<_Rep2, _Period2>& __rhs) +{ + typedef typename common_type, duration<_Rep2, _Period2> >::type _Cd; + return _Cd(_Cd(__lhs).count() - _Cd(__rhs).count()); +} + +// Duration * + +template +inline _LIBCPP_INLINE_VISIBILITY +_LIBCPP_CONSTEXPR +typename enable_if +< + is_convertible<_Rep2, typename common_type<_Rep1, _Rep2>::type>::value, + duration::type, _Period> +>::type +operator*(const duration<_Rep1, _Period>& __d, const _Rep2& __s) +{ + typedef typename common_type<_Rep1, _Rep2>::type _Cr; + typedef duration<_Cr, _Period> _Cd; + return _Cd(_Cd(__d).count() * static_cast<_Cr>(__s)); +} + +template +inline _LIBCPP_INLINE_VISIBILITY +_LIBCPP_CONSTEXPR +typename enable_if +< + is_convertible<_Rep1, typename common_type<_Rep1, _Rep2>::type>::value, + duration::type, _Period> +>::type +operator*(const _Rep1& __s, const duration<_Rep2, _Period>& __d) +{ + return __d * __s; +} + +// Duration / + +template +inline _LIBCPP_INLINE_VISIBILITY +_LIBCPP_CONSTEXPR +typename enable_if +< + !__is_duration<_Rep2>::value && + is_convertible<_Rep2, typename common_type<_Rep1, _Rep2>::type>::value, + duration::type, _Period> +>::type +operator/(const duration<_Rep1, _Period>& __d, const _Rep2& __s) +{ + typedef typename common_type<_Rep1, _Rep2>::type _Cr; + typedef duration<_Cr, _Period> _Cd; + return _Cd(_Cd(__d).count() / static_cast<_Cr>(__s)); +} + +template +inline _LIBCPP_INLINE_VISIBILITY +_LIBCPP_CONSTEXPR +typename common_type<_Rep1, _Rep2>::type +operator/(const duration<_Rep1, _Period1>& __lhs, const duration<_Rep2, _Period2>& __rhs) +{ + typedef typename common_type, duration<_Rep2, _Period2> >::type _Ct; + return _Ct(__lhs).count() / _Ct(__rhs).count(); +} + +// Duration % + +template +inline _LIBCPP_INLINE_VISIBILITY +_LIBCPP_CONSTEXPR +typename enable_if +< + !__is_duration<_Rep2>::value && + is_convertible<_Rep2, typename common_type<_Rep1, _Rep2>::type>::value, + duration::type, _Period> +>::type +operator%(const duration<_Rep1, _Period>& __d, const _Rep2& __s) +{ + typedef typename common_type<_Rep1, _Rep2>::type _Cr; + typedef duration<_Cr, _Period> _Cd; + return _Cd(_Cd(__d).count() % static_cast<_Cr>(__s)); +} + +template +inline _LIBCPP_INLINE_VISIBILITY +_LIBCPP_CONSTEXPR +typename common_type, duration<_Rep2, _Period2> >::type +operator%(const duration<_Rep1, _Period1>& __lhs, const duration<_Rep2, _Period2>& __rhs) +{ + typedef typename common_type<_Rep1, _Rep2>::type _Cr; + typedef typename common_type, duration<_Rep2, _Period2> >::type _Cd; + return _Cd(static_cast<_Cr>(_Cd(__lhs).count()) % static_cast<_Cr>(_Cd(__rhs).count())); +} + +} // namespace chrono + +#if _LIBCPP_STD_VER > 11 +// Suffixes for duration literals [time.duration.literals] +inline namespace literals +{ + inline namespace chrono_literals + { + + _LIBCPP_HIDE_FROM_ABI constexpr chrono::hours operator""h(unsigned long long __h) + { + return chrono::hours(static_cast(__h)); + } + + _LIBCPP_HIDE_FROM_ABI constexpr chrono::duration> operator""h(long double __h) + { + return chrono::duration>(__h); + } + + + _LIBCPP_HIDE_FROM_ABI constexpr chrono::minutes operator""min(unsigned long long __m) + { + return chrono::minutes(static_cast(__m)); + } + + _LIBCPP_HIDE_FROM_ABI constexpr chrono::duration> operator""min(long double __m) + { + return chrono::duration> (__m); + } + + + _LIBCPP_HIDE_FROM_ABI constexpr chrono::seconds operator""s(unsigned long long __s) + { + return chrono::seconds(static_cast(__s)); + } + + _LIBCPP_HIDE_FROM_ABI constexpr chrono::duration operator""s(long double __s) + { + return chrono::duration (__s); + } + + + _LIBCPP_HIDE_FROM_ABI constexpr chrono::milliseconds operator""ms(unsigned long long __ms) + { + return chrono::milliseconds(static_cast(__ms)); + } + + _LIBCPP_HIDE_FROM_ABI constexpr chrono::duration operator""ms(long double __ms) + { + return chrono::duration(__ms); + } + + + _LIBCPP_HIDE_FROM_ABI constexpr chrono::microseconds operator""us(unsigned long long __us) + { + return chrono::microseconds(static_cast(__us)); + } + + _LIBCPP_HIDE_FROM_ABI constexpr chrono::duration operator""us(long double __us) + { + return chrono::duration (__us); + } + + + _LIBCPP_HIDE_FROM_ABI constexpr chrono::nanoseconds operator""ns(unsigned long long __ns) + { + return chrono::nanoseconds(static_cast(__ns)); + } + + _LIBCPP_HIDE_FROM_ABI constexpr chrono::duration operator""ns(long double __ns) + { + return chrono::duration (__ns); + } + +} // namespace chrono_literals +} // namespace literals + +namespace chrono { // hoist the literals into namespace std::chrono + using namespace literals::chrono_literals; +} // namespace chrono + +#endif // _LIBCPP_STD_VER > 11 + +_LIBCPP_END_NAMESPACE_STD + +_LIBCPP_POP_MACROS + +#if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20 +# include +#endif + +#endif // _LIBCPP___CHRONO_DURATION_H diff --git a/app/src/main/cpp/libcxx/include/__chrono/file_clock.h b/app/src/main/cpp/libcxx/include/__chrono/file_clock.h new file mode 100644 index 0000000..ef62b83 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__chrono/file_clock.h @@ -0,0 +1,85 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___CHRONO_FILE_CLOCK_H +#define _LIBCPP___CHRONO_FILE_CLOCK_H + +#include <__availability> +#include <__chrono/duration.h> +#include <__chrono/system_clock.h> +#include <__chrono/time_point.h> +#include <__config> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#ifndef _LIBCPP_CXX03_LANG +_LIBCPP_BEGIN_NAMESPACE_FILESYSTEM +struct _FilesystemClock; +_LIBCPP_END_NAMESPACE_FILESYSTEM +#endif // !_LIBCPP_CXX03_LANG + +#if _LIBCPP_STD_VER > 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace chrono +{ + +// [time.clock.file], type file_clock +using file_clock = _VSTD_FS::_FilesystemClock; + +template +using file_time = time_point; + +} // namespace chrono + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER > 17 + +#ifndef _LIBCPP_CXX03_LANG +_LIBCPP_BEGIN_NAMESPACE_FILESYSTEM +struct _FilesystemClock { +#if !defined(_LIBCPP_HAS_NO_INT128) + typedef __int128_t rep; + typedef nano period; +#else + typedef long long rep; + typedef nano period; +#endif + + typedef chrono::duration duration; + typedef chrono::time_point<_FilesystemClock> time_point; + + _LIBCPP_EXPORTED_FROM_ABI + static _LIBCPP_CONSTEXPR_SINCE_CXX14 const bool is_steady = false; + + _LIBCPP_AVAILABILITY_FILESYSTEM _LIBCPP_FUNC_VIS static time_point now() noexcept; + +#if _LIBCPP_STD_VER > 17 + template + _LIBCPP_HIDE_FROM_ABI + static chrono::sys_time<_Duration> to_sys(const chrono::file_time<_Duration>& __t) { + return chrono::sys_time<_Duration>(__t.time_since_epoch()); + } + + template + _LIBCPP_HIDE_FROM_ABI + static chrono::file_time<_Duration> from_sys(const chrono::sys_time<_Duration>& __t) { + return chrono::file_time<_Duration>(__t.time_since_epoch()); + } +#endif // _LIBCPP_STD_VER > 17 +}; +_LIBCPP_END_NAMESPACE_FILESYSTEM +#endif // !_LIBCPP_CXX03_LANG + +#endif // _LIBCPP___CHRONO_FILE_CLOCK_H diff --git a/app/src/main/cpp/libcxx/include/__chrono/formatter.h b/app/src/main/cpp/libcxx/include/__chrono/formatter.h new file mode 100644 index 0000000..2015783 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__chrono/formatter.h @@ -0,0 +1,716 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___CHRONO_FORMATTER_H +#define _LIBCPP___CHRONO_FORMATTER_H + +#include <__chrono/calendar.h> +#include <__chrono/convert_to_tm.h> +#include <__chrono/day.h> +#include <__chrono/duration.h> +#include <__chrono/hh_mm_ss.h> +#include <__chrono/month.h> +#include <__chrono/month_weekday.h> +#include <__chrono/monthday.h> +#include <__chrono/ostream.h> +#include <__chrono/parser_std_format_spec.h> +#include <__chrono/statically_widen.h> +#include <__chrono/time_point.h> +#include <__chrono/weekday.h> +#include <__chrono/year.h> +#include <__chrono/year_month.h> +#include <__chrono/year_month_day.h> +#include <__chrono/year_month_weekday.h> +#include <__concepts/arithmetic.h> +#include <__concepts/same_as.h> +#include <__config> +#include <__format/concepts.h> +#include <__format/format_error.h> +#include <__format/format_functions.h> +#include <__format/format_parse_context.h> +#include <__format/formatter.h> +#include <__format/formatter_output.h> +#include <__format/parser_std_format_spec.h> +#include <__memory/addressof.h> +#include +#include +#include +#include +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_FORMAT) + +namespace __formatter { + +/// Formats a time based on a tm struct. +/// +/// This formatter passes the formatting to time_put which uses strftime. When +/// the value is outside the valid range it's unspecified what strftime will +/// output. For example weekday 8 can print 1 when the day is processed modulo +/// 7 since that handles the Sunday for 0-based weekday. It can also print 8 if +/// 7 is handled as a special case. +/// +/// The Standard doesn't specify what to do in this case so the result depends +/// on the result of the underlying code. +/// +/// \pre When the (abbreviated) weekday or month name are used, the caller +/// validates whether the value is valid. So the caller handles that +/// requirement of Table 97: Meaning of conversion specifiers +/// [tab:time.format.spec]. +/// +/// When no chrono-specs are provided it uses the stream formatter. + +// For tiny ratios it's not possible to convert a duration to a hh_mm_ss. This +// fails compile-time due to the limited precision of the ratio (64-bit is too +// small). Therefore a duration uses its own conversion. +template + requires(chrono::__is_duration<_Tp>::value) +_LIBCPP_HIDE_FROM_ABI void __format_sub_seconds(const _Tp& __value, basic_stringstream<_CharT>& __sstr) { + __sstr << std::use_facet>(__sstr.getloc()).decimal_point(); + + auto __fraction = __value - chrono::duration_cast(__value); + if constexpr (chrono::treat_as_floating_point_v) + // When the floating-point value has digits itself they are ignored based + // on the wording in [tab:time.format.spec] + // If the precision of the input cannot be exactly represented with + // seconds, then the format is a decimal floating-point number with a + // fixed format and a precision matching that of the precision of the + // input (or to a microseconds precision if the conversion to + // floating-point decimal seconds cannot be made within 18 fractional + // digits). + // + // This matches the behaviour of MSVC STL, fmtlib interprets this + // differently and uses 3 decimals. + // https://godbolt.org/z/6dsbnW8ba + std::format_to(std::ostreambuf_iterator<_CharT>{__sstr}, + _LIBCPP_STATICALLY_WIDEN(_CharT, "{:0{}.0f}"), + __fraction.count(), + chrono::hh_mm_ss<_Tp>::fractional_width); + else + std::format_to(std::ostreambuf_iterator<_CharT>{__sstr}, + _LIBCPP_STATICALLY_WIDEN(_CharT, "{:0{}}"), + __fraction.count(), + chrono::hh_mm_ss<_Tp>::fractional_width); +} + +template +consteval bool __use_fraction() { + if constexpr (chrono::__is_duration<_Tp>::value) + return chrono::hh_mm_ss<_Tp>::fractional_width; + else + return false; +} + +template +_LIBCPP_HIDE_FROM_ABI void __format_year(int __year, basic_stringstream<_CharT>& __sstr) { + if (__year < 0) { + __sstr << _CharT('-'); + __year = -__year; + } + + // TODO FMT Write an issue + // If the result has less than four digits it is zero-padded with 0 to two digits. + // is less -> has less + // left-padded -> zero-padded, otherwise the proper value would be 000-0. + + // Note according to the wording it should be left padded, which is odd. + __sstr << std::format(_LIBCPP_STATICALLY_WIDEN(_CharT, "{:04}"), __year); +} + +template +_LIBCPP_HIDE_FROM_ABI void __format_century(int __year, basic_stringstream<_CharT>& __sstr) { + // TODO FMT Write an issue + // [tab:time.format.spec] + // %C The year divided by 100 using floored division. If the result is a + // single decimal digit, it is prefixed with 0. + + bool __negative = __year < 0; + int __century = (__year - (99 * __negative)) / 100; // floored division + __sstr << std::format(_LIBCPP_STATICALLY_WIDEN(_CharT, "{:02}"), __century); +} + +template +_LIBCPP_HIDE_FROM_ABI void __format_chrono_using_chrono_specs( + const _Tp& __value, basic_stringstream<_CharT>& __sstr, basic_string_view<_CharT> __chrono_specs) { + tm __t = std::__convert_to_tm(__value); + const auto& __facet = std::use_facet>(__sstr.getloc()); + for (auto __it = __chrono_specs.begin(); __it != __chrono_specs.end(); ++__it) { + if (*__it == _CharT('%')) { + auto __s = __it; + ++__it; + // We only handle the types that can't be directly handled by time_put. + // (as an optimization n, t, and % are also handled directly.) + switch (*__it) { + case _CharT('n'): + __sstr << _CharT('\n'); + break; + case _CharT('t'): + __sstr << _CharT('\t'); + break; + case _CharT('%'): + __sstr << *__it; + break; + + case _CharT('C'): { + // strftime's output is only defined in the range [00, 99]. + int __year = __t.tm_year + 1900; + if (__year < 1000 || __year > 9999) + __formatter::__format_century(__year, __sstr); + else + __facet.put({__sstr}, __sstr, _CharT(' '), std::addressof(__t), __s, __it + 1); + } break; + + case _CharT('j'): + if constexpr (chrono::__is_duration<_Tp>::value) + // Converting a duration where the period has a small ratio to days + // may fail to compile. This due to loss of precision in the + // conversion. In order to avoid that issue convert to seconds as + // an intemediate step. + __sstr << chrono::duration_cast(chrono::duration_cast(__value)).count(); + else + __facet.put({__sstr}, __sstr, _CharT(' '), std::addressof(__t), __s, __it + 1); + break; + + case _CharT('q'): + if constexpr (chrono::__is_duration<_Tp>::value) { + __sstr << chrono::__units_suffix<_CharT, typename _Tp::period>(); + break; + } + __builtin_unreachable(); + + case _CharT('Q'): + // TODO FMT Determine the proper ideas + // - Should it honour the precision? + // - Shoult it honour the locale setting for the separators? + // The wording for Q doesn't use the word locale and the effect of + // precision is unspecified. + // + // MSVC STL ignores precision but uses separator + // FMT honours precision and has a bug for separator + // https://godbolt.org/z/78b7sMxns + if constexpr (chrono::__is_duration<_Tp>::value) { + __sstr << std::format(_LIBCPP_STATICALLY_WIDEN(_CharT, "{}"), __value.count()); + break; + } + __builtin_unreachable(); + + case _CharT('S'): + case _CharT('T'): + __facet.put({__sstr}, __sstr, _CharT(' '), std::addressof(__t), __s, __it + 1); + if constexpr (__use_fraction<_Tp>()) + __formatter::__format_sub_seconds(__value, __sstr); + break; + + // Unlike time_put and strftime the formatting library requires %Y + // + // [tab:time.format.spec] + // The year as a decimal number. If the result is less than four digits + // it is left-padded with 0 to four digits. + // + // This means years in the range (-1000, 1000) need manual formatting. + // It's unclear whether %EY needs the same treatment. For example the + // Japanese EY contains the era name and year. This is zero-padded to 2 + // digits in time_put (note that older glibc versions didn't do + // padding.) However most eras won't reach 100 years, let alone 1000. + // So padding to 4 digits seems unwanted for Japanese. + // + // The same applies to %Ex since that too depends on the era. + // + // %x the locale's date representation is currently doesn't handle the + // zero-padding too. + // + // The 4 digits can be implemented better at a later time. On POSIX + // systems the required information can be extracted by nl_langinfo + // https://man7.org/linux/man-pages/man3/nl_langinfo.3.html + // + // Note since year < -1000 is expected to be rare it uses the more + // expensive year routine. + // + // TODO FMT evaluate the comment above. + +# if defined(__GLIBC__) || defined(_AIX) + case _CharT('y'): + // Glibc fails for negative values, AIX for positive values too. + __sstr << std::format(_LIBCPP_STATICALLY_WIDEN(_CharT, "{:02}"), (std::abs(__t.tm_year + 1900)) % 100); + break; +# endif // defined(__GLIBC__) || defined(_AIX) + + case _CharT('Y'): { + int __year = __t.tm_year + 1900; + if (__year < 1000) + __formatter::__format_year(__year, __sstr); + else + __facet.put({__sstr}, __sstr, _CharT(' '), std::addressof(__t), __s, __it + 1); + } break; + + case _CharT('F'): { + int __year = __t.tm_year + 1900; + if (__year < 1000) { + __formatter::__format_year(__year, __sstr); + __sstr << std::format(_LIBCPP_STATICALLY_WIDEN(_CharT, "-{:02}-{:02}"), __t.tm_mon + 1, __t.tm_mday); + } else + __facet.put({__sstr}, __sstr, _CharT(' '), std::addressof(__t), __s, __it + 1); + } break; + + case _CharT('O'): + if constexpr (__use_fraction<_Tp>()) { + // Handle OS using the normal representation for the non-fractional + // part. There seems to be no locale information regarding how the + // fractional part should be formatted. + if (*(__it + 1) == 'S') { + ++__it; + __facet.put({__sstr}, __sstr, _CharT(' '), std::addressof(__t), __s, __it + 1); + __formatter::__format_sub_seconds(__value, __sstr); + break; + } + } + [[fallthrough]]; + case _CharT('E'): + ++__it; + [[fallthrough]]; + default: + __facet.put({__sstr}, __sstr, _CharT(' '), std::addressof(__t), __s, __it + 1); + break; + } + } else { + __sstr << *__it; + } + } +} + +template +_LIBCPP_HIDE_FROM_ABI constexpr bool __weekday_ok(const _Tp& __value) { + if constexpr (same_as<_Tp, chrono::day>) + return true; + else if constexpr (same_as<_Tp, chrono::month>) + return __value.ok(); + else if constexpr (same_as<_Tp, chrono::year>) + return true; + else if constexpr (same_as<_Tp, chrono::weekday>) + return true; + else if constexpr (same_as<_Tp, chrono::weekday_indexed>) + return true; + else if constexpr (same_as<_Tp, chrono::weekday_last>) + return true; + else if constexpr (same_as<_Tp, chrono::month_day>) + return true; + else if constexpr (same_as<_Tp, chrono::month_day_last>) + return true; + else if constexpr (same_as<_Tp, chrono::month_weekday>) + return true; + else if constexpr (same_as<_Tp, chrono::month_weekday_last>) + return true; + else if constexpr (same_as<_Tp, chrono::year_month>) + return true; + else if constexpr (same_as<_Tp, chrono::year_month_day>) + return __value.ok(); + else if constexpr (same_as<_Tp, chrono::year_month_day_last>) + return __value.ok(); + else if constexpr (same_as<_Tp, chrono::year_month_weekday>) + return __value.weekday().ok(); + else if constexpr (same_as<_Tp, chrono::year_month_weekday_last>) + return __value.weekday().ok(); + else + static_assert(sizeof(_Tp) == 0, "Add the missing type specialization"); +} + +template +_LIBCPP_HIDE_FROM_ABI constexpr bool __weekday_name_ok(const _Tp& __value) { + if constexpr (same_as<_Tp, chrono::day>) + return true; + else if constexpr (same_as<_Tp, chrono::month>) + return __value.ok(); + else if constexpr (same_as<_Tp, chrono::year>) + return true; + else if constexpr (same_as<_Tp, chrono::weekday>) + return __value.ok(); + else if constexpr (same_as<_Tp, chrono::weekday_indexed>) + return __value.weekday().ok(); + else if constexpr (same_as<_Tp, chrono::weekday_last>) + return __value.weekday().ok(); + else if constexpr (same_as<_Tp, chrono::month_day>) + return true; + else if constexpr (same_as<_Tp, chrono::month_day_last>) + return true; + else if constexpr (same_as<_Tp, chrono::month_weekday>) + return __value.weekday_indexed().ok(); + else if constexpr (same_as<_Tp, chrono::month_weekday_last>) + return __value.weekday_indexed().ok(); + else if constexpr (same_as<_Tp, chrono::year_month>) + return true; + else if constexpr (same_as<_Tp, chrono::year_month_day>) + return __value.ok(); + else if constexpr (same_as<_Tp, chrono::year_month_day_last>) + return __value.ok(); + else if constexpr (same_as<_Tp, chrono::year_month_weekday>) + return __value.weekday().ok(); + else if constexpr (same_as<_Tp, chrono::year_month_weekday_last>) + return __value.weekday().ok(); + else + static_assert(sizeof(_Tp) == 0, "Add the missing type specialization"); +} + +template +_LIBCPP_HIDE_FROM_ABI constexpr bool __date_ok(const _Tp& __value) { + if constexpr (same_as<_Tp, chrono::day>) + return true; + else if constexpr (same_as<_Tp, chrono::month>) + return __value.ok(); + else if constexpr (same_as<_Tp, chrono::year>) + return true; + else if constexpr (same_as<_Tp, chrono::weekday>) + return true; + else if constexpr (same_as<_Tp, chrono::weekday_indexed>) + return true; + else if constexpr (same_as<_Tp, chrono::weekday_last>) + return true; + else if constexpr (same_as<_Tp, chrono::month_day>) + return true; + else if constexpr (same_as<_Tp, chrono::month_day_last>) + return true; + else if constexpr (same_as<_Tp, chrono::month_weekday>) + return true; + else if constexpr (same_as<_Tp, chrono::month_weekday_last>) + return true; + else if constexpr (same_as<_Tp, chrono::year_month>) + return true; + else if constexpr (same_as<_Tp, chrono::year_month_day>) + return __value.ok(); + else if constexpr (same_as<_Tp, chrono::year_month_day_last>) + return __value.ok(); + else if constexpr (same_as<_Tp, chrono::year_month_weekday>) + return __value.ok(); + else if constexpr (same_as<_Tp, chrono::year_month_weekday_last>) + return __value.ok(); + else + static_assert(sizeof(_Tp) == 0, "Add the missing type specialization"); +} + +template +_LIBCPP_HIDE_FROM_ABI constexpr bool __month_name_ok(const _Tp& __value) { + if constexpr (same_as<_Tp, chrono::day>) + return true; + else if constexpr (same_as<_Tp, chrono::month>) + return __value.ok(); + else if constexpr (same_as<_Tp, chrono::year>) + return true; + else if constexpr (same_as<_Tp, chrono::weekday>) + return true; + else if constexpr (same_as<_Tp, chrono::weekday_indexed>) + return true; + else if constexpr (same_as<_Tp, chrono::weekday_last>) + return true; + else if constexpr (same_as<_Tp, chrono::month_day>) + return __value.month().ok(); + else if constexpr (same_as<_Tp, chrono::month_day_last>) + return __value.month().ok(); + else if constexpr (same_as<_Tp, chrono::month_weekday>) + return __value.month().ok(); + else if constexpr (same_as<_Tp, chrono::month_weekday_last>) + return __value.month().ok(); + else if constexpr (same_as<_Tp, chrono::year_month>) + return __value.month().ok(); + else if constexpr (same_as<_Tp, chrono::year_month_day>) + return __value.month().ok(); + else if constexpr (same_as<_Tp, chrono::year_month_day_last>) + return __value.month().ok(); + else if constexpr (same_as<_Tp, chrono::year_month_weekday>) + return __value.month().ok(); + else if constexpr (same_as<_Tp, chrono::year_month_weekday_last>) + return __value.month().ok(); + else + static_assert(sizeof(_Tp) == 0, "Add the missing type specialization"); +} + +template +_LIBCPP_HIDE_FROM_ABI auto +__format_chrono(const _Tp& __value, + auto& __ctx, + __format_spec::__parsed_specifications<_CharT> __specs, + basic_string_view<_CharT> __chrono_specs) -> decltype(__ctx.out()) { + basic_stringstream<_CharT> __sstr; + // [time.format]/2 + // 2.1 - the "C" locale if the L option is not present in chrono-format-spec, otherwise + // 2.2 - the locale passed to the formatting function if any, otherwise + // 2.3 - the global locale. + // Note that the __ctx's locale() call does 2.2 and 2.3. + if (__specs.__chrono_.__locale_specific_form_) + __sstr.imbue(__ctx.locale()); + else + __sstr.imbue(locale::classic()); + + if (__chrono_specs.empty()) + __sstr << __value; + else { + if constexpr (chrono::__is_duration<_Tp>::value) { + if (__value < __value.zero()) + __sstr << _CharT('-'); + __formatter::__format_chrono_using_chrono_specs(chrono::abs(__value), __sstr, __chrono_specs); + // TODO FMT When keeping the precision it will truncate the string. + // Note that the behaviour what the precision does isn't specified. + __specs.__precision_ = -1; + } else { + // Test __weekday_name_ before __weekday_ to give a better error. + if (__specs.__chrono_.__weekday_name_ && !__formatter::__weekday_name_ok(__value)) + std::__throw_format_error("formatting a weekday name needs a valid weekday"); + + if (__specs.__chrono_.__weekday_ && !__formatter::__weekday_ok(__value)) + std::__throw_format_error("formatting a weekday needs a valid weekday"); + + if (__specs.__chrono_.__day_of_year_ && !__formatter::__date_ok(__value)) + std::__throw_format_error("formatting a day of year needs a valid date"); + + if (__specs.__chrono_.__week_of_year_ && !__formatter::__date_ok(__value)) + std::__throw_format_error("formatting a week of year needs a valid date"); + + if (__specs.__chrono_.__month_name_ && !__formatter::__month_name_ok(__value)) + std::__throw_format_error("formatting a month name from an invalid month number"); + + __formatter::__format_chrono_using_chrono_specs(__value, __sstr, __chrono_specs); + } + } + + // TODO FMT Use the stringstream's view after P0408R7 has been implemented. + basic_string<_CharT> __str = __sstr.str(); + return __formatter::__write_string(basic_string_view<_CharT>{__str}, __ctx.out(), __specs); +} + +} // namespace __formatter + +template <__fmt_char_type _CharT> +struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT __formatter_chrono { +public: + _LIBCPP_HIDE_FROM_ABI constexpr auto __parse( + basic_format_parse_context<_CharT>& __parse_ctx, __format_spec::__fields __fields, __format_spec::__flags __flags) + -> decltype(__parse_ctx.begin()) { + return __parser_.__parse(__parse_ctx, __fields, __flags); + } + + template + _LIBCPP_HIDE_FROM_ABI auto format(const _Tp& __value, auto& __ctx) const -> decltype(__ctx.out()) const { + return __formatter::__format_chrono( + __value, __ctx, __parser_.__parser_.__get_parsed_chrono_specifications(__ctx), __parser_.__chrono_specs_); + } + + __format_spec::__parser_chrono<_CharT> __parser_; +}; + +template +struct formatter, _CharT> : public __formatter_chrono<_CharT> { +public: + using _Base = __formatter_chrono<_CharT>; + + _LIBCPP_HIDE_FROM_ABI constexpr auto parse(basic_format_parse_context<_CharT>& __parse_ctx) + -> decltype(__parse_ctx.begin()) { + // [time.format]/1 + // Giving a precision specification in the chrono-format-spec is valid only + // for std::chrono::duration types where the representation type Rep is a + // floating-point type. For all other Rep types, an exception of type + // format_error is thrown if the chrono-format-spec contains a precision + // specification. + // + // Note this doesn't refer to chrono::treat_as_floating_point_v<_Rep>. + if constexpr (std::floating_point<_Rep>) + return _Base::__parse(__parse_ctx, __format_spec::__fields_chrono_fractional, __format_spec::__flags::__duration); + else + return _Base::__parse(__parse_ctx, __format_spec::__fields_chrono, __format_spec::__flags::__duration); + } +}; + +template <__fmt_char_type _CharT> +struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter + : public __formatter_chrono<_CharT> { +public: + using _Base = __formatter_chrono<_CharT>; + + _LIBCPP_HIDE_FROM_ABI constexpr auto parse(basic_format_parse_context<_CharT>& __parse_ctx) + -> decltype(__parse_ctx.begin()) { + return _Base::__parse(__parse_ctx, __format_spec::__fields_chrono, __format_spec::__flags::__day); + } +}; + +template <__fmt_char_type _CharT> +struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter + : public __formatter_chrono<_CharT> { +public: + using _Base = __formatter_chrono<_CharT>; + + _LIBCPP_HIDE_FROM_ABI constexpr auto parse(basic_format_parse_context<_CharT>& __parse_ctx) + -> decltype(__parse_ctx.begin()) { + return _Base::__parse(__parse_ctx, __format_spec::__fields_chrono, __format_spec::__flags::__month); + } +}; + +template <__fmt_char_type _CharT> +struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter + : public __formatter_chrono<_CharT> { +public: + using _Base = __formatter_chrono<_CharT>; + + _LIBCPP_HIDE_FROM_ABI constexpr auto parse(basic_format_parse_context<_CharT>& __parse_ctx) + -> decltype(__parse_ctx.begin()) { + return _Base::__parse(__parse_ctx, __format_spec::__fields_chrono, __format_spec::__flags::__year); + } +}; + +template <__fmt_char_type _CharT> +struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter + : public __formatter_chrono<_CharT> { +public: + using _Base = __formatter_chrono<_CharT>; + + _LIBCPP_HIDE_FROM_ABI constexpr auto parse(basic_format_parse_context<_CharT>& __parse_ctx) + -> decltype(__parse_ctx.begin()) { + return _Base::__parse(__parse_ctx, __format_spec::__fields_chrono, __format_spec::__flags::__weekday); + } +}; + +template <__fmt_char_type _CharT> +struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter + : public __formatter_chrono<_CharT> { +public: + using _Base = __formatter_chrono<_CharT>; + + _LIBCPP_HIDE_FROM_ABI constexpr auto parse(basic_format_parse_context<_CharT>& __parse_ctx) + -> decltype(__parse_ctx.begin()) { + return _Base::__parse(__parse_ctx, __format_spec::__fields_chrono, __format_spec::__flags::__weekday); + } +}; + +template <__fmt_char_type _CharT> +struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter + : public __formatter_chrono<_CharT> { +public: + using _Base = __formatter_chrono<_CharT>; + + _LIBCPP_HIDE_FROM_ABI constexpr auto parse(basic_format_parse_context<_CharT>& __parse_ctx) + -> decltype(__parse_ctx.begin()) { + return _Base::__parse(__parse_ctx, __format_spec::__fields_chrono, __format_spec::__flags::__weekday); + } +}; + +template <__fmt_char_type _CharT> +struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter + : public __formatter_chrono<_CharT> { +public: + using _Base = __formatter_chrono<_CharT>; + + _LIBCPP_HIDE_FROM_ABI constexpr auto parse(basic_format_parse_context<_CharT>& __parse_ctx) + -> decltype(__parse_ctx.begin()) { + return _Base::__parse(__parse_ctx, __format_spec::__fields_chrono, __format_spec::__flags::__month_day); + } +}; + +template <__fmt_char_type _CharT> +struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter + : public __formatter_chrono<_CharT> { +public: + using _Base = __formatter_chrono<_CharT>; + + _LIBCPP_HIDE_FROM_ABI constexpr auto parse(basic_format_parse_context<_CharT>& __parse_ctx) + -> decltype(__parse_ctx.begin()) { + return _Base::__parse(__parse_ctx, __format_spec::__fields_chrono, __format_spec::__flags::__month); + } +}; + +template <__fmt_char_type _CharT> +struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter + : public __formatter_chrono<_CharT> { +public: + using _Base = __formatter_chrono<_CharT>; + + _LIBCPP_HIDE_FROM_ABI constexpr auto parse(basic_format_parse_context<_CharT>& __parse_ctx) + -> decltype(__parse_ctx.begin()) { + return _Base::__parse(__parse_ctx, __format_spec::__fields_chrono, __format_spec::__flags::__month_weekday); + } +}; + +template <__fmt_char_type _CharT> +struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter + : public __formatter_chrono<_CharT> { +public: + using _Base = __formatter_chrono<_CharT>; + + _LIBCPP_HIDE_FROM_ABI constexpr auto parse(basic_format_parse_context<_CharT>& __parse_ctx) + -> decltype(__parse_ctx.begin()) { + return _Base::__parse(__parse_ctx, __format_spec::__fields_chrono, __format_spec::__flags::__month_weekday); + } +}; + +template <__fmt_char_type _CharT> +struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter + : public __formatter_chrono<_CharT> { +public: + using _Base = __formatter_chrono<_CharT>; + + _LIBCPP_HIDE_FROM_ABI constexpr auto parse(basic_format_parse_context<_CharT>& __parse_ctx) + -> decltype(__parse_ctx.begin()) { + return _Base::__parse(__parse_ctx, __format_spec::__fields_chrono, __format_spec::__flags::__year_month); + } +}; + +template <__fmt_char_type _CharT> +struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter + : public __formatter_chrono<_CharT> { +public: + using _Base = __formatter_chrono<_CharT>; + + _LIBCPP_HIDE_FROM_ABI constexpr auto parse(basic_format_parse_context<_CharT>& __parse_ctx) + -> decltype(__parse_ctx.begin()) { + return _Base::__parse(__parse_ctx, __format_spec::__fields_chrono, __format_spec::__flags::__date); + } +}; + +template <__fmt_char_type _CharT> +struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter + : public __formatter_chrono<_CharT> { +public: + using _Base = __formatter_chrono<_CharT>; + + _LIBCPP_HIDE_FROM_ABI constexpr auto parse(basic_format_parse_context<_CharT>& __parse_ctx) + -> decltype(__parse_ctx.begin()) { + return _Base::__parse(__parse_ctx, __format_spec::__fields_chrono, __format_spec::__flags::__date); + } +}; + +template <__fmt_char_type _CharT> +struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter + : public __formatter_chrono<_CharT> { +public: + using _Base = __formatter_chrono<_CharT>; + + _LIBCPP_HIDE_FROM_ABI constexpr auto parse(basic_format_parse_context<_CharT>& __parse_ctx) + -> decltype(__parse_ctx.begin()) { + return _Base::__parse(__parse_ctx, __format_spec::__fields_chrono, __format_spec::__flags::__date); + } +}; + +template <__fmt_char_type _CharT> +struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter + : public __formatter_chrono<_CharT> { +public: + using _Base = __formatter_chrono<_CharT>; + + _LIBCPP_HIDE_FROM_ABI constexpr auto parse(basic_format_parse_context<_CharT>& __parse_ctx) + -> decltype(__parse_ctx.begin()) { + return _Base::__parse(__parse_ctx, __format_spec::__fields_chrono, __format_spec::__flags::__date); + } +}; + +#endif // if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_FORMAT) + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___CHRONO_FORMATTER_H diff --git a/app/src/main/cpp/libcxx/include/__chrono/hh_mm_ss.h b/app/src/main/cpp/libcxx/include/__chrono/hh_mm_ss.h new file mode 100644 index 0000000..fd61cbe --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__chrono/hh_mm_ss.h @@ -0,0 +1,112 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___CHRONO_HH_MM_SS_H +#define _LIBCPP___CHRONO_HH_MM_SS_H + +#include <__chrono/duration.h> +#include <__chrono/time_point.h> +#include <__config> +#include +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if _LIBCPP_STD_VER > 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace chrono +{ + +template +class hh_mm_ss +{ +private: + static_assert(__is_duration<_Duration>::value, "template parameter of hh_mm_ss must be a std::chrono::duration"); + using __CommonType = common_type_t<_Duration, chrono::seconds>; + + _LIBCPP_HIDE_FROM_ABI static constexpr uint64_t __pow10(unsigned __exp) + { + uint64_t __ret = 1; + for (unsigned __i = 0; __i < __exp; ++__i) + __ret *= 10U; + return __ret; + } + + _LIBCPP_HIDE_FROM_ABI static constexpr unsigned __width(uint64_t __n, uint64_t __d = 10, unsigned __w = 0) + { + if (__n >= 2 && __d != 0 && __w < 19) + return 1 + __width(__n, __d % __n * 10, __w+1); + return 0; + } + +public: + _LIBCPP_HIDE_FROM_ABI static unsigned constexpr fractional_width = __width(__CommonType::period::den) < 19 ? + __width(__CommonType::period::den) : 6u; + using precision = duration>; + + _LIBCPP_HIDE_FROM_ABI constexpr hh_mm_ss() noexcept : hh_mm_ss{_Duration::zero()} {} + + _LIBCPP_HIDE_FROM_ABI constexpr explicit hh_mm_ss(_Duration __d) noexcept : + __is_neg_(__d < _Duration(0)), + __h_(chrono::duration_cast (chrono::abs(__d))), + __m_(chrono::duration_cast(chrono::abs(__d) - hours())), + __s_(chrono::duration_cast(chrono::abs(__d) - hours() - minutes())), + __f_(chrono::duration_cast (chrono::abs(__d) - hours() - minutes() - seconds())) + {} + + _LIBCPP_HIDE_FROM_ABI constexpr bool is_negative() const noexcept { return __is_neg_; } + _LIBCPP_HIDE_FROM_ABI constexpr chrono::hours hours() const noexcept { return __h_; } + _LIBCPP_HIDE_FROM_ABI constexpr chrono::minutes minutes() const noexcept { return __m_; } + _LIBCPP_HIDE_FROM_ABI constexpr chrono::seconds seconds() const noexcept { return __s_; } + _LIBCPP_HIDE_FROM_ABI constexpr precision subseconds() const noexcept { return __f_; } + + _LIBCPP_HIDE_FROM_ABI constexpr precision to_duration() const noexcept + { + auto __dur = __h_ + __m_ + __s_ + __f_; + return __is_neg_ ? -__dur : __dur; + } + + _LIBCPP_HIDE_FROM_ABI constexpr explicit operator precision() const noexcept { return to_duration(); } + +private: + bool __is_neg_; + chrono::hours __h_; + chrono::minutes __m_; + chrono::seconds __s_; + precision __f_; +}; + +_LIBCPP_HIDE_FROM_ABI constexpr bool is_am(const hours& __h) noexcept { return __h >= hours( 0) && __h < hours(12); } +_LIBCPP_HIDE_FROM_ABI constexpr bool is_pm(const hours& __h) noexcept { return __h >= hours(12) && __h < hours(24); } + +_LIBCPP_HIDE_FROM_ABI constexpr hours make12(const hours& __h) noexcept +{ + if (__h == hours( 0)) return hours(12); + else if (__h <= hours(12)) return __h; + else return __h - hours(12); +} + +_LIBCPP_HIDE_FROM_ABI constexpr hours make24(const hours& __h, bool __is_pm) noexcept +{ + if (__is_pm) + return __h == hours(12) ? __h : __h + hours(12); + else + return __h == hours(12) ? hours(0) : __h; +} +} // namespace chrono + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER > 17 + +#endif // _LIBCPP___CHRONO_HH_MM_SS_H diff --git a/app/src/main/cpp/libcxx/include/__chrono/high_resolution_clock.h b/app/src/main/cpp/libcxx/include/__chrono/high_resolution_clock.h new file mode 100644 index 0000000..778ff44 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__chrono/high_resolution_clock.h @@ -0,0 +1,36 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___CHRONO_HIGH_RESOLUTION_CLOCK_H +#define _LIBCPP___CHRONO_HIGH_RESOLUTION_CLOCK_H + +#include <__chrono/steady_clock.h> +#include <__chrono/system_clock.h> +#include <__config> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace chrono +{ + +#ifndef _LIBCPP_HAS_NO_MONOTONIC_CLOCK +typedef steady_clock high_resolution_clock; +#else +typedef system_clock high_resolution_clock; +#endif + +} // namespace chrono + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___CHRONO_HIGH_RESOLUTION_CLOCK_H diff --git a/app/src/main/cpp/libcxx/include/__chrono/literals.h b/app/src/main/cpp/libcxx/include/__chrono/literals.h new file mode 100644 index 0000000..50529bd --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__chrono/literals.h @@ -0,0 +1,49 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___CHRONO_LITERALS_H +#define _LIBCPP___CHRONO_LITERALS_H + +#include <__chrono/day.h> +#include <__chrono/year.h> +#include <__config> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if _LIBCPP_STD_VER > 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +inline namespace literals +{ + inline namespace chrono_literals + { + _LIBCPP_HIDE_FROM_ABI constexpr chrono::day operator ""d(unsigned long long __d) noexcept + { + return chrono::day(static_cast(__d)); + } + + _LIBCPP_HIDE_FROM_ABI constexpr chrono::year operator ""y(unsigned long long __y) noexcept + { + return chrono::year(static_cast(__y)); + } +} // namespace chrono_literals +} // namespace literals + +namespace chrono { // hoist the literals into namespace std::chrono + using namespace literals::chrono_literals; +} // namespace chrono + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER > 17 + +#endif // _LIBCPP___CHRONO_LITERALS_H diff --git a/app/src/main/cpp/libcxx/include/__chrono/month.h b/app/src/main/cpp/libcxx/include/__chrono/month.h new file mode 100644 index 0000000..e929f24 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__chrono/month.h @@ -0,0 +1,103 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___CHRONO_MONTH_H +#define _LIBCPP___CHRONO_MONTH_H + +#include <__chrono/duration.h> +#include <__config> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if _LIBCPP_STD_VER > 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace chrono +{ + +class month { +private: + unsigned char __m_; +public: + _LIBCPP_HIDE_FROM_ABI month() = default; + _LIBCPP_HIDE_FROM_ABI explicit inline constexpr month(unsigned __val) noexcept : __m_(static_cast(__val)) {} + _LIBCPP_HIDE_FROM_ABI inline constexpr month& operator++() noexcept { ++__m_; return *this; } + _LIBCPP_HIDE_FROM_ABI inline constexpr month operator++(int) noexcept { month __tmp = *this; ++(*this); return __tmp; } + _LIBCPP_HIDE_FROM_ABI inline constexpr month& operator--() noexcept { --__m_; return *this; } + _LIBCPP_HIDE_FROM_ABI inline constexpr month operator--(int) noexcept { month __tmp = *this; --(*this); return __tmp; } + _LIBCPP_HIDE_FROM_ABI constexpr month& operator+=(const months& __m1) noexcept; + _LIBCPP_HIDE_FROM_ABI constexpr month& operator-=(const months& __m1) noexcept; + _LIBCPP_HIDE_FROM_ABI explicit inline constexpr operator unsigned() const noexcept { return __m_; } + _LIBCPP_HIDE_FROM_ABI inline constexpr bool ok() const noexcept { return __m_ >= 1 && __m_ <= 12; } +}; + + +_LIBCPP_HIDE_FROM_ABI inline constexpr +bool operator==(const month& __lhs, const month& __rhs) noexcept +{ return static_cast(__lhs) == static_cast(__rhs); } + +_LIBCPP_HIDE_FROM_ABI constexpr strong_ordering operator<=>(const month& __lhs, const month& __rhs) noexcept { + return static_cast(__lhs) <=> static_cast(__rhs); +} + +_LIBCPP_HIDE_FROM_ABI inline constexpr +month operator+ (const month& __lhs, const months& __rhs) noexcept +{ + auto const __mu = static_cast(static_cast(__lhs)) + (__rhs.count() - 1); + auto const __yr = (__mu >= 0 ? __mu : __mu - 11) / 12; + return month{static_cast(__mu - __yr * 12 + 1)}; +} + +_LIBCPP_HIDE_FROM_ABI inline constexpr +month operator+ (const months& __lhs, const month& __rhs) noexcept +{ return __rhs + __lhs; } + +_LIBCPP_HIDE_FROM_ABI inline constexpr +month operator- (const month& __lhs, const months& __rhs) noexcept +{ return __lhs + -__rhs; } + +_LIBCPP_HIDE_FROM_ABI inline constexpr +months operator-(const month& __lhs, const month& __rhs) noexcept +{ + auto const __dm = static_cast(__lhs) - static_cast(__rhs); + return months(__dm <= 11 ? __dm : __dm + 12); +} + +_LIBCPP_HIDE_FROM_ABI inline constexpr +month& month::operator+=(const months& __dm) noexcept +{ *this = *this + __dm; return *this; } + +_LIBCPP_HIDE_FROM_ABI inline constexpr +month& month::operator-=(const months& __dm) noexcept +{ *this = *this - __dm; return *this; } + +inline constexpr month January{1}; +inline constexpr month February{2}; +inline constexpr month March{3}; +inline constexpr month April{4}; +inline constexpr month May{5}; +inline constexpr month June{6}; +inline constexpr month July{7}; +inline constexpr month August{8}; +inline constexpr month September{9}; +inline constexpr month October{10}; +inline constexpr month November{11}; +inline constexpr month December{12}; + +} // namespace chrono + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER > 17 + +#endif // _LIBCPP___CHRONO_MONTH_H diff --git a/app/src/main/cpp/libcxx/include/__chrono/month_weekday.h b/app/src/main/cpp/libcxx/include/__chrono/month_weekday.h new file mode 100644 index 0000000..01cdf76 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__chrono/month_weekday.h @@ -0,0 +1,106 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___CHRONO_MONTH_WEEKDAY_H +#define _LIBCPP___CHRONO_MONTH_WEEKDAY_H + +#include <__chrono/month.h> +#include <__chrono/weekday.h> +#include <__config> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if _LIBCPP_STD_VER > 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace chrono +{ + +class month_weekday { +private: + chrono::month __m_; + chrono::weekday_indexed __wdi_; +public: + _LIBCPP_HIDE_FROM_ABI constexpr month_weekday(const chrono::month& __mval, const chrono::weekday_indexed& __wdival) noexcept + : __m_{__mval}, __wdi_{__wdival} {} + _LIBCPP_HIDE_FROM_ABI inline constexpr chrono::month month() const noexcept { return __m_; } + _LIBCPP_HIDE_FROM_ABI inline constexpr chrono::weekday_indexed weekday_indexed() const noexcept { return __wdi_; } + _LIBCPP_HIDE_FROM_ABI inline constexpr bool ok() const noexcept { return __m_.ok() && __wdi_.ok(); } +}; + +_LIBCPP_HIDE_FROM_ABI inline constexpr +bool operator==(const month_weekday& __lhs, const month_weekday& __rhs) noexcept +{ return __lhs.month() == __rhs.month() && __lhs.weekday_indexed() == __rhs.weekday_indexed(); } + +_LIBCPP_HIDE_FROM_ABI inline constexpr +bool operator!=(const month_weekday& __lhs, const month_weekday& __rhs) noexcept +{ return !(__lhs == __rhs); } + +_LIBCPP_HIDE_FROM_ABI inline constexpr +month_weekday operator/(const month& __lhs, const weekday_indexed& __rhs) noexcept +{ return month_weekday{__lhs, __rhs}; } + +_LIBCPP_HIDE_FROM_ABI inline constexpr +month_weekday operator/(int __lhs, const weekday_indexed& __rhs) noexcept +{ return month_weekday{month(__lhs), __rhs}; } + +_LIBCPP_HIDE_FROM_ABI inline constexpr +month_weekday operator/(const weekday_indexed& __lhs, const month& __rhs) noexcept +{ return month_weekday{__rhs, __lhs}; } + +_LIBCPP_HIDE_FROM_ABI inline constexpr +month_weekday operator/(const weekday_indexed& __lhs, int __rhs) noexcept +{ return month_weekday{month(__rhs), __lhs}; } + + +class month_weekday_last { + chrono::month __m_; + chrono::weekday_last __wdl_; + public: + _LIBCPP_HIDE_FROM_ABI constexpr month_weekday_last(const chrono::month& __mval, const chrono::weekday_last& __wdlval) noexcept + : __m_{__mval}, __wdl_{__wdlval} {} + _LIBCPP_HIDE_FROM_ABI inline constexpr chrono::month month() const noexcept { return __m_; } + _LIBCPP_HIDE_FROM_ABI inline constexpr chrono::weekday_last weekday_last() const noexcept { return __wdl_; } + _LIBCPP_HIDE_FROM_ABI inline constexpr bool ok() const noexcept { return __m_.ok() && __wdl_.ok(); } +}; + +_LIBCPP_HIDE_FROM_ABI inline constexpr +bool operator==(const month_weekday_last& __lhs, const month_weekday_last& __rhs) noexcept +{ return __lhs.month() == __rhs.month() && __lhs.weekday_last() == __rhs.weekday_last(); } + +_LIBCPP_HIDE_FROM_ABI inline constexpr +bool operator!=(const month_weekday_last& __lhs, const month_weekday_last& __rhs) noexcept +{ return !(__lhs == __rhs); } + + +_LIBCPP_HIDE_FROM_ABI inline constexpr +month_weekday_last operator/(const month& __lhs, const weekday_last& __rhs) noexcept +{ return month_weekday_last{__lhs, __rhs}; } + +_LIBCPP_HIDE_FROM_ABI inline constexpr +month_weekday_last operator/(int __lhs, const weekday_last& __rhs) noexcept +{ return month_weekday_last{month(__lhs), __rhs}; } + +_LIBCPP_HIDE_FROM_ABI inline constexpr +month_weekday_last operator/(const weekday_last& __lhs, const month& __rhs) noexcept +{ return month_weekday_last{__rhs, __lhs}; } + +_LIBCPP_HIDE_FROM_ABI inline constexpr +month_weekday_last operator/(const weekday_last& __lhs, int __rhs) noexcept +{ return month_weekday_last{month(__rhs), __lhs}; } +} // namespace chrono + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER > 17 + +#endif // _LIBCPP___CHRONO_MONTH_WEEKDAY_H diff --git a/app/src/main/cpp/libcxx/include/__chrono/monthday.h b/app/src/main/cpp/libcxx/include/__chrono/monthday.h new file mode 100644 index 0000000..c0ee3e4 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__chrono/monthday.h @@ -0,0 +1,129 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___CHRONO_MONTHDAY_H +#define _LIBCPP___CHRONO_MONTHDAY_H + +#include <__chrono/calendar.h> +#include <__chrono/day.h> +#include <__chrono/month.h> +#include <__config> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if _LIBCPP_STD_VER > 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace chrono +{ + +class month_day { +private: + chrono::month __m_; + chrono::day __d_; +public: + _LIBCPP_HIDE_FROM_ABI month_day() = default; + _LIBCPP_HIDE_FROM_ABI constexpr month_day(const chrono::month& __mval, const chrono::day& __dval) noexcept + : __m_{__mval}, __d_{__dval} {} + _LIBCPP_HIDE_FROM_ABI inline constexpr chrono::month month() const noexcept { return __m_; } + _LIBCPP_HIDE_FROM_ABI inline constexpr chrono::day day() const noexcept { return __d_; } + _LIBCPP_HIDE_FROM_ABI constexpr bool ok() const noexcept; +}; + +_LIBCPP_HIDE_FROM_ABI inline constexpr +bool month_day::ok() const noexcept +{ + if (!__m_.ok()) return false; + const unsigned __dval = static_cast(__d_); + if (__dval < 1 || __dval > 31) return false; + if (__dval <= 29) return true; +// Now we've got either 30 or 31 + const unsigned __mval = static_cast(__m_); + if (__mval == 2) return false; + if (__mval == 4 || __mval == 6 || __mval == 9 || __mval == 11) + return __dval == 30; + return true; +} + +_LIBCPP_HIDE_FROM_ABI inline constexpr +bool operator==(const month_day& __lhs, const month_day& __rhs) noexcept +{ return __lhs.month() == __rhs.month() && __lhs.day() == __rhs.day(); } + +_LIBCPP_HIDE_FROM_ABI constexpr strong_ordering operator<=>(const month_day& __lhs, const month_day& __rhs) noexcept { + if (auto __c = __lhs.month() <=> __rhs.month(); __c != 0) + return __c; + return __lhs.day() <=> __rhs.day(); +} + +_LIBCPP_HIDE_FROM_ABI inline constexpr +month_day operator/(const month& __lhs, const day& __rhs) noexcept +{ return month_day{__lhs, __rhs}; } + +_LIBCPP_HIDE_FROM_ABI constexpr +month_day operator/(const day& __lhs, const month& __rhs) noexcept +{ return __rhs / __lhs; } + +_LIBCPP_HIDE_FROM_ABI inline constexpr +month_day operator/(const month& __lhs, int __rhs) noexcept +{ return __lhs / day(__rhs); } + +_LIBCPP_HIDE_FROM_ABI constexpr +month_day operator/(int __lhs, const day& __rhs) noexcept +{ return month(__lhs) / __rhs; } + +_LIBCPP_HIDE_FROM_ABI constexpr +month_day operator/(const day& __lhs, int __rhs) noexcept +{ return month(__rhs) / __lhs; } + +class month_day_last { +private: + chrono::month __m_; +public: + _LIBCPP_HIDE_FROM_ABI explicit constexpr month_day_last(const chrono::month& __val) noexcept + : __m_{__val} {} + _LIBCPP_HIDE_FROM_ABI inline constexpr chrono::month month() const noexcept { return __m_; } + _LIBCPP_HIDE_FROM_ABI inline constexpr bool ok() const noexcept { return __m_.ok(); } +}; + +_LIBCPP_HIDE_FROM_ABI inline constexpr +bool operator==(const month_day_last& __lhs, const month_day_last& __rhs) noexcept +{ return __lhs.month() == __rhs.month(); } + +_LIBCPP_HIDE_FROM_ABI constexpr strong_ordering +operator<=>(const month_day_last& __lhs, const month_day_last& __rhs) noexcept { + return __lhs.month() <=> __rhs.month(); +} + +_LIBCPP_HIDE_FROM_ABI inline constexpr +month_day_last operator/(const month& __lhs, last_spec) noexcept +{ return month_day_last{__lhs}; } + +_LIBCPP_HIDE_FROM_ABI inline constexpr +month_day_last operator/(last_spec, const month& __rhs) noexcept +{ return month_day_last{__rhs}; } + +_LIBCPP_HIDE_FROM_ABI inline constexpr +month_day_last operator/(int __lhs, last_spec) noexcept +{ return month_day_last{month(__lhs)}; } + +_LIBCPP_HIDE_FROM_ABI inline constexpr +month_day_last operator/(last_spec, int __rhs) noexcept +{ return month_day_last{month(__rhs)}; } + +} // namespace chrono + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER > 17 + +#endif // _LIBCPP___CHRONO_MONTHDAY_H diff --git a/app/src/main/cpp/libcxx/include/__chrono/ostream.h b/app/src/main/cpp/libcxx/include/__chrono/ostream.h new file mode 100644 index 0000000..30a04bd --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__chrono/ostream.h @@ -0,0 +1,238 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___CHRONO_OSTREAM_H +#define _LIBCPP___CHRONO_OSTREAM_H + +#include <__chrono/day.h> +#include <__chrono/duration.h> +#include <__chrono/month.h> +#include <__chrono/month_weekday.h> +#include <__chrono/monthday.h> +#include <__chrono/statically_widen.h> +#include <__chrono/weekday.h> +#include <__chrono/year.h> +#include <__chrono/year_month.h> +#include <__chrono/year_month_day.h> +#include <__chrono/year_month_weekday.h> +#include <__concepts/same_as.h> +#include <__config> +#include <__format/format_functions.h> +#include +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_FORMAT) + +namespace chrono { + +// Depending on the type the return is a const _CharT* or a basic_string<_CharT> +template +_LIBCPP_HIDE_FROM_ABI auto __units_suffix() { + // TODO FMT LWG issue the suffixes are always char and not STATICALLY-WIDEN'ed. + if constexpr (same_as) + return _LIBCPP_STATICALLY_WIDEN(_CharT, "as"); + else if constexpr (same_as) + return _LIBCPP_STATICALLY_WIDEN(_CharT, "fs"); + else if constexpr (same_as) + return _LIBCPP_STATICALLY_WIDEN(_CharT, "ps"); + else if constexpr (same_as) + return _LIBCPP_STATICALLY_WIDEN(_CharT, "ns"); + else if constexpr (same_as) +# ifndef _LIBCPP_HAS_NO_UNICODE + return _LIBCPP_STATICALLY_WIDEN(_CharT, "\u00b5s"); +# else + return _LIBCPP_STATICALLY_WIDEN(_CharT, "us"); +# endif + else if constexpr (same_as) + return _LIBCPP_STATICALLY_WIDEN(_CharT, "ms"); + else if constexpr (same_as) + return _LIBCPP_STATICALLY_WIDEN(_CharT, "cs"); + else if constexpr (same_as) + return _LIBCPP_STATICALLY_WIDEN(_CharT, "ds"); + else if constexpr (same_as>) + return _LIBCPP_STATICALLY_WIDEN(_CharT, "s"); + else if constexpr (same_as) + return _LIBCPP_STATICALLY_WIDEN(_CharT, "das"); + else if constexpr (same_as) + return _LIBCPP_STATICALLY_WIDEN(_CharT, "hs"); + else if constexpr (same_as) + return _LIBCPP_STATICALLY_WIDEN(_CharT, "ks"); + else if constexpr (same_as) + return _LIBCPP_STATICALLY_WIDEN(_CharT, "Ms"); + else if constexpr (same_as) + return _LIBCPP_STATICALLY_WIDEN(_CharT, "Gs"); + else if constexpr (same_as) + return _LIBCPP_STATICALLY_WIDEN(_CharT, "Ts"); + else if constexpr (same_as) + return _LIBCPP_STATICALLY_WIDEN(_CharT, "Ps"); + else if constexpr (same_as) + return _LIBCPP_STATICALLY_WIDEN(_CharT, "Es"); + else if constexpr (same_as>) + return _LIBCPP_STATICALLY_WIDEN(_CharT, "min"); + else if constexpr (same_as>) + return _LIBCPP_STATICALLY_WIDEN(_CharT, "h"); + else if constexpr (same_as>) + return _LIBCPP_STATICALLY_WIDEN(_CharT, "d"); + else if constexpr (_Period::den == 1) + return std::format(_LIBCPP_STATICALLY_WIDEN(_CharT, "[{}]s"), _Period::num); + else + return std::format(_LIBCPP_STATICALLY_WIDEN(_CharT, "[{}/{}]s"), _Period::num, _Period::den); +} + +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT basic_ostream<_CharT, _Traits>& +operator<<(basic_ostream<_CharT, _Traits>& __os, const duration<_Rep, _Period>& __d) { + basic_ostringstream<_CharT, _Traits> __s; + __s.flags(__os.flags()); + __s.imbue(__os.getloc()); + __s.precision(__os.precision()); + __s << __d.count() << chrono::__units_suffix<_CharT, _Period>(); + return __os << __s.str(); +} + +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT basic_ostream<_CharT, _Traits>& +operator<<(basic_ostream<_CharT, _Traits>& __os, const day& __d) { + return __os + << (__d.ok() + ? std::format(_LIBCPP_STATICALLY_WIDEN(_CharT, "{:%d}"), __d) + // Note this error differs from the wording of the Standard. The + // Standard wording doesn't work well on AIX or Windows. There + // the formatted day seems to be either modulo 100 or completely + // omitted. Judging by the wording this is valid. + // TODO FMT Write a paper of file an LWG issue. + : std::format(_LIBCPP_STATICALLY_WIDEN(_CharT, "{:02} is not a valid day"), static_cast(__d))); +} + +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT basic_ostream<_CharT, _Traits>& +operator<<(basic_ostream<_CharT, _Traits>& __os, const month& __m) { + return __os << (__m.ok() ? std::format(__os.getloc(), _LIBCPP_STATICALLY_WIDEN(_CharT, "{:L%b}"), __m) + : std::format(__os.getloc(), + _LIBCPP_STATICALLY_WIDEN(_CharT, "{} is not a valid month"), + static_cast(__m))); // TODO FMT Standard mandated locale isn't used. +} + +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT basic_ostream<_CharT, _Traits>& +operator<<(basic_ostream<_CharT, _Traits>& __os, const year& __y) { + return __os << (__y.ok() ? std::format(_LIBCPP_STATICALLY_WIDEN(_CharT, "{:%Y}"), __y) + : std::format(_LIBCPP_STATICALLY_WIDEN(_CharT, "{:%Y} is not a valid year"), __y)); +} + +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT basic_ostream<_CharT, _Traits>& +operator<<(basic_ostream<_CharT, _Traits>& __os, const weekday& __wd) { + return __os << (__wd.ok() ? std::format(__os.getloc(), _LIBCPP_STATICALLY_WIDEN(_CharT, "{:L%a}"), __wd) + : std::format(__os.getloc(), // TODO FMT Standard mandated locale isn't used. + _LIBCPP_STATICALLY_WIDEN(_CharT, "{} is not a valid weekday"), + static_cast(__wd.c_encoding()))); +} + +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT basic_ostream<_CharT, _Traits>& +operator<<(basic_ostream<_CharT, _Traits>& __os, const weekday_indexed& __wdi) { + auto __i = __wdi.index(); + return __os << (__i >= 1 && __i <= 5 + ? std::format(__os.getloc(), _LIBCPP_STATICALLY_WIDEN(_CharT, "{:L}[{}]"), __wdi.weekday(), __i) + : std::format(__os.getloc(), + _LIBCPP_STATICALLY_WIDEN(_CharT, "{:L}[{} is not a valid index]"), + __wdi.weekday(), + __i)); +} + +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT basic_ostream<_CharT, _Traits>& +operator<<(basic_ostream<_CharT, _Traits>& __os, const weekday_last& __wdl) { + return __os << std::format(__os.getloc(), _LIBCPP_STATICALLY_WIDEN(_CharT, "{:L}[last]"), __wdl.weekday()); +} + +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT basic_ostream<_CharT, _Traits>& +operator<<(basic_ostream<_CharT, _Traits>& __os, const month_day& __md) { + // TODO FMT The Standard allows 30th of February to be printed. + // It would be nice to show an error message instead. + return __os << std::format(__os.getloc(), _LIBCPP_STATICALLY_WIDEN(_CharT, "{:L}/{}"), __md.month(), __md.day()); +} + +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT basic_ostream<_CharT, _Traits>& +operator<<(basic_ostream<_CharT, _Traits>& __os, const month_day_last& __mdl) { + return __os << std::format(__os.getloc(), _LIBCPP_STATICALLY_WIDEN(_CharT, "{:L}/last"), __mdl.month()); +} + +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT basic_ostream<_CharT, _Traits>& +operator<<(basic_ostream<_CharT, _Traits>& __os, const month_weekday& __mwd) { + return __os << std::format( + __os.getloc(), _LIBCPP_STATICALLY_WIDEN(_CharT, "{:L}/{:L}"), __mwd.month(), __mwd.weekday_indexed()); +} + +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT basic_ostream<_CharT, _Traits>& +operator<<(basic_ostream<_CharT, _Traits>& __os, const month_weekday_last& __mwdl) { + return __os << std::format( + __os.getloc(), _LIBCPP_STATICALLY_WIDEN(_CharT, "{:L}/{:L}"), __mwdl.month(), __mwdl.weekday_last()); +} + +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT basic_ostream<_CharT, _Traits>& +operator<<(basic_ostream<_CharT, _Traits>& __os, const year_month& __ym) { + return __os << std::format(__os.getloc(), _LIBCPP_STATICALLY_WIDEN(_CharT, "{}/{:L}"), __ym.year(), __ym.month()); +} + +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT basic_ostream<_CharT, _Traits>& +operator<<(basic_ostream<_CharT, _Traits>& __os, const year_month_day& __ymd) { + return __os << (__ymd.ok() ? std::format(_LIBCPP_STATICALLY_WIDEN(_CharT, "{:%F}"), __ymd) + : std::format(_LIBCPP_STATICALLY_WIDEN(_CharT, "{:%F} is not a valid date"), __ymd)); +} + +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT basic_ostream<_CharT, _Traits>& +operator<<(basic_ostream<_CharT, _Traits>& __os, const year_month_day_last& __ymdl) { + return __os << std::format( + __os.getloc(), _LIBCPP_STATICALLY_WIDEN(_CharT, "{}/{:L}"), __ymdl.year(), __ymdl.month_day_last()); +} + +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT basic_ostream<_CharT, _Traits>& +operator<<(basic_ostream<_CharT, _Traits>& __os, const year_month_weekday& __ymwd) { + return __os << std::format( + __os.getloc(), + _LIBCPP_STATICALLY_WIDEN(_CharT, "{}/{:L}/{:L}"), + __ymwd.year(), + __ymwd.month(), + __ymwd.weekday_indexed()); +} + +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT basic_ostream<_CharT, _Traits>& +operator<<(basic_ostream<_CharT, _Traits>& __os, const year_month_weekday_last& __ymwdl) { + return __os << std::format( + __os.getloc(), + _LIBCPP_STATICALLY_WIDEN(_CharT, "{}/{:L}/{:L}"), + __ymwdl.year(), + __ymwdl.month(), + __ymwdl.weekday_last()); +} + +} // namespace chrono + +#endif //if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_FORMAT) + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___CHRONO_OSTREAM_H diff --git a/app/src/main/cpp/libcxx/include/__chrono/parser_std_format_spec.h b/app/src/main/cpp/libcxx/include/__chrono/parser_std_format_spec.h new file mode 100644 index 0000000..dbcfe6d --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__chrono/parser_std_format_spec.h @@ -0,0 +1,410 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___CHRONO_PARSER_STD_FORMAT_SPEC_H +#define _LIBCPP___CHRONO_PARSER_STD_FORMAT_SPEC_H + +#include <__config> +#include <__format/concepts.h> +#include <__format/format_error.h> +#include <__format/format_parse_context.h> +#include <__format/formatter_string.h> +#include <__format/parser_std_format_spec.h> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_FORMAT) + +namespace __format_spec { + +// By not placing this constant in the formatter class it's not duplicated for char and wchar_t +inline constexpr __fields __fields_chrono_fractional{ + .__precision_ = true, .__locale_specific_form_ = true, .__type_ = false}; +inline constexpr __fields __fields_chrono{.__locale_specific_form_ = true, .__type_ = false}; + +/// Flags available or required in a chrono type. +/// +/// The caller of the chrono formatter lists the types it has available and the +/// validation tests whether the requested type spec (e.g. %M) is available in +/// the formatter. +/// When the type in the chrono-format-spec isn't present in the data a +/// \ref format_error is thrown. +enum class __flags { + __second = 0x1, + __minute = 0x2, + __hour = 0x4, + __time = __hour | __minute | __second, + + __day = 0x8, + __month = 0x10, + __year = 0x20, + + __weekday = 0x40, + + __month_day = __day | __month, + __month_weekday = __weekday | __month, + __year_month = __month | __year, + __date = __day | __month | __year | __weekday, + + __date_time = __date | __time, + + __duration = 0x80 | __time, + + __time_zone = 0x100, + + __clock = __date_time | __time_zone +}; + +_LIBCPP_HIDE_FROM_ABI constexpr __flags operator&(__flags __lhs, __flags __rhs) { + return static_cast<__flags>(static_cast(__lhs) & static_cast(__rhs)); +} + +_LIBCPP_HIDE_FROM_ABI constexpr void __validate_second(__flags __flags) { + if ((__flags & __flags::__second) != __flags::__second) + std::__throw_format_error("The supplied date time doesn't contain a second"); +} + +_LIBCPP_HIDE_FROM_ABI constexpr void __validate_minute(__flags __flags) { + if ((__flags & __flags::__minute) != __flags::__minute) + std::__throw_format_error("The supplied date time doesn't contain a minute"); +} + +_LIBCPP_HIDE_FROM_ABI constexpr void __validate_hour(__flags __flags) { + if ((__flags & __flags::__hour) != __flags::__hour) + std::__throw_format_error("The supplied date time doesn't contain an hour"); +} + +_LIBCPP_HIDE_FROM_ABI constexpr void __validate_time(__flags __flags) { + if ((__flags & __flags::__time) != __flags::__time) + std::__throw_format_error("The supplied date time doesn't contain a time"); +} + +_LIBCPP_HIDE_FROM_ABI constexpr void __validate_day(__flags __flags) { + if ((__flags & __flags::__day) != __flags::__day) + std::__throw_format_error("The supplied date time doesn't contain a day"); +} + +_LIBCPP_HIDE_FROM_ABI constexpr void __validate_month(__flags __flags) { + if ((__flags & __flags::__month) != __flags::__month) + std::__throw_format_error("The supplied date time doesn't contain a month"); +} + +_LIBCPP_HIDE_FROM_ABI constexpr void __validate_year(__flags __flags) { + if ((__flags & __flags::__year) != __flags::__year) + std::__throw_format_error("The supplied date time doesn't contain a year"); +} + +_LIBCPP_HIDE_FROM_ABI constexpr void __validate_date(__flags __flags) { + if ((__flags & __flags::__date) != __flags::__date) + std::__throw_format_error("The supplied date time doesn't contain a date"); +} + +_LIBCPP_HIDE_FROM_ABI constexpr void __validate_date_or_duration(__flags __flags) { + if (((__flags & __flags::__date) != __flags::__date) && ((__flags & __flags::__duration) != __flags::__duration)) + std::__throw_format_error("The supplied date time doesn't contain a date or duration"); +} + +_LIBCPP_HIDE_FROM_ABI constexpr void __validate_date_time(__flags __flags) { + if ((__flags & __flags::__date_time) != __flags::__date_time) + std::__throw_format_error("The supplied date time doesn't contain a date and time"); +} + +_LIBCPP_HIDE_FROM_ABI constexpr void __validate_weekday(__flags __flags) { + if ((__flags & __flags::__weekday) != __flags::__weekday) + std::__throw_format_error("The supplied date time doesn't contain a weekday"); +} + +_LIBCPP_HIDE_FROM_ABI constexpr void __validate_duration(__flags __flags) { + if ((__flags & __flags::__duration) != __flags::__duration) + std::__throw_format_error("The supplied date time doesn't contain a duration"); +} + +_LIBCPP_HIDE_FROM_ABI constexpr void __validate_time_zone(__flags __flags) { + if ((__flags & __flags::__time_zone) != __flags::__time_zone) + std::__throw_format_error("The supplied date time doesn't contain a time zone"); +} + +template +class _LIBCPP_TEMPLATE_VIS __parser_chrono { +public: + _LIBCPP_HIDE_FROM_ABI constexpr auto + __parse(basic_format_parse_context<_CharT>& __parse_ctx, __fields __fields, __flags __flags) + -> decltype(__parse_ctx.begin()) { + const _CharT* __begin = __parser_.__parse(__parse_ctx, __fields); + const _CharT* __end = __parse_ctx.end(); + if (__begin == __end) + return __begin; + + const _CharT* __last = __parse_chrono_specs(__begin, __end, __flags); + __chrono_specs_ = basic_string_view<_CharT>{__begin, __last}; + + return __last; + } + + __parser<_CharT> __parser_; + basic_string_view<_CharT> __chrono_specs_; + +private: + _LIBCPP_HIDE_FROM_ABI constexpr const _CharT* + __parse_chrono_specs(const _CharT* __begin, const _CharT* __end, __flags __flags) { + _LIBCPP_ASSERT(__begin != __end, + "When called with an empty input the function will cause " + "undefined behavior by evaluating data not in the input"); + + if (*__begin != _CharT('%') && *__begin != _CharT('}')) + std::__throw_format_error("Expected '%' or '}' in the chrono format-string"); + + do { + switch (*__begin) { + case _CharT('{'): + std::__throw_format_error("The chrono-specs contains a '{'"); + + case _CharT('}'): + return __begin; + + case _CharT('%'): + __parse_conversion_spec(__begin, __end, __flags); + [[fallthrough]]; + + default: + // All other literals + ++__begin; + } + + } while (__begin != __end && *__begin != _CharT('}')); + + return __begin; + } + + /// \pre *__begin == '%' + /// \post __begin points at the end parsed conversion-spec + _LIBCPP_HIDE_FROM_ABI constexpr void + __parse_conversion_spec(const _CharT*& __begin, const _CharT* __end, __flags __flags) { + ++__begin; + if (__begin == __end) + std::__throw_format_error("End of input while parsing the modifier chrono conversion-spec"); + + switch (*__begin) { + case _CharT('n'): + case _CharT('t'): + case _CharT('%'): + break; + + case _CharT('S'): + __format_spec::__validate_second(__flags); + break; + + case _CharT('M'): + __format_spec::__validate_minute(__flags); + break; + + case _CharT('p'): // TODO FMT does the formater require an hour or a time? + case _CharT('H'): + case _CharT('I'): + __validate_hour(__flags); + break; + + case _CharT('r'): + case _CharT('R'): + case _CharT('T'): + case _CharT('X'): + __format_spec::__validate_time(__flags); + break; + + case _CharT('d'): + case _CharT('e'): + __format_spec::__validate_day(__flags); + break; + + case _CharT('b'): + case _CharT('h'): + case _CharT('B'): + __parser_.__month_name_ = true; + [[fallthrough]]; + case _CharT('m'): + __format_spec::__validate_month(__flags); + break; + + case _CharT('y'): + case _CharT('C'): + case _CharT('Y'): + __format_spec::__validate_year(__flags); + break; + + case _CharT('j'): + __parser_.__day_of_year_ = true; + __format_spec::__validate_date_or_duration(__flags); + break; + + case _CharT('g'): + case _CharT('G'): + case _CharT('U'): + case _CharT('V'): + case _CharT('W'): + __parser_.__week_of_year_ = true; + [[fallthrough]]; + case _CharT('x'): + case _CharT('D'): + case _CharT('F'): + __format_spec::__validate_date(__flags); + break; + + case _CharT('c'): + __format_spec::__validate_date_time(__flags); + break; + + case _CharT('a'): + case _CharT('A'): + __parser_.__weekday_name_ = true; + [[fallthrough]]; + case _CharT('u'): + case _CharT('w'): + __parser_.__weekday_ = true; + __validate_weekday(__flags); + __format_spec::__validate_weekday(__flags); + break; + + case _CharT('q'): + case _CharT('Q'): + __format_spec::__validate_duration(__flags); + break; + + case _CharT('E'): + __parse_modifier_E(__begin, __end, __flags); + break; + + case _CharT('O'): + __parse_modifier_O(__begin, __end, __flags); + break; + + case _CharT('z'): + case _CharT('Z'): + // Currently there's no time zone information. However some clocks have a + // hard-coded "time zone", for these clocks the information can be used. + // TODO FMT implement time zones. + __format_spec::__validate_time_zone(__flags); + break; + + default: // unknown type; + std::__throw_format_error("The date time type specifier is invalid"); + } + } + + /// \pre *__begin == 'E' + /// \post __begin is incremented by one. + _LIBCPP_HIDE_FROM_ABI constexpr void + __parse_modifier_E(const _CharT*& __begin, const _CharT* __end, __flags __flags) { + ++__begin; + if (__begin == __end) + std::__throw_format_error("End of input while parsing the modifier E"); + + switch (*__begin) { + case _CharT('X'): + __format_spec::__validate_time(__flags); + break; + + case _CharT('y'): + case _CharT('C'): + case _CharT('Y'): + __format_spec::__validate_year(__flags); + break; + + case _CharT('x'): + __format_spec::__validate_date(__flags); + break; + + case _CharT('c'): + __format_spec::__validate_date_time(__flags); + break; + + case _CharT('z'): + // Currently there's no time zone information. However some clocks have a + // hard-coded "time zone", for these clocks the information can be used. + // TODO FMT implement time zones. + __format_spec::__validate_time_zone(__flags); + break; + + default: + std::__throw_format_error("The date time type specifier for modifier E is invalid"); + } + } + + /// \pre *__begin == 'O' + /// \post __begin is incremented by one. + _LIBCPP_HIDE_FROM_ABI constexpr void + __parse_modifier_O(const _CharT*& __begin, const _CharT* __end, __flags __flags) { + ++__begin; + if (__begin == __end) + std::__throw_format_error("End of input while parsing the modifier O"); + + switch (*__begin) { + case _CharT('S'): + __format_spec::__validate_second(__flags); + break; + + case _CharT('M'): + __format_spec::__validate_minute(__flags); + break; + + case _CharT('I'): + case _CharT('H'): + __format_spec::__validate_hour(__flags); + break; + + case _CharT('d'): + case _CharT('e'): + __format_spec::__validate_day(__flags); + break; + + case _CharT('m'): + __format_spec::__validate_month(__flags); + break; + + case _CharT('y'): + __format_spec::__validate_year(__flags); + break; + + case _CharT('U'): + case _CharT('V'): + case _CharT('W'): + __parser_.__week_of_year_ = true; + __format_spec::__validate_date(__flags); + break; + + case _CharT('u'): + case _CharT('w'): + __parser_.__weekday_ = true; + __format_spec::__validate_weekday(__flags); + break; + + case _CharT('z'): + // Currently there's no time zone information. However some clocks have a + // hard-coded "time zone", for these clocks the information can be used. + // TODO FMT implement time zones. + __format_spec::__validate_time_zone(__flags); + break; + + default: + std::__throw_format_error("The date time type specifier for modifier O is invalid"); + } + } +}; + +} // namespace __format_spec + +#endif //_LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_FORMAT) + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___CHRONO_PARSER_STD_FORMAT_SPEC_H diff --git a/app/src/main/cpp/libcxx/include/__chrono/statically_widen.h b/app/src/main/cpp/libcxx/include/__chrono/statically_widen.h new file mode 100644 index 0000000..360b6c2 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__chrono/statically_widen.h @@ -0,0 +1,52 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___CHRONO_STATICALLY_WIDEN_H +#define _LIBCPP___CHRONO_STATICALLY_WIDEN_H + +// Implements the STATICALLY-WIDEN exposition-only function. ([time.general]/2) + +#include <__concepts/same_as.h> +#include <__config> +#include <__format/concepts.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 17 + +# ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +template <__fmt_char_type _CharT> +_LIBCPP_HIDE_FROM_ABI constexpr const _CharT* __statically_widen(const char* __str, const wchar_t* __wstr) { + if constexpr (same_as<_CharT, char>) + return __str; + else + return __wstr; +} +# define _LIBCPP_STATICALLY_WIDEN(_CharT, __str) ::std::__statically_widen<_CharT>(__str, L##__str) +# else // _LIBCPP_HAS_NO_WIDE_CHARACTERS + +// Without this indirection the unit test test/libcxx/modules_include.sh.cpp +// fails for the CI build "No wide characters". This seems like a bug. +// TODO FMT investigate why this is needed. +template <__fmt_char_type _CharT> +_LIBCPP_HIDE_FROM_ABI constexpr const _CharT* __statically_widen(const char* __str) { + return __str; +} +# define _LIBCPP_STATICALLY_WIDEN(_CharT, __str) ::std::__statically_widen<_CharT>(__str) +# endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS + +#endif //_LIBCPP_STD_VER > 17 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___CHRONO_STATICALLY_WIDEN_H diff --git a/app/src/main/cpp/libcxx/include/__chrono/steady_clock.h b/app/src/main/cpp/libcxx/include/__chrono/steady_clock.h new file mode 100644 index 0000000..ba83351 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__chrono/steady_clock.h @@ -0,0 +1,44 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___CHRONO_STEADY_CLOCK_H +#define _LIBCPP___CHRONO_STEADY_CLOCK_H + +#include <__chrono/duration.h> +#include <__chrono/time_point.h> +#include <__config> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace chrono +{ + +#ifndef _LIBCPP_HAS_NO_MONOTONIC_CLOCK +class _LIBCPP_TYPE_VIS steady_clock +{ +public: + typedef nanoseconds duration; + typedef duration::rep rep; + typedef duration::period period; + typedef chrono::time_point time_point; + static _LIBCPP_CONSTEXPR_SINCE_CXX14 const bool is_steady = true; + + static time_point now() _NOEXCEPT; +}; +#endif + +} // namespace chrono + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___CHRONO_STEADY_CLOCK_H diff --git a/app/src/main/cpp/libcxx/include/__chrono/system_clock.h b/app/src/main/cpp/libcxx/include/__chrono/system_clock.h new file mode 100644 index 0000000..331db46 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__chrono/system_clock.h @@ -0,0 +1,54 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___CHRONO_SYSTEM_CLOCK_H +#define _LIBCPP___CHRONO_SYSTEM_CLOCK_H + +#include <__chrono/duration.h> +#include <__chrono/time_point.h> +#include <__config> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace chrono +{ + +class _LIBCPP_TYPE_VIS system_clock +{ +public: + typedef microseconds duration; + typedef duration::rep rep; + typedef duration::period period; + typedef chrono::time_point time_point; + static _LIBCPP_CONSTEXPR_SINCE_CXX14 const bool is_steady = false; + + static time_point now() _NOEXCEPT; + static time_t to_time_t (const time_point& __t) _NOEXCEPT; + static time_point from_time_t(time_t __t) _NOEXCEPT; +}; + +#if _LIBCPP_STD_VER > 17 + +template +using sys_time = time_point; +using sys_seconds = sys_time; +using sys_days = sys_time; + +#endif + +} // namespace chrono + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___CHRONO_SYSTEM_CLOCK_H diff --git a/app/src/main/cpp/libcxx/include/__chrono/time_point.h b/app/src/main/cpp/libcxx/include/__chrono/time_point.h new file mode 100644 index 0000000..8a8fa21 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__chrono/time_point.h @@ -0,0 +1,251 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___CHRONO_TIME_POINT_H +#define _LIBCPP___CHRONO_TIME_POINT_H + +#include <__chrono/duration.h> +#include <__config> +#include <__type_traits/common_type.h> +#include <__type_traits/enable_if.h> +#include <__type_traits/is_convertible.h> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace chrono +{ + +template +class _LIBCPP_TEMPLATE_VIS time_point +{ + static_assert(__is_duration<_Duration>::value, + "Second template parameter of time_point must be a std::chrono::duration"); +public: + typedef _Clock clock; + typedef _Duration duration; + typedef typename duration::rep rep; + typedef typename duration::period period; +private: + duration __d_; + +public: + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 time_point() : __d_(duration::zero()) {} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 explicit time_point(const duration& __d) : __d_(__d) {} + + // conversions + template + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 + time_point(const time_point& __t, + typename enable_if + < + is_convertible<_Duration2, duration>::value + >::type* = nullptr) + : __d_(__t.time_since_epoch()) {} + + // observer + + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 duration time_since_epoch() const {return __d_;} + + // arithmetic + + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX17 time_point& operator+=(const duration& __d) {__d_ += __d; return *this;} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX17 time_point& operator-=(const duration& __d) {__d_ -= __d; return *this;} + + // special values + + _LIBCPP_INLINE_VISIBILITY static _LIBCPP_CONSTEXPR time_point min() _NOEXCEPT {return time_point(duration::min());} + _LIBCPP_INLINE_VISIBILITY static _LIBCPP_CONSTEXPR time_point max() _NOEXCEPT {return time_point(duration::max());} +}; + +} // namespace chrono + +template +struct _LIBCPP_TEMPLATE_VIS common_type, + chrono::time_point<_Clock, _Duration2> > +{ + typedef chrono::time_point<_Clock, typename common_type<_Duration1, _Duration2>::type> type; +}; + +namespace chrono { + +template +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 +time_point<_Clock, _ToDuration> +time_point_cast(const time_point<_Clock, _Duration>& __t) +{ + return time_point<_Clock, _ToDuration>(chrono::duration_cast<_ToDuration>(__t.time_since_epoch())); +} + +#if _LIBCPP_STD_VER > 14 +template +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR +typename enable_if +< + __is_duration<_ToDuration>::value, + time_point<_Clock, _ToDuration> +>::type +floor(const time_point<_Clock, _Duration>& __t) +{ + return time_point<_Clock, _ToDuration>{chrono::floor<_ToDuration>(__t.time_since_epoch())}; +} + +template +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR +typename enable_if +< + __is_duration<_ToDuration>::value, + time_point<_Clock, _ToDuration> +>::type +ceil(const time_point<_Clock, _Duration>& __t) +{ + return time_point<_Clock, _ToDuration>{chrono::ceil<_ToDuration>(__t.time_since_epoch())}; +} + +template +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR +typename enable_if +< + __is_duration<_ToDuration>::value, + time_point<_Clock, _ToDuration> +>::type +round(const time_point<_Clock, _Duration>& __t) +{ + return time_point<_Clock, _ToDuration>{chrono::round<_ToDuration>(__t.time_since_epoch())}; +} + +template +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR +typename enable_if +< + numeric_limits<_Rep>::is_signed, + duration<_Rep, _Period> +>::type +abs(duration<_Rep, _Period> __d) +{ + return __d >= __d.zero() ? +__d : -__d; +} +#endif // _LIBCPP_STD_VER > 14 + +// time_point == + +template +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 +bool +operator==(const time_point<_Clock, _Duration1>& __lhs, const time_point<_Clock, _Duration2>& __rhs) +{ + return __lhs.time_since_epoch() == __rhs.time_since_epoch(); +} + +// time_point != + +template +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 +bool +operator!=(const time_point<_Clock, _Duration1>& __lhs, const time_point<_Clock, _Duration2>& __rhs) +{ + return !(__lhs == __rhs); +} + +// time_point < + +template +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 +bool +operator<(const time_point<_Clock, _Duration1>& __lhs, const time_point<_Clock, _Duration2>& __rhs) +{ + return __lhs.time_since_epoch() < __rhs.time_since_epoch(); +} + +// time_point > + +template +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 +bool +operator>(const time_point<_Clock, _Duration1>& __lhs, const time_point<_Clock, _Duration2>& __rhs) +{ + return __rhs < __lhs; +} + +// time_point <= + +template +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 +bool +operator<=(const time_point<_Clock, _Duration1>& __lhs, const time_point<_Clock, _Duration2>& __rhs) +{ + return !(__rhs < __lhs); +} + +// time_point >= + +template +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 +bool +operator>=(const time_point<_Clock, _Duration1>& __lhs, const time_point<_Clock, _Duration2>& __rhs) +{ + return !(__lhs < __rhs); +} + +// time_point operator+(time_point x, duration y); + +template +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 +time_point<_Clock, typename common_type<_Duration1, duration<_Rep2, _Period2> >::type> +operator+(const time_point<_Clock, _Duration1>& __lhs, const duration<_Rep2, _Period2>& __rhs) +{ + typedef time_point<_Clock, typename common_type<_Duration1, duration<_Rep2, _Period2> >::type> _Tr; + return _Tr (__lhs.time_since_epoch() + __rhs); +} + +// time_point operator+(duration x, time_point y); + +template +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 +time_point<_Clock, typename common_type, _Duration2>::type> +operator+(const duration<_Rep1, _Period1>& __lhs, const time_point<_Clock, _Duration2>& __rhs) +{ + return __rhs + __lhs; +} + +// time_point operator-(time_point x, duration y); + +template +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 +time_point<_Clock, typename common_type<_Duration1, duration<_Rep2, _Period2> >::type> +operator-(const time_point<_Clock, _Duration1>& __lhs, const duration<_Rep2, _Period2>& __rhs) +{ + typedef time_point<_Clock, typename common_type<_Duration1, duration<_Rep2, _Period2> >::type> _Ret; + return _Ret(__lhs.time_since_epoch() -__rhs); +} + +// duration operator-(time_point x, time_point y); + +template +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 +typename common_type<_Duration1, _Duration2>::type +operator-(const time_point<_Clock, _Duration1>& __lhs, const time_point<_Clock, _Duration2>& __rhs) +{ + return __lhs.time_since_epoch() - __rhs.time_since_epoch(); +} + +} // namespace chrono + +_LIBCPP_END_NAMESPACE_STD + +_LIBCPP_POP_MACROS + +#endif // _LIBCPP___CHRONO_TIME_POINT_H diff --git a/app/src/main/cpp/libcxx/include/__chrono/weekday.h b/app/src/main/cpp/libcxx/include/__chrono/weekday.h new file mode 100644 index 0000000..e0bc8a4 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__chrono/weekday.h @@ -0,0 +1,185 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___CHRONO_WEEKDAY_H +#define _LIBCPP___CHRONO_WEEKDAY_H + +#include <__chrono/calendar.h> +#include <__chrono/duration.h> +#include <__chrono/system_clock.h> +#include <__chrono/time_point.h> +#include <__config> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if _LIBCPP_STD_VER > 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace chrono +{ + +class weekday_indexed; +class weekday_last; + +class weekday { +private: + unsigned char __wd_; + _LIBCPP_HIDE_FROM_ABI static constexpr unsigned char __weekday_from_days(int __days) noexcept; +public: + _LIBCPP_HIDE_FROM_ABI weekday() = default; + _LIBCPP_HIDE_FROM_ABI inline explicit constexpr weekday(unsigned __val) noexcept : __wd_(static_cast(__val == 7 ? 0 : __val)) {} + _LIBCPP_HIDE_FROM_ABI inline constexpr weekday(const sys_days& __sysd) noexcept + : __wd_(__weekday_from_days(__sysd.time_since_epoch().count())) {} + _LIBCPP_HIDE_FROM_ABI inline explicit constexpr weekday(const local_days& __locd) noexcept + : __wd_(__weekday_from_days(__locd.time_since_epoch().count())) {} + + _LIBCPP_HIDE_FROM_ABI inline constexpr weekday& operator++() noexcept { __wd_ = (__wd_ == 6 ? 0 : __wd_ + 1); return *this; } + _LIBCPP_HIDE_FROM_ABI inline constexpr weekday operator++(int) noexcept { weekday __tmp = *this; ++(*this); return __tmp; } + _LIBCPP_HIDE_FROM_ABI inline constexpr weekday& operator--() noexcept { __wd_ = (__wd_ == 0 ? 6 : __wd_ - 1); return *this; } + _LIBCPP_HIDE_FROM_ABI inline constexpr weekday operator--(int) noexcept { weekday __tmp = *this; --(*this); return __tmp; } + _LIBCPP_HIDE_FROM_ABI constexpr weekday& operator+=(const days& __dd) noexcept; + _LIBCPP_HIDE_FROM_ABI constexpr weekday& operator-=(const days& __dd) noexcept; + _LIBCPP_HIDE_FROM_ABI inline constexpr unsigned c_encoding() const noexcept { return __wd_; } + _LIBCPP_HIDE_FROM_ABI inline constexpr unsigned iso_encoding() const noexcept { return __wd_ == 0u ? 7 : __wd_; } + _LIBCPP_HIDE_FROM_ABI inline constexpr bool ok() const noexcept { return __wd_ <= 6; } + _LIBCPP_HIDE_FROM_ABI constexpr weekday_indexed operator[](unsigned __index) const noexcept; + _LIBCPP_HIDE_FROM_ABI constexpr weekday_last operator[](last_spec) const noexcept; +}; + + +// https://howardhinnant.github.io/date_algorithms.html#weekday_from_days +_LIBCPP_HIDE_FROM_ABI inline constexpr +unsigned char weekday::__weekday_from_days(int __days) noexcept +{ + return static_cast( + static_cast(__days >= -4 ? (__days+4) % 7 : (__days+5) % 7 + 6) + ); +} + +_LIBCPP_HIDE_FROM_ABI inline constexpr +bool operator==(const weekday& __lhs, const weekday& __rhs) noexcept +{ return __lhs.c_encoding() == __rhs.c_encoding(); } + +_LIBCPP_HIDE_FROM_ABI inline constexpr +bool operator!=(const weekday& __lhs, const weekday& __rhs) noexcept +{ return !(__lhs == __rhs); } + +_LIBCPP_HIDE_FROM_ABI inline constexpr +bool operator< (const weekday& __lhs, const weekday& __rhs) noexcept +{ return __lhs.c_encoding() < __rhs.c_encoding(); } + +_LIBCPP_HIDE_FROM_ABI inline constexpr +bool operator> (const weekday& __lhs, const weekday& __rhs) noexcept +{ return __rhs < __lhs; } + +_LIBCPP_HIDE_FROM_ABI inline constexpr +bool operator<=(const weekday& __lhs, const weekday& __rhs) noexcept +{ return !(__rhs < __lhs);} + +_LIBCPP_HIDE_FROM_ABI inline constexpr +bool operator>=(const weekday& __lhs, const weekday& __rhs) noexcept +{ return !(__lhs < __rhs); } + +_LIBCPP_HIDE_FROM_ABI constexpr +weekday operator+(const weekday& __lhs, const days& __rhs) noexcept +{ + auto const __mu = static_cast(__lhs.c_encoding()) + __rhs.count(); + auto const __yr = (__mu >= 0 ? __mu : __mu - 6) / 7; + return weekday{static_cast(__mu - __yr * 7)}; +} + +_LIBCPP_HIDE_FROM_ABI constexpr +weekday operator+(const days& __lhs, const weekday& __rhs) noexcept +{ return __rhs + __lhs; } + +_LIBCPP_HIDE_FROM_ABI constexpr +weekday operator-(const weekday& __lhs, const days& __rhs) noexcept +{ return __lhs + -__rhs; } + +_LIBCPP_HIDE_FROM_ABI constexpr +days operator-(const weekday& __lhs, const weekday& __rhs) noexcept +{ + const int __wdu = __lhs.c_encoding() - __rhs.c_encoding(); + const int __wk = (__wdu >= 0 ? __wdu : __wdu-6) / 7; + return days{__wdu - __wk * 7}; +} + +_LIBCPP_HIDE_FROM_ABI inline constexpr +weekday& weekday::operator+=(const days& __dd) noexcept +{ *this = *this + __dd; return *this; } + +_LIBCPP_HIDE_FROM_ABI inline constexpr +weekday& weekday::operator-=(const days& __dd) noexcept +{ *this = *this - __dd; return *this; } + +class weekday_indexed { +private: + chrono::weekday __wd_; + unsigned char __idx_; +public: + _LIBCPP_HIDE_FROM_ABI weekday_indexed() = default; + _LIBCPP_HIDE_FROM_ABI inline constexpr weekday_indexed(const chrono::weekday& __wdval, unsigned __idxval) noexcept + : __wd_{__wdval}, __idx_(__idxval) {} + _LIBCPP_HIDE_FROM_ABI inline constexpr chrono::weekday weekday() const noexcept { return __wd_; } + _LIBCPP_HIDE_FROM_ABI inline constexpr unsigned index() const noexcept { return __idx_; } + _LIBCPP_HIDE_FROM_ABI inline constexpr bool ok() const noexcept { return __wd_.ok() && __idx_ >= 1 && __idx_ <= 5; } +}; + +_LIBCPP_HIDE_FROM_ABI inline constexpr +bool operator==(const weekday_indexed& __lhs, const weekday_indexed& __rhs) noexcept +{ return __lhs.weekday() == __rhs.weekday() && __lhs.index() == __rhs.index(); } + +_LIBCPP_HIDE_FROM_ABI inline constexpr +bool operator!=(const weekday_indexed& __lhs, const weekday_indexed& __rhs) noexcept +{ return !(__lhs == __rhs); } + + +class weekday_last { +private: + chrono::weekday __wd_; +public: + _LIBCPP_HIDE_FROM_ABI explicit constexpr weekday_last(const chrono::weekday& __val) noexcept + : __wd_{__val} {} + _LIBCPP_HIDE_FROM_ABI constexpr chrono::weekday weekday() const noexcept { return __wd_; } + _LIBCPP_HIDE_FROM_ABI constexpr bool ok() const noexcept { return __wd_.ok(); } +}; + +_LIBCPP_HIDE_FROM_ABI inline constexpr +bool operator==(const weekday_last& __lhs, const weekday_last& __rhs) noexcept +{ return __lhs.weekday() == __rhs.weekday(); } + +_LIBCPP_HIDE_FROM_ABI inline constexpr +bool operator!=(const weekday_last& __lhs, const weekday_last& __rhs) noexcept +{ return !(__lhs == __rhs); } + +_LIBCPP_HIDE_FROM_ABI inline constexpr +weekday_indexed weekday::operator[](unsigned __index) const noexcept { return weekday_indexed{*this, __index}; } + +_LIBCPP_HIDE_FROM_ABI inline constexpr +weekday_last weekday::operator[](last_spec) const noexcept { return weekday_last{*this}; } + + +inline constexpr weekday Sunday{0}; +inline constexpr weekday Monday{1}; +inline constexpr weekday Tuesday{2}; +inline constexpr weekday Wednesday{3}; +inline constexpr weekday Thursday{4}; +inline constexpr weekday Friday{5}; +inline constexpr weekday Saturday{6}; + +} // namespace chrono + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER > 17 + +#endif // _LIBCPP___CHRONO_WEEKDAY_H diff --git a/app/src/main/cpp/libcxx/include/__chrono/year.h b/app/src/main/cpp/libcxx/include/__chrono/year.h new file mode 100644 index 0000000..79ee8a0 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__chrono/year.h @@ -0,0 +1,102 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___CHRONO_YEAR_H +#define _LIBCPP___CHRONO_YEAR_H + +#include <__chrono/duration.h> +#include <__config> +#include +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + +#if _LIBCPP_STD_VER > 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace chrono +{ + +class year { +private: + short __y_; +public: + _LIBCPP_HIDE_FROM_ABI year() = default; + _LIBCPP_HIDE_FROM_ABI explicit inline constexpr year(int __val) noexcept : __y_(static_cast(__val)) {} + + _LIBCPP_HIDE_FROM_ABI inline constexpr year& operator++() noexcept { ++__y_; return *this; } + _LIBCPP_HIDE_FROM_ABI inline constexpr year operator++(int) noexcept { year __tmp = *this; ++(*this); return __tmp; } + _LIBCPP_HIDE_FROM_ABI inline constexpr year& operator--() noexcept { --__y_; return *this; } + _LIBCPP_HIDE_FROM_ABI inline constexpr year operator--(int) noexcept { year __tmp = *this; --(*this); return __tmp; } + _LIBCPP_HIDE_FROM_ABI constexpr year& operator+=(const years& __dy) noexcept; + _LIBCPP_HIDE_FROM_ABI constexpr year& operator-=(const years& __dy) noexcept; + _LIBCPP_HIDE_FROM_ABI inline constexpr year operator+() const noexcept { return *this; } + _LIBCPP_HIDE_FROM_ABI inline constexpr year operator-() const noexcept { return year{-__y_}; } + + _LIBCPP_HIDE_FROM_ABI inline constexpr bool is_leap() const noexcept { return __y_ % 4 == 0 && (__y_ % 100 != 0 || __y_ % 400 == 0); } + _LIBCPP_HIDE_FROM_ABI explicit inline constexpr operator int() const noexcept { return __y_; } + _LIBCPP_HIDE_FROM_ABI constexpr bool ok() const noexcept; + _LIBCPP_HIDE_FROM_ABI static inline constexpr year min() noexcept { return year{-32767}; } + _LIBCPP_HIDE_FROM_ABI static inline constexpr year max() noexcept { return year{ 32767}; } +}; + + +_LIBCPP_HIDE_FROM_ABI inline constexpr +bool operator==(const year& __lhs, const year& __rhs) noexcept +{ return static_cast(__lhs) == static_cast(__rhs); } + +_LIBCPP_HIDE_FROM_ABI constexpr strong_ordering operator<=>(const year& __lhs, const year& __rhs) noexcept { + return static_cast(__lhs) <=> static_cast(__rhs); +} + +_LIBCPP_HIDE_FROM_ABI inline constexpr +year operator+ (const year& __lhs, const years& __rhs) noexcept +{ return year(static_cast(__lhs) + __rhs.count()); } + +_LIBCPP_HIDE_FROM_ABI inline constexpr +year operator+ (const years& __lhs, const year& __rhs) noexcept +{ return __rhs + __lhs; } + +_LIBCPP_HIDE_FROM_ABI inline constexpr +year operator- (const year& __lhs, const years& __rhs) noexcept +{ return __lhs + -__rhs; } + +_LIBCPP_HIDE_FROM_ABI inline constexpr +years operator-(const year& __lhs, const year& __rhs) noexcept +{ return years{static_cast(__lhs) - static_cast(__rhs)}; } + + +_LIBCPP_HIDE_FROM_ABI inline constexpr +year& year::operator+=(const years& __dy) noexcept +{ *this = *this + __dy; return *this; } + +_LIBCPP_HIDE_FROM_ABI inline constexpr +year& year::operator-=(const years& __dy) noexcept +{ *this = *this - __dy; return *this; } + +_LIBCPP_HIDE_FROM_ABI constexpr bool year::ok() const noexcept { + static_assert(static_cast(std::numeric_limits::max()) == static_cast(max())); + return static_cast(min()) <= __y_; +} + +} // namespace chrono + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER > 17 + +_LIBCPP_POP_MACROS + +#endif // _LIBCPP___CHRONO_YEAR_H diff --git a/app/src/main/cpp/libcxx/include/__chrono/year_month.h b/app/src/main/cpp/libcxx/include/__chrono/year_month.h new file mode 100644 index 0000000..9f1e65c --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__chrono/year_month.h @@ -0,0 +1,101 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___CHRONO_YEAR_MONTH_H +#define _LIBCPP___CHRONO_YEAR_MONTH_H + +#include <__chrono/duration.h> +#include <__chrono/month.h> +#include <__chrono/year.h> +#include <__config> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if _LIBCPP_STD_VER > 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace chrono +{ + +class year_month { + chrono::year __y_; + chrono::month __m_; +public: + _LIBCPP_HIDE_FROM_ABI year_month() = default; + _LIBCPP_HIDE_FROM_ABI constexpr year_month(const chrono::year& __yval, const chrono::month& __mval) noexcept + : __y_{__yval}, __m_{__mval} {} + _LIBCPP_HIDE_FROM_ABI inline constexpr chrono::year year() const noexcept { return __y_; } + _LIBCPP_HIDE_FROM_ABI inline constexpr chrono::month month() const noexcept { return __m_; } + _LIBCPP_HIDE_FROM_ABI inline constexpr year_month& operator+=(const months& __dm) noexcept { this->__m_ += __dm; return *this; } + _LIBCPP_HIDE_FROM_ABI inline constexpr year_month& operator-=(const months& __dm) noexcept { this->__m_ -= __dm; return *this; } + _LIBCPP_HIDE_FROM_ABI inline constexpr year_month& operator+=(const years& __dy) noexcept { this->__y_ += __dy; return *this; } + _LIBCPP_HIDE_FROM_ABI inline constexpr year_month& operator-=(const years& __dy) noexcept { this->__y_ -= __dy; return *this; } + _LIBCPP_HIDE_FROM_ABI inline constexpr bool ok() const noexcept { return __y_.ok() && __m_.ok(); } +}; + +_LIBCPP_HIDE_FROM_ABI inline constexpr +year_month operator/(const year& __y, const month& __m) noexcept { return year_month{__y, __m}; } + +_LIBCPP_HIDE_FROM_ABI inline constexpr +year_month operator/(const year& __y, int __m) noexcept { return year_month{__y, month(__m)}; } + +_LIBCPP_HIDE_FROM_ABI inline constexpr +bool operator==(const year_month& __lhs, const year_month& __rhs) noexcept +{ return __lhs.year() == __rhs.year() && __lhs.month() == __rhs.month(); } + +_LIBCPP_HIDE_FROM_ABI constexpr strong_ordering operator<=>(const year_month& __lhs, const year_month& __rhs) noexcept { + if (auto __c = __lhs.year() <=> __rhs.year(); __c != 0) + return __c; + return __lhs.month() <=> __rhs.month(); +} + +_LIBCPP_HIDE_FROM_ABI constexpr +year_month operator+(const year_month& __lhs, const months& __rhs) noexcept +{ + int __dmi = static_cast(static_cast(__lhs.month())) - 1 + __rhs.count(); + const int __dy = (__dmi >= 0 ? __dmi : __dmi-11) / 12; + __dmi = __dmi - __dy * 12 + 1; + return (__lhs.year() + years(__dy)) / month(static_cast(__dmi)); +} + +_LIBCPP_HIDE_FROM_ABI constexpr +year_month operator+(const months& __lhs, const year_month& __rhs) noexcept +{ return __rhs + __lhs; } + +_LIBCPP_HIDE_FROM_ABI constexpr +year_month operator+(const year_month& __lhs, const years& __rhs) noexcept +{ return (__lhs.year() + __rhs) / __lhs.month(); } + +_LIBCPP_HIDE_FROM_ABI constexpr +year_month operator+(const years& __lhs, const year_month& __rhs) noexcept +{ return __rhs + __lhs; } + +_LIBCPP_HIDE_FROM_ABI constexpr +months operator-(const year_month& __lhs, const year_month& __rhs) noexcept +{ return (__lhs.year() - __rhs.year()) + months(static_cast(__lhs.month()) - static_cast(__rhs.month())); } + +_LIBCPP_HIDE_FROM_ABI constexpr +year_month operator-(const year_month& __lhs, const months& __rhs) noexcept +{ return __lhs + -__rhs; } + +_LIBCPP_HIDE_FROM_ABI constexpr +year_month operator-(const year_month& __lhs, const years& __rhs) noexcept +{ return __lhs + -__rhs; } + +} // namespace chrono + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER > 17 + +#endif // _LIBCPP___CHRONO_YEAR_MONTH_H diff --git a/app/src/main/cpp/libcxx/include/__chrono/year_month_day.h b/app/src/main/cpp/libcxx/include/__chrono/year_month_day.h new file mode 100644 index 0000000..b749014 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__chrono/year_month_day.h @@ -0,0 +1,307 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___CHRONO_YEAR_MONTH_DAY_H +#define _LIBCPP___CHRONO_YEAR_MONTH_DAY_H + +#include <__chrono/calendar.h> +#include <__chrono/day.h> +#include <__chrono/duration.h> +#include <__chrono/month.h> +#include <__chrono/monthday.h> +#include <__chrono/system_clock.h> +#include <__chrono/time_point.h> +#include <__chrono/year.h> +#include <__chrono/year_month.h> +#include <__config> +#include +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if _LIBCPP_STD_VER > 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace chrono +{ + +class year_month_day_last; + +class year_month_day { +private: + chrono::year __y_; + chrono::month __m_; + chrono::day __d_; +public: + _LIBCPP_HIDE_FROM_ABI year_month_day() = default; + _LIBCPP_HIDE_FROM_ABI inline constexpr year_month_day( + const chrono::year& __yval, const chrono::month& __mval, const chrono::day& __dval) noexcept + : __y_{__yval}, __m_{__mval}, __d_{__dval} {} + _LIBCPP_HIDE_FROM_ABI constexpr year_month_day(const year_month_day_last& __ymdl) noexcept; + _LIBCPP_HIDE_FROM_ABI inline constexpr year_month_day(const sys_days& __sysd) noexcept + : year_month_day(__from_days(__sysd.time_since_epoch())) {} + _LIBCPP_HIDE_FROM_ABI inline explicit constexpr year_month_day(const local_days& __locd) noexcept + : year_month_day(__from_days(__locd.time_since_epoch())) {} + + _LIBCPP_HIDE_FROM_ABI constexpr year_month_day& operator+=(const months& __dm) noexcept; + _LIBCPP_HIDE_FROM_ABI constexpr year_month_day& operator-=(const months& __dm) noexcept; + _LIBCPP_HIDE_FROM_ABI constexpr year_month_day& operator+=(const years& __dy) noexcept; + _LIBCPP_HIDE_FROM_ABI constexpr year_month_day& operator-=(const years& __dy) noexcept; + + _LIBCPP_HIDE_FROM_ABI inline constexpr chrono::year year() const noexcept { return __y_; } + _LIBCPP_HIDE_FROM_ABI inline constexpr chrono::month month() const noexcept { return __m_; } + _LIBCPP_HIDE_FROM_ABI inline constexpr chrono::day day() const noexcept { return __d_; } + _LIBCPP_HIDE_FROM_ABI inline constexpr operator sys_days() const noexcept { return sys_days{__to_days()}; } + _LIBCPP_HIDE_FROM_ABI inline explicit constexpr operator local_days() const noexcept { return local_days{__to_days()}; } + + _LIBCPP_HIDE_FROM_ABI constexpr bool ok() const noexcept; + + _LIBCPP_HIDE_FROM_ABI static constexpr year_month_day __from_days(days __d) noexcept; + _LIBCPP_HIDE_FROM_ABI constexpr days __to_days() const noexcept; +}; + + +// https://howardhinnant.github.io/date_algorithms.html#civil_from_days +_LIBCPP_HIDE_FROM_ABI inline constexpr +year_month_day year_month_day::__from_days(days __d) noexcept +{ + static_assert(numeric_limits::digits >= 18, ""); + static_assert(numeric_limits::digits >= 20 , ""); + const int __z = __d.count() + 719468; + const int __era = (__z >= 0 ? __z : __z - 146096) / 146097; + const unsigned __doe = static_cast(__z - __era * 146097); // [0, 146096] + const unsigned __yoe = (__doe - __doe/1460 + __doe/36524 - __doe/146096) / 365; // [0, 399] + const int __yr = static_cast(__yoe) + __era * 400; + const unsigned __doy = __doe - (365 * __yoe + __yoe/4 - __yoe/100); // [0, 365] + const unsigned __mp = (5 * __doy + 2)/153; // [0, 11] + const unsigned __dy = __doy - (153 * __mp + 2)/5 + 1; // [1, 31] + const unsigned __mth = __mp + (__mp < 10 ? 3 : -9); // [1, 12] + return year_month_day{chrono::year{__yr + (__mth <= 2)}, chrono::month{__mth}, chrono::day{__dy}}; +} + +// https://howardhinnant.github.io/date_algorithms.html#days_from_civil +_LIBCPP_HIDE_FROM_ABI inline constexpr +days year_month_day::__to_days() const noexcept +{ + static_assert(numeric_limits::digits >= 18, ""); + static_assert(numeric_limits::digits >= 20 , ""); + + const int __yr = static_cast(__y_) - (__m_ <= February); + const unsigned __mth = static_cast(__m_); + const unsigned __dy = static_cast(__d_); + + const int __era = (__yr >= 0 ? __yr : __yr - 399) / 400; + const unsigned __yoe = static_cast(__yr - __era * 400); // [0, 399] + const unsigned __doy = (153 * (__mth + (__mth > 2 ? -3 : 9)) + 2) / 5 + __dy-1; // [0, 365] + const unsigned __doe = __yoe * 365 + __yoe/4 - __yoe/100 + __doy; // [0, 146096] + return days{__era * 146097 + static_cast(__doe) - 719468}; +} + +_LIBCPP_HIDE_FROM_ABI inline constexpr +bool operator==(const year_month_day& __lhs, const year_month_day& __rhs) noexcept +{ return __lhs.year() == __rhs.year() && __lhs.month() == __rhs.month() && __lhs.day() == __rhs.day(); } + +_LIBCPP_HIDE_FROM_ABI constexpr strong_ordering +operator<=>(const year_month_day& __lhs, const year_month_day& __rhs) noexcept { + if (auto __c = __lhs.year() <=> __rhs.year(); __c != 0) + return __c; + if (auto __c = __lhs.month() <=> __rhs.month(); __c != 0) + return __c; + return __lhs.day() <=> __rhs.day(); +} + +_LIBCPP_HIDE_FROM_ABI inline constexpr +year_month_day operator/(const year_month& __lhs, const day& __rhs) noexcept +{ return year_month_day{__lhs.year(), __lhs.month(), __rhs}; } + +_LIBCPP_HIDE_FROM_ABI inline constexpr +year_month_day operator/(const year_month& __lhs, int __rhs) noexcept +{ return __lhs / day(__rhs); } + +_LIBCPP_HIDE_FROM_ABI inline constexpr +year_month_day operator/(const year& __lhs, const month_day& __rhs) noexcept +{ return __lhs / __rhs.month() / __rhs.day(); } + +_LIBCPP_HIDE_FROM_ABI inline constexpr +year_month_day operator/(int __lhs, const month_day& __rhs) noexcept +{ return year(__lhs) / __rhs; } + +_LIBCPP_HIDE_FROM_ABI inline constexpr +year_month_day operator/(const month_day& __lhs, const year& __rhs) noexcept +{ return __rhs / __lhs; } + +_LIBCPP_HIDE_FROM_ABI inline constexpr +year_month_day operator/(const month_day& __lhs, int __rhs) noexcept +{ return year(__rhs) / __lhs; } + + +_LIBCPP_HIDE_FROM_ABI inline constexpr +year_month_day operator+(const year_month_day& __lhs, const months& __rhs) noexcept +{ return (__lhs.year()/__lhs.month() + __rhs)/__lhs.day(); } + +_LIBCPP_HIDE_FROM_ABI inline constexpr +year_month_day operator+(const months& __lhs, const year_month_day& __rhs) noexcept +{ return __rhs + __lhs; } + +_LIBCPP_HIDE_FROM_ABI inline constexpr +year_month_day operator-(const year_month_day& __lhs, const months& __rhs) noexcept +{ return __lhs + -__rhs; } + +_LIBCPP_HIDE_FROM_ABI inline constexpr +year_month_day operator+(const year_month_day& __lhs, const years& __rhs) noexcept +{ return (__lhs.year() + __rhs) / __lhs.month() / __lhs.day(); } + +_LIBCPP_HIDE_FROM_ABI inline constexpr +year_month_day operator+(const years& __lhs, const year_month_day& __rhs) noexcept +{ return __rhs + __lhs; } + +_LIBCPP_HIDE_FROM_ABI inline constexpr +year_month_day operator-(const year_month_day& __lhs, const years& __rhs) noexcept +{ return __lhs + -__rhs; } + +_LIBCPP_HIDE_FROM_ABI inline constexpr year_month_day& year_month_day::operator+=(const months& __dm) noexcept { *this = *this + __dm; return *this; } +_LIBCPP_HIDE_FROM_ABI inline constexpr year_month_day& year_month_day::operator-=(const months& __dm) noexcept { *this = *this - __dm; return *this; } +_LIBCPP_HIDE_FROM_ABI inline constexpr year_month_day& year_month_day::operator+=(const years& __dy) noexcept { *this = *this + __dy; return *this; } +_LIBCPP_HIDE_FROM_ABI inline constexpr year_month_day& year_month_day::operator-=(const years& __dy) noexcept { *this = *this - __dy; return *this; } + +class year_month_day_last { +private: + chrono::year __y_; + chrono::month_day_last __mdl_; +public: + _LIBCPP_HIDE_FROM_ABI constexpr year_month_day_last(const year& __yval, const month_day_last& __mdlval) noexcept + : __y_{__yval}, __mdl_{__mdlval} {} + + _LIBCPP_HIDE_FROM_ABI constexpr year_month_day_last& operator+=(const months& __m) noexcept; + _LIBCPP_HIDE_FROM_ABI constexpr year_month_day_last& operator-=(const months& __m) noexcept; + _LIBCPP_HIDE_FROM_ABI constexpr year_month_day_last& operator+=(const years& __y) noexcept; + _LIBCPP_HIDE_FROM_ABI constexpr year_month_day_last& operator-=(const years& __y) noexcept; + + _LIBCPP_HIDE_FROM_ABI inline constexpr chrono::year year() const noexcept { return __y_; } + _LIBCPP_HIDE_FROM_ABI inline constexpr chrono::month month() const noexcept { return __mdl_.month(); } + _LIBCPP_HIDE_FROM_ABI inline constexpr chrono::month_day_last month_day_last() const noexcept { return __mdl_; } + _LIBCPP_HIDE_FROM_ABI constexpr chrono::day day() const noexcept; + _LIBCPP_HIDE_FROM_ABI inline constexpr operator sys_days() const noexcept { return sys_days{year()/month()/day()}; } + _LIBCPP_HIDE_FROM_ABI inline explicit constexpr operator local_days() const noexcept { return local_days{year()/month()/day()}; } + _LIBCPP_HIDE_FROM_ABI inline constexpr bool ok() const noexcept { return __y_.ok() && __mdl_.ok(); } +}; + +_LIBCPP_HIDE_FROM_ABI inline constexpr +chrono::day year_month_day_last::day() const noexcept +{ + constexpr chrono::day __d[] = + { + chrono::day(31), chrono::day(28), chrono::day(31), + chrono::day(30), chrono::day(31), chrono::day(30), + chrono::day(31), chrono::day(31), chrono::day(30), + chrono::day(31), chrono::day(30), chrono::day(31) + }; + return (month() != February || !__y_.is_leap()) && month().ok() ? + __d[static_cast(month()) - 1] : chrono::day{29}; +} + +_LIBCPP_HIDE_FROM_ABI inline constexpr +bool operator==(const year_month_day_last& __lhs, const year_month_day_last& __rhs) noexcept +{ return __lhs.year() == __rhs.year() && __lhs.month_day_last() == __rhs.month_day_last(); } + +_LIBCPP_HIDE_FROM_ABI inline constexpr +bool operator!=(const year_month_day_last& __lhs, const year_month_day_last& __rhs) noexcept +{ return !(__lhs == __rhs); } + +_LIBCPP_HIDE_FROM_ABI inline constexpr +bool operator< (const year_month_day_last& __lhs, const year_month_day_last& __rhs) noexcept +{ + if (__lhs.year() < __rhs.year()) return true; + if (__lhs.year() > __rhs.year()) return false; + return __lhs.month_day_last() < __rhs.month_day_last(); +} + +_LIBCPP_HIDE_FROM_ABI inline constexpr +bool operator> (const year_month_day_last& __lhs, const year_month_day_last& __rhs) noexcept +{ return __rhs < __lhs; } + +_LIBCPP_HIDE_FROM_ABI inline constexpr +bool operator<=(const year_month_day_last& __lhs, const year_month_day_last& __rhs) noexcept +{ return !(__rhs < __lhs);} + +_LIBCPP_HIDE_FROM_ABI inline constexpr +bool operator>=(const year_month_day_last& __lhs, const year_month_day_last& __rhs) noexcept +{ return !(__lhs < __rhs); } + +_LIBCPP_HIDE_FROM_ABI inline constexpr +year_month_day_last operator/(const year_month& __lhs, last_spec) noexcept +{ return year_month_day_last{__lhs.year(), month_day_last{__lhs.month()}}; } + +_LIBCPP_HIDE_FROM_ABI inline constexpr +year_month_day_last operator/(const year& __lhs, const month_day_last& __rhs) noexcept +{ return year_month_day_last{__lhs, __rhs}; } + +_LIBCPP_HIDE_FROM_ABI inline constexpr +year_month_day_last operator/(int __lhs, const month_day_last& __rhs) noexcept +{ return year_month_day_last{year{__lhs}, __rhs}; } + +_LIBCPP_HIDE_FROM_ABI inline constexpr year_month_day_last +operator/(const month_day_last& __lhs, const year& __rhs) noexcept +{ return __rhs / __lhs; } + +_LIBCPP_HIDE_FROM_ABI inline constexpr +year_month_day_last operator/(const month_day_last& __lhs, int __rhs) noexcept +{ return year{__rhs} / __lhs; } + + +_LIBCPP_HIDE_FROM_ABI inline constexpr +year_month_day_last operator+(const year_month_day_last& __lhs, const months& __rhs) noexcept +{ return (__lhs.year() / __lhs.month() + __rhs) / last; } + +_LIBCPP_HIDE_FROM_ABI inline constexpr +year_month_day_last operator+(const months& __lhs, const year_month_day_last& __rhs) noexcept +{ return __rhs + __lhs; } + +_LIBCPP_HIDE_FROM_ABI inline constexpr +year_month_day_last operator-(const year_month_day_last& __lhs, const months& __rhs) noexcept +{ return __lhs + (-__rhs); } + +_LIBCPP_HIDE_FROM_ABI inline constexpr +year_month_day_last operator+(const year_month_day_last& __lhs, const years& __rhs) noexcept +{ return year_month_day_last{__lhs.year() + __rhs, __lhs.month_day_last()}; } + +_LIBCPP_HIDE_FROM_ABI inline constexpr +year_month_day_last operator+(const years& __lhs, const year_month_day_last& __rhs) noexcept +{ return __rhs + __lhs; } + +_LIBCPP_HIDE_FROM_ABI inline constexpr +year_month_day_last operator-(const year_month_day_last& __lhs, const years& __rhs) noexcept +{ return __lhs + (-__rhs); } + +_LIBCPP_HIDE_FROM_ABI inline constexpr year_month_day_last& year_month_day_last::operator+=(const months& __dm) noexcept { *this = *this + __dm; return *this; } +_LIBCPP_HIDE_FROM_ABI inline constexpr year_month_day_last& year_month_day_last::operator-=(const months& __dm) noexcept { *this = *this - __dm; return *this; } +_LIBCPP_HIDE_FROM_ABI inline constexpr year_month_day_last& year_month_day_last::operator+=(const years& __dy) noexcept { *this = *this + __dy; return *this; } +_LIBCPP_HIDE_FROM_ABI inline constexpr year_month_day_last& year_month_day_last::operator-=(const years& __dy) noexcept { *this = *this - __dy; return *this; } + +_LIBCPP_HIDE_FROM_ABI inline constexpr +year_month_day::year_month_day(const year_month_day_last& __ymdl) noexcept + : __y_{__ymdl.year()}, __m_{__ymdl.month()}, __d_{__ymdl.day()} {} + +_LIBCPP_HIDE_FROM_ABI inline constexpr +bool year_month_day::ok() const noexcept +{ + if (!__y_.ok() || !__m_.ok()) return false; + return chrono::day{1} <= __d_ && __d_ <= (__y_ / __m_ / last).day(); +} + +} // namespace chrono + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER > 17 + +#endif // _LIBCPP___CHRONO_YEAR_MONTH_DAY_H diff --git a/app/src/main/cpp/libcxx/include/__chrono/year_month_weekday.h b/app/src/main/cpp/libcxx/include/__chrono/year_month_weekday.h new file mode 100644 index 0000000..6604dea --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__chrono/year_month_weekday.h @@ -0,0 +1,255 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___CHRONO_YEAR_MONTH_WEEKDAY_H +#define _LIBCPP___CHRONO_YEAR_MONTH_WEEKDAY_H + +#include <__chrono/calendar.h> +#include <__chrono/day.h> +#include <__chrono/duration.h> +#include <__chrono/month.h> +#include <__chrono/month_weekday.h> +#include <__chrono/system_clock.h> +#include <__chrono/time_point.h> +#include <__chrono/weekday.h> +#include <__chrono/year.h> +#include <__chrono/year_month.h> +#include <__chrono/year_month_day.h> +#include <__config> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if _LIBCPP_STD_VER > 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace chrono +{ + +class year_month_weekday { + chrono::year __y_; + chrono::month __m_; + chrono::weekday_indexed __wdi_; +public: + _LIBCPP_HIDE_FROM_ABI year_month_weekday() = default; + _LIBCPP_HIDE_FROM_ABI constexpr year_month_weekday(const chrono::year& __yval, const chrono::month& __mval, + const chrono::weekday_indexed& __wdival) noexcept + : __y_{__yval}, __m_{__mval}, __wdi_{__wdival} {} + _LIBCPP_HIDE_FROM_ABI constexpr year_month_weekday(const sys_days& __sysd) noexcept + : year_month_weekday(__from_days(__sysd.time_since_epoch())) {} + _LIBCPP_HIDE_FROM_ABI inline explicit constexpr year_month_weekday(const local_days& __locd) noexcept + : year_month_weekday(__from_days(__locd.time_since_epoch())) {} + _LIBCPP_HIDE_FROM_ABI constexpr year_month_weekday& operator+=(const months&) noexcept; + _LIBCPP_HIDE_FROM_ABI constexpr year_month_weekday& operator-=(const months&) noexcept; + _LIBCPP_HIDE_FROM_ABI constexpr year_month_weekday& operator+=(const years&) noexcept; + _LIBCPP_HIDE_FROM_ABI constexpr year_month_weekday& operator-=(const years&) noexcept; + + _LIBCPP_HIDE_FROM_ABI inline constexpr chrono::year year() const noexcept { return __y_; } + _LIBCPP_HIDE_FROM_ABI inline constexpr chrono::month month() const noexcept { return __m_; } + _LIBCPP_HIDE_FROM_ABI inline constexpr chrono::weekday weekday() const noexcept { return __wdi_.weekday(); } + _LIBCPP_HIDE_FROM_ABI inline constexpr unsigned index() const noexcept { return __wdi_.index(); } + _LIBCPP_HIDE_FROM_ABI inline constexpr chrono::weekday_indexed weekday_indexed() const noexcept { return __wdi_; } + + _LIBCPP_HIDE_FROM_ABI inline constexpr operator sys_days() const noexcept { return sys_days{__to_days()}; } + _LIBCPP_HIDE_FROM_ABI inline explicit constexpr operator local_days() const noexcept { return local_days{__to_days()}; } + _LIBCPP_HIDE_FROM_ABI inline constexpr bool ok() const noexcept + { + if (!__y_.ok() || !__m_.ok() || !__wdi_.ok()) return false; + if (__wdi_.index() <= 4) return true; + auto __nth_weekday_day = + __wdi_.weekday() - + chrono::weekday{static_cast(__y_ / __m_ / 1)} + + days{(__wdi_.index() - 1) * 7 + 1}; + return static_cast(__nth_weekday_day.count()) <= + static_cast((__y_ / __m_ / last).day()); + } + + _LIBCPP_HIDE_FROM_ABI static constexpr year_month_weekday __from_days(days __d) noexcept; + _LIBCPP_HIDE_FROM_ABI constexpr days __to_days() const noexcept; +}; + +_LIBCPP_HIDE_FROM_ABI inline constexpr +year_month_weekday year_month_weekday::__from_days(days __d) noexcept +{ + const sys_days __sysd{__d}; + const chrono::weekday __wd = chrono::weekday(__sysd); + const year_month_day __ymd = year_month_day(__sysd); + return year_month_weekday{__ymd.year(), __ymd.month(), + __wd[(static_cast(__ymd.day())-1)/7+1]}; +} + +_LIBCPP_HIDE_FROM_ABI inline constexpr +days year_month_weekday::__to_days() const noexcept +{ + const sys_days __sysd = sys_days(__y_/__m_/1); + return (__sysd + (__wdi_.weekday() - chrono::weekday(__sysd) + days{(__wdi_.index()-1)*7})) + .time_since_epoch(); +} + +_LIBCPP_HIDE_FROM_ABI inline constexpr +bool operator==(const year_month_weekday& __lhs, const year_month_weekday& __rhs) noexcept +{ return __lhs.year() == __rhs.year() && __lhs.month() == __rhs.month() && __lhs.weekday_indexed() == __rhs.weekday_indexed(); } + +_LIBCPP_HIDE_FROM_ABI inline constexpr +bool operator!=(const year_month_weekday& __lhs, const year_month_weekday& __rhs) noexcept +{ return !(__lhs == __rhs); } + +_LIBCPP_HIDE_FROM_ABI inline constexpr +year_month_weekday operator/(const year_month& __lhs, const weekday_indexed& __rhs) noexcept +{ return year_month_weekday{__lhs.year(), __lhs.month(), __rhs}; } + +_LIBCPP_HIDE_FROM_ABI inline constexpr +year_month_weekday operator/(const year& __lhs, const month_weekday& __rhs) noexcept +{ return year_month_weekday{__lhs, __rhs.month(), __rhs.weekday_indexed()}; } + +_LIBCPP_HIDE_FROM_ABI inline constexpr +year_month_weekday operator/(int __lhs, const month_weekday& __rhs) noexcept +{ return year(__lhs) / __rhs; } + +_LIBCPP_HIDE_FROM_ABI inline constexpr +year_month_weekday operator/(const month_weekday& __lhs, const year& __rhs) noexcept +{ return __rhs / __lhs; } + +_LIBCPP_HIDE_FROM_ABI inline constexpr +year_month_weekday operator/(const month_weekday& __lhs, int __rhs) noexcept +{ return year(__rhs) / __lhs; } + + +_LIBCPP_HIDE_FROM_ABI inline constexpr +year_month_weekday operator+(const year_month_weekday& __lhs, const months& __rhs) noexcept +{ return (__lhs.year() / __lhs.month() + __rhs) / __lhs.weekday_indexed(); } + +_LIBCPP_HIDE_FROM_ABI inline constexpr +year_month_weekday operator+(const months& __lhs, const year_month_weekday& __rhs) noexcept +{ return __rhs + __lhs; } + +_LIBCPP_HIDE_FROM_ABI inline constexpr +year_month_weekday operator-(const year_month_weekday& __lhs, const months& __rhs) noexcept +{ return __lhs + (-__rhs); } + +_LIBCPP_HIDE_FROM_ABI inline constexpr +year_month_weekday operator+(const year_month_weekday& __lhs, const years& __rhs) noexcept +{ return year_month_weekday{__lhs.year() + __rhs, __lhs.month(), __lhs.weekday_indexed()}; } + +_LIBCPP_HIDE_FROM_ABI inline constexpr +year_month_weekday operator+(const years& __lhs, const year_month_weekday& __rhs) noexcept +{ return __rhs + __lhs; } + +_LIBCPP_HIDE_FROM_ABI inline constexpr +year_month_weekday operator-(const year_month_weekday& __lhs, const years& __rhs) noexcept +{ return __lhs + (-__rhs); } + + +_LIBCPP_HIDE_FROM_ABI inline constexpr year_month_weekday& year_month_weekday::operator+=(const months& __dm) noexcept { *this = *this + __dm; return *this; } +_LIBCPP_HIDE_FROM_ABI inline constexpr year_month_weekday& year_month_weekday::operator-=(const months& __dm) noexcept { *this = *this - __dm; return *this; } +_LIBCPP_HIDE_FROM_ABI inline constexpr year_month_weekday& year_month_weekday::operator+=(const years& __dy) noexcept { *this = *this + __dy; return *this; } +_LIBCPP_HIDE_FROM_ABI inline constexpr year_month_weekday& year_month_weekday::operator-=(const years& __dy) noexcept { *this = *this - __dy; return *this; } + +class year_month_weekday_last { +private: + chrono::year __y_; + chrono::month __m_; + chrono::weekday_last __wdl_; +public: + _LIBCPP_HIDE_FROM_ABI constexpr year_month_weekday_last(const chrono::year& __yval, const chrono::month& __mval, + const chrono::weekday_last& __wdlval) noexcept + : __y_{__yval}, __m_{__mval}, __wdl_{__wdlval} {} + _LIBCPP_HIDE_FROM_ABI constexpr year_month_weekday_last& operator+=(const months& __dm) noexcept; + _LIBCPP_HIDE_FROM_ABI constexpr year_month_weekday_last& operator-=(const months& __dm) noexcept; + _LIBCPP_HIDE_FROM_ABI constexpr year_month_weekday_last& operator+=(const years& __dy) noexcept; + _LIBCPP_HIDE_FROM_ABI constexpr year_month_weekday_last& operator-=(const years& __dy) noexcept; + + _LIBCPP_HIDE_FROM_ABI inline constexpr chrono::year year() const noexcept { return __y_; } + _LIBCPP_HIDE_FROM_ABI inline constexpr chrono::month month() const noexcept { return __m_; } + _LIBCPP_HIDE_FROM_ABI inline constexpr chrono::weekday weekday() const noexcept { return __wdl_.weekday(); } + _LIBCPP_HIDE_FROM_ABI inline constexpr chrono::weekday_last weekday_last() const noexcept { return __wdl_; } + _LIBCPP_HIDE_FROM_ABI inline constexpr operator sys_days() const noexcept { return sys_days{__to_days()}; } + _LIBCPP_HIDE_FROM_ABI inline explicit constexpr operator local_days() const noexcept { return local_days{__to_days()}; } + _LIBCPP_HIDE_FROM_ABI inline constexpr bool ok() const noexcept { return __y_.ok() && __m_.ok() && __wdl_.ok(); } + + _LIBCPP_HIDE_FROM_ABI constexpr days __to_days() const noexcept; + +}; + +_LIBCPP_HIDE_FROM_ABI inline constexpr +days year_month_weekday_last::__to_days() const noexcept +{ + const sys_days __last = sys_days{__y_/__m_/last}; + return (__last - (chrono::weekday{__last} - __wdl_.weekday())).time_since_epoch(); + +} + +_LIBCPP_HIDE_FROM_ABI inline constexpr +bool operator==(const year_month_weekday_last& __lhs, const year_month_weekday_last& __rhs) noexcept +{ return __lhs.year() == __rhs.year() && __lhs.month() == __rhs.month() && __lhs.weekday_last() == __rhs.weekday_last(); } + +_LIBCPP_HIDE_FROM_ABI inline constexpr +bool operator!=(const year_month_weekday_last& __lhs, const year_month_weekday_last& __rhs) noexcept +{ return !(__lhs == __rhs); } + + +_LIBCPP_HIDE_FROM_ABI inline constexpr +year_month_weekday_last operator/(const year_month& __lhs, const weekday_last& __rhs) noexcept +{ return year_month_weekday_last{__lhs.year(), __lhs.month(), __rhs}; } + +_LIBCPP_HIDE_FROM_ABI inline constexpr +year_month_weekday_last operator/(const year& __lhs, const month_weekday_last& __rhs) noexcept +{ return year_month_weekday_last{__lhs, __rhs.month(), __rhs.weekday_last()}; } + +_LIBCPP_HIDE_FROM_ABI inline constexpr +year_month_weekday_last operator/(int __lhs, const month_weekday_last& __rhs) noexcept +{ return year(__lhs) / __rhs; } + +_LIBCPP_HIDE_FROM_ABI inline constexpr +year_month_weekday_last operator/(const month_weekday_last& __lhs, const year& __rhs) noexcept +{ return __rhs / __lhs; } + +_LIBCPP_HIDE_FROM_ABI inline constexpr +year_month_weekday_last operator/(const month_weekday_last& __lhs, int __rhs) noexcept +{ return year(__rhs) / __lhs; } + + +_LIBCPP_HIDE_FROM_ABI inline constexpr +year_month_weekday_last operator+(const year_month_weekday_last& __lhs, const months& __rhs) noexcept +{ return (__lhs.year() / __lhs.month() + __rhs) / __lhs.weekday_last(); } + +_LIBCPP_HIDE_FROM_ABI inline constexpr +year_month_weekday_last operator+(const months& __lhs, const year_month_weekday_last& __rhs) noexcept +{ return __rhs + __lhs; } + +_LIBCPP_HIDE_FROM_ABI inline constexpr +year_month_weekday_last operator-(const year_month_weekday_last& __lhs, const months& __rhs) noexcept +{ return __lhs + (-__rhs); } + +_LIBCPP_HIDE_FROM_ABI inline constexpr +year_month_weekday_last operator+(const year_month_weekday_last& __lhs, const years& __rhs) noexcept +{ return year_month_weekday_last{__lhs.year() + __rhs, __lhs.month(), __lhs.weekday_last()}; } + +_LIBCPP_HIDE_FROM_ABI inline constexpr +year_month_weekday_last operator+(const years& __lhs, const year_month_weekday_last& __rhs) noexcept +{ return __rhs + __lhs; } + +_LIBCPP_HIDE_FROM_ABI inline constexpr +year_month_weekday_last operator-(const year_month_weekday_last& __lhs, const years& __rhs) noexcept +{ return __lhs + (-__rhs); } + +_LIBCPP_HIDE_FROM_ABI inline constexpr year_month_weekday_last& year_month_weekday_last::operator+=(const months& __dm) noexcept { *this = *this + __dm; return *this; } +_LIBCPP_HIDE_FROM_ABI inline constexpr year_month_weekday_last& year_month_weekday_last::operator-=(const months& __dm) noexcept { *this = *this - __dm; return *this; } +_LIBCPP_HIDE_FROM_ABI inline constexpr year_month_weekday_last& year_month_weekday_last::operator+=(const years& __dy) noexcept { *this = *this + __dy; return *this; } +_LIBCPP_HIDE_FROM_ABI inline constexpr year_month_weekday_last& year_month_weekday_last::operator-=(const years& __dy) noexcept { *this = *this - __dy; return *this; } + +} // namespace chrono + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER > 17 + +#endif // _LIBCPP___CHRONO_YEAR_MONTH_WEEKDAY_H diff --git a/app/src/main/cpp/libcxx/include/__compare/common_comparison_category.h b/app/src/main/cpp/libcxx/include/__compare/common_comparison_category.h new file mode 100644 index 0000000..06c4b28 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__compare/common_comparison_category.h @@ -0,0 +1,95 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___COMPARE_COMMON_COMPARISON_CATEGORY_H +#define _LIBCPP___COMPARE_COMMON_COMPARISON_CATEGORY_H + +#include <__compare/ordering.h> +#include <__config> +#include <__type_traits/is_same.h> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 17 + +namespace __comp_detail { + +enum _ClassifyCompCategory : unsigned { + _None, + _PartialOrd, + _WeakOrd, + _StrongOrd, + _CCC_Size +}; + +template +_LIBCPP_HIDE_FROM_ABI +constexpr _ClassifyCompCategory __type_to_enum() noexcept { + if (is_same_v<_Tp, partial_ordering>) + return _PartialOrd; + if (is_same_v<_Tp, weak_ordering>) + return _WeakOrd; + if (is_same_v<_Tp, strong_ordering>) + return _StrongOrd; + return _None; +} + +template +_LIBCPP_HIDE_FROM_ABI +constexpr _ClassifyCompCategory +__compute_comp_type(const _ClassifyCompCategory (&__types)[_Size]) { + int __seen[_CCC_Size] = {}; + for (auto __type : __types) + ++__seen[__type]; + if (__seen[_None]) + return _None; + if (__seen[_PartialOrd]) + return _PartialOrd; + if (__seen[_WeakOrd]) + return _WeakOrd; + return _StrongOrd; +} + +template +_LIBCPP_HIDE_FROM_ABI +constexpr auto __get_comp_type() { + using _CCC = _ClassifyCompCategory; + constexpr _CCC __type_kinds[] = {_StrongOrd, __type_to_enum<_Ts>()...}; + constexpr _CCC _Cat = __comp_detail::__compute_comp_type(__type_kinds); + if constexpr (_Cat == _None) + return void(); + else if constexpr (_Cat == _PartialOrd) + return partial_ordering::equivalent; + else if constexpr (_Cat == _WeakOrd) + return weak_ordering::equivalent; + else if constexpr (_Cat == _StrongOrd) + return strong_ordering::equivalent; + else + static_assert(_False, "unhandled case"); +} +} // namespace __comp_detail + +// [cmp.common], common comparison category type +template +struct _LIBCPP_TEMPLATE_VIS common_comparison_category { + using type = decltype(__comp_detail::__get_comp_type<_Ts...>()); +}; + +template +using common_comparison_category_t = typename common_comparison_category<_Ts...>::type; + +#endif // _LIBCPP_STD_VER > 17 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___COMPARE_COMMON_COMPARISON_CATEGORY_H diff --git a/app/src/main/cpp/libcxx/include/__compare/compare_partial_order_fallback.h b/app/src/main/cpp/libcxx/include/__compare/compare_partial_order_fallback.h new file mode 100644 index 0000000..06f03fe --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__compare/compare_partial_order_fallback.h @@ -0,0 +1,74 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___COMPARE_COMPARE_PARTIAL_ORDER_FALLBACK +#define _LIBCPP___COMPARE_COMPARE_PARTIAL_ORDER_FALLBACK + +#include <__compare/ordering.h> +#include <__compare/partial_order.h> +#include <__config> +#include <__type_traits/decay.h> +#include <__type_traits/is_same.h> +#include <__utility/forward.h> +#include <__utility/priority_tag.h> + +#ifndef _LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 17 + +// [cmp.alg] +namespace __compare_partial_order_fallback { + struct __fn { + template + requires is_same_v, decay_t<_Up>> + _LIBCPP_HIDE_FROM_ABI static constexpr auto + __go(_Tp&& __t, _Up&& __u, __priority_tag<1>) + noexcept(noexcept(_VSTD::partial_order(_VSTD::forward<_Tp>(__t), _VSTD::forward<_Up>(__u)))) + -> decltype( _VSTD::partial_order(_VSTD::forward<_Tp>(__t), _VSTD::forward<_Up>(__u))) + { return _VSTD::partial_order(_VSTD::forward<_Tp>(__t), _VSTD::forward<_Up>(__u)); } + + template + requires is_same_v, decay_t<_Up>> + _LIBCPP_HIDE_FROM_ABI static constexpr auto + __go(_Tp&& __t, _Up&& __u, __priority_tag<0>) + noexcept(noexcept(_VSTD::forward<_Tp>(__t) == _VSTD::forward<_Up>(__u) ? partial_ordering::equivalent : + _VSTD::forward<_Tp>(__t) < _VSTD::forward<_Up>(__u) ? partial_ordering::less : + _VSTD::forward<_Up>(__u) < _VSTD::forward<_Tp>(__t) ? partial_ordering::greater : + partial_ordering::unordered)) + -> decltype( _VSTD::forward<_Tp>(__t) == _VSTD::forward<_Up>(__u) ? partial_ordering::equivalent : + _VSTD::forward<_Tp>(__t) < _VSTD::forward<_Up>(__u) ? partial_ordering::less : + _VSTD::forward<_Up>(__u) < _VSTD::forward<_Tp>(__t) ? partial_ordering::greater : + partial_ordering::unordered) + { + return _VSTD::forward<_Tp>(__t) == _VSTD::forward<_Up>(__u) ? partial_ordering::equivalent : + _VSTD::forward<_Tp>(__t) < _VSTD::forward<_Up>(__u) ? partial_ordering::less : + _VSTD::forward<_Up>(__u) < _VSTD::forward<_Tp>(__t) ? partial_ordering::greater : + partial_ordering::unordered; + } + + template + _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Tp&& __t, _Up&& __u) const + noexcept(noexcept(__go(_VSTD::forward<_Tp>(__t), _VSTD::forward<_Up>(__u), __priority_tag<1>()))) + -> decltype( __go(_VSTD::forward<_Tp>(__t), _VSTD::forward<_Up>(__u), __priority_tag<1>())) + { return __go(_VSTD::forward<_Tp>(__t), _VSTD::forward<_Up>(__u), __priority_tag<1>()); } + }; +} // namespace __compare_partial_order_fallback + +inline namespace __cpo { + inline constexpr auto compare_partial_order_fallback = __compare_partial_order_fallback::__fn{}; +} // namespace __cpo + +#endif // _LIBCPP_STD_VER > 17 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___COMPARE_COMPARE_PARTIAL_ORDER_FALLBACK diff --git a/app/src/main/cpp/libcxx/include/__compare/compare_strong_order_fallback.h b/app/src/main/cpp/libcxx/include/__compare/compare_strong_order_fallback.h new file mode 100644 index 0000000..8693868 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__compare/compare_strong_order_fallback.h @@ -0,0 +1,71 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___COMPARE_COMPARE_STRONG_ORDER_FALLBACK +#define _LIBCPP___COMPARE_COMPARE_STRONG_ORDER_FALLBACK + +#include <__compare/ordering.h> +#include <__compare/strong_order.h> +#include <__config> +#include <__type_traits/decay.h> +#include <__type_traits/is_same.h> +#include <__utility/forward.h> +#include <__utility/priority_tag.h> + +#ifndef _LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 17 + +// [cmp.alg] +namespace __compare_strong_order_fallback { + struct __fn { + template + requires is_same_v, decay_t<_Up>> + _LIBCPP_HIDE_FROM_ABI static constexpr auto + __go(_Tp&& __t, _Up&& __u, __priority_tag<1>) + noexcept(noexcept(_VSTD::strong_order(_VSTD::forward<_Tp>(__t), _VSTD::forward<_Up>(__u)))) + -> decltype( _VSTD::strong_order(_VSTD::forward<_Tp>(__t), _VSTD::forward<_Up>(__u))) + { return _VSTD::strong_order(_VSTD::forward<_Tp>(__t), _VSTD::forward<_Up>(__u)); } + + template + requires is_same_v, decay_t<_Up>> + _LIBCPP_HIDE_FROM_ABI static constexpr auto + __go(_Tp&& __t, _Up&& __u, __priority_tag<0>) + noexcept(noexcept(_VSTD::forward<_Tp>(__t) == _VSTD::forward<_Up>(__u) ? strong_ordering::equal : + _VSTD::forward<_Tp>(__t) < _VSTD::forward<_Up>(__u) ? strong_ordering::less : + strong_ordering::greater)) + -> decltype( _VSTD::forward<_Tp>(__t) == _VSTD::forward<_Up>(__u) ? strong_ordering::equal : + _VSTD::forward<_Tp>(__t) < _VSTD::forward<_Up>(__u) ? strong_ordering::less : + strong_ordering::greater) + { + return _VSTD::forward<_Tp>(__t) == _VSTD::forward<_Up>(__u) ? strong_ordering::equal : + _VSTD::forward<_Tp>(__t) < _VSTD::forward<_Up>(__u) ? strong_ordering::less : + strong_ordering::greater; + } + + template + _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Tp&& __t, _Up&& __u) const + noexcept(noexcept(__go(_VSTD::forward<_Tp>(__t), _VSTD::forward<_Up>(__u), __priority_tag<1>()))) + -> decltype( __go(_VSTD::forward<_Tp>(__t), _VSTD::forward<_Up>(__u), __priority_tag<1>())) + { return __go(_VSTD::forward<_Tp>(__t), _VSTD::forward<_Up>(__u), __priority_tag<1>()); } + }; +} // namespace __compare_strong_order_fallback + +inline namespace __cpo { + inline constexpr auto compare_strong_order_fallback = __compare_strong_order_fallback::__fn{}; +} // namespace __cpo + +#endif // _LIBCPP_STD_VER > 17 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___COMPARE_COMPARE_STRONG_ORDER_FALLBACK diff --git a/app/src/main/cpp/libcxx/include/__compare/compare_three_way.h b/app/src/main/cpp/libcxx/include/__compare/compare_three_way.h new file mode 100644 index 0000000..fdbba04 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__compare/compare_three_way.h @@ -0,0 +1,41 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___COMPARE_COMPARE_THREE_WAY_H +#define _LIBCPP___COMPARE_COMPARE_THREE_WAY_H + +#include <__compare/three_way_comparable.h> +#include <__config> +#include <__utility/forward.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 17 + +struct _LIBCPP_TEMPLATE_VIS compare_three_way +{ + template + requires three_way_comparable_with<_T1, _T2> + constexpr _LIBCPP_HIDE_FROM_ABI + auto operator()(_T1&& __t, _T2&& __u) const + noexcept(noexcept(_VSTD::forward<_T1>(__t) <=> _VSTD::forward<_T2>(__u))) + { return _VSTD::forward<_T1>(__t) <=> _VSTD::forward<_T2>(__u); } + + using is_transparent = void; +}; + +#endif // _LIBCPP_STD_VER > 17 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___COMPARE_COMPARE_THREE_WAY_H diff --git a/app/src/main/cpp/libcxx/include/__compare/compare_three_way_result.h b/app/src/main/cpp/libcxx/include/__compare/compare_three_way_result.h new file mode 100644 index 0000000..8885d7e --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__compare/compare_three_way_result.h @@ -0,0 +1,44 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___COMPARE_COMPARE_THREE_WAY_RESULT_H +#define _LIBCPP___COMPARE_COMPARE_THREE_WAY_RESULT_H + +#include <__config> +#include <__type_traits/make_const_lvalue_ref.h> +#include <__utility/declval.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 17 + +template +struct _LIBCPP_HIDE_FROM_ABI __compare_three_way_result { }; + +template +struct _LIBCPP_HIDE_FROM_ABI __compare_three_way_result<_Tp, _Up, decltype( + std::declval<__make_const_lvalue_ref<_Tp>>() <=> std::declval<__make_const_lvalue_ref<_Up>>(), void() +)> { + using type = decltype(std::declval<__make_const_lvalue_ref<_Tp>>() <=> std::declval<__make_const_lvalue_ref<_Up>>()); +}; + +template +struct _LIBCPP_TEMPLATE_VIS compare_three_way_result : __compare_three_way_result<_Tp, _Up, void> { }; + +template +using compare_three_way_result_t = typename compare_three_way_result<_Tp, _Up>::type; + +#endif // _LIBCPP_STD_VER > 17 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___COMPARE_COMPARE_THREE_WAY_RESULT_H diff --git a/app/src/main/cpp/libcxx/include/__compare/compare_weak_order_fallback.h b/app/src/main/cpp/libcxx/include/__compare/compare_weak_order_fallback.h new file mode 100644 index 0000000..f434dcb --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__compare/compare_weak_order_fallback.h @@ -0,0 +1,71 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___COMPARE_COMPARE_WEAK_ORDER_FALLBACK +#define _LIBCPP___COMPARE_COMPARE_WEAK_ORDER_FALLBACK + +#include <__compare/ordering.h> +#include <__compare/weak_order.h> +#include <__config> +#include <__type_traits/decay.h> +#include <__type_traits/is_same.h> +#include <__utility/forward.h> +#include <__utility/priority_tag.h> + +#ifndef _LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 17 + +// [cmp.alg] +namespace __compare_weak_order_fallback { + struct __fn { + template + requires is_same_v, decay_t<_Up>> + _LIBCPP_HIDE_FROM_ABI static constexpr auto + __go(_Tp&& __t, _Up&& __u, __priority_tag<1>) + noexcept(noexcept(_VSTD::weak_order(_VSTD::forward<_Tp>(__t), _VSTD::forward<_Up>(__u)))) + -> decltype( _VSTD::weak_order(_VSTD::forward<_Tp>(__t), _VSTD::forward<_Up>(__u))) + { return _VSTD::weak_order(_VSTD::forward<_Tp>(__t), _VSTD::forward<_Up>(__u)); } + + template + requires is_same_v, decay_t<_Up>> + _LIBCPP_HIDE_FROM_ABI static constexpr auto + __go(_Tp&& __t, _Up&& __u, __priority_tag<0>) + noexcept(noexcept(_VSTD::forward<_Tp>(__t) == _VSTD::forward<_Up>(__u) ? weak_ordering::equivalent : + _VSTD::forward<_Tp>(__t) < _VSTD::forward<_Up>(__u) ? weak_ordering::less : + weak_ordering::greater)) + -> decltype( _VSTD::forward<_Tp>(__t) == _VSTD::forward<_Up>(__u) ? weak_ordering::equivalent : + _VSTD::forward<_Tp>(__t) < _VSTD::forward<_Up>(__u) ? weak_ordering::less : + weak_ordering::greater) + { + return _VSTD::forward<_Tp>(__t) == _VSTD::forward<_Up>(__u) ? weak_ordering::equivalent : + _VSTD::forward<_Tp>(__t) < _VSTD::forward<_Up>(__u) ? weak_ordering::less : + weak_ordering::greater; + } + + template + _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Tp&& __t, _Up&& __u) const + noexcept(noexcept(__go(_VSTD::forward<_Tp>(__t), _VSTD::forward<_Up>(__u), __priority_tag<1>()))) + -> decltype( __go(_VSTD::forward<_Tp>(__t), _VSTD::forward<_Up>(__u), __priority_tag<1>())) + { return __go(_VSTD::forward<_Tp>(__t), _VSTD::forward<_Up>(__u), __priority_tag<1>()); } + }; +} // namespace __compare_weak_order_fallback + +inline namespace __cpo { + inline constexpr auto compare_weak_order_fallback = __compare_weak_order_fallback::__fn{}; +} // namespace __cpo + +#endif // _LIBCPP_STD_VER > 17 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___COMPARE_COMPARE_WEAK_ORDER_FALLBACK diff --git a/app/src/main/cpp/libcxx/include/__compare/is_eq.h b/app/src/main/cpp/libcxx/include/__compare/is_eq.h new file mode 100644 index 0000000..4964892 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__compare/is_eq.h @@ -0,0 +1,34 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___COMPARE_IS_EQ_H +#define _LIBCPP___COMPARE_IS_EQ_H + +#include <__compare/ordering.h> +#include <__config> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 17 + +_LIBCPP_HIDE_FROM_ABI inline constexpr bool is_eq(partial_ordering __c) noexcept { return __c == 0; } +_LIBCPP_HIDE_FROM_ABI inline constexpr bool is_neq(partial_ordering __c) noexcept { return __c != 0; } +_LIBCPP_HIDE_FROM_ABI inline constexpr bool is_lt(partial_ordering __c) noexcept { return __c < 0; } +_LIBCPP_HIDE_FROM_ABI inline constexpr bool is_lteq(partial_ordering __c) noexcept { return __c <= 0; } +_LIBCPP_HIDE_FROM_ABI inline constexpr bool is_gt(partial_ordering __c) noexcept { return __c > 0; } +_LIBCPP_HIDE_FROM_ABI inline constexpr bool is_gteq(partial_ordering __c) noexcept { return __c >= 0; } + +#endif // _LIBCPP_STD_VER > 17 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___COMPARE_IS_EQ_H diff --git a/app/src/main/cpp/libcxx/include/__compare/ordering.h b/app/src/main/cpp/libcxx/include/__compare/ordering.h new file mode 100644 index 0000000..ff148ab --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__compare/ordering.h @@ -0,0 +1,326 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___COMPARE_ORDERING_H +#define _LIBCPP___COMPARE_ORDERING_H + +#include <__config> +#include <__type_traits/enable_if.h> +#include <__type_traits/is_same.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 17 + +// exposition only +enum class _LIBCPP_ENUM_VIS _OrdResult : signed char { + __less = -1, + __equiv = 0, + __greater = 1 +}; + +enum class _LIBCPP_ENUM_VIS _NCmpResult : signed char { + __unordered = -127 +}; + +class partial_ordering; +class weak_ordering; +class strong_ordering; + +template +inline constexpr bool __one_of_v = (is_same_v<_Tp, _Args> || ...); + +struct _CmpUnspecifiedParam { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEVAL + _CmpUnspecifiedParam(int _CmpUnspecifiedParam::*) noexcept {} + + template>> + _CmpUnspecifiedParam(_Tp) = delete; +}; + +class partial_ordering { + using _ValueT = signed char; + + _LIBCPP_HIDE_FROM_ABI + explicit constexpr partial_ordering(_OrdResult __v) noexcept + : __value_(_ValueT(__v)) {} + + _LIBCPP_HIDE_FROM_ABI + explicit constexpr partial_ordering(_NCmpResult __v) noexcept + : __value_(_ValueT(__v)) {} + + _LIBCPP_HIDE_FROM_ABI + constexpr bool __is_ordered() const noexcept { + return __value_ != _ValueT(_NCmpResult::__unordered); + } +public: + // valid values + static const partial_ordering less; + static const partial_ordering equivalent; + static const partial_ordering greater; + static const partial_ordering unordered; + + // comparisons + _LIBCPP_HIDE_FROM_ABI + friend constexpr bool operator==(partial_ordering, partial_ordering) noexcept = default; + + _LIBCPP_HIDE_FROM_ABI + friend constexpr bool operator==(partial_ordering __v, _CmpUnspecifiedParam) noexcept { + return __v.__is_ordered() && __v.__value_ == 0; + } + + _LIBCPP_HIDE_FROM_ABI + friend constexpr bool operator< (partial_ordering __v, _CmpUnspecifiedParam) noexcept { + return __v.__is_ordered() && __v.__value_ < 0; + } + + _LIBCPP_HIDE_FROM_ABI + friend constexpr bool operator<=(partial_ordering __v, _CmpUnspecifiedParam) noexcept { + return __v.__is_ordered() && __v.__value_ <= 0; + } + + _LIBCPP_HIDE_FROM_ABI + friend constexpr bool operator> (partial_ordering __v, _CmpUnspecifiedParam) noexcept { + return __v.__is_ordered() && __v.__value_ > 0; + } + + _LIBCPP_HIDE_FROM_ABI + friend constexpr bool operator>=(partial_ordering __v, _CmpUnspecifiedParam) noexcept { + return __v.__is_ordered() && __v.__value_ >= 0; + } + + _LIBCPP_HIDE_FROM_ABI + friend constexpr bool operator< (_CmpUnspecifiedParam, partial_ordering __v) noexcept { + return __v.__is_ordered() && 0 < __v.__value_; + } + + _LIBCPP_HIDE_FROM_ABI + friend constexpr bool operator<=(_CmpUnspecifiedParam, partial_ordering __v) noexcept { + return __v.__is_ordered() && 0 <= __v.__value_; + } + + _LIBCPP_HIDE_FROM_ABI + friend constexpr bool operator> (_CmpUnspecifiedParam, partial_ordering __v) noexcept { + return __v.__is_ordered() && 0 > __v.__value_; + } + + _LIBCPP_HIDE_FROM_ABI + friend constexpr bool operator>=(_CmpUnspecifiedParam, partial_ordering __v) noexcept { + return __v.__is_ordered() && 0 >= __v.__value_; + } + + _LIBCPP_HIDE_FROM_ABI + friend constexpr partial_ordering operator<=>(partial_ordering __v, _CmpUnspecifiedParam) noexcept { + return __v; + } + + _LIBCPP_HIDE_FROM_ABI + friend constexpr partial_ordering operator<=>(_CmpUnspecifiedParam, partial_ordering __v) noexcept { + return __v < 0 ? partial_ordering::greater : (__v > 0 ? partial_ordering::less : __v); + } +private: + _ValueT __value_; +}; + +inline constexpr partial_ordering partial_ordering::less(_OrdResult::__less); +inline constexpr partial_ordering partial_ordering::equivalent(_OrdResult::__equiv); +inline constexpr partial_ordering partial_ordering::greater(_OrdResult::__greater); +inline constexpr partial_ordering partial_ordering::unordered(_NCmpResult ::__unordered); + +class weak_ordering { + using _ValueT = signed char; + + _LIBCPP_HIDE_FROM_ABI + explicit constexpr weak_ordering(_OrdResult __v) noexcept : __value_(_ValueT(__v)) {} + +public: + static const weak_ordering less; + static const weak_ordering equivalent; + static const weak_ordering greater; + + _LIBCPP_HIDE_FROM_ABI + constexpr operator partial_ordering() const noexcept { + return __value_ == 0 ? partial_ordering::equivalent + : (__value_ < 0 ? partial_ordering::less : partial_ordering::greater); + } + + // comparisons + _LIBCPP_HIDE_FROM_ABI + friend constexpr bool operator==(weak_ordering, weak_ordering) noexcept = default; + + _LIBCPP_HIDE_FROM_ABI + friend constexpr bool operator==(weak_ordering __v, _CmpUnspecifiedParam) noexcept { + return __v.__value_ == 0; + } + + _LIBCPP_HIDE_FROM_ABI + friend constexpr bool operator< (weak_ordering __v, _CmpUnspecifiedParam) noexcept { + return __v.__value_ < 0; + } + + _LIBCPP_HIDE_FROM_ABI + friend constexpr bool operator<=(weak_ordering __v, _CmpUnspecifiedParam) noexcept { + return __v.__value_ <= 0; + } + + _LIBCPP_HIDE_FROM_ABI + friend constexpr bool operator> (weak_ordering __v, _CmpUnspecifiedParam) noexcept { + return __v.__value_ > 0; + } + + _LIBCPP_HIDE_FROM_ABI + friend constexpr bool operator>=(weak_ordering __v, _CmpUnspecifiedParam) noexcept { + return __v.__value_ >= 0; + } + + _LIBCPP_HIDE_FROM_ABI + friend constexpr bool operator< (_CmpUnspecifiedParam, weak_ordering __v) noexcept { + return 0 < __v.__value_; + } + + _LIBCPP_HIDE_FROM_ABI + friend constexpr bool operator<=(_CmpUnspecifiedParam, weak_ordering __v) noexcept { + return 0 <= __v.__value_; + } + + _LIBCPP_HIDE_FROM_ABI + friend constexpr bool operator> (_CmpUnspecifiedParam, weak_ordering __v) noexcept { + return 0 > __v.__value_; + } + + _LIBCPP_HIDE_FROM_ABI + friend constexpr bool operator>=(_CmpUnspecifiedParam, weak_ordering __v) noexcept { + return 0 >= __v.__value_; + } + + _LIBCPP_HIDE_FROM_ABI + friend constexpr weak_ordering operator<=>(weak_ordering __v, _CmpUnspecifiedParam) noexcept { + return __v; + } + + _LIBCPP_HIDE_FROM_ABI + friend constexpr weak_ordering operator<=>(_CmpUnspecifiedParam, weak_ordering __v) noexcept { + return __v < 0 ? weak_ordering::greater : (__v > 0 ? weak_ordering::less : __v); + } + +private: + _ValueT __value_; +}; + +inline constexpr weak_ordering weak_ordering::less(_OrdResult::__less); +inline constexpr weak_ordering weak_ordering::equivalent(_OrdResult::__equiv); +inline constexpr weak_ordering weak_ordering::greater(_OrdResult::__greater); + +class strong_ordering { + using _ValueT = signed char; + + _LIBCPP_HIDE_FROM_ABI + explicit constexpr strong_ordering(_OrdResult __v) noexcept : __value_(_ValueT(__v)) {} + +public: + static const strong_ordering less; + static const strong_ordering equal; + static const strong_ordering equivalent; + static const strong_ordering greater; + + // conversions + _LIBCPP_HIDE_FROM_ABI + constexpr operator partial_ordering() const noexcept { + return __value_ == 0 ? partial_ordering::equivalent + : (__value_ < 0 ? partial_ordering::less : partial_ordering::greater); + } + + _LIBCPP_HIDE_FROM_ABI + constexpr operator weak_ordering() const noexcept { + return __value_ == 0 ? weak_ordering::equivalent + : (__value_ < 0 ? weak_ordering::less : weak_ordering::greater); + } + + // comparisons + _LIBCPP_HIDE_FROM_ABI + friend constexpr bool operator==(strong_ordering, strong_ordering) noexcept = default; + + _LIBCPP_HIDE_FROM_ABI + friend constexpr bool operator==(strong_ordering __v, _CmpUnspecifiedParam) noexcept { + return __v.__value_ == 0; + } + + _LIBCPP_HIDE_FROM_ABI + friend constexpr bool operator< (strong_ordering __v, _CmpUnspecifiedParam) noexcept { + return __v.__value_ < 0; + } + + _LIBCPP_HIDE_FROM_ABI + friend constexpr bool operator<=(strong_ordering __v, _CmpUnspecifiedParam) noexcept { + return __v.__value_ <= 0; + } + + _LIBCPP_HIDE_FROM_ABI + friend constexpr bool operator> (strong_ordering __v, _CmpUnspecifiedParam) noexcept { + return __v.__value_ > 0; + } + + _LIBCPP_HIDE_FROM_ABI + friend constexpr bool operator>=(strong_ordering __v, _CmpUnspecifiedParam) noexcept { + return __v.__value_ >= 0; + } + + _LIBCPP_HIDE_FROM_ABI + friend constexpr bool operator< (_CmpUnspecifiedParam, strong_ordering __v) noexcept { + return 0 < __v.__value_; + } + + _LIBCPP_HIDE_FROM_ABI + friend constexpr bool operator<=(_CmpUnspecifiedParam, strong_ordering __v) noexcept { + return 0 <= __v.__value_; + } + + _LIBCPP_HIDE_FROM_ABI + friend constexpr bool operator> (_CmpUnspecifiedParam, strong_ordering __v) noexcept { + return 0 > __v.__value_; + } + + _LIBCPP_HIDE_FROM_ABI + friend constexpr bool operator>=(_CmpUnspecifiedParam, strong_ordering __v) noexcept { + return 0 >= __v.__value_; + } + + _LIBCPP_HIDE_FROM_ABI + friend constexpr strong_ordering operator<=>(strong_ordering __v, _CmpUnspecifiedParam) noexcept { + return __v; + } + + _LIBCPP_HIDE_FROM_ABI + friend constexpr strong_ordering operator<=>(_CmpUnspecifiedParam, strong_ordering __v) noexcept { + return __v < 0 ? strong_ordering::greater : (__v > 0 ? strong_ordering::less : __v); + } + +private: + _ValueT __value_; +}; + +inline constexpr strong_ordering strong_ordering::less(_OrdResult::__less); +inline constexpr strong_ordering strong_ordering::equal(_OrdResult::__equiv); +inline constexpr strong_ordering strong_ordering::equivalent(_OrdResult::__equiv); +inline constexpr strong_ordering strong_ordering::greater(_OrdResult::__greater); + +/// [cmp.categories.pre]/1 +/// The types partial_ordering, weak_ordering, and strong_ordering are +/// collectively termed the comparison category types. +template +concept __comparison_category = __one_of_v<_Tp, partial_ordering, weak_ordering, strong_ordering>; + +#endif // _LIBCPP_STD_VER > 17 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___COMPARE_ORDERING_H diff --git a/app/src/main/cpp/libcxx/include/__compare/partial_order.h b/app/src/main/cpp/libcxx/include/__compare/partial_order.h new file mode 100644 index 0000000..aee07eb --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__compare/partial_order.h @@ -0,0 +1,74 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___COMPARE_PARTIAL_ORDER +#define _LIBCPP___COMPARE_PARTIAL_ORDER + +#include <__compare/compare_three_way.h> +#include <__compare/ordering.h> +#include <__compare/weak_order.h> +#include <__config> +#include <__type_traits/decay.h> +#include <__type_traits/is_same.h> +#include <__utility/forward.h> +#include <__utility/priority_tag.h> + +#ifndef _LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 17 + +// [cmp.alg] +namespace __partial_order { + struct __fn { + // NOLINTBEGIN(libcpp-robust-against-adl) partial_order should use ADL, but only here + template + requires is_same_v, decay_t<_Up>> + _LIBCPP_HIDE_FROM_ABI static constexpr auto + __go(_Tp&& __t, _Up&& __u, __priority_tag<2>) + noexcept(noexcept(partial_ordering(partial_order(_VSTD::forward<_Tp>(__t), _VSTD::forward<_Up>(__u))))) + -> decltype( partial_ordering(partial_order(_VSTD::forward<_Tp>(__t), _VSTD::forward<_Up>(__u)))) + { return partial_ordering(partial_order(_VSTD::forward<_Tp>(__t), _VSTD::forward<_Up>(__u))); } + // NOLINTEND(libcpp-robust-against-adl) + + template + requires is_same_v, decay_t<_Up>> + _LIBCPP_HIDE_FROM_ABI static constexpr auto + __go(_Tp&& __t, _Up&& __u, __priority_tag<1>) + noexcept(noexcept(partial_ordering(compare_three_way()(_VSTD::forward<_Tp>(__t), _VSTD::forward<_Up>(__u))))) + -> decltype( partial_ordering(compare_three_way()(_VSTD::forward<_Tp>(__t), _VSTD::forward<_Up>(__u)))) + { return partial_ordering(compare_three_way()(_VSTD::forward<_Tp>(__t), _VSTD::forward<_Up>(__u))); } + + template + requires is_same_v, decay_t<_Up>> + _LIBCPP_HIDE_FROM_ABI static constexpr auto + __go(_Tp&& __t, _Up&& __u, __priority_tag<0>) + noexcept(noexcept(partial_ordering(_VSTD::weak_order(_VSTD::forward<_Tp>(__t), _VSTD::forward<_Up>(__u))))) + -> decltype( partial_ordering(_VSTD::weak_order(_VSTD::forward<_Tp>(__t), _VSTD::forward<_Up>(__u)))) + { return partial_ordering(_VSTD::weak_order(_VSTD::forward<_Tp>(__t), _VSTD::forward<_Up>(__u))); } + + template + _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Tp&& __t, _Up&& __u) const + noexcept(noexcept(__go(_VSTD::forward<_Tp>(__t), _VSTD::forward<_Up>(__u), __priority_tag<2>()))) + -> decltype( __go(_VSTD::forward<_Tp>(__t), _VSTD::forward<_Up>(__u), __priority_tag<2>())) + { return __go(_VSTD::forward<_Tp>(__t), _VSTD::forward<_Up>(__u), __priority_tag<2>()); } + }; +} // namespace __partial_order + +inline namespace __cpo { + inline constexpr auto partial_order = __partial_order::__fn{}; +} // namespace __cpo + +#endif // _LIBCPP_STD_VER > 17 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___COMPARE_PARTIAL_ORDER diff --git a/app/src/main/cpp/libcxx/include/__compare/strong_order.h b/app/src/main/cpp/libcxx/include/__compare/strong_order.h new file mode 100644 index 0000000..05856c2 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__compare/strong_order.h @@ -0,0 +1,139 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___COMPARE_STRONG_ORDER +#define _LIBCPP___COMPARE_STRONG_ORDER + +#include <__bit/bit_cast.h> +#include <__compare/compare_three_way.h> +#include <__compare/ordering.h> +#include <__config> +#include <__type_traits/conditional.h> +#include <__type_traits/decay.h> +#include <__utility/forward.h> +#include <__utility/priority_tag.h> +#include +#include +#include + +#ifndef _LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER +# pragma GCC system_header +#endif + +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 17 + +// [cmp.alg] +namespace __strong_order { + struct __fn { + // NOLINTBEGIN(libcpp-robust-against-adl) strong_order should use ADL, but only here + template + requires is_same_v, decay_t<_Up>> + _LIBCPP_HIDE_FROM_ABI static constexpr auto + __go(_Tp&& __t, _Up&& __u, __priority_tag<2>) + noexcept(noexcept(strong_ordering(strong_order(_VSTD::forward<_Tp>(__t), _VSTD::forward<_Up>(__u))))) + -> decltype( strong_ordering(strong_order(_VSTD::forward<_Tp>(__t), _VSTD::forward<_Up>(__u)))) + { return strong_ordering(strong_order(_VSTD::forward<_Tp>(__t), _VSTD::forward<_Up>(__u))); } + // NOLINTEND(libcpp-robust-against-adl) + + template> + requires is_same_v<_Dp, decay_t<_Up>> && is_floating_point_v<_Dp> + _LIBCPP_HIDE_FROM_ABI static constexpr strong_ordering + __go(_Tp&& __t, _Up&& __u, __priority_tag<1>) noexcept + { + if constexpr (numeric_limits<_Dp>::is_iec559 && sizeof(_Dp) == sizeof(int32_t)) { + int32_t __rx = _VSTD::bit_cast(__t); + int32_t __ry = _VSTD::bit_cast(__u); + __rx = (__rx < 0) ? (numeric_limits::min() - __rx - 1) : __rx; + __ry = (__ry < 0) ? (numeric_limits::min() - __ry - 1) : __ry; + return (__rx <=> __ry); + } else if constexpr (numeric_limits<_Dp>::is_iec559 && sizeof(_Dp) == sizeof(int64_t)) { + int64_t __rx = _VSTD::bit_cast(__t); + int64_t __ry = _VSTD::bit_cast(__u); + __rx = (__rx < 0) ? (numeric_limits::min() - __rx - 1) : __rx; + __ry = (__ry < 0) ? (numeric_limits::min() - __ry - 1) : __ry; + return (__rx <=> __ry); + } else if (__t < __u) { + return strong_ordering::less; + } else if (__t > __u) { + return strong_ordering::greater; + } else if (__t == __u) { + if constexpr (numeric_limits<_Dp>::radix == 2) { + return _VSTD::signbit(__u) <=> _VSTD::signbit(__t); + } else { + // This is bullet 3 of the IEEE754 algorithm, relevant + // only for decimal floating-point; + // see https://stackoverflow.com/questions/69068075/ + if (__t == 0 || _VSTD::isinf(__t)) { + return _VSTD::signbit(__u) <=> _VSTD::signbit(__t); + } else { + int __texp, __uexp; + (void)_VSTD::frexp(__t, &__texp); + (void)_VSTD::frexp(__u, &__uexp); + return (__t < 0) ? (__texp <=> __uexp) : (__uexp <=> __texp); + } + } + } else { + // They're unordered, so one of them must be a NAN. + // The order is -QNAN, -SNAN, numbers, +SNAN, +QNAN. + bool __t_is_nan = _VSTD::isnan(__t); + bool __u_is_nan = _VSTD::isnan(__u); + bool __t_is_negative = _VSTD::signbit(__t); + bool __u_is_negative = _VSTD::signbit(__u); + using _IntType = conditional_t< + sizeof(__t) == sizeof(int32_t), int32_t, conditional_t< + sizeof(__t) == sizeof(int64_t), int64_t, void> + >; + if constexpr (is_same_v<_IntType, void>) { + static_assert(sizeof(_Dp) == 0, "std::strong_order is unimplemented for this floating-point type"); + } else if (__t_is_nan && __u_is_nan) { + // Order by sign bit, then by "payload bits" (we'll just use bit_cast). + if (__t_is_negative != __u_is_negative) { + return (__u_is_negative <=> __t_is_negative); + } else { + return _VSTD::bit_cast<_IntType>(__t) <=> _VSTD::bit_cast<_IntType>(__u); + } + } else if (__t_is_nan) { + return __t_is_negative ? strong_ordering::less : strong_ordering::greater; + } else { + return __u_is_negative ? strong_ordering::greater : strong_ordering::less; + } + } + } + + template + requires is_same_v, decay_t<_Up>> + _LIBCPP_HIDE_FROM_ABI static constexpr auto + __go(_Tp&& __t, _Up&& __u, __priority_tag<0>) + noexcept(noexcept(strong_ordering(compare_three_way()(_VSTD::forward<_Tp>(__t), _VSTD::forward<_Up>(__u))))) + -> decltype( strong_ordering(compare_three_way()(_VSTD::forward<_Tp>(__t), _VSTD::forward<_Up>(__u)))) + { return strong_ordering(compare_three_way()(_VSTD::forward<_Tp>(__t), _VSTD::forward<_Up>(__u))); } + + template + _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Tp&& __t, _Up&& __u) const + noexcept(noexcept(__go(_VSTD::forward<_Tp>(__t), _VSTD::forward<_Up>(__u), __priority_tag<2>()))) + -> decltype( __go(_VSTD::forward<_Tp>(__t), _VSTD::forward<_Up>(__u), __priority_tag<2>())) + { return __go(_VSTD::forward<_Tp>(__t), _VSTD::forward<_Up>(__u), __priority_tag<2>()); } + }; +} // namespace __strong_order + +inline namespace __cpo { + inline constexpr auto strong_order = __strong_order::__fn{}; +} // namespace __cpo + +#endif // _LIBCPP_STD_VER > 17 + +_LIBCPP_END_NAMESPACE_STD + +_LIBCPP_POP_MACROS + +#endif // _LIBCPP___COMPARE_STRONG_ORDER diff --git a/app/src/main/cpp/libcxx/include/__compare/synth_three_way.h b/app/src/main/cpp/libcxx/include/__compare/synth_three_way.h new file mode 100644 index 0000000..7d33898 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__compare/synth_three_way.h @@ -0,0 +1,51 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___COMPARE_SYNTH_THREE_WAY_H +#define _LIBCPP___COMPARE_SYNTH_THREE_WAY_H + +#include <__compare/ordering.h> +#include <__compare/three_way_comparable.h> +#include <__concepts/boolean_testable.h> +#include <__config> +#include <__utility/declval.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 17 + +// [expos.only.func] + +_LIBCPP_HIDE_FROM_ABI inline constexpr auto __synth_three_way = + [](const _Tp& __t, const _Up& __u) + requires requires { + { __t < __u } -> __boolean_testable; + { __u < __t } -> __boolean_testable; + } + { + if constexpr (three_way_comparable_with<_Tp, _Up>) { + return __t <=> __u; + } else { + if (__t < __u) return weak_ordering::less; + if (__u < __t) return weak_ordering::greater; + return weak_ordering::equivalent; + } + }; + +template +using __synth_three_way_result = decltype(std::__synth_three_way(std::declval<_Tp&>(), std::declval<_Up&>())); + +#endif // _LIBCPP_STD_VER > 17 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___COMPARE_SYNTH_THREE_WAY_H diff --git a/app/src/main/cpp/libcxx/include/__compare/three_way_comparable.h b/app/src/main/cpp/libcxx/include/__compare/three_way_comparable.h new file mode 100644 index 0000000..6c98916 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__compare/three_way_comparable.h @@ -0,0 +1,59 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___COMPARE_THREE_WAY_COMPARABLE_H +#define _LIBCPP___COMPARE_THREE_WAY_COMPARABLE_H + +#include <__compare/common_comparison_category.h> +#include <__compare/ordering.h> +#include <__concepts/common_reference_with.h> +#include <__concepts/equality_comparable.h> +#include <__concepts/same_as.h> +#include <__concepts/totally_ordered.h> +#include <__config> +#include <__type_traits/common_reference.h> +#include <__type_traits/make_const_lvalue_ref.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 17 + +template +concept __compares_as = + same_as, _Cat>; + +template +concept three_way_comparable = + __weakly_equality_comparable_with<_Tp, _Tp> && + __partially_ordered_with<_Tp, _Tp> && + requires(__make_const_lvalue_ref<_Tp> __a, __make_const_lvalue_ref<_Tp> __b) { + { __a <=> __b } -> __compares_as<_Cat>; + }; + +template +concept three_way_comparable_with = + three_way_comparable<_Tp, _Cat> && + three_way_comparable<_Up, _Cat> && + common_reference_with<__make_const_lvalue_ref<_Tp>, __make_const_lvalue_ref<_Up>> && + three_way_comparable, __make_const_lvalue_ref<_Up>>, _Cat> && + __weakly_equality_comparable_with<_Tp, _Up> && + __partially_ordered_with<_Tp, _Up> && + requires(__make_const_lvalue_ref<_Tp> __t, __make_const_lvalue_ref<_Up> __u) { + { __t <=> __u } -> __compares_as<_Cat>; + { __u <=> __t } -> __compares_as<_Cat>; + }; + +#endif // _LIBCPP_STD_VER > 17 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___COMPARE_THREE_WAY_COMPARABLE_H diff --git a/app/src/main/cpp/libcxx/include/__compare/weak_order.h b/app/src/main/cpp/libcxx/include/__compare/weak_order.h new file mode 100644 index 0000000..abb24e3 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__compare/weak_order.h @@ -0,0 +1,102 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___COMPARE_WEAK_ORDER +#define _LIBCPP___COMPARE_WEAK_ORDER + +#include <__compare/compare_three_way.h> +#include <__compare/ordering.h> +#include <__compare/strong_order.h> +#include <__config> +#include <__type_traits/decay.h> +#include <__utility/forward.h> +#include <__utility/priority_tag.h> +#include + +#ifndef _LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 17 + +// [cmp.alg] +namespace __weak_order { + struct __fn { + // NOLINTBEGIN(libcpp-robust-against-adl) weak_order should use ADL, but only here + template + requires is_same_v, decay_t<_Up>> + _LIBCPP_HIDE_FROM_ABI static constexpr auto + __go(_Tp&& __t, _Up&& __u, __priority_tag<3>) + noexcept(noexcept(weak_ordering(weak_order(_VSTD::forward<_Tp>(__t), _VSTD::forward<_Up>(__u))))) + -> decltype( weak_ordering(weak_order(_VSTD::forward<_Tp>(__t), _VSTD::forward<_Up>(__u)))) + { return weak_ordering(weak_order(_VSTD::forward<_Tp>(__t), _VSTD::forward<_Up>(__u))); } + // NOLINTEND(libcpp-robust-against-adl) + + template> + requires is_same_v<_Dp, decay_t<_Up>> && is_floating_point_v<_Dp> + _LIBCPP_HIDE_FROM_ABI static constexpr weak_ordering + __go(_Tp&& __t, _Up&& __u, __priority_tag<2>) noexcept + { + partial_ordering __po = (__t <=> __u); + if (__po == partial_ordering::less) { + return weak_ordering::less; + } else if (__po == partial_ordering::equivalent) { + return weak_ordering::equivalent; + } else if (__po == partial_ordering::greater) { + return weak_ordering::greater; + } else { + // Otherwise, at least one of them is a NaN. + bool __t_is_nan = _VSTD::isnan(__t); + bool __u_is_nan = _VSTD::isnan(__u); + bool __t_is_negative = _VSTD::signbit(__t); + bool __u_is_negative = _VSTD::signbit(__u); + if (__t_is_nan && __u_is_nan) { + return (__u_is_negative <=> __t_is_negative); + } else if (__t_is_nan) { + return __t_is_negative ? weak_ordering::less : weak_ordering::greater; + } else { + return __u_is_negative ? weak_ordering::greater : weak_ordering::less; + } + } + } + + template + requires is_same_v, decay_t<_Up>> + _LIBCPP_HIDE_FROM_ABI static constexpr auto + __go(_Tp&& __t, _Up&& __u, __priority_tag<1>) + noexcept(noexcept(weak_ordering(compare_three_way()(_VSTD::forward<_Tp>(__t), _VSTD::forward<_Up>(__u))))) + -> decltype( weak_ordering(compare_three_way()(_VSTD::forward<_Tp>(__t), _VSTD::forward<_Up>(__u)))) + { return weak_ordering(compare_three_way()(_VSTD::forward<_Tp>(__t), _VSTD::forward<_Up>(__u))); } + + template + requires is_same_v, decay_t<_Up>> + _LIBCPP_HIDE_FROM_ABI static constexpr auto + __go(_Tp&& __t, _Up&& __u, __priority_tag<0>) + noexcept(noexcept(weak_ordering(_VSTD::strong_order(_VSTD::forward<_Tp>(__t), _VSTD::forward<_Up>(__u))))) + -> decltype( weak_ordering(_VSTD::strong_order(_VSTD::forward<_Tp>(__t), _VSTD::forward<_Up>(__u)))) + { return weak_ordering(_VSTD::strong_order(_VSTD::forward<_Tp>(__t), _VSTD::forward<_Up>(__u))); } + + template + _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Tp&& __t, _Up&& __u) const + noexcept(noexcept(__go(_VSTD::forward<_Tp>(__t), _VSTD::forward<_Up>(__u), __priority_tag<3>()))) + -> decltype( __go(_VSTD::forward<_Tp>(__t), _VSTD::forward<_Up>(__u), __priority_tag<3>())) + { return __go(_VSTD::forward<_Tp>(__t), _VSTD::forward<_Up>(__u), __priority_tag<3>()); } + }; +} // namespace __weak_order + +inline namespace __cpo { + inline constexpr auto weak_order = __weak_order::__fn{}; +} // namespace __cpo + +#endif // _LIBCPP_STD_VER > 17 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___COMPARE_WEAK_ORDER diff --git a/app/src/main/cpp/libcxx/include/__concepts/arithmetic.h b/app/src/main/cpp/libcxx/include/__concepts/arithmetic.h new file mode 100644 index 0000000..215b52a --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__concepts/arithmetic.h @@ -0,0 +1,52 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___CONCEPTS_ARITHMETIC_H +#define _LIBCPP___CONCEPTS_ARITHMETIC_H + +#include <__config> +#include <__type_traits/is_floating_point.h> +#include <__type_traits/is_integral.h> +#include <__type_traits/is_signed.h> +#include <__type_traits/is_signed_integer.h> +#include <__type_traits/is_unsigned_integer.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 17 + +// [concepts.arithmetic], arithmetic concepts + +template +concept integral = is_integral_v<_Tp>; + +template +concept signed_integral = integral<_Tp> && is_signed_v<_Tp>; + +template +concept unsigned_integral = integral<_Tp> && !signed_integral<_Tp>; + +template +concept floating_point = is_floating_point_v<_Tp>; + +// Concept helpers for the internal type traits for the fundamental types. + +template +concept __libcpp_unsigned_integer = __libcpp_is_unsigned_integer<_Tp>::value; +template +concept __libcpp_signed_integer = __libcpp_is_signed_integer<_Tp>::value; + +#endif // _LIBCPP_STD_VER > 17 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___CONCEPTS_ARITHMETIC_H diff --git a/app/src/main/cpp/libcxx/include/__concepts/assignable.h b/app/src/main/cpp/libcxx/include/__concepts/assignable.h new file mode 100644 index 0000000..91edd40 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__concepts/assignable.h @@ -0,0 +1,41 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___CONCEPTS_ASSIGNABLE_H +#define _LIBCPP___CONCEPTS_ASSIGNABLE_H + +#include <__concepts/common_reference_with.h> +#include <__concepts/same_as.h> +#include <__config> +#include <__type_traits/is_reference.h> +#include <__type_traits/make_const_lvalue_ref.h> +#include <__utility/forward.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 17 + +// [concept.assignable] + +template +concept assignable_from = + is_lvalue_reference_v<_Lhs> && + common_reference_with<__make_const_lvalue_ref<_Lhs>, __make_const_lvalue_ref<_Rhs>> && + requires (_Lhs __lhs, _Rhs&& __rhs) { + { __lhs = _VSTD::forward<_Rhs>(__rhs) } -> same_as<_Lhs>; + }; + +#endif // _LIBCPP_STD_VER > 17 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___CONCEPTS_ASSIGNABLE_H diff --git a/app/src/main/cpp/libcxx/include/__concepts/boolean_testable.h b/app/src/main/cpp/libcxx/include/__concepts/boolean_testable.h new file mode 100644 index 0000000..a96bde7 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__concepts/boolean_testable.h @@ -0,0 +1,38 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___CONCEPTS_BOOLEAN_TESTABLE_H +#define _LIBCPP___CONCEPTS_BOOLEAN_TESTABLE_H + +#include <__concepts/convertible_to.h> +#include <__config> +#include <__utility/forward.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 17 + +// [concepts.booleantestable] + +template +concept __boolean_testable_impl = convertible_to<_Tp, bool>; + +template +concept __boolean_testable = __boolean_testable_impl<_Tp> && requires(_Tp&& __t) { + { !_VSTD::forward<_Tp>(__t) } -> __boolean_testable_impl; +}; + +#endif // _LIBCPP_STD_VER > 17 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___CONCEPTS_BOOLEAN_TESTABLE_H diff --git a/app/src/main/cpp/libcxx/include/__concepts/class_or_enum.h b/app/src/main/cpp/libcxx/include/__concepts/class_or_enum.h new file mode 100644 index 0000000..c4d2f98 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__concepts/class_or_enum.h @@ -0,0 +1,40 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___CONCEPTS_CLASS_OR_ENUM_H +#define _LIBCPP___CONCEPTS_CLASS_OR_ENUM_H + +#include <__config> +#include <__type_traits/is_class.h> +#include <__type_traits/is_enum.h> +#include <__type_traits/is_union.h> +#include <__type_traits/remove_cvref.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 17 + +// Whether a type is a class type or enumeration type according to the Core wording. + +template +concept __class_or_enum = is_class_v<_Tp> || is_union_v<_Tp> || is_enum_v<_Tp>; + +// Work around Clang bug https://llvm.org/PR52970 +// TODO: remove this workaround once libc++ no longer has to support Clang 13 (it was fixed in Clang 14). +template +concept __workaround_52970 = is_class_v<__remove_cvref_t<_Tp>> || is_union_v<__remove_cvref_t<_Tp>>; + +#endif // _LIBCPP_STD_VER > 17 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___CONCEPTS_CLASS_OR_ENUM_H diff --git a/app/src/main/cpp/libcxx/include/__concepts/common_reference_with.h b/app/src/main/cpp/libcxx/include/__concepts/common_reference_with.h new file mode 100644 index 0000000..cc92762 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__concepts/common_reference_with.h @@ -0,0 +1,37 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___CONCEPTS_COMMON_REFERENCE_WITH_H +#define _LIBCPP___CONCEPTS_COMMON_REFERENCE_WITH_H + +#include <__concepts/convertible_to.h> +#include <__concepts/same_as.h> +#include <__config> +#include <__type_traits/common_reference.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 17 + +// [concept.commonref] + +template +concept common_reference_with = + same_as, common_reference_t<_Up, _Tp>> && + convertible_to<_Tp, common_reference_t<_Tp, _Up>> && + convertible_to<_Up, common_reference_t<_Tp, _Up>>; + +#endif // _LIBCPP_STD_VER > 17 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___CONCEPTS_COMMON_REFERENCE_WITH_H diff --git a/app/src/main/cpp/libcxx/include/__concepts/common_with.h b/app/src/main/cpp/libcxx/include/__concepts/common_with.h new file mode 100644 index 0000000..569a0ee --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__concepts/common_with.h @@ -0,0 +1,50 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___CONCEPTS_COMMON_WITH_H +#define _LIBCPP___CONCEPTS_COMMON_WITH_H + +#include <__concepts/common_reference_with.h> +#include <__concepts/same_as.h> +#include <__config> +#include <__type_traits/add_lvalue_reference.h> +#include <__type_traits/common_reference.h> +#include <__type_traits/common_type.h> +#include <__utility/declval.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 17 + +// [concept.common] + +template +concept common_with = + same_as, common_type_t<_Up, _Tp>> && + requires { + static_cast>(std::declval<_Tp>()); + static_cast>(std::declval<_Up>()); + } && + common_reference_with< + add_lvalue_reference_t, + add_lvalue_reference_t> && + common_reference_with< + add_lvalue_reference_t>, + common_reference_t< + add_lvalue_reference_t, + add_lvalue_reference_t>>; + +#endif // _LIBCPP_STD_VER > 17 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___CONCEPTS_COMMON_WITH_H diff --git a/app/src/main/cpp/libcxx/include/__concepts/constructible.h b/app/src/main/cpp/libcxx/include/__concepts/constructible.h new file mode 100644 index 0000000..1d78eb5 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__concepts/constructible.h @@ -0,0 +1,56 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___CONCEPTS_CONSTRUCTIBLE_H +#define _LIBCPP___CONCEPTS_CONSTRUCTIBLE_H + +#include <__concepts/convertible_to.h> +#include <__concepts/destructible.h> +#include <__config> +#include <__type_traits/is_constructible.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 17 + +// [concept.constructible] +template +concept constructible_from = + destructible<_Tp> && is_constructible_v<_Tp, _Args...>; + +// [concept.default.init] + +template +concept __default_initializable = requires { ::new _Tp; }; + +template +concept default_initializable = constructible_from<_Tp> && + requires { _Tp{}; } && __default_initializable<_Tp>; + +// [concept.moveconstructible] +template +concept move_constructible = + constructible_from<_Tp, _Tp> && convertible_to<_Tp, _Tp>; + +// [concept.copyconstructible] +template +concept copy_constructible = + move_constructible<_Tp> && + constructible_from<_Tp, _Tp&> && convertible_to<_Tp&, _Tp> && + constructible_from<_Tp, const _Tp&> && convertible_to && + constructible_from<_Tp, const _Tp> && convertible_to; + +#endif // _LIBCPP_STD_VER > 17 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___CONCEPTS_CONSTRUCTIBLE_H diff --git a/app/src/main/cpp/libcxx/include/__concepts/convertible_to.h b/app/src/main/cpp/libcxx/include/__concepts/convertible_to.h new file mode 100644 index 0000000..2c1d267 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__concepts/convertible_to.h @@ -0,0 +1,37 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___CONCEPTS_CONVERTIBLE_TO_H +#define _LIBCPP___CONCEPTS_CONVERTIBLE_TO_H + +#include <__config> +#include <__type_traits/is_convertible.h> +#include <__utility/declval.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 17 + +// [concept.convertible] + +template +concept convertible_to = + is_convertible_v<_From, _To> && + requires { + static_cast<_To>(std::declval<_From>()); + }; + +#endif // _LIBCPP_STD_VER > 17 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___CONCEPTS_CONVERTIBLE_TO_H diff --git a/app/src/main/cpp/libcxx/include/__concepts/copyable.h b/app/src/main/cpp/libcxx/include/__concepts/copyable.h new file mode 100644 index 0000000..c5d8a80 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__concepts/copyable.h @@ -0,0 +1,39 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___CONCEPTS_COPYABLE_H +#define _LIBCPP___CONCEPTS_COPYABLE_H + +#include <__concepts/assignable.h> +#include <__concepts/constructible.h> +#include <__concepts/movable.h> +#include <__config> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 17 + +// [concepts.object] + +template +concept copyable = + copy_constructible<_Tp> && + movable<_Tp> && + assignable_from<_Tp&, _Tp&> && + assignable_from<_Tp&, const _Tp&> && + assignable_from<_Tp&, const _Tp>; + +#endif // _LIBCPP_STD_VER > 17 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___CONCEPTS_COPYABLE_H diff --git a/app/src/main/cpp/libcxx/include/__concepts/derived_from.h b/app/src/main/cpp/libcxx/include/__concepts/derived_from.h new file mode 100644 index 0000000..0d3462d --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__concepts/derived_from.h @@ -0,0 +1,35 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___CONCEPTS_DERIVED_FROM_H +#define _LIBCPP___CONCEPTS_DERIVED_FROM_H + +#include <__config> +#include <__type_traits/is_base_of.h> +#include <__type_traits/is_convertible.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 17 + +// [concept.derived] + +template +concept derived_from = + is_base_of_v<_Bp, _Dp> && + is_convertible_v; + +#endif // _LIBCPP_STD_VER > 17 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___CONCEPTS_DERIVED_FROM_H diff --git a/app/src/main/cpp/libcxx/include/__concepts/destructible.h b/app/src/main/cpp/libcxx/include/__concepts/destructible.h new file mode 100644 index 0000000..ad3819d --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__concepts/destructible.h @@ -0,0 +1,32 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___CONCEPTS_DESTRUCTIBLE_H +#define _LIBCPP___CONCEPTS_DESTRUCTIBLE_H + +#include <__config> +#include <__type_traits/is_nothrow_destructible.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 17 + +// [concept.destructible] + +template +concept destructible = is_nothrow_destructible_v<_Tp>; + +#endif // _LIBCPP_STD_VER > 17 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___CONCEPTS_DESTRUCTIBLE_H diff --git a/app/src/main/cpp/libcxx/include/__concepts/different_from.h b/app/src/main/cpp/libcxx/include/__concepts/different_from.h new file mode 100644 index 0000000..15fd8f0 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__concepts/different_from.h @@ -0,0 +1,31 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___CONCEPTS_DIFFERENT_FROM_H +#define _LIBCPP___CONCEPTS_DIFFERENT_FROM_H + +#include <__concepts/same_as.h> +#include <__config> +#include <__type_traits/remove_cvref.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 17 + +template +concept __different_from = !same_as, remove_cvref_t<_Up>>; + +#endif // _LIBCPP_STD_VER > 17 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___CONCEPTS_DIFFERENT_FROM_H diff --git a/app/src/main/cpp/libcxx/include/__concepts/equality_comparable.h b/app/src/main/cpp/libcxx/include/__concepts/equality_comparable.h new file mode 100644 index 0000000..b865141 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__concepts/equality_comparable.h @@ -0,0 +1,54 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___CONCEPTS_EQUALITY_COMPARABLE_H +#define _LIBCPP___CONCEPTS_EQUALITY_COMPARABLE_H + +#include <__concepts/boolean_testable.h> +#include <__concepts/common_reference_with.h> +#include <__config> +#include <__type_traits/common_reference.h> +#include <__type_traits/make_const_lvalue_ref.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 17 + +// [concept.equalitycomparable] + +template +concept __weakly_equality_comparable_with = + requires(__make_const_lvalue_ref<_Tp> __t, __make_const_lvalue_ref<_Up> __u) { + { __t == __u } -> __boolean_testable; + { __t != __u } -> __boolean_testable; + { __u == __t } -> __boolean_testable; + { __u != __t } -> __boolean_testable; + }; + +template +concept equality_comparable = __weakly_equality_comparable_with<_Tp, _Tp>; + +template +concept equality_comparable_with = + equality_comparable<_Tp> && equality_comparable<_Up> && + common_reference_with<__make_const_lvalue_ref<_Tp>, __make_const_lvalue_ref<_Up>> && + equality_comparable< + common_reference_t< + __make_const_lvalue_ref<_Tp>, + __make_const_lvalue_ref<_Up>>> && + __weakly_equality_comparable_with<_Tp, _Up>; + +#endif // _LIBCPP_STD_VER > 17 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___CONCEPTS_EQUALITY_COMPARABLE_H diff --git a/app/src/main/cpp/libcxx/include/__concepts/invocable.h b/app/src/main/cpp/libcxx/include/__concepts/invocable.h new file mode 100644 index 0000000..ec39b7b --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__concepts/invocable.h @@ -0,0 +1,40 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___CONCEPTS_INVOCABLE_H +#define _LIBCPP___CONCEPTS_INVOCABLE_H + +#include <__config> +#include <__functional/invoke.h> +#include <__utility/forward.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 17 + +// [concept.invocable] + +template +concept invocable = requires(_Fn&& __fn, _Args&&... __args) { + _VSTD::invoke(_VSTD::forward<_Fn>(__fn), _VSTD::forward<_Args>(__args)...); // not required to be equality preserving +}; + +// [concept.regular.invocable] + +template +concept regular_invocable = invocable<_Fn, _Args...>; + +#endif // _LIBCPP_STD_VER > 17 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___CONCEPTS_INVOCABLE_H diff --git a/app/src/main/cpp/libcxx/include/__concepts/movable.h b/app/src/main/cpp/libcxx/include/__concepts/movable.h new file mode 100644 index 0000000..749b78a --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__concepts/movable.h @@ -0,0 +1,39 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___CONCEPTS_MOVABLE_H +#define _LIBCPP___CONCEPTS_MOVABLE_H + +#include <__concepts/assignable.h> +#include <__concepts/constructible.h> +#include <__concepts/swappable.h> +#include <__config> +#include <__type_traits/is_object.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 17 + +// [concepts.object] + +template +concept movable = + is_object_v<_Tp> && + move_constructible<_Tp> && + assignable_from<_Tp&, _Tp> && + swappable<_Tp>; + +#endif // _LIBCPP_STD_VER > 17 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___CONCEPTS_MOVABLE_H diff --git a/app/src/main/cpp/libcxx/include/__concepts/predicate.h b/app/src/main/cpp/libcxx/include/__concepts/predicate.h new file mode 100644 index 0000000..7ae9783 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__concepts/predicate.h @@ -0,0 +1,35 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___CONCEPTS_PREDICATE_H +#define _LIBCPP___CONCEPTS_PREDICATE_H + +#include <__concepts/boolean_testable.h> +#include <__concepts/invocable.h> +#include <__config> +#include <__functional/invoke.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 17 + +// [concept.predicate] + +template +concept predicate = + regular_invocable<_Fn, _Args...> && __boolean_testable>; + +#endif // _LIBCPP_STD_VER > 17 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___CONCEPTS_PREDICATE_H diff --git a/app/src/main/cpp/libcxx/include/__concepts/regular.h b/app/src/main/cpp/libcxx/include/__concepts/regular.h new file mode 100644 index 0000000..d15728d --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__concepts/regular.h @@ -0,0 +1,33 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___CONCEPTS_REGULAR_H +#define _LIBCPP___CONCEPTS_REGULAR_H + +#include <__concepts/equality_comparable.h> +#include <__concepts/semiregular.h> +#include <__config> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 17 + +// [concept.object] + +template +concept regular = semiregular<_Tp> && equality_comparable<_Tp>; + +#endif // _LIBCPP_STD_VER > 17 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___CONCEPTS_REGULAR_H diff --git a/app/src/main/cpp/libcxx/include/__concepts/relation.h b/app/src/main/cpp/libcxx/include/__concepts/relation.h new file mode 100644 index 0000000..7d5141c --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__concepts/relation.h @@ -0,0 +1,44 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___CONCEPTS_RELATION_H +#define _LIBCPP___CONCEPTS_RELATION_H + +#include <__concepts/predicate.h> +#include <__config> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 17 + +// [concept.relation] + +template +concept relation = + predicate<_Rp, _Tp, _Tp> && predicate<_Rp, _Up, _Up> && + predicate<_Rp, _Tp, _Up> && predicate<_Rp, _Up, _Tp>; + +// [concept.equiv] + +template +concept equivalence_relation = relation<_Rp, _Tp, _Up>; + +// [concept.strictweakorder] + +template +concept strict_weak_order = relation<_Rp, _Tp, _Up>; + +#endif // _LIBCPP_STD_VER > 17 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___CONCEPTS_RELATION_H diff --git a/app/src/main/cpp/libcxx/include/__concepts/same_as.h b/app/src/main/cpp/libcxx/include/__concepts/same_as.h new file mode 100644 index 0000000..554ebc3 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__concepts/same_as.h @@ -0,0 +1,35 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___CONCEPTS_SAME_AS_H +#define _LIBCPP___CONCEPTS_SAME_AS_H + +#include <__config> +#include <__type_traits/is_same.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 17 + +// [concept.same] + +template +concept __same_as_impl = _IsSame<_Tp, _Up>::value; + +template +concept same_as = __same_as_impl<_Tp, _Up> && __same_as_impl<_Up, _Tp>; + +#endif // _LIBCPP_STD_VER > 17 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___CONCEPTS_SAME_AS_H diff --git a/app/src/main/cpp/libcxx/include/__concepts/semiregular.h b/app/src/main/cpp/libcxx/include/__concepts/semiregular.h new file mode 100644 index 0000000..d15bb3b --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__concepts/semiregular.h @@ -0,0 +1,33 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___CONCEPTS_SEMIREGULAR_H +#define _LIBCPP___CONCEPTS_SEMIREGULAR_H + +#include <__concepts/constructible.h> +#include <__concepts/copyable.h> +#include <__config> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 17 + +// [concept.object] + +template +concept semiregular = copyable<_Tp> && default_initializable<_Tp>; + +#endif // _LIBCPP_STD_VER > 17 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___CONCEPTS_SEMIREGULAR_H diff --git a/app/src/main/cpp/libcxx/include/__concepts/swappable.h b/app/src/main/cpp/libcxx/include/__concepts/swappable.h new file mode 100644 index 0000000..d91a7a1 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__concepts/swappable.h @@ -0,0 +1,121 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___CONCEPTS_SWAPPABLE_H +#define _LIBCPP___CONCEPTS_SWAPPABLE_H + +#include <__concepts/assignable.h> +#include <__concepts/class_or_enum.h> +#include <__concepts/common_reference_with.h> +#include <__concepts/constructible.h> +#include <__config> +#include <__type_traits/extent.h> +#include <__type_traits/is_nothrow_move_assignable.h> +#include <__type_traits/is_nothrow_move_constructible.h> +#include <__type_traits/remove_cvref.h> +#include <__utility/exchange.h> +#include <__utility/forward.h> +#include <__utility/move.h> +#include <__utility/swap.h> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 17 + +// [concept.swappable] + +namespace ranges { +namespace __swap { + + template + void swap(_Tp&, _Tp&) = delete; + + template + concept __unqualified_swappable_with = + (__class_or_enum> || __class_or_enum>) && + requires(_Tp&& __t, _Up&& __u) { + swap(_VSTD::forward<_Tp>(__t), _VSTD::forward<_Up>(__u)); + }; + + struct __fn; + + template + concept __swappable_arrays = + !__unqualified_swappable_with<_Tp(&)[_Size], _Up(&)[_Size]> && + extent_v<_Tp> == extent_v<_Up> && + requires(_Tp(& __t)[_Size], _Up(& __u)[_Size], const __fn& __swap) { + __swap(__t[0], __u[0]); + }; + + template + concept __exchangeable = + !__unqualified_swappable_with<_Tp&, _Tp&> && + move_constructible<_Tp> && + assignable_from<_Tp&, _Tp>; + + struct __fn { + // 2.1 `S` is `(void)swap(E1, E2)`* if `E1` or `E2` has class or enumeration type and... + // *The name `swap` is used here unqualified. + template + requires __unqualified_swappable_with<_Tp, _Up> + constexpr void operator()(_Tp&& __t, _Up&& __u) const + noexcept(noexcept(swap(_VSTD::forward<_Tp>(__t), _VSTD::forward<_Up>(__u)))) + { + swap(_VSTD::forward<_Tp>(__t), _VSTD::forward<_Up>(__u)); + } + + // 2.2 Otherwise, if `E1` and `E2` are lvalues of array types with equal extent and... + template + requires __swappable_arrays<_Tp, _Up, _Size> + constexpr void operator()(_Tp(& __t)[_Size], _Up(& __u)[_Size]) const + noexcept(noexcept((*this)(*__t, *__u))) + { + // TODO(cjdb): replace with `ranges::swap_ranges`. + for (size_t __i = 0; __i < _Size; ++__i) { + (*this)(__t[__i], __u[__i]); + } + } + + // 2.3 Otherwise, if `E1` and `E2` are lvalues of the same type `T` that models... + template<__exchangeable _Tp> + constexpr void operator()(_Tp& __x, _Tp& __y) const + noexcept(is_nothrow_move_constructible_v<_Tp> && is_nothrow_move_assignable_v<_Tp>) + { + __y = _VSTD::exchange(__x, _VSTD::move(__y)); + } + }; +} // namespace __swap + +inline namespace __cpo { + inline constexpr auto swap = __swap::__fn{}; +} // namespace __cpo +} // namespace ranges + +template +concept swappable = requires(_Tp& __a, _Tp& __b) { ranges::swap(__a, __b); }; + +template +concept swappable_with = + common_reference_with<_Tp, _Up> && + requires(_Tp&& __t, _Up&& __u) { + ranges::swap(_VSTD::forward<_Tp>(__t), _VSTD::forward<_Tp>(__t)); + ranges::swap(_VSTD::forward<_Up>(__u), _VSTD::forward<_Up>(__u)); + ranges::swap(_VSTD::forward<_Tp>(__t), _VSTD::forward<_Up>(__u)); + ranges::swap(_VSTD::forward<_Up>(__u), _VSTD::forward<_Tp>(__t)); + }; + +#endif // _LIBCPP_STD_VER > 17 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___CONCEPTS_SWAPPABLE_H diff --git a/app/src/main/cpp/libcxx/include/__concepts/totally_ordered.h b/app/src/main/cpp/libcxx/include/__concepts/totally_ordered.h new file mode 100644 index 0000000..f12d26b --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__concepts/totally_ordered.h @@ -0,0 +1,58 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___CONCEPTS_TOTALLY_ORDERED_H +#define _LIBCPP___CONCEPTS_TOTALLY_ORDERED_H + +#include <__concepts/boolean_testable.h> +#include <__concepts/equality_comparable.h> +#include <__config> +#include <__type_traits/common_reference.h> +#include <__type_traits/make_const_lvalue_ref.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 17 + +// [concept.totallyordered] + +template +concept __partially_ordered_with = + requires(__make_const_lvalue_ref<_Tp> __t, __make_const_lvalue_ref<_Up> __u) { + { __t < __u } -> __boolean_testable; + { __t > __u } -> __boolean_testable; + { __t <= __u } -> __boolean_testable; + { __t >= __u } -> __boolean_testable; + { __u < __t } -> __boolean_testable; + { __u > __t } -> __boolean_testable; + { __u <= __t } -> __boolean_testable; + { __u >= __t } -> __boolean_testable; + }; + +template +concept totally_ordered = equality_comparable<_Tp> && __partially_ordered_with<_Tp, _Tp>; + +template +concept totally_ordered_with = + totally_ordered<_Tp> && totally_ordered<_Up> && + equality_comparable_with<_Tp, _Up> && + totally_ordered< + common_reference_t< + __make_const_lvalue_ref<_Tp>, + __make_const_lvalue_ref<_Up>>> && + __partially_ordered_with<_Tp, _Up>; + +#endif // _LIBCPP_STD_VER > 17 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___CONCEPTS_TOTALLY_ORDERED_H diff --git a/app/src/main/cpp/libcxx/include/__config b/app/src/main/cpp/libcxx/include/__config new file mode 100644 index 0000000..40c9deb --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__config @@ -0,0 +1,1255 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___CONFIG +#define _LIBCPP___CONFIG + +#include <__config_site> + +#if defined(_MSC_VER) && !defined(__clang__) +# if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# define _LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER +# endif +#endif + +#ifndef _LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER +# pragma GCC system_header +#endif + +#if defined(__apple_build_version__) +# define _LIBCPP_COMPILER_CLANG_BASED +# define _LIBCPP_APPLE_CLANG_VER (__apple_build_version__ / 10000) +#elif defined(__clang__) +# define _LIBCPP_COMPILER_CLANG_BASED +# define _LIBCPP_CLANG_VER (__clang_major__ * 100 + __clang_minor__) +#elif defined(__GNUC__) +# define _LIBCPP_COMPILER_GCC +#endif + +#ifdef __cplusplus + +// _LIBCPP_VERSION represents the version of libc++, which matches the version of LLVM. +// Given a LLVM release LLVM XX.YY.ZZ (e.g. LLVM 17.0.1 == 17.00.01), _LIBCPP_VERSION is +// defined to XXYYZZ. +# define _LIBCPP_VERSION 170000 + +# define _LIBCPP_CONCAT_IMPL(_X, _Y) _X##_Y +# define _LIBCPP_CONCAT(_X, _Y) _LIBCPP_CONCAT_IMPL(_X, _Y) + +// Valid C++ identifier that revs with every libc++ version. This can be used to +// generate identifiers that must be unique for every released libc++ version. +# define _LIBCPP_VERSIONED_IDENTIFIER _LIBCPP_CONCAT(v, _LIBCPP_VERSION) + +# if __STDC_HOSTED__ == 0 +# define _LIBCPP_FREESTANDING +# endif + +# ifndef _LIBCPP_STD_VER +# if __cplusplus <= 201103L +# define _LIBCPP_STD_VER 11 +# elif __cplusplus <= 201402L +# define _LIBCPP_STD_VER 14 +# elif __cplusplus <= 201703L +# define _LIBCPP_STD_VER 17 +# elif __cplusplus <= 202002L +# define _LIBCPP_STD_VER 20 +# else +// Expected release year of the next C++ standard +# define _LIBCPP_STD_VER 23 +# endif +# endif // _LIBCPP_STD_VER + +# if defined(__ELF__) +# define _LIBCPP_OBJECT_FORMAT_ELF 1 +# elif defined(__MACH__) +# define _LIBCPP_OBJECT_FORMAT_MACHO 1 +# elif defined(_WIN32) +# define _LIBCPP_OBJECT_FORMAT_COFF 1 +# elif defined(__wasm__) +# define _LIBCPP_OBJECT_FORMAT_WASM 1 +# elif defined(_AIX) +# define _LIBCPP_OBJECT_FORMAT_XCOFF 1 +# else +// ... add new file formats here ... +# endif + +# if _LIBCPP_ABI_VERSION >= 2 +// Change short string representation so that string data starts at offset 0, +// improving its alignment in some cases. +# define _LIBCPP_ABI_ALTERNATE_STRING_LAYOUT +// Fix deque iterator type in order to support incomplete types. +# define _LIBCPP_ABI_INCOMPLETE_TYPES_IN_DEQUE +// Fix undefined behavior in how std::list stores its linked nodes. +# define _LIBCPP_ABI_LIST_REMOVE_NODE_POINTER_UB +// Fix undefined behavior in how __tree stores its end and parent nodes. +# define _LIBCPP_ABI_TREE_REMOVE_NODE_POINTER_UB +// Fix undefined behavior in how __hash_table stores its pointer types. +# define _LIBCPP_ABI_FIX_UNORDERED_NODE_POINTER_UB +# define _LIBCPP_ABI_FORWARD_LIST_REMOVE_NODE_POINTER_UB +# define _LIBCPP_ABI_FIX_UNORDERED_CONTAINER_SIZE_TYPE +// Define a key function for `bad_function_call` in the library, to centralize +// its vtable and typeinfo to libc++ rather than having all other libraries +// using that class define their own copies. +# define _LIBCPP_ABI_BAD_FUNCTION_CALL_KEY_FUNCTION +// Override the default return value of exception::what() for +// bad_function_call::what() with a string that is specific to +// bad_function_call (see http://wg21.link/LWG2233). This is an ABI break +// because it changes the vtable layout of bad_function_call. +# define _LIBCPP_ABI_BAD_FUNCTION_CALL_GOOD_WHAT_MESSAGE +// Enable optimized version of __do_get_(un)signed which avoids redundant copies. +# define _LIBCPP_ABI_OPTIMIZED_LOCALE_NUM_GET +// Give reverse_iterator one data member of type T, not two. +// Also, in C++17 and later, don't derive iterator types from std::iterator. +# define _LIBCPP_ABI_NO_ITERATOR_BASES +// Use the smallest possible integer type to represent the index of the variant. +// Previously libc++ used "unsigned int" exclusively. +# define _LIBCPP_ABI_VARIANT_INDEX_TYPE_OPTIMIZATION +// Unstable attempt to provide a more optimized std::function +# define _LIBCPP_ABI_OPTIMIZED_FUNCTION +// All the regex constants must be distinct and nonzero. +# define _LIBCPP_ABI_REGEX_CONSTANTS_NONZERO +// Re-worked external template instantiations for std::string with a focus on +// performance and fast-path inlining. +# define _LIBCPP_ABI_STRING_OPTIMIZED_EXTERNAL_INSTANTIATION +// Enable clang::trivial_abi on std::unique_ptr. +# define _LIBCPP_ABI_ENABLE_UNIQUE_PTR_TRIVIAL_ABI +// Enable clang::trivial_abi on std::shared_ptr and std::weak_ptr +# define _LIBCPP_ABI_ENABLE_SHARED_PTR_TRIVIAL_ABI +// std::random_device holds some state when it uses an implementation that gets +// entropy from a file (see _LIBCPP_USING_DEV_RANDOM). When switching from this +// implementation to another one on a platform that has already shipped +// std::random_device, one needs to retain the same object layout to remain ABI +// compatible. This switch removes these workarounds for platforms that don't care +// about ABI compatibility. +# define _LIBCPP_ABI_NO_RANDOM_DEVICE_COMPATIBILITY_LAYOUT +// Don't export the legacy __basic_string_common class and its methods from the built library. +# define _LIBCPP_ABI_DO_NOT_EXPORT_BASIC_STRING_COMMON +// Don't export the legacy __vector_base_common class and its methods from the built library. +# define _LIBCPP_ABI_DO_NOT_EXPORT_VECTOR_BASE_COMMON +// According to the Standard, `bitset::operator[] const` returns bool +# define _LIBCPP_ABI_BITSET_VECTOR_BOOL_CONST_SUBSCRIPT_RETURN_BOOL +// Remove the base 10 implementation of std::to_chars from the dylib. +// The implementation moved to the header, but we still export the symbols from +// the dylib for backwards compatibility. +# define _LIBCPP_ABI_DO_NOT_EXPORT_TO_CHARS_BASE_10 +# elif _LIBCPP_ABI_VERSION == 1 +# if !(defined(_LIBCPP_OBJECT_FORMAT_COFF) || defined(_LIBCPP_OBJECT_FORMAT_XCOFF)) +// Enable compiling copies of now inline methods into the dylib to support +// applications compiled against older libraries. This is unnecessary with +// COFF dllexport semantics, since dllexport forces a non-inline definition +// of inline functions to be emitted anyway. Our own non-inline copy would +// conflict with the dllexport-emitted copy, so we disable it. For XCOFF, +// the linker will take issue with the symbols in the shared object if the +// weak inline methods get visibility (such as from -fvisibility-inlines-hidden), +// so disable it. +# define _LIBCPP_DEPRECATED_ABI_LEGACY_LIBRARY_DEFINITIONS_FOR_INLINE_FUNCTIONS +# endif +// Feature macros for disabling pre ABI v1 features. All of these options +// are deprecated. +# if defined(__FreeBSD__) +# define _LIBCPP_DEPRECATED_ABI_DISABLE_PAIR_TRIVIAL_COPY_CTOR +# endif +# endif + +# if defined(_LIBCPP_BUILDING_LIBRARY) || _LIBCPP_ABI_VERSION >= 2 +// Enable additional explicit instantiations of iostreams components. This +// reduces the number of weak definitions generated in programs that use +// iostreams by providing a single strong definition in the shared library. +# define _LIBCPP_ABI_ENABLE_ADDITIONAL_IOSTREAM_EXPLICIT_INSTANTIATIONS_1 + +// Define a key function for `bad_function_call` in the library, to centralize +// its vtable and typeinfo to libc++ rather than having all other libraries +// using that class define their own copies. +# define _LIBCPP_ABI_BAD_FUNCTION_CALL_KEY_FUNCTION +# endif + +# define _LIBCPP_TOSTRING2(x) #x +# define _LIBCPP_TOSTRING(x) _LIBCPP_TOSTRING2(x) + +# if __cplusplus < 201103L +# define _LIBCPP_CXX03_LANG +# endif + +# ifndef __has_attribute +# define __has_attribute(__x) 0 +# endif + +# ifndef __has_builtin +# define __has_builtin(__x) 0 +# endif + +# ifndef __has_extension +# define __has_extension(__x) 0 +# endif + +# ifndef __has_feature +# define __has_feature(__x) 0 +# endif + +# ifndef __has_cpp_attribute +# define __has_cpp_attribute(__x) 0 +# endif + +# ifndef __has_constexpr_builtin +# define __has_constexpr_builtin(x) 0 +# endif + +// '__is_identifier' returns '0' if '__x' is a reserved identifier provided by +// the compiler and '1' otherwise. +# ifndef __is_identifier +# define __is_identifier(__x) 1 +# endif + +# ifndef __has_declspec_attribute +# define __has_declspec_attribute(__x) 0 +# endif + +# define __has_keyword(__x) !(__is_identifier(__x)) + +# ifndef __has_include +# define __has_include(...) 0 +# endif + +# if !defined(_LIBCPP_COMPILER_CLANG_BASED) && __cplusplus < 201103L +# error "libc++ only supports C++03 with Clang-based compilers. Please enable C++11" +# endif + +// FIXME: ABI detection should be done via compiler builtin macros. This +// is just a placeholder until Clang implements such macros. For now assume +// that Windows compilers pretending to be MSVC++ target the Microsoft ABI, +// and allow the user to explicitly specify the ABI to handle cases where this +// heuristic falls short. +# if defined(_LIBCPP_ABI_FORCE_ITANIUM) && defined(_LIBCPP_ABI_FORCE_MICROSOFT) +# error "Only one of _LIBCPP_ABI_FORCE_ITANIUM and _LIBCPP_ABI_FORCE_MICROSOFT can be defined" +# elif defined(_LIBCPP_ABI_FORCE_ITANIUM) +# define _LIBCPP_ABI_ITANIUM +# elif defined(_LIBCPP_ABI_FORCE_MICROSOFT) +# define _LIBCPP_ABI_MICROSOFT +# else +# if defined(_WIN32) && defined(_MSC_VER) +# define _LIBCPP_ABI_MICROSOFT +# else +# define _LIBCPP_ABI_ITANIUM +# endif +# endif + +# if defined(_LIBCPP_ABI_MICROSOFT) && !defined(_LIBCPP_NO_VCRUNTIME) +# define _LIBCPP_ABI_VCRUNTIME +# endif + +# if __has_feature(experimental_library) +# ifndef _LIBCPP_ENABLE_EXPERIMENTAL +# define _LIBCPP_ENABLE_EXPERIMENTAL +# endif +# endif + +// Incomplete features get their own specific disabling flags. This makes it +// easier to grep for target specific flags once the feature is complete. +# if !defined(_LIBCPP_ENABLE_EXPERIMENTAL) && !defined(_LIBCPP_BUILDING_LIBRARY) +# define _LIBCPP_HAS_NO_INCOMPLETE_FORMAT +# endif + +// Need to detect which libc we're using if we're on Linux. +# if defined(__linux__) +# include +# if defined(__GLIBC_PREREQ) +# define _LIBCPP_GLIBC_PREREQ(a, b) __GLIBC_PREREQ(a, b) +# else +# define _LIBCPP_GLIBC_PREREQ(a, b) 0 +# endif // defined(__GLIBC_PREREQ) +# endif // defined(__linux__) + +# if defined(__MVS__) +# include // for __NATIVE_ASCII_F +# endif + +# ifdef __LITTLE_ENDIAN__ +# if __LITTLE_ENDIAN__ +# define _LIBCPP_LITTLE_ENDIAN +# endif // __LITTLE_ENDIAN__ +# endif // __LITTLE_ENDIAN__ + +# ifdef __BIG_ENDIAN__ +# if __BIG_ENDIAN__ +# define _LIBCPP_BIG_ENDIAN +# endif // __BIG_ENDIAN__ +# endif // __BIG_ENDIAN__ + +# ifdef __BYTE_ORDER__ +# if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ +# define _LIBCPP_LITTLE_ENDIAN +# elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ +# define _LIBCPP_BIG_ENDIAN +# endif // __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ +# endif // __BYTE_ORDER__ + +# ifdef __FreeBSD__ +# include +# include +# if _BYTE_ORDER == _LITTLE_ENDIAN +# define _LIBCPP_LITTLE_ENDIAN +# else // _BYTE_ORDER == _LITTLE_ENDIAN +# define _LIBCPP_BIG_ENDIAN +# endif // _BYTE_ORDER == _LITTLE_ENDIAN +# endif // __FreeBSD__ + +# if defined(__NetBSD__) || defined(__OpenBSD__) +# include +# if _BYTE_ORDER == _LITTLE_ENDIAN +# define _LIBCPP_LITTLE_ENDIAN +# else // _BYTE_ORDER == _LITTLE_ENDIAN +# define _LIBCPP_BIG_ENDIAN +# endif // _BYTE_ORDER == _LITTLE_ENDIAN +# endif // defined(__NetBSD__) || defined(__OpenBSD__) + +# if defined(_WIN32) +# define _LIBCPP_WIN32API +# define _LIBCPP_LITTLE_ENDIAN +# define _LIBCPP_SHORT_WCHAR 1 +// Both MinGW and native MSVC provide a "MSVC"-like environment +# define _LIBCPP_MSVCRT_LIKE +// If mingw not explicitly detected, assume using MS C runtime only if +// a MS compatibility version is specified. +# if defined(_MSC_VER) && !defined(__MINGW32__) +# define _LIBCPP_MSVCRT // Using Microsoft's C Runtime library +# endif +# if (defined(_M_AMD64) || defined(__x86_64__)) || (defined(_M_ARM) || defined(__arm__)) +# define _LIBCPP_HAS_BITSCAN64 +# endif +# define _LIBCPP_HAS_OPEN_WITH_WCHAR +# endif // defined(_WIN32) + +# ifdef __sun__ +# include +# ifdef _LITTLE_ENDIAN +# define _LIBCPP_LITTLE_ENDIAN +# else +# define _LIBCPP_BIG_ENDIAN +# endif +# endif // __sun__ + +# if defined(_AIX) && !defined(__64BIT__) +// The size of wchar is 2 byte on 32-bit mode on AIX. +# define _LIBCPP_SHORT_WCHAR 1 +# endif + +// Libc++ supports various implementations of std::random_device. +// +// _LIBCPP_USING_DEV_RANDOM +// Read entropy from the given file, by default `/dev/urandom`. +// If a token is provided, it is assumed to be the path to a file +// to read entropy from. This is the default behavior if nothing +// else is specified. This implementation requires storing state +// inside `std::random_device`. +// +// _LIBCPP_USING_ARC4_RANDOM +// Use arc4random(). This allows obtaining random data even when +// using sandboxing mechanisms. On some platforms like Apple, this +// is the recommended source of entropy for user-space programs. +// When this option is used, the token passed to `std::random_device`'s +// constructor *must* be "/dev/urandom" -- anything else is an error. +// +// _LIBCPP_USING_GETENTROPY +// Use getentropy(). +// When this option is used, the token passed to `std::random_device`'s +// constructor *must* be "/dev/urandom" -- anything else is an error. +// +// _LIBCPP_USING_FUCHSIA_CPRNG +// Use Fuchsia's zx_cprng_draw() system call, which is specified to +// deliver high-quality entropy and cannot fail. +// When this option is used, the token passed to `std::random_device`'s +// constructor *must* be "/dev/urandom" -- anything else is an error. +// +// _LIBCPP_USING_NACL_RANDOM +// NaCl's sandbox (which PNaCl also runs in) doesn't allow filesystem access, +// including accesses to the special files under `/dev`. This implementation +// uses the NaCL syscall `nacl_secure_random_init()` to get entropy. +// When this option is used, the token passed to `std::random_device`'s +// constructor *must* be "/dev/urandom" -- anything else is an error. +// +// _LIBCPP_USING_WIN32_RANDOM +// Use rand_s(), for use on Windows. +// When this option is used, the token passed to `std::random_device`'s +// constructor *must* be "/dev/urandom" -- anything else is an error. +# if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || \ + defined(__DragonFly__) || defined(__sun__) +# define _LIBCPP_USING_ARC4_RANDOM +# elif defined(__wasi__) || defined(__EMSCRIPTEN__) +# define _LIBCPP_USING_GETENTROPY +# elif defined(__Fuchsia__) +# define _LIBCPP_USING_FUCHSIA_CPRNG +# elif defined(__native_client__) +# define _LIBCPP_USING_NACL_RANDOM +# elif defined(_LIBCPP_WIN32API) +# define _LIBCPP_USING_WIN32_RANDOM +# else +# define _LIBCPP_USING_DEV_RANDOM +# endif + +# if !defined(_LIBCPP_LITTLE_ENDIAN) && !defined(_LIBCPP_BIG_ENDIAN) +# include +# if __BYTE_ORDER == __LITTLE_ENDIAN +# define _LIBCPP_LITTLE_ENDIAN +# elif __BYTE_ORDER == __BIG_ENDIAN +# define _LIBCPP_BIG_ENDIAN +# else // __BYTE_ORDER == __BIG_ENDIAN +# error unable to determine endian +# endif +# endif // !defined(_LIBCPP_LITTLE_ENDIAN) && !defined(_LIBCPP_BIG_ENDIAN) + +# if __has_attribute(__no_sanitize__) && !defined(_LIBCPP_COMPILER_GCC) +# define _LIBCPP_NO_CFI __attribute__((__no_sanitize__("cfi"))) +# else +# define _LIBCPP_NO_CFI +# endif + +# ifndef _LIBCPP_CXX03_LANG + +# define _LIBCPP_ALIGNOF(_Tp) alignof(_Tp) +# define _ALIGNAS_TYPE(x) alignas(x) +# define _ALIGNAS(x) alignas(x) +# define _LIBCPP_NORETURN [[noreturn]] +# define _NOEXCEPT noexcept +# define _NOEXCEPT_(x) noexcept(x) +# define _LIBCPP_CONSTEXPR constexpr + +# else + +# define _LIBCPP_ALIGNOF(_Tp) _Alignof(_Tp) +# define _ALIGNAS_TYPE(x) __attribute__((__aligned__(_LIBCPP_ALIGNOF(x)))) +# define _ALIGNAS(x) __attribute__((__aligned__(x))) +# define _LIBCPP_NORETURN __attribute__((__noreturn__)) +# define _LIBCPP_HAS_NO_NOEXCEPT +# define nullptr __nullptr +# define _NOEXCEPT throw() +# define _NOEXCEPT_(x) +# define static_assert(...) _Static_assert(__VA_ARGS__) +# define decltype(...) __decltype(__VA_ARGS__) +# define _LIBCPP_CONSTEXPR + +typedef __char16_t char16_t; +typedef __char32_t char32_t; + +# endif + +# if !defined(__cpp_exceptions) || __cpp_exceptions < 199711L +# define _LIBCPP_NO_EXCEPTIONS +# endif + +# define _LIBCPP_PREFERRED_ALIGNOF(_Tp) __alignof(_Tp) + +# if defined(_LIBCPP_COMPILER_CLANG_BASED) + +# if defined(__APPLE__) && !defined(__i386__) && !defined(__x86_64__) && (!defined(__arm__) || __ARM_ARCH_7K__ >= 2) +# define _LIBCPP_ABI_ALTERNATE_STRING_LAYOUT +# endif + +// Objective-C++ features (opt-in) +# if __has_feature(objc_arc) +# define _LIBCPP_HAS_OBJC_ARC +# endif + +# if __has_feature(objc_arc_weak) +# define _LIBCPP_HAS_OBJC_ARC_WEAK +# endif + +# if __has_extension(blocks) +# define _LIBCPP_HAS_EXTENSION_BLOCKS +# endif + +# if defined(_LIBCPP_HAS_EXTENSION_BLOCKS) && defined(__APPLE__) +# define _LIBCPP_HAS_BLOCKS_RUNTIME +# endif + +# if !__has_feature(address_sanitizer) +# define _LIBCPP_HAS_NO_ASAN +# endif + +// Allow for build-time disabling of unsigned integer sanitization +# if __has_attribute(no_sanitize) +# define _LIBCPP_DISABLE_UBSAN_UNSIGNED_INTEGER_CHECK __attribute__((__no_sanitize__("unsigned-integer-overflow"))) +# endif + +# define _LIBCPP_ALWAYS_INLINE __attribute__((__always_inline__)) + +# define _LIBCPP_DISABLE_EXTENSION_WARNING __extension__ + +# elif defined(_LIBCPP_COMPILER_GCC) + +# if !defined(__SANITIZE_ADDRESS__) +# define _LIBCPP_HAS_NO_ASAN +# endif + +# define _LIBCPP_ALWAYS_INLINE __attribute__((__always_inline__)) + +# define _LIBCPP_DISABLE_EXTENSION_WARNING __extension__ + +# endif // _LIBCPP_COMPILER_[CLANG|GCC] + +# if defined(_LIBCPP_OBJECT_FORMAT_COFF) + +# ifdef _DLL +# define _LIBCPP_CRT_FUNC __declspec(dllimport) +# else +# define _LIBCPP_CRT_FUNC +# endif + +# if defined(_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS) || (defined(__MINGW32__) && !defined(_LIBCPP_BUILDING_LIBRARY)) +# define _LIBCPP_DLL_VIS +# define _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS +# define _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS +# define _LIBCPP_OVERRIDABLE_FUNC_VIS +# define _LIBCPP_EXPORTED_FROM_ABI +# elif defined(_LIBCPP_BUILDING_LIBRARY) +# define _LIBCPP_DLL_VIS __declspec(dllexport) +# if defined(__MINGW32__) +# define _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS _LIBCPP_DLL_VIS +# define _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS +# else +# define _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS +# define _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS _LIBCPP_DLL_VIS +# endif +# define _LIBCPP_OVERRIDABLE_FUNC_VIS _LIBCPP_DLL_VIS +# define _LIBCPP_EXPORTED_FROM_ABI __declspec(dllexport) +# else +# define _LIBCPP_DLL_VIS __declspec(dllimport) +# define _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS _LIBCPP_DLL_VIS +# define _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS +# define _LIBCPP_OVERRIDABLE_FUNC_VIS +# define _LIBCPP_EXPORTED_FROM_ABI __declspec(dllimport) +# endif + +# define _LIBCPP_TYPE_VIS _LIBCPP_DLL_VIS +# define _LIBCPP_FUNC_VIS _LIBCPP_DLL_VIS +# define _LIBCPP_EXCEPTION_ABI _LIBCPP_DLL_VIS +# define _LIBCPP_HIDDEN +# define _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS +# define _LIBCPP_TEMPLATE_VIS +# define _LIBCPP_TEMPLATE_DATA_VIS +# define _LIBCPP_ENUM_VIS + +# else + +# if !defined(_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS) +# define _LIBCPP_VISIBILITY(vis) __attribute__((__visibility__(vis))) +# else +# define _LIBCPP_VISIBILITY(vis) +# endif + +# define _LIBCPP_HIDDEN _LIBCPP_VISIBILITY("hidden") +# define _LIBCPP_FUNC_VIS _LIBCPP_VISIBILITY("default") +# define _LIBCPP_TYPE_VIS _LIBCPP_VISIBILITY("default") +# define _LIBCPP_TEMPLATE_DATA_VIS _LIBCPP_VISIBILITY("default") +# define _LIBCPP_EXPORTED_FROM_ABI _LIBCPP_VISIBILITY("default") +# define _LIBCPP_EXCEPTION_ABI _LIBCPP_VISIBILITY("default") +# define _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS _LIBCPP_VISIBILITY("default") +# define _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS + +// TODO: Make this a proper customization point or remove the option to override it. +# ifndef _LIBCPP_OVERRIDABLE_FUNC_VIS +# define _LIBCPP_OVERRIDABLE_FUNC_VIS _LIBCPP_VISIBILITY("default") +# endif + +# if !defined(_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS) +// The inline should be removed once PR32114 is resolved +# define _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS inline _LIBCPP_HIDDEN +# else +# define _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS +# endif + +# if !defined(_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS) +# if __has_attribute(__type_visibility__) +# define _LIBCPP_TEMPLATE_VIS __attribute__((__type_visibility__("default"))) +# else +# define _LIBCPP_TEMPLATE_VIS __attribute__((__visibility__("default"))) +# endif +# else +# define _LIBCPP_TEMPLATE_VIS +# endif + +# if !defined(_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS) && __has_attribute(__type_visibility__) +# define _LIBCPP_ENUM_VIS __attribute__((__type_visibility__("default"))) +# else +# define _LIBCPP_ENUM_VIS +# endif + +# endif // defined(_LIBCPP_OBJECT_FORMAT_COFF) + +# if __has_attribute(exclude_from_explicit_instantiation) +# define _LIBCPP_EXCLUDE_FROM_EXPLICIT_INSTANTIATION __attribute__((__exclude_from_explicit_instantiation__)) +# else +// Try to approximate the effect of exclude_from_explicit_instantiation +// (which is that entities are not assumed to be provided by explicit +// template instantiations in the dylib) by always inlining those entities. +# define _LIBCPP_EXCLUDE_FROM_EXPLICIT_INSTANTIATION _LIBCPP_ALWAYS_INLINE +# endif + +// This macro marks a symbol as being hidden from libc++'s ABI. This is achieved +// on two levels: +// 1. The symbol is given hidden visibility, which ensures that users won't start exporting +// symbols from their dynamic library by means of using the libc++ headers. This ensures +// that those symbols stay private to the dynamic library in which it is defined. +// +// 2. The symbol is given an ABI tag that changes with each version of libc++. This ensures +// that no ODR violation can arise from mixing two TUs compiled with different versions +// of libc++ where we would have changed the definition of a symbol. If the symbols shared +// the same name, the ODR would require that their definitions be token-by-token equivalent, +// which basically prevents us from being able to make any change to any function in our +// headers. Using this ABI tag ensures that the symbol name is "bumped" artificially at +// each release, which lets us change the definition of these symbols at our leisure. +// Note that historically, this has been achieved in various ways, including force-inlining +// all functions or giving internal linkage to all functions. Both these (previous) solutions +// suffer from drawbacks that lead notably to code bloat. +// +// Note that we use _LIBCPP_EXCLUDE_FROM_EXPLICIT_INSTANTIATION to ensure that we don't depend +// on _LIBCPP_HIDE_FROM_ABI methods of classes explicitly instantiated in the dynamic library. +// +// Also note that the _LIBCPP_HIDE_FROM_ABI_VIRTUAL macro should be used on virtual functions +// instead of _LIBCPP_HIDE_FROM_ABI. That macro does not use an ABI tag. Indeed, the mangled +// name of a virtual function is part of its ABI, since some architectures like arm64e can sign +// the virtual function pointer in the vtable based on the mangled name of the function. Since +// we use an ABI tag that changes with each released version, the mangled name of the virtual +// function would change, which is incorrect. Note that it doesn't make much sense to change +// the implementation of a virtual function in an ABI-incompatible way in the first place, +// since that would be an ABI break anyway. Hence, the lack of ABI tag should not be noticeable. +// +// TODO: We provide a escape hatch with _LIBCPP_NO_ABI_TAG for folks who want to avoid increasing +// the length of symbols with an ABI tag. In practice, we should remove the escape hatch and +// use compression mangling instead, see https://github.com/itanium-cxx-abi/cxx-abi/issues/70. +# ifndef _LIBCPP_NO_ABI_TAG +# define _LIBCPP_HIDE_FROM_ABI \ + _LIBCPP_HIDDEN _LIBCPP_EXCLUDE_FROM_EXPLICIT_INSTANTIATION \ + __attribute__((__abi_tag__(_LIBCPP_TOSTRING(_LIBCPP_VERSIONED_IDENTIFIER)))) +# else +# define _LIBCPP_HIDE_FROM_ABI _LIBCPP_HIDDEN _LIBCPP_EXCLUDE_FROM_EXPLICIT_INSTANTIATION +# endif +# define _LIBCPP_HIDE_FROM_ABI_VIRTUAL _LIBCPP_HIDDEN _LIBCPP_EXCLUDE_FROM_EXPLICIT_INSTANTIATION + +// This macro provides a HIDE_FROM_ABI equivalent that can be applied to extern +// "C" function, as those lack mangling. +# define _LIBCPP_HIDE_FROM_ABI_C _LIBCPP_HIDDEN _LIBCPP_EXCLUDE_FROM_EXPLICIT_INSTANTIATION + +# ifdef _LIBCPP_BUILDING_LIBRARY +# if _LIBCPP_ABI_VERSION > 1 +# define _LIBCPP_HIDE_FROM_ABI_AFTER_V1 _LIBCPP_HIDE_FROM_ABI +# else +# define _LIBCPP_HIDE_FROM_ABI_AFTER_V1 +# endif +# else +# define _LIBCPP_HIDE_FROM_ABI_AFTER_V1 _LIBCPP_HIDE_FROM_ABI +# endif + +// Just so we can migrate to the new macros gradually. +# define _LIBCPP_INLINE_VISIBILITY _LIBCPP_HIDE_FROM_ABI + +// Inline namespaces are available in Clang/GCC/MSVC regardless of C++ dialect. +// clang-format off +# define _LIBCPP_BEGIN_NAMESPACE_STD namespace std { inline namespace _LIBCPP_ABI_NAMESPACE { +# define _LIBCPP_END_NAMESPACE_STD }} +# define _VSTD std + +_LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD + +# if _LIBCPP_STD_VER > 14 +# define _LIBCPP_BEGIN_NAMESPACE_FILESYSTEM \ + _LIBCPP_BEGIN_NAMESPACE_STD inline namespace __fs { namespace filesystem { +# else +# define _LIBCPP_BEGIN_NAMESPACE_FILESYSTEM \ + _LIBCPP_BEGIN_NAMESPACE_STD namespace __fs { namespace filesystem { +# endif + +# define _LIBCPP_END_NAMESPACE_FILESYSTEM _LIBCPP_END_NAMESPACE_STD }} +// clang-format on + +# define _VSTD_FS std::__fs::filesystem + +# if __has_attribute(__enable_if__) +# define _LIBCPP_PREFERRED_OVERLOAD __attribute__((__enable_if__(true, ""))) +# endif + +# ifndef __SIZEOF_INT128__ +# define _LIBCPP_HAS_NO_INT128 +# endif + +# ifndef __cpp_consteval +# define _LIBCPP_CONSTEVAL _LIBCPP_CONSTEXPR +# else +# define _LIBCPP_CONSTEVAL consteval +# endif + +# if __has_attribute(__malloc__) +# define _LIBCPP_NOALIAS __attribute__((__malloc__)) +# else +# define _LIBCPP_NOALIAS +# endif + +# if __has_attribute(__using_if_exists__) +# define _LIBCPP_USING_IF_EXISTS __attribute__((__using_if_exists__)) +# else +# define _LIBCPP_USING_IF_EXISTS +# endif + +# ifdef _LIBCPP_CXX03_LANG +# define _LIBCPP_DECLARE_STRONG_ENUM(x) \ + struct _LIBCPP_TYPE_VIS x { \ + enum __lx +// clang-format off +# define _LIBCPP_DECLARE_STRONG_ENUM_EPILOG(x) \ + __lx __v_; \ + _LIBCPP_INLINE_VISIBILITY x(__lx __v) : __v_(__v) {} \ + _LIBCPP_INLINE_VISIBILITY explicit x(int __v) : __v_(static_cast<__lx>(__v)) {} \ + _LIBCPP_INLINE_VISIBILITY operator int() const { return __v_; } \ + }; +// clang-format on + +# else // _LIBCPP_CXX03_LANG +# define _LIBCPP_DECLARE_STRONG_ENUM(x) enum class _LIBCPP_ENUM_VIS x +# define _LIBCPP_DECLARE_STRONG_ENUM_EPILOG(x) +# endif // _LIBCPP_CXX03_LANG + +# if defined(__APPLE__) || defined(__FreeBSD__) || defined(_LIBCPP_MSVCRT_LIKE) || defined(__sun__) || \ + defined(__NetBSD__) +# define _LIBCPP_LOCALE__L_EXTENSIONS 1 +# endif + +# ifdef __FreeBSD__ +# define _DECLARE_C99_LDBL_MATH 1 +# endif + +// If we are getting operator new from the MSVC CRT, then allocation overloads +// for align_val_t were added in 19.12, aka VS 2017 version 15.3. +# if defined(_LIBCPP_MSVCRT) && defined(_MSC_VER) && _MSC_VER < 1912 +# define _LIBCPP_HAS_NO_LIBRARY_ALIGNED_ALLOCATION +# elif defined(_LIBCPP_ABI_VCRUNTIME) && !defined(__cpp_aligned_new) +// We're deferring to Microsoft's STL to provide aligned new et al. We don't +// have it unless the language feature test macro is defined. +# define _LIBCPP_HAS_NO_LIBRARY_ALIGNED_ALLOCATION +# elif defined(__MVS__) +# define _LIBCPP_HAS_NO_LIBRARY_ALIGNED_ALLOCATION +# endif + +# if defined(_LIBCPP_HAS_NO_LIBRARY_ALIGNED_ALLOCATION) || (!defined(__cpp_aligned_new) || __cpp_aligned_new < 201606) +# define _LIBCPP_HAS_NO_ALIGNED_ALLOCATION +# endif + +// It is not yet possible to use aligned_alloc() on all Apple platforms since +// 10.15 was the first version to ship an implementation of aligned_alloc(). +# if defined(__APPLE__) +# if (defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && \ + __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 101500) +# define _LIBCPP_HAS_NO_C11_ALIGNED_ALLOC +# endif +# elif defined(__ANDROID__) && __ANDROID_API__ < 28 +// Android only provides aligned_alloc when targeting API 28 or higher. +# define _LIBCPP_HAS_NO_C11_ALIGNED_ALLOC +# endif + +# if defined(__APPLE__) || defined(__FreeBSD__) +# define _LIBCPP_HAS_DEFAULTRUNELOCALE +# endif + +# if defined(__APPLE__) || defined(__FreeBSD__) || defined(__sun__) +# define _LIBCPP_WCTYPE_IS_MASK +# endif + +# if _LIBCPP_STD_VER <= 17 || !defined(__cpp_char8_t) +# define _LIBCPP_HAS_NO_CHAR8_T +# endif + +// Deprecation macros. +// +// Deprecations warnings are always enabled, except when users explicitly opt-out +// by defining _LIBCPP_DISABLE_DEPRECATION_WARNINGS. +# if !defined(_LIBCPP_DISABLE_DEPRECATION_WARNINGS) +# if __has_attribute(deprecated) +# define _LIBCPP_DEPRECATED __attribute__((deprecated)) +# define _LIBCPP_DEPRECATED_(m) __attribute__((deprecated(m))) +# elif _LIBCPP_STD_VER > 11 +# define _LIBCPP_DEPRECATED [[deprecated]] +# define _LIBCPP_DEPRECATED_(m) [[deprecated(m)]] +# else +# define _LIBCPP_DEPRECATED +# define _LIBCPP_DEPRECATED_(m) +# endif +# else +# define _LIBCPP_DEPRECATED +# define _LIBCPP_DEPRECATED_(m) +# endif + +# if !defined(_LIBCPP_CXX03_LANG) +# define _LIBCPP_DEPRECATED_IN_CXX11 _LIBCPP_DEPRECATED +# else +# define _LIBCPP_DEPRECATED_IN_CXX11 +# endif + +# if _LIBCPP_STD_VER > 11 +# define _LIBCPP_DEPRECATED_IN_CXX14 _LIBCPP_DEPRECATED +# else +# define _LIBCPP_DEPRECATED_IN_CXX14 +# endif + +# if _LIBCPP_STD_VER > 14 +# define _LIBCPP_DEPRECATED_IN_CXX17 _LIBCPP_DEPRECATED +# else +# define _LIBCPP_DEPRECATED_IN_CXX17 +# endif + +# if _LIBCPP_STD_VER > 17 +# define _LIBCPP_DEPRECATED_IN_CXX20 _LIBCPP_DEPRECATED +# else +# define _LIBCPP_DEPRECATED_IN_CXX20 +# endif + +#if _LIBCPP_STD_VER >= 23 +# define _LIBCPP_DEPRECATED_IN_CXX23 _LIBCPP_DEPRECATED +#else +# define _LIBCPP_DEPRECATED_IN_CXX23 +#endif + +# if !defined(_LIBCPP_HAS_NO_CHAR8_T) +# define _LIBCPP_DEPRECATED_WITH_CHAR8_T _LIBCPP_DEPRECATED +# else +# define _LIBCPP_DEPRECATED_WITH_CHAR8_T +# endif + +// Macros to enter and leave a state where deprecation warnings are suppressed. +# if defined(_LIBCPP_COMPILER_CLANG_BASED) || defined(_LIBCPP_COMPILER_GCC) +# define _LIBCPP_SUPPRESS_DEPRECATED_PUSH \ + _Pragma("GCC diagnostic push") _Pragma("GCC diagnostic ignored \"-Wdeprecated\"") \ + _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"") +# define _LIBCPP_SUPPRESS_DEPRECATED_POP _Pragma("GCC diagnostic pop") +# else +# define _LIBCPP_SUPPRESS_DEPRECATED_PUSH +# define _LIBCPP_SUPPRESS_DEPRECATED_POP +# endif + +# if _LIBCPP_STD_VER <= 11 +# define _LIBCPP_EXPLICIT_AFTER_CXX11 +# else +# define _LIBCPP_EXPLICIT_AFTER_CXX11 explicit +# endif + +# if _LIBCPP_STD_VER > 11 +# define _LIBCPP_CONSTEXPR_SINCE_CXX14 constexpr +# else +# define _LIBCPP_CONSTEXPR_SINCE_CXX14 +# endif + +# if _LIBCPP_STD_VER > 14 +# define _LIBCPP_CONSTEXPR_SINCE_CXX17 constexpr +# else +# define _LIBCPP_CONSTEXPR_SINCE_CXX17 +# endif + +# if _LIBCPP_STD_VER > 17 +# define _LIBCPP_CONSTEXPR_SINCE_CXX20 constexpr +# else +# define _LIBCPP_CONSTEXPR_SINCE_CXX20 +# endif + +# if _LIBCPP_STD_VER > 20 +# define _LIBCPP_CONSTEXPR_SINCE_CXX23 constexpr +# else +# define _LIBCPP_CONSTEXPR_SINCE_CXX23 +# endif + +# if __has_cpp_attribute(nodiscard) +# define _LIBCPP_NODISCARD [[nodiscard]] +# else +// We can't use GCC's [[gnu::warn_unused_result]] and +// __attribute__((warn_unused_result)), because GCC does not silence them via +// (void) cast. +# define _LIBCPP_NODISCARD +# endif + +// _LIBCPP_NODISCARD_EXT may be used to apply [[nodiscard]] to entities not +// specified as such as an extension. +# if !defined(_LIBCPP_DISABLE_NODISCARD_EXT) +# define _LIBCPP_NODISCARD_EXT _LIBCPP_NODISCARD +# else +# define _LIBCPP_NODISCARD_EXT +# endif + +# if _LIBCPP_STD_VER > 17 || !defined(_LIBCPP_DISABLE_NODISCARD_EXT) +# define _LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_NODISCARD +# else +# define _LIBCPP_NODISCARD_AFTER_CXX17 +# endif + +# if __has_attribute(__no_destroy__) +# define _LIBCPP_NO_DESTROY __attribute__((__no_destroy__)) +# else +# define _LIBCPP_NO_DESTROY +# endif + +# ifndef _LIBCPP_HAS_NO_ASAN + extern "C" _LIBCPP_FUNC_VIS void + __sanitizer_annotate_contiguous_container(const void*, const void*, const void*, const void*); +# endif + +// Try to find out if RTTI is disabled. +# if !defined(__cpp_rtti) || __cpp_rtti < 199711L +# define _LIBCPP_NO_RTTI +# endif + +# ifndef _LIBCPP_WEAK +# define _LIBCPP_WEAK __attribute__((__weak__)) +# endif + +// Thread API +// clang-format off +# if !defined(_LIBCPP_HAS_NO_THREADS) && \ + !defined(_LIBCPP_HAS_THREAD_API_PTHREAD) && \ + !defined(_LIBCPP_HAS_THREAD_API_WIN32) && \ + !defined(_LIBCPP_HAS_THREAD_API_EXTERNAL) + +# if defined(__FreeBSD__) || \ + defined(__wasi__) || \ + defined(__NetBSD__) || \ + defined(__OpenBSD__) || \ + defined(__NuttX__) || \ + defined(__linux__) || \ + defined(__GNU__) || \ + defined(__APPLE__) || \ + defined(__sun__) || \ + defined(__MVS__) || \ + defined(_AIX) || \ + defined(__EMSCRIPTEN__) +// clang-format on +# define _LIBCPP_HAS_THREAD_API_PTHREAD +# elif defined(__Fuchsia__) +// TODO(44575): Switch to C11 thread API when possible. +# define _LIBCPP_HAS_THREAD_API_PTHREAD +# elif defined(_LIBCPP_WIN32API) +# define _LIBCPP_HAS_THREAD_API_WIN32 +# else +# error "No thread API" +# endif // _LIBCPP_HAS_THREAD_API +# endif // _LIBCPP_HAS_NO_THREADS + +# if defined(_LIBCPP_HAS_THREAD_API_PTHREAD) +# if defined(__ANDROID__) && __ANDROID_API__ >= 30 +# define _LIBCPP_HAS_COND_CLOCKWAIT +# elif defined(_LIBCPP_GLIBC_PREREQ) +# if _LIBCPP_GLIBC_PREREQ(2, 30) +# define _LIBCPP_HAS_COND_CLOCKWAIT +# endif +# endif +# endif + +# if defined(_LIBCPP_HAS_NO_THREADS) && defined(_LIBCPP_HAS_THREAD_API_PTHREAD) +# error _LIBCPP_HAS_THREAD_API_PTHREAD may only be defined when \ + _LIBCPP_HAS_NO_THREADS is not defined. +# endif + +# if defined(_LIBCPP_HAS_NO_THREADS) && defined(_LIBCPP_HAS_THREAD_API_EXTERNAL) +# error _LIBCPP_HAS_THREAD_API_EXTERNAL may not be defined when \ + _LIBCPP_HAS_NO_THREADS is defined. +# endif + +# if defined(_LIBCPP_HAS_NO_MONOTONIC_CLOCK) && !defined(_LIBCPP_HAS_NO_THREADS) +# error _LIBCPP_HAS_NO_MONOTONIC_CLOCK may only be defined when \ + _LIBCPP_HAS_NO_THREADS is defined. +# endif + +# if !defined(_LIBCPP_HAS_NO_THREADS) && !defined(__STDCPP_THREADS__) +# define __STDCPP_THREADS__ 1 +# endif + +// The glibc and Bionic implementation of pthreads implements +// pthread_mutex_destroy as nop for regular mutexes. Additionally, Win32 +// mutexes have no destroy mechanism. +// +// This optimization can't be performed on Apple platforms, where +// pthread_mutex_destroy can allow the kernel to release resources. +// See https://llvm.org/D64298 for details. +// +// TODO(EricWF): Enable this optimization on Bionic after speaking to their +// respective stakeholders. +// clang-format off +# if (defined(_LIBCPP_HAS_THREAD_API_PTHREAD) && defined(__GLIBC__)) || \ + (defined(_LIBCPP_HAS_THREAD_API_C11) && defined(__Fuchsia__)) || \ + defined(_LIBCPP_HAS_THREAD_API_WIN32) +// clang-format on +# define _LIBCPP_HAS_TRIVIAL_MUTEX_DESTRUCTION +# endif + +// Destroying a condvar is a nop on Windows. +// +// This optimization can't be performed on Apple platforms, where +// pthread_cond_destroy can allow the kernel to release resources. +// See https://llvm.org/D64298 for details. +// +// TODO(EricWF): This is potentially true for some pthread implementations +// as well. +# if (defined(_LIBCPP_HAS_THREAD_API_C11) && defined(__Fuchsia__)) || defined(_LIBCPP_HAS_THREAD_API_WIN32) +# define _LIBCPP_HAS_TRIVIAL_CONDVAR_DESTRUCTION +# endif + +// Some systems do not provide gets() in their C library, for security reasons. +# if defined(_LIBCPP_MSVCRT) || (defined(__FreeBSD_version) && __FreeBSD_version >= 1300043) || defined(__OpenBSD__) +# define _LIBCPP_C_HAS_NO_GETS +# endif + +# if defined(__BIONIC__) || defined(__NuttX__) || defined(__Fuchsia__) || defined(__wasi__) || \ + defined(_LIBCPP_HAS_MUSL_LIBC) || defined(__OpenBSD__) +# define _LIBCPP_PROVIDES_DEFAULT_RUNE_TABLE +# endif + +# if __has_feature(cxx_atomic) || __has_extension(c_atomic) || __has_keyword(_Atomic) +# define _LIBCPP_HAS_C_ATOMIC_IMP +# elif defined(_LIBCPP_COMPILER_GCC) +# define _LIBCPP_HAS_GCC_ATOMIC_IMP +# endif + +# if !defined(_LIBCPP_HAS_C_ATOMIC_IMP) && !defined(_LIBCPP_HAS_GCC_ATOMIC_IMP) && \ + !defined(_LIBCPP_HAS_EXTERNAL_ATOMIC_IMP) +# define _LIBCPP_HAS_NO_ATOMIC_HEADER +# else +# ifndef _LIBCPP_ATOMIC_FLAG_TYPE +# define _LIBCPP_ATOMIC_FLAG_TYPE bool +# endif +# ifdef _LIBCPP_FREESTANDING +# define _LIBCPP_ATOMIC_ONLY_USE_BUILTINS +# endif +# endif + +# ifndef _LIBCPP_DISABLE_UBSAN_UNSIGNED_INTEGER_CHECK +# define _LIBCPP_DISABLE_UBSAN_UNSIGNED_INTEGER_CHECK +# endif + +# if defined(_LIBCPP_ENABLE_THREAD_SAFETY_ANNOTATIONS) +# if defined(__clang__) && __has_attribute(acquire_capability) +// Work around the attribute handling in clang. When both __declspec and +// __attribute__ are present, the processing goes awry preventing the definition +// of the types. In MinGW mode, __declspec evaluates to __attribute__, and thus +// combining the two does work. +# if !defined(_MSC_VER) +# define _LIBCPP_HAS_THREAD_SAFETY_ANNOTATIONS +# endif +# endif +# endif + +# ifdef _LIBCPP_HAS_THREAD_SAFETY_ANNOTATIONS +# define _LIBCPP_THREAD_SAFETY_ANNOTATION(x) __attribute__((x)) +# else +# define _LIBCPP_THREAD_SAFETY_ANNOTATION(x) +# endif + +# if _LIBCPP_STD_VER > 17 +# define _LIBCPP_CONSTINIT constinit +# elif __has_attribute(__require_constant_initialization__) +# define _LIBCPP_CONSTINIT __attribute__((__require_constant_initialization__)) +# else +# define _LIBCPP_CONSTINIT +# endif + +# if __has_attribute(__diagnose_if__) && !defined(_LIBCPP_DISABLE_ADDITIONAL_DIAGNOSTICS) +# define _LIBCPP_DIAGNOSE_WARNING(...) __attribute__((__diagnose_if__(__VA_ARGS__, "warning"))) +# else +# define _LIBCPP_DIAGNOSE_WARNING(...) +# endif + +// Use a function like macro to imply that it must be followed by a semicolon +# if __has_cpp_attribute(fallthrough) +# define _LIBCPP_FALLTHROUGH() [[fallthrough]] +# elif __has_attribute(__fallthrough__) +# define _LIBCPP_FALLTHROUGH() __attribute__((__fallthrough__)) +# else +# define _LIBCPP_FALLTHROUGH() ((void)0) +# endif + +# if __has_cpp_attribute(_Clang::__lifetimebound__) +# define _LIBCPP_LIFETIMEBOUND [[_Clang::__lifetimebound__]] +# else +# define _LIBCPP_LIFETIMEBOUND +# endif + +# if __has_attribute(__nodebug__) +# define _LIBCPP_NODEBUG __attribute__((__nodebug__)) +# else +# define _LIBCPP_NODEBUG +# endif + +# if __has_attribute(__standalone_debug__) +# define _LIBCPP_STANDALONE_DEBUG __attribute__((__standalone_debug__)) +# else +# define _LIBCPP_STANDALONE_DEBUG +# endif + +# if __has_attribute(__preferred_name__) +# define _LIBCPP_PREFERRED_NAME(x) __attribute__((__preferred_name__(x))) +# else +# define _LIBCPP_PREFERRED_NAME(x) +# endif + +// We often repeat things just for handling wide characters in the library. +// When wide characters are disabled, it can be useful to have a quick way of +// disabling it without having to resort to #if-#endif, which has a larger +// impact on readability. +# if defined(_LIBCPP_HAS_NO_WIDE_CHARACTERS) +# define _LIBCPP_IF_WIDE_CHARACTERS(...) +# else +# define _LIBCPP_IF_WIDE_CHARACTERS(...) __VA_ARGS__ +# endif + +# if defined(_LIBCPP_ABI_MICROSOFT) && __has_declspec_attribute(empty_bases) +# define _LIBCPP_DECLSPEC_EMPTY_BASES __declspec(empty_bases) +# else +# define _LIBCPP_DECLSPEC_EMPTY_BASES +# endif + +# if defined(_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES) +# define _LIBCPP_ENABLE_CXX17_REMOVED_AUTO_PTR +# define _LIBCPP_ENABLE_CXX17_REMOVED_BINDERS +# define _LIBCPP_ENABLE_CXX17_REMOVED_RANDOM_SHUFFLE +# define _LIBCPP_ENABLE_CXX17_REMOVED_UNEXPECTED_FUNCTIONS +# define _LIBCPP_ENABLE_CXX17_REMOVED_UNARY_BINARY_FUNCTION +# endif // _LIBCPP_ENABLE_CXX17_REMOVED_FEATURES + +# if defined(_LIBCPP_ENABLE_CXX20_REMOVED_FEATURES) +# define _LIBCPP_ENABLE_CXX20_REMOVED_ALLOCATOR_MEMBERS +# define _LIBCPP_ENABLE_CXX20_REMOVED_ALLOCATOR_VOID_SPECIALIZATION +# define _LIBCPP_ENABLE_CXX20_REMOVED_BINDER_TYPEDEFS +# define _LIBCPP_ENABLE_CXX20_REMOVED_NEGATORS +# define _LIBCPP_ENABLE_CXX20_REMOVED_RAW_STORAGE_ITERATOR +# define _LIBCPP_ENABLE_CXX20_REMOVED_TYPE_TRAITS +# endif // _LIBCPP_ENABLE_CXX20_REMOVED_FEATURES + +# define _LIBCPP_PUSH_MACROS _Pragma("push_macro(\"min\")") _Pragma("push_macro(\"max\")") +# define _LIBCPP_POP_MACROS _Pragma("pop_macro(\"min\")") _Pragma("pop_macro(\"max\")") + +# ifndef _LIBCPP_NO_AUTO_LINK +# if defined(_LIBCPP_ABI_MICROSOFT) && !defined(_LIBCPP_BUILDING_LIBRARY) +# if !defined(_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS) +# pragma comment(lib, "c++.lib") +# else +# pragma comment(lib, "libc++.lib") +# endif +# endif // defined(_LIBCPP_ABI_MICROSOFT) && !defined(_LIBCPP_BUILDING_LIBRARY) +# endif // _LIBCPP_NO_AUTO_LINK + +// Configures the fopen close-on-exec mode character, if any. This string will +// be appended to any mode string used by fstream for fopen/fdopen. +// +// Not all platforms support this, but it helps avoid fd-leaks on platforms that +// do. +# if defined(__BIONIC__) +# define _LIBCPP_FOPEN_CLOEXEC_MODE "e" +# else +# define _LIBCPP_FOPEN_CLOEXEC_MODE +# endif + +// Support for _FILE_OFFSET_BITS=64 landed gradually in Android, so the full set +// of functions used in cstdio may not be available for low API levels when +// using 64-bit file offsets on LP32. +# if defined(__BIONIC__) && defined(__USE_FILE_OFFSET64) && __ANDROID_API__ < 24 +# define _LIBCPP_HAS_NO_FGETPOS_FSETPOS +# endif + +# if __has_attribute(__init_priority__) +# define _LIBCPP_INIT_PRIORITY_MAX __attribute__((__init_priority__(100))) +# else +# define _LIBCPP_INIT_PRIORITY_MAX +# endif + +# if __has_attribute(__format__) +// The attribute uses 1-based indices for ordinary and static member functions. +// The attribute uses 2-based indices for non-static member functions. +# define _LIBCPP_ATTRIBUTE_FORMAT(archetype, format_string_index, first_format_arg_index) \ + __attribute__((__format__(archetype, format_string_index, first_format_arg_index))) +# else +# define _LIBCPP_ATTRIBUTE_FORMAT(archetype, format_string_index, first_format_arg_index) /* nothing */ +# endif + +# if __has_cpp_attribute(msvc::no_unique_address) +// MSVC implements [[no_unique_address]] as a silent no-op currently. +// (If/when MSVC breaks its C++ ABI, it will be changed to work as intended.) +// However, MSVC implements [[msvc::no_unique_address]] which does what +// [[no_unique_address]] is supposed to do, in general. + +// Clang-cl does not yet (14.0) implement either [[no_unique_address]] or +// [[msvc::no_unique_address]] though. If/when it does implement +// [[msvc::no_unique_address]], this should be preferred though. +# define _LIBCPP_NO_UNIQUE_ADDRESS [[msvc::no_unique_address]] +# elif __has_cpp_attribute(no_unique_address) +# define _LIBCPP_NO_UNIQUE_ADDRESS [[no_unique_address]] +# else +# define _LIBCPP_NO_UNIQUE_ADDRESS /* nothing */ +// Note that this can be replaced by #error as soon as clang-cl +// implements msvc::no_unique_address, since there should be no C++20 +// compiler that doesn't support one of the two attributes at that point. +// We generally don't want to use this macro outside of C++20-only code, +// because using it conditionally in one language version only would make +// the ABI inconsistent. +# endif + +# ifdef _LIBCPP_COMPILER_CLANG_BASED +# define _LIBCPP_DIAGNOSTIC_PUSH _Pragma("clang diagnostic push") +# define _LIBCPP_DIAGNOSTIC_POP _Pragma("clang diagnostic pop") +# define _LIBCPP_CLANG_DIAGNOSTIC_IGNORED(str) _Pragma(_LIBCPP_TOSTRING(clang diagnostic ignored str)) +# define _LIBCPP_GCC_DIAGNOSTIC_IGNORED(str) +# elif defined(_LIBCPP_COMPILER_GCC) +# define _LIBCPP_DIAGNOSTIC_PUSH _Pragma("GCC diagnostic push") +# define _LIBCPP_DIAGNOSTIC_POP _Pragma("GCC diagnostic pop") +# define _LIBCPP_CLANG_DIAGNOSTIC_IGNORED(str) +# define _LIBCPP_GCC_DIAGNOSTIC_IGNORED(str) _Pragma(_LIBCPP_TOSTRING(GCC diagnostic ignored str)) +# else +# define _LIBCPP_DIAGNOSTIC_PUSH +# define _LIBCPP_DIAGNOSTIC_POP +# define _LIBCPP_CLANG_DIAGNOSTIC_IGNORED(str) +# define _LIBCPP_GCC_DIAGNOSTIC_IGNORED(str) +# endif + +# if defined(_AIX) && !defined(_LIBCPP_COMPILER_GCC) +# define _LIBCPP_PACKED_BYTE_FOR_AIX _Pragma("pack(1)") +# define _LIBCPP_PACKED_BYTE_FOR_AIX_END _Pragma("pack(pop)") +# else +# define _LIBCPP_PACKED_BYTE_FOR_AIX /* empty */ +# define _LIBCPP_PACKED_BYTE_FOR_AIX_END /* empty */ +# endif + +# if __has_attribute(__packed__) +# define _LIBCPP_PACKED __attribute__((__packed__)) +# else +# define _LIBCPP_PACKED +# endif + +// c8rtomb() and mbrtoc8() were added in C++20 and C23. Support for these +// functions is gradually being added to existing C libraries. The conditions +// below check for known C library versions and conditions under which these +// functions are declared by the C library. +# define _LIBCPP_HAS_NO_C8RTOMB_MBRTOC8 +// GNU libc 2.36 and newer declare c8rtomb() and mbrtoc8() in C++ modes if +// __cpp_char8_t is defined or if C2X extensions are enabled. Unfortunately, +// determining the latter depends on internal GNU libc details. If the +// __cpp_char8_t feature test macro is not defined, then a char8_t typedef +// will be declared as well. +# if defined(_LIBCPP_GLIBC_PREREQ) && defined(__GLIBC_USE) +# if _LIBCPP_GLIBC_PREREQ(2, 36) && (defined(__cpp_char8_t) || __GLIBC_USE(ISOC2X)) +# undef _LIBCPP_HAS_NO_C8RTOMB_MBRTOC8 +# endif +# endif + +// There are a handful of public standard library types that are intended to +// support CTAD but don't need any explicit deduction guides to do so. This +// macro is used to mark them as such, which suppresses the +// '-Wctad-maybe-unsupported' compiler warning when CTAD is used in user code +// with these classes. +#if _LIBCPP_STD_VER >= 17 +# define _LIBCPP_CTAD_SUPPORTED_FOR_TYPE(_ClassName) \ + template \ + _ClassName(typename _Tag::__allow_ctad...) -> _ClassName<_Tag...> +#else +# define _LIBCPP_CTAD_SUPPORTED_FOR_TYPE(_ClassName) static_assert(true, "") +#endif + +#endif // __cplusplus + +#endif // _LIBCPP___CONFIG diff --git a/app/src/main/cpp/libcxx/include/__config_site b/app/src/main/cpp/libcxx/include/__config_site new file mode 100644 index 0000000..76d809b --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__config_site @@ -0,0 +1,39 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___CONFIG_SITE +#define _LIBCPP___CONFIG_SITE + +/* #undef _LIBCPP_ABI_VERSION */ +/* #undef _LIBCPP_ABI_NAMESPACE */ +/* #undef _LIBCPP_ABI_FORCE_ITANIUM */ +/* #undef _LIBCPP_ABI_FORCE_MICROSOFT */ +/* #undef _LIBCPP_HAS_NO_THREADS */ +/* #undef _LIBCPP_HAS_NO_MONOTONIC_CLOCK */ +/* #undef _LIBCPP_HAS_MUSL_LIBC */ +/* #undef _LIBCPP_HAS_THREAD_API_PTHREAD */ +/* #undef _LIBCPP_HAS_THREAD_API_EXTERNAL */ +/* #undef _LIBCPP_HAS_THREAD_API_WIN32 */ +/* #undef _LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL */ +/* #undef _LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS */ +#define _LIBCPP_HAS_NO_VENDOR_AVAILABILITY_ANNOTATIONS +/* #undef _LIBCPP_NO_VCRUNTIME */ +/* #undef _LIBCPP_TYPEINFO_COMPARISON_IMPLEMENTATION */ +/* #undef _LIBCPP_HAS_NO_FILESYSTEM_LIBRARY */ +/* #undef _LIBCPP_HAS_PARALLEL_ALGORITHMS */ +/* #undef _LIBCPP_HAS_NO_RANDOM_DEVICE */ +/* #undef _LIBCPP_HAS_NO_LOCALIZATION */ +/* #undef _LIBCPP_HAS_NO_FSTREAM */ +/* #undef _LIBCPP_HAS_NO_WIDE_CHARACTERS */ +/* #undef _LIBCPP_ENABLE_ASSERTIONS_DEFAULT */ +/* #undef _LIBCPP_ENABLE_DEBUG_MODE */ + + + + +#endif // _LIBCPP___CONFIG_SITE diff --git a/app/src/main/cpp/libcxx/include/__config_site.in b/app/src/main/cpp/libcxx/include/__config_site.in new file mode 100644 index 0000000..2ff6725 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__config_site.in @@ -0,0 +1,49 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___CONFIG_SITE +#define _LIBCPP___CONFIG_SITE + +#cmakedefine _LIBCPP_ABI_VERSION @_LIBCPP_ABI_VERSION@ +#cmakedefine _LIBCPP_ABI_NAMESPACE @_LIBCPP_ABI_NAMESPACE@ +#cmakedefine _LIBCPP_ABI_FORCE_ITANIUM +#cmakedefine _LIBCPP_ABI_FORCE_MICROSOFT +#cmakedefine _LIBCPP_HAS_NO_THREADS +#cmakedefine _LIBCPP_HAS_NO_MONOTONIC_CLOCK +#cmakedefine _LIBCPP_HAS_MUSL_LIBC +#cmakedefine _LIBCPP_HAS_THREAD_API_PTHREAD +#cmakedefine _LIBCPP_HAS_THREAD_API_EXTERNAL +#cmakedefine _LIBCPP_HAS_THREAD_API_WIN32 +#cmakedefine _LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL +#cmakedefine _LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS +#cmakedefine _LIBCPP_HAS_NO_VENDOR_AVAILABILITY_ANNOTATIONS +#cmakedefine _LIBCPP_NO_VCRUNTIME +#cmakedefine _LIBCPP_TYPEINFO_COMPARISON_IMPLEMENTATION @_LIBCPP_TYPEINFO_COMPARISON_IMPLEMENTATION@ +#cmakedefine _LIBCPP_HAS_NO_FILESYSTEM_LIBRARY +#cmakedefine _LIBCPP_HAS_PARALLEL_ALGORITHMS +#cmakedefine _LIBCPP_HAS_NO_RANDOM_DEVICE +#cmakedefine _LIBCPP_HAS_NO_LOCALIZATION +#cmakedefine _LIBCPP_HAS_NO_FSTREAM +#cmakedefine _LIBCPP_HAS_NO_WIDE_CHARACTERS +#cmakedefine01 _LIBCPP_ENABLE_ASSERTIONS_DEFAULT +#cmakedefine _LIBCPP_ENABLE_DEBUG_MODE + +// __USE_MINGW_ANSI_STDIO gets redefined on MinGW +#ifdef __clang__ +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wmacro-redefined" +#endif + +@_LIBCPP_ABI_DEFINES@ +@_LIBCPP_EXTRA_SITE_DEFINES@ + +#ifdef __clang__ +# pragma clang diagnostic pop +#endif + +#endif // _LIBCPP___CONFIG_SITE diff --git a/app/src/main/cpp/libcxx/include/__coroutine/coroutine_handle.h b/app/src/main/cpp/libcxx/include/__coroutine/coroutine_handle.h new file mode 100644 index 0000000..0a6cc1c --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__coroutine/coroutine_handle.h @@ -0,0 +1,203 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___COROUTINE_COROUTINE_HANDLE_H +#define _LIBCPP___COROUTINE_COROUTINE_HANDLE_H + +#include <__assert> +#include <__config> +#include <__functional/hash.h> +#include <__memory/addressof.h> +#include <__type_traits/remove_cv.h> +#include +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if _LIBCPP_STD_VER > 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +// [coroutine.handle] +template +struct _LIBCPP_TEMPLATE_VIS coroutine_handle; + +template <> +struct _LIBCPP_TEMPLATE_VIS coroutine_handle { +public: + // [coroutine.handle.con], construct/reset + _LIBCPP_HIDE_FROM_ABI + constexpr coroutine_handle() noexcept = default; + + _LIBCPP_HIDE_FROM_ABI + constexpr coroutine_handle(nullptr_t) noexcept {} + + _LIBCPP_HIDE_FROM_ABI + coroutine_handle& operator=(nullptr_t) noexcept { + __handle_ = nullptr; + return *this; + } + + // [coroutine.handle.export.import], export/import + _LIBCPP_HIDE_FROM_ABI + constexpr void* address() const noexcept { return __handle_; } + + _LIBCPP_HIDE_FROM_ABI + static constexpr coroutine_handle from_address(void* __addr) noexcept { + coroutine_handle __tmp; + __tmp.__handle_ = __addr; + return __tmp; + } + + // [coroutine.handle.observers], observers + _LIBCPP_HIDE_FROM_ABI + constexpr explicit operator bool() const noexcept { + return __handle_ != nullptr; + } + + _LIBCPP_HIDE_FROM_ABI + bool done() const { + _LIBCPP_ASSERT(__is_suspended(), "done() can be called only on suspended coroutines"); + return __builtin_coro_done(__handle_); + } + + // [coroutine.handle.resumption], resumption + _LIBCPP_HIDE_FROM_ABI + void operator()() const { resume(); } + + _LIBCPP_HIDE_FROM_ABI + void resume() const { + _LIBCPP_ASSERT(__is_suspended(), "resume() can be called only on suspended coroutines"); + _LIBCPP_ASSERT(!done(), "resume() has undefined behavior when the coroutine is done"); + __builtin_coro_resume(__handle_); + } + + _LIBCPP_HIDE_FROM_ABI + void destroy() const { + _LIBCPP_ASSERT(__is_suspended(), "destroy() can be called only on suspended coroutines"); + __builtin_coro_destroy(__handle_); + } + +private: + bool __is_suspended() const { + // FIXME actually implement a check for if the coro is suspended. + return __handle_ != nullptr; + } + + void* __handle_ = nullptr; +}; + +// [coroutine.handle.compare] +inline _LIBCPP_HIDE_FROM_ABI +constexpr bool operator==(coroutine_handle<> __x, coroutine_handle<> __y) noexcept { + return __x.address() == __y.address(); +} +inline _LIBCPP_HIDE_FROM_ABI +constexpr strong_ordering operator<=>(coroutine_handle<> __x, coroutine_handle<> __y) noexcept { + return compare_three_way()(__x.address(), __y.address()); +} + +template +struct _LIBCPP_TEMPLATE_VIS coroutine_handle { +public: + // [coroutine.handle.con], construct/reset + _LIBCPP_HIDE_FROM_ABI + constexpr coroutine_handle() noexcept = default; + + _LIBCPP_HIDE_FROM_ABI + constexpr coroutine_handle(nullptr_t) noexcept {} + + _LIBCPP_HIDE_FROM_ABI + static coroutine_handle from_promise(_Promise& __promise) { + using _RawPromise = __remove_cv_t<_Promise>; + coroutine_handle __tmp; + __tmp.__handle_ = + __builtin_coro_promise(_VSTD::addressof(const_cast<_RawPromise&>(__promise)), alignof(_Promise), true); + return __tmp; + } + + _LIBCPP_HIDE_FROM_ABI + coroutine_handle& operator=(nullptr_t) noexcept { + __handle_ = nullptr; + return *this; + } + + // [coroutine.handle.export.import], export/import + _LIBCPP_HIDE_FROM_ABI + constexpr void* address() const noexcept { return __handle_; } + + _LIBCPP_HIDE_FROM_ABI + static constexpr coroutine_handle from_address(void* __addr) noexcept { + coroutine_handle __tmp; + __tmp.__handle_ = __addr; + return __tmp; + } + + // [coroutine.handle.conv], conversion + _LIBCPP_HIDE_FROM_ABI + constexpr operator coroutine_handle<>() const noexcept { + return coroutine_handle<>::from_address(address()); + } + + // [coroutine.handle.observers], observers + _LIBCPP_HIDE_FROM_ABI + constexpr explicit operator bool() const noexcept { + return __handle_ != nullptr; + } + + _LIBCPP_HIDE_FROM_ABI + bool done() const { + _LIBCPP_ASSERT(__is_suspended(), "done() can be called only on suspended coroutines"); + return __builtin_coro_done(__handle_); + } + + // [coroutine.handle.resumption], resumption + _LIBCPP_HIDE_FROM_ABI + void operator()() const { resume(); } + + _LIBCPP_HIDE_FROM_ABI + void resume() const { + _LIBCPP_ASSERT(__is_suspended(), "resume() can be called only on suspended coroutines"); + _LIBCPP_ASSERT(!done(), "resume() has undefined behavior when the coroutine is done"); + __builtin_coro_resume(__handle_); + } + + _LIBCPP_HIDE_FROM_ABI + void destroy() const { + _LIBCPP_ASSERT(__is_suspended(), "destroy() can be called only on suspended coroutines"); + __builtin_coro_destroy(__handle_); + } + + // [coroutine.handle.promise], promise access + _LIBCPP_HIDE_FROM_ABI + _Promise& promise() const { + return *static_cast<_Promise*>(__builtin_coro_promise(this->__handle_, alignof(_Promise), false)); + } + +private: + bool __is_suspended() const { + // FIXME actually implement a check for if the coro is suspended. + return __handle_ != nullptr; + } + void* __handle_ = nullptr; +}; + +// [coroutine.handle.hash] +template +struct hash> { + _LIBCPP_HIDE_FROM_ABI + size_t operator()(const coroutine_handle<_Tp>& __v) const noexcept { return hash()(__v.address()); } +}; + +_LIBCPP_END_NAMESPACE_STD + +#endif // __LIBCPP_STD_VER > 17 + +#endif // _LIBCPP___COROUTINE_COROUTINE_HANDLE_H diff --git a/app/src/main/cpp/libcxx/include/__coroutine/coroutine_traits.h b/app/src/main/cpp/libcxx/include/__coroutine/coroutine_traits.h new file mode 100644 index 0000000..d513075 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__coroutine/coroutine_traits.h @@ -0,0 +1,53 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___COROUTINE_COROUTINE_TRAITS_H +#define _LIBCPP___COROUTINE_COROUTINE_TRAITS_H + +#include <__config> +#include <__type_traits/void_t.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if _LIBCPP_STD_VER > 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +// [coroutine.traits] +// [coroutine.traits.primary] +// The header defined the primary template coroutine_traits such that +// if ArgTypes is a parameter pack of types and if the qualified-id R::promise_type +// is valid and denotes a type ([temp.deduct]), then coroutine_traits +// has the following publicly accessible memebr: +// +// using promise_type = typename R::promise_type; +// +// Otherwise, coroutine_traits has no members. +template +struct __coroutine_traits_sfinae {}; + +template +struct __coroutine_traits_sfinae< + _Tp, __void_t > +{ + using promise_type = typename _Tp::promise_type; +}; + +template +struct coroutine_traits + : public __coroutine_traits_sfinae<_Ret> +{ +}; + +_LIBCPP_END_NAMESPACE_STD + +#endif // __LIBCPP_STD_VER > 17 + +#endif // _LIBCPP___COROUTINE_COROUTINE_TRAITS_H diff --git a/app/src/main/cpp/libcxx/include/__coroutine/noop_coroutine_handle.h b/app/src/main/cpp/libcxx/include/__coroutine/noop_coroutine_handle.h new file mode 100644 index 0000000..2993047 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__coroutine/noop_coroutine_handle.h @@ -0,0 +1,112 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___COROUTINE_NOOP_COROUTINE_HANDLE_H +#define _LIBCPP___COROUTINE_NOOP_COROUTINE_HANDLE_H + +#include <__config> +#include <__coroutine/coroutine_handle.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if _LIBCPP_STD_VER > 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if __has_builtin(__builtin_coro_noop) || defined(_LIBCPP_COMPILER_GCC) + +// [coroutine.noop] +// [coroutine.promise.noop] +struct noop_coroutine_promise {}; + +// [coroutine.handle.noop] +template <> +struct _LIBCPP_TEMPLATE_VIS coroutine_handle { +public: + // [coroutine.handle.noop.conv], conversion + _LIBCPP_HIDE_FROM_ABI + constexpr operator coroutine_handle<>() const noexcept { + return coroutine_handle<>::from_address(address()); + } + + // [coroutine.handle.noop.observers], observers + _LIBCPP_HIDE_FROM_ABI + constexpr explicit operator bool() const noexcept { return true; } + _LIBCPP_HIDE_FROM_ABI + constexpr bool done() const noexcept { return false; } + + // [coroutine.handle.noop.resumption], resumption + _LIBCPP_HIDE_FROM_ABI + constexpr void operator()() const noexcept {} + _LIBCPP_HIDE_FROM_ABI + constexpr void resume() const noexcept {} + _LIBCPP_HIDE_FROM_ABI + constexpr void destroy() const noexcept {} + + // [coroutine.handle.noop.promise], promise access + _LIBCPP_HIDE_FROM_ABI + noop_coroutine_promise& promise() const noexcept { + return *static_cast( + __builtin_coro_promise(this->__handle_, alignof(noop_coroutine_promise), false)); + } + + // [coroutine.handle.noop.address], address + _LIBCPP_HIDE_FROM_ABI + constexpr void* address() const noexcept { return __handle_; } + +private: + _LIBCPP_HIDE_FROM_ABI + friend coroutine_handle noop_coroutine() noexcept; + +#if __has_builtin(__builtin_coro_noop) + _LIBCPP_HIDE_FROM_ABI coroutine_handle() noexcept { + this->__handle_ = __builtin_coro_noop(); + } + + void* __handle_ = nullptr; + +#elif defined(_LIBCPP_COMPILER_GCC) + // GCC doesn't implement __builtin_coro_noop(). + // Construct the coroutine frame manually instead. + struct __noop_coroutine_frame_ty_ { + static void __dummy_resume_destroy_func() { } + + void (*__resume_)() = __dummy_resume_destroy_func; + void (*__destroy_)() = __dummy_resume_destroy_func; + struct noop_coroutine_promise __promise_; + }; + + static __noop_coroutine_frame_ty_ __noop_coroutine_frame_; + + void* __handle_ = &__noop_coroutine_frame_; + + _LIBCPP_HIDE_FROM_ABI coroutine_handle() noexcept = default; + +#endif // __has_builtin(__builtin_coro_noop) +}; + +using noop_coroutine_handle = coroutine_handle; + +#if defined(_LIBCPP_COMPILER_GCC) +inline noop_coroutine_handle::__noop_coroutine_frame_ty_ + noop_coroutine_handle::__noop_coroutine_frame_{}; +#endif + +// [coroutine.noop.coroutine] +inline _LIBCPP_HIDE_FROM_ABI +noop_coroutine_handle noop_coroutine() noexcept { return noop_coroutine_handle(); } + +#endif // __has_builtin(__builtin_coro_noop) || defined(_LIBCPP_COMPILER_GCC) + +_LIBCPP_END_NAMESPACE_STD + +#endif // __LIBCPP_STD_VER > 17 + +#endif // _LIBCPP___COROUTINE_NOOP_COROUTINE_HANDLE_H diff --git a/app/src/main/cpp/libcxx/include/__coroutine/trivial_awaitables.h b/app/src/main/cpp/libcxx/include/__coroutine/trivial_awaitables.h new file mode 100644 index 0000000..bbbae7a --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__coroutine/trivial_awaitables.h @@ -0,0 +1,46 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef __LIBCPP___COROUTINE_TRIVIAL_AWAITABLES_H +#define __LIBCPP___COROUTINE_TRIVIAL_AWAITABLES_H + +#include <__config> +#include <__coroutine/coroutine_handle.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if _LIBCPP_STD_VER > 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +// [coroutine.trivial.awaitables] +struct suspend_never { + _LIBCPP_HIDE_FROM_ABI + constexpr bool await_ready() const noexcept { return true; } + _LIBCPP_HIDE_FROM_ABI + constexpr void await_suspend(coroutine_handle<>) const noexcept {} + _LIBCPP_HIDE_FROM_ABI + constexpr void await_resume() const noexcept {} +}; + +struct suspend_always { + _LIBCPP_HIDE_FROM_ABI + constexpr bool await_ready() const noexcept { return false; } + _LIBCPP_HIDE_FROM_ABI + constexpr void await_suspend(coroutine_handle<>) const noexcept {} + _LIBCPP_HIDE_FROM_ABI + constexpr void await_resume() const noexcept {} +}; + +_LIBCPP_END_NAMESPACE_STD + +#endif // __LIBCPP_STD_VER > 17 + +#endif // __LIBCPP___COROUTINE_TRIVIAL_AWAITABLES_H diff --git a/app/src/main/cpp/libcxx/include/__debug b/app/src/main/cpp/libcxx/include/__debug new file mode 100644 index 0000000..140cc91 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__debug @@ -0,0 +1,266 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___DEBUG +#define _LIBCPP___DEBUG + +#include <__assert> +#include <__config> +#include <__type_traits/is_constant_evaluated.h> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if defined(_LIBCPP_ENABLE_DEBUG_MODE) && !defined(_LIBCPP_CXX03_LANG) && !defined(_LIBCPP_DEBUG_RANDOMIZE_UNSPECIFIED_STABILITY) +# define _LIBCPP_DEBUG_RANDOMIZE_UNSPECIFIED_STABILITY +#endif + +#if defined(_LIBCPP_ENABLE_DEBUG_MODE) && !defined(_LIBCPP_DEBUG_ITERATOR_BOUNDS_CHECKING) +# define _LIBCPP_DEBUG_ITERATOR_BOUNDS_CHECKING +#endif + +#ifdef _LIBCPP_ENABLE_DEBUG_MODE +# define _LIBCPP_DEBUG_ASSERT(x, m) _LIBCPP_ASSERT(::std::__libcpp_is_constant_evaluated() || (x), m) +#else +# define _LIBCPP_DEBUG_ASSERT(x, m) ((void)0) +#endif + +#if defined(_LIBCPP_ENABLE_DEBUG_MODE) || defined(_LIBCPP_BUILDING_LIBRARY) + +_LIBCPP_BEGIN_NAMESPACE_STD + +struct _LIBCPP_TYPE_VIS __c_node; + +struct _LIBCPP_TYPE_VIS __i_node +{ + void* __i_; + __i_node* __next_; + __c_node* __c_; + + __i_node(const __i_node&) = delete; + __i_node& operator=(const __i_node&) = delete; + + _LIBCPP_INLINE_VISIBILITY + __i_node(void* __i, __i_node* __next, __c_node* __c) + : __i_(__i), __next_(__next), __c_(__c) {} + ~__i_node(); +}; + +struct _LIBCPP_TYPE_VIS __c_node +{ + void* __c_; + __c_node* __next_; + __i_node** beg_; + __i_node** end_; + __i_node** cap_; + + __c_node(const __c_node&) = delete; + __c_node& operator=(const __c_node&) = delete; + + _LIBCPP_INLINE_VISIBILITY + explicit __c_node(void* __c, __c_node* __next) + : __c_(__c), __next_(__next), beg_(nullptr), end_(nullptr), cap_(nullptr) {} + virtual ~__c_node(); + + virtual bool __dereferenceable(const void*) const = 0; + virtual bool __decrementable(const void*) const = 0; + virtual bool __addable(const void*, ptrdiff_t) const = 0; + virtual bool __subscriptable(const void*, ptrdiff_t) const = 0; + + void __add(__i_node* __i); + _LIBCPP_HIDDEN void __remove(__i_node* __i); +}; + +template +struct _C_node + : public __c_node +{ + explicit _C_node(void* __c, __c_node* __n) + : __c_node(__c, __n) {} + + bool __dereferenceable(const void*) const override; + bool __decrementable(const void*) const override; + bool __addable(const void*, ptrdiff_t) const override; + bool __subscriptable(const void*, ptrdiff_t) const override; +}; + +template +inline bool +_C_node<_Cont>::__dereferenceable(const void* __i) const +{ + typedef typename _Cont::const_iterator iterator; + const iterator* __j = static_cast(__i); + _Cont* _Cp = static_cast<_Cont*>(__c_); + return _Cp->__dereferenceable(__j); +} + +template +inline bool +_C_node<_Cont>::__decrementable(const void* __i) const +{ + typedef typename _Cont::const_iterator iterator; + const iterator* __j = static_cast(__i); + _Cont* _Cp = static_cast<_Cont*>(__c_); + return _Cp->__decrementable(__j); +} + +template +inline bool +_C_node<_Cont>::__addable(const void* __i, ptrdiff_t __n) const +{ + typedef typename _Cont::const_iterator iterator; + const iterator* __j = static_cast(__i); + _Cont* _Cp = static_cast<_Cont*>(__c_); + return _Cp->__addable(__j, __n); +} + +template +inline bool +_C_node<_Cont>::__subscriptable(const void* __i, ptrdiff_t __n) const +{ + typedef typename _Cont::const_iterator iterator; + const iterator* __j = static_cast(__i); + _Cont* _Cp = static_cast<_Cont*>(__c_); + return _Cp->__subscriptable(__j, __n); +} + +class _LIBCPP_TYPE_VIS __libcpp_db +{ + __c_node** __cbeg_; + __c_node** __cend_; + size_t __csz_; + __i_node** __ibeg_; + __i_node** __iend_; + size_t __isz_; + + explicit __libcpp_db(); +public: + __libcpp_db(const __libcpp_db&) = delete; + __libcpp_db& operator=(const __libcpp_db&) = delete; + + ~__libcpp_db(); + + class __db_c_iterator; + class __db_c_const_iterator; + class __db_i_iterator; + class __db_i_const_iterator; + + __db_c_const_iterator __c_end() const; + __db_i_const_iterator __i_end() const; + + typedef __c_node*(_InsertConstruct)(void*, void*, __c_node*); + + template + _LIBCPP_INLINE_VISIBILITY static __c_node* __create_C_node(void *__mem, void *__c, __c_node *__next) { + return ::new (__mem) _C_node<_Cont>(__c, __next); + } + + template + _LIBCPP_INLINE_VISIBILITY + void __insert_c(_Cont* __c) + { + __insert_c(static_cast(__c), &__create_C_node<_Cont>); + } + + void __insert_i(void* __i); + void __insert_c(void* __c, _InsertConstruct* __fn); + void __erase_c(void* __c); + + void __insert_ic(void* __i, const void* __c); + void __iterator_copy(void* __i, const void* __i0); + void __erase_i(void* __i); + + void* __find_c_from_i(void* __i) const; + void __invalidate_all(void* __c); + __c_node* __find_c_and_lock(void* __c) const; + __c_node* __find_c(void* __c) const; + void unlock() const; + + void swap(void* __c1, void* __c2); + + + bool __dereferenceable(const void* __i) const; + bool __decrementable(const void* __i) const; + bool __addable(const void* __i, ptrdiff_t __n) const; + bool __subscriptable(const void* __i, ptrdiff_t __n) const; + bool __less_than_comparable(const void* __i, const void* __j) const; +private: + _LIBCPP_HIDDEN + __i_node* __insert_iterator(void* __i); + _LIBCPP_HIDDEN + __i_node* __find_iterator(const void* __i) const; + + friend _LIBCPP_FUNC_VIS __libcpp_db* __get_db(); +}; + +_LIBCPP_FUNC_VIS __libcpp_db* __get_db(); +_LIBCPP_FUNC_VIS const __libcpp_db* __get_const_db(); + +_LIBCPP_END_NAMESPACE_STD + +#endif // defined(_LIBCPP_ENABLE_DEBUG_MODE) || defined(_LIBCPP_BUILDING_LIBRARY) + +_LIBCPP_BEGIN_NAMESPACE_STD + +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 inline void __debug_db_insert_c(_Tp* __c) { +#ifdef _LIBCPP_ENABLE_DEBUG_MODE + if (!__libcpp_is_constant_evaluated()) + __get_db()->__insert_c(__c); +#else + (void)(__c); +#endif +} + +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 inline void __debug_db_insert_i(_Tp* __i) { +#ifdef _LIBCPP_ENABLE_DEBUG_MODE + if (!__libcpp_is_constant_evaluated()) + __get_db()->__insert_i(__i); +#else + (void)(__i); +#endif +} + +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 inline void __debug_db_erase_c(_Tp* __c) { +#ifdef _LIBCPP_ENABLE_DEBUG_MODE + if (!__libcpp_is_constant_evaluated()) + __get_db()->__erase_c(__c); +#else + (void)(__c); +#endif +} + +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 inline void __debug_db_swap(_Tp* __lhs, _Tp* __rhs) { +#ifdef _LIBCPP_ENABLE_DEBUG_MODE + if (!__libcpp_is_constant_evaluated()) + __get_db()->swap(__lhs, __rhs); +#else + (void)(__lhs); + (void)(__rhs); +#endif +} + +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 inline void __debug_db_invalidate_all(_Tp* __c) { +#ifdef _LIBCPP_ENABLE_DEBUG_MODE + if (!__libcpp_is_constant_evaluated()) + __get_db()->__invalidate_all(__c); +#else + (void)(__c); +#endif +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___DEBUG diff --git a/app/src/main/cpp/libcxx/include/__debug_utils/randomize_range.h b/app/src/main/cpp/libcxx/include/__debug_utils/randomize_range.h new file mode 100644 index 0000000..dce6192 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__debug_utils/randomize_range.h @@ -0,0 +1,43 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___LIBCXX_DEBUG_RANDOMIZE_RANGE_H +#define _LIBCPP___LIBCXX_DEBUG_RANDOMIZE_RANGE_H + +#include <__config> + +#ifdef _LIBCPP_DEBUG_RANDOMIZE_UNSPECIFIED_STABILITY +# include <__algorithm/shuffle.h> +# include <__type_traits/is_constant_evaluated.h> +#endif + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 +void __debug_randomize_range(_Iterator __first, _Sentinel __last) { +#ifdef _LIBCPP_DEBUG_RANDOMIZE_UNSPECIFIED_STABILITY +# ifdef _LIBCPP_CXX03_LANG +# error Support for unspecified stability is only for C++11 and higher +# endif + + if (!__libcpp_is_constant_evaluated()) + std::__shuffle<_AlgPolicy>(__first, __last, __libcpp_debug_randomizer()); +#else + (void)__first; + (void)__last; +#endif +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___LIBCXX_DEBUG_RANDOMIZE_RANGE_H diff --git a/app/src/main/cpp/libcxx/include/__errc b/app/src/main/cpp/libcxx/include/__errc new file mode 100644 index 0000000..17bbe0e --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__errc @@ -0,0 +1,217 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ERRC +#define _LIBCPP___ERRC + +/* + system_error synopsis + +namespace std +{ + +enum class errc +{ + address_family_not_supported, // EAFNOSUPPORT + address_in_use, // EADDRINUSE + address_not_available, // EADDRNOTAVAIL + already_connected, // EISCONN + argument_list_too_long, // E2BIG + argument_out_of_domain, // EDOM + bad_address, // EFAULT + bad_file_descriptor, // EBADF + bad_message, // EBADMSG + broken_pipe, // EPIPE + connection_aborted, // ECONNABORTED + connection_already_in_progress, // EALREADY + connection_refused, // ECONNREFUSED + connection_reset, // ECONNRESET + cross_device_link, // EXDEV + destination_address_required, // EDESTADDRREQ + device_or_resource_busy, // EBUSY + directory_not_empty, // ENOTEMPTY + executable_format_error, // ENOEXEC + file_exists, // EEXIST + file_too_large, // EFBIG + filename_too_long, // ENAMETOOLONG + function_not_supported, // ENOSYS + host_unreachable, // EHOSTUNREACH + identifier_removed, // EIDRM + illegal_byte_sequence, // EILSEQ + inappropriate_io_control_operation, // ENOTTY + interrupted, // EINTR + invalid_argument, // EINVAL + invalid_seek, // ESPIPE + io_error, // EIO + is_a_directory, // EISDIR + message_size, // EMSGSIZE + network_down, // ENETDOWN + network_reset, // ENETRESET + network_unreachable, // ENETUNREACH + no_buffer_space, // ENOBUFS + no_child_process, // ECHILD + no_link, // ENOLINK + no_lock_available, // ENOLCK + no_message_available, // ENODATA + no_message, // ENOMSG + no_protocol_option, // ENOPROTOOPT + no_space_on_device, // ENOSPC + no_stream_resources, // ENOSR + no_such_device_or_address, // ENXIO + no_such_device, // ENODEV + no_such_file_or_directory, // ENOENT + no_such_process, // ESRCH + not_a_directory, // ENOTDIR + not_a_socket, // ENOTSOCK + not_a_stream, // ENOSTR + not_connected, // ENOTCONN + not_enough_memory, // ENOMEM + not_supported, // ENOTSUP + operation_canceled, // ECANCELED + operation_in_progress, // EINPROGRESS + operation_not_permitted, // EPERM + operation_not_supported, // EOPNOTSUPP + operation_would_block, // EWOULDBLOCK + owner_dead, // EOWNERDEAD + permission_denied, // EACCES + protocol_error, // EPROTO + protocol_not_supported, // EPROTONOSUPPORT + read_only_file_system, // EROFS + resource_deadlock_would_occur, // EDEADLK + resource_unavailable_try_again, // EAGAIN + result_out_of_range, // ERANGE + state_not_recoverable, // ENOTRECOVERABLE + stream_timeout, // ETIME + text_file_busy, // ETXTBSY + timed_out, // ETIMEDOUT + too_many_files_open_in_system, // ENFILE + too_many_files_open, // EMFILE + too_many_links, // EMLINK + too_many_symbolic_link_levels, // ELOOP + value_too_large, // EOVERFLOW + wrong_protocol_type // EPROTOTYPE +}; + +*/ + +#include <__config> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +// Some error codes are not present on all platforms, so we provide equivalents +// for them: + +//enum class errc +_LIBCPP_DECLARE_STRONG_ENUM(errc) +{ + address_family_not_supported = EAFNOSUPPORT, + address_in_use = EADDRINUSE, + address_not_available = EADDRNOTAVAIL, + already_connected = EISCONN, + argument_list_too_long = E2BIG, + argument_out_of_domain = EDOM, + bad_address = EFAULT, + bad_file_descriptor = EBADF, + bad_message = EBADMSG, + broken_pipe = EPIPE, + connection_aborted = ECONNABORTED, + connection_already_in_progress = EALREADY, + connection_refused = ECONNREFUSED, + connection_reset = ECONNRESET, + cross_device_link = EXDEV, + destination_address_required = EDESTADDRREQ, + device_or_resource_busy = EBUSY, + directory_not_empty = ENOTEMPTY, + executable_format_error = ENOEXEC, + file_exists = EEXIST, + file_too_large = EFBIG, + filename_too_long = ENAMETOOLONG, + function_not_supported = ENOSYS, + host_unreachable = EHOSTUNREACH, + identifier_removed = EIDRM, + illegal_byte_sequence = EILSEQ, + inappropriate_io_control_operation = ENOTTY, + interrupted = EINTR, + invalid_argument = EINVAL, + invalid_seek = ESPIPE, + io_error = EIO, + is_a_directory = EISDIR, + message_size = EMSGSIZE, + network_down = ENETDOWN, + network_reset = ENETRESET, + network_unreachable = ENETUNREACH, + no_buffer_space = ENOBUFS, + no_child_process = ECHILD, + no_link = ENOLINK, + no_lock_available = ENOLCK, +#ifdef ENODATA + no_message_available = ENODATA, +#else + no_message_available = ENOMSG, +#endif + no_message = ENOMSG, + no_protocol_option = ENOPROTOOPT, + no_space_on_device = ENOSPC, +#ifdef ENOSR + no_stream_resources = ENOSR, +#else + no_stream_resources = ENOMEM, +#endif + no_such_device_or_address = ENXIO, + no_such_device = ENODEV, + no_such_file_or_directory = ENOENT, + no_such_process = ESRCH, + not_a_directory = ENOTDIR, + not_a_socket = ENOTSOCK, +#ifdef ENOSTR + not_a_stream = ENOSTR, +#else + not_a_stream = EINVAL, +#endif + not_connected = ENOTCONN, + not_enough_memory = ENOMEM, + not_supported = ENOTSUP, + operation_canceled = ECANCELED, + operation_in_progress = EINPROGRESS, + operation_not_permitted = EPERM, + operation_not_supported = EOPNOTSUPP, + operation_would_block = EWOULDBLOCK, + owner_dead = EOWNERDEAD, + permission_denied = EACCES, + protocol_error = EPROTO, + protocol_not_supported = EPROTONOSUPPORT, + read_only_file_system = EROFS, + resource_deadlock_would_occur = EDEADLK, + resource_unavailable_try_again = EAGAIN, + result_out_of_range = ERANGE, + state_not_recoverable = ENOTRECOVERABLE, +#ifdef ETIME + stream_timeout = ETIME, +#else + stream_timeout = ETIMEDOUT, +#endif + text_file_busy = ETXTBSY, + timed_out = ETIMEDOUT, + too_many_files_open_in_system = ENFILE, + too_many_files_open = EMFILE, + too_many_links = EMLINK, + too_many_symbolic_link_levels = ELOOP, + value_too_large = EOVERFLOW, + wrong_protocol_type = EPROTOTYPE +}; +_LIBCPP_DECLARE_STRONG_ENUM_EPILOG(errc) + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ERRC diff --git a/app/src/main/cpp/libcxx/include/__expected/bad_expected_access.h b/app/src/main/cpp/libcxx/include/__expected/bad_expected_access.h new file mode 100644 index 0000000..361eab4 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__expected/bad_expected_access.h @@ -0,0 +1,64 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +#ifndef _LIBCPP___EXPECTED_BAD_EXPECTED_ACCESS_H +#define _LIBCPP___EXPECTED_BAD_EXPECTED_ACCESS_H + +#include <__config> +#include <__utility/move.h> + +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if _LIBCPP_STD_VER >= 23 + +_LIBCPP_BEGIN_NAMESPACE_STD + +template +class bad_expected_access; + +template <> +class bad_expected_access : public exception { +protected: + _LIBCPP_HIDE_FROM_ABI bad_expected_access() noexcept = default; + _LIBCPP_HIDE_FROM_ABI bad_expected_access(const bad_expected_access&) = default; + _LIBCPP_HIDE_FROM_ABI bad_expected_access(bad_expected_access&&) = default; + _LIBCPP_HIDE_FROM_ABI bad_expected_access& operator=(const bad_expected_access&) = default; + _LIBCPP_HIDE_FROM_ABI bad_expected_access& operator=(bad_expected_access&&) = default; + ~bad_expected_access() override = default; + +public: + // The way this has been designed (by using a class template below) means that we'll already + // have a profusion of these vtables in TUs, and the dynamic linker will already have a bunch + // of work to do. So it is not worth hiding the specialization in the dylib, given that + // it adds deployment target restrictions. + const char* what() const noexcept override { return "bad access to std::expected"; } +}; + +template +class bad_expected_access : public bad_expected_access { +public: + _LIBCPP_HIDE_FROM_ABI explicit bad_expected_access(_Err __e) : __unex_(std::move(__e)) {} + + _LIBCPP_HIDE_FROM_ABI _Err& error() & noexcept { return __unex_; } + _LIBCPP_HIDE_FROM_ABI const _Err& error() const& noexcept { return __unex_; } + _LIBCPP_HIDE_FROM_ABI _Err&& error() && noexcept { return std::move(__unex_); } + _LIBCPP_HIDE_FROM_ABI const _Err&& error() const&& noexcept { return std::move(__unex_); } + +private: + _Err __unex_; +}; + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER >= 23 + +#endif // _LIBCPP___EXPECTED_BAD_EXPECTED_ACCESS_H diff --git a/app/src/main/cpp/libcxx/include/__expected/expected.h b/app/src/main/cpp/libcxx/include/__expected/expected.h new file mode 100644 index 0000000..e1f590c --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__expected/expected.h @@ -0,0 +1,973 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +#ifndef _LIBCPP___EXPECTED_EXPECTED_H +#define _LIBCPP___EXPECTED_EXPECTED_H + +#include <__assert> +#include <__config> +#include <__expected/bad_expected_access.h> +#include <__expected/unexpect.h> +#include <__expected/unexpected.h> +#include <__memory/addressof.h> +#include <__memory/construct_at.h> +#include <__type_traits/conjunction.h> +#include <__type_traits/disjunction.h> +#include <__type_traits/is_assignable.h> +#include <__type_traits/is_constructible.h> +#include <__type_traits/is_convertible.h> +#include <__type_traits/is_copy_assignable.h> +#include <__type_traits/is_copy_constructible.h> +#include <__type_traits/is_default_constructible.h> +#include <__type_traits/is_function.h> +#include <__type_traits/is_move_assignable.h> +#include <__type_traits/is_move_constructible.h> +#include <__type_traits/is_nothrow_constructible.h> +#include <__type_traits/is_nothrow_copy_assignable.h> +#include <__type_traits/is_nothrow_copy_constructible.h> +#include <__type_traits/is_nothrow_default_constructible.h> +#include <__type_traits/is_nothrow_move_assignable.h> +#include <__type_traits/is_nothrow_move_constructible.h> +#include <__type_traits/is_reference.h> +#include <__type_traits/is_same.h> +#include <__type_traits/is_swappable.h> +#include <__type_traits/is_trivially_copy_constructible.h> +#include <__type_traits/is_trivially_destructible.h> +#include <__type_traits/is_trivially_move_constructible.h> +#include <__type_traits/is_void.h> +#include <__type_traits/lazy.h> +#include <__type_traits/negation.h> +#include <__type_traits/remove_cv.h> +#include <__type_traits/remove_cvref.h> +#include <__utility/exception_guard.h> +#include <__utility/forward.h> +#include <__utility/in_place.h> +#include <__utility/move.h> +#include <__utility/swap.h> +#include // for std::abort +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if _LIBCPP_STD_VER >= 23 + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace __expected { + +template +_LIBCPP_HIDE_FROM_ABI void __throw_bad_expected_access(_Arg&& __arg) { +# ifndef _LIBCPP_NO_EXCEPTIONS + throw bad_expected_access<_Err>(std::forward<_Arg>(__arg)); +# else + (void)__arg; + std::abort(); +# endif +} + +} // namespace __expected + +template +class expected { + static_assert( + !is_reference_v<_Tp> && + !is_function_v<_Tp> && + !is_same_v, in_place_t> && + !is_same_v, unexpect_t> && + !__is_std_unexpected>::value && + __valid_std_unexpected<_Err>::value + , + "[expected.object.general] A program that instantiates the definition of template expected for a " + "reference type, a function type, or for possibly cv-qualified types in_place_t, unexpect_t, or a " + "specialization of unexpected for the T parameter is ill-formed. A program that instantiates the " + "definition of the template expected with a type for the E parameter that is not a valid " + "template argument for unexpected is ill-formed."); + + template + friend class expected; + +public: + using value_type = _Tp; + using error_type = _Err; + using unexpected_type = unexpected<_Err>; + + template + using rebind = expected<_Up, error_type>; + + // [expected.object.ctor], constructors + _LIBCPP_HIDE_FROM_ABI constexpr expected() + noexcept(is_nothrow_default_constructible_v<_Tp>) // strengthened + requires is_default_constructible_v<_Tp> + : __has_val_(true) { + std::construct_at(std::addressof(__union_.__val_)); + } + + _LIBCPP_HIDE_FROM_ABI constexpr expected(const expected&) = delete; + + _LIBCPP_HIDE_FROM_ABI constexpr expected(const expected&) + requires(is_copy_constructible_v<_Tp> && + is_copy_constructible_v<_Err> && + is_trivially_copy_constructible_v<_Tp> && + is_trivially_copy_constructible_v<_Err>) + = default; + + _LIBCPP_HIDE_FROM_ABI constexpr expected(const expected& __other) + noexcept(is_nothrow_copy_constructible_v<_Tp> && is_nothrow_copy_constructible_v<_Err>) // strengthened + requires(is_copy_constructible_v<_Tp> && is_copy_constructible_v<_Err> && + !(is_trivially_copy_constructible_v<_Tp> && is_trivially_copy_constructible_v<_Err>)) + : __has_val_(__other.__has_val_) { + if (__has_val_) { + std::construct_at(std::addressof(__union_.__val_), __other.__union_.__val_); + } else { + std::construct_at(std::addressof(__union_.__unex_), __other.__union_.__unex_); + } + } + + + _LIBCPP_HIDE_FROM_ABI constexpr expected(expected&&) + requires(is_move_constructible_v<_Tp> && is_move_constructible_v<_Err> + && is_trivially_move_constructible_v<_Tp> && is_trivially_move_constructible_v<_Err>) + = default; + + _LIBCPP_HIDE_FROM_ABI constexpr expected(expected&& __other) + noexcept(is_nothrow_move_constructible_v<_Tp> && is_nothrow_move_constructible_v<_Err>) + requires(is_move_constructible_v<_Tp> && is_move_constructible_v<_Err> && + !(is_trivially_move_constructible_v<_Tp> && is_trivially_move_constructible_v<_Err>)) + : __has_val_(__other.__has_val_) { + if (__has_val_) { + std::construct_at(std::addressof(__union_.__val_), std::move(__other.__union_.__val_)); + } else { + std::construct_at(std::addressof(__union_.__unex_), std::move(__other.__union_.__unex_)); + } + } + +private: + template + using __can_convert = + _And< is_constructible<_Tp, _UfQual>, + is_constructible<_Err, _OtherErrQual>, + _Not&>>, + _Not>>, + _Not&>>, + _Not>>, + _Not&, _Tp>>, + _Not&&, _Tp>>, + _Not&, _Tp>>, + _Not&&, _Tp>>, + _Not, expected<_Up, _OtherErr>&>>, + _Not, expected<_Up, _OtherErr>>>, + _Not, const expected<_Up, _OtherErr>&>>, + _Not, const expected<_Up, _OtherErr>>> >; + + +public: + template + requires __can_convert<_Up, _OtherErr, const _Up&, const _OtherErr&>::value + _LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v || + !is_convertible_v) + expected(const expected<_Up, _OtherErr>& __other) + noexcept(is_nothrow_constructible_v<_Tp, const _Up&> && + is_nothrow_constructible_v<_Err, const _OtherErr&>) // strengthened + : __has_val_(__other.__has_val_) { + if (__has_val_) { + std::construct_at(std::addressof(__union_.__val_), __other.__union_.__val_); + } else { + std::construct_at(std::addressof(__union_.__unex_), __other.__union_.__unex_); + } + } + + template + requires __can_convert<_Up, _OtherErr, _Up, _OtherErr>::value + _LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v<_Up, _Tp> || !is_convertible_v<_OtherErr, _Err>) + expected(expected<_Up, _OtherErr>&& __other) + noexcept(is_nothrow_constructible_v<_Tp, _Up> && is_nothrow_constructible_v<_Err, _OtherErr>) // strengthened + : __has_val_(__other.__has_val_) { + if (__has_val_) { + std::construct_at(std::addressof(__union_.__val_), std::move(__other.__union_.__val_)); + } else { + std::construct_at(std::addressof(__union_.__unex_), std::move(__other.__union_.__unex_)); + } + } + + template + requires(!is_same_v, in_place_t> && !is_same_v> && + !__is_std_unexpected>::value && is_constructible_v<_Tp, _Up>) + _LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v<_Up, _Tp>) + expected(_Up&& __u) + noexcept(is_nothrow_constructible_v<_Tp, _Up>) // strengthened + : __has_val_(true) { + std::construct_at(std::addressof(__union_.__val_), std::forward<_Up>(__u)); + } + + + template + requires is_constructible_v<_Err, const _OtherErr&> + _LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v) + expected(const unexpected<_OtherErr>& __unex) + noexcept(is_nothrow_constructible_v<_Err, const _OtherErr&>) // strengthened + : __has_val_(false) { + std::construct_at(std::addressof(__union_.__unex_), __unex.error()); + } + + template + requires is_constructible_v<_Err, _OtherErr> + _LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v<_OtherErr, _Err>) + expected(unexpected<_OtherErr>&& __unex) + noexcept(is_nothrow_constructible_v<_Err, _OtherErr>) // strengthened + : __has_val_(false) { + std::construct_at(std::addressof(__union_.__unex_), std::move(__unex.error())); + } + + template + requires is_constructible_v<_Tp, _Args...> + _LIBCPP_HIDE_FROM_ABI constexpr explicit expected(in_place_t, _Args&&... __args) + noexcept(is_nothrow_constructible_v<_Tp, _Args...>) // strengthened + : __has_val_(true) { + std::construct_at(std::addressof(__union_.__val_), std::forward<_Args>(__args)...); + } + + template + requires is_constructible_v< _Tp, initializer_list<_Up>&, _Args... > + _LIBCPP_HIDE_FROM_ABI constexpr explicit + expected(in_place_t, initializer_list<_Up> __il, _Args&&... __args) + noexcept(is_nothrow_constructible_v<_Tp, initializer_list<_Up>&, _Args...>) // strengthened + : __has_val_(true) { + std::construct_at(std::addressof(__union_.__val_), __il, std::forward<_Args>(__args)...); + } + + template + requires is_constructible_v<_Err, _Args...> + _LIBCPP_HIDE_FROM_ABI constexpr explicit expected(unexpect_t, _Args&&... __args) + noexcept(is_nothrow_constructible_v<_Err, _Args...>) // strengthened + : __has_val_(false) { + std::construct_at(std::addressof(__union_.__unex_), std::forward<_Args>(__args)...); + } + + template + requires is_constructible_v< _Err, initializer_list<_Up>&, _Args... > + _LIBCPP_HIDE_FROM_ABI constexpr explicit + expected(unexpect_t, initializer_list<_Up> __il, _Args&&... __args) + noexcept(is_nothrow_constructible_v<_Err, initializer_list<_Up>&, _Args...>) // strengthened + : __has_val_(false) { + std::construct_at(std::addressof(__union_.__unex_), __il, std::forward<_Args>(__args)...); + } + + // [expected.object.dtor], destructor + + _LIBCPP_HIDE_FROM_ABI constexpr ~expected() + requires(is_trivially_destructible_v<_Tp> && is_trivially_destructible_v<_Err>) + = default; + + _LIBCPP_HIDE_FROM_ABI constexpr ~expected() + requires(!is_trivially_destructible_v<_Tp> || !is_trivially_destructible_v<_Err>) + { + if (__has_val_) { + std::destroy_at(std::addressof(__union_.__val_)); + } else { + std::destroy_at(std::addressof(__union_.__unex_)); + } + } + +private: + template + _LIBCPP_HIDE_FROM_ABI static constexpr void __reinit_expected(_T1& __newval, _T2& __oldval, _Args&&... __args) { + if constexpr (is_nothrow_constructible_v<_T1, _Args...>) { + std::destroy_at(std::addressof(__oldval)); + std::construct_at(std::addressof(__newval), std::forward<_Args>(__args)...); + } else if constexpr (is_nothrow_move_constructible_v<_T1>) { + _T1 __tmp(std::forward<_Args>(__args)...); + std::destroy_at(std::addressof(__oldval)); + std::construct_at(std::addressof(__newval), std::move(__tmp)); + } else { + static_assert( + is_nothrow_move_constructible_v<_T2>, + "To provide strong exception guarantee, T2 has to satisfy `is_nothrow_move_constructible_v` so that it can " + "be reverted to the previous state in case an exception is thrown during the assignment."); + _T2 __tmp(std::move(__oldval)); + std::destroy_at(std::addressof(__oldval)); + __exception_guard __trans([&] { std::construct_at(std::addressof(__oldval), std::move(__tmp)); }); + std::construct_at(std::addressof(__newval), std::forward<_Args>(__args)...); + __trans.__complete(); + } + } + +public: + // [expected.object.assign], assignment + _LIBCPP_HIDE_FROM_ABI constexpr expected& operator=(const expected&) = delete; + + _LIBCPP_HIDE_FROM_ABI constexpr expected& operator=(const expected& __rhs) + noexcept(is_nothrow_copy_assignable_v<_Tp> && + is_nothrow_copy_constructible_v<_Tp> && + is_nothrow_copy_assignable_v<_Err> && + is_nothrow_copy_constructible_v<_Err>) // strengthened + requires(is_copy_assignable_v<_Tp> && + is_copy_constructible_v<_Tp> && + is_copy_assignable_v<_Err> && + is_copy_constructible_v<_Err> && + (is_nothrow_move_constructible_v<_Tp> || + is_nothrow_move_constructible_v<_Err>)) + { + if (__has_val_ && __rhs.__has_val_) { + __union_.__val_ = __rhs.__union_.__val_; + } else if (__has_val_) { + __reinit_expected(__union_.__unex_, __union_.__val_, __rhs.__union_.__unex_); + } else if (__rhs.__has_val_) { + __reinit_expected(__union_.__val_, __union_.__unex_, __rhs.__union_.__val_); + } else { + __union_.__unex_ = __rhs.__union_.__unex_; + } + // note: only reached if no exception+rollback was done inside __reinit_expected + __has_val_ = __rhs.__has_val_; + return *this; + } + + _LIBCPP_HIDE_FROM_ABI constexpr expected& operator=(expected&& __rhs) + noexcept(is_nothrow_move_assignable_v<_Tp> && + is_nothrow_move_constructible_v<_Tp> && + is_nothrow_move_assignable_v<_Err> && + is_nothrow_move_constructible_v<_Err>) + requires(is_move_constructible_v<_Tp> && + is_move_assignable_v<_Tp> && + is_move_constructible_v<_Err> && + is_move_assignable_v<_Err> && + (is_nothrow_move_constructible_v<_Tp> || + is_nothrow_move_constructible_v<_Err>)) + { + if (__has_val_ && __rhs.__has_val_) { + __union_.__val_ = std::move(__rhs.__union_.__val_); + } else if (__has_val_) { + __reinit_expected(__union_.__unex_, __union_.__val_, std::move(__rhs.__union_.__unex_)); + } else if (__rhs.__has_val_) { + __reinit_expected(__union_.__val_, __union_.__unex_, std::move(__rhs.__union_.__val_)); + } else { + __union_.__unex_ = std::move(__rhs.__union_.__unex_); + } + // note: only reached if no exception+rollback was done inside __reinit_expected + __has_val_ = __rhs.__has_val_; + return *this; + } + + template + _LIBCPP_HIDE_FROM_ABI constexpr expected& operator=(_Up&& __v) + requires(!is_same_v> && + !__is_std_unexpected>::value && + is_constructible_v<_Tp, _Up> && + is_assignable_v<_Tp&, _Up> && + (is_nothrow_constructible_v<_Tp, _Up> || + is_nothrow_move_constructible_v<_Tp> || + is_nothrow_move_constructible_v<_Err>)) + { + if (__has_val_) { + __union_.__val_ = std::forward<_Up>(__v); + } else { + __reinit_expected(__union_.__val_, __union_.__unex_, std::forward<_Up>(__v)); + __has_val_ = true; + } + return *this; + } + +private: + template + static constexpr bool __can_assign_from_unexpected = + _And< is_constructible<_Err, _OtherErrQual>, + is_assignable<_Err&, _OtherErrQual>, + _Lazy<_Or, + is_nothrow_constructible<_Err, _OtherErrQual>, + is_nothrow_move_constructible<_Tp>, + is_nothrow_move_constructible<_Err>> >::value; + +public: + template + requires(__can_assign_from_unexpected) + _LIBCPP_HIDE_FROM_ABI constexpr expected& operator=(const unexpected<_OtherErr>& __un) { + if (__has_val_) { + __reinit_expected(__union_.__unex_, __union_.__val_, __un.error()); + __has_val_ = false; + } else { + __union_.__unex_ = __un.error(); + } + return *this; + } + + template + requires(__can_assign_from_unexpected<_OtherErr>) + _LIBCPP_HIDE_FROM_ABI constexpr expected& operator=(unexpected<_OtherErr>&& __un) { + if (__has_val_) { + __reinit_expected(__union_.__unex_, __union_.__val_, std::move(__un.error())); + __has_val_ = false; + } else { + __union_.__unex_ = std::move(__un.error()); + } + return *this; + } + + template + requires is_nothrow_constructible_v<_Tp, _Args...> + _LIBCPP_HIDE_FROM_ABI constexpr _Tp& emplace(_Args&&... __args) noexcept { + if (__has_val_) { + std::destroy_at(std::addressof(__union_.__val_)); + } else { + std::destroy_at(std::addressof(__union_.__unex_)); + __has_val_ = true; + } + return *std::construct_at(std::addressof(__union_.__val_), std::forward<_Args>(__args)...); + } + + template + requires is_nothrow_constructible_v< _Tp, initializer_list<_Up>&, _Args... > + _LIBCPP_HIDE_FROM_ABI constexpr _Tp& emplace(initializer_list<_Up> __il, _Args&&... __args) noexcept { + if (__has_val_) { + std::destroy_at(std::addressof(__union_.__val_)); + } else { + std::destroy_at(std::addressof(__union_.__unex_)); + __has_val_ = true; + } + return *std::construct_at(std::addressof(__union_.__val_), __il, std::forward<_Args>(__args)...); + } + + +public: + // [expected.object.swap], swap + _LIBCPP_HIDE_FROM_ABI constexpr void swap(expected& __rhs) + noexcept(is_nothrow_move_constructible_v<_Tp> && + is_nothrow_swappable_v<_Tp> && + is_nothrow_move_constructible_v<_Err> && + is_nothrow_swappable_v<_Err>) + requires(is_swappable_v<_Tp> && + is_swappable_v<_Err> && + is_move_constructible_v<_Tp> && + is_move_constructible_v<_Err> && + (is_nothrow_move_constructible_v<_Tp> || + is_nothrow_move_constructible_v<_Err>)) + { + auto __swap_val_unex_impl = [&](expected& __with_val, expected& __with_err) { + if constexpr (is_nothrow_move_constructible_v<_Err>) { + _Err __tmp(std::move(__with_err.__union_.__unex_)); + std::destroy_at(std::addressof(__with_err.__union_.__unex_)); + __exception_guard __trans([&] { + std::construct_at(std::addressof(__with_err.__union_.__unex_), std::move(__tmp)); + }); + std::construct_at(std::addressof(__with_err.__union_.__val_), std::move(__with_val.__union_.__val_)); + __trans.__complete(); + std::destroy_at(std::addressof(__with_val.__union_.__val_)); + std::construct_at(std::addressof(__with_val.__union_.__unex_), std::move(__tmp)); + } else { + static_assert(is_nothrow_move_constructible_v<_Tp>, + "To provide strong exception guarantee, Tp has to satisfy `is_nothrow_move_constructible_v` so " + "that it can be reverted to the previous state in case an exception is thrown during swap."); + _Tp __tmp(std::move(__with_val.__union_.__val_)); + std::destroy_at(std::addressof(__with_val.__union_.__val_)); + __exception_guard __trans([&] { + std::construct_at(std::addressof(__with_val.__union_.__val_), std::move(__tmp)); + }); + std::construct_at(std::addressof(__with_val.__union_.__unex_), std::move(__with_err.__union_.__unex_)); + __trans.__complete(); + std::destroy_at(std::addressof(__with_err.__union_.__unex_)); + std::construct_at(std::addressof(__with_err.__union_.__val_), std::move(__tmp)); + } + __with_val.__has_val_ = false; + __with_err.__has_val_ = true; + }; + + if (__has_val_) { + if (__rhs.__has_val_) { + using std::swap; + swap(__union_.__val_, __rhs.__union_.__val_); + } else { + __swap_val_unex_impl(*this, __rhs); + } + } else { + if (__rhs.__has_val_) { + __swap_val_unex_impl(__rhs, *this); + } else { + using std::swap; + swap(__union_.__unex_, __rhs.__union_.__unex_); + } + } + } + + _LIBCPP_HIDE_FROM_ABI friend constexpr void swap(expected& __x, expected& __y) + noexcept(noexcept(__x.swap(__y))) + requires requires { __x.swap(__y); } + { + __x.swap(__y); + } + + // [expected.object.obs], observers + _LIBCPP_HIDE_FROM_ABI constexpr const _Tp* operator->() const noexcept { + _LIBCPP_ASSERT(__has_val_, "expected::operator-> requires the expected to contain a value"); + return std::addressof(__union_.__val_); + } + + _LIBCPP_HIDE_FROM_ABI constexpr _Tp* operator->() noexcept { + _LIBCPP_ASSERT(__has_val_, "expected::operator-> requires the expected to contain a value"); + return std::addressof(__union_.__val_); + } + + _LIBCPP_HIDE_FROM_ABI constexpr const _Tp& operator*() const& noexcept { + _LIBCPP_ASSERT(__has_val_, "expected::operator* requires the expected to contain a value"); + return __union_.__val_; + } + + _LIBCPP_HIDE_FROM_ABI constexpr _Tp& operator*() & noexcept { + _LIBCPP_ASSERT(__has_val_, "expected::operator* requires the expected to contain a value"); + return __union_.__val_; + } + + _LIBCPP_HIDE_FROM_ABI constexpr const _Tp&& operator*() const&& noexcept { + _LIBCPP_ASSERT(__has_val_, "expected::operator* requires the expected to contain a value"); + return std::move(__union_.__val_); + } + + _LIBCPP_HIDE_FROM_ABI constexpr _Tp&& operator*() && noexcept { + _LIBCPP_ASSERT(__has_val_, "expected::operator* requires the expected to contain a value"); + return std::move(__union_.__val_); + } + + _LIBCPP_HIDE_FROM_ABI constexpr explicit operator bool() const noexcept { return __has_val_; } + + _LIBCPP_HIDE_FROM_ABI constexpr bool has_value() const noexcept { return __has_val_; } + + _LIBCPP_HIDE_FROM_ABI constexpr const _Tp& value() const& { + if (!__has_val_) { + __expected::__throw_bad_expected_access<_Err>(__union_.__unex_); + } + return __union_.__val_; + } + + _LIBCPP_HIDE_FROM_ABI constexpr _Tp& value() & { + if (!__has_val_) { + __expected::__throw_bad_expected_access<_Err>(__union_.__unex_); + } + return __union_.__val_; + } + + _LIBCPP_HIDE_FROM_ABI constexpr const _Tp&& value() const&& { + if (!__has_val_) { + __expected::__throw_bad_expected_access<_Err>(std::move(__union_.__unex_)); + } + return std::move(__union_.__val_); + } + + _LIBCPP_HIDE_FROM_ABI constexpr _Tp&& value() && { + if (!__has_val_) { + __expected::__throw_bad_expected_access<_Err>(std::move(__union_.__unex_)); + } + return std::move(__union_.__val_); + } + + _LIBCPP_HIDE_FROM_ABI constexpr const _Err& error() const& noexcept { + _LIBCPP_ASSERT(!__has_val_, "expected::error requires the expected to contain an error"); + return __union_.__unex_; + } + + _LIBCPP_HIDE_FROM_ABI constexpr _Err& error() & noexcept { + _LIBCPP_ASSERT(!__has_val_, "expected::error requires the expected to contain an error"); + return __union_.__unex_; + } + + _LIBCPP_HIDE_FROM_ABI constexpr const _Err&& error() const&& noexcept { + _LIBCPP_ASSERT(!__has_val_, "expected::error requires the expected to contain an error"); + return std::move(__union_.__unex_); + } + + _LIBCPP_HIDE_FROM_ABI constexpr _Err&& error() && noexcept { + _LIBCPP_ASSERT(!__has_val_, "expected::error requires the expected to contain an error"); + return std::move(__union_.__unex_); + } + + template + _LIBCPP_HIDE_FROM_ABI constexpr _Tp value_or(_Up&& __v) const& { + static_assert(is_copy_constructible_v<_Tp>, "value_type has to be copy constructible"); + static_assert(is_convertible_v<_Up, _Tp>, "argument has to be convertible to value_type"); + return __has_val_ ? __union_.__val_ : static_cast<_Tp>(std::forward<_Up>(__v)); + } + + template + _LIBCPP_HIDE_FROM_ABI constexpr _Tp value_or(_Up&& __v) && { + static_assert(is_move_constructible_v<_Tp>, "value_type has to be move constructible"); + static_assert(is_convertible_v<_Up, _Tp>, "argument has to be convertible to value_type"); + return __has_val_ ? std::move(__union_.__val_) : static_cast<_Tp>(std::forward<_Up>(__v)); + } + + // [expected.object.eq], equality operators + template + requires(!is_void_v<_T2>) + _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const expected& __x, const expected<_T2, _E2>& __y) { + if (__x.__has_val_ != __y.__has_val_) { + return false; + } else { + if (__x.__has_val_) { + return __x.__union_.__val_ == __y.__union_.__val_; + } else { + return __x.__union_.__unex_ == __y.__union_.__unex_; + } + } + } + + template + _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const expected& __x, const _T2& __v) { + return __x.__has_val_ && static_cast(__x.__union_.__val_ == __v); + } + + template + _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const expected& __x, const unexpected<_E2>& __e) { + return !__x.__has_val_ && static_cast(__x.__union_.__unex_ == __e.error()); + } + +private: + struct __empty_t {}; + // use named union because [[no_unique_address]] cannot be applied to an unnamed union + _LIBCPP_NO_UNIQUE_ADDRESS union __union_t { + _LIBCPP_HIDE_FROM_ABI constexpr __union_t() : __empty_() {} + + _LIBCPP_HIDE_FROM_ABI constexpr ~__union_t() + requires(is_trivially_destructible_v<_Tp> && is_trivially_destructible_v<_Err>) + = default; + + // the expected's destructor handles this + _LIBCPP_HIDE_FROM_ABI constexpr ~__union_t() + requires(!is_trivially_destructible_v<_Tp> || !is_trivially_destructible_v<_Err>) + {} + + _LIBCPP_NO_UNIQUE_ADDRESS __empty_t __empty_; + _LIBCPP_NO_UNIQUE_ADDRESS _Tp __val_; + _LIBCPP_NO_UNIQUE_ADDRESS _Err __unex_; + } __union_; + + bool __has_val_; +}; + +template + requires is_void_v<_Tp> +class expected<_Tp, _Err> { + static_assert(__valid_std_unexpected<_Err>::value, + "[expected.void.general] A program that instantiates expected with a E that is not a " + "valid argument for unexpected is ill-formed"); + + template + friend class expected; + + template + using __can_convert = + _And< is_void<_Up>, + is_constructible<_Err, _OtherErrQual>, + _Not, expected<_Up, _OtherErr>&>>, + _Not, expected<_Up, _OtherErr>>>, + _Not, const expected<_Up, _OtherErr>&>>, + _Not, const expected<_Up, _OtherErr>>>>; + +public: + using value_type = _Tp; + using error_type = _Err; + using unexpected_type = unexpected<_Err>; + + template + using rebind = expected<_Up, error_type>; + + // [expected.void.ctor], constructors + _LIBCPP_HIDE_FROM_ABI constexpr expected() noexcept : __has_val_(true) {} + + _LIBCPP_HIDE_FROM_ABI constexpr expected(const expected&) = delete; + + _LIBCPP_HIDE_FROM_ABI constexpr expected(const expected&) + requires(is_copy_constructible_v<_Err> && is_trivially_copy_constructible_v<_Err>) + = default; + + _LIBCPP_HIDE_FROM_ABI constexpr expected(const expected& __rhs) + noexcept(is_nothrow_copy_constructible_v<_Err>) // strengthened + requires(is_copy_constructible_v<_Err> && !is_trivially_copy_constructible_v<_Err>) + : __has_val_(__rhs.__has_val_) { + if (!__rhs.__has_val_) { + std::construct_at(std::addressof(__union_.__unex_), __rhs.__union_.__unex_); + } + } + + _LIBCPP_HIDE_FROM_ABI constexpr expected(expected&&) + requires(is_move_constructible_v<_Err> && is_trivially_move_constructible_v<_Err>) + = default; + + _LIBCPP_HIDE_FROM_ABI constexpr expected(expected&& __rhs) + noexcept(is_nothrow_move_constructible_v<_Err>) + requires(is_move_constructible_v<_Err> && !is_trivially_move_constructible_v<_Err>) + : __has_val_(__rhs.__has_val_) { + if (!__rhs.__has_val_) { + std::construct_at(std::addressof(__union_.__unex_), std::move(__rhs.__union_.__unex_)); + } + } + + template + requires __can_convert<_Up, _OtherErr, const _OtherErr&>::value + _LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v) + expected(const expected<_Up, _OtherErr>& __rhs) + noexcept(is_nothrow_constructible_v<_Err, const _OtherErr&>) // strengthened + : __has_val_(__rhs.__has_val_) { + if (!__rhs.__has_val_) { + std::construct_at(std::addressof(__union_.__unex_), __rhs.__union_.__unex_); + } + } + + template + requires __can_convert<_Up, _OtherErr, _OtherErr>::value + _LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v<_OtherErr, _Err>) + expected(expected<_Up, _OtherErr>&& __rhs) + noexcept(is_nothrow_constructible_v<_Err, _OtherErr>) // strengthened + : __has_val_(__rhs.__has_val_) { + if (!__rhs.__has_val_) { + std::construct_at(std::addressof(__union_.__unex_), std::move(__rhs.__union_.__unex_)); + } + } + + template + requires is_constructible_v<_Err, const _OtherErr&> + _LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v) + expected(const unexpected<_OtherErr>& __unex) + noexcept(is_nothrow_constructible_v<_Err, const _OtherErr&>) // strengthened + : __has_val_(false) { + std::construct_at(std::addressof(__union_.__unex_), __unex.error()); + } + + template + requires is_constructible_v<_Err, _OtherErr> + _LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v<_OtherErr, _Err>) + expected(unexpected<_OtherErr>&& __unex) + noexcept(is_nothrow_constructible_v<_Err, _OtherErr>) // strengthened + : __has_val_(false) { + std::construct_at(std::addressof(__union_.__unex_), std::move(__unex.error())); + } + + _LIBCPP_HIDE_FROM_ABI constexpr explicit expected(in_place_t) noexcept : __has_val_(true) {} + + template + requires is_constructible_v<_Err, _Args...> + _LIBCPP_HIDE_FROM_ABI constexpr explicit expected(unexpect_t, _Args&&... __args) + noexcept(is_nothrow_constructible_v<_Err, _Args...>) // strengthened + : __has_val_(false) { + std::construct_at(std::addressof(__union_.__unex_), std::forward<_Args>(__args)...); + } + + template + requires is_constructible_v< _Err, initializer_list<_Up>&, _Args... > + _LIBCPP_HIDE_FROM_ABI constexpr explicit expected(unexpect_t, initializer_list<_Up> __il, _Args&&... __args) + noexcept(is_nothrow_constructible_v<_Err, initializer_list<_Up>&, _Args...>) // strengthened + : __has_val_(false) { + std::construct_at(std::addressof(__union_.__unex_), __il, std::forward<_Args>(__args)...); + } + + // [expected.void.dtor], destructor + + _LIBCPP_HIDE_FROM_ABI constexpr ~expected() + requires is_trivially_destructible_v<_Err> + = default; + + _LIBCPP_HIDE_FROM_ABI constexpr ~expected() + requires(!is_trivially_destructible_v<_Err>) + { + if (!__has_val_) { + std::destroy_at(std::addressof(__union_.__unex_)); + } + } + + // [expected.void.assign], assignment + + _LIBCPP_HIDE_FROM_ABI constexpr expected& operator=(const expected&) = delete; + + _LIBCPP_HIDE_FROM_ABI constexpr expected& operator=(const expected& __rhs) + noexcept(is_nothrow_copy_assignable_v<_Err> && is_nothrow_copy_constructible_v<_Err>) // strengthened + requires(is_copy_assignable_v<_Err> && is_copy_constructible_v<_Err>) + { + if (__has_val_) { + if (!__rhs.__has_val_) { + std::construct_at(std::addressof(__union_.__unex_), __rhs.__union_.__unex_); + __has_val_ = false; + } + } else { + if (__rhs.__has_val_) { + std::destroy_at(std::addressof(__union_.__unex_)); + __has_val_ = true; + } else { + __union_.__unex_ = __rhs.__union_.__unex_; + } + } + return *this; + } + + _LIBCPP_HIDE_FROM_ABI constexpr expected& operator=(expected&&) = delete; + + _LIBCPP_HIDE_FROM_ABI constexpr expected& operator=(expected&& __rhs) + noexcept(is_nothrow_move_assignable_v<_Err> && + is_nothrow_move_constructible_v<_Err>) + requires(is_move_assignable_v<_Err> && + is_move_constructible_v<_Err>) + { + if (__has_val_) { + if (!__rhs.__has_val_) { + std::construct_at(std::addressof(__union_.__unex_), std::move(__rhs.__union_.__unex_)); + __has_val_ = false; + } + } else { + if (__rhs.__has_val_) { + std::destroy_at(std::addressof(__union_.__unex_)); + __has_val_ = true; + } else { + __union_.__unex_ = std::move(__rhs.__union_.__unex_); + } + } + return *this; + } + + template + requires(is_constructible_v<_Err, const _OtherErr&> && is_assignable_v<_Err&, const _OtherErr&>) + _LIBCPP_HIDE_FROM_ABI constexpr expected& operator=(const unexpected<_OtherErr>& __un) { + if (__has_val_) { + std::construct_at(std::addressof(__union_.__unex_), __un.error()); + __has_val_ = false; + } else { + __union_.__unex_ = __un.error(); + } + return *this; + } + + template + requires(is_constructible_v<_Err, _OtherErr> && is_assignable_v<_Err&, _OtherErr>) + _LIBCPP_HIDE_FROM_ABI constexpr expected& operator=(unexpected<_OtherErr>&& __un) { + if (__has_val_) { + std::construct_at(std::addressof(__union_.__unex_), std::move(__un.error())); + __has_val_ = false; + } else { + __union_.__unex_ = std::move(__un.error()); + } + return *this; + } + + _LIBCPP_HIDE_FROM_ABI constexpr void emplace() noexcept { + if (!__has_val_) { + std::destroy_at(std::addressof(__union_.__unex_)); + __has_val_ = true; + } + } + + // [expected.void.swap], swap + _LIBCPP_HIDE_FROM_ABI constexpr void swap(expected& __rhs) + noexcept(is_nothrow_move_constructible_v<_Err> && is_nothrow_swappable_v<_Err>) + requires(is_swappable_v<_Err> && is_move_constructible_v<_Err>) + { + auto __swap_val_unex_impl = [&](expected& __with_val, expected& __with_err) { + std::construct_at(std::addressof(__with_val.__union_.__unex_), std::move(__with_err.__union_.__unex_)); + std::destroy_at(std::addressof(__with_err.__union_.__unex_)); + __with_val.__has_val_ = false; + __with_err.__has_val_ = true; + }; + + if (__has_val_) { + if (!__rhs.__has_val_) { + __swap_val_unex_impl(*this, __rhs); + } + } else { + if (__rhs.__has_val_) { + __swap_val_unex_impl(__rhs, *this); + } else { + using std::swap; + swap(__union_.__unex_, __rhs.__union_.__unex_); + } + } + } + + _LIBCPP_HIDE_FROM_ABI friend constexpr void swap(expected& __x, expected& __y) + noexcept(noexcept(__x.swap(__y))) + requires requires { __x.swap(__y); } + { + __x.swap(__y); + } + + // [expected.void.obs], observers + _LIBCPP_HIDE_FROM_ABI constexpr explicit operator bool() const noexcept { return __has_val_; } + + _LIBCPP_HIDE_FROM_ABI constexpr bool has_value() const noexcept { return __has_val_; } + + _LIBCPP_HIDE_FROM_ABI constexpr void operator*() const noexcept { + _LIBCPP_ASSERT(__has_val_, "expected::operator* requires the expected to contain a value"); + } + + _LIBCPP_HIDE_FROM_ABI constexpr void value() const& { + if (!__has_val_) { + __expected::__throw_bad_expected_access<_Err>(__union_.__unex_); + } + } + + _LIBCPP_HIDE_FROM_ABI constexpr void value() && { + if (!__has_val_) { + __expected::__throw_bad_expected_access<_Err>(std::move(__union_.__unex_)); + } + } + + _LIBCPP_HIDE_FROM_ABI constexpr const _Err& error() const& noexcept { + _LIBCPP_ASSERT(!__has_val_, "expected::error requires the expected to contain an error"); + return __union_.__unex_; + } + + _LIBCPP_HIDE_FROM_ABI constexpr _Err& error() & noexcept { + _LIBCPP_ASSERT(!__has_val_, "expected::error requires the expected to contain an error"); + return __union_.__unex_; + } + + _LIBCPP_HIDE_FROM_ABI constexpr const _Err&& error() const&& noexcept { + _LIBCPP_ASSERT(!__has_val_, "expected::error requires the expected to contain an error"); + return std::move(__union_.__unex_); + } + + _LIBCPP_HIDE_FROM_ABI constexpr _Err&& error() && noexcept { + _LIBCPP_ASSERT(!__has_val_, "expected::error requires the expected to contain an error"); + return std::move(__union_.__unex_); + } + + // [expected.void.eq], equality operators + template + requires is_void_v<_T2> + _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const expected& __x, const expected<_T2, _E2>& __y) { + if (__x.__has_val_ != __y.__has_val_) { + return false; + } else { + return __x.__has_val_ || static_cast(__x.__union_.__unex_ == __y.__union_.__unex_); + } + } + + template + _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const expected& __x, const unexpected<_E2>& __y) { + return !__x.__has_val_ && static_cast(__x.__union_.__unex_ == __y.error()); + } + +private: + struct __empty_t {}; + // use named union because [[no_unique_address]] cannot be applied to an unnamed union + _LIBCPP_NO_UNIQUE_ADDRESS union __union_t { + _LIBCPP_HIDE_FROM_ABI constexpr __union_t() : __empty_() {} + + _LIBCPP_HIDE_FROM_ABI constexpr ~__union_t() + requires(is_trivially_destructible_v<_Err>) + = default; + + // the expected's destructor handles this + _LIBCPP_HIDE_FROM_ABI constexpr ~__union_t() + requires(!is_trivially_destructible_v<_Err>) + {} + + _LIBCPP_NO_UNIQUE_ADDRESS __empty_t __empty_; + _LIBCPP_NO_UNIQUE_ADDRESS _Err __unex_; + } __union_; + + bool __has_val_; +}; + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER >= 23 + +#endif // _LIBCPP___EXPECTED_EXPECTED_H diff --git a/app/src/main/cpp/libcxx/include/__expected/unexpect.h b/app/src/main/cpp/libcxx/include/__expected/unexpect.h new file mode 100644 index 0000000..20bafc1 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__expected/unexpect.h @@ -0,0 +1,32 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +#ifndef _LIBCPP___EXPECTED_UNEXPECT_H +#define _LIBCPP___EXPECTED_UNEXPECT_H + +#include <__config> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if _LIBCPP_STD_VER >= 23 + +_LIBCPP_BEGIN_NAMESPACE_STD + +struct unexpect_t { + _LIBCPP_HIDE_FROM_ABI explicit unexpect_t() = default; +}; + +inline constexpr unexpect_t unexpect{}; + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER >= 23 + +#endif // _LIBCPP___EXPECTED_UNEXPECT_H diff --git a/app/src/main/cpp/libcxx/include/__expected/unexpected.h b/app/src/main/cpp/libcxx/include/__expected/unexpected.h new file mode 100644 index 0000000..075963a --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__expected/unexpected.h @@ -0,0 +1,122 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +#ifndef _LIBCPP___EXPECTED_UNEXPECTED_H +#define _LIBCPP___EXPECTED_UNEXPECTED_H + +#include <__config> +#include <__type_traits/conjunction.h> +#include <__type_traits/is_array.h> +#include <__type_traits/is_const.h> +#include <__type_traits/is_constructible.h> +#include <__type_traits/is_nothrow_constructible.h> +#include <__type_traits/is_object.h> +#include <__type_traits/is_same.h> +#include <__type_traits/is_swappable.h> +#include <__type_traits/is_volatile.h> +#include <__type_traits/negation.h> +#include <__type_traits/remove_cvref.h> +#include <__utility/forward.h> +#include <__utility/in_place.h> +#include <__utility/move.h> +#include <__utility/swap.h> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if _LIBCPP_STD_VER >= 23 + +_LIBCPP_BEGIN_NAMESPACE_STD + +template +class unexpected; + +template +struct __is_std_unexpected : false_type {}; + +template +struct __is_std_unexpected> : true_type {}; + +template +using __valid_std_unexpected = _BoolConstant< // + is_object_v<_Tp> && // + !is_array_v<_Tp> && // + !__is_std_unexpected<_Tp>::value && // + !is_const_v<_Tp> && // + !is_volatile_v<_Tp> // + >; + +template +class unexpected { + static_assert(__valid_std_unexpected<_Err>::value, + "[expected.un.general] states a program that instantiates std::unexpected for a non-object type, an " + "array type, a specialization of unexpected, or a cv-qualified type is ill-formed."); + +public: + _LIBCPP_HIDE_FROM_ABI constexpr unexpected(const unexpected&) = default; + _LIBCPP_HIDE_FROM_ABI constexpr unexpected(unexpected&&) = default; + + template + requires(!is_same_v, unexpected> && // + !is_same_v, in_place_t> && // + is_constructible_v<_Err, _Error>) + _LIBCPP_HIDE_FROM_ABI constexpr explicit unexpected(_Error&& __error) // + noexcept(is_nothrow_constructible_v<_Err, _Error>) // strengthened + : __unex_(std::forward<_Error>(__error)) {} + + template + requires is_constructible_v<_Err, _Args...> + _LIBCPP_HIDE_FROM_ABI constexpr explicit unexpected(in_place_t, _Args&&... __args) // + noexcept(is_nothrow_constructible_v<_Err, _Args...>) // strengthened + : __unex_(std::forward<_Args>(__args)...) {} + + template + requires is_constructible_v<_Err, initializer_list<_Up>&, _Args...> + _LIBCPP_HIDE_FROM_ABI constexpr explicit unexpected(in_place_t, initializer_list<_Up> __il, _Args&&... __args) // + noexcept(is_nothrow_constructible_v<_Err, initializer_list<_Up>&, _Args...>) // strengthened + : __unex_(__il, std::forward<_Args>(__args)...) {} + + _LIBCPP_HIDE_FROM_ABI constexpr unexpected& operator=(const unexpected&) = default; + _LIBCPP_HIDE_FROM_ABI constexpr unexpected& operator=(unexpected&&) = default; + + _LIBCPP_HIDE_FROM_ABI constexpr const _Err& error() const& noexcept { return __unex_; } + _LIBCPP_HIDE_FROM_ABI constexpr _Err& error() & noexcept { return __unex_; } + _LIBCPP_HIDE_FROM_ABI constexpr const _Err&& error() const&& noexcept { return std::move(__unex_); } + _LIBCPP_HIDE_FROM_ABI constexpr _Err&& error() && noexcept { return std::move(__unex_); } + + _LIBCPP_HIDE_FROM_ABI constexpr void swap(unexpected& __other) noexcept(is_nothrow_swappable_v<_Err>) { + static_assert(is_swappable_v<_Err>, "unexpected::swap requires is_swappable_v to be true"); + using std::swap; + swap(__unex_, __other.__unex_); + } + + _LIBCPP_HIDE_FROM_ABI friend constexpr void swap(unexpected& __x, unexpected& __y) noexcept(noexcept(__x.swap(__y))) + requires is_swappable_v<_Err> + { + __x.swap(__y); + } + + template + _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const unexpected& __x, const unexpected<_Err2>& __y) { + return __x.__unex_ == __y.__unex_; + } + +private: + _Err __unex_; +}; + +template +unexpected(_Err) -> unexpected<_Err>; + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER >= 23 + +#endif // _LIBCPP___EXPECTED_UNEXPECTED_H diff --git a/app/src/main/cpp/libcxx/include/__filesystem/copy_options.h b/app/src/main/cpp/libcxx/include/__filesystem/copy_options.h new file mode 100644 index 0000000..96c7535 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__filesystem/copy_options.h @@ -0,0 +1,84 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___FILESYSTEM_COPY_OPTIONS_H +#define _LIBCPP___FILESYSTEM_COPY_OPTIONS_H + +#include <__availability> +#include <__config> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#ifndef _LIBCPP_CXX03_LANG + +_LIBCPP_BEGIN_NAMESPACE_FILESYSTEM + +_LIBCPP_AVAILABILITY_FILESYSTEM_PUSH + +enum class _LIBCPP_ENUM_VIS copy_options : unsigned short { + none = 0, + skip_existing = 1, + overwrite_existing = 2, + update_existing = 4, + recursive = 8, + copy_symlinks = 16, + skip_symlinks = 32, + directories_only = 64, + create_symlinks = 128, + create_hard_links = 256, + __in_recursive_copy = 512, +}; + +_LIBCPP_INLINE_VISIBILITY +inline constexpr copy_options operator&(copy_options __lhs, copy_options __rhs) { + return static_cast(static_cast(__lhs) & + static_cast(__rhs)); +} + +_LIBCPP_INLINE_VISIBILITY +inline constexpr copy_options operator|(copy_options __lhs, copy_options __rhs) { + return static_cast(static_cast(__lhs) | + static_cast(__rhs)); +} + +_LIBCPP_INLINE_VISIBILITY +inline constexpr copy_options operator^(copy_options __lhs, copy_options __rhs) { + return static_cast(static_cast(__lhs) ^ + static_cast(__rhs)); +} + +_LIBCPP_INLINE_VISIBILITY +inline constexpr copy_options operator~(copy_options __lhs) { + return static_cast(~static_cast(__lhs)); +} + +_LIBCPP_INLINE_VISIBILITY +inline copy_options& operator&=(copy_options& __lhs, copy_options __rhs) { + return __lhs = __lhs & __rhs; +} + +_LIBCPP_INLINE_VISIBILITY +inline copy_options& operator|=(copy_options& __lhs, copy_options __rhs) { + return __lhs = __lhs | __rhs; +} + +_LIBCPP_INLINE_VISIBILITY +inline copy_options& operator^=(copy_options& __lhs, copy_options __rhs) { + return __lhs = __lhs ^ __rhs; +} + +_LIBCPP_AVAILABILITY_FILESYSTEM_POP + +_LIBCPP_END_NAMESPACE_FILESYSTEM + +#endif // _LIBCPP_CXX03_LANG + +#endif // _LIBCPP___FILESYSTEM_COPY_OPTIONS_H diff --git a/app/src/main/cpp/libcxx/include/__filesystem/directory_entry.h b/app/src/main/cpp/libcxx/include/__filesystem/directory_entry.h new file mode 100644 index 0000000..b17eaaa --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__filesystem/directory_entry.h @@ -0,0 +1,527 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___FILESYSTEM_DIRECTORY_ENTRY_H +#define _LIBCPP___FILESYSTEM_DIRECTORY_ENTRY_H + +#include <__availability> +#include <__chrono/time_point.h> +#include <__config> +#include <__errc> +#include <__filesystem/file_status.h> +#include <__filesystem/file_time_type.h> +#include <__filesystem/file_type.h> +#include <__filesystem/filesystem_error.h> +#include <__filesystem/operations.h> +#include <__filesystem/path.h> +#include <__filesystem/perms.h> +#include <__utility/unreachable.h> +#include +#include +#include +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + +#ifndef _LIBCPP_CXX03_LANG + +_LIBCPP_BEGIN_NAMESPACE_FILESYSTEM + +_LIBCPP_AVAILABILITY_FILESYSTEM_PUSH + + +class directory_entry { + typedef _VSTD_FS::path _Path; + +public: + // constructors and destructors + directory_entry() noexcept = default; + directory_entry(directory_entry const&) = default; + directory_entry(directory_entry&&) noexcept = default; + + _LIBCPP_INLINE_VISIBILITY + explicit directory_entry(_Path const& __p) : __p_(__p) { + error_code __ec; + __refresh(&__ec); + } + + _LIBCPP_INLINE_VISIBILITY + directory_entry(_Path const& __p, error_code& __ec) : __p_(__p) { + __refresh(&__ec); + } + + ~directory_entry() {} + + directory_entry& operator=(directory_entry const&) = default; + directory_entry& operator=(directory_entry&&) noexcept = default; + + _LIBCPP_INLINE_VISIBILITY + void assign(_Path const& __p) { + __p_ = __p; + error_code __ec; + __refresh(&__ec); + } + + _LIBCPP_INLINE_VISIBILITY + void assign(_Path const& __p, error_code& __ec) { + __p_ = __p; + __refresh(&__ec); + } + + _LIBCPP_INLINE_VISIBILITY + void replace_filename(_Path const& __p) { + __p_.replace_filename(__p); + error_code __ec; + __refresh(&__ec); + } + + _LIBCPP_INLINE_VISIBILITY + void replace_filename(_Path const& __p, error_code& __ec) { + __p_ = __p_.parent_path() / __p; + __refresh(&__ec); + } + + _LIBCPP_INLINE_VISIBILITY + void refresh() { __refresh(); } + + _LIBCPP_INLINE_VISIBILITY + void refresh(error_code& __ec) noexcept { __refresh(&__ec); } + + _LIBCPP_INLINE_VISIBILITY + _Path const& path() const noexcept { return __p_; } + + _LIBCPP_INLINE_VISIBILITY + operator const _Path&() const noexcept { return __p_; } + + _LIBCPP_INLINE_VISIBILITY + bool exists() const { return _VSTD_FS::exists(file_status{__get_ft()}); } + + _LIBCPP_INLINE_VISIBILITY + bool exists(error_code& __ec) const noexcept { + return _VSTD_FS::exists(file_status{__get_ft(&__ec)}); + } + + _LIBCPP_INLINE_VISIBILITY + bool is_block_file() const { return __get_ft() == file_type::block; } + + _LIBCPP_INLINE_VISIBILITY + bool is_block_file(error_code& __ec) const noexcept { + return __get_ft(&__ec) == file_type::block; + } + + _LIBCPP_INLINE_VISIBILITY + bool is_character_file() const { return __get_ft() == file_type::character; } + + _LIBCPP_INLINE_VISIBILITY + bool is_character_file(error_code& __ec) const noexcept { + return __get_ft(&__ec) == file_type::character; + } + + _LIBCPP_INLINE_VISIBILITY + bool is_directory() const { return __get_ft() == file_type::directory; } + + _LIBCPP_INLINE_VISIBILITY + bool is_directory(error_code& __ec) const noexcept { + return __get_ft(&__ec) == file_type::directory; + } + + _LIBCPP_INLINE_VISIBILITY + bool is_fifo() const { return __get_ft() == file_type::fifo; } + + _LIBCPP_INLINE_VISIBILITY + bool is_fifo(error_code& __ec) const noexcept { + return __get_ft(&__ec) == file_type::fifo; + } + + _LIBCPP_INLINE_VISIBILITY + bool is_other() const { return _VSTD_FS::is_other(file_status{__get_ft()}); } + + _LIBCPP_INLINE_VISIBILITY + bool is_other(error_code& __ec) const noexcept { + return _VSTD_FS::is_other(file_status{__get_ft(&__ec)}); + } + + _LIBCPP_INLINE_VISIBILITY + bool is_regular_file() const { return __get_ft() == file_type::regular; } + + _LIBCPP_INLINE_VISIBILITY + bool is_regular_file(error_code& __ec) const noexcept { + return __get_ft(&__ec) == file_type::regular; + } + + _LIBCPP_INLINE_VISIBILITY + bool is_socket() const { return __get_ft() == file_type::socket; } + + _LIBCPP_INLINE_VISIBILITY + bool is_socket(error_code& __ec) const noexcept { + return __get_ft(&__ec) == file_type::socket; + } + + _LIBCPP_INLINE_VISIBILITY + bool is_symlink() const { return __get_sym_ft() == file_type::symlink; } + + _LIBCPP_INLINE_VISIBILITY + bool is_symlink(error_code& __ec) const noexcept { + return __get_sym_ft(&__ec) == file_type::symlink; + } + _LIBCPP_INLINE_VISIBILITY + uintmax_t file_size() const { return __get_size(); } + + _LIBCPP_INLINE_VISIBILITY + uintmax_t file_size(error_code& __ec) const noexcept { + return __get_size(&__ec); + } + + _LIBCPP_INLINE_VISIBILITY + uintmax_t hard_link_count() const { return __get_nlink(); } + + _LIBCPP_INLINE_VISIBILITY + uintmax_t hard_link_count(error_code& __ec) const noexcept { + return __get_nlink(&__ec); + } + + _LIBCPP_INLINE_VISIBILITY + file_time_type last_write_time() const { return __get_write_time(); } + + _LIBCPP_INLINE_VISIBILITY + file_time_type last_write_time(error_code& __ec) const noexcept { + return __get_write_time(&__ec); + } + + _LIBCPP_INLINE_VISIBILITY + file_status status() const { return __get_status(); } + + _LIBCPP_INLINE_VISIBILITY + file_status status(error_code& __ec) const noexcept { + return __get_status(&__ec); + } + + _LIBCPP_INLINE_VISIBILITY + file_status symlink_status() const { return __get_symlink_status(); } + + _LIBCPP_INLINE_VISIBILITY + file_status symlink_status(error_code& __ec) const noexcept { + return __get_symlink_status(&__ec); + } + + + _LIBCPP_INLINE_VISIBILITY + bool operator==(directory_entry const& __rhs) const noexcept { + return __p_ == __rhs.__p_; + } + +#if _LIBCPP_STD_VER <= 17 + _LIBCPP_INLINE_VISIBILITY + bool operator!=(directory_entry const& __rhs) const noexcept { + return __p_ != __rhs.__p_; + } + + _LIBCPP_INLINE_VISIBILITY + bool operator<(directory_entry const& __rhs) const noexcept { + return __p_ < __rhs.__p_; + } + + _LIBCPP_INLINE_VISIBILITY + bool operator<=(directory_entry const& __rhs) const noexcept { + return __p_ <= __rhs.__p_; + } + + _LIBCPP_INLINE_VISIBILITY + bool operator>(directory_entry const& __rhs) const noexcept { + return __p_ > __rhs.__p_; + } + + _LIBCPP_INLINE_VISIBILITY + bool operator>=(directory_entry const& __rhs) const noexcept { + return __p_ >= __rhs.__p_; + } + +#else // _LIBCPP_STD_VER <= 17 + + _LIBCPP_HIDE_FROM_ABI + strong_ordering operator<=>(const directory_entry& __rhs) const noexcept { + return __p_ <=> __rhs.__p_; + } + +#endif // _LIBCPP_STD_VER <= 17 + + template + _LIBCPP_INLINE_VISIBILITY + friend basic_ostream<_CharT, _Traits>& operator<<(basic_ostream<_CharT, _Traits>& __os, const directory_entry& __d) { + return __os << __d.path(); + } + +private: + friend class directory_iterator; + friend class recursive_directory_iterator; + friend class _LIBCPP_HIDDEN __dir_stream; + + enum _CacheType : unsigned char { + _Empty, + _IterSymlink, + _IterNonSymlink, + _RefreshSymlink, + _RefreshSymlinkUnresolved, + _RefreshNonSymlink + }; + + struct __cached_data { + uintmax_t __size_; + uintmax_t __nlink_; + file_time_type __write_time_; + perms __sym_perms_; + perms __non_sym_perms_; + file_type __type_; + _CacheType __cache_type_; + + _LIBCPP_INLINE_VISIBILITY + __cached_data() noexcept { __reset(); } + + _LIBCPP_INLINE_VISIBILITY + void __reset() { + __cache_type_ = _Empty; + __type_ = file_type::none; + __sym_perms_ = __non_sym_perms_ = perms::unknown; + __size_ = __nlink_ = uintmax_t(-1); + __write_time_ = file_time_type::min(); + } + }; + + _LIBCPP_INLINE_VISIBILITY + static __cached_data __create_iter_result(file_type __ft) { + __cached_data __data; + __data.__type_ = __ft; + __data.__cache_type_ = [&]() { + switch (__ft) { + case file_type::none: + return _Empty; + case file_type::symlink: + return _IterSymlink; + default: + return _IterNonSymlink; + } + }(); + return __data; + } + + _LIBCPP_INLINE_VISIBILITY + void __assign_iter_entry(_Path&& __p, __cached_data __dt) { + __p_ = _VSTD::move(__p); + __data_ = __dt; + } + + _LIBCPP_FUNC_VIS + error_code __do_refresh() noexcept; + + _LIBCPP_INLINE_VISIBILITY + static bool __is_dne_error(error_code const& __ec) { + if (!__ec) + return true; + switch (static_cast(__ec.value())) { + case errc::no_such_file_or_directory: + case errc::not_a_directory: + return true; + default: + return false; + } + } + + _LIBCPP_INLINE_VISIBILITY + void __handle_error(const char* __msg, error_code* __dest_ec, + error_code const& __ec, bool __allow_dne = false) const { + if (__dest_ec) { + *__dest_ec = __ec; + return; + } + if (__ec && (!__allow_dne || !__is_dne_error(__ec))) + __throw_filesystem_error(__msg, __p_, __ec); + } + + _LIBCPP_INLINE_VISIBILITY + void __refresh(error_code* __ec = nullptr) { + __handle_error("in directory_entry::refresh", __ec, __do_refresh(), + /*allow_dne*/ true); + } + + _LIBCPP_INLINE_VISIBILITY + file_type __get_sym_ft(error_code* __ec = nullptr) const { + switch (__data_.__cache_type_) { + case _Empty: + return __symlink_status(__p_, __ec).type(); + case _IterSymlink: + case _RefreshSymlink: + case _RefreshSymlinkUnresolved: + if (__ec) + __ec->clear(); + return file_type::symlink; + case _IterNonSymlink: + case _RefreshNonSymlink: + file_status __st(__data_.__type_); + if (__ec && !_VSTD_FS::exists(__st)) + *__ec = make_error_code(errc::no_such_file_or_directory); + else if (__ec) + __ec->clear(); + return __data_.__type_; + } + __libcpp_unreachable(); + } + + _LIBCPP_INLINE_VISIBILITY + file_type __get_ft(error_code* __ec = nullptr) const { + switch (__data_.__cache_type_) { + case _Empty: + case _IterSymlink: + case _RefreshSymlinkUnresolved: + return __status(__p_, __ec).type(); + case _IterNonSymlink: + case _RefreshNonSymlink: + case _RefreshSymlink: { + file_status __st(__data_.__type_); + if (__ec && !_VSTD_FS::exists(__st)) + *__ec = make_error_code(errc::no_such_file_or_directory); + else if (__ec) + __ec->clear(); + return __data_.__type_; + } + } + __libcpp_unreachable(); + } + + _LIBCPP_INLINE_VISIBILITY + file_status __get_status(error_code* __ec = nullptr) const { + switch (__data_.__cache_type_) { + case _Empty: + case _IterNonSymlink: + case _IterSymlink: + case _RefreshSymlinkUnresolved: + return __status(__p_, __ec); + case _RefreshNonSymlink: + case _RefreshSymlink: + return file_status(__get_ft(__ec), __data_.__non_sym_perms_); + } + __libcpp_unreachable(); + } + + _LIBCPP_INLINE_VISIBILITY + file_status __get_symlink_status(error_code* __ec = nullptr) const { + switch (__data_.__cache_type_) { + case _Empty: + case _IterNonSymlink: + case _IterSymlink: + return __symlink_status(__p_, __ec); + case _RefreshNonSymlink: + return file_status(__get_sym_ft(__ec), __data_.__non_sym_perms_); + case _RefreshSymlink: + case _RefreshSymlinkUnresolved: + return file_status(__get_sym_ft(__ec), __data_.__sym_perms_); + } + __libcpp_unreachable(); + } + + _LIBCPP_INLINE_VISIBILITY + uintmax_t __get_size(error_code* __ec = nullptr) const { + switch (__data_.__cache_type_) { + case _Empty: + case _IterNonSymlink: + case _IterSymlink: + case _RefreshSymlinkUnresolved: + return _VSTD_FS::__file_size(__p_, __ec); + case _RefreshSymlink: + case _RefreshNonSymlink: { + error_code __m_ec; + file_status __st(__get_ft(&__m_ec)); + __handle_error("in directory_entry::file_size", __ec, __m_ec); + if (_VSTD_FS::exists(__st) && !_VSTD_FS::is_regular_file(__st)) { + errc __err_kind = _VSTD_FS::is_directory(__st) ? errc::is_a_directory + : errc::not_supported; + __handle_error("in directory_entry::file_size", __ec, + make_error_code(__err_kind)); + } + return __data_.__size_; + } + } + __libcpp_unreachable(); + } + + _LIBCPP_INLINE_VISIBILITY + uintmax_t __get_nlink(error_code* __ec = nullptr) const { + switch (__data_.__cache_type_) { + case _Empty: + case _IterNonSymlink: + case _IterSymlink: + case _RefreshSymlinkUnresolved: + return _VSTD_FS::__hard_link_count(__p_, __ec); + case _RefreshSymlink: + case _RefreshNonSymlink: { + error_code __m_ec; + (void)__get_ft(&__m_ec); + __handle_error("in directory_entry::hard_link_count", __ec, __m_ec); + return __data_.__nlink_; + } + } + __libcpp_unreachable(); + } + + _LIBCPP_INLINE_VISIBILITY + file_time_type __get_write_time(error_code* __ec = nullptr) const { + switch (__data_.__cache_type_) { + case _Empty: + case _IterNonSymlink: + case _IterSymlink: + case _RefreshSymlinkUnresolved: + return _VSTD_FS::__last_write_time(__p_, __ec); + case _RefreshSymlink: + case _RefreshNonSymlink: { + error_code __m_ec; + file_status __st(__get_ft(&__m_ec)); + __handle_error("in directory_entry::last_write_time", __ec, __m_ec); + if (_VSTD_FS::exists(__st) && + __data_.__write_time_ == file_time_type::min()) + __handle_error("in directory_entry::last_write_time", __ec, + make_error_code(errc::value_too_large)); + return __data_.__write_time_; + } + } + __libcpp_unreachable(); + } + +private: + _Path __p_; + __cached_data __data_; +}; + +class __dir_element_proxy { +public: + inline _LIBCPP_INLINE_VISIBILITY directory_entry operator*() { + return _VSTD::move(__elem_); + } + +private: + friend class directory_iterator; + friend class recursive_directory_iterator; + explicit __dir_element_proxy(directory_entry const& __e) : __elem_(__e) {} + __dir_element_proxy(__dir_element_proxy&& __o) + : __elem_(_VSTD::move(__o.__elem_)) {} + directory_entry __elem_; +}; + +_LIBCPP_AVAILABILITY_FILESYSTEM_POP + +_LIBCPP_END_NAMESPACE_FILESYSTEM + +#endif // _LIBCPP_CXX03_LANG + +_LIBCPP_POP_MACROS + +#endif // _LIBCPP___FILESYSTEM_DIRECTORY_ENTRY_H diff --git a/app/src/main/cpp/libcxx/include/__filesystem/directory_iterator.h b/app/src/main/cpp/libcxx/include/__filesystem/directory_iterator.h new file mode 100644 index 0000000..5ff2f01 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__filesystem/directory_iterator.h @@ -0,0 +1,165 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___FILESYSTEM_DIRECTORY_ITERATOR_H +#define _LIBCPP___FILESYSTEM_DIRECTORY_ITERATOR_H + +#include <__assert> +#include <__availability> +#include <__config> +#include <__filesystem/directory_entry.h> +#include <__filesystem/directory_options.h> +#include <__filesystem/path.h> +#include <__iterator/iterator_traits.h> +#include <__memory/shared_ptr.h> +#include <__ranges/enable_borrowed_range.h> +#include <__ranges/enable_view.h> +#include +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#ifndef _LIBCPP_CXX03_LANG + +_LIBCPP_BEGIN_NAMESPACE_FILESYSTEM + +_LIBCPP_AVAILABILITY_FILESYSTEM_PUSH + +class _LIBCPP_HIDDEN __dir_stream; +class directory_iterator { +public: + typedef directory_entry value_type; + typedef ptrdiff_t difference_type; + typedef value_type const* pointer; + typedef value_type const& reference; + typedef input_iterator_tag iterator_category; + +public: + //ctor & dtor + _LIBCPP_HIDE_FROM_ABI + directory_iterator() noexcept {} + + _LIBCPP_HIDE_FROM_ABI + explicit directory_iterator(const path& __p) + : directory_iterator(__p, nullptr) {} + + _LIBCPP_HIDE_FROM_ABI + directory_iterator(const path& __p, directory_options __opts) + : directory_iterator(__p, nullptr, __opts) {} + + _LIBCPP_HIDE_FROM_ABI + directory_iterator(const path& __p, error_code& __ec) + : directory_iterator(__p, &__ec) {} + + _LIBCPP_HIDE_FROM_ABI + directory_iterator(const path& __p, directory_options __opts, + error_code& __ec) + : directory_iterator(__p, &__ec, __opts) {} + + _LIBCPP_HIDE_FROM_ABI directory_iterator(const directory_iterator&) = default; + _LIBCPP_HIDE_FROM_ABI directory_iterator(directory_iterator&&) = default; + _LIBCPP_HIDE_FROM_ABI directory_iterator& operator=(const directory_iterator&) = default; + + _LIBCPP_HIDE_FROM_ABI + directory_iterator& operator=(directory_iterator&& __o) noexcept { + // non-default implementation provided to support self-move assign. + if (this != &__o) { + __imp_ = _VSTD::move(__o.__imp_); + } + return *this; + } + + _LIBCPP_HIDE_FROM_ABI ~directory_iterator() = default; + + _LIBCPP_HIDE_FROM_ABI + const directory_entry& operator*() const { + _LIBCPP_ASSERT(__imp_, "The end iterator cannot be dereferenced"); + return __dereference(); + } + + _LIBCPP_HIDE_FROM_ABI + const directory_entry* operator->() const { return &**this; } + + _LIBCPP_HIDE_FROM_ABI + directory_iterator& operator++() { return __increment(); } + + _LIBCPP_HIDE_FROM_ABI + __dir_element_proxy operator++(int) { + __dir_element_proxy __p(**this); + __increment(); + return __p; + } + + _LIBCPP_HIDE_FROM_ABI + directory_iterator& increment(error_code& __ec) { return __increment(&__ec); } + +private: + inline _LIBCPP_HIDE_FROM_ABI friend bool + operator==(const directory_iterator& __lhs, + const directory_iterator& __rhs) noexcept; + + // construct the dir_stream + _LIBCPP_FUNC_VIS + directory_iterator(const path&, error_code*, + directory_options = directory_options::none); + + _LIBCPP_FUNC_VIS + directory_iterator& __increment(error_code* __ec = nullptr); + + _LIBCPP_FUNC_VIS + const directory_entry& __dereference() const; + +private: + shared_ptr<__dir_stream> __imp_; +}; + +inline _LIBCPP_HIDE_FROM_ABI bool +operator==(const directory_iterator& __lhs, + const directory_iterator& __rhs) noexcept { + return __lhs.__imp_ == __rhs.__imp_; +} + +inline _LIBCPP_HIDE_FROM_ABI bool +operator!=(const directory_iterator& __lhs, + const directory_iterator& __rhs) noexcept { + return !(__lhs == __rhs); +} + +// enable directory_iterator range-based for statements +inline _LIBCPP_HIDE_FROM_ABI directory_iterator +begin(directory_iterator __iter) noexcept { + return __iter; +} + +inline _LIBCPP_HIDE_FROM_ABI directory_iterator +end(directory_iterator) noexcept { + return directory_iterator(); +} + +_LIBCPP_AVAILABILITY_FILESYSTEM_POP + +_LIBCPP_END_NAMESPACE_FILESYSTEM + +#if _LIBCPP_STD_VER > 17 + +template <> +_LIBCPP_AVAILABILITY_FILESYSTEM +inline constexpr bool _VSTD::ranges::enable_borrowed_range<_VSTD_FS::directory_iterator> = true; + +template <> +_LIBCPP_AVAILABILITY_FILESYSTEM +inline constexpr bool _VSTD::ranges::enable_view<_VSTD_FS::directory_iterator> = true; + +#endif // _LIBCPP_STD_VER > 17 + +#endif // _LIBCPP_CXX03_LANG + +#endif // _LIBCPP___FILESYSTEM_DIRECTORY_ITERATOR_H diff --git a/app/src/main/cpp/libcxx/include/__filesystem/directory_options.h b/app/src/main/cpp/libcxx/include/__filesystem/directory_options.h new file mode 100644 index 0000000..c5c031a --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__filesystem/directory_options.h @@ -0,0 +1,82 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___FILESYSTEM_DIRECTORY_OPTIONS_H +#define _LIBCPP___FILESYSTEM_DIRECTORY_OPTIONS_H + +#include <__availability> +#include <__config> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#ifndef _LIBCPP_CXX03_LANG + +_LIBCPP_BEGIN_NAMESPACE_FILESYSTEM + +_LIBCPP_AVAILABILITY_FILESYSTEM_PUSH + +enum class _LIBCPP_ENUM_VIS directory_options : unsigned char { + none = 0, + follow_directory_symlink = 1, + skip_permission_denied = 2 +}; + +_LIBCPP_INLINE_VISIBILITY +inline constexpr directory_options operator&(directory_options __lhs, + directory_options __rhs) { + return static_cast(static_cast(__lhs) & + static_cast(__rhs)); +} + +_LIBCPP_INLINE_VISIBILITY +inline constexpr directory_options operator|(directory_options __lhs, + directory_options __rhs) { + return static_cast(static_cast(__lhs) | + static_cast(__rhs)); +} + +_LIBCPP_INLINE_VISIBILITY +inline constexpr directory_options operator^(directory_options __lhs, + directory_options __rhs) { + return static_cast(static_cast(__lhs) ^ + static_cast(__rhs)); +} + +_LIBCPP_INLINE_VISIBILITY +inline constexpr directory_options operator~(directory_options __lhs) { + return static_cast(~static_cast(__lhs)); +} + +_LIBCPP_INLINE_VISIBILITY +inline directory_options& operator&=(directory_options& __lhs, + directory_options __rhs) { + return __lhs = __lhs & __rhs; +} + +_LIBCPP_INLINE_VISIBILITY +inline directory_options& operator|=(directory_options& __lhs, + directory_options __rhs) { + return __lhs = __lhs | __rhs; +} + +_LIBCPP_INLINE_VISIBILITY +inline directory_options& operator^=(directory_options& __lhs, + directory_options __rhs) { + return __lhs = __lhs ^ __rhs; +} + +_LIBCPP_AVAILABILITY_FILESYSTEM_POP + +_LIBCPP_END_NAMESPACE_FILESYSTEM + +#endif // _LIBCPP_CXX03_LANG + +#endif // _LIBCPP___FILESYSTEM_DIRECTORY_OPTIONS_H diff --git a/app/src/main/cpp/libcxx/include/__filesystem/file_status.h b/app/src/main/cpp/libcxx/include/__filesystem/file_status.h new file mode 100644 index 0000000..ac3f6cb --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__filesystem/file_status.h @@ -0,0 +1,72 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___FILESYSTEM_FILE_STATUS_H +#define _LIBCPP___FILESYSTEM_FILE_STATUS_H + +#include <__availability> +#include <__config> +#include <__filesystem/file_type.h> +#include <__filesystem/perms.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#ifndef _LIBCPP_CXX03_LANG + +_LIBCPP_BEGIN_NAMESPACE_FILESYSTEM + +_LIBCPP_AVAILABILITY_FILESYSTEM_PUSH + +class _LIBCPP_TYPE_VIS file_status { +public: + // constructors + _LIBCPP_INLINE_VISIBILITY + file_status() noexcept : file_status(file_type::none) {} + _LIBCPP_INLINE_VISIBILITY + explicit file_status(file_type __ft, perms __prms = perms::unknown) noexcept + : __ft_(__ft), + __prms_(__prms) {} + + file_status(const file_status&) noexcept = default; + file_status(file_status&&) noexcept = default; + + _LIBCPP_INLINE_VISIBILITY + ~file_status() {} + + file_status& operator=(const file_status&) noexcept = default; + file_status& operator=(file_status&&) noexcept = default; + + // observers + _LIBCPP_INLINE_VISIBILITY + file_type type() const noexcept { return __ft_; } + + _LIBCPP_INLINE_VISIBILITY + perms permissions() const noexcept { return __prms_; } + + // modifiers + _LIBCPP_INLINE_VISIBILITY + void type(file_type __ft) noexcept { __ft_ = __ft; } + + _LIBCPP_INLINE_VISIBILITY + void permissions(perms __p) noexcept { __prms_ = __p; } + +private: + file_type __ft_; + perms __prms_; +}; + +_LIBCPP_AVAILABILITY_FILESYSTEM_POP + +_LIBCPP_END_NAMESPACE_FILESYSTEM + +#endif // _LIBCPP_CXX03_LANG + +#endif // _LIBCPP___FILESYSTEM_FILE_STATUS_H diff --git a/app/src/main/cpp/libcxx/include/__filesystem/file_time_type.h b/app/src/main/cpp/libcxx/include/__filesystem/file_time_type.h new file mode 100644 index 0000000..7c4932e --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__filesystem/file_time_type.h @@ -0,0 +1,32 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___FILESYSTEM_FILE_TIME_TYPE_H +#define _LIBCPP___FILESYSTEM_FILE_TIME_TYPE_H + +#include <__availability> +#include <__chrono/file_clock.h> +#include <__chrono/time_point.h> +#include <__config> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#ifndef _LIBCPP_CXX03_LANG + +_LIBCPP_BEGIN_NAMESPACE_FILESYSTEM + +typedef chrono::time_point<_FilesystemClock> file_time_type; + +_LIBCPP_END_NAMESPACE_FILESYSTEM + +#endif // _LIBCPP_CXX03_LANG + +#endif // _LIBCPP___FILESYSTEM_FILE_TIME_TYPE_H diff --git a/app/src/main/cpp/libcxx/include/__filesystem/file_type.h b/app/src/main/cpp/libcxx/include/__filesystem/file_type.h new file mode 100644 index 0000000..c756a05 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__filesystem/file_type.h @@ -0,0 +1,43 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___FILESYSTEM_FILE_TYPE_H +#define _LIBCPP___FILESYSTEM_FILE_TYPE_H + +#include <__availability> +#include <__config> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#ifndef _LIBCPP_CXX03_LANG + +_LIBCPP_BEGIN_NAMESPACE_FILESYSTEM + +// On Windows, the library never identifies files as block, character, fifo +// or socket. +enum class _LIBCPP_ENUM_VIS file_type : signed char { + none = 0, + not_found = -1, + regular = 1, + directory = 2, + symlink = 3, + block = 4, + character = 5, + fifo = 6, + socket = 7, + unknown = 8 +}; + +_LIBCPP_END_NAMESPACE_FILESYSTEM + +#endif // _LIBCPP_CXX03_LANG + +#endif // _LIBCPP___FILESYSTEM_FILE_TYPE_H diff --git a/app/src/main/cpp/libcxx/include/__filesystem/filesystem_error.h b/app/src/main/cpp/libcxx/include/__filesystem/filesystem_error.h new file mode 100644 index 0000000..effe699 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__filesystem/filesystem_error.h @@ -0,0 +1,104 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___FILESYSTEM_FILESYSTEM_ERROR_H +#define _LIBCPP___FILESYSTEM_FILESYSTEM_ERROR_H + +#include <__availability> +#include <__config> +#include <__filesystem/path.h> +#include <__memory/shared_ptr.h> +#include <__utility/forward.h> +#include +#include +#include +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#ifndef _LIBCPP_CXX03_LANG + +_LIBCPP_BEGIN_NAMESPACE_FILESYSTEM + +class _LIBCPP_AVAILABILITY_FILESYSTEM _LIBCPP_EXCEPTION_ABI filesystem_error : public system_error { +public: + _LIBCPP_INLINE_VISIBILITY + filesystem_error(const string& __what, error_code __ec) + : system_error(__ec, __what), + __storage_(make_shared<_Storage>(path(), path())) { + __create_what(0); + } + + _LIBCPP_INLINE_VISIBILITY + filesystem_error(const string& __what, const path& __p1, error_code __ec) + : system_error(__ec, __what), + __storage_(make_shared<_Storage>(__p1, path())) { + __create_what(1); + } + + _LIBCPP_INLINE_VISIBILITY + filesystem_error(const string& __what, const path& __p1, const path& __p2, + error_code __ec) + : system_error(__ec, __what), + __storage_(make_shared<_Storage>(__p1, __p2)) { + __create_what(2); + } + + _LIBCPP_INLINE_VISIBILITY + const path& path1() const noexcept { return __storage_->__p1_; } + + _LIBCPP_INLINE_VISIBILITY + const path& path2() const noexcept { return __storage_->__p2_; } + + filesystem_error(const filesystem_error&) = default; + ~filesystem_error() override; // key function + + _LIBCPP_HIDE_FROM_ABI_VIRTUAL + const char* what() const noexcept override { + return __storage_->__what_.c_str(); + } + + void __create_what(int __num_paths); + +private: + struct _LIBCPP_HIDDEN _Storage { + _LIBCPP_INLINE_VISIBILITY + _Storage(const path& __p1, const path& __p2) : __p1_(__p1), __p2_(__p2) {} + + path __p1_; + path __p2_; + string __what_; + }; + shared_ptr<_Storage> __storage_; +}; + +// TODO(ldionne): We need to pop the pragma and push it again after +// filesystem_error to work around PR41078. +_LIBCPP_AVAILABILITY_FILESYSTEM_PUSH + +template +_LIBCPP_NORETURN inline _LIBCPP_INLINE_VISIBILITY +#ifndef _LIBCPP_NO_EXCEPTIONS +void __throw_filesystem_error(_Args&&... __args) { + throw filesystem_error(_VSTD::forward<_Args>(__args)...); +} +#else +void __throw_filesystem_error(_Args&&...) { + _VSTD::abort(); +} +#endif +_LIBCPP_AVAILABILITY_FILESYSTEM_POP + +_LIBCPP_END_NAMESPACE_FILESYSTEM + +#endif // _LIBCPP_CXX03_LANG + +#endif // _LIBCPP___FILESYSTEM_FILESYSTEM_ERROR_H diff --git a/app/src/main/cpp/libcxx/include/__filesystem/operations.h b/app/src/main/cpp/libcxx/include/__filesystem/operations.h new file mode 100644 index 0000000..f48d301 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__filesystem/operations.h @@ -0,0 +1,201 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___FILESYSTEM_OPERATIONS_H +#define _LIBCPP___FILESYSTEM_OPERATIONS_H + +#include <__availability> +#include <__chrono/time_point.h> +#include <__config> +#include <__filesystem/copy_options.h> +#include <__filesystem/file_status.h> +#include <__filesystem/file_time_type.h> +#include <__filesystem/file_type.h> +#include <__filesystem/path.h> +#include <__filesystem/perm_options.h> +#include <__filesystem/perms.h> +#include <__filesystem/space_info.h> +#include +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#ifndef _LIBCPP_CXX03_LANG + +_LIBCPP_BEGIN_NAMESPACE_FILESYSTEM + +_LIBCPP_AVAILABILITY_FILESYSTEM_PUSH + +_LIBCPP_FUNC_VIS path __absolute(const path&, error_code* __ec = nullptr); +_LIBCPP_FUNC_VIS path __canonical(const path&, error_code* __ec = nullptr); +_LIBCPP_FUNC_VIS bool __copy_file(const path& __from, const path& __to, copy_options __opt, error_code* __ec = nullptr); +_LIBCPP_FUNC_VIS void __copy_symlink(const path& __existing_symlink, const path& __new_symlink, error_code* __ec = nullptr); +_LIBCPP_FUNC_VIS void __copy(const path& __from, const path& __to, copy_options __opt, error_code* __ec = nullptr); +_LIBCPP_FUNC_VIS bool __create_directories(const path&, error_code* = nullptr); +_LIBCPP_FUNC_VIS void __create_directory_symlink(const path& __to, const path& __new_symlink, error_code* __ec = nullptr); +_LIBCPP_FUNC_VIS bool __create_directory(const path&, error_code* = nullptr); +_LIBCPP_FUNC_VIS bool __create_directory(const path&, const path& __attributes, error_code* = nullptr); +_LIBCPP_FUNC_VIS void __create_hard_link(const path& __to, const path& __new_hard_link, error_code* __ec = nullptr); +_LIBCPP_FUNC_VIS void __create_symlink(const path& __to, const path& __new_symlink, error_code* __ec = nullptr); +_LIBCPP_FUNC_VIS path __current_path(error_code* __ec = nullptr); +_LIBCPP_FUNC_VIS void __current_path(const path&, error_code* __ec = nullptr); +_LIBCPP_FUNC_VIS bool __equivalent(const path&, const path&, error_code* __ec = nullptr); +_LIBCPP_FUNC_VIS file_status __status(const path&, error_code* __ec = nullptr); +_LIBCPP_FUNC_VIS uintmax_t __file_size(const path&, error_code* __ec = nullptr); +_LIBCPP_FUNC_VIS uintmax_t __hard_link_count(const path&, error_code* __ec = nullptr); +_LIBCPP_FUNC_VIS file_status __symlink_status(const path&, error_code* __ec = nullptr); +_LIBCPP_FUNC_VIS file_time_type __last_write_time(const path&, error_code* __ec = nullptr); +_LIBCPP_FUNC_VIS void __last_write_time(const path&, file_time_type __new_time, error_code* __ec = nullptr); +_LIBCPP_FUNC_VIS path __weakly_canonical(path const& __p, error_code* __ec = nullptr); +_LIBCPP_FUNC_VIS path __read_symlink(const path&, error_code* __ec = nullptr); +_LIBCPP_FUNC_VIS uintmax_t __remove_all(const path&, error_code* __ec = nullptr); +_LIBCPP_FUNC_VIS bool __remove(const path&, error_code* __ec = nullptr); +_LIBCPP_FUNC_VIS void __rename(const path& __from, const path& __to, error_code* __ec = nullptr); +_LIBCPP_FUNC_VIS void __resize_file(const path&, uintmax_t __size, error_code* = nullptr); +_LIBCPP_FUNC_VIS path __temp_directory_path(error_code* __ec = nullptr); + +inline _LIBCPP_HIDE_FROM_ABI path absolute(const path& __p) { return __absolute(__p); } +inline _LIBCPP_HIDE_FROM_ABI path absolute(const path& __p, error_code& __ec) { return __absolute(__p, &__ec); } +inline _LIBCPP_HIDE_FROM_ABI path canonical(const path& __p) { return __canonical(__p); } +inline _LIBCPP_HIDE_FROM_ABI path canonical(const path& __p, error_code& __ec) { return __canonical(__p, &__ec); } +inline _LIBCPP_HIDE_FROM_ABI bool copy_file(const path& __from, const path& __to) { return __copy_file(__from, __to, copy_options::none); } +inline _LIBCPP_HIDE_FROM_ABI bool copy_file(const path& __from, const path& __to, error_code& __ec) { return __copy_file(__from, __to, copy_options::none, &__ec); } +inline _LIBCPP_HIDE_FROM_ABI bool copy_file(const path& __from, const path& __to, copy_options __opt) { return __copy_file(__from, __to, __opt); } +inline _LIBCPP_HIDE_FROM_ABI bool copy_file(const path& __from, const path& __to, copy_options __opt, error_code& __ec) { return __copy_file(__from, __to, __opt, &__ec); } +inline _LIBCPP_HIDE_FROM_ABI void copy_symlink(const path& __from, const path& __to) { __copy_symlink(__from, __to); } +inline _LIBCPP_HIDE_FROM_ABI void copy_symlink(const path& __from, const path& __to, error_code& __ec) noexcept { __copy_symlink(__from, __to, &__ec); } +inline _LIBCPP_HIDE_FROM_ABI void copy(const path& __from, const path& __to) { __copy(__from, __to, copy_options::none); } +inline _LIBCPP_HIDE_FROM_ABI void copy(const path& __from, const path& __to, error_code& __ec) { __copy(__from, __to, copy_options::none, &__ec); } +inline _LIBCPP_HIDE_FROM_ABI void copy(const path& __from, const path& __to, copy_options __opt) { __copy(__from, __to, __opt); } +inline _LIBCPP_HIDE_FROM_ABI void copy(const path& __from, const path& __to, copy_options __opt, error_code& __ec) { __copy(__from, __to, __opt, &__ec); } +inline _LIBCPP_HIDE_FROM_ABI bool create_directories(const path& __p) { return __create_directories(__p); } +inline _LIBCPP_HIDE_FROM_ABI bool create_directories(const path& __p, error_code& __ec) { return __create_directories(__p, &__ec); } +inline _LIBCPP_HIDE_FROM_ABI void create_directory_symlink(const path& __target, const path& __link) { __create_directory_symlink(__target, __link); } +inline _LIBCPP_HIDE_FROM_ABI void create_directory_symlink(const path& __target, const path& __link, error_code& __ec) noexcept { __create_directory_symlink(__target, __link, &__ec); } +inline _LIBCPP_HIDE_FROM_ABI bool create_directory(const path& __p) { return __create_directory(__p); } +inline _LIBCPP_HIDE_FROM_ABI bool create_directory(const path& __p, error_code& __ec) noexcept { return __create_directory(__p, &__ec); } +inline _LIBCPP_HIDE_FROM_ABI bool create_directory(const path& __p, const path& __attrs) { return __create_directory(__p, __attrs); } +inline _LIBCPP_HIDE_FROM_ABI bool create_directory(const path& __p, const path& __attrs, error_code& __ec) noexcept { return __create_directory(__p, __attrs, &__ec); } +inline _LIBCPP_HIDE_FROM_ABI void create_hard_link(const path& __target, const path& __link) { __create_hard_link(__target, __link); } +inline _LIBCPP_HIDE_FROM_ABI void create_hard_link(const path& __target, const path& __link, error_code& __ec) noexcept { __create_hard_link(__target, __link, &__ec); } +inline _LIBCPP_HIDE_FROM_ABI void create_symlink(const path& __target, const path& __link) { __create_symlink(__target, __link); } +inline _LIBCPP_HIDE_FROM_ABI void create_symlink(const path& __target, const path& __link, error_code& __ec) noexcept { return __create_symlink(__target, __link, &__ec); } +inline _LIBCPP_HIDE_FROM_ABI path current_path() { return __current_path(); } +inline _LIBCPP_HIDE_FROM_ABI path current_path(error_code& __ec) { return __current_path(&__ec); } +inline _LIBCPP_HIDE_FROM_ABI void current_path(const path& __p) { __current_path(__p); } +inline _LIBCPP_HIDE_FROM_ABI void current_path(const path& __p, error_code& __ec) noexcept { __current_path(__p, &__ec); } +inline _LIBCPP_HIDE_FROM_ABI bool equivalent(const path& __p1, const path& __p2) { return __equivalent(__p1, __p2); } +inline _LIBCPP_HIDE_FROM_ABI bool equivalent(const path& __p1, const path& __p2, error_code& __ec) noexcept { return __equivalent(__p1, __p2, &__ec); } +inline _LIBCPP_HIDE_FROM_ABI bool status_known(file_status __s) noexcept { return __s.type() != file_type::none; } +inline _LIBCPP_HIDE_FROM_ABI bool exists(file_status __s) noexcept { return status_known(__s) && __s.type() != file_type::not_found; } +inline _LIBCPP_HIDE_FROM_ABI bool exists(const path& __p) { return exists(__status(__p)); } + +inline _LIBCPP_INLINE_VISIBILITY bool exists(const path& __p, error_code& __ec) noexcept { + auto __s = __status(__p, &__ec); + if (status_known(__s)) + __ec.clear(); + return exists(__s); +} + +inline _LIBCPP_HIDE_FROM_ABI uintmax_t file_size(const path& __p) { return __file_size(__p); } +inline _LIBCPP_HIDE_FROM_ABI uintmax_t file_size(const path& __p, error_code& __ec) noexcept { return __file_size(__p, &__ec); } +inline _LIBCPP_HIDE_FROM_ABI uintmax_t hard_link_count(const path& __p) { return __hard_link_count(__p); } +inline _LIBCPP_HIDE_FROM_ABI uintmax_t hard_link_count(const path& __p, error_code& __ec) noexcept { return __hard_link_count(__p, &__ec); } +inline _LIBCPP_HIDE_FROM_ABI bool is_block_file(file_status __s) noexcept { return __s.type() == file_type::block; } +inline _LIBCPP_HIDE_FROM_ABI bool is_block_file(const path& __p) { return is_block_file(__status(__p)); } +inline _LIBCPP_HIDE_FROM_ABI bool is_block_file(const path& __p, error_code& __ec) noexcept { return is_block_file(__status(__p, &__ec)); } +inline _LIBCPP_HIDE_FROM_ABI bool is_character_file(file_status __s) noexcept { return __s.type() == file_type::character; } +inline _LIBCPP_HIDE_FROM_ABI bool is_character_file(const path& __p) { return is_character_file(__status(__p)); } +inline _LIBCPP_HIDE_FROM_ABI bool is_character_file(const path& __p, error_code& __ec) noexcept { return is_character_file(__status(__p, &__ec)); } +inline _LIBCPP_HIDE_FROM_ABI bool is_directory(file_status __s) noexcept { return __s.type() == file_type::directory; } +inline _LIBCPP_HIDE_FROM_ABI bool is_directory(const path& __p) { return is_directory(__status(__p)); } +inline _LIBCPP_HIDE_FROM_ABI bool is_directory(const path& __p, error_code& __ec) noexcept { return is_directory(__status(__p, &__ec)); } +_LIBCPP_FUNC_VIS bool __fs_is_empty(const path& __p, error_code* __ec = nullptr); +inline _LIBCPP_HIDE_FROM_ABI bool is_empty(const path& __p) { return __fs_is_empty(__p); } +inline _LIBCPP_HIDE_FROM_ABI bool is_empty(const path& __p, error_code& __ec) { return __fs_is_empty(__p, &__ec); } +inline _LIBCPP_HIDE_FROM_ABI bool is_fifo(file_status __s) noexcept { return __s.type() == file_type::fifo; } +inline _LIBCPP_HIDE_FROM_ABI bool is_fifo(const path& __p) { return is_fifo(__status(__p)); } +inline _LIBCPP_HIDE_FROM_ABI bool is_fifo(const path& __p, error_code& __ec) noexcept { return is_fifo(__status(__p, &__ec)); } +inline _LIBCPP_HIDE_FROM_ABI bool is_regular_file(file_status __s) noexcept { return __s.type() == file_type::regular; } +inline _LIBCPP_HIDE_FROM_ABI bool is_regular_file(const path& __p) { return is_regular_file(__status(__p)); } +inline _LIBCPP_HIDE_FROM_ABI bool is_regular_file(const path& __p, error_code& __ec) noexcept { return is_regular_file(__status(__p, &__ec)); } +inline _LIBCPP_HIDE_FROM_ABI bool is_symlink(file_status __s) noexcept { return __s.type() == file_type::symlink; } +inline _LIBCPP_HIDE_FROM_ABI bool is_symlink(const path& __p) { return is_symlink(__symlink_status(__p)); } +inline _LIBCPP_HIDE_FROM_ABI bool is_symlink(const path& __p, error_code& __ec) noexcept { return is_symlink(__symlink_status(__p, &__ec)); } +inline _LIBCPP_HIDE_FROM_ABI bool is_other(file_status __s) noexcept { return exists(__s) && !is_regular_file(__s) && !is_directory(__s) && !is_symlink(__s); } +inline _LIBCPP_HIDE_FROM_ABI bool is_other(const path& __p) { return is_other(__status(__p)); } +inline _LIBCPP_HIDE_FROM_ABI bool is_other(const path& __p, error_code& __ec) noexcept { return is_other(__status(__p, &__ec)); } +inline _LIBCPP_HIDE_FROM_ABI bool is_socket(file_status __s) noexcept { return __s.type() == file_type::socket; } +inline _LIBCPP_HIDE_FROM_ABI bool is_socket(const path& __p) { return is_socket(__status(__p)); } +inline _LIBCPP_HIDE_FROM_ABI bool is_socket(const path& __p, error_code& __ec) noexcept { return is_socket(__status(__p, &__ec)); } +inline _LIBCPP_HIDE_FROM_ABI file_time_type last_write_time(const path& __p) { return __last_write_time(__p); } +inline _LIBCPP_HIDE_FROM_ABI file_time_type last_write_time(const path& __p, error_code& __ec) noexcept { return __last_write_time(__p, &__ec); } +inline _LIBCPP_HIDE_FROM_ABI void last_write_time(const path& __p, file_time_type __t) { __last_write_time(__p, __t); } +inline _LIBCPP_HIDE_FROM_ABI void last_write_time(const path& __p, file_time_type __t, error_code& __ec) noexcept { __last_write_time(__p, __t, &__ec); } +_LIBCPP_FUNC_VIS void __permissions(const path&, perms, perm_options, error_code* = nullptr); +inline _LIBCPP_HIDE_FROM_ABI void permissions(const path& __p, perms __prms, perm_options __opts = perm_options::replace) { __permissions(__p, __prms, __opts); } +inline _LIBCPP_HIDE_FROM_ABI void permissions(const path& __p, perms __prms, error_code& __ec) noexcept { __permissions(__p, __prms, perm_options::replace, &__ec); } +inline _LIBCPP_HIDE_FROM_ABI void permissions(const path& __p, perms __prms, perm_options __opts, error_code& __ec) { __permissions(__p, __prms, __opts, &__ec); } + +inline _LIBCPP_INLINE_VISIBILITY path proximate(const path& __p, const path& __base, error_code& __ec) { + path __tmp = __weakly_canonical(__p, &__ec); + if (__ec) + return {}; + path __tmp_base = __weakly_canonical(__base, &__ec); + if (__ec) + return {}; + return __tmp.lexically_proximate(__tmp_base); +} + +inline _LIBCPP_HIDE_FROM_ABI path proximate(const path& __p, error_code& __ec) { return proximate(__p, current_path(), __ec); } +inline _LIBCPP_HIDE_FROM_ABI path proximate(const path& __p, const path& __base = current_path()) { return __weakly_canonical(__p).lexically_proximate(__weakly_canonical(__base)); } +inline _LIBCPP_HIDE_FROM_ABI path read_symlink(const path& __p) { return __read_symlink(__p); } +inline _LIBCPP_HIDE_FROM_ABI path read_symlink(const path& __p, error_code& __ec) { return __read_symlink(__p, &__ec); } + +inline _LIBCPP_INLINE_VISIBILITY path relative(const path& __p, const path& __base, error_code& __ec) { + path __tmp = __weakly_canonical(__p, &__ec); + if (__ec) + return path(); + path __tmpbase = __weakly_canonical(__base, &__ec); + if (__ec) + return path(); + return __tmp.lexically_relative(__tmpbase); +} + +inline _LIBCPP_HIDE_FROM_ABI path relative(const path& __p, error_code& __ec) { return relative(__p, current_path(), __ec); } +inline _LIBCPP_HIDE_FROM_ABI path relative(const path& __p, const path& __base = current_path()) { return __weakly_canonical(__p).lexically_relative(__weakly_canonical(__base)); } +inline _LIBCPP_HIDE_FROM_ABI uintmax_t remove_all(const path& __p) { return __remove_all(__p); } +inline _LIBCPP_HIDE_FROM_ABI uintmax_t remove_all(const path& __p, error_code& __ec) { return __remove_all(__p, &__ec); } +inline _LIBCPP_HIDE_FROM_ABI bool remove(const path& __p) { return __remove(__p); } +inline _LIBCPP_HIDE_FROM_ABI bool remove(const path& __p, error_code& __ec) noexcept { return __remove(__p, &__ec); } +inline _LIBCPP_HIDE_FROM_ABI void rename(const path& __from, const path& __to) { return __rename(__from, __to); } +inline _LIBCPP_HIDE_FROM_ABI void rename(const path& __from, const path& __to, error_code& __ec) noexcept { return __rename(__from, __to, &__ec); } +inline _LIBCPP_HIDE_FROM_ABI void resize_file(const path& __p, uintmax_t __ns) { return __resize_file(__p, __ns); } +inline _LIBCPP_HIDE_FROM_ABI void resize_file(const path& __p, uintmax_t __ns, error_code& __ec) noexcept { return __resize_file(__p, __ns, &__ec); } +_LIBCPP_FUNC_VIS space_info __space(const path&, error_code* __ec = nullptr); +inline _LIBCPP_HIDE_FROM_ABI space_info space(const path& __p) { return __space(__p); } +inline _LIBCPP_HIDE_FROM_ABI space_info space(const path& __p, error_code& __ec) noexcept { return __space(__p, &__ec); } +inline _LIBCPP_HIDE_FROM_ABI file_status status(const path& __p) { return __status(__p); } +inline _LIBCPP_HIDE_FROM_ABI file_status status(const path& __p, error_code& __ec) noexcept { return __status(__p, &__ec); } +inline _LIBCPP_HIDE_FROM_ABI file_status symlink_status(const path& __p) { return __symlink_status(__p); } +inline _LIBCPP_HIDE_FROM_ABI file_status symlink_status(const path& __p, error_code& __ec) noexcept { return __symlink_status(__p, &__ec); } +inline _LIBCPP_HIDE_FROM_ABI path temp_directory_path() { return __temp_directory_path(); } +inline _LIBCPP_HIDE_FROM_ABI path temp_directory_path(error_code& __ec) { return __temp_directory_path(&__ec); } +inline _LIBCPP_HIDE_FROM_ABI path weakly_canonical(path const& __p) { return __weakly_canonical(__p); } +inline _LIBCPP_HIDE_FROM_ABI path weakly_canonical(path const& __p, error_code& __ec) { return __weakly_canonical(__p, &__ec); } + +_LIBCPP_AVAILABILITY_FILESYSTEM_POP + +_LIBCPP_END_NAMESPACE_FILESYSTEM + +#endif // _LIBCPP_CXX03_LANG + +#endif // _LIBCPP___FILESYSTEM_OPERATIONS_H diff --git a/app/src/main/cpp/libcxx/include/__filesystem/path.h b/app/src/main/cpp/libcxx/include/__filesystem/path.h new file mode 100644 index 0000000..4e6912f --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__filesystem/path.h @@ -0,0 +1,1091 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___FILESYSTEM_PATH_H +#define _LIBCPP___FILESYSTEM_PATH_H + +#include <__algorithm/replace.h> +#include <__algorithm/replace_copy.h> +#include <__availability> +#include <__config> +#include <__iterator/back_insert_iterator.h> +#include <__iterator/iterator_traits.h> +#include +#include +#include +#include + +#if !defined(_LIBCPP_HAS_NO_LOCALIZATION) +# include // for quoted +# include +#endif + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#ifndef _LIBCPP_CXX03_LANG + +_LIBCPP_BEGIN_NAMESPACE_FILESYSTEM + +_LIBCPP_AVAILABILITY_FILESYSTEM_PUSH + +template +struct __can_convert_char { + static const bool value = false; +}; +template +struct __can_convert_char : public __can_convert_char<_Tp> {}; +template <> +struct __can_convert_char { + static const bool value = true; + using __char_type = char; +}; +template <> +struct __can_convert_char { + static const bool value = true; + using __char_type = wchar_t; +}; +#ifndef _LIBCPP_HAS_NO_CHAR8_T +template <> +struct __can_convert_char { + static const bool value = true; + using __char_type = char8_t; +}; +#endif +template <> +struct __can_convert_char { + static const bool value = true; + using __char_type = char16_t; +}; +template <> +struct __can_convert_char { + static const bool value = true; + using __char_type = char32_t; +}; + +template +_LIBCPP_HIDE_FROM_ABI +typename enable_if<__can_convert_char<_ECharT>::value, bool>::type +__is_separator(_ECharT __e) { +#if defined(_LIBCPP_WIN32API) + return __e == _ECharT('/') || __e == _ECharT('\\'); +#else + return __e == _ECharT('/'); +#endif +} + +#ifndef _LIBCPP_HAS_NO_CHAR8_T +typedef u8string __u8_string; +#else +typedef string __u8_string; +#endif + +struct _NullSentinel {}; + +template +using _Void = void; + +template +struct __is_pathable_string : public false_type {}; + +template +struct __is_pathable_string< + basic_string<_ECharT, _Traits, _Alloc>, + _Void::__char_type> > + : public __can_convert_char<_ECharT> { + using _Str = basic_string<_ECharT, _Traits, _Alloc>; + using _Base = __can_convert_char<_ECharT>; + + _LIBCPP_HIDE_FROM_ABI + static _ECharT const* __range_begin(_Str const& __s) { return __s.data(); } + + _LIBCPP_HIDE_FROM_ABI + static _ECharT const* __range_end(_Str const& __s) { + return __s.data() + __s.length(); + } + + _LIBCPP_HIDE_FROM_ABI + static _ECharT __first_or_null(_Str const& __s) { + return __s.empty() ? _ECharT{} : __s[0]; + } +}; + +template +struct __is_pathable_string< + basic_string_view<_ECharT, _Traits>, + _Void::__char_type> > + : public __can_convert_char<_ECharT> { + using _Str = basic_string_view<_ECharT, _Traits>; + using _Base = __can_convert_char<_ECharT>; + + _LIBCPP_HIDE_FROM_ABI + static _ECharT const* __range_begin(_Str const& __s) { return __s.data(); } + + _LIBCPP_HIDE_FROM_ABI + static _ECharT const* __range_end(_Str const& __s) { + return __s.data() + __s.length(); + } + + _LIBCPP_HIDE_FROM_ABI + static _ECharT __first_or_null(_Str const& __s) { + return __s.empty() ? _ECharT{} : __s[0]; + } +}; + +template ::type, + class _UnqualPtrType = + __remove_const_t<__remove_pointer_t<_DS> >, + bool _IsCharPtr = is_pointer<_DS>::value&& + __can_convert_char<_UnqualPtrType>::value> +struct __is_pathable_char_array : false_type {}; + +template +struct __is_pathable_char_array<_Source, _ECharT*, _UPtr, true> + : __can_convert_char<__remove_const_t<_ECharT> > { + using _Base = __can_convert_char<__remove_const_t<_ECharT> >; + + _LIBCPP_HIDE_FROM_ABI + static _ECharT const* __range_begin(const _ECharT* __b) { return __b; } + + _LIBCPP_HIDE_FROM_ABI + static _ECharT const* __range_end(const _ECharT* __b) { + using _Iter = const _ECharT*; + const _ECharT __sentinel = _ECharT{}; + _Iter __e = __b; + for (; *__e != __sentinel; ++__e) + ; + return __e; + } + + _LIBCPP_HIDE_FROM_ABI + static _ECharT __first_or_null(const _ECharT* __b) { return *__b; } +}; + +template ::value, + class = void> +struct __is_pathable_iter : false_type {}; + +template +struct __is_pathable_iter< + _Iter, true, + _Void::value_type>::__char_type> > + : __can_convert_char::value_type> { + using _ECharT = typename iterator_traits<_Iter>::value_type; + using _Base = __can_convert_char<_ECharT>; + + _LIBCPP_HIDE_FROM_ABI + static _Iter __range_begin(_Iter __b) { return __b; } + + _LIBCPP_HIDE_FROM_ABI + static _NullSentinel __range_end(_Iter) { return _NullSentinel{}; } + + _LIBCPP_HIDE_FROM_ABI + static _ECharT __first_or_null(_Iter __b) { return *__b; } +}; + +template ::value, + bool _IsCharIterT = __is_pathable_char_array<_Tp>::value, + bool _IsIterT = !_IsCharIterT && __is_pathable_iter<_Tp>::value> +struct __is_pathable : false_type { + static_assert(!_IsStringT && !_IsCharIterT && !_IsIterT, "Must all be false"); +}; + +template +struct __is_pathable<_Tp, true, false, false> : __is_pathable_string<_Tp> {}; + +template +struct __is_pathable<_Tp, false, true, false> : __is_pathable_char_array<_Tp> { +}; + +template +struct __is_pathable<_Tp, false, false, true> : __is_pathable_iter<_Tp> {}; + +#if defined(_LIBCPP_WIN32API) +typedef wstring __path_string; +typedef wchar_t __path_value; +#else +typedef string __path_string; +typedef char __path_value; +#endif + +#if defined(_LIBCPP_WIN32API) +_LIBCPP_FUNC_VIS +size_t __wide_to_char(const wstring&, char*, size_t); +_LIBCPP_FUNC_VIS +size_t __char_to_wide(const string&, wchar_t*, size_t); +#endif + +template +struct _PathCVT; + +#if !defined(_LIBCPP_HAS_NO_LOCALIZATION) +template +struct _PathCVT { + static_assert(__can_convert_char<_ECharT>::value, + "Char type not convertible"); + + typedef __narrow_to_utf8 _Narrower; +#if defined(_LIBCPP_WIN32API) + typedef __widen_from_utf8 _Widener; +#endif + + _LIBCPP_HIDE_FROM_ABI + static void __append_range(__path_string& __dest, _ECharT const* __b, + _ECharT const* __e) { +#if defined(_LIBCPP_WIN32API) + string __utf8; + _Narrower()(back_inserter(__utf8), __b, __e); + _Widener()(back_inserter(__dest), __utf8.data(), __utf8.data() + __utf8.size()); +#else + _Narrower()(back_inserter(__dest), __b, __e); +#endif + } + + template + _LIBCPP_HIDE_FROM_ABI + static void __append_range(__path_string& __dest, _Iter __b, _Iter __e) { + static_assert(!is_same<_Iter, _ECharT*>::value, "Call const overload"); + if (__b == __e) + return; + basic_string<_ECharT> __tmp(__b, __e); +#if defined(_LIBCPP_WIN32API) + string __utf8; + _Narrower()(back_inserter(__utf8), __tmp.data(), + __tmp.data() + __tmp.length()); + _Widener()(back_inserter(__dest), __utf8.data(), __utf8.data() + __utf8.size()); +#else + _Narrower()(back_inserter(__dest), __tmp.data(), + __tmp.data() + __tmp.length()); +#endif + } + + template + _LIBCPP_HIDE_FROM_ABI + static void __append_range(__path_string& __dest, _Iter __b, _NullSentinel) { + static_assert(!is_same<_Iter, _ECharT*>::value, "Call const overload"); + const _ECharT __sentinel = _ECharT{}; + if (*__b == __sentinel) + return; + basic_string<_ECharT> __tmp; + for (; *__b != __sentinel; ++__b) + __tmp.push_back(*__b); +#if defined(_LIBCPP_WIN32API) + string __utf8; + _Narrower()(back_inserter(__utf8), __tmp.data(), + __tmp.data() + __tmp.length()); + _Widener()(back_inserter(__dest), __utf8.data(), __utf8.data() + __utf8.size()); +#else + _Narrower()(back_inserter(__dest), __tmp.data(), + __tmp.data() + __tmp.length()); +#endif + } + + template + _LIBCPP_HIDE_FROM_ABI + static void __append_source(__path_string& __dest, _Source const& __s) { + using _Traits = __is_pathable<_Source>; + __append_range(__dest, _Traits::__range_begin(__s), + _Traits::__range_end(__s)); + } +}; +#endif // !_LIBCPP_HAS_NO_LOCALIZATION + +template <> +struct _PathCVT<__path_value> { + + template + _LIBCPP_HIDE_FROM_ABI + static typename enable_if<__is_exactly_cpp17_input_iterator<_Iter>::value>::type + __append_range(__path_string& __dest, _Iter __b, _Iter __e) { + for (; __b != __e; ++__b) + __dest.push_back(*__b); + } + + template + _LIBCPP_HIDE_FROM_ABI + static typename enable_if<__is_cpp17_forward_iterator<_Iter>::value>::type + __append_range(__path_string& __dest, _Iter __b, _Iter __e) { + __dest.append(__b, __e); + } + + template + _LIBCPP_HIDE_FROM_ABI + static void __append_range(__path_string& __dest, _Iter __b, _NullSentinel) { + const char __sentinel = char{}; + for (; *__b != __sentinel; ++__b) + __dest.push_back(*__b); + } + + template + _LIBCPP_HIDE_FROM_ABI + static void __append_source(__path_string& __dest, _Source const& __s) { + using _Traits = __is_pathable<_Source>; + __append_range(__dest, _Traits::__range_begin(__s), + _Traits::__range_end(__s)); + } +}; + +#if defined(_LIBCPP_WIN32API) +template <> +struct _PathCVT { + + _LIBCPP_HIDE_FROM_ABI + static void + __append_string(__path_string& __dest, const basic_string &__str) { + size_t __size = __char_to_wide(__str, nullptr, 0); + size_t __pos = __dest.size(); + __dest.resize(__pos + __size); + __char_to_wide(__str, const_cast<__path_value*>(__dest.data()) + __pos, __size); + } + + template + _LIBCPP_HIDE_FROM_ABI + static typename enable_if<__is_exactly_cpp17_input_iterator<_Iter>::value>::type + __append_range(__path_string& __dest, _Iter __b, _Iter __e) { + basic_string __tmp(__b, __e); + __append_string(__dest, __tmp); + } + + template + _LIBCPP_HIDE_FROM_ABI + static typename enable_if<__is_cpp17_forward_iterator<_Iter>::value>::type + __append_range(__path_string& __dest, _Iter __b, _Iter __e) { + basic_string __tmp(__b, __e); + __append_string(__dest, __tmp); + } + + template + _LIBCPP_HIDE_FROM_ABI + static void __append_range(__path_string& __dest, _Iter __b, _NullSentinel) { + const char __sentinel = char{}; + basic_string __tmp; + for (; *__b != __sentinel; ++__b) + __tmp.push_back(*__b); + __append_string(__dest, __tmp); + } + + template + _LIBCPP_HIDE_FROM_ABI + static void __append_source(__path_string& __dest, _Source const& __s) { + using _Traits = __is_pathable<_Source>; + __append_range(__dest, _Traits::__range_begin(__s), + _Traits::__range_end(__s)); + } +}; + +template +struct _PathExport { + typedef __narrow_to_utf8 _Narrower; + typedef __widen_from_utf8 _Widener; + + template + _LIBCPP_HIDE_FROM_ABI + static void __append(_Str& __dest, const __path_string& __src) { + string __utf8; + _Narrower()(back_inserter(__utf8), __src.data(), __src.data() + __src.size()); + _Widener()(back_inserter(__dest), __utf8.data(), __utf8.data() + __utf8.size()); + } +}; + +template <> +struct _PathExport { + template + _LIBCPP_HIDE_FROM_ABI + static void __append(_Str& __dest, const __path_string& __src) { + size_t __size = __wide_to_char(__src, nullptr, 0); + size_t __pos = __dest.size(); + __dest.resize(__size); + __wide_to_char(__src, const_cast(__dest.data()) + __pos, __size); + } +}; + +template <> +struct _PathExport { + template + _LIBCPP_HIDE_FROM_ABI + static void __append(_Str& __dest, const __path_string& __src) { + __dest.append(__src.begin(), __src.end()); + } +}; + +template <> +struct _PathExport { + template + _LIBCPP_HIDE_FROM_ABI + static void __append(_Str& __dest, const __path_string& __src) { + __dest.append(__src.begin(), __src.end()); + } +}; + +#ifndef _LIBCPP_HAS_NO_CHAR8_T +template <> +struct _PathExport { + typedef __narrow_to_utf8 _Narrower; + + template + _LIBCPP_HIDE_FROM_ABI + static void __append(_Str& __dest, const __path_string& __src) { + _Narrower()(back_inserter(__dest), __src.data(), __src.data() + __src.size()); + } +}; +#endif /* !_LIBCPP_HAS_NO_CHAR8_T */ +#endif /* _LIBCPP_WIN32API */ + +class _LIBCPP_TYPE_VIS path { + template + using _EnableIfPathable = + typename enable_if<__is_pathable<_SourceOrIter>::value, _Tp>::type; + + template + using _SourceChar = typename __is_pathable<_Tp>::__char_type; + + template + using _SourceCVT = _PathCVT<_SourceChar<_Tp> >; + +public: +#if defined(_LIBCPP_WIN32API) + typedef wchar_t value_type; + static constexpr value_type preferred_separator = L'\\'; +#else + typedef char value_type; + static constexpr value_type preferred_separator = '/'; +#endif + typedef basic_string string_type; + typedef basic_string_view __string_view; + + enum _LIBCPP_ENUM_VIS format : unsigned char { + auto_format, + native_format, + generic_format + }; + + // constructors and destructor + _LIBCPP_HIDE_FROM_ABI path() noexcept {} + _LIBCPP_HIDE_FROM_ABI path(const path& __p) : __pn_(__p.__pn_) {} + _LIBCPP_HIDE_FROM_ABI path(path&& __p) noexcept + : __pn_(_VSTD::move(__p.__pn_)) {} + + _LIBCPP_HIDE_FROM_ABI + path(string_type&& __s, format = format::auto_format) noexcept + : __pn_(_VSTD::move(__s)) {} + + template > + _LIBCPP_HIDE_FROM_ABI + path(const _Source& __src, format = format::auto_format) { + _SourceCVT<_Source>::__append_source(__pn_, __src); + } + + template + _LIBCPP_HIDE_FROM_ABI + path(_InputIt __first, _InputIt __last, format = format::auto_format) { + typedef typename iterator_traits<_InputIt>::value_type _ItVal; + _PathCVT<_ItVal>::__append_range(__pn_, __first, __last); + } + +/* +#if !defined(_LIBCPP_HAS_NO_LOCALIZATION) + // TODO Implement locale conversions. + template > + path(const _Source& __src, const locale& __loc, format = format::auto_format); + template + path(_InputIt __first, _InputIt _last, const locale& __loc, + format = format::auto_format); +#endif +*/ + + _LIBCPP_HIDE_FROM_ABI + ~path() = default; + + // assignments + _LIBCPP_HIDE_FROM_ABI + path& operator=(const path& __p) { + __pn_ = __p.__pn_; + return *this; + } + + _LIBCPP_HIDE_FROM_ABI + path& operator=(path&& __p) noexcept { + __pn_ = _VSTD::move(__p.__pn_); + return *this; + } + + _LIBCPP_HIDE_FROM_ABI + path& operator=(string_type&& __s) noexcept { + __pn_ = _VSTD::move(__s); + return *this; + } + + _LIBCPP_HIDE_FROM_ABI + path& assign(string_type&& __s) noexcept { + __pn_ = _VSTD::move(__s); + return *this; + } + + template + _LIBCPP_HIDE_FROM_ABI _EnableIfPathable<_Source> + operator=(const _Source& __src) { + return this->assign(__src); + } + + template + _LIBCPP_HIDE_FROM_ABI + _EnableIfPathable<_Source> assign(const _Source& __src) { + __pn_.clear(); + _SourceCVT<_Source>::__append_source(__pn_, __src); + return *this; + } + + template + _LIBCPP_HIDE_FROM_ABI + path& assign(_InputIt __first, _InputIt __last) { + typedef typename iterator_traits<_InputIt>::value_type _ItVal; + __pn_.clear(); + _PathCVT<_ItVal>::__append_range(__pn_, __first, __last); + return *this; + } + +public: + // appends +#if defined(_LIBCPP_WIN32API) + _LIBCPP_HIDE_FROM_ABI + path& operator/=(const path& __p) { + auto __p_root_name = __p.__root_name(); + auto __p_root_name_size = __p_root_name.size(); + if (__p.is_absolute() || + (!__p_root_name.empty() && __p_root_name != __string_view(root_name().__pn_))) { + __pn_ = __p.__pn_; + return *this; + } + if (__p.has_root_directory()) { + path __root_name_str = root_name(); + __pn_ = __root_name_str.native(); + __pn_ += __string_view(__p.__pn_).substr(__p_root_name_size); + return *this; + } + if (has_filename() || (!has_root_directory() && is_absolute())) + __pn_ += preferred_separator; + __pn_ += __string_view(__p.__pn_).substr(__p_root_name_size); + return *this; + } + template + _LIBCPP_INLINE_VISIBILITY _EnableIfPathable<_Source> + operator/=(const _Source& __src) { + return operator/=(path(__src)); + } + + template + _LIBCPP_HIDE_FROM_ABI + _EnableIfPathable<_Source> append(const _Source& __src) { + return operator/=(path(__src)); + } + + template + _LIBCPP_HIDE_FROM_ABI + path& append(_InputIt __first, _InputIt __last) { + return operator/=(path(__first, __last)); + } +#else + _LIBCPP_HIDE_FROM_ABI + path& operator/=(const path& __p) { + if (__p.is_absolute()) { + __pn_ = __p.__pn_; + return *this; + } + if (has_filename()) + __pn_ += preferred_separator; + __pn_ += __p.native(); + return *this; + } + + // FIXME: Use _LIBCPP_DIAGNOSE_WARNING to produce a diagnostic when __src + // is known at compile time to be "/' since the user almost certainly intended + // to append a separator instead of overwriting the path with "/" + template + _LIBCPP_HIDE_FROM_ABI _EnableIfPathable<_Source> + operator/=(const _Source& __src) { + return this->append(__src); + } + + template + _LIBCPP_HIDE_FROM_ABI + _EnableIfPathable<_Source> append(const _Source& __src) { + using _Traits = __is_pathable<_Source>; + using _CVT = _PathCVT<_SourceChar<_Source> >; + bool __source_is_absolute = _VSTD_FS::__is_separator(_Traits::__first_or_null(__src)); + if (__source_is_absolute) + __pn_.clear(); + else if (has_filename()) + __pn_ += preferred_separator; + _CVT::__append_source(__pn_, __src); + return *this; + } + + template + _LIBCPP_HIDE_FROM_ABI + path& append(_InputIt __first, _InputIt __last) { + typedef typename iterator_traits<_InputIt>::value_type _ItVal; + static_assert(__can_convert_char<_ItVal>::value, "Must convertible"); + using _CVT = _PathCVT<_ItVal>; + if (__first != __last && _VSTD_FS::__is_separator(*__first)) + __pn_.clear(); + else if (has_filename()) + __pn_ += preferred_separator; + _CVT::__append_range(__pn_, __first, __last); + return *this; + } +#endif + + // concatenation + _LIBCPP_HIDE_FROM_ABI + path& operator+=(const path& __x) { + __pn_ += __x.__pn_; + return *this; + } + + _LIBCPP_HIDE_FROM_ABI + path& operator+=(const string_type& __x) { + __pn_ += __x; + return *this; + } + + _LIBCPP_HIDE_FROM_ABI + path& operator+=(__string_view __x) { + __pn_ += __x; + return *this; + } + + _LIBCPP_HIDE_FROM_ABI + path& operator+=(const value_type* __x) { + __pn_ += __x; + return *this; + } + + _LIBCPP_HIDE_FROM_ABI + path& operator+=(value_type __x) { + __pn_ += __x; + return *this; + } + + template + _LIBCPP_HIDE_FROM_ABI + typename enable_if<__can_convert_char<_ECharT>::value, path&>::type + operator+=(_ECharT __x) { + _PathCVT<_ECharT>::__append_source(__pn_, + basic_string_view<_ECharT>(&__x, 1)); + return *this; + } + + template + _LIBCPP_HIDE_FROM_ABI + _EnableIfPathable<_Source> operator+=(const _Source& __x) { + return this->concat(__x); + } + + template + _LIBCPP_HIDE_FROM_ABI + _EnableIfPathable<_Source> concat(const _Source& __x) { + _SourceCVT<_Source>::__append_source(__pn_, __x); + return *this; + } + + template + _LIBCPP_HIDE_FROM_ABI + path& concat(_InputIt __first, _InputIt __last) { + typedef typename iterator_traits<_InputIt>::value_type _ItVal; + _PathCVT<_ItVal>::__append_range(__pn_, __first, __last); + return *this; + } + + // modifiers + _LIBCPP_HIDE_FROM_ABI + void clear() noexcept { __pn_.clear(); } + + _LIBCPP_HIDE_FROM_ABI + path& make_preferred() { +#if defined(_LIBCPP_WIN32API) + _VSTD::replace(__pn_.begin(), __pn_.end(), L'/', L'\\'); +#endif + return *this; + } + + _LIBCPP_HIDE_FROM_ABI + path& remove_filename() { + auto __fname = __filename(); + if (!__fname.empty()) + __pn_.erase(__fname.data() - __pn_.data()); + return *this; + } + + _LIBCPP_HIDE_FROM_ABI + path& replace_filename(const path& __replacement) { + remove_filename(); + return (*this /= __replacement); + } + + path& replace_extension(const path& __replacement = path()); + + friend _LIBCPP_HIDE_FROM_ABI bool operator==(const path& __lhs, const path& __rhs) noexcept { + return __lhs.__compare(__rhs.__pn_) == 0; + } +# if _LIBCPP_STD_VER <= 17 + friend _LIBCPP_HIDE_FROM_ABI bool operator!=(const path& __lhs, const path& __rhs) noexcept { + return __lhs.__compare(__rhs.__pn_) != 0; + } + friend _LIBCPP_HIDE_FROM_ABI bool operator<(const path& __lhs, const path& __rhs) noexcept { + return __lhs.__compare(__rhs.__pn_) < 0; + } + friend _LIBCPP_HIDE_FROM_ABI bool operator<=(const path& __lhs, const path& __rhs) noexcept { + return __lhs.__compare(__rhs.__pn_) <= 0; + } + friend _LIBCPP_HIDE_FROM_ABI bool operator>(const path& __lhs, const path& __rhs) noexcept { + return __lhs.__compare(__rhs.__pn_) > 0; + } + friend _LIBCPP_HIDE_FROM_ABI bool operator>=(const path& __lhs, const path& __rhs) noexcept { + return __lhs.__compare(__rhs.__pn_) >= 0; + } +# else // _LIBCPP_STD_VER <= 17 + friend _LIBCPP_HIDE_FROM_ABI strong_ordering operator<=>(const path& __lhs, const path& __rhs) noexcept { + return __lhs.__compare(__rhs.__pn_) <=> 0; + } +# endif // _LIBCPP_STD_VER <= 17 + + friend _LIBCPP_HIDE_FROM_ABI path operator/(const path& __lhs, const path& __rhs) { + path __result(__lhs); + __result /= __rhs; + return __result; + } + + _LIBCPP_HIDE_FROM_ABI + void swap(path& __rhs) noexcept { __pn_.swap(__rhs.__pn_); } + + // private helper to allow reserving memory in the path + _LIBCPP_HIDE_FROM_ABI + void __reserve(size_t __s) { __pn_.reserve(__s); } + + // native format observers + _LIBCPP_HIDE_FROM_ABI + const string_type& native() const noexcept { return __pn_; } + + _LIBCPP_HIDE_FROM_ABI + const value_type* c_str() const noexcept { return __pn_.c_str(); } + + _LIBCPP_HIDE_FROM_ABI operator string_type() const { return __pn_; } + +#if defined(_LIBCPP_WIN32API) + _LIBCPP_HIDE_FROM_ABI _VSTD::wstring wstring() const { return __pn_; } + + _LIBCPP_HIDE_FROM_ABI + _VSTD::wstring generic_wstring() const { + _VSTD::wstring __s; + __s.resize(__pn_.size()); + _VSTD::replace_copy(__pn_.begin(), __pn_.end(), __s.begin(), '\\', '/'); + return __s; + } + +#if !defined(_LIBCPP_HAS_NO_LOCALIZATION) + template , + class _Allocator = allocator<_ECharT> > + _LIBCPP_HIDE_FROM_ABI + basic_string<_ECharT, _Traits, _Allocator> + string(const _Allocator& __a = _Allocator()) const { + using _Str = basic_string<_ECharT, _Traits, _Allocator>; + _Str __s(__a); + __s.reserve(__pn_.size()); + _PathExport<_ECharT>::__append(__s, __pn_); + return __s; + } + + _LIBCPP_HIDE_FROM_ABI _VSTD::string string() const { + return string(); + } + _LIBCPP_HIDE_FROM_ABI __u8_string u8string() const { + using _CVT = __narrow_to_utf8; + __u8_string __s; + __s.reserve(__pn_.size()); + _CVT()(back_inserter(__s), __pn_.data(), __pn_.data() + __pn_.size()); + return __s; + } + + _LIBCPP_HIDE_FROM_ABI _VSTD::u16string u16string() const { + return string(); + } + _LIBCPP_HIDE_FROM_ABI _VSTD::u32string u32string() const { + return string(); + } + + // generic format observers + template , + class _Allocator = allocator<_ECharT> > + _LIBCPP_HIDE_FROM_ABI + basic_string<_ECharT, _Traits, _Allocator> + generic_string(const _Allocator& __a = _Allocator()) const { + using _Str = basic_string<_ECharT, _Traits, _Allocator>; + _Str __s = string<_ECharT, _Traits, _Allocator>(__a); + // Note: This (and generic_u8string below) is slightly suboptimal as + // it iterates twice over the string; once to convert it to the right + // character type, and once to replace path delimiters. + _VSTD::replace(__s.begin(), __s.end(), + static_cast<_ECharT>('\\'), static_cast<_ECharT>('/')); + return __s; + } + + _LIBCPP_HIDE_FROM_ABI _VSTD::string generic_string() const { return generic_string(); } + _LIBCPP_HIDE_FROM_ABI _VSTD::u16string generic_u16string() const { return generic_string(); } + _LIBCPP_HIDE_FROM_ABI _VSTD::u32string generic_u32string() const { return generic_string(); } + _LIBCPP_HIDE_FROM_ABI + __u8_string generic_u8string() const { + __u8_string __s = u8string(); + _VSTD::replace(__s.begin(), __s.end(), '\\', '/'); + return __s; + } +#endif /* !_LIBCPP_HAS_NO_LOCALIZATION */ +#else /* _LIBCPP_WIN32API */ + + _LIBCPP_HIDE_FROM_ABI _VSTD::string string() const { return __pn_; } +#ifndef _LIBCPP_HAS_NO_CHAR8_T + _LIBCPP_HIDE_FROM_ABI _VSTD::u8string u8string() const { return _VSTD::u8string(__pn_.begin(), __pn_.end()); } +#else + _LIBCPP_HIDE_FROM_ABI _VSTD::string u8string() const { return __pn_; } +#endif + +#if !defined(_LIBCPP_HAS_NO_LOCALIZATION) + template , + class _Allocator = allocator<_ECharT> > + _LIBCPP_HIDE_FROM_ABI + basic_string<_ECharT, _Traits, _Allocator> + string(const _Allocator& __a = _Allocator()) const { + using _CVT = __widen_from_utf8; + using _Str = basic_string<_ECharT, _Traits, _Allocator>; + _Str __s(__a); + __s.reserve(__pn_.size()); + _CVT()(std::back_inserter(__s), __pn_.data(), __pn_.data() + __pn_.size()); + return __s; + } + +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS + _LIBCPP_HIDE_FROM_ABI _VSTD::wstring wstring() const { + return string(); + } +#endif + _LIBCPP_HIDE_FROM_ABI _VSTD::u16string u16string() const { + return string(); + } + _LIBCPP_HIDE_FROM_ABI _VSTD::u32string u32string() const { + return string(); + } +#endif /* !_LIBCPP_HAS_NO_LOCALIZATION */ + + // generic format observers + _LIBCPP_HIDE_FROM_ABI _VSTD::string generic_string() const { return __pn_; } +#ifndef _LIBCPP_HAS_NO_CHAR8_T + _LIBCPP_HIDE_FROM_ABI _VSTD::u8string generic_u8string() const { return _VSTD::u8string(__pn_.begin(), __pn_.end()); } +#else + _LIBCPP_HIDE_FROM_ABI _VSTD::string generic_u8string() const { return __pn_; } +#endif + +#if !defined(_LIBCPP_HAS_NO_LOCALIZATION) + template , + class _Allocator = allocator<_ECharT> > + _LIBCPP_HIDE_FROM_ABI + basic_string<_ECharT, _Traits, _Allocator> + generic_string(const _Allocator& __a = _Allocator()) const { + return string<_ECharT, _Traits, _Allocator>(__a); + } + +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS + _LIBCPP_HIDE_FROM_ABI _VSTD::wstring generic_wstring() const { return string(); } +#endif + _LIBCPP_HIDE_FROM_ABI _VSTD::u16string generic_u16string() const { return string(); } + _LIBCPP_HIDE_FROM_ABI _VSTD::u32string generic_u32string() const { return string(); } +#endif /* !_LIBCPP_HAS_NO_LOCALIZATION */ +#endif /* !_LIBCPP_WIN32API */ + +private: + int __compare(__string_view) const; + __string_view __root_name() const; + __string_view __root_directory() const; + __string_view __root_path_raw() const; + __string_view __relative_path() const; + __string_view __parent_path() const; + __string_view __filename() const; + __string_view __stem() const; + __string_view __extension() const; + +public: + // compare + _LIBCPP_HIDE_FROM_ABI int compare(const path& __p) const noexcept { + return __compare(__p.__pn_); + } + _LIBCPP_HIDE_FROM_ABI int compare(const string_type& __s) const { + return __compare(__s); + } + _LIBCPP_HIDE_FROM_ABI int compare(__string_view __s) const { + return __compare(__s); + } + _LIBCPP_HIDE_FROM_ABI int compare(const value_type* __s) const { + return __compare(__s); + } + + // decomposition + _LIBCPP_HIDE_FROM_ABI path root_name() const { + return string_type(__root_name()); + } + _LIBCPP_HIDE_FROM_ABI path root_directory() const { + return string_type(__root_directory()); + } + _LIBCPP_HIDE_FROM_ABI path root_path() const { +#if defined(_LIBCPP_WIN32API) + return string_type(__root_path_raw()); +#else + return root_name().append(string_type(__root_directory())); +#endif + } + _LIBCPP_HIDE_FROM_ABI path relative_path() const { + return string_type(__relative_path()); + } + _LIBCPP_HIDE_FROM_ABI path parent_path() const { + return string_type(__parent_path()); + } + _LIBCPP_HIDE_FROM_ABI path filename() const { + return string_type(__filename()); + } + _LIBCPP_HIDE_FROM_ABI path stem() const { return string_type(__stem()); } + _LIBCPP_HIDE_FROM_ABI path extension() const { + return string_type(__extension()); + } + + // query + _LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_HIDE_FROM_ABI bool + empty() const noexcept { + return __pn_.empty(); + } + + _LIBCPP_HIDE_FROM_ABI bool has_root_name() const { + return !__root_name().empty(); + } + _LIBCPP_HIDE_FROM_ABI bool has_root_directory() const { + return !__root_directory().empty(); + } + _LIBCPP_HIDE_FROM_ABI bool has_root_path() const { + return !__root_path_raw().empty(); + } + _LIBCPP_HIDE_FROM_ABI bool has_relative_path() const { + return !__relative_path().empty(); + } + _LIBCPP_HIDE_FROM_ABI bool has_parent_path() const { + return !__parent_path().empty(); + } + _LIBCPP_HIDE_FROM_ABI bool has_filename() const { + return !__filename().empty(); + } + _LIBCPP_HIDE_FROM_ABI bool has_stem() const { return !__stem().empty(); } + _LIBCPP_HIDE_FROM_ABI bool has_extension() const { + return !__extension().empty(); + } + + _LIBCPP_HIDE_FROM_ABI bool is_absolute() const { +#if defined(_LIBCPP_WIN32API) + __string_view __root_name_str = __root_name(); + __string_view __root_dir = __root_directory(); + if (__root_name_str.size() == 2 && __root_name_str[1] == ':') { + // A drive letter with no root directory is relative, e.g. x:example. + return !__root_dir.empty(); + } + // If no root name, it's relative, e.g. \example is relative to the current drive + if (__root_name_str.empty()) + return false; + if (__root_name_str.size() < 3) + return false; + // A server root name, like \\server, is always absolute + if (__root_name_str[0] != '/' && __root_name_str[0] != '\\') + return false; + if (__root_name_str[1] != '/' && __root_name_str[1] != '\\') + return false; + // Seems to be a server root name + return true; +#else + return has_root_directory(); +#endif + } + _LIBCPP_HIDE_FROM_ABI bool is_relative() const { return !is_absolute(); } + + // relative paths + path lexically_normal() const; + path lexically_relative(const path& __base) const; + + _LIBCPP_HIDE_FROM_ABI path lexically_proximate(const path& __base) const { + path __result = this->lexically_relative(__base); + if (__result.native().empty()) + return *this; + return __result; + } + + // iterators + class _LIBCPP_TYPE_VIS iterator; + typedef iterator const_iterator; + + iterator begin() const; + iterator end() const; + +#if !defined(_LIBCPP_HAS_NO_LOCALIZATION) + template + _LIBCPP_HIDE_FROM_ABI friend + typename enable_if::value && + is_same<_Traits, char_traits >::value, + basic_ostream<_CharT, _Traits>&>::type + operator<<(basic_ostream<_CharT, _Traits>& __os, const path& __p) { + __os << _VSTD::__quoted(__p.native()); + return __os; + } + + template + _LIBCPP_HIDE_FROM_ABI friend + typename enable_if::value || + !is_same<_Traits, char_traits >::value, + basic_ostream<_CharT, _Traits>&>::type + operator<<(basic_ostream<_CharT, _Traits>& __os, const path& __p) { + __os << _VSTD::__quoted(__p.string<_CharT, _Traits>()); + return __os; + } + + template + _LIBCPP_HIDE_FROM_ABI friend basic_istream<_CharT, _Traits>& + operator>>(basic_istream<_CharT, _Traits>& __is, path& __p) { + basic_string<_CharT, _Traits> __tmp; + __is >> _VSTD::__quoted(__tmp); + __p = __tmp; + return __is; + } +#endif // !_LIBCPP_HAS_NO_LOCALIZATION + +private: + inline _LIBCPP_HIDE_FROM_ABI path& + __assign_view(__string_view const& __s) noexcept { + __pn_ = string_type(__s); + return *this; + } + string_type __pn_; +}; + +inline _LIBCPP_HIDE_FROM_ABI void swap(path& __lhs, path& __rhs) noexcept { + __lhs.swap(__rhs); +} + +_LIBCPP_FUNC_VIS +size_t hash_value(const path& __p) noexcept; + +_LIBCPP_AVAILABILITY_FILESYSTEM_POP + +_LIBCPP_END_NAMESPACE_FILESYSTEM + +#endif // _LIBCPP_CXX03_LANG + +#endif // _LIBCPP___FILESYSTEM_PATH_H diff --git a/app/src/main/cpp/libcxx/include/__filesystem/path_iterator.h b/app/src/main/cpp/libcxx/include/__filesystem/path_iterator.h new file mode 100644 index 0000000..6f2baf8 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__filesystem/path_iterator.h @@ -0,0 +1,134 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___FILESYSTEM_PATH_ITERATOR_H +#define _LIBCPP___FILESYSTEM_PATH_ITERATOR_H + +#include <__assert> +#include <__availability> +#include <__config> +#include <__filesystem/path.h> +#include <__iterator/iterator_traits.h> +#include +#include +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#ifndef _LIBCPP_CXX03_LANG + +_LIBCPP_BEGIN_NAMESPACE_FILESYSTEM + +_LIBCPP_AVAILABILITY_FILESYSTEM_PUSH + +class _LIBCPP_TYPE_VIS path::iterator { +public: + enum _ParserState : unsigned char { + _Singular, + _BeforeBegin, + _InRootName, + _InRootDir, + _InFilenames, + _InTrailingSep, + _AtEnd + }; + +public: + typedef input_iterator_tag iterator_category; + typedef bidirectional_iterator_tag iterator_concept; + + typedef path value_type; + typedef ptrdiff_t difference_type; + typedef const path* pointer; + typedef path reference; + +public: + _LIBCPP_INLINE_VISIBILITY + iterator() + : __stashed_elem_(), __path_ptr_(nullptr), __entry_(), + __state_(_Singular) {} + + iterator(const iterator&) = default; + ~iterator() = default; + + iterator& operator=(const iterator&) = default; + + _LIBCPP_INLINE_VISIBILITY + reference operator*() const { return __stashed_elem_; } + + _LIBCPP_INLINE_VISIBILITY + pointer operator->() const { return &__stashed_elem_; } + + _LIBCPP_INLINE_VISIBILITY + iterator& operator++() { + _LIBCPP_ASSERT(__state_ != _Singular, + "attempting to increment a singular iterator"); + _LIBCPP_ASSERT(__state_ != _AtEnd, + "attempting to increment the end iterator"); + return __increment(); + } + + _LIBCPP_INLINE_VISIBILITY + iterator operator++(int) { + iterator __it(*this); + this->operator++(); + return __it; + } + + _LIBCPP_INLINE_VISIBILITY + iterator& operator--() { + _LIBCPP_ASSERT(__state_ != _Singular, + "attempting to decrement a singular iterator"); + _LIBCPP_ASSERT(__entry_.data() != __path_ptr_->native().data(), + "attempting to decrement the begin iterator"); + return __decrement(); + } + + _LIBCPP_INLINE_VISIBILITY + iterator operator--(int) { + iterator __it(*this); + this->operator--(); + return __it; + } + +private: + friend class path; + + inline _LIBCPP_INLINE_VISIBILITY friend bool operator==(const iterator&, + const iterator&); + + iterator& __increment(); + iterator& __decrement(); + + path __stashed_elem_; + const path* __path_ptr_; + path::__string_view __entry_; + _ParserState __state_; +}; + +inline _LIBCPP_INLINE_VISIBILITY bool operator==(const path::iterator& __lhs, + const path::iterator& __rhs) { + return __lhs.__path_ptr_ == __rhs.__path_ptr_ && + __lhs.__entry_.data() == __rhs.__entry_.data(); +} + +inline _LIBCPP_INLINE_VISIBILITY bool operator!=(const path::iterator& __lhs, + const path::iterator& __rhs) { + return !(__lhs == __rhs); +} + +_LIBCPP_AVAILABILITY_FILESYSTEM_POP + +_LIBCPP_END_NAMESPACE_FILESYSTEM + +#endif // _LIBCPP_CXX03_LANG + +#endif // _LIBCPP___FILESYSTEM_PATH_ITERATOR_H diff --git a/app/src/main/cpp/libcxx/include/__filesystem/perm_options.h b/app/src/main/cpp/libcxx/include/__filesystem/perm_options.h new file mode 100644 index 0000000..4aba302 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__filesystem/perm_options.h @@ -0,0 +1,77 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___FILESYSTEM_PERM_OPTIONS_H +#define _LIBCPP___FILESYSTEM_PERM_OPTIONS_H + +#include <__availability> +#include <__config> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#ifndef _LIBCPP_CXX03_LANG + +_LIBCPP_BEGIN_NAMESPACE_FILESYSTEM + +_LIBCPP_AVAILABILITY_FILESYSTEM_PUSH + +enum class _LIBCPP_ENUM_VIS perm_options : unsigned char { + replace = 1, + add = 2, + remove = 4, + nofollow = 8 +}; + +_LIBCPP_INLINE_VISIBILITY +inline constexpr perm_options operator&(perm_options __lhs, perm_options __rhs) { + return static_cast(static_cast(__lhs) & + static_cast(__rhs)); +} + +_LIBCPP_INLINE_VISIBILITY +inline constexpr perm_options operator|(perm_options __lhs, perm_options __rhs) { + return static_cast(static_cast(__lhs) | + static_cast(__rhs)); +} + +_LIBCPP_INLINE_VISIBILITY +inline constexpr perm_options operator^(perm_options __lhs, perm_options __rhs) { + return static_cast(static_cast(__lhs) ^ + static_cast(__rhs)); +} + +_LIBCPP_INLINE_VISIBILITY +inline constexpr perm_options operator~(perm_options __lhs) { + return static_cast(~static_cast(__lhs)); +} + +_LIBCPP_INLINE_VISIBILITY +inline perm_options& operator&=(perm_options& __lhs, perm_options __rhs) { + return __lhs = __lhs & __rhs; +} + +_LIBCPP_INLINE_VISIBILITY +inline perm_options& operator|=(perm_options& __lhs, perm_options __rhs) { + return __lhs = __lhs | __rhs; +} + +_LIBCPP_INLINE_VISIBILITY +inline perm_options& operator^=(perm_options& __lhs, perm_options __rhs) { + return __lhs = __lhs ^ __rhs; +} + +_LIBCPP_AVAILABILITY_FILESYSTEM_POP + +_LIBCPP_END_NAMESPACE_FILESYSTEM + +#endif // _LIBCPP_CXX03_LANG + +#endif // _LIBCPP___FILESYSTEM_PERM_OPTIONS_H diff --git a/app/src/main/cpp/libcxx/include/__filesystem/perms.h b/app/src/main/cpp/libcxx/include/__filesystem/perms.h new file mode 100644 index 0000000..df45900 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__filesystem/perms.h @@ -0,0 +1,95 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___FILESYSTEM_PERMS_H +#define _LIBCPP___FILESYSTEM_PERMS_H + +#include <__availability> +#include <__config> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#ifndef _LIBCPP_CXX03_LANG + +_LIBCPP_BEGIN_NAMESPACE_FILESYSTEM + +_LIBCPP_AVAILABILITY_FILESYSTEM_PUSH + +// On Windows, these permission bits map to one single readonly flag per +// file, and the executable bit is always returned as set. When setting +// permissions, as long as the write bit is set for either owner, group or +// others, the readonly flag is cleared. +enum class _LIBCPP_ENUM_VIS perms : unsigned { + none = 0, + + owner_read = 0400, + owner_write = 0200, + owner_exec = 0100, + owner_all = 0700, + + group_read = 040, + group_write = 020, + group_exec = 010, + group_all = 070, + + others_read = 04, + others_write = 02, + others_exec = 01, + others_all = 07, + + all = 0777, + + set_uid = 04000, + set_gid = 02000, + sticky_bit = 01000, + mask = 07777, + unknown = 0xFFFF, +}; + +_LIBCPP_INLINE_VISIBILITY +inline constexpr perms operator&(perms __lhs, perms __rhs) { + return static_cast(static_cast(__lhs) & + static_cast(__rhs)); +} + +_LIBCPP_INLINE_VISIBILITY +inline constexpr perms operator|(perms __lhs, perms __rhs) { + return static_cast(static_cast(__lhs) | + static_cast(__rhs)); +} + +_LIBCPP_INLINE_VISIBILITY +inline constexpr perms operator^(perms __lhs, perms __rhs) { + return static_cast(static_cast(__lhs) ^ + static_cast(__rhs)); +} + +_LIBCPP_INLINE_VISIBILITY +inline constexpr perms operator~(perms __lhs) { + return static_cast(~static_cast(__lhs)); +} + +_LIBCPP_INLINE_VISIBILITY +inline perms& operator&=(perms& __lhs, perms __rhs) { return __lhs = __lhs & __rhs; } + +_LIBCPP_INLINE_VISIBILITY +inline perms& operator|=(perms& __lhs, perms __rhs) { return __lhs = __lhs | __rhs; } + +_LIBCPP_INLINE_VISIBILITY +inline perms& operator^=(perms& __lhs, perms __rhs) { return __lhs = __lhs ^ __rhs; } + +_LIBCPP_AVAILABILITY_FILESYSTEM_POP + +_LIBCPP_END_NAMESPACE_FILESYSTEM + +#endif // _LIBCPP_CXX03_LANG + +#endif // _LIBCPP___FILESYSTEM_PERMS_H diff --git a/app/src/main/cpp/libcxx/include/__filesystem/recursive_directory_iterator.h b/app/src/main/cpp/libcxx/include/__filesystem/recursive_directory_iterator.h new file mode 100644 index 0000000..b20d201 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__filesystem/recursive_directory_iterator.h @@ -0,0 +1,185 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___FILESYSTEM_RECURSIVE_DIRECTORY_ITERATOR_H +#define _LIBCPP___FILESYSTEM_RECURSIVE_DIRECTORY_ITERATOR_H + +#include <__availability> +#include <__config> +#include <__filesystem/directory_entry.h> +#include <__filesystem/directory_options.h> +#include <__filesystem/path.h> +#include <__iterator/iterator_traits.h> +#include <__memory/shared_ptr.h> +#include <__ranges/enable_borrowed_range.h> +#include <__ranges/enable_view.h> +#include +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#ifndef _LIBCPP_CXX03_LANG + +_LIBCPP_BEGIN_NAMESPACE_FILESYSTEM + +_LIBCPP_AVAILABILITY_FILESYSTEM_PUSH + +class recursive_directory_iterator { +public: + using value_type = directory_entry; + using difference_type = ptrdiff_t; + using pointer = directory_entry const*; + using reference = directory_entry const&; + using iterator_category = input_iterator_tag; + +public: + // constructors and destructor + _LIBCPP_INLINE_VISIBILITY + recursive_directory_iterator() noexcept : __rec_(false) {} + + _LIBCPP_INLINE_VISIBILITY + explicit recursive_directory_iterator( + const path& __p, directory_options __xoptions = directory_options::none) + : recursive_directory_iterator(__p, __xoptions, nullptr) {} + + _LIBCPP_INLINE_VISIBILITY + recursive_directory_iterator(const path& __p, directory_options __xoptions, + error_code& __ec) + : recursive_directory_iterator(__p, __xoptions, &__ec) {} + + _LIBCPP_INLINE_VISIBILITY + recursive_directory_iterator(const path& __p, error_code& __ec) + : recursive_directory_iterator(__p, directory_options::none, &__ec) {} + + recursive_directory_iterator(const recursive_directory_iterator&) = default; + recursive_directory_iterator(recursive_directory_iterator&&) = default; + + recursive_directory_iterator& + operator=(const recursive_directory_iterator&) = default; + + _LIBCPP_INLINE_VISIBILITY + recursive_directory_iterator& + operator=(recursive_directory_iterator&& __o) noexcept { + // non-default implementation provided to support self-move assign. + if (this != &__o) { + __imp_ = _VSTD::move(__o.__imp_); + __rec_ = __o.__rec_; + } + return *this; + } + + ~recursive_directory_iterator() = default; + + _LIBCPP_INLINE_VISIBILITY + const directory_entry& operator*() const { return __dereference(); } + + _LIBCPP_INLINE_VISIBILITY + const directory_entry* operator->() const { return &__dereference(); } + + recursive_directory_iterator& operator++() { return __increment(); } + + _LIBCPP_INLINE_VISIBILITY + __dir_element_proxy operator++(int) { + __dir_element_proxy __p(**this); + __increment(); + return __p; + } + + _LIBCPP_INLINE_VISIBILITY + recursive_directory_iterator& increment(error_code& __ec) { + return __increment(&__ec); + } + + _LIBCPP_FUNC_VIS directory_options options() const; + _LIBCPP_FUNC_VIS int depth() const; + + _LIBCPP_INLINE_VISIBILITY + void pop() { __pop(); } + + _LIBCPP_INLINE_VISIBILITY + void pop(error_code& __ec) { __pop(&__ec); } + + _LIBCPP_INLINE_VISIBILITY + bool recursion_pending() const { return __rec_; } + + _LIBCPP_INLINE_VISIBILITY + void disable_recursion_pending() { __rec_ = false; } + +private: + _LIBCPP_FUNC_VIS + recursive_directory_iterator(const path& __p, directory_options __opt, + error_code* __ec); + + _LIBCPP_FUNC_VIS + const directory_entry& __dereference() const; + + _LIBCPP_FUNC_VIS + bool __try_recursion(error_code* __ec); + + _LIBCPP_FUNC_VIS + void __advance(error_code* __ec = nullptr); + + _LIBCPP_FUNC_VIS + recursive_directory_iterator& __increment(error_code* __ec = nullptr); + + _LIBCPP_FUNC_VIS + void __pop(error_code* __ec = nullptr); + + inline _LIBCPP_INLINE_VISIBILITY friend bool + operator==(const recursive_directory_iterator&, + const recursive_directory_iterator&) noexcept; + + struct _LIBCPP_HIDDEN __shared_imp; + shared_ptr<__shared_imp> __imp_; + bool __rec_; +}; // class recursive_directory_iterator + +inline _LIBCPP_INLINE_VISIBILITY bool +operator==(const recursive_directory_iterator& __lhs, + const recursive_directory_iterator& __rhs) noexcept { + return __lhs.__imp_ == __rhs.__imp_; +} + +_LIBCPP_INLINE_VISIBILITY +inline bool operator!=(const recursive_directory_iterator& __lhs, + const recursive_directory_iterator& __rhs) noexcept { + return !(__lhs == __rhs); +} +// enable recursive_directory_iterator range-based for statements +inline _LIBCPP_INLINE_VISIBILITY recursive_directory_iterator +begin(recursive_directory_iterator __iter) noexcept { + return __iter; +} + +inline _LIBCPP_INLINE_VISIBILITY recursive_directory_iterator +end(recursive_directory_iterator) noexcept { + return recursive_directory_iterator(); +} + +_LIBCPP_AVAILABILITY_FILESYSTEM_POP + +_LIBCPP_END_NAMESPACE_FILESYSTEM + +#if _LIBCPP_STD_VER > 17 + +template <> +_LIBCPP_AVAILABILITY_FILESYSTEM +inline constexpr bool _VSTD::ranges::enable_borrowed_range<_VSTD_FS::recursive_directory_iterator> = true; + +template <> +_LIBCPP_AVAILABILITY_FILESYSTEM +inline constexpr bool _VSTD::ranges::enable_view<_VSTD_FS::recursive_directory_iterator> = true; + +#endif // _LIBCPP_STD_VER > 17 + +#endif // _LIBCPP_CXX03_LANG + +#endif // _LIBCPP___FILESYSTEM_RECURSIVE_DIRECTORY_ITERATOR_H diff --git a/app/src/main/cpp/libcxx/include/__filesystem/space_info.h b/app/src/main/cpp/libcxx/include/__filesystem/space_info.h new file mode 100644 index 0000000..d0747e3 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__filesystem/space_info.h @@ -0,0 +1,43 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___FILESYSTEM_SPACE_INFO_H +#define _LIBCPP___FILESYSTEM_SPACE_INFO_H + +#include <__availability> +#include <__config> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#ifndef _LIBCPP_CXX03_LANG + +_LIBCPP_BEGIN_NAMESPACE_FILESYSTEM + +_LIBCPP_AVAILABILITY_FILESYSTEM_PUSH + +struct _LIBCPP_TYPE_VIS space_info { + uintmax_t capacity; + uintmax_t free; + uintmax_t available; + +# if _LIBCPP_STD_VER > 17 + friend _LIBCPP_HIDE_FROM_ABI bool operator==(const space_info&, const space_info&) = default; +# endif +}; + +_LIBCPP_AVAILABILITY_FILESYSTEM_POP + +_LIBCPP_END_NAMESPACE_FILESYSTEM + +#endif // _LIBCPP_CXX03_LANG + +#endif // _LIBCPP___FILESYSTEM_SPACE_INFO_H diff --git a/app/src/main/cpp/libcxx/include/__filesystem/u8path.h b/app/src/main/cpp/libcxx/include/__filesystem/u8path.h new file mode 100644 index 0000000..d35faa1 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__filesystem/u8path.h @@ -0,0 +1,108 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___FILESYSTEM_U8PATH_H +#define _LIBCPP___FILESYSTEM_U8PATH_H + +#include <__algorithm/unwrap_iter.h> +#include <__availability> +#include <__config> +#include <__filesystem/path.h> +#include +#include + +// Only required on Windows for __widen_from_utf8, and included conservatively +// because it requires support for localization. +#if defined(_LIBCPP_WIN32API) +# include +#endif + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#ifndef _LIBCPP_CXX03_LANG + +_LIBCPP_BEGIN_NAMESPACE_FILESYSTEM + +_LIBCPP_AVAILABILITY_FILESYSTEM_PUSH + +template +_LIBCPP_INLINE_VISIBILITY _LIBCPP_DEPRECATED_WITH_CHAR8_T + typename enable_if<__is_pathable<_InputIt>::value, path>::type + u8path(_InputIt __f, _InputIt __l) { + static_assert( +#ifndef _LIBCPP_HAS_NO_CHAR8_T + is_same::__char_type, char8_t>::value || +#endif + is_same::__char_type, char>::value, + "u8path(Iter, Iter) requires Iter have a value_type of type 'char'" + " or 'char8_t'"); +#if defined(_LIBCPP_WIN32API) + string __tmp(__f, __l); + using _CVT = __widen_from_utf8; + _VSTD::wstring __w; + __w.reserve(__tmp.size()); + _CVT()(back_inserter(__w), __tmp.data(), __tmp.data() + __tmp.size()); + return path(__w); +#else + return path(__f, __l); +#endif /* !_LIBCPP_WIN32API */ +} + +#if defined(_LIBCPP_WIN32API) +template +_LIBCPP_INLINE_VISIBILITY _LIBCPP_DEPRECATED_WITH_CHAR8_T + typename enable_if<__is_pathable<_InputIt>::value, path>::type + u8path(_InputIt __f, _NullSentinel) { + static_assert( +#ifndef _LIBCPP_HAS_NO_CHAR8_T + is_same::__char_type, char8_t>::value || +#endif + is_same::__char_type, char>::value, + "u8path(Iter, Iter) requires Iter have a value_type of type 'char'" + " or 'char8_t'"); + string __tmp; + const char __sentinel = char{}; + for (; *__f != __sentinel; ++__f) + __tmp.push_back(*__f); + using _CVT = __widen_from_utf8; + _VSTD::wstring __w; + __w.reserve(__tmp.size()); + _CVT()(back_inserter(__w), __tmp.data(), __tmp.data() + __tmp.size()); + return path(__w); +} +#endif /* _LIBCPP_WIN32API */ + +template +_LIBCPP_INLINE_VISIBILITY _LIBCPP_DEPRECATED_WITH_CHAR8_T + typename enable_if<__is_pathable<_Source>::value, path>::type + u8path(const _Source& __s) { + static_assert( +#ifndef _LIBCPP_HAS_NO_CHAR8_T + is_same::__char_type, char8_t>::value || +#endif + is_same::__char_type, char>::value, + "u8path(Source const&) requires Source have a character type of type " + "'char' or 'char8_t'"); +#if defined(_LIBCPP_WIN32API) + using _Traits = __is_pathable<_Source>; + return u8path(_VSTD::__unwrap_iter(_Traits::__range_begin(__s)), _VSTD::__unwrap_iter(_Traits::__range_end(__s))); +#else + return path(__s); +#endif +} + +_LIBCPP_AVAILABILITY_FILESYSTEM_POP + +_LIBCPP_END_NAMESPACE_FILESYSTEM + +#endif // _LIBCPP_CXX03_LANG + +#endif // _LIBCPP___FILESYSTEM_U8PATH_H diff --git a/app/src/main/cpp/libcxx/include/__format/buffer.h b/app/src/main/cpp/libcxx/include/__format/buffer.h new file mode 100644 index 0000000..ddfe767 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__format/buffer.h @@ -0,0 +1,573 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___FORMAT_BUFFER_H +#define _LIBCPP___FORMAT_BUFFER_H + +#include <__algorithm/copy_n.h> +#include <__algorithm/fill_n.h> +#include <__algorithm/max.h> +#include <__algorithm/min.h> +#include <__algorithm/ranges_copy_n.h> +#include <__algorithm/transform.h> +#include <__algorithm/unwrap_iter.h> +#include <__concepts/same_as.h> +#include <__config> +#include <__format/concepts.h> +#include <__format/enable_insertable.h> +#include <__format/format_to_n_result.h> +#include <__iterator/back_insert_iterator.h> +#include <__iterator/concepts.h> +#include <__iterator/incrementable_traits.h> +#include <__iterator/iterator_traits.h> +#include <__iterator/wrap_iter.h> +#include <__utility/move.h> +#include +#include +#include +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 17 + +namespace __format { + +/// A "buffer" that handles writing to the proper iterator. +/// +/// This helper is used together with the @ref back_insert_iterator to offer +/// type-erasure for the formatting functions. This reduces the number to +/// template instantiations. +template <__fmt_char_type _CharT> +class _LIBCPP_TEMPLATE_VIS __output_buffer { +public: + using value_type = _CharT; + + template + _LIBCPP_HIDE_FROM_ABI explicit __output_buffer(_CharT* __ptr, size_t __capacity, _Tp* __obj) + : __ptr_(__ptr), + __capacity_(__capacity), + __flush_([](_CharT* __p, size_t __n, void* __o) { static_cast<_Tp*>(__o)->__flush(__p, __n); }), + __obj_(__obj) {} + + _LIBCPP_HIDE_FROM_ABI void __reset(_CharT* __ptr, size_t __capacity) { + __ptr_ = __ptr; + __capacity_ = __capacity; + } + + _LIBCPP_HIDE_FROM_ABI auto __make_output_iterator() { return std::back_insert_iterator{*this}; } + + // Used in std::back_insert_iterator. + _LIBCPP_HIDE_FROM_ABI void push_back(_CharT __c) { + __ptr_[__size_++] = __c; + + // Profiling showed flushing after adding is more efficient than flushing + // when entering the function. + if (__size_ == __capacity_) + __flush(); + } + + /// Copies the input __str to the buffer. + /// + /// Since some of the input is generated by std::to_chars, there needs to be a + /// conversion when _CharT is wchar_t. + template <__fmt_char_type _InCharT> + _LIBCPP_HIDE_FROM_ABI void __copy(basic_string_view<_InCharT> __str) { + // When the underlying iterator is a simple iterator the __capacity_ is + // infinite. For a string or container back_inserter it isn't. This means + // adding a large string the the buffer can cause some overhead. In that + // case a better approach could be: + // - flush the buffer + // - container.append(__str.begin(), __str.end()); + // The same holds true for the fill. + // For transform it might be slightly harder, however the use case for + // transform is slightly less common; it converts hexadecimal values to + // upper case. For integral these strings are short. + // TODO FMT Look at the improvements above. + size_t __n = __str.size(); + + __flush_on_overflow(__n); + if (__n <= __capacity_) { + _VSTD::copy_n(__str.data(), __n, _VSTD::addressof(__ptr_[__size_])); + __size_ += __n; + return; + } + + // The output doesn't fit in the internal buffer. + // Copy the data in "__capacity_" sized chunks. + _LIBCPP_ASSERT(__size_ == 0, "the buffer should be flushed by __flush_on_overflow"); + const _InCharT* __first = __str.data(); + do { + size_t __chunk = _VSTD::min(__n, __capacity_); + _VSTD::copy_n(__first, __chunk, _VSTD::addressof(__ptr_[__size_])); + __size_ = __chunk; + __first += __chunk; + __n -= __chunk; + __flush(); + } while (__n); + } + + /// A std::transform wrapper. + /// + /// Like @ref __copy it may need to do type conversion. + template <__fmt_char_type _InCharT, class _UnaryOperation> + _LIBCPP_HIDE_FROM_ABI void __transform(const _InCharT* __first, const _InCharT* __last, _UnaryOperation __operation) { + _LIBCPP_ASSERT(__first <= __last, "not a valid range"); + + size_t __n = static_cast(__last - __first); + __flush_on_overflow(__n); + if (__n <= __capacity_) { + _VSTD::transform(__first, __last, _VSTD::addressof(__ptr_[__size_]), _VSTD::move(__operation)); + __size_ += __n; + return; + } + + // The output doesn't fit in the internal buffer. + // Transform the data in "__capacity_" sized chunks. + _LIBCPP_ASSERT(__size_ == 0, "the buffer should be flushed by __flush_on_overflow"); + do { + size_t __chunk = _VSTD::min(__n, __capacity_); + _VSTD::transform(__first, __first + __chunk, _VSTD::addressof(__ptr_[__size_]), __operation); + __size_ = __chunk; + __first += __chunk; + __n -= __chunk; + __flush(); + } while (__n); + } + + /// A \c fill_n wrapper. + _LIBCPP_HIDE_FROM_ABI void __fill(size_t __n, _CharT __value) { + __flush_on_overflow(__n); + if (__n <= __capacity_) { + _VSTD::fill_n(_VSTD::addressof(__ptr_[__size_]), __n, __value); + __size_ += __n; + return; + } + + // The output doesn't fit in the internal buffer. + // Fill the buffer in "__capacity_" sized chunks. + _LIBCPP_ASSERT(__size_ == 0, "the buffer should be flushed by __flush_on_overflow"); + do { + size_t __chunk = _VSTD::min(__n, __capacity_); + _VSTD::fill_n(_VSTD::addressof(__ptr_[__size_]), __chunk, __value); + __size_ = __chunk; + __n -= __chunk; + __flush(); + } while (__n); + } + + _LIBCPP_HIDE_FROM_ABI void __flush() { + __flush_(__ptr_, __size_, __obj_); + __size_ = 0; + } + +private: + _CharT* __ptr_; + size_t __capacity_; + size_t __size_{0}; + void (*__flush_)(_CharT*, size_t, void*); + void* __obj_; + + /// Flushes the buffer when the output operation would overflow the buffer. + /// + /// A simple approach for the overflow detection would be something along the + /// lines: + /// \code + /// // The internal buffer is large enough. + /// if (__n <= __capacity_) { + /// // Flush when we really would overflow. + /// if (__size_ + __n >= __capacity_) + /// __flush(); + /// ... + /// } + /// \endcode + /// + /// This approach works for all cases but one: + /// A __format_to_n_buffer_base where \ref __enable_direct_output is true. + /// In that case the \ref __capacity_ of the buffer changes during the first + /// \ref __flush. During that operation the output buffer switches from its + /// __writer_ to its __storage_. The \ref __capacity_ of the former depends + /// on the value of n, of the latter is a fixed size. For example: + /// - a format_to_n call with a 10'000 char buffer, + /// - the buffer is filled with 9'500 chars, + /// - adding 1'000 elements would overflow the buffer so the buffer gets + /// changed and the \ref __capacity_ decreases from 10'000 to + /// __buffer_size (256 at the time of writing). + /// + /// This means that the \ref __flush for this class may need to copy a part of + /// the internal buffer to the proper output. In this example there will be + /// 500 characters that need this copy operation. + /// + /// Note it would be more efficient to write 500 chars directly and then swap + /// the buffers. This would make the code more complex and \ref format_to_n is + /// not the most common use case. Therefore the optimization isn't done. + _LIBCPP_HIDE_FROM_ABI void __flush_on_overflow(size_t __n) { + if (__size_ + __n >= __capacity_) + __flush(); + } +}; + +/// A storage using an internal buffer. +/// +/// This storage is used when writing a single element to the output iterator +/// is expensive. +template <__fmt_char_type _CharT> +class _LIBCPP_TEMPLATE_VIS __internal_storage { +public: + _LIBCPP_HIDE_FROM_ABI _CharT* __begin() { return __buffer_; } + + static constexpr size_t __buffer_size = 256 / sizeof(_CharT); + +private: + _CharT __buffer_[__buffer_size]; +}; + +/// A storage writing directly to the storage. +/// +/// This requires the storage to be a contiguous buffer of \a _CharT. +/// Since the output is directly written to the underlying storage this class +/// is just an empty class. +template <__fmt_char_type _CharT> +class _LIBCPP_TEMPLATE_VIS __direct_storage {}; + +template +concept __enable_direct_output = __fmt_char_type<_CharT> && + (same_as<_OutIt, _CharT*> +#ifndef _LIBCPP_ENABLE_DEBUG_MODE + || same_as<_OutIt, __wrap_iter<_CharT*>> +#endif + ); + +/// Write policy for directly writing to the underlying output. +template +class _LIBCPP_TEMPLATE_VIS __writer_direct { +public: + _LIBCPP_HIDE_FROM_ABI explicit __writer_direct(_OutIt __out_it) + : __out_it_(__out_it) {} + + _LIBCPP_HIDE_FROM_ABI _OutIt __out_it() { return __out_it_; } + + _LIBCPP_HIDE_FROM_ABI void __flush(_CharT*, size_t __n) { + // _OutIt can be a __wrap_iter. Therefore the original iterator + // is adjusted. + __out_it_ += __n; + } + +private: + _OutIt __out_it_; +}; + +/// Write policy for copying the buffer to the output. +template +class _LIBCPP_TEMPLATE_VIS __writer_iterator { +public: + _LIBCPP_HIDE_FROM_ABI explicit __writer_iterator(_OutIt __out_it) + : __out_it_{_VSTD::move(__out_it)} {} + + _LIBCPP_HIDE_FROM_ABI _OutIt __out_it() && { return std::move(__out_it_); } + + _LIBCPP_HIDE_FROM_ABI void __flush(_CharT* __ptr, size_t __n) { + __out_it_ = std::ranges::copy_n(__ptr, __n, std::move(__out_it_)).out; + } + +private: + _OutIt __out_it_; +}; + +/// Concept to see whether a \a _Container is insertable. +/// +/// The concept is used to validate whether multiple calls to a +/// \ref back_insert_iterator can be replace by a call to \c _Container::insert. +/// +/// \note a \a _Container needs to opt-in to the concept by specializing +/// \ref __enable_insertable. +template +concept __insertable = + __enable_insertable<_Container> && __fmt_char_type && + requires(_Container& __t, add_pointer_t __first, + add_pointer_t __last) { __t.insert(__t.end(), __first, __last); }; + +/// Extract the container type of a \ref back_insert_iterator. +template +struct _LIBCPP_TEMPLATE_VIS __back_insert_iterator_container { + using type = void; +}; + +template <__insertable _Container> +struct _LIBCPP_TEMPLATE_VIS __back_insert_iterator_container> { + using type = _Container; +}; + +/// Write policy for inserting the buffer in a container. +template +class _LIBCPP_TEMPLATE_VIS __writer_container { +public: + using _CharT = typename _Container::value_type; + + _LIBCPP_HIDE_FROM_ABI explicit __writer_container(back_insert_iterator<_Container> __out_it) + : __container_{__out_it.__get_container()} {} + + _LIBCPP_HIDE_FROM_ABI auto __out_it() { return std::back_inserter(*__container_); } + + _LIBCPP_HIDE_FROM_ABI void __flush(_CharT* __ptr, size_t __n) { + __container_->insert(__container_->end(), __ptr, __ptr + __n); + } + +private: + _Container* __container_; +}; + +/// Selects the type of the writer used for the output iterator. +template +class _LIBCPP_TEMPLATE_VIS __writer_selector { + using _Container = typename __back_insert_iterator_container<_OutIt>::type; + +public: + using type = conditional_t, __writer_container<_Container>, + conditional_t<__enable_direct_output<_OutIt, _CharT>, __writer_direct<_OutIt, _CharT>, + __writer_iterator<_OutIt, _CharT>>>; +}; + +/// The generic formatting buffer. +template +requires(output_iterator<_OutIt, const _CharT&>) class _LIBCPP_TEMPLATE_VIS + __format_buffer { + using _Storage = + conditional_t<__enable_direct_output<_OutIt, _CharT>, + __direct_storage<_CharT>, __internal_storage<_CharT>>; + +public: + _LIBCPP_HIDE_FROM_ABI explicit __format_buffer(_OutIt __out_it) + requires(same_as<_Storage, __internal_storage<_CharT>>) + : __output_(__storage_.__begin(), __storage_.__buffer_size, this), __writer_(_VSTD::move(__out_it)) {} + + _LIBCPP_HIDE_FROM_ABI explicit __format_buffer(_OutIt __out_it) requires( + same_as<_Storage, __direct_storage<_CharT>>) + : __output_(_VSTD::__unwrap_iter(__out_it), size_t(-1), this), + __writer_(_VSTD::move(__out_it)) {} + + _LIBCPP_HIDE_FROM_ABI auto __make_output_iterator() { return __output_.__make_output_iterator(); } + + _LIBCPP_HIDE_FROM_ABI void __flush(_CharT* __ptr, size_t __n) { __writer_.__flush(__ptr, __n); } + + _LIBCPP_HIDE_FROM_ABI _OutIt __out_it() && { + __output_.__flush(); + return _VSTD::move(__writer_).__out_it(); + } + +private: + _LIBCPP_NO_UNIQUE_ADDRESS _Storage __storage_; + __output_buffer<_CharT> __output_; + typename __writer_selector<_OutIt, _CharT>::type __writer_; +}; + +/// A buffer that counts the number of insertions. +/// +/// Since \ref formatted_size only needs to know the size, the output itself is +/// discarded. +template <__fmt_char_type _CharT> +class _LIBCPP_TEMPLATE_VIS __formatted_size_buffer { +public: + _LIBCPP_HIDE_FROM_ABI auto __make_output_iterator() { return __output_.__make_output_iterator(); } + + _LIBCPP_HIDE_FROM_ABI void __flush(const _CharT*, size_t __n) { __size_ += __n; } + + _LIBCPP_HIDE_FROM_ABI size_t __result() && { + __output_.__flush(); + return __size_; + } + +private: + __internal_storage<_CharT> __storage_; + __output_buffer<_CharT> __output_{__storage_.__begin(), __storage_.__buffer_size, this}; + size_t __size_{0}; +}; + +/// The base of a buffer that counts and limits the number of insertions. +template + requires(output_iterator<_OutIt, const _CharT&>) +struct _LIBCPP_TEMPLATE_VIS __format_to_n_buffer_base { + using _Size = iter_difference_t<_OutIt>; + +public: + _LIBCPP_HIDE_FROM_ABI explicit __format_to_n_buffer_base(_OutIt __out_it, _Size __max_size) + : __writer_(_VSTD::move(__out_it)), __max_size_(_VSTD::max(_Size(0), __max_size)) {} + + _LIBCPP_HIDE_FROM_ABI void __flush(_CharT* __ptr, size_t __n) { + if (_Size(__size_) <= __max_size_) + __writer_.__flush(__ptr, _VSTD::min(_Size(__n), __max_size_ - __size_)); + __size_ += __n; + } + +protected: + __internal_storage<_CharT> __storage_; + __output_buffer<_CharT> __output_{__storage_.__begin(), __storage_.__buffer_size, this}; + typename __writer_selector<_OutIt, _CharT>::type __writer_; + + _Size __max_size_; + _Size __size_{0}; +}; + +/// The base of a buffer that counts and limits the number of insertions. +/// +/// This version is used when \c __enable_direct_output<_OutIt, _CharT> == true. +/// +/// This class limits the size available to the direct writer so it will not +/// exceed the maximum number of code units. +template + requires(output_iterator<_OutIt, const _CharT&>) +class _LIBCPP_TEMPLATE_VIS __format_to_n_buffer_base<_OutIt, _CharT, true> { + using _Size = iter_difference_t<_OutIt>; + +public: + _LIBCPP_HIDE_FROM_ABI explicit __format_to_n_buffer_base(_OutIt __out_it, _Size __max_size) + : __output_(_VSTD::__unwrap_iter(__out_it), __max_size, this), + __writer_(_VSTD::move(__out_it)), + __max_size_(__max_size) { + if (__max_size <= 0) [[unlikely]] + __output_.__reset(__storage_.__begin(), __storage_.__buffer_size); + } + + _LIBCPP_HIDE_FROM_ABI void __flush(_CharT* __ptr, size_t __n) { + // A __flush to the direct writer happens in the following occasions: + // - The format function has written the maximum number of allowed code + // units. At this point it's no longer valid to write to this writer. So + // switch to the internal storage. This internal storage doesn't need to + // be written anywhere so the __flush for that storage writes no output. + // - Like above, but the next "mass write" operation would overflow the + // buffer. In that case the buffer is pre-emptively switched. The still + // valid code units will be written separately. + // - The format_to_n function is finished. In this case there's no need to + // switch the buffer, but for simplicity the buffers are still switched. + // When the __max_size <= 0 the constructor already switched the buffers. + if (__size_ == 0 && __ptr != __storage_.__begin()) { + __writer_.__flush(__ptr, __n); + __output_.__reset(__storage_.__begin(), __storage_.__buffer_size); + } else if (__size_ < __max_size_) { + // Copies a part of the internal buffer to the output up to n characters. + // See __output_buffer<_CharT>::__flush_on_overflow for more information. + _Size __s = _VSTD::min(_Size(__n), __max_size_ - __size_); + std::copy_n(__ptr, __s, __writer_.__out_it()); + __writer_.__flush(__ptr, __s); + } + + __size_ += __n; + } + +protected: + __internal_storage<_CharT> __storage_; + __output_buffer<_CharT> __output_; + __writer_direct<_OutIt, _CharT> __writer_; + + _Size __max_size_; + _Size __size_{0}; +}; + +/// The buffer that counts and limits the number of insertions. +template + requires(output_iterator<_OutIt, const _CharT&>) +struct _LIBCPP_TEMPLATE_VIS __format_to_n_buffer final + : public __format_to_n_buffer_base< _OutIt, _CharT, __enable_direct_output<_OutIt, _CharT>> { + using _Base = __format_to_n_buffer_base<_OutIt, _CharT, __enable_direct_output<_OutIt, _CharT>>; + using _Size = iter_difference_t<_OutIt>; + +public: + _LIBCPP_HIDE_FROM_ABI explicit __format_to_n_buffer(_OutIt __out_it, _Size __max_size) + : _Base(_VSTD::move(__out_it), __max_size) {} + _LIBCPP_HIDE_FROM_ABI auto __make_output_iterator() { return this->__output_.__make_output_iterator(); } + + _LIBCPP_HIDE_FROM_ABI format_to_n_result<_OutIt> __result() && { + this->__output_.__flush(); + return {_VSTD::move(this->__writer_).__out_it(), this->__size_}; + } +}; + +// A dynamically growing buffer intended to be used for retargeting a context. +// +// P2286 Formatting ranges adds range formatting support. It allows the user to +// specify the minimum width for the entire formatted range. The width of the +// range is not known until the range is formatted. Formatting is done to an +// output_iterator so there's no guarantee it would be possible to add the fill +// to the front of the output. Instead the range is formatted to a temporary +// buffer and that buffer is formatted as a string. +// +// There is an issue with that approach, the format context used in +// std::formatter::format contains the output iterator used as part of its +// type. So using this output iterator means there needs to be a new format +// context and the format arguments need to be retargeted to the new context. +// This retargeting is done by a basic_format_context specialized for the +// __iterator of this container. +template <__fmt_char_type _CharT> +class _LIBCPP_TEMPLATE_VIS __retarget_buffer { +public: + using value_type = _CharT; + + struct __iterator { + using difference_type = ptrdiff_t; + + _LIBCPP_HIDE_FROM_ABI constexpr explicit __iterator(__retarget_buffer& __buffer) + : __buffer_(std::addressof(__buffer)) {} + _LIBCPP_HIDE_FROM_ABI constexpr __iterator& operator=(const _CharT& __c) { + __buffer_->push_back(__c); + return *this; + } + _LIBCPP_HIDE_FROM_ABI constexpr __iterator& operator=(_CharT&& __c) { + __buffer_->push_back(__c); + return *this; + } + + _LIBCPP_HIDE_FROM_ABI constexpr __iterator& operator*() { return *this; } + _LIBCPP_HIDE_FROM_ABI constexpr __iterator& operator++() { return *this; } + _LIBCPP_HIDE_FROM_ABI constexpr __iterator operator++(int) { return *this; } + __retarget_buffer* __buffer_; + }; + + _LIBCPP_HIDE_FROM_ABI explicit __retarget_buffer(size_t __size_hint) { __buffer_.reserve(__size_hint); } + + _LIBCPP_HIDE_FROM_ABI __iterator __make_output_iterator() { return __iterator{*this}; } + + _LIBCPP_HIDE_FROM_ABI void push_back(_CharT __c) { __buffer_.push_back(__c); } + + template <__fmt_char_type _InCharT> + _LIBCPP_HIDE_FROM_ABI void __copy(basic_string_view<_InCharT> __str) { + __buffer_.insert(__buffer_.end(), __str.begin(), __str.end()); + } + + template <__fmt_char_type _InCharT, class _UnaryOperation> + _LIBCPP_HIDE_FROM_ABI void __transform(const _InCharT* __first, const _InCharT* __last, _UnaryOperation __operation) { + _LIBCPP_ASSERT(__first <= __last, "not a valid range"); + std::transform(__first, __last, std::back_inserter(__buffer_), std::move(__operation)); + } + + _LIBCPP_HIDE_FROM_ABI void __fill(size_t __n, _CharT __value) { __buffer_.insert(__buffer_.end(), __n, __value); } + + _LIBCPP_HIDE_FROM_ABI basic_string_view<_CharT> __view() { return {__buffer_.data(), __buffer_.size()}; } + +private: + // Use vector instead of string to avoid adding zeros after every append + // operation. The buffer is exposed as a string_view and not as a c-string. + vector<_CharT> __buffer_; +}; + +} // namespace __format + +#endif //_LIBCPP_STD_VER > 17 + +_LIBCPP_END_NAMESPACE_STD + +_LIBCPP_POP_MACROS + +#endif // _LIBCPP___FORMAT_BUFFER_H diff --git a/app/src/main/cpp/libcxx/include/__format/concepts.h b/app/src/main/cpp/libcxx/include/__format/concepts.h new file mode 100644 index 0000000..fe4a7b9 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__format/concepts.h @@ -0,0 +1,78 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___FORMAT_CONCEPTS_H +#define _LIBCPP___FORMAT_CONCEPTS_H + +#include <__concepts/same_as.h> +#include <__concepts/semiregular.h> +#include <__config> +#include <__format/format_fwd.h> +#include <__format/format_parse_context.h> +#include <__type_traits/is_specialization.h> +#include <__utility/pair.h> +#include +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 17 + +/// The character type specializations of \ref formatter. +template +concept __fmt_char_type = + same_as<_CharT, char> +# ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS + || same_as<_CharT, wchar_t> +# endif + ; + +// The output iterator isn't specified. A formatter should accept any +// output_iterator. This iterator is a minimal iterator to test the concept. +// (Note testing for (w)format_context would be a valid choice, but requires +// selecting the proper one depending on the type of _CharT.) +template +using __fmt_iter_for = _CharT*; + +template +concept __formattable = + (semiregular, _CharT>>) && + requires(formatter, _CharT> __f, + const formatter, _CharT> __cf, + _Tp __t, + basic_format_context<__fmt_iter_for<_CharT>, _CharT> __fc, + basic_format_parse_context<_CharT> __pc) { + { __f.parse(__pc) } -> same_as::iterator>; + { __cf.format(__t, __fc) } -> same_as<__fmt_iter_for<_CharT>>; + }; + +# if _LIBCPP_STD_VER > 20 +template +concept formattable = __formattable<_Tp, _CharT>; + +// [tuple.like] defines a tuple-like exposition only concept. This concept is +// not related to that. Therefore it uses a different name for the concept. +// +// TODO FMT Add a test to validate we fail when using that concept after P2165 +// has been implemented. +template +concept __fmt_pair_like = __is_specialization_v<_Tp, pair> || + // Use a requires since tuple_size_v may fail to instantiate, + (__is_specialization_v<_Tp, tuple> && requires { tuple_size_v<_Tp> == 2; }); + +# endif //_LIBCPP_STD_VER > 20 +#endif //_LIBCPP_STD_VER > 17 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___FORMAT_CONCEPTS_H diff --git a/app/src/main/cpp/libcxx/include/__format/container_adaptor.h b/app/src/main/cpp/libcxx/include/__format/container_adaptor.h new file mode 100644 index 0000000..62b6981 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__format/container_adaptor.h @@ -0,0 +1,70 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___FORMAT_CONTAINER_ADAPTOR_H +#define _LIBCPP___FORMAT_CONTAINER_ADAPTOR_H + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#include <__availability> +#include <__config> +#include <__format/concepts.h> +#include <__format/formatter.h> +#include <__format/range_default_formatter.h> +#include +#include + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 20 + +// [container.adaptors.format] only specifies the library should provide the +// formatter specializations, not which header should provide them. +// Since includes a lot of headers, add these headers here instead of +// adding more dependencies like, locale, optinal, string, tuple, etc. to the +// adaptor headers. To use the format functions users already include . + +template +struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT __formatter_container_adaptor { +private: + using __maybe_const_adaptor = __fmt_maybe_const<_Adaptor, _CharT>; + formatter __underlying_; + +public: + template + _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator parse(_ParseContext& __ctx) { + return __underlying_.parse(__ctx); + } + + template + _LIBCPP_HIDE_FROM_ABI typename _FormatContext::iterator + format(__maybe_const_adaptor& __adaptor, _FormatContext& __ctx) const { + return __underlying_.format(__adaptor.__get_container(), __ctx); + } +}; + +template _Container> +struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter, _CharT> + : public __formatter_container_adaptor, _CharT> {}; + +template +struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter, _CharT> + : public __formatter_container_adaptor, _CharT> {}; + +template _Container> +struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter, _CharT> + : public __formatter_container_adaptor, _CharT> {}; + +#endif //_LIBCPP_STD_VER > 20 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___FORMAT_CONTAINER_ADAPTOR_H diff --git a/app/src/main/cpp/libcxx/include/__format/enable_insertable.h b/app/src/main/cpp/libcxx/include/__format/enable_insertable.h new file mode 100644 index 0000000..71b4252 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__format/enable_insertable.h @@ -0,0 +1,35 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___FORMAT_ENABLE_INSERTABLE_H +#define _LIBCPP___FORMAT_ENABLE_INSERTABLE_H + +#include <__config> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 17 + +namespace __format { + +/// Opt-in to enable \ref __insertable for a \a _Container. +template +inline constexpr bool __enable_insertable = false; + +} // namespace __format + +#endif //_LIBCPP_STD_VER > 17 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___FORMAT_ENABLE_INSERTABLE_H diff --git a/app/src/main/cpp/libcxx/include/__format/escaped_output_table.h b/app/src/main/cpp/libcxx/include/__format/escaped_output_table.h new file mode 100644 index 0000000..bd2994b --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__format/escaped_output_table.h @@ -0,0 +1,1038 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// WARNING, this entire header is generated by +// utils/generate_escaped_output_table.py +// DO NOT MODIFY! + +// UNICODE, INC. LICENSE AGREEMENT - DATA FILES AND SOFTWARE +// +// See Terms of Use +// for definitions of Unicode Inc.'s Data Files and Software. +// +// NOTICE TO USER: Carefully read the following legal agreement. +// BY DOWNLOADING, INSTALLING, COPYING OR OTHERWISE USING UNICODE INC.'S +// DATA FILES ("DATA FILES"), AND/OR SOFTWARE ("SOFTWARE"), +// YOU UNEQUIVOCALLY ACCEPT, AND AGREE TO BE BOUND BY, ALL OF THE +// TERMS AND CONDITIONS OF THIS AGREEMENT. +// IF YOU DO NOT AGREE, DO NOT DOWNLOAD, INSTALL, COPY, DISTRIBUTE OR USE +// THE DATA FILES OR SOFTWARE. +// +// COPYRIGHT AND PERMISSION NOTICE +// +// Copyright (c) 1991-2022 Unicode, Inc. All rights reserved. +// Distributed under the Terms of Use in https://www.unicode.org/copyright.html. +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of the Unicode data files and any associated documentation +// (the "Data Files") or Unicode software and any associated documentation +// (the "Software") to deal in the Data Files or Software +// without restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, and/or sell copies of +// the Data Files or Software, and to permit persons to whom the Data Files +// or Software are furnished to do so, provided that either +// (a) this copyright and permission notice appear with all copies +// of the Data Files or Software, or +// (b) this copyright and permission notice appear in associated +// Documentation. +// +// THE DATA FILES AND SOFTWARE ARE PROVIDED "AS IS", WITHOUT WARRANTY OF +// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +// WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT OF THIRD PARTY RIGHTS. +// IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS +// NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL +// DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, +// DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER +// TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +// PERFORMANCE OF THE DATA FILES OR SOFTWARE. +// +// Except as contained in this notice, the name of a copyright holder +// shall not be used in advertising or otherwise to promote the sale, +// use or other dealings in these Data Files or Software without prior +// written authorization of the copyright holder. + +#ifndef _LIBCPP___FORMAT_ESCAPED_OUTPUT_TABLE_H +#define _LIBCPP___FORMAT_ESCAPED_OUTPUT_TABLE_H + +#include <__algorithm/ranges_upper_bound.h> +#include <__config> +#include +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 20 + +namespace __escaped_output_table { + +/// The entries of the characters to escape in format's debug string. +/// +/// Contains the entries for [format.string.escaped]/2.2.1.2.1 +/// CE is a Unicode encoding and C corresponds to either a UCS scalar value +/// whose Unicode property General_Category has a value in the groups +/// Separator (Z) or Other (C) or to a UCS scalar value which has the Unicode +/// property Grapheme_Extend=Yes, as described by table 12 of UAX #44 +/// +/// Separator (Z) consists of General_Category +/// - Space_Separator, +/// - Line_Separator, +/// - Paragraph_Separator. +/// +/// Other (C) consists of General_Category +/// - Control, +/// - Format, +/// - Surrogate, +/// - Private_Use, +/// - Unassigned. +/// +/// The data is generated from +/// - https://www.unicode.org/Public/UCD/latest/ucd/DerivedCoreProperties.txt +/// - https://www.unicode.org/Public/UCD/latest/ucd/extracted/DerivedGeneralCategory.txt +/// +/// The table is similar to the table +/// __extended_grapheme_custer_property_boundary::__entries +/// which explains the details of these classes. The only difference is this +/// table lacks a property, thus having more bits available for the size. +/// +/// The data has 2 values: +/// - bits [0, 10] The size of the range, allowing 2048 elements. +/// - bits [11, 31] The lower bound code point of the range. The upper bound of +/// the range is lower bound + size. +inline constexpr uint32_t __entries[893] = { + 0x00000020, + 0x0003f821, + 0x00056800, + 0x0018006f, + 0x001bc001, + 0x001c0003, + 0x001c5800, + 0x001c6800, + 0x001d1000, + 0x00241806, + 0x00298000, + 0x002ab801, + 0x002c5801, + 0x002c802d, + 0x002df800, + 0x002e0801, + 0x002e2001, + 0x002e3808, + 0x002f5803, + 0x002fa810, + 0x0030800a, + 0x0030e000, + 0x00325814, + 0x00338000, + 0x0036b007, + 0x0036f805, + 0x00373801, + 0x00375003, + 0x00387001, + 0x00388800, + 0x0039801c, + 0x003d300a, + 0x003d900d, + 0x003f5808, + 0x003fd802, + 0x0040b003, + 0x0040d808, + 0x00412802, + 0x00414806, + 0x0041f800, + 0x0042c804, + 0x0042f800, + 0x00435804, + 0x00447810, + 0x00465038, + 0x0049d000, + 0x0049e000, + 0x004a0807, + 0x004a6800, + 0x004a8806, + 0x004b1001, + 0x004c0800, + 0x004c2000, + 0x004c6801, + 0x004c8801, + 0x004d4800, + 0x004d8800, + 0x004d9802, + 0x004dd002, + 0x004df000, + 0x004e0805, + 0x004e4801, + 0x004e6800, + 0x004e780c, + 0x004ef000, + 0x004f1003, + 0x004ff004, + 0x00502000, + 0x00505803, + 0x00508801, + 0x00514800, + 0x00518800, + 0x0051a000, + 0x0051b800, + 0x0051d003, + 0x00520817, + 0x0052e800, + 0x0052f806, + 0x00538001, + 0x0053a800, + 0x0053b80b, + 0x00542000, + 0x00547000, + 0x00549000, + 0x00554800, + 0x00558800, + 0x0055a000, + 0x0055d002, + 0x00560807, + 0x00565000, + 0x00566802, + 0x0056880e, + 0x00571003, + 0x00579006, + 0x0057d007, + 0x00582000, + 0x00586801, + 0x00588801, + 0x00594800, + 0x00598800, + 0x0059a000, + 0x0059d002, + 0x0059f001, + 0x005a0805, + 0x005a4801, + 0x005a680e, + 0x005af000, + 0x005b1003, + 0x005bc00a, + 0x005c2000, + 0x005c5802, + 0x005c8800, + 0x005cb002, + 0x005cd800, + 0x005ce800, + 0x005d0002, + 0x005d2802, + 0x005d5802, + 0x005dd004, + 0x005e0000, + 0x005e1802, + 0x005e4800, + 0x005e6802, + 0x005e8814, + 0x005fd805, + 0x00602000, + 0x00606800, + 0x00608800, + 0x00614800, + 0x0061d002, + 0x0061f002, + 0x00622812, + 0x0062d801, + 0x0062f001, + 0x00631003, + 0x00638006, + 0x00640800, + 0x00646800, + 0x00648800, + 0x00654800, + 0x0065a000, + 0x0065d002, + 0x0065f800, + 0x00661000, + 0x00662801, + 0x00664800, + 0x00666010, + 0x0066f800, + 0x00671003, + 0x00678000, + 0x0067a00d, + 0x00686800, + 0x00688800, + 0x0069d801, + 0x0069f000, + 0x006a0804, + 0x006a4800, + 0x006a6800, + 0x006a8003, + 0x006ab800, + 0x006b1003, + 0x006c0001, + 0x006c2000, + 0x006cb802, + 0x006d9000, + 0x006de000, + 0x006df001, + 0x006e3808, + 0x006e9005, + 0x006ef806, + 0x006f8001, + 0x006fa80b, + 0x00718800, + 0x0071a00a, + 0x00723807, + 0x0072e024, + 0x00741800, + 0x00742800, + 0x00745800, + 0x00752000, + 0x00753000, + 0x00758800, + 0x0075a008, + 0x0075f001, + 0x00762800, + 0x00763808, + 0x0076d001, + 0x0077001f, + 0x0078c001, + 0x0079a800, + 0x0079b800, + 0x0079c800, + 0x007a4000, + 0x007b6811, + 0x007c0004, + 0x007c3001, + 0x007c6830, + 0x007e3000, + 0x007e6800, + 0x007ed824, + 0x00816803, + 0x00819005, + 0x0081c801, + 0x0081e801, + 0x0082c001, + 0x0082f002, + 0x00838803, + 0x00841000, + 0x00842801, + 0x00846800, + 0x0084e800, + 0x00863000, + 0x00864004, + 0x00867001, + 0x00924800, + 0x00927001, + 0x0092b800, + 0x0092c800, + 0x0092f001, + 0x00944800, + 0x00947001, + 0x00958800, + 0x0095b001, + 0x0095f800, + 0x00960800, + 0x00963001, + 0x0096b800, + 0x00988800, + 0x0098b001, + 0x009ad804, + 0x009be802, + 0x009cd005, + 0x009fb001, + 0x009ff001, + 0x00b40000, + 0x00b4e802, + 0x00b7c806, + 0x00b89002, + 0x00b8b008, + 0x00b99001, + 0x00b9b808, + 0x00ba900d, + 0x00bb6800, + 0x00bb880e, + 0x00bda001, + 0x00bdb806, + 0x00be3000, + 0x00be480a, + 0x00bee802, + 0x00bf5005, + 0x00bfd005, + 0x00c05804, + 0x00c0d005, + 0x00c3c806, + 0x00c42801, + 0x00c54800, + 0x00c55804, + 0x00c7b009, + 0x00c8f803, + 0x00c93801, + 0x00c96003, + 0x00c99000, + 0x00c9c806, + 0x00ca0802, + 0x00cb7001, + 0x00cba80a, + 0x00cd6003, + 0x00ce5005, + 0x00ced802, + 0x00d0b801, + 0x00d0d802, + 0x00d2b000, + 0x00d2c008, + 0x00d31000, + 0x00d32807, + 0x00d3980c, + 0x00d45005, + 0x00d4d005, + 0x00d57055, + 0x00d9a006, + 0x00d9e000, + 0x00da1000, + 0x00da6802, + 0x00db5808, + 0x00dbf802, + 0x00dd1003, + 0x00dd4001, + 0x00dd5802, + 0x00df3000, + 0x00df4001, + 0x00df6800, + 0x00df7802, + 0x00dfa007, + 0x00e16007, + 0x00e1b004, + 0x00e25002, + 0x00e44806, + 0x00e5d801, + 0x00e6400a, + 0x00e6a00c, + 0x00e71006, + 0x00e76800, + 0x00e7a000, + 0x00e7c001, + 0x00e7d804, + 0x00ee003f, + 0x00f8b001, + 0x00f8f001, + 0x00fa3001, + 0x00fa7001, + 0x00fac000, + 0x00fad000, + 0x00fae000, + 0x00faf000, + 0x00fbf001, + 0x00fda800, + 0x00fe2800, + 0x00fea001, + 0x00fee000, + 0x00ff8001, + 0x00ffa800, + 0x00fff810, + 0x01014007, + 0x0102f810, + 0x01039001, + 0x01047800, + 0x0104e802, + 0x0106083e, + 0x010c6003, + 0x01213818, + 0x01225814, + 0x015ba001, + 0x015cb000, + 0x01677802, + 0x0167a004, + 0x01693000, + 0x01694004, + 0x01697001, + 0x016b4006, + 0x016b880e, + 0x016cb808, + 0x016d3800, + 0x016d7800, + 0x016db800, + 0x016df800, + 0x016e3800, + 0x016e7800, + 0x016eb800, + 0x016ef820, + 0x0172f021, + 0x0174d000, + 0x0177a00b, + 0x017eb019, + 0x017fe004, + 0x01815005, + 0x01820000, + 0x0184b803, + 0x01880004, + 0x01898000, + 0x018c7800, + 0x018f200b, + 0x0190f800, + 0x05246802, + 0x05263808, + 0x05316013, + 0x05337803, + 0x0533a009, + 0x0534f001, + 0x05378001, + 0x0537c007, + 0x053e5804, + 0x053e9000, + 0x053ea000, + 0x053ed017, + 0x05401000, + 0x05403000, + 0x05405800, + 0x05412801, + 0x05416003, + 0x0541d005, + 0x0543c007, + 0x05462009, + 0x0546d017, + 0x0547f800, + 0x05493007, + 0x054a380a, + 0x054aa00a, + 0x054be805, + 0x054d9800, + 0x054db003, + 0x054de001, + 0x054e7000, + 0x054ed003, + 0x054f2800, + 0x054ff800, + 0x05514805, + 0x05518801, + 0x0551a80a, + 0x05521800, + 0x05526000, + 0x05527001, + 0x0552d001, + 0x0553e000, + 0x05558000, + 0x05559002, + 0x0555b801, + 0x0555f001, + 0x05560800, + 0x05561817, + 0x05576001, + 0x0557b00a, + 0x05583801, + 0x05587801, + 0x0558b808, + 0x05593800, + 0x05597800, + 0x055b6003, + 0x055f2800, + 0x055f4000, + 0x055f6802, + 0x055fd005, + 0x06bd200b, + 0x06be3803, + 0x06bfe7ff, + 0x06ffe7ff, + 0x073fe7ff, + 0x077fe7ff, + 0x07bfe103, + 0x07d37001, + 0x07d6d025, + 0x07d8380b, + 0x07d8c004, + 0x07d8f000, + 0x07d9b800, + 0x07d9e800, + 0x07d9f800, + 0x07da1000, + 0x07da2800, + 0x07de180f, + 0x07ec8001, + 0x07ee4006, + 0x07ee801f, + 0x07f0000f, + 0x07f0d015, + 0x07f29800, + 0x07f33800, + 0x07f36003, + 0x07f3a800, + 0x07f7e803, + 0x07fcf001, + 0x07fdf802, + 0x07fe4001, + 0x07fe8001, + 0x07fec001, + 0x07fee802, + 0x07ff3800, + 0x07ff780c, + 0x07fff001, + 0x08006000, + 0x08013800, + 0x0801d800, + 0x0801f000, + 0x08027001, + 0x0802f021, + 0x0807d804, + 0x08081803, + 0x0809a002, + 0x080c7800, + 0x080ce802, + 0x080d082e, + 0x080fe882, + 0x0814e802, + 0x0816880f, + 0x0817e003, + 0x08192008, + 0x081a5804, + 0x081bb009, + 0x081cf000, + 0x081e2003, + 0x081eb029, + 0x0824f001, + 0x08255005, + 0x0826a003, + 0x0827e003, + 0x08294007, + 0x082b200a, + 0x082bd800, + 0x082c5800, + 0x082c9800, + 0x082cb000, + 0x082d1000, + 0x082d9000, + 0x082dd000, + 0x082de842, + 0x0839b808, + 0x083ab009, + 0x083b4017, + 0x083c3000, + 0x083d8800, + 0x083dd844, + 0x08403001, + 0x08404800, + 0x0841b000, + 0x0841c802, + 0x0841e801, + 0x0842b000, + 0x0844f807, + 0x0845802f, + 0x08479800, + 0x0847b004, + 0x0848e002, + 0x0849d004, + 0x084a003f, + 0x084dc003, + 0x084e8001, + 0x0850080e, + 0x0850a000, + 0x0850c000, + 0x0851b009, + 0x08524806, + 0x0852c806, + 0x0855001f, + 0x08572805, + 0x0857b808, + 0x0859b002, + 0x085ab001, + 0x085b9804, + 0x085c9006, + 0x085ce80b, + 0x085d804f, + 0x08624836, + 0x0865980c, + 0x08679806, + 0x0869200b, + 0x0869d125, + 0x0873f800, + 0x08755002, + 0x08757001, + 0x0875904d, + 0x08794007, + 0x087a300a, + 0x087ad015, + 0x087c1003, + 0x087c5025, + 0x087e6013, + 0x087fb808, + 0x08800800, + 0x0881c00e, + 0x08827003, + 0x08838000, + 0x08839801, + 0x0883b00b, + 0x08859803, + 0x0885c801, + 0x0885e800, + 0x0886100d, + 0x08874806, + 0x0887d008, + 0x08893804, + 0x08896808, + 0x088a4007, + 0x088b9800, + 0x088bb80a, + 0x088db008, + 0x088e4803, + 0x088e7800, + 0x088f0000, + 0x088fa80a, + 0x08909000, + 0x08917802, + 0x0891a000, + 0x0891b001, + 0x0891f000, + 0x0892083e, + 0x08943800, + 0x08944800, + 0x08947000, + 0x0894f000, + 0x08955005, + 0x0896f800, + 0x0897180c, + 0x0897d007, + 0x08982000, + 0x08986801, + 0x08988801, + 0x08994800, + 0x08998800, + 0x0899a000, + 0x0899d002, + 0x0899f000, + 0x089a0000, + 0x089a2801, + 0x089a4801, + 0x089a7001, + 0x089a880b, + 0x089b209b, + 0x08a1c007, + 0x08a21002, + 0x08a23000, + 0x08a2e000, + 0x08a2f000, + 0x08a3101d, + 0x08a58000, + 0x08a59805, + 0x08a5d000, + 0x08a5e800, + 0x08a5f801, + 0x08a61001, + 0x08a64007, + 0x08a6d0a5, + 0x08ad7800, + 0x08ad9005, + 0x08ade001, + 0x08adf801, + 0x08aee023, + 0x08b19807, + 0x08b1e800, + 0x08b1f801, + 0x08b2280a, + 0x08b2d005, + 0x08b36812, + 0x08b55800, + 0x08b56800, + 0x08b58005, + 0x08b5b800, + 0x08b5d005, + 0x08b65035, + 0x08b8d804, + 0x08b91003, + 0x08b93808, + 0x08ba38b8, + 0x08c17808, + 0x08c1c801, + 0x08c1e063, + 0x08c7980b, + 0x08c83801, + 0x08c85001, + 0x08c8a000, + 0x08c8b800, + 0x08c98000, + 0x08c9b000, + 0x08c9c803, + 0x08c9f000, + 0x08ca1800, + 0x08ca3808, + 0x08cad045, + 0x08cd4001, + 0x08cea007, + 0x08cf0000, + 0x08cf281a, + 0x08d00809, + 0x08d19805, + 0x08d1d803, + 0x08d23808, + 0x08d28805, + 0x08d2c802, + 0x08d4500c, + 0x08d4c001, + 0x08d5180c, + 0x08d7c806, + 0x08d850f5, + 0x08e04800, + 0x08e1800d, + 0x08e1f800, + 0x08e23009, + 0x08e36802, + 0x08e48018, + 0x08e55006, + 0x08e59001, + 0x08e5a84a, + 0x08e83800, + 0x08e85000, + 0x08e98814, + 0x08ea3808, + 0x08ead005, + 0x08eb3000, + 0x08eb4800, + 0x08ec7803, + 0x08eca800, + 0x08ecb800, + 0x08ecc806, + 0x08ed5135, + 0x08f79801, + 0x08f7c808, + 0x08f88800, + 0x08f9b007, + 0x08fa0000, + 0x08fa1000, + 0x08fad055, + 0x08fd880e, + 0x08ff900c, + 0x091cd065, + 0x09237800, + 0x0923a80a, + 0x092a27ff, + 0x096a224b, + 0x097f980c, + 0x09a18010, + 0x09a23fff, + 0x09e23fb8, + 0x0a323fff, + 0x0a723fff, + 0x0ab23fff, + 0x0af23fff, + 0x0b3239b8, + 0x0b51c806, + 0x0b52f800, + 0x0b535003, + 0x0b55f800, + 0x0b565005, + 0x0b577006, + 0x0b57b009, + 0x0b598006, + 0x0b5a3009, + 0x0b5ad000, + 0x0b5b1000, + 0x0b5bc004, + 0x0b5c82af, + 0x0b74d864, + 0x0b7a5804, + 0x0b7c400a, + 0x0b7d003f, + 0x0b7f200b, + 0x0b7f900d, + 0x0c3fc007, + 0x0c66b029, + 0x0c684fff, + 0x0ca84fff, + 0x0ce84fff, + 0x0d284fff, + 0x0d684ae6, + 0x0d7fa000, + 0x0d7fe000, + 0x0d7ff800, + 0x0d89180e, + 0x0d89981c, + 0x0d8a9801, + 0x0d8ab00d, + 0x0d8b4007, + 0x0d97e7ff, + 0x0dd7e103, + 0x0de35804, + 0x0de3e802, + 0x0de44806, + 0x0de4d001, + 0x0de4e801, + 0x0de507ff, + 0x0e2507ff, + 0x0e6502af, + 0x0e7e203b, + 0x0e87b009, + 0x0e893801, + 0x0e8b2800, + 0x0e8b3802, + 0x0e8b7014, + 0x0e8c2806, + 0x0e8d5003, + 0x0e8f5814, + 0x0e921002, + 0x0e923079, + 0x0e96a00b, + 0x0e97a00b, + 0x0e9ab808, + 0x0e9bc886, + 0x0ea2a800, + 0x0ea4e800, + 0x0ea50001, + 0x0ea51801, + 0x0ea53801, + 0x0ea56800, + 0x0ea5d000, + 0x0ea5e000, + 0x0ea62000, + 0x0ea83000, + 0x0ea85801, + 0x0ea8a800, + 0x0ea8e800, + 0x0ea9d000, + 0x0ea9f800, + 0x0eaa2800, + 0x0eaa3802, + 0x0eaa8800, + 0x0eb53001, + 0x0ebe6001, + 0x0ed00036, + 0x0ed1d831, + 0x0ed3a800, + 0x0ed42000, + 0x0ed46473, + 0x0ef8f805, + 0x0ef95904, + 0x0f037091, + 0x0f096809, + 0x0f09f001, + 0x0f0a5003, + 0x0f0a813f, + 0x0f157011, + 0x0f176003, + 0x0f17d004, + 0x0f1801cf, + 0x0f276003, + 0x0f27d2e5, + 0x0f3f3800, + 0x0f3f6000, + 0x0f3f7800, + 0x0f3ff800, + 0x0f462801, + 0x0f46802f, + 0x0f4a2006, + 0x0f4a6003, + 0x0f4ad003, + 0x0f4b0310, + 0x0f65a84b, + 0x0f69f0c1, + 0x0f702000, + 0x0f710000, + 0x0f711800, + 0x0f712801, + 0x0f714000, + 0x0f719800, + 0x0f71c000, + 0x0f71d000, + 0x0f71e005, + 0x0f721803, + 0x0f724000, + 0x0f725000, + 0x0f726000, + 0x0f728000, + 0x0f729800, + 0x0f72a801, + 0x0f72c000, + 0x0f72d000, + 0x0f72e000, + 0x0f72f000, + 0x0f730000, + 0x0f731800, + 0x0f732801, + 0x0f735800, + 0x0f739800, + 0x0f73c000, + 0x0f73e800, + 0x0f73f800, + 0x0f745000, + 0x0f74e004, + 0x0f752000, + 0x0f755000, + 0x0f75e033, + 0x0f77910d, + 0x0f816003, + 0x0f84a00b, + 0x0f857801, + 0x0f860000, + 0x0f868000, + 0x0f87b009, + 0x0f8d7037, + 0x0f90180c, + 0x0f91e003, + 0x0f924806, + 0x0f92900d, + 0x0f933099, + 0x0fb6c003, + 0x0fb76802, + 0x0fb7e802, + 0x0fbbb803, + 0x0fbed005, + 0x0fbf6003, + 0x0fbf880e, + 0x0fc06003, + 0x0fc24007, + 0x0fc2d005, + 0x0fc44007, + 0x0fc57001, + 0x0fc5904d, + 0x0fd2a00b, + 0x0fd37001, + 0x0fd3e802, + 0x0fd44806, + 0x0fd5f000, + 0x0fd63007, + 0x0fd6e003, + 0x0fd74806, + 0x0fd7c806, + 0x0fdc9800, + 0x0fde5824, + 0x0fdfd405, + 0x1537001f, + 0x15b9d005, + 0x15c0f001, + 0x1675100d, + 0x175f0fff, + 0x179f0c1e, + 0x17d0f5e1, + 0x189a5804}; + +/// At the end of the valid Unicode code points space a lot of code points are +/// either reserved or a noncharacter. Adding all these entries to the +/// lookup table would add 446 entries to the table (in Unicode 14). +/// Instead the only the start of the region is stored, every code point in +/// this region needs to be escaped. +inline constexpr uint32_t __unallocated_region_lower_bound = 0x000323b0; + +/// Returns whether the code unit needs to be escaped. +/// +/// \pre The code point is a valid Unicode code point. +[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool __needs_escape(const char32_t __code_point) noexcept { + // Since __unallocated_region_lower_bound contains the unshifted range do the + // comparison without shifting. + if (__code_point >= __unallocated_region_lower_bound) + return true; + + ptrdiff_t __i = std::ranges::upper_bound(__entries, (__code_point << 11) | 0x7ffu) - __entries; + if (__i == 0) + return false; + + --__i; + uint32_t __upper_bound = (__entries[__i] >> 11) + (__entries[__i] & 0x7ffu); + return __code_point <= __upper_bound; +} + +} // namespace __escaped_output_table + +#endif //_LIBCPP_STD_VER > 20 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___FORMAT_ESCAPED_OUTPUT_TABLE_H diff --git a/app/src/main/cpp/libcxx/include/__format/extended_grapheme_cluster_table.h b/app/src/main/cpp/libcxx/include/__format/extended_grapheme_cluster_table.h new file mode 100644 index 0000000..1ffcfeb --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__format/extended_grapheme_cluster_table.h @@ -0,0 +1,1661 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// WARNING, this entire header is generated by +// utils/generate_extended_grapheme_cluster_table.py +// DO NOT MODIFY! + +// UNICODE, INC. LICENSE AGREEMENT - DATA FILES AND SOFTWARE +// +// See Terms of Use +// for definitions of Unicode Inc.'s Data Files and Software. +// +// NOTICE TO USER: Carefully read the following legal agreement. +// BY DOWNLOADING, INSTALLING, COPYING OR OTHERWISE USING UNICODE INC.'S +// DATA FILES ("DATA FILES"), AND/OR SOFTWARE ("SOFTWARE"), +// YOU UNEQUIVOCALLY ACCEPT, AND AGREE TO BE BOUND BY, ALL OF THE +// TERMS AND CONDITIONS OF THIS AGREEMENT. +// IF YOU DO NOT AGREE, DO NOT DOWNLOAD, INSTALL, COPY, DISTRIBUTE OR USE +// THE DATA FILES OR SOFTWARE. +// +// COPYRIGHT AND PERMISSION NOTICE +// +// Copyright (c) 1991-2022 Unicode, Inc. All rights reserved. +// Distributed under the Terms of Use in https://www.unicode.org/copyright.html. +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of the Unicode data files and any associated documentation +// (the "Data Files") or Unicode software and any associated documentation +// (the "Software") to deal in the Data Files or Software +// without restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, and/or sell copies of +// the Data Files or Software, and to permit persons to whom the Data Files +// or Software are furnished to do so, provided that either +// (a) this copyright and permission notice appear with all copies +// of the Data Files or Software, or +// (b) this copyright and permission notice appear in associated +// Documentation. +// +// THE DATA FILES AND SOFTWARE ARE PROVIDED "AS IS", WITHOUT WARRANTY OF +// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +// WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT OF THIRD PARTY RIGHTS. +// IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS +// NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL +// DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, +// DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER +// TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +// PERFORMANCE OF THE DATA FILES OR SOFTWARE. +// +// Except as contained in this notice, the name of a copyright holder +// shall not be used in advertising or otherwise to promote the sale, +// use or other dealings in these Data Files or Software without prior +// written authorization of the copyright holder. + +#ifndef _LIBCPP___FORMAT_EXTENDED_GRAPHEME_CLUSTER_TABLE_H +#define _LIBCPP___FORMAT_EXTENDED_GRAPHEME_CLUSTER_TABLE_H + +#include <__algorithm/ranges_upper_bound.h> +#include <__config> +#include <__iterator/access.h> +#include +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 17 + +namespace __extended_grapheme_custer_property_boundary { + +enum class __property : uint8_t { + // Values generated from the data files. + __CR, + __Control, + __Extend, + __Extended_Pictographic, + __L, + __LF, + __LV, + __LVT, + __Prepend, + __Regional_Indicator, + __SpacingMark, + __T, + __V, + __ZWJ, + + // The properies below aren't stored in the "database". + + // Text position properties. + __sot, + __eot, + + // The code unit has none of above properties. + __none +}; + +/// The entries of the extended grapheme cluster bondary property table. +/// +/// The data is generated from +/// - https://www.unicode.org/Public/UCD/latest/ucd/auxiliary/GraphemeBreakProperty.txt +/// - https://www.unicode.org/Public/UCD/latest/ucd/emoji/emoji-data.txt +/// +/// The data has 3 values +/// - bits [0, 3] The property. One of the values generated from the datafiles +/// of \ref __property +/// - bits [4, 10] The size of the range. +/// - bits [11, 31] The lower bound code point of the range. The upper bound of +/// the range is lower bound + size. +/// +/// The 7 bits for the size allow a maximum range of 128 elements. Some ranges +/// in the Unicode tables are larger. They are stored in multiple consecutive +/// ranges in the data table. An alternative would be to store the sizes in a +/// separate 16-bit value. The original MSVC STL code had such an approach, but +/// this approach uses less space for the data and is about 4% faster in the +/// following benchmark. +/// libcxx/benchmarks/std_format_spec_string_unicode.bench.cpp +inline constexpr uint32_t __entries[1496] = { + 0x00000091, + 0x00005005, + 0x00005811, + 0x00006800, + 0x00007111, + 0x0003fa01, + 0x00054803, + 0x00056801, + 0x00057003, + 0x001806f2, + 0x00241862, + 0x002c8ac2, + 0x002df802, + 0x002e0812, + 0x002e2012, + 0x002e3802, + 0x00300058, + 0x003080a2, + 0x0030e001, + 0x00325942, + 0x00338002, + 0x0036b062, + 0x0036e808, + 0x0036f852, + 0x00373812, + 0x00375032, + 0x00387808, + 0x00388802, + 0x003981a2, + 0x003d30a2, + 0x003f5882, + 0x003fe802, + 0x0040b032, + 0x0040d882, + 0x00412822, + 0x00414842, + 0x0042c822, + 0x00448018, + 0x0044c072, + 0x00465172, + 0x00471008, + 0x004719f2, + 0x0048180a, + 0x0049d002, + 0x0049d80a, + 0x0049e002, + 0x0049f02a, + 0x004a0872, + 0x004a483a, + 0x004a6802, + 0x004a701a, + 0x004a8862, + 0x004b1012, + 0x004c0802, + 0x004c101a, + 0x004de002, + 0x004df002, + 0x004df81a, + 0x004e0832, + 0x004e381a, + 0x004e581a, + 0x004e6802, + 0x004eb802, + 0x004f1012, + 0x004ff002, + 0x00500812, + 0x0050180a, + 0x0051e002, + 0x0051f02a, + 0x00520812, + 0x00523812, + 0x00525822, + 0x00528802, + 0x00538012, + 0x0053a802, + 0x00540812, + 0x0054180a, + 0x0055e002, + 0x0055f02a, + 0x00560842, + 0x00563812, + 0x0056480a, + 0x0056581a, + 0x00566802, + 0x00571012, + 0x0057d052, + 0x00580802, + 0x0058101a, + 0x0059e002, + 0x0059f012, + 0x005a000a, + 0x005a0832, + 0x005a381a, + 0x005a581a, + 0x005a6802, + 0x005aa822, + 0x005b1012, + 0x005c1002, + 0x005df002, + 0x005df80a, + 0x005e0002, + 0x005e081a, + 0x005e302a, + 0x005e502a, + 0x005e6802, + 0x005eb802, + 0x00600002, + 0x0060082a, + 0x00602002, + 0x0061e002, + 0x0061f022, + 0x0062083a, + 0x00623022, + 0x00625032, + 0x0062a812, + 0x00631012, + 0x00640802, + 0x0064101a, + 0x0065e002, + 0x0065f00a, + 0x0065f802, + 0x0066001a, + 0x00661002, + 0x0066181a, + 0x00663002, + 0x0066381a, + 0x0066501a, + 0x00666012, + 0x0066a812, + 0x00671012, + 0x0067980a, + 0x00680012, + 0x0068101a, + 0x0069d812, + 0x0069f002, + 0x0069f81a, + 0x006a0832, + 0x006a302a, + 0x006a502a, + 0x006a6802, + 0x006a7008, + 0x006ab802, + 0x006b1012, + 0x006c0802, + 0x006c101a, + 0x006e5002, + 0x006e7802, + 0x006e801a, + 0x006e9022, + 0x006eb002, + 0x006ec06a, + 0x006ef802, + 0x006f901a, + 0x00718802, + 0x0071980a, + 0x0071a062, + 0x00723872, + 0x00758802, + 0x0075980a, + 0x0075a082, + 0x00764062, + 0x0078c012, + 0x0079a802, + 0x0079b802, + 0x0079c802, + 0x0079f01a, + 0x007b88d2, + 0x007bf80a, + 0x007c0042, + 0x007c3012, + 0x007c68a2, + 0x007cca32, + 0x007e3002, + 0x00816832, + 0x0081880a, + 0x00819052, + 0x0081c812, + 0x0081d81a, + 0x0081e812, + 0x0082b01a, + 0x0082c012, + 0x0082f022, + 0x00838832, + 0x00841002, + 0x0084200a, + 0x00842812, + 0x00846802, + 0x0084e802, + 0x008805f4, + 0x008b047c, + 0x008d457b, + 0x009ae822, + 0x00b89022, + 0x00b8a80a, + 0x00b99012, + 0x00b9a00a, + 0x00ba9012, + 0x00bb9012, + 0x00bda012, + 0x00bdb00a, + 0x00bdb862, + 0x00bdf07a, + 0x00be3002, + 0x00be381a, + 0x00be48a2, + 0x00bee802, + 0x00c05822, + 0x00c07001, + 0x00c07802, + 0x00c42812, + 0x00c54802, + 0x00c90022, + 0x00c9183a, + 0x00c93812, + 0x00c9482a, + 0x00c9801a, + 0x00c99002, + 0x00c9985a, + 0x00c9c822, + 0x00d0b812, + 0x00d0c81a, + 0x00d0d802, + 0x00d2a80a, + 0x00d2b002, + 0x00d2b80a, + 0x00d2c062, + 0x00d30002, + 0x00d31002, + 0x00d32872, + 0x00d3685a, + 0x00d39892, + 0x00d3f802, + 0x00d581e2, + 0x00d80032, + 0x00d8200a, + 0x00d9a062, + 0x00d9d80a, + 0x00d9e002, + 0x00d9e84a, + 0x00da1002, + 0x00da181a, + 0x00db5882, + 0x00dc0012, + 0x00dc100a, + 0x00dd080a, + 0x00dd1032, + 0x00dd301a, + 0x00dd4012, + 0x00dd500a, + 0x00dd5822, + 0x00df3002, + 0x00df380a, + 0x00df4012, + 0x00df502a, + 0x00df6802, + 0x00df700a, + 0x00df7822, + 0x00df901a, + 0x00e1207a, + 0x00e16072, + 0x00e1a01a, + 0x00e1b012, + 0x00e68022, + 0x00e6a0c2, + 0x00e7080a, + 0x00e71062, + 0x00e76802, + 0x00e7a002, + 0x00e7b80a, + 0x00e7c012, + 0x00ee03f2, + 0x01005801, + 0x01006002, + 0x0100680d, + 0x01007011, + 0x01014061, + 0x0101e003, + 0x01024803, + 0x010300f1, + 0x01068202, + 0x01091003, + 0x0109c803, + 0x010ca053, + 0x010d4813, + 0x0118d013, + 0x01194003, + 0x011c4003, + 0x011e7803, + 0x011f48a3, + 0x011fc023, + 0x01261003, + 0x012d5013, + 0x012db003, + 0x012e0003, + 0x012fd833, + 0x01300053, + 0x013038b3, + 0x0130a713, + 0x01348753, + 0x013840a3, + 0x0138a003, + 0x0138b003, + 0x0138e803, + 0x01390803, + 0x01394003, + 0x01399813, + 0x013a2003, + 0x013a3803, + 0x013a6003, + 0x013a7003, + 0x013a9823, + 0x013ab803, + 0x013b1843, + 0x013ca823, + 0x013d0803, + 0x013d8003, + 0x013df803, + 0x0149a013, + 0x01582823, + 0x0158d813, + 0x015a8003, + 0x015aa803, + 0x01677822, + 0x016bf802, + 0x016f01f2, + 0x01815052, + 0x01818003, + 0x0181e803, + 0x0184c812, + 0x0194b803, + 0x0194c803, + 0x05337832, + 0x0533a092, + 0x0534f012, + 0x05378012, + 0x05401002, + 0x05403002, + 0x05405802, + 0x0541181a, + 0x05412812, + 0x0541380a, + 0x05416002, + 0x0544001a, + 0x0545a0fa, + 0x05462012, + 0x05470112, + 0x0547f802, + 0x05493072, + 0x054a38a2, + 0x054a901a, + 0x054b01c4, + 0x054c0022, + 0x054c180a, + 0x054d9802, + 0x054da01a, + 0x054db032, + 0x054dd01a, + 0x054de012, + 0x054df02a, + 0x054f2802, + 0x05514852, + 0x0551781a, + 0x05518812, + 0x0551981a, + 0x0551a812, + 0x05521802, + 0x05526002, + 0x0552680a, + 0x0553e002, + 0x05558002, + 0x05559022, + 0x0555b812, + 0x0555f012, + 0x05560802, + 0x0557580a, + 0x05576012, + 0x0557701a, + 0x0557a80a, + 0x0557b002, + 0x055f181a, + 0x055f2802, + 0x055f301a, + 0x055f4002, + 0x055f481a, + 0x055f600a, + 0x055f6802, + 0x05600006, + 0x056009a7, + 0x0560e006, + 0x0560e9a7, + 0x0561c006, + 0x0561c9a7, + 0x0562a006, + 0x0562a9a7, + 0x05638006, + 0x056389a7, + 0x05646006, + 0x056469a7, + 0x05654006, + 0x056549a7, + 0x05662006, + 0x056629a7, + 0x05670006, + 0x056709a7, + 0x0567e006, + 0x0567e9a7, + 0x0568c006, + 0x0568c9a7, + 0x0569a006, + 0x0569a9a7, + 0x056a8006, + 0x056a89a7, + 0x056b6006, + 0x056b69a7, + 0x056c4006, + 0x056c49a7, + 0x056d2006, + 0x056d29a7, + 0x056e0006, + 0x056e09a7, + 0x056ee006, + 0x056ee9a7, + 0x056fc006, + 0x056fc9a7, + 0x0570a006, + 0x0570a9a7, + 0x05718006, + 0x057189a7, + 0x05726006, + 0x057269a7, + 0x05734006, + 0x057349a7, + 0x05742006, + 0x057429a7, + 0x05750006, + 0x057509a7, + 0x0575e006, + 0x0575e9a7, + 0x0576c006, + 0x0576c9a7, + 0x0577a006, + 0x0577a9a7, + 0x05788006, + 0x057889a7, + 0x05796006, + 0x057969a7, + 0x057a4006, + 0x057a49a7, + 0x057b2006, + 0x057b29a7, + 0x057c0006, + 0x057c09a7, + 0x057ce006, + 0x057ce9a7, + 0x057dc006, + 0x057dc9a7, + 0x057ea006, + 0x057ea9a7, + 0x057f8006, + 0x057f89a7, + 0x05806006, + 0x058069a7, + 0x05814006, + 0x058149a7, + 0x05822006, + 0x058229a7, + 0x05830006, + 0x058309a7, + 0x0583e006, + 0x0583e9a7, + 0x0584c006, + 0x0584c9a7, + 0x0585a006, + 0x0585a9a7, + 0x05868006, + 0x058689a7, + 0x05876006, + 0x058769a7, + 0x05884006, + 0x058849a7, + 0x05892006, + 0x058929a7, + 0x058a0006, + 0x058a09a7, + 0x058ae006, + 0x058ae9a7, + 0x058bc006, + 0x058bc9a7, + 0x058ca006, + 0x058ca9a7, + 0x058d8006, + 0x058d89a7, + 0x058e6006, + 0x058e69a7, + 0x058f4006, + 0x058f49a7, + 0x05902006, + 0x059029a7, + 0x05910006, + 0x059109a7, + 0x0591e006, + 0x0591e9a7, + 0x0592c006, + 0x0592c9a7, + 0x0593a006, + 0x0593a9a7, + 0x05948006, + 0x059489a7, + 0x05956006, + 0x059569a7, + 0x05964006, + 0x059649a7, + 0x05972006, + 0x059729a7, + 0x05980006, + 0x059809a7, + 0x0598e006, + 0x0598e9a7, + 0x0599c006, + 0x0599c9a7, + 0x059aa006, + 0x059aa9a7, + 0x059b8006, + 0x059b89a7, + 0x059c6006, + 0x059c69a7, + 0x059d4006, + 0x059d49a7, + 0x059e2006, + 0x059e29a7, + 0x059f0006, + 0x059f09a7, + 0x059fe006, + 0x059fe9a7, + 0x05a0c006, + 0x05a0c9a7, + 0x05a1a006, + 0x05a1a9a7, + 0x05a28006, + 0x05a289a7, + 0x05a36006, + 0x05a369a7, + 0x05a44006, + 0x05a449a7, + 0x05a52006, + 0x05a529a7, + 0x05a60006, + 0x05a609a7, + 0x05a6e006, + 0x05a6e9a7, + 0x05a7c006, + 0x05a7c9a7, + 0x05a8a006, + 0x05a8a9a7, + 0x05a98006, + 0x05a989a7, + 0x05aa6006, + 0x05aa69a7, + 0x05ab4006, + 0x05ab49a7, + 0x05ac2006, + 0x05ac29a7, + 0x05ad0006, + 0x05ad09a7, + 0x05ade006, + 0x05ade9a7, + 0x05aec006, + 0x05aec9a7, + 0x05afa006, + 0x05afa9a7, + 0x05b08006, + 0x05b089a7, + 0x05b16006, + 0x05b169a7, + 0x05b24006, + 0x05b249a7, + 0x05b32006, + 0x05b329a7, + 0x05b40006, + 0x05b409a7, + 0x05b4e006, + 0x05b4e9a7, + 0x05b5c006, + 0x05b5c9a7, + 0x05b6a006, + 0x05b6a9a7, + 0x05b78006, + 0x05b789a7, + 0x05b86006, + 0x05b869a7, + 0x05b94006, + 0x05b949a7, + 0x05ba2006, + 0x05ba29a7, + 0x05bb0006, + 0x05bb09a7, + 0x05bbe006, + 0x05bbe9a7, + 0x05bcc006, + 0x05bcc9a7, + 0x05bda006, + 0x05bda9a7, + 0x05be8006, + 0x05be89a7, + 0x05bf6006, + 0x05bf69a7, + 0x05c04006, + 0x05c049a7, + 0x05c12006, + 0x05c129a7, + 0x05c20006, + 0x05c209a7, + 0x05c2e006, + 0x05c2e9a7, + 0x05c3c006, + 0x05c3c9a7, + 0x05c4a006, + 0x05c4a9a7, + 0x05c58006, + 0x05c589a7, + 0x05c66006, + 0x05c669a7, + 0x05c74006, + 0x05c749a7, + 0x05c82006, + 0x05c829a7, + 0x05c90006, + 0x05c909a7, + 0x05c9e006, + 0x05c9e9a7, + 0x05cac006, + 0x05cac9a7, + 0x05cba006, + 0x05cba9a7, + 0x05cc8006, + 0x05cc89a7, + 0x05cd6006, + 0x05cd69a7, + 0x05ce4006, + 0x05ce49a7, + 0x05cf2006, + 0x05cf29a7, + 0x05d00006, + 0x05d009a7, + 0x05d0e006, + 0x05d0e9a7, + 0x05d1c006, + 0x05d1c9a7, + 0x05d2a006, + 0x05d2a9a7, + 0x05d38006, + 0x05d389a7, + 0x05d46006, + 0x05d469a7, + 0x05d54006, + 0x05d549a7, + 0x05d62006, + 0x05d629a7, + 0x05d70006, + 0x05d709a7, + 0x05d7e006, + 0x05d7e9a7, + 0x05d8c006, + 0x05d8c9a7, + 0x05d9a006, + 0x05d9a9a7, + 0x05da8006, + 0x05da89a7, + 0x05db6006, + 0x05db69a7, + 0x05dc4006, + 0x05dc49a7, + 0x05dd2006, + 0x05dd29a7, + 0x05de0006, + 0x05de09a7, + 0x05dee006, + 0x05dee9a7, + 0x05dfc006, + 0x05dfc9a7, + 0x05e0a006, + 0x05e0a9a7, + 0x05e18006, + 0x05e189a7, + 0x05e26006, + 0x05e269a7, + 0x05e34006, + 0x05e349a7, + 0x05e42006, + 0x05e429a7, + 0x05e50006, + 0x05e509a7, + 0x05e5e006, + 0x05e5e9a7, + 0x05e6c006, + 0x05e6c9a7, + 0x05e7a006, + 0x05e7a9a7, + 0x05e88006, + 0x05e889a7, + 0x05e96006, + 0x05e969a7, + 0x05ea4006, + 0x05ea49a7, + 0x05eb2006, + 0x05eb29a7, + 0x05ec0006, + 0x05ec09a7, + 0x05ece006, + 0x05ece9a7, + 0x05edc006, + 0x05edc9a7, + 0x05eea006, + 0x05eea9a7, + 0x05ef8006, + 0x05ef89a7, + 0x05f06006, + 0x05f069a7, + 0x05f14006, + 0x05f149a7, + 0x05f22006, + 0x05f229a7, + 0x05f30006, + 0x05f309a7, + 0x05f3e006, + 0x05f3e9a7, + 0x05f4c006, + 0x05f4c9a7, + 0x05f5a006, + 0x05f5a9a7, + 0x05f68006, + 0x05f689a7, + 0x05f76006, + 0x05f769a7, + 0x05f84006, + 0x05f849a7, + 0x05f92006, + 0x05f929a7, + 0x05fa0006, + 0x05fa09a7, + 0x05fae006, + 0x05fae9a7, + 0x05fbc006, + 0x05fbc9a7, + 0x05fca006, + 0x05fca9a7, + 0x05fd8006, + 0x05fd89a7, + 0x05fe6006, + 0x05fe69a7, + 0x05ff4006, + 0x05ff49a7, + 0x06002006, + 0x060029a7, + 0x06010006, + 0x060109a7, + 0x0601e006, + 0x0601e9a7, + 0x0602c006, + 0x0602c9a7, + 0x0603a006, + 0x0603a9a7, + 0x06048006, + 0x060489a7, + 0x06056006, + 0x060569a7, + 0x06064006, + 0x060649a7, + 0x06072006, + 0x060729a7, + 0x06080006, + 0x060809a7, + 0x0608e006, + 0x0608e9a7, + 0x0609c006, + 0x0609c9a7, + 0x060aa006, + 0x060aa9a7, + 0x060b8006, + 0x060b89a7, + 0x060c6006, + 0x060c69a7, + 0x060d4006, + 0x060d49a7, + 0x060e2006, + 0x060e29a7, + 0x060f0006, + 0x060f09a7, + 0x060fe006, + 0x060fe9a7, + 0x0610c006, + 0x0610c9a7, + 0x0611a006, + 0x0611a9a7, + 0x06128006, + 0x061289a7, + 0x06136006, + 0x061369a7, + 0x06144006, + 0x061449a7, + 0x06152006, + 0x061529a7, + 0x06160006, + 0x061609a7, + 0x0616e006, + 0x0616e9a7, + 0x0617c006, + 0x0617c9a7, + 0x0618a006, + 0x0618a9a7, + 0x06198006, + 0x061989a7, + 0x061a6006, + 0x061a69a7, + 0x061b4006, + 0x061b49a7, + 0x061c2006, + 0x061c29a7, + 0x061d0006, + 0x061d09a7, + 0x061de006, + 0x061de9a7, + 0x061ec006, + 0x061ec9a7, + 0x061fa006, + 0x061fa9a7, + 0x06208006, + 0x062089a7, + 0x06216006, + 0x062169a7, + 0x06224006, + 0x062249a7, + 0x06232006, + 0x062329a7, + 0x06240006, + 0x062409a7, + 0x0624e006, + 0x0624e9a7, + 0x0625c006, + 0x0625c9a7, + 0x0626a006, + 0x0626a9a7, + 0x06278006, + 0x062789a7, + 0x06286006, + 0x062869a7, + 0x06294006, + 0x062949a7, + 0x062a2006, + 0x062a29a7, + 0x062b0006, + 0x062b09a7, + 0x062be006, + 0x062be9a7, + 0x062cc006, + 0x062cc9a7, + 0x062da006, + 0x062da9a7, + 0x062e8006, + 0x062e89a7, + 0x062f6006, + 0x062f69a7, + 0x06304006, + 0x063049a7, + 0x06312006, + 0x063129a7, + 0x06320006, + 0x063209a7, + 0x0632e006, + 0x0632e9a7, + 0x0633c006, + 0x0633c9a7, + 0x0634a006, + 0x0634a9a7, + 0x06358006, + 0x063589a7, + 0x06366006, + 0x063669a7, + 0x06374006, + 0x063749a7, + 0x06382006, + 0x063829a7, + 0x06390006, + 0x063909a7, + 0x0639e006, + 0x0639e9a7, + 0x063ac006, + 0x063ac9a7, + 0x063ba006, + 0x063ba9a7, + 0x063c8006, + 0x063c89a7, + 0x063d6006, + 0x063d69a7, + 0x063e4006, + 0x063e49a7, + 0x063f2006, + 0x063f29a7, + 0x06400006, + 0x064009a7, + 0x0640e006, + 0x0640e9a7, + 0x0641c006, + 0x0641c9a7, + 0x0642a006, + 0x0642a9a7, + 0x06438006, + 0x064389a7, + 0x06446006, + 0x064469a7, + 0x06454006, + 0x064549a7, + 0x06462006, + 0x064629a7, + 0x06470006, + 0x064709a7, + 0x0647e006, + 0x0647e9a7, + 0x0648c006, + 0x0648c9a7, + 0x0649a006, + 0x0649a9a7, + 0x064a8006, + 0x064a89a7, + 0x064b6006, + 0x064b69a7, + 0x064c4006, + 0x064c49a7, + 0x064d2006, + 0x064d29a7, + 0x064e0006, + 0x064e09a7, + 0x064ee006, + 0x064ee9a7, + 0x064fc006, + 0x064fc9a7, + 0x0650a006, + 0x0650a9a7, + 0x06518006, + 0x065189a7, + 0x06526006, + 0x065269a7, + 0x06534006, + 0x065349a7, + 0x06542006, + 0x065429a7, + 0x06550006, + 0x065509a7, + 0x0655e006, + 0x0655e9a7, + 0x0656c006, + 0x0656c9a7, + 0x0657a006, + 0x0657a9a7, + 0x06588006, + 0x065889a7, + 0x06596006, + 0x065969a7, + 0x065a4006, + 0x065a49a7, + 0x065b2006, + 0x065b29a7, + 0x065c0006, + 0x065c09a7, + 0x065ce006, + 0x065ce9a7, + 0x065dc006, + 0x065dc9a7, + 0x065ea006, + 0x065ea9a7, + 0x065f8006, + 0x065f89a7, + 0x06606006, + 0x066069a7, + 0x06614006, + 0x066149a7, + 0x06622006, + 0x066229a7, + 0x06630006, + 0x066309a7, + 0x0663e006, + 0x0663e9a7, + 0x0664c006, + 0x0664c9a7, + 0x0665a006, + 0x0665a9a7, + 0x06668006, + 0x066689a7, + 0x06676006, + 0x066769a7, + 0x06684006, + 0x066849a7, + 0x06692006, + 0x066929a7, + 0x066a0006, + 0x066a09a7, + 0x066ae006, + 0x066ae9a7, + 0x066bc006, + 0x066bc9a7, + 0x066ca006, + 0x066ca9a7, + 0x066d8006, + 0x066d89a7, + 0x066e6006, + 0x066e69a7, + 0x066f4006, + 0x066f49a7, + 0x06702006, + 0x067029a7, + 0x06710006, + 0x067109a7, + 0x0671e006, + 0x0671e9a7, + 0x0672c006, + 0x0672c9a7, + 0x0673a006, + 0x0673a9a7, + 0x06748006, + 0x067489a7, + 0x06756006, + 0x067569a7, + 0x06764006, + 0x067649a7, + 0x06772006, + 0x067729a7, + 0x06780006, + 0x067809a7, + 0x0678e006, + 0x0678e9a7, + 0x0679c006, + 0x0679c9a7, + 0x067aa006, + 0x067aa9a7, + 0x067b8006, + 0x067b89a7, + 0x067c6006, + 0x067c69a7, + 0x067d4006, + 0x067d49a7, + 0x067e2006, + 0x067e29a7, + 0x067f0006, + 0x067f09a7, + 0x067fe006, + 0x067fe9a7, + 0x0680c006, + 0x0680c9a7, + 0x0681a006, + 0x0681a9a7, + 0x06828006, + 0x068289a7, + 0x06836006, + 0x068369a7, + 0x06844006, + 0x068449a7, + 0x06852006, + 0x068529a7, + 0x06860006, + 0x068609a7, + 0x0686e006, + 0x0686e9a7, + 0x0687c006, + 0x0687c9a7, + 0x0688a006, + 0x0688a9a7, + 0x06898006, + 0x068989a7, + 0x068a6006, + 0x068a69a7, + 0x068b4006, + 0x068b49a7, + 0x068c2006, + 0x068c29a7, + 0x068d0006, + 0x068d09a7, + 0x068de006, + 0x068de9a7, + 0x068ec006, + 0x068ec9a7, + 0x068fa006, + 0x068fa9a7, + 0x06908006, + 0x069089a7, + 0x06916006, + 0x069169a7, + 0x06924006, + 0x069249a7, + 0x06932006, + 0x069329a7, + 0x06940006, + 0x069409a7, + 0x0694e006, + 0x0694e9a7, + 0x0695c006, + 0x0695c9a7, + 0x0696a006, + 0x0696a9a7, + 0x06978006, + 0x069789a7, + 0x06986006, + 0x069869a7, + 0x06994006, + 0x069949a7, + 0x069a2006, + 0x069a29a7, + 0x069b0006, + 0x069b09a7, + 0x069be006, + 0x069be9a7, + 0x069cc006, + 0x069cc9a7, + 0x069da006, + 0x069da9a7, + 0x069e8006, + 0x069e89a7, + 0x069f6006, + 0x069f69a7, + 0x06a04006, + 0x06a049a7, + 0x06a12006, + 0x06a129a7, + 0x06a20006, + 0x06a209a7, + 0x06a2e006, + 0x06a2e9a7, + 0x06a3c006, + 0x06a3c9a7, + 0x06a4a006, + 0x06a4a9a7, + 0x06a58006, + 0x06a589a7, + 0x06a66006, + 0x06a669a7, + 0x06a74006, + 0x06a749a7, + 0x06a82006, + 0x06a829a7, + 0x06a90006, + 0x06a909a7, + 0x06a9e006, + 0x06a9e9a7, + 0x06aac006, + 0x06aac9a7, + 0x06aba006, + 0x06aba9a7, + 0x06ac8006, + 0x06ac89a7, + 0x06ad6006, + 0x06ad69a7, + 0x06ae4006, + 0x06ae49a7, + 0x06af2006, + 0x06af29a7, + 0x06b00006, + 0x06b009a7, + 0x06b0e006, + 0x06b0e9a7, + 0x06b1c006, + 0x06b1c9a7, + 0x06b2a006, + 0x06b2a9a7, + 0x06b38006, + 0x06b389a7, + 0x06b46006, + 0x06b469a7, + 0x06b54006, + 0x06b549a7, + 0x06b62006, + 0x06b629a7, + 0x06b70006, + 0x06b709a7, + 0x06b7e006, + 0x06b7e9a7, + 0x06b8c006, + 0x06b8c9a7, + 0x06b9a006, + 0x06b9a9a7, + 0x06ba8006, + 0x06ba89a7, + 0x06bb6006, + 0x06bb69a7, + 0x06bc4006, + 0x06bc49a7, + 0x06bd816c, + 0x06be5b0b, + 0x07d8f002, + 0x07f000f2, + 0x07f100f2, + 0x07f7f801, + 0x07fcf012, + 0x07ff80b1, + 0x080fe802, + 0x08170002, + 0x081bb042, + 0x08500822, + 0x08502812, + 0x08506032, + 0x0851c022, + 0x0851f802, + 0x08572812, + 0x08692032, + 0x08755812, + 0x0877e822, + 0x087a30a2, + 0x087c1032, + 0x0880000a, + 0x08800802, + 0x0880100a, + 0x0881c0e2, + 0x08838002, + 0x08839812, + 0x0883f822, + 0x0884100a, + 0x0885802a, + 0x08859832, + 0x0885b81a, + 0x0885c812, + 0x0885e808, + 0x08861002, + 0x08866808, + 0x08880022, + 0x08893842, + 0x0889600a, + 0x08896872, + 0x088a281a, + 0x088b9802, + 0x088c0012, + 0x088c100a, + 0x088d982a, + 0x088db082, + 0x088df81a, + 0x088e1018, + 0x088e4832, + 0x088e700a, + 0x088e7802, + 0x0891602a, + 0x08917822, + 0x0891901a, + 0x0891a002, + 0x0891a80a, + 0x0891b012, + 0x0891f002, + 0x08920802, + 0x0896f802, + 0x0897002a, + 0x08971872, + 0x08980012, + 0x0898101a, + 0x0899d812, + 0x0899f002, + 0x0899f80a, + 0x089a0002, + 0x089a083a, + 0x089a381a, + 0x089a582a, + 0x089ab802, + 0x089b101a, + 0x089b3062, + 0x089b8042, + 0x08a1a82a, + 0x08a1c072, + 0x08a2001a, + 0x08a21022, + 0x08a2280a, + 0x08a23002, + 0x08a2f002, + 0x08a58002, + 0x08a5881a, + 0x08a59852, + 0x08a5c80a, + 0x08a5d002, + 0x08a5d81a, + 0x08a5e802, + 0x08a5f00a, + 0x08a5f812, + 0x08a6080a, + 0x08a61012, + 0x08ad7802, + 0x08ad801a, + 0x08ad9032, + 0x08adc03a, + 0x08ade012, + 0x08adf00a, + 0x08adf812, + 0x08aee012, + 0x08b1802a, + 0x08b19872, + 0x08b1d81a, + 0x08b1e802, + 0x08b1f00a, + 0x08b1f812, + 0x08b55802, + 0x08b5600a, + 0x08b56802, + 0x08b5701a, + 0x08b58052, + 0x08b5b00a, + 0x08b5b802, + 0x08b8e822, + 0x08b91032, + 0x08b9300a, + 0x08b93842, + 0x08c1602a, + 0x08c17882, + 0x08c1c00a, + 0x08c1c812, + 0x08c98002, + 0x08c9884a, + 0x08c9b81a, + 0x08c9d812, + 0x08c9e80a, + 0x08c9f002, + 0x08c9f808, + 0x08ca000a, + 0x08ca0808, + 0x08ca100a, + 0x08ca1802, + 0x08ce882a, + 0x08cea032, + 0x08ced012, + 0x08cee03a, + 0x08cf0002, + 0x08cf200a, + 0x08d00892, + 0x08d19852, + 0x08d1c80a, + 0x08d1d008, + 0x08d1d832, + 0x08d23802, + 0x08d28852, + 0x08d2b81a, + 0x08d2c822, + 0x08d42058, + 0x08d450c2, + 0x08d4b80a, + 0x08d4c012, + 0x08e1780a, + 0x08e18062, + 0x08e1c052, + 0x08e1f00a, + 0x08e1f802, + 0x08e49152, + 0x08e5480a, + 0x08e55062, + 0x08e5880a, + 0x08e59012, + 0x08e5a00a, + 0x08e5a812, + 0x08e98852, + 0x08e9d002, + 0x08e9e012, + 0x08e9f862, + 0x08ea3008, + 0x08ea3802, + 0x08ec504a, + 0x08ec8012, + 0x08ec981a, + 0x08eca802, + 0x08ecb00a, + 0x08ecb802, + 0x08f79812, + 0x08f7a81a, + 0x08f80012, + 0x08f81008, + 0x08f8180a, + 0x08f9a01a, + 0x08f9b042, + 0x08f9f01a, + 0x08fa0002, + 0x08fa080a, + 0x08fa1002, + 0x09a180f1, + 0x09a20002, + 0x09a238e2, + 0x0b578042, + 0x0b598062, + 0x0b7a7802, + 0x0b7a8b6a, + 0x0b7c7832, + 0x0b7f2002, + 0x0b7f801a, + 0x0de4e812, + 0x0de50031, + 0x0e7802d2, + 0x0e798162, + 0x0e8b2802, + 0x0e8b300a, + 0x0e8b3822, + 0x0e8b680a, + 0x0e8b7042, + 0x0e8b9871, + 0x0e8bd872, + 0x0e8c2862, + 0x0e8d5032, + 0x0e921022, + 0x0ed00362, + 0x0ed1db12, + 0x0ed3a802, + 0x0ed42002, + 0x0ed4d842, + 0x0ed508e2, + 0x0f000062, + 0x0f004102, + 0x0f00d862, + 0x0f011812, + 0x0f013042, + 0x0f047802, + 0x0f098062, + 0x0f157002, + 0x0f176032, + 0x0f276032, + 0x0f468062, + 0x0f4a2062, + 0x0f8007f3, + 0x0f8407f3, + 0x0f886823, + 0x0f897803, + 0x0f8b6053, + 0x0f8bf013, + 0x0f8c7003, + 0x0f8c8893, + 0x0f8d6b83, + 0x0f8f3199, + 0x0f9008e3, + 0x0f90d003, + 0x0f917803, + 0x0f919083, + 0x0f91e033, + 0x0f924ff3, + 0x0f964ff3, + 0x0f9a4ff3, + 0x0f9e4b13, + 0x0f9fd842, + 0x0fa007f3, + 0x0fa407f3, + 0x0fa803d3, + 0x0faa37f3, + 0x0fae37f3, + 0x0fb23093, + 0x0fb407f3, + 0x0fbba0b3, + 0x0fbeaaa3, + 0x0fc06033, + 0x0fc24073, + 0x0fc2d053, + 0x0fc44073, + 0x0fc57513, + 0x0fc862e3, + 0x0fc9e093, + 0x0fca3ff3, + 0x0fce3ff3, + 0x0fd23ff3, + 0x0fd63b83, + 0x0fe007f3, + 0x0fe407f3, + 0x0fe807f3, + 0x0fec07f3, + 0x0ff007f3, + 0x0ff407f3, + 0x0ff807f3, + 0x0ffc07d3, + 0x700001f1, + 0x700105f2, + 0x700407f1, + 0x700807f2, + 0x700c06f2, + 0x700f87f1, + 0x701387f1, + 0x701787f1, + 0x701b87f1, + 0x701f87f1, + 0x702387f1, + 0x702787f1, + 0x702b87f1, + 0x702f87f1, + 0x703387f1, + 0x703787f1, + 0x703b87f1, + 0x703f87f1, + 0x704387f1, + 0x704787f1, + 0x704b87f1, + 0x704f87f1, + 0x705387f1, + 0x705787f1, + 0x705b87f1, + 0x705f87f1, + 0x706387f1, + 0x706787f1, + 0x706b87f1, + 0x706f87f1, + 0x707387f1, + 0x707787f1, + 0x707b87f1, + 0x707f80f1}; + +/// Returns the extended grapheme cluster bondary property of a code point. +[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr __property __get_property(const char32_t __code_point) noexcept { + // The algorithm searches for the upper bound of the range and, when found, + // steps back one entry. This algorithm is used since the code point can be + // anywhere in the range. After a lower bound is found the next step is to + // compare whether the code unit is indeed in the range. + // + // Since the entry contains a code unit, size, and property the code point + // being sought needs to be adjusted. Just shifting the code point to the + // proper position doesn't work; suppose an entry has property 0, size 1, + // and lower bound 3. This results in the entry 0x1810. + // When searching for code point 3 it will search for 0x1800, find 0x1810 + // and moves to the previous entry. Thus the lower bound value will never + // be found. + // The simple solution is to set the bits belonging to the property and + // size. Then the upper bound for code point 3 will return the entry after + // 0x1810. After moving to the previous entry the algorithm arrives at the + // correct entry. + ptrdiff_t __i = std::ranges::upper_bound(__entries, (__code_point << 11) | 0x7ffu) - __entries; + if (__i == 0) + return __property::__none; + + --__i; + uint32_t __upper_bound = (__entries[__i] >> 11) + ((__entries[__i] >> 4) & 0x7f); + if (__code_point <= __upper_bound) + return static_cast<__property>(__entries[__i] & 0xf); + + return __property::__none; +} + +} // namespace __extended_grapheme_custer_property_boundary + +#endif //_LIBCPP_STD_VER > 17 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___FORMAT_EXTENDED_GRAPHEME_CLUSTER_TABLE_H diff --git a/app/src/main/cpp/libcxx/include/__format/format_arg.h b/app/src/main/cpp/libcxx/include/__format/format_arg.h new file mode 100644 index 0000000..771a03f --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__format/format_arg.h @@ -0,0 +1,302 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___FORMAT_FORMAT_ARG_H +#define _LIBCPP___FORMAT_FORMAT_ARG_H + +#include <__assert> +#include <__concepts/arithmetic.h> +#include <__config> +#include <__format/format_error.h> +#include <__format/format_fwd.h> +#include <__format/format_parse_context.h> +#include <__functional/invoke.h> +#include <__memory/addressof.h> +#include <__utility/forward.h> +#include <__utility/unreachable.h> +#include <__variant/monostate.h> +#include +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 17 + +namespace __format { +/// The type stored in @ref basic_format_arg. +/// +/// @note The 128-bit types are unconditionally in the list to avoid the values +/// of the enums to depend on the availability of 128-bit integers. +/// +/// @note The value is stored as a 5-bit value in the __packed_arg_t_bits. This +/// limits the maximum number of elements to 32. +/// When modifying update the test +/// test/libcxx/utilities/format/format.arguments/format.arg/arg_t.compile.pass.cpp +/// It could be packed in 4-bits but that means a new type directly becomes an +/// ABI break. The packed type is 64-bit so this reduces the maximum number of +/// packed elements from 16 to 12. +/// +/// @note Some members of this enum are an extension. These extensions need +/// special behaviour in visit_format_arg. There they need to be wrapped in a +/// handle to satisfy the user observable behaviour. The internal function +/// __visit_format_arg doesn't do this wrapping. So in the format functions +/// this function is used to avoid unneeded overhead. +enum class _LIBCPP_ENUM_VIS __arg_t : uint8_t { + __none, + __boolean, + __char_type, + __int, + __long_long, + __i128, // extension + __unsigned, + __unsigned_long_long, + __u128, // extension + __float, + __double, + __long_double, + __const_char_type_ptr, + __string_view, + __ptr, + __handle +}; + +inline constexpr unsigned __packed_arg_t_bits = 5; +inline constexpr uint8_t __packed_arg_t_mask = 0x1f; + +inline constexpr unsigned __packed_types_storage_bits = 64; +inline constexpr unsigned __packed_types_max = __packed_types_storage_bits / __packed_arg_t_bits; + +_LIBCPP_HIDE_FROM_ABI +constexpr bool __use_packed_format_arg_store(size_t __size) { return __size <= __packed_types_max; } + +_LIBCPP_HIDE_FROM_ABI +constexpr __arg_t __get_packed_type(uint64_t __types, size_t __id) { + _LIBCPP_ASSERT(__id <= __packed_types_max, ""); + + if (__id > 0) + __types >>= __id * __packed_arg_t_bits; + + return static_cast<__format::__arg_t>(__types & __packed_arg_t_mask); +} + +} // namespace __format + +// This function is not user obervable, so it can directly use the non-standard +// types of the "variant". See __arg_t for more details. +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT decltype(auto) +__visit_format_arg(_Visitor&& __vis, basic_format_arg<_Context> __arg) { + switch (__arg.__type_) { + case __format::__arg_t::__none: + return _VSTD::invoke(_VSTD::forward<_Visitor>(__vis), __arg.__value_.__monostate_); + case __format::__arg_t::__boolean: + return _VSTD::invoke(_VSTD::forward<_Visitor>(__vis), __arg.__value_.__boolean_); + case __format::__arg_t::__char_type: + return _VSTD::invoke(_VSTD::forward<_Visitor>(__vis), __arg.__value_.__char_type_); + case __format::__arg_t::__int: + return _VSTD::invoke(_VSTD::forward<_Visitor>(__vis), __arg.__value_.__int_); + case __format::__arg_t::__long_long: + return _VSTD::invoke(_VSTD::forward<_Visitor>(__vis), __arg.__value_.__long_long_); + case __format::__arg_t::__i128: +# ifndef _LIBCPP_HAS_NO_INT128 + return _VSTD::invoke(_VSTD::forward<_Visitor>(__vis), __arg.__value_.__i128_); +# else + __libcpp_unreachable(); +# endif + case __format::__arg_t::__unsigned: + return _VSTD::invoke(_VSTD::forward<_Visitor>(__vis), __arg.__value_.__unsigned_); + case __format::__arg_t::__unsigned_long_long: + return _VSTD::invoke(_VSTD::forward<_Visitor>(__vis), __arg.__value_.__unsigned_long_long_); + case __format::__arg_t::__u128: +# ifndef _LIBCPP_HAS_NO_INT128 + return _VSTD::invoke(_VSTD::forward<_Visitor>(__vis), __arg.__value_.__u128_); +# else + __libcpp_unreachable(); +# endif + case __format::__arg_t::__float: + return _VSTD::invoke(_VSTD::forward<_Visitor>(__vis), __arg.__value_.__float_); + case __format::__arg_t::__double: + return _VSTD::invoke(_VSTD::forward<_Visitor>(__vis), __arg.__value_.__double_); + case __format::__arg_t::__long_double: + return _VSTD::invoke(_VSTD::forward<_Visitor>(__vis), __arg.__value_.__long_double_); + case __format::__arg_t::__const_char_type_ptr: + return _VSTD::invoke(_VSTD::forward<_Visitor>(__vis), __arg.__value_.__const_char_type_ptr_); + case __format::__arg_t::__string_view: + return _VSTD::invoke(_VSTD::forward<_Visitor>(__vis), __arg.__value_.__string_view_); + case __format::__arg_t::__ptr: + return _VSTD::invoke(_VSTD::forward<_Visitor>(__vis), __arg.__value_.__ptr_); + case __format::__arg_t::__handle: + return _VSTD::invoke(_VSTD::forward<_Visitor>(__vis), + typename basic_format_arg<_Context>::handle{__arg.__value_.__handle_}); + } + + __libcpp_unreachable(); +} + +/// Contains the values used in basic_format_arg. +/// +/// This is a separate type so it's possible to store the values and types in +/// separate arrays. +template +class __basic_format_arg_value { + using _CharT = typename _Context::char_type; + +public: + /// Contains the implementation for basic_format_arg::handle. + struct __handle { + template + _LIBCPP_HIDE_FROM_ABI explicit __handle(_Tp&& __v) noexcept + : __ptr_(_VSTD::addressof(__v)), + __format_([](basic_format_parse_context<_CharT>& __parse_ctx, _Context& __ctx, const void* __ptr) { + using _Dp = remove_cvref_t<_Tp>; + using _Formatter = typename _Context::template formatter_type<_Dp>; + constexpr bool __const_formattable = + requires { _Formatter().format(std::declval(), std::declval<_Context&>()); }; + using _Qp = conditional_t<__const_formattable, const _Dp, _Dp>; + + static_assert(__const_formattable || !is_const_v>, "Mandated by [format.arg]/18"); + + _Formatter __f; + __parse_ctx.advance_to(__f.parse(__parse_ctx)); + __ctx.advance_to(__f.format(*const_cast<_Qp*>(static_cast(__ptr)), __ctx)); + }) {} + + const void* __ptr_; + void (*__format_)(basic_format_parse_context<_CharT>&, _Context&, const void*); + }; + + union { + monostate __monostate_; + bool __boolean_; + _CharT __char_type_; + int __int_; + unsigned __unsigned_; + long long __long_long_; + unsigned long long __unsigned_long_long_; +# ifndef _LIBCPP_HAS_NO_INT128 + __int128_t __i128_; + __uint128_t __u128_; +# endif + float __float_; + double __double_; + long double __long_double_; + const _CharT* __const_char_type_ptr_; + basic_string_view<_CharT> __string_view_; + const void* __ptr_; + __handle __handle_; + }; + + // These constructors contain the exact storage type used. If adjustments are + // required, these will be done in __create_format_arg. + + _LIBCPP_HIDE_FROM_ABI __basic_format_arg_value() noexcept : __monostate_() {} + _LIBCPP_HIDE_FROM_ABI __basic_format_arg_value(bool __value) noexcept : __boolean_(__value) {} + _LIBCPP_HIDE_FROM_ABI __basic_format_arg_value(_CharT __value) noexcept : __char_type_(__value) {} + _LIBCPP_HIDE_FROM_ABI __basic_format_arg_value(int __value) noexcept : __int_(__value) {} + _LIBCPP_HIDE_FROM_ABI __basic_format_arg_value(unsigned __value) noexcept : __unsigned_(__value) {} + _LIBCPP_HIDE_FROM_ABI __basic_format_arg_value(long long __value) noexcept : __long_long_(__value) {} + _LIBCPP_HIDE_FROM_ABI __basic_format_arg_value(unsigned long long __value) noexcept + : __unsigned_long_long_(__value) {} +# ifndef _LIBCPP_HAS_NO_INT128 + _LIBCPP_HIDE_FROM_ABI __basic_format_arg_value(__int128_t __value) noexcept : __i128_(__value) {} + _LIBCPP_HIDE_FROM_ABI __basic_format_arg_value(__uint128_t __value) noexcept : __u128_(__value) {} +# endif + _LIBCPP_HIDE_FROM_ABI __basic_format_arg_value(float __value) noexcept : __float_(__value) {} + _LIBCPP_HIDE_FROM_ABI __basic_format_arg_value(double __value) noexcept : __double_(__value) {} + _LIBCPP_HIDE_FROM_ABI __basic_format_arg_value(long double __value) noexcept : __long_double_(__value) {} + _LIBCPP_HIDE_FROM_ABI __basic_format_arg_value(const _CharT* __value) noexcept : __const_char_type_ptr_(__value) {} + _LIBCPP_HIDE_FROM_ABI __basic_format_arg_value(basic_string_view<_CharT> __value) noexcept + : __string_view_(__value) {} + _LIBCPP_HIDE_FROM_ABI __basic_format_arg_value(const void* __value) noexcept : __ptr_(__value) {} + _LIBCPP_HIDE_FROM_ABI __basic_format_arg_value(__handle __value) noexcept + // TODO FMT Investigate why it doesn't work without the forward. + : __handle_(std::forward<__handle>(__value)) {} +}; + +template +class _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT basic_format_arg { +public: + class _LIBCPP_TEMPLATE_VIS handle; + + _LIBCPP_HIDE_FROM_ABI basic_format_arg() noexcept + : __type_{__format::__arg_t::__none} {} + + _LIBCPP_HIDE_FROM_ABI explicit operator bool() const noexcept { + return __type_ != __format::__arg_t::__none; + } + +private: + using char_type = typename _Context::char_type; + + // TODO FMT Implement constrain [format.arg]/4 + // Constraints: The template specialization + // typename Context::template formatter_type + // meets the Formatter requirements ([formatter.requirements]). The extent + // to which an implementation determines that the specialization meets the + // Formatter requirements is unspecified, except that as a minimum the + // expression + // typename Context::template formatter_type() + // .format(declval(), declval()) + // shall be well-formed when treated as an unevaluated operand. + +public: + __basic_format_arg_value<_Context> __value_; + __format::__arg_t __type_; + + _LIBCPP_HIDE_FROM_ABI explicit basic_format_arg(__format::__arg_t __type, + __basic_format_arg_value<_Context> __value) noexcept + : __value_(__value), __type_(__type) {} +}; + +template +class _LIBCPP_TEMPLATE_VIS basic_format_arg<_Context>::handle { +public: + _LIBCPP_HIDE_FROM_ABI + void format(basic_format_parse_context& __parse_ctx, _Context& __ctx) const { + __handle_.__format_(__parse_ctx, __ctx, __handle_.__ptr_); + } + + _LIBCPP_HIDE_FROM_ABI explicit handle(typename __basic_format_arg_value<_Context>::__handle& __handle) noexcept + : __handle_(__handle) {} + +private: + typename __basic_format_arg_value<_Context>::__handle& __handle_; +}; + +// This function is user facing, so it must wrap the non-standard types of +// the "variant" in a handle to stay conforming. See __arg_t for more details. +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT decltype(auto) +visit_format_arg(_Visitor&& __vis, basic_format_arg<_Context> __arg) { + switch (__arg.__type_) { +# ifndef _LIBCPP_HAS_NO_INT128 + case __format::__arg_t::__i128: { + typename __basic_format_arg_value<_Context>::__handle __h{__arg.__value_.__i128_}; + return _VSTD::invoke(_VSTD::forward<_Visitor>(__vis), typename basic_format_arg<_Context>::handle{__h}); + } + + case __format::__arg_t::__u128: { + typename __basic_format_arg_value<_Context>::__handle __h{__arg.__value_.__u128_}; + return _VSTD::invoke(_VSTD::forward<_Visitor>(__vis), typename basic_format_arg<_Context>::handle{__h}); + } +# endif + default: + return _VSTD::__visit_format_arg(_VSTD::forward<_Visitor>(__vis), __arg); + } +} + +#endif //_LIBCPP_STD_VER > 17 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___FORMAT_FORMAT_ARG_H diff --git a/app/src/main/cpp/libcxx/include/__format/format_arg_store.h b/app/src/main/cpp/libcxx/include/__format/format_arg_store.h new file mode 100644 index 0000000..6f4f4c3 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__format/format_arg_store.h @@ -0,0 +1,254 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___FORMAT_FORMAT_ARG_STORE_H +#define _LIBCPP___FORMAT_FORMAT_ARG_STORE_H + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#include <__concepts/arithmetic.h> +#include <__concepts/same_as.h> +#include <__config> +#include <__format/concepts.h> +#include <__format/format_arg.h> +#include <__utility/forward.h> +#include +#include +#include +#include + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 17 + +namespace __format { + +/// \returns The @c __arg_t based on the type of the formatting argument. +/// +/// \pre \c __formattable<_Tp, typename _Context::char_type> +template +consteval __arg_t __determine_arg_t(); + +// Boolean +template _Tp> +consteval __arg_t __determine_arg_t() { + return __arg_t::__boolean; +} + +// Char +template _Tp> +consteval __arg_t __determine_arg_t() { + return __arg_t::__char_type; +} +# ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +template + requires(same_as && same_as<_CharT, char>) +consteval __arg_t __determine_arg_t() { + return __arg_t::__char_type; +} +# endif + +// Signed integers +template +consteval __arg_t __determine_arg_t() { + if constexpr (sizeof(_Tp) <= sizeof(int)) + return __arg_t::__int; + else if constexpr (sizeof(_Tp) <= sizeof(long long)) + return __arg_t::__long_long; +# ifndef _LIBCPP_HAS_NO_INT128 + else if constexpr (sizeof(_Tp) == sizeof(__int128_t)) + return __arg_t::__i128; +# endif + else + static_assert(sizeof(_Tp) == 0, "an unsupported signed integer was used"); +} + +// Unsigned integers +template +consteval __arg_t __determine_arg_t() { + if constexpr (sizeof(_Tp) <= sizeof(unsigned)) + return __arg_t::__unsigned; + else if constexpr (sizeof(_Tp) <= sizeof(unsigned long long)) + return __arg_t::__unsigned_long_long; +# ifndef _LIBCPP_HAS_NO_INT128 + else if constexpr (sizeof(_Tp) == sizeof(__uint128_t)) + return __arg_t::__u128; +# endif + else + static_assert(sizeof(_Tp) == 0, "an unsupported unsigned integer was used"); +} + +// Floating-point +template _Tp> +consteval __arg_t __determine_arg_t() { + return __arg_t::__float; +} +template _Tp> +consteval __arg_t __determine_arg_t() { + return __arg_t::__double; +} +template _Tp> +consteval __arg_t __determine_arg_t() { + return __arg_t::__long_double; +} + +// Char pointer +template + requires(same_as || same_as) +consteval __arg_t __determine_arg_t() { + return __arg_t::__const_char_type_ptr; +} + +// Char array +template + requires(is_array_v<_Tp> && same_as<_Tp, typename _Context::char_type[extent_v<_Tp>]>) +consteval __arg_t __determine_arg_t() { + return __arg_t::__string_view; +} + +// String view +template + requires(same_as && + same_as<_Tp, basic_string_view>) +consteval __arg_t __determine_arg_t() { + return __arg_t::__string_view; +} + +// String +template + requires( + same_as && + same_as<_Tp, basic_string>) +consteval __arg_t __determine_arg_t() { + return __arg_t::__string_view; +} + +// Pointers +template + requires(same_as<_Ptr, void*> || same_as<_Ptr, const void*> || same_as<_Ptr, nullptr_t>) +consteval __arg_t __determine_arg_t() { + return __arg_t::__ptr; +} + +// Handle +// +// Note this version can't be constrained avoiding ambiguous overloads. +// That means it can be instantiated by disabled formatters. To solve this, a +// constrained version for not formattable formatters is added. That overload +// is marked as deleted to fail creating a storage type for disabled formatters. +template +consteval __arg_t __determine_arg_t() { + return __arg_t::__handle; +} + +template + requires(!__formattable<_Tp, typename _Context::char_type>) +consteval __arg_t __determine_arg_t() = delete; + +template +_LIBCPP_HIDE_FROM_ABI basic_format_arg<_Context> __create_format_arg(_Tp&& __value) noexcept { + constexpr __arg_t __arg = __determine_arg_t<_Context, remove_cvref_t<_Tp>>(); + static_assert(__arg != __arg_t::__none); + + // Not all types can be used to directly initialize the + // __basic_format_arg_value. First handle all types needing adjustment, the + // final else requires no adjustment. + if constexpr (__arg == __arg_t::__char_type) + // On some platforms initializing a wchar_t from a char is a narrowing + // conversion. + return basic_format_arg<_Context>{__arg, static_cast(__value)}; + else if constexpr (__arg == __arg_t::__int) + return basic_format_arg<_Context>{__arg, static_cast(__value)}; + else if constexpr (__arg == __arg_t::__long_long) + return basic_format_arg<_Context>{__arg, static_cast(__value)}; + else if constexpr (__arg == __arg_t::__unsigned) + return basic_format_arg<_Context>{__arg, static_cast(__value)}; + else if constexpr (__arg == __arg_t::__unsigned_long_long) + return basic_format_arg<_Context>{__arg, static_cast(__value)}; + else if constexpr (__arg == __arg_t::__string_view) + // Using std::size on a character array will add the NUL-terminator to the size. + if constexpr (is_array_v>) + return basic_format_arg<_Context>{ + __arg, basic_string_view{__value, extent_v> - 1}}; + else + // When the _Traits or _Allocator are different an implicit conversion will + // fail. + return basic_format_arg<_Context>{ + __arg, basic_string_view{__value.data(), __value.size()}}; + else if constexpr (__arg == __arg_t::__ptr) + return basic_format_arg<_Context>{__arg, static_cast(__value)}; + else if constexpr (__arg == __arg_t::__handle) + return basic_format_arg<_Context>{ + __arg, typename __basic_format_arg_value<_Context>::__handle{_VSTD::forward<_Tp>(__value)}}; + else + return basic_format_arg<_Context>{__arg, __value}; +} + +template +_LIBCPP_HIDE_FROM_ABI void __create_packed_storage(uint64_t& __types, __basic_format_arg_value<_Context>* __values, + _Args&&... __args) noexcept { + int __shift = 0; + ( + [&] { + basic_format_arg<_Context> __arg = __format::__create_format_arg<_Context>(__args); + if (__shift != 0) + __types |= static_cast(__arg.__type_) << __shift; + else + // Assigns the initial value. + __types = static_cast(__arg.__type_); + __shift += __packed_arg_t_bits; + *__values++ = __arg.__value_; + }(), + ...); +} + +template +_LIBCPP_HIDE_FROM_ABI void __store_basic_format_arg(basic_format_arg<_Context>* __data, _Args&&... __args) noexcept { + ([&] { *__data++ = __format::__create_format_arg<_Context>(__args); }(), ...); +} + +template +struct __packed_format_arg_store { + __basic_format_arg_value<_Context> __values_[N]; + uint64_t __types_; +}; + +template +struct __unpacked_format_arg_store { + basic_format_arg<_Context> __args_[N]; +}; + +} // namespace __format + +template +struct _LIBCPP_TEMPLATE_VIS __format_arg_store { + _LIBCPP_HIDE_FROM_ABI + __format_arg_store(_Args&... __args) noexcept { + if constexpr (sizeof...(_Args) != 0) { + if constexpr (__format::__use_packed_format_arg_store(sizeof...(_Args))) + __format::__create_packed_storage(__storage.__types_, __storage.__values_, __args...); + else + __format::__store_basic_format_arg<_Context>(__storage.__args_, __args...); + } + } + + using _Storage = conditional_t<__format::__use_packed_format_arg_store(sizeof...(_Args)), + __format::__packed_format_arg_store<_Context, sizeof...(_Args)>, + __format::__unpacked_format_arg_store<_Context, sizeof...(_Args)>>; + + _Storage __storage; +}; + +#endif //_LIBCPP_STD_VER > 17 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___FORMAT_FORMAT_ARG_STORE_H diff --git a/app/src/main/cpp/libcxx/include/__format/format_args.h b/app/src/main/cpp/libcxx/include/__format/format_args.h new file mode 100644 index 0000000..8b8fbde --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__format/format_args.h @@ -0,0 +1,80 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___FORMAT_FORMAT_ARGS_H +#define _LIBCPP___FORMAT_FORMAT_ARGS_H + +#include <__availability> +#include <__config> +#include <__format/format_arg.h> +#include <__format/format_arg_store.h> +#include <__format/format_fwd.h> +#include +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 17 + +template +class _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT basic_format_args { +public: + _LIBCPP_HIDE_FROM_ABI basic_format_args() noexcept = default; + + template + _LIBCPP_HIDE_FROM_ABI basic_format_args(const __format_arg_store<_Context, _Args...>& __store) noexcept + : __size_(sizeof...(_Args)) { + if constexpr (sizeof...(_Args) != 0) { + if constexpr (__format::__use_packed_format_arg_store(sizeof...(_Args))) { + __values_ = __store.__storage.__values_; + __types_ = __store.__storage.__types_; + } else + __args_ = __store.__storage.__args_; + } + } + + _LIBCPP_HIDE_FROM_ABI + basic_format_arg<_Context> get(size_t __id) const noexcept { + if (__id >= __size_) + return basic_format_arg<_Context>{}; + + if (__format::__use_packed_format_arg_store(__size_)) + return basic_format_arg<_Context>{__format::__get_packed_type(__types_, __id), __values_[__id]}; + + return __args_[__id]; + } + + _LIBCPP_HIDE_FROM_ABI size_t __size() const noexcept { return __size_; } + +private: + size_t __size_{0}; + // [format.args]/5 + // [Note 1: Implementations are encouraged to optimize the representation of + // basic_format_args for small number of formatting arguments by storing + // indices of type alternatives separately from values and packing the + // former. - end note] + union { + struct { + const __basic_format_arg_value<_Context>* __values_; + uint64_t __types_; + }; + const basic_format_arg<_Context>* __args_; + }; +}; +_LIBCPP_CTAD_SUPPORTED_FOR_TYPE(basic_format_args); + +#endif //_LIBCPP_STD_VER > 17 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___FORMAT_FORMAT_ARGS_H diff --git a/app/src/main/cpp/libcxx/include/__format/format_context.h b/app/src/main/cpp/libcxx/include/__format/format_context.h new file mode 100644 index 0000000..85e00eb --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__format/format_context.h @@ -0,0 +1,223 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___FORMAT_FORMAT_CONTEXT_H +#define _LIBCPP___FORMAT_FORMAT_CONTEXT_H + +#include <__availability> +#include <__concepts/same_as.h> +#include <__config> +#include <__format/buffer.h> +#include <__format/format_arg.h> +#include <__format/format_arg_store.h> +#include <__format/format_args.h> +#include <__format/format_error.h> +#include <__format/format_fwd.h> +#include <__iterator/back_insert_iterator.h> +#include <__iterator/concepts.h> +#include <__memory/addressof.h> +#include <__utility/move.h> +#include <__variant/monostate.h> +#include + +#ifndef _LIBCPP_HAS_NO_LOCALIZATION +#include +#include +#endif + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 17 + +template +requires output_iterator<_OutIt, const _CharT&> +class _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT basic_format_context; + +#ifndef _LIBCPP_HAS_NO_LOCALIZATION +/** + * Helper to create a basic_format_context. + * + * This is needed since the constructor is private. + */ +template +_LIBCPP_HIDE_FROM_ABI basic_format_context<_OutIt, _CharT> +__format_context_create( + _OutIt __out_it, + basic_format_args> __args, + optional<_VSTD::locale>&& __loc = nullopt) { + return _VSTD::basic_format_context(_VSTD::move(__out_it), __args, _VSTD::move(__loc)); +} +#else +template +_LIBCPP_HIDE_FROM_ABI basic_format_context<_OutIt, _CharT> +__format_context_create( + _OutIt __out_it, + basic_format_args> __args) { + return _VSTD::basic_format_context(_VSTD::move(__out_it), __args); +} +#endif + +using format_context = + basic_format_context>, + char>; +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +using wformat_context = basic_format_context< + back_insert_iterator<__format::__output_buffer>, wchar_t>; +#endif + +template +requires output_iterator<_OutIt, const _CharT&> +class + // clang-format off + _LIBCPP_TEMPLATE_VIS + _LIBCPP_AVAILABILITY_FORMAT + _LIBCPP_PREFERRED_NAME(format_context) + _LIBCPP_IF_WIDE_CHARACTERS(_LIBCPP_PREFERRED_NAME(wformat_context)) + // clang-format on + basic_format_context { +public: + using iterator = _OutIt; + using char_type = _CharT; + template + using formatter_type = formatter<_Tp, _CharT>; + + _LIBCPP_HIDE_FROM_ABI basic_format_arg + arg(size_t __id) const noexcept { + return __args_.get(__id); + } +#ifndef _LIBCPP_HAS_NO_LOCALIZATION + _LIBCPP_HIDE_FROM_ABI _VSTD::locale locale() { + if (!__loc_) + __loc_ = _VSTD::locale{}; + return *__loc_; + } +#endif + _LIBCPP_HIDE_FROM_ABI iterator out() { return std::move(__out_it_); } + _LIBCPP_HIDE_FROM_ABI void advance_to(iterator __it) { __out_it_ = std::move(__it); } + +private: + iterator __out_it_; + basic_format_args __args_; +#ifndef _LIBCPP_HAS_NO_LOCALIZATION + + // The Standard doesn't specify how the locale is stored. + // [format.context]/6 + // std::locale locale(); + // Returns: The locale passed to the formatting function if the latter + // takes one, and std::locale() otherwise. + // This is done by storing the locale of the constructor in this optional. If + // locale() is called and the optional has no value the value will be created. + // This allows the implementation to lazily create the locale. + // TODO FMT Validate whether lazy creation is the best solution. + optional<_VSTD::locale> __loc_; + + template + friend _LIBCPP_HIDE_FROM_ABI basic_format_context<__OutIt, __CharT> + __format_context_create(__OutIt, basic_format_args>, + optional<_VSTD::locale>&&); + + // Note: the Standard doesn't specify the required constructors. + _LIBCPP_HIDE_FROM_ABI + explicit basic_format_context(_OutIt __out_it, + basic_format_args __args, + optional<_VSTD::locale>&& __loc) + : __out_it_(_VSTD::move(__out_it)), __args_(__args), + __loc_(_VSTD::move(__loc)) {} +#else + template + friend _LIBCPP_HIDE_FROM_ABI basic_format_context<__OutIt, __CharT> + __format_context_create(__OutIt, basic_format_args>); + + _LIBCPP_HIDE_FROM_ABI + explicit basic_format_context(_OutIt __out_it, + basic_format_args __args) + : __out_it_(_VSTD::move(__out_it)), __args_(__args) {} +#endif +}; + +// A specialization for __retarget_buffer +// +// See __retarget_buffer for the motivation for this specialization. +// +// This context holds a reference to the instance of the basic_format_context +// that is retargeted. It converts a formatting argument when it is requested +// during formatting. It is expected that the usage of the arguments is rare so +// the lookups are not expected to be used often. An alternative would be to +// convert all elements during construction. +// +// The elements of the retargets context are only used when an underlying +// formatter uses a locale specific formatting or an formatting argument is +// part for the format spec. For example +// format("{:256:{}}", input, 8); +// Here the width of an element in input is determined dynamically. +// Note when the top-level element has no width the retargeting is not needed. +template +class _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT + basic_format_context::__iterator, _CharT> { +public: + using iterator = typename __format::__retarget_buffer<_CharT>::__iterator; + using char_type = _CharT; + template + using formatter_type = formatter<_Tp, _CharT>; + + template + _LIBCPP_HIDE_FROM_ABI explicit basic_format_context(iterator __out_it, _Context& __ctx) + : __out_it_(std::move(__out_it)), +# ifndef _LIBCPP_HAS_NO_LOCALIZATION + __loc_([](void* __c) { return static_cast<_Context*>(__c)->locale(); }), +# endif + __ctx_(std::addressof(__ctx)), + __arg_([](void* __c, size_t __id) { + return std::visit_format_arg( + [&](auto __arg) -> basic_format_arg { + if constexpr (same_as) + return {}; + else if constexpr (same_as::handle>) + // At the moment it's not possible for formatting to use a re-targeted handle. + // TODO FMT add this when support is needed. + std::__throw_format_error("Re-targeting handle not supported"); + else + return basic_format_arg{ + __format::__determine_arg_t(), + __basic_format_arg_value(__arg)}; + }, + static_cast<_Context*>(__c)->arg(__id)); + }) { + } + + _LIBCPP_HIDE_FROM_ABI basic_format_arg arg(size_t __id) const noexcept { + return __arg_(__ctx_, __id); + } +# ifndef _LIBCPP_HAS_NO_LOCALIZATION + _LIBCPP_HIDE_FROM_ABI _VSTD::locale locale() { return __loc_(__ctx_); } +# endif + _LIBCPP_HIDE_FROM_ABI iterator out() { return std::move(__out_it_); } + _LIBCPP_HIDE_FROM_ABI void advance_to(iterator __it) { __out_it_ = std::move(__it); } + +private: + iterator __out_it_; + +# ifndef _LIBCPP_HAS_NO_LOCALIZATION + std::locale (*__loc_)(void* __ctx); +# endif + + void* __ctx_; + basic_format_arg (*__arg_)(void* __ctx, size_t __id); +}; + +_LIBCPP_CTAD_SUPPORTED_FOR_TYPE(basic_format_context); +#endif //_LIBCPP_STD_VER > 17 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___FORMAT_FORMAT_CONTEXT_H diff --git a/app/src/main/cpp/libcxx/include/__format/format_error.h b/app/src/main/cpp/libcxx/include/__format/format_error.h new file mode 100644 index 0000000..002d1a4 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__format/format_error.h @@ -0,0 +1,55 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___FORMAT_FORMAT_ERROR_H +#define _LIBCPP___FORMAT_FORMAT_ERROR_H + +#include <__config> +#include +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 17 + +class _LIBCPP_EXCEPTION_ABI format_error : public runtime_error { +public: + _LIBCPP_HIDE_FROM_ABI explicit format_error(const string& __s) + : runtime_error(__s) {} + _LIBCPP_HIDE_FROM_ABI explicit format_error(const char* __s) + : runtime_error(__s) {} + // TODO FMT Remove when format is no longer experimental. + // Avoids linker errors when building the Clang-cl Windows DLL which doesn't + // support the experimental library. +# ifndef _LIBCPP_INLINE_FORMAT_ERROR_DTOR + ~format_error() noexcept override; +# else + ~format_error() noexcept override {} +# endif +}; + +_LIBCPP_NORETURN inline _LIBCPP_HIDE_FROM_ABI void +__throw_format_error(const char* __s) { +#ifndef _LIBCPP_NO_EXCEPTIONS + throw format_error(__s); +#else + (void)__s; + _VSTD::abort(); +#endif +} + +#endif //_LIBCPP_STD_VER > 17 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___FORMAT_FORMAT_ERROR_H diff --git a/app/src/main/cpp/libcxx/include/__format/format_functions.h b/app/src/main/cpp/libcxx/include/__format/format_functions.h new file mode 100644 index 0000000..185148c --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__format/format_functions.h @@ -0,0 +1,661 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___FORMAT_FORMAT_FUNCTIONS +#define _LIBCPP___FORMAT_FORMAT_FUNCTIONS + +// TODO FMT This is added to fix Apple back-deployment. +#include +#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_FORMAT) + +#include <__algorithm/clamp.h> +#include <__availability> +#include <__concepts/convertible_to.h> +#include <__concepts/same_as.h> +#include <__config> +#include <__debug> +#include <__format/buffer.h> +#include <__format/format_arg.h> +#include <__format/format_arg_store.h> +#include <__format/format_args.h> +#include <__format/format_context.h> +#include <__format/format_error.h> +#include <__format/format_parse_context.h> +#include <__format/format_string.h> +#include <__format/format_to_n_result.h> +#include <__format/formatter.h> +#include <__format/formatter_bool.h> +#include <__format/formatter_char.h> +#include <__format/formatter_floating_point.h> +#include <__format/formatter_integer.h> +#include <__format/formatter_pointer.h> +#include <__format/formatter_string.h> +#include <__format/parser_std_format_spec.h> +#include <__iterator/back_insert_iterator.h> +#include <__iterator/incrementable_traits.h> +#include <__variant/monostate.h> +#include +#include +#include + +#ifndef _LIBCPP_HAS_NO_LOCALIZATION +#include +#endif + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 17 + +// TODO FMT Evaluate which templates should be external templates. This +// improves the efficiency of the header. However since the header is still +// under heavy development and not all classes are stable it makes no sense +// to do this optimization now. + +using format_args = basic_format_args; +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +using wformat_args = basic_format_args; +#endif + +template +_LIBCPP_HIDE_FROM_ABI __format_arg_store<_Context, _Args...> make_format_args(_Args&&... __args) { + return _VSTD::__format_arg_store<_Context, _Args...>(__args...); +} + +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +template +_LIBCPP_HIDE_FROM_ABI __format_arg_store make_wformat_args(_Args&&... __args) { + return _VSTD::__format_arg_store(__args...); +} +#endif + +namespace __format { + +/// Helper class parse and handle argument. +/// +/// When parsing a handle which is not enabled the code is ill-formed. +/// This helper uses the parser of the appropriate formatter for the stored type. +template +class _LIBCPP_TEMPLATE_VIS __compile_time_handle { +public: + _LIBCPP_HIDE_FROM_ABI + constexpr void __parse(basic_format_parse_context<_CharT>& __parse_ctx) const { __parse_(__parse_ctx); } + + template + _LIBCPP_HIDE_FROM_ABI constexpr void __enable() { + __parse_ = [](basic_format_parse_context<_CharT>& __parse_ctx) { + formatter<_Tp, _CharT> __f; + __parse_ctx.advance_to(__f.parse(__parse_ctx)); + }; + } + + // Before calling __parse the proper handler needs to be set with __enable. + // The default handler isn't a core constant expression. + _LIBCPP_HIDE_FROM_ABI constexpr __compile_time_handle() + : __parse_([](basic_format_parse_context<_CharT>&) { std::__throw_format_error("Not a handle"); }) {} + +private: + void (*__parse_)(basic_format_parse_context<_CharT>&); +}; + +// Dummy format_context only providing the parts used during constant +// validation of the basic_format_string. +template +struct _LIBCPP_TEMPLATE_VIS __compile_time_basic_format_context { +public: + using char_type = _CharT; + + _LIBCPP_HIDE_FROM_ABI constexpr explicit __compile_time_basic_format_context( + const __arg_t* __args, const __compile_time_handle<_CharT>* __handles, size_t __size) + : __args_(__args), __handles_(__handles), __size_(__size) {} + + // During the compile-time validation nothing needs to be written. + // Therefore all operations of this iterator are a NOP. + struct iterator { + _LIBCPP_HIDE_FROM_ABI constexpr iterator& operator=(_CharT) { return *this; } + _LIBCPP_HIDE_FROM_ABI constexpr iterator& operator*() { return *this; } + _LIBCPP_HIDE_FROM_ABI constexpr iterator operator++(int) { return *this; } + }; + + _LIBCPP_HIDE_FROM_ABI constexpr __arg_t arg(size_t __id) const { + if (__id >= __size_) + std::__throw_format_error("Argument index out of bounds"); + return __args_[__id]; + } + + _LIBCPP_HIDE_FROM_ABI constexpr const __compile_time_handle<_CharT>& __handle(size_t __id) const { + if (__id >= __size_) + std::__throw_format_error("Argument index out of bounds"); + return __handles_[__id]; + } + + _LIBCPP_HIDE_FROM_ABI constexpr iterator out() { return {}; } + _LIBCPP_HIDE_FROM_ABI constexpr void advance_to(iterator) {} + +private: + const __arg_t* __args_; + const __compile_time_handle<_CharT>* __handles_; + size_t __size_; +}; + +_LIBCPP_HIDE_FROM_ABI +constexpr void __compile_time_validate_integral(__arg_t __type) { + switch (__type) { + case __arg_t::__int: + case __arg_t::__long_long: + case __arg_t::__i128: + case __arg_t::__unsigned: + case __arg_t::__unsigned_long_long: + case __arg_t::__u128: + return; + + default: + std::__throw_format_error("Argument isn't an integral type"); + } +} + +// _HasPrecision does the formatter have a precision? +template +_LIBCPP_HIDE_FROM_ABI constexpr void +__compile_time_validate_argument(basic_format_parse_context<_CharT>& __parse_ctx, + __compile_time_basic_format_context<_CharT>& __ctx) { + formatter<_Tp, _CharT> __formatter; + __parse_ctx.advance_to(__formatter.parse(__parse_ctx)); + // [format.string.std]/7 + // ... If the corresponding formatting argument is not of integral type, or + // its value is negative for precision or non-positive for width, an + // exception of type format_error is thrown. + // + // Validate whether the arguments are integrals. + if (__formatter.__parser_.__width_as_arg_) + __format::__compile_time_validate_integral(__ctx.arg(__formatter.__parser_.__width_)); + + if constexpr (_HasPrecision) + if (__formatter.__parser_.__precision_as_arg_) + __format::__compile_time_validate_integral(__ctx.arg(__formatter.__parser_.__precision_)); +} + +// This function is not user facing, so it can directly use the non-standard types of the "variant". +template +_LIBCPP_HIDE_FROM_ABI constexpr void __compile_time_visit_format_arg(basic_format_parse_context<_CharT>& __parse_ctx, + __compile_time_basic_format_context<_CharT>& __ctx, + __arg_t __type) { + switch (__type) { + case __arg_t::__none: + std::__throw_format_error("Invalid argument"); + case __arg_t::__boolean: + return __format::__compile_time_validate_argument<_CharT, bool>(__parse_ctx, __ctx); + case __arg_t::__char_type: + return __format::__compile_time_validate_argument<_CharT, _CharT>(__parse_ctx, __ctx); + case __arg_t::__int: + return __format::__compile_time_validate_argument<_CharT, int>(__parse_ctx, __ctx); + case __arg_t::__long_long: + return __format::__compile_time_validate_argument<_CharT, long long>(__parse_ctx, __ctx); + case __arg_t::__i128: +# ifndef _LIBCPP_HAS_NO_INT128 + return __format::__compile_time_validate_argument<_CharT, __int128_t>(__parse_ctx, __ctx); +# else + std::__throw_format_error("Invalid argument"); +# endif + return; + case __arg_t::__unsigned: + return __format::__compile_time_validate_argument<_CharT, unsigned>(__parse_ctx, __ctx); + case __arg_t::__unsigned_long_long: + return __format::__compile_time_validate_argument<_CharT, unsigned long long>(__parse_ctx, __ctx); + case __arg_t::__u128: +# ifndef _LIBCPP_HAS_NO_INT128 + return __format::__compile_time_validate_argument<_CharT, __uint128_t>(__parse_ctx, __ctx); +# else + std::__throw_format_error("Invalid argument"); +# endif + return; + case __arg_t::__float: + return __format::__compile_time_validate_argument<_CharT, float, true>(__parse_ctx, __ctx); + case __arg_t::__double: + return __format::__compile_time_validate_argument<_CharT, double, true>(__parse_ctx, __ctx); + case __arg_t::__long_double: + return __format::__compile_time_validate_argument<_CharT, long double, true>(__parse_ctx, __ctx); + case __arg_t::__const_char_type_ptr: + return __format::__compile_time_validate_argument<_CharT, const _CharT*, true>(__parse_ctx, __ctx); + case __arg_t::__string_view: + return __format::__compile_time_validate_argument<_CharT, basic_string_view<_CharT>, true>(__parse_ctx, __ctx); + case __arg_t::__ptr: + return __format::__compile_time_validate_argument<_CharT, const void*>(__parse_ctx, __ctx); + case __arg_t::__handle: + std::__throw_format_error("Handle should use __compile_time_validate_handle_argument"); + } + std::__throw_format_error("Invalid argument"); +} + +template +_LIBCPP_HIDE_FROM_ABI constexpr const _CharT* +__handle_replacement_field(const _CharT* __begin, const _CharT* __end, + _ParseCtx& __parse_ctx, _Ctx& __ctx) { + __format::__parse_number_result __r = __format::__parse_arg_id(__begin, __end, __parse_ctx); + + bool __parse = *__r.__ptr == _CharT(':'); + switch (*__r.__ptr) { + case _CharT(':'): + // The arg-id has a format-specifier, advance the input to the format-spec. + __parse_ctx.advance_to(__r.__ptr + 1); + break; + case _CharT('}'): + // The arg-id has no format-specifier. + __parse_ctx.advance_to(__r.__ptr); + break; + default: + std::__throw_format_error("The replacement field arg-id should terminate at a ':' or '}'"); + } + + if constexpr (same_as<_Ctx, __compile_time_basic_format_context<_CharT>>) { + __arg_t __type = __ctx.arg(__r.__value); + if (__type == __arg_t::__handle) + __ctx.__handle(__r.__value).__parse(__parse_ctx); + else + __format::__compile_time_visit_format_arg(__parse_ctx, __ctx, __type); + } else + _VSTD::__visit_format_arg( + [&](auto __arg) { + if constexpr (same_as) + std::__throw_format_error("Argument index out of bounds"); + else if constexpr (same_as::handle>) + __arg.format(__parse_ctx, __ctx); + else { + formatter __formatter; + if (__parse) + __parse_ctx.advance_to(__formatter.parse(__parse_ctx)); + __ctx.advance_to(__formatter.format(__arg, __ctx)); + } + }, + __ctx.arg(__r.__value)); + + __begin = __parse_ctx.begin(); + if (__begin == __end || *__begin != _CharT('}')) + std::__throw_format_error("The replacement field misses a terminating '}'"); + + return ++__begin; +} + +template +_LIBCPP_HIDE_FROM_ABI constexpr typename _Ctx::iterator +__vformat_to(_ParseCtx&& __parse_ctx, _Ctx&& __ctx) { + using _CharT = typename _ParseCtx::char_type; + static_assert(same_as); + + const _CharT* __begin = __parse_ctx.begin(); + const _CharT* __end = __parse_ctx.end(); + typename _Ctx::iterator __out_it = __ctx.out(); + while (__begin != __end) { + switch (*__begin) { + case _CharT('{'): + ++__begin; + if (__begin == __end) + std::__throw_format_error("The format string terminates at a '{'"); + + if (*__begin != _CharT('{')) [[likely]] { + __ctx.advance_to(_VSTD::move(__out_it)); + __begin = + __format::__handle_replacement_field(__begin, __end, __parse_ctx, __ctx); + __out_it = __ctx.out(); + + // The output is written and __begin points to the next character. So + // start the next iteration. + continue; + } + // The string is an escape character. + break; + + case _CharT('}'): + ++__begin; + if (__begin == __end || *__begin != _CharT('}')) + std::__throw_format_error("The format string contains an invalid escape sequence"); + + break; + } + + // Copy the character to the output verbatim. + *__out_it++ = *__begin++; + } + return __out_it; +} + +} // namespace __format + +template +struct _LIBCPP_TEMPLATE_VIS basic_format_string { + template + requires convertible_to> + consteval basic_format_string(const _Tp& __str) : __str_{__str} { + __format::__vformat_to(basic_format_parse_context<_CharT>{__str_, sizeof...(_Args)}, + _Context{__types_.data(), __handles_.data(), sizeof...(_Args)}); + } + + _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT constexpr basic_string_view<_CharT> get() const noexcept { + return __str_; + } + +private: + basic_string_view<_CharT> __str_; + + using _Context = __format::__compile_time_basic_format_context<_CharT>; + + static constexpr array<__format::__arg_t, sizeof...(_Args)> __types_{ + __format::__determine_arg_t<_Context, remove_cvref_t<_Args>>()...}; + + // TODO FMT remove this work-around when the AIX ICE has been resolved. +# if defined(_AIX) && defined(_LIBCPP_CLANG_VER) && _LIBCPP_CLANG_VER < 1400 + template + static constexpr __format::__compile_time_handle<_CharT> __get_handle() { + __format::__compile_time_handle<_CharT> __handle; + if (__format::__determine_arg_t<_Context, _Tp>() == __format::__arg_t::__handle) + __handle.template __enable<_Tp>(); + + return __handle; + } + + static constexpr array<__format::__compile_time_handle<_CharT>, sizeof...(_Args)> __handles_{ + __get_handle<_Args>()...}; +# else + static constexpr array<__format::__compile_time_handle<_CharT>, sizeof...(_Args)> __handles_{[] { + using _Tp = remove_cvref_t<_Args>; + __format::__compile_time_handle<_CharT> __handle; + if (__format::__determine_arg_t<_Context, _Tp>() == __format::__arg_t::__handle) + __handle.template __enable<_Tp>(); + + return __handle; + }()...}; +# endif +}; + +template +using format_string = basic_format_string...>; + +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +template +using wformat_string = basic_format_string...>; +#endif + +template +requires(output_iterator<_OutIt, const _CharT&>) _LIBCPP_HIDE_FROM_ABI _OutIt + __vformat_to( + _OutIt __out_it, basic_string_view<_CharT> __fmt, + basic_format_args> __args) { + if constexpr (same_as<_OutIt, _FormatOutIt>) + return _VSTD::__format::__vformat_to(basic_format_parse_context{__fmt, __args.__size()}, + _VSTD::__format_context_create(_VSTD::move(__out_it), __args)); + else { + __format::__format_buffer<_OutIt, _CharT> __buffer{_VSTD::move(__out_it)}; + _VSTD::__format::__vformat_to(basic_format_parse_context{__fmt, __args.__size()}, + _VSTD::__format_context_create(__buffer.__make_output_iterator(), __args)); + return _VSTD::move(__buffer).__out_it(); + } +} + +// The function is _LIBCPP_ALWAYS_INLINE since the compiler is bad at inlining +// https://reviews.llvm.org/D110499#inline-1180704 +// TODO FMT Evaluate whether we want to file a Clang bug report regarding this. +template _OutIt> +_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt +vformat_to(_OutIt __out_it, string_view __fmt, format_args __args) { + return _VSTD::__vformat_to(_VSTD::move(__out_it), __fmt, __args); +} + +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +template _OutIt> +_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt +vformat_to(_OutIt __out_it, wstring_view __fmt, wformat_args __args) { + return _VSTD::__vformat_to(_VSTD::move(__out_it), __fmt, __args); +} +#endif + +template _OutIt, class... _Args> +_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt +format_to(_OutIt __out_it, format_string<_Args...> __fmt, _Args&&... __args) { + return _VSTD::vformat_to(_VSTD::move(__out_it), __fmt.get(), + _VSTD::make_format_args(__args...)); +} + +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +template _OutIt, class... _Args> +_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt +format_to(_OutIt __out_it, wformat_string<_Args...> __fmt, _Args&&... __args) { + return _VSTD::vformat_to(_VSTD::move(__out_it), __fmt.get(), + _VSTD::make_wformat_args(__args...)); +} +#endif + +_LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT string +vformat(string_view __fmt, format_args __args) { + string __res; + _VSTD::vformat_to(_VSTD::back_inserter(__res), __fmt, __args); + return __res; +} + +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +_LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT wstring +vformat(wstring_view __fmt, wformat_args __args) { + wstring __res; + _VSTD::vformat_to(_VSTD::back_inserter(__res), __fmt, __args); + return __res; +} +#endif + +template +_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT string format(format_string<_Args...> __fmt, + _Args&&... __args) { + return _VSTD::vformat(__fmt.get(), _VSTD::make_format_args(__args...)); +} + +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +template +_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT wstring +format(wformat_string<_Args...> __fmt, _Args&&... __args) { + return _VSTD::vformat(__fmt.get(), _VSTD::make_wformat_args(__args...)); +} +#endif + +template +_LIBCPP_HIDE_FROM_ABI format_to_n_result<_OutIt> __vformat_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, + basic_string_view<_CharT> __fmt, + basic_format_args<_Context> __args) { + __format::__format_to_n_buffer<_OutIt, _CharT> __buffer{_VSTD::move(__out_it), __n}; + _VSTD::__format::__vformat_to(basic_format_parse_context{__fmt, __args.__size()}, + _VSTD::__format_context_create(__buffer.__make_output_iterator(), __args)); + return _VSTD::move(__buffer).__result(); +} + +template _OutIt, class... _Args> +_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT format_to_n_result<_OutIt> +format_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, format_string<_Args...> __fmt, _Args&&... __args) { + return _VSTD::__vformat_to_n(_VSTD::move(__out_it), __n, __fmt.get(), _VSTD::make_format_args(__args...)); +} + +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +template _OutIt, class... _Args> +_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT format_to_n_result<_OutIt> +format_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, wformat_string<_Args...> __fmt, + _Args&&... __args) { + return _VSTD::__vformat_to_n(_VSTD::move(__out_it), __n, __fmt.get(), _VSTD::make_wformat_args(__args...)); +} +#endif + +template +_LIBCPP_HIDE_FROM_ABI size_t __vformatted_size(basic_string_view<_CharT> __fmt, auto __args) { + __format::__formatted_size_buffer<_CharT> __buffer; + _VSTD::__format::__vformat_to(basic_format_parse_context{__fmt, __args.__size()}, + _VSTD::__format_context_create(__buffer.__make_output_iterator(), __args)); + return _VSTD::move(__buffer).__result(); +} + +template +_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT size_t +formatted_size(format_string<_Args...> __fmt, _Args&&... __args) { + return _VSTD::__vformatted_size(__fmt.get(), basic_format_args{_VSTD::make_format_args(__args...)}); +} + +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +template +_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT size_t +formatted_size(wformat_string<_Args...> __fmt, _Args&&... __args) { + return _VSTD::__vformatted_size(__fmt.get(), basic_format_args{_VSTD::make_wformat_args(__args...)}); +} +#endif + +#ifndef _LIBCPP_HAS_NO_LOCALIZATION + +template +requires(output_iterator<_OutIt, const _CharT&>) _LIBCPP_HIDE_FROM_ABI _OutIt + __vformat_to( + _OutIt __out_it, locale __loc, basic_string_view<_CharT> __fmt, + basic_format_args> __args) { + if constexpr (same_as<_OutIt, _FormatOutIt>) + return _VSTD::__format::__vformat_to( + basic_format_parse_context{__fmt, __args.__size()}, + _VSTD::__format_context_create(_VSTD::move(__out_it), __args, _VSTD::move(__loc))); + else { + __format::__format_buffer<_OutIt, _CharT> __buffer{_VSTD::move(__out_it)}; + _VSTD::__format::__vformat_to( + basic_format_parse_context{__fmt, __args.__size()}, + _VSTD::__format_context_create(__buffer.__make_output_iterator(), __args, _VSTD::move(__loc))); + return _VSTD::move(__buffer).__out_it(); + } +} + +template _OutIt> +_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt vformat_to( + _OutIt __out_it, locale __loc, string_view __fmt, format_args __args) { + return _VSTD::__vformat_to(_VSTD::move(__out_it), _VSTD::move(__loc), __fmt, + __args); +} + +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +template _OutIt> +_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt vformat_to( + _OutIt __out_it, locale __loc, wstring_view __fmt, wformat_args __args) { + return _VSTD::__vformat_to(_VSTD::move(__out_it), _VSTD::move(__loc), __fmt, + __args); +} +#endif + +template _OutIt, class... _Args> +_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt +format_to(_OutIt __out_it, locale __loc, format_string<_Args...> __fmt, _Args&&... __args) { + return _VSTD::vformat_to(_VSTD::move(__out_it), _VSTD::move(__loc), __fmt.get(), + _VSTD::make_format_args(__args...)); +} + +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +template _OutIt, class... _Args> +_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt +format_to(_OutIt __out_it, locale __loc, wformat_string<_Args...> __fmt, _Args&&... __args) { + return _VSTD::vformat_to(_VSTD::move(__out_it), _VSTD::move(__loc), __fmt.get(), + _VSTD::make_wformat_args(__args...)); +} +#endif + +_LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT string +vformat(locale __loc, string_view __fmt, format_args __args) { + string __res; + _VSTD::vformat_to(_VSTD::back_inserter(__res), _VSTD::move(__loc), __fmt, + __args); + return __res; +} + +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +_LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT wstring +vformat(locale __loc, wstring_view __fmt, wformat_args __args) { + wstring __res; + _VSTD::vformat_to(_VSTD::back_inserter(__res), _VSTD::move(__loc), __fmt, + __args); + return __res; +} +#endif + +template +_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT string format(locale __loc, + format_string<_Args...> __fmt, + _Args&&... __args) { + return _VSTD::vformat(_VSTD::move(__loc), __fmt.get(), + _VSTD::make_format_args(__args...)); +} + +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +template +_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT wstring +format(locale __loc, wformat_string<_Args...> __fmt, _Args&&... __args) { + return _VSTD::vformat(_VSTD::move(__loc), __fmt.get(), + _VSTD::make_wformat_args(__args...)); +} +#endif + +template +_LIBCPP_HIDE_FROM_ABI format_to_n_result<_OutIt> __vformat_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, + locale __loc, basic_string_view<_CharT> __fmt, + basic_format_args<_Context> __args) { + __format::__format_to_n_buffer<_OutIt, _CharT> __buffer{_VSTD::move(__out_it), __n}; + _VSTD::__format::__vformat_to( + basic_format_parse_context{__fmt, __args.__size()}, + _VSTD::__format_context_create(__buffer.__make_output_iterator(), __args, _VSTD::move(__loc))); + return _VSTD::move(__buffer).__result(); +} + +template _OutIt, class... _Args> +_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT format_to_n_result<_OutIt> +format_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, locale __loc, format_string<_Args...> __fmt, + _Args&&... __args) { + return _VSTD::__vformat_to_n(_VSTD::move(__out_it), __n, _VSTD::move(__loc), __fmt.get(), + _VSTD::make_format_args(__args...)); +} + +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +template _OutIt, class... _Args> +_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT format_to_n_result<_OutIt> +format_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, locale __loc, wformat_string<_Args...> __fmt, + _Args&&... __args) { + return _VSTD::__vformat_to_n(_VSTD::move(__out_it), __n, _VSTD::move(__loc), __fmt.get(), + _VSTD::make_wformat_args(__args...)); +} +#endif + +template +_LIBCPP_HIDE_FROM_ABI size_t __vformatted_size(locale __loc, basic_string_view<_CharT> __fmt, auto __args) { + __format::__formatted_size_buffer<_CharT> __buffer; + _VSTD::__format::__vformat_to( + basic_format_parse_context{__fmt, __args.__size()}, + _VSTD::__format_context_create(__buffer.__make_output_iterator(), __args, _VSTD::move(__loc))); + return _VSTD::move(__buffer).__result(); +} + +template +_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT size_t +formatted_size(locale __loc, format_string<_Args...> __fmt, _Args&&... __args) { + return _VSTD::__vformatted_size(_VSTD::move(__loc), __fmt.get(), basic_format_args{_VSTD::make_format_args(__args...)}); +} + +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +template +_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT size_t +formatted_size(locale __loc, wformat_string<_Args...> __fmt, _Args&&... __args) { + return _VSTD::__vformatted_size(_VSTD::move(__loc), __fmt.get(), basic_format_args{_VSTD::make_wformat_args(__args...)}); +} +#endif + +#endif // _LIBCPP_HAS_NO_LOCALIZATION + + +#endif //_LIBCPP_STD_VER > 17 + +_LIBCPP_END_NAMESPACE_STD + +#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_FORMAT) + +#endif // _LIBCPP___FORMAT_FORMAT_FUNCTIONS diff --git a/app/src/main/cpp/libcxx/include/__format/format_fwd.h b/app/src/main/cpp/libcxx/include/__format/format_fwd.h new file mode 100644 index 0000000..f7c72e2 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__format/format_fwd.h @@ -0,0 +1,39 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___FORMAT_FORMAT_FWD_H +#define _LIBCPP___FORMAT_FORMAT_FWD_H + +#include <__availability> +#include <__config> +#include <__iterator/concepts.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 17 + +template +class _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT basic_format_arg; + +template + requires output_iterator<_OutIt, const _CharT&> +class _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT basic_format_context; + +template +struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter; + +#endif //_LIBCPP_STD_VER > 17 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___FORMAT_FORMAT_FWD_H diff --git a/app/src/main/cpp/libcxx/include/__format/format_parse_context.h b/app/src/main/cpp/libcxx/include/__format/format_parse_context.h new file mode 100644 index 0000000..30e3a7d --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__format/format_parse_context.h @@ -0,0 +1,100 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___FORMAT_FORMAT_PARSE_CONTEXT_H +#define _LIBCPP___FORMAT_FORMAT_PARSE_CONTEXT_H + +#include <__config> +#include <__format/format_error.h> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 17 + +template +class _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT basic_format_parse_context { +public: + using char_type = _CharT; + using const_iterator = typename basic_string_view<_CharT>::const_iterator; + using iterator = const_iterator; + + _LIBCPP_HIDE_FROM_ABI + constexpr explicit basic_format_parse_context(basic_string_view<_CharT> __fmt, + size_t __num_args = 0) noexcept + : __begin_(__fmt.begin()), + __end_(__fmt.end()), + __indexing_(__unknown), + __next_arg_id_(0), + __num_args_(__num_args) {} + + basic_format_parse_context(const basic_format_parse_context&) = delete; + basic_format_parse_context& + operator=(const basic_format_parse_context&) = delete; + + _LIBCPP_HIDE_FROM_ABI constexpr const_iterator begin() const noexcept { + return __begin_; + } + _LIBCPP_HIDE_FROM_ABI constexpr const_iterator end() const noexcept { + return __end_; + } + _LIBCPP_HIDE_FROM_ABI constexpr void advance_to(const_iterator __it) { + __begin_ = __it; + } + + _LIBCPP_HIDE_FROM_ABI constexpr size_t next_arg_id() { + if (__indexing_ == __manual) + std::__throw_format_error("Using automatic argument numbering in manual argument numbering mode"); + + if (__indexing_ == __unknown) + __indexing_ = __automatic; + return __next_arg_id_++; + } + _LIBCPP_HIDE_FROM_ABI constexpr void check_arg_id(size_t __id) { + if (__indexing_ == __automatic) + std::__throw_format_error("Using manual argument numbering in automatic argument numbering mode"); + + if (__indexing_ == __unknown) + __indexing_ = __manual; + + // Throws an exception to make the expression a non core constant + // expression as required by: + // [format.parse.ctx]/11 + // Remarks: Call expressions where id >= num_args_ are not core constant + // expressions ([expr.const]). + // Note: the Throws clause [format.parse.ctx]/10 doesn't specify the + // behavior when id >= num_args_. + if (is_constant_evaluated() && __id >= __num_args_) + std::__throw_format_error("Argument index outside the valid range"); + } + +private: + iterator __begin_; + iterator __end_; + enum _Indexing { __unknown, __manual, __automatic }; + _Indexing __indexing_; + size_t __next_arg_id_; + size_t __num_args_; +}; +_LIBCPP_CTAD_SUPPORTED_FOR_TYPE(basic_format_parse_context); + +using format_parse_context = basic_format_parse_context; +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +using wformat_parse_context = basic_format_parse_context; +#endif + +#endif //_LIBCPP_STD_VER > 17 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___FORMAT_FORMAT_PARSE_CONTEXT_H diff --git a/app/src/main/cpp/libcxx/include/__format/format_string.h b/app/src/main/cpp/libcxx/include/__format/format_string.h new file mode 100644 index 0000000..d9caf86 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__format/format_string.h @@ -0,0 +1,163 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___FORMAT_FORMAT_STRING_H +#define _LIBCPP___FORMAT_FORMAT_STRING_H + +#include <__assert> +#include <__config> +#include <__format/format_error.h> +#include +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 17 + +namespace __format { + +template +struct _LIBCPP_TEMPLATE_VIS __parse_number_result { + const _CharT* __ptr; + uint32_t __value; +}; + +template +__parse_number_result(const _CharT*, uint32_t) -> __parse_number_result<_CharT>; + +template +_LIBCPP_HIDE_FROM_ABI constexpr __parse_number_result<_CharT> +__parse_number(const _CharT* __begin, const _CharT* __end); + +/** + * The maximum value of a numeric argument. + * + * This is used for: + * * arg-id + * * width as value or arg-id. + * * precision as value or arg-id. + * + * The value is compatible with the maximum formatting width and precision + * using the `%*` syntax on a 32-bit system. + */ +inline constexpr uint32_t __number_max = INT32_MAX; + +namespace __detail { +template +_LIBCPP_HIDE_FROM_ABI constexpr __parse_number_result<_CharT> +__parse_zero(const _CharT* __begin, const _CharT*, auto& __parse_ctx) { + __parse_ctx.check_arg_id(0); + return {++__begin, 0}; // can never be larger than the maximum. +} + +template +_LIBCPP_HIDE_FROM_ABI constexpr __parse_number_result<_CharT> +__parse_automatic(const _CharT* __begin, const _CharT*, auto& __parse_ctx) { + size_t __value = __parse_ctx.next_arg_id(); + _LIBCPP_ASSERT(__value <= __number_max, + "Compilers don't support this number of arguments"); + + return {__begin, uint32_t(__value)}; +} + +template +_LIBCPP_HIDE_FROM_ABI constexpr __parse_number_result<_CharT> +__parse_manual(const _CharT* __begin, const _CharT* __end, auto& __parse_ctx) { + __parse_number_result<_CharT> __r = __format::__parse_number(__begin, __end); + __parse_ctx.check_arg_id(__r.__value); + return __r; +} + +} // namespace __detail + +/** + * Parses a number. + * + * The number is used for the 31-bit values @em width and @em precision. This + * allows a maximum value of 2147483647. + */ +template +_LIBCPP_HIDE_FROM_ABI constexpr __parse_number_result<_CharT> +__parse_number(const _CharT* __begin, const _CharT* __end_input) { + static_assert(__format::__number_max == INT32_MAX, + "The algorithm is implemented based on this value."); + /* + * Limit the input to 9 digits, otherwise we need two checks during every + * iteration: + * - Are we at the end of the input? + * - Does the value exceed width of an uint32_t? (Switching to uint64_t would + * have the same issue, but with a higher maximum.) + */ + const _CharT* __end = __end_input - __begin > 9 ? __begin + 9 : __end_input; + uint32_t __value = *__begin - _CharT('0'); + while (++__begin != __end) { + if (*__begin < _CharT('0') || *__begin > _CharT('9')) + return {__begin, __value}; + + __value = __value * 10 + *__begin - _CharT('0'); + } + + if (__begin != __end_input && *__begin >= _CharT('0') && + *__begin <= _CharT('9')) { + + /* + * There are more than 9 digits, do additional validations: + * - Does the 10th digit exceed the maximum allowed value? + * - Are there more than 10 digits? + * (More than 10 digits always overflows the maximum.) + */ + uint64_t __v = uint64_t(__value) * 10 + *__begin++ - _CharT('0'); + if (__v > __number_max || + (__begin != __end_input && *__begin >= _CharT('0') && + *__begin <= _CharT('9'))) + std::__throw_format_error("The numeric value of the format-spec is too large"); + + __value = __v; + } + + return {__begin, __value}; +} + +/** + * Multiplexer for all parse functions. + * + * The parser will return a pointer beyond the last consumed character. This + * should be the closing '}' of the arg-id. + */ +template +_LIBCPP_HIDE_FROM_ABI constexpr __parse_number_result<_CharT> +__parse_arg_id(const _CharT* __begin, const _CharT* __end, auto& __parse_ctx) { + switch (*__begin) { + case _CharT('0'): + return __detail::__parse_zero(__begin, __end, __parse_ctx); + + case _CharT(':'): + // This case is conditionally valid. It's allowed in an arg-id in the + // replacement-field, but not in the std-format-spec. The caller can + // provide a better diagnostic, so accept it here unconditionally. + case _CharT('}'): + return __detail::__parse_automatic(__begin, __end, __parse_ctx); + } + if (*__begin < _CharT('0') || *__begin > _CharT('9')) + std::__throw_format_error("The arg-id of the format-spec starts with an invalid character"); + + return __detail::__parse_manual(__begin, __end, __parse_ctx); +} + +} // namespace __format + +#endif //_LIBCPP_STD_VER > 17 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___FORMAT_FORMAT_STRING_H diff --git a/app/src/main/cpp/libcxx/include/__format/format_to_n_result.h b/app/src/main/cpp/libcxx/include/__format/format_to_n_result.h new file mode 100644 index 0000000..f1ed9a0 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__format/format_to_n_result.h @@ -0,0 +1,35 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___FORMAT_FORMAT_TO_N_RESULT_H +#define _LIBCPP___FORMAT_FORMAT_TO_N_RESULT_H + +#include <__config> +#include <__iterator/incrementable_traits.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 17 + +template +struct _LIBCPP_TEMPLATE_VIS format_to_n_result { + _OutIt out; + iter_difference_t<_OutIt> size; +}; +_LIBCPP_CTAD_SUPPORTED_FOR_TYPE(format_to_n_result); + +#endif //_LIBCPP_STD_VER > 17 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___FORMAT_FORMAT_TO_N_RESULT_H diff --git a/app/src/main/cpp/libcxx/include/__format/formatter.h b/app/src/main/cpp/libcxx/include/__format/formatter.h new file mode 100644 index 0000000..900a09a --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__format/formatter.h @@ -0,0 +1,54 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___FORMAT_FORMATTER_H +#define _LIBCPP___FORMAT_FORMATTER_H + +#include <__availability> +#include <__config> +#include <__format/format_fwd.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 17 + +/// The default formatter template. +/// +/// [format.formatter.spec]/5 +/// If F is a disabled specialization of formatter, these values are false: +/// - is_default_constructible_v, +/// - is_copy_constructible_v, +/// - is_move_constructible_v, +/// - is_copy_assignable, and +/// - is_move_assignable. +template +struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter { + formatter() = delete; + formatter(const formatter&) = delete; + formatter& operator=(const formatter&) = delete; +}; + +# if _LIBCPP_STD_VER > 20 + +template +_LIBCPP_HIDE_FROM_ABI constexpr void __set_debug_format(_Tp& __formatter) { + if constexpr (requires { __formatter.set_debug_format(); }) + __formatter.set_debug_format(); +} + +# endif // _LIBCPP_STD_VER > 20 +#endif // _LIBCPP_STD_VER > 17 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___FORMAT_FORMATTER_H diff --git a/app/src/main/cpp/libcxx/include/__format/formatter_bool.h b/app/src/main/cpp/libcxx/include/__format/formatter_bool.h new file mode 100644 index 0000000..0d005a1 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__format/formatter_bool.h @@ -0,0 +1,78 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___FORMAT_FORMATTER_BOOL_H +#define _LIBCPP___FORMAT_FORMATTER_BOOL_H + +#include <__algorithm/copy.h> +#include <__availability> +#include <__config> +#include <__debug> +#include <__format/concepts.h> +#include <__format/format_error.h> +#include <__format/format_parse_context.h> +#include <__format/formatter.h> +#include <__format/formatter_integral.h> +#include <__format/parser_std_format_spec.h> +#include <__utility/unreachable.h> +#include + +#ifndef _LIBCPP_HAS_NO_LOCALIZATION +# include +#endif + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 17 + +template <__fmt_char_type _CharT> +struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter { +public: + _LIBCPP_HIDE_FROM_ABI constexpr auto + parse(basic_format_parse_context<_CharT>& __parse_ctx) -> decltype(__parse_ctx.begin()) { + auto __result = __parser_.__parse(__parse_ctx, __format_spec::__fields_integral); + __format_spec::__process_parsed_bool(__parser_); + return __result; + } + + _LIBCPP_HIDE_FROM_ABI auto format(bool __value, auto& __ctx) const -> decltype(__ctx.out()) { + switch (__parser_.__type_) { + case __format_spec::__type::__default: + case __format_spec::__type::__string: + return __formatter::__format_bool(__value, __ctx, __parser_.__get_parsed_std_specifications(__ctx)); + + case __format_spec::__type::__binary_lower_case: + case __format_spec::__type::__binary_upper_case: + case __format_spec::__type::__octal: + case __format_spec::__type::__decimal: + case __format_spec::__type::__hexadecimal_lower_case: + case __format_spec::__type::__hexadecimal_upper_case: + // Promotes bool to an integral type. This reduces the number of + // instantiations of __format_integer reducing code size. + return __formatter::__format_integer( + static_cast(__value), __ctx, __parser_.__get_parsed_std_specifications(__ctx)); + + default: + _LIBCPP_ASSERT(false, "The parse function should have validated the type"); + __libcpp_unreachable(); + } + } + + __format_spec::__parser<_CharT> __parser_; +}; + +#endif //_LIBCPP_STD_VER > 17 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___FORMAT_FORMATTER_BOOL_H diff --git a/app/src/main/cpp/libcxx/include/__format/formatter_char.h b/app/src/main/cpp/libcxx/include/__format/formatter_char.h new file mode 100644 index 0000000..8a92e74 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__format/formatter_char.h @@ -0,0 +1,93 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___FORMAT_FORMATTER_CHAR_H +#define _LIBCPP___FORMAT_FORMATTER_CHAR_H + +#include <__availability> +#include <__concepts/same_as.h> +#include <__config> +#include <__format/concepts.h> +#include <__format/format_parse_context.h> +#include <__format/formatter.h> +#include <__format/formatter_integral.h> +#include <__format/formatter_output.h> +#include <__format/parser_std_format_spec.h> +#include <__type_traits/conditional.h> +#include <__type_traits/is_signed.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 17 + +template <__fmt_char_type _CharT> +struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT __formatter_char { +public: + _LIBCPP_HIDE_FROM_ABI constexpr auto + parse(basic_format_parse_context<_CharT>& __parse_ctx) -> decltype(__parse_ctx.begin()) { + auto __result = __parser_.__parse(__parse_ctx, __format_spec::__fields_integral); + __format_spec::__process_parsed_char(__parser_); + return __result; + } + + _LIBCPP_HIDE_FROM_ABI auto format(_CharT __value, auto& __ctx) const -> decltype(__ctx.out()) { + if (__parser_.__type_ == __format_spec::__type::__default || __parser_.__type_ == __format_spec::__type::__char) + return __formatter::__format_char(__value, __ctx.out(), __parser_.__get_parsed_std_specifications(__ctx)); + +# if _LIBCPP_STD_VER > 20 + if (__parser_.__type_ == __format_spec::__type::__debug) + return __formatter::__format_escaped_char(__value, __ctx.out(), __parser_.__get_parsed_std_specifications(__ctx)); +# endif + + if constexpr (sizeof(_CharT) <= sizeof(int)) + // Promotes _CharT to an integral type. This reduces the number of + // instantiations of __format_integer reducing code size. + return __formatter::__format_integer( + static_cast, int, unsigned>>(__value), + __ctx, + __parser_.__get_parsed_std_specifications(__ctx)); + else + return __formatter::__format_integer(__value, __ctx, __parser_.__get_parsed_std_specifications(__ctx)); + } + + _LIBCPP_HIDE_FROM_ABI auto format(char __value, auto& __ctx) const -> decltype(__ctx.out()) + requires(same_as<_CharT, wchar_t>) + { + return format(static_cast(__value), __ctx); + } + +# if _LIBCPP_STD_VER > 20 + _LIBCPP_HIDE_FROM_ABI constexpr void set_debug_format() { __parser_.__type_ = __format_spec::__type::__debug; } +# endif + + __format_spec::__parser<_CharT> __parser_; +}; + +template <> +struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter : public __formatter_char {}; + +# ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +template <> +struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter : public __formatter_char {}; + +template <> +struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter : public __formatter_char { +}; + +# endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS + +#endif //_LIBCPP_STD_VER > 17 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___FORMAT_FORMATTER_CHAR_H diff --git a/app/src/main/cpp/libcxx/include/__format/formatter_floating_point.h b/app/src/main/cpp/libcxx/include/__format/formatter_floating_point.h new file mode 100644 index 0000000..a544b53 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__format/formatter_floating_point.h @@ -0,0 +1,757 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___FORMAT_FORMATTER_FLOATING_POINT_H +#define _LIBCPP___FORMAT_FORMATTER_FLOATING_POINT_H + +#include <__algorithm/copy_n.h> +#include <__algorithm/find.h> +#include <__algorithm/max.h> +#include <__algorithm/min.h> +#include <__algorithm/rotate.h> +#include <__algorithm/transform.h> +#include <__concepts/arithmetic.h> +#include <__concepts/same_as.h> +#include <__config> +#include <__format/concepts.h> +#include <__format/format_parse_context.h> +#include <__format/formatter.h> +#include <__format/formatter_integral.h> +#include <__format/formatter_output.h> +#include <__format/parser_std_format_spec.h> +#include <__memory/allocator.h> +#include <__utility/move.h> +#include <__utility/unreachable.h> +#include + +#ifndef _LIBCPP_HAS_NO_LOCALIZATION +# include +#endif + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 17 + +namespace __formatter { + +template +_LIBCPP_HIDE_FROM_ABI char* __to_buffer(char* __first, char* __last, _Tp __value) { + to_chars_result __r = _VSTD::to_chars(__first, __last, __value); + _LIBCPP_ASSERT(__r.ec == errc(0), "Internal buffer too small"); + return __r.ptr; +} + +template +_LIBCPP_HIDE_FROM_ABI char* __to_buffer(char* __first, char* __last, _Tp __value, chars_format __fmt) { + to_chars_result __r = _VSTD::to_chars(__first, __last, __value, __fmt); + _LIBCPP_ASSERT(__r.ec == errc(0), "Internal buffer too small"); + return __r.ptr; +} + +template +_LIBCPP_HIDE_FROM_ABI char* __to_buffer(char* __first, char* __last, _Tp __value, chars_format __fmt, int __precision) { + to_chars_result __r = _VSTD::to_chars(__first, __last, __value, __fmt, __precision); + _LIBCPP_ASSERT(__r.ec == errc(0), "Internal buffer too small"); + return __r.ptr; +} + +// https://en.cppreference.com/w/cpp/language/types#cite_note-1 +// float min subnormal: +/-0x1p-149 max: +/- 3.402,823,4 10^38 +// double min subnormal: +/-0x1p-1074 max +/- 1.797,693,134,862,315,7 10^308 +// long double (x86) min subnormal: +/-0x1p-16446 max: +/- 1.189,731,495,357,231,765,021 10^4932 +// +// The maximum number of digits required for the integral part is based on the +// maximum's value power of 10. Every power of 10 requires one additional +// decimal digit. +// The maximum number of digits required for the fractional part is based on +// the minimal subnormal hexadecimal output's power of 10. Every division of a +// fraction's binary 1 by 2, requires one additional decimal digit. +// +// The maximum size of a formatted value depends on the selected output format. +// Ignoring the fact the format string can request a precision larger than the +// values maximum required, these values are: +// +// sign 1 code unit +// __max_integral +// radix point 1 code unit +// __max_fractional +// exponent character 1 code unit +// sign 1 code unit +// __max_fractional_value +// ----------------------------------- +// total 4 code units extra required. +// +// TODO FMT Optimize the storage to avoid storing digits that are known to be zero. +// https://www.exploringbinary.com/maximum-number-of-decimal-digits-in-binary-floating-point-numbers/ + +// TODO FMT Add long double specialization when to_chars has proper long double support. +template +struct __traits; + +template +_LIBCPP_HIDE_FROM_ABI constexpr size_t __float_buffer_size(int __precision) { + using _Traits = __traits<_Fp>; + return 4 + _Traits::__max_integral + __precision + _Traits::__max_fractional_value; +} + +template <> +struct __traits { + static constexpr int __max_integral = 38; + static constexpr int __max_fractional = 149; + static constexpr int __max_fractional_value = 3; + static constexpr size_t __stack_buffer_size = 256; + + static constexpr int __hex_precision_digits = 3; +}; + +template <> +struct __traits { + static constexpr int __max_integral = 308; + static constexpr int __max_fractional = 1074; + static constexpr int __max_fractional_value = 4; + static constexpr size_t __stack_buffer_size = 1024; + + static constexpr int __hex_precision_digits = 4; +}; + +/// Helper class to store the conversion buffer. +/// +/// Depending on the maxium size required for a value, the buffer is allocated +/// on the stack or the heap. +template +class _LIBCPP_TEMPLATE_VIS __float_buffer { + using _Traits = __traits<_Fp>; + +public: + // TODO FMT Improve this constructor to do a better estimate. + // When using a scientific formatting with a precision of 6 a stack buffer + // will always suffice. At the moment that isn't important since floats and + // doubles use a stack buffer, unless the precision used in the format string + // is large. + // When supporting long doubles the __max_integral part becomes 4932 which + // may be too much for some platforms. For these cases a better estimate is + // required. + explicit _LIBCPP_HIDE_FROM_ABI __float_buffer(int __precision) + : __precision_(__precision != -1 ? __precision : _Traits::__max_fractional) { + + // When the precision is larger than _Traits::__max_fractional the digits in + // the range (_Traits::__max_fractional, precision] will contain the value + // zero. There's no need to request to_chars to write these zeros: + // - When the value is large a temporary heap buffer needs to be allocated. + // - When to_chars writes the values they need to be "copied" to the output: + // - char: std::fill on the output iterator is faster than std::copy. + // - wchar_t: same argument as char, but additional std::copy won't work. + // The input is always a char buffer, so every char in the buffer needs + // to be converted from a char to a wchar_t. + if (__precision_ > _Traits::__max_fractional) { + __num_trailing_zeros_ = __precision_ - _Traits::__max_fractional; + __precision_ = _Traits::__max_fractional; + } + + __size_ = __formatter::__float_buffer_size<_Fp>(__precision_); + if (__size_ > _Traits::__stack_buffer_size) + // The allocated buffer's contents don't need initialization. + __begin_ = allocator{}.allocate(__size_); + else + __begin_ = __buffer_; + } + + _LIBCPP_HIDE_FROM_ABI ~__float_buffer() { + if (__size_ > _Traits::__stack_buffer_size) + allocator{}.deallocate(__begin_, __size_); + } + _LIBCPP_HIDE_FROM_ABI __float_buffer(const __float_buffer&) = delete; + _LIBCPP_HIDE_FROM_ABI __float_buffer& operator=(const __float_buffer&) = delete; + + _LIBCPP_HIDE_FROM_ABI char* begin() const { return __begin_; } + _LIBCPP_HIDE_FROM_ABI char* end() const { return __begin_ + __size_; } + + _LIBCPP_HIDE_FROM_ABI int __precision() const { return __precision_; } + _LIBCPP_HIDE_FROM_ABI int __num_trailing_zeros() const { return __num_trailing_zeros_; } + _LIBCPP_HIDE_FROM_ABI void __remove_trailing_zeros() { __num_trailing_zeros_ = 0; } + _LIBCPP_HIDE_FROM_ABI void __add_trailing_zeros(int __zeros) { __num_trailing_zeros_ += __zeros; } + +private: + int __precision_; + int __num_trailing_zeros_{0}; + size_t __size_; + char* __begin_; + char __buffer_[_Traits::__stack_buffer_size]; +}; + +struct __float_result { + /// Points at the beginning of the integral part in the buffer. + /// + /// When there's no sign character this points at the start of the buffer. + char* __integral; + + /// Points at the radix point, when not present it's the same as \ref __last. + char* __radix_point; + + /// Points at the exponent character, when not present it's the same as \ref __last. + char* __exponent; + + /// Points beyond the last written element in the buffer. + char* __last; +}; + +/// Finds the position of the exponent character 'e' at the end of the buffer. +/// +/// Assuming there is an exponent the input will terminate with +/// eSdd and eSdddd (S = sign, d = digit) +/// +/// \returns a pointer to the exponent or __last when not found. +constexpr inline _LIBCPP_HIDE_FROM_ABI char* __find_exponent(char* __first, char* __last) { + ptrdiff_t __size = __last - __first; + if (__size >= 4) { + __first = __last - _VSTD::min(__size, ptrdiff_t(6)); + for (; __first != __last - 3; ++__first) { + if (*__first == 'e') + return __first; + } + } + return __last; +} + +template +_LIBCPP_HIDE_FROM_ABI __float_result __format_buffer_default(const __float_buffer<_Fp>& __buffer, _Tp __value, + char* __integral) { + __float_result __result; + __result.__integral = __integral; + __result.__last = __formatter::__to_buffer(__integral, __buffer.end(), __value); + + __result.__exponent = __formatter::__find_exponent(__result.__integral, __result.__last); + + // Constrains: + // - There's at least one decimal digit before the radix point. + // - The radix point, when present, is placed before the exponent. + __result.__radix_point = _VSTD::find(__result.__integral + 1, __result.__exponent, '.'); + + // When the radix point isn't found its position is the exponent instead of + // __result.__last. + if (__result.__radix_point == __result.__exponent) + __result.__radix_point = __result.__last; + + // clang-format off + _LIBCPP_ASSERT((__result.__integral != __result.__last) && + (__result.__radix_point == __result.__last || *__result.__radix_point == '.') && + (__result.__exponent == __result.__last || *__result.__exponent == 'e'), + "Post-condition failure."); + // clang-format on + + return __result; +} + +template +_LIBCPP_HIDE_FROM_ABI __float_result __format_buffer_hexadecimal_lower_case(const __float_buffer<_Fp>& __buffer, + _Tp __value, int __precision, + char* __integral) { + __float_result __result; + __result.__integral = __integral; + if (__precision == -1) + __result.__last = __formatter::__to_buffer(__integral, __buffer.end(), __value, chars_format::hex); + else + __result.__last = __formatter::__to_buffer(__integral, __buffer.end(), __value, chars_format::hex, __precision); + + // H = one or more hex-digits + // S = sign + // D = one or more decimal-digits + // When the fractional part is zero and no precision the output is 0p+0 + // else the output is 0.HpSD + // So testing the second position can differentiate between these two cases. + char* __first = __integral + 1; + if (*__first == '.') { + __result.__radix_point = __first; + // One digit is the minimum + // 0.hpSd + // ^-- last + // ^---- integral = end of search + // ^-------- start of search + // 0123456 + // + // Four digits is the maximum + // 0.hpSdddd + // ^-- last + // ^---- integral = end of search + // ^-------- start of search + // 0123456789 + static_assert(__traits<_Fp>::__hex_precision_digits <= 4, "Guard against possible underflow."); + + char* __last = __result.__last - 2; + __first = __last - __traits<_Fp>::__hex_precision_digits; + __result.__exponent = _VSTD::find(__first, __last, 'p'); + } else { + __result.__radix_point = __result.__last; + __result.__exponent = __first; + } + + // clang-format off + _LIBCPP_ASSERT((__result.__integral != __result.__last) && + (__result.__radix_point == __result.__last || *__result.__radix_point == '.') && + (__result.__exponent != __result.__last && *__result.__exponent == 'p'), + "Post-condition failure."); + // clang-format on + + return __result; +} + +template +_LIBCPP_HIDE_FROM_ABI __float_result __format_buffer_hexadecimal_upper_case(const __float_buffer<_Fp>& __buffer, + _Tp __value, int __precision, + char* __integral) { + __float_result __result = + __formatter::__format_buffer_hexadecimal_lower_case(__buffer, __value, __precision, __integral); + _VSTD::transform(__result.__integral, __result.__exponent, __result.__integral, __hex_to_upper); + *__result.__exponent = 'P'; + return __result; +} + +template +_LIBCPP_HIDE_FROM_ABI __float_result __format_buffer_scientific_lower_case(const __float_buffer<_Fp>& __buffer, + _Tp __value, int __precision, + char* __integral) { + __float_result __result; + __result.__integral = __integral; + __result.__last = + __formatter::__to_buffer(__integral, __buffer.end(), __value, chars_format::scientific, __precision); + + char* __first = __integral + 1; + _LIBCPP_ASSERT(__first != __result.__last, "No exponent present"); + if (*__first == '.') { + __result.__radix_point = __first; + __result.__exponent = __formatter::__find_exponent(__first + 1, __result.__last); + } else { + __result.__radix_point = __result.__last; + __result.__exponent = __first; + } + + // clang-format off + _LIBCPP_ASSERT((__result.__integral != __result.__last) && + (__result.__radix_point == __result.__last || *__result.__radix_point == '.') && + (__result.__exponent != __result.__last && *__result.__exponent == 'e'), + "Post-condition failure."); + // clang-format on + return __result; +} + +template +_LIBCPP_HIDE_FROM_ABI __float_result __format_buffer_scientific_upper_case(const __float_buffer<_Fp>& __buffer, + _Tp __value, int __precision, + char* __integral) { + __float_result __result = + __formatter::__format_buffer_scientific_lower_case(__buffer, __value, __precision, __integral); + *__result.__exponent = 'E'; + return __result; +} + +template +_LIBCPP_HIDE_FROM_ABI __float_result __format_buffer_fixed(const __float_buffer<_Fp>& __buffer, _Tp __value, + int __precision, char* __integral) { + __float_result __result; + __result.__integral = __integral; + __result.__last = __formatter::__to_buffer(__integral, __buffer.end(), __value, chars_format::fixed, __precision); + + // When there's no precision there's no radix point. + // Else the radix point is placed at __precision + 1 from the end. + // By converting __precision to a bool the subtraction can be done + // unconditionally. + __result.__radix_point = __result.__last - (__precision + bool(__precision)); + __result.__exponent = __result.__last; + + // clang-format off + _LIBCPP_ASSERT((__result.__integral != __result.__last) && + (__result.__radix_point == __result.__last || *__result.__radix_point == '.') && + (__result.__exponent == __result.__last), + "Post-condition failure."); + // clang-format on + return __result; +} + +template +_LIBCPP_HIDE_FROM_ABI __float_result __format_buffer_general_lower_case(__float_buffer<_Fp>& __buffer, _Tp __value, + int __precision, char* __integral) { + + __buffer.__remove_trailing_zeros(); + + __float_result __result; + __result.__integral = __integral; + __result.__last = __formatter::__to_buffer(__integral, __buffer.end(), __value, chars_format::general, __precision); + + char* __first = __integral + 1; + if (__first == __result.__last) { + __result.__radix_point = __result.__last; + __result.__exponent = __result.__last; + } else { + __result.__exponent = __formatter::__find_exponent(__first, __result.__last); + if (__result.__exponent != __result.__last) + // In scientific mode if there's a radix point it will always be after + // the first digit. (This is the position __first points at). + __result.__radix_point = *__first == '.' ? __first : __result.__last; + else { + // In fixed mode the algorithm truncates trailing spaces and possibly the + // radix point. There's no good guess for the position of the radix point + // therefore scan the output after the first digit. + + __result.__radix_point = _VSTD::find(__first, __result.__last, '.'); + } + } + + // clang-format off + _LIBCPP_ASSERT((__result.__integral != __result.__last) && + (__result.__radix_point == __result.__last || *__result.__radix_point == '.') && + (__result.__exponent == __result.__last || *__result.__exponent == 'e'), + "Post-condition failure."); + // clang-format on + + return __result; +} + +template +_LIBCPP_HIDE_FROM_ABI __float_result __format_buffer_general_upper_case(__float_buffer<_Fp>& __buffer, _Tp __value, + int __precision, char* __integral) { + __float_result __result = __formatter::__format_buffer_general_lower_case(__buffer, __value, __precision, __integral); + if (__result.__exponent != __result.__last) + *__result.__exponent = 'E'; + return __result; +} + +/// Fills the buffer with the data based on the requested formatting. +/// +/// This function, when needed, turns the characters to upper case and +/// determines the "interesting" locations which are returned to the caller. +/// +/// This means the caller never has to convert the contents of the buffer to +/// upper case or search for radix points and the location of the exponent. +/// This gives a bit of overhead. The original code didn't do that, but due +/// to the number of possible additional work needed to turn this number to +/// the proper output the code was littered with tests for upper cases and +/// searches for radix points and exponents. +/// - When a precision larger than the type's precision is selected +/// additional zero characters need to be written before the exponent. +/// - alternate form needs to add a radix point when not present. +/// - localization needs to do grouping in the integral part. +template +// TODO FMT _Fp should just be _Tp when to_chars has proper long double support. +_LIBCPP_HIDE_FROM_ABI __float_result __format_buffer( + __float_buffer<_Fp>& __buffer, + _Tp __value, + bool __negative, + bool __has_precision, + __format_spec::__sign __sign, + __format_spec::__type __type) { + char* __first = __formatter::__insert_sign(__buffer.begin(), __negative, __sign); + switch (__type) { + case __format_spec::__type::__default: + if (__has_precision) + return __formatter::__format_buffer_general_lower_case(__buffer, __value, __buffer.__precision(), __first); + else + return __formatter::__format_buffer_default(__buffer, __value, __first); + + case __format_spec::__type::__hexfloat_lower_case: + return __formatter::__format_buffer_hexadecimal_lower_case( + __buffer, __value, __has_precision ? __buffer.__precision() : -1, __first); + + case __format_spec::__type::__hexfloat_upper_case: + return __formatter::__format_buffer_hexadecimal_upper_case( + __buffer, __value, __has_precision ? __buffer.__precision() : -1, __first); + + case __format_spec::__type::__scientific_lower_case: + return __formatter::__format_buffer_scientific_lower_case(__buffer, __value, __buffer.__precision(), __first); + + case __format_spec::__type::__scientific_upper_case: + return __formatter::__format_buffer_scientific_upper_case(__buffer, __value, __buffer.__precision(), __first); + + case __format_spec::__type::__fixed_lower_case: + case __format_spec::__type::__fixed_upper_case: + return __formatter::__format_buffer_fixed(__buffer, __value, __buffer.__precision(), __first); + + case __format_spec::__type::__general_lower_case: + return __formatter::__format_buffer_general_lower_case(__buffer, __value, __buffer.__precision(), __first); + + case __format_spec::__type::__general_upper_case: + return __formatter::__format_buffer_general_upper_case(__buffer, __value, __buffer.__precision(), __first); + + default: + _LIBCPP_ASSERT(false, "The parser should have validated the type"); + __libcpp_unreachable(); + } +} + +# ifndef _LIBCPP_HAS_NO_LOCALIZATION +template +_LIBCPP_HIDE_FROM_ABI _OutIt __format_locale_specific_form( + _OutIt __out_it, + const __float_buffer<_Fp>& __buffer, + const __float_result& __result, + _VSTD::locale __loc, + __format_spec::__parsed_specifications<_CharT> __specs) { + const auto& __np = std::use_facet>(__loc); + string __grouping = __np.grouping(); + char* __first = __result.__integral; + // When no radix point or exponent are present __last will be __result.__last. + char* __last = _VSTD::min(__result.__radix_point, __result.__exponent); + + ptrdiff_t __digits = __last - __first; + if (!__grouping.empty()) { + if (__digits <= __grouping[0]) + __grouping.clear(); + else + __grouping = __formatter::__determine_grouping(__digits, __grouping); + } + + ptrdiff_t __size = + __result.__last - __buffer.begin() + // Formatted string + __buffer.__num_trailing_zeros() + // Not yet rendered zeros + __grouping.size() - // Grouping contains one + !__grouping.empty(); // additional character + + __formatter::__padding_size_result __padding = {0, 0}; + bool __zero_padding = __specs.__alignment_ == __format_spec::__alignment::__zero_padding; + if (__size < __specs.__width_) { + if (__zero_padding) { + __specs.__alignment_ = __format_spec::__alignment::__right; + __specs.__fill_ = _CharT('0'); + } + + __padding = __formatter::__padding_size(__size, __specs.__width_, __specs.__alignment_); + } + + // sign and (zero padding or alignment) + if (__zero_padding && __first != __buffer.begin()) + *__out_it++ = *__buffer.begin(); + __out_it = __formatter::__fill(_VSTD::move(__out_it), __padding.__before_, __specs.__fill_); + if (!__zero_padding && __first != __buffer.begin()) + *__out_it++ = *__buffer.begin(); + + // integral part + if (__grouping.empty()) { + __out_it = __formatter::__copy(__first, __digits, _VSTD::move(__out_it)); + } else { + auto __r = __grouping.rbegin(); + auto __e = __grouping.rend() - 1; + _CharT __sep = __np.thousands_sep(); + // The output is divided in small groups of numbers to write: + // - A group before the first separator. + // - A separator and a group, repeated for the number of separators. + // - A group after the last separator. + // This loop achieves that process by testing the termination condition + // midway in the loop. + while (true) { + __out_it = __formatter::__copy(__first, *__r, _VSTD::move(__out_it)); + __first += *__r; + + if (__r == __e) + break; + + ++__r; + *__out_it++ = __sep; + } + } + + // fractional part + if (__result.__radix_point != __result.__last) { + *__out_it++ = __np.decimal_point(); + __out_it = __formatter::__copy(__result.__radix_point + 1, __result.__exponent, _VSTD::move(__out_it)); + __out_it = __formatter::__fill(_VSTD::move(__out_it), __buffer.__num_trailing_zeros(), _CharT('0')); + } + + // exponent + if (__result.__exponent != __result.__last) + __out_it = __formatter::__copy(__result.__exponent, __result.__last, _VSTD::move(__out_it)); + + // alignment + return __formatter::__fill(_VSTD::move(__out_it), __padding.__after_, __specs.__fill_); +} +# endif // _LIBCPP_HAS_NO_LOCALIZATION + +template +_LIBCPP_HIDE_FROM_ABI _OutIt __format_floating_point_non_finite( + _OutIt __out_it, __format_spec::__parsed_specifications<_CharT> __specs, bool __negative, bool __isnan) { + char __buffer[4]; + char* __last = __formatter::__insert_sign(__buffer, __negative, __specs.__std_.__sign_); + + // to_chars can return inf, infinity, nan, and nan(n-char-sequence). + // The format library requires inf and nan. + // All in one expression to avoid dangling references. + bool __upper_case = + __specs.__std_.__type_ == __format_spec::__type::__hexfloat_upper_case || + __specs.__std_.__type_ == __format_spec::__type::__scientific_upper_case || + __specs.__std_.__type_ == __format_spec::__type::__fixed_upper_case || + __specs.__std_.__type_ == __format_spec::__type::__general_upper_case; + __last = _VSTD::copy_n(&("infnanINFNAN"[6 * __upper_case + 3 * __isnan]), 3, __last); + + // [format.string.std]/13 + // A zero (0) character preceding the width field pads the field with + // leading zeros (following any indication of sign or base) to the field + // width, except when applied to an infinity or NaN. + if (__specs.__alignment_ == __format_spec::__alignment::__zero_padding) + __specs.__alignment_ = __format_spec::__alignment::__right; + + return __formatter::__write(__buffer, __last, _VSTD::move(__out_it), __specs); +} + +template +_LIBCPP_HIDE_FROM_ABI auto +__format_floating_point(_Tp __value, auto& __ctx, __format_spec::__parsed_specifications<_CharT> __specs) + -> decltype(__ctx.out()) { + bool __negative = _VSTD::signbit(__value); + + if (!_VSTD::isfinite(__value)) [[unlikely]] + return __formatter::__format_floating_point_non_finite(__ctx.out(), __specs, __negative, _VSTD::isnan(__value)); + + // Depending on the std-format-spec string the sign and the value + // might not be outputted together: + // - zero-padding may insert additional '0' characters. + // Therefore the value is processed as a non negative value. + // The function @ref __insert_sign will insert a '-' when the value was + // negative. + + if (__negative) + __value = -__value; + + // TODO FMT _Fp should just be _Tp when to_chars has proper long double support. + using _Fp = conditional_t, double, _Tp>; + // Force the type of the precision to avoid -1 to become an unsigned value. + __float_buffer<_Fp> __buffer(__specs.__precision_); + __float_result __result = __formatter::__format_buffer( + __buffer, __value, __negative, (__specs.__has_precision()), __specs.__std_.__sign_, __specs.__std_.__type_); + + if (__specs.__std_.__alternate_form_) { + if (__result.__radix_point == __result.__last) { + *__result.__last++ = '.'; + + // When there is an exponent the point needs to be moved before the + // exponent. When there's no exponent the rotate does nothing. Since + // rotate tests whether the operation is a nop, call it unconditionally. + _VSTD::rotate(__result.__exponent, __result.__last - 1, __result.__last); + __result.__radix_point = __result.__exponent; + + // The radix point is always placed before the exponent. + // - No exponent needs to point to the new last. + // - An exponent needs to move one position to the right. + // So it's safe to increment the value unconditionally. + ++__result.__exponent; + } + + // [format.string.std]/6 + // In addition, for g and G conversions, trailing zeros are not removed + // from the result. + // + // If the type option for a floating-point type is none it may use the + // general formatting, but it's not a g or G conversion. So in that case + // the formatting should not append trailing zeros. + bool __is_general = __specs.__std_.__type_ == __format_spec::__type::__general_lower_case || + __specs.__std_.__type_ == __format_spec::__type::__general_upper_case; + + if (__is_general) { + // https://en.cppreference.com/w/c/io/fprintf + // Let P equal the precision if nonzero, 6 if the precision is not + // specified, or 1 if the precision is 0. Then, if a conversion with + // style E would have an exponent of X: + int __p = _VSTD::max(1, (__specs.__has_precision() ? __specs.__precision_ : 6)); + if (__result.__exponent == __result.__last) + // if P > X >= -4, the conversion is with style f or F and precision P - 1 - X. + // By including the radix point it calculates P - (1 + X) + __p -= __result.__radix_point - __buffer.begin(); + else + // otherwise, the conversion is with style e or E and precision P - 1. + --__p; + + ptrdiff_t __precision = (__result.__exponent - __result.__radix_point) - 1; + if (__precision < __p) + __buffer.__add_trailing_zeros(__p - __precision); + } + } + +# ifndef _LIBCPP_HAS_NO_LOCALIZATION + if (__specs.__std_.__locale_specific_form_) + return __formatter::__format_locale_specific_form(__ctx.out(), __buffer, __result, __ctx.locale(), __specs); +# endif + + ptrdiff_t __size = __result.__last - __buffer.begin(); + int __num_trailing_zeros = __buffer.__num_trailing_zeros(); + if (__size + __num_trailing_zeros >= __specs.__width_) { + if (__num_trailing_zeros && __result.__exponent != __result.__last) + // Insert trailing zeros before exponent character. + return __formatter::__copy( + __result.__exponent, + __result.__last, + __formatter::__fill(__formatter::__copy(__buffer.begin(), __result.__exponent, __ctx.out()), + __num_trailing_zeros, + _CharT('0'))); + + return __formatter::__fill( + __formatter::__copy(__buffer.begin(), __result.__last, __ctx.out()), __num_trailing_zeros, _CharT('0')); + } + + auto __out_it = __ctx.out(); + char* __first = __buffer.begin(); + if (__specs.__alignment_ == __format_spec::__alignment ::__zero_padding) { + // When there is a sign output it before the padding. Note the __size + // doesn't need any adjustment, regardless whether the sign is written + // here or in __formatter::__write. + if (__first != __result.__integral) + *__out_it++ = *__first++; + // After the sign is written, zero padding is the same a right alignment + // with '0'. + __specs.__alignment_ = __format_spec::__alignment::__right; + __specs.__fill_ = _CharT('0'); + } + + if (__num_trailing_zeros) + return __formatter::__write_using_trailing_zeros( + __first, __result.__last, _VSTD::move(__out_it), __specs, __size, __result.__exponent, __num_trailing_zeros); + + return __formatter::__write(__first, __result.__last, _VSTD::move(__out_it), __specs, __size); +} + +} // namespace __formatter + +template <__fmt_char_type _CharT> +struct _LIBCPP_TEMPLATE_VIS __formatter_floating_point { +public: + _LIBCPP_HIDE_FROM_ABI constexpr auto + parse(basic_format_parse_context<_CharT>& __parse_ctx) -> decltype(__parse_ctx.begin()) { + auto __result = __parser_.__parse(__parse_ctx, __format_spec::__fields_floating_point); + __format_spec::__process_parsed_floating_point(__parser_); + return __result; + } + + template + _LIBCPP_HIDE_FROM_ABI auto format(_Tp __value, auto& __ctx) const -> decltype(__ctx.out()) { + return __formatter::__format_floating_point(__value, __ctx, __parser_.__get_parsed_std_specifications(__ctx)); + } + + __format_spec::__parser<_CharT> __parser_; +}; + +template <__fmt_char_type _CharT> +struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter + : public __formatter_floating_point<_CharT> {}; +template <__fmt_char_type _CharT> +struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter + : public __formatter_floating_point<_CharT> {}; +template <__fmt_char_type _CharT> +struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter + : public __formatter_floating_point<_CharT> {}; + +#endif //_LIBCPP_STD_VER > 17 + +_LIBCPP_END_NAMESPACE_STD + +_LIBCPP_POP_MACROS + +#endif // _LIBCPP___FORMAT_FORMATTER_FLOATING_POINT_H diff --git a/app/src/main/cpp/libcxx/include/__format/formatter_integer.h b/app/src/main/cpp/libcxx/include/__format/formatter_integer.h new file mode 100644 index 0000000..b4be9f9 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__format/formatter_integer.h @@ -0,0 +1,107 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___FORMAT_FORMATTER_INTEGER_H +#define _LIBCPP___FORMAT_FORMATTER_INTEGER_H + +#include <__availability> +#include <__concepts/arithmetic.h> +#include <__config> +#include <__format/concepts.h> +#include <__format/format_parse_context.h> +#include <__format/formatter.h> +#include <__format/formatter_integral.h> +#include <__format/formatter_output.h> +#include <__format/parser_std_format_spec.h> +#include <__type_traits/make_32_64_or_128_bit.h> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + + _LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 17 + + template <__fmt_char_type _CharT> + struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT __formatter_integer { + +public: + _LIBCPP_HIDE_FROM_ABI constexpr auto + parse(basic_format_parse_context<_CharT>& __parse_ctx) -> decltype(__parse_ctx.begin()) { + auto __result = __parser_.__parse(__parse_ctx, __format_spec::__fields_integral); + __format_spec::__process_parsed_integer(__parser_); + return __result; + } + + template + _LIBCPP_HIDE_FROM_ABI auto format(_Tp __value, auto& __ctx) const -> decltype(__ctx.out()) { + __format_spec::__parsed_specifications<_CharT> __specs = __parser_.__get_parsed_std_specifications(__ctx); + + if (__specs.__std_.__type_ == __format_spec::__type::__char) + return __formatter::__format_char(__value, __ctx.out(), __specs); + + using _Type = __make_32_64_or_128_bit_t<_Tp>; + static_assert(!is_same<_Type, void>::value, "unsupported integral type used in __formatter_integer::__format"); + + // Reduce the number of instantiation of the integer formatter + return __formatter::__format_integer(static_cast<_Type>(__value), __ctx, __specs); + } + + __format_spec::__parser<_CharT> __parser_; +}; + +// Signed integral types. +template <__fmt_char_type _CharT> +struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter + : public __formatter_integer<_CharT> {}; +template <__fmt_char_type _CharT> +struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter : public __formatter_integer<_CharT> { +}; +template <__fmt_char_type _CharT> +struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter : public __formatter_integer<_CharT> {}; +template <__fmt_char_type _CharT> +struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter : public __formatter_integer<_CharT> {}; +template <__fmt_char_type _CharT> +struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter + : public __formatter_integer<_CharT> {}; +# ifndef _LIBCPP_HAS_NO_INT128 +template <__fmt_char_type _CharT> +struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<__int128_t, _CharT> + : public __formatter_integer<_CharT> {}; +# endif + +// Unsigned integral types. +template <__fmt_char_type _CharT> +struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter + : public __formatter_integer<_CharT> {}; +template <__fmt_char_type _CharT> +struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter + : public __formatter_integer<_CharT> {}; +template <__fmt_char_type _CharT> +struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter + : public __formatter_integer<_CharT> {}; +template <__fmt_char_type _CharT> +struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter + : public __formatter_integer<_CharT> {}; +template <__fmt_char_type _CharT> +struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter + : public __formatter_integer<_CharT> {}; +# ifndef _LIBCPP_HAS_NO_INT128 +template <__fmt_char_type _CharT> +struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<__uint128_t, _CharT> + : public __formatter_integer<_CharT> {}; +# endif + +#endif //_LIBCPP_STD_VER > 17 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___FORMAT_FORMATTER_INTEGER_H diff --git a/app/src/main/cpp/libcxx/include/__format/formatter_integral.h b/app/src/main/cpp/libcxx/include/__format/formatter_integral.h new file mode 100644 index 0000000..fe3a063 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__format/formatter_integral.h @@ -0,0 +1,363 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___FORMAT_FORMATTER_INTEGRAL_H +#define _LIBCPP___FORMAT_FORMATTER_INTEGRAL_H + +#include <__concepts/arithmetic.h> +#include <__concepts/same_as.h> +#include <__config> +#include <__format/concepts.h> +#include <__format/format_error.h> +#include <__format/formatter_output.h> +#include <__format/parser_std_format_spec.h> +#include <__utility/unreachable.h> +#include +#include +#include +#include + +#ifndef _LIBCPP_HAS_NO_LOCALIZATION +# include +#endif + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 17 + +namespace __formatter { + +// +// Generic +// + +_LIBCPP_HIDE_FROM_ABI inline char* __insert_sign(char* __buf, bool __negative, __format_spec::__sign __sign) { + if (__negative) + *__buf++ = '-'; + else + switch (__sign) { + case __format_spec::__sign::__default: + case __format_spec::__sign::__minus: + // No sign added. + break; + case __format_spec::__sign::__plus: + *__buf++ = '+'; + break; + case __format_spec::__sign::__space: + *__buf++ = ' '; + break; + } + + return __buf; +} + +/** + * Determines the required grouping based on the size of the input. + * + * The grouping's last element will be repeated. For simplicity this repeating + * is unwrapped based on the length of the input. (When the input is short some + * groups are not processed.) + * + * @returns The size of the groups to write. This means the number of + * separator characters written is size() - 1. + * + * @note Since zero-sized groups cause issues they are silently ignored. + * + * @note The grouping field of the locale is always a @c std::string, + * regardless whether the @c std::numpunct's type is @c char or @c wchar_t. + */ +_LIBCPP_HIDE_FROM_ABI inline string __determine_grouping(ptrdiff_t __size, const string& __grouping) { + _LIBCPP_ASSERT(!__grouping.empty() && __size > __grouping[0], + "The slow grouping formatting is used while there will be no " + "separators written"); + string __r; + auto __end = __grouping.end() - 1; + auto __ptr = __grouping.begin(); + + while (true) { + __size -= *__ptr; + if (__size > 0) + __r.push_back(*__ptr); + else { + // __size <= 0 so the value pushed will be <= *__ptr. + __r.push_back(*__ptr + __size); + return __r; + } + + // Proceed to the next group. + if (__ptr != __end) { + do { + ++__ptr; + // Skip grouping with a width of 0. + } while (*__ptr == 0 && __ptr != __end); + } + } + + __libcpp_unreachable(); +} + +// +// Char +// + +template <__fmt_char_type _CharT> +_LIBCPP_HIDE_FROM_ABI auto __format_char( + integral auto __value, + output_iterator auto __out_it, + __format_spec::__parsed_specifications<_CharT> __specs) -> decltype(__out_it) { + using _Tp = decltype(__value); + if constexpr (!same_as<_CharT, _Tp>) { + // cmp_less and cmp_greater can't be used for character types. + if constexpr (signed_integral<_CharT> == signed_integral<_Tp>) { + if (__value < numeric_limits<_CharT>::min() || __value > numeric_limits<_CharT>::max()) + std::__throw_format_error("Integral value outside the range of the char type"); + } else if constexpr (signed_integral<_CharT>) { + // _CharT is signed _Tp is unsigned + if (__value > static_cast>(numeric_limits<_CharT>::max())) + std::__throw_format_error("Integral value outside the range of the char type"); + } else { + // _CharT is unsigned _Tp is signed + if (__value < 0 || static_cast>(__value) > numeric_limits<_CharT>::max()) + std::__throw_format_error("Integral value outside the range of the char type"); + } + } + + const auto __c = static_cast<_CharT>(__value); + return __formatter::__write(_VSTD::addressof(__c), _VSTD::addressof(__c) + 1, _VSTD::move(__out_it), __specs); +} + +// +// Integer +// + +/** Wrapper around @ref to_chars, returning the output pointer. */ +template +_LIBCPP_HIDE_FROM_ABI char* __to_buffer(char* __first, char* __last, _Tp __value, int __base) { + // TODO FMT Evaluate code overhead due to not calling the internal function + // directly. (Should be zero overhead.) + to_chars_result __r = _VSTD::to_chars(__first, __last, __value, __base); + _LIBCPP_ASSERT(__r.ec == errc(0), "Internal buffer too small"); + return __r.ptr; +} + +/** + * Helper to determine the buffer size to output a integer in Base @em x. + * + * There are several overloads for the supported bases. The function uses the + * base as template argument so it can be used in a constant expression. + */ +template +consteval size_t __buffer_size() noexcept + requires(_Base == 2) +{ + return numeric_limits<_Tp>::digits // The number of binary digits. + + 2 // Reserve space for the '0[Bb]' prefix. + + 1; // Reserve space for the sign. +} + +template +consteval size_t __buffer_size() noexcept + requires(_Base == 8) +{ + return numeric_limits<_Tp>::digits // The number of binary digits. + / 3 // Adjust to octal. + + 1 // Turn floor to ceil. + + 1 // Reserve space for the '0' prefix. + + 1; // Reserve space for the sign. +} + +template +consteval size_t __buffer_size() noexcept + requires(_Base == 10) +{ + return numeric_limits<_Tp>::digits10 // The floored value. + + 1 // Turn floor to ceil. + + 1; // Reserve space for the sign. +} + +template +consteval size_t __buffer_size() noexcept + requires(_Base == 16) +{ + return numeric_limits<_Tp>::digits // The number of binary digits. + / 4 // Adjust to hexadecimal. + + 2 // Reserve space for the '0[Xx]' prefix. + + 1; // Reserve space for the sign. +} + +template +_LIBCPP_HIDE_FROM_ABI auto __format_integer( + _Tp __value, + auto& __ctx, + __format_spec::__parsed_specifications<_CharT> __specs, + bool __negative, + char* __begin, + char* __end, + const char* __prefix, + int __base) -> decltype(__ctx.out()) { + char* __first = __formatter::__insert_sign(__begin, __negative, __specs.__std_.__sign_); + if (__specs.__std_.__alternate_form_ && __prefix) + while (*__prefix) + *__first++ = *__prefix++; + + char* __last = __formatter::__to_buffer(__first, __end, __value, __base); + +# ifndef _LIBCPP_HAS_NO_LOCALIZATION + if (__specs.__std_.__locale_specific_form_) { + const auto& __np = std::use_facet>(__ctx.locale()); + string __grouping = __np.grouping(); + ptrdiff_t __size = __last - __first; + // Writing the grouped form has more overhead than the normal output + // routines. If there will be no separators written the locale-specific + // form is identical to the normal routine. Test whether to grouped form + // is required. + if (!__grouping.empty() && __size > __grouping[0]) + return __formatter::__write_using_decimal_separators( + __ctx.out(), + __begin, + __first, + __last, + __formatter::__determine_grouping(__size, __grouping), + __np.thousands_sep(), + __specs); + } +# endif + auto __out_it = __ctx.out(); + if (__specs.__alignment_ != __format_spec::__alignment::__zero_padding) + __first = __begin; + else { + // __buf contains [sign][prefix]data + // ^ location of __first + // The zero padding is done like: + // - Write [sign][prefix] + // - Write data right aligned with '0' as fill character. + __out_it = __formatter::__copy(__begin, __first, _VSTD::move(__out_it)); + __specs.__alignment_ = __format_spec::__alignment::__right; + __specs.__fill_ = _CharT('0'); + int32_t __size = __first - __begin; + + __specs.__width_ -= _VSTD::min(__size, __specs.__width_); + } + + if (__specs.__std_.__type_ != __format_spec::__type::__hexadecimal_upper_case) [[likely]] + return __formatter::__write(__first, __last, __ctx.out(), __specs); + + return __formatter::__write_transformed(__first, __last, __ctx.out(), __specs, __formatter::__hex_to_upper); +} + +template +_LIBCPP_HIDE_FROM_ABI auto __format_integer( + _Tp __value, auto& __ctx, __format_spec::__parsed_specifications<_CharT> __specs, bool __negative = false) + -> decltype(__ctx.out()) { + switch (__specs.__std_.__type_) { + case __format_spec::__type::__binary_lower_case: { + array()> __array; + return __formatter::__format_integer(__value, __ctx, __specs, __negative, __array.begin(), __array.end(), "0b", 2); + } + case __format_spec::__type::__binary_upper_case: { + array()> __array; + return __formatter::__format_integer(__value, __ctx, __specs, __negative, __array.begin(), __array.end(), "0B", 2); + } + case __format_spec::__type::__octal: { + // Octal is special; if __value == 0 there's no prefix. + array()> __array; + return __formatter::__format_integer( + __value, __ctx, __specs, __negative, __array.begin(), __array.end(), __value != 0 ? "0" : nullptr, 8); + } + case __format_spec::__type::__default: + case __format_spec::__type::__decimal: { + array()> __array; + return __formatter::__format_integer( + __value, __ctx, __specs, __negative, __array.begin(), __array.end(), nullptr, 10); + } + case __format_spec::__type::__hexadecimal_lower_case: { + array()> __array; + return __formatter::__format_integer(__value, __ctx, __specs, __negative, __array.begin(), __array.end(), "0x", 16); + } + case __format_spec::__type::__hexadecimal_upper_case: { + array()> __array; + return __formatter::__format_integer(__value, __ctx, __specs, __negative, __array.begin(), __array.end(), "0X", 16); + } + default: + _LIBCPP_ASSERT(false, "The parse function should have validated the type"); + __libcpp_unreachable(); + } +} + +template +_LIBCPP_HIDE_FROM_ABI auto +__format_integer(_Tp __value, auto& __ctx, __format_spec::__parsed_specifications<_CharT> __specs) + -> decltype(__ctx.out()) { + // Depending on the std-format-spec string the sign and the value + // might not be outputted together: + // - alternate form may insert a prefix string. + // - zero-padding may insert additional '0' characters. + // Therefore the value is processed as a positive unsigned value. + // The function @ref __insert_sign will a '-' when the value was negative. + auto __r = std::__to_unsigned_like(__value); + bool __negative = __value < 0; + if (__negative) + __r = std::__complement(__r); + + return __formatter::__format_integer(__r, __ctx, __specs, __negative); +} + +// +// Formatter arithmetic (bool) +// + +template +struct _LIBCPP_TEMPLATE_VIS __bool_strings; + +template <> +struct _LIBCPP_TEMPLATE_VIS __bool_strings { + static constexpr string_view __true{"true"}; + static constexpr string_view __false{"false"}; +}; + +# ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +template <> +struct _LIBCPP_TEMPLATE_VIS __bool_strings { + static constexpr wstring_view __true{L"true"}; + static constexpr wstring_view __false{L"false"}; +}; +# endif + +template +_LIBCPP_HIDE_FROM_ABI auto +__format_bool(bool __value, auto& __ctx, __format_spec::__parsed_specifications<_CharT> __specs) + -> decltype(__ctx.out()) { +# ifndef _LIBCPP_HAS_NO_LOCALIZATION + if (__specs.__std_.__locale_specific_form_) { + const auto& __np = std::use_facet>(__ctx.locale()); + basic_string<_CharT> __str = __value ? __np.truename() : __np.falsename(); + return __formatter::__write_string_no_precision(basic_string_view<_CharT>{__str}, __ctx.out(), __specs); + } +# endif + basic_string_view<_CharT> __str = + __value ? __formatter::__bool_strings<_CharT>::__true : __formatter::__bool_strings<_CharT>::__false; + return __formatter::__write(__str.begin(), __str.end(), __ctx.out(), __specs); +} + +} // namespace __formatter + +#endif //_LIBCPP_STD_VER > 17 + +_LIBCPP_END_NAMESPACE_STD + +_LIBCPP_POP_MACROS + +#endif // _LIBCPP___FORMAT_FORMATTER_INTEGRAL_H diff --git a/app/src/main/cpp/libcxx/include/__format/formatter_output.h b/app/src/main/cpp/libcxx/include/__format/formatter_output.h new file mode 100644 index 0000000..4676925 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__format/formatter_output.h @@ -0,0 +1,570 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___FORMAT_FORMATTER_OUTPUT_H +#define _LIBCPP___FORMAT_FORMATTER_OUTPUT_H + +#include <__algorithm/ranges_copy.h> +#include <__algorithm/ranges_fill_n.h> +#include <__algorithm/ranges_transform.h> +#include <__chrono/statically_widen.h> +#include <__concepts/same_as.h> +#include <__config> +#include <__format/buffer.h> +#include <__format/concepts.h> +#include <__format/escaped_output_table.h> +#include <__format/formatter.h> +#include <__format/parser_std_format_spec.h> +#include <__format/unicode.h> +#include <__iterator/back_insert_iterator.h> +#include <__type_traits/make_unsigned.h> +#include <__utility/move.h> +#include <__utility/unreachable.h> +#include +#include +#include +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 17 + +namespace __formatter { + +_LIBCPP_HIDE_FROM_ABI constexpr char __hex_to_upper(char __c) { + switch (__c) { + case 'a': + return 'A'; + case 'b': + return 'B'; + case 'c': + return 'C'; + case 'd': + return 'D'; + case 'e': + return 'E'; + case 'f': + return 'F'; + } + return __c; +} + +struct _LIBCPP_TYPE_VIS __padding_size_result { + size_t __before_; + size_t __after_; +}; + +_LIBCPP_HIDE_FROM_ABI constexpr __padding_size_result +__padding_size(size_t __size, size_t __width, __format_spec::__alignment __align) { + _LIBCPP_ASSERT(__width > __size, "don't call this function when no padding is required"); + _LIBCPP_ASSERT( + __align != __format_spec::__alignment::__zero_padding, "the caller should have handled the zero-padding"); + + size_t __fill = __width - __size; + switch (__align) { + case __format_spec::__alignment::__zero_padding: + __libcpp_unreachable(); + + case __format_spec::__alignment::__left: + return {0, __fill}; + + case __format_spec::__alignment::__center: { + // The extra padding is divided per [format.string.std]/3 + // __before = floor(__fill, 2); + // __after = ceil(__fill, 2); + size_t __before = __fill / 2; + size_t __after = __fill - __before; + return {__before, __after}; + } + case __format_spec::__alignment::__default: + case __format_spec::__alignment::__right: + return {__fill, 0}; + } + __libcpp_unreachable(); +} + +/// Copy wrapper. +/// +/// This uses a "mass output function" of __format::__output_buffer when possible. +template <__fmt_char_type _CharT, __fmt_char_type _OutCharT = _CharT> +_LIBCPP_HIDE_FROM_ABI auto __copy(basic_string_view<_CharT> __str, output_iterator auto __out_it) + -> decltype(__out_it) { + if constexpr (_VSTD::same_as>>) { + __out_it.__get_container()->__copy(__str); + return __out_it; + } else if constexpr (_VSTD::same_as::__iterator>) { + __out_it.__buffer_->__copy(__str); + return __out_it; + } else { + return std::ranges::copy(__str, _VSTD::move(__out_it)).out; + } +} + +template <__fmt_char_type _CharT, __fmt_char_type _OutCharT = _CharT> +_LIBCPP_HIDE_FROM_ABI auto +__copy(const _CharT* __first, const _CharT* __last, output_iterator auto __out_it) + -> decltype(__out_it) { + return __formatter::__copy(basic_string_view{__first, __last}, _VSTD::move(__out_it)); +} + +template <__fmt_char_type _CharT, __fmt_char_type _OutCharT = _CharT> +_LIBCPP_HIDE_FROM_ABI auto __copy(const _CharT* __first, size_t __n, output_iterator auto __out_it) + -> decltype(__out_it) { + return __formatter::__copy(basic_string_view{__first, __n}, _VSTD::move(__out_it)); +} + +/// Transform wrapper. +/// +/// This uses a "mass output function" of __format::__output_buffer when possible. +template <__fmt_char_type _CharT, __fmt_char_type _OutCharT = _CharT, class _UnaryOperation> +_LIBCPP_HIDE_FROM_ABI auto +__transform(const _CharT* __first, + const _CharT* __last, + output_iterator auto __out_it, + _UnaryOperation __operation) -> decltype(__out_it) { + if constexpr (_VSTD::same_as>>) { + __out_it.__get_container()->__transform(__first, __last, _VSTD::move(__operation)); + return __out_it; + } else if constexpr (_VSTD::same_as::__iterator>) { + __out_it.__buffer_->__transform(__first, __last, _VSTD::move(__operation)); + return __out_it; + } else { + return std::ranges::transform(__first, __last, _VSTD::move(__out_it), __operation).out; + } +} + +/// Fill wrapper. +/// +/// This uses a "mass output function" of __format::__output_buffer when possible. +template <__fmt_char_type _CharT, output_iterator _OutIt> +_LIBCPP_HIDE_FROM_ABI _OutIt __fill(_OutIt __out_it, size_t __n, _CharT __value) { + if constexpr (_VSTD::same_as>>) { + __out_it.__get_container()->__fill(__n, __value); + return __out_it; + } else if constexpr (_VSTD::same_as::__iterator>) { + __out_it.__buffer_->__fill(__n, __value); + return __out_it; + } else { + return std::ranges::fill_n(_VSTD::move(__out_it), __n, __value); + } +} + +template +_LIBCPP_HIDE_FROM_ABI _OutIt __write_using_decimal_separators(_OutIt __out_it, const char* __begin, const char* __first, + const char* __last, string&& __grouping, _CharT __sep, + __format_spec::__parsed_specifications<_CharT> __specs) { + int __size = (__first - __begin) + // [sign][prefix] + (__last - __first) + // data + (__grouping.size() - 1); // number of separator characters + + __padding_size_result __padding = {0, 0}; + if (__specs.__alignment_ == __format_spec::__alignment::__zero_padding) { + // Write [sign][prefix]. + __out_it = __formatter::__copy(__begin, __first, _VSTD::move(__out_it)); + + if (__specs.__width_ > __size) { + // Write zero padding. + __padding.__before_ = __specs.__width_ - __size; + __out_it = __formatter::__fill(_VSTD::move(__out_it), __specs.__width_ - __size, _CharT('0')); + } + } else { + if (__specs.__width_ > __size) { + // Determine padding and write padding. + __padding = __formatter::__padding_size(__size, __specs.__width_, __specs.__alignment_); + + __out_it = __formatter::__fill(_VSTD::move(__out_it), __padding.__before_, __specs.__fill_); + } + // Write [sign][prefix]. + __out_it = __formatter::__copy(__begin, __first, _VSTD::move(__out_it)); + } + + auto __r = __grouping.rbegin(); + auto __e = __grouping.rend() - 1; + _LIBCPP_ASSERT(__r != __e, "The slow grouping formatting is used while " + "there will be no separators written."); + // The output is divided in small groups of numbers to write: + // - A group before the first separator. + // - A separator and a group, repeated for the number of separators. + // - A group after the last separator. + // This loop achieves that process by testing the termination condition + // midway in the loop. + // + // TODO FMT This loop evaluates the loop invariant `__parser.__type != + // _Flags::_Type::__hexadecimal_upper_case` for every iteration. (This test + // happens in the __write call.) Benchmark whether making two loops and + // hoisting the invariant is worth the effort. + while (true) { + if (__specs.__std_.__type_ == __format_spec::__type::__hexadecimal_upper_case) { + __last = __first + *__r; + __out_it = __formatter::__transform(__first, __last, _VSTD::move(__out_it), __hex_to_upper); + __first = __last; + } else { + __out_it = __formatter::__copy(__first, *__r, _VSTD::move(__out_it)); + __first += *__r; + } + + if (__r == __e) + break; + + ++__r; + *__out_it++ = __sep; + } + + return __formatter::__fill(_VSTD::move(__out_it), __padding.__after_, __specs.__fill_); +} + +/// Writes the input to the output with the required padding. +/// +/// Since the output column width is specified the function can be used for +/// ASCII and Unicode output. +/// +/// \pre \a __size <= \a __width. Using this function when this pre-condition +/// doesn't hold incurs an unwanted overhead. +/// +/// \param __str The string to write. +/// \param __out_it The output iterator to write to. +/// \param __specs The parsed formatting specifications. +/// \param __size The (estimated) output column width. When the elements +/// to be written are ASCII the following condition holds +/// \a __size == \a __last - \a __first. +/// +/// \returns An iterator pointing beyond the last element written. +/// +/// \note The type of the elements in range [\a __first, \a __last) can differ +/// from the type of \a __specs. Integer output uses \c std::to_chars for its +/// conversion, which means the [\a __first, \a __last) always contains elements +/// of the type \c char. +template +_LIBCPP_HIDE_FROM_ABI auto +__write(basic_string_view<_CharT> __str, + output_iterator auto __out_it, + __format_spec::__parsed_specifications<_ParserCharT> __specs, + ptrdiff_t __size) -> decltype(__out_it) { + if (__size >= __specs.__width_) + return __formatter::__copy(__str, _VSTD::move(__out_it)); + + __padding_size_result __padding = __formatter::__padding_size(__size, __specs.__width_, __specs.__std_.__alignment_); + __out_it = __formatter::__fill(_VSTD::move(__out_it), __padding.__before_, __specs.__fill_); + __out_it = __formatter::__copy(__str, _VSTD::move(__out_it)); + return __formatter::__fill(_VSTD::move(__out_it), __padding.__after_, __specs.__fill_); +} + +template +_LIBCPP_HIDE_FROM_ABI auto +__write(const _CharT* __first, + const _CharT* __last, + output_iterator auto __out_it, + __format_spec::__parsed_specifications<_ParserCharT> __specs, + ptrdiff_t __size) -> decltype(__out_it) { + _LIBCPP_ASSERT(__first <= __last, "Not a valid range"); + return __formatter::__write(basic_string_view{__first, __last}, _VSTD::move(__out_it), __specs, __size); +} + +/// \overload +/// +/// Calls the function above where \a __size = \a __last - \a __first. +template +_LIBCPP_HIDE_FROM_ABI auto +__write(const _CharT* __first, + const _CharT* __last, + output_iterator auto __out_it, + __format_spec::__parsed_specifications<_ParserCharT> __specs) -> decltype(__out_it) { + _LIBCPP_ASSERT(__first <= __last, "Not a valid range"); + return __formatter::__write(__first, __last, _VSTD::move(__out_it), __specs, __last - __first); +} + +template +_LIBCPP_HIDE_FROM_ABI auto __write_transformed(const _CharT* __first, const _CharT* __last, + output_iterator auto __out_it, + __format_spec::__parsed_specifications<_ParserCharT> __specs, + _UnaryOperation __op) -> decltype(__out_it) { + _LIBCPP_ASSERT(__first <= __last, "Not a valid range"); + + ptrdiff_t __size = __last - __first; + if (__size >= __specs.__width_) + return __formatter::__transform(__first, __last, _VSTD::move(__out_it), __op); + + __padding_size_result __padding = __formatter::__padding_size(__size, __specs.__width_, __specs.__alignment_); + __out_it = __formatter::__fill(_VSTD::move(__out_it), __padding.__before_, __specs.__fill_); + __out_it = __formatter::__transform(__first, __last, _VSTD::move(__out_it), __op); + return __formatter::__fill(_VSTD::move(__out_it), __padding.__after_, __specs.__fill_); +} + +/// Writes additional zero's for the precision before the exponent. +/// This is used when the precision requested in the format string is larger +/// than the maximum precision of the floating-point type. These precision +/// digits are always 0. +/// +/// \param __exponent The location of the exponent character. +/// \param __num_trailing_zeros The number of 0's to write before the exponent +/// character. +template +_LIBCPP_HIDE_FROM_ABI auto __write_using_trailing_zeros( + const _CharT* __first, + const _CharT* __last, + output_iterator auto __out_it, + __format_spec::__parsed_specifications<_ParserCharT> __specs, + size_t __size, + const _CharT* __exponent, + size_t __num_trailing_zeros) -> decltype(__out_it) { + _LIBCPP_ASSERT(__first <= __last, "Not a valid range"); + _LIBCPP_ASSERT(__num_trailing_zeros > 0, "The overload not writing trailing zeros should have been used"); + + __padding_size_result __padding = + __formatter::__padding_size(__size + __num_trailing_zeros, __specs.__width_, __specs.__alignment_); + __out_it = __formatter::__fill(_VSTD::move(__out_it), __padding.__before_, __specs.__fill_); + __out_it = __formatter::__copy(__first, __exponent, _VSTD::move(__out_it)); + __out_it = __formatter::__fill(_VSTD::move(__out_it), __num_trailing_zeros, _CharT('0')); + __out_it = __formatter::__copy(__exponent, __last, _VSTD::move(__out_it)); + return __formatter::__fill(_VSTD::move(__out_it), __padding.__after_, __specs.__fill_); +} + +/// Writes a string using format's width estimation algorithm. +/// +/// \pre !__specs.__has_precision() +/// +/// \note When \c _LIBCPP_HAS_NO_UNICODE is defined the function assumes the +/// input is ASCII. +template +_LIBCPP_HIDE_FROM_ABI auto __write_string_no_precision( + basic_string_view<_CharT> __str, + output_iterator auto __out_it, + __format_spec::__parsed_specifications<_CharT> __specs) -> decltype(__out_it) { + _LIBCPP_ASSERT(!__specs.__has_precision(), "use __write_string"); + + // No padding -> copy the string + if (!__specs.__has_width()) + return __formatter::__copy(__str, _VSTD::move(__out_it)); + + // Note when the estimated width is larger than size there's no padding. So + // there's no reason to get the real size when the estimate is larger than or + // equal to the minimum field width. + size_t __size = + __format_spec::__estimate_column_width(__str, __specs.__width_, __format_spec::__column_width_rounding::__up) + .__width_; + return __formatter::__write(__str, _VSTD::move(__out_it), __specs, __size); +} + +template +_LIBCPP_HIDE_FROM_ABI int __truncate(basic_string_view<_CharT>& __str, int __precision) { + __format_spec::__column_width_result<_CharT> __result = + __format_spec::__estimate_column_width(__str, __precision, __format_spec::__column_width_rounding::__down); + __str = basic_string_view<_CharT>{__str.begin(), __result.__last_}; + return __result.__width_; +} + +/// Writes a string using format's width estimation algorithm. +/// +/// \note When \c _LIBCPP_HAS_NO_UNICODE is defined the function assumes the +/// input is ASCII. +template +_LIBCPP_HIDE_FROM_ABI auto __write_string( + basic_string_view<_CharT> __str, + output_iterator auto __out_it, + __format_spec::__parsed_specifications<_CharT> __specs) -> decltype(__out_it) { + if (!__specs.__has_precision()) + return __formatter::__write_string_no_precision(__str, _VSTD::move(__out_it), __specs); + + int __size = __formatter::__truncate(__str, __specs.__precision_); + + return __formatter::__write(__str.begin(), __str.end(), _VSTD::move(__out_it), __specs, __size); +} + +# if _LIBCPP_STD_VER > 20 + +struct __nul_terminator {}; + +template +_LIBCPP_HIDE_FROM_ABI bool operator==(const _CharT* __cstr, __nul_terminator) { + return *__cstr == _CharT('\0'); +} + +template +_LIBCPP_HIDE_FROM_ABI void +__write_escaped_code_unit(basic_string<_CharT>& __str, char32_t __value, const _CharT* __prefix) { + back_insert_iterator __out_it{__str}; + std::ranges::copy(__prefix, __nul_terminator{}, __out_it); + + char __buffer[8]; + to_chars_result __r = std::to_chars(std::begin(__buffer), std::end(__buffer), __value, 16); + _LIBCPP_ASSERT(__r.ec == errc(0), "Internal buffer too small"); + std::ranges::copy(std::begin(__buffer), __r.ptr, __out_it); + + __str += _CharT('}'); +} + +// [format.string.escaped]/2.2.1.2 +// ... +// then the sequence \u{hex-digit-sequence} is appended to E, where +// hex-digit-sequence is the shortest hexadecimal representation of C using +// lower-case hexadecimal digits. +template +_LIBCPP_HIDE_FROM_ABI void __write_well_formed_escaped_code_unit(basic_string<_CharT>& __str, char32_t __value) { + __formatter::__write_escaped_code_unit(__str, __value, _LIBCPP_STATICALLY_WIDEN(_CharT, "\\u{")); +} + +// [format.string.escaped]/2.2.3 +// Otherwise (X is a sequence of ill-formed code units), each code unit U is +// appended to E in order as the sequence \x{hex-digit-sequence}, where +// hex-digit-sequence is the shortest hexadecimal representation of U using +// lower-case hexadecimal digits. +template +_LIBCPP_HIDE_FROM_ABI void __write_escape_ill_formed_code_unit(basic_string<_CharT>& __str, char32_t __value) { + __formatter::__write_escaped_code_unit(__str, __value, _LIBCPP_STATICALLY_WIDEN(_CharT, "\\x{")); +} + +template +[[nodiscard]] _LIBCPP_HIDE_FROM_ABI bool __is_escaped_sequence_written(basic_string<_CharT>& __str, char32_t __value) { +# ifdef _LIBCPP_HAS_NO_UNICODE + // For ASCII assume everything above 127 is printable. + if (__value > 127) + return false; +# endif + + if (!__escaped_output_table::__needs_escape(__value)) + return false; + + __formatter::__write_well_formed_escaped_code_unit(__str, __value); + return true; +} + +template +[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr char32_t __to_char32(_CharT __value) { + return static_cast>(__value); +} + +enum class _LIBCPP_ENUM_VIS __escape_quotation_mark { __apostrophe, __double_quote }; + +// [format.string.escaped]/2 +template +[[nodiscard]] _LIBCPP_HIDE_FROM_ABI bool +__is_escaped_sequence_written(basic_string<_CharT>& __str, char32_t __value, __escape_quotation_mark __mark) { + // 2.2.1.1 - Mapped character in [tab:format.escape.sequences] + switch (__value) { + case _CharT('\t'): + __str += _LIBCPP_STATICALLY_WIDEN(_CharT, "\\t"); + return true; + case _CharT('\n'): + __str += _LIBCPP_STATICALLY_WIDEN(_CharT, "\\n"); + return true; + case _CharT('\r'): + __str += _LIBCPP_STATICALLY_WIDEN(_CharT, "\\r"); + return true; + case _CharT('\''): + if (__mark == __escape_quotation_mark::__apostrophe) + __str += _LIBCPP_STATICALLY_WIDEN(_CharT, R"(\')"); + else + __str += __value; + return true; + case _CharT('"'): + if (__mark == __escape_quotation_mark::__double_quote) + __str += _LIBCPP_STATICALLY_WIDEN(_CharT, R"(\")"); + else + __str += __value; + return true; + case _CharT('\\'): + __str += _LIBCPP_STATICALLY_WIDEN(_CharT, R"(\\)"); + return true; + + // 2.2.1.2 - Space + case _CharT(' '): + __str += __value; + return true; + } + + // 2.2.2 + // Otherwise, if X is a shift sequence, the effect on E and further + // decoding of S is unspecified. + // For now shift sequences are ignored and treated as Unicode. Other parts + // of the format library do the same. It's unknown how ostream treats them. + // TODO FMT determine what to do with shift sequences. + + // 2.2.1.2.1 and 2.2.1.2.2 - Escape + return __formatter::__is_escaped_sequence_written(__str, __formatter::__to_char32(__value)); +} + +template +_LIBCPP_HIDE_FROM_ABI void +__escape(basic_string<_CharT>& __str, basic_string_view<_CharT> __values, __escape_quotation_mark __mark) { + __unicode::__code_point_view<_CharT> __view{__values.begin(), __values.end()}; + + while (!__view.__at_end()) { + const _CharT* __first = __view.__position(); + typename __unicode::__consume_p2286_result __result = __view.__consume_p2286(); + if (__result.__ill_formed_size == 0) { + if (!__formatter::__is_escaped_sequence_written(__str, __result.__value, __mark)) + // 2.2.1.3 - Add the character + ranges::copy(__first, __view.__position(), std::back_insert_iterator(__str)); + + } else { + // 2.2.3 sequence of ill-formed code units + // The number of code-units in __result.__value depends on the character type being used. + if constexpr (sizeof(_CharT) == 1) { + _LIBCPP_ASSERT(__result.__ill_formed_size == 1 || __result.__ill_formed_size == 4, + "illegal number of invalid code units."); + if (__result.__ill_formed_size == 1) // ill-formed, one code unit + __formatter::__write_escape_ill_formed_code_unit(__str, __result.__value & 0xff); + else { // out of valid range, four code units + // The code point was properly encoded, decode the value. + __formatter::__write_escape_ill_formed_code_unit(__str, __result.__value >> 18 | 0xf0); + __formatter::__write_escape_ill_formed_code_unit(__str, (__result.__value >> 12 & 0x3f) | 0x80); + __formatter::__write_escape_ill_formed_code_unit(__str, (__result.__value >> 6 & 0x3f) | 0x80); + __formatter::__write_escape_ill_formed_code_unit(__str, (__result.__value & 0x3f) | 0x80); + } + } else if constexpr (sizeof(_CharT) == 2) { + _LIBCPP_ASSERT(__result.__ill_formed_size == 1, "for UTF-16 at most one invalid code unit"); + __formatter::__write_escape_ill_formed_code_unit(__str, __result.__value & 0xffff); + } else { + static_assert(sizeof(_CharT) == 4, "unsupported character width"); + _LIBCPP_ASSERT(__result.__ill_formed_size == 1, "for UTF-32 one code unit is one code point"); + __formatter::__write_escape_ill_formed_code_unit(__str, __result.__value); + } + } + } +} + +template +_LIBCPP_HIDE_FROM_ABI auto +__format_escaped_char(_CharT __value, + output_iterator auto __out_it, + __format_spec::__parsed_specifications<_CharT> __specs) -> decltype(__out_it) { + basic_string<_CharT> __str; + __str += _CharT('\''); + __formatter::__escape(__str, basic_string_view{std::addressof(__value), 1}, __escape_quotation_mark::__apostrophe); + __str += _CharT('\''); + return __formatter::__write(__str.data(), __str.data() + __str.size(), _VSTD::move(__out_it), __specs, __str.size()); +} + +template +_LIBCPP_HIDE_FROM_ABI auto +__format_escaped_string(basic_string_view<_CharT> __values, + output_iterator auto __out_it, + __format_spec::__parsed_specifications<_CharT> __specs) -> decltype(__out_it) { + basic_string<_CharT> __str; + __str += _CharT('"'); + __formatter::__escape(__str, __values, __escape_quotation_mark::__double_quote); + __str += _CharT('"'); + return __formatter::__write_string(basic_string_view{__str}, _VSTD::move(__out_it), __specs); +} + +# endif // _LIBCPP_STD_VER > 20 + +} // namespace __formatter + +#endif //_LIBCPP_STD_VER > 17 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___FORMAT_FORMATTER_OUTPUT_H diff --git a/app/src/main/cpp/libcxx/include/__format/formatter_pointer.h b/app/src/main/cpp/libcxx/include/__format/formatter_pointer.h new file mode 100644 index 0000000..31b49e1 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__format/formatter_pointer.h @@ -0,0 +1,73 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___FORMAT_FORMATTER_POINTER_H +#define _LIBCPP___FORMAT_FORMATTER_POINTER_H + +#include <__availability> +#include <__config> +#include <__format/concepts.h> +#include <__format/format_parse_context.h> +#include <__format/formatter.h> +#include <__format/formatter_integral.h> +#include <__format/formatter_output.h> +#include <__format/parser_std_format_spec.h> +#include +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 17 + +template <__fmt_char_type _CharT> +struct _LIBCPP_TEMPLATE_VIS __formatter_pointer { +public: + constexpr __formatter_pointer() { __parser_.__alignment_ = __format_spec::__alignment::__right; } + + _LIBCPP_HIDE_FROM_ABI constexpr auto + parse(basic_format_parse_context<_CharT>& __parse_ctx) -> decltype(__parse_ctx.begin()) { + auto __result = __parser_.__parse(__parse_ctx, __format_spec::__fields_pointer); + __format_spec::__process_display_type_pointer(__parser_.__type_); + return __result; + } + + _LIBCPP_HIDE_FROM_ABI auto format(const void* __ptr, auto& __ctx) const -> decltype(__ctx.out()) { + __format_spec::__parsed_specifications<_CharT> __specs = __parser_.__get_parsed_std_specifications(__ctx); + __specs.__std_.__alternate_form_ = true; + __specs.__std_.__type_ = __format_spec::__type::__hexadecimal_lower_case; + return __formatter::__format_integer(reinterpret_cast(__ptr), __ctx, __specs); + } + + __format_spec::__parser<_CharT> __parser_; +}; + +// [format.formatter.spec]/2.4 +// For each charT, the pointer type specializations template<> +// - struct formatter; +// - template<> struct formatter; +// - template<> struct formatter; +template <__fmt_char_type _CharT> +struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter + : public __formatter_pointer<_CharT> {}; +template <__fmt_char_type _CharT> +struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter : public __formatter_pointer<_CharT> { +}; +template <__fmt_char_type _CharT> +struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter + : public __formatter_pointer<_CharT> {}; + +#endif //_LIBCPP_STD_VER > 17 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___FORMAT_FORMATTER_POINTER_H diff --git a/app/src/main/cpp/libcxx/include/__format/formatter_string.h b/app/src/main/cpp/libcxx/include/__format/formatter_string.h new file mode 100644 index 0000000..606fb79 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__format/formatter_string.h @@ -0,0 +1,159 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___FORMAT_FORMATTER_STRING_H +#define _LIBCPP___FORMAT_FORMATTER_STRING_H + +#include <__availability> +#include <__config> +#include <__format/concepts.h> +#include <__format/format_parse_context.h> +#include <__format/formatter.h> +#include <__format/formatter_output.h> +#include <__format/parser_std_format_spec.h> +#include <__utility/move.h> +#include +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 17 + +template <__fmt_char_type _CharT> +struct _LIBCPP_TEMPLATE_VIS __formatter_string { +public: + _LIBCPP_HIDE_FROM_ABI constexpr auto parse(basic_format_parse_context<_CharT>& __parse_ctx) + -> decltype(__parse_ctx.begin()) { + auto __result = __parser_.__parse(__parse_ctx, __format_spec::__fields_string); + __format_spec::__process_display_type_string(__parser_.__type_); + return __result; + } + + _LIBCPP_HIDE_FROM_ABI auto format(basic_string_view<_CharT> __str, auto& __ctx) const -> decltype(__ctx.out()) { +# if _LIBCPP_STD_VER > 20 + if (__parser_.__type_ == __format_spec::__type::__debug) + return __formatter::__format_escaped_string(__str, __ctx.out(), __parser_.__get_parsed_std_specifications(__ctx)); +# endif + + return __formatter::__write_string(__str, __ctx.out(), __parser_.__get_parsed_std_specifications(__ctx)); + } + +# if _LIBCPP_STD_VER > 20 + _LIBCPP_HIDE_FROM_ABI constexpr void set_debug_format() { __parser_.__type_ = __format_spec::__type::__debug; } +# endif + + __format_spec::__parser<_CharT> __parser_{.__alignment_ = __format_spec::__alignment::__left}; +}; + +// Formatter const char*. +template <__fmt_char_type _CharT> +struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter + : public __formatter_string<_CharT> { + using _Base = __formatter_string<_CharT>; + + _LIBCPP_HIDE_FROM_ABI auto format(const _CharT* __str, auto& __ctx) const -> decltype(__ctx.out()) { + _LIBCPP_ASSERT(__str, "The basic_format_arg constructor should have " + "prevented an invalid pointer."); + + __format_spec::__parsed_specifications<_CharT> __specs = _Base::__parser_.__get_parsed_std_specifications(__ctx); +# if _LIBCPP_STD_VER > 20 + if (_Base::__parser_.__type_ == __format_spec::__type::__debug) + return __formatter::__format_escaped_string(basic_string_view<_CharT>{__str}, __ctx.out(), __specs); +# endif + + // When using a center or right alignment and the width option the length + // of __str must be known to add the padding upfront. This case is handled + // by the base class by converting the argument to a basic_string_view. + // + // When using left alignment and the width option the padding is added + // after outputting __str so the length can be determined while outputting + // __str. The same holds true for the precision, during outputting __str it + // can be validated whether the precision threshold has been reached. For + // now these optimizations aren't implemented. Instead the base class + // handles these options. + // TODO FMT Implement these improvements. + if (__specs.__has_width() || __specs.__has_precision()) + return __formatter::__write_string(basic_string_view<_CharT>{__str}, __ctx.out(), __specs); + + // No formatting required, copy the string to the output. + auto __out_it = __ctx.out(); + while (*__str) + *__out_it++ = *__str++; + return __out_it; + } +}; + +// Formatter char*. +template <__fmt_char_type _CharT> +struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<_CharT*, _CharT> + : public formatter { + using _Base = formatter; + + _LIBCPP_HIDE_FROM_ABI auto format(_CharT* __str, auto& __ctx) const -> decltype(__ctx.out()) { + return _Base::format(__str, __ctx); + } +}; + +// Formatter char[]. +template <__fmt_char_type _CharT, size_t _Size> +struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<_CharT[_Size], _CharT> + : public __formatter_string<_CharT> { + using _Base = __formatter_string<_CharT>; + + _LIBCPP_HIDE_FROM_ABI auto format(_CharT __str[_Size], auto& __ctx) const -> decltype(__ctx.out()) { + return _Base::format(basic_string_view<_CharT>(__str, _Size), __ctx); + } +}; + +// Formatter const char[]. +template <__fmt_char_type _CharT, size_t _Size> +struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter + : public __formatter_string<_CharT> { + using _Base = __formatter_string<_CharT>; + + _LIBCPP_HIDE_FROM_ABI auto format(const _CharT __str[_Size], auto& __ctx) const -> decltype(__ctx.out()) { + return _Base::format(basic_string_view<_CharT>(__str, _Size), __ctx); + } +}; + +// Formatter std::string. +template <__fmt_char_type _CharT, class _Traits, class _Allocator> +struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter, _CharT> + : public __formatter_string<_CharT> { + using _Base = __formatter_string<_CharT>; + + _LIBCPP_HIDE_FROM_ABI auto format(const basic_string<_CharT, _Traits, _Allocator>& __str, auto& __ctx) const + -> decltype(__ctx.out()) { + // Drop _Traits and _Allocator to have one std::basic_string formatter. + return _Base::format(basic_string_view<_CharT>(__str.data(), __str.size()), __ctx); + } +}; + +// Formatter std::string_view. +template <__fmt_char_type _CharT, class _Traits> +struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter, _CharT> + : public __formatter_string<_CharT> { + using _Base = __formatter_string<_CharT>; + + _LIBCPP_HIDE_FROM_ABI auto format(basic_string_view<_CharT, _Traits> __str, auto& __ctx) const + -> decltype(__ctx.out()) { + // Drop _Traits to have one std::basic_string_view formatter. + return _Base::format(basic_string_view<_CharT>(__str.data(), __str.size()), __ctx); + } +}; + +#endif //_LIBCPP_STD_VER > 17 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___FORMAT_FORMATTER_STRING_H diff --git a/app/src/main/cpp/libcxx/include/__format/formatter_tuple.h b/app/src/main/cpp/libcxx/include/__format/formatter_tuple.h new file mode 100644 index 0000000..82f5ada --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__format/formatter_tuple.h @@ -0,0 +1,178 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___FORMAT_FORMATTER_TUPLE_H +#define _LIBCPP___FORMAT_FORMATTER_TUPLE_H + +#include <__algorithm/ranges_copy.h> +#include <__availability> +#include <__chrono/statically_widen.h> +#include <__config> +#include <__format/concepts.h> +#include <__format/format_args.h> +#include <__format/format_context.h> +#include <__format/format_error.h> +#include <__format/format_parse_context.h> +#include <__format/formatter.h> +#include <__format/formatter_output.h> +#include <__format/parser_std_format_spec.h> +#include <__iterator/back_insert_iterator.h> +#include <__type_traits/remove_cvref.h> +#include <__utility/integer_sequence.h> +#include <__utility/pair.h> +#include +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 20 + +template <__fmt_char_type _CharT, class _Tuple, formattable<_CharT>... _Args> +struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT __formatter_tuple { + _LIBCPP_HIDE_FROM_ABI constexpr void set_separator(basic_string_view<_CharT> __separator) { + __separator_ = __separator; + } + _LIBCPP_HIDE_FROM_ABI constexpr void + set_brackets(basic_string_view<_CharT> __opening_bracket, basic_string_view<_CharT> __closing_bracket) { + __opening_bracket_ = __opening_bracket; + __closing_bracket_ = __closing_bracket; + } + + template + _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator parse(_ParseContext& __parse_ctx) { + const _CharT* __begin = __parser_.__parse(__parse_ctx, __format_spec::__fields_tuple); + + // [format.tuple]/7 + // ... For each element e in underlying_, if e.set_debug_format() + // is a valid expression, calls e.set_debug_format(). + // TODO FMT this can be removed when P2733 is accepted. + std::__for_each_index_sequence(make_index_sequence(), [&] { + std::__set_debug_format(std::get<_Index>(__underlying_)); + }); + + const _CharT* __end = __parse_ctx.end(); + if (__begin == __end) + return __begin; + + if (*__begin == _CharT('m')) { + if constexpr (sizeof...(_Args) == 2) { + set_separator(_LIBCPP_STATICALLY_WIDEN(_CharT, ": ")); + set_brackets({}, {}); + ++__begin; + } else + std::__throw_format_error("The format specifier m requires a pair or a two-element tuple"); + } else if (*__begin == _CharT('n')) { + set_brackets({}, {}); + ++__begin; + } + + if (__begin != __end && *__begin != _CharT('}')) + std::__throw_format_error("The format-spec should consume the input or end with a '}'"); + + return __begin; + } + + template + typename _FormatContext::iterator _LIBCPP_HIDE_FROM_ABI + format(conditional_t<(formattable && ...), const _Tuple&, _Tuple&> __tuple, + _FormatContext& __ctx) const { + __format_spec::__parsed_specifications<_CharT> __specs = __parser_.__get_parsed_std_specifications(__ctx); + + if (!__specs.__has_width()) + return __format_tuple(__tuple, __ctx); + + basic_string<_CharT> __str; + + // Since the output is written to a different iterator a new context is + // created. Since the underlying formatter uses the default formatting it + // doesn't need a locale or the formatting arguments. So creating a new + // context works. + // + // This solution works for this formatter, but it will not work for the + // range_formatter. In that patch a generic solution is work in progress. + // Once that is finished it can be used here. (The range_formatter will use + // these features so it's easier to add it there and then port it.) + // + // TODO FMT Use formatting wrapping used in the range_formatter. + basic_format_context __c = std::__format_context_create( + back_insert_iterator{__str}, + basic_format_args>, _CharT>>{}); + + __format_tuple(__tuple, __c); + + return __formatter::__write_string_no_precision(basic_string_view{__str}, __ctx.out(), __specs); + } + + template + _LIBCPP_HIDE_FROM_ABI typename _FormatContext::iterator __format_tuple(auto&& __tuple, _FormatContext& __ctx) const { + __ctx.advance_to(std::ranges::copy(__opening_bracket_, __ctx.out()).out); + + std::__for_each_index_sequence(make_index_sequence(), [&] { + if constexpr (_Index) + __ctx.advance_to(std::ranges::copy(__separator_, __ctx.out()).out); + + // During review Victor suggested to make the exposition only + // __underlying_ member a local variable. Currently the Standard + // requires nested debug-enabled formatter specializations not to + // output escaped output. P2733 fixes that bug, once accepted the + // code below can be used. + // (Note when a paper allows parsing a tuple-underlying-spec the + // exposition only member needs to be a class member. Earlier + // revisions of P2286 proposed that, but this was not pursued, + // due to time constrains and complexity of the matter.) + // TODO FMT This can be updated after P2733 is accepted. +# if 0 + // P2286 uses an exposition only member in the formatter + // tuple, _CharT>...> __underlying_; + // This was used in earlier versions of the paper since + // __underlying_.parse(...) was called. This is no longer the case + // so we can reduce the scope of the formatter. + // + // It does require the underlying's parse effect to be moved here too. + using _Arg = tuple_element<_Index, decltype(__tuple)>; + formatter, _CharT> __underlying; + + // [format.tuple]/7 + // ... For each element e in underlying_, if e.set_debug_format() + // is a valid expression, calls e.set_debug_format(). + std::__set_debug_format(__underlying); +# else + __ctx.advance_to(std::get<_Index>(__underlying_).format(std::get<_Index>(__tuple), __ctx)); +# endif + }); + + return std::ranges::copy(__closing_bracket_, __ctx.out()).out; + } + + __format_spec::__parser<_CharT> __parser_{.__alignment_ = __format_spec::__alignment::__left}; + +private: + tuple, _CharT>...> __underlying_; + basic_string_view<_CharT> __separator_ = _LIBCPP_STATICALLY_WIDEN(_CharT, ", "); + basic_string_view<_CharT> __opening_bracket_ = _LIBCPP_STATICALLY_WIDEN(_CharT, "("); + basic_string_view<_CharT> __closing_bracket_ = _LIBCPP_STATICALLY_WIDEN(_CharT, ")"); +}; + +template <__fmt_char_type _CharT, formattable<_CharT>... _Args> +struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter, _CharT> + : public __formatter_tuple<_CharT, pair<_Args...>, _Args...> {}; + +template <__fmt_char_type _CharT, formattable<_CharT>... _Args> +struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter, _CharT> + : public __formatter_tuple<_CharT, tuple<_Args...>, _Args...> {}; + +#endif //_LIBCPP_STD_VER > 20 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___FORMAT_FORMATTER_TUPLE_H diff --git a/app/src/main/cpp/libcxx/include/__format/parser_std_format_spec.h b/app/src/main/cpp/libcxx/include/__format/parser_std_format_spec.h new file mode 100644 index 0000000..c03cec9 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__format/parser_std_format_spec.h @@ -0,0 +1,954 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___FORMAT_PARSER_STD_FORMAT_SPEC_H +#define _LIBCPP___FORMAT_PARSER_STD_FORMAT_SPEC_H + +/// \file Contains the std-format-spec parser. +/// +/// Most of the code can be reused in the chrono-format-spec. +/// This header has some support for the chrono-format-spec since it doesn't +/// affect the std-format-spec. + +#include <__algorithm/find_if.h> +#include <__algorithm/min.h> +#include <__assert> +#include <__concepts/arithmetic.h> +#include <__concepts/same_as.h> +#include <__config> +#include <__debug> +#include <__format/format_arg.h> +#include <__format/format_error.h> +#include <__format/format_parse_context.h> +#include <__format/format_string.h> +#include <__format/unicode.h> +#include <__variant/monostate.h> +#include +#include +#include +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 17 + +namespace __format_spec { + +template +_LIBCPP_HIDE_FROM_ABI constexpr __format::__parse_number_result< _CharT> +__parse_arg_id(const _CharT* __begin, const _CharT* __end, auto& __parse_ctx) { + // This function is a wrapper to call the real parser. But it does the + // validation for the pre-conditions and post-conditions. + if (__begin == __end) + std::__throw_format_error("End of input while parsing format-spec arg-id"); + + __format::__parse_number_result __r = __format::__parse_arg_id(__begin, __end, __parse_ctx); + + if (__r.__ptr == __end || *__r.__ptr != _CharT('}')) + std::__throw_format_error("Invalid arg-id"); + + ++__r.__ptr; + return __r; +} + +template +_LIBCPP_HIDE_FROM_ABI constexpr uint32_t +__substitute_arg_id(basic_format_arg<_Context> __format_arg) { + // [format.string.std]/8 + // If the corresponding formatting argument is not of integral type... + // This wording allows char and bool too. LWG-3720 changes the wording to + // If the corresponding formatting argument is not of standard signed or + // unsigned integer type, + // This means the 128-bit will not be valid anymore. + // TODO FMT Verify this resolution is accepted and add a test to verify + // 128-bit integrals fail and switch to visit_format_arg. + return _VSTD::__visit_format_arg( + [](auto __arg) -> uint32_t { + using _Type = decltype(__arg); + if constexpr (integral<_Type>) { + if constexpr (signed_integral<_Type>) { + if (__arg < 0) + std::__throw_format_error("A format-spec arg-id replacement shouldn't have a negative value"); + } + + using _CT = common_type_t<_Type, decltype(__format::__number_max)>; + if (static_cast<_CT>(__arg) > + static_cast<_CT>(__format::__number_max)) + std::__throw_format_error("A format-spec arg-id replacement exceeds the maximum supported value"); + + return __arg; + } else if constexpr (same_as<_Type, monostate>) + std::__throw_format_error("Argument index out of bounds"); + else + std::__throw_format_error("A format-spec arg-id replacement argument isn't an integral type"); + }, + __format_arg); +} + +/// These fields are a filter for which elements to parse. +/// +/// They default to false so when a new field is added it needs to be opted in +/// explicitly. +// TODO FMT Use an ABI tag for this struct. +struct __fields { + uint8_t __sign_ : 1 {false}; + uint8_t __alternate_form_ : 1 {false}; + uint8_t __zero_padding_ : 1 {false}; + uint8_t __precision_ : 1 {false}; + uint8_t __locale_specific_form_ : 1 {false}; + uint8_t __type_ : 1 {false}; + // Determines the valid values for fill. + // + // Originally the fill could be any character except { and }. Range-based + // formatters use the colon to mark the beginning of the + // underlying-format-spec. To avoid parsing ambiguities these formatter + // specializations prohibit the use of the colon as a fill character. + uint8_t __allow_colon_in_fill_ : 1 {false}; +}; + +// By not placing this constant in the formatter class it's not duplicated for +// char and wchar_t. +inline constexpr __fields __fields_integral{ + .__sign_ = true, + .__alternate_form_ = true, + .__zero_padding_ = true, + .__locale_specific_form_ = true, + .__type_ = true}; +inline constexpr __fields __fields_floating_point{ + .__sign_ = true, + .__alternate_form_ = true, + .__zero_padding_ = true, + .__precision_ = true, + .__locale_specific_form_ = true, + .__type_ = true}; +inline constexpr __fields __fields_string{.__precision_ = true, .__type_ = true}; +inline constexpr __fields __fields_pointer{.__type_ = true}; + +# if _LIBCPP_STD_VER > 20 +inline constexpr __fields __fields_tuple{.__type_ = false, .__allow_colon_in_fill_ = true}; +inline constexpr __fields __fields_range{.__type_ = false, .__allow_colon_in_fill_ = true}; +# endif + +enum class _LIBCPP_ENUM_VIS __alignment : uint8_t { + /// No alignment is set in the format string. + __default, + __left, + __center, + __right, + __zero_padding +}; + +enum class _LIBCPP_ENUM_VIS __sign : uint8_t { + /// No sign is set in the format string. + /// + /// The sign isn't allowed for certain format-types. By using this value + /// it's possible to detect whether or not the user explicitly set the sign + /// flag. For formatting purposes it behaves the same as \ref __minus. + __default, + __minus, + __plus, + __space +}; + +enum class _LIBCPP_ENUM_VIS __type : uint8_t { + __default, + __string, + __binary_lower_case, + __binary_upper_case, + __octal, + __decimal, + __hexadecimal_lower_case, + __hexadecimal_upper_case, + __pointer, + __char, + __hexfloat_lower_case, + __hexfloat_upper_case, + __scientific_lower_case, + __scientific_upper_case, + __fixed_lower_case, + __fixed_upper_case, + __general_lower_case, + __general_upper_case, + __debug +}; + +struct __std { + __alignment __alignment_ : 3; + __sign __sign_ : 2; + bool __alternate_form_ : 1; + bool __locale_specific_form_ : 1; + __type __type_; +}; + +struct __chrono { + __alignment __alignment_ : 3; + bool __locale_specific_form_ : 1; + bool __weekday_name_ : 1; + bool __weekday_ : 1; + bool __day_of_year_ : 1; + bool __week_of_year_ : 1; + bool __month_name_ : 1; +}; + +/// Contains the parsed formatting specifications. +/// +/// This contains information for both the std-format-spec and the +/// chrono-format-spec. This results in some unused members for both +/// specifications. However these unused members don't increase the size +/// of the structure. +/// +/// This struct doesn't cross ABI boundaries so its layout doesn't need to be +/// kept stable. +template +struct __parsed_specifications { + union { + // The field __alignment_ is the first element in __std_ and __chrono_. + // This allows the code to always inspect this value regards which member + // of the union is the active member [class.union.general]/2. + // + // This is needed since the generic output routines handle the alignment of + // the output. + __alignment __alignment_ : 3; + __std __std_; + __chrono __chrono_; + }; + + /// The requested width. + /// + /// When the format-spec used an arg-id for this field it has already been + /// replaced with the value of that arg-id. + int32_t __width_; + + /// The requested precision. + /// + /// When the format-spec used an arg-id for this field it has already been + /// replaced with the value of that arg-id. + int32_t __precision_; + + _CharT __fill_; + + _LIBCPP_HIDE_FROM_ABI constexpr bool __has_width() const { return __width_ > 0; } + + _LIBCPP_HIDE_FROM_ABI constexpr bool __has_precision() const { return __precision_ >= 0; } +}; + +// Validate the struct is small and cheap to copy since the struct is passed by +// value in formatting functions. +static_assert(sizeof(__parsed_specifications) == 16); +static_assert(is_trivially_copyable_v<__parsed_specifications>); +# ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +static_assert(sizeof(__parsed_specifications) == 16); +static_assert(is_trivially_copyable_v<__parsed_specifications>); +# endif + +/// The parser for the std-format-spec. +/// +/// Note this class is a member of std::formatter specializations. It's +/// expected developers will create their own formatter specializations that +/// inherit from the std::formatter specializations. This means this class +/// must be ABI stable. To aid the stability the unused bits in the class are +/// set to zero. That way they can be repurposed if a future revision of the +/// Standards adds new fields to std-format-spec. +template +class _LIBCPP_TEMPLATE_VIS __parser { +public: + _LIBCPP_HIDE_FROM_ABI constexpr auto __parse(basic_format_parse_context<_CharT>& __parse_ctx, __fields __fields) + -> decltype(__parse_ctx.begin()) { + + const _CharT* __begin = __parse_ctx.begin(); + const _CharT* __end = __parse_ctx.end(); + if (__begin == __end) + return __begin; + + if (__parse_fill_align(__begin, __end, __fields.__allow_colon_in_fill_) && __begin == __end) + return __begin; + + if (__fields.__sign_ && __parse_sign(__begin) && __begin == __end) + return __begin; + + if (__fields.__alternate_form_ && __parse_alternate_form(__begin) && __begin == __end) + return __begin; + + if (__fields.__zero_padding_ && __parse_zero_padding(__begin) && __begin == __end) + return __begin; + + if (__parse_width(__begin, __end, __parse_ctx) && __begin == __end) + return __begin; + + if (__fields.__precision_ && __parse_precision(__begin, __end, __parse_ctx) && __begin == __end) + return __begin; + + if (__fields.__locale_specific_form_ && __parse_locale_specific_form(__begin) && __begin == __end) + return __begin; + + if (__fields.__type_) { + __parse_type(__begin); + + // When __type_ is false the calling parser is expected to do additional + // parsing. In that case that parser should do the end of format string + // validation. + if (__begin != __end && *__begin != _CharT('}')) + std::__throw_format_error("The format-spec should consume the input or end with a '}'"); + } + + return __begin; + } + + /// \returns the `__parsed_specifications` with the resolved dynamic sizes.. + _LIBCPP_HIDE_FROM_ABI + __parsed_specifications<_CharT> __get_parsed_std_specifications(auto& __ctx) const { + return __parsed_specifications<_CharT>{ + .__std_ = __std{.__alignment_ = __alignment_, + .__sign_ = __sign_, + .__alternate_form_ = __alternate_form_, + .__locale_specific_form_ = __locale_specific_form_, + .__type_ = __type_}, + .__width_{__get_width(__ctx)}, + .__precision_{__get_precision(__ctx)}, + .__fill_{__fill_}}; + } + + _LIBCPP_HIDE_FROM_ABI __parsed_specifications<_CharT> __get_parsed_chrono_specifications(auto& __ctx) const { + return __parsed_specifications<_CharT>{ + .__chrono_ = + __chrono{.__alignment_ = __alignment_, + .__locale_specific_form_ = __locale_specific_form_, + .__weekday_name_ = __weekday_name_, + .__weekday_ = __weekday_, + .__day_of_year_ = __day_of_year_, + .__week_of_year_ = __week_of_year_, + .__month_name_ = __month_name_}, + .__width_{__get_width(__ctx)}, + .__precision_{__get_precision(__ctx)}, + .__fill_{__fill_}}; + } + + __alignment __alignment_ : 3 {__alignment::__default}; + __sign __sign_ : 2 {__sign::__default}; + bool __alternate_form_ : 1 {false}; + bool __locale_specific_form_ : 1 {false}; + bool __reserved_0_ : 1 {false}; + __type __type_{__type::__default}; + + // These flags are only used for formatting chrono. Since the struct has + // padding space left it's added to this structure. + bool __weekday_name_ : 1 {false}; + bool __weekday_ : 1 {false}; + + bool __day_of_year_ : 1 {false}; + bool __week_of_year_ : 1 {false}; + + bool __month_name_ : 1 {false}; + + uint8_t __reserved_1_ : 3 {0}; + uint8_t __reserved_2_ : 6 {0}; + // These two flags are only used internally and not part of the + // __parsed_specifications. Therefore put them at the end. + bool __width_as_arg_ : 1 {false}; + bool __precision_as_arg_ : 1 {false}; + + /// The requested width, either the value or the arg-id. + int32_t __width_{0}; + + /// The requested precision, either the value or the arg-id. + int32_t __precision_{-1}; + + // LWG 3576 will probably change this to always accept a Unicode code point + // To avoid changing the size with that change align the field so when it + // becomes 32-bit its alignment will remain the same. That also means the + // size will remain the same. (D2572 addresses the solution for LWG 3576.) + _CharT __fill_{_CharT(' ')}; + +private: + _LIBCPP_HIDE_FROM_ABI constexpr bool __parse_alignment(_CharT __c) { + switch (__c) { + case _CharT('<'): + __alignment_ = __alignment::__left; + return true; + + case _CharT('^'): + __alignment_ = __alignment::__center; + return true; + + case _CharT('>'): + __alignment_ = __alignment::__right; + return true; + } + return false; + } + + // range-fill and tuple-fill are identical + _LIBCPP_HIDE_FROM_ABI constexpr bool + __parse_fill_align(const _CharT*& __begin, const _CharT* __end, bool __use_range_fill) { + _LIBCPP_ASSERT(__begin != __end, "when called with an empty input the function will cause " + "undefined behavior by evaluating data not in the input"); + if (__begin + 1 != __end) { + if (__parse_alignment(*(__begin + 1))) { + if (__use_range_fill && (*__begin == _CharT('{') || *__begin == _CharT('}') || *__begin == _CharT(':'))) + std::__throw_format_error("The format-spec range-fill field contains an invalid character"); + else if (*__begin == _CharT('{') || *__begin == _CharT('}')) + std::__throw_format_error("The format-spec fill field contains an invalid character"); + + __fill_ = *__begin; + __begin += 2; + return true; + } + } + + if (!__parse_alignment(*__begin)) + return false; + + ++__begin; + return true; + } + + _LIBCPP_HIDE_FROM_ABI constexpr bool __parse_sign(const _CharT*& __begin) { + switch (*__begin) { + case _CharT('-'): + __sign_ = __sign::__minus; + break; + case _CharT('+'): + __sign_ = __sign::__plus; + break; + case _CharT(' '): + __sign_ = __sign::__space; + break; + default: + return false; + } + ++__begin; + return true; + } + + _LIBCPP_HIDE_FROM_ABI constexpr bool __parse_alternate_form(const _CharT*& __begin) { + if (*__begin != _CharT('#')) + return false; + + __alternate_form_ = true; + ++__begin; + return true; + } + + _LIBCPP_HIDE_FROM_ABI constexpr bool __parse_zero_padding(const _CharT*& __begin) { + if (*__begin != _CharT('0')) + return false; + + if (__alignment_ == __alignment::__default) + __alignment_ = __alignment::__zero_padding; + ++__begin; + return true; + } + + _LIBCPP_HIDE_FROM_ABI constexpr bool __parse_width(const _CharT*& __begin, const _CharT* __end, auto& __parse_ctx) { + if (*__begin == _CharT('0')) + std::__throw_format_error("A format-spec width field shouldn't have a leading zero"); + + if (*__begin == _CharT('{')) { + __format::__parse_number_result __r = __format_spec::__parse_arg_id(++__begin, __end, __parse_ctx); + __width_as_arg_ = true; + __width_ = __r.__value; + __begin = __r.__ptr; + return true; + } + + if (*__begin < _CharT('0') || *__begin > _CharT('9')) + return false; + + __format::__parse_number_result __r = __format::__parse_number(__begin, __end); + __width_ = __r.__value; + _LIBCPP_ASSERT(__width_ != 0, "A zero value isn't allowed and should be impossible, " + "due to validations in this function"); + __begin = __r.__ptr; + return true; + } + + _LIBCPP_HIDE_FROM_ABI constexpr bool __parse_precision(const _CharT*& __begin, const _CharT* __end, + auto& __parse_ctx) { + if (*__begin != _CharT('.')) + return false; + + ++__begin; + if (__begin == __end) + std::__throw_format_error("End of input while parsing format-spec precision"); + + if (*__begin == _CharT('{')) { + __format::__parse_number_result __arg_id = __format_spec::__parse_arg_id(++__begin, __end, __parse_ctx); + __precision_as_arg_ = true; + __precision_ = __arg_id.__value; + __begin = __arg_id.__ptr; + return true; + } + + if (*__begin < _CharT('0') || *__begin > _CharT('9')) + std::__throw_format_error("The format-spec precision field doesn't contain a value or arg-id"); + + __format::__parse_number_result __r = __format::__parse_number(__begin, __end); + __precision_ = __r.__value; + __precision_as_arg_ = false; + __begin = __r.__ptr; + return true; + } + + _LIBCPP_HIDE_FROM_ABI constexpr bool __parse_locale_specific_form(const _CharT*& __begin) { + if (*__begin != _CharT('L')) + return false; + + __locale_specific_form_ = true; + ++__begin; + return true; + } + + _LIBCPP_HIDE_FROM_ABI constexpr void __parse_type(const _CharT*& __begin) { + // Determines the type. It does not validate whether the selected type is + // valid. Most formatters have optional fields that are only allowed for + // certain types. These parsers need to do validation after the type has + // been parsed. So its easier to implement the validation for all types in + // the specific parse function. + switch (*__begin) { + case 'A': + __type_ = __type::__hexfloat_upper_case; + break; + case 'B': + __type_ = __type::__binary_upper_case; + break; + case 'E': + __type_ = __type::__scientific_upper_case; + break; + case 'F': + __type_ = __type::__fixed_upper_case; + break; + case 'G': + __type_ = __type::__general_upper_case; + break; + case 'X': + __type_ = __type::__hexadecimal_upper_case; + break; + case 'a': + __type_ = __type::__hexfloat_lower_case; + break; + case 'b': + __type_ = __type::__binary_lower_case; + break; + case 'c': + __type_ = __type::__char; + break; + case 'd': + __type_ = __type::__decimal; + break; + case 'e': + __type_ = __type::__scientific_lower_case; + break; + case 'f': + __type_ = __type::__fixed_lower_case; + break; + case 'g': + __type_ = __type::__general_lower_case; + break; + case 'o': + __type_ = __type::__octal; + break; + case 'p': + __type_ = __type::__pointer; + break; + case 's': + __type_ = __type::__string; + break; + case 'x': + __type_ = __type::__hexadecimal_lower_case; + break; +# if _LIBCPP_STD_VER > 20 + case '?': + __type_ = __type::__debug; + break; +# endif + default: + return; + } + ++__begin; + } + + _LIBCPP_HIDE_FROM_ABI + int32_t __get_width(auto& __ctx) const { + if (!__width_as_arg_) + return __width_; + + return __format_spec::__substitute_arg_id(__ctx.arg(__width_)); + } + + _LIBCPP_HIDE_FROM_ABI + int32_t __get_precision(auto& __ctx) const { + if (!__precision_as_arg_) + return __precision_; + + return __format_spec::__substitute_arg_id(__ctx.arg(__precision_)); + } +}; + +// Validates whether the reserved bitfields don't change the size. +static_assert(sizeof(__parser) == 16); +# ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +static_assert(sizeof(__parser) == 16); +# endif + +_LIBCPP_HIDE_FROM_ABI constexpr void __process_display_type_string(__format_spec::__type __type) { + switch (__type) { + case __format_spec::__type::__default: + case __format_spec::__type::__string: + case __format_spec::__type::__debug: + break; + + default: + std::__throw_format_error("The format-spec type has a type not supported for a string argument"); + } +} + +template +_LIBCPP_HIDE_FROM_ABI constexpr void __process_display_type_bool_string(__parser<_CharT>& __parser) { + if (__parser.__sign_ != __sign::__default) + std::__throw_format_error("A sign field isn't allowed in this format-spec"); + + if (__parser.__alternate_form_) + std::__throw_format_error("An alternate form field isn't allowed in this format-spec"); + + if (__parser.__alignment_ == __alignment::__zero_padding) + std::__throw_format_error("A zero-padding field isn't allowed in this format-spec"); + + if (__parser.__alignment_ == __alignment::__default) + __parser.__alignment_ = __alignment::__left; +} + +template +_LIBCPP_HIDE_FROM_ABI constexpr void __process_display_type_char(__parser<_CharT>& __parser) { + __format_spec::__process_display_type_bool_string(__parser); +} + +template +_LIBCPP_HIDE_FROM_ABI constexpr void __process_parsed_bool(__parser<_CharT>& __parser) { + switch (__parser.__type_) { + case __format_spec::__type::__default: + case __format_spec::__type::__string: + __format_spec::__process_display_type_bool_string(__parser); + break; + + case __format_spec::__type::__binary_lower_case: + case __format_spec::__type::__binary_upper_case: + case __format_spec::__type::__octal: + case __format_spec::__type::__decimal: + case __format_spec::__type::__hexadecimal_lower_case: + case __format_spec::__type::__hexadecimal_upper_case: + break; + + default: + std::__throw_format_error("The format-spec type has a type not supported for a bool argument"); + } +} + +template +_LIBCPP_HIDE_FROM_ABI constexpr void __process_parsed_char(__parser<_CharT>& __parser) { + switch (__parser.__type_) { + case __format_spec::__type::__default: + case __format_spec::__type::__char: + case __format_spec::__type::__debug: + __format_spec::__process_display_type_char(__parser); + break; + + case __format_spec::__type::__binary_lower_case: + case __format_spec::__type::__binary_upper_case: + case __format_spec::__type::__octal: + case __format_spec::__type::__decimal: + case __format_spec::__type::__hexadecimal_lower_case: + case __format_spec::__type::__hexadecimal_upper_case: + break; + + default: + std::__throw_format_error("The format-spec type has a type not supported for a char argument"); + } +} + +template +_LIBCPP_HIDE_FROM_ABI constexpr void __process_parsed_integer(__parser<_CharT>& __parser) { + switch (__parser.__type_) { + case __format_spec::__type::__default: + case __format_spec::__type::__binary_lower_case: + case __format_spec::__type::__binary_upper_case: + case __format_spec::__type::__octal: + case __format_spec::__type::__decimal: + case __format_spec::__type::__hexadecimal_lower_case: + case __format_spec::__type::__hexadecimal_upper_case: + break; + + case __format_spec::__type::__char: + __format_spec::__process_display_type_char(__parser); + break; + + default: + std::__throw_format_error("The format-spec type has a type not supported for an integer argument"); + } +} + +template +_LIBCPP_HIDE_FROM_ABI constexpr void __process_parsed_floating_point(__parser<_CharT>& __parser) { + switch (__parser.__type_) { + case __format_spec::__type::__default: + case __format_spec::__type::__hexfloat_lower_case: + case __format_spec::__type::__hexfloat_upper_case: + // Precision specific behavior will be handled later. + break; + case __format_spec::__type::__scientific_lower_case: + case __format_spec::__type::__scientific_upper_case: + case __format_spec::__type::__fixed_lower_case: + case __format_spec::__type::__fixed_upper_case: + case __format_spec::__type::__general_lower_case: + case __format_spec::__type::__general_upper_case: + if (!__parser.__precision_as_arg_ && __parser.__precision_ == -1) + // Set the default precision for the call to to_chars. + __parser.__precision_ = 6; + break; + + default: + std::__throw_format_error("The format-spec type has a type not supported for a floating-point argument"); + } +} + +_LIBCPP_HIDE_FROM_ABI constexpr void __process_display_type_pointer(__format_spec::__type __type) { + switch (__type) { + case __format_spec::__type::__default: + case __format_spec::__type::__pointer: + break; + + default: + std::__throw_format_error("The format-spec type has a type not supported for a pointer argument"); + } +} + +template +struct __column_width_result { + /// The number of output columns. + size_t __width_; + /// One beyond the last code unit used in the estimation. + /// + /// This limits the original output to fit in the wanted number of columns. + const _CharT* __last_; +}; + +template +__column_width_result(size_t, const _CharT*) -> __column_width_result<_CharT>; + +/// Since a column width can be two it's possible that the requested column +/// width can't be achieved. Depending on the intended usage the policy can be +/// selected. +/// - When used as precision the maximum width may not be exceeded and the +/// result should be "rounded down" to the previous boundary. +/// - When used as a width we're done once the minimum is reached, but +/// exceeding is not an issue. Rounding down is an issue since that will +/// result in writing fill characters. Therefore the result needs to be +/// "rounded up". +enum class __column_width_rounding { __down, __up }; + +# ifndef _LIBCPP_HAS_NO_UNICODE + +namespace __detail { + +/// Converts a code point to the column width. +/// +/// The estimations are conforming to [format.string.general]/11 +/// +/// This version expects a value less than 0x1'0000, which is a 3-byte UTF-8 +/// character. +_LIBCPP_HIDE_FROM_ABI constexpr int __column_width_3(uint32_t __c) noexcept { + _LIBCPP_ASSERT(__c < 0x10000, "Use __column_width_4 or __column_width for larger values"); + + // clang-format off + return 1 + (__c >= 0x1100 && (__c <= 0x115f || + (__c >= 0x2329 && (__c <= 0x232a || + (__c >= 0x2e80 && (__c <= 0x303e || + (__c >= 0x3040 && (__c <= 0xa4cf || + (__c >= 0xac00 && (__c <= 0xd7a3 || + (__c >= 0xf900 && (__c <= 0xfaff || + (__c >= 0xfe10 && (__c <= 0xfe19 || + (__c >= 0xfe30 && (__c <= 0xfe6f || + (__c >= 0xff00 && (__c <= 0xff60 || + (__c >= 0xffe0 && (__c <= 0xffe6 + )))))))))))))))))))); + // clang-format on +} + +/// @overload +/// +/// This version expects a value greater than or equal to 0x1'0000, which is a +/// 4-byte UTF-8 character. +_LIBCPP_HIDE_FROM_ABI constexpr int __column_width_4(uint32_t __c) noexcept { + _LIBCPP_ASSERT(__c >= 0x10000, "Use __column_width_3 or __column_width for smaller values"); + + // clang-format off + return 1 + (__c >= 0x1'f300 && (__c <= 0x1'f64f || + (__c >= 0x1'f900 && (__c <= 0x1'f9ff || + (__c >= 0x2'0000 && (__c <= 0x2'fffd || + (__c >= 0x3'0000 && (__c <= 0x3'fffd + )))))))); + // clang-format on +} + +/// @overload +/// +/// The general case, accepting all values. +_LIBCPP_HIDE_FROM_ABI constexpr int __column_width(uint32_t __c) noexcept { + if (__c < 0x10000) + return __detail::__column_width_3(__c); + + return __detail::__column_width_4(__c); +} + +template +_LIBCPP_HIDE_FROM_ABI constexpr __column_width_result<_CharT> __estimate_column_width_grapheme_clustering( + const _CharT* __first, const _CharT* __last, size_t __maximum, __column_width_rounding __rounding) noexcept { + __unicode::__extended_grapheme_cluster_view<_CharT> __view{__first, __last}; + + __column_width_result<_CharT> __result{0, __first}; + while (__result.__last_ != __last && __result.__width_ <= __maximum) { + typename __unicode::__extended_grapheme_cluster_view<_CharT>::__cluster __cluster = __view.__consume(); + int __width = __detail::__column_width(__cluster.__code_point_); + + // When the next entry would exceed the maximum width the previous width + // might be returned. For example when a width of 100 is requested the + // returned width might be 99, since the next code point has an estimated + // column width of 2. This depends on the rounding flag. + // When the maximum is exceeded the loop will abort the next iteration. + if (__rounding == __column_width_rounding::__down && __result.__width_ + __width > __maximum) + return __result; + + __result.__width_ += __width; + __result.__last_ = __cluster.__last_; + } + + return __result; +} + +} // namespace __detail + +// Unicode can be stored in several formats: UTF-8, UTF-16, and UTF-32. +// Depending on format the relation between the number of code units stored and +// the number of output columns differs. The first relation is the number of +// code units forming a code point. (The text assumes the code units are +// unsigned.) +// - UTF-8 The number of code units is between one and four. The first 127 +// Unicode code points match the ASCII character set. When the highest bit is +// set it means the code point has more than one code unit. +// - UTF-16: The number of code units is between 1 and 2. When the first +// code unit is in the range [0xd800,0xdfff) it means the code point uses two +// code units. +// - UTF-32: The number of code units is always one. +// +// The code point to the number of columns is specified in +// [format.string.std]/11. This list might change in the future. +// +// Another thing to be taken into account is Grapheme clustering. This means +// that in some cases multiple code points are combined one element in the +// output. For example: +// - an ASCII character with a combined diacritical mark +// - an emoji with a skin tone modifier +// - a group of combined people emoji to create a family +// - a combination of flag emoji +// +// See also: +// - [format.string.general]/11 +// - https://en.wikipedia.org/wiki/UTF-8#Encoding +// - https://en.wikipedia.org/wiki/UTF-16#U+D800_to_U+DFFF + +_LIBCPP_HIDE_FROM_ABI constexpr bool __is_ascii(char32_t __c) { return __c < 0x80; } + +/// Determines the number of output columns needed to render the input. +/// +/// \note When the scanner encounters malformed Unicode it acts as-if every +/// code unit is a one column code point. Typically a terminal uses the same +/// strategy and replaces every malformed code unit with a one column +/// replacement character. +/// +/// \param __first Points to the first element of the input range. +/// \param __last Points beyond the last element of the input range. +/// \param __maximum The maximum number of output columns. The returned number +/// of estimated output columns will not exceed this value. +/// \param __rounding Selects the rounding method. +/// \c __down result.__width_ <= __maximum +/// \c __up result.__width_ <= __maximum + 1 +template +_LIBCPP_HIDE_FROM_ABI constexpr __column_width_result<_CharT> __estimate_column_width( + basic_string_view<_CharT> __str, size_t __maximum, __column_width_rounding __rounding) noexcept { + // The width estimation is done in two steps: + // - Quickly process for the ASCII part. ASCII has the following properties + // - One code unit is one code point + // - Every code point has an estimated width of one + // - When needed it will a Unicode Grapheme clustering algorithm to find + // the proper place for truncation. + + if (__str.empty() || __maximum == 0) + return {0, __str.begin()}; + + // ASCII has one caveat; when an ASCII character is followed by a non-ASCII + // character they might be part of an extended grapheme cluster. For example: + // an ASCII letter and a COMBINING ACUTE ACCENT + // The truncate should happen after the COMBINING ACUTE ACCENT. Therefore we + // need to scan one code unit beyond the requested precision. When this code + // unit is non-ASCII we omit the current code unit and let the Grapheme + // clustering algorithm do its work. + const _CharT* __it = __str.begin(); + if (__format_spec::__is_ascii(*__it)) { + do { + --__maximum; + ++__it; + if (__it == __str.end()) + return {__str.size(), __str.end()}; + + if (__maximum == 0) { + if (__format_spec::__is_ascii(*__it)) + return {static_cast(__it - __str.begin()), __it}; + + break; + } + } while (__format_spec::__is_ascii(*__it)); + --__it; + ++__maximum; + } + + ptrdiff_t __ascii_size = __it - __str.begin(); + __column_width_result __result = + __detail::__estimate_column_width_grapheme_clustering(__it, __str.end(), __maximum, __rounding); + + __result.__width_ += __ascii_size; + return __result; +} +# else // !defined(_LIBCPP_HAS_NO_UNICODE) +template +_LIBCPP_HIDE_FROM_ABI constexpr __column_width_result<_CharT> +__estimate_column_width(basic_string_view<_CharT> __str, size_t __maximum, __column_width_rounding) noexcept { + // When Unicode isn't supported assume ASCII and every code unit is one code + // point. In ASCII the estimated column width is always one. Thus there's no + // need for rounding. + size_t __width_ = _VSTD::min(__str.size(), __maximum); + return {__width_, __str.begin() + __width_}; +} + +# endif // !defined(_LIBCPP_HAS_NO_UNICODE) + +} // namespace __format_spec + +#endif //_LIBCPP_STD_VER > 17 + +_LIBCPP_END_NAMESPACE_STD + +_LIBCPP_POP_MACROS + +#endif // _LIBCPP___FORMAT_PARSER_STD_FORMAT_SPEC_H diff --git a/app/src/main/cpp/libcxx/include/__format/range_default_formatter.h b/app/src/main/cpp/libcxx/include/__format/range_default_formatter.h new file mode 100644 index 0000000..774887b --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__format/range_default_formatter.h @@ -0,0 +1,201 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___FORMAT_RANGE_DEFAULT_FORMATTER_H +#define _LIBCPP___FORMAT_RANGE_DEFAULT_FORMATTER_H + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#include <__availability> +#include <__chrono/statically_widen.h> +#include <__concepts/same_as.h> +#include <__config> +#include <__format/concepts.h> +#include <__format/formatter.h> +#include <__format/range_formatter.h> +#include <__ranges/concepts.h> +#include <__type_traits/remove_cvref.h> +#include <__utility/pair.h> +#include +#include + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 20 + +template +concept __const_formattable_range = + ranges::input_range && formattable, _CharT>; + +template +using __fmt_maybe_const = conditional_t<__const_formattable_range<_Rp, _CharT>, const _Rp, _Rp>; + +_LIBCPP_DIAGNOSTIC_PUSH +_LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wshadow") +_LIBCPP_GCC_DIAGNOSTIC_IGNORED("-Wshadow") +// This shadows map, set, and string. +enum class range_format { disabled, map, set, sequence, string, debug_string }; +_LIBCPP_DIAGNOSTIC_POP + +// There is no definition of this struct, it's purely intended to be used to +// generate diagnostics. +template +struct _LIBCPP_TEMPLATE_VIS __instantiated_the_primary_template_of_format_kind; + +template +constexpr range_format format_kind = [] { + // [format.range.fmtkind]/1 + // A program that instantiates the primary template of format_kind is ill-formed. + static_assert(sizeof(_Rp) != sizeof(_Rp), "create a template specialization of format_kind for your type"); + return range_format::disabled; +}(); + +template + requires same_as<_Rp, remove_cvref_t<_Rp>> +inline constexpr range_format format_kind<_Rp> = [] { + // [format.range.fmtkind]/2 + + // 2.1 If same_as>, R> is true, + // Otherwise format_kind is range_format::disabled. + if constexpr (same_as>, _Rp>) + return range_format::disabled; + // 2.2 Otherwise, if the qualified-id R::key_type is valid and denotes a type: + else if constexpr (requires { typename _Rp::key_type; }) { + // 2.2.1 If the qualified-id R::mapped_type is valid and denotes a type ... + if constexpr (requires { typename _Rp::mapped_type; } && + // 2.2.1 ... If either U is a specialization of pair or U is a specialization + // of tuple and tuple_size_v == 2 + __fmt_pair_like>>) + return range_format::map; + else + // 2.2.2 Otherwise format_kind is range_format::set. + return range_format::set; + } else + // 2.3 Otherwise, format_kind is range_format::sequence. + return range_format::sequence; +}(); + +// This is a non-standard work-around to fix instantiation of +// formatter +// const _CharT[N] satisfies the ranges::input_range concept. +// remove_cvref_t is _CharT[N] so it does not satisfy the +// requirement of the above specialization. Instead it will instantiate the +// primary template, which is ill-formed. +// +// An alternative solution is to remove the offending formatter. +// +// https://godbolt.org/z/bqjhhaexx +// +// The removal is proposed in LWG3833, but use the work-around until the issue +// has been adopted. +// TODO FMT Implement LWG3833. +template +inline constexpr range_format format_kind = range_format::disabled; + +template +struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT __range_default_formatter; + +// Required specializations + +template +struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT __range_default_formatter { +private: + using __maybe_const_r = __fmt_maybe_const<_Rp, _CharT>; + range_formatter>, _CharT> __underlying_; + +public: + _LIBCPP_HIDE_FROM_ABI constexpr void set_separator(basic_string_view<_CharT> __separator) { + __underlying_.set_separator(__separator); + } + _LIBCPP_HIDE_FROM_ABI constexpr void + set_brackets(basic_string_view<_CharT> __opening_bracket, basic_string_view<_CharT> __closing_bracket) { + __underlying_.set_brackets(__opening_bracket, __closing_bracket); + } + + template + _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator parse(_ParseContext& __ctx) { + return __underlying_.parse(__ctx); + } + + template + _LIBCPP_HIDE_FROM_ABI typename FormatContext::iterator format(__maybe_const_r& __range, FormatContext& __ctx) const { + return __underlying_.format(__range, __ctx); + } +}; + +template +struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT __range_default_formatter { +private: + using __maybe_const_map = __fmt_maybe_const<_Rp, _CharT>; + using __element_type = remove_cvref_t>; + range_formatter<__element_type, _CharT> __underlying_; + +public: + _LIBCPP_HIDE_FROM_ABI constexpr __range_default_formatter() + requires(__fmt_pair_like<__element_type>) + { + __underlying_.set_brackets(_LIBCPP_STATICALLY_WIDEN(_CharT, "{"), _LIBCPP_STATICALLY_WIDEN(_CharT, "}")); + __underlying_.underlying().set_brackets({}, {}); + __underlying_.underlying().set_separator(_LIBCPP_STATICALLY_WIDEN(_CharT, ": ")); + } + + template + _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator parse(_ParseContext& __ctx) { + return __underlying_.parse(__ctx); + } + + template + _LIBCPP_HIDE_FROM_ABI typename _FormatContext::iterator + format(__maybe_const_map& __range, _FormatContext& __ctx) const { + return __underlying_.format(__range, __ctx); + } +}; + +template +struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT __range_default_formatter { +private: + using __maybe_const_set = __fmt_maybe_const<_Rp, _CharT>; + using __element_type = remove_cvref_t>; + range_formatter<__element_type, _CharT> __underlying_; + +public: + _LIBCPP_HIDE_FROM_ABI constexpr __range_default_formatter() { + __underlying_.set_brackets(_LIBCPP_STATICALLY_WIDEN(_CharT, "{"), _LIBCPP_STATICALLY_WIDEN(_CharT, "}")); + } + + template + _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator parse(_ParseContext& __ctx) { + return __underlying_.parse(__ctx); + } + + template + _LIBCPP_HIDE_FROM_ABI typename _FormatContext::iterator + format(__maybe_const_set& __range, _FormatContext& __ctx) const { + return __underlying_.format(__range, __ctx); + } +}; + +template + requires(_Kp == range_format::string || _Kp == range_format::debug_string) +struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT __range_default_formatter<_Kp, _Rp, _CharT> { + __range_default_formatter() = delete; // TODO FMT Implement +}; + +template + requires(format_kind<_Rp> != range_format::disabled && formattable, _CharT>) +struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<_Rp, _CharT> + : __range_default_formatter, _Rp, _CharT> {}; + +#endif //_LIBCPP_STD_VER > 20 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___FORMAT_RANGE_DEFAULT_FORMATTER_H diff --git a/app/src/main/cpp/libcxx/include/__format/range_formatter.h b/app/src/main/cpp/libcxx/include/__format/range_formatter.h new file mode 100644 index 0000000..9ea61a7 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__format/range_formatter.h @@ -0,0 +1,255 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___FORMAT_RANGE_FORMATTER_H +#define _LIBCPP___FORMAT_RANGE_FORMATTER_H + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#include <__algorithm/ranges_copy.h> +#include <__availability> +#include <__chrono/statically_widen.h> +#include <__concepts/same_as.h> +#include <__config> +#include <__format/buffer.h> +#include <__format/concepts.h> +#include <__format/format_args.h> +#include <__format/format_context.h> +#include <__format/format_error.h> +#include <__format/formatter.h> +#include <__format/formatter_output.h> +#include <__format/parser_std_format_spec.h> +#include <__iterator/back_insert_iterator.h> +#include <__ranges/concepts.h> +#include <__ranges/data.h> +#include <__ranges/size.h> +#include <__type_traits/remove_cvref.h> +#include + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 20 + +template + requires same_as, _Tp> && formattable<_Tp, _CharT> +struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT range_formatter { + _LIBCPP_HIDE_FROM_ABI constexpr void set_separator(basic_string_view<_CharT> __separator) { + __separator_ = __separator; + } + _LIBCPP_HIDE_FROM_ABI constexpr void + set_brackets(basic_string_view<_CharT> __opening_bracket, basic_string_view<_CharT> __closing_bracket) { + __opening_bracket_ = __opening_bracket; + __closing_bracket_ = __closing_bracket; + } + + _LIBCPP_HIDE_FROM_ABI constexpr formatter<_Tp, _CharT>& underlying() { return __underlying_; } + _LIBCPP_HIDE_FROM_ABI constexpr const formatter<_Tp, _CharT>& underlying() const { return __underlying_; } + + template + _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator parse(_ParseContext& __parse_ctx) { + const _CharT* __begin = __parser_.__parse(__parse_ctx, __format_spec::__fields_range); + const _CharT* __end = __parse_ctx.end(); + if (__begin == __end) + return __begin; + + // The n field overrides a possible m type, therefore delay applying the + // effect of n until the type has been procesed. + bool __clear_brackets = (*__begin == _CharT('n')); + if (__clear_brackets) { + ++__begin; + if (__begin == __end) { + // Since there is no more data, clear the brackets before returning. + set_brackets({}, {}); + return __begin; + } + } + + __parse_type(__begin, __end); + if (__clear_brackets) + set_brackets({}, {}); + if (__begin == __end) + return __begin; + + bool __has_range_underlying_spec = *__begin == _CharT(':'); + if (__parser_.__type_ != __format_spec::__type::__default) { + // [format.range.formatter]/6 + // If the range-type is s or ?s, then there shall be no n option and no + // range-underlying-spec. + if (__clear_brackets) { + if (__parser_.__type_ == __format_spec::__type::__string) + std::__throw_format_error("The n option and type s can't be used together"); + std::__throw_format_error("The n option and type ?s can't be used together"); + } + if (__has_range_underlying_spec) { + if (__parser_.__type_ == __format_spec::__type::__string) + std::__throw_format_error("Type s and an underlying format specification can't be used together"); + std::__throw_format_error("Type ?s and an underlying format specification can't be used together"); + } + } else if (!__has_range_underlying_spec) + std::__set_debug_format(__underlying_); + + if (__has_range_underlying_spec) { + // range-underlying-spec: + // : format-spec + ++__begin; + if (__begin == __end) + return __begin; + + __parse_ctx.advance_to(__begin); + __begin = __underlying_.parse(__parse_ctx); + } + + if (__begin != __end && *__begin != _CharT('}')) + std::__throw_format_error("The format-spec should consume the input or end with a '}'"); + + return __begin; + } + + template + requires formattable, _CharT> && + same_as>, _Tp> + _LIBCPP_HIDE_FROM_ABI typename _FormatContext::iterator format(_Rp&& __range, _FormatContext& __ctx) const { + __format_spec::__parsed_specifications<_CharT> __specs = __parser_.__get_parsed_std_specifications(__ctx); + + if (!__specs.__has_width()) + return __format_range(__range, __ctx, __specs); + + // The size of the buffer needed is: + // - open bracket characters + // - close bracket character + // - n elements where every element may have a different size + // - (n -1) separators + // The size of the element is hard to predict, knowing the type helps but + // it depends on the format-spec. As an initial estimate we guess 6 + // characters. + // Typically both brackets are 1 character and the separator is 2 + // characters. Which means there will be + // (n - 1) * 2 + 1 + 1 = n * 2 character + // So estimate 8 times the range size as buffer. + std::size_t __capacity_hint = 0; + if constexpr (std::ranges::sized_range<_Rp>) + __capacity_hint = 8 * ranges::size(__range); + __format::__retarget_buffer<_CharT> __buffer{__capacity_hint}; + basic_format_context::__iterator, _CharT> __c{ + __buffer.__make_output_iterator(), __ctx}; + + __format_range(__range, __c, __specs); + + return __formatter::__write_string_no_precision(__buffer.__view(), __ctx.out(), __specs); + } + + template + typename _FormatContext::iterator _LIBCPP_HIDE_FROM_ABI + __format_range(_Rp&& __range, _FormatContext& __ctx, __format_spec::__parsed_specifications<_CharT> __specs) const { + if constexpr (same_as<_Tp, _CharT>) { + switch (__specs.__std_.__type_) { + case __format_spec::__type::__string: + case __format_spec::__type::__debug: + return __format_as_string(__range, __ctx, __specs.__std_.__type_ == __format_spec::__type::__debug); + default: + return __format_as_sequence(__range, __ctx); + } + } else + return __format_as_sequence(__range, __ctx); + } + + template + _LIBCPP_HIDE_FROM_ABI typename _FormatContext::iterator + __format_as_string(_Rp&& __range, _FormatContext& __ctx, bool __debug_format) const { + // When the range is contiguous use a basic_string_view instead to avoid a + // copy of the underlying data. The basic_string_view formatter + // specialization is the "basic" string formatter in libc++. + if constexpr (ranges::contiguous_range<_Rp> && std::ranges::sized_range<_Rp>) { + std::formatter, _CharT> __formatter; + if (__debug_format) + __formatter.set_debug_format(); + return __formatter.format( + basic_string_view<_CharT>{ + ranges::data(__range), + ranges::size(__range), + }, + __ctx); + } else { + std::formatter, _CharT> __formatter; + if (__debug_format) + __formatter.set_debug_format(); + // P2106's from_range has not been implemented yet. Instead use a simple + // copy operation. + // TODO FMT use basic_string's "from_range" constructor. + // return std::formatter, _CharT>{}.format(basic_string<_CharT>{from_range, __range}, __ctx); + basic_string<_CharT> __str; + ranges::copy(__range, back_insert_iterator{__str}); + return __formatter.format(__str, __ctx); + } + } + + template + _LIBCPP_HIDE_FROM_ABI typename _FormatContext::iterator + __format_as_sequence(_Rp&& __range, _FormatContext& __ctx) const { + __ctx.advance_to(ranges::copy(__opening_bracket_, __ctx.out()).out); + bool __use_separator = false; + for (auto&& __e : __range) { + if (__use_separator) + __ctx.advance_to(ranges::copy(__separator_, __ctx.out()).out); + else + __use_separator = true; + + __ctx.advance_to(__underlying_.format(__e, __ctx)); + } + + return ranges::copy(__closing_bracket_, __ctx.out()).out; + } + + __format_spec::__parser<_CharT> __parser_{.__alignment_ = __format_spec::__alignment::__left}; + +private: + _LIBCPP_HIDE_FROM_ABI constexpr void __parse_type(const _CharT*& __begin, const _CharT* __end) { + switch (*__begin) { + case _CharT('m'): + if constexpr (__fmt_pair_like<_Tp>) { + set_brackets(_LIBCPP_STATICALLY_WIDEN(_CharT, "{"), _LIBCPP_STATICALLY_WIDEN(_CharT, "}")); + set_separator(_LIBCPP_STATICALLY_WIDEN(_CharT, ", ")); + ++__begin; + } else + std::__throw_format_error("The range-format-spec type m requires two elements for a pair or tuple"); + break; + + case _CharT('s'): + if constexpr (same_as<_Tp, _CharT>) { + __parser_.__type_ = __format_spec::__type::__string; + ++__begin; + } else + std::__throw_format_error("The range-format-spec type s requires formatting a character type"); + break; + + case _CharT('?'): + ++__begin; + if (__begin == __end || *__begin != _CharT('s')) + std::__throw_format_error("The format-spec should consume the input or end with a '}'"); + if constexpr (same_as<_Tp, _CharT>) { + __parser_.__type_ = __format_spec::__type::__debug; + ++__begin; + } else + std::__throw_format_error("The range-format-spec type ?s requires formatting a character type"); + } + } + + formatter<_Tp, _CharT> __underlying_; + basic_string_view<_CharT> __separator_ = _LIBCPP_STATICALLY_WIDEN(_CharT, ", "); + basic_string_view<_CharT> __opening_bracket_ = _LIBCPP_STATICALLY_WIDEN(_CharT, "["); + basic_string_view<_CharT> __closing_bracket_ = _LIBCPP_STATICALLY_WIDEN(_CharT, "]"); +}; + +#endif //_LIBCPP_STD_VER > 20 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___FORMAT_RANGE_FORMATTER_H diff --git a/app/src/main/cpp/libcxx/include/__format/unicode.h b/app/src/main/cpp/libcxx/include/__format/unicode.h new file mode 100644 index 0000000..4327258 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__format/unicode.h @@ -0,0 +1,489 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___FORMAT_UNICODE_H +#define _LIBCPP___FORMAT_UNICODE_H + +#include <__assert> +#include <__config> +#include <__format/extended_grapheme_cluster_table.h> +#include <__type_traits/make_unsigned.h> +#include <__utility/unreachable.h> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 17 + +namespace __unicode { + +# if _LIBCPP_STD_VER > 20 + +/// The result of consuming a code point using P2286' semantics +/// +/// TODO FMT Combine __consume and __consume_p2286 in one function. +struct __consume_p2286_result { + // A size of 0 means well formed. This to differenciate between + // a valid code point and a code unit that's invalid like 0b11111xxx. + int __ill_formed_size; + + // If well formed the consumed code point. + // Otherwise the ill-formed code units as unsigned 8-bit values. They are + // stored in reverse order, to make it easier to extract the values. + char32_t __value; +}; + +# endif // _LIBCPP_STD_VER > 20 + +# ifndef _LIBCPP_HAS_NO_UNICODE + +/// Implements the grapheme cluster boundary rules +/// +/// These rules are used to implement format's width estimation as stated in +/// [format.string.std]/11 +/// +/// The Standard refers to UAX \#29 for Unicode 12.0.0 +/// https://www.unicode.org/reports/tr29/#Grapheme_Cluster_Boundary_Rules +/// +/// The data tables used are +/// https://www.unicode.org/Public/UCD/latest/ucd/auxiliary/GraphemeBreakProperty.txt +/// https://www.unicode.org/Public/UCD/latest/ucd/emoji/emoji-data.txt +/// https://www.unicode.org/Public/UCD/latest/ucd/auxiliary/GraphemeBreakTest.txt (for testing only) + +inline constexpr char32_t __replacement_character = U'\ufffd'; + +_LIBCPP_HIDE_FROM_ABI constexpr bool __is_continuation(const char* __char, int __count) { + do { + if ((*__char & 0b1000'0000) != 0b1000'0000) + return false; + --__count; + ++__char; + } while (__count); + return true; +} + +/// Helper class to extract a code unit from a Unicode character range. +/// +/// The stored range is a view. There are multiple specialization for different +/// character types. +template +class __code_point_view; + +/// UTF-8 specialization. +template <> +class __code_point_view { +public: + _LIBCPP_HIDE_FROM_ABI constexpr explicit __code_point_view(const char* __first, const char* __last) + : __first_(__first), __last_(__last) {} + + _LIBCPP_HIDE_FROM_ABI constexpr bool __at_end() const noexcept { return __first_ == __last_; } + _LIBCPP_HIDE_FROM_ABI constexpr const char* __position() const noexcept { return __first_; } + + _LIBCPP_HIDE_FROM_ABI constexpr char32_t __consume() noexcept { + _LIBCPP_ASSERT(__first_ != __last_, "can't move beyond the end of input"); + + // Based on the number of leading 1 bits the number of code units in the + // code point can be determined. See + // https://en.wikipedia.org/wiki/UTF-8#Encoding + switch (_VSTD::countl_one(static_cast(*__first_))) { + case 0: + return *__first_++; + + case 2: + if (__last_ - __first_ < 2 || !__unicode::__is_continuation(__first_ + 1, 1)) [[unlikely]] + break; + else { + char32_t __value = static_cast(*__first_++) & 0x1f; + __value <<= 6; + __value |= static_cast(*__first_++) & 0x3f; + return __value; + } + + case 3: + if (__last_ - __first_ < 3 || !__unicode::__is_continuation(__first_ + 1, 2)) [[unlikely]] + break; + else { + char32_t __value = static_cast(*__first_++) & 0x0f; + __value <<= 6; + __value |= static_cast(*__first_++) & 0x3f; + __value <<= 6; + __value |= static_cast(*__first_++) & 0x3f; + return __value; + } + + case 4: + if (__last_ - __first_ < 4 || !__unicode::__is_continuation(__first_ + 1, 3)) [[unlikely]] + break; + else { + char32_t __value = static_cast(*__first_++) & 0x07; + __value <<= 6; + __value |= static_cast(*__first_++) & 0x3f; + __value <<= 6; + __value |= static_cast(*__first_++) & 0x3f; + __value <<= 6; + __value |= static_cast(*__first_++) & 0x3f; + return __value; + } + } + // An invalid number of leading ones can be garbage or a code unit in the + // middle of a code point. By consuming one code unit the parser may get + // "in sync" after a few code units. + ++__first_; + return __replacement_character; + } + +# if _LIBCPP_STD_VER > 20 + _LIBCPP_HIDE_FROM_ABI constexpr __consume_p2286_result __consume_p2286() noexcept { + _LIBCPP_ASSERT(__first_ != __last_, "can't move beyond the end of input"); + + // Based on the number of leading 1 bits the number of code units in the + // code point can be determined. See + // https://en.wikipedia.org/wiki/UTF-8#Encoding + switch (std::countl_one(static_cast(*__first_))) { + case 0: + return {0, static_cast(*__first_++)}; + + case 2: + if (__last_ - __first_ < 2) [[unlikely]] + break; + + if (__unicode::__is_continuation(__first_ + 1, 1)) { + char32_t __value = static_cast(*__first_++) & 0x1f; + __value <<= 6; + __value |= static_cast(*__first_++) & 0x3f; + return {0, __value}; + } + break; + + case 3: + if (__last_ - __first_ < 3) [[unlikely]] + break; + + if (__unicode::__is_continuation(__first_ + 1, 2)) { + char32_t __value = static_cast(*__first_++) & 0x0f; + __value <<= 6; + __value |= static_cast(*__first_++) & 0x3f; + __value <<= 6; + __value |= static_cast(*__first_++) & 0x3f; + return {0, __value}; + } + break; + + case 4: + if (__last_ - __first_ < 4) [[unlikely]] + break; + + if (__unicode::__is_continuation(__first_ + 1, 3)) { + char32_t __value = static_cast(*__first_++) & 0x07; + __value <<= 6; + __value |= static_cast(*__first_++) & 0x3f; + __value <<= 6; + __value |= static_cast(*__first_++) & 0x3f; + __value <<= 6; + __value |= static_cast(*__first_++) & 0x3f; + + if (__value > 0x10FFFF) // Outside the valid Unicode range? + return {4, __value}; + + return {0, __value}; + } + break; + } + // An invalid number of leading ones can be garbage or a code unit in the + // middle of a code point. By consuming one code unit the parser may get + // "in sync" after a few code units. + return {1, static_cast(*__first_++)}; + } +# endif // _LIBCPP_STD_VER > 20 + +private: + const char* __first_; + const char* __last_; +}; + +# ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +_LIBCPP_HIDE_FROM_ABI constexpr bool __is_surrogate_pair_high(wchar_t __value) { + return __value >= 0xd800 && __value <= 0xdbff; +} + +_LIBCPP_HIDE_FROM_ABI constexpr bool __is_surrogate_pair_low(wchar_t __value) { + return __value >= 0xdc00 && __value <= 0xdfff; +} + +/// This specialization depends on the size of wchar_t +/// - 2 UTF-16 (for example Windows and AIX) +/// - 4 UTF-32 (for example Linux) +template <> +class __code_point_view { +public: + static_assert(sizeof(wchar_t) == 2 || sizeof(wchar_t) == 4, "sizeof(wchar_t) has a not implemented value"); + + _LIBCPP_HIDE_FROM_ABI constexpr explicit __code_point_view(const wchar_t* __first, const wchar_t* __last) + : __first_(__first), __last_(__last) {} + + _LIBCPP_HIDE_FROM_ABI constexpr const wchar_t* __position() const noexcept { return __first_; } + _LIBCPP_HIDE_FROM_ABI constexpr bool __at_end() const noexcept { return __first_ == __last_; } + + _LIBCPP_HIDE_FROM_ABI constexpr char32_t __consume() noexcept { + _LIBCPP_ASSERT(__first_ != __last_, "can't move beyond the end of input"); + + if constexpr (sizeof(wchar_t) == 2) { + char32_t __result = *__first_++; + // Is the code unit part of a surrogate pair? See + // https://en.wikipedia.org/wiki/UTF-16#U+D800_to_U+DFFF + if (__result >= 0xd800 && __result <= 0xDfff) { + // Malformed Unicode. + if (__first_ == __last_) [[unlikely]] + return __replacement_character; + + __result -= 0xd800; + __result <<= 10; + __result += *__first_++ - 0xdc00; + __result += 0x10000; + } + return __result; + + } else if constexpr (sizeof(wchar_t) == 4) { + char32_t __result = *__first_++; + if (__result > 0x10FFFF) [[unlikely]] + return __replacement_character; + return __result; + } else { + __libcpp_unreachable(); + } + } + +# if _LIBCPP_STD_VER > 20 + _LIBCPP_HIDE_FROM_ABI constexpr __consume_p2286_result __consume_p2286() noexcept { + _LIBCPP_ASSERT(__first_ != __last_, "can't move beyond the end of input"); + + char32_t __result = *__first_++; + if constexpr (sizeof(wchar_t) == 2) { + // https://en.wikipedia.org/wiki/UTF-16#U+D800_to_U+DFFF + if (__is_surrogate_pair_high(__result)) { + // Malformed Unicode. + if (__first_ == __last_ || !__is_surrogate_pair_low(*(__first_ + 1))) [[unlikely]] + return {1, __result}; + + __result -= 0xd800; + __result <<= 10; + __result += *__first_++ - 0xdc00; + __result += 0x10000; + } else if (__is_surrogate_pair_low(__result)) + // A code point shouldn't start with the low surrogate pair + return {1, __result}; + } else { + if (__result > 0x10FFFF) [[unlikely]] + return {1, __result}; + } + + return {0, __result}; + } +# endif // _LIBCPP_STD_VER > 20 + +private: + const wchar_t* __first_; + const wchar_t* __last_; +}; +# endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS + +_LIBCPP_HIDE_FROM_ABI constexpr bool __at_extended_grapheme_cluster_break( + bool& __ri_break_allowed, + bool __has_extened_pictographic, + __extended_grapheme_custer_property_boundary::__property __prev, + __extended_grapheme_custer_property_boundary::__property __next) { + using __extended_grapheme_custer_property_boundary::__property; + + __has_extened_pictographic |= __prev == __property::__Extended_Pictographic; + + // https://www.unicode.org/reports/tr29/tr29-39.html#Grapheme_Cluster_Boundary_Rules + + // *** Break at the start and end of text, unless the text is empty. *** + + _LIBCPP_ASSERT(__prev != __property::__sot, "should be handled in the constructor"); // GB1 + _LIBCPP_ASSERT(__prev != __property::__eot, "should be handled by our caller"); // GB2 + + // *** Do not break between a CR and LF. Otherwise, break before and after controls. *** + if (__prev == __property::__CR && __next == __property::__LF) // GB3 + return false; + + if (__prev == __property::__Control || __prev == __property::__CR || __prev == __property::__LF) // GB4 + return true; + + if (__next == __property::__Control || __next == __property::__CR || __next == __property::__LF) // GB5 + return true; + + // *** Do not break Hangul syllable sequences. *** + if (__prev == __property::__L && + (__next == __property::__L || __next == __property::__V || __next == __property::__LV || + __next == __property::__LVT)) // GB6 + return false; + + if ((__prev == __property::__LV || __prev == __property::__V) && + (__next == __property::__V || __next == __property::__T)) // GB7 + return false; + + if ((__prev == __property::__LVT || __prev == __property::__T) && __next == __property::__T) // GB8 + return false; + + // *** Do not break before extending characters or ZWJ. *** + if (__next == __property::__Extend || __next == __property::__ZWJ) + return false; // GB9 + + // *** Do not break before SpacingMarks, or after Prepend characters. *** + if (__next == __property::__SpacingMark) // GB9a + return false; + + if (__prev == __property::__Prepend) // GB9b + return false; + + // *** Do not break within emoji modifier sequences or emoji zwj sequences. *** + + // GB11 \p{Extended_Pictographic} Extend* ZWJ x \p{Extended_Pictographic} + // + // Note that several parts of this rule are matched by GB9: Any x (Extend | ZWJ) + // - \p{Extended_Pictographic} x Extend + // - Extend x Extend + // - \p{Extended_Pictographic} x ZWJ + // - Extend x ZWJ + // + // So the only case left to test is + // - \p{Extended_Pictographic}' x ZWJ x \p{Extended_Pictographic} + // where \p{Extended_Pictographic}' is stored in __has_extened_pictographic + if (__has_extened_pictographic && __prev == __property::__ZWJ && __next == __property::__Extended_Pictographic) + return false; + + // *** Do not break within emoji flag sequences *** + + // That is, do not break between regional indicator (RI) symbols if there + // is an odd number of RI characters before the break point. + + if (__prev == __property::__Regional_Indicator && __next == __property::__Regional_Indicator) { // GB12 + GB13 + __ri_break_allowed = !__ri_break_allowed; + return __ri_break_allowed; + } + + // *** Otherwise, break everywhere. *** + return true; // GB999 +} + +/// Helper class to extract an extended grapheme cluster from a Unicode character range. +/// +/// This function is used to determine the column width of an extended grapheme +/// cluster. In order to do that only the first code point is evaluated. +/// Therefore only this code point is extracted. +template +class __extended_grapheme_cluster_view { +public: + _LIBCPP_HIDE_FROM_ABI constexpr explicit __extended_grapheme_cluster_view(const _CharT* __first, const _CharT* __last) + : __code_point_view_(__first, __last), + __next_code_point_(__code_point_view_.__consume()), + __next_prop_(__extended_grapheme_custer_property_boundary::__get_property(__next_code_point_)) {} + + struct __cluster { + /// The first code point of the extended grapheme cluster. + /// + /// The first code point is used to estimate the width of the extended + /// grapheme cluster. + char32_t __code_point_; + + /// Points one beyond the last code unit in the extended grapheme cluster. + /// + /// It's expected the caller has the start position and thus can determine + /// the code unit range of the extended grapheme cluster. + const _CharT* __last_; + }; + + _LIBCPP_HIDE_FROM_ABI constexpr __cluster __consume() { + _LIBCPP_ASSERT( + __next_prop_ != __extended_grapheme_custer_property_boundary::__property::__eot, + "can't move beyond the end of input"); + char32_t __code_point = __next_code_point_; + if (!__code_point_view_.__at_end()) + return {__code_point, __get_break()}; + + __next_prop_ = __extended_grapheme_custer_property_boundary::__property::__eot; + return {__code_point, __code_point_view_.__position()}; + } + +private: + __code_point_view<_CharT> __code_point_view_; + + char32_t __next_code_point_; + __extended_grapheme_custer_property_boundary::__property __next_prop_; + + _LIBCPP_HIDE_FROM_ABI constexpr const _CharT* __get_break() { + bool __ri_break_allowed = true; + bool __has_extened_pictographic = false; + while (true) { + const _CharT* __result = __code_point_view_.__position(); + __extended_grapheme_custer_property_boundary::__property __prev = __next_prop_; + if (__code_point_view_.__at_end()) { + __next_prop_ = __extended_grapheme_custer_property_boundary::__property::__eot; + return __result; + } + __next_code_point_ = __code_point_view_.__consume(); + __next_prop_ = __extended_grapheme_custer_property_boundary::__get_property(__next_code_point_); + + __has_extened_pictographic |= + __prev == __extended_grapheme_custer_property_boundary::__property::__Extended_Pictographic; + + if (__at_extended_grapheme_cluster_break(__ri_break_allowed, __has_extened_pictographic, __prev, __next_prop_)) + return __result; + } + } +}; + +template +__extended_grapheme_cluster_view(const _CharT*, const _CharT*) -> __extended_grapheme_cluster_view<_CharT>; + +# else // _LIBCPP_HAS_NO_UNICODE + +// For ASCII every character is a "code point". +// This makes it easier to write code agnostic of the _LIBCPP_HAS_NO_UNICODE define. +template +class __code_point_view { +public: + _LIBCPP_HIDE_FROM_ABI constexpr explicit __code_point_view(const _CharT* __first, const _CharT* __last) + : __first_(__first), __last_(__last) {} + + _LIBCPP_HIDE_FROM_ABI constexpr bool __at_end() const noexcept { return __first_ == __last_; } + _LIBCPP_HIDE_FROM_ABI constexpr const _CharT* __position() const noexcept { return __first_; } + + _LIBCPP_HIDE_FROM_ABI constexpr char32_t __consume() noexcept { + _LIBCPP_ASSERT(__first_ != __last_, "can't move beyond the end of input"); + return *__first_++; + } + +# if _LIBCPP_STD_VER > 20 + _LIBCPP_HIDE_FROM_ABI constexpr __consume_p2286_result __consume_p2286() noexcept { + _LIBCPP_ASSERT(__first_ != __last_, "can't move beyond the end of input"); + + return {0, std::make_unsigned_t<_CharT>(*__first_++)}; + } +# endif // _LIBCPP_STD_VER > 20 + +private: + const _CharT* __first_; + const _CharT* __last_; +}; + +# endif // _LIBCPP_HAS_NO_UNICODE + +} // namespace __unicode + +#endif //_LIBCPP_STD_VER > 17 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___FORMAT_UNICODE_H diff --git a/app/src/main/cpp/libcxx/include/__functional/binary_function.h b/app/src/main/cpp/libcxx/include/__functional/binary_function.h new file mode 100644 index 0000000..fdedb8b --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__functional/binary_function.h @@ -0,0 +1,54 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___FUNCTIONAL_BINARY_FUNCTION_H +#define _LIBCPP___FUNCTIONAL_BINARY_FUNCTION_H + +#include <__config> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER <= 14 || defined(_LIBCPP_ENABLE_CXX17_REMOVED_UNARY_BINARY_FUNCTION) + +template +struct _LIBCPP_TEMPLATE_VIS _LIBCPP_DEPRECATED_IN_CXX11 binary_function +{ + typedef _Arg1 first_argument_type; + typedef _Arg2 second_argument_type; + typedef _Result result_type; +}; + +#endif // _LIBCPP_STD_VER <= 14 || defined(_LIBCPP_ENABLE_CXX17_REMOVED_UNARY_BINARY_FUNCTION) + +template struct __binary_function_keep_layout_base { +#if _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_ENABLE_CXX20_REMOVED_BINDER_TYPEDEFS) + using first_argument_type _LIBCPP_DEPRECATED_IN_CXX17 = _Arg1; + using second_argument_type _LIBCPP_DEPRECATED_IN_CXX17 = _Arg2; + using result_type _LIBCPP_DEPRECATED_IN_CXX17 = _Result; +#endif +}; + +#if _LIBCPP_STD_VER <= 14 || defined(_LIBCPP_ENABLE_CXX17_REMOVED_UNARY_BINARY_FUNCTION) +_LIBCPP_DIAGNOSTIC_PUSH +_LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wdeprecated-declarations") +template +using __binary_function = binary_function<_Arg1, _Arg2, _Result>; +_LIBCPP_DIAGNOSTIC_POP +#else +template +using __binary_function = __binary_function_keep_layout_base<_Arg1, _Arg2, _Result>; +#endif + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___FUNCTIONAL_BINARY_FUNCTION_H diff --git a/app/src/main/cpp/libcxx/include/__functional/binary_negate.h b/app/src/main/cpp/libcxx/include/__functional/binary_negate.h new file mode 100644 index 0000000..73ecea9 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__functional/binary_negate.h @@ -0,0 +1,50 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___FUNCTIONAL_BINARY_NEGATE_H +#define _LIBCPP___FUNCTIONAL_BINARY_NEGATE_H + +#include <__config> +#include <__functional/binary_function.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_ENABLE_CXX20_REMOVED_NEGATORS) + +template +class _LIBCPP_TEMPLATE_VIS _LIBCPP_DEPRECATED_IN_CXX17 binary_negate + : public __binary_function +{ + _Predicate __pred_; +public: + _LIBCPP_INLINE_VISIBILITY explicit _LIBCPP_CONSTEXPR_SINCE_CXX14 + binary_negate(const _Predicate& __pred) : __pred_(__pred) {} + + _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_INLINE_VISIBILITY + bool operator()(const typename _Predicate::first_argument_type& __x, + const typename _Predicate::second_argument_type& __y) const + {return !__pred_(__x, __y);} +}; + +template +_LIBCPP_DEPRECATED_IN_CXX17 inline _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_INLINE_VISIBILITY +binary_negate<_Predicate> +not2(const _Predicate& __pred) {return binary_negate<_Predicate>(__pred);} + +#endif // _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_ENABLE_CXX20_REMOVED_NEGATORS) + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___FUNCTIONAL_BINARY_NEGATE_H diff --git a/app/src/main/cpp/libcxx/include/__functional/bind.h b/app/src/main/cpp/libcxx/include/__functional/bind.h new file mode 100644 index 0000000..297e4e5 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__functional/bind.h @@ -0,0 +1,389 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___FUNCTIONAL_BIND_H +#define _LIBCPP___FUNCTIONAL_BIND_H + +#include <__config> +#include <__functional/invoke.h> +#include <__functional/weak_result_type.h> +#include +#include +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +template +struct is_bind_expression : _If< + _IsSame<_Tp, __remove_cvref_t<_Tp> >::value, + false_type, + is_bind_expression<__remove_cvref_t<_Tp> > +> {}; + +#if _LIBCPP_STD_VER > 14 +template +inline constexpr size_t is_bind_expression_v = is_bind_expression<_Tp>::value; +#endif + +template +struct is_placeholder : _If< + _IsSame<_Tp, __remove_cvref_t<_Tp> >::value, + integral_constant, + is_placeholder<__remove_cvref_t<_Tp> > +> {}; + +#if _LIBCPP_STD_VER > 14 +template +inline constexpr size_t is_placeholder_v = is_placeholder<_Tp>::value; +#endif + +namespace placeholders +{ + +template struct __ph {}; + +#if defined(_LIBCPP_CXX03_LANG) || defined(_LIBCPP_BUILDING_LIBRARY) +_LIBCPP_FUNC_VIS extern const __ph<1> _1; +_LIBCPP_FUNC_VIS extern const __ph<2> _2; +_LIBCPP_FUNC_VIS extern const __ph<3> _3; +_LIBCPP_FUNC_VIS extern const __ph<4> _4; +_LIBCPP_FUNC_VIS extern const __ph<5> _5; +_LIBCPP_FUNC_VIS extern const __ph<6> _6; +_LIBCPP_FUNC_VIS extern const __ph<7> _7; +_LIBCPP_FUNC_VIS extern const __ph<8> _8; +_LIBCPP_FUNC_VIS extern const __ph<9> _9; +_LIBCPP_FUNC_VIS extern const __ph<10> _10; +#else +/* inline */ constexpr __ph<1> _1{}; +/* inline */ constexpr __ph<2> _2{}; +/* inline */ constexpr __ph<3> _3{}; +/* inline */ constexpr __ph<4> _4{}; +/* inline */ constexpr __ph<5> _5{}; +/* inline */ constexpr __ph<6> _6{}; +/* inline */ constexpr __ph<7> _7{}; +/* inline */ constexpr __ph<8> _8{}; +/* inline */ constexpr __ph<9> _9{}; +/* inline */ constexpr __ph<10> _10{}; +#endif // defined(_LIBCPP_CXX03_LANG) || defined(_LIBCPP_BUILDING_LIBRARY) + +} // namespace placeholders + +template +struct is_placeholder > + : public integral_constant {}; + + +#ifndef _LIBCPP_CXX03_LANG + +template +inline _LIBCPP_INLINE_VISIBILITY +_Tp& +__mu(reference_wrapper<_Tp> __t, _Uj&) +{ + return __t.get(); +} + +template +inline _LIBCPP_INLINE_VISIBILITY +typename __invoke_of<_Ti&, _Uj...>::type +__mu_expand(_Ti& __ti, tuple<_Uj...>& __uj, __tuple_indices<_Indx...>) +{ + return __ti(_VSTD::forward<_Uj>(_VSTD::get<_Indx>(__uj))...); +} + +template +inline _LIBCPP_INLINE_VISIBILITY +typename __enable_if_t +< + is_bind_expression<_Ti>::value, + __invoke_of<_Ti&, _Uj...> +>::type +__mu(_Ti& __ti, tuple<_Uj...>& __uj) +{ + typedef typename __make_tuple_indices::type __indices; + return _VSTD::__mu_expand(__ti, __uj, __indices()); +} + +template +struct __mu_return2 {}; + +template +struct __mu_return2 +{ + typedef typename tuple_element::value - 1, _Uj>::type type; +}; + +template +inline _LIBCPP_INLINE_VISIBILITY +typename enable_if +< + 0 < is_placeholder<_Ti>::value, + typename __mu_return2<0 < is_placeholder<_Ti>::value, _Ti, _Uj>::type +>::type +__mu(_Ti&, _Uj& __uj) +{ + const size_t _Indx = is_placeholder<_Ti>::value - 1; + return _VSTD::forward::type>(_VSTD::get<_Indx>(__uj)); +} + +template +inline _LIBCPP_INLINE_VISIBILITY +typename enable_if +< + !is_bind_expression<_Ti>::value && + is_placeholder<_Ti>::value == 0 && + !__is_reference_wrapper<_Ti>::value, + _Ti& +>::type +__mu(_Ti& __ti, _Uj&) +{ + return __ti; +} + +template +struct __mu_return_impl; + +template +struct __mu_return_invokable // false +{ + typedef __nat type; +}; + +template +struct __mu_return_invokable +{ + typedef typename __invoke_of<_Ti&, _Uj...>::type type; +}; + +template +struct __mu_return_impl<_Ti, false, true, false, tuple<_Uj...> > + : public __mu_return_invokable<__invokable<_Ti&, _Uj...>::value, _Ti, _Uj...> +{ +}; + +template +struct __mu_return_impl<_Ti, false, false, true, _TupleUj> +{ + typedef typename tuple_element::value - 1, + _TupleUj>::type&& type; +}; + +template +struct __mu_return_impl<_Ti, true, false, false, _TupleUj> +{ + typedef typename _Ti::type& type; +}; + +template +struct __mu_return_impl<_Ti, false, false, false, _TupleUj> +{ + typedef _Ti& type; +}; + +template +struct __mu_return + : public __mu_return_impl<_Ti, + __is_reference_wrapper<_Ti>::value, + is_bind_expression<_Ti>::value, + 0 < is_placeholder<_Ti>::value && + is_placeholder<_Ti>::value <= tuple_size<_TupleUj>::value, + _TupleUj> +{ +}; + +template +struct __is_valid_bind_return +{ + static const bool value = false; +}; + +template +struct __is_valid_bind_return<_Fp, tuple<_BoundArgs...>, _TupleUj> +{ + static const bool value = __invokable<_Fp, + typename __mu_return<_BoundArgs, _TupleUj>::type...>::value; +}; + +template +struct __is_valid_bind_return<_Fp, const tuple<_BoundArgs...>, _TupleUj> +{ + static const bool value = __invokable<_Fp, + typename __mu_return::type...>::value; +}; + +template ::value> +struct __bind_return; + +template +struct __bind_return<_Fp, tuple<_BoundArgs...>, _TupleUj, true> +{ + typedef typename __invoke_of + < + _Fp&, + typename __mu_return + < + _BoundArgs, + _TupleUj + >::type... + >::type type; +}; + +template +struct __bind_return<_Fp, const tuple<_BoundArgs...>, _TupleUj, true> +{ + typedef typename __invoke_of + < + _Fp&, + typename __mu_return + < + const _BoundArgs, + _TupleUj + >::type... + >::type type; +}; + +template +inline _LIBCPP_INLINE_VISIBILITY +typename __bind_return<_Fp, _BoundArgs, _Args>::type +__apply_functor(_Fp& __f, _BoundArgs& __bound_args, __tuple_indices<_Indx...>, + _Args&& __args) +{ + return _VSTD::__invoke(__f, _VSTD::__mu(_VSTD::get<_Indx>(__bound_args), __args)...); +} + +template +class __bind : public __weak_result_type::type> +{ +protected: + typedef typename decay<_Fp>::type _Fd; + typedef tuple::type...> _Td; +private: + _Fd __f_; + _Td __bound_args_; + + typedef typename __make_tuple_indices::type __indices; +public: + template ::value && + !is_same<__libcpp_remove_reference_t<_Gp>, + __bind>::value + >::type> + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 + explicit __bind(_Gp&& __f, _BA&& ...__bound_args) + : __f_(_VSTD::forward<_Gp>(__f)), + __bound_args_(_VSTD::forward<_BA>(__bound_args)...) {} + + template + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 + typename __bind_return<_Fd, _Td, tuple<_Args&&...> >::type + operator()(_Args&& ...__args) + { + return _VSTD::__apply_functor(__f_, __bound_args_, __indices(), + tuple<_Args&&...>(_VSTD::forward<_Args>(__args)...)); + } + + template + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 + typename __bind_return >::type + operator()(_Args&& ...__args) const + { + return _VSTD::__apply_functor(__f_, __bound_args_, __indices(), + tuple<_Args&&...>(_VSTD::forward<_Args>(__args)...)); + } +}; + +template +struct is_bind_expression<__bind<_Fp, _BoundArgs...> > : public true_type {}; + +template +class __bind_r + : public __bind<_Fp, _BoundArgs...> +{ + typedef __bind<_Fp, _BoundArgs...> base; + typedef typename base::_Fd _Fd; + typedef typename base::_Td _Td; +public: + typedef _Rp result_type; + + + template ::value && + !is_same<__libcpp_remove_reference_t<_Gp>, + __bind_r>::value + >::type> + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 + explicit __bind_r(_Gp&& __f, _BA&& ...__bound_args) + : base(_VSTD::forward<_Gp>(__f), + _VSTD::forward<_BA>(__bound_args)...) {} + + template + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 + typename enable_if + < + is_convertible >::type, + result_type>::value || is_void<_Rp>::value, + result_type + >::type + operator()(_Args&& ...__args) + { + typedef __invoke_void_return_wrapper<_Rp> _Invoker; + return _Invoker::__call(static_cast(*this), _VSTD::forward<_Args>(__args)...); + } + + template + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 + typename enable_if + < + is_convertible >::type, + result_type>::value || is_void<_Rp>::value, + result_type + >::type + operator()(_Args&& ...__args) const + { + typedef __invoke_void_return_wrapper<_Rp> _Invoker; + return _Invoker::__call(static_cast(*this), _VSTD::forward<_Args>(__args)...); + } +}; + +template +struct is_bind_expression<__bind_r<_Rp, _Fp, _BoundArgs...> > : public true_type {}; + +template +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 +__bind<_Fp, _BoundArgs...> +bind(_Fp&& __f, _BoundArgs&&... __bound_args) +{ + typedef __bind<_Fp, _BoundArgs...> type; + return type(_VSTD::forward<_Fp>(__f), _VSTD::forward<_BoundArgs>(__bound_args)...); +} + +template +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 +__bind_r<_Rp, _Fp, _BoundArgs...> +bind(_Fp&& __f, _BoundArgs&&... __bound_args) +{ + typedef __bind_r<_Rp, _Fp, _BoundArgs...> type; + return type(_VSTD::forward<_Fp>(__f), _VSTD::forward<_BoundArgs>(__bound_args)...); +} + +#endif // _LIBCPP_CXX03_LANG + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___FUNCTIONAL_BIND_H diff --git a/app/src/main/cpp/libcxx/include/__functional/bind_back.h b/app/src/main/cpp/libcxx/include/__functional/bind_back.h new file mode 100644 index 0000000..f0a6e49 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__functional/bind_back.h @@ -0,0 +1,64 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___FUNCTIONAL_BIND_BACK_H +#define _LIBCPP___FUNCTIONAL_BIND_BACK_H + +#include <__config> +#include <__functional/invoke.h> +#include <__functional/perfect_forward.h> +#include <__utility/forward.h> +#include <__utility/integer_sequence.h> +#include +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 17 + +template > +struct __bind_back_op; + +template +struct __bind_back_op<_NBound, index_sequence<_Ip...>> { + template + _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Fn&& __f, _BoundArgs&& __bound_args, _Args&&... __args) const + noexcept(noexcept(_VSTD::invoke(_VSTD::forward<_Fn>(__f), _VSTD::forward<_Args>(__args)..., _VSTD::get<_Ip>(_VSTD::forward<_BoundArgs>(__bound_args))...))) + -> decltype( _VSTD::invoke(_VSTD::forward<_Fn>(__f), _VSTD::forward<_Args>(__args)..., _VSTD::get<_Ip>(_VSTD::forward<_BoundArgs>(__bound_args))...)) + { return _VSTD::invoke(_VSTD::forward<_Fn>(__f), _VSTD::forward<_Args>(__args)..., _VSTD::get<_Ip>(_VSTD::forward<_BoundArgs>(__bound_args))...); } +}; + +template +struct __bind_back_t : __perfect_forward<__bind_back_op>, _Fn, _BoundArgs> { + using __perfect_forward<__bind_back_op>, _Fn, _BoundArgs>::__perfect_forward; +}; + +template , _Fn>, + is_move_constructible>, + is_constructible, _Args>..., + is_move_constructible>... + >::value +>> +_LIBCPP_HIDE_FROM_ABI +constexpr auto __bind_back(_Fn&& __f, _Args&&... __args) + noexcept(noexcept(__bind_back_t, tuple...>>(_VSTD::forward<_Fn>(__f), _VSTD::forward_as_tuple(_VSTD::forward<_Args>(__args)...)))) + -> decltype( __bind_back_t, tuple...>>(_VSTD::forward<_Fn>(__f), _VSTD::forward_as_tuple(_VSTD::forward<_Args>(__args)...))) + { return __bind_back_t, tuple...>>(_VSTD::forward<_Fn>(__f), _VSTD::forward_as_tuple(_VSTD::forward<_Args>(__args)...)); } + +#endif // _LIBCPP_STD_VER > 17 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___FUNCTIONAL_BIND_BACK_H diff --git a/app/src/main/cpp/libcxx/include/__functional/bind_front.h b/app/src/main/cpp/libcxx/include/__functional/bind_front.h new file mode 100644 index 0000000..22fb3a6 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__functional/bind_front.h @@ -0,0 +1,58 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___FUNCTIONAL_BIND_FRONT_H +#define _LIBCPP___FUNCTIONAL_BIND_FRONT_H + +#include <__config> +#include <__functional/invoke.h> +#include <__functional/perfect_forward.h> +#include <__utility/forward.h> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 17 + +struct __bind_front_op { + template + _LIBCPP_HIDE_FROM_ABI + constexpr auto operator()(_Args&& ...__args) const + noexcept(noexcept(_VSTD::invoke(_VSTD::forward<_Args>(__args)...))) + -> decltype( _VSTD::invoke(_VSTD::forward<_Args>(__args)...)) + { return _VSTD::invoke(_VSTD::forward<_Args>(__args)...); } +}; + +template +struct __bind_front_t : __perfect_forward<__bind_front_op, _Fn, _BoundArgs...> { + using __perfect_forward<__bind_front_op, _Fn, _BoundArgs...>::__perfect_forward; +}; + +template , _Fn>, + is_move_constructible>, + is_constructible, _Args>..., + is_move_constructible>... + >::value +>> +_LIBCPP_HIDE_FROM_ABI +constexpr auto bind_front(_Fn&& __f, _Args&&... __args) { + return __bind_front_t, decay_t<_Args>...>(_VSTD::forward<_Fn>(__f), _VSTD::forward<_Args>(__args)...); +} + +#endif // _LIBCPP_STD_VER > 17 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___FUNCTIONAL_BIND_FRONT_H diff --git a/app/src/main/cpp/libcxx/include/__functional/binder1st.h b/app/src/main/cpp/libcxx/include/__functional/binder1st.h new file mode 100644 index 0000000..dea22c7 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__functional/binder1st.h @@ -0,0 +1,53 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___FUNCTIONAL_BINDER1ST_H +#define _LIBCPP___FUNCTIONAL_BINDER1ST_H + +#include <__config> +#include <__functional/unary_function.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER <= 14 || defined(_LIBCPP_ENABLE_CXX17_REMOVED_BINDERS) + +template +class _LIBCPP_TEMPLATE_VIS _LIBCPP_DEPRECATED_IN_CXX11 binder1st + : public __unary_function +{ +protected: + __Operation op; + typename __Operation::first_argument_type value; +public: + _LIBCPP_INLINE_VISIBILITY binder1st(const __Operation& __x, + const typename __Operation::first_argument_type __y) + : op(__x), value(__y) {} + _LIBCPP_INLINE_VISIBILITY typename __Operation::result_type operator() + (typename __Operation::second_argument_type& __x) const + {return op(value, __x);} + _LIBCPP_INLINE_VISIBILITY typename __Operation::result_type operator() + (const typename __Operation::second_argument_type& __x) const + {return op(value, __x);} +}; + +template +_LIBCPP_DEPRECATED_IN_CXX11 inline _LIBCPP_INLINE_VISIBILITY +binder1st<__Operation> +bind1st(const __Operation& __op, const _Tp& __x) + {return binder1st<__Operation>(__op, __x);} + +#endif // _LIBCPP_STD_VER <= 14 || defined(_LIBCPP_ENABLE_CXX17_REMOVED_BINDERS) + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___FUNCTIONAL_BINDER1ST_H diff --git a/app/src/main/cpp/libcxx/include/__functional/binder2nd.h b/app/src/main/cpp/libcxx/include/__functional/binder2nd.h new file mode 100644 index 0000000..c98a146 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__functional/binder2nd.h @@ -0,0 +1,53 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___FUNCTIONAL_BINDER2ND_H +#define _LIBCPP___FUNCTIONAL_BINDER2ND_H + +#include <__config> +#include <__functional/unary_function.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER <= 14 || defined(_LIBCPP_ENABLE_CXX17_REMOVED_BINDERS) + +template +class _LIBCPP_TEMPLATE_VIS _LIBCPP_DEPRECATED_IN_CXX11 binder2nd + : public __unary_function +{ +protected: + __Operation op; + typename __Operation::second_argument_type value; +public: + _LIBCPP_INLINE_VISIBILITY + binder2nd(const __Operation& __x, const typename __Operation::second_argument_type __y) + : op(__x), value(__y) {} + _LIBCPP_INLINE_VISIBILITY typename __Operation::result_type operator() + ( typename __Operation::first_argument_type& __x) const + {return op(__x, value);} + _LIBCPP_INLINE_VISIBILITY typename __Operation::result_type operator() + (const typename __Operation::first_argument_type& __x) const + {return op(__x, value);} +}; + +template +_LIBCPP_DEPRECATED_IN_CXX11 inline _LIBCPP_INLINE_VISIBILITY +binder2nd<__Operation> +bind2nd(const __Operation& __op, const _Tp& __x) + {return binder2nd<__Operation>(__op, __x);} + +#endif // _LIBCPP_STD_VER <= 14 || defined(_LIBCPP_ENABLE_CXX17_REMOVED_BINDERS) + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___FUNCTIONAL_BINDER2ND_H diff --git a/app/src/main/cpp/libcxx/include/__functional/boyer_moore_searcher.h b/app/src/main/cpp/libcxx/include/__functional/boyer_moore_searcher.h new file mode 100644 index 0000000..a675089 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__functional/boyer_moore_searcher.h @@ -0,0 +1,315 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___FUNCTIONAL_BOYER_MOORE_SEARCHER_H +#define _LIBCPP___FUNCTIONAL_BOYER_MOORE_SEARCHER_H + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#include <__algorithm/fill_n.h> +#include <__config> +#include <__functional/hash.h> +#include <__functional/operations.h> +#include <__iterator/distance.h> +#include <__iterator/iterator_traits.h> +#include <__memory/shared_ptr.h> +#include <__utility/pair.h> +#include +#include +#include + +#if _LIBCPP_STD_VER > 14 + +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + +_LIBCPP_BEGIN_NAMESPACE_STD + +template +class _BMSkipTable; + +// General case for BM data searching; use a map +template +class _BMSkipTable<_Key, _Value, _Hash, _BinaryPredicate, false> { +private: + using value_type = _Value; + using key_type = _Key; + + const value_type __default_value_; + unordered_map<_Key, _Value, _Hash, _BinaryPredicate> __table_; + +public: + _LIBCPP_HIDE_FROM_ABI + explicit _BMSkipTable(size_t __sz, value_type __default_value, _Hash __hash, _BinaryPredicate __pred) + : __default_value_(__default_value), + __table_(__sz, __hash, __pred) {} + + _LIBCPP_HIDE_FROM_ABI void insert(const key_type& __key, value_type __val) { + __table_[__key] = __val; + } + + _LIBCPP_HIDE_FROM_ABI value_type operator[](const key_type& __key) const { + auto __it = __table_.find(__key); + return __it == __table_.end() ? __default_value_ : __it->second; + } +}; + +// Special case small numeric values; use an array +template +class _BMSkipTable<_Key, _Value, _Hash, _BinaryPredicate, true> { +private: + using value_type = _Value; + using key_type = _Key; + + using unsigned_key_type = make_unsigned_t; + std::array __table_; + static_assert(numeric_limits::max() < 256); + +public: + _LIBCPP_HIDE_FROM_ABI explicit _BMSkipTable(size_t, value_type __default_value, _Hash, _BinaryPredicate) { + std::fill_n(__table_.data(), __table_.size(), __default_value); + } + + _LIBCPP_HIDE_FROM_ABI void insert(key_type __key, value_type __val) { + __table_[static_cast(__key)] = __val; + } + + _LIBCPP_HIDE_FROM_ABI value_type operator[](key_type __key) const { + return __table_[static_cast(__key)]; + } +}; + +template ::value_type>, + class _BinaryPredicate = equal_to<>> +class _LIBCPP_TEMPLATE_VIS boyer_moore_searcher { +private: + using difference_type = typename std::iterator_traits<_RandomAccessIterator1>::difference_type; + using value_type = typename std::iterator_traits<_RandomAccessIterator1>::value_type; + using __skip_table_type = _BMSkipTable + && sizeof(value_type) == 1 + && is_same_v<_Hash, hash> + && is_same_v<_BinaryPredicate, equal_to<>>>; + +public: + boyer_moore_searcher(_RandomAccessIterator1 __first, + _RandomAccessIterator1 __last, + _Hash __hash = _Hash(), + _BinaryPredicate __pred = _BinaryPredicate()) + : __first_(__first), + __last_(__last), + __pred_(__pred), + __pattern_length_(__last - __first), + __skip_table_(std::make_shared<__skip_table_type>(__pattern_length_, -1, __hash, __pred_)), + __suffix_(std::__allocate_shared_unbounded_array( + allocator(), __pattern_length_ + 1)) { + difference_type __i = 0; + while (__first != __last) { + __skip_table_->insert(*__first, __i); + ++__first; + ++__i; + } + __build_suffix_table(__first_, __last_, __pred_); + } + + template + pair<_RandomAccessIterator2, _RandomAccessIterator2> + operator()(_RandomAccessIterator2 __first, _RandomAccessIterator2 __last) const { + static_assert(__is_same_uncvref::value_type, + typename iterator_traits<_RandomAccessIterator2>::value_type>::value, + "Corpus and Pattern iterators must point to the same type"); + if (__first == __last) + return std::make_pair(__last, __last); + if (__first_ == __last_) + return std::make_pair(__first, __first); + + if (__pattern_length_ > (__last - __first)) + return std::make_pair(__last, __last); + return __search(__first, __last); + } + +private: + _RandomAccessIterator1 __first_; + _RandomAccessIterator1 __last_; + _BinaryPredicate __pred_; + difference_type __pattern_length_; + shared_ptr<__skip_table_type> __skip_table_; + shared_ptr __suffix_; + + template + pair<_RandomAccessIterator2, _RandomAccessIterator2> + __search(_RandomAccessIterator2 __f, _RandomAccessIterator2 __l) const { + _RandomAccessIterator2 __current = __f; + const _RandomAccessIterator2 __last = __l - __pattern_length_; + const __skip_table_type& __skip_table = *__skip_table_; + + while (__current <= __last) { + difference_type __j = __pattern_length_; + while (__pred_(__first_[__j - 1], __current[__j - 1])) { + --__j; + if (__j == 0) + return std::make_pair(__current, __current + __pattern_length_); + } + + difference_type __k = __skip_table[__current[__j - 1]]; + difference_type __m = __j - __k - 1; + if (__k < __j && __m > __suffix_[__j]) + __current += __m; + else + __current += __suffix_[__j]; + } + return std::make_pair(__l, __l); + } + + template + void __compute_bm_prefix(_Iterator __first, _Iterator __last, _BinaryPredicate __pred, _Container& __prefix) { + const size_t __count = __last - __first; + + __prefix[0] = 0; + size_t __k = 0; + + for (size_t __i = 1; __i != __count; ++__i) { + while (__k > 0 && !__pred(__first[__k], __first[__i])) + __k = __prefix[__k - 1]; + + if (__pred(__first[__k], __first[__i])) + ++__k; + __prefix[__i] = __k; + } + } + + void __build_suffix_table(_RandomAccessIterator1 __first, _RandomAccessIterator1 __last, _BinaryPredicate __pred) { + const size_t __count = __last - __first; + + if (__count == 0) + return; + + vector __scratch(__count); + + __compute_bm_prefix(__first, __last, __pred, __scratch); + for (size_t __i = 0; __i <= __count; ++__i) + __suffix_[__i] = __count - __scratch[__count - 1]; + + using _ReverseIter = reverse_iterator<_RandomAccessIterator1>; + __compute_bm_prefix(_ReverseIter(__last), _ReverseIter(__first), __pred, __scratch); + + for (size_t __i = 0; __i != __count; ++__i) { + const size_t __j = __count - __scratch[__i]; + const difference_type __k = __i - __scratch[__i] + 1; + + if (__suffix_[__j] > __k) + __suffix_[__j] = __k; + } + } +}; +_LIBCPP_CTAD_SUPPORTED_FOR_TYPE(boyer_moore_searcher); + +template ::value_type>, + class _BinaryPredicate = equal_to<>> +class _LIBCPP_TEMPLATE_VIS boyer_moore_horspool_searcher { +private: + using difference_type = typename iterator_traits<_RandomAccessIterator1>::difference_type; + using value_type = typename iterator_traits<_RandomAccessIterator1>::value_type; + using __skip_table_type = _BMSkipTable + && sizeof(value_type) == 1 + && is_same_v<_Hash, hash> + && is_same_v<_BinaryPredicate, equal_to<>>>; +public: + boyer_moore_horspool_searcher(_RandomAccessIterator1 __first, + _RandomAccessIterator1 __last, + _Hash __hash = _Hash(), + _BinaryPredicate __pred = _BinaryPredicate()) + : __first_(__first), + __last_(__last), + __pred_(__pred), + __pattern_length_(__last - __first), + __skip_table_(std::make_shared<__skip_table_type>(__pattern_length_, __pattern_length_, __hash, __pred_)) { + if (__first == __last) + return; + --__last; + difference_type __i = 0; + while (__first != __last) { + __skip_table_->insert(*__first, __pattern_length_ - 1 - __i); + ++__first; + ++__i; + } + } + + template + pair<_RandomAccessIterator2, _RandomAccessIterator2> + operator()(_RandomAccessIterator2 __first, _RandomAccessIterator2 __last) const { + static_assert(__is_same_uncvref::value_type, + typename std::iterator_traits<_RandomAccessIterator2>::value_type>::value, + "Corpus and Pattern iterators must point to the same type"); + if (__first == __last) + return std::make_pair(__last, __last); + if (__first_ == __last_) + return std::make_pair(__first, __first); + + if (__pattern_length_ > __last - __first) + return std::make_pair(__last, __last); + + return __search(__first, __last); + } + +private: + _RandomAccessIterator1 __first_; + _RandomAccessIterator1 __last_; + _BinaryPredicate __pred_; + difference_type __pattern_length_; + shared_ptr<__skip_table_type> __skip_table_; + + template + pair<_RandomAccessIterator2, _RandomAccessIterator2> + __search(_RandomAccessIterator2 __f, _RandomAccessIterator2 __l) const { + _RandomAccessIterator2 __current = __f; + const _RandomAccessIterator2 __last = __l - __pattern_length_; + const __skip_table_type& __skip_table = *__skip_table_; + + while (__current <= __last) { + difference_type __j = __pattern_length_; + while (__pred_(__first_[__j - 1], __current[__j - 1])) { + --__j; + if (__j == 0) + return std::make_pair(__current, __current + __pattern_length_); + } + __current += __skip_table[__current[__pattern_length_ - 1]]; + } + return std::make_pair(__l, __l); + } +}; +_LIBCPP_CTAD_SUPPORTED_FOR_TYPE(boyer_moore_horspool_searcher); + +_LIBCPP_END_NAMESPACE_STD + +_LIBCPP_POP_MACROS + +#endif // _LIBCPP_STD_VER > 14 + +#endif // _LIBCPP___FUNCTIONAL_BOYER_MOORE_SEARCHER_H diff --git a/app/src/main/cpp/libcxx/include/__functional/compose.h b/app/src/main/cpp/libcxx/include/__functional/compose.h new file mode 100644 index 0000000..25213f2 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__functional/compose.h @@ -0,0 +1,52 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___FUNCTIONAL_COMPOSE_H +#define _LIBCPP___FUNCTIONAL_COMPOSE_H + +#include <__config> +#include <__functional/invoke.h> +#include <__functional/perfect_forward.h> +#include <__utility/forward.h> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 17 + +struct __compose_op { + template + _LIBCPP_HIDE_FROM_ABI + constexpr auto operator()(_Fn1&& __f1, _Fn2&& __f2, _Args&&... __args) const + noexcept(noexcept(_VSTD::invoke(_VSTD::forward<_Fn1>(__f1), _VSTD::invoke(_VSTD::forward<_Fn2>(__f2), _VSTD::forward<_Args>(__args)...)))) + -> decltype( _VSTD::invoke(_VSTD::forward<_Fn1>(__f1), _VSTD::invoke(_VSTD::forward<_Fn2>(__f2), _VSTD::forward<_Args>(__args)...))) + { return _VSTD::invoke(_VSTD::forward<_Fn1>(__f1), _VSTD::invoke(_VSTD::forward<_Fn2>(__f2), _VSTD::forward<_Args>(__args)...)); } +}; + +template +struct __compose_t : __perfect_forward<__compose_op, _Fn1, _Fn2> { + using __perfect_forward<__compose_op, _Fn1, _Fn2>::__perfect_forward; +}; + +template +_LIBCPP_HIDE_FROM_ABI +constexpr auto __compose(_Fn1&& __f1, _Fn2&& __f2) + noexcept(noexcept(__compose_t, decay_t<_Fn2>>(_VSTD::forward<_Fn1>(__f1), _VSTD::forward<_Fn2>(__f2)))) + -> decltype( __compose_t, decay_t<_Fn2>>(_VSTD::forward<_Fn1>(__f1), _VSTD::forward<_Fn2>(__f2))) + { return __compose_t, decay_t<_Fn2>>(_VSTD::forward<_Fn1>(__f1), _VSTD::forward<_Fn2>(__f2)); } + +#endif // _LIBCPP_STD_VER > 17 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___FUNCTIONAL_COMPOSE_H diff --git a/app/src/main/cpp/libcxx/include/__functional/default_searcher.h b/app/src/main/cpp/libcxx/include/__functional/default_searcher.h new file mode 100644 index 0000000..e4151e5 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__functional/default_searcher.h @@ -0,0 +1,57 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___FUNCTIONAL_DEFAULT_SEARCHER_H +#define _LIBCPP___FUNCTIONAL_DEFAULT_SEARCHER_H + +#include <__algorithm/search.h> +#include <__config> +#include <__functional/identity.h> +#include <__functional/operations.h> +#include <__iterator/iterator_traits.h> +#include <__utility/pair.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 14 + +// default searcher +template> +class _LIBCPP_TEMPLATE_VIS default_searcher { +public: + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 + default_searcher(_ForwardIterator __f, _ForwardIterator __l, + _BinaryPredicate __p = _BinaryPredicate()) + : __first_(__f), __last_(__l), __pred_(__p) {} + + template + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 + pair<_ForwardIterator2, _ForwardIterator2> + operator () (_ForwardIterator2 __f, _ForwardIterator2 __l) const + { + auto __proj = __identity(); + return std::__search_impl(__f, __l, __first_, __last_, __pred_, __proj, __proj); + } + +private: + _ForwardIterator __first_; + _ForwardIterator __last_; + _BinaryPredicate __pred_; +}; +_LIBCPP_CTAD_SUPPORTED_FOR_TYPE(default_searcher); + +#endif // _LIBCPP_STD_VER > 14 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___FUNCTIONAL_DEFAULT_SEARCHER_H diff --git a/app/src/main/cpp/libcxx/include/__functional/function.h b/app/src/main/cpp/libcxx/include/__functional/function.h new file mode 100644 index 0000000..ca79d33 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__functional/function.h @@ -0,0 +1,1216 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___FUNCTIONAL_FUNCTION_H +#define _LIBCPP___FUNCTIONAL_FUNCTION_H + +#include <__assert> +#include <__config> +#include <__functional/binary_function.h> +#include <__functional/invoke.h> +#include <__functional/unary_function.h> +#include <__iterator/iterator_traits.h> +#include <__memory/addressof.h> +#include <__memory/allocator.h> +#include <__memory/allocator_destructor.h> +#include <__memory/allocator_traits.h> +#include <__memory/builtin_new_allocator.h> +#include <__memory/compressed_pair.h> +#include <__memory/unique_ptr.h> +#include <__type_traits/strip_signature.h> +#include <__utility/forward.h> +#include <__utility/move.h> +#include <__utility/piecewise_construct.h> +#include <__utility/swap.h> +#include +#include +#include +#include +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#ifndef _LIBCPP_CXX03_LANG + +_LIBCPP_BEGIN_NAMESPACE_STD + +// bad_function_call + +_LIBCPP_DIAGNOSTIC_PUSH +_LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wweak-vtables") +class _LIBCPP_EXCEPTION_ABI bad_function_call + : public exception +{ +public: +// Note that when a key function is not used, every translation unit that uses +// bad_function_call will end up containing a weak definition of the vtable and +// typeinfo. +#ifdef _LIBCPP_ABI_BAD_FUNCTION_CALL_KEY_FUNCTION + ~bad_function_call() _NOEXCEPT override; +#else + ~bad_function_call() _NOEXCEPT override {} +#endif + +#ifdef _LIBCPP_ABI_BAD_FUNCTION_CALL_GOOD_WHAT_MESSAGE + const char* what() const _NOEXCEPT override; +#endif +}; +_LIBCPP_DIAGNOSTIC_POP + +_LIBCPP_NORETURN inline _LIBCPP_INLINE_VISIBILITY +void __throw_bad_function_call() +{ +#ifndef _LIBCPP_NO_EXCEPTIONS + throw bad_function_call(); +#else + _VSTD::abort(); +#endif +} + +template class _LIBCPP_TEMPLATE_VIS function; // undefined + +namespace __function +{ + +template +struct __maybe_derive_from_unary_function +{ +}; + +template +struct __maybe_derive_from_unary_function<_Rp(_A1)> + : public __unary_function<_A1, _Rp> +{ +}; + +template +struct __maybe_derive_from_binary_function +{ +}; + +template +struct __maybe_derive_from_binary_function<_Rp(_A1, _A2)> + : public __binary_function<_A1, _A2, _Rp> +{ +}; + +template +_LIBCPP_INLINE_VISIBILITY +bool __not_null(_Fp const&) { return true; } + +template +_LIBCPP_INLINE_VISIBILITY +bool __not_null(_Fp* __ptr) { return __ptr; } + +template +_LIBCPP_INLINE_VISIBILITY +bool __not_null(_Ret _Class::*__ptr) { return __ptr; } + +template +_LIBCPP_INLINE_VISIBILITY +bool __not_null(function<_Fp> const& __f) { return !!__f; } + +#ifdef _LIBCPP_HAS_EXTENSION_BLOCKS +template +_LIBCPP_INLINE_VISIBILITY +bool __not_null(_Rp (^__p)(_Args...)) { return __p; } +#endif + +} // namespace __function + +namespace __function { + +// __alloc_func holds a functor and an allocator. + +template class __alloc_func; +template +class __default_alloc_func; + +template +class __alloc_func<_Fp, _Ap, _Rp(_ArgTypes...)> +{ + __compressed_pair<_Fp, _Ap> __f_; + + public: + typedef _LIBCPP_NODEBUG _Fp _Target; + typedef _LIBCPP_NODEBUG _Ap _Alloc; + + _LIBCPP_INLINE_VISIBILITY + const _Target& __target() const { return __f_.first(); } + + // WIN32 APIs may define __allocator, so use __get_allocator instead. + _LIBCPP_INLINE_VISIBILITY + const _Alloc& __get_allocator() const { return __f_.second(); } + + _LIBCPP_INLINE_VISIBILITY + explicit __alloc_func(_Target&& __f) + : __f_(piecewise_construct, _VSTD::forward_as_tuple(_VSTD::move(__f)), + _VSTD::forward_as_tuple()) + { + } + + _LIBCPP_INLINE_VISIBILITY + explicit __alloc_func(const _Target& __f, const _Alloc& __a) + : __f_(piecewise_construct, _VSTD::forward_as_tuple(__f), + _VSTD::forward_as_tuple(__a)) + { + } + + _LIBCPP_INLINE_VISIBILITY + explicit __alloc_func(const _Target& __f, _Alloc&& __a) + : __f_(piecewise_construct, _VSTD::forward_as_tuple(__f), + _VSTD::forward_as_tuple(_VSTD::move(__a))) + { + } + + _LIBCPP_INLINE_VISIBILITY + explicit __alloc_func(_Target&& __f, _Alloc&& __a) + : __f_(piecewise_construct, _VSTD::forward_as_tuple(_VSTD::move(__f)), + _VSTD::forward_as_tuple(_VSTD::move(__a))) + { + } + + _LIBCPP_INLINE_VISIBILITY + _Rp operator()(_ArgTypes&&... __arg) + { + typedef __invoke_void_return_wrapper<_Rp> _Invoker; + return _Invoker::__call(__f_.first(), + _VSTD::forward<_ArgTypes>(__arg)...); + } + + _LIBCPP_INLINE_VISIBILITY + __alloc_func* __clone() const + { + typedef allocator_traits<_Alloc> __alloc_traits; + typedef __rebind_alloc<__alloc_traits, __alloc_func> _AA; + _AA __a(__f_.second()); + typedef __allocator_destructor<_AA> _Dp; + unique_ptr<__alloc_func, _Dp> __hold(__a.allocate(1), _Dp(__a, 1)); + ::new ((void*)__hold.get()) __alloc_func(__f_.first(), _Alloc(__a)); + return __hold.release(); + } + + _LIBCPP_INLINE_VISIBILITY + void destroy() _NOEXCEPT { __f_.~__compressed_pair<_Target, _Alloc>(); } + + static void __destroy_and_delete(__alloc_func* __f) { + typedef allocator_traits<_Alloc> __alloc_traits; + typedef __rebind_alloc<__alloc_traits, __alloc_func> _FunAlloc; + _FunAlloc __a(__f->__get_allocator()); + __f->destroy(); + __a.deallocate(__f, 1); + } +}; + +template +class __default_alloc_func<_Fp, _Rp(_ArgTypes...)> { + _Fp __f_; + +public: + typedef _LIBCPP_NODEBUG _Fp _Target; + + _LIBCPP_INLINE_VISIBILITY + const _Target& __target() const { return __f_; } + + _LIBCPP_INLINE_VISIBILITY + explicit __default_alloc_func(_Target&& __f) : __f_(_VSTD::move(__f)) {} + + _LIBCPP_INLINE_VISIBILITY + explicit __default_alloc_func(const _Target& __f) : __f_(__f) {} + + _LIBCPP_INLINE_VISIBILITY + _Rp operator()(_ArgTypes&&... __arg) { + typedef __invoke_void_return_wrapper<_Rp> _Invoker; + return _Invoker::__call(__f_, _VSTD::forward<_ArgTypes>(__arg)...); + } + + _LIBCPP_INLINE_VISIBILITY + __default_alloc_func* __clone() const { + __builtin_new_allocator::__holder_t __hold = + __builtin_new_allocator::__allocate_type<__default_alloc_func>(1); + __default_alloc_func* __res = + ::new ((void*)__hold.get()) __default_alloc_func(__f_); + (void)__hold.release(); + return __res; + } + + _LIBCPP_INLINE_VISIBILITY + void destroy() _NOEXCEPT { __f_.~_Target(); } + + static void __destroy_and_delete(__default_alloc_func* __f) { + __f->destroy(); + __builtin_new_allocator::__deallocate_type<__default_alloc_func>(__f, 1); + } +}; + +// __base provides an abstract interface for copyable functors. + +template class _LIBCPP_TEMPLATE_VIS __base; + +template +class __base<_Rp(_ArgTypes...)> +{ + __base(const __base&); + __base& operator=(const __base&); +public: + _LIBCPP_INLINE_VISIBILITY __base() {} + _LIBCPP_HIDE_FROM_ABI_VIRTUAL virtual ~__base() {} + virtual __base* __clone() const = 0; + virtual void __clone(__base*) const = 0; + virtual void destroy() _NOEXCEPT = 0; + virtual void destroy_deallocate() _NOEXCEPT = 0; + virtual _Rp operator()(_ArgTypes&& ...) = 0; +#ifndef _LIBCPP_NO_RTTI + virtual const void* target(const type_info&) const _NOEXCEPT = 0; + virtual const std::type_info& target_type() const _NOEXCEPT = 0; +#endif // _LIBCPP_NO_RTTI +}; + +// __func implements __base for a given functor type. + +template class __func; + +template +class __func<_Fp, _Alloc, _Rp(_ArgTypes...)> + : public __base<_Rp(_ArgTypes...)> +{ + __alloc_func<_Fp, _Alloc, _Rp(_ArgTypes...)> __f_; +public: + _LIBCPP_INLINE_VISIBILITY + explicit __func(_Fp&& __f) + : __f_(_VSTD::move(__f)) {} + + _LIBCPP_INLINE_VISIBILITY + explicit __func(const _Fp& __f, const _Alloc& __a) + : __f_(__f, __a) {} + + _LIBCPP_INLINE_VISIBILITY + explicit __func(const _Fp& __f, _Alloc&& __a) + : __f_(__f, _VSTD::move(__a)) {} + + _LIBCPP_INLINE_VISIBILITY + explicit __func(_Fp&& __f, _Alloc&& __a) + : __f_(_VSTD::move(__f), _VSTD::move(__a)) {} + + virtual __base<_Rp(_ArgTypes...)>* __clone() const; + virtual void __clone(__base<_Rp(_ArgTypes...)>*) const; + virtual void destroy() _NOEXCEPT; + virtual void destroy_deallocate() _NOEXCEPT; + virtual _Rp operator()(_ArgTypes&&... __arg); +#ifndef _LIBCPP_NO_RTTI + virtual const void* target(const type_info&) const _NOEXCEPT; + virtual const std::type_info& target_type() const _NOEXCEPT; +#endif // _LIBCPP_NO_RTTI +}; + +template +__base<_Rp(_ArgTypes...)>* +__func<_Fp, _Alloc, _Rp(_ArgTypes...)>::__clone() const +{ + typedef allocator_traits<_Alloc> __alloc_traits; + typedef __rebind_alloc<__alloc_traits, __func> _Ap; + _Ap __a(__f_.__get_allocator()); + typedef __allocator_destructor<_Ap> _Dp; + unique_ptr<__func, _Dp> __hold(__a.allocate(1), _Dp(__a, 1)); + ::new ((void*)__hold.get()) __func(__f_.__target(), _Alloc(__a)); + return __hold.release(); +} + +template +void +__func<_Fp, _Alloc, _Rp(_ArgTypes...)>::__clone(__base<_Rp(_ArgTypes...)>* __p) const +{ + ::new ((void*)__p) __func(__f_.__target(), __f_.__get_allocator()); +} + +template +void +__func<_Fp, _Alloc, _Rp(_ArgTypes...)>::destroy() _NOEXCEPT +{ + __f_.destroy(); +} + +template +void +__func<_Fp, _Alloc, _Rp(_ArgTypes...)>::destroy_deallocate() _NOEXCEPT +{ + typedef allocator_traits<_Alloc> __alloc_traits; + typedef __rebind_alloc<__alloc_traits, __func> _Ap; + _Ap __a(__f_.__get_allocator()); + __f_.destroy(); + __a.deallocate(this, 1); +} + +template +_Rp +__func<_Fp, _Alloc, _Rp(_ArgTypes...)>::operator()(_ArgTypes&& ... __arg) +{ + return __f_(_VSTD::forward<_ArgTypes>(__arg)...); +} + +#ifndef _LIBCPP_NO_RTTI + +template +const void* +__func<_Fp, _Alloc, _Rp(_ArgTypes...)>::target(const type_info& __ti) const _NOEXCEPT +{ + if (__ti == typeid(_Fp)) + return _VSTD::addressof(__f_.__target()); + return nullptr; +} + +template +const std::type_info& +__func<_Fp, _Alloc, _Rp(_ArgTypes...)>::target_type() const _NOEXCEPT +{ + return typeid(_Fp); +} + +#endif // _LIBCPP_NO_RTTI + +// __value_func creates a value-type from a __func. + +template class __value_func; + +template class __value_func<_Rp(_ArgTypes...)> +{ + _LIBCPP_SUPPRESS_DEPRECATED_PUSH + typename aligned_storage<3 * sizeof(void*)>::type __buf_; + _LIBCPP_SUPPRESS_DEPRECATED_POP + + typedef __base<_Rp(_ArgTypes...)> __func; + __func* __f_; + + _LIBCPP_NO_CFI static __func* __as_base(void* __p) + { + return reinterpret_cast<__func*>(__p); + } + + public: + _LIBCPP_INLINE_VISIBILITY + __value_func() _NOEXCEPT : __f_(nullptr) {} + + template + _LIBCPP_INLINE_VISIBILITY __value_func(_Fp&& __f, const _Alloc& __a) + : __f_(nullptr) + { + typedef allocator_traits<_Alloc> __alloc_traits; + typedef __function::__func<_Fp, _Alloc, _Rp(_ArgTypes...)> _Fun; + typedef __rebind_alloc<__alloc_traits, _Fun> _FunAlloc; + + if (__function::__not_null(__f)) + { + _FunAlloc __af(__a); + if (sizeof(_Fun) <= sizeof(__buf_) && + is_nothrow_copy_constructible<_Fp>::value && + is_nothrow_copy_constructible<_FunAlloc>::value) + { + __f_ = + ::new ((void*)&__buf_) _Fun(_VSTD::move(__f), _Alloc(__af)); + } + else + { + typedef __allocator_destructor<_FunAlloc> _Dp; + unique_ptr<__func, _Dp> __hold(__af.allocate(1), _Dp(__af, 1)); + ::new ((void*)__hold.get()) _Fun(_VSTD::move(__f), _Alloc(__a)); + __f_ = __hold.release(); + } + } + } + + template ::type, __value_func>::value>::type> + _LIBCPP_INLINE_VISIBILITY explicit __value_func(_Fp&& __f) + : __value_func(_VSTD::forward<_Fp>(__f), allocator<_Fp>()) {} + + _LIBCPP_INLINE_VISIBILITY + __value_func(const __value_func& __f) + { + if (__f.__f_ == nullptr) + __f_ = nullptr; + else if ((void*)__f.__f_ == &__f.__buf_) + { + __f_ = __as_base(&__buf_); + __f.__f_->__clone(__f_); + } + else + __f_ = __f.__f_->__clone(); + } + + _LIBCPP_INLINE_VISIBILITY + __value_func(__value_func&& __f) _NOEXCEPT + { + if (__f.__f_ == nullptr) + __f_ = nullptr; + else if ((void*)__f.__f_ == &__f.__buf_) + { + __f_ = __as_base(&__buf_); + __f.__f_->__clone(__f_); + } + else + { + __f_ = __f.__f_; + __f.__f_ = nullptr; + } + } + + _LIBCPP_INLINE_VISIBILITY + ~__value_func() + { + if ((void*)__f_ == &__buf_) + __f_->destroy(); + else if (__f_) + __f_->destroy_deallocate(); + } + + _LIBCPP_INLINE_VISIBILITY + __value_func& operator=(__value_func&& __f) + { + *this = nullptr; + if (__f.__f_ == nullptr) + __f_ = nullptr; + else if ((void*)__f.__f_ == &__f.__buf_) + { + __f_ = __as_base(&__buf_); + __f.__f_->__clone(__f_); + } + else + { + __f_ = __f.__f_; + __f.__f_ = nullptr; + } + return *this; + } + + _LIBCPP_INLINE_VISIBILITY + __value_func& operator=(nullptr_t) + { + __func* __f = __f_; + __f_ = nullptr; + if ((void*)__f == &__buf_) + __f->destroy(); + else if (__f) + __f->destroy_deallocate(); + return *this; + } + + _LIBCPP_INLINE_VISIBILITY + _Rp operator()(_ArgTypes&&... __args) const + { + if (__f_ == nullptr) + __throw_bad_function_call(); + return (*__f_)(_VSTD::forward<_ArgTypes>(__args)...); + } + + _LIBCPP_INLINE_VISIBILITY + void swap(__value_func& __f) _NOEXCEPT + { + if (&__f == this) + return; + if ((void*)__f_ == &__buf_ && (void*)__f.__f_ == &__f.__buf_) + { + _LIBCPP_SUPPRESS_DEPRECATED_PUSH + typename aligned_storage::type __tempbuf; + _LIBCPP_SUPPRESS_DEPRECATED_POP + __func* __t = __as_base(&__tempbuf); + __f_->__clone(__t); + __f_->destroy(); + __f_ = nullptr; + __f.__f_->__clone(__as_base(&__buf_)); + __f.__f_->destroy(); + __f.__f_ = nullptr; + __f_ = __as_base(&__buf_); + __t->__clone(__as_base(&__f.__buf_)); + __t->destroy(); + __f.__f_ = __as_base(&__f.__buf_); + } + else if ((void*)__f_ == &__buf_) + { + __f_->__clone(__as_base(&__f.__buf_)); + __f_->destroy(); + __f_ = __f.__f_; + __f.__f_ = __as_base(&__f.__buf_); + } + else if ((void*)__f.__f_ == &__f.__buf_) + { + __f.__f_->__clone(__as_base(&__buf_)); + __f.__f_->destroy(); + __f.__f_ = __f_; + __f_ = __as_base(&__buf_); + } + else + _VSTD::swap(__f_, __f.__f_); + } + + _LIBCPP_INLINE_VISIBILITY + explicit operator bool() const _NOEXCEPT { return __f_ != nullptr; } + +#ifndef _LIBCPP_NO_RTTI + _LIBCPP_INLINE_VISIBILITY + const std::type_info& target_type() const _NOEXCEPT + { + if (__f_ == nullptr) + return typeid(void); + return __f_->target_type(); + } + + template + _LIBCPP_INLINE_VISIBILITY const _Tp* target() const _NOEXCEPT + { + if (__f_ == nullptr) + return nullptr; + return (const _Tp*)__f_->target(typeid(_Tp)); + } +#endif // _LIBCPP_NO_RTTI +}; + +// Storage for a functor object, to be used with __policy to manage copy and +// destruction. +union __policy_storage +{ + mutable char __small[sizeof(void*) * 2]; + void* __large; +}; + +// True if _Fun can safely be held in __policy_storage.__small. +template +struct __use_small_storage + : public integral_constant< + bool, sizeof(_Fun) <= sizeof(__policy_storage) && + _LIBCPP_ALIGNOF(_Fun) <= _LIBCPP_ALIGNOF(__policy_storage) && + is_trivially_copy_constructible<_Fun>::value && + is_trivially_destructible<_Fun>::value> {}; + +// Policy contains information about how to copy, destroy, and move the +// underlying functor. You can think of it as a vtable of sorts. +struct __policy +{ + // Used to copy or destroy __large values. null for trivial objects. + void* (*const __clone)(const void*); + void (*const __destroy)(void*); + + // True if this is the null policy (no value). + const bool __is_null; + + // The target type. May be null if RTTI is disabled. + const std::type_info* const __type_info; + + // Returns a pointer to a static policy object suitable for the functor + // type. + template + _LIBCPP_INLINE_VISIBILITY static const __policy* __create() + { + return __choose_policy<_Fun>(__use_small_storage<_Fun>()); + } + + _LIBCPP_INLINE_VISIBILITY + static const __policy* __create_empty() + { + static const _LIBCPP_CONSTEXPR __policy __policy_ = {nullptr, nullptr, + true, +#ifndef _LIBCPP_NO_RTTI + &typeid(void) +#else + nullptr +#endif + }; + return &__policy_; + } + + private: + template static void* __large_clone(const void* __s) + { + const _Fun* __f = static_cast(__s); + return __f->__clone(); + } + + template + static void __large_destroy(void* __s) { + _Fun::__destroy_and_delete(static_cast<_Fun*>(__s)); + } + + template + _LIBCPP_INLINE_VISIBILITY static const __policy* + __choose_policy(/* is_small = */ false_type) { + static const _LIBCPP_CONSTEXPR __policy __policy_ = { + &__large_clone<_Fun>, &__large_destroy<_Fun>, false, +#ifndef _LIBCPP_NO_RTTI + &typeid(typename _Fun::_Target) +#else + nullptr +#endif + }; + return &__policy_; + } + + template + _LIBCPP_INLINE_VISIBILITY static const __policy* + __choose_policy(/* is_small = */ true_type) + { + static const _LIBCPP_CONSTEXPR __policy __policy_ = { + nullptr, nullptr, false, +#ifndef _LIBCPP_NO_RTTI + &typeid(typename _Fun::_Target) +#else + nullptr +#endif + }; + return &__policy_; + } +}; + +// Used to choose between perfect forwarding or pass-by-value. Pass-by-value is +// faster for types that can be passed in registers. +template +using __fast_forward = __conditional_t::value, _Tp, _Tp&&>; + +// __policy_invoker calls an instance of __alloc_func held in __policy_storage. + +template struct __policy_invoker; + +template +struct __policy_invoker<_Rp(_ArgTypes...)> +{ + typedef _Rp (*__Call)(const __policy_storage*, + __fast_forward<_ArgTypes>...); + + __Call __call_; + + // Creates an invoker that throws bad_function_call. + _LIBCPP_INLINE_VISIBILITY + __policy_invoker() : __call_(&__call_empty) {} + + // Creates an invoker that calls the given instance of __func. + template + _LIBCPP_INLINE_VISIBILITY static __policy_invoker __create() + { + return __policy_invoker(&__call_impl<_Fun>); + } + + private: + _LIBCPP_INLINE_VISIBILITY + explicit __policy_invoker(__Call __c) : __call_(__c) {} + + static _Rp __call_empty(const __policy_storage*, + __fast_forward<_ArgTypes>...) + { + __throw_bad_function_call(); + } + + template + static _Rp __call_impl(const __policy_storage* __buf, + __fast_forward<_ArgTypes>... __args) + { + _Fun* __f = reinterpret_cast<_Fun*>(__use_small_storage<_Fun>::value + ? &__buf->__small + : __buf->__large); + return (*__f)(_VSTD::forward<_ArgTypes>(__args)...); + } +}; + +// __policy_func uses a __policy and __policy_invoker to create a type-erased, +// copyable functor. + +template class __policy_func; + +template class __policy_func<_Rp(_ArgTypes...)> +{ + // Inline storage for small objects. + __policy_storage __buf_; + + // Calls the value stored in __buf_. This could technically be part of + // policy, but storing it here eliminates a level of indirection inside + // operator(). + typedef __function::__policy_invoker<_Rp(_ArgTypes...)> __invoker; + __invoker __invoker_; + + // The policy that describes how to move / copy / destroy __buf_. Never + // null, even if the function is empty. + const __policy* __policy_; + + public: + _LIBCPP_INLINE_VISIBILITY + __policy_func() : __policy_(__policy::__create_empty()) {} + + template + _LIBCPP_INLINE_VISIBILITY __policy_func(_Fp&& __f, const _Alloc& __a) + : __policy_(__policy::__create_empty()) + { + typedef __alloc_func<_Fp, _Alloc, _Rp(_ArgTypes...)> _Fun; + typedef allocator_traits<_Alloc> __alloc_traits; + typedef __rebind_alloc<__alloc_traits, _Fun> _FunAlloc; + + if (__function::__not_null(__f)) + { + __invoker_ = __invoker::template __create<_Fun>(); + __policy_ = __policy::__create<_Fun>(); + + _FunAlloc __af(__a); + if (__use_small_storage<_Fun>()) + { + ::new ((void*)&__buf_.__small) + _Fun(_VSTD::move(__f), _Alloc(__af)); + } + else + { + typedef __allocator_destructor<_FunAlloc> _Dp; + unique_ptr<_Fun, _Dp> __hold(__af.allocate(1), _Dp(__af, 1)); + ::new ((void*)__hold.get()) + _Fun(_VSTD::move(__f), _Alloc(__af)); + __buf_.__large = __hold.release(); + } + } + } + + template ::type, __policy_func>::value>::type> + _LIBCPP_INLINE_VISIBILITY explicit __policy_func(_Fp&& __f) + : __policy_(__policy::__create_empty()) { + typedef __default_alloc_func<_Fp, _Rp(_ArgTypes...)> _Fun; + + if (__function::__not_null(__f)) { + __invoker_ = __invoker::template __create<_Fun>(); + __policy_ = __policy::__create<_Fun>(); + if (__use_small_storage<_Fun>()) { + ::new ((void*)&__buf_.__small) _Fun(_VSTD::move(__f)); + } else { + __builtin_new_allocator::__holder_t __hold = + __builtin_new_allocator::__allocate_type<_Fun>(1); + __buf_.__large = ::new ((void*)__hold.get()) _Fun(_VSTD::move(__f)); + (void)__hold.release(); + } + } + } + + _LIBCPP_INLINE_VISIBILITY + __policy_func(const __policy_func& __f) + : __buf_(__f.__buf_), __invoker_(__f.__invoker_), + __policy_(__f.__policy_) + { + if (__policy_->__clone) + __buf_.__large = __policy_->__clone(__f.__buf_.__large); + } + + _LIBCPP_INLINE_VISIBILITY + __policy_func(__policy_func&& __f) + : __buf_(__f.__buf_), __invoker_(__f.__invoker_), + __policy_(__f.__policy_) + { + if (__policy_->__destroy) + { + __f.__policy_ = __policy::__create_empty(); + __f.__invoker_ = __invoker(); + } + } + + _LIBCPP_INLINE_VISIBILITY + ~__policy_func() + { + if (__policy_->__destroy) + __policy_->__destroy(__buf_.__large); + } + + _LIBCPP_INLINE_VISIBILITY + __policy_func& operator=(__policy_func&& __f) + { + *this = nullptr; + __buf_ = __f.__buf_; + __invoker_ = __f.__invoker_; + __policy_ = __f.__policy_; + __f.__policy_ = __policy::__create_empty(); + __f.__invoker_ = __invoker(); + return *this; + } + + _LIBCPP_INLINE_VISIBILITY + __policy_func& operator=(nullptr_t) + { + const __policy* __p = __policy_; + __policy_ = __policy::__create_empty(); + __invoker_ = __invoker(); + if (__p->__destroy) + __p->__destroy(__buf_.__large); + return *this; + } + + _LIBCPP_INLINE_VISIBILITY + _Rp operator()(_ArgTypes&&... __args) const + { + return __invoker_.__call_(_VSTD::addressof(__buf_), + _VSTD::forward<_ArgTypes>(__args)...); + } + + _LIBCPP_INLINE_VISIBILITY + void swap(__policy_func& __f) + { + _VSTD::swap(__invoker_, __f.__invoker_); + _VSTD::swap(__policy_, __f.__policy_); + _VSTD::swap(__buf_, __f.__buf_); + } + + _LIBCPP_INLINE_VISIBILITY + explicit operator bool() const _NOEXCEPT + { + return !__policy_->__is_null; + } + +#ifndef _LIBCPP_NO_RTTI + _LIBCPP_INLINE_VISIBILITY + const std::type_info& target_type() const _NOEXCEPT + { + return *__policy_->__type_info; + } + + template + _LIBCPP_INLINE_VISIBILITY const _Tp* target() const _NOEXCEPT + { + if (__policy_->__is_null || typeid(_Tp) != *__policy_->__type_info) + return nullptr; + if (__policy_->__clone) // Out of line storage. + return reinterpret_cast(__buf_.__large); + else + return reinterpret_cast(&__buf_.__small); + } +#endif // _LIBCPP_NO_RTTI +}; + +#if defined(_LIBCPP_HAS_BLOCKS_RUNTIME) + +extern "C" void *_Block_copy(const void *); +extern "C" void _Block_release(const void *); + +template +class __func<_Rp1(^)(_ArgTypes1...), _Alloc, _Rp(_ArgTypes...)> + : public __base<_Rp(_ArgTypes...)> +{ + typedef _Rp1(^__block_type)(_ArgTypes1...); + __block_type __f_; + +public: + _LIBCPP_INLINE_VISIBILITY + explicit __func(__block_type const& __f) +#ifdef _LIBCPP_HAS_OBJC_ARC + : __f_(__f) +#else + : __f_(reinterpret_cast<__block_type>(__f ? _Block_copy(__f) : nullptr)) +#endif + { } + + // [TODO] add && to save on a retain + + _LIBCPP_INLINE_VISIBILITY + explicit __func(__block_type __f, const _Alloc& /* unused */) +#ifdef _LIBCPP_HAS_OBJC_ARC + : __f_(__f) +#else + : __f_(reinterpret_cast<__block_type>(__f ? _Block_copy(__f) : nullptr)) +#endif + { } + + virtual __base<_Rp(_ArgTypes...)>* __clone() const { + _LIBCPP_ASSERT(false, + "Block pointers are just pointers, so they should always fit into " + "std::function's small buffer optimization. This function should " + "never be invoked."); + return nullptr; + } + + virtual void __clone(__base<_Rp(_ArgTypes...)>* __p) const { + ::new ((void*)__p) __func(__f_); + } + + virtual void destroy() _NOEXCEPT { +#ifndef _LIBCPP_HAS_OBJC_ARC + if (__f_) + _Block_release(__f_); +#endif + __f_ = 0; + } + + virtual void destroy_deallocate() _NOEXCEPT { + _LIBCPP_ASSERT(false, + "Block pointers are just pointers, so they should always fit into " + "std::function's small buffer optimization. This function should " + "never be invoked."); + } + + virtual _Rp operator()(_ArgTypes&& ... __arg) { + return _VSTD::__invoke(__f_, _VSTD::forward<_ArgTypes>(__arg)...); + } + +#ifndef _LIBCPP_NO_RTTI + virtual const void* target(type_info const& __ti) const _NOEXCEPT { + if (__ti == typeid(__func::__block_type)) + return &__f_; + return (const void*)nullptr; + } + + virtual const std::type_info& target_type() const _NOEXCEPT { + return typeid(__func::__block_type); + } +#endif // _LIBCPP_NO_RTTI +}; + +#endif // _LIBCPP_HAS_EXTENSION_BLOCKS + +} // namespace __function + +template +class _LIBCPP_TEMPLATE_VIS function<_Rp(_ArgTypes...)> + : public __function::__maybe_derive_from_unary_function<_Rp(_ArgTypes...)>, + public __function::__maybe_derive_from_binary_function<_Rp(_ArgTypes...)> +{ +#ifndef _LIBCPP_ABI_OPTIMIZED_FUNCTION + typedef __function::__value_func<_Rp(_ArgTypes...)> __func; +#else + typedef __function::__policy_func<_Rp(_ArgTypes...)> __func; +#endif + + __func __f_; + + template , function>, + __invokable<_Fp, _ArgTypes...> + >::value> + struct __callable; + template + struct __callable<_Fp, true> + { + static const bool value = is_void<_Rp>::value || + __is_core_convertible::type, + _Rp>::value; + }; + template + struct __callable<_Fp, false> + { + static const bool value = false; + }; + + template + using _EnableIfLValueCallable = typename enable_if<__callable<_Fp&>::value>::type; +public: + typedef _Rp result_type; + + // construct/copy/destroy: + _LIBCPP_INLINE_VISIBILITY + function() _NOEXCEPT { } + _LIBCPP_INLINE_VISIBILITY + function(nullptr_t) _NOEXCEPT {} + function(const function&); + function(function&&) _NOEXCEPT; + template> + function(_Fp); + +#if _LIBCPP_STD_VER <= 14 + template + _LIBCPP_INLINE_VISIBILITY + function(allocator_arg_t, const _Alloc&) _NOEXCEPT {} + template + _LIBCPP_INLINE_VISIBILITY + function(allocator_arg_t, const _Alloc&, nullptr_t) _NOEXCEPT {} + template + function(allocator_arg_t, const _Alloc&, const function&); + template + function(allocator_arg_t, const _Alloc&, function&&); + template> + function(allocator_arg_t, const _Alloc& __a, _Fp __f); +#endif + + function& operator=(const function&); + function& operator=(function&&) _NOEXCEPT; + function& operator=(nullptr_t) _NOEXCEPT; + template::type>> + function& operator=(_Fp&&); + + ~function(); + + // function modifiers: + void swap(function&) _NOEXCEPT; + +#if _LIBCPP_STD_VER <= 14 + template + _LIBCPP_INLINE_VISIBILITY + void assign(_Fp&& __f, const _Alloc& __a) + {function(allocator_arg, __a, _VSTD::forward<_Fp>(__f)).swap(*this);} +#endif + + // function capacity: + _LIBCPP_INLINE_VISIBILITY + explicit operator bool() const _NOEXCEPT { + return static_cast(__f_); + } + + // deleted overloads close possible hole in the type system + template + bool operator==(const function<_R2(_ArgTypes2...)>&) const = delete; + template + bool operator!=(const function<_R2(_ArgTypes2...)>&) const = delete; +public: + // function invocation: + _Rp operator()(_ArgTypes...) const; + +#ifndef _LIBCPP_NO_RTTI + // function target access: + const std::type_info& target_type() const _NOEXCEPT; + template _Tp* target() _NOEXCEPT; + template const _Tp* target() const _NOEXCEPT; +#endif // _LIBCPP_NO_RTTI +}; + +#if _LIBCPP_STD_VER >= 17 +template +function(_Rp(*)(_Ap...)) -> function<_Rp(_Ap...)>; + +template::type> +function(_Fp) -> function<_Stripped>; +#endif // _LIBCPP_STD_VER >= 17 + +template +function<_Rp(_ArgTypes...)>::function(const function& __f) : __f_(__f.__f_) {} + +#if _LIBCPP_STD_VER <= 14 +template +template +function<_Rp(_ArgTypes...)>::function(allocator_arg_t, const _Alloc&, + const function& __f) : __f_(__f.__f_) {} +#endif + +template +function<_Rp(_ArgTypes...)>::function(function&& __f) _NOEXCEPT + : __f_(_VSTD::move(__f.__f_)) {} + +#if _LIBCPP_STD_VER <= 14 +template +template +function<_Rp(_ArgTypes...)>::function(allocator_arg_t, const _Alloc&, + function&& __f) + : __f_(_VSTD::move(__f.__f_)) {} +#endif + +template +template +function<_Rp(_ArgTypes...)>::function(_Fp __f) : __f_(_VSTD::move(__f)) {} + +#if _LIBCPP_STD_VER <= 14 +template +template +function<_Rp(_ArgTypes...)>::function(allocator_arg_t, const _Alloc& __a, + _Fp __f) + : __f_(_VSTD::move(__f), __a) {} +#endif + +template +function<_Rp(_ArgTypes...)>& +function<_Rp(_ArgTypes...)>::operator=(const function& __f) +{ + function(__f).swap(*this); + return *this; +} + +template +function<_Rp(_ArgTypes...)>& +function<_Rp(_ArgTypes...)>::operator=(function&& __f) _NOEXCEPT +{ + __f_ = _VSTD::move(__f.__f_); + return *this; +} + +template +function<_Rp(_ArgTypes...)>& +function<_Rp(_ArgTypes...)>::operator=(nullptr_t) _NOEXCEPT +{ + __f_ = nullptr; + return *this; +} + +template +template +function<_Rp(_ArgTypes...)>& +function<_Rp(_ArgTypes...)>::operator=(_Fp&& __f) +{ + function(_VSTD::forward<_Fp>(__f)).swap(*this); + return *this; +} + +template +function<_Rp(_ArgTypes...)>::~function() {} + +template +void +function<_Rp(_ArgTypes...)>::swap(function& __f) _NOEXCEPT +{ + __f_.swap(__f.__f_); +} + +template +_Rp +function<_Rp(_ArgTypes...)>::operator()(_ArgTypes... __arg) const +{ + return __f_(_VSTD::forward<_ArgTypes>(__arg)...); +} + +#ifndef _LIBCPP_NO_RTTI + +template +const std::type_info& +function<_Rp(_ArgTypes...)>::target_type() const _NOEXCEPT +{ + return __f_.target_type(); +} + +template +template +_Tp* +function<_Rp(_ArgTypes...)>::target() _NOEXCEPT +{ + return (_Tp*)(__f_.template target<_Tp>()); +} + +template +template +const _Tp* +function<_Rp(_ArgTypes...)>::target() const _NOEXCEPT +{ + return __f_.template target<_Tp>(); +} + +#endif // _LIBCPP_NO_RTTI + +template +inline _LIBCPP_INLINE_VISIBILITY +bool +operator==(const function<_Rp(_ArgTypes...)>& __f, nullptr_t) _NOEXCEPT {return !__f;} + +template +inline _LIBCPP_INLINE_VISIBILITY +bool +operator==(nullptr_t, const function<_Rp(_ArgTypes...)>& __f) _NOEXCEPT {return !__f;} + +template +inline _LIBCPP_INLINE_VISIBILITY +bool +operator!=(const function<_Rp(_ArgTypes...)>& __f, nullptr_t) _NOEXCEPT {return (bool)__f;} + +template +inline _LIBCPP_INLINE_VISIBILITY +bool +operator!=(nullptr_t, const function<_Rp(_ArgTypes...)>& __f) _NOEXCEPT {return (bool)__f;} + +template +inline _LIBCPP_INLINE_VISIBILITY +void +swap(function<_Rp(_ArgTypes...)>& __x, function<_Rp(_ArgTypes...)>& __y) _NOEXCEPT +{return __x.swap(__y);} + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_CXX03_LANG + +#endif // _LIBCPP___FUNCTIONAL_FUNCTION_H diff --git a/app/src/main/cpp/libcxx/include/__functional/hash.h b/app/src/main/cpp/libcxx/include/__functional/hash.h new file mode 100644 index 0000000..dfd8ea2 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__functional/hash.h @@ -0,0 +1,693 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___FUNCTIONAL_HASH_H +#define _LIBCPP___FUNCTIONAL_HASH_H + +#include <__config> +#include <__functional/invoke.h> +#include <__functional/unary_function.h> +#include <__fwd/hash.h> +#include <__tuple_dir/sfinae_helpers.h> +#include <__type_traits/is_copy_constructible.h> +#include <__type_traits/is_default_constructible.h> +#include <__type_traits/is_enum.h> +#include <__type_traits/is_move_constructible.h> +#include <__type_traits/underlying_type.h> +#include <__utility/forward.h> +#include <__utility/move.h> +#include <__utility/pair.h> +#include <__utility/swap.h> +#include +#include +#include +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +template +inline _LIBCPP_INLINE_VISIBILITY +_Size +__loadword(const void* __p) +{ + _Size __r; + _VSTD::memcpy(&__r, __p, sizeof(__r)); + return __r; +} + +// We use murmur2 when size_t is 32 bits, and cityhash64 when size_t +// is 64 bits. This is because cityhash64 uses 64bit x 64bit +// multiplication, which can be very slow on 32-bit systems. +template +struct __murmur2_or_cityhash; + +template +struct __murmur2_or_cityhash<_Size, 32> +{ + inline _Size operator()(const void* __key, _Size __len) + _LIBCPP_DISABLE_UBSAN_UNSIGNED_INTEGER_CHECK; +}; + +// murmur2 +template +_Size +__murmur2_or_cityhash<_Size, 32>::operator()(const void* __key, _Size __len) +{ + const _Size __m = 0x5bd1e995; + const _Size __r = 24; + _Size __h = __len; + const unsigned char* __data = static_cast(__key); + for (; __len >= 4; __data += 4, __len -= 4) + { + _Size __k = std::__loadword<_Size>(__data); + __k *= __m; + __k ^= __k >> __r; + __k *= __m; + __h *= __m; + __h ^= __k; + } + switch (__len) + { + case 3: + __h ^= static_cast<_Size>(__data[2] << 16); + _LIBCPP_FALLTHROUGH(); + case 2: + __h ^= static_cast<_Size>(__data[1] << 8); + _LIBCPP_FALLTHROUGH(); + case 1: + __h ^= __data[0]; + __h *= __m; + } + __h ^= __h >> 13; + __h *= __m; + __h ^= __h >> 15; + return __h; +} + +template +struct __murmur2_or_cityhash<_Size, 64> +{ + inline _Size operator()(const void* __key, _Size __len) _LIBCPP_DISABLE_UBSAN_UNSIGNED_INTEGER_CHECK; + + private: + // Some primes between 2^63 and 2^64. + static const _Size __k0 = 0xc3a5c85c97cb3127ULL; + static const _Size __k1 = 0xb492b66fbe98f273ULL; + static const _Size __k2 = 0x9ae16a3b2f90404fULL; + static const _Size __k3 = 0xc949d7c7509e6557ULL; + + static _Size __rotate(_Size __val, int __shift) { + return __shift == 0 ? __val : ((__val >> __shift) | (__val << (64 - __shift))); + } + + static _Size __rotate_by_at_least_1(_Size __val, int __shift) { + return (__val >> __shift) | (__val << (64 - __shift)); + } + + static _Size __shift_mix(_Size __val) { + return __val ^ (__val >> 47); + } + + static _Size __hash_len_16(_Size __u, _Size __v) + _LIBCPP_DISABLE_UBSAN_UNSIGNED_INTEGER_CHECK + { + const _Size __mul = 0x9ddfea08eb382d69ULL; + _Size __a = (__u ^ __v) * __mul; + __a ^= (__a >> 47); + _Size __b = (__v ^ __a) * __mul; + __b ^= (__b >> 47); + __b *= __mul; + return __b; + } + + static _Size __hash_len_0_to_16(const char* __s, _Size __len) + _LIBCPP_DISABLE_UBSAN_UNSIGNED_INTEGER_CHECK + { + if (__len > 8) { + const _Size __a = std::__loadword<_Size>(__s); + const _Size __b = std::__loadword<_Size>(__s + __len - 8); + return __hash_len_16(__a, __rotate_by_at_least_1(__b + __len, __len)) ^ __b; + } + if (__len >= 4) { + const uint32_t __a = std::__loadword(__s); + const uint32_t __b = std::__loadword(__s + __len - 4); + return __hash_len_16(__len + (static_cast<_Size>(__a) << 3), __b); + } + if (__len > 0) { + const unsigned char __a = static_cast(__s[0]); + const unsigned char __b = static_cast(__s[__len >> 1]); + const unsigned char __c = static_cast(__s[__len - 1]); + const uint32_t __y = static_cast(__a) + + (static_cast(__b) << 8); + const uint32_t __z = __len + (static_cast(__c) << 2); + return __shift_mix(__y * __k2 ^ __z * __k3) * __k2; + } + return __k2; + } + + static _Size __hash_len_17_to_32(const char *__s, _Size __len) + _LIBCPP_DISABLE_UBSAN_UNSIGNED_INTEGER_CHECK + { + const _Size __a = std::__loadword<_Size>(__s) * __k1; + const _Size __b = std::__loadword<_Size>(__s + 8); + const _Size __c = std::__loadword<_Size>(__s + __len - 8) * __k2; + const _Size __d = std::__loadword<_Size>(__s + __len - 16) * __k0; + return __hash_len_16(__rotate(__a - __b, 43) + __rotate(__c, 30) + __d, + __a + __rotate(__b ^ __k3, 20) - __c + __len); + } + + // Return a 16-byte hash for 48 bytes. Quick and dirty. + // Callers do best to use "random-looking" values for a and b. + static pair<_Size, _Size> __weak_hash_len_32_with_seeds( + _Size __w, _Size __x, _Size __y, _Size __z, _Size __a, _Size __b) + _LIBCPP_DISABLE_UBSAN_UNSIGNED_INTEGER_CHECK + { + __a += __w; + __b = __rotate(__b + __a + __z, 21); + const _Size __c = __a; + __a += __x; + __a += __y; + __b += __rotate(__a, 44); + return pair<_Size, _Size>(__a + __z, __b + __c); + } + + // Return a 16-byte hash for s[0] ... s[31], a, and b. Quick and dirty. + static pair<_Size, _Size> __weak_hash_len_32_with_seeds( + const char* __s, _Size __a, _Size __b) + _LIBCPP_DISABLE_UBSAN_UNSIGNED_INTEGER_CHECK + { + return __weak_hash_len_32_with_seeds(std::__loadword<_Size>(__s), + std::__loadword<_Size>(__s + 8), + std::__loadword<_Size>(__s + 16), + std::__loadword<_Size>(__s + 24), + __a, + __b); + } + + // Return an 8-byte hash for 33 to 64 bytes. + static _Size __hash_len_33_to_64(const char *__s, size_t __len) + _LIBCPP_DISABLE_UBSAN_UNSIGNED_INTEGER_CHECK + { + _Size __z = std::__loadword<_Size>(__s + 24); + _Size __a = std::__loadword<_Size>(__s) + + (__len + std::__loadword<_Size>(__s + __len - 16)) * __k0; + _Size __b = __rotate(__a + __z, 52); + _Size __c = __rotate(__a, 37); + __a += std::__loadword<_Size>(__s + 8); + __c += __rotate(__a, 7); + __a += std::__loadword<_Size>(__s + 16); + _Size __vf = __a + __z; + _Size __vs = __b + __rotate(__a, 31) + __c; + __a = std::__loadword<_Size>(__s + 16) + std::__loadword<_Size>(__s + __len - 32); + __z += std::__loadword<_Size>(__s + __len - 8); + __b = __rotate(__a + __z, 52); + __c = __rotate(__a, 37); + __a += std::__loadword<_Size>(__s + __len - 24); + __c += __rotate(__a, 7); + __a += std::__loadword<_Size>(__s + __len - 16); + _Size __wf = __a + __z; + _Size __ws = __b + __rotate(__a, 31) + __c; + _Size __r = __shift_mix((__vf + __ws) * __k2 + (__wf + __vs) * __k0); + return __shift_mix(__r * __k0 + __vs) * __k2; + } +}; + +// cityhash64 +template +_Size +__murmur2_or_cityhash<_Size, 64>::operator()(const void* __key, _Size __len) +{ + const char* __s = static_cast(__key); + if (__len <= 32) { + if (__len <= 16) { + return __hash_len_0_to_16(__s, __len); + } else { + return __hash_len_17_to_32(__s, __len); + } + } else if (__len <= 64) { + return __hash_len_33_to_64(__s, __len); + } + + // For strings over 64 bytes we hash the end first, and then as we + // loop we keep 56 bytes of state: v, w, x, y, and z. + _Size __x = std::__loadword<_Size>(__s + __len - 40); + _Size __y = std::__loadword<_Size>(__s + __len - 16) + + std::__loadword<_Size>(__s + __len - 56); + _Size __z = __hash_len_16(std::__loadword<_Size>(__s + __len - 48) + __len, + std::__loadword<_Size>(__s + __len - 24)); + pair<_Size, _Size> __v = __weak_hash_len_32_with_seeds(__s + __len - 64, __len, __z); + pair<_Size, _Size> __w = __weak_hash_len_32_with_seeds(__s + __len - 32, __y + __k1, __x); + __x = __x * __k1 + std::__loadword<_Size>(__s); + + // Decrease len to the nearest multiple of 64, and operate on 64-byte chunks. + __len = (__len - 1) & ~static_cast<_Size>(63); + do { + __x = __rotate(__x + __y + __v.first + std::__loadword<_Size>(__s + 8), 37) * __k1; + __y = __rotate(__y + __v.second + std::__loadword<_Size>(__s + 48), 42) * __k1; + __x ^= __w.second; + __y += __v.first + std::__loadword<_Size>(__s + 40); + __z = __rotate(__z + __w.first, 33) * __k1; + __v = __weak_hash_len_32_with_seeds(__s, __v.second * __k1, __x + __w.first); + __w = __weak_hash_len_32_with_seeds(__s + 32, __z + __w.second, + __y + std::__loadword<_Size>(__s + 16)); + _VSTD::swap(__z, __x); + __s += 64; + __len -= 64; + } while (__len != 0); + return __hash_len_16( + __hash_len_16(__v.first, __w.first) + __shift_mix(__y) * __k1 + __z, + __hash_len_16(__v.second, __w.second) + __x); +} + +template +struct __scalar_hash; + +template +struct __scalar_hash<_Tp, 0> + : public __unary_function<_Tp, size_t> +{ + _LIBCPP_INLINE_VISIBILITY + size_t operator()(_Tp __v) const _NOEXCEPT + { + union + { + _Tp __t; + size_t __a; + } __u; + __u.__a = 0; + __u.__t = __v; + return __u.__a; + } +}; + +template +struct __scalar_hash<_Tp, 1> + : public __unary_function<_Tp, size_t> +{ + _LIBCPP_INLINE_VISIBILITY + size_t operator()(_Tp __v) const _NOEXCEPT + { + union + { + _Tp __t; + size_t __a; + } __u; + __u.__t = __v; + return __u.__a; + } +}; + +template +struct __scalar_hash<_Tp, 2> + : public __unary_function<_Tp, size_t> +{ + _LIBCPP_INLINE_VISIBILITY + size_t operator()(_Tp __v) const _NOEXCEPT + { + union + { + _Tp __t; + struct + { + size_t __a; + size_t __b; + } __s; + } __u; + __u.__t = __v; + return __murmur2_or_cityhash()(&__u, sizeof(__u)); + } +}; + +template +struct __scalar_hash<_Tp, 3> + : public __unary_function<_Tp, size_t> +{ + _LIBCPP_INLINE_VISIBILITY + size_t operator()(_Tp __v) const _NOEXCEPT + { + union + { + _Tp __t; + struct + { + size_t __a; + size_t __b; + size_t __c; + } __s; + } __u; + __u.__t = __v; + return __murmur2_or_cityhash()(&__u, sizeof(__u)); + } +}; + +template +struct __scalar_hash<_Tp, 4> + : public __unary_function<_Tp, size_t> +{ + _LIBCPP_INLINE_VISIBILITY + size_t operator()(_Tp __v) const _NOEXCEPT + { + union + { + _Tp __t; + struct + { + size_t __a; + size_t __b; + size_t __c; + size_t __d; + } __s; + } __u; + __u.__t = __v; + return __murmur2_or_cityhash()(&__u, sizeof(__u)); + } +}; + +struct _PairT { + size_t first; + size_t second; +}; + +_LIBCPP_INLINE_VISIBILITY +inline size_t __hash_combine(size_t __lhs, size_t __rhs) _NOEXCEPT { + typedef __scalar_hash<_PairT> _HashT; + const _PairT __p = {__lhs, __rhs}; + return _HashT()(__p); +} + +template +struct _LIBCPP_TEMPLATE_VIS hash<_Tp*> + : public __unary_function<_Tp*, size_t> +{ + _LIBCPP_INLINE_VISIBILITY + size_t operator()(_Tp* __v) const _NOEXCEPT + { + union + { + _Tp* __t; + size_t __a; + } __u; + __u.__t = __v; + return __murmur2_or_cityhash()(&__u, sizeof(__u)); + } +}; + +template <> +struct _LIBCPP_TEMPLATE_VIS hash + : public __unary_function +{ + _LIBCPP_INLINE_VISIBILITY + size_t operator()(bool __v) const _NOEXCEPT {return static_cast(__v);} +}; + +template <> +struct _LIBCPP_TEMPLATE_VIS hash + : public __unary_function +{ + _LIBCPP_INLINE_VISIBILITY + size_t operator()(char __v) const _NOEXCEPT {return static_cast(__v);} +}; + +template <> +struct _LIBCPP_TEMPLATE_VIS hash + : public __unary_function +{ + _LIBCPP_INLINE_VISIBILITY + size_t operator()(signed char __v) const _NOEXCEPT {return static_cast(__v);} +}; + +template <> +struct _LIBCPP_TEMPLATE_VIS hash + : public __unary_function +{ + _LIBCPP_INLINE_VISIBILITY + size_t operator()(unsigned char __v) const _NOEXCEPT {return static_cast(__v);} +}; + +#ifndef _LIBCPP_HAS_NO_CHAR8_T +template <> +struct _LIBCPP_TEMPLATE_VIS hash + : public __unary_function +{ + _LIBCPP_INLINE_VISIBILITY + size_t operator()(char8_t __v) const _NOEXCEPT {return static_cast(__v);} +}; +#endif // !_LIBCPP_HAS_NO_CHAR8_T + +template <> +struct _LIBCPP_TEMPLATE_VIS hash + : public __unary_function +{ + _LIBCPP_INLINE_VISIBILITY + size_t operator()(char16_t __v) const _NOEXCEPT {return static_cast(__v);} +}; + +template <> +struct _LIBCPP_TEMPLATE_VIS hash + : public __unary_function +{ + _LIBCPP_INLINE_VISIBILITY + size_t operator()(char32_t __v) const _NOEXCEPT {return static_cast(__v);} +}; + +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +template <> +struct _LIBCPP_TEMPLATE_VIS hash + : public __unary_function +{ + _LIBCPP_INLINE_VISIBILITY + size_t operator()(wchar_t __v) const _NOEXCEPT {return static_cast(__v);} +}; +#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS + +template <> +struct _LIBCPP_TEMPLATE_VIS hash + : public __unary_function +{ + _LIBCPP_INLINE_VISIBILITY + size_t operator()(short __v) const _NOEXCEPT {return static_cast(__v);} +}; + +template <> +struct _LIBCPP_TEMPLATE_VIS hash + : public __unary_function +{ + _LIBCPP_INLINE_VISIBILITY + size_t operator()(unsigned short __v) const _NOEXCEPT {return static_cast(__v);} +}; + +template <> +struct _LIBCPP_TEMPLATE_VIS hash + : public __unary_function +{ + _LIBCPP_INLINE_VISIBILITY + size_t operator()(int __v) const _NOEXCEPT {return static_cast(__v);} +}; + +template <> +struct _LIBCPP_TEMPLATE_VIS hash + : public __unary_function +{ + _LIBCPP_INLINE_VISIBILITY + size_t operator()(unsigned int __v) const _NOEXCEPT {return static_cast(__v);} +}; + +template <> +struct _LIBCPP_TEMPLATE_VIS hash + : public __unary_function +{ + _LIBCPP_INLINE_VISIBILITY + size_t operator()(long __v) const _NOEXCEPT {return static_cast(__v);} +}; + +template <> +struct _LIBCPP_TEMPLATE_VIS hash + : public __unary_function +{ + _LIBCPP_INLINE_VISIBILITY + size_t operator()(unsigned long __v) const _NOEXCEPT {return static_cast(__v);} +}; + +template <> +struct _LIBCPP_TEMPLATE_VIS hash + : public __scalar_hash +{ +}; + +template <> +struct _LIBCPP_TEMPLATE_VIS hash + : public __scalar_hash +{ +}; + +#ifndef _LIBCPP_HAS_NO_INT128 + +template <> +struct _LIBCPP_TEMPLATE_VIS hash<__int128_t> + : public __scalar_hash<__int128_t> +{ +}; + +template <> +struct _LIBCPP_TEMPLATE_VIS hash<__uint128_t> + : public __scalar_hash<__uint128_t> +{ +}; + +#endif + +template <> +struct _LIBCPP_TEMPLATE_VIS hash + : public __scalar_hash +{ + _LIBCPP_INLINE_VISIBILITY + size_t operator()(float __v) const _NOEXCEPT + { + // -0.0 and 0.0 should return same hash + if (__v == 0.0f) + return 0; + return __scalar_hash::operator()(__v); + } +}; + +template <> +struct _LIBCPP_TEMPLATE_VIS hash + : public __scalar_hash +{ + _LIBCPP_INLINE_VISIBILITY + size_t operator()(double __v) const _NOEXCEPT + { + // -0.0 and 0.0 should return same hash + if (__v == 0.0) + return 0; + return __scalar_hash::operator()(__v); + } +}; + +template <> +struct _LIBCPP_TEMPLATE_VIS hash + : public __scalar_hash +{ + _LIBCPP_INLINE_VISIBILITY + size_t operator()(long double __v) const _NOEXCEPT + { + // -0.0 and 0.0 should return same hash + if (__v == 0.0L) + return 0; +#if defined(__i386__) || (defined(__x86_64__) && defined(__ILP32__)) + // Zero out padding bits + union + { + long double __t; + struct + { + size_t __a; + size_t __b; + size_t __c; + size_t __d; + } __s; + } __u; + __u.__s.__a = 0; + __u.__s.__b = 0; + __u.__s.__c = 0; + __u.__s.__d = 0; + __u.__t = __v; + return __u.__s.__a ^ __u.__s.__b ^ __u.__s.__c ^ __u.__s.__d; +#elif defined(__x86_64__) + // Zero out padding bits + union + { + long double __t; + struct + { + size_t __a; + size_t __b; + } __s; + } __u; + __u.__s.__a = 0; + __u.__s.__b = 0; + __u.__t = __v; + return __u.__s.__a ^ __u.__s.__b; +#else + return __scalar_hash::operator()(__v); +#endif + } +}; + +template ::value> +struct _LIBCPP_TEMPLATE_VIS __enum_hash + : public __unary_function<_Tp, size_t> +{ + _LIBCPP_INLINE_VISIBILITY + size_t operator()(_Tp __v) const _NOEXCEPT + { + typedef typename underlying_type<_Tp>::type type; + return hash()(static_cast(__v)); + } +}; +template +struct _LIBCPP_TEMPLATE_VIS __enum_hash<_Tp, false> { + __enum_hash() = delete; + __enum_hash(__enum_hash const&) = delete; + __enum_hash& operator=(__enum_hash const&) = delete; +}; + +template +struct _LIBCPP_TEMPLATE_VIS hash : public __enum_hash<_Tp> +{ +}; + +#if _LIBCPP_STD_VER > 14 + +template <> +struct _LIBCPP_TEMPLATE_VIS hash + : public __unary_function +{ + _LIBCPP_INLINE_VISIBILITY + size_t operator()(nullptr_t) const _NOEXCEPT { + return 662607004ull; + } +}; +#endif + +#ifndef _LIBCPP_CXX03_LANG +template +using __check_hash_requirements _LIBCPP_NODEBUG = integral_constant::value && + is_move_constructible<_Hash>::value && + __invokable_r::value +>; + +template > +using __has_enabled_hash _LIBCPP_NODEBUG = integral_constant::value && + is_default_constructible<_Hash>::value +>; + +#if _LIBCPP_STD_VER > 14 +template +using __enable_hash_helper_imp _LIBCPP_NODEBUG = _Type; + +template +using __enable_hash_helper _LIBCPP_NODEBUG = __enable_hash_helper_imp<_Type, + typename enable_if<__all<__has_enabled_hash<_Keys>::value...>::value>::type +>; +#else +template +using __enable_hash_helper _LIBCPP_NODEBUG = _Type; +#endif + +#endif // !_LIBCPP_CXX03_LANG + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___FUNCTIONAL_HASH_H diff --git a/app/src/main/cpp/libcxx/include/__functional/identity.h b/app/src/main/cpp/libcxx/include/__functional/identity.h new file mode 100644 index 0000000..2fe3acc --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__functional/identity.h @@ -0,0 +1,46 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___FUNCTIONAL_IDENTITY_H +#define _LIBCPP___FUNCTIONAL_IDENTITY_H + +#include <__config> +#include <__utility/forward.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +struct __identity { + template + _LIBCPP_NODISCARD _LIBCPP_CONSTEXPR _Tp&& operator()(_Tp&& __t) const _NOEXCEPT { + return std::forward<_Tp>(__t); + } + + using is_transparent = void; +}; + +#if _LIBCPP_STD_VER > 17 + +struct identity { + template + _LIBCPP_NODISCARD_EXT constexpr _Tp&& operator()(_Tp&& __t) const noexcept + { + return _VSTD::forward<_Tp>(__t); + } + + using is_transparent = void; +}; +#endif // _LIBCPP_STD_VER > 17 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___FUNCTIONAL_IDENTITY_H diff --git a/app/src/main/cpp/libcxx/include/__functional/invoke.h b/app/src/main/cpp/libcxx/include/__functional/invoke.h new file mode 100644 index 0000000..48e6eac --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__functional/invoke.h @@ -0,0 +1,546 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___FUNCTIONAL_INVOKE_H +#define _LIBCPP___FUNCTIONAL_INVOKE_H + +#include <__config> +#include <__type_traits/add_lvalue_reference.h> +#include <__type_traits/apply_cv.h> +#include <__type_traits/conditional.h> +#include <__type_traits/decay.h> +#include <__type_traits/enable_if.h> +#include <__type_traits/integral_constant.h> +#include <__type_traits/is_base_of.h> +#include <__type_traits/is_core_convertible.h> +#include <__type_traits/is_member_function_pointer.h> +#include <__type_traits/is_member_object_pointer.h> +#include <__type_traits/is_reference_wrapper.h> +#include <__type_traits/is_same.h> +#include <__type_traits/is_void.h> +#include <__type_traits/nat.h> +#include <__type_traits/remove_cv.h> +#include <__utility/declval.h> +#include <__utility/forward.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +// TODO: Disentangle the type traits and std::invoke properly + +_LIBCPP_BEGIN_NAMESPACE_STD + +struct __any +{ + __any(...); +}; + +template +struct __member_pointer_traits_imp +{ +}; + +template +struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param...), true, false> +{ + typedef _Class _ClassType; + typedef _Rp _ReturnType; + typedef _Rp (_FnType) (_Param...); +}; + +template +struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param..., ...), true, false> +{ + typedef _Class _ClassType; + typedef _Rp _ReturnType; + typedef _Rp (_FnType) (_Param..., ...); +}; + +template +struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param...) const, true, false> +{ + typedef _Class const _ClassType; + typedef _Rp _ReturnType; + typedef _Rp (_FnType) (_Param...); +}; + +template +struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param..., ...) const, true, false> +{ + typedef _Class const _ClassType; + typedef _Rp _ReturnType; + typedef _Rp (_FnType) (_Param..., ...); +}; + +template +struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param...) volatile, true, false> +{ + typedef _Class volatile _ClassType; + typedef _Rp _ReturnType; + typedef _Rp (_FnType) (_Param...); +}; + +template +struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param..., ...) volatile, true, false> +{ + typedef _Class volatile _ClassType; + typedef _Rp _ReturnType; + typedef _Rp (_FnType) (_Param..., ...); +}; + +template +struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param...) const volatile, true, false> +{ + typedef _Class const volatile _ClassType; + typedef _Rp _ReturnType; + typedef _Rp (_FnType) (_Param...); +}; + +template +struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param..., ...) const volatile, true, false> +{ + typedef _Class const volatile _ClassType; + typedef _Rp _ReturnType; + typedef _Rp (_FnType) (_Param..., ...); +}; + +template +struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param...) &, true, false> +{ + typedef _Class& _ClassType; + typedef _Rp _ReturnType; + typedef _Rp (_FnType) (_Param...); +}; + +template +struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param..., ...) &, true, false> +{ + typedef _Class& _ClassType; + typedef _Rp _ReturnType; + typedef _Rp (_FnType) (_Param..., ...); +}; + +template +struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param...) const&, true, false> +{ + typedef _Class const& _ClassType; + typedef _Rp _ReturnType; + typedef _Rp (_FnType) (_Param...); +}; + +template +struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param..., ...) const&, true, false> +{ + typedef _Class const& _ClassType; + typedef _Rp _ReturnType; + typedef _Rp (_FnType) (_Param..., ...); +}; + +template +struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param...) volatile&, true, false> +{ + typedef _Class volatile& _ClassType; + typedef _Rp _ReturnType; + typedef _Rp (_FnType) (_Param...); +}; + +template +struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param..., ...) volatile&, true, false> +{ + typedef _Class volatile& _ClassType; + typedef _Rp _ReturnType; + typedef _Rp (_FnType) (_Param..., ...); +}; + +template +struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param...) const volatile&, true, false> +{ + typedef _Class const volatile& _ClassType; + typedef _Rp _ReturnType; + typedef _Rp (_FnType) (_Param...); +}; + +template +struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param..., ...) const volatile&, true, false> +{ + typedef _Class const volatile& _ClassType; + typedef _Rp _ReturnType; + typedef _Rp (_FnType) (_Param..., ...); +}; + +template +struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param...) &&, true, false> +{ + typedef _Class&& _ClassType; + typedef _Rp _ReturnType; + typedef _Rp (_FnType) (_Param...); +}; + +template +struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param..., ...) &&, true, false> +{ + typedef _Class&& _ClassType; + typedef _Rp _ReturnType; + typedef _Rp (_FnType) (_Param..., ...); +}; + +template +struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param...) const&&, true, false> +{ + typedef _Class const&& _ClassType; + typedef _Rp _ReturnType; + typedef _Rp (_FnType) (_Param...); +}; + +template +struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param..., ...) const&&, true, false> +{ + typedef _Class const&& _ClassType; + typedef _Rp _ReturnType; + typedef _Rp (_FnType) (_Param..., ...); +}; + +template +struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param...) volatile&&, true, false> +{ + typedef _Class volatile&& _ClassType; + typedef _Rp _ReturnType; + typedef _Rp (_FnType) (_Param...); +}; + +template +struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param..., ...) volatile&&, true, false> +{ + typedef _Class volatile&& _ClassType; + typedef _Rp _ReturnType; + typedef _Rp (_FnType) (_Param..., ...); +}; + +template +struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param...) const volatile&&, true, false> +{ + typedef _Class const volatile&& _ClassType; + typedef _Rp _ReturnType; + typedef _Rp (_FnType) (_Param...); +}; + +template +struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param..., ...) const volatile&&, true, false> +{ + typedef _Class const volatile&& _ClassType; + typedef _Rp _ReturnType; + typedef _Rp (_FnType) (_Param..., ...); +}; + +template +struct __member_pointer_traits_imp<_Rp _Class::*, false, true> +{ + typedef _Class _ClassType; + typedef _Rp _ReturnType; +}; + +template +struct __member_pointer_traits + : public __member_pointer_traits_imp<__remove_cv_t<_MP>, + is_member_function_pointer<_MP>::value, + is_member_object_pointer<_MP>::value> +{ +// typedef ... _ClassType; +// typedef ... _ReturnType; +// typedef ... _FnType; +}; + +template +struct __member_pointer_class_type {}; + +template +struct __member_pointer_class_type<_Ret _ClassType::*> { + typedef _ClassType type; +}; + +template ::type, + class _DecayA0 = typename decay<_A0>::type, + class _ClassT = typename __member_pointer_class_type<_DecayFp>::type> +using __enable_if_bullet1 = typename enable_if + < + is_member_function_pointer<_DecayFp>::value + && is_base_of<_ClassT, _DecayA0>::value + >::type; + +template ::type, + class _DecayA0 = typename decay<_A0>::type> +using __enable_if_bullet2 = typename enable_if + < + is_member_function_pointer<_DecayFp>::value + && __is_reference_wrapper<_DecayA0>::value + >::type; + +template ::type, + class _DecayA0 = typename decay<_A0>::type, + class _ClassT = typename __member_pointer_class_type<_DecayFp>::type> +using __enable_if_bullet3 = typename enable_if + < + is_member_function_pointer<_DecayFp>::value + && !is_base_of<_ClassT, _DecayA0>::value + && !__is_reference_wrapper<_DecayA0>::value + >::type; + +template ::type, + class _DecayA0 = typename decay<_A0>::type, + class _ClassT = typename __member_pointer_class_type<_DecayFp>::type> +using __enable_if_bullet4 = typename enable_if + < + is_member_object_pointer<_DecayFp>::value + && is_base_of<_ClassT, _DecayA0>::value + >::type; + +template ::type, + class _DecayA0 = typename decay<_A0>::type> +using __enable_if_bullet5 = typename enable_if + < + is_member_object_pointer<_DecayFp>::value + && __is_reference_wrapper<_DecayA0>::value + >::type; + +template ::type, + class _DecayA0 = typename decay<_A0>::type, + class _ClassT = typename __member_pointer_class_type<_DecayFp>::type> +using __enable_if_bullet6 = typename enable_if + < + is_member_object_pointer<_DecayFp>::value + && !is_base_of<_ClassT, _DecayA0>::value + && !__is_reference_wrapper<_DecayA0>::value + >::type; + +// __invoke forward declarations + +// fall back - none of the bullets + +template +__nat __invoke(__any, _Args&& ...__args); + +// bullets 1, 2 and 3 + +template > +inline _LIBCPP_INLINE_VISIBILITY +_LIBCPP_CONSTEXPR decltype((std::declval<_A0>().*std::declval<_Fp>())(std::declval<_Args>()...)) +__invoke(_Fp&& __f, _A0&& __a0, _Args&& ...__args) + _NOEXCEPT_(noexcept((static_cast<_A0&&>(__a0).*__f)(static_cast<_Args&&>(__args)...))) + { return (static_cast<_A0&&>(__a0).*__f)(static_cast<_Args&&>(__args)...); } + +template > +inline _LIBCPP_INLINE_VISIBILITY +_LIBCPP_CONSTEXPR decltype((std::declval<_A0>().get().*std::declval<_Fp>())(std::declval<_Args>()...)) +__invoke(_Fp&& __f, _A0&& __a0, _Args&& ...__args) + _NOEXCEPT_(noexcept((__a0.get().*__f)(static_cast<_Args&&>(__args)...))) + { return (__a0.get().*__f)(static_cast<_Args&&>(__args)...); } + +template > +inline _LIBCPP_INLINE_VISIBILITY +_LIBCPP_CONSTEXPR decltype(((*std::declval<_A0>()).*std::declval<_Fp>())(std::declval<_Args>()...)) +__invoke(_Fp&& __f, _A0&& __a0, _Args&& ...__args) + _NOEXCEPT_(noexcept(((*static_cast<_A0&&>(__a0)).*__f)(static_cast<_Args&&>(__args)...))) + { return ((*static_cast<_A0&&>(__a0)).*__f)(static_cast<_Args&&>(__args)...); } + +// bullets 4, 5 and 6 + +template > +inline _LIBCPP_INLINE_VISIBILITY +_LIBCPP_CONSTEXPR decltype(std::declval<_A0>().*std::declval<_Fp>()) +__invoke(_Fp&& __f, _A0&& __a0) + _NOEXCEPT_(noexcept(static_cast<_A0&&>(__a0).*__f)) + { return static_cast<_A0&&>(__a0).*__f; } + +template > +inline _LIBCPP_INLINE_VISIBILITY +_LIBCPP_CONSTEXPR decltype(std::declval<_A0>().get().*std::declval<_Fp>()) +__invoke(_Fp&& __f, _A0&& __a0) + _NOEXCEPT_(noexcept(__a0.get().*__f)) + { return __a0.get().*__f; } + +template > +inline _LIBCPP_INLINE_VISIBILITY +_LIBCPP_CONSTEXPR decltype((*std::declval<_A0>()).*std::declval<_Fp>()) +__invoke(_Fp&& __f, _A0&& __a0) + _NOEXCEPT_(noexcept((*static_cast<_A0&&>(__a0)).*__f)) + { return (*static_cast<_A0&&>(__a0)).*__f; } + +// bullet 7 + +template +inline _LIBCPP_INLINE_VISIBILITY +_LIBCPP_CONSTEXPR decltype(std::declval<_Fp>()(std::declval<_Args>()...)) +__invoke(_Fp&& __f, _Args&& ...__args) + _NOEXCEPT_(noexcept(static_cast<_Fp&&>(__f)(static_cast<_Args&&>(__args)...))) + { return static_cast<_Fp&&>(__f)(static_cast<_Args&&>(__args)...); } + +// __invokable +template +struct __invokable_r +{ + template + static decltype(std::__invoke(std::declval<_XFp>(), std::declval<_XArgs>()...)) __try_call(int); + template + static __nat __try_call(...); + + // FIXME: Check that _Ret, _Fp, and _Args... are all complete types, cv void, + // or incomplete array types as required by the standard. + using _Result = decltype(__try_call<_Fp, _Args...>(0)); + + using type = __conditional_t< + _IsNotSame<_Result, __nat>::value, + __conditional_t::value, true_type, __is_core_convertible<_Result, _Ret> >, + false_type>; + static const bool value = type::value; +}; +template +using __invokable = __invokable_r; + +template +struct __nothrow_invokable_r_imp { + static const bool value = false; +}; + +template +struct __nothrow_invokable_r_imp +{ + typedef __nothrow_invokable_r_imp _ThisT; + + template + static void __test_noexcept(_Tp) _NOEXCEPT; + +#ifdef _LIBCPP_CXX03_LANG + static const bool value = false; +#else + static const bool value = noexcept(_ThisT::__test_noexcept<_Ret>( + _VSTD::__invoke(std::declval<_Fp>(), std::declval<_Args>()...))); +#endif +}; + +template +struct __nothrow_invokable_r_imp +{ +#ifdef _LIBCPP_CXX03_LANG + static const bool value = false; +#else + static const bool value = noexcept( + _VSTD::__invoke(std::declval<_Fp>(), std::declval<_Args>()...)); +#endif +}; + +template +using __nothrow_invokable_r = + __nothrow_invokable_r_imp< + __invokable_r<_Ret, _Fp, _Args...>::value, + is_void<_Ret>::value, + _Ret, _Fp, _Args... + >; + +template +using __nothrow_invokable = + __nothrow_invokable_r_imp< + __invokable<_Fp, _Args...>::value, + true, void, _Fp, _Args... + >; + +template +struct __invoke_of + : public enable_if< + __invokable<_Fp, _Args...>::value, + typename __invokable_r::_Result> +{ +}; + +template ::value> +struct __invoke_void_return_wrapper +{ + template + static _Ret __call(_Args&&... __args) { + return std::__invoke(std::forward<_Args>(__args)...); + } +}; + +template +struct __invoke_void_return_wrapper<_Ret, true> +{ + template + static void __call(_Args&&... __args) { + std::__invoke(std::forward<_Args>(__args)...); + } +}; + +#if _LIBCPP_STD_VER > 14 + +// is_invocable + +template +struct _LIBCPP_TEMPLATE_VIS is_invocable + : integral_constant::value> {}; + +template +struct _LIBCPP_TEMPLATE_VIS is_invocable_r + : integral_constant::value> {}; + +template +inline constexpr bool is_invocable_v = is_invocable<_Fn, _Args...>::value; + +template +inline constexpr bool is_invocable_r_v = is_invocable_r<_Ret, _Fn, _Args...>::value; + +// is_nothrow_invocable + +template +struct _LIBCPP_TEMPLATE_VIS is_nothrow_invocable + : integral_constant::value> {}; + +template +struct _LIBCPP_TEMPLATE_VIS is_nothrow_invocable_r + : integral_constant::value> {}; + +template +inline constexpr bool is_nothrow_invocable_v = is_nothrow_invocable<_Fn, _Args...>::value; + +template +inline constexpr bool is_nothrow_invocable_r_v = is_nothrow_invocable_r<_Ret, _Fn, _Args...>::value; + +template +struct _LIBCPP_TEMPLATE_VIS invoke_result + : __invoke_of<_Fn, _Args...> +{ +}; + +template +using invoke_result_t = typename invoke_result<_Fn, _Args...>::type; + +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 invoke_result_t<_Fn, _Args...> +invoke(_Fn&& __f, _Args&&... __args) + noexcept(is_nothrow_invocable_v<_Fn, _Args...>) +{ + return _VSTD::__invoke(_VSTD::forward<_Fn>(__f), _VSTD::forward<_Args>(__args)...); +} + +#endif // _LIBCPP_STD_VER > 14 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___FUNCTIONAL_INVOKE_H diff --git a/app/src/main/cpp/libcxx/include/__functional/is_transparent.h b/app/src/main/cpp/libcxx/include/__functional/is_transparent.h new file mode 100644 index 0000000..c7a0ee9 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__functional/is_transparent.h @@ -0,0 +1,35 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___FUNCTIONAL_IS_TRANSPARENT +#define _LIBCPP___FUNCTIONAL_IS_TRANSPARENT + +#include <__config> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 11 + +template +struct __is_transparent : false_type {}; + +template +struct __is_transparent<_Tp, _Up, __void_t > + : true_type {}; + +#endif + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___FUNCTIONAL_IS_TRANSPARENT diff --git a/app/src/main/cpp/libcxx/include/__functional/mem_fn.h b/app/src/main/cpp/libcxx/include/__functional/mem_fn.h new file mode 100644 index 0000000..8b51627 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__functional/mem_fn.h @@ -0,0 +1,59 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___FUNCTIONAL_MEM_FN_H +#define _LIBCPP___FUNCTIONAL_MEM_FN_H + +#include <__config> +#include <__functional/binary_function.h> +#include <__functional/invoke.h> +#include <__functional/weak_result_type.h> +#include <__utility/forward.h> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +template +class __mem_fn : public __weak_result_type<_Tp> +{ +public: + // types + typedef _Tp type; +private: + type __f_; + +public: + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 + __mem_fn(type __f) _NOEXCEPT : __f_(__f) {} + + // invoke + template + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 + + typename __invoke_return::type + operator() (_ArgTypes&&... __args) const { + return std::__invoke(__f_, std::forward<_ArgTypes>(__args)...); + } +}; + +template +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 +__mem_fn<_Rp _Tp::*> +mem_fn(_Rp _Tp::* __pm) _NOEXCEPT +{ + return __mem_fn<_Rp _Tp::*>(__pm); +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___FUNCTIONAL_MEM_FN_H diff --git a/app/src/main/cpp/libcxx/include/__functional/mem_fun_ref.h b/app/src/main/cpp/libcxx/include/__functional/mem_fun_ref.h new file mode 100644 index 0000000..65aab06 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__functional/mem_fun_ref.h @@ -0,0 +1,173 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___FUNCTIONAL_MEM_FUN_REF_H +#define _LIBCPP___FUNCTIONAL_MEM_FUN_REF_H + +#include <__config> +#include <__functional/binary_function.h> +#include <__functional/unary_function.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER <= 14 || defined(_LIBCPP_ENABLE_CXX17_REMOVED_BINDERS) + +template +class _LIBCPP_TEMPLATE_VIS _LIBCPP_DEPRECATED_IN_CXX11 mem_fun_t + : public __unary_function<_Tp*, _Sp> +{ + _Sp (_Tp::*__p_)(); +public: + _LIBCPP_INLINE_VISIBILITY explicit mem_fun_t(_Sp (_Tp::*__p)()) + : __p_(__p) {} + _LIBCPP_INLINE_VISIBILITY _Sp operator()(_Tp* __p) const + {return (__p->*__p_)();} +}; + +template +class _LIBCPP_TEMPLATE_VIS _LIBCPP_DEPRECATED_IN_CXX11 mem_fun1_t + : public __binary_function<_Tp*, _Ap, _Sp> +{ + _Sp (_Tp::*__p_)(_Ap); +public: + _LIBCPP_INLINE_VISIBILITY explicit mem_fun1_t(_Sp (_Tp::*__p)(_Ap)) + : __p_(__p) {} + _LIBCPP_INLINE_VISIBILITY _Sp operator()(_Tp* __p, _Ap __x) const + {return (__p->*__p_)(__x);} +}; + +template +_LIBCPP_DEPRECATED_IN_CXX11 inline _LIBCPP_INLINE_VISIBILITY +mem_fun_t<_Sp,_Tp> +mem_fun(_Sp (_Tp::*__f)()) + {return mem_fun_t<_Sp,_Tp>(__f);} + +template +_LIBCPP_DEPRECATED_IN_CXX11 inline _LIBCPP_INLINE_VISIBILITY +mem_fun1_t<_Sp,_Tp,_Ap> +mem_fun(_Sp (_Tp::*__f)(_Ap)) + {return mem_fun1_t<_Sp,_Tp,_Ap>(__f);} + +template +class _LIBCPP_TEMPLATE_VIS _LIBCPP_DEPRECATED_IN_CXX11 mem_fun_ref_t + : public __unary_function<_Tp, _Sp> +{ + _Sp (_Tp::*__p_)(); +public: + _LIBCPP_INLINE_VISIBILITY explicit mem_fun_ref_t(_Sp (_Tp::*__p)()) + : __p_(__p) {} + _LIBCPP_INLINE_VISIBILITY _Sp operator()(_Tp& __p) const + {return (__p.*__p_)();} +}; + +template +class _LIBCPP_TEMPLATE_VIS _LIBCPP_DEPRECATED_IN_CXX11 mem_fun1_ref_t + : public __binary_function<_Tp, _Ap, _Sp> +{ + _Sp (_Tp::*__p_)(_Ap); +public: + _LIBCPP_INLINE_VISIBILITY explicit mem_fun1_ref_t(_Sp (_Tp::*__p)(_Ap)) + : __p_(__p) {} + _LIBCPP_INLINE_VISIBILITY _Sp operator()(_Tp& __p, _Ap __x) const + {return (__p.*__p_)(__x);} +}; + +template +_LIBCPP_DEPRECATED_IN_CXX11 inline _LIBCPP_INLINE_VISIBILITY +mem_fun_ref_t<_Sp,_Tp> +mem_fun_ref(_Sp (_Tp::*__f)()) + {return mem_fun_ref_t<_Sp,_Tp>(__f);} + +template +_LIBCPP_DEPRECATED_IN_CXX11 inline _LIBCPP_INLINE_VISIBILITY +mem_fun1_ref_t<_Sp,_Tp,_Ap> +mem_fun_ref(_Sp (_Tp::*__f)(_Ap)) + {return mem_fun1_ref_t<_Sp,_Tp,_Ap>(__f);} + +template +class _LIBCPP_TEMPLATE_VIS _LIBCPP_DEPRECATED_IN_CXX11 const_mem_fun_t + : public __unary_function +{ + _Sp (_Tp::*__p_)() const; +public: + _LIBCPP_INLINE_VISIBILITY explicit const_mem_fun_t(_Sp (_Tp::*__p)() const) + : __p_(__p) {} + _LIBCPP_INLINE_VISIBILITY _Sp operator()(const _Tp* __p) const + {return (__p->*__p_)();} +}; + +template +class _LIBCPP_TEMPLATE_VIS _LIBCPP_DEPRECATED_IN_CXX11 const_mem_fun1_t + : public __binary_function +{ + _Sp (_Tp::*__p_)(_Ap) const; +public: + _LIBCPP_INLINE_VISIBILITY explicit const_mem_fun1_t(_Sp (_Tp::*__p)(_Ap) const) + : __p_(__p) {} + _LIBCPP_INLINE_VISIBILITY _Sp operator()(const _Tp* __p, _Ap __x) const + {return (__p->*__p_)(__x);} +}; + +template +_LIBCPP_DEPRECATED_IN_CXX11 inline _LIBCPP_INLINE_VISIBILITY +const_mem_fun_t<_Sp,_Tp> +mem_fun(_Sp (_Tp::*__f)() const) + {return const_mem_fun_t<_Sp,_Tp>(__f);} + +template +_LIBCPP_DEPRECATED_IN_CXX11 inline _LIBCPP_INLINE_VISIBILITY +const_mem_fun1_t<_Sp,_Tp,_Ap> +mem_fun(_Sp (_Tp::*__f)(_Ap) const) + {return const_mem_fun1_t<_Sp,_Tp,_Ap>(__f);} + +template +class _LIBCPP_TEMPLATE_VIS _LIBCPP_DEPRECATED_IN_CXX11 const_mem_fun_ref_t + : public __unary_function<_Tp, _Sp> +{ + _Sp (_Tp::*__p_)() const; +public: + _LIBCPP_INLINE_VISIBILITY explicit const_mem_fun_ref_t(_Sp (_Tp::*__p)() const) + : __p_(__p) {} + _LIBCPP_INLINE_VISIBILITY _Sp operator()(const _Tp& __p) const + {return (__p.*__p_)();} +}; + +template +class _LIBCPP_TEMPLATE_VIS _LIBCPP_DEPRECATED_IN_CXX11 const_mem_fun1_ref_t + : public __binary_function<_Tp, _Ap, _Sp> +{ + _Sp (_Tp::*__p_)(_Ap) const; +public: + _LIBCPP_INLINE_VISIBILITY explicit const_mem_fun1_ref_t(_Sp (_Tp::*__p)(_Ap) const) + : __p_(__p) {} + _LIBCPP_INLINE_VISIBILITY _Sp operator()(const _Tp& __p, _Ap __x) const + {return (__p.*__p_)(__x);} +}; + +template +_LIBCPP_DEPRECATED_IN_CXX11 inline _LIBCPP_INLINE_VISIBILITY +const_mem_fun_ref_t<_Sp,_Tp> +mem_fun_ref(_Sp (_Tp::*__f)() const) + {return const_mem_fun_ref_t<_Sp,_Tp>(__f);} + +template +_LIBCPP_DEPRECATED_IN_CXX11 inline _LIBCPP_INLINE_VISIBILITY +const_mem_fun1_ref_t<_Sp,_Tp,_Ap> +mem_fun_ref(_Sp (_Tp::*__f)(_Ap) const) + {return const_mem_fun1_ref_t<_Sp,_Tp,_Ap>(__f);} + +#endif // _LIBCPP_STD_VER <= 14 || defined(_LIBCPP_ENABLE_CXX17_REMOVED_BINDERS) + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___FUNCTIONAL_MEM_FUN_REF_H diff --git a/app/src/main/cpp/libcxx/include/__functional/not_fn.h b/app/src/main/cpp/libcxx/include/__functional/not_fn.h new file mode 100644 index 0000000..79d9a87 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__functional/not_fn.h @@ -0,0 +1,54 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___FUNCTIONAL_NOT_FN_H +#define _LIBCPP___FUNCTIONAL_NOT_FN_H + +#include <__config> +#include <__functional/invoke.h> +#include <__functional/perfect_forward.h> +#include <__utility/forward.h> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 14 + +struct __not_fn_op { + template + _LIBCPP_HIDE_FROM_ABI + _LIBCPP_CONSTEXPR_SINCE_CXX20 auto operator()(_Args&&... __args) const + noexcept(noexcept(!_VSTD::invoke(_VSTD::forward<_Args>(__args)...))) + -> decltype( !_VSTD::invoke(_VSTD::forward<_Args>(__args)...)) + { return !_VSTD::invoke(_VSTD::forward<_Args>(__args)...); } +}; + +template +struct __not_fn_t : __perfect_forward<__not_fn_op, _Fn> { + using __perfect_forward<__not_fn_op, _Fn>::__perfect_forward; +}; + +template , _Fn> && + is_move_constructible_v> +>> +_LIBCPP_HIDE_FROM_ABI +_LIBCPP_CONSTEXPR_SINCE_CXX20 auto not_fn(_Fn&& __f) { + return __not_fn_t>(_VSTD::forward<_Fn>(__f)); +} + +#endif // _LIBCPP_STD_VER > 14 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___FUNCTIONAL_NOT_FN_H diff --git a/app/src/main/cpp/libcxx/include/__functional/operations.h b/app/src/main/cpp/libcxx/include/__functional/operations.h new file mode 100644 index 0000000..8a781ef --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__functional/operations.h @@ -0,0 +1,580 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___FUNCTIONAL_OPERATIONS_H +#define _LIBCPP___FUNCTIONAL_OPERATIONS_H + +#include <__config> +#include <__functional/binary_function.h> +#include <__functional/unary_function.h> +#include <__utility/forward.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +// Arithmetic operations + +#if _LIBCPP_STD_VER > 11 +template +#else +template +#endif +struct _LIBCPP_TEMPLATE_VIS plus + : __binary_function<_Tp, _Tp, _Tp> +{ + typedef _Tp __result_type; // used by valarray + _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_INLINE_VISIBILITY + _Tp operator()(const _Tp& __x, const _Tp& __y) const + {return __x + __y;} +}; +_LIBCPP_CTAD_SUPPORTED_FOR_TYPE(plus); + +#if _LIBCPP_STD_VER > 11 +template <> +struct _LIBCPP_TEMPLATE_VIS plus +{ + template + _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_INLINE_VISIBILITY + auto operator()(_T1&& __t, _T2&& __u) const + noexcept(noexcept(_VSTD::forward<_T1>(__t) + _VSTD::forward<_T2>(__u))) + -> decltype( _VSTD::forward<_T1>(__t) + _VSTD::forward<_T2>(__u)) + { return _VSTD::forward<_T1>(__t) + _VSTD::forward<_T2>(__u); } + typedef void is_transparent; +}; +#endif + +#if _LIBCPP_STD_VER > 11 +template +#else +template +#endif +struct _LIBCPP_TEMPLATE_VIS minus + : __binary_function<_Tp, _Tp, _Tp> +{ + typedef _Tp __result_type; // used by valarray + _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_INLINE_VISIBILITY + _Tp operator()(const _Tp& __x, const _Tp& __y) const + {return __x - __y;} +}; +_LIBCPP_CTAD_SUPPORTED_FOR_TYPE(minus); + +#if _LIBCPP_STD_VER > 11 +template <> +struct _LIBCPP_TEMPLATE_VIS minus +{ + template + _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_INLINE_VISIBILITY + auto operator()(_T1&& __t, _T2&& __u) const + noexcept(noexcept(_VSTD::forward<_T1>(__t) - _VSTD::forward<_T2>(__u))) + -> decltype( _VSTD::forward<_T1>(__t) - _VSTD::forward<_T2>(__u)) + { return _VSTD::forward<_T1>(__t) - _VSTD::forward<_T2>(__u); } + typedef void is_transparent; +}; +#endif + +#if _LIBCPP_STD_VER > 11 +template +#else +template +#endif +struct _LIBCPP_TEMPLATE_VIS multiplies + : __binary_function<_Tp, _Tp, _Tp> +{ + typedef _Tp __result_type; // used by valarray + _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_INLINE_VISIBILITY + _Tp operator()(const _Tp& __x, const _Tp& __y) const + {return __x * __y;} +}; +_LIBCPP_CTAD_SUPPORTED_FOR_TYPE(multiplies); + +#if _LIBCPP_STD_VER > 11 +template <> +struct _LIBCPP_TEMPLATE_VIS multiplies +{ + template + _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_INLINE_VISIBILITY + auto operator()(_T1&& __t, _T2&& __u) const + noexcept(noexcept(_VSTD::forward<_T1>(__t) * _VSTD::forward<_T2>(__u))) + -> decltype( _VSTD::forward<_T1>(__t) * _VSTD::forward<_T2>(__u)) + { return _VSTD::forward<_T1>(__t) * _VSTD::forward<_T2>(__u); } + typedef void is_transparent; +}; +#endif + +#if _LIBCPP_STD_VER > 11 +template +#else +template +#endif +struct _LIBCPP_TEMPLATE_VIS divides + : __binary_function<_Tp, _Tp, _Tp> +{ + typedef _Tp __result_type; // used by valarray + _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_INLINE_VISIBILITY + _Tp operator()(const _Tp& __x, const _Tp& __y) const + {return __x / __y;} +}; +_LIBCPP_CTAD_SUPPORTED_FOR_TYPE(divides); + +#if _LIBCPP_STD_VER > 11 +template <> +struct _LIBCPP_TEMPLATE_VIS divides +{ + template + _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_INLINE_VISIBILITY + auto operator()(_T1&& __t, _T2&& __u) const + noexcept(noexcept(_VSTD::forward<_T1>(__t) / _VSTD::forward<_T2>(__u))) + -> decltype( _VSTD::forward<_T1>(__t) / _VSTD::forward<_T2>(__u)) + { return _VSTD::forward<_T1>(__t) / _VSTD::forward<_T2>(__u); } + typedef void is_transparent; +}; +#endif + +#if _LIBCPP_STD_VER > 11 +template +#else +template +#endif +struct _LIBCPP_TEMPLATE_VIS modulus + : __binary_function<_Tp, _Tp, _Tp> +{ + typedef _Tp __result_type; // used by valarray + _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_INLINE_VISIBILITY + _Tp operator()(const _Tp& __x, const _Tp& __y) const + {return __x % __y;} +}; +_LIBCPP_CTAD_SUPPORTED_FOR_TYPE(modulus); + +#if _LIBCPP_STD_VER > 11 +template <> +struct _LIBCPP_TEMPLATE_VIS modulus +{ + template + _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_INLINE_VISIBILITY + auto operator()(_T1&& __t, _T2&& __u) const + noexcept(noexcept(_VSTD::forward<_T1>(__t) % _VSTD::forward<_T2>(__u))) + -> decltype( _VSTD::forward<_T1>(__t) % _VSTD::forward<_T2>(__u)) + { return _VSTD::forward<_T1>(__t) % _VSTD::forward<_T2>(__u); } + typedef void is_transparent; +}; +#endif + +#if _LIBCPP_STD_VER > 11 +template +#else +template +#endif +struct _LIBCPP_TEMPLATE_VIS negate + : __unary_function<_Tp, _Tp> +{ + typedef _Tp __result_type; // used by valarray + _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_INLINE_VISIBILITY + _Tp operator()(const _Tp& __x) const + {return -__x;} +}; +_LIBCPP_CTAD_SUPPORTED_FOR_TYPE(negate); + +#if _LIBCPP_STD_VER > 11 +template <> +struct _LIBCPP_TEMPLATE_VIS negate +{ + template + _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_INLINE_VISIBILITY + auto operator()(_Tp&& __x) const + noexcept(noexcept(- _VSTD::forward<_Tp>(__x))) + -> decltype( - _VSTD::forward<_Tp>(__x)) + { return - _VSTD::forward<_Tp>(__x); } + typedef void is_transparent; +}; +#endif + +// Bitwise operations + +#if _LIBCPP_STD_VER > 11 +template +#else +template +#endif +struct _LIBCPP_TEMPLATE_VIS bit_and + : __binary_function<_Tp, _Tp, _Tp> +{ + typedef _Tp __result_type; // used by valarray + _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_INLINE_VISIBILITY + _Tp operator()(const _Tp& __x, const _Tp& __y) const + {return __x & __y;} +}; +_LIBCPP_CTAD_SUPPORTED_FOR_TYPE(bit_and); + +#if _LIBCPP_STD_VER > 11 +template <> +struct _LIBCPP_TEMPLATE_VIS bit_and +{ + template + _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_INLINE_VISIBILITY + auto operator()(_T1&& __t, _T2&& __u) const + noexcept(noexcept(_VSTD::forward<_T1>(__t) & _VSTD::forward<_T2>(__u))) + -> decltype( _VSTD::forward<_T1>(__t) & _VSTD::forward<_T2>(__u)) + { return _VSTD::forward<_T1>(__t) & _VSTD::forward<_T2>(__u); } + typedef void is_transparent; +}; +#endif + +#if _LIBCPP_STD_VER > 11 +template +struct _LIBCPP_TEMPLATE_VIS bit_not + : __unary_function<_Tp, _Tp> +{ + _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_INLINE_VISIBILITY + _Tp operator()(const _Tp& __x) const + {return ~__x;} +}; +_LIBCPP_CTAD_SUPPORTED_FOR_TYPE(bit_not); + +template <> +struct _LIBCPP_TEMPLATE_VIS bit_not +{ + template + _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_INLINE_VISIBILITY + auto operator()(_Tp&& __x) const + noexcept(noexcept(~_VSTD::forward<_Tp>(__x))) + -> decltype( ~_VSTD::forward<_Tp>(__x)) + { return ~_VSTD::forward<_Tp>(__x); } + typedef void is_transparent; +}; +#endif + +#if _LIBCPP_STD_VER > 11 +template +#else +template +#endif +struct _LIBCPP_TEMPLATE_VIS bit_or + : __binary_function<_Tp, _Tp, _Tp> +{ + typedef _Tp __result_type; // used by valarray + _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_INLINE_VISIBILITY + _Tp operator()(const _Tp& __x, const _Tp& __y) const + {return __x | __y;} +}; +_LIBCPP_CTAD_SUPPORTED_FOR_TYPE(bit_or); + +#if _LIBCPP_STD_VER > 11 +template <> +struct _LIBCPP_TEMPLATE_VIS bit_or +{ + template + _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_INLINE_VISIBILITY + auto operator()(_T1&& __t, _T2&& __u) const + noexcept(noexcept(_VSTD::forward<_T1>(__t) | _VSTD::forward<_T2>(__u))) + -> decltype( _VSTD::forward<_T1>(__t) | _VSTD::forward<_T2>(__u)) + { return _VSTD::forward<_T1>(__t) | _VSTD::forward<_T2>(__u); } + typedef void is_transparent; +}; +#endif + +#if _LIBCPP_STD_VER > 11 +template +#else +template +#endif +struct _LIBCPP_TEMPLATE_VIS bit_xor + : __binary_function<_Tp, _Tp, _Tp> +{ + typedef _Tp __result_type; // used by valarray + _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_INLINE_VISIBILITY + _Tp operator()(const _Tp& __x, const _Tp& __y) const + {return __x ^ __y;} +}; +_LIBCPP_CTAD_SUPPORTED_FOR_TYPE(bit_xor); + +#if _LIBCPP_STD_VER > 11 +template <> +struct _LIBCPP_TEMPLATE_VIS bit_xor +{ + template + _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_INLINE_VISIBILITY + auto operator()(_T1&& __t, _T2&& __u) const + noexcept(noexcept(_VSTD::forward<_T1>(__t) ^ _VSTD::forward<_T2>(__u))) + -> decltype( _VSTD::forward<_T1>(__t) ^ _VSTD::forward<_T2>(__u)) + { return _VSTD::forward<_T1>(__t) ^ _VSTD::forward<_T2>(__u); } + typedef void is_transparent; +}; +#endif + +// Comparison operations + +#if _LIBCPP_STD_VER > 11 +template +#else +template +#endif +struct _LIBCPP_TEMPLATE_VIS equal_to + : __binary_function<_Tp, _Tp, bool> +{ + typedef bool __result_type; // used by valarray + _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_INLINE_VISIBILITY + bool operator()(const _Tp& __x, const _Tp& __y) const + {return __x == __y;} +}; +_LIBCPP_CTAD_SUPPORTED_FOR_TYPE(equal_to); + +#if _LIBCPP_STD_VER > 11 +template <> +struct _LIBCPP_TEMPLATE_VIS equal_to +{ + template + _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_INLINE_VISIBILITY + auto operator()(_T1&& __t, _T2&& __u) const + noexcept(noexcept(_VSTD::forward<_T1>(__t) == _VSTD::forward<_T2>(__u))) + -> decltype( _VSTD::forward<_T1>(__t) == _VSTD::forward<_T2>(__u)) + { return _VSTD::forward<_T1>(__t) == _VSTD::forward<_T2>(__u); } + typedef void is_transparent; +}; +#endif + +#if _LIBCPP_STD_VER > 11 +template +#else +template +#endif +struct _LIBCPP_TEMPLATE_VIS not_equal_to + : __binary_function<_Tp, _Tp, bool> +{ + typedef bool __result_type; // used by valarray + _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_INLINE_VISIBILITY + bool operator()(const _Tp& __x, const _Tp& __y) const + {return __x != __y;} +}; +_LIBCPP_CTAD_SUPPORTED_FOR_TYPE(not_equal_to); + +#if _LIBCPP_STD_VER > 11 +template <> +struct _LIBCPP_TEMPLATE_VIS not_equal_to +{ + template + _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_INLINE_VISIBILITY + auto operator()(_T1&& __t, _T2&& __u) const + noexcept(noexcept(_VSTD::forward<_T1>(__t) != _VSTD::forward<_T2>(__u))) + -> decltype( _VSTD::forward<_T1>(__t) != _VSTD::forward<_T2>(__u)) + { return _VSTD::forward<_T1>(__t) != _VSTD::forward<_T2>(__u); } + typedef void is_transparent; +}; +#endif + +#if _LIBCPP_STD_VER > 11 +template +#else +template +#endif +struct _LIBCPP_TEMPLATE_VIS less + : __binary_function<_Tp, _Tp, bool> +{ + typedef bool __result_type; // used by valarray + _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_INLINE_VISIBILITY + bool operator()(const _Tp& __x, const _Tp& __y) const + {return __x < __y;} +}; +_LIBCPP_CTAD_SUPPORTED_FOR_TYPE(less); + +#if _LIBCPP_STD_VER > 11 +template <> +struct _LIBCPP_TEMPLATE_VIS less +{ + template + _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_INLINE_VISIBILITY + auto operator()(_T1&& __t, _T2&& __u) const + noexcept(noexcept(_VSTD::forward<_T1>(__t) < _VSTD::forward<_T2>(__u))) + -> decltype( _VSTD::forward<_T1>(__t) < _VSTD::forward<_T2>(__u)) + { return _VSTD::forward<_T1>(__t) < _VSTD::forward<_T2>(__u); } + typedef void is_transparent; +}; +#endif + +#if _LIBCPP_STD_VER > 11 +template +#else +template +#endif +struct _LIBCPP_TEMPLATE_VIS less_equal + : __binary_function<_Tp, _Tp, bool> +{ + typedef bool __result_type; // used by valarray + _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_INLINE_VISIBILITY + bool operator()(const _Tp& __x, const _Tp& __y) const + {return __x <= __y;} +}; +_LIBCPP_CTAD_SUPPORTED_FOR_TYPE(less_equal); + +#if _LIBCPP_STD_VER > 11 +template <> +struct _LIBCPP_TEMPLATE_VIS less_equal +{ + template + _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_INLINE_VISIBILITY + auto operator()(_T1&& __t, _T2&& __u) const + noexcept(noexcept(_VSTD::forward<_T1>(__t) <= _VSTD::forward<_T2>(__u))) + -> decltype( _VSTD::forward<_T1>(__t) <= _VSTD::forward<_T2>(__u)) + { return _VSTD::forward<_T1>(__t) <= _VSTD::forward<_T2>(__u); } + typedef void is_transparent; +}; +#endif + +#if _LIBCPP_STD_VER > 11 +template +#else +template +#endif +struct _LIBCPP_TEMPLATE_VIS greater_equal + : __binary_function<_Tp, _Tp, bool> +{ + typedef bool __result_type; // used by valarray + _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_INLINE_VISIBILITY + bool operator()(const _Tp& __x, const _Tp& __y) const + {return __x >= __y;} +}; +_LIBCPP_CTAD_SUPPORTED_FOR_TYPE(greater_equal); + +#if _LIBCPP_STD_VER > 11 +template <> +struct _LIBCPP_TEMPLATE_VIS greater_equal +{ + template + _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_INLINE_VISIBILITY + auto operator()(_T1&& __t, _T2&& __u) const + noexcept(noexcept(_VSTD::forward<_T1>(__t) >= _VSTD::forward<_T2>(__u))) + -> decltype( _VSTD::forward<_T1>(__t) >= _VSTD::forward<_T2>(__u)) + { return _VSTD::forward<_T1>(__t) >= _VSTD::forward<_T2>(__u); } + typedef void is_transparent; +}; +#endif + +#if _LIBCPP_STD_VER > 11 +template +#else +template +#endif +struct _LIBCPP_TEMPLATE_VIS greater + : __binary_function<_Tp, _Tp, bool> +{ + typedef bool __result_type; // used by valarray + _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_INLINE_VISIBILITY + bool operator()(const _Tp& __x, const _Tp& __y) const + {return __x > __y;} +}; +_LIBCPP_CTAD_SUPPORTED_FOR_TYPE(greater); + +#if _LIBCPP_STD_VER > 11 +template <> +struct _LIBCPP_TEMPLATE_VIS greater +{ + template + _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_INLINE_VISIBILITY + auto operator()(_T1&& __t, _T2&& __u) const + noexcept(noexcept(_VSTD::forward<_T1>(__t) > _VSTD::forward<_T2>(__u))) + -> decltype( _VSTD::forward<_T1>(__t) > _VSTD::forward<_T2>(__u)) + { return _VSTD::forward<_T1>(__t) > _VSTD::forward<_T2>(__u); } + typedef void is_transparent; +}; +#endif + +// Logical operations + +#if _LIBCPP_STD_VER > 11 +template +#else +template +#endif +struct _LIBCPP_TEMPLATE_VIS logical_and + : __binary_function<_Tp, _Tp, bool> +{ + typedef bool __result_type; // used by valarray + _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_INLINE_VISIBILITY + bool operator()(const _Tp& __x, const _Tp& __y) const + {return __x && __y;} +}; +_LIBCPP_CTAD_SUPPORTED_FOR_TYPE(logical_and); + +#if _LIBCPP_STD_VER > 11 +template <> +struct _LIBCPP_TEMPLATE_VIS logical_and +{ + template + _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_INLINE_VISIBILITY + auto operator()(_T1&& __t, _T2&& __u) const + noexcept(noexcept(_VSTD::forward<_T1>(__t) && _VSTD::forward<_T2>(__u))) + -> decltype( _VSTD::forward<_T1>(__t) && _VSTD::forward<_T2>(__u)) + { return _VSTD::forward<_T1>(__t) && _VSTD::forward<_T2>(__u); } + typedef void is_transparent; +}; +#endif + +#if _LIBCPP_STD_VER > 11 +template +#else +template +#endif +struct _LIBCPP_TEMPLATE_VIS logical_not + : __unary_function<_Tp, bool> +{ + typedef bool __result_type; // used by valarray + _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_INLINE_VISIBILITY + bool operator()(const _Tp& __x) const + {return !__x;} +}; +_LIBCPP_CTAD_SUPPORTED_FOR_TYPE(logical_not); + +#if _LIBCPP_STD_VER > 11 +template <> +struct _LIBCPP_TEMPLATE_VIS logical_not +{ + template + _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_INLINE_VISIBILITY + auto operator()(_Tp&& __x) const + noexcept(noexcept(!_VSTD::forward<_Tp>(__x))) + -> decltype( !_VSTD::forward<_Tp>(__x)) + { return !_VSTD::forward<_Tp>(__x); } + typedef void is_transparent; +}; +#endif + +#if _LIBCPP_STD_VER > 11 +template +#else +template +#endif +struct _LIBCPP_TEMPLATE_VIS logical_or + : __binary_function<_Tp, _Tp, bool> +{ + typedef bool __result_type; // used by valarray + _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_INLINE_VISIBILITY + bool operator()(const _Tp& __x, const _Tp& __y) const + {return __x || __y;} +}; +_LIBCPP_CTAD_SUPPORTED_FOR_TYPE(logical_or); + +#if _LIBCPP_STD_VER > 11 +template <> +struct _LIBCPP_TEMPLATE_VIS logical_or +{ + template + _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_INLINE_VISIBILITY + auto operator()(_T1&& __t, _T2&& __u) const + noexcept(noexcept(_VSTD::forward<_T1>(__t) || _VSTD::forward<_T2>(__u))) + -> decltype( _VSTD::forward<_T1>(__t) || _VSTD::forward<_T2>(__u)) + { return _VSTD::forward<_T1>(__t) || _VSTD::forward<_T2>(__u); } + typedef void is_transparent; +}; +#endif + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___FUNCTIONAL_OPERATIONS_H diff --git a/app/src/main/cpp/libcxx/include/__functional/perfect_forward.h b/app/src/main/cpp/libcxx/include/__functional/perfect_forward.h new file mode 100644 index 0000000..9ffea1a --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__functional/perfect_forward.h @@ -0,0 +1,94 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___FUNCTIONAL_PERFECT_FORWARD_H +#define _LIBCPP___FUNCTIONAL_PERFECT_FORWARD_H + +#include <__config> +#include <__utility/declval.h> +#include <__utility/forward.h> +#include <__utility/move.h> +#include +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 14 + +template +struct __perfect_forward_impl; + +template +struct __perfect_forward_impl<_Op, index_sequence<_Idx...>, _BoundArgs...> { +private: + tuple<_BoundArgs...> __bound_args_; + +public: + template , _Args&&...> + >> + explicit constexpr __perfect_forward_impl(_Args&&... __bound_args) + : __bound_args_(_VSTD::forward<_Args>(__bound_args)...) {} + + __perfect_forward_impl(__perfect_forward_impl const&) = default; + __perfect_forward_impl(__perfect_forward_impl&&) = default; + + __perfect_forward_impl& operator=(__perfect_forward_impl const&) = default; + __perfect_forward_impl& operator=(__perfect_forward_impl&&) = default; + + template >> + _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Args&&... __args) & + noexcept(noexcept(_Op()(_VSTD::get<_Idx>(__bound_args_)..., _VSTD::forward<_Args>(__args)...))) + -> decltype( _Op()(_VSTD::get<_Idx>(__bound_args_)..., _VSTD::forward<_Args>(__args)...)) + { return _Op()(_VSTD::get<_Idx>(__bound_args_)..., _VSTD::forward<_Args>(__args)...); } + + template >> + auto operator()(_Args&&...) & = delete; + + template >> + _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Args&&... __args) const& + noexcept(noexcept(_Op()(_VSTD::get<_Idx>(__bound_args_)..., _VSTD::forward<_Args>(__args)...))) + -> decltype( _Op()(_VSTD::get<_Idx>(__bound_args_)..., _VSTD::forward<_Args>(__args)...)) + { return _Op()(_VSTD::get<_Idx>(__bound_args_)..., _VSTD::forward<_Args>(__args)...); } + + template >> + auto operator()(_Args&&...) const& = delete; + + template >> + _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Args&&... __args) && + noexcept(noexcept(_Op()(_VSTD::get<_Idx>(_VSTD::move(__bound_args_))..., _VSTD::forward<_Args>(__args)...))) + -> decltype( _Op()(_VSTD::get<_Idx>(_VSTD::move(__bound_args_))..., _VSTD::forward<_Args>(__args)...)) + { return _Op()(_VSTD::get<_Idx>(_VSTD::move(__bound_args_))..., _VSTD::forward<_Args>(__args)...); } + + template >> + auto operator()(_Args&&...) && = delete; + + template >> + _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Args&&... __args) const&& + noexcept(noexcept(_Op()(_VSTD::get<_Idx>(_VSTD::move(__bound_args_))..., _VSTD::forward<_Args>(__args)...))) + -> decltype( _Op()(_VSTD::get<_Idx>(_VSTD::move(__bound_args_))..., _VSTD::forward<_Args>(__args)...)) + { return _Op()(_VSTD::get<_Idx>(_VSTD::move(__bound_args_))..., _VSTD::forward<_Args>(__args)...); } + + template >> + auto operator()(_Args&&...) const&& = delete; +}; + +// __perfect_forward implements a perfect-forwarding call wrapper as explained in [func.require]. +template +using __perfect_forward = __perfect_forward_impl<_Op, index_sequence_for<_Args...>, _Args...>; + +#endif // _LIBCPP_STD_VER > 14 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___FUNCTIONAL_PERFECT_FORWARD_H diff --git a/app/src/main/cpp/libcxx/include/__functional/pointer_to_binary_function.h b/app/src/main/cpp/libcxx/include/__functional/pointer_to_binary_function.h new file mode 100644 index 0000000..b2676c5 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__functional/pointer_to_binary_function.h @@ -0,0 +1,46 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___FUNCTIONAL_POINTER_TO_BINARY_FUNCTION_H +#define _LIBCPP___FUNCTIONAL_POINTER_TO_BINARY_FUNCTION_H + +#include <__config> +#include <__functional/binary_function.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER <= 14 || defined(_LIBCPP_ENABLE_CXX17_REMOVED_BINDERS) + +template +class _LIBCPP_TEMPLATE_VIS _LIBCPP_DEPRECATED_IN_CXX11 pointer_to_binary_function + : public __binary_function<_Arg1, _Arg2, _Result> +{ + _Result (*__f_)(_Arg1, _Arg2); +public: + _LIBCPP_INLINE_VISIBILITY explicit pointer_to_binary_function(_Result (*__f)(_Arg1, _Arg2)) + : __f_(__f) {} + _LIBCPP_INLINE_VISIBILITY _Result operator()(_Arg1 __x, _Arg2 __y) const + {return __f_(__x, __y);} +}; + +template +_LIBCPP_DEPRECATED_IN_CXX11 inline _LIBCPP_INLINE_VISIBILITY +pointer_to_binary_function<_Arg1,_Arg2,_Result> +ptr_fun(_Result (*__f)(_Arg1,_Arg2)) + {return pointer_to_binary_function<_Arg1,_Arg2,_Result>(__f);} + +#endif + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___FUNCTIONAL_POINTER_TO_BINARY_FUNCTION_H diff --git a/app/src/main/cpp/libcxx/include/__functional/pointer_to_unary_function.h b/app/src/main/cpp/libcxx/include/__functional/pointer_to_unary_function.h new file mode 100644 index 0000000..77d07ad --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__functional/pointer_to_unary_function.h @@ -0,0 +1,46 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___FUNCTIONAL_POINTER_TO_UNARY_FUNCTION_H +#define _LIBCPP___FUNCTIONAL_POINTER_TO_UNARY_FUNCTION_H + +#include <__config> +#include <__functional/unary_function.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER <= 14 || defined(_LIBCPP_ENABLE_CXX17_REMOVED_BINDERS) + +template +class _LIBCPP_TEMPLATE_VIS _LIBCPP_DEPRECATED_IN_CXX11 pointer_to_unary_function + : public __unary_function<_Arg, _Result> +{ + _Result (*__f_)(_Arg); +public: + _LIBCPP_INLINE_VISIBILITY explicit pointer_to_unary_function(_Result (*__f)(_Arg)) + : __f_(__f) {} + _LIBCPP_INLINE_VISIBILITY _Result operator()(_Arg __x) const + {return __f_(__x);} +}; + +template +_LIBCPP_DEPRECATED_IN_CXX11 inline _LIBCPP_INLINE_VISIBILITY +pointer_to_unary_function<_Arg,_Result> +ptr_fun(_Result (*__f)(_Arg)) + {return pointer_to_unary_function<_Arg,_Result>(__f);} + +#endif // _LIBCPP_STD_VER <= 14 || defined(_LIBCPP_ENABLE_CXX17_REMOVED_BINDERS) + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___FUNCTIONAL_POINTER_TO_UNARY_FUNCTION_H diff --git a/app/src/main/cpp/libcxx/include/__functional/ranges_operations.h b/app/src/main/cpp/libcxx/include/__functional/ranges_operations.h new file mode 100644 index 0000000..87081dd --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__functional/ranges_operations.h @@ -0,0 +1,100 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___FUNCTIONAL_RANGES_OPERATIONS_H +#define _LIBCPP___FUNCTIONAL_RANGES_OPERATIONS_H + +#include <__concepts/equality_comparable.h> +#include <__concepts/totally_ordered.h> +#include <__config> +#include <__utility/forward.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 17 + +namespace ranges { + +struct equal_to { + template + requires equality_comparable_with<_Tp, _Up> + [[nodiscard]] constexpr bool operator()(_Tp &&__t, _Up &&__u) const + noexcept(noexcept(bool(_VSTD::forward<_Tp>(__t) == _VSTD::forward<_Up>(__u)))) { + return _VSTD::forward<_Tp>(__t) == _VSTD::forward<_Up>(__u); + } + + using is_transparent = void; +}; + +struct not_equal_to { + template + requires equality_comparable_with<_Tp, _Up> + [[nodiscard]] constexpr bool operator()(_Tp &&__t, _Up &&__u) const + noexcept(noexcept(bool(!(_VSTD::forward<_Tp>(__t) == _VSTD::forward<_Up>(__u))))) { + return !(_VSTD::forward<_Tp>(__t) == _VSTD::forward<_Up>(__u)); + } + + using is_transparent = void; +}; + +struct less { + template + requires totally_ordered_with<_Tp, _Up> + [[nodiscard]] constexpr bool operator()(_Tp &&__t, _Up &&__u) const + noexcept(noexcept(bool(_VSTD::forward<_Tp>(__t) < _VSTD::forward<_Up>(__u)))) { + return _VSTD::forward<_Tp>(__t) < _VSTD::forward<_Up>(__u); + } + + using is_transparent = void; +}; + +struct less_equal { + template + requires totally_ordered_with<_Tp, _Up> + [[nodiscard]] constexpr bool operator()(_Tp &&__t, _Up &&__u) const + noexcept(noexcept(bool(!(_VSTD::forward<_Up>(__u) < _VSTD::forward<_Tp>(__t))))) { + return !(_VSTD::forward<_Up>(__u) < _VSTD::forward<_Tp>(__t)); + } + + using is_transparent = void; +}; + +struct greater { + template + requires totally_ordered_with<_Tp, _Up> + [[nodiscard]] constexpr bool operator()(_Tp &&__t, _Up &&__u) const + noexcept(noexcept(bool(_VSTD::forward<_Up>(__u) < _VSTD::forward<_Tp>(__t)))) { + return _VSTD::forward<_Up>(__u) < _VSTD::forward<_Tp>(__t); + } + + using is_transparent = void; +}; + +struct greater_equal { + template + requires totally_ordered_with<_Tp, _Up> + [[nodiscard]] constexpr bool operator()(_Tp &&__t, _Up &&__u) const + noexcept(noexcept(bool(!(_VSTD::forward<_Tp>(__t) < _VSTD::forward<_Up>(__u))))) { + return !(_VSTD::forward<_Tp>(__t) < _VSTD::forward<_Up>(__u)); + } + + using is_transparent = void; +}; + +} // namespace ranges + +#endif // _LIBCPP_STD_VER > 17 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___FUNCTIONAL_RANGES_OPERATIONS_H diff --git a/app/src/main/cpp/libcxx/include/__functional/reference_wrapper.h b/app/src/main/cpp/libcxx/include/__functional/reference_wrapper.h new file mode 100644 index 0000000..c377b64 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__functional/reference_wrapper.h @@ -0,0 +1,105 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___FUNCTIONAL_REFERENCE_WRAPPER_H +#define _LIBCPP___FUNCTIONAL_REFERENCE_WRAPPER_H + +#include <__config> +#include <__functional/invoke.h> +#include <__functional/weak_result_type.h> +#include <__memory/addressof.h> +#include <__type_traits/enable_if.h> +#include <__type_traits/remove_cvref.h> +#include <__utility/declval.h> +#include <__utility/forward.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +template +class _LIBCPP_TEMPLATE_VIS reference_wrapper : public __weak_result_type<_Tp> +{ +public: + // types + typedef _Tp type; +private: + type* __f_; + + static void __fun(_Tp&) _NOEXCEPT; + static void __fun(_Tp&&) = delete; + +public: + template ::value, decltype(__fun(std::declval<_Up>())) > > + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 + reference_wrapper(_Up&& __u) _NOEXCEPT_(noexcept(__fun(std::declval<_Up>()))) { + type& __f = static_cast<_Up&&>(__u); + __f_ = _VSTD::addressof(__f); + } + + // access + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 + operator type&() const _NOEXCEPT {return *__f_;} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 + type& get() const _NOEXCEPT {return *__f_;} + + // invoke + template + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 + typename __invoke_of::type + operator() (_ArgTypes&&... __args) const { + return std::__invoke(get(), std::forward<_ArgTypes>(__args)...); + } +}; + +#if _LIBCPP_STD_VER > 14 +template +reference_wrapper(_Tp&) -> reference_wrapper<_Tp>; +#endif + +template +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 +reference_wrapper<_Tp> +ref(_Tp& __t) _NOEXCEPT +{ + return reference_wrapper<_Tp>(__t); +} + +template +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 +reference_wrapper<_Tp> +ref(reference_wrapper<_Tp> __t) _NOEXCEPT +{ + return __t; +} + +template +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 +reference_wrapper +cref(const _Tp& __t) _NOEXCEPT +{ + return reference_wrapper(__t); +} + +template +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 +reference_wrapper +cref(reference_wrapper<_Tp> __t) _NOEXCEPT +{ + return __t; +} + +template void ref(const _Tp&&) = delete; +template void cref(const _Tp&&) = delete; + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___FUNCTIONAL_REFERENCE_WRAPPER_H diff --git a/app/src/main/cpp/libcxx/include/__functional/unary_function.h b/app/src/main/cpp/libcxx/include/__functional/unary_function.h new file mode 100644 index 0000000..f07cac1 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__functional/unary_function.h @@ -0,0 +1,51 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___FUNCTIONAL_UNARY_FUNCTION_H +#define _LIBCPP___FUNCTIONAL_UNARY_FUNCTION_H + +#include <__config> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER <= 14 || defined(_LIBCPP_ENABLE_CXX17_REMOVED_UNARY_BINARY_FUNCTION) + +template +struct _LIBCPP_TEMPLATE_VIS _LIBCPP_DEPRECATED_IN_CXX11 unary_function +{ + typedef _Arg argument_type; + typedef _Result result_type; +}; + +#endif // _LIBCPP_STD_VER <= 14 + +template struct __unary_function_keep_layout_base { +#if _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_ENABLE_CXX20_REMOVED_BINDER_TYPEDEFS) + using argument_type _LIBCPP_DEPRECATED_IN_CXX17 = _Arg; + using result_type _LIBCPP_DEPRECATED_IN_CXX17 = _Result; +#endif +}; + +#if _LIBCPP_STD_VER <= 14 || defined(_LIBCPP_ENABLE_CXX17_REMOVED_UNARY_BINARY_FUNCTION) +_LIBCPP_DIAGNOSTIC_PUSH +_LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wdeprecated-declarations") +template +using __unary_function = unary_function<_Arg, _Result>; +_LIBCPP_DIAGNOSTIC_POP +#else +template +using __unary_function = __unary_function_keep_layout_base<_Arg, _Result>; +#endif + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___FUNCTIONAL_UNARY_FUNCTION_H diff --git a/app/src/main/cpp/libcxx/include/__functional/unary_negate.h b/app/src/main/cpp/libcxx/include/__functional/unary_negate.h new file mode 100644 index 0000000..ab87e86 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__functional/unary_negate.h @@ -0,0 +1,47 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___FUNCTIONAL_UNARY_NEGATE_H +#define _LIBCPP___FUNCTIONAL_UNARY_NEGATE_H + +#include <__config> +#include <__functional/unary_function.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_ENABLE_CXX20_REMOVED_NEGATORS) + +template +class _LIBCPP_TEMPLATE_VIS _LIBCPP_DEPRECATED_IN_CXX17 unary_negate + : public __unary_function +{ + _Predicate __pred_; +public: + _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_INLINE_VISIBILITY + explicit unary_negate(const _Predicate& __pred) + : __pred_(__pred) {} + _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_INLINE_VISIBILITY + bool operator()(const typename _Predicate::argument_type& __x) const + {return !__pred_(__x);} +}; + +template +_LIBCPP_DEPRECATED_IN_CXX17 inline _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_INLINE_VISIBILITY +unary_negate<_Predicate> +not1(const _Predicate& __pred) {return unary_negate<_Predicate>(__pred);} + +#endif // _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_ENABLE_CXX20_REMOVED_NEGATORS) + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___FUNCTIONAL_UNARY_NEGATE_H diff --git a/app/src/main/cpp/libcxx/include/__functional/unwrap_ref.h b/app/src/main/cpp/libcxx/include/__functional/unwrap_ref.h new file mode 100644 index 0000000..da000d8 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__functional/unwrap_ref.h @@ -0,0 +1,58 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___FUNCTIONAL_UNWRAP_REF_H +#define _LIBCPP___FUNCTIONAL_UNWRAP_REF_H + +#include <__config> +#include <__type_traits/decay.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +template +struct __unwrap_reference { typedef _LIBCPP_NODEBUG _Tp type; }; + +template +class reference_wrapper; + +template +struct __unwrap_reference > { typedef _LIBCPP_NODEBUG _Tp& type; }; + +template +struct decay; + +#if _LIBCPP_STD_VER > 17 +template +struct unwrap_reference : __unwrap_reference<_Tp> { }; + +template +using unwrap_reference_t = typename unwrap_reference<_Tp>::type; + +template +struct unwrap_ref_decay : unwrap_reference::type> { }; + +template +using unwrap_ref_decay_t = typename unwrap_ref_decay<_Tp>::type; +#endif // > C++17 + +template +struct __unwrap_ref_decay +#if _LIBCPP_STD_VER > 17 + : unwrap_ref_decay<_Tp> +#else + : __unwrap_reference::type> +#endif +{ }; + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___FUNCTIONAL_UNWRAP_REF_H diff --git a/app/src/main/cpp/libcxx/include/__functional/weak_result_type.h b/app/src/main/cpp/libcxx/include/__functional/weak_result_type.h new file mode 100644 index 0000000..18d1bf7 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__functional/weak_result_type.h @@ -0,0 +1,294 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___FUNCTIONAL_WEAK_RESULT_TYPE_H +#define _LIBCPP___FUNCTIONAL_WEAK_RESULT_TYPE_H + +#include <__config> +#include <__functional/binary_function.h> +#include <__functional/invoke.h> +#include <__functional/unary_function.h> +#include <__type_traits/integral_constant.h> +#include <__type_traits/is_same.h> +#include <__utility/declval.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +template +struct __has_result_type +{ +private: + template static false_type __test(...); + template static true_type __test(typename _Up::result_type* = 0); +public: + static const bool value = decltype(__test<_Tp>(0))::value; +}; + +// __weak_result_type + +template +struct __derives_from_unary_function +{ +private: + struct __two {char __lx; char __lxx;}; + static __two __test(...); + template + static __unary_function<_Ap, _Rp> + __test(const volatile __unary_function<_Ap, _Rp>*); + +public: + static const bool value = !is_same::value; + typedef decltype(__test((_Tp*)0)) type; +}; + +template +struct __derives_from_binary_function +{ +private: + struct __two {char __lx; char __lxx;}; + static __two __test(...); + template + static __binary_function<_A1, _A2, _Rp> + __test(const volatile __binary_function<_A1, _A2, _Rp>*); + +public: + static const bool value = !is_same::value; + typedef decltype(__test((_Tp*)0)) type; +}; + +template ::value> +struct __maybe_derive_from_unary_function // bool is true + : public __derives_from_unary_function<_Tp>::type +{ +}; + +template +struct __maybe_derive_from_unary_function<_Tp, false> +{ +}; + +template ::value> +struct __maybe_derive_from_binary_function // bool is true + : public __derives_from_binary_function<_Tp>::type +{ +}; + +template +struct __maybe_derive_from_binary_function<_Tp, false> +{ +}; + +template ::value> +struct __weak_result_type_imp // bool is true + : public __maybe_derive_from_unary_function<_Tp>, + public __maybe_derive_from_binary_function<_Tp> +{ +#if _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_ENABLE_CXX20_REMOVED_BINDER_TYPEDEFS) + using result_type _LIBCPP_NODEBUG _LIBCPP_DEPRECATED_IN_CXX17 = typename _Tp::result_type; +#endif +}; + +template +struct __weak_result_type_imp<_Tp, false> + : public __maybe_derive_from_unary_function<_Tp>, + public __maybe_derive_from_binary_function<_Tp> +{ +}; + +template +struct __weak_result_type + : public __weak_result_type_imp<_Tp> +{ +}; + +// 0 argument case + +template +struct __weak_result_type<_Rp ()> +{ +#if _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_ENABLE_CXX20_REMOVED_BINDER_TYPEDEFS) + using result_type _LIBCPP_NODEBUG _LIBCPP_DEPRECATED_IN_CXX17 = _Rp; +#endif +}; + +template +struct __weak_result_type<_Rp (&)()> +{ +#if _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_ENABLE_CXX20_REMOVED_BINDER_TYPEDEFS) + using result_type _LIBCPP_NODEBUG _LIBCPP_DEPRECATED_IN_CXX17 = _Rp; +#endif +}; + +template +struct __weak_result_type<_Rp (*)()> +{ +#if _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_ENABLE_CXX20_REMOVED_BINDER_TYPEDEFS) + using result_type _LIBCPP_NODEBUG _LIBCPP_DEPRECATED_IN_CXX17 = _Rp; +#endif +}; + +// 1 argument case + +template +struct __weak_result_type<_Rp (_A1)> + : public __unary_function<_A1, _Rp> +{ +}; + +template +struct __weak_result_type<_Rp (&)(_A1)> + : public __unary_function<_A1, _Rp> +{ +}; + +template +struct __weak_result_type<_Rp (*)(_A1)> + : public __unary_function<_A1, _Rp> +{ +}; + +template +struct __weak_result_type<_Rp (_Cp::*)()> + : public __unary_function<_Cp*, _Rp> +{ +}; + +template +struct __weak_result_type<_Rp (_Cp::*)() const> + : public __unary_function +{ +}; + +template +struct __weak_result_type<_Rp (_Cp::*)() volatile> + : public __unary_function +{ +}; + +template +struct __weak_result_type<_Rp (_Cp::*)() const volatile> + : public __unary_function +{ +}; + +// 2 argument case + +template +struct __weak_result_type<_Rp (_A1, _A2)> + : public __binary_function<_A1, _A2, _Rp> +{ +}; + +template +struct __weak_result_type<_Rp (*)(_A1, _A2)> + : public __binary_function<_A1, _A2, _Rp> +{ +}; + +template +struct __weak_result_type<_Rp (&)(_A1, _A2)> + : public __binary_function<_A1, _A2, _Rp> +{ +}; + +template +struct __weak_result_type<_Rp (_Cp::*)(_A1)> + : public __binary_function<_Cp*, _A1, _Rp> +{ +}; + +template +struct __weak_result_type<_Rp (_Cp::*)(_A1) const> + : public __binary_function +{ +}; + +template +struct __weak_result_type<_Rp (_Cp::*)(_A1) volatile> + : public __binary_function +{ +}; + +template +struct __weak_result_type<_Rp (_Cp::*)(_A1) const volatile> + : public __binary_function +{ +}; + +// 3 or more arguments + +template +struct __weak_result_type<_Rp (_A1, _A2, _A3, _A4...)> +{ +#if _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_ENABLE_CXX20_REMOVED_BINDER_TYPEDEFS) + using result_type _LIBCPP_NODEBUG _LIBCPP_DEPRECATED_IN_CXX17 = _Rp; +#endif +}; + +template +struct __weak_result_type<_Rp (&)(_A1, _A2, _A3, _A4...)> +{ +#if _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_ENABLE_CXX20_REMOVED_BINDER_TYPEDEFS) + using result_type _LIBCPP_NODEBUG _LIBCPP_DEPRECATED_IN_CXX17 = _Rp; +#endif +}; + +template +struct __weak_result_type<_Rp (*)(_A1, _A2, _A3, _A4...)> +{ +#if _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_ENABLE_CXX20_REMOVED_BINDER_TYPEDEFS) + using result_type _LIBCPP_NODEBUG _LIBCPP_DEPRECATED_IN_CXX17 = _Rp; +#endif +}; + +template +struct __weak_result_type<_Rp (_Cp::*)(_A1, _A2, _A3...)> +{ +#if _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_ENABLE_CXX20_REMOVED_BINDER_TYPEDEFS) + using result_type _LIBCPP_NODEBUG _LIBCPP_DEPRECATED_IN_CXX17 = _Rp; +#endif +}; + +template +struct __weak_result_type<_Rp (_Cp::*)(_A1, _A2, _A3...) const> +{ +#if _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_ENABLE_CXX20_REMOVED_BINDER_TYPEDEFS) + using result_type _LIBCPP_NODEBUG _LIBCPP_DEPRECATED_IN_CXX17 = _Rp; +#endif +}; + +template +struct __weak_result_type<_Rp (_Cp::*)(_A1, _A2, _A3...) volatile> +{ +#if _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_ENABLE_CXX20_REMOVED_BINDER_TYPEDEFS) + using result_type _LIBCPP_NODEBUG _LIBCPP_DEPRECATED_IN_CXX17 = _Rp; +#endif +}; + +template +struct __weak_result_type<_Rp (_Cp::*)(_A1, _A2, _A3...) const volatile> +{ +#if _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_ENABLE_CXX20_REMOVED_BINDER_TYPEDEFS) + using result_type _LIBCPP_NODEBUG _LIBCPP_DEPRECATED_IN_CXX17 = _Rp; +#endif +}; + +template +struct __invoke_return +{ + typedef decltype(_VSTD::__invoke(std::declval<_Tp>(), std::declval<_Args>()...)) type; +}; + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___FUNCTIONAL_WEAK_RESULT_TYPE_H diff --git a/app/src/main/cpp/libcxx/include/__fwd/array.h b/app/src/main/cpp/libcxx/include/__fwd/array.h new file mode 100644 index 0000000..9a79eff --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__fwd/array.h @@ -0,0 +1,26 @@ +//===---------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===---------------------------------------------------------------------===// + +#ifndef _LIBCPP___FWD_ARRAY_H +#define _LIBCPP___FWD_ARRAY_H + +#include <__config> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +template +struct _LIBCPP_TEMPLATE_VIS array; + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___FWD_ARRAY_H diff --git a/app/src/main/cpp/libcxx/include/__fwd/get.h b/app/src/main/cpp/libcxx/include/__fwd/get.h new file mode 100644 index 0000000..ec1fab4 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__fwd/get.h @@ -0,0 +1,115 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___FWD_GET_H +#define _LIBCPP___FWD_GET_H + +#include <__concepts/copyable.h> +#include <__config> +#include <__fwd/array.h> +#include <__fwd/pair.h> +#include <__fwd/subrange.h> +#include <__fwd/tuple.h> +#include <__tuple_dir/tuple_element.h> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#ifndef _LIBCPP_CXX03_LANG + +template +_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 +typename tuple_element<_Ip, tuple<_Tp...> >::type& +get(tuple<_Tp...>&) _NOEXCEPT; + +template +_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 +const typename tuple_element<_Ip, tuple<_Tp...> >::type& +get(const tuple<_Tp...>&) _NOEXCEPT; + +template +_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 +typename tuple_element<_Ip, tuple<_Tp...> >::type&& +get(tuple<_Tp...>&&) _NOEXCEPT; + +template +_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 +const typename tuple_element<_Ip, tuple<_Tp...> >::type&& +get(const tuple<_Tp...>&&) _NOEXCEPT; + +#endif //_LIBCPP_CXX03_LANG + +template +_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 +typename tuple_element<_Ip, pair<_T1, _T2> >::type& +get(pair<_T1, _T2>&) _NOEXCEPT; + +template +_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 +const typename tuple_element<_Ip, pair<_T1, _T2> >::type& +get(const pair<_T1, _T2>&) _NOEXCEPT; + +#ifndef _LIBCPP_CXX03_LANG +template +_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 +typename tuple_element<_Ip, pair<_T1, _T2> >::type&& +get(pair<_T1, _T2>&&) _NOEXCEPT; + +template +_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 +const typename tuple_element<_Ip, pair<_T1, _T2> >::type&& +get(const pair<_T1, _T2>&&) _NOEXCEPT; +#endif + +template +_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 +_Tp& +get(array<_Tp, _Size>&) _NOEXCEPT; + +template +_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 +const _Tp& +get(const array<_Tp, _Size>&) _NOEXCEPT; + +#ifndef _LIBCPP_CXX03_LANG +template +_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 +_Tp&& +get(array<_Tp, _Size>&&) _NOEXCEPT; + +template +_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 +const _Tp&& +get(const array<_Tp, _Size>&&) _NOEXCEPT; +#endif + +#if _LIBCPP_STD_VER >= 20 + +namespace ranges { + +template + requires((_Index == 0 && copyable<_Iter>) || _Index == 1) +_LIBCPP_HIDE_FROM_ABI constexpr auto get(const subrange<_Iter, _Sent, _Kind>& __subrange); + +template + requires(_Index < 2) +_LIBCPP_HIDE_FROM_ABI constexpr auto get(subrange<_Iter, _Sent, _Kind>&& __subrange); + +} // namespace ranges + +using ranges::get; + +#endif // _LIBCPP_STD_VER >= 20 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___FWD_GET_H diff --git a/app/src/main/cpp/libcxx/include/__fwd/hash.h b/app/src/main/cpp/libcxx/include/__fwd/hash.h new file mode 100644 index 0000000..af9eca8 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__fwd/hash.h @@ -0,0 +1,25 @@ +//===---------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===---------------------------------------------------------------------===// + +#ifndef _LIBCPP___FWD_HASH_H +#define _LIBCPP___FWD_HASH_H + +#include <__config> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +template +struct _LIBCPP_TEMPLATE_VIS hash; + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___FWD_HASH_H diff --git a/app/src/main/cpp/libcxx/include/__fwd/memory_resource.h b/app/src/main/cpp/libcxx/include/__fwd/memory_resource.h new file mode 100644 index 0000000..718a907 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__fwd/memory_resource.h @@ -0,0 +1,27 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___FWD_MEMORY_RESOURCE_H +#define _LIBCPP___FWD_MEMORY_RESOURCE_H + +#include <__config> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace pmr { +template +class _LIBCPP_TEMPLATE_VIS polymorphic_allocator; +} // namespace pmr + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___FWD_MEMORY_RESOURCE_H diff --git a/app/src/main/cpp/libcxx/include/__fwd/pair.h b/app/src/main/cpp/libcxx/include/__fwd/pair.h new file mode 100644 index 0000000..3844014 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__fwd/pair.h @@ -0,0 +1,25 @@ +//===---------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===---------------------------------------------------------------------===// + +#ifndef _LIBCPP___FWD_PAIR_H +#define _LIBCPP___FWD_PAIR_H + +#include <__config> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +template +struct _LIBCPP_TEMPLATE_VIS pair; + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___FWD_PAIR_H diff --git a/app/src/main/cpp/libcxx/include/__fwd/span.h b/app/src/main/cpp/libcxx/include/__fwd/span.h new file mode 100644 index 0000000..943cb13 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__fwd/span.h @@ -0,0 +1,37 @@ +// -*- C++ -*- +//===---------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===---------------------------------------------------------------------===// + +#ifndef _LIBCPP___FWD_SPAN_H +#define _LIBCPP___FWD_SPAN_H + +#include <__config> +#include +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 17 + +inline constexpr size_t dynamic_extent = numeric_limits::max(); +template class span; + +#endif + +_LIBCPP_END_NAMESPACE_STD + +_LIBCPP_POP_MACROS + +#endif // _LIBCPP___FWD_SPAN_H diff --git a/app/src/main/cpp/libcxx/include/__fwd/string.h b/app/src/main/cpp/libcxx/include/__fwd/string.h new file mode 100644 index 0000000..7ab5561 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__fwd/string.h @@ -0,0 +1,110 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___FWD_STRING_H +#define _LIBCPP___FWD_STRING_H + +#include <__config> +#include <__fwd/memory_resource.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +template +struct _LIBCPP_TEMPLATE_VIS char_traits; +template <> +struct char_traits; + +#ifndef _LIBCPP_HAS_NO_CHAR8_T +template <> +struct char_traits; +#endif + +template <> +struct char_traits; +template <> +struct char_traits; + +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +template <> +struct char_traits; +#endif + +template +class _LIBCPP_TEMPLATE_VIS allocator; + +template , class _Allocator = allocator<_CharT> > +class _LIBCPP_TEMPLATE_VIS basic_string; + +using string = basic_string; + +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +using wstring = basic_string; +#endif + +#ifndef _LIBCPP_HAS_NO_CHAR8_T +using u8string = basic_string; +#endif + +using u16string = basic_string; +using u32string = basic_string; + +#if _LIBCPP_STD_VER >= 17 + +namespace pmr { +template > +using basic_string = std::basic_string<_CharT, _Traits, polymorphic_allocator<_CharT>>; + +using string = basic_string; + +# ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +using wstring = basic_string; +# endif + +# ifndef _LIBCPP_HAS_NO_CHAR8_T +using u8string = basic_string; +# endif + +using u16string = basic_string; +using u32string = basic_string; + +} // namespace pmr + +#endif // _LIBCPP_STD_VER >= 17 + +// clang-format off +template +class _LIBCPP_PREFERRED_NAME(string) +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS + _LIBCPP_PREFERRED_NAME(wstring) +#endif +#ifndef _LIBCPP_HAS_NO_CHAR8_T + _LIBCPP_PREFERRED_NAME(u8string) +#endif + _LIBCPP_PREFERRED_NAME(u16string) + _LIBCPP_PREFERRED_NAME(u32string) +#if _LIBCPP_STD_VER >= 17 + _LIBCPP_PREFERRED_NAME(pmr::string) +# ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS + _LIBCPP_PREFERRED_NAME(pmr::wstring) +# endif +# ifndef _LIBCPP_HAS_NO_CHAR8_T + _LIBCPP_PREFERRED_NAME(pmr::u8string) +# endif + _LIBCPP_PREFERRED_NAME(pmr::u16string) + _LIBCPP_PREFERRED_NAME(pmr::u32string) +#endif + basic_string; +// clang-format on + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___FWD_STRING_H diff --git a/app/src/main/cpp/libcxx/include/__fwd/string_view.h b/app/src/main/cpp/libcxx/include/__fwd/string_view.h new file mode 100644 index 0000000..4818990 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__fwd/string_view.h @@ -0,0 +1,50 @@ +// -*- C++ -*- +//===---------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===---------------------------------------------------------------------===// + +#ifndef _LIBCPP___FWD_STRING_VIEW_H +#define _LIBCPP___FWD_STRING_VIEW_H + +#include <__config> +#include // char_traits + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +template > +class _LIBCPP_TEMPLATE_VIS basic_string_view; + +typedef basic_string_view string_view; +#ifndef _LIBCPP_HAS_NO_CHAR8_T +typedef basic_string_view u8string_view; +#endif +typedef basic_string_view u16string_view; +typedef basic_string_view u32string_view; +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +typedef basic_string_view wstring_view; +#endif + +// clang-format off +template +class _LIBCPP_PREFERRED_NAME(string_view) +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS + _LIBCPP_PREFERRED_NAME(wstring_view) +#endif +#ifndef _LIBCPP_HAS_NO_CHAR8_T + _LIBCPP_PREFERRED_NAME(u8string_view) +#endif + _LIBCPP_PREFERRED_NAME(u16string_view) + _LIBCPP_PREFERRED_NAME(u32string_view) + basic_string_view; +// clang-format on +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___FWD_STRING_VIEW_H diff --git a/app/src/main/cpp/libcxx/include/__fwd/subrange.h b/app/src/main/cpp/libcxx/include/__fwd/subrange.h new file mode 100644 index 0000000..8f72392 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__fwd/subrange.h @@ -0,0 +1,38 @@ +//===---------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===---------------------------------------------------------------------===// + +#ifndef _LIBCPP___FWD_SUBRANGE_H +#define _LIBCPP___FWD_SUBRANGE_H + +#include <__config> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if _LIBCPP_STD_VER >= 20 + +#include <__iterator/concepts.h> + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace ranges { + +enum class _LIBCPP_ENUM_VIS subrange_kind : bool { unsized, sized }; + +template _Sent, subrange_kind _Kind> + requires(_Kind == subrange_kind::sized || !sized_sentinel_for<_Sent, _Iter>) +class _LIBCPP_TEMPLATE_VIS subrange; + +} // namespace ranges + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER >= 20 + +#endif // _LIBCPP___FWD_SUBRANGE_H diff --git a/app/src/main/cpp/libcxx/include/__fwd/tuple.h b/app/src/main/cpp/libcxx/include/__fwd/tuple.h new file mode 100644 index 0000000..16b3fab --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__fwd/tuple.h @@ -0,0 +1,29 @@ +//===---------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===---------------------------------------------------------------------===// + +#ifndef _LIBCPP___FWD_TUPLE_H +#define _LIBCPP___FWD_TUPLE_H + +#include <__config> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#ifndef _LIBCPP_CXX03_LANG + +template +class _LIBCPP_TEMPLATE_VIS tuple; + +#endif // _LIBCPP_CXX03_LANG + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___FWD_TUPLE_H diff --git a/app/src/main/cpp/libcxx/include/__hash_table b/app/src/main/cpp/libcxx/include/__hash_table new file mode 100644 index 0000000..f8896c8 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__hash_table @@ -0,0 +1,2715 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___HASH_TABLE +#define _LIBCPP___HASH_TABLE + +#include <__algorithm/max.h> +#include <__algorithm/min.h> +#include <__assert> +#include <__bit/countl.h> +#include <__config> +#include <__debug> +#include <__functional/hash.h> +#include <__iterator/iterator_traits.h> +#include <__memory/addressof.h> +#include <__memory/allocator_traits.h> +#include <__memory/compressed_pair.h> +#include <__memory/pointer_traits.h> +#include <__memory/swap_allocator.h> +#include <__memory/unique_ptr.h> +#include <__type_traits/can_extract_key.h> +#include <__utility/forward.h> +#include <__utility/move.h> +#include <__utility/pair.h> +#include <__utility/swap.h> +#include +#include +#include +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + + +_LIBCPP_BEGIN_NAMESPACE_STD + +template +struct __hash_value_type; + +template +struct __is_hash_value_type_imp : false_type {}; + +template +struct __is_hash_value_type_imp<__hash_value_type<_Key, _Value> > : true_type {}; + +template +struct __is_hash_value_type : false_type {}; + +template +struct __is_hash_value_type<_One> : __is_hash_value_type_imp<__remove_cvref_t<_One> > {}; + +_LIBCPP_FUNC_VIS +size_t __next_prime(size_t __n); + +template +struct __hash_node_base +{ + typedef typename pointer_traits<_NodePtr>::element_type __node_type; + typedef __hash_node_base __first_node; + typedef __rebind_pointer_t<_NodePtr, __first_node> __node_base_pointer; + typedef _NodePtr __node_pointer; + +#if defined(_LIBCPP_ABI_FIX_UNORDERED_NODE_POINTER_UB) + typedef __node_base_pointer __next_pointer; +#else + typedef __conditional_t::value, __node_base_pointer, __node_pointer> __next_pointer; +#endif + + __next_pointer __next_; + + _LIBCPP_INLINE_VISIBILITY + __next_pointer __ptr() _NOEXCEPT { + return static_cast<__next_pointer>( + pointer_traits<__node_base_pointer>::pointer_to(*this)); + } + + _LIBCPP_INLINE_VISIBILITY + __node_pointer __upcast() _NOEXCEPT { + return static_cast<__node_pointer>( + pointer_traits<__node_base_pointer>::pointer_to(*this)); + } + + _LIBCPP_INLINE_VISIBILITY + size_t __hash() const _NOEXCEPT { + return static_cast<__node_type const&>(*this).__hash_; + } + + _LIBCPP_INLINE_VISIBILITY __hash_node_base() _NOEXCEPT : __next_(nullptr) {} +}; + +template +struct _LIBCPP_STANDALONE_DEBUG __hash_node + : public __hash_node_base + < + __rebind_pointer_t<_VoidPtr, __hash_node<_Tp, _VoidPtr> > + > +{ + typedef _Tp __node_value_type; + + size_t __hash_; + __node_value_type __value_; +}; + +inline _LIBCPP_INLINE_VISIBILITY +bool +__is_hash_power2(size_t __bc) +{ + return __bc > 2 && !(__bc & (__bc - 1)); +} + +inline _LIBCPP_INLINE_VISIBILITY +size_t +__constrain_hash(size_t __h, size_t __bc) +{ + return !(__bc & (__bc - 1)) ? __h & (__bc - 1) : + (__h < __bc ? __h : __h % __bc); +} + +inline _LIBCPP_INLINE_VISIBILITY +size_t +__next_hash_pow2(size_t __n) +{ + return __n < 2 ? __n : (size_t(1) << (numeric_limits::digits - __libcpp_clz(__n-1))); +} + + +template class __hash_table; + +template class _LIBCPP_TEMPLATE_VIS __hash_iterator; +template class _LIBCPP_TEMPLATE_VIS __hash_const_iterator; +template class _LIBCPP_TEMPLATE_VIS __hash_local_iterator; +template class _LIBCPP_TEMPLATE_VIS __hash_const_local_iterator; +template class _LIBCPP_TEMPLATE_VIS __hash_map_iterator; +template class _LIBCPP_TEMPLATE_VIS __hash_map_const_iterator; + +template +struct __hash_key_value_types { + static_assert(!is_reference<_Tp>::value && !is_const<_Tp>::value, ""); + typedef _Tp key_type; + typedef _Tp __node_value_type; + typedef _Tp __container_value_type; + static const bool __is_map = false; + + _LIBCPP_INLINE_VISIBILITY + static key_type const& __get_key(_Tp const& __v) { + return __v; + } + _LIBCPP_INLINE_VISIBILITY + static __container_value_type const& __get_value(__node_value_type const& __v) { + return __v; + } + _LIBCPP_INLINE_VISIBILITY + static __container_value_type* __get_ptr(__node_value_type& __n) { + return _VSTD::addressof(__n); + } + _LIBCPP_INLINE_VISIBILITY + static __container_value_type&& __move(__node_value_type& __v) { + return _VSTD::move(__v); + } +}; + +template +struct __hash_key_value_types<__hash_value_type<_Key, _Tp> > { + typedef _Key key_type; + typedef _Tp mapped_type; + typedef __hash_value_type<_Key, _Tp> __node_value_type; + typedef pair __container_value_type; + typedef __container_value_type __map_value_type; + static const bool __is_map = true; + + _LIBCPP_INLINE_VISIBILITY + static key_type const& __get_key(__container_value_type const& __v) { + return __v.first; + } + + template + _LIBCPP_INLINE_VISIBILITY + static __enable_if_t<__is_same_uncvref<_Up, __node_value_type>::value, __container_value_type const&> + __get_value(_Up& __t) { + return __t.__get_value(); + } + + template + _LIBCPP_INLINE_VISIBILITY + static __enable_if_t<__is_same_uncvref<_Up, __container_value_type>::value, __container_value_type const&> + __get_value(_Up& __t) { + return __t; + } + + _LIBCPP_INLINE_VISIBILITY + static __container_value_type* __get_ptr(__node_value_type& __n) { + return _VSTD::addressof(__n.__get_value()); + } + _LIBCPP_INLINE_VISIBILITY + static pair __move(__node_value_type& __v) { + return __v.__move(); + } +}; + +template , + bool = _KVTypes::__is_map> +struct __hash_map_pointer_types {}; + +template +struct __hash_map_pointer_types<_Tp, _AllocPtr, _KVTypes, true> { + typedef typename _KVTypes::__map_value_type _Mv; + typedef __rebind_pointer_t<_AllocPtr, _Mv> + __map_value_type_pointer; + typedef __rebind_pointer_t<_AllocPtr, const _Mv> + __const_map_value_type_pointer; +}; + +template ::element_type> +struct __hash_node_types; + +template +struct __hash_node_types<_NodePtr, __hash_node<_Tp, _VoidPtr> > + : public __hash_key_value_types<_Tp>, __hash_map_pointer_types<_Tp, _VoidPtr> + +{ + typedef __hash_key_value_types<_Tp> __base; + +public: + typedef ptrdiff_t difference_type; + typedef size_t size_type; + + typedef __rebind_pointer_t<_NodePtr, void> __void_pointer; + + typedef typename pointer_traits<_NodePtr>::element_type __node_type; + typedef _NodePtr __node_pointer; + + typedef __hash_node_base<__node_pointer> __node_base_type; + typedef __rebind_pointer_t<_NodePtr, __node_base_type> + __node_base_pointer; + + typedef typename __node_base_type::__next_pointer __next_pointer; + + typedef _Tp __node_value_type; + typedef __rebind_pointer_t<_VoidPtr, __node_value_type> + __node_value_type_pointer; + typedef __rebind_pointer_t<_VoidPtr, const __node_value_type> + __const_node_value_type_pointer; + +private: + static_assert(!is_const<__node_type>::value, + "_NodePtr should never be a pointer to const"); + static_assert((is_same::element_type, void>::value), + "_VoidPtr does not point to unqualified void type"); + static_assert((is_same<__rebind_pointer_t<_VoidPtr, __node_type>, + _NodePtr>::value), "_VoidPtr does not rebind to _NodePtr."); +}; + +template +struct __hash_node_types_from_iterator; +template +struct __hash_node_types_from_iterator<__hash_iterator<_NodePtr> > : __hash_node_types<_NodePtr> {}; +template +struct __hash_node_types_from_iterator<__hash_const_iterator<_NodePtr> > : __hash_node_types<_NodePtr> {}; +template +struct __hash_node_types_from_iterator<__hash_local_iterator<_NodePtr> > : __hash_node_types<_NodePtr> {}; +template +struct __hash_node_types_from_iterator<__hash_const_local_iterator<_NodePtr> > : __hash_node_types<_NodePtr> {}; + + +template +struct __make_hash_node_types { + typedef __hash_node<_NodeValueTp, _VoidPtr> _NodeTp; + typedef __rebind_pointer_t<_VoidPtr, _NodeTp> _NodePtr; + typedef __hash_node_types<_NodePtr> type; +}; + +template +class _LIBCPP_TEMPLATE_VIS __hash_iterator +{ + typedef __hash_node_types<_NodePtr> _NodeTypes; + typedef _NodePtr __node_pointer; + typedef typename _NodeTypes::__next_pointer __next_pointer; + + __next_pointer __node_; + +public: + typedef forward_iterator_tag iterator_category; + typedef typename _NodeTypes::__node_value_type value_type; + typedef typename _NodeTypes::difference_type difference_type; + typedef value_type& reference; + typedef typename _NodeTypes::__node_value_type_pointer pointer; + + _LIBCPP_INLINE_VISIBILITY __hash_iterator() _NOEXCEPT : __node_(nullptr) { + _VSTD::__debug_db_insert_i(this); + } + +#ifdef _LIBCPP_ENABLE_DEBUG_MODE + _LIBCPP_INLINE_VISIBILITY + __hash_iterator(const __hash_iterator& __i) + : __node_(__i.__node_) + { + __get_db()->__iterator_copy(this, _VSTD::addressof(__i)); + } + + _LIBCPP_INLINE_VISIBILITY + ~__hash_iterator() + { + __get_db()->__erase_i(this); + } + + _LIBCPP_INLINE_VISIBILITY + __hash_iterator& operator=(const __hash_iterator& __i) + { + if (this != _VSTD::addressof(__i)) + { + __get_db()->__iterator_copy(this, _VSTD::addressof(__i)); + __node_ = __i.__node_; + } + return *this; + } +#endif // _LIBCPP_ENABLE_DEBUG_MODE + + _LIBCPP_INLINE_VISIBILITY + reference operator*() const { + _LIBCPP_DEBUG_ASSERT(__get_const_db()->__dereferenceable(this), + "Attempted to dereference a non-dereferenceable unordered container iterator"); + return __node_->__upcast()->__value_; + } + + _LIBCPP_INLINE_VISIBILITY + pointer operator->() const { + _LIBCPP_DEBUG_ASSERT(__get_const_db()->__dereferenceable(this), + "Attempted to dereference a non-dereferenceable unordered container iterator"); + return pointer_traits::pointer_to(__node_->__upcast()->__value_); + } + + _LIBCPP_INLINE_VISIBILITY + __hash_iterator& operator++() { + _LIBCPP_DEBUG_ASSERT(__get_const_db()->__dereferenceable(this), + "Attempted to increment a non-incrementable unordered container iterator"); + __node_ = __node_->__next_; + return *this; + } + + _LIBCPP_INLINE_VISIBILITY + __hash_iterator operator++(int) + { + __hash_iterator __t(*this); + ++(*this); + return __t; + } + + friend _LIBCPP_INLINE_VISIBILITY + bool operator==(const __hash_iterator& __x, const __hash_iterator& __y) + { + return __x.__node_ == __y.__node_; + } + friend _LIBCPP_INLINE_VISIBILITY + bool operator!=(const __hash_iterator& __x, const __hash_iterator& __y) + {return !(__x == __y);} + +private: + _LIBCPP_INLINE_VISIBILITY + explicit __hash_iterator(__next_pointer __node, const void* __c) _NOEXCEPT + : __node_(__node) + { + (void)__c; +#ifdef _LIBCPP_ENABLE_DEBUG_MODE + __get_db()->__insert_ic(this, __c); +#endif + } + template friend class __hash_table; + template friend class _LIBCPP_TEMPLATE_VIS __hash_const_iterator; + template friend class _LIBCPP_TEMPLATE_VIS __hash_map_iterator; + template friend class _LIBCPP_TEMPLATE_VIS unordered_map; + template friend class _LIBCPP_TEMPLATE_VIS unordered_multimap; +}; + +template +class _LIBCPP_TEMPLATE_VIS __hash_const_iterator +{ + static_assert(!is_const::element_type>::value, ""); + typedef __hash_node_types<_NodePtr> _NodeTypes; + typedef _NodePtr __node_pointer; + typedef typename _NodeTypes::__next_pointer __next_pointer; + + __next_pointer __node_; + +public: + typedef __hash_iterator<_NodePtr> __non_const_iterator; + + typedef forward_iterator_tag iterator_category; + typedef typename _NodeTypes::__node_value_type value_type; + typedef typename _NodeTypes::difference_type difference_type; + typedef const value_type& reference; + typedef typename _NodeTypes::__const_node_value_type_pointer pointer; + + + _LIBCPP_INLINE_VISIBILITY __hash_const_iterator() _NOEXCEPT : __node_(nullptr) { + _VSTD::__debug_db_insert_i(this); + } + + _LIBCPP_INLINE_VISIBILITY + __hash_const_iterator(const __non_const_iterator& __x) _NOEXCEPT + : __node_(__x.__node_) + { +#ifdef _LIBCPP_ENABLE_DEBUG_MODE + __get_db()->__iterator_copy(this, _VSTD::addressof(__x)); +#endif + } + +#ifdef _LIBCPP_ENABLE_DEBUG_MODE + _LIBCPP_INLINE_VISIBILITY + __hash_const_iterator(const __hash_const_iterator& __i) + : __node_(__i.__node_) + { + __get_db()->__iterator_copy(this, _VSTD::addressof(__i)); + } + + _LIBCPP_INLINE_VISIBILITY + ~__hash_const_iterator() + { + __get_db()->__erase_i(this); + } + + _LIBCPP_INLINE_VISIBILITY + __hash_const_iterator& operator=(const __hash_const_iterator& __i) + { + if (this != _VSTD::addressof(__i)) + { + __get_db()->__iterator_copy(this, _VSTD::addressof(__i)); + __node_ = __i.__node_; + } + return *this; + } +#endif // _LIBCPP_ENABLE_DEBUG_MODE + + _LIBCPP_INLINE_VISIBILITY + reference operator*() const { + _LIBCPP_DEBUG_ASSERT(__get_const_db()->__dereferenceable(this), + "Attempted to dereference a non-dereferenceable unordered container const_iterator"); + return __node_->__upcast()->__value_; + } + _LIBCPP_INLINE_VISIBILITY + pointer operator->() const { + _LIBCPP_DEBUG_ASSERT(__get_const_db()->__dereferenceable(this), + "Attempted to dereference a non-dereferenceable unordered container const_iterator"); + return pointer_traits::pointer_to(__node_->__upcast()->__value_); + } + + _LIBCPP_INLINE_VISIBILITY + __hash_const_iterator& operator++() { + _LIBCPP_DEBUG_ASSERT(__get_const_db()->__dereferenceable(this), + "Attempted to increment a non-incrementable unordered container const_iterator"); + __node_ = __node_->__next_; + return *this; + } + + _LIBCPP_INLINE_VISIBILITY + __hash_const_iterator operator++(int) + { + __hash_const_iterator __t(*this); + ++(*this); + return __t; + } + + friend _LIBCPP_INLINE_VISIBILITY + bool operator==(const __hash_const_iterator& __x, const __hash_const_iterator& __y) + { + return __x.__node_ == __y.__node_; + } + friend _LIBCPP_INLINE_VISIBILITY + bool operator!=(const __hash_const_iterator& __x, const __hash_const_iterator& __y) + {return !(__x == __y);} + +private: + _LIBCPP_INLINE_VISIBILITY + explicit __hash_const_iterator(__next_pointer __node, const void* __c) _NOEXCEPT + : __node_(__node) + { + (void)__c; +#ifdef _LIBCPP_ENABLE_DEBUG_MODE + __get_db()->__insert_ic(this, __c); +#endif + } + template friend class __hash_table; + template friend class _LIBCPP_TEMPLATE_VIS __hash_map_const_iterator; + template friend class _LIBCPP_TEMPLATE_VIS unordered_map; + template friend class _LIBCPP_TEMPLATE_VIS unordered_multimap; +}; + +template +class _LIBCPP_TEMPLATE_VIS __hash_local_iterator +{ + typedef __hash_node_types<_NodePtr> _NodeTypes; + typedef _NodePtr __node_pointer; + typedef typename _NodeTypes::__next_pointer __next_pointer; + + __next_pointer __node_; + size_t __bucket_; + size_t __bucket_count_; + +public: + typedef forward_iterator_tag iterator_category; + typedef typename _NodeTypes::__node_value_type value_type; + typedef typename _NodeTypes::difference_type difference_type; + typedef value_type& reference; + typedef typename _NodeTypes::__node_value_type_pointer pointer; + + _LIBCPP_INLINE_VISIBILITY __hash_local_iterator() _NOEXCEPT : __node_(nullptr) { + _VSTD::__debug_db_insert_i(this); + } + +#ifdef _LIBCPP_ENABLE_DEBUG_MODE + _LIBCPP_INLINE_VISIBILITY + __hash_local_iterator(const __hash_local_iterator& __i) + : __node_(__i.__node_), + __bucket_(__i.__bucket_), + __bucket_count_(__i.__bucket_count_) + { + __get_db()->__iterator_copy(this, _VSTD::addressof(__i)); + } + + _LIBCPP_INLINE_VISIBILITY + ~__hash_local_iterator() + { + __get_db()->__erase_i(this); + } + + _LIBCPP_INLINE_VISIBILITY + __hash_local_iterator& operator=(const __hash_local_iterator& __i) + { + if (this != _VSTD::addressof(__i)) + { + __get_db()->__iterator_copy(this, _VSTD::addressof(__i)); + __node_ = __i.__node_; + __bucket_ = __i.__bucket_; + __bucket_count_ = __i.__bucket_count_; + } + return *this; + } +#endif // _LIBCPP_ENABLE_DEBUG_MODE + + _LIBCPP_INLINE_VISIBILITY + reference operator*() const { + _LIBCPP_DEBUG_ASSERT(__get_const_db()->__dereferenceable(this), + "Attempted to dereference a non-dereferenceable unordered container local_iterator"); + return __node_->__upcast()->__value_; + } + + _LIBCPP_INLINE_VISIBILITY + pointer operator->() const { + _LIBCPP_DEBUG_ASSERT(__get_const_db()->__dereferenceable(this), + "Attempted to dereference a non-dereferenceable unordered container local_iterator"); + return pointer_traits::pointer_to(__node_->__upcast()->__value_); + } + + _LIBCPP_INLINE_VISIBILITY + __hash_local_iterator& operator++() { + _LIBCPP_DEBUG_ASSERT(__get_const_db()->__dereferenceable(this), + "Attempted to increment a non-incrementable unordered container local_iterator"); + __node_ = __node_->__next_; + if (__node_ != nullptr && std::__constrain_hash(__node_->__hash(), __bucket_count_) != __bucket_) + __node_ = nullptr; + return *this; + } + + _LIBCPP_INLINE_VISIBILITY + __hash_local_iterator operator++(int) + { + __hash_local_iterator __t(*this); + ++(*this); + return __t; + } + + friend _LIBCPP_INLINE_VISIBILITY + bool operator==(const __hash_local_iterator& __x, const __hash_local_iterator& __y) + { + return __x.__node_ == __y.__node_; + } + friend _LIBCPP_INLINE_VISIBILITY + bool operator!=(const __hash_local_iterator& __x, const __hash_local_iterator& __y) + {return !(__x == __y);} + +private: + _LIBCPP_INLINE_VISIBILITY + explicit __hash_local_iterator(__next_pointer __node, size_t __bucket, + size_t __bucket_count, const void* __c) _NOEXCEPT + : __node_(__node), + __bucket_(__bucket), + __bucket_count_(__bucket_count) + { + (void)__c; +#ifdef _LIBCPP_ENABLE_DEBUG_MODE + __get_db()->__insert_ic(this, __c); +#endif + if (__node_ != nullptr) + __node_ = __node_->__next_; + } + template friend class __hash_table; + template friend class _LIBCPP_TEMPLATE_VIS __hash_const_local_iterator; + template friend class _LIBCPP_TEMPLATE_VIS __hash_map_iterator; +}; + +template +class _LIBCPP_TEMPLATE_VIS __hash_const_local_iterator +{ + typedef __hash_node_types<_ConstNodePtr> _NodeTypes; + typedef _ConstNodePtr __node_pointer; + typedef typename _NodeTypes::__next_pointer __next_pointer; + + __next_pointer __node_; + size_t __bucket_; + size_t __bucket_count_; + + typedef pointer_traits<__node_pointer> __pointer_traits; + typedef typename __pointer_traits::element_type __node; + typedef __remove_const_t<__node> __non_const_node; + typedef __rebind_pointer_t<__node_pointer, __non_const_node> + __non_const_node_pointer; +public: + typedef __hash_local_iterator<__non_const_node_pointer> + __non_const_iterator; + + typedef forward_iterator_tag iterator_category; + typedef typename _NodeTypes::__node_value_type value_type; + typedef typename _NodeTypes::difference_type difference_type; + typedef const value_type& reference; + typedef typename _NodeTypes::__const_node_value_type_pointer pointer; + + + _LIBCPP_INLINE_VISIBILITY __hash_const_local_iterator() _NOEXCEPT : __node_(nullptr) { + _VSTD::__debug_db_insert_i(this); + } + + _LIBCPP_INLINE_VISIBILITY + __hash_const_local_iterator(const __non_const_iterator& __x) _NOEXCEPT + : __node_(__x.__node_), + __bucket_(__x.__bucket_), + __bucket_count_(__x.__bucket_count_) + { +#ifdef _LIBCPP_ENABLE_DEBUG_MODE + __get_db()->__iterator_copy(this, _VSTD::addressof(__x)); +#endif + } + +#ifdef _LIBCPP_ENABLE_DEBUG_MODE + _LIBCPP_INLINE_VISIBILITY + __hash_const_local_iterator(const __hash_const_local_iterator& __i) + : __node_(__i.__node_), + __bucket_(__i.__bucket_), + __bucket_count_(__i.__bucket_count_) + { + __get_db()->__iterator_copy(this, _VSTD::addressof(__i)); + } + + _LIBCPP_INLINE_VISIBILITY + ~__hash_const_local_iterator() + { + __get_db()->__erase_i(this); + } + + _LIBCPP_INLINE_VISIBILITY + __hash_const_local_iterator& operator=(const __hash_const_local_iterator& __i) + { + if (this != _VSTD::addressof(__i)) + { + __get_db()->__iterator_copy(this, _VSTD::addressof(__i)); + __node_ = __i.__node_; + __bucket_ = __i.__bucket_; + __bucket_count_ = __i.__bucket_count_; + } + return *this; + } +#endif // _LIBCPP_ENABLE_DEBUG_MODE + + _LIBCPP_INLINE_VISIBILITY + reference operator*() const { + _LIBCPP_DEBUG_ASSERT(__get_const_db()->__dereferenceable(this), + "Attempted to dereference a non-dereferenceable unordered container const_local_iterator"); + return __node_->__upcast()->__value_; + } + + _LIBCPP_INLINE_VISIBILITY + pointer operator->() const { + _LIBCPP_DEBUG_ASSERT(__get_const_db()->__dereferenceable(this), + "Attempted to dereference a non-dereferenceable unordered container const_local_iterator"); + return pointer_traits::pointer_to(__node_->__upcast()->__value_); + } + + _LIBCPP_INLINE_VISIBILITY + __hash_const_local_iterator& operator++() { + _LIBCPP_DEBUG_ASSERT(__get_const_db()->__dereferenceable(this), + "Attempted to increment a non-incrementable unordered container const_local_iterator"); + __node_ = __node_->__next_; + if (__node_ != nullptr && std::__constrain_hash(__node_->__hash(), __bucket_count_) != __bucket_) + __node_ = nullptr; + return *this; + } + + _LIBCPP_INLINE_VISIBILITY + __hash_const_local_iterator operator++(int) + { + __hash_const_local_iterator __t(*this); + ++(*this); + return __t; + } + + friend _LIBCPP_INLINE_VISIBILITY + bool operator==(const __hash_const_local_iterator& __x, const __hash_const_local_iterator& __y) + { + return __x.__node_ == __y.__node_; + } + friend _LIBCPP_INLINE_VISIBILITY + bool operator!=(const __hash_const_local_iterator& __x, const __hash_const_local_iterator& __y) + {return !(__x == __y);} + +private: + _LIBCPP_INLINE_VISIBILITY + explicit __hash_const_local_iterator(__next_pointer __node_ptr, size_t __bucket, + size_t __bucket_count, const void* __c) _NOEXCEPT + : __node_(__node_ptr), + __bucket_(__bucket), + __bucket_count_(__bucket_count) + { + (void)__c; +#ifdef _LIBCPP_ENABLE_DEBUG_MODE + __get_db()->__insert_ic(this, __c); +#endif + if (__node_ != nullptr) + __node_ = __node_->__next_; + } + template friend class __hash_table; + template friend class _LIBCPP_TEMPLATE_VIS __hash_map_const_iterator; +}; + +template +class __bucket_list_deallocator +{ + typedef _Alloc allocator_type; + typedef allocator_traits __alloc_traits; + typedef typename __alloc_traits::size_type size_type; + + __compressed_pair __data_; +public: + typedef typename __alloc_traits::pointer pointer; + + _LIBCPP_INLINE_VISIBILITY + __bucket_list_deallocator() + _NOEXCEPT_(is_nothrow_default_constructible::value) + : __data_(0, __default_init_tag()) {} + + _LIBCPP_INLINE_VISIBILITY + __bucket_list_deallocator(const allocator_type& __a, size_type __size) + _NOEXCEPT_(is_nothrow_copy_constructible::value) + : __data_(__size, __a) {} + + _LIBCPP_INLINE_VISIBILITY + __bucket_list_deallocator(__bucket_list_deallocator&& __x) + _NOEXCEPT_(is_nothrow_move_constructible::value) + : __data_(_VSTD::move(__x.__data_)) + { + __x.size() = 0; + } + + _LIBCPP_INLINE_VISIBILITY + size_type& size() _NOEXCEPT {return __data_.first();} + _LIBCPP_INLINE_VISIBILITY + size_type size() const _NOEXCEPT {return __data_.first();} + + _LIBCPP_INLINE_VISIBILITY + allocator_type& __alloc() _NOEXCEPT {return __data_.second();} + _LIBCPP_INLINE_VISIBILITY + const allocator_type& __alloc() const _NOEXCEPT {return __data_.second();} + + _LIBCPP_INLINE_VISIBILITY + void operator()(pointer __p) _NOEXCEPT + { + __alloc_traits::deallocate(__alloc(), __p, size()); + } +}; + +template class __hash_map_node_destructor; + +template +class __hash_node_destructor +{ + typedef _Alloc allocator_type; + typedef allocator_traits __alloc_traits; + +public: + typedef typename __alloc_traits::pointer pointer; +private: + typedef __hash_node_types _NodeTypes; + + allocator_type& __na_; + +public: + bool __value_constructed; + + __hash_node_destructor(__hash_node_destructor const&) = default; + __hash_node_destructor& operator=(const __hash_node_destructor&) = delete; + + + _LIBCPP_INLINE_VISIBILITY + explicit __hash_node_destructor(allocator_type& __na, + bool __constructed = false) _NOEXCEPT + : __na_(__na), + __value_constructed(__constructed) + {} + + _LIBCPP_INLINE_VISIBILITY + void operator()(pointer __p) _NOEXCEPT + { + if (__value_constructed) + __alloc_traits::destroy(__na_, _NodeTypes::__get_ptr(__p->__value_)); + if (__p) + __alloc_traits::deallocate(__na_, __p, 1); + } + + template friend class __hash_map_node_destructor; +}; + +#if _LIBCPP_STD_VER > 14 +template +struct __generic_container_node_destructor; + +template +struct __generic_container_node_destructor<__hash_node<_Tp, _VoidPtr>, _Alloc> + : __hash_node_destructor<_Alloc> +{ + using __hash_node_destructor<_Alloc>::__hash_node_destructor; +}; +#endif + +template +struct __enforce_unordered_container_requirements { +#ifndef _LIBCPP_CXX03_LANG + static_assert(__check_hash_requirements<_Key, _Hash>::value, + "the specified hash does not meet the Hash requirements"); + static_assert(is_copy_constructible<_Equal>::value, + "the specified comparator is required to be copy constructible"); +#endif + typedef int type; +}; + +template +#ifndef _LIBCPP_CXX03_LANG + _LIBCPP_DIAGNOSE_WARNING(!__invokable<_Equal const&, _Key const&, _Key const&>::value, + "the specified comparator type does not provide a viable const call operator") + _LIBCPP_DIAGNOSE_WARNING(!__invokable<_Hash const&, _Key const&>::value, + "the specified hash functor does not provide a viable const call operator") +#endif +typename __enforce_unordered_container_requirements<_Key, _Hash, _Equal>::type +__diagnose_unordered_container_requirements(int); + +// This dummy overload is used so that the compiler won't emit a spurious +// "no matching function for call to __diagnose_unordered_xxx" diagnostic +// when the overload above causes a hard error. +template +int __diagnose_unordered_container_requirements(void*); + +template +class __hash_table +{ +public: + typedef _Tp value_type; + typedef _Hash hasher; + typedef _Equal key_equal; + typedef _Alloc allocator_type; + +private: + typedef allocator_traits __alloc_traits; + typedef typename + __make_hash_node_types::type + _NodeTypes; +public: + + typedef typename _NodeTypes::__node_value_type __node_value_type; + typedef typename _NodeTypes::__container_value_type __container_value_type; + typedef typename _NodeTypes::key_type key_type; + typedef value_type& reference; + typedef const value_type& const_reference; + typedef typename __alloc_traits::pointer pointer; + typedef typename __alloc_traits::const_pointer const_pointer; +#ifndef _LIBCPP_ABI_FIX_UNORDERED_CONTAINER_SIZE_TYPE + typedef typename __alloc_traits::size_type size_type; +#else + typedef typename _NodeTypes::size_type size_type; +#endif + typedef typename _NodeTypes::difference_type difference_type; +public: + // Create __node + + typedef typename _NodeTypes::__node_type __node; + typedef __rebind_alloc<__alloc_traits, __node> __node_allocator; + typedef allocator_traits<__node_allocator> __node_traits; + typedef typename _NodeTypes::__void_pointer __void_pointer; + typedef typename _NodeTypes::__node_pointer __node_pointer; + typedef typename _NodeTypes::__node_pointer __node_const_pointer; + typedef typename _NodeTypes::__node_base_type __first_node; + typedef typename _NodeTypes::__node_base_pointer __node_base_pointer; + typedef typename _NodeTypes::__next_pointer __next_pointer; + +private: + // check for sane allocator pointer rebinding semantics. Rebinding the + // allocator for a new pointer type should be exactly the same as rebinding + // the pointer using 'pointer_traits'. + static_assert((is_same<__node_pointer, typename __node_traits::pointer>::value), + "Allocator does not rebind pointers in a sane manner."); + typedef __rebind_alloc<__node_traits, __first_node> __node_base_allocator; + typedef allocator_traits<__node_base_allocator> __node_base_traits; + static_assert((is_same<__node_base_pointer, typename __node_base_traits::pointer>::value), + "Allocator does not rebind pointers in a sane manner."); + +private: + + typedef __rebind_alloc<__node_traits, __next_pointer> __pointer_allocator; + typedef __bucket_list_deallocator<__pointer_allocator> __bucket_list_deleter; + typedef unique_ptr<__next_pointer[], __bucket_list_deleter> __bucket_list; + typedef allocator_traits<__pointer_allocator> __pointer_alloc_traits; + typedef typename __bucket_list_deleter::pointer __node_pointer_pointer; + + // --- Member data begin --- + __bucket_list __bucket_list_; + __compressed_pair<__first_node, __node_allocator> __p1_; + __compressed_pair __p2_; + __compressed_pair __p3_; + // --- Member data end --- + + _LIBCPP_INLINE_VISIBILITY + size_type& size() _NOEXCEPT {return __p2_.first();} +public: + _LIBCPP_INLINE_VISIBILITY + size_type size() const _NOEXCEPT {return __p2_.first();} + + _LIBCPP_INLINE_VISIBILITY + hasher& hash_function() _NOEXCEPT {return __p2_.second();} + _LIBCPP_INLINE_VISIBILITY + const hasher& hash_function() const _NOEXCEPT {return __p2_.second();} + + _LIBCPP_INLINE_VISIBILITY + float& max_load_factor() _NOEXCEPT {return __p3_.first();} + _LIBCPP_INLINE_VISIBILITY + float max_load_factor() const _NOEXCEPT {return __p3_.first();} + + _LIBCPP_INLINE_VISIBILITY + key_equal& key_eq() _NOEXCEPT {return __p3_.second();} + _LIBCPP_INLINE_VISIBILITY + const key_equal& key_eq() const _NOEXCEPT {return __p3_.second();} + + _LIBCPP_INLINE_VISIBILITY + __node_allocator& __node_alloc() _NOEXCEPT {return __p1_.second();} + _LIBCPP_INLINE_VISIBILITY + const __node_allocator& __node_alloc() const _NOEXCEPT + {return __p1_.second();} + +public: + typedef __hash_iterator<__node_pointer> iterator; + typedef __hash_const_iterator<__node_pointer> const_iterator; + typedef __hash_local_iterator<__node_pointer> local_iterator; + typedef __hash_const_local_iterator<__node_pointer> const_local_iterator; + + _LIBCPP_INLINE_VISIBILITY + __hash_table() + _NOEXCEPT_( + is_nothrow_default_constructible<__bucket_list>::value && + is_nothrow_default_constructible<__first_node>::value && + is_nothrow_default_constructible<__node_allocator>::value && + is_nothrow_default_constructible::value && + is_nothrow_default_constructible::value); + _LIBCPP_INLINE_VISIBILITY + __hash_table(const hasher& __hf, const key_equal& __eql); + __hash_table(const hasher& __hf, const key_equal& __eql, + const allocator_type& __a); + explicit __hash_table(const allocator_type& __a); + __hash_table(const __hash_table& __u); + __hash_table(const __hash_table& __u, const allocator_type& __a); + __hash_table(__hash_table&& __u) + _NOEXCEPT_( + is_nothrow_move_constructible<__bucket_list>::value && + is_nothrow_move_constructible<__first_node>::value && + is_nothrow_move_constructible<__node_allocator>::value && + is_nothrow_move_constructible::value && + is_nothrow_move_constructible::value); + __hash_table(__hash_table&& __u, const allocator_type& __a); + ~__hash_table(); + + __hash_table& operator=(const __hash_table& __u); + _LIBCPP_INLINE_VISIBILITY + __hash_table& operator=(__hash_table&& __u) + _NOEXCEPT_( + __node_traits::propagate_on_container_move_assignment::value && + is_nothrow_move_assignable<__node_allocator>::value && + is_nothrow_move_assignable::value && + is_nothrow_move_assignable::value); + template + void __assign_unique(_InputIterator __first, _InputIterator __last); + template + void __assign_multi(_InputIterator __first, _InputIterator __last); + + _LIBCPP_INLINE_VISIBILITY + size_type max_size() const _NOEXCEPT + { + return _VSTD::min( + __node_traits::max_size(__node_alloc()), + numeric_limits::max() + ); + } + +private: + _LIBCPP_INLINE_VISIBILITY + __next_pointer __node_insert_multi_prepare(size_t __cp_hash, + value_type& __cp_val); + _LIBCPP_INLINE_VISIBILITY + void __node_insert_multi_perform(__node_pointer __cp, + __next_pointer __pn) _NOEXCEPT; + + _LIBCPP_INLINE_VISIBILITY + __next_pointer __node_insert_unique_prepare(size_t __nd_hash, + value_type& __nd_val); + _LIBCPP_INLINE_VISIBILITY + void __node_insert_unique_perform(__node_pointer __ptr) _NOEXCEPT; + +public: + _LIBCPP_INLINE_VISIBILITY + pair __node_insert_unique(__node_pointer __nd); + _LIBCPP_INLINE_VISIBILITY + iterator __node_insert_multi(__node_pointer __nd); + _LIBCPP_INLINE_VISIBILITY + iterator __node_insert_multi(const_iterator __p, + __node_pointer __nd); + + template + _LIBCPP_INLINE_VISIBILITY + pair __emplace_unique_key_args(_Key const& __k, _Args&&... __args); + + template + _LIBCPP_INLINE_VISIBILITY + pair __emplace_unique_impl(_Args&&... __args); + + template + _LIBCPP_INLINE_VISIBILITY + pair __emplace_unique(_Pp&& __x) { + return __emplace_unique_extract_key(_VSTD::forward<_Pp>(__x), + __can_extract_key<_Pp, key_type>()); + } + + template + _LIBCPP_INLINE_VISIBILITY + __enable_if_t<__can_extract_map_key<_First, key_type, __container_value_type>::value, pair > + __emplace_unique(_First&& __f, _Second&& __s) { + return __emplace_unique_key_args(__f, _VSTD::forward<_First>(__f), + _VSTD::forward<_Second>(__s)); + } + + template + _LIBCPP_INLINE_VISIBILITY + pair __emplace_unique(_Args&&... __args) { + return __emplace_unique_impl(_VSTD::forward<_Args>(__args)...); + } + + template + _LIBCPP_INLINE_VISIBILITY + pair + __emplace_unique_extract_key(_Pp&& __x, __extract_key_fail_tag) { + return __emplace_unique_impl(_VSTD::forward<_Pp>(__x)); + } + template + _LIBCPP_INLINE_VISIBILITY + pair + __emplace_unique_extract_key(_Pp&& __x, __extract_key_self_tag) { + return __emplace_unique_key_args(__x, _VSTD::forward<_Pp>(__x)); + } + template + _LIBCPP_INLINE_VISIBILITY + pair + __emplace_unique_extract_key(_Pp&& __x, __extract_key_first_tag) { + return __emplace_unique_key_args(__x.first, _VSTD::forward<_Pp>(__x)); + } + + template + _LIBCPP_INLINE_VISIBILITY + iterator __emplace_multi(_Args&&... __args); + template + _LIBCPP_INLINE_VISIBILITY + iterator __emplace_hint_multi(const_iterator __p, _Args&&... __args); + + + _LIBCPP_INLINE_VISIBILITY + pair + __insert_unique(__container_value_type&& __x) { + return __emplace_unique_key_args(_NodeTypes::__get_key(__x), _VSTD::move(__x)); + } + + template ::value> > + _LIBCPP_INLINE_VISIBILITY + pair __insert_unique(_Pp&& __x) { + return __emplace_unique(_VSTD::forward<_Pp>(__x)); + } + + template + _LIBCPP_INLINE_VISIBILITY + iterator __insert_multi(_Pp&& __x) { + return __emplace_multi(_VSTD::forward<_Pp>(__x)); + } + + template + _LIBCPP_INLINE_VISIBILITY + iterator __insert_multi(const_iterator __p, _Pp&& __x) { + return __emplace_hint_multi(__p, _VSTD::forward<_Pp>(__x)); + } + + _LIBCPP_INLINE_VISIBILITY + pair __insert_unique(const __container_value_type& __x) { + return __emplace_unique_key_args(_NodeTypes::__get_key(__x), __x); + } + +#if _LIBCPP_STD_VER > 14 + template + _LIBCPP_INLINE_VISIBILITY + _InsertReturnType __node_handle_insert_unique(_NodeHandle&& __nh); + template + _LIBCPP_INLINE_VISIBILITY + iterator __node_handle_insert_unique(const_iterator __hint, + _NodeHandle&& __nh); + template + _LIBCPP_INLINE_VISIBILITY + void __node_handle_merge_unique(_Table& __source); + + template + _LIBCPP_INLINE_VISIBILITY + iterator __node_handle_insert_multi(_NodeHandle&& __nh); + template + _LIBCPP_INLINE_VISIBILITY + iterator __node_handle_insert_multi(const_iterator __hint, _NodeHandle&& __nh); + template + _LIBCPP_INLINE_VISIBILITY + void __node_handle_merge_multi(_Table& __source); + + template + _LIBCPP_INLINE_VISIBILITY + _NodeHandle __node_handle_extract(key_type const& __key); + template + _LIBCPP_INLINE_VISIBILITY + _NodeHandle __node_handle_extract(const_iterator __it); +#endif + + void clear() _NOEXCEPT; + _LIBCPP_INLINE_VISIBILITY void __rehash_unique(size_type __n) { __rehash(__n); } + _LIBCPP_INLINE_VISIBILITY void __rehash_multi(size_type __n) { __rehash(__n); } + _LIBCPP_INLINE_VISIBILITY void __reserve_unique(size_type __n) + { + __rehash_unique(static_cast(std::ceil(__n / max_load_factor()))); + } + _LIBCPP_INLINE_VISIBILITY void __reserve_multi(size_type __n) + { + __rehash_multi(static_cast(std::ceil(__n / max_load_factor()))); + } + + _LIBCPP_INLINE_VISIBILITY + size_type bucket_count() const _NOEXCEPT + { + return __bucket_list_.get_deleter().size(); + } + + _LIBCPP_INLINE_VISIBILITY + iterator begin() _NOEXCEPT; + _LIBCPP_INLINE_VISIBILITY + iterator end() _NOEXCEPT; + _LIBCPP_INLINE_VISIBILITY + const_iterator begin() const _NOEXCEPT; + _LIBCPP_INLINE_VISIBILITY + const_iterator end() const _NOEXCEPT; + + template + _LIBCPP_INLINE_VISIBILITY + size_type bucket(const _Key& __k) const + { + _LIBCPP_ASSERT(bucket_count() > 0, + "unordered container::bucket(key) called when bucket_count() == 0"); + return std::__constrain_hash(hash_function()(__k), bucket_count()); + } + + template + iterator find(const _Key& __x); + template + const_iterator find(const _Key& __x) const; + + typedef __hash_node_destructor<__node_allocator> _Dp; + typedef unique_ptr<__node, _Dp> __node_holder; + + iterator erase(const_iterator __p); + iterator erase(const_iterator __first, const_iterator __last); + template + size_type __erase_unique(const _Key& __k); + template + size_type __erase_multi(const _Key& __k); + __node_holder remove(const_iterator __p) _NOEXCEPT; + + template + _LIBCPP_INLINE_VISIBILITY + size_type __count_unique(const _Key& __k) const; + template + size_type __count_multi(const _Key& __k) const; + + template + pair + __equal_range_unique(const _Key& __k); + template + pair + __equal_range_unique(const _Key& __k) const; + + template + pair + __equal_range_multi(const _Key& __k); + template + pair + __equal_range_multi(const _Key& __k) const; + + void swap(__hash_table& __u) +#if _LIBCPP_STD_VER <= 11 + _NOEXCEPT_( + __is_nothrow_swappable::value && __is_nothrow_swappable::value + && (!allocator_traits<__pointer_allocator>::propagate_on_container_swap::value + || __is_nothrow_swappable<__pointer_allocator>::value) + && (!__node_traits::propagate_on_container_swap::value + || __is_nothrow_swappable<__node_allocator>::value) + ); +#else + _NOEXCEPT_(__is_nothrow_swappable::value && __is_nothrow_swappable::value); +#endif + + _LIBCPP_INLINE_VISIBILITY + size_type max_bucket_count() const _NOEXCEPT + {return max_size(); } + size_type bucket_size(size_type __n) const; + _LIBCPP_INLINE_VISIBILITY float load_factor() const _NOEXCEPT + { + size_type __bc = bucket_count(); + return __bc != 0 ? (float)size() / __bc : 0.f; + } + _LIBCPP_INLINE_VISIBILITY void max_load_factor(float __mlf) _NOEXCEPT + { + _LIBCPP_ASSERT(__mlf > 0, + "unordered container::max_load_factor(lf) called with lf <= 0"); + max_load_factor() = _VSTD::max(__mlf, load_factor()); + } + + _LIBCPP_INLINE_VISIBILITY + local_iterator + begin(size_type __n) + { + _LIBCPP_ASSERT(__n < bucket_count(), + "unordered container::begin(n) called with n >= bucket_count()"); + return local_iterator(__bucket_list_[__n], __n, bucket_count(), this); + } + + _LIBCPP_INLINE_VISIBILITY + local_iterator + end(size_type __n) + { + _LIBCPP_ASSERT(__n < bucket_count(), + "unordered container::end(n) called with n >= bucket_count()"); + return local_iterator(nullptr, __n, bucket_count(), this); + } + + _LIBCPP_INLINE_VISIBILITY + const_local_iterator + cbegin(size_type __n) const + { + _LIBCPP_ASSERT(__n < bucket_count(), + "unordered container::cbegin(n) called with n >= bucket_count()"); + return const_local_iterator(__bucket_list_[__n], __n, bucket_count(), this); + } + + _LIBCPP_INLINE_VISIBILITY + const_local_iterator + cend(size_type __n) const + { + _LIBCPP_ASSERT(__n < bucket_count(), + "unordered container::cend(n) called with n >= bucket_count()"); + return const_local_iterator(nullptr, __n, bucket_count(), this); + } + +#ifdef _LIBCPP_ENABLE_DEBUG_MODE + + bool __dereferenceable(const const_iterator* __i) const; + bool __decrementable(const const_iterator* __i) const; + bool __addable(const const_iterator* __i, ptrdiff_t __n) const; + bool __subscriptable(const const_iterator* __i, ptrdiff_t __n) const; + +#endif // _LIBCPP_ENABLE_DEBUG_MODE + +private: + template void __rehash(size_type __n); + template void __do_rehash(size_type __n); + + template + __node_holder __construct_node(_Args&& ...__args); + + template + __node_holder __construct_node_hash(size_t __hash, _First&& __f, _Rest&&... __rest); + + + _LIBCPP_INLINE_VISIBILITY + void __copy_assign_alloc(const __hash_table& __u) + {__copy_assign_alloc(__u, integral_constant());} + void __copy_assign_alloc(const __hash_table& __u, true_type); + _LIBCPP_INLINE_VISIBILITY + void __copy_assign_alloc(const __hash_table&, false_type) {} + + void __move_assign(__hash_table& __u, false_type); + void __move_assign(__hash_table& __u, true_type) + _NOEXCEPT_( + is_nothrow_move_assignable<__node_allocator>::value && + is_nothrow_move_assignable::value && + is_nothrow_move_assignable::value); + _LIBCPP_INLINE_VISIBILITY + void __move_assign_alloc(__hash_table& __u) + _NOEXCEPT_( + !__node_traits::propagate_on_container_move_assignment::value || + (is_nothrow_move_assignable<__pointer_allocator>::value && + is_nothrow_move_assignable<__node_allocator>::value)) + {__move_assign_alloc(__u, integral_constant());} + _LIBCPP_INLINE_VISIBILITY + void __move_assign_alloc(__hash_table& __u, true_type) + _NOEXCEPT_( + is_nothrow_move_assignable<__pointer_allocator>::value && + is_nothrow_move_assignable<__node_allocator>::value) + { + __bucket_list_.get_deleter().__alloc() = + _VSTD::move(__u.__bucket_list_.get_deleter().__alloc()); + __node_alloc() = _VSTD::move(__u.__node_alloc()); + } + _LIBCPP_INLINE_VISIBILITY + void __move_assign_alloc(__hash_table&, false_type) _NOEXCEPT {} + + void __deallocate_node(__next_pointer __np) _NOEXCEPT; + __next_pointer __detach() _NOEXCEPT; + + template friend class _LIBCPP_TEMPLATE_VIS unordered_map; + template friend class _LIBCPP_TEMPLATE_VIS unordered_multimap; +}; + +template +inline +__hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table() + _NOEXCEPT_( + is_nothrow_default_constructible<__bucket_list>::value && + is_nothrow_default_constructible<__first_node>::value && + is_nothrow_default_constructible<__node_allocator>::value && + is_nothrow_default_constructible::value && + is_nothrow_default_constructible::value) + : __p2_(0, __default_init_tag()), + __p3_(1.0f, __default_init_tag()) +{ +} + +template +inline +__hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(const hasher& __hf, + const key_equal& __eql) + : __bucket_list_(nullptr, __bucket_list_deleter()), + __p1_(), + __p2_(0, __hf), + __p3_(1.0f, __eql) +{ +} + +template +__hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(const hasher& __hf, + const key_equal& __eql, + const allocator_type& __a) + : __bucket_list_(nullptr, __bucket_list_deleter(__pointer_allocator(__a), 0)), + __p1_(__default_init_tag(), __node_allocator(__a)), + __p2_(0, __hf), + __p3_(1.0f, __eql) +{ +} + +template +__hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(const allocator_type& __a) + : __bucket_list_(nullptr, __bucket_list_deleter(__pointer_allocator(__a), 0)), + __p1_(__default_init_tag(), __node_allocator(__a)), + __p2_(0, __default_init_tag()), + __p3_(1.0f, __default_init_tag()) +{ +} + +template +__hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(const __hash_table& __u) + : __bucket_list_(nullptr, + __bucket_list_deleter(allocator_traits<__pointer_allocator>:: + select_on_container_copy_construction( + __u.__bucket_list_.get_deleter().__alloc()), 0)), + __p1_(__default_init_tag(), allocator_traits<__node_allocator>:: + select_on_container_copy_construction(__u.__node_alloc())), + __p2_(0, __u.hash_function()), + __p3_(__u.__p3_) +{ +} + +template +__hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(const __hash_table& __u, + const allocator_type& __a) + : __bucket_list_(nullptr, __bucket_list_deleter(__pointer_allocator(__a), 0)), + __p1_(__default_init_tag(), __node_allocator(__a)), + __p2_(0, __u.hash_function()), + __p3_(__u.__p3_) +{ +} + +template +__hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(__hash_table&& __u) + _NOEXCEPT_( + is_nothrow_move_constructible<__bucket_list>::value && + is_nothrow_move_constructible<__first_node>::value && + is_nothrow_move_constructible<__node_allocator>::value && + is_nothrow_move_constructible::value && + is_nothrow_move_constructible::value) + : __bucket_list_(_VSTD::move(__u.__bucket_list_)), + __p1_(_VSTD::move(__u.__p1_)), + __p2_(_VSTD::move(__u.__p2_)), + __p3_(_VSTD::move(__u.__p3_)) +{ + if (size() > 0) + { + __bucket_list_[std::__constrain_hash(__p1_.first().__next_->__hash(), bucket_count())] = + __p1_.first().__ptr(); + __u.__p1_.first().__next_ = nullptr; + __u.size() = 0; + } +} + +template +__hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(__hash_table&& __u, + const allocator_type& __a) + : __bucket_list_(nullptr, __bucket_list_deleter(__pointer_allocator(__a), 0)), + __p1_(__default_init_tag(), __node_allocator(__a)), + __p2_(0, _VSTD::move(__u.hash_function())), + __p3_(_VSTD::move(__u.__p3_)) +{ + if (__a == allocator_type(__u.__node_alloc())) + { + __bucket_list_.reset(__u.__bucket_list_.release()); + __bucket_list_.get_deleter().size() = __u.__bucket_list_.get_deleter().size(); + __u.__bucket_list_.get_deleter().size() = 0; + if (__u.size() > 0) + { + __p1_.first().__next_ = __u.__p1_.first().__next_; + __u.__p1_.first().__next_ = nullptr; + __bucket_list_[std::__constrain_hash(__p1_.first().__next_->__hash(), bucket_count())] = + __p1_.first().__ptr(); + size() = __u.size(); + __u.size() = 0; + } + } +} + +template +__hash_table<_Tp, _Hash, _Equal, _Alloc>::~__hash_table() +{ +#if defined(_LIBCPP_CXX03_LANG) + static_assert((is_copy_constructible::value), + "Predicate must be copy-constructible."); + static_assert((is_copy_constructible::value), + "Hasher must be copy-constructible."); +#endif + + __deallocate_node(__p1_.first().__next_); + std::__debug_db_erase_c(this); +} + +template +void +__hash_table<_Tp, _Hash, _Equal, _Alloc>::__copy_assign_alloc( + const __hash_table& __u, true_type) +{ + if (__node_alloc() != __u.__node_alloc()) + { + clear(); + __bucket_list_.reset(); + __bucket_list_.get_deleter().size() = 0; + } + __bucket_list_.get_deleter().__alloc() = __u.__bucket_list_.get_deleter().__alloc(); + __node_alloc() = __u.__node_alloc(); +} + +template +__hash_table<_Tp, _Hash, _Equal, _Alloc>& +__hash_table<_Tp, _Hash, _Equal, _Alloc>::operator=(const __hash_table& __u) +{ + if (this != _VSTD::addressof(__u)) + { + __copy_assign_alloc(__u); + hash_function() = __u.hash_function(); + key_eq() = __u.key_eq(); + max_load_factor() = __u.max_load_factor(); + __assign_multi(__u.begin(), __u.end()); + } + return *this; +} + +template +void +__hash_table<_Tp, _Hash, _Equal, _Alloc>::__deallocate_node(__next_pointer __np) + _NOEXCEPT +{ + __node_allocator& __na = __node_alloc(); + while (__np != nullptr) + { + __next_pointer __next = __np->__next_; +#ifdef _LIBCPP_ENABLE_DEBUG_MODE + __c_node* __c = __get_db()->__find_c_and_lock(this); + for (__i_node** __p = __c->end_; __p != __c->beg_; ) + { + --__p; + iterator* __i = static_cast((*__p)->__i_); + if (__i->__node_ == __np) + { + (*__p)->__c_ = nullptr; + if (--__c->end_ != __p) + _VSTD::memmove(__p, __p+1, (__c->end_ - __p)*sizeof(__i_node*)); + } + } + __get_db()->unlock(); +#endif + __node_pointer __real_np = __np->__upcast(); + __node_traits::destroy(__na, _NodeTypes::__get_ptr(__real_np->__value_)); + __node_traits::deallocate(__na, __real_np, 1); + __np = __next; + } +} + +template +typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::__next_pointer +__hash_table<_Tp, _Hash, _Equal, _Alloc>::__detach() _NOEXCEPT +{ + size_type __bc = bucket_count(); + for (size_type __i = 0; __i < __bc; ++__i) + __bucket_list_[__i] = nullptr; + size() = 0; + __next_pointer __cache = __p1_.first().__next_; + __p1_.first().__next_ = nullptr; + return __cache; +} + +template +void +__hash_table<_Tp, _Hash, _Equal, _Alloc>::__move_assign( + __hash_table& __u, true_type) + _NOEXCEPT_( + is_nothrow_move_assignable<__node_allocator>::value && + is_nothrow_move_assignable::value && + is_nothrow_move_assignable::value) +{ + clear(); + __bucket_list_.reset(__u.__bucket_list_.release()); + __bucket_list_.get_deleter().size() = __u.__bucket_list_.get_deleter().size(); + __u.__bucket_list_.get_deleter().size() = 0; + __move_assign_alloc(__u); + size() = __u.size(); + hash_function() = _VSTD::move(__u.hash_function()); + max_load_factor() = __u.max_load_factor(); + key_eq() = _VSTD::move(__u.key_eq()); + __p1_.first().__next_ = __u.__p1_.first().__next_; + if (size() > 0) + { + __bucket_list_[std::__constrain_hash(__p1_.first().__next_->__hash(), bucket_count())] = + __p1_.first().__ptr(); + __u.__p1_.first().__next_ = nullptr; + __u.size() = 0; + } + std::__debug_db_swap(this, std::addressof(__u)); +} + +template +void +__hash_table<_Tp, _Hash, _Equal, _Alloc>::__move_assign( + __hash_table& __u, false_type) +{ + if (__node_alloc() == __u.__node_alloc()) + __move_assign(__u, true_type()); + else + { + hash_function() = _VSTD::move(__u.hash_function()); + key_eq() = _VSTD::move(__u.key_eq()); + max_load_factor() = __u.max_load_factor(); + if (bucket_count() != 0) + { + __next_pointer __cache = __detach(); +#ifndef _LIBCPP_NO_EXCEPTIONS + try + { +#endif // _LIBCPP_NO_EXCEPTIONS + const_iterator __i = __u.begin(); + while (__cache != nullptr && __u.size() != 0) + { + __cache->__upcast()->__value_ = + _VSTD::move(__u.remove(__i++)->__value_); + __next_pointer __next = __cache->__next_; + __node_insert_multi(__cache->__upcast()); + __cache = __next; + } +#ifndef _LIBCPP_NO_EXCEPTIONS + } + catch (...) + { + __deallocate_node(__cache); + throw; + } +#endif // _LIBCPP_NO_EXCEPTIONS + __deallocate_node(__cache); + } + const_iterator __i = __u.begin(); + while (__u.size() != 0) + { + __node_holder __h = __construct_node(_NodeTypes::__move(__u.remove(__i++)->__value_)); + __node_insert_multi(__h.get()); + __h.release(); + } + } +} + +template +inline +__hash_table<_Tp, _Hash, _Equal, _Alloc>& +__hash_table<_Tp, _Hash, _Equal, _Alloc>::operator=(__hash_table&& __u) + _NOEXCEPT_( + __node_traits::propagate_on_container_move_assignment::value && + is_nothrow_move_assignable<__node_allocator>::value && + is_nothrow_move_assignable::value && + is_nothrow_move_assignable::value) +{ + __move_assign(__u, integral_constant()); + return *this; +} + +template +template +void +__hash_table<_Tp, _Hash, _Equal, _Alloc>::__assign_unique(_InputIterator __first, + _InputIterator __last) +{ + typedef iterator_traits<_InputIterator> _ITraits; + typedef typename _ITraits::value_type _ItValueType; + static_assert((is_same<_ItValueType, __container_value_type>::value), + "__assign_unique may only be called with the containers value type"); + + if (bucket_count() != 0) + { + __next_pointer __cache = __detach(); +#ifndef _LIBCPP_NO_EXCEPTIONS + try + { +#endif // _LIBCPP_NO_EXCEPTIONS + for (; __cache != nullptr && __first != __last; ++__first) + { + __cache->__upcast()->__value_ = *__first; + __next_pointer __next = __cache->__next_; + __node_insert_unique(__cache->__upcast()); + __cache = __next; + } +#ifndef _LIBCPP_NO_EXCEPTIONS + } + catch (...) + { + __deallocate_node(__cache); + throw; + } +#endif // _LIBCPP_NO_EXCEPTIONS + __deallocate_node(__cache); + } + for (; __first != __last; ++__first) + __insert_unique(*__first); +} + +template +template +void +__hash_table<_Tp, _Hash, _Equal, _Alloc>::__assign_multi(_InputIterator __first, + _InputIterator __last) +{ + typedef iterator_traits<_InputIterator> _ITraits; + typedef typename _ITraits::value_type _ItValueType; + static_assert((is_same<_ItValueType, __container_value_type>::value || + is_same<_ItValueType, __node_value_type>::value), + "__assign_multi may only be called with the containers value type" + " or the nodes value type"); + if (bucket_count() != 0) + { + __next_pointer __cache = __detach(); +#ifndef _LIBCPP_NO_EXCEPTIONS + try + { +#endif // _LIBCPP_NO_EXCEPTIONS + for (; __cache != nullptr && __first != __last; ++__first) + { + __cache->__upcast()->__value_ = *__first; + __next_pointer __next = __cache->__next_; + __node_insert_multi(__cache->__upcast()); + __cache = __next; + } +#ifndef _LIBCPP_NO_EXCEPTIONS + } + catch (...) + { + __deallocate_node(__cache); + throw; + } +#endif // _LIBCPP_NO_EXCEPTIONS + __deallocate_node(__cache); + } + for (; __first != __last; ++__first) + __insert_multi(_NodeTypes::__get_value(*__first)); +} + +template +inline +typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator +__hash_table<_Tp, _Hash, _Equal, _Alloc>::begin() _NOEXCEPT +{ + return iterator(__p1_.first().__next_, this); +} + +template +inline +typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator +__hash_table<_Tp, _Hash, _Equal, _Alloc>::end() _NOEXCEPT +{ + return iterator(nullptr, this); +} + +template +inline +typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::const_iterator +__hash_table<_Tp, _Hash, _Equal, _Alloc>::begin() const _NOEXCEPT +{ + return const_iterator(__p1_.first().__next_, this); +} + +template +inline +typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::const_iterator +__hash_table<_Tp, _Hash, _Equal, _Alloc>::end() const _NOEXCEPT +{ + return const_iterator(nullptr, this); +} + +template +void +__hash_table<_Tp, _Hash, _Equal, _Alloc>::clear() _NOEXCEPT +{ + if (size() > 0) + { + __deallocate_node(__p1_.first().__next_); + __p1_.first().__next_ = nullptr; + size_type __bc = bucket_count(); + for (size_type __i = 0; __i < __bc; ++__i) + __bucket_list_[__i] = nullptr; + size() = 0; + } +} + + +// Prepare the container for an insertion of the value __value with the hash +// __hash. This does a lookup into the container to see if __value is already +// present, and performs a rehash if necessary. Returns a pointer to the +// existing element if it exists, otherwise nullptr. +// +// Note that this function does forward exceptions if key_eq() throws, and never +// mutates __value or actually inserts into the map. +template +_LIBCPP_INLINE_VISIBILITY +typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::__next_pointer +__hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_insert_unique_prepare( + size_t __hash, value_type& __value) +{ + size_type __bc = bucket_count(); + + if (__bc != 0) + { + size_t __chash = std::__constrain_hash(__hash, __bc); + __next_pointer __ndptr = __bucket_list_[__chash]; + if (__ndptr != nullptr) + { + for (__ndptr = __ndptr->__next_; __ndptr != nullptr && + std::__constrain_hash(__ndptr->__hash(), __bc) == __chash; + __ndptr = __ndptr->__next_) + { + if (key_eq()(__ndptr->__upcast()->__value_, __value)) + return __ndptr; + } + } + } + if (size()+1 > __bc * max_load_factor() || __bc == 0) + { + __rehash_unique(_VSTD::max(2 * __bc + !std::__is_hash_power2(__bc), + size_type(std::ceil(float(size() + 1) / max_load_factor())))); + } + return nullptr; +} + +// Insert the node __nd into the container by pushing it into the right bucket, +// and updating size(). Assumes that __nd->__hash is up-to-date, and that +// rehashing has already occurred and that no element with the same key exists +// in the map. +template +_LIBCPP_INLINE_VISIBILITY +void +__hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_insert_unique_perform( + __node_pointer __nd) _NOEXCEPT +{ + size_type __bc = bucket_count(); + size_t __chash = std::__constrain_hash(__nd->__hash(), __bc); + // insert_after __bucket_list_[__chash], or __first_node if bucket is null + __next_pointer __pn = __bucket_list_[__chash]; + if (__pn == nullptr) + { + __pn =__p1_.first().__ptr(); + __nd->__next_ = __pn->__next_; + __pn->__next_ = __nd->__ptr(); + // fix up __bucket_list_ + __bucket_list_[__chash] = __pn; + if (__nd->__next_ != nullptr) + __bucket_list_[std::__constrain_hash(__nd->__next_->__hash(), __bc)] = __nd->__ptr(); + } + else + { + __nd->__next_ = __pn->__next_; + __pn->__next_ = __nd->__ptr(); + } + ++size(); +} + +template +pair::iterator, bool> +__hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_insert_unique(__node_pointer __nd) +{ + __nd->__hash_ = hash_function()(__nd->__value_); + __next_pointer __existing_node = + __node_insert_unique_prepare(__nd->__hash(), __nd->__value_); + + // Insert the node, unless it already exists in the container. + bool __inserted = false; + if (__existing_node == nullptr) + { + __node_insert_unique_perform(__nd); + __existing_node = __nd->__ptr(); + __inserted = true; + } + return pair(iterator(__existing_node, this), __inserted); +} + +// Prepare the container for an insertion of the value __cp_val with the hash +// __cp_hash. This does a lookup into the container to see if __cp_value is +// already present, and performs a rehash if necessary. Returns a pointer to the +// last occurrence of __cp_val in the map. +// +// Note that this function does forward exceptions if key_eq() throws, and never +// mutates __value or actually inserts into the map. +template +typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::__next_pointer +__hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_insert_multi_prepare( + size_t __cp_hash, value_type& __cp_val) +{ + size_type __bc = bucket_count(); + if (size()+1 > __bc * max_load_factor() || __bc == 0) + { + __rehash_multi(_VSTD::max(2 * __bc + !std::__is_hash_power2(__bc), + size_type(std::ceil(float(size() + 1) / max_load_factor())))); + __bc = bucket_count(); + } + size_t __chash = std::__constrain_hash(__cp_hash, __bc); + __next_pointer __pn = __bucket_list_[__chash]; + if (__pn != nullptr) + { + for (bool __found = false; __pn->__next_ != nullptr && + std::__constrain_hash(__pn->__next_->__hash(), __bc) == __chash; + __pn = __pn->__next_) + { + // __found key_eq() action + // false false loop + // true true loop + // false true set __found to true + // true false break + if (__found != (__pn->__next_->__hash() == __cp_hash && + key_eq()(__pn->__next_->__upcast()->__value_, __cp_val))) + { + if (!__found) + __found = true; + else + break; + } + } + } + return __pn; +} + +// Insert the node __cp into the container after __pn (which is the last node in +// the bucket that compares equal to __cp). Rehashing, and checking for +// uniqueness has already been performed (in __node_insert_multi_prepare), so +// all we need to do is update the bucket and size(). Assumes that __cp->__hash +// is up-to-date. +template +void +__hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_insert_multi_perform( + __node_pointer __cp, __next_pointer __pn) _NOEXCEPT +{ + size_type __bc = bucket_count(); + size_t __chash = std::__constrain_hash(__cp->__hash_, __bc); + if (__pn == nullptr) + { + __pn =__p1_.first().__ptr(); + __cp->__next_ = __pn->__next_; + __pn->__next_ = __cp->__ptr(); + // fix up __bucket_list_ + __bucket_list_[__chash] = __pn; + if (__cp->__next_ != nullptr) + __bucket_list_[std::__constrain_hash(__cp->__next_->__hash(), __bc)] + = __cp->__ptr(); + } + else + { + __cp->__next_ = __pn->__next_; + __pn->__next_ = __cp->__ptr(); + if (__cp->__next_ != nullptr) + { + size_t __nhash = std::__constrain_hash(__cp->__next_->__hash(), __bc); + if (__nhash != __chash) + __bucket_list_[__nhash] = __cp->__ptr(); + } + } + ++size(); +} + + +template +typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator +__hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_insert_multi(__node_pointer __cp) +{ + __cp->__hash_ = hash_function()(__cp->__value_); + __next_pointer __pn = __node_insert_multi_prepare(__cp->__hash(), __cp->__value_); + __node_insert_multi_perform(__cp, __pn); + + return iterator(__cp->__ptr(), this); +} + +template +typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator +__hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_insert_multi( + const_iterator __p, __node_pointer __cp) +{ + _LIBCPP_DEBUG_ASSERT(__get_const_db()->__find_c_from_i(_VSTD::addressof(__p)) == this, + "unordered container::emplace_hint(const_iterator, args...) called with an iterator not" + " referring to this unordered container"); + if (__p != end() && key_eq()(*__p, __cp->__value_)) + { + __next_pointer __np = __p.__node_; + __cp->__hash_ = __np->__hash(); + size_type __bc = bucket_count(); + if (size()+1 > __bc * max_load_factor() || __bc == 0) + { + __rehash_multi(_VSTD::max(2 * __bc + !std::__is_hash_power2(__bc), + size_type(std::ceil(float(size() + 1) / max_load_factor())))); + __bc = bucket_count(); + } + size_t __chash = std::__constrain_hash(__cp->__hash_, __bc); + __next_pointer __pp = __bucket_list_[__chash]; + while (__pp->__next_ != __np) + __pp = __pp->__next_; + __cp->__next_ = __np; + __pp->__next_ = static_cast<__next_pointer>(__cp); + ++size(); + return iterator(static_cast<__next_pointer>(__cp), this); + } + return __node_insert_multi(__cp); +} + + + +template +template +pair::iterator, bool> +__hash_table<_Tp, _Hash, _Equal, _Alloc>::__emplace_unique_key_args(_Key const& __k, _Args&&... __args) +{ + + size_t __hash = hash_function()(__k); + size_type __bc = bucket_count(); + bool __inserted = false; + __next_pointer __nd; + size_t __chash; + if (__bc != 0) + { + __chash = std::__constrain_hash(__hash, __bc); + __nd = __bucket_list_[__chash]; + if (__nd != nullptr) + { + for (__nd = __nd->__next_; __nd != nullptr && + (__nd->__hash() == __hash || std::__constrain_hash(__nd->__hash(), __bc) == __chash); + __nd = __nd->__next_) + { + if (key_eq()(__nd->__upcast()->__value_, __k)) + goto __done; + } + } + } + { + __node_holder __h = __construct_node_hash(__hash, _VSTD::forward<_Args>(__args)...); + if (size()+1 > __bc * max_load_factor() || __bc == 0) + { + __rehash_unique(_VSTD::max(2 * __bc + !std::__is_hash_power2(__bc), + size_type(std::ceil(float(size() + 1) / max_load_factor())))); + __bc = bucket_count(); + __chash = std::__constrain_hash(__hash, __bc); + } + // insert_after __bucket_list_[__chash], or __first_node if bucket is null + __next_pointer __pn = __bucket_list_[__chash]; + if (__pn == nullptr) + { + __pn = __p1_.first().__ptr(); + __h->__next_ = __pn->__next_; + __pn->__next_ = __h.get()->__ptr(); + // fix up __bucket_list_ + __bucket_list_[__chash] = __pn; + if (__h->__next_ != nullptr) + __bucket_list_[std::__constrain_hash(__h->__next_->__hash(), __bc)] + = __h.get()->__ptr(); + } + else + { + __h->__next_ = __pn->__next_; + __pn->__next_ = static_cast<__next_pointer>(__h.get()); + } + __nd = static_cast<__next_pointer>(__h.release()); + // increment size + ++size(); + __inserted = true; + } +__done: + return pair(iterator(__nd, this), __inserted); +} + +template +template +pair::iterator, bool> +__hash_table<_Tp, _Hash, _Equal, _Alloc>::__emplace_unique_impl(_Args&&... __args) +{ + __node_holder __h = __construct_node(_VSTD::forward<_Args>(__args)...); + pair __r = __node_insert_unique(__h.get()); + if (__r.second) + __h.release(); + return __r; +} + +template +template +typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator +__hash_table<_Tp, _Hash, _Equal, _Alloc>::__emplace_multi(_Args&&... __args) +{ + __node_holder __h = __construct_node(_VSTD::forward<_Args>(__args)...); + iterator __r = __node_insert_multi(__h.get()); + __h.release(); + return __r; +} + +template +template +typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator +__hash_table<_Tp, _Hash, _Equal, _Alloc>::__emplace_hint_multi( + const_iterator __p, _Args&&... __args) +{ + _LIBCPP_DEBUG_ASSERT(__get_const_db()->__find_c_from_i(_VSTD::addressof(__p)) == this, + "unordered container::emplace_hint(const_iterator, args...) called with an iterator not" + " referring to this unordered container"); + __node_holder __h = __construct_node(_VSTD::forward<_Args>(__args)...); + iterator __r = __node_insert_multi(__p, __h.get()); + __h.release(); + return __r; +} + +#if _LIBCPP_STD_VER > 14 +template +template +_LIBCPP_INLINE_VISIBILITY +_InsertReturnType +__hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_handle_insert_unique( + _NodeHandle&& __nh) +{ + if (__nh.empty()) + return _InsertReturnType{end(), false, _NodeHandle()}; + pair __result = __node_insert_unique(__nh.__ptr_); + if (__result.second) + __nh.__release_ptr(); + return _InsertReturnType{__result.first, __result.second, _VSTD::move(__nh)}; +} + +template +template +_LIBCPP_INLINE_VISIBILITY +typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator +__hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_handle_insert_unique( + const_iterator, _NodeHandle&& __nh) +{ + if (__nh.empty()) + return end(); + pair __result = __node_insert_unique(__nh.__ptr_); + if (__result.second) + __nh.__release_ptr(); + return __result.first; +} + +template +template +_LIBCPP_INLINE_VISIBILITY +_NodeHandle +__hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_handle_extract( + key_type const& __key) +{ + iterator __i = find(__key); + if (__i == end()) + return _NodeHandle(); + return __node_handle_extract<_NodeHandle>(__i); +} + +template +template +_LIBCPP_INLINE_VISIBILITY +_NodeHandle +__hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_handle_extract( + const_iterator __p) +{ + allocator_type __alloc(__node_alloc()); + return _NodeHandle(remove(__p).release(), __alloc); +} + +template +template +_LIBCPP_INLINE_VISIBILITY +void +__hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_handle_merge_unique( + _Table& __source) +{ + static_assert(is_same<__node, typename _Table::__node>::value, ""); + + for (typename _Table::iterator __it = __source.begin(); + __it != __source.end();) + { + __node_pointer __src_ptr = __it.__node_->__upcast(); + size_t __hash = hash_function()(__src_ptr->__value_); + __next_pointer __existing_node = + __node_insert_unique_prepare(__hash, __src_ptr->__value_); + auto __prev_iter = __it++; + if (__existing_node == nullptr) + { + (void)__source.remove(__prev_iter).release(); + __src_ptr->__hash_ = __hash; + __node_insert_unique_perform(__src_ptr); + } + } +} + +template +template +_LIBCPP_INLINE_VISIBILITY +typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator +__hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_handle_insert_multi( + _NodeHandle&& __nh) +{ + if (__nh.empty()) + return end(); + iterator __result = __node_insert_multi(__nh.__ptr_); + __nh.__release_ptr(); + return __result; +} + +template +template +_LIBCPP_INLINE_VISIBILITY +typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator +__hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_handle_insert_multi( + const_iterator __hint, _NodeHandle&& __nh) +{ + if (__nh.empty()) + return end(); + iterator __result = __node_insert_multi(__hint, __nh.__ptr_); + __nh.__release_ptr(); + return __result; +} + +template +template +_LIBCPP_INLINE_VISIBILITY +void +__hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_handle_merge_multi( + _Table& __source) +{ + static_assert(is_same::value, ""); + + for (typename _Table::iterator __it = __source.begin(); + __it != __source.end();) + { + __node_pointer __src_ptr = __it.__node_->__upcast(); + size_t __src_hash = hash_function()(__src_ptr->__value_); + __next_pointer __pn = + __node_insert_multi_prepare(__src_hash, __src_ptr->__value_); + (void)__source.remove(__it++).release(); + __src_ptr->__hash_ = __src_hash; + __node_insert_multi_perform(__src_ptr, __pn); + } +} +#endif // _LIBCPP_STD_VER > 14 + +template +template +void +__hash_table<_Tp, _Hash, _Equal, _Alloc>::__rehash(size_type __n) +_LIBCPP_DISABLE_UBSAN_UNSIGNED_INTEGER_CHECK +{ + if (__n == 1) + __n = 2; + else if (__n & (__n - 1)) + __n = std::__next_prime(__n); + size_type __bc = bucket_count(); + if (__n > __bc) + __do_rehash<_UniqueKeys>(__n); + else if (__n < __bc) + { + __n = _VSTD::max + ( + __n, + std::__is_hash_power2(__bc) ? std::__next_hash_pow2(size_t(std::ceil(float(size()) / max_load_factor()))) : + std::__next_prime(size_t(std::ceil(float(size()) / max_load_factor()))) + ); + if (__n < __bc) + __do_rehash<_UniqueKeys>(__n); + } +} + +template +template +void +__hash_table<_Tp, _Hash, _Equal, _Alloc>::__do_rehash(size_type __nbc) +{ + std::__debug_db_invalidate_all(this); + __pointer_allocator& __npa = __bucket_list_.get_deleter().__alloc(); + __bucket_list_.reset(__nbc > 0 ? + __pointer_alloc_traits::allocate(__npa, __nbc) : nullptr); + __bucket_list_.get_deleter().size() = __nbc; + if (__nbc > 0) + { + for (size_type __i = 0; __i < __nbc; ++__i) + __bucket_list_[__i] = nullptr; + __next_pointer __pp = __p1_.first().__ptr(); + __next_pointer __cp = __pp->__next_; + if (__cp != nullptr) + { + size_type __chash = std::__constrain_hash(__cp->__hash(), __nbc); + __bucket_list_[__chash] = __pp; + size_type __phash = __chash; + for (__pp = __cp, void(), __cp = __cp->__next_; __cp != nullptr; + __cp = __pp->__next_) + { + __chash = std::__constrain_hash(__cp->__hash(), __nbc); + if (__chash == __phash) + __pp = __cp; + else + { + if (__bucket_list_[__chash] == nullptr) + { + __bucket_list_[__chash] = __pp; + __pp = __cp; + __phash = __chash; + } + else + { + __next_pointer __np = __cp; + if _LIBCPP_CONSTEXPR_SINCE_CXX17 (!_UniqueKeys) + { + for (; __np->__next_ != nullptr && + key_eq()(__cp->__upcast()->__value_, + __np->__next_->__upcast()->__value_); + __np = __np->__next_) + ; + } + __pp->__next_ = __np->__next_; + __np->__next_ = __bucket_list_[__chash]->__next_; + __bucket_list_[__chash]->__next_ = __cp; + + } + } + } + } + } +} + +template +template +typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator +__hash_table<_Tp, _Hash, _Equal, _Alloc>::find(const _Key& __k) +{ + size_t __hash = hash_function()(__k); + size_type __bc = bucket_count(); + if (__bc != 0) + { + size_t __chash = std::__constrain_hash(__hash, __bc); + __next_pointer __nd = __bucket_list_[__chash]; + if (__nd != nullptr) + { + for (__nd = __nd->__next_; __nd != nullptr && + (__nd->__hash() == __hash + || std::__constrain_hash(__nd->__hash(), __bc) == __chash); + __nd = __nd->__next_) + { + if ((__nd->__hash() == __hash) + && key_eq()(__nd->__upcast()->__value_, __k)) + return iterator(__nd, this); + } + } + } + return end(); +} + +template +template +typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::const_iterator +__hash_table<_Tp, _Hash, _Equal, _Alloc>::find(const _Key& __k) const +{ + size_t __hash = hash_function()(__k); + size_type __bc = bucket_count(); + if (__bc != 0) + { + size_t __chash = std::__constrain_hash(__hash, __bc); + __next_pointer __nd = __bucket_list_[__chash]; + if (__nd != nullptr) + { + for (__nd = __nd->__next_; __nd != nullptr && + (__hash == __nd->__hash() + || std::__constrain_hash(__nd->__hash(), __bc) == __chash); + __nd = __nd->__next_) + { + if ((__nd->__hash() == __hash) + && key_eq()(__nd->__upcast()->__value_, __k)) + return const_iterator(__nd, this); + } + } + + } + return end(); +} + +template +template +typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_holder +__hash_table<_Tp, _Hash, _Equal, _Alloc>::__construct_node(_Args&& ...__args) +{ + static_assert(!__is_hash_value_type<_Args...>::value, + "Construct cannot be called with a hash value type"); + __node_allocator& __na = __node_alloc(); + __node_holder __h(__node_traits::allocate(__na, 1), _Dp(__na)); + __node_traits::construct(__na, _NodeTypes::__get_ptr(__h->__value_), _VSTD::forward<_Args>(__args)...); + __h.get_deleter().__value_constructed = true; + __h->__hash_ = hash_function()(__h->__value_); + __h->__next_ = nullptr; + return __h; +} + +template +template +typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_holder +__hash_table<_Tp, _Hash, _Equal, _Alloc>::__construct_node_hash( + size_t __hash, _First&& __f, _Rest&& ...__rest) +{ + static_assert(!__is_hash_value_type<_First, _Rest...>::value, + "Construct cannot be called with a hash value type"); + __node_allocator& __na = __node_alloc(); + __node_holder __h(__node_traits::allocate(__na, 1), _Dp(__na)); + __node_traits::construct(__na, _NodeTypes::__get_ptr(__h->__value_), + _VSTD::forward<_First>(__f), + _VSTD::forward<_Rest>(__rest)...); + __h.get_deleter().__value_constructed = true; + __h->__hash_ = __hash; + __h->__next_ = nullptr; + return __h; +} + +template +typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator +__hash_table<_Tp, _Hash, _Equal, _Alloc>::erase(const_iterator __p) +{ + __next_pointer __np = __p.__node_; + _LIBCPP_DEBUG_ASSERT(__get_const_db()->__find_c_from_i(_VSTD::addressof(__p)) == this, + "unordered container erase(iterator) called with an iterator not" + " referring to this container"); + _LIBCPP_ASSERT(__p != end(), + "unordered container erase(iterator) called with a non-dereferenceable iterator"); + iterator __r(__np, this); + ++__r; + remove(__p); + return __r; +} + +template +typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator +__hash_table<_Tp, _Hash, _Equal, _Alloc>::erase(const_iterator __first, + const_iterator __last) +{ + _LIBCPP_DEBUG_ASSERT(__get_const_db()->__find_c_from_i(_VSTD::addressof(__first)) == this, + "unordered container::erase(iterator, iterator) called with an iterator not" + " referring to this container"); + _LIBCPP_DEBUG_ASSERT(__get_const_db()->__find_c_from_i(_VSTD::addressof(__last)) == this, + "unordered container::erase(iterator, iterator) called with an iterator not" + " referring to this container"); + for (const_iterator __p = __first; __first != __last; __p = __first) + { + ++__first; + erase(__p); + } + __next_pointer __np = __last.__node_; + return iterator (__np, this); +} + +template +template +typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::size_type +__hash_table<_Tp, _Hash, _Equal, _Alloc>::__erase_unique(const _Key& __k) +{ + iterator __i = find(__k); + if (__i == end()) + return 0; + erase(__i); + return 1; +} + +template +template +typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::size_type +__hash_table<_Tp, _Hash, _Equal, _Alloc>::__erase_multi(const _Key& __k) +{ + size_type __r = 0; + iterator __i = find(__k); + if (__i != end()) + { + iterator __e = end(); + do + { + erase(__i++); + ++__r; + } while (__i != __e && key_eq()(*__i, __k)); + } + return __r; +} + +template +typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_holder +__hash_table<_Tp, _Hash, _Equal, _Alloc>::remove(const_iterator __p) _NOEXCEPT +{ + // current node + __next_pointer __cn = __p.__node_; + size_type __bc = bucket_count(); + size_t __chash = std::__constrain_hash(__cn->__hash(), __bc); + // find previous node + __next_pointer __pn = __bucket_list_[__chash]; + for (; __pn->__next_ != __cn; __pn = __pn->__next_) + ; + // Fix up __bucket_list_ + // if __pn is not in same bucket (before begin is not in same bucket) && + // if __cn->__next_ is not in same bucket (nullptr is not in same bucket) + if (__pn == __p1_.first().__ptr() + || std::__constrain_hash(__pn->__hash(), __bc) != __chash) + { + if (__cn->__next_ == nullptr + || std::__constrain_hash(__cn->__next_->__hash(), __bc) != __chash) + __bucket_list_[__chash] = nullptr; + } + // if __cn->__next_ is not in same bucket (nullptr is in same bucket) + if (__cn->__next_ != nullptr) + { + size_t __nhash = std::__constrain_hash(__cn->__next_->__hash(), __bc); + if (__nhash != __chash) + __bucket_list_[__nhash] = __pn; + } + // remove __cn + __pn->__next_ = __cn->__next_; + __cn->__next_ = nullptr; + --size(); +#ifdef _LIBCPP_ENABLE_DEBUG_MODE + __c_node* __c = __get_db()->__find_c_and_lock(this); + for (__i_node** __dp = __c->end_; __dp != __c->beg_; ) + { + --__dp; + iterator* __i = static_cast((*__dp)->__i_); + if (__i->__node_ == __cn) + { + (*__dp)->__c_ = nullptr; + if (--__c->end_ != __dp) + _VSTD::memmove(__dp, __dp+1, (__c->end_ - __dp)*sizeof(__i_node*)); + } + } + __get_db()->unlock(); +#endif + return __node_holder(__cn->__upcast(), _Dp(__node_alloc(), true)); +} + +template +template +inline +typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::size_type +__hash_table<_Tp, _Hash, _Equal, _Alloc>::__count_unique(const _Key& __k) const +{ + return static_cast(find(__k) != end()); +} + +template +template +typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::size_type +__hash_table<_Tp, _Hash, _Equal, _Alloc>::__count_multi(const _Key& __k) const +{ + size_type __r = 0; + const_iterator __i = find(__k); + if (__i != end()) + { + const_iterator __e = end(); + do + { + ++__i; + ++__r; + } while (__i != __e && key_eq()(*__i, __k)); + } + return __r; +} + +template +template +pair::iterator, + typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator> +__hash_table<_Tp, _Hash, _Equal, _Alloc>::__equal_range_unique( + const _Key& __k) +{ + iterator __i = find(__k); + iterator __j = __i; + if (__i != end()) + ++__j; + return pair(__i, __j); +} + +template +template +pair::const_iterator, + typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::const_iterator> +__hash_table<_Tp, _Hash, _Equal, _Alloc>::__equal_range_unique( + const _Key& __k) const +{ + const_iterator __i = find(__k); + const_iterator __j = __i; + if (__i != end()) + ++__j; + return pair(__i, __j); +} + +template +template +pair::iterator, + typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator> +__hash_table<_Tp, _Hash, _Equal, _Alloc>::__equal_range_multi( + const _Key& __k) +{ + iterator __i = find(__k); + iterator __j = __i; + if (__i != end()) + { + iterator __e = end(); + do + { + ++__j; + } while (__j != __e && key_eq()(*__j, __k)); + } + return pair(__i, __j); +} + +template +template +pair::const_iterator, + typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::const_iterator> +__hash_table<_Tp, _Hash, _Equal, _Alloc>::__equal_range_multi( + const _Key& __k) const +{ + const_iterator __i = find(__k); + const_iterator __j = __i; + if (__i != end()) + { + const_iterator __e = end(); + do + { + ++__j; + } while (__j != __e && key_eq()(*__j, __k)); + } + return pair(__i, __j); +} + +template +void +__hash_table<_Tp, _Hash, _Equal, _Alloc>::swap(__hash_table& __u) +#if _LIBCPP_STD_VER <= 11 + _NOEXCEPT_( + __is_nothrow_swappable::value && __is_nothrow_swappable::value + && (!allocator_traits<__pointer_allocator>::propagate_on_container_swap::value + || __is_nothrow_swappable<__pointer_allocator>::value) + && (!__node_traits::propagate_on_container_swap::value + || __is_nothrow_swappable<__node_allocator>::value) + ) +#else + _NOEXCEPT_(__is_nothrow_swappable::value && __is_nothrow_swappable::value) +#endif +{ + _LIBCPP_ASSERT(__node_traits::propagate_on_container_swap::value || + this->__node_alloc() == __u.__node_alloc(), + "list::swap: Either propagate_on_container_swap must be true" + " or the allocators must compare equal"); + { + __node_pointer_pointer __npp = __bucket_list_.release(); + __bucket_list_.reset(__u.__bucket_list_.release()); + __u.__bucket_list_.reset(__npp); + } + _VSTD::swap(__bucket_list_.get_deleter().size(), __u.__bucket_list_.get_deleter().size()); + _VSTD::__swap_allocator(__bucket_list_.get_deleter().__alloc(), + __u.__bucket_list_.get_deleter().__alloc()); + _VSTD::__swap_allocator(__node_alloc(), __u.__node_alloc()); + _VSTD::swap(__p1_.first().__next_, __u.__p1_.first().__next_); + __p2_.swap(__u.__p2_); + __p3_.swap(__u.__p3_); + if (size() > 0) + __bucket_list_[std::__constrain_hash(__p1_.first().__next_->__hash(), bucket_count())] = + __p1_.first().__ptr(); + if (__u.size() > 0) + __u.__bucket_list_[std::__constrain_hash(__u.__p1_.first().__next_->__hash(), __u.bucket_count())] = + __u.__p1_.first().__ptr(); + std::__debug_db_swap(this, std::addressof(__u)); +} + +template +typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::size_type +__hash_table<_Tp, _Hash, _Equal, _Alloc>::bucket_size(size_type __n) const +{ + _LIBCPP_ASSERT(__n < bucket_count(), + "unordered container::bucket_size(n) called with n >= bucket_count()"); + __next_pointer __np = __bucket_list_[__n]; + size_type __bc = bucket_count(); + size_type __r = 0; + if (__np != nullptr) + { + for (__np = __np->__next_; __np != nullptr && + std::__constrain_hash(__np->__hash(), __bc) == __n; + __np = __np->__next_, (void) ++__r) + ; + } + return __r; +} + +template +inline _LIBCPP_INLINE_VISIBILITY +void +swap(__hash_table<_Tp, _Hash, _Equal, _Alloc>& __x, + __hash_table<_Tp, _Hash, _Equal, _Alloc>& __y) + _NOEXCEPT_(_NOEXCEPT_(__x.swap(__y))) +{ + __x.swap(__y); +} + +#ifdef _LIBCPP_ENABLE_DEBUG_MODE + +template +bool +__hash_table<_Tp, _Hash, _Equal, _Alloc>::__dereferenceable(const const_iterator* __i) const +{ + return __i->__node_ != nullptr; +} + +template +bool +__hash_table<_Tp, _Hash, _Equal, _Alloc>::__decrementable(const const_iterator*) const +{ + return false; +} + +template +bool +__hash_table<_Tp, _Hash, _Equal, _Alloc>::__addable(const const_iterator*, ptrdiff_t) const +{ + return false; +} + +template +bool +__hash_table<_Tp, _Hash, _Equal, _Alloc>::__subscriptable(const const_iterator*, ptrdiff_t) const +{ + return false; +} + +#endif // _LIBCPP_ENABLE_DEBUG_MODE + +_LIBCPP_END_NAMESPACE_STD + +_LIBCPP_POP_MACROS + +#endif // _LIBCPP___HASH_TABLE diff --git a/app/src/main/cpp/libcxx/include/__ios/fpos.h b/app/src/main/cpp/libcxx/include/__ios/fpos.h new file mode 100644 index 0000000..87f0135 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__ios/fpos.h @@ -0,0 +1,79 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___IOS_FPOS_H +#define _LIBCPP___IOS_FPOS_H + +#include <__config> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +template +class _LIBCPP_TEMPLATE_VIS fpos { +private: + _StateT __st_; + streamoff __off_; + +public: + _LIBCPP_HIDE_FROM_ABI fpos(streamoff __off = streamoff()) : __st_(), __off_(__off) {} + + _LIBCPP_HIDE_FROM_ABI operator streamoff() const { return __off_; } + + _LIBCPP_HIDE_FROM_ABI _StateT state() const { return __st_; } + _LIBCPP_HIDE_FROM_ABI void state(_StateT __st) { __st_ = __st; } + + _LIBCPP_HIDE_FROM_ABI fpos& operator+=(streamoff __off) { + __off_ += __off; + return *this; + } + + _LIBCPP_HIDE_FROM_ABI fpos operator+(streamoff __off) const { + fpos __t(*this); + __t += __off; + return __t; + } + + _LIBCPP_HIDE_FROM_ABI fpos& operator-=(streamoff __off) { + __off_ -= __off; + return *this; + } + + _LIBCPP_HIDE_FROM_ABI fpos operator-(streamoff __off) const { + fpos __t(*this); + __t -= __off; + return __t; + } +}; + +template +inline _LIBCPP_HIDE_FROM_ABI +streamoff operator-(const fpos<_StateT>& __x, const fpos<_StateT>& __y) { + return streamoff(__x) - streamoff(__y); +} + +template +inline _LIBCPP_HIDE_FROM_ABI +bool operator==(const fpos<_StateT>& __x, const fpos<_StateT>& __y) { + return streamoff(__x) == streamoff(__y); +} + +template +inline _LIBCPP_HIDE_FROM_ABI +bool operator!=(const fpos<_StateT>& __x, const fpos<_StateT>& __y) { + return streamoff(__x) != streamoff(__y); +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___IOS_FPOS_H diff --git a/app/src/main/cpp/libcxx/include/__iterator/access.h b/app/src/main/cpp/libcxx/include/__iterator/access.h new file mode 100644 index 0000000..0b8d523 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__iterator/access.h @@ -0,0 +1,129 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ITERATOR_ACCESS_H +#define _LIBCPP___ITERATOR_ACCESS_H + +#include <__config> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +template +_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 +_Tp* +begin(_Tp (&__array)[_Np]) +{ + return __array; +} + +template +_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 +_Tp* +end(_Tp (&__array)[_Np]) +{ + return __array + _Np; +} + +#if !defined(_LIBCPP_CXX03_LANG) + +template +_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX17 +auto +begin(_Cp& __c) -> decltype(__c.begin()) +{ + return __c.begin(); +} + +template +_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX17 +auto +begin(const _Cp& __c) -> decltype(__c.begin()) +{ + return __c.begin(); +} + +template +_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX17 +auto +end(_Cp& __c) -> decltype(__c.end()) +{ + return __c.end(); +} + +template +_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX17 +auto +end(const _Cp& __c) -> decltype(__c.end()) +{ + return __c.end(); +} + +#if _LIBCPP_STD_VER > 11 + +template +_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 +auto cbegin(const _Cp& __c) -> decltype(_VSTD::begin(__c)) +{ + return _VSTD::begin(__c); +} + +template +_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 +auto cend(const _Cp& __c) -> decltype(_VSTD::end(__c)) +{ + return _VSTD::end(__c); +} + +#endif + + +#else // defined(_LIBCPP_CXX03_LANG) + +template +_LIBCPP_INLINE_VISIBILITY +typename _Cp::iterator +begin(_Cp& __c) +{ + return __c.begin(); +} + +template +_LIBCPP_INLINE_VISIBILITY +typename _Cp::const_iterator +begin(const _Cp& __c) +{ + return __c.begin(); +} + +template +_LIBCPP_INLINE_VISIBILITY +typename _Cp::iterator +end(_Cp& __c) +{ + return __c.end(); +} + +template +_LIBCPP_INLINE_VISIBILITY +typename _Cp::const_iterator +end(const _Cp& __c) +{ + return __c.end(); +} + +#endif // !defined(_LIBCPP_CXX03_LANG) + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ITERATOR_ACCESS_H diff --git a/app/src/main/cpp/libcxx/include/__iterator/advance.h b/app/src/main/cpp/libcxx/include/__iterator/advance.h new file mode 100644 index 0000000..154c273 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__iterator/advance.h @@ -0,0 +1,203 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ITERATOR_ADVANCE_H +#define _LIBCPP___ITERATOR_ADVANCE_H + +#include <__assert> +#include <__concepts/assignable.h> +#include <__concepts/same_as.h> +#include <__config> +#include <__iterator/concepts.h> +#include <__iterator/incrementable_traits.h> +#include <__iterator/iterator_traits.h> +#include <__type_traits/enable_if.h> +#include <__type_traits/is_integral.h> +#include <__utility/convert_to_integral.h> +#include <__utility/declval.h> +#include <__utility/move.h> +#include <__utility/unreachable.h> +#include +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 +void __advance(_InputIter& __i, typename iterator_traits<_InputIter>::difference_type __n, input_iterator_tag) { + for (; __n > 0; --__n) + ++__i; +} + +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 +void __advance(_BiDirIter& __i, typename iterator_traits<_BiDirIter>::difference_type __n, bidirectional_iterator_tag) { + if (__n >= 0) + for (; __n > 0; --__n) + ++__i; + else + for (; __n < 0; ++__n) + --__i; +} + +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 +void __advance(_RandIter& __i, typename iterator_traits<_RandIter>::difference_type __n, random_access_iterator_tag) { + __i += __n; +} + +template < + class _InputIter, class _Distance, + class _IntegralDistance = decltype(_VSTD::__convert_to_integral(std::declval<_Distance>())), + class = __enable_if_t::value> > +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 +void advance(_InputIter& __i, _Distance __orig_n) { + typedef typename iterator_traits<_InputIter>::difference_type _Difference; + _Difference __n = static_cast<_Difference>(_VSTD::__convert_to_integral(__orig_n)); + _LIBCPP_ASSERT(__n >= 0 || __is_cpp17_bidirectional_iterator<_InputIter>::value, + "Attempt to advance(it, n) with negative n on a non-bidirectional iterator"); + _VSTD::__advance(__i, __n, typename iterator_traits<_InputIter>::iterator_category()); +} + +#if _LIBCPP_STD_VER > 17 + +// [range.iter.op.advance] + +namespace ranges { +namespace __advance { + +struct __fn { +private: + template + _LIBCPP_HIDE_FROM_ABI + static constexpr void __advance_forward(_Ip& __i, iter_difference_t<_Ip> __n) { + while (__n > 0) { + --__n; + ++__i; + } + } + + template + _LIBCPP_HIDE_FROM_ABI + static constexpr void __advance_backward(_Ip& __i, iter_difference_t<_Ip> __n) { + while (__n < 0) { + ++__n; + --__i; + } + } + +public: + // Preconditions: If `I` does not model `bidirectional_iterator`, `n` is not negative. + template + _LIBCPP_HIDE_FROM_ABI + constexpr void operator()(_Ip& __i, iter_difference_t<_Ip> __n) const { + _LIBCPP_ASSERT(__n >= 0 || bidirectional_iterator<_Ip>, + "If `n < 0`, then `bidirectional_iterator` must be true."); + + // If `I` models `random_access_iterator`, equivalent to `i += n`. + if constexpr (random_access_iterator<_Ip>) { + __i += __n; + return; + } else if constexpr (bidirectional_iterator<_Ip>) { + // Otherwise, if `n` is non-negative, increments `i` by `n`. + __advance_forward(__i, __n); + // Otherwise, decrements `i` by `-n`. + __advance_backward(__i, __n); + return; + } else { + // Otherwise, if `n` is non-negative, increments `i` by `n`. + __advance_forward(__i, __n); + return; + } + } + + // Preconditions: Either `assignable_from || sized_sentinel_for` is modeled, or [i, bound_sentinel) denotes a range. + template _Sp> + _LIBCPP_HIDE_FROM_ABI constexpr void operator()(_Ip& __i, _Sp __bound_sentinel) const { + // If `I` and `S` model `assignable_from`, equivalent to `i = std::move(bound_sentinel)`. + if constexpr (assignable_from<_Ip&, _Sp>) { + __i = _VSTD::move(__bound_sentinel); + } + // Otherwise, if `S` and `I` model `sized_sentinel_for`, equivalent to `ranges::advance(i, bound_sentinel - i)`. + else if constexpr (sized_sentinel_for<_Sp, _Ip>) { + (*this)(__i, __bound_sentinel - __i); + } + // Otherwise, while `bool(i != bound_sentinel)` is true, increments `i`. + else { + while (__i != __bound_sentinel) { + ++__i; + } + } + } + + // Preconditions: + // * If `n > 0`, [i, bound_sentinel) denotes a range. + // * If `n == 0`, [i, bound_sentinel) or [bound_sentinel, i) denotes a range. + // * If `n < 0`, [bound_sentinel, i) denotes a range, `I` models `bidirectional_iterator`, and `I` and `S` model `same_as`. + // Returns: `n - M`, where `M` is the difference between the ending and starting position. + template _Sp> + _LIBCPP_HIDE_FROM_ABI constexpr iter_difference_t<_Ip> operator()(_Ip& __i, iter_difference_t<_Ip> __n, + _Sp __bound_sentinel) const { + _LIBCPP_ASSERT((__n >= 0) || (bidirectional_iterator<_Ip> && same_as<_Ip, _Sp>), + "If `n < 0`, then `bidirectional_iterator && same_as` must be true."); + // If `S` and `I` model `sized_sentinel_for`: + if constexpr (sized_sentinel_for<_Sp, _Ip>) { + // If |n| >= |bound_sentinel - i|, equivalent to `ranges::advance(i, bound_sentinel)`. + // __magnitude_geq(a, b) returns |a| >= |b|, assuming they have the same sign. + auto __magnitude_geq = [](auto __a, auto __b) { + return __a == 0 ? __b == 0 : + __a > 0 ? __a >= __b : + __a <= __b; + }; + if (const auto __M = __bound_sentinel - __i; __magnitude_geq(__n, __M)) { + (*this)(__i, __bound_sentinel); + return __n - __M; + } + + // Otherwise, equivalent to `ranges::advance(i, n)`. + (*this)(__i, __n); + return 0; + } else { + // Otherwise, if `n` is non-negative, while `bool(i != bound_sentinel)` is true, increments `i` but at + // most `n` times. + while (__i != __bound_sentinel && __n > 0) { + ++__i; + --__n; + } + + // Otherwise, while `bool(i != bound_sentinel)` is true, decrements `i` but at most `-n` times. + if constexpr (bidirectional_iterator<_Ip> && same_as<_Ip, _Sp>) { + while (__i != __bound_sentinel && __n < 0) { + --__i; + ++__n; + } + } + return __n; + } + + __libcpp_unreachable(); + } +}; + +} // namespace __advance + +inline namespace __cpo { + inline constexpr auto advance = __advance::__fn{}; +} // namespace __cpo +} // namespace ranges + +#endif // _LIBCPP_STD_VER > 17 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ITERATOR_ADVANCE_H diff --git a/app/src/main/cpp/libcxx/include/__iterator/back_insert_iterator.h b/app/src/main/cpp/libcxx/include/__iterator/back_insert_iterator.h new file mode 100644 index 0000000..4c00a7e --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__iterator/back_insert_iterator.h @@ -0,0 +1,73 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ITERATOR_BACK_INSERT_ITERATOR_H +#define _LIBCPP___ITERATOR_BACK_INSERT_ITERATOR_H + +#include <__config> +#include <__iterator/iterator.h> +#include <__iterator/iterator_traits.h> +#include <__memory/addressof.h> +#include <__utility/move.h> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +_LIBCPP_SUPPRESS_DEPRECATED_PUSH +template +class _LIBCPP_TEMPLATE_VIS back_insert_iterator +#if _LIBCPP_STD_VER <= 14 || !defined(_LIBCPP_ABI_NO_ITERATOR_BASES) + : public iterator +#endif +{ +_LIBCPP_SUPPRESS_DEPRECATED_POP +protected: + _Container* container; +public: + typedef output_iterator_tag iterator_category; + typedef void value_type; +#if _LIBCPP_STD_VER > 17 + typedef ptrdiff_t difference_type; +#else + typedef void difference_type; +#endif + typedef void pointer; + typedef void reference; + typedef _Container container_type; + + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 explicit back_insert_iterator(_Container& __x) : container(_VSTD::addressof(__x)) {} + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 back_insert_iterator& operator=(const typename _Container::value_type& __value) + {container->push_back(__value); return *this;} +#ifndef _LIBCPP_CXX03_LANG + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 back_insert_iterator& operator=(typename _Container::value_type&& __value) + {container->push_back(_VSTD::move(__value)); return *this;} +#endif // _LIBCPP_CXX03_LANG + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 back_insert_iterator& operator*() {return *this;} + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 back_insert_iterator& operator++() {return *this;} + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 back_insert_iterator operator++(int) {return *this;} + + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Container* __get_container() const { return container; } +}; +_LIBCPP_CTAD_SUPPORTED_FOR_TYPE(back_insert_iterator); + +template +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 +back_insert_iterator<_Container> +back_inserter(_Container& __x) +{ + return back_insert_iterator<_Container>(__x); +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ITERATOR_BACK_INSERT_ITERATOR_H diff --git a/app/src/main/cpp/libcxx/include/__iterator/bounded_iter.h b/app/src/main/cpp/libcxx/include/__iterator/bounded_iter.h new file mode 100644 index 0000000..2682f2a --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__iterator/bounded_iter.h @@ -0,0 +1,231 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ITERATOR_BOUNDED_ITER_H +#define _LIBCPP___ITERATOR_BOUNDED_ITER_H + +#include <__assert> +#include <__config> +#include <__iterator/iterator_traits.h> +#include <__memory/pointer_traits.h> +#include <__type_traits/enable_if.h> +#include <__type_traits/integral_constant.h> +#include <__type_traits/is_convertible.h> +#include <__utility/move.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +// Iterator wrapper that carries the valid range it is allowed to access. +// +// This is a simple iterator wrapper for contiguous iterators that points +// within a [begin, end) range and carries these bounds with it. The iterator +// ensures that it is pointing within that [begin, end) range when it is +// dereferenced. +// +// Arithmetic operations are allowed and the bounds of the resulting iterator +// are not checked. Hence, it is possible to create an iterator pointing outside +// its range, but it is not possible to dereference it. +template ::value > > +struct __bounded_iter { + using value_type = typename iterator_traits<_Iterator>::value_type; + using difference_type = typename iterator_traits<_Iterator>::difference_type; + using pointer = typename iterator_traits<_Iterator>::pointer; + using reference = typename iterator_traits<_Iterator>::reference; + using iterator_category = typename iterator_traits<_Iterator>::iterator_category; +#if _LIBCPP_STD_VER > 17 + using iterator_concept = contiguous_iterator_tag; +#endif + + // Create a singular iterator. + // + // Such an iterator does not point to any object and is conceptually out of bounds, so it is + // not dereferenceable. Observing operations like comparison and assignment are valid. + _LIBCPP_HIDE_FROM_ABI __bounded_iter() = default; + + _LIBCPP_HIDE_FROM_ABI __bounded_iter(__bounded_iter const&) = default; + _LIBCPP_HIDE_FROM_ABI __bounded_iter(__bounded_iter&&) = default; + + template ::value > > + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR __bounded_iter(__bounded_iter<_OtherIterator> const& __other) _NOEXCEPT + : __current_(__other.__current_), + __begin_(__other.__begin_), + __end_(__other.__end_) {} + + // Assign a bounded iterator to another one, rebinding the bounds of the iterator as well. + _LIBCPP_HIDE_FROM_ABI __bounded_iter& operator=(__bounded_iter const&) = default; + _LIBCPP_HIDE_FROM_ABI __bounded_iter& operator=(__bounded_iter&&) = default; + +private: + // Create an iterator wrapping the given iterator, and whose bounds are described + // by the provided [begin, end) range. + // + // This constructor does not check whether the resulting iterator is within its bounds. + // However, it does check that the provided [begin, end) range is a valid range (that + // is, begin <= end). + // + // Since it is non-standard for iterators to have this constructor, __bounded_iter must + // be created via `std::__make_bounded_iter`. + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 explicit __bounded_iter( + _Iterator __current, _Iterator __begin, _Iterator __end) + : __current_(__current), __begin_(__begin), __end_(__end) { + _LIBCPP_ASSERT(__begin <= __end, "__bounded_iter(current, begin, end): [begin, end) is not a valid range"); + } + + template + friend _LIBCPP_CONSTEXPR __bounded_iter<_It> __make_bounded_iter(_It, _It, _It); + +public: + // Dereference and indexing operations. + // + // These operations check that the iterator is dereferenceable, that is within [begin, end). + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 reference operator*() const _NOEXCEPT { + _LIBCPP_ASSERT( + __in_bounds(__current_), "__bounded_iter::operator*: Attempt to dereference an out-of-range iterator"); + return *__current_; + } + + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pointer operator->() const _NOEXCEPT { + _LIBCPP_ASSERT( + __in_bounds(__current_), "__bounded_iter::operator->: Attempt to dereference an out-of-range iterator"); + return std::__to_address(__current_); + } + + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 reference operator[](difference_type __n) const _NOEXCEPT { + _LIBCPP_ASSERT( + __in_bounds(__current_ + __n), "__bounded_iter::operator[]: Attempt to index an iterator out-of-range"); + return __current_[__n]; + } + + // Arithmetic operations. + // + // These operations do not check that the resulting iterator is within the bounds, since that + // would make it impossible to create a past-the-end iterator. + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 __bounded_iter& operator++() _NOEXCEPT { + ++__current_; + return *this; + } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 __bounded_iter operator++(int) _NOEXCEPT { + __bounded_iter __tmp(*this); + ++*this; + return __tmp; + } + + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 __bounded_iter& operator--() _NOEXCEPT { + --__current_; + return *this; + } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 __bounded_iter operator--(int) _NOEXCEPT { + __bounded_iter __tmp(*this); + --*this; + return __tmp; + } + + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 __bounded_iter& operator+=(difference_type __n) _NOEXCEPT { + __current_ += __n; + return *this; + } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 friend __bounded_iter + operator+(__bounded_iter const& __self, difference_type __n) _NOEXCEPT { + __bounded_iter __tmp(__self); + __tmp += __n; + return __tmp; + } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 friend __bounded_iter + operator+(difference_type __n, __bounded_iter const& __self) _NOEXCEPT { + __bounded_iter __tmp(__self); + __tmp += __n; + return __tmp; + } + + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 __bounded_iter& operator-=(difference_type __n) _NOEXCEPT { + __current_ -= __n; + return *this; + } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 friend __bounded_iter + operator-(__bounded_iter const& __self, difference_type __n) _NOEXCEPT { + __bounded_iter __tmp(__self); + __tmp -= __n; + return __tmp; + } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 friend difference_type + operator-(__bounded_iter const& __x, __bounded_iter const& __y) _NOEXCEPT { + return __x.__current_ - __y.__current_; + } + + // Comparison operations. + // + // These operations do not check whether the iterators are within their bounds. + // The valid range for each iterator is also not considered as part of the comparison, + // i.e. two iterators pointing to the same location will be considered equal even + // if they have different validity ranges. + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR friend bool + operator==(__bounded_iter const& __x, __bounded_iter const& __y) _NOEXCEPT { + return __x.__current_ == __y.__current_; + } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR friend bool + operator!=(__bounded_iter const& __x, __bounded_iter const& __y) _NOEXCEPT { + return __x.__current_ != __y.__current_; + } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR friend bool + operator<(__bounded_iter const& __x, __bounded_iter const& __y) _NOEXCEPT { + return __x.__current_ < __y.__current_; + } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR friend bool + operator>(__bounded_iter const& __x, __bounded_iter const& __y) _NOEXCEPT { + return __x.__current_ > __y.__current_; + } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR friend bool + operator<=(__bounded_iter const& __x, __bounded_iter const& __y) _NOEXCEPT { + return __x.__current_ <= __y.__current_; + } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR friend bool + operator>=(__bounded_iter const& __x, __bounded_iter const& __y) _NOEXCEPT { + return __x.__current_ >= __y.__current_; + } + +private: + // Return whether the given iterator is in the bounds of this __bounded_iter. + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR bool __in_bounds(_Iterator const& __iter) const { + return __iter >= __begin_ && __iter < __end_; + } + + template + friend struct pointer_traits; + _Iterator __current_; // current iterator + _Iterator __begin_, __end_; // valid range represented as [begin, end) +}; + +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR __bounded_iter<_It> __make_bounded_iter(_It __it, _It __begin, _It __end) { + return __bounded_iter<_It>(std::move(__it), std::move(__begin), std::move(__end)); +} + +#if _LIBCPP_STD_VER <= 17 +template +struct __is_cpp17_contiguous_iterator<__bounded_iter<_Iterator> > : true_type {}; +#endif + +template +struct pointer_traits<__bounded_iter<_Iterator> > { + using pointer = __bounded_iter<_Iterator>; + using element_type = typename pointer_traits<_Iterator>::element_type; + using difference_type = typename pointer_traits<_Iterator>::difference_type; + + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR static element_type* to_address(pointer __it) _NOEXCEPT { + return std::__to_address(__it.__current_); + } +}; + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ITERATOR_BOUNDED_ITER_H diff --git a/app/src/main/cpp/libcxx/include/__iterator/common_iterator.h b/app/src/main/cpp/libcxx/include/__iterator/common_iterator.h new file mode 100644 index 0000000..f7883e2 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__iterator/common_iterator.h @@ -0,0 +1,281 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ITERATOR_COMMON_ITERATOR_H +#define _LIBCPP___ITERATOR_COMMON_ITERATOR_H + +#include <__assert> +#include <__concepts/assignable.h> +#include <__concepts/constructible.h> +#include <__concepts/convertible_to.h> +#include <__concepts/copyable.h> +#include <__concepts/derived_from.h> +#include <__concepts/equality_comparable.h> +#include <__concepts/same_as.h> +#include <__config> +#include <__iterator/concepts.h> +#include <__iterator/incrementable_traits.h> +#include <__iterator/iter_move.h> +#include <__iterator/iter_swap.h> +#include <__iterator/iterator_traits.h> +#include <__iterator/readable_traits.h> +#include <__type_traits/is_pointer.h> +#include <__utility/declval.h> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 17 + +template +concept __can_use_postfix_proxy = + constructible_from, iter_reference_t<_Iter>> && + move_constructible>; + +template _Sent> + requires (!same_as<_Iter, _Sent> && copyable<_Iter>) +class common_iterator { + struct __proxy { + constexpr const iter_value_t<_Iter>* operator->() const noexcept { + return _VSTD::addressof(__value_); + } + iter_value_t<_Iter> __value_; + }; + + struct __postfix_proxy { + constexpr const iter_value_t<_Iter>& operator*() const noexcept { + return __value_; + } + iter_value_t<_Iter> __value_; + }; + +public: + variant<_Iter, _Sent> __hold_; + + common_iterator() requires default_initializable<_Iter> = default; + + constexpr common_iterator(_Iter __i) : __hold_(in_place_type<_Iter>, _VSTD::move(__i)) {} + constexpr common_iterator(_Sent __s) : __hold_(in_place_type<_Sent>, _VSTD::move(__s)) {} + + template + requires convertible_to && convertible_to + constexpr common_iterator(const common_iterator<_I2, _S2>& __other) + : __hold_([&]() -> variant<_Iter, _Sent> { + _LIBCPP_ASSERT(!__other.__hold_.valueless_by_exception(), "Attempted to construct from a valueless common_iterator"); + if (__other.__hold_.index() == 0) + return variant<_Iter, _Sent>{in_place_index<0>, _VSTD::__unchecked_get<0>(__other.__hold_)}; + return variant<_Iter, _Sent>{in_place_index<1>, _VSTD::__unchecked_get<1>(__other.__hold_)}; + }()) {} + + template + requires convertible_to && convertible_to && + assignable_from<_Iter&, const _I2&> && assignable_from<_Sent&, const _S2&> + common_iterator& operator=(const common_iterator<_I2, _S2>& __other) { + _LIBCPP_ASSERT(!__other.__hold_.valueless_by_exception(), "Attempted to assign from a valueless common_iterator"); + + auto __idx = __hold_.index(); + auto __other_idx = __other.__hold_.index(); + + // If they're the same index, just assign. + if (__idx == 0 && __other_idx == 0) + _VSTD::__unchecked_get<0>(__hold_) = _VSTD::__unchecked_get<0>(__other.__hold_); + else if (__idx == 1 && __other_idx == 1) + _VSTD::__unchecked_get<1>(__hold_) = _VSTD::__unchecked_get<1>(__other.__hold_); + + // Otherwise replace with the oposite element. + else if (__other_idx == 1) + __hold_.template emplace<1>(_VSTD::__unchecked_get<1>(__other.__hold_)); + else if (__other_idx == 0) + __hold_.template emplace<0>(_VSTD::__unchecked_get<0>(__other.__hold_)); + + return *this; + } + + constexpr decltype(auto) operator*() + { + _LIBCPP_ASSERT(std::holds_alternative<_Iter>(__hold_), "Attempted to dereference a non-dereferenceable common_iterator"); + return *_VSTD::__unchecked_get<_Iter>(__hold_); + } + + constexpr decltype(auto) operator*() const + requires __dereferenceable + { + _LIBCPP_ASSERT(std::holds_alternative<_Iter>(__hold_), "Attempted to dereference a non-dereferenceable common_iterator"); + return *_VSTD::__unchecked_get<_Iter>(__hold_); + } + + template + decltype(auto) operator->() const + requires indirectly_readable && + (requires(const _I2& __i) { __i.operator->(); } || + is_reference_v> || + constructible_from, iter_reference_t<_I2>>) + { + _LIBCPP_ASSERT(std::holds_alternative<_Iter>(__hold_), "Attempted to dereference a non-dereferenceable common_iterator"); + if constexpr (is_pointer_v<_Iter> || requires(const _Iter& __i) { __i.operator->(); }) { + return _VSTD::__unchecked_get<_Iter>(__hold_); + } else if constexpr (is_reference_v>) { + auto&& __tmp = *_VSTD::__unchecked_get<_Iter>(__hold_); + return _VSTD::addressof(__tmp); + } else { + return __proxy{*_VSTD::__unchecked_get<_Iter>(__hold_)}; + } + } + + common_iterator& operator++() { + _LIBCPP_ASSERT(std::holds_alternative<_Iter>(__hold_), "Attempted to increment a non-dereferenceable common_iterator"); + ++_VSTD::__unchecked_get<_Iter>(__hold_); return *this; + } + + decltype(auto) operator++(int) { + _LIBCPP_ASSERT(std::holds_alternative<_Iter>(__hold_), "Attempted to increment a non-dereferenceable common_iterator"); + if constexpr (forward_iterator<_Iter>) { + auto __tmp = *this; + ++*this; + return __tmp; + } else if constexpr (requires (_Iter& __i) { { *__i++ } -> __can_reference; } || + !__can_use_postfix_proxy<_Iter>) { + return _VSTD::__unchecked_get<_Iter>(__hold_)++; + } else { + auto __p = __postfix_proxy{**this}; + ++*this; + return __p; + } + } + + template _S2> + requires sentinel_for<_Sent, _I2> + _LIBCPP_HIDE_FROM_ABI + friend constexpr bool operator==(const common_iterator& __x, const common_iterator<_I2, _S2>& __y) { + _LIBCPP_ASSERT(!__x.__hold_.valueless_by_exception(), "Attempted to compare a valueless common_iterator"); + _LIBCPP_ASSERT(!__y.__hold_.valueless_by_exception(), "Attempted to compare a valueless common_iterator"); + + auto __x_index = __x.__hold_.index(); + auto __y_index = __y.__hold_.index(); + + if (__x_index == __y_index) + return true; + + if (__x_index == 0) + return _VSTD::__unchecked_get<_Iter>(__x.__hold_) == _VSTD::__unchecked_get<_S2>(__y.__hold_); + + return _VSTD::__unchecked_get<_Sent>(__x.__hold_) == _VSTD::__unchecked_get<_I2>(__y.__hold_); + } + + template _S2> + requires sentinel_for<_Sent, _I2> && equality_comparable_with<_Iter, _I2> + _LIBCPP_HIDE_FROM_ABI + friend constexpr bool operator==(const common_iterator& __x, const common_iterator<_I2, _S2>& __y) { + _LIBCPP_ASSERT(!__x.__hold_.valueless_by_exception(), "Attempted to compare a valueless common_iterator"); + _LIBCPP_ASSERT(!__y.__hold_.valueless_by_exception(), "Attempted to compare a valueless common_iterator"); + + auto __x_index = __x.__hold_.index(); + auto __y_index = __y.__hold_.index(); + + if (__x_index == 1 && __y_index == 1) + return true; + + if (__x_index == 0 && __y_index == 0) + return _VSTD::__unchecked_get<_Iter>(__x.__hold_) == _VSTD::__unchecked_get<_I2>(__y.__hold_); + + if (__x_index == 0) + return _VSTD::__unchecked_get<_Iter>(__x.__hold_) == _VSTD::__unchecked_get<_S2>(__y.__hold_); + + return _VSTD::__unchecked_get<_Sent>(__x.__hold_) == _VSTD::__unchecked_get<_I2>(__y.__hold_); + } + + template _I2, sized_sentinel_for<_Iter> _S2> + requires sized_sentinel_for<_Sent, _I2> + _LIBCPP_HIDE_FROM_ABI + friend constexpr iter_difference_t<_I2> operator-(const common_iterator& __x, const common_iterator<_I2, _S2>& __y) { + _LIBCPP_ASSERT(!__x.__hold_.valueless_by_exception(), "Attempted to subtract from a valueless common_iterator"); + _LIBCPP_ASSERT(!__y.__hold_.valueless_by_exception(), "Attempted to subtract a valueless common_iterator"); + + auto __x_index = __x.__hold_.index(); + auto __y_index = __y.__hold_.index(); + + if (__x_index == 1 && __y_index == 1) + return 0; + + if (__x_index == 0 && __y_index == 0) + return _VSTD::__unchecked_get<_Iter>(__x.__hold_) - _VSTD::__unchecked_get<_I2>(__y.__hold_); + + if (__x_index == 0) + return _VSTD::__unchecked_get<_Iter>(__x.__hold_) - _VSTD::__unchecked_get<_S2>(__y.__hold_); + + return _VSTD::__unchecked_get<_Sent>(__x.__hold_) - _VSTD::__unchecked_get<_I2>(__y.__hold_); + } + + _LIBCPP_HIDE_FROM_ABI friend constexpr iter_rvalue_reference_t<_Iter> iter_move(const common_iterator& __i) + noexcept(noexcept(ranges::iter_move(std::declval()))) + requires input_iterator<_Iter> + { + _LIBCPP_ASSERT(std::holds_alternative<_Iter>(__i.__hold_), "Attempted to iter_move a non-dereferenceable common_iterator"); + return ranges::iter_move( _VSTD::__unchecked_get<_Iter>(__i.__hold_)); + } + + template _I2, class _S2> + _LIBCPP_HIDE_FROM_ABI friend constexpr void iter_swap(const common_iterator& __x, const common_iterator<_I2, _S2>& __y) + noexcept(noexcept(ranges::iter_swap(std::declval(), std::declval()))) + { + _LIBCPP_ASSERT(std::holds_alternative<_Iter>(__x.__hold_), "Attempted to iter_swap a non-dereferenceable common_iterator"); + _LIBCPP_ASSERT(std::holds_alternative<_I2>(__y.__hold_), "Attempted to iter_swap a non-dereferenceable common_iterator"); + return ranges::iter_swap(_VSTD::__unchecked_get<_Iter>(__x.__hold_), _VSTD::__unchecked_get<_I2>(__y.__hold_)); + } +}; + +template +struct incrementable_traits> { + using difference_type = iter_difference_t<_Iter>; +}; + +template +concept __denotes_forward_iter = + requires { typename iterator_traits<_Iter>::iterator_category; } && + derived_from::iterator_category, forward_iterator_tag>; + +template +concept __common_iter_has_ptr_op = requires(const common_iterator<_Iter, _Sent>& __a) { + __a.operator->(); +}; + +template +struct __arrow_type_or_void { + using type = void; +}; + +template + requires __common_iter_has_ptr_op<_Iter, _Sent> +struct __arrow_type_or_void<_Iter, _Sent> { + using type = decltype(std::declval&>().operator->()); +}; + +template +struct iterator_traits> { + using iterator_concept = _If, + forward_iterator_tag, + input_iterator_tag>; + using iterator_category = _If<__denotes_forward_iter<_Iter>, + forward_iterator_tag, + input_iterator_tag>; + using pointer = typename __arrow_type_or_void<_Iter, _Sent>::type; + using value_type = iter_value_t<_Iter>; + using difference_type = iter_difference_t<_Iter>; + using reference = iter_reference_t<_Iter>; +}; + +#endif // _LIBCPP_STD_VER > 17 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ITERATOR_COMMON_ITERATOR_H diff --git a/app/src/main/cpp/libcxx/include/__iterator/concepts.h b/app/src/main/cpp/libcxx/include/__iterator/concepts.h new file mode 100644 index 0000000..d9d40a4 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__iterator/concepts.h @@ -0,0 +1,300 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ITERATOR_CONCEPTS_H +#define _LIBCPP___ITERATOR_CONCEPTS_H + +#include <__concepts/arithmetic.h> +#include <__concepts/assignable.h> +#include <__concepts/common_reference_with.h> +#include <__concepts/constructible.h> +#include <__concepts/copyable.h> +#include <__concepts/derived_from.h> +#include <__concepts/equality_comparable.h> +#include <__concepts/invocable.h> +#include <__concepts/movable.h> +#include <__concepts/predicate.h> +#include <__concepts/regular.h> +#include <__concepts/relation.h> +#include <__concepts/same_as.h> +#include <__concepts/semiregular.h> +#include <__concepts/totally_ordered.h> +#include <__config> +#include <__functional/invoke.h> +#include <__iterator/incrementable_traits.h> +#include <__iterator/iter_move.h> +#include <__iterator/iterator_traits.h> +#include <__iterator/readable_traits.h> +#include <__memory/pointer_traits.h> +#include <__type_traits/add_pointer.h> +#include <__type_traits/common_reference.h> +#include <__type_traits/is_pointer.h> +#include <__type_traits/is_reference.h> +#include <__type_traits/remove_cv.h> +#include <__type_traits/remove_cvref.h> +#include <__utility/forward.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 17 + +// [iterator.concept.readable] +template +concept __indirectly_readable_impl = + requires(const _In __i) { + typename iter_value_t<_In>; + typename iter_reference_t<_In>; + typename iter_rvalue_reference_t<_In>; + { *__i } -> same_as>; + { ranges::iter_move(__i) } -> same_as>; + } && + common_reference_with&&, iter_value_t<_In>&> && + common_reference_with&&, iter_rvalue_reference_t<_In>&&> && + common_reference_with&&, const iter_value_t<_In>&>; + +template +concept indirectly_readable = __indirectly_readable_impl>; + +template +using iter_common_reference_t = common_reference_t, iter_value_t<_Tp>&>; + +// [iterator.concept.writable] +template +concept indirectly_writable = + requires(_Out&& __o, _Tp&& __t) { + *__o = _VSTD::forward<_Tp>(__t); // not required to be equality-preserving + *_VSTD::forward<_Out>(__o) = _VSTD::forward<_Tp>(__t); // not required to be equality-preserving + const_cast&&>(*__o) = _VSTD::forward<_Tp>(__t); // not required to be equality-preserving + const_cast&&>(*_VSTD::forward<_Out>(__o)) = _VSTD::forward<_Tp>(__t); // not required to be equality-preserving + }; + +// [iterator.concept.winc] +template +concept __integer_like = integral<_Tp> && !same_as<_Tp, bool>; + +template +concept __signed_integer_like = signed_integral<_Tp>; + +template +concept weakly_incrementable = + // TODO: remove this once the clang bug is fixed (bugs.llvm.org/PR48173). + !same_as<_Ip, bool> && // Currently, clang does not handle bool correctly. + movable<_Ip> && + requires(_Ip __i) { + typename iter_difference_t<_Ip>; + requires __signed_integer_like>; + { ++__i } -> same_as<_Ip&>; // not required to be equality-preserving + __i++; // not required to be equality-preserving + }; + +// [iterator.concept.inc] +template +concept incrementable = + regular<_Ip> && + weakly_incrementable<_Ip> && + requires(_Ip __i) { + { __i++ } -> same_as<_Ip>; + }; + +// [iterator.concept.iterator] +template +concept input_or_output_iterator = + requires(_Ip __i) { + { *__i } -> __can_reference; + } && + weakly_incrementable<_Ip>; + +// [iterator.concept.sentinel] +template +concept sentinel_for = + semiregular<_Sp> && + input_or_output_iterator<_Ip> && + __weakly_equality_comparable_with<_Sp, _Ip>; + +template +inline constexpr bool disable_sized_sentinel_for = false; + +template +concept sized_sentinel_for = + sentinel_for<_Sp, _Ip> && + !disable_sized_sentinel_for, remove_cv_t<_Ip>> && + requires(const _Ip& __i, const _Sp& __s) { + { __s - __i } -> same_as>; + { __i - __s } -> same_as>; + }; + +// [iterator.concept.input] +template +concept input_iterator = + input_or_output_iterator<_Ip> && + indirectly_readable<_Ip> && + requires { typename _ITER_CONCEPT<_Ip>; } && + derived_from<_ITER_CONCEPT<_Ip>, input_iterator_tag>; + +// [iterator.concept.output] +template +concept output_iterator = + input_or_output_iterator<_Ip> && + indirectly_writable<_Ip, _Tp> && + requires (_Ip __it, _Tp&& __t) { + *__it++ = _VSTD::forward<_Tp>(__t); // not required to be equality-preserving + }; + +// [iterator.concept.forward] +template +concept forward_iterator = + input_iterator<_Ip> && + derived_from<_ITER_CONCEPT<_Ip>, forward_iterator_tag> && + incrementable<_Ip> && + sentinel_for<_Ip, _Ip>; + +// [iterator.concept.bidir] +template +concept bidirectional_iterator = + forward_iterator<_Ip> && + derived_from<_ITER_CONCEPT<_Ip>, bidirectional_iterator_tag> && + requires(_Ip __i) { + { --__i } -> same_as<_Ip&>; + { __i-- } -> same_as<_Ip>; + }; + +template +concept random_access_iterator = + bidirectional_iterator<_Ip> && + derived_from<_ITER_CONCEPT<_Ip>, random_access_iterator_tag> && + totally_ordered<_Ip> && + sized_sentinel_for<_Ip, _Ip> && + requires(_Ip __i, const _Ip __j, const iter_difference_t<_Ip> __n) { + { __i += __n } -> same_as<_Ip&>; + { __j + __n } -> same_as<_Ip>; + { __n + __j } -> same_as<_Ip>; + { __i -= __n } -> same_as<_Ip&>; + { __j - __n } -> same_as<_Ip>; + { __j[__n] } -> same_as>; + }; + +template +concept contiguous_iterator = + random_access_iterator<_Ip> && + derived_from<_ITER_CONCEPT<_Ip>, contiguous_iterator_tag> && + is_lvalue_reference_v> && + same_as, remove_cvref_t>> && + requires(const _Ip& __i) { + { _VSTD::to_address(__i) } -> same_as>>; + }; + +template +concept __has_arrow = input_iterator<_Ip> && (is_pointer_v<_Ip> || requires(_Ip __i) { __i.operator->(); }); + +// [indirectcallable.indirectinvocable] +template +concept indirectly_unary_invocable = + indirectly_readable<_It> && + copy_constructible<_Fp> && + invocable<_Fp&, iter_value_t<_It>&> && + invocable<_Fp&, iter_reference_t<_It>> && + invocable<_Fp&, iter_common_reference_t<_It>> && + common_reference_with< + invoke_result_t<_Fp&, iter_value_t<_It>&>, + invoke_result_t<_Fp&, iter_reference_t<_It>>>; + +template +concept indirectly_regular_unary_invocable = + indirectly_readable<_It> && + copy_constructible<_Fp> && + regular_invocable<_Fp&, iter_value_t<_It>&> && + regular_invocable<_Fp&, iter_reference_t<_It>> && + regular_invocable<_Fp&, iter_common_reference_t<_It>> && + common_reference_with< + invoke_result_t<_Fp&, iter_value_t<_It>&>, + invoke_result_t<_Fp&, iter_reference_t<_It>>>; + +template +concept indirect_unary_predicate = + indirectly_readable<_It> && + copy_constructible<_Fp> && + predicate<_Fp&, iter_value_t<_It>&> && + predicate<_Fp&, iter_reference_t<_It>> && + predicate<_Fp&, iter_common_reference_t<_It>>; + +template +concept indirect_binary_predicate = + indirectly_readable<_It1> && indirectly_readable<_It2> && + copy_constructible<_Fp> && + predicate<_Fp&, iter_value_t<_It1>&, iter_value_t<_It2>&> && + predicate<_Fp&, iter_value_t<_It1>&, iter_reference_t<_It2>> && + predicate<_Fp&, iter_reference_t<_It1>, iter_value_t<_It2>&> && + predicate<_Fp&, iter_reference_t<_It1>, iter_reference_t<_It2>> && + predicate<_Fp&, iter_common_reference_t<_It1>, iter_common_reference_t<_It2>>; + +template +concept indirect_equivalence_relation = + indirectly_readable<_It1> && indirectly_readable<_It2> && + copy_constructible<_Fp> && + equivalence_relation<_Fp&, iter_value_t<_It1>&, iter_value_t<_It2>&> && + equivalence_relation<_Fp&, iter_value_t<_It1>&, iter_reference_t<_It2>> && + equivalence_relation<_Fp&, iter_reference_t<_It1>, iter_value_t<_It2>&> && + equivalence_relation<_Fp&, iter_reference_t<_It1>, iter_reference_t<_It2>> && + equivalence_relation<_Fp&, iter_common_reference_t<_It1>, iter_common_reference_t<_It2>>; + +template +concept indirect_strict_weak_order = + indirectly_readable<_It1> && indirectly_readable<_It2> && + copy_constructible<_Fp> && + strict_weak_order<_Fp&, iter_value_t<_It1>&, iter_value_t<_It2>&> && + strict_weak_order<_Fp&, iter_value_t<_It1>&, iter_reference_t<_It2>> && + strict_weak_order<_Fp&, iter_reference_t<_It1>, iter_value_t<_It2>&> && + strict_weak_order<_Fp&, iter_reference_t<_It1>, iter_reference_t<_It2>> && + strict_weak_order<_Fp&, iter_common_reference_t<_It1>, iter_common_reference_t<_It2>>; + +template + requires (indirectly_readable<_Its> && ...) && invocable<_Fp, iter_reference_t<_Its>...> +using indirect_result_t = invoke_result_t<_Fp, iter_reference_t<_Its>...>; + +template +concept indirectly_movable = + indirectly_readable<_In> && + indirectly_writable<_Out, iter_rvalue_reference_t<_In>>; + +template +concept indirectly_movable_storable = + indirectly_movable<_In, _Out> && + indirectly_writable<_Out, iter_value_t<_In>> && + movable> && + constructible_from, iter_rvalue_reference_t<_In>> && + assignable_from&, iter_rvalue_reference_t<_In>>; + +template +concept indirectly_copyable = + indirectly_readable<_In> && + indirectly_writable<_Out, iter_reference_t<_In>>; + +template +concept indirectly_copyable_storable = + indirectly_copyable<_In, _Out> && + indirectly_writable<_Out, iter_value_t<_In>&> && + indirectly_writable<_Out, const iter_value_t<_In>&> && + indirectly_writable<_Out, iter_value_t<_In>&&> && + indirectly_writable<_Out, const iter_value_t<_In>&&> && + copyable> && + constructible_from, iter_reference_t<_In>> && + assignable_from&, iter_reference_t<_In>>; + +// Note: indirectly_swappable is located in iter_swap.h to prevent a dependency cycle +// (both iter_swap and indirectly_swappable require indirectly_readable). + +#endif // _LIBCPP_STD_VER > 17 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ITERATOR_CONCEPTS_H diff --git a/app/src/main/cpp/libcxx/include/__iterator/counted_iterator.h b/app/src/main/cpp/libcxx/include/__iterator/counted_iterator.h new file mode 100644 index 0000000..5fdbff4 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__iterator/counted_iterator.h @@ -0,0 +1,310 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ITERATOR_COUNTED_ITERATOR_H +#define _LIBCPP___ITERATOR_COUNTED_ITERATOR_H + +#include <__assert> +#include <__concepts/assignable.h> +#include <__concepts/common_with.h> +#include <__concepts/constructible.h> +#include <__concepts/convertible_to.h> +#include <__concepts/same_as.h> +#include <__config> +#include <__iterator/concepts.h> +#include <__iterator/default_sentinel.h> +#include <__iterator/incrementable_traits.h> +#include <__iterator/iter_move.h> +#include <__iterator/iter_swap.h> +#include <__iterator/iterator_traits.h> +#include <__iterator/readable_traits.h> +#include <__memory/pointer_traits.h> +#include <__type_traits/add_pointer.h> +#include <__type_traits/conditional.h> +#include <__utility/move.h> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 17 + +template +struct __counted_iterator_concept {}; + +template + requires requires { typename _Iter::iterator_concept; } +struct __counted_iterator_concept<_Iter> { + using iterator_concept = typename _Iter::iterator_concept; +}; + +template +struct __counted_iterator_category {}; + +template + requires requires { typename _Iter::iterator_category; } +struct __counted_iterator_category<_Iter> { + using iterator_category = typename _Iter::iterator_category; +}; + +template +struct __counted_iterator_value_type {}; + +template +struct __counted_iterator_value_type<_Iter> { + using value_type = iter_value_t<_Iter>; +}; + +template +class counted_iterator + : public __counted_iterator_concept<_Iter> + , public __counted_iterator_category<_Iter> + , public __counted_iterator_value_type<_Iter> +{ +public: + _LIBCPP_NO_UNIQUE_ADDRESS _Iter __current_ = _Iter(); + iter_difference_t<_Iter> __count_ = 0; + + using iterator_type = _Iter; + using difference_type = iter_difference_t<_Iter>; + + _LIBCPP_HIDE_FROM_ABI + constexpr counted_iterator() requires default_initializable<_Iter> = default; + + _LIBCPP_HIDE_FROM_ABI + constexpr counted_iterator(_Iter __iter, iter_difference_t<_Iter> __n) + : __current_(_VSTD::move(__iter)), __count_(__n) { + _LIBCPP_ASSERT(__n >= 0, "__n must not be negative."); + } + + template + requires convertible_to + _LIBCPP_HIDE_FROM_ABI + constexpr counted_iterator(const counted_iterator<_I2>& __other) + : __current_(__other.__current_), __count_(__other.__count_) {} + + template + requires assignable_from<_Iter&, const _I2&> + _LIBCPP_HIDE_FROM_ABI + constexpr counted_iterator& operator=(const counted_iterator<_I2>& __other) { + __current_ = __other.__current_; + __count_ = __other.__count_; + return *this; + } + + _LIBCPP_HIDE_FROM_ABI + constexpr const _Iter& base() const& noexcept { return __current_; } + + _LIBCPP_HIDE_FROM_ABI + constexpr _Iter base() && { return _VSTD::move(__current_); } + + _LIBCPP_HIDE_FROM_ABI + constexpr iter_difference_t<_Iter> count() const noexcept { return __count_; } + + _LIBCPP_HIDE_FROM_ABI + constexpr decltype(auto) operator*() { + _LIBCPP_ASSERT(__count_ > 0, "Iterator is equal to or past end."); + return *__current_; + } + + _LIBCPP_HIDE_FROM_ABI + constexpr decltype(auto) operator*() const + requires __dereferenceable + { + _LIBCPP_ASSERT(__count_ > 0, "Iterator is equal to or past end."); + return *__current_; + } + + _LIBCPP_HIDE_FROM_ABI + constexpr auto operator->() const noexcept + requires contiguous_iterator<_Iter> + { + return _VSTD::to_address(__current_); + } + + _LIBCPP_HIDE_FROM_ABI + constexpr counted_iterator& operator++() { + _LIBCPP_ASSERT(__count_ > 0, "Iterator already at or past end."); + ++__current_; + --__count_; + return *this; + } + + _LIBCPP_HIDE_FROM_ABI + decltype(auto) operator++(int) { + _LIBCPP_ASSERT(__count_ > 0, "Iterator already at or past end."); + --__count_; +#ifndef _LIBCPP_NO_EXCEPTIONS + try { return __current_++; } + catch(...) { ++__count_; throw; } +#else + return __current_++; +#endif // _LIBCPP_NO_EXCEPTIONS + } + + _LIBCPP_HIDE_FROM_ABI + constexpr counted_iterator operator++(int) + requires forward_iterator<_Iter> + { + _LIBCPP_ASSERT(__count_ > 0, "Iterator already at or past end."); + counted_iterator __tmp = *this; + ++*this; + return __tmp; + } + + _LIBCPP_HIDE_FROM_ABI + constexpr counted_iterator& operator--() + requires bidirectional_iterator<_Iter> + { + --__current_; + ++__count_; + return *this; + } + + _LIBCPP_HIDE_FROM_ABI + constexpr counted_iterator operator--(int) + requires bidirectional_iterator<_Iter> + { + counted_iterator __tmp = *this; + --*this; + return __tmp; + } + + _LIBCPP_HIDE_FROM_ABI + constexpr counted_iterator operator+(iter_difference_t<_Iter> __n) const + requires random_access_iterator<_Iter> + { + return counted_iterator(__current_ + __n, __count_ - __n); + } + + _LIBCPP_HIDE_FROM_ABI + friend constexpr counted_iterator operator+( + iter_difference_t<_Iter> __n, const counted_iterator& __x) + requires random_access_iterator<_Iter> + { + return __x + __n; + } + + _LIBCPP_HIDE_FROM_ABI + constexpr counted_iterator& operator+=(iter_difference_t<_Iter> __n) + requires random_access_iterator<_Iter> + { + _LIBCPP_ASSERT(__n <= __count_, "Cannot advance iterator past end."); + __current_ += __n; + __count_ -= __n; + return *this; + } + + _LIBCPP_HIDE_FROM_ABI + constexpr counted_iterator operator-(iter_difference_t<_Iter> __n) const + requires random_access_iterator<_Iter> + { + return counted_iterator(__current_ - __n, __count_ + __n); + } + + template _I2> + _LIBCPP_HIDE_FROM_ABI + friend constexpr iter_difference_t<_I2> operator-( + const counted_iterator& __lhs, const counted_iterator<_I2>& __rhs) + { + return __rhs.__count_ - __lhs.__count_; + } + + _LIBCPP_HIDE_FROM_ABI + friend constexpr iter_difference_t<_Iter> operator-( + const counted_iterator& __lhs, default_sentinel_t) + { + return -__lhs.__count_; + } + + _LIBCPP_HIDE_FROM_ABI + friend constexpr iter_difference_t<_Iter> operator-( + default_sentinel_t, const counted_iterator& __rhs) + { + return __rhs.__count_; + } + + _LIBCPP_HIDE_FROM_ABI + constexpr counted_iterator& operator-=(iter_difference_t<_Iter> __n) + requires random_access_iterator<_Iter> + { + _LIBCPP_ASSERT(-__n <= __count_, "Attempt to subtract too large of a size: " + "counted_iterator would be decremented before the " + "first element of its range."); + __current_ -= __n; + __count_ += __n; + return *this; + } + + _LIBCPP_HIDE_FROM_ABI + constexpr decltype(auto) operator[](iter_difference_t<_Iter> __n) const + requires random_access_iterator<_Iter> + { + _LIBCPP_ASSERT(__n < __count_, "Subscript argument must be less than size."); + return __current_[__n]; + } + + template _I2> + _LIBCPP_HIDE_FROM_ABI + friend constexpr bool operator==( + const counted_iterator& __lhs, const counted_iterator<_I2>& __rhs) + { + return __lhs.__count_ == __rhs.__count_; + } + + _LIBCPP_HIDE_FROM_ABI + friend constexpr bool operator==( + const counted_iterator& __lhs, default_sentinel_t) + { + return __lhs.__count_ == 0; + } + + template _I2> + _LIBCPP_HIDE_FROM_ABI friend constexpr strong_ordering operator<=>( + const counted_iterator& __lhs, const counted_iterator<_I2>& __rhs) + { + return __rhs.__count_ <=> __lhs.__count_; + } + + _LIBCPP_HIDE_FROM_ABI + friend constexpr iter_rvalue_reference_t<_Iter> iter_move(const counted_iterator& __i) + noexcept(noexcept(ranges::iter_move(__i.__current_))) + requires input_iterator<_Iter> + { + _LIBCPP_ASSERT(__i.__count_ > 0, "Iterator must not be past end of range."); + return ranges::iter_move(__i.__current_); + } + + template _I2> + _LIBCPP_HIDE_FROM_ABI + friend constexpr void iter_swap(const counted_iterator& __x, const counted_iterator<_I2>& __y) + noexcept(noexcept(ranges::iter_swap(__x.__current_, __y.__current_))) + { + _LIBCPP_ASSERT(__x.__count_ > 0 && __y.__count_ > 0, + "Iterators must not be past end of range."); + return ranges::iter_swap(__x.__current_, __y.__current_); + } +}; +_LIBCPP_CTAD_SUPPORTED_FOR_TYPE(counted_iterator); + +template + requires same_as<_ITER_TRAITS<_Iter>, iterator_traits<_Iter>> +struct iterator_traits> : iterator_traits<_Iter> { + using pointer = conditional_t, + add_pointer_t>, void>; +}; + +#endif // _LIBCPP_STD_VER > 17 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ITERATOR_COUNTED_ITERATOR_H diff --git a/app/src/main/cpp/libcxx/include/__iterator/data.h b/app/src/main/cpp/libcxx/include/__iterator/data.h new file mode 100644 index 0000000..88eb752 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__iterator/data.h @@ -0,0 +1,51 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ITERATOR_DATA_H +#define _LIBCPP___ITERATOR_DATA_H + +#include <__config> +#include +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 14 + +template constexpr +_LIBCPP_INLINE_VISIBILITY +auto data(_Cont& __c) +_NOEXCEPT_(noexcept(__c.data())) +-> decltype (__c.data()) +{ return __c.data(); } + +template constexpr +_LIBCPP_INLINE_VISIBILITY +auto data(const _Cont& __c) +_NOEXCEPT_(noexcept(__c.data())) +-> decltype (__c.data()) +{ return __c.data(); } + +template +_LIBCPP_INLINE_VISIBILITY +constexpr _Tp* data(_Tp (&__array)[_Sz]) noexcept { return __array; } + +template +_LIBCPP_INLINE_VISIBILITY +constexpr const _Ep* data(initializer_list<_Ep> __il) noexcept { return __il.begin(); } + +#endif + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ITERATOR_DATA_H diff --git a/app/src/main/cpp/libcxx/include/__iterator/default_sentinel.h b/app/src/main/cpp/libcxx/include/__iterator/default_sentinel.h new file mode 100644 index 0000000..669032a --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__iterator/default_sentinel.h @@ -0,0 +1,30 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ITERATOR_DEFAULT_SENTINEL_H +#define _LIBCPP___ITERATOR_DEFAULT_SENTINEL_H + +#include <__config> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 17 + +struct default_sentinel_t { }; +inline constexpr default_sentinel_t default_sentinel{}; + +#endif // _LIBCPP_STD_VER > 17 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ITERATOR_DEFAULT_SENTINEL_H diff --git a/app/src/main/cpp/libcxx/include/__iterator/distance.h b/app/src/main/cpp/libcxx/include/__iterator/distance.h new file mode 100644 index 0000000..681e20d --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__iterator/distance.h @@ -0,0 +1,108 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ITERATOR_DISTANCE_H +#define _LIBCPP___ITERATOR_DISTANCE_H + +#include <__config> +#include <__iterator/concepts.h> +#include <__iterator/incrementable_traits.h> +#include <__iterator/iterator_traits.h> +#include <__ranges/access.h> +#include <__ranges/concepts.h> +#include <__ranges/size.h> +#include <__type_traits/decay.h> +#include <__type_traits/remove_cvref.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +template +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX17 +typename iterator_traits<_InputIter>::difference_type +__distance(_InputIter __first, _InputIter __last, input_iterator_tag) +{ + typename iterator_traits<_InputIter>::difference_type __r(0); + for (; __first != __last; ++__first) + ++__r; + return __r; +} + +template +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX17 +typename iterator_traits<_RandIter>::difference_type +__distance(_RandIter __first, _RandIter __last, random_access_iterator_tag) +{ + return __last - __first; +} + +template +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX17 +typename iterator_traits<_InputIter>::difference_type +distance(_InputIter __first, _InputIter __last) +{ + return _VSTD::__distance(__first, __last, typename iterator_traits<_InputIter>::iterator_category()); +} + +#if _LIBCPP_STD_VER > 17 + +// [range.iter.op.distance] + +namespace ranges { +namespace __distance { + +struct __fn { + template _Sp> + requires (!sized_sentinel_for<_Sp, _Ip>) + _LIBCPP_HIDE_FROM_ABI + constexpr iter_difference_t<_Ip> operator()(_Ip __first, _Sp __last) const { + iter_difference_t<_Ip> __n = 0; + while (__first != __last) { + ++__first; + ++__n; + } + return __n; + } + + template> _Sp> + _LIBCPP_HIDE_FROM_ABI + constexpr iter_difference_t<_Ip> operator()(_Ip&& __first, _Sp __last) const { + if constexpr (sized_sentinel_for<_Sp, __remove_cvref_t<_Ip>>) { + return __last - __first; + } else { + return __last - decay_t<_Ip>(__first); + } + } + + template + _LIBCPP_HIDE_FROM_ABI + constexpr range_difference_t<_Rp> operator()(_Rp&& __r) const { + if constexpr (sized_range<_Rp>) { + return static_cast>(ranges::size(__r)); + } else { + return operator()(ranges::begin(__r), ranges::end(__r)); + } + } +}; + +} // namespace __distance + +inline namespace __cpo { + inline constexpr auto distance = __distance::__fn{}; +} // namespace __cpo +} // namespace ranges + +#endif // _LIBCPP_STD_VER > 17 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ITERATOR_DISTANCE_H diff --git a/app/src/main/cpp/libcxx/include/__iterator/empty.h b/app/src/main/cpp/libcxx/include/__iterator/empty.h new file mode 100644 index 0000000..748ca9e --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__iterator/empty.h @@ -0,0 +1,44 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ITERATOR_EMPTY_H +#define _LIBCPP___ITERATOR_EMPTY_H + +#include <__config> +#include +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 14 + +template +_LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY +constexpr auto empty(const _Cont& __c) +_NOEXCEPT_(noexcept(__c.empty())) +-> decltype (__c.empty()) +{ return __c.empty(); } + +template +_LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY +constexpr bool empty(const _Tp (&)[_Sz]) noexcept { return false; } + +template +_LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY +constexpr bool empty(initializer_list<_Ep> __il) noexcept { return __il.size() == 0; } + +#endif // _LIBCPP_STD_VER > 14 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ITERATOR_EMPTY_H diff --git a/app/src/main/cpp/libcxx/include/__iterator/erase_if_container.h b/app/src/main/cpp/libcxx/include/__iterator/erase_if_container.h new file mode 100644 index 0000000..d7c71a9 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__iterator/erase_if_container.h @@ -0,0 +1,40 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ITERATOR_ERASE_IF_CONTAINER_H +#define _LIBCPP___ITERATOR_ERASE_IF_CONTAINER_H + +#include <__config> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +template +_LIBCPP_HIDE_FROM_ABI +typename _Container::size_type +__libcpp_erase_if_container(_Container& __c, _Predicate& __pred) { + typename _Container::size_type __old_size = __c.size(); + + const typename _Container::iterator __last = __c.end(); + for (typename _Container::iterator __iter = __c.begin(); __iter != __last;) { + if (__pred(*__iter)) + __iter = __c.erase(__iter); + else + ++__iter; + } + + return __old_size - __c.size(); +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ITERATOR_ERASE_IF_CONTAINER_H diff --git a/app/src/main/cpp/libcxx/include/__iterator/front_insert_iterator.h b/app/src/main/cpp/libcxx/include/__iterator/front_insert_iterator.h new file mode 100644 index 0000000..e278359 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__iterator/front_insert_iterator.h @@ -0,0 +1,71 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ITERATOR_FRONT_INSERT_ITERATOR_H +#define _LIBCPP___ITERATOR_FRONT_INSERT_ITERATOR_H + +#include <__config> +#include <__iterator/iterator.h> +#include <__iterator/iterator_traits.h> +#include <__memory/addressof.h> +#include <__utility/move.h> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +_LIBCPP_SUPPRESS_DEPRECATED_PUSH +template +class _LIBCPP_TEMPLATE_VIS front_insert_iterator +#if _LIBCPP_STD_VER <= 14 || !defined(_LIBCPP_ABI_NO_ITERATOR_BASES) + : public iterator +#endif +{ +_LIBCPP_SUPPRESS_DEPRECATED_POP +protected: + _Container* container; +public: + typedef output_iterator_tag iterator_category; + typedef void value_type; +#if _LIBCPP_STD_VER > 17 + typedef ptrdiff_t difference_type; +#else + typedef void difference_type; +#endif + typedef void pointer; + typedef void reference; + typedef _Container container_type; + + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 explicit front_insert_iterator(_Container& __x) : container(_VSTD::addressof(__x)) {} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 front_insert_iterator& operator=(const typename _Container::value_type& __value) + {container->push_front(__value); return *this;} +#ifndef _LIBCPP_CXX03_LANG + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 front_insert_iterator& operator=(typename _Container::value_type&& __value) + {container->push_front(_VSTD::move(__value)); return *this;} +#endif // _LIBCPP_CXX03_LANG + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 front_insert_iterator& operator*() {return *this;} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 front_insert_iterator& operator++() {return *this;} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 front_insert_iterator operator++(int) {return *this;} +}; +_LIBCPP_CTAD_SUPPORTED_FOR_TYPE(front_insert_iterator); + +template +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 +front_insert_iterator<_Container> +front_inserter(_Container& __x) +{ + return front_insert_iterator<_Container>(__x); +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ITERATOR_FRONT_INSERT_ITERATOR_H diff --git a/app/src/main/cpp/libcxx/include/__iterator/incrementable_traits.h b/app/src/main/cpp/libcxx/include/__iterator/incrementable_traits.h new file mode 100644 index 0000000..3d06dc0 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__iterator/incrementable_traits.h @@ -0,0 +1,78 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ITERATOR_INCREMENTABLE_TRAITS_H +#define _LIBCPP___ITERATOR_INCREMENTABLE_TRAITS_H + +#include <__concepts/arithmetic.h> +#include <__config> +#include <__type_traits/conditional.h> +#include <__type_traits/is_object.h> +#include <__type_traits/is_primary_template.h> +#include <__type_traits/make_signed.h> +#include <__type_traits/remove_cvref.h> +#include <__utility/declval.h> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 17 + +// [incrementable.traits] +template struct incrementable_traits {}; + +template +requires is_object_v<_Tp> +struct incrementable_traits<_Tp*> { + using difference_type = ptrdiff_t; +}; + +template +struct incrementable_traits : incrementable_traits<_Ip> {}; + +template +concept __has_member_difference_type = requires { typename _Tp::difference_type; }; + +template<__has_member_difference_type _Tp> +struct incrementable_traits<_Tp> { + using difference_type = typename _Tp::difference_type; +}; + +template +concept __has_integral_minus = + requires(const _Tp& __x, const _Tp& __y) { + { __x - __y } -> integral; + }; + +template<__has_integral_minus _Tp> +requires (!__has_member_difference_type<_Tp>) +struct incrementable_traits<_Tp> { + using difference_type = make_signed_t() - std::declval<_Tp>())>; +}; + +template +struct iterator_traits; + +// Let `RI` be `remove_cvref_t`. The type `iter_difference_t` denotes +// `incrementable_traits::difference_type` if `iterator_traits` names a specialization +// generated from the primary template, and `iterator_traits::difference_type` otherwise. +template +using iter_difference_t = typename conditional_t<__is_primary_template > >::value, + incrementable_traits >, + iterator_traits > >::difference_type; + +#endif // _LIBCPP_STD_VER > 17 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ITERATOR_INCREMENTABLE_TRAITS_H diff --git a/app/src/main/cpp/libcxx/include/__iterator/indirectly_comparable.h b/app/src/main/cpp/libcxx/include/__iterator/indirectly_comparable.h new file mode 100644 index 0000000..868190f --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__iterator/indirectly_comparable.h @@ -0,0 +1,34 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ITERATOR_INDIRECTLY_COMPARABLE_H +#define _LIBCPP___ITERATOR_INDIRECTLY_COMPARABLE_H + +#include <__config> +#include <__functional/identity.h> +#include <__iterator/concepts.h> +#include <__iterator/projected.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 17 + +template +concept indirectly_comparable = + indirect_binary_predicate<_Rp, projected<_I1, _P1>, projected<_I2, _P2>>; + +#endif // _LIBCPP_STD_VER > 17 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ITERATOR_INDIRECTLY_COMPARABLE_H diff --git a/app/src/main/cpp/libcxx/include/__iterator/insert_iterator.h b/app/src/main/cpp/libcxx/include/__iterator/insert_iterator.h new file mode 100644 index 0000000..ecaea61 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__iterator/insert_iterator.h @@ -0,0 +1,81 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ITERATOR_INSERT_ITERATOR_H +#define _LIBCPP___ITERATOR_INSERT_ITERATOR_H + +#include <__config> +#include <__iterator/iterator.h> +#include <__iterator/iterator_traits.h> +#include <__memory/addressof.h> +#include <__ranges/access.h> +#include <__utility/move.h> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 17 +template +using __insert_iterator_iter_t = ranges::iterator_t<_Container>; +#else +template +using __insert_iterator_iter_t = typename _Container::iterator; +#endif + +_LIBCPP_SUPPRESS_DEPRECATED_PUSH +template +class _LIBCPP_TEMPLATE_VIS insert_iterator +#if _LIBCPP_STD_VER <= 14 || !defined(_LIBCPP_ABI_NO_ITERATOR_BASES) + : public iterator +#endif +{ +_LIBCPP_SUPPRESS_DEPRECATED_POP +protected: + _Container* container; + __insert_iterator_iter_t<_Container> iter; +public: + typedef output_iterator_tag iterator_category; + typedef void value_type; +#if _LIBCPP_STD_VER > 17 + typedef ptrdiff_t difference_type; +#else + typedef void difference_type; +#endif + typedef void pointer; + typedef void reference; + typedef _Container container_type; + + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 insert_iterator(_Container& __x, __insert_iterator_iter_t<_Container> __i) + : container(_VSTD::addressof(__x)), iter(__i) {} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 insert_iterator& operator=(const typename _Container::value_type& __value) + {iter = container->insert(iter, __value); ++iter; return *this;} +#ifndef _LIBCPP_CXX03_LANG + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 insert_iterator& operator=(typename _Container::value_type&& __value) + {iter = container->insert(iter, _VSTD::move(__value)); ++iter; return *this;} +#endif // _LIBCPP_CXX03_LANG + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 insert_iterator& operator*() {return *this;} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 insert_iterator& operator++() {return *this;} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 insert_iterator& operator++(int) {return *this;} +}; + +template +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 +insert_iterator<_Container> +inserter(_Container& __x, __insert_iterator_iter_t<_Container> __i) +{ + return insert_iterator<_Container>(__x, __i); +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ITERATOR_INSERT_ITERATOR_H diff --git a/app/src/main/cpp/libcxx/include/__iterator/istream_iterator.h b/app/src/main/cpp/libcxx/include/__iterator/istream_iterator.h new file mode 100644 index 0000000..a056961 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__iterator/istream_iterator.h @@ -0,0 +1,105 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ITERATOR_ISTREAM_ITERATOR_H +#define _LIBCPP___ITERATOR_ISTREAM_ITERATOR_H + +#include <__config> +#include <__iterator/default_sentinel.h> +#include <__iterator/iterator.h> +#include <__iterator/iterator_traits.h> +#include <__memory/addressof.h> +#include +#include // for forward declarations of char_traits and basic_istream + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +_LIBCPP_SUPPRESS_DEPRECATED_PUSH +template , class _Distance = ptrdiff_t> +class _LIBCPP_TEMPLATE_VIS istream_iterator +#if _LIBCPP_STD_VER <= 14 || !defined(_LIBCPP_ABI_NO_ITERATOR_BASES) + : public iterator +#endif +{ +_LIBCPP_SUPPRESS_DEPRECATED_POP +public: + typedef input_iterator_tag iterator_category; + typedef _Tp value_type; + typedef _Distance difference_type; + typedef const _Tp* pointer; + typedef const _Tp& reference; + typedef _CharT char_type; + typedef _Traits traits_type; + typedef basic_istream<_CharT,_Traits> istream_type; +private: + istream_type* __in_stream_; + _Tp __value_; +public: + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR istream_iterator() : __in_stream_(nullptr), __value_() {} +#if _LIBCPP_STD_VER > 17 + _LIBCPP_HIDE_FROM_ABI constexpr istream_iterator(default_sentinel_t) : istream_iterator() {} +#endif // _LIBCPP_STD_VER > 17 + _LIBCPP_INLINE_VISIBILITY istream_iterator(istream_type& __s) : __in_stream_(_VSTD::addressof(__s)) + { + if (!(*__in_stream_ >> __value_)) + __in_stream_ = nullptr; + } + + _LIBCPP_INLINE_VISIBILITY const _Tp& operator*() const {return __value_;} + _LIBCPP_INLINE_VISIBILITY const _Tp* operator->() const {return _VSTD::addressof((operator*()));} + _LIBCPP_INLINE_VISIBILITY istream_iterator& operator++() + { + if (!(*__in_stream_ >> __value_)) + __in_stream_ = nullptr; + return *this; + } + _LIBCPP_INLINE_VISIBILITY istream_iterator operator++(int) + {istream_iterator __t(*this); ++(*this); return __t;} + + template + friend _LIBCPP_INLINE_VISIBILITY + bool + operator==(const istream_iterator<_Up, _CharU, _TraitsU, _DistanceU>& __x, + const istream_iterator<_Up, _CharU, _TraitsU, _DistanceU>& __y); + +#if _LIBCPP_STD_VER > 17 + friend _LIBCPP_HIDE_FROM_ABI bool operator==(const istream_iterator& __i, default_sentinel_t) { + return __i.__in_stream_ == nullptr; + } +#endif // _LIBCPP_STD_VER > 17 +}; + +template +inline _LIBCPP_INLINE_VISIBILITY +bool +operator==(const istream_iterator<_Tp, _CharT, _Traits, _Distance>& __x, + const istream_iterator<_Tp, _CharT, _Traits, _Distance>& __y) +{ + return __x.__in_stream_ == __y.__in_stream_; +} + +#if _LIBCPP_STD_VER <= 17 +template +inline _LIBCPP_INLINE_VISIBILITY +bool +operator!=(const istream_iterator<_Tp, _CharT, _Traits, _Distance>& __x, + const istream_iterator<_Tp, _CharT, _Traits, _Distance>& __y) +{ + return !(__x == __y); +} +#endif // _LIBCPP_STD_VER <= 17 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ITERATOR_ISTREAM_ITERATOR_H diff --git a/app/src/main/cpp/libcxx/include/__iterator/istreambuf_iterator.h b/app/src/main/cpp/libcxx/include/__iterator/istreambuf_iterator.h new file mode 100644 index 0000000..bc53a6a --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__iterator/istreambuf_iterator.h @@ -0,0 +1,119 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ITERATOR_ISTREAMBUF_ITERATOR_H +#define _LIBCPP___ITERATOR_ISTREAMBUF_ITERATOR_H + +#include <__config> +#include <__iterator/default_sentinel.h> +#include <__iterator/iterator.h> +#include <__iterator/iterator_traits.h> +#include // for forward declaration of basic_streambuf + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +_LIBCPP_SUPPRESS_DEPRECATED_PUSH +template +class _LIBCPP_TEMPLATE_VIS istreambuf_iterator +#if _LIBCPP_STD_VER <= 14 || !defined(_LIBCPP_ABI_NO_ITERATOR_BASES) + : public iterator +#endif +{ +_LIBCPP_SUPPRESS_DEPRECATED_POP +public: + typedef input_iterator_tag iterator_category; + typedef _CharT value_type; + typedef typename _Traits::off_type difference_type; + typedef _CharT* pointer; + typedef _CharT reference; + typedef _CharT char_type; + typedef _Traits traits_type; + typedef typename _Traits::int_type int_type; + typedef basic_streambuf<_CharT,_Traits> streambuf_type; + typedef basic_istream<_CharT,_Traits> istream_type; +private: + mutable streambuf_type* __sbuf_; + + class __proxy + { + char_type __keep_; + streambuf_type* __sbuf_; + _LIBCPP_INLINE_VISIBILITY + explicit __proxy(char_type __c, streambuf_type* __s) + : __keep_(__c), __sbuf_(__s) {} + friend class istreambuf_iterator; + public: + _LIBCPP_INLINE_VISIBILITY char_type operator*() const {return __keep_;} + }; + + _LIBCPP_INLINE_VISIBILITY + bool __test_for_eof() const + { + if (__sbuf_ && traits_type::eq_int_type(__sbuf_->sgetc(), traits_type::eof())) + __sbuf_ = nullptr; + return __sbuf_ == nullptr; + } +public: + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR istreambuf_iterator() _NOEXCEPT : __sbuf_(nullptr) {} +#if _LIBCPP_STD_VER > 17 + _LIBCPP_INLINE_VISIBILITY constexpr istreambuf_iterator(default_sentinel_t) noexcept + : istreambuf_iterator() {} +#endif // _LIBCPP_STD_VER > 17 + _LIBCPP_INLINE_VISIBILITY istreambuf_iterator(istream_type& __s) _NOEXCEPT + : __sbuf_(__s.rdbuf()) {} + _LIBCPP_INLINE_VISIBILITY istreambuf_iterator(streambuf_type* __s) _NOEXCEPT + : __sbuf_(__s) {} + _LIBCPP_INLINE_VISIBILITY istreambuf_iterator(const __proxy& __p) _NOEXCEPT + : __sbuf_(__p.__sbuf_) {} + + _LIBCPP_INLINE_VISIBILITY char_type operator*() const + {return static_cast(__sbuf_->sgetc());} + _LIBCPP_INLINE_VISIBILITY istreambuf_iterator& operator++() + { + __sbuf_->sbumpc(); + return *this; + } + _LIBCPP_INLINE_VISIBILITY __proxy operator++(int) + { + return __proxy(__sbuf_->sbumpc(), __sbuf_); + } + + _LIBCPP_INLINE_VISIBILITY bool equal(const istreambuf_iterator& __b) const + {return __test_for_eof() == __b.__test_for_eof();} + +#if _LIBCPP_STD_VER > 17 + friend _LIBCPP_HIDE_FROM_ABI bool operator==(const istreambuf_iterator& __i, default_sentinel_t) { + return __i.__test_for_eof(); + } +#endif // _LIBCPP_STD_VER > 17 +}; + +template +inline _LIBCPP_INLINE_VISIBILITY +bool operator==(const istreambuf_iterator<_CharT,_Traits>& __a, + const istreambuf_iterator<_CharT,_Traits>& __b) + {return __a.equal(__b);} + +#if _LIBCPP_STD_VER <= 17 +template +inline _LIBCPP_INLINE_VISIBILITY +bool operator!=(const istreambuf_iterator<_CharT,_Traits>& __a, + const istreambuf_iterator<_CharT,_Traits>& __b) + {return !__a.equal(__b);} +#endif // _LIBCPP_STD_VER <= 17 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ITERATOR_ISTREAMBUF_ITERATOR_H diff --git a/app/src/main/cpp/libcxx/include/__iterator/iter_move.h b/app/src/main/cpp/libcxx/include/__iterator/iter_move.h new file mode 100644 index 0000000..a7d9413 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__iterator/iter_move.h @@ -0,0 +1,104 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ITERATOR_ITER_MOVE_H +#define _LIBCPP___ITERATOR_ITER_MOVE_H + +#include <__concepts/class_or_enum.h> +#include <__config> +#include <__iterator/iterator_traits.h> +#include <__type_traits/is_reference.h> +#include <__type_traits/remove_cvref.h> +#include <__utility/declval.h> +#include <__utility/forward.h> +#include <__utility/move.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 17 + +// [iterator.cust.move] + +namespace ranges { +namespace __iter_move { + +void iter_move(); + +template +concept __unqualified_iter_move = + __class_or_enum> && + requires (_Tp&& __t) { + // NOLINTNEXTLINE(libcpp-robust-against-adl) iter_swap ADL calls should only be made through ranges::iter_swap + iter_move(std::forward<_Tp>(__t)); + }; + +template +concept __move_deref = + !__unqualified_iter_move<_Tp> && + requires (_Tp&& __t) { + *__t; + requires is_lvalue_reference_v; + }; + +template +concept __just_deref = + !__unqualified_iter_move<_Tp> && + !__move_deref<_Tp> && + requires (_Tp&& __t) { + *__t; + requires (!is_lvalue_reference_v); + }; + +// [iterator.cust.move] + +struct __fn { + // NOLINTBEGIN(libcpp-robust-against-adl) iter_move ADL calls should only be made through ranges::iter_move + template + requires __unqualified_iter_move<_Ip> + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr decltype(auto) operator()(_Ip&& __i) const + noexcept(noexcept(iter_move(std::forward<_Ip>(__i)))) + { + return iter_move(std::forward<_Ip>(__i)); + } + // NOLINTEND(libcpp-robust-against-adl) + + template + requires __move_deref<_Ip> + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Ip&& __i) const + noexcept(noexcept(std::move(*std::forward<_Ip>(__i)))) + -> decltype( std::move(*std::forward<_Ip>(__i))) + { return std::move(*std::forward<_Ip>(__i)); } + + template + requires __just_deref<_Ip> + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Ip&& __i) const + noexcept(noexcept(*std::forward<_Ip>(__i))) + -> decltype( *std::forward<_Ip>(__i)) + { return *std::forward<_Ip>(__i); } +}; +} // namespace __iter_move + +inline namespace __cpo { + inline constexpr auto iter_move = __iter_move::__fn{}; +} // namespace __cpo +} // namespace ranges + +template<__dereferenceable _Tp> + requires requires(_Tp& __t) { { ranges::iter_move(__t) } -> __can_reference; } +using iter_rvalue_reference_t = decltype(ranges::iter_move(std::declval<_Tp&>())); + +#endif // _LIBCPP_STD_VER > 17 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ITERATOR_ITER_MOVE_H diff --git a/app/src/main/cpp/libcxx/include/__iterator/iter_swap.h b/app/src/main/cpp/libcxx/include/__iterator/iter_swap.h new file mode 100644 index 0000000..d4c0dca --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__iterator/iter_swap.h @@ -0,0 +1,113 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ITERATOR_ITER_SWAP_H +#define _LIBCPP___ITERATOR_ITER_SWAP_H + +#include <__concepts/class_or_enum.h> +#include <__concepts/swappable.h> +#include <__config> +#include <__iterator/concepts.h> +#include <__iterator/iter_move.h> +#include <__iterator/iterator_traits.h> +#include <__iterator/readable_traits.h> +#include <__type_traits/remove_cvref.h> +#include <__utility/declval.h> +#include <__utility/forward.h> +#include <__utility/move.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 17 + +// [iter.cust.swap] + +namespace ranges { +namespace __iter_swap { + template + void iter_swap(_I1, _I2) = delete; + + template + concept __unqualified_iter_swap = + (__class_or_enum> || __class_or_enum>) && + requires (_T1&& __x, _T2&& __y) { + // NOLINTNEXTLINE(libcpp-robust-against-adl) iter_swap ADL calls should only be made through ranges::iter_swap + iter_swap(_VSTD::forward<_T1>(__x), _VSTD::forward<_T2>(__y)); + }; + + template + concept __readable_swappable = + indirectly_readable<_T1> && indirectly_readable<_T2> && + swappable_with, iter_reference_t<_T2>>; + + + struct __fn { + // NOLINTBEGIN(libcpp-robust-against-adl) iter_swap ADL calls should only be made through ranges::iter_swap + template + requires __unqualified_iter_swap<_T1, _T2> + _LIBCPP_HIDE_FROM_ABI + constexpr void operator()(_T1&& __x, _T2&& __y) const + noexcept(noexcept(iter_swap(_VSTD::forward<_T1>(__x), _VSTD::forward<_T2>(__y)))) + { + (void)iter_swap(_VSTD::forward<_T1>(__x), _VSTD::forward<_T2>(__y)); + } + // NOLINTEND(libcpp-robust-against-adl) + + template + requires (!__unqualified_iter_swap<_T1, _T2>) && + __readable_swappable<_T1, _T2> + _LIBCPP_HIDE_FROM_ABI + constexpr void operator()(_T1&& __x, _T2&& __y) const + noexcept(noexcept(ranges::swap(*_VSTD::forward<_T1>(__x), *_VSTD::forward<_T2>(__y)))) + { + ranges::swap(*_VSTD::forward<_T1>(__x), *_VSTD::forward<_T2>(__y)); + } + + template + requires (!__unqualified_iter_swap<_T1, _T2> && + !__readable_swappable<_T1, _T2>) && + indirectly_movable_storable<_T1, _T2> && + indirectly_movable_storable<_T2, _T1> + _LIBCPP_HIDE_FROM_ABI + constexpr void operator()(_T1&& __x, _T2&& __y) const + noexcept(noexcept(iter_value_t<_T2>(ranges::iter_move(__y))) && + noexcept(*__y = ranges::iter_move(__x)) && + noexcept(*_VSTD::forward<_T1>(__x) = std::declval>())) + { + iter_value_t<_T2> __old(ranges::iter_move(__y)); + *__y = ranges::iter_move(__x); + *_VSTD::forward<_T1>(__x) = _VSTD::move(__old); + } + }; +} // namespace __iter_swap + +inline namespace __cpo { + inline constexpr auto iter_swap = __iter_swap::__fn{}; +} // namespace __cpo +} // namespace ranges + +template +concept indirectly_swappable = + indirectly_readable<_I1> && indirectly_readable<_I2> && + requires(const _I1 __i1, const _I2 __i2) { + ranges::iter_swap(__i1, __i1); + ranges::iter_swap(__i2, __i2); + ranges::iter_swap(__i1, __i2); + ranges::iter_swap(__i2, __i1); + }; + +#endif // _LIBCPP_STD_VER > 17 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ITERATOR_ITER_SWAP_H diff --git a/app/src/main/cpp/libcxx/include/__iterator/iterator.h b/app/src/main/cpp/libcxx/include/__iterator/iterator.h new file mode 100644 index 0000000..b417eea --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__iterator/iterator.h @@ -0,0 +1,35 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ITERATOR_ITERATOR_H +#define _LIBCPP___ITERATOR_ITERATOR_H + +#include <__config> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +template +struct _LIBCPP_TEMPLATE_VIS _LIBCPP_DEPRECATED_IN_CXX17 iterator +{ + typedef _Tp value_type; + typedef _Distance difference_type; + typedef _Pointer pointer; + typedef _Reference reference; + typedef _Category iterator_category; +}; + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ITERATOR_ITERATOR_H diff --git a/app/src/main/cpp/libcxx/include/__iterator/iterator_traits.h b/app/src/main/cpp/libcxx/include/__iterator/iterator_traits.h new file mode 100644 index 0000000..c9d8944 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__iterator/iterator_traits.h @@ -0,0 +1,539 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ITERATOR_ITERATOR_TRAITS_H +#define _LIBCPP___ITERATOR_ITERATOR_TRAITS_H + +#include <__concepts/arithmetic.h> +#include <__concepts/constructible.h> +#include <__concepts/convertible_to.h> +#include <__concepts/copyable.h> +#include <__concepts/equality_comparable.h> +#include <__concepts/same_as.h> +#include <__concepts/totally_ordered.h> +#include <__config> +#include <__fwd/pair.h> +#include <__iterator/incrementable_traits.h> +#include <__iterator/readable_traits.h> +#include <__type_traits/add_const.h> +#include <__type_traits/common_reference.h> +#include <__type_traits/conditional.h> +#include <__type_traits/disjunction.h> +#include <__type_traits/is_convertible.h> +#include <__type_traits/is_object.h> +#include <__type_traits/is_primary_template.h> +#include <__type_traits/is_reference.h> +#include <__type_traits/is_valid_expansion.h> +#include <__type_traits/remove_const.h> +#include <__type_traits/remove_cv.h> +#include <__type_traits/remove_cvref.h> +#include <__type_traits/void_t.h> +#include <__utility/declval.h> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 17 + +template +using __with_reference = _Tp&; + +template +concept __can_reference = requires { + typename __with_reference<_Tp>; +}; + +template +concept __dereferenceable = requires(_Tp& __t) { + { *__t } -> __can_reference; // not required to be equality-preserving +}; + +// [iterator.traits] +template<__dereferenceable _Tp> +using iter_reference_t = decltype(*std::declval<_Tp&>()); + +#endif // _LIBCPP_STD_VER > 17 + +template +struct _LIBCPP_TEMPLATE_VIS iterator_traits; + +struct _LIBCPP_TEMPLATE_VIS input_iterator_tag {}; +struct _LIBCPP_TEMPLATE_VIS output_iterator_tag {}; +struct _LIBCPP_TEMPLATE_VIS forward_iterator_tag : public input_iterator_tag {}; +struct _LIBCPP_TEMPLATE_VIS bidirectional_iterator_tag : public forward_iterator_tag {}; +struct _LIBCPP_TEMPLATE_VIS random_access_iterator_tag : public bidirectional_iterator_tag {}; +#if _LIBCPP_STD_VER > 17 +struct _LIBCPP_TEMPLATE_VIS contiguous_iterator_tag : public random_access_iterator_tag {}; +#endif + +template +struct __iter_traits_cache { + using type = _If< + __is_primary_template >::value, + _Iter, + iterator_traits<_Iter> + >; +}; +template +using _ITER_TRAITS = typename __iter_traits_cache<_Iter>::type; + +struct __iter_concept_concept_test { + template + using _Apply = typename _ITER_TRAITS<_Iter>::iterator_concept; +}; +struct __iter_concept_category_test { + template + using _Apply = typename _ITER_TRAITS<_Iter>::iterator_category; +}; +struct __iter_concept_random_fallback { + template + using _Apply = __enable_if_t< + __is_primary_template >::value, + random_access_iterator_tag + >; +}; + +template struct __test_iter_concept + : _IsValidExpansion<_Tester::template _Apply, _Iter>, + _Tester +{ +}; + +template +struct __iter_concept_cache { + using type = _Or< + __test_iter_concept<_Iter, __iter_concept_concept_test>, + __test_iter_concept<_Iter, __iter_concept_category_test>, + __test_iter_concept<_Iter, __iter_concept_random_fallback> + >; +}; + +template +using _ITER_CONCEPT = typename __iter_concept_cache<_Iter>::type::template _Apply<_Iter>; + + +template +struct __has_iterator_typedefs +{ +private: + template static false_type __test(...); + template static true_type __test(__void_t* = nullptr, + __void_t* = nullptr, + __void_t* = nullptr, + __void_t* = nullptr, + __void_t* = nullptr); +public: + static const bool value = decltype(__test<_Tp>(0,0,0,0,0))::value; +}; + + +template +struct __has_iterator_category +{ +private: + template static false_type __test(...); + template static true_type __test(typename _Up::iterator_category* = nullptr); +public: + static const bool value = decltype(__test<_Tp>(nullptr))::value; +}; + +template +struct __has_iterator_concept +{ +private: + template static false_type __test(...); + template static true_type __test(typename _Up::iterator_concept* = nullptr); +public: + static const bool value = decltype(__test<_Tp>(nullptr))::value; +}; + +#if _LIBCPP_STD_VER > 17 + +// The `cpp17-*-iterator` exposition-only concepts have very similar names to the `Cpp17*Iterator` named requirements +// from `[iterator.cpp17]`. To avoid confusion between the two, the exposition-only concepts have been banished to +// a "detail" namespace indicating they have a niche use-case. +namespace __iterator_traits_detail { +template +concept __cpp17_iterator = + requires(_Ip __i) { + { *__i } -> __can_reference; + { ++__i } -> same_as<_Ip&>; + { *__i++ } -> __can_reference; + } && + copyable<_Ip>; + +template +concept __cpp17_input_iterator = + __cpp17_iterator<_Ip> && + equality_comparable<_Ip> && + requires(_Ip __i) { + typename incrementable_traits<_Ip>::difference_type; + typename indirectly_readable_traits<_Ip>::value_type; + typename common_reference_t&&, + typename indirectly_readable_traits<_Ip>::value_type&>; + typename common_reference_t::value_type&>; + requires signed_integral::difference_type>; + }; + +template +concept __cpp17_forward_iterator = + __cpp17_input_iterator<_Ip> && + constructible_from<_Ip> && + is_lvalue_reference_v> && + same_as>, + typename indirectly_readable_traits<_Ip>::value_type> && + requires(_Ip __i) { + { __i++ } -> convertible_to<_Ip const&>; + { *__i++ } -> same_as>; + }; + +template +concept __cpp17_bidirectional_iterator = + __cpp17_forward_iterator<_Ip> && + requires(_Ip __i) { + { --__i } -> same_as<_Ip&>; + { __i-- } -> convertible_to<_Ip const&>; + { *__i-- } -> same_as>; + }; + +template +concept __cpp17_random_access_iterator = + __cpp17_bidirectional_iterator<_Ip> && + totally_ordered<_Ip> && + requires(_Ip __i, typename incrementable_traits<_Ip>::difference_type __n) { + { __i += __n } -> same_as<_Ip&>; + { __i -= __n } -> same_as<_Ip&>; + { __i + __n } -> same_as<_Ip>; + { __n + __i } -> same_as<_Ip>; + { __i - __n } -> same_as<_Ip>; + { __i - __i } -> same_as; // NOLINT(misc-redundant-expression) ; This is llvm.org/PR54114 + { __i[__n] } -> convertible_to>; + }; +} // namespace __iterator_traits_detail + +template +concept __has_member_reference = requires { typename _Ip::reference; }; + +template +concept __has_member_pointer = requires { typename _Ip::pointer; }; + +template +concept __has_member_iterator_category = requires { typename _Ip::iterator_category; }; + +template +concept __specifies_members = requires { + typename _Ip::value_type; + typename _Ip::difference_type; + requires __has_member_reference<_Ip>; + requires __has_member_iterator_category<_Ip>; + }; + +template +struct __iterator_traits_member_pointer_or_void { + using type = void; +}; + +template<__has_member_pointer _Tp> +struct __iterator_traits_member_pointer_or_void<_Tp> { + using type = typename _Tp::pointer; +}; + +template +concept __cpp17_iterator_missing_members = + !__specifies_members<_Tp> && + __iterator_traits_detail::__cpp17_iterator<_Tp>; + +template +concept __cpp17_input_iterator_missing_members = + __cpp17_iterator_missing_members<_Tp> && + __iterator_traits_detail::__cpp17_input_iterator<_Tp>; + +// Otherwise, `pointer` names `void`. +template +struct __iterator_traits_member_pointer_or_arrow_or_void { using type = void; }; + +// [iterator.traits]/3.2.1 +// If the qualified-id `I::pointer` is valid and denotes a type, `pointer` names that type. +template<__has_member_pointer _Ip> +struct __iterator_traits_member_pointer_or_arrow_or_void<_Ip> { using type = typename _Ip::pointer; }; + +// Otherwise, if `decltype(declval().operator->())` is well-formed, then `pointer` names that +// type. +template + requires requires(_Ip& __i) { __i.operator->(); } && (!__has_member_pointer<_Ip>) +struct __iterator_traits_member_pointer_or_arrow_or_void<_Ip> { + using type = decltype(std::declval<_Ip&>().operator->()); +}; + +// Otherwise, `reference` names `iter-reference-t`. +template +struct __iterator_traits_member_reference { using type = iter_reference_t<_Ip>; }; + +// [iterator.traits]/3.2.2 +// If the qualified-id `I::reference` is valid and denotes a type, `reference` names that type. +template<__has_member_reference _Ip> +struct __iterator_traits_member_reference<_Ip> { using type = typename _Ip::reference; }; + +// [iterator.traits]/3.2.3.4 +// input_iterator_tag +template +struct __deduce_iterator_category { + using type = input_iterator_tag; +}; + +// [iterator.traits]/3.2.3.1 +// `random_access_iterator_tag` if `I` satisfies `cpp17-random-access-iterator`, or otherwise +template<__iterator_traits_detail::__cpp17_random_access_iterator _Ip> +struct __deduce_iterator_category<_Ip> { + using type = random_access_iterator_tag; +}; + +// [iterator.traits]/3.2.3.2 +// `bidirectional_iterator_tag` if `I` satisfies `cpp17-bidirectional-iterator`, or otherwise +template<__iterator_traits_detail::__cpp17_bidirectional_iterator _Ip> +struct __deduce_iterator_category<_Ip> { + using type = bidirectional_iterator_tag; +}; + +// [iterator.traits]/3.2.3.3 +// `forward_iterator_tag` if `I` satisfies `cpp17-forward-iterator`, or otherwise +template<__iterator_traits_detail::__cpp17_forward_iterator _Ip> +struct __deduce_iterator_category<_Ip> { + using type = forward_iterator_tag; +}; + +template +struct __iterator_traits_iterator_category : __deduce_iterator_category<_Ip> {}; + +// [iterator.traits]/3.2.3 +// If the qualified-id `I::iterator-category` is valid and denotes a type, `iterator-category` names +// that type. +template<__has_member_iterator_category _Ip> +struct __iterator_traits_iterator_category<_Ip> { + using type = typename _Ip::iterator_category; +}; + +// otherwise, it names void. +template +struct __iterator_traits_difference_type { using type = void; }; + +// If the qualified-id `incrementable_traits::difference_type` is valid and denotes a type, then +// `difference_type` names that type; +template +requires requires { typename incrementable_traits<_Ip>::difference_type; } +struct __iterator_traits_difference_type<_Ip> { + using type = typename incrementable_traits<_Ip>::difference_type; +}; + +// [iterator.traits]/3.4 +// Otherwise, `iterator_traits` has no members by any of the above names. +template +struct __iterator_traits {}; + +// [iterator.traits]/3.1 +// If `I` has valid ([temp.deduct]) member types `difference-type`, `value-type`, `reference`, and +// `iterator-category`, then `iterator-traits` has the following publicly accessible members: +template<__specifies_members _Ip> +struct __iterator_traits<_Ip> { + using iterator_category = typename _Ip::iterator_category; + using value_type = typename _Ip::value_type; + using difference_type = typename _Ip::difference_type; + using pointer = typename __iterator_traits_member_pointer_or_void<_Ip>::type; + using reference = typename _Ip::reference; +}; + +// [iterator.traits]/3.2 +// Otherwise, if `I` satisfies the exposition-only concept `cpp17-input-iterator`, +// `iterator-traits` has the following publicly accessible members: +template<__cpp17_input_iterator_missing_members _Ip> +struct __iterator_traits<_Ip> { + using iterator_category = typename __iterator_traits_iterator_category<_Ip>::type; + using value_type = typename indirectly_readable_traits<_Ip>::value_type; + using difference_type = typename incrementable_traits<_Ip>::difference_type; + using pointer = typename __iterator_traits_member_pointer_or_arrow_or_void<_Ip>::type; + using reference = typename __iterator_traits_member_reference<_Ip>::type; +}; + +// Otherwise, if `I` satisfies the exposition-only concept `cpp17-iterator`, then +// `iterator_traits` has the following publicly accessible members: +template<__cpp17_iterator_missing_members _Ip> +struct __iterator_traits<_Ip> { + using iterator_category = output_iterator_tag; + using value_type = void; + using difference_type = typename __iterator_traits_difference_type<_Ip>::type; + using pointer = void; + using reference = void; +}; + +template +struct iterator_traits : __iterator_traits<_Ip> { + using __primary_template = iterator_traits; +}; + +#else // _LIBCPP_STD_VER > 17 + +template struct __iterator_traits {}; + +template struct __iterator_traits_impl {}; + +template +struct __iterator_traits_impl<_Iter, true> +{ + typedef typename _Iter::difference_type difference_type; + typedef typename _Iter::value_type value_type; + typedef typename _Iter::pointer pointer; + typedef typename _Iter::reference reference; + typedef typename _Iter::iterator_category iterator_category; +}; + +template +struct __iterator_traits<_Iter, true> + : __iterator_traits_impl + < + _Iter, + is_convertible::value || + is_convertible::value + > +{}; + +// iterator_traits will only have the nested types if Iterator::iterator_category +// exists. Else iterator_traits will be an empty class. This is a +// conforming extension which allows some programs to compile and behave as +// the client expects instead of failing at compile time. + +template +struct _LIBCPP_TEMPLATE_VIS iterator_traits + : __iterator_traits<_Iter, __has_iterator_typedefs<_Iter>::value> { + + using __primary_template = iterator_traits; +}; +#endif // _LIBCPP_STD_VER > 17 + +template +#if _LIBCPP_STD_VER > 17 +requires is_object_v<_Tp> +#endif +struct _LIBCPP_TEMPLATE_VIS iterator_traits<_Tp*> +{ + typedef ptrdiff_t difference_type; + typedef __remove_cv_t<_Tp> value_type; + typedef _Tp* pointer; + typedef _Tp& reference; + typedef random_access_iterator_tag iterator_category; +#if _LIBCPP_STD_VER > 17 + typedef contiguous_iterator_tag iterator_concept; +#endif +}; + +template >::value> +struct __has_iterator_category_convertible_to + : is_convertible::iterator_category, _Up> +{}; + +template +struct __has_iterator_category_convertible_to<_Tp, _Up, false> : false_type {}; + +template ::value> +struct __has_iterator_concept_convertible_to + : is_convertible +{}; + +template +struct __has_iterator_concept_convertible_to<_Tp, _Up, false> : false_type {}; + +template +struct __is_cpp17_input_iterator : public __has_iterator_category_convertible_to<_Tp, input_iterator_tag> {}; + +template +struct __is_cpp17_forward_iterator : public __has_iterator_category_convertible_to<_Tp, forward_iterator_tag> {}; + +template +struct __is_cpp17_bidirectional_iterator : public __has_iterator_category_convertible_to<_Tp, bidirectional_iterator_tag> {}; + +template +struct __is_cpp17_random_access_iterator : public __has_iterator_category_convertible_to<_Tp, random_access_iterator_tag> {}; + +// __is_cpp17_contiguous_iterator determines if an iterator is known by +// libc++ to be contiguous, either because it advertises itself as such +// (in C++20) or because it is a pointer type or a known trivial wrapper +// around a (possibly fancy) pointer type, such as __wrap_iter. +// Such iterators receive special "contiguous" optimizations in +// std::copy and std::sort. +// +#if _LIBCPP_STD_VER > 17 +template +struct __is_cpp17_contiguous_iterator : _Or< + __has_iterator_category_convertible_to<_Tp, contiguous_iterator_tag>, + __has_iterator_concept_convertible_to<_Tp, contiguous_iterator_tag> +> {}; +#else +template +struct __is_cpp17_contiguous_iterator : false_type {}; +#endif + +// Any native pointer which is an iterator is also a contiguous iterator. +template +struct __is_cpp17_contiguous_iterator<_Up*> : true_type {}; + + +template +class __wrap_iter; + +template +struct __is_exactly_cpp17_input_iterator + : public integral_constant::value && + !__has_iterator_category_convertible_to<_Tp, forward_iterator_tag>::value> {}; + +template +struct __is_exactly_cpp17_forward_iterator + : public integral_constant::value && + !__has_iterator_category_convertible_to<_Tp, bidirectional_iterator_tag>::value> {}; + +template +struct __is_exactly_cpp17_bidirectional_iterator + : public integral_constant::value && + !__has_iterator_category_convertible_to<_Tp, random_access_iterator_tag>::value> {}; + +template +using __iter_value_type = typename iterator_traits<_InputIterator>::value_type; + +template +using __iter_key_type = __remove_const_t::value_type::first_type>; + +template +using __iter_mapped_type = typename iterator_traits<_InputIterator>::value_type::second_type; + +template +using __iter_to_alloc_type = pair< + typename add_const::value_type::first_type>::type, + typename iterator_traits<_InputIterator>::value_type::second_type>; + +template +using __iterator_category_type = typename iterator_traits<_Iter>::iterator_category; + +template +using __iterator_pointer_type = typename iterator_traits<_Iter>::pointer; + +template +using __iter_diff_t = typename iterator_traits<_Iter>::difference_type; + +template +using __iter_value_type = typename iterator_traits<_InputIterator>::value_type; + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ITERATOR_ITERATOR_TRAITS_H diff --git a/app/src/main/cpp/libcxx/include/__iterator/iterator_with_data.h b/app/src/main/cpp/libcxx/include/__iterator/iterator_with_data.h new file mode 100644 index 0000000..06c2fa6 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__iterator/iterator_with_data.h @@ -0,0 +1,100 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ITERATOR_ITERATOR_WITH_DATA_H +#define _LIBCPP___ITERATOR_ITERATOR_WITH_DATA_H + +#include <__compare/compare_three_way_result.h> +#include <__compare/three_way_comparable.h> +#include <__config> +#include <__iterator/concepts.h> +#include <__iterator/incrementable_traits.h> +#include <__iterator/iter_move.h> +#include <__iterator/iter_swap.h> +#include <__iterator/iterator_traits.h> +#include <__iterator/readable_traits.h> +#include <__utility/move.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if _LIBCPP_STD_VER >= 20 + +_LIBCPP_BEGIN_NAMESPACE_STD + +template +class __iterator_with_data { + _Iterator __iter_{}; + _Data __data_{}; + +public: + using value_type = iter_value_t<_Iterator>; + using difference_type = iter_difference_t<_Iterator>; + + _LIBCPP_HIDE_FROM_ABI __iterator_with_data() = default; + + constexpr _LIBCPP_HIDE_FROM_ABI __iterator_with_data(_Iterator __iter, _Data __data) + : __iter_(std::move(__iter)), __data_(std::move(__data)) {} + + constexpr _LIBCPP_HIDE_FROM_ABI _Iterator __get_iter() const { return __iter_; } + + constexpr _LIBCPP_HIDE_FROM_ABI _Data __get_data() && { return std::move(__data_); } + + friend constexpr _LIBCPP_HIDE_FROM_ABI bool + operator==(const __iterator_with_data& __lhs, const __iterator_with_data& __rhs) { + return __lhs.__iter_ == __rhs.__iter_; + } + + constexpr _LIBCPP_HIDE_FROM_ABI __iterator_with_data& operator++() { + ++__iter_; + return *this; + } + + constexpr _LIBCPP_HIDE_FROM_ABI __iterator_with_data operator++(int) { + auto __tmp = *this; + __iter_++; + return __tmp; + } + + constexpr _LIBCPP_HIDE_FROM_ABI __iterator_with_data& operator--() + requires bidirectional_iterator<_Iterator> + { + --__iter_; + return *this; + } + + constexpr _LIBCPP_HIDE_FROM_ABI __iterator_with_data operator--(int) + requires bidirectional_iterator<_Iterator> + { + auto __tmp = *this; + --__iter_; + return __tmp; + } + + constexpr _LIBCPP_HIDE_FROM_ABI iter_reference_t<_Iterator> operator*() const { return *__iter_; } + + _LIBCPP_HIDE_FROM_ABI friend constexpr iter_rvalue_reference_t<_Iterator> + iter_move(const __iterator_with_data& __iter) noexcept(noexcept(ranges::iter_move(__iter.__iter_))) { + return ranges::iter_move(__iter.__iter_); + } + + _LIBCPP_HIDE_FROM_ABI friend constexpr void + iter_swap(const __iterator_with_data& __lhs, + const __iterator_with_data& __rhs) noexcept(noexcept(ranges::iter_swap(__lhs.__iter_, __rhs.__iter_))) + requires indirectly_swappable<_Iterator> + { + return ranges::iter_swap(__lhs.__data_, __rhs.__iter_); + } +}; + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER >= 20 + +#endif // _LIBCPP___ITERATOR_ITERATOR_WITH_DATA_H diff --git a/app/src/main/cpp/libcxx/include/__iterator/mergeable.h b/app/src/main/cpp/libcxx/include/__iterator/mergeable.h new file mode 100644 index 0000000..b9f2d08 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__iterator/mergeable.h @@ -0,0 +1,41 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ITERATOR_MERGEABLE_H +#define _LIBCPP___ITERATOR_MERGEABLE_H + +#include <__config> +#include <__functional/identity.h> +#include <__functional/ranges_operations.h> +#include <__iterator/concepts.h> +#include <__iterator/projected.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 17 + +template +concept mergeable = + input_iterator<_Input1> && + input_iterator<_Input2> && + weakly_incrementable<_Output> && + indirectly_copyable<_Input1, _Output> && + indirectly_copyable<_Input2, _Output> && + indirect_strict_weak_order<_Comp, projected<_Input1, _Proj1>, projected<_Input2, _Proj2>>; + +#endif // _LIBCPP_STD_VER > 17 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ITERATOR_MERGEABLE_H diff --git a/app/src/main/cpp/libcxx/include/__iterator/move_iterator.h b/app/src/main/cpp/libcxx/include/__iterator/move_iterator.h new file mode 100644 index 0000000..fa806db --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__iterator/move_iterator.h @@ -0,0 +1,335 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ITERATOR_MOVE_ITERATOR_H +#define _LIBCPP___ITERATOR_MOVE_ITERATOR_H + +#include <__compare/compare_three_way_result.h> +#include <__compare/three_way_comparable.h> +#include <__concepts/assignable.h> +#include <__concepts/convertible_to.h> +#include <__concepts/derived_from.h> +#include <__concepts/same_as.h> +#include <__config> +#include <__iterator/concepts.h> +#include <__iterator/incrementable_traits.h> +#include <__iterator/iter_move.h> +#include <__iterator/iter_swap.h> +#include <__iterator/iterator_traits.h> +#include <__iterator/move_sentinel.h> +#include <__iterator/readable_traits.h> +#include <__type_traits/conditional.h> +#include <__type_traits/enable_if.h> +#include <__type_traits/is_assignable.h> +#include <__type_traits/is_constructible.h> +#include <__type_traits/is_convertible.h> +#include <__type_traits/is_reference.h> +#include <__type_traits/is_same.h> +#include <__type_traits/remove_reference.h> +#include <__utility/declval.h> +#include <__utility/move.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 17 +template +struct __move_iter_category_base {}; + +template + requires requires { typename iterator_traits<_Iter>::iterator_category; } +struct __move_iter_category_base<_Iter> { + using iterator_category = _If< + derived_from::iterator_category, random_access_iterator_tag>, + random_access_iterator_tag, + typename iterator_traits<_Iter>::iterator_category + >; +}; + +template +concept __move_iter_comparable = requires { + { std::declval() == std::declval<_Sent>() } -> convertible_to; +}; +#endif // _LIBCPP_STD_VER > 17 + +template +class _LIBCPP_TEMPLATE_VIS move_iterator +#if _LIBCPP_STD_VER > 17 + : public __move_iter_category_base<_Iter> +#endif +{ +public: +#if _LIBCPP_STD_VER > 17 + using iterator_type = _Iter; + using iterator_concept = input_iterator_tag; + // iterator_category is inherited and not always present + using value_type = iter_value_t<_Iter>; + using difference_type = iter_difference_t<_Iter>; + using pointer = _Iter; + using reference = iter_rvalue_reference_t<_Iter>; +#else + typedef _Iter iterator_type; + typedef _If< + __is_cpp17_random_access_iterator<_Iter>::value, + random_access_iterator_tag, + typename iterator_traits<_Iter>::iterator_category + > iterator_category; + typedef typename iterator_traits::value_type value_type; + typedef typename iterator_traits::difference_type difference_type; + typedef iterator_type pointer; + + typedef typename iterator_traits::reference __reference; + typedef typename conditional< + is_reference<__reference>::value, + __libcpp_remove_reference_t<__reference>&&, + __reference + >::type reference; +#endif // _LIBCPP_STD_VER > 17 + + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 + explicit move_iterator(_Iter __i) : __current_(std::move(__i)) {} + + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 + move_iterator& operator++() { ++__current_; return *this; } + + _LIBCPP_DEPRECATED_IN_CXX20 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 + pointer operator->() const { return __current_; } + +#if _LIBCPP_STD_VER > 17 + _LIBCPP_HIDE_FROM_ABI constexpr + move_iterator() requires is_constructible_v<_Iter> : __current_() {} + + template + requires (!_IsSame<_Up, _Iter>::value) && convertible_to + _LIBCPP_HIDE_FROM_ABI constexpr + move_iterator(const move_iterator<_Up>& __u) : __current_(__u.base()) {} + + template + requires (!_IsSame<_Up, _Iter>::value) && + convertible_to && + assignable_from<_Iter&, const _Up&> + _LIBCPP_HIDE_FROM_ABI constexpr + move_iterator& operator=(const move_iterator<_Up>& __u) { + __current_ = __u.base(); + return *this; + } + + _LIBCPP_HIDE_FROM_ABI constexpr const _Iter& base() const & noexcept { return __current_; } + _LIBCPP_HIDE_FROM_ABI constexpr _Iter base() && { return std::move(__current_); } + + _LIBCPP_HIDE_FROM_ABI constexpr + reference operator*() const { return ranges::iter_move(__current_); } + _LIBCPP_HIDE_FROM_ABI constexpr + reference operator[](difference_type __n) const { return ranges::iter_move(__current_ + __n); } + + _LIBCPP_HIDE_FROM_ABI constexpr + auto operator++(int) + requires forward_iterator<_Iter> + { + move_iterator __tmp(*this); ++__current_; return __tmp; + } + + _LIBCPP_HIDE_FROM_ABI constexpr + void operator++(int) { ++__current_; } +#else + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 + move_iterator() : __current_() {} + + template ::value && is_convertible::value + > > + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 + move_iterator(const move_iterator<_Up>& __u) : __current_(__u.base()) {} + + template ::value && + is_convertible::value && + is_assignable<_Iter&, const _Up&>::value + > > + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 + move_iterator& operator=(const move_iterator<_Up>& __u) { + __current_ = __u.base(); + return *this; + } + + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 + _Iter base() const { return __current_; } + + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 + reference operator*() const { return static_cast(*__current_); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 + reference operator[](difference_type __n) const { return static_cast(__current_[__n]); } + + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 + move_iterator operator++(int) { move_iterator __tmp(*this); ++__current_; return __tmp; } +#endif // _LIBCPP_STD_VER > 17 + + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 + move_iterator& operator--() { --__current_; return *this; } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 + move_iterator operator--(int) { move_iterator __tmp(*this); --__current_; return __tmp; } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 + move_iterator operator+(difference_type __n) const { return move_iterator(__current_ + __n); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 + move_iterator& operator+=(difference_type __n) { __current_ += __n; return *this; } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 + move_iterator operator-(difference_type __n) const { return move_iterator(__current_ - __n); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 + move_iterator& operator-=(difference_type __n) { __current_ -= __n; return *this; } + +#if _LIBCPP_STD_VER > 17 + template _Sent> + friend _LIBCPP_HIDE_FROM_ABI constexpr + bool operator==(const move_iterator& __x, const move_sentinel<_Sent>& __y) + requires __move_iter_comparable<_Iter, _Sent> + { + return __x.base() == __y.base(); + } + + template _Sent> + friend _LIBCPP_HIDE_FROM_ABI constexpr + iter_difference_t<_Iter> operator-(const move_sentinel<_Sent>& __x, const move_iterator& __y) + { + return __x.base() - __y.base(); + } + + template _Sent> + friend _LIBCPP_HIDE_FROM_ABI constexpr + iter_difference_t<_Iter> operator-(const move_iterator& __x, const move_sentinel<_Sent>& __y) + { + return __x.base() - __y.base(); + } + + friend _LIBCPP_HIDE_FROM_ABI constexpr + iter_rvalue_reference_t<_Iter> iter_move(const move_iterator& __i) + noexcept(noexcept(ranges::iter_move(__i.__current_))) + { + return ranges::iter_move(__i.__current_); + } + + template _It2> + friend _LIBCPP_HIDE_FROM_ABI constexpr + void iter_swap(const move_iterator& __x, const move_iterator<_It2>& __y) + noexcept(noexcept(ranges::iter_swap(__x.__current_, __y.__current_))) + { + return ranges::iter_swap(__x.__current_, __y.__current_); + } +#endif // _LIBCPP_STD_VER > 17 + +private: + template friend class move_iterator; + + _Iter __current_; +}; +_LIBCPP_CTAD_SUPPORTED_FOR_TYPE(move_iterator); + +template +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 +bool operator==(const move_iterator<_Iter1>& __x, const move_iterator<_Iter2>& __y) +{ + return __x.base() == __y.base(); +} + +#if _LIBCPP_STD_VER <= 17 +template +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 +bool operator!=(const move_iterator<_Iter1>& __x, const move_iterator<_Iter2>& __y) +{ + return __x.base() != __y.base(); +} +#endif // _LIBCPP_STD_VER <= 17 + +template +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 +bool operator<(const move_iterator<_Iter1>& __x, const move_iterator<_Iter2>& __y) +{ + return __x.base() < __y.base(); +} + +template +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 +bool operator>(const move_iterator<_Iter1>& __x, const move_iterator<_Iter2>& __y) +{ + return __x.base() > __y.base(); +} + +template +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 +bool operator<=(const move_iterator<_Iter1>& __x, const move_iterator<_Iter2>& __y) +{ + return __x.base() <= __y.base(); +} + +template +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 +bool operator>=(const move_iterator<_Iter1>& __x, const move_iterator<_Iter2>& __y) +{ + return __x.base() >= __y.base(); +} + +#if _LIBCPP_STD_VER > 17 +template _Iter2> +inline _LIBCPP_HIDE_FROM_ABI constexpr +auto operator<=>(const move_iterator<_Iter1>& __x, const move_iterator<_Iter2>& __y) + -> compare_three_way_result_t<_Iter1, _Iter2> +{ + return __x.base() <=> __y.base(); +} +#endif // _LIBCPP_STD_VER > 17 + +#ifndef _LIBCPP_CXX03_LANG +template +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 +auto operator-(const move_iterator<_Iter1>& __x, const move_iterator<_Iter2>& __y) + -> decltype(__x.base() - __y.base()) +{ + return __x.base() - __y.base(); +} +#else +template +inline _LIBCPP_HIDE_FROM_ABI +typename move_iterator<_Iter1>::difference_type +operator-(const move_iterator<_Iter1>& __x, const move_iterator<_Iter2>& __y) +{ + return __x.base() - __y.base(); +} +#endif // !_LIBCPP_CXX03_LANG + +#if _LIBCPP_STD_VER > 17 +template +inline _LIBCPP_HIDE_FROM_ABI constexpr +move_iterator<_Iter> operator+(iter_difference_t<_Iter> __n, const move_iterator<_Iter>& __x) + requires requires { { __x.base() + __n } -> same_as<_Iter>; } +{ + return __x + __n; +} +#else +template +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 +move_iterator<_Iter> +operator+(typename move_iterator<_Iter>::difference_type __n, const move_iterator<_Iter>& __x) +{ + return move_iterator<_Iter>(__x.base() + __n); +} +#endif // _LIBCPP_STD_VER > 17 + +template +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 +move_iterator<_Iter> +make_move_iterator(_Iter __i) +{ + return move_iterator<_Iter>(std::move(__i)); +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ITERATOR_MOVE_ITERATOR_H diff --git a/app/src/main/cpp/libcxx/include/__iterator/move_sentinel.h b/app/src/main/cpp/libcxx/include/__iterator/move_sentinel.h new file mode 100644 index 0000000..0d7336a --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__iterator/move_sentinel.h @@ -0,0 +1,59 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ITERATOR_MOVE_SENTINEL_H +#define _LIBCPP___ITERATOR_MOVE_SENTINEL_H + +#include <__concepts/assignable.h> +#include <__concepts/convertible_to.h> +#include <__concepts/semiregular.h> +#include <__config> +#include <__utility/move.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 17 + +template +class _LIBCPP_TEMPLATE_VIS move_sentinel +{ +public: + _LIBCPP_HIDE_FROM_ABI + move_sentinel() = default; + + _LIBCPP_HIDE_FROM_ABI constexpr + explicit move_sentinel(_Sent __s) : __last_(std::move(__s)) {} + + template + requires convertible_to + _LIBCPP_HIDE_FROM_ABI constexpr + move_sentinel(const move_sentinel<_S2>& __s) : __last_(__s.base()) {} + + template + requires assignable_from<_Sent&, const _S2&> + _LIBCPP_HIDE_FROM_ABI constexpr + move_sentinel& operator=(const move_sentinel<_S2>& __s) + { __last_ = __s.base(); return *this; } + + constexpr _Sent base() const { return __last_; } + +private: + _Sent __last_ = _Sent(); +}; + +_LIBCPP_CTAD_SUPPORTED_FOR_TYPE(move_sentinel); + +#endif // _LIBCPP_STD_VER > 17 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ITERATOR_MOVE_SENTINEL_H diff --git a/app/src/main/cpp/libcxx/include/__iterator/next.h b/app/src/main/cpp/libcxx/include/__iterator/next.h new file mode 100644 index 0000000..49970ae --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__iterator/next.h @@ -0,0 +1,84 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ITERATOR_NEXT_H +#define _LIBCPP___ITERATOR_NEXT_H + +#include <__assert> +#include <__config> +#include <__iterator/advance.h> +#include <__iterator/concepts.h> +#include <__iterator/incrementable_traits.h> +#include <__iterator/iterator_traits.h> +#include <__type_traits/enable_if.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +template +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX17 + typename enable_if<__is_cpp17_input_iterator<_InputIter>::value, _InputIter>::type + next(_InputIter __x, typename iterator_traits<_InputIter>::difference_type __n = 1) { + _LIBCPP_ASSERT(__n >= 0 || __is_cpp17_bidirectional_iterator<_InputIter>::value, + "Attempt to next(it, n) with negative n on a non-bidirectional iterator"); + + _VSTD::advance(__x, __n); + return __x; +} + +#if _LIBCPP_STD_VER > 17 + +// [range.iter.op.next] + +namespace ranges { +namespace __next { + +struct __fn { + template + _LIBCPP_HIDE_FROM_ABI + constexpr _Ip operator()(_Ip __x) const { + ++__x; + return __x; + } + + template + _LIBCPP_HIDE_FROM_ABI + constexpr _Ip operator()(_Ip __x, iter_difference_t<_Ip> __n) const { + ranges::advance(__x, __n); + return __x; + } + + template _Sp> + _LIBCPP_HIDE_FROM_ABI constexpr _Ip operator()(_Ip __x, _Sp __bound_sentinel) const { + ranges::advance(__x, __bound_sentinel); + return __x; + } + + template _Sp> + _LIBCPP_HIDE_FROM_ABI constexpr _Ip operator()(_Ip __x, iter_difference_t<_Ip> __n, _Sp __bound_sentinel) const { + ranges::advance(__x, __n, __bound_sentinel); + return __x; + } +}; + +} // namespace __next + +inline namespace __cpo { + inline constexpr auto next = __next::__fn{}; +} // namespace __cpo +} // namespace ranges + +#endif // _LIBCPP_STD_VER > 17 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ITERATOR_NEXT_H diff --git a/app/src/main/cpp/libcxx/include/__iterator/ostream_iterator.h b/app/src/main/cpp/libcxx/include/__iterator/ostream_iterator.h new file mode 100644 index 0000000..d16f5a2 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__iterator/ostream_iterator.h @@ -0,0 +1,71 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ITERATOR_OSTREAM_ITERATOR_H +#define _LIBCPP___ITERATOR_OSTREAM_ITERATOR_H + +#include <__config> +#include <__iterator/iterator.h> +#include <__iterator/iterator_traits.h> +#include <__memory/addressof.h> +#include +#include // for forward declarations of char_traits and basic_ostream + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +_LIBCPP_SUPPRESS_DEPRECATED_PUSH +template > +class _LIBCPP_TEMPLATE_VIS ostream_iterator +#if _LIBCPP_STD_VER <= 14 || !defined(_LIBCPP_ABI_NO_ITERATOR_BASES) + : public iterator +#endif +{ +_LIBCPP_SUPPRESS_DEPRECATED_POP +public: + typedef output_iterator_tag iterator_category; + typedef void value_type; +#if _LIBCPP_STD_VER > 17 + typedef ptrdiff_t difference_type; +#else + typedef void difference_type; +#endif + typedef void pointer; + typedef void reference; + typedef _CharT char_type; + typedef _Traits traits_type; + typedef basic_ostream<_CharT, _Traits> ostream_type; + +private: + ostream_type* __out_stream_; + const char_type* __delim_; +public: + _LIBCPP_INLINE_VISIBILITY ostream_iterator(ostream_type& __s) _NOEXCEPT + : __out_stream_(_VSTD::addressof(__s)), __delim_(nullptr) {} + _LIBCPP_INLINE_VISIBILITY ostream_iterator(ostream_type& __s, const _CharT* __delimiter) _NOEXCEPT + : __out_stream_(_VSTD::addressof(__s)), __delim_(__delimiter) {} + _LIBCPP_INLINE_VISIBILITY ostream_iterator& operator=(const _Tp& __value) + { + *__out_stream_ << __value; + if (__delim_) + *__out_stream_ << __delim_; + return *this; + } + + _LIBCPP_INLINE_VISIBILITY ostream_iterator& operator*() {return *this;} + _LIBCPP_INLINE_VISIBILITY ostream_iterator& operator++() {return *this;} + _LIBCPP_INLINE_VISIBILITY ostream_iterator& operator++(int) {return *this;} +}; + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ITERATOR_OSTREAM_ITERATOR_H diff --git a/app/src/main/cpp/libcxx/include/__iterator/ostreambuf_iterator.h b/app/src/main/cpp/libcxx/include/__iterator/ostreambuf_iterator.h new file mode 100644 index 0000000..b75f7b6 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__iterator/ostreambuf_iterator.h @@ -0,0 +1,77 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ITERATOR_OSTREAMBUF_ITERATOR_H +#define _LIBCPP___ITERATOR_OSTREAMBUF_ITERATOR_H + +#include <__config> +#include <__iterator/iterator.h> +#include <__iterator/iterator_traits.h> +#include +#include // for forward declaration of basic_streambuf + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +_LIBCPP_SUPPRESS_DEPRECATED_PUSH +template +class _LIBCPP_TEMPLATE_VIS ostreambuf_iterator +#if _LIBCPP_STD_VER <= 14 || !defined(_LIBCPP_ABI_NO_ITERATOR_BASES) + : public iterator +#endif +{ +_LIBCPP_SUPPRESS_DEPRECATED_POP +public: + typedef output_iterator_tag iterator_category; + typedef void value_type; +#if _LIBCPP_STD_VER > 17 + typedef ptrdiff_t difference_type; +#else + typedef void difference_type; +#endif + typedef void pointer; + typedef void reference; + typedef _CharT char_type; + typedef _Traits traits_type; + typedef basic_streambuf<_CharT, _Traits> streambuf_type; + typedef basic_ostream<_CharT, _Traits> ostream_type; + +private: + streambuf_type* __sbuf_; +public: + _LIBCPP_INLINE_VISIBILITY ostreambuf_iterator(ostream_type& __s) _NOEXCEPT + : __sbuf_(__s.rdbuf()) {} + _LIBCPP_INLINE_VISIBILITY ostreambuf_iterator(streambuf_type* __s) _NOEXCEPT + : __sbuf_(__s) {} + _LIBCPP_INLINE_VISIBILITY ostreambuf_iterator& operator=(_CharT __c) + { + if (__sbuf_ && traits_type::eq_int_type(__sbuf_->sputc(__c), traits_type::eof())) + __sbuf_ = nullptr; + return *this; + } + _LIBCPP_INLINE_VISIBILITY ostreambuf_iterator& operator*() {return *this;} + _LIBCPP_INLINE_VISIBILITY ostreambuf_iterator& operator++() {return *this;} + _LIBCPP_INLINE_VISIBILITY ostreambuf_iterator& operator++(int) {return *this;} + _LIBCPP_INLINE_VISIBILITY bool failed() const _NOEXCEPT {return __sbuf_ == nullptr;} + + template + friend + _LIBCPP_HIDE_FROM_ABI + ostreambuf_iterator<_Ch, _Tr> + __pad_and_output(ostreambuf_iterator<_Ch, _Tr> __s, + const _Ch* __ob, const _Ch* __op, const _Ch* __oe, + ios_base& __iob, _Ch __fl); +}; + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ITERATOR_OSTREAMBUF_ITERATOR_H diff --git a/app/src/main/cpp/libcxx/include/__iterator/permutable.h b/app/src/main/cpp/libcxx/include/__iterator/permutable.h new file mode 100644 index 0000000..28d193e --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__iterator/permutable.h @@ -0,0 +1,35 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ITERATOR_PERMUTABLE_H +#define _LIBCPP___ITERATOR_PERMUTABLE_H + +#include <__config> +#include <__iterator/concepts.h> +#include <__iterator/iter_swap.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 17 + +template +concept permutable = + forward_iterator<_Iterator> && + indirectly_movable_storable<_Iterator, _Iterator> && + indirectly_swappable<_Iterator, _Iterator>; + +#endif // _LIBCPP_STD_VER > 17 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ITERATOR_PERMUTABLE_H diff --git a/app/src/main/cpp/libcxx/include/__iterator/prev.h b/app/src/main/cpp/libcxx/include/__iterator/prev.h new file mode 100644 index 0000000..af1e1ba --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__iterator/prev.h @@ -0,0 +1,77 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ITERATOR_PREV_H +#define _LIBCPP___ITERATOR_PREV_H + +#include <__assert> +#include <__config> +#include <__iterator/advance.h> +#include <__iterator/concepts.h> +#include <__iterator/incrementable_traits.h> +#include <__iterator/iterator_traits.h> +#include <__type_traits/enable_if.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +template +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX17 + typename enable_if<__is_cpp17_input_iterator<_InputIter>::value, _InputIter>::type + prev(_InputIter __x, typename iterator_traits<_InputIter>::difference_type __n = 1) { + _LIBCPP_ASSERT(__n <= 0 || __is_cpp17_bidirectional_iterator<_InputIter>::value, + "Attempt to prev(it, n) with a positive n on a non-bidirectional iterator"); + _VSTD::advance(__x, -__n); + return __x; +} + +#if _LIBCPP_STD_VER > 17 + +// [range.iter.op.prev] + +namespace ranges { +namespace __prev { + +struct __fn { + template + _LIBCPP_HIDE_FROM_ABI + constexpr _Ip operator()(_Ip __x) const { + --__x; + return __x; + } + + template + _LIBCPP_HIDE_FROM_ABI + constexpr _Ip operator()(_Ip __x, iter_difference_t<_Ip> __n) const { + ranges::advance(__x, -__n); + return __x; + } + + template + _LIBCPP_HIDE_FROM_ABI constexpr _Ip operator()(_Ip __x, iter_difference_t<_Ip> __n, _Ip __bound_iter) const { + ranges::advance(__x, -__n, __bound_iter); + return __x; + } +}; + +} // namespace __prev + +inline namespace __cpo { + inline constexpr auto prev = __prev::__fn{}; +} // namespace __cpo +} // namespace ranges + +#endif // _LIBCPP_STD_VER > 17 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ITERATOR_PREV_H diff --git a/app/src/main/cpp/libcxx/include/__iterator/projected.h b/app/src/main/cpp/libcxx/include/__iterator/projected.h new file mode 100644 index 0000000..19c076b --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__iterator/projected.h @@ -0,0 +1,41 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ITERATOR_PROJECTED_H +#define _LIBCPP___ITERATOR_PROJECTED_H + +#include <__config> +#include <__iterator/concepts.h> +#include <__iterator/incrementable_traits.h> +#include <__type_traits/remove_cvref.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 17 + +template _Proj> +struct projected { + using value_type = remove_cvref_t>; + indirect_result_t<_Proj&, _It> operator*() const; // not defined +}; + +template +struct incrementable_traits> { + using difference_type = iter_difference_t<_It>; +}; + +#endif // _LIBCPP_STD_VER > 17 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ITERATOR_PROJECTED_H diff --git a/app/src/main/cpp/libcxx/include/__iterator/readable_traits.h b/app/src/main/cpp/libcxx/include/__iterator/readable_traits.h new file mode 100644 index 0000000..8f17757 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__iterator/readable_traits.h @@ -0,0 +1,92 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ITERATOR_READABLE_TRAITS_H +#define _LIBCPP___ITERATOR_READABLE_TRAITS_H + +#include <__concepts/same_as.h> +#include <__config> +#include <__type_traits/conditional.h> +#include <__type_traits/is_array.h> +#include <__type_traits/is_object.h> +#include <__type_traits/is_primary_template.h> +#include <__type_traits/remove_cv.h> +#include <__type_traits/remove_cvref.h> +#include <__type_traits/remove_extent.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 17 + +// [readable.traits] +template struct __cond_value_type {}; + +template +requires is_object_v<_Tp> +struct __cond_value_type<_Tp> { using value_type = remove_cv_t<_Tp>; }; + +template +concept __has_member_value_type = requires { typename _Tp::value_type; }; + +template +concept __has_member_element_type = requires { typename _Tp::element_type; }; + +template struct indirectly_readable_traits {}; + +template +requires is_array_v<_Ip> +struct indirectly_readable_traits<_Ip> { + using value_type = remove_cv_t>; +}; + +template +struct indirectly_readable_traits : indirectly_readable_traits<_Ip> {}; + +template +struct indirectly_readable_traits<_Tp*> : __cond_value_type<_Tp> {}; + +template<__has_member_value_type _Tp> +struct indirectly_readable_traits<_Tp> + : __cond_value_type {}; + +template<__has_member_element_type _Tp> +struct indirectly_readable_traits<_Tp> + : __cond_value_type {}; + +template<__has_member_value_type _Tp> + requires __has_member_element_type<_Tp> +struct indirectly_readable_traits<_Tp> {}; + +template<__has_member_value_type _Tp> + requires __has_member_element_type<_Tp> && + same_as, + remove_cv_t> +struct indirectly_readable_traits<_Tp> + : __cond_value_type {}; + +template +struct iterator_traits; + +// Let `RI` be `remove_cvref_t`. The type `iter_value_t` denotes +// `indirectly_readable_traits::value_type` if `iterator_traits` names a specialization +// generated from the primary template, and `iterator_traits::value_type` otherwise. +template +using iter_value_t = typename conditional_t<__is_primary_template > >::value, + indirectly_readable_traits >, + iterator_traits > >::value_type; + +#endif // _LIBCPP_STD_VER > 17 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ITERATOR_READABLE_TRAITS_H diff --git a/app/src/main/cpp/libcxx/include/__iterator/reverse_access.h b/app/src/main/cpp/libcxx/include/__iterator/reverse_access.h new file mode 100644 index 0000000..79b599c --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__iterator/reverse_access.h @@ -0,0 +1,100 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ITERATOR_REVERSE_ACCESS_H +#define _LIBCPP___ITERATOR_REVERSE_ACCESS_H + +#include <__config> +#include <__iterator/reverse_iterator.h> +#include +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 11 + +template +_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX17 +reverse_iterator<_Tp*> rbegin(_Tp (&__array)[_Np]) +{ + return reverse_iterator<_Tp*>(__array + _Np); +} + +template +_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX17 +reverse_iterator<_Tp*> rend(_Tp (&__array)[_Np]) +{ + return reverse_iterator<_Tp*>(__array); +} + +template +_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX17 +reverse_iterator rbegin(initializer_list<_Ep> __il) +{ + return reverse_iterator(__il.end()); +} + +template +_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX17 +reverse_iterator rend(initializer_list<_Ep> __il) +{ + return reverse_iterator(__il.begin()); +} + +template +_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX17 +auto rbegin(_Cp& __c) -> decltype(__c.rbegin()) +{ + return __c.rbegin(); +} + +template +_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX17 +auto rbegin(const _Cp& __c) -> decltype(__c.rbegin()) +{ + return __c.rbegin(); +} + +template +_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX17 +auto rend(_Cp& __c) -> decltype(__c.rend()) +{ + return __c.rend(); +} + +template +_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX17 +auto rend(const _Cp& __c) -> decltype(__c.rend()) +{ + return __c.rend(); +} + +template +_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX17 +auto crbegin(const _Cp& __c) -> decltype(_VSTD::rbegin(__c)) +{ + return _VSTD::rbegin(__c); +} + +template +_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX17 +auto crend(const _Cp& __c) -> decltype(_VSTD::rend(__c)) +{ + return _VSTD::rend(__c); +} + +#endif // _LIBCPP_STD_VER > 11 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ITERATOR_REVERSE_ACCESS_H diff --git a/app/src/main/cpp/libcxx/include/__iterator/reverse_iterator.h b/app/src/main/cpp/libcxx/include/__iterator/reverse_iterator.h new file mode 100644 index 0000000..f272e03 --- /dev/null +++ b/app/src/main/cpp/libcxx/include/__iterator/reverse_iterator.h @@ -0,0 +1,533 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ITERATOR_REVERSE_ITERATOR_H +#define _LIBCPP___ITERATOR_REVERSE_ITERATOR_H + +#include <__algorithm/unwrap_iter.h> +#include <__compare/compare_three_way_result.h> +#include <__compare/three_way_comparable.h> +#include <__concepts/convertible_to.h> +#include <__config> +#include <__iterator/advance.h> +#include <__iterator/concepts.h> +#include <__iterator/incrementable_traits.h> +#include <__iterator/iter_move.h> +#include <__iterator/iter_swap.h> +#include <__iterator/iterator.h> +#include <__iterator/iterator_traits.h> +#include <__iterator/next.h> +#include <__iterator/prev.h> +#include <__iterator/readable_traits.h> +#include <__iterator/segmented_iterator.h> +#include <__memory/addressof.h> +#include <__ranges/access.h> +#include <__ranges/concepts.h> +#include <__ranges/subrange.h> +#include <__type_traits/conditional.h> +#include <__type_traits/enable_if.h> +#include <__type_traits/is_assignable.h> +#include <__type_traits/is_convertible.h> +#include <__type_traits/is_nothrow_copy_constructible.h> +#include <__type_traits/is_pointer.h> +#include <__type_traits/is_same.h> +#include <__utility/declval.h> +#include <__utility/move.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +_LIBCPP_SUPPRESS_DEPRECATED_PUSH +template +class _LIBCPP_TEMPLATE_VIS reverse_iterator +#if _LIBCPP_STD_VER <= 14 || !defined(_LIBCPP_ABI_NO_ITERATOR_BASES) + : public iterator::iterator_category, + typename iterator_traits<_Iter>::value_type, + typename iterator_traits<_Iter>::difference_type, + typename iterator_traits<_Iter>::pointer, + typename iterator_traits<_Iter>::reference> +#endif +{ +_LIBCPP_SUPPRESS_DEPRECATED_POP +private: +#ifndef _LIBCPP_ABI_NO_ITERATOR_BASES + _Iter __t_; // no longer used as of LWG #2360, not removed due to ABI break +#endif + +#if _LIBCPP_STD_VER > 17 + static_assert(__is_cpp17_bidirectional_iterator<_Iter>::value || bidirectional_iterator<_Iter>, + "reverse_iterator requires It to be a bidirectional iterator."); +#endif // _LIBCPP_STD_VER > 17 + +protected: + _Iter current; +public: + using iterator_type = _Iter; + + using iterator_category = _If<__is_cpp17_random_access_iterator<_Iter>::value, + random_access_iterator_tag, + typename iterator_traits<_Iter>::iterator_category>; + using pointer = typename iterator_traits<_Iter>::pointer; +#if _LIBCPP_STD_VER > 17 + using iterator_concept = _If, random_access_iterator_tag, bidirectional_iterator_tag>; + using value_type = iter_value_t<_Iter>; + using difference_type = iter_difference_t<_Iter>; + using reference = iter_reference_t<_Iter>; +#else + using value_type = typename iterator_traits<_Iter>::value_type; + using difference_type = typename iterator_traits<_Iter>::difference_type; + using reference = typename iterator_traits<_Iter>::reference; +#endif + +#ifndef _LIBCPP_ABI_NO_ITERATOR_BASES + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX17 + reverse_iterator() : __t_(), current() {} + + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX17 + explicit reverse_iterator(_Iter __x) : __t_(__x), current(__x) {} + + template ::value && is_convertible<_Up const&, _Iter>::value + > > + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX17 + reverse_iterator(const reverse_iterator<_Up>& __u) + : __t_(__u.base()), current(__u.base()) + { } + + template ::value && + is_convertible<_Up const&, _Iter>::value && + is_assignable<_Iter&, _Up const&>::value + > > + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX17 + reverse_iterator& operator=(const reverse_iterator<_Up>& __u) { + __t_ = current = __u.base(); + return *this; + } +#else + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX17 + reverse_iterator() : current() {} + + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX17 + explicit reverse_iterator(_Iter __x) : current(__x) {} + + template ::value && is_convertible<_Up const&, _Iter>::value + > > + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX17 + reverse_iterator(const reverse_iterator<_Up>& __u) + : current(__u.base()) + { } + + template ::value && + is_convertible<_Up const&, _Iter>::value && + is_assignable<_Iter&, _Up const&>::value + > > + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX17 + reverse_iterator& operator=(const reverse_iterator<_Up>& __u) { + current = __u.base(); + return *this; + } +#endif + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX17 + _Iter base() const {return current;} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX17 + reference operator*() const {_Iter __tmp = current; return *--__tmp;} + +#if _LIBCPP_STD_VER > 17 + _LIBCPP_INLINE_VISIBILITY + constexpr pointer operator->() const + requires is_pointer_v<_Iter> || requires(const _Iter __i) { __i.operator->(); } + { + if constexpr (is_pointer_v<_Iter>) { + return std::prev(current); + } else { + return std::prev(current).operator->(); + } + } +#else + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX17 + pointer operator->() const { + return std::addressof(operator*()); + } +#endif // _LIBCPP_STD_VER > 17 + + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX17 + reverse_iterator& operator++() {--current; return *this;} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX17 + reverse_iterator operator++(int) {reverse_iterator __tmp(*this); --current; return __tmp;} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX17 + reverse_iterator& operator--() {++current; return *this;} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX17 + reverse_iterator operator--(int) {reverse_iterator __tmp(*this); ++current; return __tmp;} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX17 + reverse_iterator operator+(difference_type __n) const {return reverse_iterator(current - __n);} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX17 + reverse_iterator& operator+=(difference_type __n) {current -= __n; return *this;} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX17 + reverse_iterator operator-(difference_type __n) const {return reverse_iterator(current + __n);} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX17 + reverse_iterator& operator-=(difference_type __n) {current += __n; return *this;} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX17 + reference operator[](difference_type __n) const {return *(*this + __n);} + +#if _LIBCPP_STD_VER > 17 + _LIBCPP_HIDE_FROM_ABI friend constexpr + iter_rvalue_reference_t<_Iter> iter_move(const reverse_iterator& __i) + noexcept(is_nothrow_copy_constructible_v<_Iter> && + noexcept(ranges::iter_move(--std::declval<_Iter&>()))) { + auto __tmp = __i.base(); + return ranges::iter_move(--__tmp); + } + + template _Iter2> + _LIBCPP_HIDE_FROM_ABI friend constexpr + void iter_swap(const reverse_iterator& __x, const reverse_iterator<_Iter2>& __y) + noexcept(is_nothrow_copy_constructible_v<_Iter> && + is_nothrow_copy_constructible_v<_Iter2> && + noexcept(ranges::iter_swap(--std::declval<_Iter&>(), --std::declval<_Iter2&>()))) { + auto __xtmp = __x.base(); + auto __ytmp = __y.base(); + ranges::iter_swap(--__xtmp, --__ytmp); + } +#endif // _LIBCPP_STD_VER > 17 +}; + +template +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX17 +bool +operator==(const reverse_iterator<_Iter1>& __x, const reverse_iterator<_Iter2>& __y) +#if _LIBCPP_STD_VER > 17 + requires requires { + { __x.base() == __y.base() } -> convertible_to; + } +#endif // _LIBCPP_STD_VER > 17 +{ + return __x.base() == __y.base(); +} + +template +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX17 +bool +operator<(const reverse_iterator<_Iter1>& __x, const reverse_iterator<_Iter2>& __y) +#if _LIBCPP_STD_VER > 17 + requires requires { + { __x.base() > __y.base() } -> convertible_to; + } +#endif // _LIBCPP_STD_VER > 17 +{ + return __x.base() > __y.base(); +} + +template +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX17 +bool +operator!=(const reverse_iterator<_Iter1>& __x, const reverse_iterator<_Iter2>& __y) +#if _LIBCPP_STD_VER > 17 + requires requires { + { __x.base() != __y.base() } -> convertible_to; + } +#endif // _LIBCPP_STD_VER > 17 +{ + return __x.base() != __y.base(); +} + +template +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX17 +bool +operator>(const reverse_iterator<_Iter1>& __x, const reverse_iterator<_Iter2>& __y) +#if _LIBCPP_STD_VER > 17 + requires requires { + { __x.base() < __y.base() } -> convertible_to; + } +#endif // _LIBCPP_STD_VER > 17 +{ + return __x.base() < __y.base(); +} + +template +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX17 +bool +operator>=(const reverse_iterator<_Iter1>& __x, const reverse_iterator<_Iter2>& __y) +#if _LIBCPP_STD_VER > 17 + requires requires { + { __x.base() <= __y.base() } -> convertible_to; + } +#endif // _LIBCPP_STD_VER > 17 +{ + return __x.base() <= __y.base(); +} + +template +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX17 +bool +operator<=(const reverse_iterator<_Iter1>& __x, const reverse_iterator<_Iter2>& __y) +#if _LIBCPP_STD_VER > 17 + requires requires { + { __x.base() >= __y.base() } -> convertible_to; + } +#endif // _LIBCPP_STD_VER > 17 +{ + return __x.base() >= __y.base(); +} + +#if _LIBCPP_STD_VER > 17 +template _Iter2> +_LIBCPP_HIDE_FROM_ABI constexpr +compare_three_way_result_t<_Iter1, _Iter2> +operator<=>(const reverse_iterator<_Iter1>& __x, const reverse_iterator<_Iter2>& __y) +{ + return __y.base() <=> __x.base(); +} +#endif // _LIBCPP_STD_VER > 17 + +#ifndef _LIBCPP_CXX03_LANG +template +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX17 +auto +operator-(const reverse_iterator<_Iter1>& __x, const reverse_iterator<_Iter2>& __y) +-> decltype(__y.base() - __x.base()) +{ + return __y.base() - __x.base(); +} +#else +template +inline _LIBCPP_INLINE_VISIBILITY +typename reverse_iterator<_Iter1>::difference_type +operator-(const reverse_iterator<_Iter1>& __x, const reverse_iterator<_Iter2>& __y) +{ + return __y.base() - __x.base(); +} +#endif + +template +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX17 +reverse_iterator<_Iter> +operator+(typename reverse_iterator<_Iter>::difference_type __n, const reverse_iterator<_Iter>& __x) +{ + return reverse_iterator<_Iter>(__x.base() - __n); +} + +#if _LIBCPP_STD_VER > 17 +template + requires (!sized_sentinel_for<_Iter1, _Iter2>) +inline constexpr bool disable_sized_sentinel_for, reverse_iterator<_Iter2>> = true; +#endif // _LIBCPP_STD_VER > 17 + +#if _LIBCPP_STD_VER > 11 +template +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX17 +reverse_iterator<_Iter> make_reverse_iterator(_Iter __i) +{ + return reverse_iterator<_Iter>(__i); +} +#endif + +#if _LIBCPP_STD_VER <= 17 +template +using __unconstrained_reverse_iterator = reverse_iterator<_Iter>; +#else + +// __unconstrained_reverse_iterator allows us to use reverse iterators in the implementation of algorithms by working +// around a language issue in C++20. +// In C++20, when a reverse iterator wraps certain C++20-hostile iterators, calling comparison operators on it will +// result in a compilation error. However, calling comparison operators on the pristine hostile iterator is not +// an error. Thus, we cannot use reverse_iterators in the implementation of an algorithm that accepts a +// C++20-hostile iterator. This class is an internal workaround -- it is a copy of reverse_iterator with +// tweaks to make it support hostile iterators. +// +// A C++20-hostile iterator is one that defines a comparison operator where one of the arguments is an exact match +// and the other requires an implicit conversion, for example: +// friend bool operator==(const BaseIter&, const DerivedIter&); +// +// C++20 rules for rewriting equality operators create another overload of this function with parameters reversed: +// friend bool operator==(const DerivedIter&, const BaseIter&); +// +// This creates an ambiguity in overload resolution. +// +// Clang treats this ambiguity differently in different contexts. When operator== is actually called in the function +// body, the code is accepted with a warning. When a concept requires operator== to be a valid expression, however, +// it evaluates to false. Thus, the implementation of reverse_iterator::operator== can actually call operator== on its +// base iterators, but the constraints on reverse_iterator::operator== prevent it from being considered during overload +// resolution. This class simply removes the problematic constraints from comparison functions. +template +class __unconstrained_reverse_iterator { + _Iter __iter_; + +public: + static_assert(__is_cpp17_bidirectional_iterator<_Iter>::value || bidirectional_iterator<_Iter>); + + using iterator_type = _Iter; + using iterator_category = + _If<__is_cpp17_random_access_iterator<_Iter>::value, random_access_iterator_tag, __iterator_category_type<_Iter>>; + using pointer = __iterator_pointer_type<_Iter>; + using value_type = iter_value_t<_Iter>; + using difference_type = iter_difference_t<_Iter>; + using reference = iter_reference_t<_Iter>; + + _LIBCPP_HIDE_FROM_ABI constexpr __unconstrained_reverse_iterator() = default; + _LIBCPP_HIDE_FROM_ABI constexpr __unconstrained_reverse_iterator(const __unconstrained_reverse_iterator&) = default; + _LIBCPP_HIDE_FROM_ABI constexpr explicit __unconstrained_reverse_iterator(_Iter __iter) : __iter_(__iter) {} + + _LIBCPP_HIDE_FROM_ABI constexpr _Iter base() const { return __iter_; } + _LIBCPP_HIDE_FROM_ABI constexpr reference operator*() const { + auto __tmp = __iter_; + return *--__tmp; + } + + _LIBCPP_HIDE_FROM_ABI constexpr pointer operator->() const { + if constexpr (is_pointer_v<_Iter>) { + return std::prev(__iter_); + } else { + return std::prev(__iter_).operator->(); + } + } + + _LIBCPP_HIDE_FROM_ABI friend constexpr + iter_rvalue_reference_t<_Iter> iter_move(const __unconstrained_reverse_iterator& __i) + noexcept(is_nothrow_copy_constructible_v<_Iter> && + noexcept(ranges::iter_move(--std::declval<_Iter&>()))) { + auto __tmp = __i.base(); + return ranges::iter_move(--__tmp); + } + + _LIBCPP_HIDE_FROM_ABI constexpr __unconstrained_reverse_iterator& operator++() { + --__iter_; + return *this; + } + + _LIBCPP_HIDE_FROM_ABI constexpr __unconstrained_reverse_iterator operator++(int) { + auto __tmp = *this; + --__iter_; + return __tmp; + } + + _LIBCPP_HIDE_FROM_ABI constexpr __unconstrained_reverse_iterator& operator--() { + ++__iter_; + return *this; + } + + _LIBCPP_HIDE_FROM_ABI constexpr __unconstrained_reverse_iterator operator--(int) { + auto __tmp = *this; + ++__iter_; + return __tmp; + } + + _LIBCPP_HIDE_FROM_ABI constexpr __unconstrained_reverse_iterator& operator+=(difference_type __n) { + __iter_ -= __n; + return *this; + } + + _LIBCPP_HIDE_FROM_ABI constexpr __unconstrained_reverse_iterator& operator-=(difference_type __n) { + __iter_ += __n; + return *this; + } + + _LIBCPP_HIDE_FROM_ABI constexpr __unconstrained_reverse_iterator operator+(difference_type __n) const { + return __unconstrained_reverse_iterator(__iter_ - __n); + } + + _LIBCPP_HIDE_FROM_ABI constexpr __unconstrained_reverse_iterator operator-(difference_type __n) const { + return __unconstrained_reverse_iterator(__iter_ + __n); + } + + _LIBCPP_HIDE_FROM_ABI constexpr difference_type operator-(const __unconstrained_reverse_iterator& __other) const { + return __other.__iter_ - __iter_; + } + + _LIBCPP_HIDE_FROM_ABI constexpr auto operator[](difference_type __n) const { return *(*this + __n); } + + // Deliberately unconstrained unlike the comparison functions in `reverse_iterator` -- see the class comment for the + // rationale. + _LIBCPP_HIDE_FROM_ABI friend constexpr bool + operator==(const __unconstrained_reverse_iterator& __lhs, const __unconstrained_reverse_iterator& __rhs) { + return __lhs.base() == __rhs.base(); + } + + _LIBCPP_HIDE_FROM_ABI friend constexpr bool + operator!=(const __unconstrained_reverse_iterator& __lhs, const __unconstrained_reverse_iterator& __rhs) { + return __lhs.base() != __rhs.base(); + } + + _LIBCPP_HIDE_FROM_ABI friend constexpr bool + operator<(const __unconstrained_reverse_iterator& __lhs, const __unconstrained_reverse_iterator& __rhs) { + return __lhs.base() > __rhs.base(); + } + + _LIBCPP_HIDE_FROM_ABI friend constexpr bool + operator>(const __unconstrained_reverse_iterator& __lhs, const __unconstrained_reverse_iterator& __rhs) { + return __lhs.base() < __rhs.base(); + } + + _LIBCPP_HIDE_FROM_ABI friend constexpr bool + operator<=(const __unconstrained_reverse_iterator& __lhs, const __unconstrained_reverse_iterator& __rhs) { + return __lhs.base() >= __rhs.base(); + } + + _LIBCPP_HIDE_FROM_ABI friend constexpr bool + operator>=(const __unconstrained_reverse_iterator& __lhs, const __unconstrained_reverse_iterator& __rhs) { + return __lhs.base() <= __rhs.base(); + } +}; + +#endif // _LIBCPP_STD_VER <= 17 + +template