Compare commits
35 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 8b878a841e | |||
| 8aade382bb | |||
| a522016953 | |||
| 6f444be1de | |||
| 72527d63a0 | |||
| 3ff2819922 | |||
| 559768c351 | |||
| 316b8dbec2 | |||
| 1724c3a7fa | |||
| 112e089166 | |||
| 250c406098 | |||
| 11c3369cf4 | |||
| f4ce1dc8f6 | |||
| 49f07cbb8e | |||
| 68d5dbc919 | |||
| 068a1da098 | |||
| ff02ae92f4 | |||
| a65c9cbcb1 | |||
| 13d8eebbca | |||
| 93820be50e | |||
| 47d1630e7f | |||
| 79da3793c1 | |||
| c5cf8c31ac | |||
| 67558b796f | |||
| 2a3f539bb2 | |||
| ada954cd8d | |||
| 9398bbc382 | |||
| 2e3f3e90ef | |||
| 2e54842ce8 | |||
| cf4141dffd | |||
| c3683201e6 | |||
| 0f5ffc2a84 | |||
| fafe1d4f81 | |||
| f1087e81ec | |||
| 178bcb974e |
@@ -17,7 +17,6 @@ Checks: >
|
||||
-bugprone-incorrect-enable-if,
|
||||
-bugprone-switch-missing-default-case,
|
||||
-bugprone-empty-catch,
|
||||
-bugprone-unchecked-optional-access,
|
||||
-clang-analyzer-*,
|
||||
-clang-diagnostic-deprecated-declarations,
|
||||
-clang-diagnostic-constant-conversion,
|
||||
|
||||
@@ -170,49 +170,52 @@ jobs:
|
||||
continue-on-error: false
|
||||
node: 20
|
||||
runs-on: ubuntu-24.04
|
||||
BUILD_TOOLS: ON
|
||||
BUILD_TYPE: Debug
|
||||
CCOMPILER: gcc-13
|
||||
CUCUMBER_TIMEOUT: 20000
|
||||
CXXCOMPILER: g++-13
|
||||
ENABLE_COVERAGE: ON
|
||||
|
||||
- name: clang-18-debug-asan-ubsan
|
||||
- name: clang-15-debug-asan-ubsan
|
||||
continue-on-error: false
|
||||
node: 20
|
||||
runs-on: ubuntu-24.04
|
||||
runs-on: ubuntu-22.04
|
||||
BUILD_TOOLS: ON
|
||||
BUILD_TYPE: Debug
|
||||
CCOMPILER: clang-18
|
||||
CCOMPILER: clang-15
|
||||
CUCUMBER_TIMEOUT: 20000
|
||||
CXXCOMPILER: clang++-18
|
||||
CXXCOMPILER: clang++-15
|
||||
ENABLE_SANITIZER: ON
|
||||
TARGET_ARCH: x86_64-asan-ubsan
|
||||
OSRM_CONNECTION_RETRIES: 10
|
||||
OSRM_CONNECTION_EXP_BACKOFF_COEF: 1.5
|
||||
|
||||
- name: clang-18-release
|
||||
- name: clang-15-release
|
||||
continue-on-error: false
|
||||
node: 18
|
||||
runs-on: ubuntu-24.04
|
||||
runs-on: ubuntu-22.04
|
||||
BUILD_TOOLS: ON
|
||||
BUILD_TYPE: Release
|
||||
CCOMPILER: clang-18
|
||||
CXXCOMPILER: clang++-18
|
||||
CCOMPILER: clang-15
|
||||
CXXCOMPILER: clang++-15
|
||||
CUCUMBER_TIMEOUT: 60000
|
||||
ENABLE_LTO: OFF
|
||||
|
||||
- name: clang-18-debug
|
||||
- name: clang-15-debug
|
||||
continue-on-error: false
|
||||
node: 18
|
||||
runs-on: ubuntu-24.04
|
||||
runs-on: ubuntu-22.04
|
||||
BUILD_TOOLS: ON
|
||||
BUILD_TYPE: Debug
|
||||
CCOMPILER: clang-18
|
||||
CXXCOMPILER: clang++-18
|
||||
CCOMPILER: clang-15
|
||||
CXXCOMPILER: clang++-15
|
||||
CUCUMBER_TIMEOUT: 60000
|
||||
ENABLE_LTO: OFF
|
||||
|
||||
- name: clang-18-debug-clang-tidy
|
||||
continue-on-error: false
|
||||
node: 18
|
||||
runs-on: ubuntu-24.04
|
||||
BUILD_TOOLS: ON
|
||||
BUILD_TYPE: Debug
|
||||
CCOMPILER: clang-18
|
||||
CXXCOMPILER: clang++-18
|
||||
@@ -220,51 +223,52 @@ jobs:
|
||||
ENABLE_CLANG_TIDY: ON
|
||||
|
||||
|
||||
- name: clang-17-release
|
||||
- name: clang-14-release
|
||||
continue-on-error: false
|
||||
node: 18
|
||||
runs-on: ubuntu-24.04
|
||||
runs-on: ubuntu-22.04
|
||||
BUILD_TOOLS: ON
|
||||
BUILD_TYPE: Release
|
||||
CCOMPILER: clang-17
|
||||
CXXCOMPILER: clang++-17
|
||||
CCOMPILER: clang-14
|
||||
CXXCOMPILER: clang++-14
|
||||
CUCUMBER_TIMEOUT: 60000
|
||||
ENABLE_LTO: OFF
|
||||
|
||||
- name: clang-16-release
|
||||
- name: clang-13-release
|
||||
continue-on-error: false
|
||||
node: 18
|
||||
runs-on: ubuntu-24.04
|
||||
runs-on: ubuntu-22.04
|
||||
BUILD_TOOLS: ON
|
||||
BUILD_TYPE: Release
|
||||
CCOMPILER: clang-16
|
||||
CXXCOMPILER: clang++-16
|
||||
CCOMPILER: clang-13
|
||||
CXXCOMPILER: clang++-13
|
||||
CUCUMBER_TIMEOUT: 60000
|
||||
ENABLE_LTO: OFF
|
||||
|
||||
- name: conan-linux-debug-asan-ubsan
|
||||
continue-on-error: false
|
||||
node: 18
|
||||
runs-on: ubuntu-24.04
|
||||
runs-on: ubuntu-22.04
|
||||
BUILD_TOOLS: ON
|
||||
BUILD_TYPE: Release
|
||||
CCOMPILER: clang-18
|
||||
CXXCOMPILER: clang++-18
|
||||
CCOMPILER: clang-15
|
||||
CXXCOMPILER: clang++-15
|
||||
ENABLE_CONAN: ON
|
||||
ENABLE_SANITIZER: ON
|
||||
ENABLE_LTO: OFF
|
||||
|
||||
- name: conan-linux-release
|
||||
continue-on-error: false
|
||||
node: 18
|
||||
runs-on: ubuntu-24.04
|
||||
runs-on: ubuntu-22.04
|
||||
BUILD_TOOLS: ON
|
||||
BUILD_TYPE: Release
|
||||
CCOMPILER: clang-18
|
||||
CXXCOMPILER: clang++-18
|
||||
CCOMPILER: clang-15
|
||||
CXXCOMPILER: clang++-15
|
||||
ENABLE_CONAN: ON
|
||||
ENABLE_LTO: OFF
|
||||
|
||||
- name: gcc-14-release
|
||||
continue-on-error: false
|
||||
node: 20
|
||||
runs-on: ubuntu-24.04
|
||||
BUILD_TOOLS: ON
|
||||
BUILD_TYPE: Release
|
||||
CCOMPILER: gcc-14
|
||||
CXXCOMPILER: g++-14
|
||||
@@ -274,6 +278,7 @@ jobs:
|
||||
continue-on-error: false
|
||||
node: 20
|
||||
runs-on: ubuntu-24.04
|
||||
BUILD_TOOLS: ON
|
||||
BUILD_TYPE: Release
|
||||
CCOMPILER: gcc-13
|
||||
CXXCOMPILER: g++-13
|
||||
@@ -283,6 +288,7 @@ jobs:
|
||||
continue-on-error: false
|
||||
node: 20
|
||||
runs-on: ubuntu-22.04
|
||||
BUILD_TOOLS: ON
|
||||
BUILD_TYPE: Release
|
||||
CCOMPILER: gcc-12
|
||||
CXXCOMPILER: g++-12
|
||||
@@ -292,10 +298,10 @@ jobs:
|
||||
build_node_package: true
|
||||
continue-on-error: false
|
||||
node: 20
|
||||
runs-on: ubuntu-24.04
|
||||
runs-on: ubuntu-22.04
|
||||
BUILD_TYPE: Release
|
||||
CCOMPILER: clang-16
|
||||
CXXCOMPILER: clang++-16
|
||||
CCOMPILER: clang-13
|
||||
CXXCOMPILER: clang++-13
|
||||
ENABLE_CONAN: ON
|
||||
NODE_PACKAGE_TESTS_ONLY: ON
|
||||
|
||||
@@ -303,10 +309,10 @@ jobs:
|
||||
build_node_package: true
|
||||
continue-on-error: false
|
||||
node: 20
|
||||
runs-on: ubuntu-24.04
|
||||
runs-on: ubuntu-22.04
|
||||
BUILD_TYPE: Debug
|
||||
CCOMPILER: clang-16
|
||||
CXXCOMPILER: clang++-16
|
||||
CCOMPILER: clang-13
|
||||
CXXCOMPILER: clang++-13
|
||||
ENABLE_CONAN: ON
|
||||
NODE_PACKAGE_TESTS_ONLY: ON
|
||||
|
||||
@@ -338,6 +344,7 @@ jobs:
|
||||
continue-on-error: ${{ matrix.continue-on-error }}
|
||||
runs-on: ${{ matrix.runs-on }}
|
||||
env:
|
||||
BUILD_TOOLS: ${{ matrix.BUILD_TOOLS }}
|
||||
BUILD_TYPE: ${{ matrix.BUILD_TYPE }}
|
||||
BUILD_SHARED_LIBS: ${{ matrix.BUILD_SHARED_LIBS }}
|
||||
CCOMPILER: ${{ matrix.CCOMPILER }}
|
||||
@@ -354,7 +361,6 @@ jobs:
|
||||
TARGET_ARCH: ${{ matrix.TARGET_ARCH }}
|
||||
OSRM_CONNECTION_RETRIES: ${{ matrix.OSRM_CONNECTION_RETRIES }}
|
||||
OSRM_CONNECTION_EXP_BACKOFF_COEF: ${{ matrix.OSRM_CONNECTION_EXP_BACKOFF_COEF }}
|
||||
ENABLE_LTO: ${{ matrix.ENABLE_LTO }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Build machine architecture
|
||||
@@ -482,13 +488,6 @@ jobs:
|
||||
tar zxvf onetbb.tgz
|
||||
sudo cp -a oneapi-tbb-${TBB_VERSION}/lib/. /usr/local/lib/
|
||||
sudo cp -a oneapi-tbb-${TBB_VERSION}/include/. /usr/local/include/
|
||||
- name: Add Clang 18 to list of Conan compilers # workaround for the issue that Conan 1.x doesn't know about Clang 18
|
||||
if: ${{ matrix.ENABLE_CONAN == 'ON' && matrix.CCOMPILER == 'clang-18' }}
|
||||
run: |
|
||||
sudo wget https://github.com/mikefarah/yq/releases/download/v4.9.6/yq_linux_amd64 -O /usr/bin/yq && sudo chmod +x /usr/bin/yq
|
||||
|
||||
conan config init
|
||||
yq eval '.compiler.clang.version += ["18"]' -i "$HOME/.conan/settings.yml"
|
||||
- name: Prepare build
|
||||
run: |
|
||||
mkdir ${OSRM_BUILD_DIR}
|
||||
@@ -520,8 +519,8 @@ jobs:
|
||||
-DENABLE_COVERAGE=${ENABLE_COVERAGE:-OFF} \
|
||||
-DENABLE_NODE_BINDINGS=${ENABLE_NODE_BINDINGS:-OFF} \
|
||||
-DENABLE_SANITIZER=${ENABLE_SANITIZER:-OFF} \
|
||||
-DBUILD_TOOLS=${BUILD_TOOLS:-OFF} \
|
||||
-DENABLE_CCACHE=ON \
|
||||
-DENABLE_LTO=${ENABLE_LTO:-ON} \
|
||||
-DCMAKE_INSTALL_PREFIX=${OSRM_INSTALL_DIR}
|
||||
make --jobs=${JOBS}
|
||||
|
||||
@@ -536,6 +535,13 @@ jobs:
|
||||
echo "PKG_CONFIG_PATH=${OSRM_INSTALL_DIR}/lib/pkgconfig" >> $GITHUB_ENV
|
||||
fi
|
||||
popd
|
||||
- name: Build example
|
||||
if: ${{ matrix.NODE_PACKAGE_TESTS_ONLY != 'ON' }}
|
||||
run: |
|
||||
mkdir example/build && pushd example/build
|
||||
cmake .. -DCMAKE_BUILD_TYPE=${BUILD_TYPE}
|
||||
make --jobs=${JOBS}
|
||||
popd
|
||||
- name: Run all tests
|
||||
if: ${{ matrix.NODE_PACKAGE_TESTS_ONLY != 'ON' }}
|
||||
run: |
|
||||
@@ -543,6 +549,7 @@ jobs:
|
||||
|
||||
# macOS SIP strips the linker path. Reset this inside the running shell
|
||||
export LD_LIBRARY_PATH=${{ env.LD_LIBRARY_PATH }}
|
||||
./example/build/osrm-example test/data/mld/monaco.osrm
|
||||
|
||||
# All tests assume to be run from the build directory
|
||||
pushd ${OSRM_BUILD_DIR}
|
||||
@@ -631,12 +638,12 @@ jobs:
|
||||
benchmarks:
|
||||
if: github.event_name == 'pull_request'
|
||||
needs: [format-taginfo-docs]
|
||||
runs-on: ubuntu-24.04
|
||||
runs-on: ubuntu-22.04
|
||||
env:
|
||||
CCOMPILER: clang-16
|
||||
CXXCOMPILER: clang++-16
|
||||
CC: clang-16
|
||||
CXX: clang++-16
|
||||
CCOMPILER: clang-13
|
||||
CXXCOMPILER: clang++-13
|
||||
CC: clang-13
|
||||
CXX: clang++-13
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
PR_NUMBER: ${{ github.event.pull_request.number }}
|
||||
GITHUB_REPOSITORY: ${{ github.repository }}
|
||||
@@ -671,7 +678,7 @@ jobs:
|
||||
path: pr
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
python3 -m pip install "conan<2.0.0" "requests==2.31.0" "numpy==1.26.4" --break-system-packages
|
||||
python3 -m pip install "conan<2.0.0" "requests==2.31.0" "numpy==1.26.4"
|
||||
sudo apt-get update -y && sudo apt-get install ccache
|
||||
- name: Prepare data
|
||||
run: |
|
||||
@@ -681,7 +688,7 @@ jobs:
|
||||
gunzip -c ./pr/test/data/poland_gps_traces.csv.gz > ~/gps_traces.csv
|
||||
else
|
||||
if [ ! -f "~/data.osm.pbf" ]; then
|
||||
wget http://download.geofabrik.de/europe/germany/berlin-latest.osm.pbf -O ~/data.osm.pbf
|
||||
wget http://download.geofabrik.de/europe/germany/berlin-latest.osm.pbf -O ~/data.osm.pbf --quiet
|
||||
else
|
||||
echo "Using cached data.osm.pbf"
|
||||
fi
|
||||
|
||||
@@ -1,9 +1,5 @@
|
||||
name: 'Close stale issues'
|
||||
on:
|
||||
# NOTE: uncomment if you want to test changes to this file in PRs CI
|
||||
# pull_request:
|
||||
# branches:
|
||||
# - master
|
||||
schedule:
|
||||
- cron: '30 1 * * *' # every day at 1:30am
|
||||
permissions:
|
||||
@@ -16,7 +12,6 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/stale@v9
|
||||
with:
|
||||
operations-per-run: 3000
|
||||
stale-issue-message: 'This issue seems to be stale. It will be closed in 30 days if no further activity occurs.'
|
||||
stale-pr-message: 'This PR seems to be stale. Is it still relevant?'
|
||||
days-before-issue-stale: 180 # 6 months
|
||||
|
||||
@@ -43,6 +43,7 @@ Thumbs.db
|
||||
#######################
|
||||
/_build*
|
||||
/build/
|
||||
/example/build/
|
||||
/test/data/monaco.osrm*
|
||||
/test/data/ch
|
||||
/test/data/corech
|
||||
|
||||
@@ -24,11 +24,6 @@
|
||||
- NodeJS:
|
||||
- CHANGED: Use node-api instead of NAN. [#6452](https://github.com/Project-OSRM/osrm-backend/pull/6452)
|
||||
- Misc:
|
||||
- CHANGED: Add .reserve(...) to assembleGeometry function. [#6983](https://github.com/Project-OSRM/osrm-backend/pull/6983)
|
||||
- CHANGED: Get rid of boost::optional leftovers. [#6977](https://github.com/Project-OSRM/osrm-backend/pull/6977)
|
||||
- CHANGED: Use Link Time Optimisation whenever possible. [#6967](https://github.com/Project-OSRM/osrm-backend/pull/6967)
|
||||
- CHANGED: Use struct instead of tuple to define UnpackedPath. [#6974](https://github.com/Project-OSRM/osrm-backend/pull/6974)
|
||||
- CHANGED: Micro performance optimisation in map matching. [#6976](https://github.com/Project-OSRM/osrm-backend/pull/6976)
|
||||
- CHANGED: Re-use priority queue in StaticRTree. [#6952](https://github.com/Project-OSRM/osrm-backend/pull/6952)
|
||||
- CHANGED: Optimise encodePolyline function. [#6940](https://github.com/Project-OSRM/osrm-backend/pull/6940)
|
||||
- CHANGED: Avoid reallocations in base64 encoding. [#6951](https://github.com/Project-OSRM/osrm-backend/pull/6951)
|
||||
|
||||
+110
-44
@@ -1,5 +1,5 @@
|
||||
cmake_minimum_required(VERSION 3.18)
|
||||
project(OSRM C CXX)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 20)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
set(CMAKE_CXX_EXTENSIONS OFF)
|
||||
@@ -10,12 +10,6 @@ Please create a directory and run cmake from there, passing the path to this sou
|
||||
This process created the file `CMakeCache.txt' and the directory `CMakeFiles'. Please delete them.")
|
||||
endif()
|
||||
|
||||
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
|
||||
message(STATUS "Building on a 64 bit system")
|
||||
else()
|
||||
message(FATAL_ERROR "Building on a 32 bit system is not supported")
|
||||
endif()
|
||||
|
||||
# detect if this is included as subproject and if so expose
|
||||
# some variables to its parent scope
|
||||
get_directory_property(BUILD_AS_SUBPROJECT PARENT_DIRECTORY)
|
||||
@@ -28,37 +22,41 @@ if (NOT WIN32 AND NOT DEFINED ENV{OSRM_BUILD_DIR})
|
||||
set(ENV{OSRM_BUILD_DIR} ${CMAKE_CURRENT_BINARY_DIR})
|
||||
endif()
|
||||
|
||||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
|
||||
|
||||
option(BUILD_PACKAGE "Build OSRM package" OFF)
|
||||
option(ENABLE_ASSERTIONS "Use assertions in release mode" OFF)
|
||||
option(ENABLE_CCACHE "Speed up incremental rebuilds via ccache" ON)
|
||||
option(ENABLE_CLANG_TIDY "Enables clang-tidy checks" OFF)
|
||||
option(ENABLE_CONAN "Use conan for dependencies" OFF)
|
||||
option(ENABLE_COVERAGE "Build with coverage instrumentalisation" OFF)
|
||||
option(ENABLE_CCACHE "Speed up incremental rebuilds via ccache" ON)
|
||||
option(BUILD_TOOLS "Build OSRM tools" OFF)
|
||||
option(BUILD_PACKAGE "Build OSRM package" OFF)
|
||||
option(BUILD_ROUTED "Build osrm-routed HTTP server" ON)
|
||||
option(ENABLE_ASSERTIONS "Use assertions in release mode" OFF)
|
||||
option(ENABLE_DEBUG_LOGGING "Use debug logging in release mode" OFF)
|
||||
option(ENABLE_FUZZING "Fuzz testing using LLVM's libFuzzer" OFF)
|
||||
option(ENABLE_LTO "Use Link Time Optimisation" ON)
|
||||
option(ENABLE_NODE_BINDINGS "Build NodeJs bindings" OFF)
|
||||
option(ENABLE_COVERAGE "Build with coverage instrumentalisation" OFF)
|
||||
option(ENABLE_SANITIZER "Use memory sanitizer for Debug build" OFF)
|
||||
option(ENABLE_LTO "Use LTO if available" OFF)
|
||||
option(ENABLE_FUZZING "Fuzz testing using LLVM's libFuzzer" OFF)
|
||||
option(ENABLE_NODE_BINDINGS "Build NodeJs bindings" OFF)
|
||||
option(ENABLE_CLANG_TIDY "Enables clang-tidy checks" OFF)
|
||||
|
||||
if (ENABLE_CLANG_TIDY)
|
||||
find_program(CLANG_TIDY_COMMAND NAMES clang-tidy REQUIRED)
|
||||
message(STATUS "Found clang-tidy at ${CLANG_TIDY_COMMAND}")
|
||||
set(CMAKE_CXX_CLANG_TIDY "${CLANG_TIDY_COMMAND};--warnings-as-errors=*;--header-filter=.*")
|
||||
endif()
|
||||
|
||||
if(ENABLE_LTO AND (CMAKE_BUILD_TYPE MATCHES Release OR CMAKE_BUILD_TYPE MATCHES MinRelSize OR CMAKE_BUILD_TYPE MATCHES RelWithDebInfo))
|
||||
include(CheckIPOSupported)
|
||||
check_ipo_supported(RESULT LTO_SUPPORTED OUTPUT error)
|
||||
if(LTO_SUPPORTED)
|
||||
message(STATUS "IPO / LTO enabled")
|
||||
set(CMAKE_INTERPROCEDURAL_OPTIMIZATION TRUE)
|
||||
find_program(CLANG_TIDY_COMMAND NAMES clang-tidy)
|
||||
if(NOT CLANG_TIDY_COMMAND)
|
||||
message(FATAL_ERROR "ENABLE_CLANG_TIDY is ON but clang-tidy is not found!")
|
||||
else()
|
||||
message(FATAL_ERROR "IPO / LTO not supported: <${error}>")
|
||||
message(STATUS "Found clang-tidy at ${CLANG_TIDY_COMMAND}")
|
||||
set(CMAKE_CXX_CLANG_TIDY "${CLANG_TIDY_COMMAND};--warnings-as-errors=*;--header-filter=.*")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
|
||||
|
||||
# be compatible with version handling before cmake 3.x
|
||||
if (POLICY CMP0057)
|
||||
cmake_policy(SET CMP0057 NEW)
|
||||
endif()
|
||||
if (POLICY CMP0074)
|
||||
cmake_policy(SET CMP0074 NEW)
|
||||
endif()
|
||||
project(OSRM C CXX)
|
||||
|
||||
# add @loader_path/$ORIGIN to rpath to make binaries relocatable
|
||||
if (APPLE)
|
||||
set(CMAKE_BUILD_RPATH "@loader_path")
|
||||
@@ -75,14 +73,14 @@ sbeParseJson(packagejson packagejsonraw)
|
||||
# This regex is not strict enough, but the correct one is too complicated for cmake matching.
|
||||
# https://semver.org/#is-there-a-suggested-regular-expression-regex-to-check-a-semver-string
|
||||
if (packagejson.version MATCHES "^([0-9]+)\.([0-9]+)\.([0-9]+)([-+][0-9a-zA-Z.-]+)?$")
|
||||
set(OSRM_VERSION_MAJOR ${CMAKE_MATCH_1})
|
||||
set(OSRM_VERSION_MINOR ${CMAKE_MATCH_2})
|
||||
set(OSRM_VERSION_PATCH ${CMAKE_MATCH_3})
|
||||
set(OSRM_VERSION_PRERELEASE_BUILD ${CMAKE_MATCH_4})
|
||||
set(OSRM_VERSION_MAJOR ${CMAKE_MATCH_1})
|
||||
set(OSRM_VERSION_MINOR ${CMAKE_MATCH_2})
|
||||
set(OSRM_VERSION_PATCH ${CMAKE_MATCH_3})
|
||||
set(OSRM_VERSION_PRERELEASE_BUILD ${CMAKE_MATCH_4})
|
||||
|
||||
set(OSRM_VERSION packagejson.version)
|
||||
set(OSRM_VERSION packagejson.version)
|
||||
else()
|
||||
message(FATAL_ERROR "Version from package.json cannot be parsed, expected semver compatible label, but found ${packagejson.version}")
|
||||
message(FATAL_ERROR "Version from package.json cannot be parsed, expected semver compatible label, but found ${packagejson.version}")
|
||||
endif()
|
||||
|
||||
if (MSVC)
|
||||
@@ -114,6 +112,12 @@ include(CheckCXXCompilerFlag)
|
||||
include(FindPackageHandleStandardArgs)
|
||||
include(GNUInstallDirs)
|
||||
|
||||
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
|
||||
message(STATUS "Building on a 64 bit system")
|
||||
else()
|
||||
message(FATAL_ERROR "Building on a 32 bit system is not supported")
|
||||
endif()
|
||||
|
||||
include_directories(BEFORE ${CMAKE_CURRENT_BINARY_DIR}/include/)
|
||||
include_directories(BEFORE ${CMAKE_CURRENT_SOURCE_DIR}/include/)
|
||||
include_directories(SYSTEM ${CMAKE_CURRENT_SOURCE_DIR}/third_party/sol2/include)
|
||||
@@ -134,6 +138,7 @@ file(GLOB UpdaterGlob src/updater/*.cpp)
|
||||
file(GLOB StorageGlob src/storage/*.cpp)
|
||||
file(GLOB ServerGlob src/server/*.cpp src/server/**/*.cpp)
|
||||
file(GLOB EngineGlob src/engine/*.cpp src/engine/**/*.cpp)
|
||||
file(GLOB ErrorcodesGlob src/osrm/errorcodes.cpp)
|
||||
|
||||
add_library(UTIL OBJECT ${UtilGlob})
|
||||
add_library(EXTRACTOR OBJECT ${ExtractorGlob})
|
||||
@@ -144,11 +149,14 @@ add_library(CONTRACTOR OBJECT ${ContractorGlob})
|
||||
add_library(UPDATER OBJECT ${UpdaterGlob})
|
||||
add_library(STORAGE OBJECT ${StorageGlob})
|
||||
add_library(ENGINE OBJECT ${EngineGlob})
|
||||
add_library(SERVER OBJECT ${ServerGlob})
|
||||
|
||||
if (BUILD_ROUTED)
|
||||
add_library(SERVER OBJECT ${ServerGlob})
|
||||
add_executable(osrm-routed src/tools/routed.cpp $<TARGET_OBJECTS:SERVER> $<TARGET_OBJECTS:UTIL>)
|
||||
endif()
|
||||
|
||||
set_target_properties(UTIL PROPERTIES LINKER_LANGUAGE CXX)
|
||||
|
||||
add_executable(osrm-routed src/tools/routed.cpp $<TARGET_OBJECTS:SERVER> $<TARGET_OBJECTS:UTIL>)
|
||||
add_executable(osrm-extract src/tools/extract.cpp)
|
||||
add_executable(osrm-partition src/tools/partition.cpp)
|
||||
add_executable(osrm-customize src/tools/customize.cpp)
|
||||
@@ -200,6 +208,17 @@ if(CMAKE_CXX_COMPILER_ID MATCHES "GNU")
|
||||
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -Og -ggdb")
|
||||
endif()
|
||||
|
||||
if(ENABLE_LTO AND (CMAKE_BUILD_TYPE MATCHES Release OR CMAKE_BUILD_TYPE MATCHES MinRelSize OR CMAKE_BUILD_TYPE MATCHES RelWithDebInfo))
|
||||
include(CheckIPOSupported)
|
||||
check_ipo_supported(RESULT LTO_SUPPORTED OUTPUT error)
|
||||
if(LTO_SUPPORTED)
|
||||
message(STATUS "IPO / LTO enabled")
|
||||
set(CMAKE_INTERPROCEDURAL_OPTIMIZATION TRUE)
|
||||
else()
|
||||
message(WARNING "IPO / LTO not supported: <${error}>")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set(MAYBE_COVERAGE_LIBRARIES "")
|
||||
if (ENABLE_COVERAGE)
|
||||
if (NOT CMAKE_BUILD_TYPE MATCHES "Debug")
|
||||
@@ -271,7 +290,6 @@ include_directories(SYSTEM ${MICROTAR_INCLUDE_DIR})
|
||||
|
||||
add_library(MICROTAR OBJECT "${CMAKE_CURRENT_SOURCE_DIR}/third_party/microtar/src/microtar.c")
|
||||
set_property(TARGET MICROTAR PROPERTY POSITION_INDEPENDENT_CODE ON)
|
||||
|
||||
target_no_warning(MICROTAR unused-variable)
|
||||
target_no_warning(MICROTAR format)
|
||||
|
||||
@@ -281,6 +299,10 @@ include_directories(SYSTEM ${PROTOZERO_INCLUDE_DIR})
|
||||
set(VTZERO_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/third_party/vtzero/include")
|
||||
include_directories(SYSTEM ${VTZERO_INCLUDE_DIR})
|
||||
|
||||
set(ANKERL_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/third_party/unordered_dense/include")
|
||||
include_directories(SYSTEM ${ANKERL_INCLUDE_DIR})
|
||||
|
||||
|
||||
set(FLATBUFFERS_BUILD_TESTS OFF CACHE BOOL "Disable the build of Flatbuffers tests and samples.")
|
||||
set(FLATBUFFERS_SRC_DIR "${CMAKE_CURRENT_SOURCE_DIR}/third_party/flatbuffers")
|
||||
set(FLATBUFFERS_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/third_party/flatbuffers/include")
|
||||
@@ -458,7 +480,9 @@ target_link_libraries(osrm-extract osrm_extract ${Boost_PROGRAM_OPTIONS_LIBRARY}
|
||||
target_link_libraries(osrm-partition osrm_partition ${Boost_PROGRAM_OPTIONS_LIBRARY})
|
||||
target_link_libraries(osrm-customize osrm_customize ${Boost_PROGRAM_OPTIONS_LIBRARY})
|
||||
target_link_libraries(osrm-contract osrm_contract ${Boost_PROGRAM_OPTIONS_LIBRARY})
|
||||
target_link_libraries(osrm-routed osrm ${Boost_PROGRAM_OPTIONS_LIBRARY} ${OPTIONAL_SOCKET_LIBS} ${ZLIB_LIBRARY})
|
||||
if (BUILD_ROUTED)
|
||||
target_link_libraries(osrm-routed osrm ${Boost_PROGRAM_OPTIONS_LIBRARY} ${OPTIONAL_SOCKET_LIBS} ${ZLIB_LIBRARY})
|
||||
endif()
|
||||
|
||||
set(EXTRACTOR_LIBRARIES
|
||||
${BZIP2_LIBRARIES}
|
||||
@@ -532,13 +556,18 @@ target_link_libraries(osrm_partition ${PARTITIONER_LIBRARIES})
|
||||
target_link_libraries(osrm_customize ${CUSTOMIZER_LIBRARIES} osrm_update osrm_store)
|
||||
target_link_libraries(osrm_store ${STORAGE_LIBRARIES})
|
||||
|
||||
# BUILD_COMPONENTS
|
||||
add_executable(osrm-components src/tools/components.cpp $<TARGET_OBJECTS:MICROTAR> $<TARGET_OBJECTS:UTIL>)
|
||||
target_link_libraries(osrm-components ${TBB_LIBRARIES} ${BOOST_BASE_LIBRARIES} ${UTIL_LIBRARIES})
|
||||
install(TARGETS osrm-components DESTINATION bin)
|
||||
|
||||
add_executable(osrm-io-benchmark src/tools/io-benchmark.cpp $<TARGET_OBJECTS:UTIL>)
|
||||
target_link_libraries(osrm-io-benchmark ${BOOST_BASE_LIBRARIES} ${TBB_LIBRARIES})
|
||||
install(TARGETS osrm-io-benchmark DESTINATION bin)
|
||||
if(BUILD_TOOLS)
|
||||
message(STATUS "Activating OSRM internal tools")
|
||||
add_executable(osrm-io-benchmark src/tools/io-benchmark.cpp $<TARGET_OBJECTS:UTIL>)
|
||||
target_link_libraries(osrm-io-benchmark ${BOOST_BASE_LIBRARIES} ${TBB_LIBRARIES})
|
||||
|
||||
install(TARGETS osrm-io-benchmark DESTINATION bin)
|
||||
endif()
|
||||
|
||||
if (ENABLE_ASSERTIONS)
|
||||
message(STATUS "Enabling assertions")
|
||||
@@ -557,14 +586,47 @@ set_property(TARGET osrm-extract PROPERTY INSTALL_RPATH_USE_LINK_PATH TRUE)
|
||||
set_property(TARGET osrm-partition PROPERTY INSTALL_RPATH_USE_LINK_PATH TRUE)
|
||||
set_property(TARGET osrm-contract PROPERTY INSTALL_RPATH_USE_LINK_PATH TRUE)
|
||||
set_property(TARGET osrm-datastore PROPERTY INSTALL_RPATH_USE_LINK_PATH TRUE)
|
||||
set_property(TARGET osrm-routed PROPERTY INSTALL_RPATH_USE_LINK_PATH TRUE)
|
||||
if (BUILD_ROUTED)
|
||||
set_property(TARGET osrm-routed PROPERTY INSTALL_RPATH_USE_LINK_PATH TRUE)
|
||||
endif()
|
||||
|
||||
file(GLOB FlatbuffersGlob third_party/flatbuffers/include/flatbuffers/*.h)
|
||||
file(GLOB LibraryGlob include/osrm/*.hpp)
|
||||
file(GLOB ParametersGlob include/engine/api/*_parameters.hpp)
|
||||
set(ApiHeader include/engine/api/base_result.hpp)
|
||||
set(EngineHeader include/engine/status.hpp include/engine/engine_config.hpp include/engine/hint.hpp include/engine/bearing.hpp include/engine/approach.hpp include/engine/phantom_node.hpp)
|
||||
set(UtilHeader include/util/coordinate.hpp include/util/json_container.hpp include/util/typedefs.hpp include/util/alias.hpp include/util/exception.hpp include/util/bearing.hpp)
|
||||
set(ExtractorHeader include/extractor/extractor.hpp include/storage/io_config.hpp include/extractor/extractor_config.hpp include/extractor/travel_mode.hpp)
|
||||
set(PartitionerHeader include/partitioner/partitioner.hpp include/partitioner/partitioner_config.hpp)
|
||||
set(ContractorHeader include/contractor/contractor.hpp include/contractor/contractor_config.hpp)
|
||||
set(StorageHeader include/storage/storage.hpp include/storage/io_config.hpp include/storage/storage_config.hpp)
|
||||
install(FILES ${EngineHeader} DESTINATION include/osrm/engine)
|
||||
install(FILES ${UtilHeader} DESTINATION include/osrm/util)
|
||||
install(FILES ${StorageHeader} DESTINATION include/osrm/storage)
|
||||
install(FILES ${ExtractorHeader} DESTINATION include/osrm/extractor)
|
||||
install(FILES ${PartitionerHeader} DESTINATION include/osrm/partitioner)
|
||||
install(FILES ${ContractorHeader} DESTINATION include/osrm/contractor)
|
||||
install(FILES ${LibraryGlob} DESTINATION include/osrm)
|
||||
install(FILES ${ParametersGlob} DESTINATION include/osrm/engine/api)
|
||||
install(FILES ${ApiHeader} DESTINATION include/osrm/engine/api)
|
||||
install(FILES ${FlatbuffersGlob} DESTINATION include/flatbuffers)
|
||||
install(TARGETS osrm-extract DESTINATION bin)
|
||||
install(TARGETS osrm-partition DESTINATION bin)
|
||||
install(TARGETS osrm-customize DESTINATION bin)
|
||||
install(TARGETS osrm-contract DESTINATION bin)
|
||||
install(TARGETS osrm-datastore DESTINATION bin)
|
||||
install(TARGETS osrm-routed DESTINATION bin)
|
||||
if (BUILD_ROUTED)
|
||||
install(TARGETS osrm-routed DESTINATION bin)
|
||||
endif()
|
||||
install(TARGETS osrm DESTINATION lib)
|
||||
install(TARGETS osrm_extract DESTINATION lib)
|
||||
install(TARGETS osrm_partition DESTINATION lib)
|
||||
install(TARGETS osrm_customize DESTINATION lib)
|
||||
install(TARGETS osrm_update DESTINATION lib)
|
||||
install(TARGETS osrm_contract DESTINATION lib)
|
||||
install(TARGETS osrm_store DESTINATION lib)
|
||||
install(TARGETS osrm_guidance DESTINATION lib)
|
||||
|
||||
|
||||
# Install profiles and support library to /usr/local/share/osrm/profiles by default
|
||||
set(DefaultProfilesDir profiles)
|
||||
@@ -575,6 +637,8 @@ set(DefaultProfilesDir data)
|
||||
install(DIRECTORY ${DefaultProfilesDir} DESTINATION share/osrm)
|
||||
|
||||
# Setup exporting variables for pkgconfig and subproject
|
||||
#
|
||||
|
||||
if(BUILD_PACKAGE)
|
||||
include(CPackConfig)
|
||||
include(CPack)
|
||||
@@ -651,6 +715,7 @@ if (ENABLE_NODE_BINDINGS)
|
||||
add_subdirectory(src/nodejs)
|
||||
endif()
|
||||
|
||||
|
||||
if (ENABLE_FUZZING)
|
||||
# Requires libosrm being built with sanitizers; make configurable and default to ubsan
|
||||
set(FUZZ_SANITIZER "undefined" CACHE STRING "Sanitizer to be used for Fuzz testing")
|
||||
@@ -684,3 +749,4 @@ foreach(header ${headers_to_check})
|
||||
endforeach()
|
||||
add_library(check-headers STATIC EXCLUDE_FROM_ALL ${sources})
|
||||
set_target_properties(check-headers PROPERTIES ARCHIVE_OUTPUT_DIRECTORY ${check_headers_dir})
|
||||
|
||||
|
||||
@@ -64,6 +64,7 @@ add_warning(init-self)
|
||||
add_warning(bool-compare)
|
||||
add_warning(logical-not-parentheses)
|
||||
add_warning(logical-op)
|
||||
add_warning(maybe-uninitialized)
|
||||
add_warning(misleading-indentation)
|
||||
# `no-` prefix is part of warning name(i.e. doesn't mean we are disabling it)
|
||||
add_warning(no-return-local-addr)
|
||||
@@ -83,6 +84,3 @@ no_warning(comma-subscript)
|
||||
no_warning(ambiguous-reversed-operator)
|
||||
no_warning(restrict)
|
||||
no_warning(free-nonheap-object)
|
||||
if(CMAKE_CXX_COMPILER_ID MATCHES "GNU")
|
||||
no_warning(stringop-overflow)
|
||||
endif()
|
||||
@@ -27,10 +27,11 @@ RUN NPROC=${BUILD_CONCURRENCY:-$(nproc)} && \
|
||||
cd build && \
|
||||
BUILD_TYPE="Release" && \
|
||||
ENABLE_ASSERTIONS="Off" && \
|
||||
BUILD_TOOLS="Off" && \
|
||||
case ${DOCKER_TAG} in *"-debug"*) BUILD_TYPE="Debug";; esac && \
|
||||
case ${DOCKER_TAG} in *"-assertions"*) BUILD_TYPE="RelWithDebInfo" && ENABLE_ASSERTIONS="On";; esac && \
|
||||
echo "Building ${BUILD_TYPE} with ENABLE_ASSERTIONS=${ENABLE_ASSERTIONS} && \
|
||||
cmake .. -DCMAKE_BUILD_TYPE=${BUILD_TYPE} -DENABLE_ASSERTIONS=${ENABLE_ASSERTIONS} -DENABLE_LTO=OFF && \
|
||||
case ${DOCKER_TAG} in *"-assertions"*) BUILD_TYPE="RelWithDebInfo" && ENABLE_ASSERTIONS="On" && BUILD_TOOLS="On";; esac && \
|
||||
echo "Building ${BUILD_TYPE} with ENABLE_ASSERTIONS=${ENABLE_ASSERTIONS} BUILD_TOOLS=${BUILD_TOOLS}" && \
|
||||
cmake .. -DCMAKE_BUILD_TYPE=${BUILD_TYPE} -DENABLE_ASSERTIONS=${ENABLE_ASSERTIONS} -DBUILD_TOOLS=${BUILD_TOOLS} -DENABLE_LTO=On && \
|
||||
make -j${NPROC} install && \
|
||||
cd ../profiles && \
|
||||
cp -r * /opt && \
|
||||
|
||||
@@ -21,7 +21,7 @@ COPY . /src
|
||||
WORKDIR /src
|
||||
|
||||
RUN NPROC=${BUILD_CONCURRENCY:-$(nproc)} && \
|
||||
export CXXFLAGS="-Wno-array-bounds -Wno-uninitialized -Wno-stringop-overflow" && \
|
||||
export CXXFLAGS="-Wno-array-bounds -Wno-uninitialized" && \
|
||||
echo "Building OSRM ${DOCKER_TAG}" && \
|
||||
git show --format="%H" | head -n1 > /opt/OSRM_GITSHA && \
|
||||
echo "Building OSRM gitsha $(cat /opt/OSRM_GITSHA)" && \
|
||||
@@ -29,10 +29,11 @@ RUN NPROC=${BUILD_CONCURRENCY:-$(nproc)} && \
|
||||
cd build && \
|
||||
BUILD_TYPE="Release" && \
|
||||
ENABLE_ASSERTIONS="Off" && \
|
||||
BUILD_TOOLS="Off" && \
|
||||
case ${DOCKER_TAG} in *"-debug"*) BUILD_TYPE="Debug";; esac && \
|
||||
case ${DOCKER_TAG} in *"-assertions"*) BUILD_TYPE="RelWithDebInfo" && ENABLE_ASSERTIONS="On";; esac && \
|
||||
echo "Building ${BUILD_TYPE} with ENABLE_ASSERTIONS=${ENABLE_ASSERTIONS} && \
|
||||
cmake .. -DCMAKE_BUILD_TYPE=${BUILD_TYPE} -DENABLE_ASSERTIONS=${ENABLE_ASSERTIONS} -DENABLE_LTO=On && \
|
||||
case ${DOCKER_TAG} in *"-assertions"*) BUILD_TYPE="RelWithDebInfo" && ENABLE_ASSERTIONS="On" && BUILD_TOOLS="On";; esac && \
|
||||
echo "Building ${BUILD_TYPE} with ENABLE_ASSERTIONS=${ENABLE_ASSERTIONS} BUILD_TOOLS=${BUILD_TOOLS}" && \
|
||||
cmake .. -DCMAKE_BUILD_TYPE=${BUILD_TYPE} -DENABLE_ASSERTIONS=${ENABLE_ASSERTIONS} -DBUILD_TOOLS=${BUILD_TOOLS} -DENABLE_LTO=On && \
|
||||
make -j${NPROC} install && \
|
||||
cd ../profiles && \
|
||||
cp -r * /opt && \
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
## Introduction
|
||||
|
||||
OSRM can be used as a library (libosrm) via C++ instead of using it through the HTTP interface and `osrm-routed`. This allows for fine-tuning OSRM and has much less overhead. Here is a quick introduction into how to use `libosrm` in the upcoming v5 release.
|
||||
|
||||
Take a look at the example code that lives in the [example directory](https://github.com/Project-OSRM/osrm-backend/tree/master/example). Here is all you ever wanted to know about `libosrm`, that is a short description of what the types do and where to find documentation on it:
|
||||
|
||||
## Important interface objects
|
||||
|
||||
- [`EngineConfig`](https://github.com/Project-OSRM/osrm-backend/blob/master/include/engine/engine_config.hpp) - for initializing an OSRM instance we can configure certain properties and constraints. E.g. the storage config is the base path such as `france.osm.osrm` from which we derive and load `france.osm.osrm.*` auxiliary files. This also lets you set constraints such as the maximum number of locations allowed for specific services.
|
||||
|
||||
- [`OSRM`](https://github.com/Project-OSRM/osrm-backend/blob/master/include/osrm/osrm.hpp) - this is the main Routing Machine type with functions such as `Route` and `Table`. You initialize it with a `EngineConfig`. It does all the heavy lifting for you. Each function takes its own parameters, e.g. the `Route` function takes `RouteParameters`, and a out-reference to a JSON result that gets filled. The return value is a `Status`, indicating error or success.
|
||||
|
||||
- [`Status`](https://github.com/Project-OSRM/osrm-backend/blob/master/include/engine/status.hpp) - this is a type wrapping `Error` or `Ok` for indicating error or success, respectively.
|
||||
|
||||
- [`TableParameters`](https://github.com/Project-OSRM/osrm-backend/blob/master/include/engine/api/table_parameters.hpp) - this is an example of parameter types the Routing Machine functions expect. In this case `Table` expects its own parameters as `TableParameters`. You can see it wrapping two vectors, sources and destinations --- these are indices into your coordinates for the table service to construct a matrix from (empty sources or destinations means: use all of them). If you ask yourself where coordinates come from, you can see `TableParameters` inheriting from `BaseParameters`.
|
||||
|
||||
- [`BaseParameter`](https://github.com/Project-OSRM/osrm-backend/blob/master/include/engine/api/base_parameters.hpp) - this most importantly holds coordinates (and a few other optional properties that you don't need for basic usage); the specific parameter types inherit from `BaseParameters` to get these member attributes. That means your `TableParameters` type has `coordinates`, `sources` and `destination` member attributes (and a few other that we ignore for now).
|
||||
|
||||
- [`Coordinate`](https://github.com/Project-OSRM/osrm-backend/blob/master/include/util/coordinate.hpp) - this is a wrapper around a (longitude, latitude) pair. We really don't care about (lon,lat) vs (lat, lon) but we don't want you to accidentally mix them up, so both latitude and longitude are strictly typed wrappers around integers (fixed notation such as `13423240`) and floating points (floating notation such as `13.42324`).
|
||||
|
||||
- [Parameters for other services](https://github.com/Project-OSRM/osrm-backend/tree/master/include/engine/api) - here are all other `*Parameters` you need for other Routing Machine services.
|
||||
|
||||
- [JSON](https://github.com/Project-OSRM/osrm-backend/blob/master/include/util/json_container.hpp) - this is a sum type resembling JSON. The Routing Machine service functions take a out-ref to a JSON result and fill it accordingly. It is currently implemented using [mapbox/variant](https://github.com/mapbox/variant) which is similar to [Boost.Variant](http://www.boost.org/doc/libs/1_55_0/doc/html/variant.html). There are two ways to work with this sum type: either provide a visitor that acts on each type on visitation or use the `get` function in case you're sure about the structure. The JSON structure is written down in the [HTTP API](#http-api).
|
||||
|
||||
## Example
|
||||
|
||||
See [the example folder](https://github.com/Project-OSRM/osrm-backend/tree/master/example) in the OSRM repository.
|
||||
|
||||
## Workflow
|
||||
|
||||
- Create an `OSRM` instance initialized with a `EngineConfig`
|
||||
- Call the service function on the `OSRM` object providing service specific `*Parameters`
|
||||
- Check the return code and use the JSON result
|
||||
@@ -0,0 +1,34 @@
|
||||
cmake_minimum_required(VERSION 3.18)
|
||||
|
||||
if(CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_CURRENT_BINARY_DIR AND NOT MSVC_IDE)
|
||||
message(FATAL_ERROR "In-source builds are not allowed.
|
||||
Please create a directory and run cmake from there, passing the path to this source directory as the last argument.
|
||||
This process created the file `CMakeCache.txt' and the directory `CMakeFiles'. Please delete them.")
|
||||
endif()
|
||||
|
||||
if(NOT CMAKE_BUILD_TYPE MATCHES Debug)
|
||||
set(CMAKE_BUILD_TYPE Release)
|
||||
endif()
|
||||
|
||||
project(osrm-example C CXX)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
set(CMAKE_CXX_EXTENSIONS OFF)
|
||||
|
||||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
|
||||
|
||||
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
|
||||
message(STATUS "Building on a 64 bit system")
|
||||
else()
|
||||
message(STATUS "Building on a 32 bit system")
|
||||
endif()
|
||||
|
||||
link_directories(${LibOSRM_LIBRARY_DIRS})
|
||||
add_executable(osrm-example example.cpp)
|
||||
|
||||
find_package(LibOSRM REQUIRED)
|
||||
|
||||
target_link_libraries(osrm-example ${LibOSRM_LIBRARIES} ${LibOSRM_DEPENDENT_LIBRARIES})
|
||||
include_directories(SYSTEM ${LibOSRM_INCLUDE_DIRS})
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${LibOSRM_CXXFLAGS}")
|
||||
@@ -0,0 +1,63 @@
|
||||
# - Try to find LibOSRM
|
||||
# Once done this will define
|
||||
# LibOSRM_FOUND - System has LibOSRM
|
||||
# LibOSRM_LIBRARIES - The libraries and ldflags needed to use LibOSRM
|
||||
# LibOSRM_DEPENDENT_LIBRARIES - The libraries and ldflags need to link LibOSRM dependencies
|
||||
# LibOSRM_LIBRARY_DIRS - The libraries paths needed to find LibOSRM
|
||||
# LibOSRM_CXXFLAGS - Compiler switches required for using LibOSRM
|
||||
|
||||
find_package(PkgConfig)
|
||||
pkg_search_module(PC_LibOSRM QUIET libosrm)
|
||||
|
||||
function(JOIN VALUES GLUE OUTPUT)
|
||||
string (REPLACE ";" "${GLUE}" _TMP_STR "${VALUES}")
|
||||
set (${OUTPUT} "${_TMP_STR}" PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
list(REMOVE_ITEM PC_LibOSRM_CFLAGS " ")
|
||||
JOIN("${PC_LibOSRM_CFLAGS}" " " output)
|
||||
|
||||
set(LibOSRM_CXXFLAGS ${output})
|
||||
set(LibOSRM_LIBRARY_DIRS ${PC_LibOSRM_LIBRARY_DIRS})
|
||||
|
||||
find_path(LibOSRM_INCLUDE_DIR osrm/osrm.hpp
|
||||
PATH_SUFFIXES osrm include/osrm include
|
||||
HINTS ${PC_LibOSRM_INCLUDEDIR} ${PC_LibOSRM_INCLUDE_DIRS}
|
||||
~/Library/Frameworks
|
||||
/Library/Frameworks
|
||||
/usr/local
|
||||
/usr
|
||||
/opt/local
|
||||
/opt)
|
||||
|
||||
find_library(TEST_LibOSRM_STATIC_LIBRARY Names osrm.lib libosrm.a
|
||||
PATH_SUFFIXES osrm lib/osrm lib
|
||||
HINTS ${PC_LibOSRM_LIBDIR} ${PC_LibOSRM_LIBRARY_DIRS}
|
||||
~/Library/Frameworks
|
||||
/Library/Frameworks
|
||||
/usr/local
|
||||
/usr
|
||||
/opt/local
|
||||
/opt)
|
||||
find_library(TEST_LibOSRM_DYNAMIC_LIBRARY Names libosrm.dylib libosrm.so
|
||||
PATH_SUFFIXES osrm lib/osrm lib
|
||||
HINTS ${PC_LibOSRM_LIBDIR} ${PC_LibOSRM_LIBRARY_DIRS}
|
||||
~/Library/Frameworks
|
||||
/Library/Frameworks
|
||||
/usr/local
|
||||
/usr
|
||||
/opt/local
|
||||
/opt)
|
||||
|
||||
set(LibOSRM_DEPENDENT_LIBRARIES ${PC_LibOSRM_STATIC_LDFLAGS})
|
||||
set(LibOSRM_LIBRARIES ${PC_LibOSRM_LDFLAGS})
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
# handle the QUIETLY and REQUIRED arguments and set LIBOSRM_FOUND to TRUE
|
||||
# if all listed variables are TRUE
|
||||
find_package_handle_standard_args(LibOSRM DEFAULT_MSG
|
||||
LibOSRM_LIBRARY_DIRS
|
||||
LibOSRM_CXXFLAGS
|
||||
LibOSRM_LIBRARIES
|
||||
LibOSRM_DEPENDENT_LIBRARIES
|
||||
LibOSRM_INCLUDE_DIR)
|
||||
Symlink
+1
@@ -0,0 +1 @@
|
||||
../../cmake/FindTBB.cmake
|
||||
@@ -0,0 +1,90 @@
|
||||
#include "osrm/match_parameters.hpp"
|
||||
#include "osrm/nearest_parameters.hpp"
|
||||
#include "osrm/route_parameters.hpp"
|
||||
#include "osrm/table_parameters.hpp"
|
||||
#include "osrm/trip_parameters.hpp"
|
||||
|
||||
#include "osrm/coordinate.hpp"
|
||||
#include "osrm/engine_config.hpp"
|
||||
#include "osrm/json_container.hpp"
|
||||
|
||||
#include "osrm/osrm.hpp"
|
||||
#include "osrm/status.hpp"
|
||||
|
||||
#include <exception>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
#include <cstdlib>
|
||||
|
||||
int main(int argc, const char *argv[])
|
||||
{
|
||||
if (argc < 2)
|
||||
{
|
||||
std::cerr << "Usage: " << argv[0] << " data.osrm\n";
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
using namespace osrm;
|
||||
|
||||
// Configure based on a .osrm base path, and no datasets in shared mem from osrm-datastore
|
||||
EngineConfig config;
|
||||
|
||||
config.storage_config = {argv[1]};
|
||||
config.use_shared_memory = false;
|
||||
|
||||
// We support two routing speed up techniques:
|
||||
// - Contraction Hierarchies (CH): requires extract+contract pre-processing
|
||||
// - Multi-Level Dijkstra (MLD): requires extract+partition+customize pre-processing
|
||||
//
|
||||
// config.algorithm = EngineConfig::Algorithm::CH;
|
||||
config.algorithm = EngineConfig::Algorithm::MLD;
|
||||
|
||||
// Routing machine with several services (such as Route, Table, Nearest, Trip, Match)
|
||||
const OSRM osrm{config};
|
||||
|
||||
// The following shows how to use the Route service; configure this service
|
||||
RouteParameters params;
|
||||
|
||||
// Route in monaco
|
||||
params.coordinates.push_back({util::FloatLongitude{7.419758}, util::FloatLatitude{43.731142}});
|
||||
params.coordinates.push_back({util::FloatLongitude{7.419505}, util::FloatLatitude{43.736825}});
|
||||
|
||||
// Response is in JSON format
|
||||
engine::api::ResultT result = json::Object();
|
||||
|
||||
// Execute routing request, this does the heavy lifting
|
||||
const auto status = osrm.Route(params, result);
|
||||
|
||||
auto &json_result = std::get<json::Object>(result);
|
||||
if (status == Status::Ok)
|
||||
{
|
||||
auto &routes = std::get<json::Array>(json_result.values["routes"]);
|
||||
|
||||
// Let's just use the first route
|
||||
auto &route = std::get<json::Object>(routes.values.at(0));
|
||||
const auto distance = std::get<json::Number>(route.values["distance"]).value;
|
||||
const auto duration = std::get<json::Number>(route.values["duration"]).value;
|
||||
|
||||
// Warn users if extract does not contain the default coordinates from above
|
||||
if (distance == 0 || duration == 0)
|
||||
{
|
||||
std::cout << "Note: distance or duration is zero. ";
|
||||
std::cout << "You are probably doing a query outside of the OSM extract.\n\n";
|
||||
}
|
||||
|
||||
std::cout << "Distance: " << distance << " meter\n";
|
||||
std::cout << "Duration: " << duration << " seconds\n";
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
else if (status == Status::Error)
|
||||
{
|
||||
const auto code = std::get<json::String>(json_result.values["code"]).value;
|
||||
const auto message = std::get<json::String>(json_result.values["message"]).value;
|
||||
|
||||
std::cout << "Code: " << code << "\n";
|
||||
std::cout << "Message: " << code << "\n";
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
@@ -33,7 +33,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include "engine/hint.hpp"
|
||||
#include "util/coordinate.hpp"
|
||||
|
||||
#include <optional>
|
||||
#include <boost/optional.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
@@ -74,12 +74,12 @@ struct BaseParameters
|
||||
};
|
||||
|
||||
std::vector<util::Coordinate> coordinates;
|
||||
std::vector<std::optional<Hint>> hints;
|
||||
std::vector<std::optional<double>> radiuses;
|
||||
std::vector<std::optional<Bearing>> bearings;
|
||||
std::vector<std::optional<Approach>> approaches;
|
||||
std::vector<boost::optional<Hint>> hints;
|
||||
std::vector<boost::optional<double>> radiuses;
|
||||
std::vector<boost::optional<Bearing>> bearings;
|
||||
std::vector<boost::optional<Approach>> approaches;
|
||||
std::vector<std::string> exclude;
|
||||
std::optional<OutputFormatType> format = OutputFormatType::JSON;
|
||||
boost::optional<OutputFormatType> format = OutputFormatType::JSON;
|
||||
|
||||
// Adds hints to response which can be included in subsequent requests, see `hints` above.
|
||||
bool generate_hints = true;
|
||||
@@ -90,10 +90,10 @@ struct BaseParameters
|
||||
SnappingType snapping = SnappingType::Default;
|
||||
|
||||
BaseParameters(std::vector<util::Coordinate> coordinates_ = {},
|
||||
std::vector<std::optional<Hint>> hints_ = {},
|
||||
std::vector<std::optional<double>> radiuses_ = {},
|
||||
std::vector<std::optional<Bearing>> bearings_ = {},
|
||||
std::vector<std::optional<Approach>> approaches_ = {},
|
||||
std::vector<boost::optional<Hint>> hints_ = {},
|
||||
std::vector<boost::optional<double>> radiuses_ = {},
|
||||
std::vector<boost::optional<Bearing>> bearings_ = {},
|
||||
std::vector<boost::optional<Approach>> approaches_ = {},
|
||||
bool generate_hints_ = true,
|
||||
std::vector<std::string> exclude = {},
|
||||
const SnappingType snapping_ = SnappingType::Default)
|
||||
@@ -112,7 +112,7 @@ struct BaseParameters
|
||||
(approaches.empty() || approaches.size() == coordinates.size()) &&
|
||||
std::all_of(bearings.begin(),
|
||||
bearings.end(),
|
||||
[](const std::optional<Bearing> &bearing_and_range)
|
||||
[](const boost::optional<Bearing> &bearing_and_range)
|
||||
{
|
||||
if (bearing_and_range)
|
||||
{
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
#include "util/coordinate.hpp"
|
||||
#include "util/json_container.hpp"
|
||||
|
||||
#include <optional>
|
||||
#include <boost/optional.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
@@ -90,7 +90,7 @@ util::json::Object makeRouteStep(guidance::RouteStep step, util::json::Value geo
|
||||
|
||||
util::json::Object makeRoute(const guidance::Route &route,
|
||||
util::json::Array legs,
|
||||
std::optional<util::json::Value> geometry,
|
||||
boost::optional<util::json::Value> geometry,
|
||||
const char *weight_name);
|
||||
|
||||
// Creates a Waypoint without Hint, see the Hint overload below
|
||||
|
||||
@@ -45,7 +45,7 @@ class NearestAPI final : public BaseAPI
|
||||
flatbuffers::FlatBufferBuilder &fb_result) const
|
||||
{
|
||||
auto data_timestamp = facade.GetTimestamp();
|
||||
std::optional<flatbuffers::Offset<flatbuffers::String>> data_version_string = std::nullopt;
|
||||
boost::optional<flatbuffers::Offset<flatbuffers::String>> data_version_string = boost::none;
|
||||
if (!data_timestamp.empty())
|
||||
{
|
||||
data_version_string = fb_result.CreateString(data_timestamp);
|
||||
|
||||
@@ -184,10 +184,10 @@ class RouteAPI : public BaseAPI
|
||||
return builder.CreateVectorOfStructs(coordinates);
|
||||
}
|
||||
|
||||
std::optional<util::json::Value>
|
||||
MakeGeometry(std::optional<std::vector<Coordinate>> &&annotations) const
|
||||
boost::optional<util::json::Value>
|
||||
MakeGeometry(boost::optional<std::vector<Coordinate>> &&annotations) const
|
||||
{
|
||||
std::optional<util::json::Value> json_geometry;
|
||||
boost::optional<util::json::Value> json_geometry;
|
||||
if (annotations)
|
||||
{
|
||||
auto begin = annotations->begin();
|
||||
@@ -720,7 +720,8 @@ class RouteAPI : public BaseAPI
|
||||
std::vector<guidance::LegGeometry> &leg_geometries = legs_info.second;
|
||||
|
||||
auto route = guidance::assembleRoute(legs);
|
||||
std::optional<util::json::Value> json_overview = MakeGeometry(MakeOverview(leg_geometries));
|
||||
boost::optional<util::json::Value> json_overview =
|
||||
MakeGeometry(MakeOverview(leg_geometries));
|
||||
|
||||
std::vector<util::json::Value> step_geometries;
|
||||
const auto total_step_count =
|
||||
@@ -996,10 +997,10 @@ class RouteAPI : public BaseAPI
|
||||
return result;
|
||||
}
|
||||
|
||||
std::optional<std::vector<Coordinate>>
|
||||
boost::optional<std::vector<Coordinate>>
|
||||
MakeOverview(const std::vector<guidance::LegGeometry> &leg_geometries) const
|
||||
{
|
||||
std::optional<std::vector<Coordinate>> overview;
|
||||
boost::optional<std::vector<Coordinate>> overview;
|
||||
if (parameters.overview != RouteParameters::OverviewType::False)
|
||||
{
|
||||
const auto use_simplification =
|
||||
|
||||
@@ -82,7 +82,7 @@ struct RouteParameters : public BaseParameters
|
||||
const bool alternatives_,
|
||||
const GeometriesType geometries_,
|
||||
const OverviewType overview_,
|
||||
const std::optional<bool> continue_straight_,
|
||||
const boost::optional<bool> continue_straight_,
|
||||
Args &&...args_)
|
||||
// Once we perfectly-forward `args` (see #2990) this constructor can delegate to the one
|
||||
// below.
|
||||
@@ -100,7 +100,7 @@ struct RouteParameters : public BaseParameters
|
||||
const bool annotations_,
|
||||
const GeometriesType geometries_,
|
||||
const OverviewType overview_,
|
||||
const std::optional<bool> continue_straight_,
|
||||
const boost::optional<bool> continue_straight_,
|
||||
Args &&...args_)
|
||||
: BaseParameters{std::forward<Args>(args_)...}, steps{steps_}, alternatives{alternatives_},
|
||||
number_of_alternatives{alternatives_ ? 1u : 0u}, annotations{annotations_},
|
||||
@@ -118,7 +118,7 @@ struct RouteParameters : public BaseParameters
|
||||
const AnnotationsType annotations_,
|
||||
const GeometriesType geometries_,
|
||||
const OverviewType overview_,
|
||||
const std::optional<bool> continue_straight_,
|
||||
const boost::optional<bool> continue_straight_,
|
||||
Args &&...args_)
|
||||
: BaseParameters{std::forward<Args>(args_)...}, steps{steps_}, alternatives{alternatives_},
|
||||
number_of_alternatives{alternatives_ ? 1u : 0u},
|
||||
@@ -135,7 +135,7 @@ struct RouteParameters : public BaseParameters
|
||||
const bool annotations_,
|
||||
const GeometriesType geometries_,
|
||||
const OverviewType overview_,
|
||||
const std::optional<bool> continue_straight_,
|
||||
const boost::optional<bool> continue_straight_,
|
||||
std::vector<std::size_t> waypoints_,
|
||||
const Args &&...args_)
|
||||
: BaseParameters{std::forward<Args>(args_)...}, steps{steps_}, alternatives{alternatives_},
|
||||
@@ -153,7 +153,7 @@ struct RouteParameters : public BaseParameters
|
||||
const AnnotationsType annotations_,
|
||||
const GeometriesType geometries_,
|
||||
const OverviewType overview_,
|
||||
const std::optional<bool> continue_straight_,
|
||||
const boost::optional<bool> continue_straight_,
|
||||
std::vector<std::size_t> waypoints_,
|
||||
Args &&...args_)
|
||||
: BaseParameters{std::forward<Args>(args_)...}, steps{steps_}, alternatives{alternatives_},
|
||||
@@ -172,7 +172,7 @@ struct RouteParameters : public BaseParameters
|
||||
AnnotationsType annotations_type = AnnotationsType::None;
|
||||
GeometriesType geometries = GeometriesType::Polyline;
|
||||
OverviewType overview = OverviewType::Simplified;
|
||||
std::optional<bool> continue_straight;
|
||||
boost::optional<bool> continue_straight;
|
||||
std::vector<std::size_t> waypoints;
|
||||
|
||||
bool IsValid() const
|
||||
|
||||
@@ -30,7 +30,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include "engine/api/route_parameters.hpp"
|
||||
|
||||
#include <optional>
|
||||
#include <boost/optional.hpp>
|
||||
#include <vector>
|
||||
|
||||
namespace osrm::engine::api
|
||||
|
||||
@@ -369,7 +369,7 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
|
||||
std::vector<PhantomNodeWithDistance>
|
||||
NearestPhantomNodesInRange(const util::Coordinate input_coordinate,
|
||||
const double max_distance,
|
||||
const std::optional<Bearing> bearing,
|
||||
const boost::optional<Bearing> bearing,
|
||||
const Approach approach,
|
||||
const bool use_all_edges) const override final
|
||||
{
|
||||
@@ -382,20 +382,20 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
|
||||
std::vector<PhantomNodeWithDistance>
|
||||
NearestPhantomNodes(const util::Coordinate input_coordinate,
|
||||
const size_t max_results,
|
||||
const std::optional<double> max_distance,
|
||||
const std::optional<Bearing> bearing,
|
||||
const boost::optional<double> max_distance,
|
||||
const boost::optional<Bearing> bearing,
|
||||
const Approach approach) const override final
|
||||
{
|
||||
BOOST_ASSERT(m_geospatial_query.get());
|
||||
|
||||
return m_geospatial_query->NearestPhantomNodes(
|
||||
input_coordinate, approach, max_results, max_distance, bearing, std::nullopt);
|
||||
input_coordinate, approach, max_results, max_distance, bearing, boost::none);
|
||||
}
|
||||
|
||||
PhantomCandidateAlternatives
|
||||
NearestCandidatesWithAlternativeFromBigComponent(const util::Coordinate input_coordinate,
|
||||
const std::optional<double> max_distance,
|
||||
const std::optional<Bearing> bearing,
|
||||
const boost::optional<double> max_distance,
|
||||
const boost::optional<Bearing> bearing,
|
||||
const Approach approach,
|
||||
const bool use_all_edges) const override final
|
||||
{
|
||||
|
||||
@@ -35,7 +35,6 @@
|
||||
#include <cstddef>
|
||||
|
||||
#include <engine/bearing.hpp>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <utility>
|
||||
@@ -127,21 +126,21 @@ class BaseDataFacade
|
||||
virtual std::vector<PhantomNodeWithDistance>
|
||||
NearestPhantomNodesInRange(const util::Coordinate input_coordinate,
|
||||
const double max_distance,
|
||||
const std::optional<Bearing> bearing,
|
||||
const boost::optional<Bearing> bearing,
|
||||
const Approach approach,
|
||||
const bool use_all_edges) const = 0;
|
||||
|
||||
virtual std::vector<PhantomNodeWithDistance>
|
||||
NearestPhantomNodes(const util::Coordinate input_coordinate,
|
||||
const size_t max_results,
|
||||
const std::optional<double> max_distance,
|
||||
const std::optional<Bearing> bearing,
|
||||
const boost::optional<double> max_distance,
|
||||
const boost::optional<Bearing> bearing,
|
||||
const Approach approach) const = 0;
|
||||
|
||||
virtual PhantomCandidateAlternatives
|
||||
NearestCandidatesWithAlternativeFromBigComponent(const util::Coordinate input_coordinate,
|
||||
const std::optional<double> max_distance,
|
||||
const std::optional<Bearing> bearing,
|
||||
const boost::optional<double> max_distance,
|
||||
const boost::optional<Bearing> bearing,
|
||||
const Approach approach,
|
||||
const bool use_all_edges) const = 0;
|
||||
|
||||
|
||||
@@ -79,7 +79,7 @@ struct EngineConfig final
|
||||
int max_locations_map_matching = -1;
|
||||
double max_radius_map_matching = -1.0;
|
||||
int max_results_nearest = -1;
|
||||
double default_radius = -1.0;
|
||||
boost::optional<double> default_radius = -1.0;
|
||||
int max_alternatives = 3; // set an arbitrary upper bound; can be adjusted by user
|
||||
bool use_shared_memory = true;
|
||||
std::filesystem::path memory_file;
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
#include "osrm/coordinate.hpp"
|
||||
|
||||
#include <optional>
|
||||
#include <boost/optional.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
@@ -53,8 +53,8 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
|
||||
NearestPhantomNodes(const util::Coordinate input_coordinate,
|
||||
const Approach approach,
|
||||
const double max_distance,
|
||||
const std::optional<Bearing> bearing_with_range,
|
||||
const std::optional<bool> use_all_edges) const
|
||||
const boost::optional<Bearing> bearing_with_range,
|
||||
const boost::optional<bool> use_all_edges) const
|
||||
{
|
||||
auto results = rtree.SearchInRange(
|
||||
input_coordinate,
|
||||
@@ -85,9 +85,9 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
|
||||
NearestPhantomNodes(const util::Coordinate input_coordinate,
|
||||
const Approach approach,
|
||||
const size_t max_results,
|
||||
const std::optional<double> max_distance,
|
||||
const std::optional<Bearing> bearing_with_range,
|
||||
const std::optional<bool> use_all_edges) const
|
||||
const boost::optional<double> max_distance,
|
||||
const boost::optional<Bearing> bearing_with_range,
|
||||
const boost::optional<bool> use_all_edges) const
|
||||
{
|
||||
auto results = rtree.Nearest(
|
||||
input_coordinate,
|
||||
@@ -121,9 +121,9 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
|
||||
PhantomCandidateAlternatives NearestCandidatesWithAlternativeFromBigComponent(
|
||||
const util::Coordinate input_coordinate,
|
||||
const Approach approach,
|
||||
const std::optional<double> max_distance,
|
||||
const std::optional<Bearing> bearing_with_range,
|
||||
const std::optional<bool> use_all_edges) const
|
||||
const boost::optional<double> max_distance,
|
||||
const boost::optional<Bearing> bearing_with_range,
|
||||
const boost::optional<bool> use_all_edges) const
|
||||
{
|
||||
bool has_nearest = false;
|
||||
bool has_big_component = false;
|
||||
|
||||
@@ -37,14 +37,6 @@ inline LegGeometry assembleGeometry(const datafacade::BaseDataFacade &facade,
|
||||
{
|
||||
LegGeometry geometry;
|
||||
|
||||
// each container will at most have `leg_data.size()` + 1/2 elements in it
|
||||
// these additional 1/2 elements come from processing of very first and very last segment
|
||||
geometry.locations.reserve(leg_data.size() + 2);
|
||||
geometry.segment_distances.reserve(leg_data.size() + 1);
|
||||
geometry.segment_offsets.reserve(leg_data.size() + 1);
|
||||
geometry.annotations.reserve(leg_data.size() + 1);
|
||||
geometry.node_ids.reserve(leg_data.size() + 2);
|
||||
|
||||
// segment 0 first and last
|
||||
geometry.segment_offsets.push_back(0);
|
||||
geometry.locations.push_back(source_node.location);
|
||||
|
||||
@@ -17,9 +17,9 @@
|
||||
#include "util/guidance/turn_lanes.hpp"
|
||||
#include "util/typedefs.hpp"
|
||||
|
||||
#include <boost/optional.hpp>
|
||||
#include <cstddef>
|
||||
#include <guidance/turn_bearing.hpp>
|
||||
#include <optional>
|
||||
#include <vector>
|
||||
|
||||
namespace osrm::engine::guidance
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
#include "engine/guidance/route_step.hpp"
|
||||
|
||||
#include <optional>
|
||||
#include <boost/optional.hpp>
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
#include "util/integer_range.hpp"
|
||||
#include "util/typedefs.hpp"
|
||||
|
||||
#include <optional>
|
||||
#include <boost/optional.hpp>
|
||||
#include <vector>
|
||||
|
||||
namespace osrm::engine
|
||||
@@ -42,7 +42,7 @@ struct PathData
|
||||
// Source of the speed value on this road segment
|
||||
DatasourceID datasource_id;
|
||||
// If segment precedes a turn, ID of the turn itself
|
||||
std::optional<EdgeID> turn_edge;
|
||||
boost::optional<EdgeID> turn_edge;
|
||||
};
|
||||
|
||||
struct InternalRouteResult
|
||||
|
||||
@@ -22,7 +22,7 @@ class MatchPlugin : public BasePlugin
|
||||
|
||||
MatchPlugin(const int max_locations_map_matching,
|
||||
const double max_radius_map_matching,
|
||||
const std::optional<double> default_radius)
|
||||
const boost::optional<double> default_radius)
|
||||
: BasePlugin(default_radius), max_locations_map_matching(max_locations_map_matching),
|
||||
max_radius_map_matching(max_radius_map_matching)
|
||||
{
|
||||
|
||||
@@ -13,7 +13,7 @@ namespace osrm::engine::plugins
|
||||
class NearestPlugin final : public BasePlugin
|
||||
{
|
||||
public:
|
||||
explicit NearestPlugin(const int max_results, const std::optional<double> default_radius);
|
||||
explicit NearestPlugin(const int max_results, const boost::optional<double> default_radius);
|
||||
|
||||
Status HandleRequest(const RoutingAlgorithmsInterface &algorithms,
|
||||
const api::NearestParameters ¶ms,
|
||||
|
||||
@@ -29,7 +29,7 @@ class BasePlugin
|
||||
protected:
|
||||
BasePlugin() = default;
|
||||
|
||||
BasePlugin(const std::optional<double> default_radius_) : default_radius(default_radius_) {}
|
||||
BasePlugin(const boost::optional<double> default_radius_) : default_radius(default_radius_) {}
|
||||
|
||||
bool CheckAllCoordinates(const std::vector<util::Coordinate> &coordinates) const
|
||||
{
|
||||
@@ -200,8 +200,8 @@ class BasePlugin
|
||||
phantom_nodes[i] = facade.NearestPhantomNodesInRange(
|
||||
parameters.coordinates[i],
|
||||
radiuses[i],
|
||||
use_bearings ? parameters.bearings[i] : std::nullopt,
|
||||
use_approaches && parameters.approaches[i] ? parameters.approaches[i].value()
|
||||
use_bearings ? parameters.bearings[i] : boost::none,
|
||||
use_approaches && parameters.approaches[i] ? parameters.approaches[i].get()
|
||||
: engine::Approach::UNRESTRICTED,
|
||||
use_all_edges);
|
||||
}
|
||||
@@ -242,8 +242,8 @@ class BasePlugin
|
||||
parameters.coordinates[i],
|
||||
number_of_results,
|
||||
use_radiuses ? parameters.radiuses[i] : default_radius,
|
||||
use_bearings ? parameters.bearings[i] : std::nullopt,
|
||||
use_approaches && parameters.approaches[i] ? parameters.approaches[i].value()
|
||||
use_bearings ? parameters.bearings[i] : boost::none,
|
||||
use_approaches && parameters.approaches[i] ? parameters.approaches[i].get()
|
||||
: engine::Approach::UNRESTRICTED);
|
||||
|
||||
// we didn't find a fitting node, return error
|
||||
@@ -284,8 +284,8 @@ class BasePlugin
|
||||
alternatives[i] = facade.NearestCandidatesWithAlternativeFromBigComponent(
|
||||
parameters.coordinates[i],
|
||||
use_radiuses ? parameters.radiuses[i] : default_radius,
|
||||
use_bearings ? parameters.bearings[i] : std::nullopt,
|
||||
use_approaches && parameters.approaches[i] ? parameters.approaches[i].value()
|
||||
use_bearings ? parameters.bearings[i] : boost::none,
|
||||
use_approaches && parameters.approaches[i] ? parameters.approaches[i].get()
|
||||
: engine::Approach::UNRESTRICTED,
|
||||
use_all_edges);
|
||||
|
||||
@@ -325,7 +325,7 @@ class BasePlugin
|
||||
std::to_string(missing_index);
|
||||
}
|
||||
|
||||
const std::optional<double> default_radius;
|
||||
const boost::optional<double> default_radius;
|
||||
};
|
||||
} // namespace osrm::engine::plugins
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ class TablePlugin final : public BasePlugin
|
||||
{
|
||||
public:
|
||||
explicit TablePlugin(const int max_locations_distance_table,
|
||||
const std::optional<double> default_radius);
|
||||
const boost::optional<double> default_radius);
|
||||
|
||||
Status HandleRequest(const RoutingAlgorithmsInterface &algorithms,
|
||||
const api::TableParameters ¶ms,
|
||||
|
||||
@@ -32,7 +32,7 @@ class TripPlugin final : public BasePlugin
|
||||
const bool roundtrip) const;
|
||||
|
||||
public:
|
||||
explicit TripPlugin(const int max_locations_trip_, std::optional<double> default_radius)
|
||||
explicit TripPlugin(const int max_locations_trip_, boost::optional<double> default_radius)
|
||||
: BasePlugin(default_radius), max_locations_trip(max_locations_trip_)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ class ViaRoutePlugin final : public BasePlugin
|
||||
public:
|
||||
explicit ViaRoutePlugin(int max_locations_viaroute,
|
||||
int max_alternatives,
|
||||
std::optional<double> default_radius);
|
||||
boost::optional<double> default_radius);
|
||||
|
||||
Status HandleRequest(const RoutingAlgorithmsInterface &algorithms,
|
||||
const api::RouteParameters &route_parameters,
|
||||
|
||||
@@ -25,7 +25,7 @@ class RoutingAlgorithmsInterface
|
||||
|
||||
virtual InternalRouteResult
|
||||
ShortestPathSearch(const std::vector<PhantomNodeCandidates> &waypoint_candidates,
|
||||
const std::optional<bool> continue_straight_at_waypoint) const = 0;
|
||||
const boost::optional<bool> continue_straight_at_waypoint) const = 0;
|
||||
|
||||
virtual InternalRouteResult
|
||||
DirectShortestPathSearch(const PhantomEndpointCandidates &endpoint_candidates) const = 0;
|
||||
@@ -40,7 +40,7 @@ class RoutingAlgorithmsInterface
|
||||
MapMatching(const routing_algorithms::CandidateLists &candidates_list,
|
||||
const std::vector<util::Coordinate> &trace_coordinates,
|
||||
const std::vector<unsigned> &trace_timestamps,
|
||||
const std::vector<std::optional<double>> &trace_gps_precision,
|
||||
const std::vector<boost::optional<double>> &trace_gps_precision,
|
||||
const bool allow_splitting) const = 0;
|
||||
|
||||
virtual std::vector<routing_algorithms::TurnData>
|
||||
@@ -78,7 +78,7 @@ template <typename Algorithm> class RoutingAlgorithms final : public RoutingAlgo
|
||||
|
||||
InternalRouteResult ShortestPathSearch(
|
||||
const std::vector<PhantomNodeCandidates> &waypoint_candidates,
|
||||
const std::optional<bool> continue_straight_at_waypoint) const final override;
|
||||
const boost::optional<bool> continue_straight_at_waypoint) const final override;
|
||||
|
||||
InternalRouteResult DirectShortestPathSearch(
|
||||
const PhantomEndpointCandidates &endpoint_candidates) const final override;
|
||||
@@ -93,7 +93,7 @@ template <typename Algorithm> class RoutingAlgorithms final : public RoutingAlgo
|
||||
MapMatching(const routing_algorithms::CandidateLists &candidates_list,
|
||||
const std::vector<util::Coordinate> &trace_coordinates,
|
||||
const std::vector<unsigned> &trace_timestamps,
|
||||
const std::vector<std::optional<double>> &trace_gps_precision,
|
||||
const std::vector<boost::optional<double>> &trace_gps_precision,
|
||||
const bool allow_splitting) const final override;
|
||||
|
||||
std::vector<routing_algorithms::TurnData>
|
||||
@@ -160,7 +160,7 @@ InternalManyRoutesResult RoutingAlgorithms<Algorithm>::AlternativePathSearch(
|
||||
template <typename Algorithm>
|
||||
InternalRouteResult RoutingAlgorithms<Algorithm>::ShortestPathSearch(
|
||||
const std::vector<PhantomNodeCandidates> &waypoint_candidates,
|
||||
const std::optional<bool> continue_straight_at_waypoint) const
|
||||
const boost::optional<bool> continue_straight_at_waypoint) const
|
||||
{
|
||||
return routing_algorithms::shortestPathSearch(
|
||||
heaps, *facade, waypoint_candidates, continue_straight_at_waypoint);
|
||||
@@ -178,7 +178,7 @@ inline routing_algorithms::SubMatchingList RoutingAlgorithms<Algorithm>::MapMatc
|
||||
const routing_algorithms::CandidateLists &candidates_list,
|
||||
const std::vector<util::Coordinate> &trace_coordinates,
|
||||
const std::vector<unsigned> &trace_timestamps,
|
||||
const std::vector<std::optional<double>> &trace_gps_precision,
|
||||
const std::vector<boost::optional<double>> &trace_gps_precision,
|
||||
const bool allow_splitting) const
|
||||
{
|
||||
return routing_algorithms::mapMatching(heaps,
|
||||
|
||||
@@ -24,7 +24,7 @@ SubMatchingList mapMatching(SearchEngineData<Algorithm> &engine_working_data,
|
||||
const CandidateLists &candidates_list,
|
||||
const std::vector<util::Coordinate> &trace_coordinates,
|
||||
const std::vector<unsigned> &trace_timestamps,
|
||||
const std::vector<std::optional<double>> &trace_gps_precision,
|
||||
const std::vector<boost::optional<double>> &trace_gps_precision,
|
||||
const bool allow_splitting);
|
||||
|
||||
} // namespace osrm::engine::routing_algorithms
|
||||
|
||||
@@ -258,7 +258,7 @@ void annotatePath(const FacadeT &facade,
|
||||
alias_cast<EdgeDuration>(duration_vector[segment_idx]),
|
||||
{0},
|
||||
datasource_vector[segment_idx],
|
||||
std::nullopt});
|
||||
boost::none});
|
||||
}
|
||||
BOOST_ASSERT(!unpacked_path.empty());
|
||||
|
||||
@@ -315,7 +315,7 @@ void annotatePath(const FacadeT &facade,
|
||||
alias_cast<EdgeDuration>(duration_vector[segment_idx]),
|
||||
{0},
|
||||
datasource_vector[segment_idx],
|
||||
std::nullopt});
|
||||
boost::none});
|
||||
}
|
||||
|
||||
if (!unpacked_path.empty())
|
||||
|
||||
@@ -487,13 +487,7 @@ void routingStep(const DataFacade<Algorithm> &facade,
|
||||
|
||||
using UnpackedNodes = std::vector<NodeID>;
|
||||
using UnpackedEdges = std::vector<EdgeID>;
|
||||
|
||||
struct UnpackedPath
|
||||
{
|
||||
EdgeWeight weight;
|
||||
UnpackedNodes nodes;
|
||||
UnpackedEdges edges;
|
||||
};
|
||||
using UnpackedPath = std::tuple<EdgeWeight, UnpackedNodes, UnpackedEdges>;
|
||||
|
||||
template <typename Algorithm, typename Heap, typename... Args>
|
||||
std::optional<std::pair<NodeID, EdgeWeight>> runSearch(const DataFacade<Algorithm> &facade,
|
||||
@@ -557,7 +551,7 @@ UnpackedPath search(SearchEngineData<Algorithm> &engine_working_data,
|
||||
facade, forward_heap, reverse_heap, force_step_nodes, weight_upper_bound, args...);
|
||||
if (!searchResult)
|
||||
{
|
||||
return {INVALID_EDGE_WEIGHT, std::vector<NodeID>(), std::vector<EdgeID>()};
|
||||
return std::make_tuple(INVALID_EDGE_WEIGHT, std::vector<NodeID>(), std::vector<EdgeID>());
|
||||
}
|
||||
|
||||
auto [middle, weight] = *searchResult;
|
||||
@@ -601,27 +595,25 @@ UnpackedPath search(SearchEngineData<Algorithm> &engine_working_data,
|
||||
forward_heap.Insert(source, {0}, {source});
|
||||
reverse_heap.Insert(target, {0}, {target});
|
||||
|
||||
auto unpacked_subpath = search(engine_working_data,
|
||||
facade,
|
||||
forward_heap,
|
||||
reverse_heap,
|
||||
force_step_nodes,
|
||||
INVALID_EDGE_WEIGHT,
|
||||
sublevel,
|
||||
parent_cell_id);
|
||||
BOOST_ASSERT(!unpacked_subpath.edges.empty());
|
||||
BOOST_ASSERT(unpacked_subpath.nodes.size() > 1);
|
||||
BOOST_ASSERT(unpacked_subpath.nodes.front() == source);
|
||||
BOOST_ASSERT(unpacked_subpath.nodes.back() == target);
|
||||
unpacked_nodes.insert(unpacked_nodes.end(),
|
||||
std::next(unpacked_subpath.nodes.begin()),
|
||||
unpacked_subpath.nodes.end());
|
||||
unpacked_edges.insert(
|
||||
unpacked_edges.end(), unpacked_subpath.edges.begin(), unpacked_subpath.edges.end());
|
||||
auto [subpath_weight, subpath_nodes, subpath_edges] = search(engine_working_data,
|
||||
facade,
|
||||
forward_heap,
|
||||
reverse_heap,
|
||||
force_step_nodes,
|
||||
INVALID_EDGE_WEIGHT,
|
||||
sublevel,
|
||||
parent_cell_id);
|
||||
BOOST_ASSERT(!subpath_edges.empty());
|
||||
BOOST_ASSERT(subpath_nodes.size() > 1);
|
||||
BOOST_ASSERT(subpath_nodes.front() == source);
|
||||
BOOST_ASSERT(subpath_nodes.back() == target);
|
||||
unpacked_nodes.insert(
|
||||
unpacked_nodes.end(), std::next(subpath_nodes.begin()), subpath_nodes.end());
|
||||
unpacked_edges.insert(unpacked_edges.end(), subpath_edges.begin(), subpath_edges.end());
|
||||
}
|
||||
}
|
||||
|
||||
return {weight, std::move(unpacked_nodes), std::move(unpacked_edges)};
|
||||
return std::make_tuple(weight, std::move(unpacked_nodes), std::move(unpacked_edges));
|
||||
}
|
||||
|
||||
template <typename Algorithm, typename... Args>
|
||||
@@ -662,15 +654,13 @@ inline void search(SearchEngineData<Algorithm> &engine_working_data,
|
||||
const EdgeWeight weight_upper_bound = INVALID_EDGE_WEIGHT)
|
||||
{
|
||||
// TODO: change search calling interface to use unpacked_edges result
|
||||
auto unpacked_path = search(engine_working_data,
|
||||
facade,
|
||||
forward_heap,
|
||||
reverse_heap,
|
||||
force_step_nodes,
|
||||
weight_upper_bound,
|
||||
endpoints);
|
||||
weight = unpacked_path.weight;
|
||||
unpacked_nodes = std::move(unpacked_path.nodes);
|
||||
std::tie(weight, unpacked_nodes, std::ignore) = search(engine_working_data,
|
||||
facade,
|
||||
forward_heap,
|
||||
reverse_heap,
|
||||
force_step_nodes,
|
||||
weight_upper_bound,
|
||||
endpoints);
|
||||
}
|
||||
|
||||
// TODO: refactor CH-related stub to use unpacked_edges
|
||||
|
||||
@@ -14,7 +14,7 @@ InternalRouteResult
|
||||
shortestPathSearch(SearchEngineData<Algorithm> &engine_working_data,
|
||||
const DataFacade<Algorithm> &facade,
|
||||
const std::vector<PhantomNodeCandidates> &waypoint_candidates,
|
||||
const std::optional<bool> continue_straight_at_waypoint);
|
||||
const boost::optional<bool> continue_straight_at_waypoint);
|
||||
|
||||
} // namespace osrm::engine::routing_algorithms
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
#include "engine/routing_algorithms/shortest_path.hpp"
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <optional>
|
||||
#include <boost/optional.hpp>
|
||||
|
||||
namespace osrm::engine::routing_algorithms
|
||||
{
|
||||
@@ -339,10 +339,10 @@ struct leg_connections
|
||||
{
|
||||
// X_to_Y = i can be read as
|
||||
// sources[i].X is the source of the shortest leg path to target.Y
|
||||
std::optional<size_t> forward_to_forward;
|
||||
std::optional<size_t> reverse_to_forward;
|
||||
std::optional<size_t> forward_to_reverse;
|
||||
std::optional<size_t> reverse_to_reverse;
|
||||
boost::optional<size_t> forward_to_forward;
|
||||
boost::optional<size_t> reverse_to_forward;
|
||||
boost::optional<size_t> forward_to_reverse;
|
||||
boost::optional<size_t> reverse_to_reverse;
|
||||
};
|
||||
|
||||
// Identify which of the source candidates segments is being used for paths to the
|
||||
@@ -771,7 +771,7 @@ InternalRouteResult
|
||||
shortestPathSearch(SearchEngineData<Algorithm> &engine_working_data,
|
||||
const DataFacade<Algorithm> &facade,
|
||||
const std::vector<PhantomNodeCandidates> &waypoint_candidates,
|
||||
const std::optional<bool> continue_straight_at_waypoint)
|
||||
const boost::optional<bool> continue_straight_at_waypoint)
|
||||
{
|
||||
const bool allow_uturn_at_waypoint =
|
||||
!(continue_straight_at_waypoint ? *continue_straight_at_waypoint
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
#include <napi.h>
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <optional>
|
||||
#include <boost/optional.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
@@ -395,11 +395,11 @@ inline engine_config_ptr argumentsToEngineConfig(const Napi::CallbackInfo &args)
|
||||
return engine_config;
|
||||
}
|
||||
|
||||
inline std::optional<std::vector<osrm::Coordinate>>
|
||||
inline boost::optional<std::vector<osrm::Coordinate>>
|
||||
parseCoordinateArray(const Napi::Array &coordinates_array)
|
||||
{
|
||||
Napi::HandleScope scope(coordinates_array.Env());
|
||||
std::optional<std::vector<osrm::Coordinate>> resulting_coordinates;
|
||||
boost::optional<std::vector<osrm::Coordinate>> resulting_coordinates;
|
||||
std::vector<osrm::Coordinate> temp_coordinates;
|
||||
|
||||
for (uint32_t i = 0; i < coordinates_array.Length(); ++i)
|
||||
@@ -450,7 +450,7 @@ parseCoordinateArray(const Napi::Array &coordinates_array)
|
||||
osrm::util::FloatLatitude{std::move(lat)});
|
||||
}
|
||||
|
||||
resulting_coordinates = std::make_optional(std::move(temp_coordinates));
|
||||
resulting_coordinates = boost::make_optional(std::move(temp_coordinates));
|
||||
return resulting_coordinates;
|
||||
}
|
||||
|
||||
@@ -1023,7 +1023,7 @@ inline bool parseCommonParameters(const Napi::Object &obj, ParamType ¶ms)
|
||||
|
||||
inline PluginParameters argumentsToPluginParameters(
|
||||
const Napi::CallbackInfo &args,
|
||||
const std::optional<osrm::engine::api::BaseParameters::OutputFormatType> &output_format = {})
|
||||
const boost::optional<osrm::engine::api::BaseParameters::OutputFormatType> &output_format = {})
|
||||
{
|
||||
if (args.Length() < 3 || !args[1].IsObject())
|
||||
{
|
||||
|
||||
@@ -7,9 +7,9 @@
|
||||
#include "engine/hint.hpp"
|
||||
#include "engine/polyline_compressor.hpp"
|
||||
|
||||
#include <boost/optional.hpp>
|
||||
#include <boost/phoenix.hpp>
|
||||
#include <boost/spirit/include/qi.hpp>
|
||||
#include <optional>
|
||||
|
||||
#include <limits>
|
||||
#include <string>
|
||||
@@ -88,7 +88,7 @@ struct BaseParametersGrammar : boost::spirit::qi::grammar<Iterator, Signature>
|
||||
}
|
||||
else
|
||||
{
|
||||
base_parameters.hints.emplace_back(std::nullopt);
|
||||
base_parameters.hints.emplace_back(boost::none);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -96,24 +96,13 @@ struct BaseParametersGrammar : boost::spirit::qi::grammar<Iterator, Signature>
|
||||
[](engine::api::BaseParameters &base_parameters,
|
||||
boost::optional<boost::fusion::vector2<short, short>> bearing_range)
|
||||
{
|
||||
std::optional<engine::Bearing> bearing;
|
||||
boost::optional<engine::Bearing> bearing;
|
||||
if (bearing_range)
|
||||
{
|
||||
bearing = engine::Bearing{boost::fusion::at_c<0>(*bearing_range),
|
||||
boost::fusion::at_c<1>(*bearing_range)};
|
||||
}
|
||||
base_parameters.bearings.push_back(bearing);
|
||||
};
|
||||
|
||||
const auto add_approach = [](engine::api::BaseParameters &base_parameters,
|
||||
boost::optional<osrm::engine::Approach> approach) {
|
||||
base_parameters.approaches.push_back(approach ? std::make_optional(*approach)
|
||||
: std::nullopt);
|
||||
};
|
||||
|
||||
const auto add_radius = [](engine::api::BaseParameters &base_parameters,
|
||||
boost::optional<double> radius) {
|
||||
base_parameters.radiuses.push_back(radius ? std::make_optional(*radius) : std::nullopt);
|
||||
base_parameters.bearings.push_back(std::move(bearing));
|
||||
};
|
||||
|
||||
polyline_chars = qi::char_("a-zA-Z0-9_.--[]{}@?|\\%~`^");
|
||||
@@ -155,9 +144,9 @@ struct BaseParametersGrammar : boost::spirit::qi::grammar<Iterator, Signature>
|
||||
((location_rule % ';') | polyline_rule |
|
||||
polyline6_rule)[ph::bind(&engine::api::BaseParameters::coordinates, qi::_r1) = qi::_1];
|
||||
|
||||
radiuses_rule =
|
||||
qi::lit("radiuses=") >
|
||||
(-(qi::double_ | unlimited_rule))[ph::bind(add_radius, qi::_r1, qi::_1)] % ';';
|
||||
radiuses_rule = qi::lit("radiuses=") >
|
||||
(-(qi::double_ | unlimited_rule) %
|
||||
';')[ph::bind(&engine::api::BaseParameters::radiuses, qi::_r1) = qi::_1];
|
||||
|
||||
hints_rule =
|
||||
qi::lit("hints=") >
|
||||
@@ -181,7 +170,8 @@ struct BaseParametersGrammar : boost::spirit::qi::grammar<Iterator, Signature>
|
||||
"curb", engine::Approach::CURB)("opposite", engine::Approach::OPPOSITE);
|
||||
|
||||
approach_rule = qi::lit("approaches=") >
|
||||
(-approach_type)[ph::bind(add_approach, qi::_r1, qi::_1)] % ';';
|
||||
(-approach_type %
|
||||
';')[ph::bind(&engine::api::BaseParameters::approaches, qi::_r1) = qi::_1];
|
||||
|
||||
snapping_type.add("default", engine::api::BaseParameters::SnappingType::Default)(
|
||||
"any", engine::api::BaseParameters::SnappingType::Any);
|
||||
|
||||
@@ -26,13 +26,13 @@ using is_parameter_t =
|
||||
// Starts parsing and iter and modifies it until iter == end or parsing failed
|
||||
template <typename ParameterT,
|
||||
typename std::enable_if<detail::is_parameter_t<ParameterT>::value, int>::type = 0>
|
||||
std::optional<ParameterT> parseParameters(std::string::iterator &iter,
|
||||
const std::string::iterator end);
|
||||
boost::optional<ParameterT> parseParameters(std::string::iterator &iter,
|
||||
const std::string::iterator end);
|
||||
|
||||
// Copy on purpose because we need mutability
|
||||
template <typename ParameterT,
|
||||
typename std::enable_if<detail::is_parameter_t<ParameterT>::value, int>::type = 0>
|
||||
std::optional<ParameterT> parseParameters(std::string options_string)
|
||||
boost::optional<ParameterT> parseParameters(std::string options_string)
|
||||
{
|
||||
auto first = options_string.begin();
|
||||
const auto last = options_string.end();
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
#include "server/api/parsed_url.hpp"
|
||||
|
||||
#include <optional>
|
||||
#include <boost/optional.hpp>
|
||||
|
||||
#include <string>
|
||||
|
||||
@@ -11,9 +11,9 @@ namespace osrm::server::api
|
||||
{
|
||||
|
||||
// Starts parsing and iter and modifies it until iter == end or parsing failed
|
||||
std::optional<ParsedURL> parseURL(std::string::iterator &iter, const std::string::iterator end);
|
||||
boost::optional<ParsedURL> parseURL(std::string::iterator &iter, const std::string::iterator end);
|
||||
|
||||
inline std::optional<ParsedURL> parseURL(std::string url_string)
|
||||
inline boost::optional<ParsedURL> parseURL(std::string url_string)
|
||||
{
|
||||
auto iter = url_string.begin();
|
||||
return parseURL(iter, url_string.end());
|
||||
|
||||
@@ -5,58 +5,19 @@
|
||||
#include <boost/heap/d_ary_heap.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
#include <ankerl/unordered_dense.h>
|
||||
#include <boost/unordered_map.hpp>
|
||||
#include <cstdint>
|
||||
#include <limits>
|
||||
#include <map>
|
||||
#include <optional>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include <vector>
|
||||
|
||||
namespace osrm::util
|
||||
{
|
||||
|
||||
template <typename NodeID, typename Key> class GenerationArrayStorage
|
||||
{
|
||||
using GenerationCounter = std::uint16_t;
|
||||
|
||||
public:
|
||||
explicit GenerationArrayStorage(std::size_t size)
|
||||
: positions(size, 0), generation(1), generations(size, 0)
|
||||
{
|
||||
}
|
||||
|
||||
Key &operator[](NodeID node)
|
||||
{
|
||||
generation[node] = generation;
|
||||
return positions[node];
|
||||
}
|
||||
|
||||
Key peek_index(const NodeID node) const
|
||||
{
|
||||
if (generations[node] < generation)
|
||||
{
|
||||
return std::numeric_limits<Key>::max();
|
||||
}
|
||||
return positions[node];
|
||||
}
|
||||
|
||||
void Clear()
|
||||
{
|
||||
generation++;
|
||||
// if generation overflows we end up at 0 again and need to clear the vector
|
||||
if (generation == 0)
|
||||
{
|
||||
generation = 1;
|
||||
std::fill(generations.begin(), generations.end(), 0);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
GenerationCounter generation;
|
||||
std::vector<GenerationCounter> generations;
|
||||
std::vector<Key> positions;
|
||||
};
|
||||
|
||||
template <typename NodeID, typename Key> class ArrayStorage
|
||||
{
|
||||
public:
|
||||
@@ -72,33 +33,10 @@ template <typename NodeID, typename Key> class ArrayStorage
|
||||
std::vector<Key> positions;
|
||||
};
|
||||
|
||||
template <typename NodeID, typename Key> class MapStorage
|
||||
{
|
||||
public:
|
||||
explicit MapStorage(std::size_t) {}
|
||||
|
||||
Key &operator[](NodeID node) { return nodes[node]; }
|
||||
|
||||
void Clear() { nodes.clear(); }
|
||||
|
||||
Key peek_index(const NodeID node) const
|
||||
{
|
||||
const auto iter = nodes.find(node);
|
||||
if (nodes.end() != iter)
|
||||
{
|
||||
return iter->second;
|
||||
}
|
||||
return std::numeric_limits<Key>::max();
|
||||
}
|
||||
|
||||
private:
|
||||
std::map<NodeID, Key> nodes;
|
||||
};
|
||||
|
||||
template <typename NodeID, typename Key> class UnorderedMapStorage
|
||||
{
|
||||
public:
|
||||
explicit UnorderedMapStorage(std::size_t) { nodes.rehash(1000); }
|
||||
explicit UnorderedMapStorage(std::size_t) {}
|
||||
|
||||
Key &operator[](const NodeID node) { return nodes[node]; }
|
||||
|
||||
@@ -121,7 +59,7 @@ template <typename NodeID, typename Key> class UnorderedMapStorage
|
||||
void Clear() { nodes.clear(); }
|
||||
|
||||
private:
|
||||
std::unordered_map<NodeID, Key> nodes;
|
||||
ankerl::unordered_dense::segmented_map<NodeID, Key> nodes;
|
||||
};
|
||||
|
||||
template <typename NodeID,
|
||||
|
||||
@@ -86,9 +86,9 @@ def bootstrap_confidence_interval(data, num_samples=1000, confidence_level=0.95)
|
||||
mean = np.mean(means)
|
||||
return mean, lower_bound, upper_bound
|
||||
|
||||
def calculate_confidence_interval(data, min_is_best=True):
|
||||
def calculate_confidence_interval(data):
|
||||
mean, lower, upper = bootstrap_confidence_interval(data)
|
||||
min_value = np.min(data) if min_is_best else np.max(data)
|
||||
min_value = np.min(data)
|
||||
return mean, (upper - lower) / 2, min_value
|
||||
|
||||
|
||||
@@ -117,7 +117,7 @@ def main():
|
||||
|
||||
|
||||
total_time, total_ci, total_best = calculate_confidence_interval(np.sum(all_times, axis=1))
|
||||
ops_per_sec, ops_per_sec_ci, ops_per_sec_best = calculate_confidence_interval(float(all_times.shape[1]) / np.sum(all_times / 1000, axis=1), min_is_best=False)
|
||||
ops_per_sec, ops_per_sec_ci, ops_per_sec_best = calculate_confidence_interval(float(all_times.shape[1]) / np.sum(all_times / 1000, axis=1))
|
||||
min_time, min_ci, _ = calculate_confidence_interval(np.min(all_times, axis=1))
|
||||
mean_time, mean_ci, _ = calculate_confidence_interval(np.mean(all_times, axis=1))
|
||||
median_time, median_ci, _ = calculate_confidence_interval(np.median(all_times, axis=1))
|
||||
|
||||
@@ -102,4 +102,4 @@ def main():
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
main()
|
||||
@@ -62,7 +62,7 @@ SET test_region_ch=ch\monaco
|
||||
SET test_region_corech=corech\monaco
|
||||
SET test_region_mld=mld\monaco
|
||||
SET test_osm=%test_region%.osm.pbf
|
||||
COPY %PROJECT_DIR%\test\data\%test_region%.osm.pbf %test_osm%
|
||||
COPY %PROJECT_DIR%\test\data\%test_region%.osm.pbf %test_osm%
|
||||
%CONFIGURATION%\osrm-extract.exe -p %PROJECT_DIR%\profiles\car.lua %test_osm%
|
||||
IF %ERRORLEVEL% NEQ 0 GOTO ERROR
|
||||
|
||||
|
||||
@@ -30,6 +30,9 @@ VTZERO_TAG=v1.1.0
|
||||
FMT_PATH="fmtlib/fmt"
|
||||
FMT_TAG=v10.2.1
|
||||
|
||||
ANKERL_PATH="martinus/unordered_dense"
|
||||
ANKERL_TAG=v4.4.0
|
||||
|
||||
function update_subtree () {
|
||||
name=$(echo "$1" | tr '[:lower:]' '[:upper:]')
|
||||
path=$(tmpvar=${name}_PATH && echo ${!tmpvar})
|
||||
@@ -53,6 +56,6 @@ function update_subtree () {
|
||||
}
|
||||
|
||||
## Update dependencies
|
||||
for dep in osmium sol rapidjson microtar protozero vtzero fmt; do
|
||||
for dep in ankerl osmium sol rapidjson microtar protozero vtzero fmt; do
|
||||
update_subtree $dep
|
||||
done
|
||||
|
||||
@@ -134,7 +134,6 @@ struct ConfidenceInterval
|
||||
double mean;
|
||||
double confidence;
|
||||
double min;
|
||||
double max;
|
||||
};
|
||||
|
||||
// Helper function to calculate the bootstrap confidence interval
|
||||
@@ -162,10 +161,8 @@ ConfidenceInterval confidenceInterval(const std::vector<double> &data,
|
||||
double upper_bound = means[(int)((1 + confidence_level) / 2 * num_samples)];
|
||||
double mean = std::accumulate(means.begin(), means.end(), 0.0) / means.size();
|
||||
|
||||
ConfidenceInterval ci = {mean,
|
||||
(upper_bound - lower_bound) / 2,
|
||||
*std::min_element(data.begin(), data.end()),
|
||||
*std::max_element(data.begin(), data.end())};
|
||||
ConfidenceInterval ci = {
|
||||
mean, (upper_bound - lower_bound) / 2, *std::min_element(data.begin(), data.end())};
|
||||
return ci;
|
||||
}
|
||||
|
||||
@@ -263,7 +260,7 @@ std::ostream &operator<<(std::ostream &os, Statistics &statistics)
|
||||
ConfidenceInterval ops_ci = statistics.ops_per_sec();
|
||||
|
||||
os << "ops: " << ops_ci.mean << " ± " << ops_ci.confidence << " ops/s. "
|
||||
<< "best: " << ops_ci.max << "ops/s." << std::endl;
|
||||
<< "best: " << ops_ci.min << "ops/s." << std::endl;
|
||||
os << "total: " << total_ci.mean << " ± " << total_ci.confidence << "ms. "
|
||||
<< "best: " << total_ci.min << "ms." << std::endl;
|
||||
os << "avg: " << mean_ci.mean << " ± " << mean_ci.confidence << "ms" << std::endl;
|
||||
@@ -360,8 +357,8 @@ void runRouteBenchmark(const OSRM &osrm, const GPSTraces &gpsTraces, int iterati
|
||||
|
||||
if (benchmark.radius)
|
||||
{
|
||||
params.radiuses = std::vector<std::optional<double>>(
|
||||
params.coordinates.size(), std::make_optional(*benchmark.radius));
|
||||
params.radiuses = std::vector<boost::optional<double>>(
|
||||
params.coordinates.size(), boost::make_optional(*benchmark.radius));
|
||||
}
|
||||
|
||||
engine::api::ResultT result = json::Object();
|
||||
|
||||
@@ -66,8 +66,8 @@ try
|
||||
|
||||
if (benchmark.radius)
|
||||
{
|
||||
params.radiuses = std::vector<std::optional<double>>(
|
||||
params.coordinates.size(), std::make_optional(*benchmark.radius));
|
||||
params.radiuses = std::vector<boost::optional<double>>(
|
||||
params.coordinates.size(), boost::make_optional(*benchmark.radius));
|
||||
}
|
||||
|
||||
TIMER_START(routes);
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
#include "util/typedefs.hpp"
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <optional>
|
||||
#include <boost/optional.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
@@ -215,7 +215,7 @@ util::json::Object makeRouteStep(guidance::RouteStep step, util::json::Value geo
|
||||
|
||||
util::json::Object makeRoute(const guidance::Route &route,
|
||||
util::json::Array legs,
|
||||
std::optional<util::json::Value> geometry,
|
||||
boost::optional<util::json::Value> geometry,
|
||||
const char *weight_name)
|
||||
{
|
||||
util::json::Object json_route;
|
||||
|
||||
@@ -12,13 +12,15 @@ bool EngineConfig::IsValid() const
|
||||
const auto unlimited_or_more_than = [](const auto v, const auto limit)
|
||||
{ return v == -1 || v > limit; };
|
||||
|
||||
const bool limits_valid = unlimited_or_more_than(max_locations_distance_table, 2) &&
|
||||
unlimited_or_more_than(max_locations_map_matching, 2) &&
|
||||
unlimited_or_more_than(max_radius_map_matching, 0) &&
|
||||
unlimited_or_more_than(max_locations_trip, 2) &&
|
||||
unlimited_or_more_than(max_locations_viaroute, 2) &&
|
||||
unlimited_or_more_than(max_results_nearest, 0) &&
|
||||
unlimited_or_more_than(default_radius, 0) && max_alternatives >= 0;
|
||||
const bool limits_valid =
|
||||
unlimited_or_more_than(max_locations_distance_table, 2) &&
|
||||
unlimited_or_more_than(max_locations_map_matching, 2) &&
|
||||
unlimited_or_more_than(max_radius_map_matching, 0) &&
|
||||
unlimited_or_more_than(max_locations_trip, 2) &&
|
||||
unlimited_or_more_than(max_locations_viaroute, 2) &&
|
||||
unlimited_or_more_than(max_results_nearest, 0) &&
|
||||
(!default_radius.has_value() || unlimited_or_more_than(*default_radius, 0)) &&
|
||||
max_alternatives >= 0;
|
||||
|
||||
return ((use_shared_memory && all_path_are_empty) || (use_mmap && storage_config.IsValid()) ||
|
||||
storage_config.IsValid()) &&
|
||||
|
||||
@@ -194,7 +194,7 @@ Status MatchPlugin::HandleRequest(const RoutingAlgorithmsInterface &algorithms,
|
||||
tidied.parameters.radiuses.begin(),
|
||||
tidied.parameters.radiuses.end(),
|
||||
search_radiuses.begin(),
|
||||
[default_radius = this->default_radius](const std::optional<double> &maybe_radius)
|
||||
[default_radius = this->default_radius](const boost::optional<double> &maybe_radius)
|
||||
{
|
||||
if (maybe_radius)
|
||||
{
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
namespace osrm::engine::plugins
|
||||
{
|
||||
|
||||
NearestPlugin::NearestPlugin(const int max_results_, const std::optional<double> default_radius_)
|
||||
NearestPlugin::NearestPlugin(const int max_results_, const boost::optional<double> default_radius_)
|
||||
: BasePlugin(default_radius_), max_results{max_results_}
|
||||
{
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ namespace osrm::engine::plugins
|
||||
{
|
||||
|
||||
TablePlugin::TablePlugin(const int max_locations_distance_table,
|
||||
const std::optional<double> default_radius)
|
||||
const boost::optional<double> default_radius)
|
||||
: BasePlugin(default_radius), max_locations_distance_table(max_locations_distance_table)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ namespace osrm::engine::plugins
|
||||
|
||||
ViaRoutePlugin::ViaRoutePlugin(int max_locations_viaroute,
|
||||
int max_alternatives,
|
||||
std::optional<double> default_radius)
|
||||
boost::optional<double> default_radius)
|
||||
: BasePlugin(default_radius), max_locations_viaroute(max_locations_viaroute),
|
||||
max_alternatives(max_alternatives)
|
||||
{
|
||||
|
||||
@@ -621,24 +621,27 @@ void unpackPackedPaths(InputIt first,
|
||||
BOOST_ASSERT(!facade.ExcludeNode(source));
|
||||
BOOST_ASSERT(!facade.ExcludeNode(target));
|
||||
|
||||
auto unpacked_subpath = search(search_engine_data,
|
||||
facade,
|
||||
forward_heap,
|
||||
reverse_heap,
|
||||
{},
|
||||
INVALID_EDGE_WEIGHT,
|
||||
sublevel,
|
||||
parent_cell_id);
|
||||
BOOST_ASSERT(!unpacked_subpath.edges.empty());
|
||||
BOOST_ASSERT(unpacked_subpath.nodes.size() > 1);
|
||||
BOOST_ASSERT(unpacked_subpath.nodes.front() == source);
|
||||
BOOST_ASSERT(unpacked_subpath.nodes.back() == target);
|
||||
unpacked_nodes.insert(unpacked_nodes.end(),
|
||||
std::next(unpacked_subpath.nodes.begin()),
|
||||
unpacked_subpath.nodes.end());
|
||||
unpacked_edges.insert(unpacked_edges.end(),
|
||||
unpacked_subpath.edges.begin(),
|
||||
unpacked_subpath.edges.end());
|
||||
// TODO: when structured bindings will be allowed change to
|
||||
// auto [subpath_weight, subpath_source, subpath_target, subpath] = ...
|
||||
EdgeWeight subpath_weight;
|
||||
std::vector<NodeID> subpath_nodes;
|
||||
std::vector<EdgeID> subpath_edges;
|
||||
std::tie(subpath_weight, subpath_nodes, subpath_edges) = search(search_engine_data,
|
||||
facade,
|
||||
forward_heap,
|
||||
reverse_heap,
|
||||
{},
|
||||
INVALID_EDGE_WEIGHT,
|
||||
sublevel,
|
||||
parent_cell_id);
|
||||
BOOST_ASSERT(!subpath_edges.empty());
|
||||
BOOST_ASSERT(subpath_nodes.size() > 1);
|
||||
BOOST_ASSERT(subpath_nodes.front() == source);
|
||||
BOOST_ASSERT(subpath_nodes.back() == target);
|
||||
unpacked_nodes.insert(
|
||||
unpacked_nodes.end(), std::next(subpath_nodes.begin()), subpath_nodes.end());
|
||||
unpacked_edges.insert(
|
||||
unpacked_edges.end(), subpath_edges.begin(), subpath_edges.end());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -70,19 +70,20 @@ InternalRouteResult directShortestPathSearch(SearchEngineData<mld::Algorithm> &e
|
||||
auto &reverse_heap = *engine_working_data.reverse_heap_1;
|
||||
insertNodesInHeaps(forward_heap, reverse_heap, endpoint_candidates);
|
||||
|
||||
auto unpacked_path = mld::search(engine_working_data,
|
||||
facade,
|
||||
forward_heap,
|
||||
reverse_heap,
|
||||
{},
|
||||
INVALID_EDGE_WEIGHT,
|
||||
endpoint_candidates);
|
||||
// TODO: when structured bindings will be allowed change to
|
||||
// auto [weight, source_node, target_node, unpacked_edges] = ...
|
||||
EdgeWeight weight = INVALID_EDGE_WEIGHT;
|
||||
std::vector<NodeID> unpacked_nodes;
|
||||
std::vector<EdgeID> unpacked_edges;
|
||||
std::tie(weight, unpacked_nodes, unpacked_edges) = mld::search(engine_working_data,
|
||||
facade,
|
||||
forward_heap,
|
||||
reverse_heap,
|
||||
{},
|
||||
INVALID_EDGE_WEIGHT,
|
||||
endpoint_candidates);
|
||||
|
||||
return extractRoute(facade,
|
||||
unpacked_path.weight,
|
||||
endpoint_candidates,
|
||||
unpacked_path.nodes,
|
||||
unpacked_path.edges);
|
||||
return extractRoute(facade, weight, endpoint_candidates, unpacked_nodes, unpacked_edges);
|
||||
}
|
||||
|
||||
} // namespace osrm::engine::routing_algorithms
|
||||
|
||||
@@ -70,7 +70,7 @@ SubMatchingList mapMatching(SearchEngineData<Algorithm> &engine_working_data,
|
||||
const CandidateLists &candidates_list,
|
||||
const std::vector<util::Coordinate> &trace_coordinates,
|
||||
const std::vector<unsigned> &trace_timestamps,
|
||||
const std::vector<std::optional<double>> &trace_gps_precision,
|
||||
const std::vector<boost::optional<double>> &trace_gps_precision,
|
||||
const bool allow_splitting)
|
||||
{
|
||||
map_matching::MatchingConfidence confidence;
|
||||
@@ -401,7 +401,6 @@ SubMatchingList mapMatching(SearchEngineData<Algorithm> &engine_working_data,
|
||||
auto trace_distance = 0.0;
|
||||
matching.nodes.reserve(reconstructed_indices.size());
|
||||
matching.indices.reserve(reconstructed_indices.size());
|
||||
matching.alternatives_count.reserve(reconstructed_indices.size());
|
||||
for (const auto &idx : reconstructed_indices)
|
||||
{
|
||||
const auto timestamp_index = idx.first;
|
||||
@@ -429,7 +428,7 @@ SubMatchingList mapMatching(SearchEngineData<Algorithm> &engine_working_data,
|
||||
|
||||
matching.confidence = confidence(trace_distance, matching_distance);
|
||||
|
||||
sub_matchings.emplace_back(std::move(matching));
|
||||
sub_matchings.push_back(matching);
|
||||
sub_matching_begin = sub_matching_end;
|
||||
}
|
||||
|
||||
@@ -437,22 +436,24 @@ SubMatchingList mapMatching(SearchEngineData<Algorithm> &engine_working_data,
|
||||
}
|
||||
|
||||
// CH
|
||||
template SubMatchingList mapMatching(SearchEngineData<ch::Algorithm> &engine_working_data,
|
||||
const DataFacade<ch::Algorithm> &facade,
|
||||
const CandidateLists &candidates_list,
|
||||
const std::vector<util::Coordinate> &trace_coordinates,
|
||||
const std::vector<unsigned> &trace_timestamps,
|
||||
const std::vector<std::optional<double>> &trace_gps_precision,
|
||||
const bool allow_splitting);
|
||||
template SubMatchingList
|
||||
mapMatching(SearchEngineData<ch::Algorithm> &engine_working_data,
|
||||
const DataFacade<ch::Algorithm> &facade,
|
||||
const CandidateLists &candidates_list,
|
||||
const std::vector<util::Coordinate> &trace_coordinates,
|
||||
const std::vector<unsigned> &trace_timestamps,
|
||||
const std::vector<boost::optional<double>> &trace_gps_precision,
|
||||
const bool allow_splitting);
|
||||
|
||||
// MLD
|
||||
template SubMatchingList mapMatching(SearchEngineData<mld::Algorithm> &engine_working_data,
|
||||
const DataFacade<mld::Algorithm> &facade,
|
||||
const CandidateLists &candidates_list,
|
||||
const std::vector<util::Coordinate> &trace_coordinates,
|
||||
const std::vector<unsigned> &trace_timestamps,
|
||||
const std::vector<std::optional<double>> &trace_gps_precision,
|
||||
const bool allow_splitting);
|
||||
template SubMatchingList
|
||||
mapMatching(SearchEngineData<mld::Algorithm> &engine_working_data,
|
||||
const DataFacade<mld::Algorithm> &facade,
|
||||
const CandidateLists &candidates_list,
|
||||
const std::vector<util::Coordinate> &trace_coordinates,
|
||||
const std::vector<unsigned> &trace_timestamps,
|
||||
const std::vector<boost::optional<double>> &trace_gps_precision,
|
||||
const bool allow_splitting);
|
||||
|
||||
} // namespace osrm::engine::routing_algorithms
|
||||
|
||||
|
||||
@@ -9,12 +9,12 @@ template InternalRouteResult
|
||||
shortestPathSearch(SearchEngineData<ch::Algorithm> &engine_working_data,
|
||||
const DataFacade<ch::Algorithm> &facade,
|
||||
const std::vector<PhantomNodeCandidates> &waypoint_candidates,
|
||||
const std::optional<bool> continue_straight_at_waypoint);
|
||||
const boost::optional<bool> continue_straight_at_waypoint);
|
||||
|
||||
template InternalRouteResult
|
||||
shortestPathSearch(SearchEngineData<mld::Algorithm> &engine_working_data,
|
||||
const DataFacade<mld::Algorithm> &facade,
|
||||
const std::vector<PhantomNodeCandidates> &waypoint_candidates,
|
||||
const std::optional<bool> continue_straight_at_waypoint);
|
||||
const boost::optional<bool> continue_straight_at_waypoint);
|
||||
|
||||
} // namespace osrm::engine::routing_algorithms
|
||||
|
||||
@@ -23,6 +23,8 @@
|
||||
#include <vector>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#if (_MSC_VER >= 1928)
|
||||
#ifdef _DEBUG
|
||||
namespace osrm
|
||||
{
|
||||
namespace extractor
|
||||
@@ -35,6 +37,8 @@ const ByEdgeOrByMeterValue::ValueByMeter ByEdgeOrByMeterValue::by_meter;
|
||||
} // namespace extractor
|
||||
} // namespace osrm
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
namespace osrm::extractor
|
||||
{
|
||||
|
||||
@@ -28,8 +28,8 @@ template <typename ParameterT,
|
||||
typename GrammarT,
|
||||
typename std::enable_if<detail::is_parameter_t<ParameterT>::value, int>::type = 0,
|
||||
typename std::enable_if<detail::is_grammar_t<GrammarT>::value, int>::type = 0>
|
||||
std::optional<ParameterT> parseParameters(std::string::iterator &iter,
|
||||
const std::string::iterator end)
|
||||
boost::optional<ParameterT> parseParameters(std::string::iterator &iter,
|
||||
const std::string::iterator end)
|
||||
{
|
||||
using It = std::decay<decltype(iter)>::type;
|
||||
|
||||
@@ -56,52 +56,52 @@ std::optional<ParameterT> parseParameters(std::string::iterator &iter,
|
||||
// as normal parser error
|
||||
}
|
||||
|
||||
return std::nullopt;
|
||||
return boost::none;
|
||||
}
|
||||
} // namespace detail
|
||||
|
||||
template <>
|
||||
std::optional<engine::api::RouteParameters> parseParameters(std::string::iterator &iter,
|
||||
const std::string::iterator end)
|
||||
boost::optional<engine::api::RouteParameters> parseParameters(std::string::iterator &iter,
|
||||
const std::string::iterator end)
|
||||
{
|
||||
return detail::parseParameters<engine::api::RouteParameters, RouteParametersGrammar<>>(iter,
|
||||
end);
|
||||
}
|
||||
|
||||
template <>
|
||||
std::optional<engine::api::TableParameters> parseParameters(std::string::iterator &iter,
|
||||
const std::string::iterator end)
|
||||
boost::optional<engine::api::TableParameters> parseParameters(std::string::iterator &iter,
|
||||
const std::string::iterator end)
|
||||
{
|
||||
return detail::parseParameters<engine::api::TableParameters, TableParametersGrammar<>>(iter,
|
||||
end);
|
||||
}
|
||||
|
||||
template <>
|
||||
std::optional<engine::api::NearestParameters> parseParameters(std::string::iterator &iter,
|
||||
const std::string::iterator end)
|
||||
boost::optional<engine::api::NearestParameters> parseParameters(std::string::iterator &iter,
|
||||
const std::string::iterator end)
|
||||
{
|
||||
return detail::parseParameters<engine::api::NearestParameters, NearestParametersGrammar<>>(iter,
|
||||
end);
|
||||
}
|
||||
|
||||
template <>
|
||||
std::optional<engine::api::TripParameters> parseParameters(std::string::iterator &iter,
|
||||
const std::string::iterator end)
|
||||
boost::optional<engine::api::TripParameters> parseParameters(std::string::iterator &iter,
|
||||
const std::string::iterator end)
|
||||
{
|
||||
return detail::parseParameters<engine::api::TripParameters, TripParametersGrammar<>>(iter, end);
|
||||
}
|
||||
|
||||
template <>
|
||||
std::optional<engine::api::MatchParameters> parseParameters(std::string::iterator &iter,
|
||||
const std::string::iterator end)
|
||||
boost::optional<engine::api::MatchParameters> parseParameters(std::string::iterator &iter,
|
||||
const std::string::iterator end)
|
||||
{
|
||||
return detail::parseParameters<engine::api::MatchParameters, MatchParametersGrammar<>>(iter,
|
||||
end);
|
||||
}
|
||||
|
||||
template <>
|
||||
std::optional<engine::api::TileParameters> parseParameters(std::string::iterator &iter,
|
||||
const std::string::iterator end)
|
||||
boost::optional<engine::api::TileParameters> parseParameters(std::string::iterator &iter,
|
||||
const std::string::iterator end)
|
||||
{
|
||||
return detail::parseParameters<engine::api::TileParameters, TileParametersGrammar<>>(iter, end);
|
||||
}
|
||||
|
||||
@@ -65,7 +65,7 @@ struct URLParser final : qi::grammar<Iterator, Into>
|
||||
namespace osrm::server::api
|
||||
{
|
||||
|
||||
std::optional<ParsedURL> parseURL(std::string::iterator &iter, const std::string::iterator end)
|
||||
boost::optional<ParsedURL> parseURL(std::string::iterator &iter, const std::string::iterator end)
|
||||
{
|
||||
using It = std::decay<decltype(iter)>::type;
|
||||
|
||||
@@ -77,7 +77,7 @@ std::optional<ParsedURL> parseURL(std::string::iterator &iter, const std::string
|
||||
const auto ok = boost::spirit::qi::parse(iter, end, parser(boost::phoenix::val(iter)), out);
|
||||
|
||||
if (ok && iter == end)
|
||||
return std::make_optional(out);
|
||||
return boost::make_optional(out);
|
||||
}
|
||||
catch (const qi::expectation_failure<It> &failure)
|
||||
{
|
||||
@@ -86,7 +86,7 @@ std::optional<ParsedURL> parseURL(std::string::iterator &iter, const std::string
|
||||
iter = failure.first;
|
||||
}
|
||||
|
||||
return std::nullopt;
|
||||
return boost::none;
|
||||
}
|
||||
|
||||
} // namespace osrm::server::api
|
||||
|
||||
@@ -186,7 +186,7 @@ inline unsigned generateServerProgramOptions(const int argc,
|
||||
value<double>(&config.max_radius_map_matching)->default_value(-1.0),
|
||||
"Max. radius size supported in map matching query. Default: unlimited.") //
|
||||
("default-radius",
|
||||
value<double>(&config.default_radius)->default_value(-1.0),
|
||||
value<boost::optional<double>>(&config.default_radius)->default_value(-1.0),
|
||||
"Default radius size for queries. Default: unlimited.");
|
||||
|
||||
// hidden options, will be allowed on command line, but will not be shown to the user
|
||||
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
# see https://clang.llvm.org/docs/ClangFormatStyleOptions.html
|
||||
---
|
||||
BasedOnStyle: LLVM
|
||||
Language: Cpp
|
||||
Standard: c++17
|
||||
ColumnLimit: 127
|
||||
|
||||
AccessModifierOffset: -4
|
||||
AlignEscapedNewlines: Left
|
||||
AllowShortFunctionsOnASingleLine: Empty
|
||||
AllowShortLambdasOnASingleLine: false
|
||||
AlwaysBreakTemplateDeclarations: true
|
||||
BinPackArguments: false
|
||||
BinPackParameters: false
|
||||
BreakConstructorInitializers: BeforeComma
|
||||
BreakStringLiterals: false
|
||||
IndentPPDirectives: AfterHash
|
||||
IndentWidth: 4
|
||||
PointerAlignment: Left
|
||||
UseTab: Never
|
||||
+55
@@ -0,0 +1,55 @@
|
||||
---
|
||||
Checks: '*
|
||||
-abseil-string-find-str-contains
|
||||
-altera*
|
||||
-bugprone-easily-swappable-parameters
|
||||
-cert-err58-cpp
|
||||
-cppcoreguidelines-avoid-magic-numbers
|
||||
-cppcoreguidelines-pro-bounds-constant-array-index
|
||||
-cppcoreguidelines-pro-bounds-pointer-arithmetic
|
||||
-fuchsia*
|
||||
-llvm-header-guard
|
||||
-llvmlibc*
|
||||
-readability-function-cognitive-complexity
|
||||
-readability-identifier-length
|
||||
-readability-magic-numbers
|
||||
'
|
||||
HeaderFilterRegex: ''
|
||||
CheckOptions:
|
||||
cppcoreguidelines-avoid-do-while.IgnoreMacros: 'true'
|
||||
readability-identifier-naming.MacroDefinitionCase: 'UPPER_CASE'
|
||||
readability-identifier-naming.TemplateParameterCase: 'CamelCase'
|
||||
readability-identifier-naming.TypeTemplateParameterCase: 'CamelCase'
|
||||
readability-identifier-naming.ValueTemplateParameterCase: 'CamelCase'
|
||||
readability-identifier-naming.ParameterPackCase: 'lower_case'
|
||||
readability-identifier-naming.AbstractClassCase: 'lower_case'
|
||||
readability-identifier-naming.ClassCase: 'lower_case'
|
||||
readability-identifier-naming.ClassMemberCase: 'lower_case'
|
||||
readability-identifier-naming.ConstantCase: 'lower_case'
|
||||
readability-identifier-naming.ConstexprVariableCase: 'lower_case'
|
||||
readability-identifier-naming.EnumCase: 'lower_case'
|
||||
readability-identifier-naming.EnumConstantCase: 'lower_case'
|
||||
readability-identifier-naming.FunctionCase: 'lower_case'
|
||||
readability-identifier-naming.GlobalConstantCase: 'lower_case'
|
||||
readability-identifier-naming.LocalVariableCase: 'lower_case'
|
||||
readability-identifier-naming.MemberCase: 'lower_case'
|
||||
readability-identifier-naming.NamespaceCase: 'lower_case'
|
||||
readability-identifier-naming.ParameterCase: 'lower_case'
|
||||
readability-identifier-naming.StructCase: 'lower_case'
|
||||
readability-identifier-naming.TypeAliasCase: 'lower_case'
|
||||
readability-identifier-naming.TypedefCase: 'lower_case'
|
||||
readability-identifier-naming.StaticConstantCase: 'lower_case'
|
||||
readability-identifier-naming.StaticVariableCase: 'lower_case'
|
||||
readability-identifier-naming.UnionCase: 'lower_case'
|
||||
readability-identifier-naming.VariableCase: 'lower_case'
|
||||
readability-identifier-naming.GlobalConstantPrefix: 'global_'
|
||||
readability-identifier-naming.GlobalVariablePrefix: 'global_'
|
||||
readability-identifier-naming.MemberPrefix: 'm_'
|
||||
readability-identifier-naming.PrivateMemberPrefix: 'm_'
|
||||
readability-identifier-naming.PrivateMemberPrefix: 'm_'
|
||||
readability-identifier-naming.ProtectedMemberPrefix: 'm_'
|
||||
readability-identifier-naming.PublicMemberPrefix: ''
|
||||
readability-identifier-naming.StaticConstantPrefix: 'static_'
|
||||
readability-identifier-naming.StaticVariablePrefix: 'static_'
|
||||
readability-identifier-naming.ClassMemberPrefix: 'static_'
|
||||
...
|
||||
@@ -0,0 +1 @@
|
||||
data/fuzz
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
# These are supported funding model platforms
|
||||
|
||||
github: [martinus] # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
|
||||
patreon: # Replace with a single Patreon username
|
||||
open_collective: # Replace with a single Open Collective username
|
||||
ko_fi: # Replace with a single Ko-fi username
|
||||
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
|
||||
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
|
||||
liberapay: # Replace with a single Liberapay username
|
||||
issuehunt: # Replace with a single IssueHunt username
|
||||
otechie: # Replace with a single Otechie username
|
||||
lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry
|
||||
custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
|
||||
@@ -0,0 +1,28 @@
|
||||
---
|
||||
name: Bug report
|
||||
about: Create a report to help us improve
|
||||
title: "[BUG] "
|
||||
labels: bug
|
||||
assignees: martinus
|
||||
|
||||
---
|
||||
|
||||
**Describe the bug**
|
||||
A clear and concise description of what the bug is.
|
||||
|
||||
**To Reproduce**
|
||||
Steps to reproduce the behavior:
|
||||
1.
|
||||
2.
|
||||
3.
|
||||
|
||||
**Expected behavior**
|
||||
A clear and concise description of what you expected to happen.
|
||||
|
||||
**System (please complete the following information):**
|
||||
- OS: [e.g. Linux]
|
||||
- Compiler: [e.g. clang++, g++]
|
||||
- Version [e.g. 13.0.1]
|
||||
|
||||
**Additional context**
|
||||
Add any other context about the problem here.
|
||||
@@ -0,0 +1,20 @@
|
||||
---
|
||||
name: Feature request
|
||||
about: Suggest an idea for this project
|
||||
title: ''
|
||||
labels: enhancement
|
||||
assignees: martinus
|
||||
|
||||
---
|
||||
|
||||
**Is your feature request related to a problem? Please describe.**
|
||||
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
||||
|
||||
**Describe the solution you'd like**
|
||||
A clear and concise description of what you want to happen.
|
||||
|
||||
**Describe alternatives you've considered**
|
||||
A clear and concise description of any alternative solutions or features you've considered.
|
||||
|
||||
**Additional context**
|
||||
Add any other context or screenshots about the feature request here.
|
||||
@@ -0,0 +1,74 @@
|
||||
name: Build, Test, Lint
|
||||
|
||||
on: [push, pull_request]
|
||||
|
||||
# see https://github.com/mesonbuild/meson/blob/master/docs/markdown/Continuous-Integration.md
|
||||
jobs:
|
||||
|
||||
lint:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: '3.x'
|
||||
- run: ./scripts/lint/lint-version.py
|
||||
|
||||
linux:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- run: sudo apt-get install -yq libboost-dev
|
||||
- uses: hendrikmuhs/ccache-action@v1.2
|
||||
- uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: '3.x'
|
||||
- run: pip install meson ninja
|
||||
- run: meson setup builddir/
|
||||
env:
|
||||
CXX: ccache c++
|
||||
- run: meson test -C builddir/ -v
|
||||
- uses: actions/upload-artifact@v3
|
||||
if: failure()
|
||||
with:
|
||||
name: Linux_Meson_Testlog
|
||||
path: builddir/meson-logs/testlog.txt
|
||||
|
||||
macos:
|
||||
runs-on: macos-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: '3.x'
|
||||
- run: brew install gcc ccache meson ninja
|
||||
- run: meson setup builddir/
|
||||
env:
|
||||
CXX: ccache c++
|
||||
- run: meson test -C builddir/ -v
|
||||
- uses: actions/upload-artifact@v3
|
||||
if: failure()
|
||||
with:
|
||||
name: MacOS_Meson_Testlog
|
||||
path: builddir/meson-logs/testlog.txt
|
||||
|
||||
windows:
|
||||
runs-on: windows-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: '3.x'
|
||||
- uses: BSFishy/pip-action@v1
|
||||
with:
|
||||
packages: ninja meson
|
||||
- uses: ilammy/msvc-dev-cmd@v1
|
||||
- run: meson setup builddir
|
||||
- run: meson test -C builddir -v
|
||||
- uses: actions/upload-artifact@v3
|
||||
if: failure()
|
||||
with:
|
||||
name: Windows_Meson_Testlog
|
||||
path: |
|
||||
builddir/meson-logs/testlog.txt
|
||||
builddir/test/udm-test.exe
|
||||
@@ -0,0 +1,14 @@
|
||||
build
|
||||
builddir
|
||||
.cache
|
||||
.vscode
|
||||
compile_commands.json
|
||||
|
||||
# ignore all in subprojects except the .wrap files
|
||||
/subprojects/*
|
||||
!/subprojects/*.wrap
|
||||
|
||||
# c++ modules
|
||||
*.pcm
|
||||
a.out
|
||||
*.o
|
||||
+61
@@ -0,0 +1,61 @@
|
||||
cmake_minimum_required(VERSION 3.12)
|
||||
project("unordered_dense"
|
||||
VERSION 4.4.0
|
||||
DESCRIPTION "A fast & densely stored hashmap and hashset based on robin-hood backward shift deletion"
|
||||
HOMEPAGE_URL "https://github.com/martinus/unordered_dense")
|
||||
|
||||
include(GNUInstallDirs)
|
||||
|
||||
# determine whether this is a standalone project or included by other projects
|
||||
if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME)
|
||||
set(_unordered_dense_is_toplevel_project TRUE)
|
||||
else()
|
||||
set(_unordered_dense_is_toplevel_project FALSE)
|
||||
endif()
|
||||
|
||||
add_library(unordered_dense INTERFACE)
|
||||
add_library(unordered_dense::unordered_dense ALIAS unordered_dense)
|
||||
|
||||
target_include_directories(
|
||||
unordered_dense
|
||||
INTERFACE
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
|
||||
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>)
|
||||
|
||||
target_compile_features(unordered_dense INTERFACE cxx_std_17)
|
||||
|
||||
if(_unordered_dense_is_toplevel_project)
|
||||
# locations are provided by GNUInstallDirs
|
||||
install(
|
||||
TARGETS unordered_dense
|
||||
EXPORT unordered_dense_Targets
|
||||
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
|
||||
|
||||
include(CMakePackageConfigHelpers)
|
||||
write_basic_package_version_file(
|
||||
"unordered_denseConfigVersion.cmake"
|
||||
VERSION ${PROJECT_VERSION}
|
||||
COMPATIBILITY SameMajorVersion)
|
||||
|
||||
configure_package_config_file(
|
||||
"${PROJECT_SOURCE_DIR}/cmake/unordered_denseConfig.cmake.in"
|
||||
"${PROJECT_BINARY_DIR}/unordered_denseConfig.cmake"
|
||||
INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME})
|
||||
|
||||
install(
|
||||
EXPORT unordered_dense_Targets
|
||||
FILE unordered_denseTargets.cmake
|
||||
NAMESPACE unordered_dense::
|
||||
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME})
|
||||
|
||||
install(
|
||||
FILES "${PROJECT_BINARY_DIR}/unordered_denseConfig.cmake"
|
||||
"${PROJECT_BINARY_DIR}/unordered_denseConfigVersion.cmake"
|
||||
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME})
|
||||
|
||||
install(
|
||||
DIRECTORY ${PROJECT_SOURCE_DIR}/include/ankerl
|
||||
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
|
||||
endif()
|
||||
+76
@@ -0,0 +1,76 @@
|
||||
# Contributor Covenant Code of Conduct
|
||||
|
||||
## Our Pledge
|
||||
|
||||
In the interest of fostering an open and welcoming environment, we as
|
||||
contributors and maintainers pledge to making participation in our project and
|
||||
our community a harassment-free experience for everyone, regardless of age, body
|
||||
size, disability, ethnicity, sex characteristics, gender identity and expression,
|
||||
level of experience, education, socio-economic status, nationality, personal
|
||||
appearance, race, religion, or sexual identity and orientation.
|
||||
|
||||
## Our Standards
|
||||
|
||||
Examples of behavior that contributes to creating a positive environment
|
||||
include:
|
||||
|
||||
* Using welcoming and inclusive language
|
||||
* Being respectful of differing viewpoints and experiences
|
||||
* Gracefully accepting constructive criticism
|
||||
* Focusing on what is best for the community
|
||||
* Showing empathy towards other community members
|
||||
|
||||
Examples of unacceptable behavior by participants include:
|
||||
|
||||
* The use of sexualized language or imagery and unwelcome sexual attention or
|
||||
advances
|
||||
* Trolling, insulting/derogatory comments, and personal or political attacks
|
||||
* Public or private harassment
|
||||
* Publishing others' private information, such as a physical or electronic
|
||||
address, without explicit permission
|
||||
* Other conduct which could reasonably be considered inappropriate in a
|
||||
professional setting
|
||||
|
||||
## Our Responsibilities
|
||||
|
||||
Project maintainers are responsible for clarifying the standards of acceptable
|
||||
behavior and are expected to take appropriate and fair corrective action in
|
||||
response to any instances of unacceptable behavior.
|
||||
|
||||
Project maintainers have the right and responsibility to remove, edit, or
|
||||
reject comments, commits, code, wiki edits, issues, and other contributions
|
||||
that are not aligned to this Code of Conduct, or to ban temporarily or
|
||||
permanently any contributor for other behaviors that they deem inappropriate,
|
||||
threatening, offensive, or harmful.
|
||||
|
||||
## Scope
|
||||
|
||||
This Code of Conduct applies both within project spaces and in public spaces
|
||||
when an individual is representing the project or its community. Examples of
|
||||
representing a project or community include using an official project e-mail
|
||||
address, posting via an official social media account, or acting as an appointed
|
||||
representative at an online or offline event. Representation of a project may be
|
||||
further defined and clarified by project maintainers.
|
||||
|
||||
## Enforcement
|
||||
|
||||
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
||||
reported by contacting the project team at martin.ankerl@gmail.com. All
|
||||
complaints will be reviewed and investigated and will result in a response that
|
||||
is deemed necessary and appropriate to the circumstances. The project team is
|
||||
obligated to maintain confidentiality with regard to the reporter of an incident.
|
||||
Further details of specific enforcement policies may be posted separately.
|
||||
|
||||
Project maintainers who do not follow or enforce the Code of Conduct in good
|
||||
faith may face temporary or permanent repercussions as determined by other
|
||||
members of the project's leadership.
|
||||
|
||||
## Attribution
|
||||
|
||||
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
|
||||
available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
|
||||
|
||||
[homepage]: https://www.contributor-covenant.org
|
||||
|
||||
For answers to common questions about this code of conduct, see
|
||||
https://www.contributor-covenant.org/faq
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
* Coding style should be consistent with the code around you.
|
||||
* Use automatic formatting with clang-format.
|
||||
* One feature per pull request
|
||||
Vendored
+21
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2022 Martin Leitner-Ankerl
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
+374
@@ -0,0 +1,374 @@
|
||||
<a id="top"></a>
|
||||
|
||||
[](https://github.com/martinus/unordered_dense/releases)
|
||||
[](https://raw.githubusercontent.com/martinus/unordered_dense/main/LICENSE)
|
||||
[](https://github.com/martinus/unordered_dense/actions)
|
||||
[](https://bestpractices.coreinfrastructure.org/projects/6220)
|
||||
[](https://github.com/sponsors/martinus)
|
||||
|
||||
# 🚀 ankerl::unordered_dense::{map, set} <!-- omit in toc -->
|
||||
|
||||
A fast & densely stored hashmap and hashset based on robin-hood backward shift deletion for C++17 and later.
|
||||
|
||||
The classes `ankerl::unordered_dense::map` and `ankerl::unordered_dense::set` are (almost) drop-in replacements of `std::unordered_map` and `std::unordered_set`. While they don't have as strong iterator / reference stability guaranties, they are typically *much* faster.
|
||||
|
||||
Additionally, there are `ankerl::unordered_dense::segmented_map` and `ankerl::unordered_dense::segmented_set` with lower peak memory usage. and stable iterator/references on insert.
|
||||
|
||||
- [1. Overview](#1-overview)
|
||||
- [2. Installation](#2-installation)
|
||||
- [2.1. Installing using cmake](#21-installing-using-cmake)
|
||||
- [3. Usage](#3-usage)
|
||||
- [3.1. Modules](#31-modules)
|
||||
- [3.2. Hash](#32-hash)
|
||||
- [3.2.1. Simple Hash](#321-simple-hash)
|
||||
- [3.2.2. High Quality Hash](#322-high-quality-hash)
|
||||
- [3.2.3. Specialize `ankerl::unordered_dense::hash`](#323-specialize-ankerlunordered_densehash)
|
||||
- [3.2.4. Heterogeneous Overloads using `is_transparent`](#324-heterogeneous-overloads-using-is_transparent)
|
||||
- [3.2.5. Automatic Fallback to `std::hash`](#325-automatic-fallback-to-stdhash)
|
||||
- [3.2.6. Hash the Whole Memory](#326-hash-the-whole-memory)
|
||||
- [3.3. Container API](#33-container-api)
|
||||
- [3.3.1. `auto extract() && -> value_container_type`](#331-auto-extract----value_container_type)
|
||||
- [3.3.2. `extract()` single Elements](#332-extract-single-elements)
|
||||
- [3.3.3. `[[nodiscard]] auto values() const noexcept -> value_container_type const&`](#333-nodiscard-auto-values-const-noexcept---value_container_type-const)
|
||||
- [3.3.4. `auto replace(value_container_type&& container)`](#334-auto-replacevalue_container_type-container)
|
||||
- [3.4. Custom Container Types](#34-custom-container-types)
|
||||
- [3.5. Custom Bucket Types](#35-custom-bucket-types)
|
||||
- [3.5.1. `ankerl::unordered_dense::bucket_type::standard`](#351-ankerlunordered_densebucket_typestandard)
|
||||
- [3.5.2. `ankerl::unordered_dense::bucket_type::big`](#352-ankerlunordered_densebucket_typebig)
|
||||
- [4. `segmented_map` and `segmented_set`](#4-segmented_map-and-segmented_set)
|
||||
- [5. Design](#5-design)
|
||||
- [5.1. Inserts](#51-inserts)
|
||||
- [5.2. Lookups](#52-lookups)
|
||||
- [5.3. Removals](#53-removals)
|
||||
- [6. Real World Usage](#6-real-world-usage)
|
||||
|
||||
## 1. Overview
|
||||
|
||||
The chosen design has a few advantages over `std::unordered_map`:
|
||||
|
||||
* Perfect iteration speed - Data is stored in a `std::vector`, all data is contiguous!
|
||||
* Very fast insertion & lookup speed, in the same ballpark as [`absl::flat_hash_map`](https://abseil.io/docs/cpp/guides/container`)
|
||||
* Low memory usage
|
||||
* Full support for `std::allocators`, and [polymorphic allocators](https://en.cppreference.com/w/cpp/memory/polymorphic_allocator). There are `ankerl::unordered_dense::pmr` typedefs available
|
||||
* Customizeable storage type: with a template parameter you can e.g. switch from `std::vector` to `boost::interprocess::vector` or any other compatible random-access container.
|
||||
* Better debugging: the underlying data can be easily seen in any debugger that can show an `std::vector`.
|
||||
|
||||
There's no free lunch, so there are a few disadvantages:
|
||||
|
||||
* Deletion speed is relatively slow. This needs two lookups: one for the element to delete, and one for the element that is moved onto the newly empty spot.
|
||||
* no `const Key` in `std::pair<Key, Value>`
|
||||
* Iterators and references are not stable on insert or erase.
|
||||
|
||||
## 2. Installation
|
||||
|
||||
<!-- See https://github.com/bernedom/SI/blob/main/doc/installation-guide.md -->
|
||||
The default installation location is `/usr/local`.
|
||||
|
||||
### 2.1. Installing using cmake
|
||||
|
||||
Clone the repository and run these commands in the cloned folder:
|
||||
|
||||
```sh
|
||||
mkdir build && cd build
|
||||
cmake ..
|
||||
cmake --build . --target install
|
||||
```
|
||||
|
||||
Consider setting an install prefix if you do not want to install `unordered_dense` system wide, like so:
|
||||
|
||||
```sh
|
||||
mkdir build && cd build
|
||||
cmake -DCMAKE_INSTALL_PREFIX:PATH=${HOME}/unordered_dense_install ..
|
||||
cmake --build . --target install
|
||||
```
|
||||
|
||||
To make use of the installed library, add this to your project:
|
||||
|
||||
```cmake
|
||||
find_package(unordered_dense CONFIG REQUIRED)
|
||||
target_link_libraries(your_project_name unordered_dense::unordered_dense)
|
||||
```
|
||||
|
||||
## 3. Usage
|
||||
|
||||
### 3.1. Modules
|
||||
|
||||
`ankerl::unordered_dense` supports c++20 modules. Simply compile `src/ankerl.unordered_dense.cpp` and use the resulting module, e.g. like so:
|
||||
|
||||
```sh
|
||||
clang++ -std=c++20 -I include --precompile -x c++-module src/ankerl.unordered_dense.cpp
|
||||
clang++ -std=c++20 -c ankerl.unordered_dense.pcm
|
||||
```
|
||||
|
||||
To use the module with e.g. in `module_test.cpp`, use
|
||||
|
||||
```cpp
|
||||
import ankerl.unordered_dense;
|
||||
```
|
||||
|
||||
and compile with e.g.
|
||||
|
||||
```sh
|
||||
clang++ -std=c++20 -fprebuilt-module-path=. ankerl.unordered_dense.o module_test.cpp -o main
|
||||
```
|
||||
|
||||
A simple demo script can be found in `test/modules`.
|
||||
|
||||
### 3.2. Hash
|
||||
|
||||
`ankerl::unordered_dense::hash` is a fast and high quality hash, based on [wyhash](https://github.com/wangyi-fudan/wyhash). The `ankerl::unordered_dense` map/set differentiates between hashes of high quality (good [avalanching effect](https://en.wikipedia.org/wiki/Avalanche_effect)) and bad quality. Hashes with good quality contain a special marker:
|
||||
|
||||
```cpp
|
||||
using is_avalanching = void;
|
||||
```
|
||||
|
||||
This is the cases for the specializations `bool`, `char`, `signed char`, `unsigned char`, `char8_t`, `char16_t`, `char32_t`, `wchar_t`, `short`, `unsigned short`, `int`, `unsigned int`, `long`, `long long`, `unsigned long`, `unsigned long long`, `T*`, `std::unique_ptr<T>`, `std::shared_ptr<T>`, `enum`, `std::basic_string<C>`, and `std::basic_string_view<C>`.
|
||||
|
||||
Hashes that do not contain such a marker are assumed to be of bad quality and receive an additional mixing step inside the map/set implementation.
|
||||
|
||||
#### 3.2.1. Simple Hash
|
||||
|
||||
Consider a simple custom key type:
|
||||
|
||||
```cpp
|
||||
struct id {
|
||||
uint64_t value{};
|
||||
|
||||
auto operator==(id const& other) const -> bool {
|
||||
return value == other.value;
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
The simplest implementation of a hash is this:
|
||||
|
||||
```cpp
|
||||
struct custom_hash_simple {
|
||||
auto operator()(id const& x) const noexcept -> uint64_t {
|
||||
return x.value;
|
||||
}
|
||||
};
|
||||
```
|
||||
This can be used e.g. with
|
||||
|
||||
```cpp
|
||||
auto ids = ankerl::unordered_dense::set<id, custom_hash_simple>();
|
||||
```
|
||||
|
||||
Since `custom_hash_simple` doesn't have a `using is_avalanching = void;` marker it is considered to be of bad quality and additional mixing of `x.value` is automatically provided inside the set.
|
||||
|
||||
#### 3.2.2. High Quality Hash
|
||||
|
||||
Back to the `id` example, we can easily implement a higher quality hash:
|
||||
|
||||
```cpp
|
||||
struct custom_hash_avalanching {
|
||||
using is_avalanching = void;
|
||||
|
||||
auto operator()(id const& x) const noexcept -> uint64_t {
|
||||
return ankerl::unordered_dense::detail::wyhash::hash(x.value);
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
We know `wyhash::hash` is of high quality, so we can add `using is_avalanching = void;` which makes the map/set directly use the returned value.
|
||||
|
||||
|
||||
#### 3.2.3. Specialize `ankerl::unordered_dense::hash`
|
||||
|
||||
Instead of creating a new class you can also specialize `ankerl::unordered_dense::hash`:
|
||||
|
||||
```cpp
|
||||
template <>
|
||||
struct ankerl::unordered_dense::hash<id> {
|
||||
using is_avalanching = void;
|
||||
|
||||
[[nodiscard]] auto operator()(id const& x) const noexcept -> uint64_t {
|
||||
return detail::wyhash::hash(x.value);
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
#### 3.2.4. Heterogeneous Overloads using `is_transparent`
|
||||
|
||||
This map/set supports heterogeneous overloads as described in [P2363 Extending associative containers with the remaining heterogeneous overloads](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2363r3.html) which is [targeted for C++26](https://wg21.link/p2077r2). This has overloads for `find`, `count`, `contains`, `equal_range` (see [P0919R3](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0919r3.html)), `erase` (see [P2077R2](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/p2077r2.html)), and `try_emplace`, `insert_or_assign`, `operator[]`, `at`, and `insert` & `emplace` for sets (see [P2363R3](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2363r3.html)).
|
||||
|
||||
For heterogeneous overloads to take affect, both `hasher` and `key_equal` need to have the attribute `is_transparent` set.
|
||||
|
||||
Here is an example implementation that's usable with any string types that is convertible to `std::string_view` (e.g. `char const*` and `std::string`):
|
||||
|
||||
```cpp
|
||||
struct string_hash {
|
||||
using is_transparent = void; // enable heterogeneous overloads
|
||||
using is_avalanching = void; // mark class as high quality avalanching hash
|
||||
|
||||
[[nodiscard]] auto operator()(std::string_view str) const noexcept -> uint64_t {
|
||||
return ankerl::unordered_dense::hash<std::string_view>{}(str);
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
To make use of this hash you'll need to specify it as a type, and also a `key_equal` with `is_transparent` like [std::equal_to<>](https://en.cppreference.com/w/cpp/utility/functional/equal_to_void):
|
||||
|
||||
```cpp
|
||||
auto map = ankerl::unordered_dense::map<std::string, size_t, string_hash, std::equal_to<>>();
|
||||
```
|
||||
|
||||
For more information see the examples in `test/unit/transparent.cpp`.
|
||||
|
||||
|
||||
#### 3.2.5. Automatic Fallback to `std::hash`
|
||||
|
||||
When an implementation for `std::hash` of a custom type is available, this is automatically used and assumed to be of bad quality (thus `std::hash` is used, but an additional mixing step is performed).
|
||||
|
||||
|
||||
#### 3.2.6. Hash the Whole Memory
|
||||
|
||||
When the type [has a unique object representation](https://en.cppreference.com/w/cpp/types/has_unique_object_representations) (no padding, trivially copyable), one can just hash the object's memory. Consider a simple class
|
||||
|
||||
```cpp
|
||||
struct point {
|
||||
int x{};
|
||||
int y{};
|
||||
|
||||
auto operator==(point const& other) const -> bool {
|
||||
return x == other.x && y == other.y;
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
A fast and high quality hash can be easily provided like so:
|
||||
|
||||
```cpp
|
||||
struct custom_hash_unique_object_representation {
|
||||
using is_avalanching = void;
|
||||
|
||||
[[nodiscard]] auto operator()(point const& f) const noexcept -> uint64_t {
|
||||
static_assert(std::has_unique_object_representations_v<point>);
|
||||
return ankerl::unordered_dense::detail::wyhash::hash(&f, sizeof(f));
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
### 3.3. Container API
|
||||
|
||||
In addition to the standard `std::unordered_map` API (see https://en.cppreference.com/w/cpp/container/unordered_map) we have additional API that is somewhat similar to the node API, but leverages the fact that we're using a random access container internally:
|
||||
|
||||
#### 3.3.1. `auto extract() && -> value_container_type`
|
||||
|
||||
Extracts the internally used container. `*this` is emptied.
|
||||
|
||||
#### 3.3.2. `extract()` single Elements
|
||||
|
||||
Similar to `erase()` I have an API call `extract()`. It behaves exactly the same as `erase`, except that the return value is the moved element that is removed from the container:
|
||||
|
||||
* `auto extract(const_iterator it) -> value_type`
|
||||
* `auto extract(Key const& key) -> std::optional<value_type>`
|
||||
* `template <class K> auto extract(K&& key) -> std::optional<value_type>`
|
||||
|
||||
Note that the `extract(key)` API returns an `std::optional<value_type>` that is empty when the key is not found.
|
||||
|
||||
#### 3.3.3. `[[nodiscard]] auto values() const noexcept -> value_container_type const&`
|
||||
|
||||
Exposes the underlying values container.
|
||||
|
||||
#### 3.3.4. `auto replace(value_container_type&& container)`
|
||||
|
||||
Discards the internally held container and replaces it with the one passed. Non-unique elements are
|
||||
removed, and the container will be partly reordered when non-unique elements are found.
|
||||
|
||||
### 3.4. Custom Container Types
|
||||
|
||||
`unordered_dense` accepts a custom allocator, but you can also specify a custom container for that template argument. That way it is possible to replace the internally used `std::vector` with e.g. `std::deque` or any other container like `boost::interprocess::vector`. This supports fancy pointers (e.g. [offset_ptr](https://www.boost.org/doc/libs/1_80_0/doc/html/interprocess/offset_ptr.html)), so the container can be used with e.g. shared memory provided by `boost::interprocess`.
|
||||
|
||||
### 3.5. Custom Bucket Types
|
||||
|
||||
The map/set supports two different bucket types. The default should be good for pretty much everyone.
|
||||
|
||||
#### 3.5.1. `ankerl::unordered_dense::bucket_type::standard`
|
||||
|
||||
* Up to 2^32 = 4.29 billion elements.
|
||||
* 8 bytes overhead per bucket.
|
||||
|
||||
#### 3.5.2. `ankerl::unordered_dense::bucket_type::big`
|
||||
|
||||
* up to 2^63 = 9223372036854775808 elements.
|
||||
* 12 bytes overhead per bucket.
|
||||
|
||||
## 4. `segmented_map` and `segmented_set`
|
||||
|
||||
`ankerl::unordered_dense` provides a custom container implementation that has lower memory requirements than the default `std::vector`. Memory is not contiguous, but it can allocate segments without having to reallocate and move all the elements. In summary, this leads to
|
||||
|
||||
* Much smoother memory usage, memory usage increases continuously.
|
||||
* No high peak memory usage.
|
||||
* Faster insertion because elements never need to be moved to new allocated blocks
|
||||
* Slightly slower indexing compared to `std::vector` because an additional indirection is needed.
|
||||
|
||||
Here is a comparison against `absl::flat_hash_map` and the `ankerl::unordered_dense::map` when inserting 10 million entries
|
||||

|
||||
|
||||
Abseil is fastest for this simple inserting test, taking a bit over 0.8 seconds. It's peak memory usage is about 430 MB. Note how the memory usage goes down after the last peak; when it goes down to ~290MB it has finished rehashing and could free the previously used memory block.
|
||||
|
||||
`ankerl::unordered_dense::segmented_map` doesn't have these peaks, and instead has a smooth increase of memory usage. Note there are still sudden drops & increases in memory because the indexing data structure needs still needs to increase by a fixed factor. But due to holding the data in a separate container we are able to first free the old data structure, and then allocate a new, bigger indexing structure; thus we do not have peaks.
|
||||
|
||||
## 5. Design
|
||||
|
||||
The map/set has two data structures:
|
||||
* `std::vector<value_type>` which holds all data. map/set iterators are just `std::vector<value_type>::iterator`!
|
||||
* An indexing structure (bucket array), which is a flat array with 8-byte buckets.
|
||||
|
||||
### 5.1. Inserts
|
||||
|
||||
Whenever an element is added it is `emplace_back` to the vector. The key is hashed, and an entry (bucket) is added at the
|
||||
corresponding location in the bucket array. The bucket has this structure:
|
||||
|
||||
```cpp
|
||||
struct Bucket {
|
||||
uint32_t dist_and_fingerprint;
|
||||
uint32_t value_idx;
|
||||
};
|
||||
```
|
||||
|
||||
Each bucket stores 3 things:
|
||||
* The distance of that value from the original hashed location (3 most significant bytes in `dist_and_fingerprint`)
|
||||
* A fingerprint; 1 byte of the hash (lowest significant byte in `dist_and_fingerprint`)
|
||||
* An index where in the vector the actual data is stored.
|
||||
|
||||
This structure is especially designed for the collision resolution strategy robin-hood hashing with backward shift
|
||||
deletion.
|
||||
|
||||
### 5.2. Lookups
|
||||
|
||||
The key is hashed and the bucket array is searched if it has an entry at that location with that fingerprint. When found,
|
||||
the key in the data vector is compared, and when equal the value is returned.
|
||||
|
||||
### 5.3. Removals
|
||||
|
||||
Since all data is stored in a vector, removals are a bit more complicated:
|
||||
|
||||
1. First, lookup the element to delete in the index array.
|
||||
2. When found, replace that element in the vector with the last element in the vector.
|
||||
3. Update *two* locations in the bucket array: First remove the bucket for the removed element
|
||||
4. Then, update the `value_idx` of the moved element. This requires another lookup.
|
||||
|
||||
|
||||
## 6. Real World Usage
|
||||
|
||||
On 2023-09-10 I did a quick search on github to see if this map is used in any popular open source projects. Here are some of the projects
|
||||
I found. Please send me a note if you want on that list!
|
||||
|
||||
* [PruaSlicer](https://github.com/prusa3d/PrusaSlicer) - G-code generator for 3D printers (RepRap, Makerbot, Ultimaker etc.)
|
||||
* [Kismet](https://github.com/kismetwireless/kismet): Wi-Fi, Bluetooth, RF, and more. Kismet is a sniffer, WIDS, and wardriving tool for Wi-Fi, Bluetooth, Zigbee, RF, and more, which runs on Linux and macOS
|
||||
* [Rspamd](https://github.com/rspamd/rspamd) - Fast, free and open-source spam filtering system.
|
||||
* [kallisto](https://github.com/pachterlab/kallisto) - Near-optimal RNA-Seq quantification
|
||||
* [Slang](https://github.com/shader-slang/slang) - Slang is a shading language that makes it easier to build and maintain large shader codebases in a modular and extensible fashion.
|
||||
* [CyberFSR2](https://github.com/PotatoOfDoom/CyberFSR2) - Drop-in DLSS replacement with FSR 2.0 for various games such as Cyberpunk 2077.
|
||||
* [ossia score](https://github.com/ossia/score) - A free, open-source, cross-platform intermedia sequencer for precise and flexible scripting of interactive scenarios.
|
||||
* [HiveWE](https://github.com/stijnherfst/HiveWE) - A Warcraft III World Editor (WE) that focusses on speed and ease of use.
|
||||
* [opentxs](https://github.com/Open-Transactions/opentxs) - The Open-Transactions project is a collaborative effort to develop a robust, commercial-grade, fully-featured, free-software toolkit implementing the OTX protocol as well as a full-strength financial cryptography library, API, GUI, command-line interface, and prototype notary server.
|
||||
* [LuisaCompute](https://github.com/LuisaGroup/LuisaCompute) - High-Performance Rendering Framework on Stream Architectures
|
||||
* [Lethe](https://github.com/lethe-cfd/lethe) - Lethe (pronounced /ˈliːθiː/) is open-source computational fluid dynamics (CFD) software which uses high-order continuous Galerkin formulations to solve the incompressible Navier–Stokes equations (among others).
|
||||
* [PECOS](https://github.com/amzn/pecos) - PECOS is a versatile and modular machine learning (ML) framework for fast learning and inference on problems with large output spaces, such as extreme multi-label ranking (XMR) and large-scale retrieval.
|
||||
* [Operon](https://github.com/heal-research/operon) - A modern C++ framework for symbolic regression that uses genetic programming to explore a hypothesis space of possible mathematical expressions in order to find the best-fitting model for a given regression target.
|
||||
* [MashMap](https://github.com/marbl/MashMap) - A fast approximate aligner for long DNA sequences
|
||||
* [minigpt4.cpp](https://github.com/Maknee/minigpt4.cpp) - Port of MiniGPT4 in C++ (4bit, 5bit, 6bit, 8bit, 16bit CPU inference with GGML)
|
||||
@@ -0,0 +1,4 @@
|
||||
@PACKAGE_INIT@
|
||||
|
||||
include("${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@Targets.cmake")
|
||||
check_required_components("@PROJECT_NAME@")
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
#!/usr/bin/gnuplot
|
||||
|
||||
#set terminal pngcairo
|
||||
#set terminal pngcairo size 730,510 enhanced font 'Verdana,10'
|
||||
set terminal pngcairo size 800,600 enhanced font 'Verdana,10'
|
||||
|
||||
# define axis
|
||||
# remove border on top and right and set color to gray
|
||||
set style line 11 lc rgb '#808080' lt 1
|
||||
set border 3 back ls 11
|
||||
set tics nomirror
|
||||
# define grid
|
||||
set style line 12 lc rgb '#808080' lt 0 lw 1
|
||||
set grid back ls 12
|
||||
|
||||
# line styles
|
||||
set style line 1 lt 1 lc rgb '#1B9E77' # dark teal
|
||||
set style line 2 lt 1 lc rgb '#D95F02' # dark orange
|
||||
set style line 3 lt 1 lc rgb '#7570B3' # dark lilac
|
||||
set style line 4 lt 1 lc rgb '#E7298A' # dark magenta
|
||||
set style line 5 lt 1 lc rgb '#66A61E' # dark lime green
|
||||
set style line 6 lt 1 lc rgb '#E6AB02' # dark banana
|
||||
set style line 7 lt 1 lc rgb '#A6761D' # dark tan
|
||||
set style line 8 lt 1 lc rgb '#666666' # dark gray
|
||||
|
||||
|
||||
set style line 101 lc rgb '#808080' lt 1 lw 1
|
||||
set border 3 front ls 101
|
||||
set tics nomirror out scale 0.75
|
||||
|
||||
set key left top
|
||||
|
||||
set output 'allocated_memory.png'
|
||||
|
||||
set xlabel "Runtime [s]"
|
||||
set ylabel "Allocated memory [MB]"
|
||||
|
||||
set title "Inserting 10 Million uint64\\\_t -> uint64\\\_t pairs"
|
||||
|
||||
# allocated_memory_segmented_vector.txt allocated_memory_std_unordered_map.txt allocated_memory_std_vector.txt
|
||||
plot \
|
||||
'allocated_memory_segmented_vector.txt' using ($1):($2/1e6) w steps ls 1 lw 2 title "ankerl::unordered\\\_dense::segmented\\\_map" , \
|
||||
'allocated_memory_std_vector.txt' using ($1):($2/1e6) w steps ls 2 lw 2 title "ankerl::unordered\\\_dense::map" , \
|
||||
'allocated_memory_absl_flat_hash_map.txt' using ($1):($2/1e6) w steps ls 3 lw 2 title "absl::flat\\\_hash\\\_map"
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 32 KiB |
@@ -0,0 +1,6 @@
|
||||
cmake_minimum_required(VERSION 3.12)
|
||||
project("UnorderedDenseExample")
|
||||
|
||||
add_executable(UnorderedDenseExample main.cpp)
|
||||
find_package(unordered_dense CONFIG REQUIRED)
|
||||
target_link_libraries(UnorderedDenseExample unordered_dense::unordered_dense)
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
A simple example that demonstrats how to make use of `unordered_dense` with cmake.
|
||||
|
||||
Use globally installed `unordered_dense`:
|
||||
```sh
|
||||
mkdir build && cd build
|
||||
cmake -DCMAKE_INSTALL_PREFIX:PATH=${HOME}/unordered_dense_install ..
|
||||
make
|
||||
```
|
||||
|
||||
Use locall installed `unordered_dense`, as in the main README.md:
|
||||
|
||||
```sh
|
||||
mkdir build && cd build
|
||||
cmake -DCMAKE_INSTALL_PREFIX:PATH=${HOME}/unordered_dense_install ..
|
||||
make
|
||||
```
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
#include <ankerl/unordered_dense.h>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
auto main() -> int {
|
||||
auto map = ankerl::unordered_dense::map<int, std::string>();
|
||||
map[123] = "hello";
|
||||
map[987] = "world!";
|
||||
|
||||
for (auto const& [key, val] : map) {
|
||||
std::cout << key << " => " << val << std::endl;
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
+32
@@ -0,0 +1,32 @@
|
||||
# meson commands cheat sheet:
|
||||
#
|
||||
# # Setup ###################
|
||||
#
|
||||
# release & debug setup
|
||||
# CXX="ccache clang++" meson setup --buildtype release builddir/clang_release
|
||||
# CXX="ccache clang++" meson setup builddir/clang_debug
|
||||
# c++20 build
|
||||
# CXX="ccache clang++" meson setup -Dcpp_std=c++20 builddir/clang_cpp20
|
||||
# lcov coverage:
|
||||
# CXX="ccache clang++" meson setup -Db_coverage=true builddir/coverage
|
||||
# ninja clean && ninja test && ninja coverage
|
||||
#
|
||||
# # Testing ################
|
||||
#
|
||||
# Run with valgrind:
|
||||
# meson test --wrap='valgrind --leak-check=full --error-exitcode=1'
|
||||
#
|
||||
|
||||
project('unordered_dense', 'cpp',
|
||||
version: '4.4.0',
|
||||
license: 'MIT',
|
||||
default_options : [
|
||||
'cpp_std=c++17',
|
||||
'warning_level=3',
|
||||
'werror=true',
|
||||
'b_ndebug=true', # otherwise absl is really slow!
|
||||
])
|
||||
|
||||
incdir = include_directories('include')
|
||||
subdir('test')
|
||||
|
||||
+86
@@ -0,0 +1,86 @@
|
||||
#!/bin/env python
|
||||
|
||||
import os
|
||||
from pathlib import Path
|
||||
import subprocess
|
||||
|
||||
|
||||
cmd_and_dir = [
|
||||
# needs honggfuzz installed
|
||||
['env', 'CXX_LD=mold', 'CXX=ccache clang++', 'meson', 'setup', '--buildtype', 'debug', '-Dcpp_std=c++17', 'builddir/clang_cpp17_debug'],
|
||||
['env', 'CXX_LD=mold', 'CXX=ccache clang++', 'meson', 'setup', '--buildtype', 'release', '-Dcpp_std=c++17', 'builddir/clang_cpp17_release'],
|
||||
['env', 'CXX_LD=mold', 'CXX=ccache g++', 'meson', 'setup', '--buildtype', 'release', '-Dcpp_std=c++17', 'builddir/gcc_cpp17_release'],
|
||||
['env', 'CXX_LD=mold', 'CXX=ccache hfuzz-clang++ -DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION', 'meson', 'setup', '--buildtype', 'release', '-Dcpp_std=c++17', 'builddir/hfuzz-clang_cpp17_release'],
|
||||
['env', 'CXX_LD=mold', 'CXX=ccache g++', 'meson', 'setup', '--buildtype', 'debug', '-Dcpp_std=c++17', 'builddir/gcc_cpp17_debug'],
|
||||
|
||||
# 32bit. Install lib32-clang
|
||||
['env', 'CXX_LD=mold', 'CXX=ccache g++', 'meson', 'setup', '--buildtype', 'debug', '-Dcpp_std=c++17', '-Dcpp_args=-m32', '-Dcpp_link_args=-m32', '-Dc_args=-m32', '-Dc_link_args=-m32', 'builddir/gcc_cpp17_debug_32'],
|
||||
['env', 'CXX_LD=mold', 'CXX=ccache clang++', 'meson', 'setup', '--buildtype', 'debug', '-Dcpp_std=c++17', '-Dcpp_args=-m32', '-Dcpp_link_args=-m32', '-Dc_args=-m32', '-Dc_link_args=-m32', 'builddir/clang_cpp17_debug_32'],
|
||||
|
||||
# c++20
|
||||
['env', 'CXX_LD=mold', 'CXX=ccache clang++', 'meson', 'setup', '--buildtype', 'debug', '-Dcpp_std=c++20', 'builddir/clang_cpp20_debug'],
|
||||
['env', 'CXX_LD=mold', 'CXX=ccache g++', 'meson', 'setup', '--buildtype', 'debug', '-Dcpp_std=c++20', 'builddir/gcc_cpp20_debug'],
|
||||
|
||||
# coverage; use "ninja clean && ninja test && ninja coverage"
|
||||
#['env', 'CXX_LD=mold', 'CXX=ccache clang++', 'meson', 'setup', '-Db_coverage=true', 'builddir/coverage'],
|
||||
|
||||
# sanitizers
|
||||
# It is not possible to combine more than one of the -fsanitize=address, -fsanitize=thread, and -fsanitize=memory checkers in the same program.
|
||||
# see https://clang.llvm.org/docs/UsersManual.html#controlling-code-generation
|
||||
#
|
||||
# can't use ccache, it doesn't work with the ignorelist.txt
|
||||
['env', 'CXX_LD=mold', 'CXX=ccache g++', 'meson', 'setup', '-Db_sanitize=address', 'builddir/gcc_sanitize_address'],
|
||||
['env', 'CXX_LD=mold', 'CXX=ccache clang++', 'meson', 'setup', '-Db_sanitize=address', 'builddir/clang_sanitize_address'],
|
||||
|
||||
['env', 'CXX_LD=mold', 'CXX=ccache g++', 'meson', 'setup', '-Db_sanitize=thread', 'builddir/gcc_sanitize_thread'],
|
||||
['env', 'CXX_LD=mold', 'CXX=ccache clang++', 'meson', 'setup', '-Db_sanitize=thread', 'builddir/clang_sanitize_thread'],
|
||||
|
||||
# ['env', 'CXX_LD=mold', 'CXX=ccache g++', 'meson', 'setup', '-Db_sanitize=memory', 'builddir/gcc_sanitize_memory'], # doesn't work due to STL, and ignore doesn't work either :-(
|
||||
# ['env', 'CXX_LD=mold', 'CXX=ccache clang++', 'meson', 'setup', '-Db_sanitize=memory', 'builddir/clang_sanitize_memory'], # doesn't work due to STL, and ignore doesn't work either :-(
|
||||
|
||||
['env', 'CXX_LD=mold', 'CXX=ccache g++', 'meson', 'setup', '-Db_sanitize=undefined', 'builddir/gcc_sanitize_undefined'],
|
||||
['env', 'CXX_LD=mold', 'CXX=ccache clang++', 'meson', 'setup', '-Db_sanitize=undefined', 'builddir/clang_sanitize_undefined'],
|
||||
]
|
||||
|
||||
root_path = Path(__file__).parent.parent
|
||||
os.chdir(root_path)
|
||||
|
||||
|
||||
def run(cmd):
|
||||
result = subprocess.run(cmd)
|
||||
if result.returncode != 0:
|
||||
exit(result.returncode)
|
||||
|
||||
run('scripts/lint/lint-all.py')
|
||||
|
||||
for cmd_dir in cmd_and_dir:
|
||||
workdir = cmd_dir[-1]
|
||||
|
||||
# setup
|
||||
if not os.path.isdir(workdir):
|
||||
out = run(cmd_dir)
|
||||
|
||||
# clean
|
||||
run(['meson', 'compile', '--clean', '-C', workdir])
|
||||
|
||||
# compile everything
|
||||
run(['meson', 'compile', '-C', workdir])
|
||||
|
||||
# test
|
||||
#if workdir.find("clang_cpp17_debug") != -1:
|
||||
# run(['meson', 'test', '--wrap=\'valgrind --leak-check=full --error-exitcode=1\'', '-q', '--print-errorlogs', '-C', workdir])
|
||||
#else:
|
||||
|
||||
if workdir.find("hfuzz") == -1:
|
||||
# no testing for hfuzz
|
||||
run(['meson', 'test', '-q', '--print-errorlogs', '-C', workdir])
|
||||
|
||||
# coverage
|
||||
if workdir.find("coverage") != -1:
|
||||
print(workdir)
|
||||
run(['meson', 'compile', '--ninja-args', 'coverage', '-C', workdir])
|
||||
|
||||
|
||||
for cmd_dir in cmd_and_dir:
|
||||
workdir = cmd_dir[-1]
|
||||
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
#!/bin/env bash
|
||||
set -e
|
||||
|
||||
# Start from a build directory, usually clang_cpp17_release
|
||||
# usage: fuzz_merge.sh <testname>
|
||||
FUZZ_TARGET=$1
|
||||
SCRIPT_DIR=`dirname "$0"`
|
||||
CORPUS_SMALL=${SCRIPT_DIR}/../data/fuzz/${FUZZ_TARGET}
|
||||
CORPUS_BIG=CORPUS_BIG/${FUZZ_TARGET}
|
||||
ninja
|
||||
./test/fuzz_${FUZZ_TARGET} -merge=1 ${CORPUS_SMALL} ${CORPUS_BIG}
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
#!/bin/env bash
|
||||
set -ev
|
||||
|
||||
# Start from a build directory, usually clang_cpp17_release
|
||||
# ../../scripts/fuzz_run.sh <testname>
|
||||
#
|
||||
# Found a crash? Minimize it like so:
|
||||
# ./test/fuzz_replace -minimize_crash=1 ./crash-123abcdef
|
||||
|
||||
FUZZ_TARGET=$1
|
||||
SCRIPT_DIR=`dirname "$0"`
|
||||
CORPUS_SMALL=${SCRIPT_DIR}/../data/fuzz/${FUZZ_TARGET}
|
||||
CORPUS_BIG=CORPUS_BIG/${FUZZ_TARGET}
|
||||
NUM_JOBS=$(nproc)
|
||||
|
||||
mkdir -p ${CORPUS_BIG}
|
||||
ninja
|
||||
chrt -i 0 ./test/fuzz_${FUZZ_TARGET} -jobs=${NUM_JOBS} -workers=${NUM_JOBS} ${CORPUS_BIG} ${CORPUS_SMALL}
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
from glob import glob
|
||||
from pathlib import Path
|
||||
from subprocess import run
|
||||
from os import path
|
||||
from time import time
|
||||
|
||||
|
||||
time_start = time()
|
||||
|
||||
exit_code = 0
|
||||
num_linters = 0
|
||||
mod_path = Path(__file__).parent
|
||||
for lint in glob(f"{mod_path}/lint-*"):
|
||||
lint = path.abspath(lint)
|
||||
if lint == path.abspath(__file__):
|
||||
continue
|
||||
|
||||
num_linters += 1
|
||||
result = run([lint])
|
||||
if result.returncode == 0:
|
||||
continue
|
||||
|
||||
print(f"^---- failure from {lint.split('/')[-1]}")
|
||||
exit_code |= result.returncode
|
||||
|
||||
time_end = time()
|
||||
print(f"{num_linters} linters in {time_end - time_start:0.2}s")
|
||||
exit(exit_code)
|
||||
+50
@@ -0,0 +1,50 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
from glob import glob
|
||||
from pathlib import Path
|
||||
from subprocess import run
|
||||
from os import path
|
||||
import subprocess
|
||||
import sys
|
||||
from time import time
|
||||
import re
|
||||
|
||||
root_path = path.abspath(Path(__file__).parent.parent.parent)
|
||||
|
||||
globs = [
|
||||
f"{root_path}/include/**/*.h",
|
||||
f"{root_path}/test/**/*.h",
|
||||
f"{root_path}/test/**/*.cpp",
|
||||
]
|
||||
exclusions = [
|
||||
"nanobench\\.h",
|
||||
"FuzzedDataProvider\\.h",
|
||||
'/third-party/']
|
||||
|
||||
files = []
|
||||
for g in globs:
|
||||
r = glob(g, recursive=True)
|
||||
files.extend(r)
|
||||
|
||||
# filter out exclusions
|
||||
for exclusion in exclusions:
|
||||
l = filter(lambda file: re.search(exclusion, file) == None, files)
|
||||
files = list(l)
|
||||
|
||||
if len(files) == 0:
|
||||
print("could not find any files!")
|
||||
sys.exit(1)
|
||||
|
||||
command = ['clang-format', '--dry-run', '-Werror'] + files
|
||||
p = subprocess.Popen(command,
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=None,
|
||||
stdin=subprocess.PIPE,
|
||||
universal_newlines=True)
|
||||
|
||||
stdout, stderr = p.communicate()
|
||||
|
||||
print(f"clang-format checked {len(files)} files")
|
||||
|
||||
if p.returncode != 0:
|
||||
sys.exit(p.returncode)
|
||||
+68
@@ -0,0 +1,68 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import os
|
||||
import pathlib
|
||||
import re
|
||||
|
||||
|
||||
root = os.path.abspath(pathlib.Path(__file__).parent.parent.parent)
|
||||
|
||||
# filename, pattern, number of occurrences
|
||||
file_pattern_count = [
|
||||
(
|
||||
f"{root}/meson.build",
|
||||
r"version: '(\d+)\.(\d+)\.(\d+)'",
|
||||
1),
|
||||
(
|
||||
f"{root}/include/ankerl/unordered_dense.h",
|
||||
r"Version (\d+)\.(\d+)\.(\d+)\n",
|
||||
1),
|
||||
(
|
||||
f"{root}/CMakeLists.txt",
|
||||
r"^\s+VERSION (\d+)\.(\d+)\.(\d+)\n",
|
||||
1),
|
||||
(
|
||||
f"{root}/test/unit/namespace.cpp",
|
||||
r"unordered_dense::v(\d+)_(\d+)_(\d+)",
|
||||
1
|
||||
)
|
||||
]
|
||||
|
||||
# let's parse the reference from svector.h
|
||||
major = "??"
|
||||
minor = "??"
|
||||
patch = "??"
|
||||
with open(f"{root}/include/ankerl/unordered_dense.h", "r") as f:
|
||||
for line in f:
|
||||
r = re.search(r"#define ANKERL_UNORDERED_DENSE_VERSION_([A-Z]+) (\d+)", line)
|
||||
if not r:
|
||||
continue
|
||||
|
||||
if "MAJOR" == r.group(1):
|
||||
major = r.group(2)
|
||||
elif "MINOR" == r.group(1):
|
||||
minor = r.group(2)
|
||||
elif "PATCH" == r.group(1):
|
||||
patch = r.group(2)
|
||||
else:
|
||||
"match but with something else!"
|
||||
exit(1)
|
||||
|
||||
is_ok = True
|
||||
for (filename, pattern, count) in file_pattern_count:
|
||||
num_found = 0
|
||||
with open(filename, "r") as f:
|
||||
for line in f:
|
||||
r = re.search(pattern, line)
|
||||
if r:
|
||||
num_found += 1
|
||||
if major != r.group(1) or minor != r.group(2) or patch != r.group(3):
|
||||
is_ok = False
|
||||
print(f"ERROR in {filename}: got '{line.strip()}' but version should be '{major}.{minor}.{patch}'")
|
||||
if num_found != count:
|
||||
is_ok = False
|
||||
print(f"ERROR in {filename}: expected {count} occurrences but found it {num_found} times")
|
||||
|
||||
if not is_ok:
|
||||
exit(1)
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
module;
|
||||
|
||||
// see https://github.com/fmtlib/fmt/blob/master/src/fmt.cc
|
||||
|
||||
// Put all implementation-provided headers into the global module fragment
|
||||
// to prevent attachment to this module.
|
||||
|
||||
#include <array> // for array
|
||||
#include <cstdint> // for uint64_t, uint32_t, uint8_t, UINT64_C
|
||||
#include <cstring> // for size_t, memcpy, memset
|
||||
#include <functional> // for equal_to, hash
|
||||
#include <initializer_list> // for initializer_list
|
||||
#include <iterator> // for pair, distance
|
||||
#include <limits> // for numeric_limits
|
||||
#include <memory> // for allocator, allocator_traits, shared_ptr
|
||||
#include <stdexcept> // for out_of_range
|
||||
#include <string> // for basic_string
|
||||
#include <string_view> // for basic_string_view, hash
|
||||
#include <tuple> // for forward_as_tuple
|
||||
#include <type_traits> // for enable_if_t, declval, conditional_t, ena...
|
||||
#include <utility> // for forward, exchange, pair, as_const, piece...
|
||||
#include <vector> // for vector
|
||||
#if defined(__has_include)
|
||||
# if __has_include(<memory_resource>)
|
||||
# include <memory_resource> // for polymorphic_allocator
|
||||
# elif __has_include(<experimental/memory_resource>)
|
||||
# include <experimental/memory_resource> // for polymorphic_allocator
|
||||
# endif
|
||||
#endif
|
||||
#if defined(_MSC_VER) && defined(_M_X64)
|
||||
# include <intrin.h>
|
||||
# pragma intrinsic(_umul128)
|
||||
#endif
|
||||
|
||||
export module ankerl.unordered_dense;
|
||||
|
||||
#define ANKERL_UNORDERED_DENSE_EXPORT export
|
||||
|
||||
#include "ankerl/unordered_dense.h"
|
||||
@@ -0,0 +1,2 @@
|
||||
---
|
||||
Checks: '-*'
|
||||
@@ -0,0 +1,23 @@
|
||||
[wrap-file]
|
||||
directory = abseil-cpp-20220623.0
|
||||
source_url = https://github.com/abseil/abseil-cpp/archive/20220623.0.tar.gz
|
||||
source_filename = abseil-cpp-20220623.0.tar.gz
|
||||
source_hash = 4208129b49006089ba1d6710845a45e31c59b0ab6bff9e5788a87f55c5abd602
|
||||
patch_filename = abseil-cpp_20220623.0-2_patch.zip
|
||||
patch_url = https://wrapdb.mesonbuild.com/v2/abseil-cpp_20220623.0-2/get_patch
|
||||
patch_hash = d19cb16610d9310658a815ebcd87a9e2966aafbd57964341c0d1a3a3778c03b6
|
||||
wrapdb_version = 20220623.0-2
|
||||
|
||||
[provide]
|
||||
absl_base = absl_base_dep
|
||||
absl_container = absl_container_dep
|
||||
absl_debugging = absl_debugging_dep
|
||||
absl_flags = absl_flags_dep
|
||||
absl_hash = absl_hash_dep
|
||||
absl_numeric = absl_numeric_dep
|
||||
absl_random = absl_random_dep
|
||||
absl_status = absl_status_dep
|
||||
absl_strings = absl_strings_dep
|
||||
absl_synchronization = absl_synchronization_dep
|
||||
absl_time = absl_time_dep
|
||||
absl_types = absl_types_dep
|
||||
@@ -0,0 +1,9 @@
|
||||
[wrap-file]
|
||||
directory = doctest-2.4.9
|
||||
source_url = https://github.com/doctest/doctest/archive/refs/tags/v2.4.9.tar.gz
|
||||
source_filename = doctest-2.4.9.tar.gz
|
||||
source_hash = 19b2df757f2f3703a5e63cee553d85596875f06d91a3333acd80a969ef210856
|
||||
wrapdb_version = 2.4.9-1
|
||||
|
||||
[provide]
|
||||
dependency_names = doctest
|
||||
@@ -0,0 +1,12 @@
|
||||
[wrap-file]
|
||||
directory = fmt-9.1.0
|
||||
source_url = https://github.com/fmtlib/fmt/archive/9.1.0.tar.gz
|
||||
source_filename = fmt-9.1.0.tar.gz
|
||||
source_hash = 5dea48d1fcddc3ec571ce2058e13910a0d4a6bab4cc09a809d8b1dd1c88ae6f2
|
||||
patch_filename = fmt_9.1.0-1_patch.zip
|
||||
patch_url = https://wrapdb.mesonbuild.com/v2/fmt_9.1.0-1/get_patch
|
||||
patch_hash = 4557b9ba87b3eb63694ed9b21d1a2117d4a97ca56b91085b10288e9a5294adf8
|
||||
wrapdb_version = 9.1.0-1
|
||||
|
||||
[provide]
|
||||
fmt = fmt_dep
|
||||
+75
@@ -0,0 +1,75 @@
|
||||
#pragma once
|
||||
|
||||
#include <app/counter.h>
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <string_view>
|
||||
|
||||
namespace checksum {
|
||||
|
||||
// final step from MurmurHash3
|
||||
[[nodiscard]] static inline auto mix(uint64_t k) -> uint64_t {
|
||||
k ^= k >> 33U;
|
||||
k *= 0xff51afd7ed558ccdULL;
|
||||
k ^= k >> 33U;
|
||||
k *= 0xc4ceb9fe1a85ec53ULL;
|
||||
k ^= k >> 33U;
|
||||
return k;
|
||||
}
|
||||
|
||||
[[maybe_unused]] [[nodiscard]] static inline auto mix(std::string_view data) -> uint64_t {
|
||||
static constexpr uint64_t fnv_offset_basis = UINT64_C(14695981039346656037);
|
||||
static constexpr uint64_t fnv_prime = UINT64_C(1099511628211);
|
||||
|
||||
uint64_t val = fnv_offset_basis;
|
||||
for (auto c : data) {
|
||||
val ^= static_cast<uint64_t>(c);
|
||||
val *= fnv_prime;
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
[[maybe_unused]] [[nodiscard]] static inline auto mix(counter::obj const& cdv) -> uint64_t {
|
||||
return mix(cdv.get());
|
||||
}
|
||||
|
||||
// from boost::hash_combine, with additional fmix64 of value
|
||||
[[maybe_unused]] [[nodiscard]] static inline auto combine(uint64_t seed, uint64_t value) -> uint64_t {
|
||||
return seed ^ (value + 0x9e3779b9 + (seed << 6U) + (seed >> 2U));
|
||||
}
|
||||
|
||||
// calculates a hash of any iterable map. Order is irrelevant for the hash's result, as it simply
|
||||
// xors the elements together.
|
||||
template <typename M>
|
||||
[[nodiscard]] auto map(const M& map) -> uint64_t {
|
||||
uint64_t combined_hash = 1;
|
||||
|
||||
uint64_t num_elements = 0;
|
||||
for (auto const& entry : map) {
|
||||
auto entry_hash = combine(mix(entry.first), mix(entry.second));
|
||||
|
||||
combined_hash ^= entry_hash;
|
||||
++num_elements;
|
||||
}
|
||||
|
||||
return combine(combined_hash, num_elements);
|
||||
}
|
||||
|
||||
// map of maps
|
||||
template <typename MM>
|
||||
[[nodiscard]] auto mapmap(const MM& mapmap) -> uint64_t {
|
||||
uint64_t combined_hash = 1;
|
||||
|
||||
uint64_t num_elements = 0;
|
||||
for (auto const& entry : mapmap) {
|
||||
auto entry_hash = combine(mix(entry.first), map(entry.second));
|
||||
|
||||
combined_hash ^= entry_hash;
|
||||
++num_elements;
|
||||
}
|
||||
|
||||
return combine(combined_hash, num_elements);
|
||||
}
|
||||
|
||||
} // namespace checksum
|
||||
+254
@@ -0,0 +1,254 @@
|
||||
#include <app/counter.h>
|
||||
|
||||
#include <app/print.h> // for print
|
||||
|
||||
#include <cstdlib> // for abort
|
||||
#include <ostream> // for ostream
|
||||
#include <stdexcept> // for runtime_error
|
||||
#include <unordered_set> // for unordered_set
|
||||
#include <utility> // for swap, pair
|
||||
|
||||
static inline constexpr bool counter_enable_unordered_set = true;
|
||||
|
||||
auto singleton_constructed_objects() -> std::unordered_set<counter::obj const*>& {
|
||||
static std::unordered_set<counter::obj const*> static_data{};
|
||||
return static_data;
|
||||
}
|
||||
|
||||
counter::obj::obj()
|
||||
: m_data(0)
|
||||
, m_counts(nullptr) {
|
||||
if constexpr (counter_enable_unordered_set) {
|
||||
if (!singleton_constructed_objects().emplace(this).second) {
|
||||
test::print("ERROR at {}({}): {}\n", __FILE__, __LINE__, __func__);
|
||||
std::abort();
|
||||
}
|
||||
}
|
||||
++static_default_ctor;
|
||||
}
|
||||
|
||||
counter::obj::obj(const size_t& data, counter& counts)
|
||||
: m_data(data)
|
||||
, m_counts(&counts) {
|
||||
if constexpr (counter_enable_unordered_set) {
|
||||
if (!singleton_constructed_objects().emplace(this).second) {
|
||||
test::print("ERROR at {}({}): {}\n", __FILE__, __LINE__, __func__);
|
||||
std::abort();
|
||||
}
|
||||
}
|
||||
++m_counts->m_data.m_ctor;
|
||||
}
|
||||
|
||||
counter::obj::obj(const counter::obj& o)
|
||||
: m_data(o.m_data)
|
||||
, m_counts(o.m_counts) {
|
||||
if constexpr (counter_enable_unordered_set) {
|
||||
if (1 != singleton_constructed_objects().count(&o)) {
|
||||
test::print("ERROR at {}({}): {}\n", __FILE__, __LINE__, __func__);
|
||||
std::abort();
|
||||
}
|
||||
if (!singleton_constructed_objects().emplace(this).second) {
|
||||
test::print("ERROR at {}({}): {}\n", __FILE__, __LINE__, __func__);
|
||||
std::abort();
|
||||
}
|
||||
}
|
||||
if (nullptr != m_counts) {
|
||||
++m_counts->m_data.m_copy_ctor;
|
||||
}
|
||||
}
|
||||
|
||||
counter::obj::obj(counter::obj&& o) noexcept
|
||||
: m_data(o.m_data)
|
||||
, m_counts(o.m_counts) {
|
||||
if constexpr (counter_enable_unordered_set) {
|
||||
if (1 != singleton_constructed_objects().count(&o)) {
|
||||
test::print("ERROR at {}({}): {}\n", __FILE__, __LINE__, __func__);
|
||||
std::abort();
|
||||
}
|
||||
if (!singleton_constructed_objects().emplace(this).second) {
|
||||
test::print("ERROR at {}({}): {}\n", __FILE__, __LINE__, __func__);
|
||||
std::abort();
|
||||
}
|
||||
}
|
||||
if (nullptr != m_counts) {
|
||||
++m_counts->m_data.m_move_ctor;
|
||||
}
|
||||
}
|
||||
|
||||
counter::obj::~obj() {
|
||||
if constexpr (counter_enable_unordered_set) {
|
||||
if (1 != singleton_constructed_objects().erase(this)) {
|
||||
test::print("ERROR at {}({}): {}\n", __FILE__, __LINE__, __func__);
|
||||
std::abort();
|
||||
}
|
||||
}
|
||||
if (nullptr != m_counts) {
|
||||
++m_counts->m_data.m_dtor;
|
||||
} else {
|
||||
++static_dtor;
|
||||
}
|
||||
}
|
||||
|
||||
auto counter::obj::operator==(obj const& o) const -> bool {
|
||||
if constexpr (counter_enable_unordered_set) {
|
||||
if (1 != singleton_constructed_objects().count(this) || 1 != singleton_constructed_objects().count(&o)) {
|
||||
test::print("ERROR at {}({}): {}\n", __FILE__, __LINE__, __func__);
|
||||
std::abort();
|
||||
}
|
||||
}
|
||||
if (nullptr != m_counts) {
|
||||
++m_counts->m_data.m_equals;
|
||||
}
|
||||
return m_data == o.m_data;
|
||||
}
|
||||
|
||||
auto counter::obj::operator<(obj const& o) const -> bool {
|
||||
if constexpr (counter_enable_unordered_set) {
|
||||
if (1 != singleton_constructed_objects().count(this) || 1 != singleton_constructed_objects().count(&o)) {
|
||||
test::print("ERROR at {}({}): {}\n", __FILE__, __LINE__, __func__);
|
||||
std::abort();
|
||||
}
|
||||
}
|
||||
if (nullptr != m_counts) {
|
||||
++m_counts->m_data.m_less;
|
||||
}
|
||||
return m_data < o.m_data;
|
||||
}
|
||||
|
||||
// NOLINTNEXTLINE(bugprone-unhandled-self-assignment,cert-oop54-cpp)
|
||||
auto counter::obj::operator=(obj const& o) -> counter::obj& {
|
||||
if constexpr (counter_enable_unordered_set) {
|
||||
if (1 != singleton_constructed_objects().count(this) || 1 != singleton_constructed_objects().count(&o)) {
|
||||
test::print("ERROR at {}({}): {}\n", __FILE__, __LINE__, __func__);
|
||||
std::abort();
|
||||
}
|
||||
}
|
||||
m_counts = o.m_counts;
|
||||
if (nullptr != m_counts) {
|
||||
++m_counts->m_data.m_assign;
|
||||
}
|
||||
m_data = o.m_data;
|
||||
return *this;
|
||||
}
|
||||
|
||||
auto counter::obj::operator=(obj&& o) noexcept -> counter::obj& {
|
||||
if constexpr (counter_enable_unordered_set) {
|
||||
if (1 != singleton_constructed_objects().count(this) || 1 != singleton_constructed_objects().count(&o)) {
|
||||
test::print("ERROR at {}({}): {}\n", __FILE__, __LINE__, __func__);
|
||||
std::abort();
|
||||
}
|
||||
}
|
||||
if (nullptr != o.m_counts) {
|
||||
m_counts = o.m_counts;
|
||||
}
|
||||
m_data = o.m_data;
|
||||
if (nullptr != m_counts) {
|
||||
++m_counts->m_data.m_move_assign;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
auto counter::obj::get() const -> size_t const& {
|
||||
if (nullptr != m_counts) {
|
||||
++m_counts->m_data.m_const_get;
|
||||
}
|
||||
return m_data;
|
||||
}
|
||||
|
||||
auto counter::obj::get() -> size_t& {
|
||||
if (nullptr != m_counts) {
|
||||
++m_counts->m_data.m_get;
|
||||
}
|
||||
return m_data;
|
||||
}
|
||||
|
||||
void counter::obj::swap(obj& other) {
|
||||
if constexpr (counter_enable_unordered_set) {
|
||||
if (1 != singleton_constructed_objects().count(this) || 1 != singleton_constructed_objects().count(&other)) {
|
||||
test::print("ERROR at {}({}): {}\n", __FILE__, __LINE__, __func__);
|
||||
std::abort();
|
||||
}
|
||||
}
|
||||
using std::swap;
|
||||
swap(m_data, other.m_data);
|
||||
swap(m_counts, other.m_counts);
|
||||
if (nullptr != m_counts) {
|
||||
++m_counts->m_data.m_swaps;
|
||||
}
|
||||
}
|
||||
|
||||
auto counter::obj::get_for_hash() const -> size_t {
|
||||
if (nullptr != m_counts) {
|
||||
++m_counts->m_data.m_hash;
|
||||
}
|
||||
return m_data;
|
||||
}
|
||||
|
||||
counter::counter() {
|
||||
counter::static_default_ctor = 0;
|
||||
counter::static_dtor = 0;
|
||||
}
|
||||
|
||||
void counter::check_all_done() const {
|
||||
if constexpr (counter_enable_unordered_set) {
|
||||
// check that all are destructed
|
||||
if (!singleton_constructed_objects().empty()) {
|
||||
test::print("ERROR at ~counter(): got {} objects still alive!", singleton_constructed_objects().size());
|
||||
std::abort();
|
||||
}
|
||||
|
||||
if (m_data.m_dtor + static_dtor !=
|
||||
m_data.m_ctor + static_default_ctor + m_data.m_copy_ctor + m_data.m_default_ctor + m_data.m_move_ctor) {
|
||||
test::print("ERROR at ~counter(): number of counts does not match!\n");
|
||||
test::print(
|
||||
"{} dtor + {} staticDtor != {} ctor + {} staticDefaultCtor + {} copyCtor + {} defaultCtor + {} moveCtor\n",
|
||||
m_data.m_dtor,
|
||||
static_dtor,
|
||||
m_data.m_ctor,
|
||||
static_default_ctor,
|
||||
m_data.m_copy_ctor,
|
||||
m_data.m_default_ctor,
|
||||
m_data.m_move_ctor);
|
||||
std::abort();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
counter::~counter() {
|
||||
check_all_done();
|
||||
}
|
||||
|
||||
auto counter::total() const -> size_t {
|
||||
return m_data.m_ctor + static_default_ctor + m_data.m_copy_ctor + (m_data.m_dtor + static_dtor) + m_data.m_equals +
|
||||
m_data.m_less + m_data.m_assign + m_data.m_swaps + m_data.m_get + m_data.m_const_get + m_data.m_hash +
|
||||
m_data.m_move_ctor + m_data.m_move_assign;
|
||||
}
|
||||
|
||||
void counter::operator()(std::string_view title) {
|
||||
m_records += fmt::format("{:9}{:9}{:9}{:9}{:9}{:9}{:9}{:9}{:9}{:9}{:9}{:9}{:9}|{:9}| {}\n",
|
||||
m_data.m_ctor,
|
||||
static_default_ctor,
|
||||
m_data.m_copy_ctor,
|
||||
m_data.m_dtor + static_dtor,
|
||||
m_data.m_assign,
|
||||
m_data.m_swaps,
|
||||
m_data.m_get,
|
||||
m_data.m_const_get,
|
||||
m_data.m_hash,
|
||||
m_data.m_equals,
|
||||
m_data.m_less,
|
||||
m_data.m_move_ctor,
|
||||
m_data.m_move_assign,
|
||||
total(),
|
||||
title);
|
||||
}
|
||||
|
||||
auto operator<<(std::ostream& os, counter const& c) -> std::ostream& {
|
||||
return os << c.m_records;
|
||||
}
|
||||
|
||||
auto operator new(size_t /*unused*/, counter::obj* /*unused*/) -> void* {
|
||||
throw std::runtime_error("operator new overload is taken! Cast to void* to ensure the void pointer overload is taken.");
|
||||
}
|
||||
size_t counter::static_default_ctor = 0; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
|
||||
size_t counter::static_dtor = 0; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
|
||||
+170
@@ -0,0 +1,170 @@
|
||||
#pragma once
|
||||
|
||||
#include <fmt/core.h> // for format_context, format_parse_context, format_to
|
||||
|
||||
#include <cstddef> // for size_t
|
||||
#include <functional> // for hash
|
||||
#include <iosfwd> // for ostream
|
||||
#include <string> // for allocator, string
|
||||
#include <string_view> // for hash, string_view
|
||||
#include <type_traits>
|
||||
|
||||
class counter {
|
||||
public:
|
||||
struct data_t {
|
||||
size_t m_ctor{};
|
||||
size_t m_default_ctor{};
|
||||
size_t m_copy_ctor{};
|
||||
size_t m_dtor{};
|
||||
size_t m_assign{};
|
||||
size_t m_swaps{};
|
||||
size_t m_get{};
|
||||
size_t m_const_get{};
|
||||
size_t m_hash{};
|
||||
size_t m_equals{};
|
||||
size_t m_less{};
|
||||
size_t m_move_ctor{};
|
||||
size_t m_move_assign{};
|
||||
|
||||
friend auto operator==(data_t const& a, data_t const& b) -> bool {
|
||||
static_assert(std::has_unique_object_representations_v<data_t>);
|
||||
return 0 == std::memcmp(&a, &b, sizeof(data_t));
|
||||
}
|
||||
|
||||
friend auto operator!=(data_t const& a, data_t const& b) -> bool {
|
||||
return !(a == b);
|
||||
}
|
||||
};
|
||||
|
||||
counter(counter const&) = delete;
|
||||
counter(counter&&) = delete;
|
||||
auto operator=(counter const&) -> counter& = delete;
|
||||
auto operator=(counter&&) -> counter&& = delete;
|
||||
|
||||
// Obj for only swaps & equals. Used for optimizing.
|
||||
// Can't use static counters here because I want to do it in parallel.
|
||||
class obj {
|
||||
public:
|
||||
// required for operator[]
|
||||
obj();
|
||||
obj(const size_t& data, counter& counts);
|
||||
obj(const obj& o);
|
||||
obj(obj&& o) noexcept;
|
||||
~obj();
|
||||
|
||||
auto operator==(const obj& o) const -> bool;
|
||||
auto operator<(const obj& o) const -> bool;
|
||||
auto operator=(const obj& o) -> obj&;
|
||||
auto operator=(obj&& o) noexcept -> obj&;
|
||||
|
||||
[[nodiscard]] auto get() const -> size_t const&;
|
||||
auto get() -> size_t&;
|
||||
|
||||
void swap(obj& other);
|
||||
[[nodiscard]] auto get_for_hash() const -> size_t;
|
||||
|
||||
private:
|
||||
size_t m_data;
|
||||
counter* m_counts;
|
||||
};
|
||||
|
||||
counter();
|
||||
~counter();
|
||||
|
||||
void check_all_done() const;
|
||||
|
||||
[[nodiscard]] auto ctor() const -> size_t {
|
||||
return m_data.m_ctor;
|
||||
}
|
||||
|
||||
[[nodiscard]] auto default_ctor() const -> size_t {
|
||||
return m_data.m_default_ctor;
|
||||
}
|
||||
|
||||
[[nodiscard]] auto copy_ctor() const -> size_t {
|
||||
return m_data.m_copy_ctor;
|
||||
}
|
||||
|
||||
[[nodiscard]] auto dtor() const -> size_t {
|
||||
return m_data.m_dtor;
|
||||
}
|
||||
|
||||
[[nodiscard]] auto equals() const -> size_t {
|
||||
return m_data.m_equals;
|
||||
}
|
||||
|
||||
[[nodiscard]] auto less() const -> size_t {
|
||||
return m_data.m_less;
|
||||
}
|
||||
|
||||
[[nodiscard]] auto assign() const -> size_t {
|
||||
return m_data.m_assign;
|
||||
}
|
||||
|
||||
[[nodiscard]] auto swaps() const -> size_t {
|
||||
return m_data.m_swaps;
|
||||
}
|
||||
|
||||
[[nodiscard]] auto get() const -> size_t {
|
||||
return m_data.m_get;
|
||||
}
|
||||
|
||||
[[nodiscard]] auto const_get() const -> size_t {
|
||||
return m_data.m_const_get;
|
||||
}
|
||||
|
||||
[[nodiscard]] auto hash() const -> size_t {
|
||||
return m_data.m_hash;
|
||||
}
|
||||
|
||||
[[nodiscard]] auto move_ctor() const -> size_t {
|
||||
return m_data.m_move_ctor;
|
||||
}
|
||||
|
||||
[[nodiscard]] auto move_assign() const -> size_t {
|
||||
return m_data.m_move_assign;
|
||||
}
|
||||
|
||||
[[nodiscard]] auto data() const -> data_t const& {
|
||||
return m_data;
|
||||
}
|
||||
|
||||
friend auto operator<<(std::ostream& os, counter const& c) -> std::ostream&;
|
||||
|
||||
void operator()(std::string_view title);
|
||||
|
||||
[[nodiscard]] auto total() const -> size_t;
|
||||
|
||||
static size_t static_default_ctor; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
|
||||
static size_t static_dtor; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
|
||||
|
||||
private:
|
||||
data_t m_data{};
|
||||
|
||||
std::string m_records =
|
||||
"\n ctor defctor cpyctor dtor assign swaps get cnstget hash equals less ctormv assignmv| total |\n";
|
||||
};
|
||||
|
||||
// Throws an exception, this overload should never be taken!
|
||||
inline auto operator new(size_t s, counter::obj* ptr) -> void*;
|
||||
|
||||
namespace std {
|
||||
|
||||
template <>
|
||||
struct hash<counter::obj> {
|
||||
[[nodiscard]] auto operator()(const counter::obj& c) const noexcept -> size_t {
|
||||
return hash<size_t>{}(c.get_for_hash());
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace std
|
||||
|
||||
template <>
|
||||
struct fmt::formatter<counter::obj> {
|
||||
static constexpr auto parse(format_parse_context& ctx) -> decltype(ctx.begin()) {
|
||||
return ctx.end();
|
||||
}
|
||||
static auto format(counter::obj const& o, fmt::format_context& ctx) -> decltype(ctx.out()) {
|
||||
return fmt::format_to(ctx.out(), "{}", o.get());
|
||||
}
|
||||
};
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user