Compare commits
44 Commits
master
...
oxidize_cu
Author | SHA1 | Date | |
---|---|---|---|
|
5d6c27762c | ||
|
2596a9354f | ||
|
eb15e5bde4 | ||
|
51c7421ebc | ||
|
bc56a1f8e6 | ||
|
4f36d2dce1 | ||
|
772f9ccc21 | ||
|
85eb7a9383 | ||
|
9457f36f49 | ||
|
37f5780472 | ||
|
d985459696 | ||
|
edffbae777 | ||
|
77477a86dd | ||
|
eba856af17 | ||
|
c9b8462754 | ||
|
a7956f65ca | ||
|
38bd6b547d | ||
|
926a6c1849 | ||
|
aa1b47c596 | ||
|
9003881a77 | ||
|
f1ad997a4b | ||
|
20708b0ff8 | ||
|
995eaec555 | ||
|
beaaa597d4 | ||
|
96e90ce321 | ||
|
7f7aa3dc2c | ||
|
9fff420a1a | ||
|
b04f3200b1 | ||
|
5cf37a0c7c | ||
|
59cbb08c0e | ||
|
9b88056062 | ||
|
3808617142 | ||
|
32dffeb54d | ||
|
3f14453f5b | ||
|
3ba8001807 | ||
|
6960bd42c5 | ||
|
699ac31383 | ||
|
797db7a097 | ||
|
63c9d599f9 | ||
|
6faa5f45e8 | ||
|
86d4db97ca | ||
|
844685102d | ||
|
97bd968b2a | ||
|
80eb71ded5 |
@ -1,65 +0,0 @@
|
||||
name: Build and Publish Docker Image
|
||||
|
||||
on:
|
||||
release:
|
||||
types: [published, prereleased]
|
||||
|
||||
env:
|
||||
IMAGE_NAME: openharbor/osrm-backend
|
||||
|
||||
jobs:
|
||||
publish:
|
||||
strategy:
|
||||
matrix:
|
||||
docker-base-image: ["debian", "alpine"]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Check out the repo
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v2
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v2
|
||||
|
||||
- name: Docker meta
|
||||
id: meta
|
||||
uses: docker/metadata-action@v4
|
||||
with:
|
||||
images: ${{ env.IMAGE_NAME }}
|
||||
|
||||
- name: Docker meta - debug
|
||||
id: metadebug
|
||||
uses: docker/metadata-action@v4
|
||||
with:
|
||||
images: ${{ env.IMAGE_NAME }}
|
||||
flavor: |
|
||||
latest=true
|
||||
suffix=-debug,onlatest=true
|
||||
|
||||
- name: Log in to DockerHub
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_ACCESS_TOKEN }}
|
||||
|
||||
- name: Build and push debug image
|
||||
uses: docker/build-push-action@v4
|
||||
with:
|
||||
push: true
|
||||
platforms: linux/amd64,linux/arm64,linux/ppc64le,linux/riscv64
|
||||
file: ./docker/Dockerfile-${{ matrix.docker-base-image }}
|
||||
tags: ${{ steps.metadebug.outputs.tags }}
|
||||
build-args: |
|
||||
DOCKER_TAG=${{ join(steps.metadebug.outputs.tags) }}-${{ matrix.docker-base-image }}
|
||||
|
||||
- name: Build and push normal image
|
||||
uses: docker/build-push-action@v4
|
||||
with:
|
||||
push: true
|
||||
platforms: linux/amd64,linux/arm64,linux/ppc64le,linux/riscv64
|
||||
file: ./docker/Dockerfile-${{ matrix.docker-base-image }}
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
build-args: |
|
||||
DOCKER_TAG=${{ join(steps.meta.outputs.tags) }}-${{ matrix.docker-base-image }}
|
106
.github/workflows/osrm-backend.yml
vendored
106
.github/workflows/osrm-backend.yml
vendored
@ -446,14 +446,14 @@ jobs:
|
||||
if: steps.cache-boost.outputs.cache-hit != 'true' && runner.os == 'Linux' && matrix.ENABLE_CONAN != 'ON'
|
||||
run: |
|
||||
BOOST_VERSION="1.85.0"
|
||||
BOOST_VERSION_FLAVOR="${BOOST_VERSION}-b2-nodocs"
|
||||
wget -q https://github.com/boostorg/boost/releases/download/boost-${BOOST_VERSION}/boost-${BOOST_VERSION_FLAVOR}.tar.gz
|
||||
tar xzf boost-${BOOST_VERSION_FLAVOR}.tar.gz
|
||||
cd boost-${BOOST_VERSION}
|
||||
BOOST_VERSION_UNDERSCORE="${BOOST_VERSION//./_}"
|
||||
wget -q https://boostorg.jfrog.io/artifactory/main/release/${BOOST_VERSION}/source/boost_${BOOST_VERSION_UNDERSCORE}.tar.gz
|
||||
tar xzf boost_${BOOST_VERSION_UNDERSCORE}.tar.gz
|
||||
cd boost_${BOOST_VERSION_UNDERSCORE}
|
||||
sudo ./bootstrap.sh
|
||||
sudo ./b2 install
|
||||
cd ..
|
||||
sudo rm -rf boost-${BOOST_VERSION}*
|
||||
sudo rm -rf boost_${BOOST_VERSION_UNDERSCORE}*
|
||||
|
||||
- name: Install dev dependencies
|
||||
run: |
|
||||
@ -502,13 +502,6 @@ jobs:
|
||||
|
||||
conan config init
|
||||
yq eval '.compiler.clang.version += ["18"]' -i "$HOME/.conan/settings.yml"
|
||||
- name: Add Apple-clang 16 to list of Conan compilers # workaround for the issue that Conan 1.x doesn't know about Apple-clang 16
|
||||
if: ${{ matrix.ENABLE_CONAN == 'ON' && matrix.runs-on == 'macos-14' }}
|
||||
run: |
|
||||
sudo wget https://github.com/mikefarah/yq/releases/download/v4.9.6/yq_darwin_arm64 -O /usr/local/bin/yq && sudo chmod +x /usr/local/bin/yq
|
||||
|
||||
conan config init
|
||||
yq eval '.compiler.apple-clang.version += ["16.0"]' -i "$HOME/.conan/settings.yml"
|
||||
- name: Prepare build
|
||||
run: |
|
||||
mkdir ${OSRM_BUILD_DIR}
|
||||
@ -660,7 +653,7 @@ jobs:
|
||||
benchmarks:
|
||||
if: github.event_name == 'pull_request'
|
||||
needs: [format-taginfo-docs]
|
||||
runs-on: self-hosted
|
||||
runs-on: ubuntu-24.04
|
||||
env:
|
||||
CCOMPILER: clang-16
|
||||
CXXCOMPILER: clang++-16
|
||||
@ -671,17 +664,37 @@ jobs:
|
||||
GITHUB_REPOSITORY: ${{ github.repository }}
|
||||
RUN_BIG_BENCHMARK: ${{ contains(github.event.pull_request.labels.*.name, 'Performance') }}
|
||||
steps:
|
||||
- name: Enable data.osm.pbf cache
|
||||
if: ${{ ! env.RUN_BIG_BENCHMARK }}
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ~/data.osm.pbf
|
||||
key: v1-data-osm-pbf
|
||||
restore-keys: |
|
||||
v1-data-osm-pbf
|
||||
- name: Enable compiler cache
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ~/.ccache
|
||||
key: v1-ccache-benchmarks-${{ github.sha }}
|
||||
restore-keys: |
|
||||
v1-ccache-benchmarks-
|
||||
- name: Enable Conan cache
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ~/.conan
|
||||
key: v1-conan-benchmarks-${{ github.sha }}
|
||||
restore-keys: |
|
||||
v1-conan-benchmarks-
|
||||
- name: Checkout PR Branch
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ github.head_ref }}
|
||||
path: pr
|
||||
- name: Activate virtualenv
|
||||
run: |
|
||||
python3 -m venv .venv
|
||||
source .venv/bin/activate
|
||||
echo PATH=$PATH >> $GITHUB_ENV
|
||||
pip install "conan<2.0.0" "requests==2.31.0" "numpy==1.26.4"
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
python3 -m pip install "conan<2.0.0" "requests==2.31.0" "numpy==1.26.4" --break-system-packages
|
||||
sudo apt-get update -y && sudo apt-get install ccache
|
||||
- name: Prepare data
|
||||
run: |
|
||||
if [ "$RUN_BIG_BENCHMARK" = "true" ]; then
|
||||
@ -709,67 +722,50 @@ jobs:
|
||||
path: base
|
||||
- name: Build Base Branch
|
||||
run: |
|
||||
cd base
|
||||
npm ci --ignore-scripts
|
||||
cd ..
|
||||
mkdir base/build
|
||||
cd base/build
|
||||
cmake -DENABLE_CONAN=ON -DCMAKE_BUILD_TYPE=Release -DENABLE_NODE_BINDINGS=ON ..
|
||||
cmake -DENABLE_CONAN=ON -DCMAKE_BUILD_TYPE=Release ..
|
||||
make -j$(nproc)
|
||||
make -j$(nproc) benchmarks
|
||||
cd ..
|
||||
make -C test/data
|
||||
- name: Build PR Branch
|
||||
run: |
|
||||
cd pr
|
||||
npm ci --ignore-scripts
|
||||
cd ..
|
||||
mkdir -p pr/build
|
||||
cd pr/build
|
||||
cmake -DENABLE_CONAN=ON -DCMAKE_BUILD_TYPE=Release -DENABLE_NODE_BINDINGS=ON ..
|
||||
cmake -DENABLE_CONAN=ON -DCMAKE_BUILD_TYPE=Release ..
|
||||
make -j$(nproc)
|
||||
make -j$(nproc) benchmarks
|
||||
cd ..
|
||||
make -C test/data
|
||||
# we run benchmarks in tmpfs to avoid impact of disk IO
|
||||
- name: Create folder for tmpfs
|
||||
run: |
|
||||
# if by any chance it was mounted before(e.g. due to previous job failed), unmount it
|
||||
sudo umount ~/benchmarks | true
|
||||
rm -rf ~/benchmarks
|
||||
mkdir -p ~/benchmarks
|
||||
# see https://llvm.org/docs/Benchmarking.html
|
||||
run: mkdir -p /opt/benchmarks
|
||||
- name: Run PR Benchmarks
|
||||
run: |
|
||||
sudo cset shield -c 2-3 -k on
|
||||
sudo mount -t tmpfs -o size=4g none ~/benchmarks
|
||||
cp -rf pr/build ~/benchmarks/build
|
||||
cp -rf pr/lib ~/benchmarks/lib
|
||||
mkdir -p ~/benchmarks/test
|
||||
cp -rf pr/test/data ~/benchmarks/test/data
|
||||
cp -rf pr/profiles ~/benchmarks/profiles
|
||||
sudo mount -t tmpfs -o size=4g none /opt/benchmarks
|
||||
cp -rf pr/build /opt/benchmarks/build
|
||||
mkdir -p /opt/benchmarks/test
|
||||
cp -rf pr/test/data /opt/benchmarks/test/data
|
||||
cp -rf pr/profiles /opt/benchmarks/profiles
|
||||
|
||||
sudo cset shield --exec -- ./pr/scripts/ci/run_benchmarks.sh -f ~/benchmarks -r $(pwd)/pr_results -s $(pwd)/pr -b ~/benchmarks/build -o ~/data.osm.pbf -g ~/gps_traces.csv
|
||||
sudo umount ~/benchmarks
|
||||
sudo cset shield --reset
|
||||
./pr/scripts/ci/run_benchmarks.sh -f /opt/benchmarks -r $(pwd)/pr_results -s $(pwd)/pr -b /opt/benchmarks/build -o ~/data.osm.pbf -g ~/gps_traces.csv
|
||||
sudo umount /opt/benchmarks
|
||||
- name: Run Base Benchmarks
|
||||
run: |
|
||||
sudo cset shield -c 2-3 -k on
|
||||
sudo mount -t tmpfs -o size=4g none ~/benchmarks
|
||||
cp -rf base/build ~/benchmarks/build
|
||||
cp -rf base/lib ~/benchmarks/lib
|
||||
mkdir -p ~/benchmarks/test
|
||||
cp -rf base/test/data ~/benchmarks/test/data
|
||||
cp -rf base/profiles ~/benchmarks/profiles
|
||||
sudo mount -t tmpfs -o size=4g none /opt/benchmarks
|
||||
cp -rf base/build /opt/benchmarks/build
|
||||
mkdir -p /opt/benchmarks/test
|
||||
cp -rf base/test/data /opt/benchmarks/test/data
|
||||
cp -rf base/profiles /opt/benchmarks/profiles
|
||||
|
||||
# TODO: remove it when base branch will have this file at needed location
|
||||
if [ ! -f ~/benchmarks/test/data/portugal_to_korea.json ]; then
|
||||
cp base/src/benchmarks/portugal_to_korea.json ~/benchmarks/test/data/portugal_to_korea.json
|
||||
if [ ! -f /opt/benchmarks/test/data/portugal_to_korea.json ]; then
|
||||
cp base/src/benchmarks/portugal_to_korea.json /opt/benchmarks/test/data/portugal_to_korea.json
|
||||
fi
|
||||
# we intentionally use scripts from PR branch to be able to update them and see results in the same PR
|
||||
sudo cset shield --exec -- cset shield --exec -- ./pr/scripts/ci/run_benchmarks.sh -f ~/benchmarks -r $(pwd)/base_results -s $(pwd)/pr -b ~/benchmarks/build -o ~/data.osm.pbf -g ~/gps_traces.csv
|
||||
sudo umount ~/benchmarks
|
||||
sudo cset shield --reset
|
||||
./pr/scripts/ci/run_benchmarks.sh -f /opt/benchmarks -r $(pwd)/base_results -s $(pwd)/pr -b /opt/benchmarks/build -o ~/data.osm.pbf -g ~/gps_traces.csv
|
||||
sudo umount /opt/benchmarks
|
||||
- name: Post Benchmark Results
|
||||
run: |
|
||||
python3 pr/scripts/ci/post_benchmark_results.py base_results pr_results
|
||||
|
1
.gitignore
vendored
1
.gitignore
vendored
@ -48,6 +48,7 @@ Thumbs.db
|
||||
/test/data/ch
|
||||
/test/data/mld
|
||||
/cmake/postinst
|
||||
/target
|
||||
|
||||
# Eclipse related files #
|
||||
#########################
|
||||
|
@ -1,7 +1,6 @@
|
||||
# Unreleased
|
||||
- Changes from 5.27.1
|
||||
- Features
|
||||
- ADDED: Route pedestrians over highway=platform [#6993](https://github.com/Project-OSRM/osrm-backend/pull/6993)
|
||||
- REMOVED: Remove all core-CH left-overs [#6920](https://github.com/Project-OSRM/osrm-backend/pull/6920)
|
||||
- ADDED: Add support for a keepalive_timeout flag. [#6674](https://github.com/Project-OSRM/osrm-backend/pull/6674)
|
||||
- ADDED: Add support for a default_radius flag. [#6575](https://github.com/Project-OSRM/osrm-backend/pull/6575)
|
||||
@ -25,7 +24,6 @@
|
||||
- NodeJS:
|
||||
- CHANGED: Use node-api instead of NAN. [#6452](https://github.com/Project-OSRM/osrm-backend/pull/6452)
|
||||
- Misc:
|
||||
- CHANGED: Use std::string_view for key type in json::Object. [#7062](https://github.com/Project-OSRM/osrm-backend/pull/7062)
|
||||
- CHANGED: Use thread_local instead of boost::thread_specific_ptr. [#6991](https://github.com/Project-OSRM/osrm-backend/pull/6991)
|
||||
- CHANGED: Bump flatbuffers to v24.3.25 version. [#6988](https://github.com/Project-OSRM/osrm-backend/pull/6988)
|
||||
- CHANGED: Add .reserve(...) to assembleGeometry function. [#6983](https://github.com/Project-OSRM/osrm-backend/pull/6983)
|
||||
@ -80,7 +78,6 @@
|
||||
- ADDED: Extract prerelease/build information from package semver [#6839](https://github.com/Project-OSRM/osrm-backend/pull/6839)
|
||||
- Profiles:
|
||||
- FIXED: Bicycle and foot profiles now don't route on proposed ways [#6615](https://github.com/Project-OSRM/osrm-backend/pull/6615)
|
||||
- ADDED: Add optional support of cargo bike exclusion and width to bicyle profile [#7044](https://github.com/Project-OSRM/osrm-backend/pull/7044)
|
||||
- Routing:
|
||||
- FIXED: Fix adding traffic signal penalties during compression [#6419](https://github.com/Project-OSRM/osrm-backend/pull/6419)
|
||||
- FIXED: Correctly handle compressed traffic signals. [#6724](https://github.com/Project-OSRM/osrm-backend/pull/6724)
|
||||
|
@ -56,9 +56,6 @@ endif()
|
||||
if (POLICY CMP0074)
|
||||
cmake_policy(SET CMP0074 NEW)
|
||||
endif()
|
||||
if (POLICY CMP0167)
|
||||
cmake_policy(SET CMP0167 NEW)
|
||||
endif()
|
||||
project(OSRM C CXX)
|
||||
|
||||
|
||||
|
2582
Cargo.lock
generated
Normal file
2582
Cargo.lock
generated
Normal file
File diff suppressed because it is too large
Load Diff
37
Cargo.toml
Normal file
37
Cargo.toml
Normal file
@ -0,0 +1,37 @@
|
||||
[package]
|
||||
name = "osrm-backend"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
cheap-ruler = "0.4.0"
|
||||
chksum-md5 = "0.0.0"
|
||||
clap = "4.5.7"
|
||||
colored = "2.1.0"
|
||||
cucumber = { version = "0.21.1", features = ["tracing"] }
|
||||
flatbuffers = "24.3.25"
|
||||
futures = "0.3.30"
|
||||
geo-types = "0.7.13"
|
||||
help = "0.0.0"
|
||||
log = "0.4.21"
|
||||
reqwest = {version = "0.12.5", features = ["blocking"] }
|
||||
serde = { version = "1.0.203", features = ["serde_derive"] }
|
||||
serde_json = "1.0.118"
|
||||
xml-builder = "0.5.2"
|
||||
|
||||
[[test]]
|
||||
name = "cucumber"
|
||||
harness = false
|
||||
|
||||
[profile.bench]
|
||||
debug = true
|
||||
|
||||
[profile.release]
|
||||
debug = true
|
||||
|
||||
[build-dependencies]
|
||||
flatc-rust = "0.2.0"
|
||||
reqwest = {version = "0.12.5", features = ["blocking"] }
|
||||
serde = { version = "1.0.203", features = ["serde_derive"] }
|
||||
toml = "0.8.14"
|
||||
zip-extract = "0.1.3"
|
117
build.rs
Normal file
117
build.rs
Normal file
@ -0,0 +1,117 @@
|
||||
use std::env;
|
||||
use std::fmt::Display;
|
||||
use std::io::Cursor;
|
||||
use std::path::PathBuf;
|
||||
use std::{collections::HashMap, path::Path};
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
macro_rules! build_println {
|
||||
($($tokens: tt)*) => {
|
||||
println!("cargo:warning=\r\x1b[32;1m {}", format!($($tokens)*))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
enum OS {
|
||||
Mac,
|
||||
MacIntel,
|
||||
Linux,
|
||||
Windows,
|
||||
}
|
||||
|
||||
impl Display for OS {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "{:?}", self)
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
#[serde(untagged)]
|
||||
enum DependencyValue {
|
||||
String(String),
|
||||
Object {
|
||||
version: String,
|
||||
features: Vec<String>,
|
||||
},
|
||||
}
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
struct CargoToml {
|
||||
dependencies: HashMap<String, DependencyValue>,
|
||||
}
|
||||
|
||||
let cargo_toml_raw = include_str!("Cargo.toml");
|
||||
let cargo_toml: CargoToml = toml::from_str(cargo_toml_raw).unwrap();
|
||||
|
||||
let version = match cargo_toml
|
||||
.dependencies
|
||||
.get("flatbuffers")
|
||||
.expect("Must have dependency flatbuffers")
|
||||
{
|
||||
DependencyValue::String(s) => s,
|
||||
DependencyValue::Object {
|
||||
version,
|
||||
features: _,
|
||||
} => version,
|
||||
};
|
||||
|
||||
let executable_path = match env::consts::OS {
|
||||
"windows" => "target/flatc.exe",
|
||||
_ => "target/flatc",
|
||||
};
|
||||
|
||||
if let Some((platform, compiler)) = match env::consts::OS {
|
||||
"linux" if env::consts::ARCH == "x86_64" => Some((OS::Linux, ".clang++-15")),
|
||||
"macos" if env::consts::ARCH == "x86_64" => Some((OS::MacIntel, "")),
|
||||
"macos" if env::consts::ARCH == "aarch64" => Some((OS::Mac, "")),
|
||||
"windows" if env::consts::ARCH == "x86_64" => Some((OS::Windows, "")),
|
||||
_ => None,
|
||||
} {
|
||||
let url = format!("https://github.com/google/flatbuffers/releases/download/v{version}/{platform}.flatc.binary{compiler}.zip");
|
||||
|
||||
if !Path::new(executable_path).exists() {
|
||||
build_println!("Downloading flatc executable from {url}");
|
||||
let response = match reqwest::blocking::get(url) {
|
||||
Ok(response) => response,
|
||||
Err(e) => panic!("network error during build: {e}"),
|
||||
};
|
||||
let archive = match response.bytes() {
|
||||
Ok(archive) => archive,
|
||||
Err(e) => panic!("could not retrieve byte stream during build: {e}"),
|
||||
};
|
||||
let target_dir = PathBuf::from("target");
|
||||
zip_extract::extract(Cursor::new(archive), &target_dir, true)
|
||||
.expect("flatc cannot be unpacked")
|
||||
} else {
|
||||
build_println!("cached flatc executable found, not downloading");
|
||||
}
|
||||
} else {
|
||||
build_println!("unsupported platform: {} {}. 'flatc' binary supporting version {} of the library needs to be in system path", env::consts::OS, env::consts::ARCH, version);
|
||||
}
|
||||
|
||||
let (flatc, location) = match Path::new(executable_path).exists() {
|
||||
true => (flatc_rust::Flatc::from_path(executable_path), "downloaded"),
|
||||
false => (flatc_rust::Flatc::from_env_path(), "locally installed"),
|
||||
};
|
||||
assert!(flatc.check().is_ok());
|
||||
let version = &flatc.version().unwrap();
|
||||
build_println!(
|
||||
"Using {location} flatc v{} to compile schema files ({executable_path})",
|
||||
version.version()
|
||||
);
|
||||
flatc
|
||||
.run(flatc_rust::Args {
|
||||
extra: &["--gen-all"],
|
||||
inputs: &[
|
||||
Path::new("generated/include/engine/api/flatbuffers/position.fbs"),
|
||||
Path::new("generated/include/engine/api/flatbuffers/waypoint.fbs"),
|
||||
Path::new("generated/include/engine/api/flatbuffers/route.fbs"),
|
||||
Path::new("generated/include/engine/api/flatbuffers/table.fbs"),
|
||||
Path::new("generated/include/engine/api/flatbuffers/fbresult.fbs"),
|
||||
],
|
||||
out_dir: Path::new("target/flatbuffers/"),
|
||||
..Default::default()
|
||||
})
|
||||
.expect("flatc failed generating files");
|
||||
}
|
@ -1,34 +1,20 @@
|
||||
FROM alpine:3.21.2 AS alpine-mimalloc
|
||||
FROM alpine:3.20.0 as alpine-mimalloc
|
||||
|
||||
RUN apk update && \
|
||||
apk upgrade && \
|
||||
apk add --no-cache \
|
||||
boost-iostreams \
|
||||
boost-program_options \
|
||||
boost-thread \
|
||||
mimalloc
|
||||
RUN apk add --no-cache mimalloc
|
||||
|
||||
ENV LD_PRELOAD=/usr/lib/libmimalloc.so.2
|
||||
ENV MIMALLOC_LARGE_OS_PAGES=1
|
||||
|
||||
|
||||
FROM alpine-mimalloc AS builder
|
||||
FROM alpine-mimalloc as builder
|
||||
ARG DOCKER_TAG
|
||||
ARG BUILD_CONCURRENCY
|
||||
RUN mkdir -p /src && mkdir -p /opt
|
||||
|
||||
RUN mkdir -p /src /opt && \
|
||||
apk add --no-cache \
|
||||
boost-dev \
|
||||
boost-filesystem \
|
||||
clang \
|
||||
cmake \
|
||||
expat-dev \
|
||||
git \
|
||||
libbz2 \
|
||||
libxml2 \
|
||||
lua5.4-dev \
|
||||
make \
|
||||
onetbb-dev
|
||||
RUN apk add --no-cache \
|
||||
cmake make git clang libbz2 libxml2 \
|
||||
boost-dev boost-program_options boost-filesystem boost-iostreams boost-thread \
|
||||
lua5.4-dev onetbb-dev expat-dev
|
||||
|
||||
COPY . /src
|
||||
WORKDIR /src
|
||||
@ -53,18 +39,16 @@ RUN NPROC=${BUILD_CONCURRENCY:-$(nproc)} && \
|
||||
rm -rf /src
|
||||
|
||||
|
||||
# Multistage build to reduce image size - https://docs.docker.com/build/building/multi-stage/#use-multi-stage-builds
|
||||
# Multistage build to reduce image size - https://docs.docker.com/engine/userguide/eng-image/multistage-build/#use-multi-stage-builds
|
||||
# Only the content below ends up in the image, this helps remove /src from the image (which is large)
|
||||
FROM alpine-mimalloc AS runstage
|
||||
FROM alpine-mimalloc as runstage
|
||||
|
||||
COPY --from=builder /usr/local /usr/local
|
||||
COPY --from=builder /opt /opt
|
||||
|
||||
RUN apk add --no-cache \
|
||||
boost-date_time \
|
||||
expat \
|
||||
lua5.4 \
|
||||
onetbb && \
|
||||
boost-program_options boost-date_time boost-iostreams boost-thread \
|
||||
expat lua5.4 onetbb && \
|
||||
ldconfig /usr/local/lib
|
||||
|
||||
RUN /usr/local/bin/osrm-extract --help && \
|
||||
@ -76,4 +60,3 @@ RUN /usr/local/bin/osrm-extract --help && \
|
||||
WORKDIR /opt
|
||||
|
||||
EXPOSE 5000
|
||||
|
||||
|
@ -1,24 +1,21 @@
|
||||
FROM debian:bookworm-slim AS builder
|
||||
FROM debian:bookworm-slim as builder
|
||||
ARG DOCKER_TAG
|
||||
ARG BUILD_CONCURRENCY
|
||||
RUN mkdir -p /src && mkdir -p /opt
|
||||
|
||||
RUN mkdir -p /src /opt && \
|
||||
apt-get update && \
|
||||
apt-get -y --no-install-recommends --no-install-suggests install \
|
||||
ca-certificates \
|
||||
cmake \
|
||||
g++ \
|
||||
gcc \
|
||||
git \
|
||||
libboost1.81-all-dev \
|
||||
libbz2-dev \
|
||||
liblua5.4-dev \
|
||||
libtbb-dev \
|
||||
libxml2-dev \
|
||||
libzip-dev \
|
||||
lua5.4 \
|
||||
make \
|
||||
pkg-config
|
||||
RUN apt-get update && \
|
||||
apt-get -y --no-install-recommends install ca-certificates cmake make git gcc g++ libbz2-dev libxml2-dev wget \
|
||||
libzip-dev libboost1.81-all-dev lua5.4 liblua5.4-dev pkg-config -o APT::Install-Suggests=0 -o APT::Install-Recommends=0
|
||||
|
||||
RUN NPROC=${BUILD_CONCURRENCY:-$(nproc)} && \
|
||||
ldconfig /usr/local/lib && \
|
||||
git clone --branch v2021.12.0 --single-branch https://github.com/oneapi-src/oneTBB.git && \
|
||||
cd oneTBB && \
|
||||
mkdir build && \
|
||||
cd build && \
|
||||
cmake -DTBB_TEST=OFF -DCMAKE_BUILD_TYPE=Release .. && \
|
||||
cmake --build . && \
|
||||
cmake --install .
|
||||
|
||||
COPY . /src
|
||||
WORKDIR /src
|
||||
@ -44,24 +41,19 @@ RUN NPROC=${BUILD_CONCURRENCY:-$(nproc)} && \
|
||||
rm -rf /src
|
||||
|
||||
|
||||
# Multistage build to reduce image size - https://docs.docker.com/build/building/multi-stage/#use-multi-stage-builds
|
||||
# Multistage build to reduce image size - https://docs.docker.com/engine/userguide/eng-image/multistage-build/#use-multi-stage-builds
|
||||
# Only the content below ends up in the image, this helps remove /src from the image (which is large)
|
||||
FROM debian:bookworm-slim AS runstage
|
||||
FROM debian:bookworm-slim as runstage
|
||||
|
||||
COPY --from=builder /usr/local /usr/local
|
||||
COPY --from=builder /opt /opt
|
||||
|
||||
RUN apt-get update && \
|
||||
apt-get install -y --no-install-recommends --no-install-suggests \
|
||||
expat \
|
||||
libboost-date-time1.81.0 \
|
||||
libboost-iostreams1.81.0 \
|
||||
libboost-program-options1.81.0 \
|
||||
libboost-thread1.81.0 \
|
||||
liblua5.4-0 \
|
||||
libtbb12 && \
|
||||
apt-get install -y --no-install-recommends \
|
||||
libboost-program-options1.81.0 libboost-date-time1.81.0 libboost-iostreams1.81.0 libboost-thread1.81.0 \
|
||||
expat liblua5.4-0 && \
|
||||
rm -rf /var/lib/apt/lists/* && \
|
||||
# Add /usr/local/lib to ldconfig to allow loading libraries from there
|
||||
# add /usr/local/lib to ldconfig to allow loading libraries from there
|
||||
ldconfig /usr/local/lib
|
||||
|
||||
RUN /usr/local/bin/osrm-extract --help && \
|
||||
@ -73,4 +65,3 @@ RUN /usr/local/bin/osrm-extract --help && \
|
||||
WORKDIR /opt
|
||||
|
||||
EXPOSE 5000
|
||||
|
||||
|
@ -200,7 +200,7 @@ curl 'http://router.project-osrm.org/nearest/v1/driving/13.388860,52.517037?numb
|
||||
Finds the fastest route between coordinates in the supplied order.
|
||||
|
||||
```endpoint
|
||||
GET /route/v1/{profile}/{coordinates}?alternatives={true|false|number}&steps={true|false}&geometries={polyline|polyline6|geojson}&overview={full|simplified|false}&annotations={true|false}
|
||||
GET /route/v1/{profile}/{coordinates}?alternatives={true|false|number}&steps={true|false}&geometries={polyline|polyline6|geojson}&overview={full|simplified|false}&annotations={true|false}&continue_straight={default|true|false}
|
||||
```
|
||||
|
||||
In addition to the [general options](#general-options) the following options are supported for this service:
|
||||
|
@ -60,5 +60,5 @@ Feature: Car - Handle driving
|
||||
When I route I should get
|
||||
| from | to | route | modes | speed | turns |
|
||||
| a | g | abc,cde,efg,efg | driving,driving,driving,driving | 7 km/h | depart,new name right,new name left,arrive |
|
||||
| c | e | cde,cde | driving,driving | 2 km/h | depart,arrive |
|
||||
| e | c | cde,cde | driving,driving | 2 km/h | depart,arrive |
|
||||
| c | e | cde,cde | driving,driving | 2.4 km/h | depart,arrive |
|
||||
| e | c | cde,cde | driving,driving | 2.4 km/h | depart,arrive |
|
||||
|
@ -113,12 +113,12 @@ Feature: Car - Destination only, no passing through
|
||||
Scenario: Car - Routing around a way that becomes destination only
|
||||
Given the node map
|
||||
"""
|
||||
a---c---b
|
||||
+ \
|
||||
+ |
|
||||
d |
|
||||
1 |
|
||||
\___e
|
||||
a---c---b
|
||||
+ \
|
||||
+ |
|
||||
d |
|
||||
1 |
|
||||
\___e
|
||||
"""
|
||||
|
||||
And the ways
|
||||
@ -136,12 +136,12 @@ Feature: Car - Destination only, no passing through
|
||||
Scenario: Car - Routing through a parking lot tagged access=destination,service
|
||||
Given the node map
|
||||
"""
|
||||
a----c++++b+++g------h---i
|
||||
| + + + /
|
||||
| + + + /
|
||||
| + + + /
|
||||
| d++++e+f /
|
||||
z--------------y
|
||||
a----c++++b+++g------h---i
|
||||
| + + + /
|
||||
| + + + /
|
||||
| + + + /
|
||||
| d++++e+f /
|
||||
z--------------y
|
||||
"""
|
||||
|
||||
And the ways
|
||||
@ -165,12 +165,12 @@ Feature: Car - Destination only, no passing through
|
||||
Given a grid size of 20 meters
|
||||
Given the node map
|
||||
"""
|
||||
a---c---b
|
||||
:
|
||||
x
|
||||
:
|
||||
d
|
||||
\__e
|
||||
a---c---b
|
||||
:
|
||||
x
|
||||
:
|
||||
d
|
||||
\__e
|
||||
"""
|
||||
|
||||
And the ways
|
||||
|
@ -26,15 +26,7 @@ Feature: Foot - Access tags on ways
|
||||
| motorway | no | | |
|
||||
| motorway | no | yes | x |
|
||||
| motorway | no | no | |
|
||||
| platform | | | x |
|
||||
| platform | | yes | x |
|
||||
| platform | | no | |
|
||||
| platform | yes | | x |
|
||||
| platform | yes | yes | x |
|
||||
| platform | yes | no | |
|
||||
| platform | no | | |
|
||||
| platform | no | yes | x |
|
||||
| platform | no | no | |
|
||||
|
||||
|
||||
Scenario: Foot - Overwriting implied acccess on ways
|
||||
Then routability should be
|
||||
|
@ -46,7 +46,7 @@ class OSRMBaseLoader{
|
||||
let retry = (err) => {
|
||||
if (err) {
|
||||
if (retryCount < this.scope.OSRM_CONNECTION_RETRIES) {
|
||||
const timeoutMs = 10 * Math.pow(this.scope.OSRM_CONNECTION_EXP_BACKOFF_COEF, retryCount);
|
||||
const timeoutMs = 10 * Math.pow(1.1, retryCount);
|
||||
retryCount++;
|
||||
setTimeout(() => { tryConnect(this.scope.OSRM_IP, this.scope.OSRM_PORT, retry); }, timeoutMs);
|
||||
} else {
|
||||
|
@ -603,8 +603,6 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
|
||||
auto found_range = std::equal_range(
|
||||
m_maneuver_overrides.begin(), m_maneuver_overrides.end(), edge_based_node_id, Comp{});
|
||||
|
||||
results.reserve(std::distance(found_range.first, found_range.second));
|
||||
|
||||
std::for_each(found_range.first,
|
||||
found_range.second,
|
||||
[&](const auto &override)
|
||||
|
@ -30,7 +30,7 @@ struct V8Renderer
|
||||
{
|
||||
Napi::Value child;
|
||||
std::visit(V8Renderer(env, child), keyValue.second);
|
||||
obj.Set(keyValue.first.data(), child);
|
||||
obj.Set(keyValue.first, child);
|
||||
}
|
||||
out = obj;
|
||||
}
|
||||
|
@ -11,6 +11,46 @@ namespace osrm::util
|
||||
namespace bearing
|
||||
{
|
||||
|
||||
inline std::string get(const double heading)
|
||||
{
|
||||
BOOST_ASSERT(heading >= 0);
|
||||
BOOST_ASSERT(heading <= 360);
|
||||
|
||||
if (heading <= 22.5)
|
||||
{
|
||||
return "N";
|
||||
}
|
||||
if (heading <= 67.5)
|
||||
{
|
||||
return "NE";
|
||||
}
|
||||
if (heading <= 112.5)
|
||||
{
|
||||
return "E";
|
||||
}
|
||||
if (heading <= 157.5)
|
||||
{
|
||||
return "SE";
|
||||
}
|
||||
if (heading <= 202.5)
|
||||
{
|
||||
return "S";
|
||||
}
|
||||
if (heading <= 247.5)
|
||||
{
|
||||
return "SW";
|
||||
}
|
||||
if (heading <= 292.5)
|
||||
{
|
||||
return "W";
|
||||
}
|
||||
if (heading <= 337.5)
|
||||
{
|
||||
return "NW";
|
||||
}
|
||||
return "N";
|
||||
}
|
||||
|
||||
// Checks whether A is between B-range and B+range, all modulo 360
|
||||
// e.g. A = 5, B = 5, range = 10 == true
|
||||
// A = -6, B = 5, range = 10 == false
|
||||
|
@ -2,13 +2,43 @@
|
||||
#define OSRM_UTIL_BIT_RANGE_HPP
|
||||
|
||||
#include "util/msb.hpp"
|
||||
#include <bit>
|
||||
|
||||
#include <boost/iterator/iterator_facade.hpp>
|
||||
#include <boost/range/iterator_range.hpp>
|
||||
|
||||
namespace osrm::util
|
||||
{
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template <typename T> std::size_t countOnes(T value)
|
||||
{
|
||||
static_assert(std::is_unsigned<T>::value, "Only unsigned types allowed");
|
||||
std::size_t number_of_ones = 0;
|
||||
while (value > 0)
|
||||
{
|
||||
auto index = msb(value);
|
||||
value = value & ~(T{1} << index);
|
||||
number_of_ones++;
|
||||
}
|
||||
return number_of_ones;
|
||||
}
|
||||
|
||||
#if (defined(__clang__) || defined(__GNUC__) || defined(__GNUG__))
|
||||
inline std::size_t countOnes(std::uint8_t value)
|
||||
{
|
||||
return __builtin_popcount(std::uint32_t{value});
|
||||
}
|
||||
inline std::size_t countOnes(std::uint16_t value)
|
||||
{
|
||||
return __builtin_popcount(std::uint32_t{value});
|
||||
}
|
||||
inline std::size_t countOnes(unsigned int value) { return __builtin_popcount(value); }
|
||||
inline std::size_t countOnes(unsigned long value) { return __builtin_popcountl(value); }
|
||||
inline std::size_t countOnes(unsigned long long value) { return __builtin_popcountll(value); }
|
||||
#endif
|
||||
} // namespace detail
|
||||
|
||||
// Investigate if we can replace this with
|
||||
// http://www.boost.org/doc/libs/1_64_0/libs/dynamic_bitset/dynamic_bitset.html
|
||||
template <typename DataT>
|
||||
@ -40,7 +70,7 @@ class BitIterator : public boost::iterator_facade<BitIterator<DataT>,
|
||||
|
||||
difference_type distance_to(const BitIterator &other) const
|
||||
{
|
||||
return std::popcount(m_value) - std::popcount(other.m_value);
|
||||
return detail::countOnes(m_value) - detail::countOnes(other.m_value);
|
||||
}
|
||||
|
||||
bool equal(const BitIterator &other) const { return m_value == other.m_value; }
|
||||
|
@ -104,7 +104,7 @@ using Value = std::variant<String, Number, Object, Array, True, False, Null>;
|
||||
*/
|
||||
struct Object
|
||||
{
|
||||
std::unordered_map<std::string_view, Value> values;
|
||||
std::unordered_map<std::string, Value> values;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -44,13 +44,13 @@ struct Comparator
|
||||
|
||||
bool operator()(const Object &lhs, const Object &rhs) const
|
||||
{
|
||||
std::set<std::string_view> lhs_keys;
|
||||
std::set<std::string> lhs_keys;
|
||||
for (const auto &key_value : lhs.values)
|
||||
{
|
||||
lhs_keys.insert(key_value.first);
|
||||
}
|
||||
|
||||
std::set<std::string_view> rhs_keys;
|
||||
std::set<std::string> rhs_keys;
|
||||
for (const auto &key_value : rhs.values)
|
||||
{
|
||||
rhs_keys.insert(key_value.first);
|
||||
@ -60,7 +60,7 @@ struct Comparator
|
||||
{
|
||||
if (rhs_keys.find(key) == rhs_keys.end())
|
||||
{
|
||||
reason = rhs_path + " doesn't have key \"" + std::string(key) + "\"";
|
||||
reason = rhs_path + " doesn't have key \"" + key + "\"";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -69,7 +69,7 @@ struct Comparator
|
||||
{
|
||||
if (lhs_keys.find(key) == lhs_keys.end())
|
||||
{
|
||||
reason = lhs_path + " doesn't have key \"" + std::string(key) + "\"";
|
||||
reason = lhs_path + " doesn't have key \"" + key + "\"";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -81,11 +81,10 @@ struct Comparator
|
||||
|
||||
const auto &rhs_child = rhs.values.find(key)->second;
|
||||
const auto &lhs_child = lhs.values.find(key)->second;
|
||||
auto is_same = std::visit(Comparator(reason,
|
||||
lhs_path + "." + std::string(key),
|
||||
rhs_path + "." + std::string(key)),
|
||||
lhs_child,
|
||||
rhs_child);
|
||||
auto is_same =
|
||||
std::visit(Comparator(reason, lhs_path + "." + key, rhs_path + "." + key),
|
||||
lhs_child,
|
||||
rhs_child);
|
||||
if (!is_same)
|
||||
{
|
||||
return false;
|
||||
|
@ -97,7 +97,7 @@ template <typename Out> struct Renderer
|
||||
void operator()(const Null &) { write<>("null"); }
|
||||
|
||||
private:
|
||||
void write(std::string_view str);
|
||||
void write(const std::string &str);
|
||||
void write(const char *str, size_t size);
|
||||
void write(char ch);
|
||||
|
||||
@ -110,7 +110,7 @@ template <typename Out> struct Renderer
|
||||
Out &out;
|
||||
};
|
||||
|
||||
template <> void Renderer<std::vector<char>>::write(std::string_view str)
|
||||
template <> void Renderer<std::vector<char>>::write(const std::string &str)
|
||||
{
|
||||
out.insert(out.end(), str.begin(), str.end());
|
||||
}
|
||||
@ -122,7 +122,7 @@ template <> void Renderer<std::vector<char>>::write(const char *str, size_t size
|
||||
|
||||
template <> void Renderer<std::vector<char>>::write(char ch) { out.push_back(ch); }
|
||||
|
||||
template <> void Renderer<std::ostream>::write(std::string_view str) { out << str; }
|
||||
template <> void Renderer<std::ostream>::write(const std::string &str) { out << str; }
|
||||
|
||||
template <> void Renderer<std::ostream>::write(const char *str, size_t size)
|
||||
{
|
||||
@ -131,7 +131,7 @@ template <> void Renderer<std::ostream>::write(const char *str, size_t size)
|
||||
|
||||
template <> void Renderer<std::ostream>::write(char ch) { out << ch; }
|
||||
|
||||
template <> void Renderer<std::string>::write(std::string_view str) { out += str; }
|
||||
template <> void Renderer<std::string>::write(const std::string &str) { out += str; }
|
||||
|
||||
template <> void Renderer<std::string>::write(const char *str, size_t size)
|
||||
{
|
||||
|
@ -2,7 +2,6 @@
|
||||
#define MEMINFO_HPP
|
||||
|
||||
#include "util/log.hpp"
|
||||
#include <cstddef>
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <sys/resource.h>
|
||||
@ -11,31 +10,22 @@
|
||||
namespace osrm::util
|
||||
{
|
||||
|
||||
inline size_t PeakRAMUsedInBytes()
|
||||
inline void DumpMemoryStats()
|
||||
{
|
||||
#ifndef _WIN32
|
||||
rusage usage;
|
||||
getrusage(RUSAGE_SELF, &usage);
|
||||
#ifdef __linux__
|
||||
// Under linux, ru.maxrss is in kb
|
||||
return usage.ru_maxrss * 1024;
|
||||
util::Log() << "RAM: peak bytes used: " << usage.ru_maxrss * 1024;
|
||||
#else // __linux__
|
||||
// Under BSD systems (OSX), it's in bytes
|
||||
return usage.ru_maxrss;
|
||||
util::Log() << "RAM: peak bytes used: " << usage.ru_maxrss;
|
||||
#endif // __linux__
|
||||
#else // _WIN32
|
||||
return 0;
|
||||
#endif // _WIN32
|
||||
}
|
||||
|
||||
inline void DumpMemoryStats()
|
||||
{
|
||||
#ifndef _WIN32
|
||||
util::Log() << "RAM: peak bytes used: " << PeakRAMUsedInBytes();
|
||||
#else // _WIN32
|
||||
util::Log() << "RAM: peak bytes used: <not implemented on Windows>";
|
||||
#endif // _WIN32
|
||||
}
|
||||
} // namespace osrm::util
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
@ -1,24 +1,50 @@
|
||||
#ifndef OSRM_UTIL_MSB_HPP
|
||||
#define OSRM_UTIL_MSB_HPP
|
||||
|
||||
#include <bit>
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
#include <climits>
|
||||
#include <cstdint>
|
||||
#include <limits>
|
||||
#include <utility>
|
||||
|
||||
namespace osrm::util
|
||||
{
|
||||
|
||||
// get the msb of an integer
|
||||
// return 0 for integers without msb
|
||||
template <typename T> std::size_t msb(T value)
|
||||
{
|
||||
BOOST_ASSERT(value > 0);
|
||||
|
||||
static_assert(std::is_integral<T>::value && !std::is_signed<T>::value, "Integer required.");
|
||||
constexpr auto MSB_INDEX = std::numeric_limits<unsigned char>::digits * sizeof(T) - 1;
|
||||
|
||||
return MSB_INDEX - std::countl_zero(value);
|
||||
std::size_t msb = 0;
|
||||
while (value > 0)
|
||||
{
|
||||
value >>= 1u;
|
||||
msb++;
|
||||
}
|
||||
BOOST_ASSERT(msb > 0);
|
||||
return msb - 1;
|
||||
}
|
||||
|
||||
#if (defined(__clang__) || defined(__GNUC__) || defined(__GNUG__))
|
||||
inline std::size_t msb(unsigned long long v)
|
||||
{
|
||||
BOOST_ASSERT(v > 0);
|
||||
constexpr auto MSB_INDEX = CHAR_BIT * sizeof(unsigned long long) - 1;
|
||||
return MSB_INDEX - __builtin_clzll(v);
|
||||
}
|
||||
inline std::size_t msb(unsigned long v)
|
||||
{
|
||||
BOOST_ASSERT(v > 0);
|
||||
constexpr auto MSB_INDEX = CHAR_BIT * sizeof(unsigned long) - 1;
|
||||
return MSB_INDEX - __builtin_clzl(v);
|
||||
}
|
||||
inline std::size_t msb(unsigned int v)
|
||||
{
|
||||
BOOST_ASSERT(v > 0);
|
||||
constexpr auto MSB_INDEX = CHAR_BIT * sizeof(unsigned int) - 1;
|
||||
return MSB_INDEX - __builtin_clz(v);
|
||||
}
|
||||
#endif
|
||||
} // namespace osrm::util
|
||||
|
||||
#endif
|
||||
|
13
package-lock.json
generated
13
package-lock.json
generated
@ -10,8 +10,7 @@
|
||||
"hasInstallScript": true,
|
||||
"license": "BSD-2-Clause",
|
||||
"dependencies": {
|
||||
"@mapbox/node-pre-gyp": "^1.0.11",
|
||||
"seedrandom": "^3.0.5"
|
||||
"@mapbox/node-pre-gyp": "^1.0.11"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/cli": "^7.18.10",
|
||||
@ -14653,11 +14652,6 @@
|
||||
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
|
||||
"devOptional": true
|
||||
},
|
||||
"node_modules/seedrandom": {
|
||||
"version": "3.0.5",
|
||||
"resolved": "https://registry.npmjs.org/seedrandom/-/seedrandom-3.0.5.tgz",
|
||||
"integrity": "sha512-8OwmbklUNzwezjGInmZ+2clQmExQPvomqjL7LFqOYqtmuxRgQYqOD3mHaU+MvZn5FLUeVxVfQjwLZW/n/JFuqg=="
|
||||
},
|
||||
"node_modules/semver": {
|
||||
"version": "5.7.2",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz",
|
||||
@ -30302,11 +30296,6 @@
|
||||
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
|
||||
"devOptional": true
|
||||
},
|
||||
"seedrandom": {
|
||||
"version": "3.0.5",
|
||||
"resolved": "https://registry.npmjs.org/seedrandom/-/seedrandom-3.0.5.tgz",
|
||||
"integrity": "sha512-8OwmbklUNzwezjGInmZ+2clQmExQPvomqjL7LFqOYqtmuxRgQYqOD3mHaU+MvZn5FLUeVxVfQjwLZW/n/JFuqg=="
|
||||
},
|
||||
"semver": {
|
||||
"version": "5.7.2",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz",
|
||||
|
11
package.json
11
package.json
@ -4,8 +4,7 @@
|
||||
"private": false,
|
||||
"description": "The Open Source Routing Machine is a high performance routing engine written in C++ designed to run on OpenStreetMap data.",
|
||||
"dependencies": {
|
||||
"@mapbox/node-pre-gyp": "^1.0.11",
|
||||
"seedrandom": "^3.0.5"
|
||||
"@mapbox/node-pre-gyp": "^1.0.11"
|
||||
},
|
||||
"browserify": {
|
||||
"transform": [
|
||||
@ -58,7 +57,6 @@
|
||||
"jsonpath": "^1.1.1",
|
||||
"mkdirp": "^0.5.6",
|
||||
"node-addon-api": "^5.0.0",
|
||||
"node-cmake": "^2.5.1",
|
||||
"node-timeout": "0.0.4",
|
||||
"polyline": "^0.2.0",
|
||||
"request": "^2.88.2",
|
||||
@ -66,13 +64,12 @@
|
||||
"tape": "^4.16.0",
|
||||
"turf": "^3.0.14",
|
||||
"uglify-js": "^3.17.0",
|
||||
"xmlbuilder": "^4.2.1"
|
||||
"xmlbuilder": "^4.2.1",
|
||||
"node-cmake": "^2.5.1"
|
||||
},
|
||||
"main": "lib/index.js",
|
||||
"binary": {
|
||||
"napi_versions": [
|
||||
8
|
||||
],
|
||||
"napi_versions": [8],
|
||||
"module_name": "node_osrm",
|
||||
"module_path": "./lib/binding_napi_v{napi_build_version}/",
|
||||
"host": "https://github.com",
|
||||
|
@ -35,10 +35,6 @@ function setup()
|
||||
turn_bias = 1.4,
|
||||
use_public_transport = true,
|
||||
|
||||
-- Exclude narrow ways, in particular to route with cargo bike
|
||||
width = nil, -- Cargo bike could 0.5 width, in meters
|
||||
exclude_cargo_bike = false,
|
||||
|
||||
allowed_start_modes = Set {
|
||||
mode.cycling,
|
||||
mode.pushing_bike
|
||||
@ -247,27 +243,6 @@ function process_node(profile, node, result)
|
||||
end
|
||||
end
|
||||
|
||||
if profile.exclude_cargo_bike then
|
||||
local cargo_bike = node:get_value_by_key("cargo_bike")
|
||||
if cargo_bike and cargo_bike == "no" then
|
||||
result.barrier = true
|
||||
end
|
||||
end
|
||||
|
||||
-- width
|
||||
if profile.width then
|
||||
-- From barrier=cycle_barrier or other barriers
|
||||
local maxwidth_physical = node:get_value_by_key("maxwidth:physical")
|
||||
local maxwidth_physical_meter = maxwidth_physical and Measure.parse_value_meters(maxwidth_physical) or 99
|
||||
local opening = node:get_value_by_key("opening")
|
||||
local opening_meter = opening and Measure.parse_value_meters(opening) or 99
|
||||
local width_meter = math.min(maxwidth_physical_meter, opening_meter)
|
||||
|
||||
if width_meter and width_meter < profile.width then
|
||||
result.barrier = true
|
||||
end
|
||||
end
|
||||
|
||||
-- check if node is a traffic light
|
||||
result.traffic_lights = TrafficSignal.get_value(node)
|
||||
end
|
||||
@ -324,8 +299,6 @@ function handle_bicycle_tags(profile,way,result,data)
|
||||
|
||||
bike_push_handler(profile,way,result,data)
|
||||
|
||||
-- width should be after bike_push
|
||||
width_handler(profile,way,result,data)
|
||||
|
||||
-- maxspeed
|
||||
limit( result, data.maxspeed, data.maxspeed_forward, data.maxspeed_backward )
|
||||
@ -480,27 +453,6 @@ function cycleway_handler(profile,way,result,data)
|
||||
end
|
||||
end
|
||||
|
||||
function width_handler(profile,way,result,data)
|
||||
if profile.exclude_cargo_bike then
|
||||
local cargo_bike = way:get_value_by_key("cargo_bike")
|
||||
if cargo_bike and cargo_bike == "no" then
|
||||
result.forward_mode = mode.inaccessible
|
||||
result.backward_mode = mode.inaccessible
|
||||
end
|
||||
end
|
||||
|
||||
if profile.width then
|
||||
local width = way:get_value_by_key("width")
|
||||
if width then
|
||||
local width_meter = Measure.parse_value_meters(width)
|
||||
if width_meter and width_meter < profile.width then
|
||||
result.forward_mode = mode.inaccessible
|
||||
result.backward_mode = mode.inaccessible
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function bike_push_handler(profile,way,result,data)
|
||||
-- pushing bikes - if no other mode found
|
||||
if result.forward_mode == mode.inaccessible or result.backward_mode == mode.inaccessible or
|
||||
|
@ -90,7 +90,6 @@ function setup()
|
||||
path = walking_speed,
|
||||
steps = walking_speed,
|
||||
pedestrian = walking_speed,
|
||||
platform = walking_speed,
|
||||
footway = walking_speed,
|
||||
pier = walking_speed,
|
||||
},
|
||||
|
@ -1,211 +0,0 @@
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const readline = require('readline');
|
||||
const seedrandom = require('seedrandom');
|
||||
|
||||
|
||||
let RNG;
|
||||
|
||||
class GPSData {
|
||||
constructor(gpsTracesFilePath) {
|
||||
this.tracks = {};
|
||||
this.coordinates = [];
|
||||
this.trackIds = [];
|
||||
this._loadGPSTraces(gpsTracesFilePath);
|
||||
}
|
||||
|
||||
_loadGPSTraces(gpsTracesFilePath) {
|
||||
const expandedPath = path.resolve(gpsTracesFilePath);
|
||||
const data = fs.readFileSync(expandedPath, 'utf-8');
|
||||
const lines = data.split('\n');
|
||||
const headers = lines[0].split(',');
|
||||
|
||||
const latitudeIndex = headers.indexOf('Latitude');
|
||||
const longitudeIndex = headers.indexOf('Longitude');
|
||||
const trackIdIndex = headers.indexOf('TrackID');
|
||||
|
||||
for (let i = 1; i < lines.length; i++) {
|
||||
if (lines[i].trim() === '') continue;
|
||||
const row = lines[i].split(',');
|
||||
|
||||
const latitude = parseFloat(row[latitudeIndex]);
|
||||
const longitude = parseFloat(row[longitudeIndex]);
|
||||
const trackId = row[trackIdIndex];
|
||||
|
||||
const coord = [longitude, latitude];
|
||||
this.coordinates.push(coord);
|
||||
|
||||
if (!this.tracks[trackId]) {
|
||||
this.tracks[trackId] = [];
|
||||
}
|
||||
this.tracks[trackId].push(coord);
|
||||
}
|
||||
|
||||
this.trackIds = Object.keys(this.tracks);
|
||||
}
|
||||
|
||||
getRandomCoordinate() {
|
||||
const randomIndex = Math.floor(RNG() * this.coordinates.length);
|
||||
return this.coordinates[randomIndex];
|
||||
}
|
||||
|
||||
getRandomTrack() {
|
||||
const randomIndex = Math.floor(RNG() * this.trackIds.length);
|
||||
const trackId = this.trackIds[randomIndex];
|
||||
return this.tracks[trackId];
|
||||
}
|
||||
};
|
||||
|
||||
async function runOSRMMethod(osrm, method, coordinates) {
|
||||
const time = await new Promise((resolve, reject) => {
|
||||
const startTime = process.hrtime();
|
||||
osrm[method]({coordinates}, (err, result) => {
|
||||
if (err) {
|
||||
if (['NoSegment', 'NoMatch', 'NoRoute', 'NoTrips'].includes(err.message)) {
|
||||
resolve(null);
|
||||
} else {
|
||||
|
||||
reject(err);
|
||||
}
|
||||
} else {
|
||||
const endTime = process.hrtime(startTime);
|
||||
resolve(endTime[0] + endTime[1] / 1e9);
|
||||
}
|
||||
});
|
||||
});
|
||||
return time;
|
||||
}
|
||||
|
||||
async function nearest(osrm, gpsData) {
|
||||
const times = [];
|
||||
for (let i = 0; i < 1000; i++) {
|
||||
const coord = gpsData.getRandomCoordinate();
|
||||
times.push(await runOSRMMethod(osrm, 'nearest', [coord]));
|
||||
}
|
||||
return times;
|
||||
}
|
||||
|
||||
async function route(osrm, gpsData) {
|
||||
const times = [];
|
||||
for (let i = 0; i < 1000; i++) {
|
||||
const from = gpsData.getRandomCoordinate();
|
||||
const to = gpsData.getRandomCoordinate();
|
||||
|
||||
|
||||
times.push(await runOSRMMethod(osrm, 'route', [from, to]));
|
||||
}
|
||||
return times;
|
||||
}
|
||||
|
||||
async function table(osrm, gpsData) {
|
||||
const times = [];
|
||||
for (let i = 0; i < 250; i++) {
|
||||
const numPoints = Math.floor(RNG() * 3) + 15;
|
||||
const coordinates = [];
|
||||
for (let i = 0; i < numPoints; i++) {
|
||||
coordinates.push(gpsData.getRandomCoordinate());
|
||||
}
|
||||
|
||||
|
||||
times.push(await runOSRMMethod(osrm, 'table', coordinates));
|
||||
}
|
||||
return times;
|
||||
}
|
||||
|
||||
async function match(osrm, gpsData) {
|
||||
const times = [];
|
||||
for (let i = 0; i < 1000; i++) {
|
||||
const numPoints = Math.floor(RNG() * 50) + 50;
|
||||
const coordinates = gpsData.getRandomTrack().slice(0, numPoints);
|
||||
|
||||
|
||||
times.push(await runOSRMMethod(osrm, 'match', coordinates));
|
||||
}
|
||||
return times;
|
||||
}
|
||||
|
||||
async function trip(osrm, gpsData) {
|
||||
const times = [];
|
||||
for (let i = 0; i < 250; i++) {
|
||||
const numPoints = Math.floor(RNG() * 2) + 5;
|
||||
const coordinates = [];
|
||||
for (let i = 0; i < numPoints; i++) {
|
||||
coordinates.push(gpsData.getRandomCoordinate());
|
||||
}
|
||||
|
||||
|
||||
times.push(await runOSRMMethod(osrm, 'trip', coordinates));
|
||||
}
|
||||
return times;
|
||||
}
|
||||
|
||||
function bootstrapConfidenceInterval(data, numSamples = 1000, confidenceLevel = 0.95) {
|
||||
let means = [];
|
||||
let dataLength = data.length;
|
||||
|
||||
for (let i = 0; i < numSamples; i++) {
|
||||
let sample = [];
|
||||
for (let j = 0; j < dataLength; j++) {
|
||||
let randomIndex = Math.floor(RNG() * dataLength);
|
||||
sample.push(data[randomIndex]);
|
||||
}
|
||||
let sampleMean = sample.reduce((a, b) => a + b, 0) / sample.length;
|
||||
means.push(sampleMean);
|
||||
}
|
||||
|
||||
means.sort((a, b) => a - b);
|
||||
let lowerBoundIndex = Math.floor((1 - confidenceLevel) / 2 * numSamples);
|
||||
let upperBoundIndex = Math.floor((1 + confidenceLevel) / 2 * numSamples);
|
||||
let mean = means.reduce((a, b) => a + b, 0) / means.length;
|
||||
let lowerBound = means[lowerBoundIndex];
|
||||
let upperBound = means[upperBoundIndex];
|
||||
|
||||
return { mean: mean, lowerBound: lowerBound, upperBound: upperBound };
|
||||
}
|
||||
|
||||
function calculateConfidenceInterval(data) {
|
||||
let { mean, lowerBound, upperBound } = bootstrapConfidenceInterval(data);
|
||||
let bestValue = Math.max(...data);
|
||||
let errorMargin = (upperBound - lowerBound) / 2;
|
||||
|
||||
return { mean, errorMargin, bestValue };
|
||||
}
|
||||
|
||||
async function main() {
|
||||
const args = process.argv.slice(2);
|
||||
|
||||
const {OSRM} = require(args[0]);
|
||||
const path = args[1];
|
||||
const algorithm = args[2].toUpperCase();
|
||||
const method = args[3];
|
||||
const gpsTracesFilePath = args[4];
|
||||
const iterations = parseInt(args[5]);
|
||||
|
||||
const gpsData = new GPSData(gpsTracesFilePath);
|
||||
const osrm = new OSRM({path, algorithm});
|
||||
|
||||
|
||||
const functions = {
|
||||
route: route,
|
||||
table: table,
|
||||
nearest: nearest,
|
||||
match: match,
|
||||
trip: trip
|
||||
};
|
||||
const func = functions[method];
|
||||
if (!func) {
|
||||
throw new Error('Unknown method');
|
||||
}
|
||||
const allTimes = [];
|
||||
for (let i = 0; i < iterations; i++) {
|
||||
RNG = seedrandom(42);
|
||||
allTimes.push((await func(osrm, gpsData)).filter(t => t !== null));
|
||||
}
|
||||
|
||||
const opsPerSec = allTimes.map(times => times.length / times.reduce((a, b) => a + b, 0));
|
||||
const { mean, errorMargin, bestValue } = calculateConfidenceInterval(opsPerSec);
|
||||
console.log(`Ops: ${mean.toFixed(1)} ± ${errorMargin.toFixed(1)} ops/s. Best: ${bestValue.toFixed(1)} ops/s`);
|
||||
|
||||
}
|
||||
|
||||
main();
|
@ -53,7 +53,6 @@ function run_benchmarks_for_folder {
|
||||
mkdir -p $RESULTS_FOLDER
|
||||
|
||||
BENCHMARKS_FOLDER="$BINARIES_FOLDER/src/benchmarks"
|
||||
|
||||
echo "Running match-bench MLD"
|
||||
$BENCHMARKS_FOLDER/match-bench "$FOLDER/test/data/mld/monaco.osrm" mld > "$RESULTS_FOLDER/match_mld.bench"
|
||||
echo "Running match-bench CH"
|
||||
@ -82,18 +81,6 @@ function run_benchmarks_for_folder {
|
||||
echo "Running osrm-contract"
|
||||
measure_peak_ram_and_time "$BINARIES_FOLDER/osrm-contract $FOLDER/data.osrm" "$RESULTS_FOLDER/osrm_contract.bench"
|
||||
|
||||
|
||||
for ALGORITHM in ch mld; do
|
||||
for BENCH in nearest table trip route match; do
|
||||
echo "Running node $BENCH $ALGORITHM"
|
||||
START=$(date +%s.%N)
|
||||
node $SCRIPTS_FOLDER/scripts/ci/bench.js $FOLDER/lib/binding/node_osrm.node $FOLDER/data.osrm $ALGORITHM $BENCH $GPS_TRACES > "$RESULTS_FOLDER/node_${BENCH}_${ALGORITHM}.bench" 5
|
||||
END=$(date +%s.%N)
|
||||
DIFF=$(echo "$END - $START" | bc)
|
||||
echo "Took: ${DIFF}s"
|
||||
done
|
||||
done
|
||||
|
||||
for ALGORITHM in ch mld; do
|
||||
for BENCH in nearest table trip route match; do
|
||||
echo "Running random $BENCH $ALGORITHM"
|
||||
|
@ -10,7 +10,7 @@ set -o nounset
|
||||
# http://git.661346.n2.nabble.com/subtree-merges-lose-prefix-after-rebase-td7332850.html
|
||||
|
||||
OSMIUM_PATH="osmcode/libosmium"
|
||||
OSMIUM_TAG=v2.20.0
|
||||
OSMIUM_TAG=v2.14.0
|
||||
|
||||
SOL_PATH="ThePhD/sol2"
|
||||
SOL_TAG=v3.3.0
|
||||
@ -22,7 +22,7 @@ MICROTAR_PATH="rxi/microtar"
|
||||
MICROTAR_TAG=v0.1.0
|
||||
|
||||
PROTOZERO_PATH="mapbox/protozero"
|
||||
PROTOZERO_TAG=v1.7.1
|
||||
PROTOZERO_TAG=v1.6.2
|
||||
|
||||
VTZERO_PATH="mapbox/vtzero"
|
||||
VTZERO_TAG=v1.1.0
|
||||
|
@ -16,8 +16,8 @@
|
||||
#include "osrm/osrm.hpp"
|
||||
#include "osrm/status.hpp"
|
||||
|
||||
#include "util/meminfo.hpp"
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
#include <boost/optional/optional.hpp>
|
||||
#include <cstdlib>
|
||||
#include <exception>
|
||||
@ -655,12 +655,6 @@ try
|
||||
std::cerr << "Unknown benchmark: " << benchmarkToRun << std::endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
std::cout << "Peak RAM: " << std::setprecision(3)
|
||||
<< static_cast<double>(osrm::util::PeakRAMUsedInBytes()) /
|
||||
static_cast<double>((1024 * 1024))
|
||||
<< "MB" << std::endl;
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
|
@ -9,17 +9,12 @@
|
||||
#include <rapidjson/document.h>
|
||||
#include <sstream>
|
||||
#include <stdexcept>
|
||||
#include <unordered_set>
|
||||
|
||||
using namespace osrm;
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
// we use std::string_view as a key in the object, so since here we have dynamic keys we have to
|
||||
// "hold" them somewhere okay for tests...
|
||||
static std::unordered_set<std::string> gKeysHolder;
|
||||
|
||||
void convert(const rapidjson::Value &value, json::Value &result)
|
||||
{
|
||||
if (value.IsString())
|
||||
@ -37,8 +32,7 @@ void convert(const rapidjson::Value &value, json::Value &result)
|
||||
{
|
||||
json::Value member;
|
||||
convert(itr->value, member);
|
||||
auto keyItr = gKeysHolder.emplace(itr->name.GetString()).first;
|
||||
object.values.emplace(*keyItr, std::move(member));
|
||||
object.values.emplace(itr->name.GetString(), std::move(member));
|
||||
}
|
||||
result = std::move(object);
|
||||
}
|
||||
@ -128,7 +122,6 @@ int main(int argc, char **argv)
|
||||
|
||||
if (std::string{out_vec.begin(), out_vec.end()} != out_str || out_str != out_ss_str)
|
||||
{
|
||||
std::cerr << "Vector/string results are not equal\n";
|
||||
throw std::logic_error("Vector/stringstream/string results are not equal");
|
||||
}
|
||||
return EXIT_SUCCESS;
|
||||
|
@ -222,6 +222,7 @@ oneToManySearch(SearchEngineData<Algorithm> &engine_working_data,
|
||||
std::vector<EdgeDuration> durations_table(target_indices.size(), MAXIMAL_EDGE_DURATION);
|
||||
std::vector<EdgeDistance> distances_table(calculate_distance ? target_indices.size() : 0,
|
||||
MAXIMAL_EDGE_DISTANCE);
|
||||
std::vector<NodeID> middle_nodes_table(target_indices.size(), SPECIAL_NODEID);
|
||||
|
||||
// Collect destination (source) nodes into a map
|
||||
std::unordered_multimap<NodeID, std::tuple<std::size_t, EdgeWeight, EdgeDuration, EdgeDistance>>
|
||||
@ -306,6 +307,7 @@ oneToManySearch(SearchEngineData<Algorithm> &engine_working_data,
|
||||
weights_table[index] = path_weight;
|
||||
durations_table[index] = path_duration;
|
||||
current_distance = path_distance;
|
||||
middle_nodes_table[index] = node;
|
||||
}
|
||||
|
||||
// Remove node from destinations list
|
||||
|
3
src/main.rs
Normal file
3
src/main.rs
Normal file
@ -0,0 +1,3 @@
|
||||
fn main() {
|
||||
println!("Hello, world!");
|
||||
}
|
@ -7,6 +7,7 @@
|
||||
#include "util/json_container.hpp"
|
||||
|
||||
#include <boost/format.hpp>
|
||||
#include <iostream>
|
||||
|
||||
namespace osrm::server::service
|
||||
{
|
||||
@ -30,11 +31,11 @@ std::string getWrongOptionHelp(const engine::api::NearestParameters ¶meters)
|
||||
return help;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
engine::Status NearestService::RunQuery(std::size_t prefix_length,
|
||||
std::string &query,
|
||||
osrm::engine::api::ResultT &result)
|
||||
{
|
||||
std::cout << "running query: " << query << "\n";
|
||||
result = util::json::Object();
|
||||
auto &json_result = std::get<util::json::Object>(result);
|
||||
|
||||
|
51
tests/common/cli_arguments.rs
Normal file
51
tests/common/cli_arguments.rs
Normal file
@ -0,0 +1,51 @@
|
||||
use std::fmt::Display;
|
||||
|
||||
use clap::Parser;
|
||||
|
||||
#[derive(clap::ValueEnum, Clone, Default, Debug)]
|
||||
pub enum LoadMethod {
|
||||
Mmap,
|
||||
#[default]
|
||||
Datastore,
|
||||
Directly,
|
||||
}
|
||||
impl Display for LoadMethod {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
let result = match self {
|
||||
LoadMethod::Mmap => "mmap",
|
||||
LoadMethod::Datastore => "datastore",
|
||||
LoadMethod::Directly => "directly",
|
||||
};
|
||||
write!(f, "{result}")
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(clap::ValueEnum, Clone, Default, Debug)]
|
||||
pub enum RoutingAlgorithm {
|
||||
#[default]
|
||||
Ch,
|
||||
Mld,
|
||||
}
|
||||
|
||||
impl Display for RoutingAlgorithm {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
let result = match self {
|
||||
RoutingAlgorithm::Ch => "ch",
|
||||
RoutingAlgorithm::Mld => "mld",
|
||||
};
|
||||
write!(f, "{result}")
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: move to external file
|
||||
#[derive(Parser, Debug)]
|
||||
#[command(version, about, long_about = None)]
|
||||
pub struct Args {
|
||||
// underlying memory storage
|
||||
#[arg(short, default_value_t = LoadMethod::Datastore)]
|
||||
memory: LoadMethod,
|
||||
|
||||
// Number of times to greet
|
||||
#[arg(short, default_value_t = RoutingAlgorithm::Ch)]
|
||||
p: RoutingAlgorithm,
|
||||
}
|
17
tests/common/comparison.rs
Normal file
17
tests/common/comparison.rs
Normal file
@ -0,0 +1,17 @@
|
||||
#[derive(Debug)]
|
||||
pub enum Offset {
|
||||
Absolute(f64),
|
||||
Percentage(f64),
|
||||
}
|
||||
|
||||
// #[cfg(test)]
|
||||
// mod tests {
|
||||
// use crate::extract_number_and_offset;
|
||||
|
||||
// #[test]
|
||||
// fn extract_number_and_offset() {
|
||||
// let (value, result) = extract_number_and_offset("m", "300 +- 1m");
|
||||
// assert_eq!(value, 300.);
|
||||
// assert_eq!(offset, 1);
|
||||
// }
|
||||
// }
|
101
tests/common/dot_writer.rs
Normal file
101
tests/common/dot_writer.rs
Normal file
@ -0,0 +1,101 @@
|
||||
use colored::Colorize;
|
||||
use cucumber::{cli, event, parser, Event};
|
||||
use std::{
|
||||
io::{self, Write},
|
||||
time::Instant,
|
||||
};
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
pub struct DotWriter {
|
||||
scenarios_started: usize,
|
||||
scenarios_failed: usize,
|
||||
scenarios_finished: usize,
|
||||
features_started: usize,
|
||||
features_finished: usize,
|
||||
step_started: usize,
|
||||
step_failed: usize,
|
||||
step_passed: usize,
|
||||
step_skipped: usize,
|
||||
start_time: Option<Instant>,
|
||||
}
|
||||
|
||||
impl<W: 'static> cucumber::Writer<W> for DotWriter {
|
||||
type Cli = cli::Empty; // we provide no CLI options
|
||||
|
||||
async fn handle_event(&mut self, ev: parser::Result<Event<event::Cucumber<W>>>, _: &Self::Cli) {
|
||||
let green_dot = ".".green();
|
||||
let cyan_dash = "-".cyan();
|
||||
let red_cross = "X".red();
|
||||
match ev {
|
||||
Ok(Event { value, .. }) => match value {
|
||||
event::Cucumber::Feature(_feature, ev) => match ev {
|
||||
event::Feature::Started => {
|
||||
self.features_started += 1;
|
||||
print!("{green_dot}")
|
||||
}
|
||||
event::Feature::Scenario(_scenario, ev) => match ev.event {
|
||||
event::Scenario::Started => {
|
||||
self.scenarios_started += 1;
|
||||
print!("{green_dot}")
|
||||
}
|
||||
event::Scenario::Step(_step, ev) => match ev {
|
||||
event::Step::Started => {
|
||||
self.step_started += 1;
|
||||
print!("{green_dot}")
|
||||
}
|
||||
event::Step::Passed(..) => {
|
||||
self.step_passed += 1;
|
||||
print!("{green_dot}")
|
||||
}
|
||||
event::Step::Skipped => {
|
||||
self.step_skipped += 1;
|
||||
print!("{cyan_dash}")
|
||||
}
|
||||
event::Step::Failed(_, _, _, _err) => {
|
||||
self.step_failed += 1;
|
||||
print!("{red_cross}")
|
||||
}
|
||||
},
|
||||
event::Scenario::Hook(_, _) => {}
|
||||
event::Scenario::Background(_, _) => {}
|
||||
event::Scenario::Log(_) => {}
|
||||
event::Scenario::Finished => {
|
||||
self.scenarios_finished += 1;
|
||||
}
|
||||
},
|
||||
event::Feature::Rule(_, _) => {}
|
||||
event::Feature::Finished => {
|
||||
self.features_finished += 1;
|
||||
}
|
||||
},
|
||||
event::Cucumber::Finished => {
|
||||
println!();
|
||||
let f = format!("{} failed", self.scenarios_failed).red();
|
||||
let p = format!("{} passed", self.scenarios_finished).green();
|
||||
println!("{} scenarios ({f}, {p})", self.scenarios_started);
|
||||
let f = format!("{} failed", self.step_failed).red();
|
||||
let s = format!("{} skipped", self.step_skipped).cyan();
|
||||
let p = format!("{} passed", self.step_passed).green();
|
||||
println!("{} steps ({f}, {s}, {p})", self.step_started);
|
||||
|
||||
let elapsed = Instant::now() - self.start_time.unwrap();
|
||||
let minutes = elapsed.as_secs() / 60;
|
||||
let seconds = (elapsed.as_millis() % 60_000) as f64 / 1000.;
|
||||
println!("{}m{}s", minutes, seconds);
|
||||
}
|
||||
event::Cucumber::ParsingFinished {
|
||||
features: _,
|
||||
rules: _,
|
||||
scenarios: _,
|
||||
steps: _,
|
||||
parser_errors: _,
|
||||
} => {}
|
||||
event::Cucumber::Started => {
|
||||
self.start_time = Some(Instant::now());
|
||||
}
|
||||
},
|
||||
Err(e) => println!("Error: {e}"),
|
||||
}
|
||||
let _ = io::stdout().flush();
|
||||
}
|
||||
}
|
24
tests/common/f64_utils.rs
Normal file
24
tests/common/f64_utils.rs
Normal file
@ -0,0 +1,24 @@
|
||||
use super::comparison::Offset;
|
||||
|
||||
pub fn approx_equal(a: f64, b: f64, dp: u8) -> bool {
|
||||
let p = 10f64.powi(-(dp as i32));
|
||||
(a - b).abs() < p
|
||||
}
|
||||
|
||||
fn aprox_equal_within_percentage_range(actual: f64, expectation: f64, percentage: f64) -> bool {
|
||||
assert!(percentage.is_sign_positive() && percentage <= 100.);
|
||||
let factor = 0.01 * percentage as f64;
|
||||
actual >= expectation - (factor * expectation) && actual <= expectation + (factor * expectation)
|
||||
}
|
||||
|
||||
fn approx_equal_within_offset_range(actual: f64, expectation: f64, offset: f64) -> bool {
|
||||
assert!(offset >= 0., "offset must be positive");
|
||||
actual >= expectation - offset && actual <= expectation + offset
|
||||
}
|
||||
|
||||
pub fn approximate_within_range(actual: f64, expectation: f64, offset: &Offset) -> bool {
|
||||
match offset {
|
||||
Offset::Absolute(a) => approx_equal_within_offset_range(actual, expectation, *a),
|
||||
Offset::Percentage(p) => aprox_equal_within_percentage_range(actual, expectation, *p),
|
||||
}
|
||||
}
|
20
tests/common/file_util.rs
Normal file
20
tests/common/file_util.rs
Normal file
@ -0,0 +1,20 @@
|
||||
use std::{
|
||||
fs::{self, File},
|
||||
io::Read,
|
||||
path::PathBuf,
|
||||
};
|
||||
|
||||
use log::debug;
|
||||
|
||||
pub fn get_file_as_byte_vec(path: &PathBuf) -> Vec<u8> {
|
||||
debug!("opening {path:?}");
|
||||
let mut f = File::open(path).expect("no file found");
|
||||
let metadata = fs::metadata(path).expect("unable to read metadata");
|
||||
let mut buffer = vec![0; metadata.len() as usize];
|
||||
match f.read(&mut buffer) {
|
||||
Ok(l) => assert_eq!(metadata.len() as usize, l, "data was not completely read"),
|
||||
Err(e) => panic!("Error: {e}"),
|
||||
}
|
||||
|
||||
buffer
|
||||
}
|
80
tests/common/hash_util.rs
Normal file
80
tests/common/hash_util.rs
Normal file
@ -0,0 +1,80 @@
|
||||
use std::{env, fs, path::PathBuf};
|
||||
|
||||
use log::debug;
|
||||
|
||||
use crate::common::{
|
||||
file_util::get_file_as_byte_vec, lexicographic_file_walker::LexicographicFileWalker,
|
||||
};
|
||||
|
||||
pub fn md5_of_osrm_executables() -> chksum_md5::MD5 {
|
||||
// create OSRM digest before any tests are executed since cucumber-rs doesn't have @beforeAll
|
||||
let exe_path = env::current_exe().expect("failed to get current exe path");
|
||||
let path = exe_path
|
||||
.ancestors()
|
||||
.find(|p| p.ends_with("target"))
|
||||
.expect("compiled cucumber test executable resides in a directory tree with the root name 'target'")
|
||||
.parent().unwrap();
|
||||
// TODO: Remove after migration to Rust build dir
|
||||
let build_path = path.join("build");
|
||||
// TODO: Remove after migration to Rust build dir
|
||||
let mut dependencies = Vec::new();
|
||||
|
||||
// FIXME: the following iterator gymnastics port the exact order and behavior of the JavaScript implementation
|
||||
let names = [
|
||||
"osrm-extract",
|
||||
"osrm-contract",
|
||||
"osrm-customize",
|
||||
"osrm-partition",
|
||||
"osrm_extract",
|
||||
"osrm_contract",
|
||||
"osrm_customize",
|
||||
"osrm_partition",
|
||||
];
|
||||
|
||||
let files: Vec<PathBuf> = fs::read_dir(build_path)
|
||||
.unwrap()
|
||||
.filter_map(|e| e.ok())
|
||||
.map(|dir_entry| dir_entry.path())
|
||||
.collect();
|
||||
|
||||
let iter = names.iter().map(|name| {
|
||||
files
|
||||
.iter()
|
||||
.find(|path_buf| {
|
||||
path_buf
|
||||
.file_stem()
|
||||
.unwrap()
|
||||
.to_str()
|
||||
.unwrap()
|
||||
.contains(name)
|
||||
})
|
||||
.cloned()
|
||||
.expect("file exists and is usable")
|
||||
});
|
||||
|
||||
dependencies.extend(iter);
|
||||
|
||||
let profiles_path = path.join("profiles");
|
||||
debug!("{profiles_path:?}");
|
||||
|
||||
dependencies.extend(
|
||||
LexicographicFileWalker::new(&profiles_path)
|
||||
.filter(|pb| !pb.to_str().unwrap().contains("examples"))
|
||||
.filter(|pathbuf| match pathbuf.extension() {
|
||||
Some(ext) => ext.to_str().unwrap() == "lua",
|
||||
None => false,
|
||||
}),
|
||||
);
|
||||
let mut md5 = chksum_md5::new();
|
||||
debug!("md5: {}", md5.digest().to_hex_lowercase());
|
||||
|
||||
for path_buf in dependencies {
|
||||
let data = get_file_as_byte_vec(&path_buf);
|
||||
if data.is_empty() {
|
||||
continue;
|
||||
}
|
||||
md5.update(data);
|
||||
// debug!("md5: {}", md5.digest().to_hex_lowercase());
|
||||
}
|
||||
md5
|
||||
}
|
24
tests/common/http_request.rs
Normal file
24
tests/common/http_request.rs
Normal file
@ -0,0 +1,24 @@
|
||||
// struct to keep state agent, profile, host, etc
|
||||
// functions to make nearest, route, etc calls
|
||||
// fn nearest(arg1, ... argn) -> NearestResponse
|
||||
|
||||
// use std::{path::Path, time::Duration};
|
||||
|
||||
// use ureq::{Agent, AgentBuilder};
|
||||
|
||||
// pub struct HttpRequest {
|
||||
// agent: Agent,
|
||||
// }
|
||||
|
||||
// impl HttpRequest {
|
||||
// // pub fn fetch_to_file(url: &str, output: &Path) -> Result<()> {}
|
||||
|
||||
// pub fn new() -> Self {
|
||||
// let agent = AgentBuilder::new()
|
||||
// .timeout_read(Duration::from_secs(5))
|
||||
// .timeout_write(Duration::from_secs(5))
|
||||
// .build();
|
||||
|
||||
// Self { agent }
|
||||
// }
|
||||
// }
|
55
tests/common/lexicographic_file_walker.rs
Normal file
55
tests/common/lexicographic_file_walker.rs
Normal file
@ -0,0 +1,55 @@
|
||||
use std::{
|
||||
collections::VecDeque,
|
||||
fs,
|
||||
path::{Path, PathBuf},
|
||||
};
|
||||
|
||||
// TODO: port into toolbox-rs
|
||||
pub struct LexicographicFileWalker {
|
||||
dirs: VecDeque<PathBuf>,
|
||||
files: VecDeque<PathBuf>,
|
||||
}
|
||||
|
||||
impl LexicographicFileWalker {
|
||||
pub fn new(path: &Path) -> Self {
|
||||
let mut dirs = VecDeque::new();
|
||||
|
||||
if path.is_dir() {
|
||||
dirs.push_back(path.to_path_buf());
|
||||
}
|
||||
|
||||
Self {
|
||||
dirs,
|
||||
files: VecDeque::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Iterator for LexicographicFileWalker {
|
||||
type Item = PathBuf;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
if self.dirs.is_empty() && self.files.is_empty() {
|
||||
return None;
|
||||
}
|
||||
while self.files.is_empty() && !self.dirs.is_empty() {
|
||||
assert!(!self.dirs.is_empty());
|
||||
let current_dir = self.dirs.pop_front().unwrap();
|
||||
let mut temp_dirs = Vec::new();
|
||||
|
||||
for entry in fs::read_dir(current_dir).unwrap() {
|
||||
let entry = entry.unwrap();
|
||||
let path = entry.path();
|
||||
if path.is_dir() {
|
||||
temp_dirs.push(path.clone());
|
||||
} else {
|
||||
self.files.push_back(path.clone());
|
||||
}
|
||||
}
|
||||
self.files.make_contiguous().sort();
|
||||
temp_dirs.sort();
|
||||
self.dirs.extend(temp_dirs.into_iter());
|
||||
}
|
||||
self.files.pop_front()
|
||||
}
|
||||
}
|
68
tests/common/local_task.rs
Normal file
68
tests/common/local_task.rs
Normal file
@ -0,0 +1,68 @@
|
||||
use std::{
|
||||
io::{BufRead, BufReader},
|
||||
process::{Child, Command, Stdio},
|
||||
};
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
pub struct LocalTask {
|
||||
ready: bool,
|
||||
command: String,
|
||||
arguments: Vec<String>,
|
||||
child: Option<Child>,
|
||||
}
|
||||
|
||||
impl LocalTask {
|
||||
pub fn new(command: String) -> Self {
|
||||
Self {
|
||||
ready: false,
|
||||
command: command,
|
||||
arguments: Vec::new(),
|
||||
child: None,
|
||||
}
|
||||
}
|
||||
pub fn is_ready(&self) -> bool {
|
||||
// TODO: also check that process is running
|
||||
self.ready
|
||||
}
|
||||
pub fn arg(mut self, argument: &str) -> Self {
|
||||
self.arguments.push(argument.into());
|
||||
self
|
||||
}
|
||||
|
||||
pub fn spawn_wait_till_ready(&mut self, ready_token: &str) {
|
||||
let mut command = &mut Command::new(&self.command);
|
||||
for argument in &self.arguments {
|
||||
command = command.arg(argument);
|
||||
}
|
||||
|
||||
match command.stdout(Stdio::piped()).spawn() {
|
||||
Ok(o) => self.child = Some(o),
|
||||
Err(e) => panic!("cannot spawn task: {e}"),
|
||||
}
|
||||
|
||||
if self.child.is_none() {
|
||||
return;
|
||||
}
|
||||
|
||||
if let Some(output) = &mut self.child.as_mut().unwrap().stdout {
|
||||
// implement with a timeout
|
||||
let mut reader = BufReader::new(output);
|
||||
let mut line = String::new();
|
||||
while let Ok(_count) = reader.read_line(&mut line) {
|
||||
// println!("count: {count} ->{line}");
|
||||
if line.contains(ready_token) {
|
||||
self.ready = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// impl Drop for LocalTask {
|
||||
// fn drop(&mut self) {
|
||||
// if let Err(e) = self.child.as_mut().expect("can't access child").kill() {
|
||||
// panic!("shutdown failed: {e}");
|
||||
// }
|
||||
// }
|
||||
// }
|
8
tests/common/location.rs
Normal file
8
tests/common/location.rs
Normal file
@ -0,0 +1,8 @@
|
||||
use serde::Deserialize;
|
||||
|
||||
#[derive(Clone, Copy, Debug, Default, Deserialize)]
|
||||
pub struct Location {
|
||||
// Note: The order is important since we derive Deserialize
|
||||
pub longitude: f64,
|
||||
pub latitude: f64,
|
||||
}
|
37
tests/common/mod.rs
Normal file
37
tests/common/mod.rs
Normal file
@ -0,0 +1,37 @@
|
||||
#![allow(clippy::derivable_impls, clippy::all)]
|
||||
extern crate flatbuffers;
|
||||
|
||||
pub mod cli_arguments;
|
||||
pub mod comparison;
|
||||
pub mod dot_writer;
|
||||
pub mod f64_utils;
|
||||
pub mod file_util;
|
||||
pub mod hash_util;
|
||||
pub mod http_request;
|
||||
pub mod lexicographic_file_walker;
|
||||
pub mod local_task;
|
||||
pub mod location;
|
||||
pub mod nearest_response;
|
||||
pub mod osm;
|
||||
pub mod osm_db;
|
||||
pub mod osrm_error;
|
||||
pub mod osrm_world;
|
||||
pub mod route_response;
|
||||
pub mod scenario_id;
|
||||
|
||||
// flatbuffer
|
||||
#[allow(dead_code, unused_imports)]
|
||||
#[path = "../../target/flatbuffers/fbresult_generated.rs"]
|
||||
pub mod fbresult_flatbuffers;
|
||||
#[allow(dead_code, unused_imports)]
|
||||
#[path = "../../target/flatbuffers/position_generated.rs"]
|
||||
pub mod position_flatbuffers;
|
||||
#[allow(dead_code, unused_imports)]
|
||||
#[path = "../../target/flatbuffers/route_generated.rs"]
|
||||
pub mod route_flatbuffers;
|
||||
#[allow(dead_code, unused_imports)]
|
||||
#[path = "../../target/flatbuffers/table_generated.rs"]
|
||||
pub mod table_flatbuffers;
|
||||
#[allow(dead_code, unused_imports)]
|
||||
#[path = "../../target/flatbuffers/waypoint_generated.rs"]
|
||||
pub mod waypoint_flatbuffers;
|
88
tests/common/nearest_response.rs
Normal file
88
tests/common/nearest_response.rs
Normal file
@ -0,0 +1,88 @@
|
||||
use super::location::Location;
|
||||
use crate::common::fbresult_flatbuffers::osrm::engine::api::fbresult::FBResult;
|
||||
use serde::Deserialize;
|
||||
|
||||
#[derive(Deserialize, Debug)]
|
||||
pub struct Waypoint {
|
||||
pub hint: String,
|
||||
pub nodes: Option<Vec<u64>>,
|
||||
pub distance: f32,
|
||||
pub name: String,
|
||||
location: Location,
|
||||
}
|
||||
|
||||
impl Waypoint {
|
||||
pub fn location(&self) -> &Location {
|
||||
&self.location
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug)]
|
||||
pub struct NearestResponse {
|
||||
pub code: String,
|
||||
pub waypoints: Vec<Waypoint>,
|
||||
pub data_version: Option<String>,
|
||||
}
|
||||
|
||||
impl NearestResponse {
|
||||
// TODO: the from_* functions should be a) into_. or b) implement From<_> trait
|
||||
pub fn from_json_reader(reader: impl std::io::Read) -> Self {
|
||||
let response = match serde_json::from_reader::<_, NearestResponse>(reader) {
|
||||
Ok(response) => response,
|
||||
Err(e) => panic!("parsing error {e}"),
|
||||
};
|
||||
response
|
||||
}
|
||||
|
||||
pub fn from_flatbuffer(mut reader: impl std::io::Read) -> Self {
|
||||
let mut buffer = Vec::new();
|
||||
if let Err(e) = reader.read_to_end(&mut buffer) {
|
||||
panic!("cannot read from strem: {e}");
|
||||
};
|
||||
let decoded: Result<FBResult, flatbuffers::InvalidFlatbuffer> =
|
||||
flatbuffers::root::<FBResult>(&buffer);
|
||||
let decoded: FBResult = match decoded {
|
||||
Ok(d) => d,
|
||||
Err(e) => panic!("Error during parsing: {e} {:?}", buffer),
|
||||
};
|
||||
let code = match decoded.code() {
|
||||
Some(e) => e.message().expect("code exists but is not unwrappable"),
|
||||
None => "",
|
||||
};
|
||||
let data_version = match decoded.data_version() {
|
||||
Some(s) => s,
|
||||
None => "",
|
||||
};
|
||||
|
||||
let waypoints = decoded
|
||||
.waypoints()
|
||||
.expect("waypoints should be at least an empty list")
|
||||
.iter()
|
||||
.map(|wp| {
|
||||
let hint = wp.hint().expect("hint is missing").to_string();
|
||||
let location = wp.location().expect("waypoint must have a location");
|
||||
let location = Location {
|
||||
latitude: location.latitude() as f64,
|
||||
longitude: location.longitude() as f64,
|
||||
};
|
||||
let nodes = wp.nodes().expect("waypoint mus have nodes");
|
||||
let nodes = Some(vec![nodes.first(), nodes.second()]);
|
||||
let distance = wp.distance();
|
||||
|
||||
Waypoint {
|
||||
hint,
|
||||
nodes,
|
||||
distance,
|
||||
name: "".into(),
|
||||
location,
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
|
||||
Self {
|
||||
code: code.into(),
|
||||
waypoints,
|
||||
data_version: Some(data_version.into()),
|
||||
}
|
||||
}
|
||||
}
|
143
tests/common/osm.rs
Normal file
143
tests/common/osm.rs
Normal file
@ -0,0 +1,143 @@
|
||||
use std::collections::HashMap;
|
||||
|
||||
use xml_builder::XMLElement;
|
||||
|
||||
use super::location::Location;
|
||||
|
||||
static OSM_USER: &str = "osrm";
|
||||
static OSM_TIMESTAMP: &str = "2000-01-01T00:00:00Z";
|
||||
static OSM_UID: &str = "1";
|
||||
|
||||
#[derive(Clone, Debug, Default)]
|
||||
pub struct OSMNode {
|
||||
pub id: u64,
|
||||
pub location: Location,
|
||||
pub tags: HashMap<String, String>,
|
||||
}
|
||||
|
||||
impl OSMNode {
|
||||
pub fn add_tag(&mut self, key: &str, value: &str) {
|
||||
if key.is_empty() || value.is_empty() {
|
||||
return;
|
||||
}
|
||||
self.tags.insert(key.into(), value.into());
|
||||
}
|
||||
|
||||
// pub fn set_id_(&mut self, id: u64) {
|
||||
// self.id = id;
|
||||
// }
|
||||
|
||||
// pub fn set_tags(&mut self, tags: HashMap<String, String>) {
|
||||
// self.tags = tags
|
||||
// }
|
||||
|
||||
pub fn to_xml(&self) -> XMLElement {
|
||||
let mut node = XMLElement::new("node");
|
||||
node.add_attribute("id", &self.id.to_string());
|
||||
node.add_attribute("version", "1");
|
||||
node.add_attribute("uid", OSM_UID);
|
||||
node.add_attribute("user", OSM_USER);
|
||||
node.add_attribute("timestamp", OSM_TIMESTAMP);
|
||||
node.add_attribute("lon", &format!("{:?}", self.location.longitude));
|
||||
node.add_attribute("lat", &format!("{:?}", self.location.latitude));
|
||||
|
||||
if !self.tags.is_empty() {
|
||||
for (key, value) in &self.tags {
|
||||
let mut tags = XMLElement::new("tag");
|
||||
tags.add_attribute("k", key);
|
||||
tags.add_attribute("v", value);
|
||||
node.add_child(tags).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
node
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Default)]
|
||||
pub struct OSMWay {
|
||||
pub id: u64,
|
||||
pub tags: HashMap<String, String>,
|
||||
pub nodes: Vec<OSMNode>,
|
||||
pub add_locations: bool,
|
||||
}
|
||||
|
||||
impl OSMWay {
|
||||
pub fn add_node(&mut self, node: OSMNode) {
|
||||
self.nodes.push(node);
|
||||
}
|
||||
|
||||
// pub fn set_tags(&mut self, tags: HashMap<String, String>) {
|
||||
// self.tags = tags;
|
||||
// }
|
||||
|
||||
pub fn add_tag(&mut self, key: &str, value: &str) {
|
||||
if key.is_empty() || value.is_empty() {
|
||||
return;
|
||||
}
|
||||
self.tags.insert(key.into(), value.into());
|
||||
}
|
||||
|
||||
pub fn to_xml(&self) -> XMLElement {
|
||||
let mut way = XMLElement::new("way");
|
||||
way.add_attribute("id", &self.id.to_string());
|
||||
way.add_attribute("version", "1");
|
||||
way.add_attribute("uid", OSM_UID);
|
||||
way.add_attribute("user", OSM_USER);
|
||||
way.add_attribute("timestamp", OSM_TIMESTAMP);
|
||||
|
||||
assert!(self.nodes.len() >= 2);
|
||||
|
||||
for node in &self.nodes {
|
||||
let mut nd = XMLElement::new("nd");
|
||||
nd.add_attribute("ref", &node.id.to_string());
|
||||
if self.add_locations {
|
||||
nd.add_attribute("lon", &format!("{:?}", node.location.longitude));
|
||||
nd.add_attribute("lat", &format!("{:?}", node.location.latitude));
|
||||
}
|
||||
way.add_child(nd).unwrap();
|
||||
}
|
||||
|
||||
if !self.tags.is_empty() {
|
||||
for (key, value) in &self.tags {
|
||||
let mut tags = XMLElement::new("tag");
|
||||
tags.add_attribute("k", key);
|
||||
tags.add_attribute("v", value);
|
||||
way.add_child(tags).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
way
|
||||
}
|
||||
}
|
||||
|
||||
// #[derive(Clone, Debug)]
|
||||
// struct Member {
|
||||
// id: u64,
|
||||
// member_type: String,
|
||||
// member_role: String,
|
||||
// }
|
||||
|
||||
// #[derive(Clone, Debug)]
|
||||
// struct OSMRelation {
|
||||
// id: u64,
|
||||
// osm_user: String,
|
||||
// osm_time_stamp: String,
|
||||
// osm_uid: String,
|
||||
// members: Vec<Member>,
|
||||
// tags: HashMap<String, String>,
|
||||
// }
|
||||
|
||||
// impl OSMRelation {
|
||||
// fn add_member(&mut self, member_type: String, id: u64, member_role: String) {
|
||||
// self.members.push(Member {
|
||||
// id,
|
||||
// member_type,
|
||||
// member_role,
|
||||
// });
|
||||
// }
|
||||
|
||||
// pub fn add_tag(&mut self, key: &str, value: &str) {
|
||||
// self.tags.insert(key.into(), value.into());
|
||||
// }
|
||||
// }
|
131
tests/common/osm_db.rs
Normal file
131
tests/common/osm_db.rs
Normal file
@ -0,0 +1,131 @@
|
||||
use super::osm::{OSMNode, OSMWay};
|
||||
use xml_builder::{XMLBuilder, XMLElement, XMLVersion};
|
||||
|
||||
// TODO: better error handling in XML creation
|
||||
#[derive(Debug, Default)]
|
||||
pub struct OSMDb {
|
||||
nodes: Vec<(String, OSMNode)>,
|
||||
ways: Vec<OSMWay>,
|
||||
// relations: Vec<OSMRelation>,
|
||||
}
|
||||
|
||||
impl OSMDb {
|
||||
pub fn add_node(&mut self, node: OSMNode) {
|
||||
let name = node.tags.get("name").unwrap();
|
||||
// assert!(
|
||||
// name.len() == 1,
|
||||
// "name needs to be of length 1, but was \"{name}\""
|
||||
// );
|
||||
self.nodes.push((name.clone(), node));
|
||||
}
|
||||
|
||||
pub fn find_node(&self, search_name: String) -> Option<&(String, OSMNode)> {
|
||||
// TODO: this is a linear search.
|
||||
self.nodes.iter().find(|(name, _node)| search_name == *name)
|
||||
}
|
||||
|
||||
pub fn add_way(&mut self, way: OSMWay) {
|
||||
self.ways.push(way);
|
||||
}
|
||||
|
||||
// pub fn add_relation(&mut self, relation: OSMRelation) {
|
||||
// self.relations.push(relation);
|
||||
// }
|
||||
|
||||
// pub fn clear(&mut self) {
|
||||
// self.nodes.clear();
|
||||
// self.ways.clear();
|
||||
// // self.relations.clear();
|
||||
// }
|
||||
|
||||
pub fn to_xml(&self) -> String {
|
||||
let mut xml = XMLBuilder::new()
|
||||
.version(XMLVersion::XML1_0)
|
||||
.encoding("UTF-8".into())
|
||||
.build();
|
||||
|
||||
let mut osm = XMLElement::new("osm");
|
||||
osm.add_attribute("generator", "osrm-test");
|
||||
osm.add_attribute("version", "0.6");
|
||||
|
||||
for (_, node) in &self.nodes {
|
||||
osm.add_child(node.to_xml()).unwrap();
|
||||
}
|
||||
|
||||
for way in &self.ways {
|
||||
osm.add_child(way.to_xml()).unwrap();
|
||||
}
|
||||
|
||||
xml.set_root_element(osm);
|
||||
|
||||
let mut writer: Vec<u8> = Vec::new();
|
||||
xml.generate(&mut writer).unwrap();
|
||||
String::from_utf8(writer).unwrap()
|
||||
}
|
||||
|
||||
// pub fn node_len(&self) -> usize {
|
||||
// self.nodes.len()
|
||||
// }
|
||||
// pub fn way_len(&self) -> usize {
|
||||
// self.ways.len()
|
||||
// }
|
||||
// pub fn relation_len(&self) -> usize {
|
||||
// self.relations.len()
|
||||
// }
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
|
||||
#[test]
|
||||
fn empty_db_by_default() {
|
||||
use super::*;
|
||||
let osm_db = OSMDb::default();
|
||||
assert_eq!(0, osm_db.node_len());
|
||||
assert_eq!(0, osm_db.way_len());
|
||||
// assert_eq!(0, osm_db.relation_len());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn osm_db_with_single_node() {
|
||||
use super::*;
|
||||
let mut osm_db = OSMDb::default();
|
||||
|
||||
let mut node1 = OSMNode {
|
||||
id: 123,
|
||||
location: Location {
|
||||
longitude: 8.9876,
|
||||
latitude: 50.1234,
|
||||
},
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
let mut node2 = OSMNode {
|
||||
id: 321,
|
||||
location: Location {
|
||||
longitude: 8.9876,
|
||||
latitude: 50.1234,
|
||||
},
|
||||
..Default::default()
|
||||
};
|
||||
node1.add_tag("name", "a");
|
||||
node2.add_tag("name", "b");
|
||||
osm_db.add_node(node1.clone());
|
||||
osm_db.add_node(node2.clone());
|
||||
|
||||
let mut way = OSMWay {
|
||||
id: 890,
|
||||
..Default::default()
|
||||
};
|
||||
way.nodes.push(node1);
|
||||
way.nodes.push(node2);
|
||||
|
||||
osm_db.add_way(way);
|
||||
|
||||
let actual = osm_db.to_xml();
|
||||
let expected = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<osm generator=\"osrm-test\" version=\"0.6\">\n\t<node id=\"123\" version=\"1.0\" user=\"osrm\" timestamp=\"2000-01-01T00:00:00Z\" lon=\"8.9876\" lat=\"50.1234\">\n\t\t<tag name=\"a\" />\n\t</node>\n\t<node id=\"321\" version=\"1.0\" user=\"osrm\" timestamp=\"2000-01-01T00:00:00Z\" lon=\"8.9876\" lat=\"50.1234\">\n\t\t<tag name=\"b\" />\n\t</node>\n\t<way id=\"890\" version=\"1\" uid=\"1\" user=\"osrm\" timestamp=\"2000-01-01T00:00:00Z\">\n\t\t<nd ref=\"123\" />\n\t\t<nd ref=\"321\" />\n\t</way>\n</osm>\n";
|
||||
|
||||
// println!("{actual}");
|
||||
assert_eq!(actual, expected);
|
||||
}
|
||||
}
|
17
tests/common/osrm_error.rs
Normal file
17
tests/common/osrm_error.rs
Normal file
@ -0,0 +1,17 @@
|
||||
use serde::Deserialize;
|
||||
|
||||
#[derive(Debug, Default, Deserialize)]
|
||||
pub struct OSRMError {
|
||||
pub code: String,
|
||||
pub message: String,
|
||||
}
|
||||
|
||||
impl OSRMError {
|
||||
pub fn from_json_reader(reader: impl std::io::Read) -> Self {
|
||||
let response = match serde_json::from_reader::<_, Self>(reader) {
|
||||
Ok(response) => response,
|
||||
Err(e) => panic!("parsing error {e}"),
|
||||
};
|
||||
response
|
||||
}
|
||||
}
|
335
tests/common/osrm_world.rs
Normal file
335
tests/common/osrm_world.rs
Normal file
@ -0,0 +1,335 @@
|
||||
use super::{
|
||||
nearest_response::NearestResponse,
|
||||
osm::{OSMNode, OSMWay},
|
||||
osm_db::OSMDb,
|
||||
osrm_error::OSRMError,
|
||||
route_response::RouteResponse,
|
||||
};
|
||||
use crate::{common::local_task::LocalTask, Location};
|
||||
use core::panic;
|
||||
use cucumber::World;
|
||||
use log::debug;
|
||||
use reqwest::StatusCode;
|
||||
use std::{
|
||||
collections::HashMap,
|
||||
fs::{create_dir_all, File},
|
||||
io::Write,
|
||||
path::PathBuf,
|
||||
time::Duration,
|
||||
};
|
||||
|
||||
const DEFAULT_ORIGIN: Location = Location {
|
||||
longitude: 1.0f64,
|
||||
latitude: 1.0f64,
|
||||
};
|
||||
const DEFAULT_GRID_SIZE: f64 = 100.;
|
||||
const WAY_SPACING: f64 = 100.;
|
||||
const DEFAULT_PROFILE: &str = "bicycle";
|
||||
|
||||
#[derive(Debug, World)]
|
||||
pub struct OSRMWorld {
|
||||
pub feature_path: Option<PathBuf>,
|
||||
pub scenario_id: String,
|
||||
pub feature_digest: String,
|
||||
pub osrm_digest: String,
|
||||
pub osm_id: u64,
|
||||
pub profile: String,
|
||||
|
||||
pub known_osm_nodes: HashMap<char, Location>,
|
||||
pub known_locations: HashMap<char, Location>,
|
||||
|
||||
pub osm_db: OSMDb,
|
||||
pub extraction_parameters: Vec<String>,
|
||||
|
||||
pub request_with_flatbuffers: bool,
|
||||
pub query_options: HashMap<String, String>,
|
||||
pub request_string: Option<String>,
|
||||
|
||||
pub grid_size: f64,
|
||||
pub origin: Location,
|
||||
pub way_spacing: f64,
|
||||
|
||||
task: LocalTask,
|
||||
client: reqwest::blocking::Client,
|
||||
}
|
||||
|
||||
impl Default for OSRMWorld {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
feature_path: Default::default(),
|
||||
scenario_id: Default::default(),
|
||||
feature_digest: Default::default(),
|
||||
osrm_digest: Default::default(),
|
||||
osm_id: Default::default(),
|
||||
profile: DEFAULT_PROFILE.into(),
|
||||
known_osm_nodes: Default::default(),
|
||||
known_locations: Default::default(),
|
||||
osm_db: Default::default(),
|
||||
extraction_parameters: Default::default(),
|
||||
request_with_flatbuffers: Default::default(),
|
||||
query_options: HashMap::from([
|
||||
// default parameters // TODO: check if necessary
|
||||
("steps".into(), "true".into()),
|
||||
("alternatives".into(), "false".into()),
|
||||
// ("annotations".into(), "true".into()),
|
||||
]),
|
||||
request_string: Default::default(),
|
||||
|
||||
grid_size: DEFAULT_GRID_SIZE,
|
||||
origin: DEFAULT_ORIGIN,
|
||||
way_spacing: WAY_SPACING,
|
||||
task: LocalTask::default(),
|
||||
client: reqwest::blocking::Client::builder()
|
||||
.connect_timeout(Duration::from_secs(5))
|
||||
.no_proxy()
|
||||
.http1_only()
|
||||
.build()
|
||||
.unwrap(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl OSRMWorld {
|
||||
pub fn feature_cache_path(&self) -> PathBuf {
|
||||
let full_path = self.feature_path.clone().unwrap();
|
||||
let path = full_path
|
||||
.ancestors()
|
||||
.find(|p| p.ends_with("features"))
|
||||
.expect(".feature files reside in a directory tree with the root name 'features'");
|
||||
|
||||
let suffix = full_path.strip_prefix(path).unwrap();
|
||||
let path = path.parent().unwrap();
|
||||
debug!("suffix: {suffix:?}");
|
||||
let cache_path = path
|
||||
.join("test")
|
||||
.join("cache")
|
||||
.join(suffix)
|
||||
.join(&self.feature_digest);
|
||||
|
||||
debug!("{cache_path:?}");
|
||||
if !cache_path.exists() {
|
||||
create_dir_all(&cache_path).expect("cache path could not be created");
|
||||
} else {
|
||||
debug!("not creating cache dir");
|
||||
}
|
||||
cache_path
|
||||
}
|
||||
|
||||
pub fn routed_path(&self) -> PathBuf {
|
||||
let full_path = self.feature_path.clone().unwrap();
|
||||
let path = full_path
|
||||
.ancestors()
|
||||
.find(|p| p.ends_with("features"))
|
||||
.expect(".feature files reside in a directory tree with the root name 'features'");
|
||||
let routed_path = path
|
||||
.parent()
|
||||
.expect("cannot get parent path")
|
||||
.join("build")
|
||||
.join("osrm-routed");
|
||||
assert!(routed_path.exists(), "osrm-routed binary not found");
|
||||
routed_path
|
||||
}
|
||||
|
||||
pub fn set_scenario_specific_paths_and_digests(&mut self, path: Option<PathBuf>) {
|
||||
self.feature_path.clone_from(&path);
|
||||
|
||||
let file = File::open(path.clone().unwrap())
|
||||
.unwrap_or_else(|_| panic!("filesystem broken? can't open file {:?}", path));
|
||||
self.feature_digest = chksum_md5::chksum(file)
|
||||
.expect("md5 could not be computed")
|
||||
.to_hex_lowercase();
|
||||
}
|
||||
|
||||
pub fn make_osm_id(&mut self) -> u64 {
|
||||
// number implicitly starts a 1. This is in line with previous implementations
|
||||
self.osm_id += 1;
|
||||
self.osm_id
|
||||
}
|
||||
|
||||
pub fn add_osm_node(&mut self, name: char, location: Location, id: Option<u64>) {
|
||||
if self.known_osm_nodes.contains_key(&name) {
|
||||
panic!("duplicate node: {name}");
|
||||
}
|
||||
let id = match id {
|
||||
Some(id) => id,
|
||||
None => self.make_osm_id(),
|
||||
};
|
||||
let node = OSMNode {
|
||||
id,
|
||||
location,
|
||||
tags: HashMap::from([("name".to_string(), name.to_string())]),
|
||||
};
|
||||
|
||||
self.known_osm_nodes.insert(name, location);
|
||||
self.osm_db.add_node(node);
|
||||
}
|
||||
|
||||
pub fn add_osm_way(&mut self, way: OSMWay) {
|
||||
way.nodes.iter().for_each(|node| {
|
||||
self.osm_db.add_node(node.clone());
|
||||
});
|
||||
|
||||
self.osm_db.add_way(way);
|
||||
}
|
||||
|
||||
pub fn get_location(&self, name: char) -> Location {
|
||||
*match name {
|
||||
// TODO: move lookup to world
|
||||
'0'..='9' => self
|
||||
.known_locations
|
||||
.get(&name)
|
||||
.expect("test case specifies unknown location: {name}"),
|
||||
'a'..='z' => self
|
||||
.known_osm_nodes
|
||||
.get(&name)
|
||||
.expect("test case specifies unknown osm node: {name}"),
|
||||
_ => unreachable!("nodes have to be name in [0-9][a-z]"),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add_location(&mut self, name: char, location: Location) {
|
||||
if self.known_locations.contains_key(&name) {
|
||||
panic!("duplicate location: {name}")
|
||||
}
|
||||
self.known_locations.insert(name, location);
|
||||
}
|
||||
|
||||
pub fn write_osm_file(&self) {
|
||||
let osm_file = self
|
||||
.feature_cache_path()
|
||||
.join(self.scenario_id.clone() + ".osm");
|
||||
if !osm_file.exists() {
|
||||
debug!("writing to osm file: {osm_file:?}");
|
||||
let mut file = File::create(osm_file).expect("could not create OSM file");
|
||||
file.write_all(self.osm_db.to_xml().as_bytes())
|
||||
.expect("could not write OSM file");
|
||||
} else {
|
||||
debug!("not writing to OSM file {osm_file:?}");
|
||||
}
|
||||
}
|
||||
|
||||
pub fn extract_osm_file(&self) {
|
||||
let cache_path = self.artefact_cache_path();
|
||||
if cache_path.exists() {
|
||||
debug!("{cache_path:?} exists");
|
||||
} else {
|
||||
unimplemented!("{cache_path:?} does not exist");
|
||||
}
|
||||
}
|
||||
|
||||
pub fn artefact_cache_path(&self) -> PathBuf {
|
||||
self.feature_cache_path().join(&self.osrm_digest)
|
||||
}
|
||||
|
||||
fn start_routed(&mut self) {
|
||||
if self.task.is_ready() {
|
||||
// task running already
|
||||
return;
|
||||
}
|
||||
let data_path = self
|
||||
.artefact_cache_path()
|
||||
.join(self.scenario_id.to_owned() + ".osrm");
|
||||
|
||||
self.task = LocalTask::new(self.routed_path().to_string_lossy().into())
|
||||
.arg(data_path.to_str().expect("data path unwrappable"));
|
||||
self.task
|
||||
.spawn_wait_till_ready("running and waiting for requests");
|
||||
assert!(self.task.is_ready());
|
||||
}
|
||||
|
||||
pub fn nearest(
|
||||
&mut self,
|
||||
query_location: &Location,
|
||||
) -> Result<(u16, NearestResponse), (u16, OSRMError)> {
|
||||
self.start_routed();
|
||||
|
||||
let mut url = format!(
|
||||
"http://localhost:5000/nearest/v1/{}/{:?},{:?}",
|
||||
self.profile, query_location.longitude, query_location.latitude
|
||||
);
|
||||
if self.request_with_flatbuffers {
|
||||
url += ".flatbuffers";
|
||||
}
|
||||
|
||||
let response = match self.client.get(url).send() {
|
||||
Ok(response) => response,
|
||||
Err(e) => panic!("http error: {e}"),
|
||||
};
|
||||
let status = response.status();
|
||||
let bytes = &response.bytes().unwrap()[..];
|
||||
|
||||
match status {
|
||||
StatusCode::OK => {
|
||||
let response = match self.request_with_flatbuffers {
|
||||
true => NearestResponse::from_flatbuffer(bytes),
|
||||
false => NearestResponse::from_json_reader(bytes),
|
||||
};
|
||||
return Ok((status.as_u16(), response));
|
||||
}
|
||||
_ => {
|
||||
return Err((status.as_u16(), OSRMError::from_json_reader(bytes)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn route(
|
||||
&mut self,
|
||||
waypoints: &[Location],
|
||||
) -> Result<(u16, RouteResponse), (u16, OSRMError)> {
|
||||
self.start_routed();
|
||||
|
||||
let waypoint_string = waypoints
|
||||
.iter()
|
||||
.map(|location| format!("{:?},{:?}", location.longitude, location.latitude))
|
||||
.collect::<Vec<String>>()
|
||||
.join(";");
|
||||
|
||||
let url = match &self.request_string {
|
||||
None => {
|
||||
let mut url = format!(
|
||||
"http://127.0.0.1:5000/route/v1/{}/{waypoint_string}",
|
||||
self.profile,
|
||||
);
|
||||
if self.request_with_flatbuffers {
|
||||
url += ".flatbuffers";
|
||||
}
|
||||
if !self.query_options.is_empty() {
|
||||
let options = self
|
||||
.query_options
|
||||
.iter()
|
||||
.map(|(key, value)| format!("{key}={value}"))
|
||||
.collect::<Vec<String>>()
|
||||
.join("&");
|
||||
url += "?";
|
||||
url += &options;
|
||||
}
|
||||
url
|
||||
}
|
||||
Some(request_string) => {
|
||||
let temp = format!("http://127.0.0.1:5000/{}", request_string);
|
||||
temp
|
||||
}
|
||||
};
|
||||
// println!("url: {url}");
|
||||
let response = match self.client.get(url).send() {
|
||||
Ok(response) => response,
|
||||
Err(e) => panic!("http error: {e}"),
|
||||
};
|
||||
let status = &response.status();
|
||||
|
||||
match *status {
|
||||
StatusCode::OK => {
|
||||
let text = response.text().unwrap();
|
||||
let response = match self.request_with_flatbuffers {
|
||||
true => unimplemented!("RouteResponse::from_flatbuffer(body)"),
|
||||
false => RouteResponse::from_string(&text),
|
||||
};
|
||||
Ok((status.as_u16(), response))
|
||||
}
|
||||
_ => {
|
||||
let bytes = &response.bytes().unwrap()[..];
|
||||
return Err((status.as_u16(), OSRMError::from_json_reader(bytes)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
105
tests/common/route_response.rs
Normal file
105
tests/common/route_response.rs
Normal file
@ -0,0 +1,105 @@
|
||||
use serde::Deserialize;
|
||||
|
||||
use super::{location::Location, nearest_response::Waypoint};
|
||||
|
||||
#[derive(Deserialize, Default, Debug)]
|
||||
pub struct Maneuver {
|
||||
pub bearing_after: u64,
|
||||
pub bearing_before: u64,
|
||||
pub location: Location,
|
||||
pub modifier: Option<String>, // TODO: should be an enum
|
||||
pub r#type: String, // TODO: should be an enum
|
||||
pub exit: Option<u64>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize)]
|
||||
#[serde(untagged)]
|
||||
pub enum Geometry {
|
||||
A(String),
|
||||
B {
|
||||
coordinates: Vec<Location>,
|
||||
r#type: String,
|
||||
},
|
||||
}
|
||||
|
||||
impl Default for Geometry {
|
||||
fn default() -> Self {
|
||||
Geometry::A("".to_string())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Clone, Deserialize)]
|
||||
pub struct Intersection {
|
||||
pub r#in: Option<u64>,
|
||||
pub out: Option<u64>,
|
||||
pub entry: Vec<bool>,
|
||||
pub bearings: Vec<u64>,
|
||||
pub location: Location,
|
||||
pub classes: Option<Vec<String>>,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Default, Debug)]
|
||||
pub struct Step {
|
||||
pub geometry: Geometry,
|
||||
pub mode: String,
|
||||
pub maneuver: Maneuver,
|
||||
pub name: String,
|
||||
pub pronunciation: Option<String>,
|
||||
pub rotary_name: Option<String>,
|
||||
pub r#ref: Option<String>,
|
||||
pub duration: f64,
|
||||
pub distance: f64,
|
||||
pub intersections: Vec<Intersection>,
|
||||
}
|
||||
|
||||
// #[derive(Deserialize, Debug)]
|
||||
// pub struct Annotation {
|
||||
// pub nodes: Option<Vec<u64>>,
|
||||
// }
|
||||
|
||||
#[derive(Debug, Default, Deserialize)]
|
||||
pub struct Leg {
|
||||
pub summary: String,
|
||||
pub weight: f64,
|
||||
pub duration: f64,
|
||||
pub steps: Vec<Step>,
|
||||
pub distance: f64,
|
||||
// pub annotation: Option<Vec<Annotation>>,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug, Default)]
|
||||
pub struct Route {
|
||||
pub geometry: Geometry,
|
||||
pub weight: f64,
|
||||
pub duration: f64,
|
||||
pub legs: Vec<Leg>,
|
||||
pub weight_name: String,
|
||||
pub distance: f64,
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Deserialize)]
|
||||
pub struct RouteResponse {
|
||||
pub code: String,
|
||||
pub routes: Vec<Route>,
|
||||
pub waypoints: Option<Vec<Waypoint>>,
|
||||
pub data_version: Option<String>,
|
||||
}
|
||||
|
||||
impl RouteResponse {
|
||||
pub fn from_json_reader(reader: impl std::io::Read) -> Self {
|
||||
let response = match serde_json::from_reader::<_, Self>(reader) {
|
||||
Ok(response) => response,
|
||||
Err(e) => panic!("parsing error {e}"),
|
||||
};
|
||||
response
|
||||
}
|
||||
|
||||
pub fn from_string(input: &str) -> Self {
|
||||
// println!("{input}");
|
||||
let response = match serde_json::from_str(input) {
|
||||
Ok(response) => response,
|
||||
Err(e) => panic!("parsing error {e} => {input}"),
|
||||
};
|
||||
response
|
||||
}
|
||||
}
|
24
tests/common/scenario_id.rs
Normal file
24
tests/common/scenario_id.rs
Normal file
@ -0,0 +1,24 @@
|
||||
pub fn scenario_id(scenario: &cucumber::gherkin::Scenario) -> String {
|
||||
// ports the following logic:
|
||||
// let name = scenario.getName().toLowerCase().replace(/[/\-'=,():*#]/g, '')
|
||||
// .replace(/\s/g, '_').replace(/__/g, '_').replace(/\.\./g, '.')
|
||||
// .substring(0, 64);
|
||||
let mut s = scenario
|
||||
.name
|
||||
.to_ascii_lowercase()
|
||||
.replace(
|
||||
&['/', '\\', '-', '\'', '=', ',', '(', ')', ':', '*', '#'][..],
|
||||
"",
|
||||
)
|
||||
.chars()
|
||||
.map(|x| match x {
|
||||
' ' => '_',
|
||||
_ => x,
|
||||
})
|
||||
.collect::<String>()
|
||||
.replace('\\', "_")
|
||||
.replace("__", "_")
|
||||
.replace("..", ".");
|
||||
s.truncate(64);
|
||||
format!("{}_{}", scenario.position.line, s)
|
||||
}
|
1183
tests/cucumber.rs
Normal file
1183
tests/cucumber.rs
Normal file
File diff suppressed because it is too large
Load Diff
5
third_party/libosmium/.clang-tidy
vendored
5
third_party/libosmium/.clang-tidy
vendored
@ -1,5 +1,5 @@
|
||||
---
|
||||
Checks: '*,-abseil-string-find-str-contains,-altera-*,-android-cloexec-*,-bugprone-branch-clone,-bugprone-easily-swappable-parameters,-bugprone-macro-parentheses,-cert-dcl21-cpp,-cert-err58-cpp,-clang-analyzer-optin.cplusplus.VirtualCall,-cppcoreguidelines-avoid-c-arrays,-cppcoreguidelines-avoid-magic-numbers,-cppcoreguidelines-macro-usage,-cppcoreguidelines-non-private-member-variables-in-classes,-cppcoreguidelines-owning-memory,-cppcoreguidelines-pro-bounds-array-to-pointer-decay,-cppcoreguidelines-pro-bounds-constant-array-index,-cppcoreguidelines-pro-bounds-pointer-arithmetic,-cppcoreguidelines-pro-type-const-cast,-cppcoreguidelines-pro-type-reinterpret-cast,-cppcoreguidelines-pro-type-static-cast-downcast,-cppcoreguidelines-pro-type-vararg,-fuchsia-*,-google-runtime-references,-hicpp-avoid-c-arrays,-hicpp-invalid-access-moved,-hicpp-no-array-decay,-hicpp-no-assembler,-hicpp-vararg,-llvmlibc-*,-llvm-qualified-auto,-misc-macro-parentheses,-misc-non-private-member-variables-in-classes,-misc-no-recursion,-misc-unused-parameters,-modernize-avoid-c-arrays,-modernize-make-unique,-modernize-raw-string-literal,-modernize-use-trailing-return-type,-readability-avoid-const-params-in-decls,-readability-convert-member-functions-to-static,-readability-function-cognitive-complexity,-readability-identifier-length,-readability-implicit-bool-cast,-readability-implicit-bool-conversion,-readability-magic-numbers,-readability-qualified-auto'
|
||||
Checks: '*,-abseil-string-find-str-contains,-altera-*,-android-cloexec-*,-bugprone-branch-clone,-bugprone-easily-swappable-parameters,-bugprone-macro-parentheses,-cert-dcl21-cpp,-cert-err58-cpp,-clang-analyzer-optin.cplusplus.VirtualCall,-cppcoreguidelines-avoid-c-arrays,-cppcoreguidelines-avoid-magic-numbers,-cppcoreguidelines-macro-usage,-cppcoreguidelines-non-private-member-variables-in-classes,-cppcoreguidelines-owning-memory,-cppcoreguidelines-pro-bounds-array-to-pointer-decay,-cppcoreguidelines-pro-bounds-constant-array-index,-cppcoreguidelines-pro-bounds-pointer-arithmetic,-cppcoreguidelines-pro-type-const-cast,-cppcoreguidelines-pro-type-reinterpret-cast,-cppcoreguidelines-pro-type-static-cast-downcast,-cppcoreguidelines-pro-type-vararg,-fuchsia-*,-google-runtime-references,-hicpp-avoid-c-arrays,-hicpp-invalid-access-moved,-hicpp-no-array-decay,-hicpp-no-assembler,-hicpp-vararg,-llvmlibc-*,-llvm-qualified-auto,-misc-macro-parentheses,-misc-non-private-member-variables-in-classes,-misc-no-recursion,-misc-unused-parameters,-modernize-avoid-c-arrays,-modernize-make-unique,-modernize-raw-string-literal,-modernize-use-trailing-return-type,-readability-avoid-const-params-in-decls,-readability-function-cognitive-complexity,-readability-identifier-length,-readability-implicit-bool-cast,-readability-implicit-bool-conversion,-readability-magic-numbers,-readability-qualified-auto'
|
||||
#
|
||||
# For a list of check options, see:
|
||||
# https://clang.llvm.org/extra/clang-tidy/checks/list.html
|
||||
@ -137,9 +137,6 @@ Checks: '*,-abseil-string-find-str-contains,-altera-*,-android-cloexec-*,-bugpro
|
||||
# This is header only library, so the declaration and implementation are
|
||||
# often the same and we want to have the const in implementations.
|
||||
#
|
||||
# readability-convert-member-functions-to-static
|
||||
# Reports too many false positives
|
||||
#
|
||||
# readability-function-cognitive-complexity
|
||||
# Sometimes the large functions are needed.
|
||||
#
|
||||
|
@ -7,13 +7,7 @@ runs:
|
||||
run: mkdir build
|
||||
shell: bash
|
||||
- name: Configure
|
||||
run: |
|
||||
cmake -LA .. \
|
||||
-DCMAKE_TOOLCHAIN_FILE=C:/vcpkg/scripts/buildsystems/vcpkg.cmake \
|
||||
-DBUILD_HEADERS=OFF \
|
||||
-DBUILD_BENCHMARKS=ON \
|
||||
-DOsmium_DEBUG=TRUE \
|
||||
-DPROTOZERO_INCLUDE_DIR=${GITHUB_WORKSPACE}/../protozero/include
|
||||
run: cmake -LA .. -DCMAKE_TOOLCHAIN_FILE=C:/vcpkg/scripts/buildsystems/vcpkg.cmake -DBUILD_HEADERS=OFF -DBUILD_BENCHMARKS=ON -DOsmium_DEBUG=TRUE -DPROTOZERO_INCLUDE_DIR=${GITHUB_WORKSPACE}/../protozero/include
|
||||
shell: bash
|
||||
working-directory: build
|
||||
|
||||
|
@ -5,7 +5,7 @@ runs:
|
||||
steps:
|
||||
- name: Install packages
|
||||
run: |
|
||||
sudo apt-get update -qq
|
||||
sudo apt-get update -q
|
||||
sudo apt-get install -yq \
|
||||
doxygen \
|
||||
libboost-dev \
|
||||
@ -16,5 +16,8 @@ runs:
|
||||
libsparsehash-dev \
|
||||
ruby-json \
|
||||
spatialite-bin
|
||||
test "$CC" = clang-6.0 && sudo apt-get install -yq --no-install-suggests --no-install-recommends clang-6.0
|
||||
test "$CC" = clang-8 && sudo apt-get install -yq --no-install-suggests --no-install-recommends clang-8
|
||||
test "$CC" = clang-13 && sudo apt-get install -yq --no-install-suggests --no-install-recommends clang-13
|
||||
shell: bash
|
||||
|
||||
|
236
third_party/libosmium/.github/workflows/ci.yml
vendored
236
third_party/libosmium/.github/workflows/ci.yml
vendored
@ -3,13 +3,14 @@ name: CI
|
||||
on: [ push, pull_request ]
|
||||
|
||||
jobs:
|
||||
|
||||
linux:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 40
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
name: [Ubuntu-18, Ubuntu-20, Ubuntu-22, Debian-10, Debian-11, Debian-12, Debian-Testing, Debian-Experimental, Fedora-35, Fedora-36, Fedora-37, Fedora-38]
|
||||
name: [Ubuntu-18, Ubuntu-20, Ubuntu-21, Debian-9, Debian-10, Debian-11, Debian-Testing, Debian-Experimental, Fedora-34]
|
||||
build_type: [Dev]
|
||||
cpp_compiler: [g++]
|
||||
cpp_version: [c++11]
|
||||
@ -18,136 +19,122 @@ jobs:
|
||||
# Uses gcc 7.5.0, clang 6.0.0, cmake 3.10.2
|
||||
image: "ubuntu:18.04"
|
||||
ubuntu: 18
|
||||
installer: apt
|
||||
- name: Ubuntu-20
|
||||
# Uses gcc 9.3.0, clang 10.0.0, cmake 3.16.3
|
||||
image: "ubuntu:20.04"
|
||||
ubuntu: 20
|
||||
- name: Ubuntu-22
|
||||
# Uses gcc 12.2.0, clang 15.0.7, cmake 3.24.2
|
||||
image: "ubuntu:22.04"
|
||||
ubuntu: 22
|
||||
CXXFLAGS: -Wno-stringop-overread
|
||||
installer: apt
|
||||
- name: Ubuntu-21
|
||||
# Uses gcc 10.3.0, clang, 12.0.0, cmake 3.18.4
|
||||
image: "ubuntu:21.04"
|
||||
ubuntu: 21
|
||||
installer: apt
|
||||
- name: Debian-9
|
||||
# Uses gcc 6.3.0, clang 3.8.1, cmake 3.7.2
|
||||
image: "debian:stretch"
|
||||
installer: apt
|
||||
- name: Debian-10
|
||||
# Uses gcc 8.3.0, clang 7.0.1, cmake 3.13.4
|
||||
image: "debian:buster"
|
||||
installer: apt
|
||||
- name: Debian-11
|
||||
# Uses gcc 10.2.1, clang 11.0.1, cmake 3.18.4
|
||||
image: "debian:bullseye"
|
||||
installer: apt
|
||||
- name: Debian-11
|
||||
# Uses gcc 10.2.1, clang 11.0.1, cmake 3.18.4
|
||||
image: "debian:bullseye"
|
||||
installer: apt
|
||||
cpp_version: c++17
|
||||
- name: Debian-11
|
||||
# Uses gcc 10.2.1, clang 11.0.1, cmake 3.18.4
|
||||
image: "debian:bullseye"
|
||||
installer: apt
|
||||
cpp_version: c++20
|
||||
- name: Debian-11
|
||||
# Uses gcc 10.2.1, clang 11.0.1, cmake 3.18.4
|
||||
image: "debian:bullseye"
|
||||
c_compiler: clang
|
||||
cpp_compiler: clang++
|
||||
- name: Debian-11
|
||||
image: "debian:bullseye"
|
||||
installer: apt
|
||||
c_compiler: clang
|
||||
cpp_compiler: clang++
|
||||
cpp_version: c++17
|
||||
- name: Debian-11
|
||||
# Uses gcc 10.2.1, clang 11.0.1, cmake 3.18.4
|
||||
image: "debian:bullseye"
|
||||
installer: apt
|
||||
c_compiler: clang
|
||||
cpp_compiler: clang++
|
||||
cpp_version: c++20
|
||||
- name: Debian-11
|
||||
# Uses gcc 10.2.1, clang 11.0.1, cmake 3.18.4
|
||||
image: "debian:bullseye"
|
||||
installer: apt
|
||||
build_type: RelWithDebInfo
|
||||
- name: Debian-11
|
||||
# Uses gcc 10.2.1, clang 11.0.1, cmake 3.18.4
|
||||
image: "debian:bullseye"
|
||||
installer: apt
|
||||
c_compiler: clang
|
||||
cpp_compiler: clang++
|
||||
CXXFLAGS: -fsanitize=address,undefined -fno-sanitize-recover=all -fno-omit-frame-pointer
|
||||
LDFLAGS: -fsanitize=address,undefined
|
||||
- name: Debian-12
|
||||
# Uses gcc 12.2.0, clang 15.0.6, cmake 3.25.1
|
||||
image: "debian:bookworm"
|
||||
CXXFLAGS: -Wno-stringop-overread
|
||||
- name: Debian-12
|
||||
image: "debian:bookworm"
|
||||
cpp_version: c++17
|
||||
CXXFLAGS: -Wno-stringop-overread
|
||||
- name: Debian-12
|
||||
image: "debian:bookworm"
|
||||
cpp_version: c++20
|
||||
CXXFLAGS: -Wno-stringop-overread
|
||||
- name: Debian-12
|
||||
image: "debian:bookworm"
|
||||
- name: Debian-11
|
||||
# Uses gcc 10.2.1, clang 11.0.1, cmake 3.18.4
|
||||
image: "debian:bullseye"
|
||||
installer: apt
|
||||
c_compiler: clang
|
||||
cpp_compiler: clang++
|
||||
- name: Debian-12
|
||||
image: "debian:bookworm"
|
||||
c_compiler: clang
|
||||
cpp_compiler: clang++
|
||||
cpp_version: c++17
|
||||
- name: Debian-12
|
||||
image: "debian:bookworm"
|
||||
c_compiler: clang
|
||||
cpp_compiler: clang++
|
||||
cpp_version: c++20
|
||||
- name: Debian-12
|
||||
image: "debian:bookworm"
|
||||
build_type: RelWithDebInfo
|
||||
CXXFLAGS: -Wno-stringop-overread
|
||||
- name: Debian-12
|
||||
image: "debian:bookworm"
|
||||
c_compiler: clang
|
||||
cpp_compiler: clang++
|
||||
CXXFLAGS: -fsanitize=address,undefined -fno-sanitize-recover=all -fno-omit-frame-pointer
|
||||
LDFLAGS: -fsanitize=address,undefined
|
||||
CXXFLAGS: -fsanitize=address,undefined,integer -fno-sanitize-recover=all -fno-omit-frame-pointer
|
||||
LDFLAGS: -fsanitize=address,undefined,integer
|
||||
- name: Debian-Testing
|
||||
# Uses gcc 10.3.0, clang 11.1.0, cmake 3.21.3
|
||||
image: "debian:testing"
|
||||
CXXFLAGS: -Wno-stringop-overread -Wno-dangling-reference
|
||||
installer: apt
|
||||
CXXFLAGS: -Wno-stringop-overread
|
||||
- name: Debian-Testing
|
||||
# Uses gcc 10.3.0, clang 11.1.0, cmake 3.21.3
|
||||
image: "debian:testing"
|
||||
installer: apt
|
||||
c_compiler: clang
|
||||
cpp_compiler: clang++
|
||||
- name: Debian-Experimental
|
||||
# Uses gcc 11, clang 14, cmake 3.21.3
|
||||
image: "debian:experimental"
|
||||
CXXFLAGS: -Wno-stringop-overread -Wno-dangling-reference
|
||||
installer: apt
|
||||
CXXFLAGS: -Wno-stringop-overread
|
||||
- name: Debian-Experimental
|
||||
# Uses gcc 11, clang 14, cmake 3.21.3
|
||||
image: "debian:experimental"
|
||||
c_compiler: clang
|
||||
cpp_compiler: clang++
|
||||
installer: apt
|
||||
c_compiler: clang-14
|
||||
cpp_compiler: clang++-14
|
||||
- name: Fedora-34
|
||||
# Uses gcc 11.2.1, clang 12.0.1, cmake 3.20.5
|
||||
image: "fedora:34"
|
||||
installer: dnf
|
||||
CXXFLAGS: -Wno-stringop-overread
|
||||
- name: Fedora-35
|
||||
# Uses gcc 11.2.1, clang 12.0.1, cmake 3.20.5
|
||||
image: "fedora:35"
|
||||
installer: dnf
|
||||
CXXFLAGS: -Wno-stringop-overread
|
||||
- name: Fedora-36
|
||||
# Uses gcc 12.2.0, clang 14.0.5, cmake 3.24.2
|
||||
image: "fedora:36"
|
||||
CXXFLAGS: -Wno-stringop-overread
|
||||
- name: Fedora-37
|
||||
# Uses gcc 12.3.1, clang 15.0.7, cmake 3.26.4
|
||||
image: "fedora:37"
|
||||
CXXFLAGS: -Wno-stringop-overread
|
||||
- name: Fedora-38
|
||||
# Uses gcc 13.0.1, clang 16.0.5, cmake 3.26.4
|
||||
image: "fedora:38"
|
||||
CXXFLAGS: -Wno-stringop-overread -Wno-dangling-reference
|
||||
container:
|
||||
image: ${{ matrix.image }}
|
||||
env:
|
||||
LANG: en_US.UTF-8
|
||||
BUILD_TYPE: ${{ matrix.build_type }}
|
||||
CC: ${{ matrix.c_compiler }}
|
||||
CXX: ${{ matrix.cpp_compiler }}
|
||||
CXXFLAGS: ${{ matrix.CXXFLAGS }}
|
||||
LDFLAGS: ${{ matrix.LDFLAGS }}
|
||||
CC: ${{ matrix.c_compiler }}
|
||||
CXX: ${{ matrix.cpp_compiler }}
|
||||
CPP_VERSION: ${{ matrix.cpp_version }}
|
||||
WITH_PROJ: ON
|
||||
APT_LISTCHANGES_FRONTEND: none
|
||||
DEBIAN_FRONTEND: noninteractive
|
||||
steps:
|
||||
- name: Prepare container (apt)
|
||||
shell: bash
|
||||
if: startsWith(matrix.image, 'debian:') || startsWith(matrix.image, 'ubuntu:')
|
||||
run: |
|
||||
export APT_LISTCHANGES_FRONTEND=none
|
||||
export DEBIAN_FRONTEND=noninteractive
|
||||
apt-get update -qq
|
||||
apt-get install -yq \
|
||||
apt-get install -y \
|
||||
clang \
|
||||
cmake \
|
||||
doxygen \
|
||||
@ -167,13 +154,16 @@ jobs:
|
||||
ruby-json \
|
||||
spatialite-bin \
|
||||
zlib1g-dev
|
||||
shell: bash
|
||||
if: matrix.installer == 'apt'
|
||||
- name: Install compiler
|
||||
shell: bash
|
||||
run: |
|
||||
export APT_LISTCHANGES_FRONTEND=none
|
||||
export DEBIAN_FRONTEND=noninteractive
|
||||
apt-get install -y clang-14
|
||||
if: matrix.cpp_compiler == 'clang++-14'
|
||||
run: apt-get install -yq clang-14
|
||||
- name: Prepare container (dnf)
|
||||
shell: bash
|
||||
if: startsWith(matrix.image, 'fedora:')
|
||||
run: |
|
||||
dnf install --quiet --assumeyes \
|
||||
boost-devel \
|
||||
@ -195,7 +185,9 @@ jobs:
|
||||
sparsehash-devel \
|
||||
spatialite-tools \
|
||||
zlib-devel
|
||||
# Use v1 of checkout because v3 doesn't work with submodules
|
||||
shell: bash
|
||||
if: matrix.installer == 'dnf'
|
||||
# Use v1 of checkout because v2 doesn't work with submodules
|
||||
- uses: actions/checkout@v1
|
||||
with:
|
||||
submodules: true
|
||||
@ -205,23 +197,21 @@ jobs:
|
||||
- uses: ./.github/actions/ctest
|
||||
|
||||
ubuntu-latest:
|
||||
runs-on: ubuntu-22.04
|
||||
runs-on: ubuntu-20.04
|
||||
timeout-minutes: 40
|
||||
env:
|
||||
CC: clang-15
|
||||
CXX: clang++-15
|
||||
CC: clang-13
|
||||
CXX: clang++-13
|
||||
BUILD_TYPE: Dev
|
||||
WITH_PROJ: ON
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
submodules: true
|
||||
- name: Install new clang
|
||||
run: |
|
||||
wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | sudo tee /etc/apt/trusted.gpg.d/llvm-snapshot.asc
|
||||
sudo add-apt-repository 'deb http://apt.llvm.org/jammy/ llvm-toolchain-jammy-15 main'
|
||||
sudo apt-get update -qq
|
||||
sudo apt-get install -yq clang-15
|
||||
wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add -
|
||||
sudo add-apt-repository 'deb http://apt.llvm.org/focal/ llvm-toolchain-focal-13 main'
|
||||
shell: bash
|
||||
- uses: ./.github/actions/install-ubuntu
|
||||
- uses: ./.github/actions/install-protozero
|
||||
@ -229,27 +219,16 @@ jobs:
|
||||
- uses: ./.github/actions/build
|
||||
- uses: ./.github/actions/ctest
|
||||
|
||||
macos:
|
||||
macos10-dev:
|
||||
runs-on: macos-10.15
|
||||
timeout-minutes: 60
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os:
|
||||
- "macos-11"
|
||||
- "macos-12"
|
||||
- "macos-13"
|
||||
build_type: [Dev]
|
||||
include:
|
||||
- os: "macos-12"
|
||||
build_type: Release
|
||||
runs-on: ${{ matrix.os }}
|
||||
env:
|
||||
CC: clang
|
||||
CXX: clang++
|
||||
BUILD_TYPE: ${{ matrix.build_type }}
|
||||
BUILD_TYPE: Dev
|
||||
WITH_PROJ: OFF
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
submodules: true
|
||||
- uses: ./.github/actions/install-macos
|
||||
@ -258,17 +237,47 @@ jobs:
|
||||
- uses: ./.github/actions/build
|
||||
- uses: ./.github/actions/ctest
|
||||
|
||||
windows-minimal:
|
||||
timeout-minutes: 40
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os:
|
||||
- windows-2019
|
||||
- windows-2022
|
||||
runs-on: ${{ matrix.os }}
|
||||
macos11-dev:
|
||||
runs-on: macos-11
|
||||
timeout-minutes: 60
|
||||
env:
|
||||
CC: clang
|
||||
CXX: clang++
|
||||
BUILD_TYPE: Dev
|
||||
WITH_PROJ: OFF
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
submodules: true
|
||||
- uses: ./.github/actions/install-macos
|
||||
- uses: ./.github/actions/install-protozero
|
||||
- uses: ./.github/actions/cmake
|
||||
- uses: ./.github/actions/build
|
||||
- uses: ./.github/actions/ctest
|
||||
|
||||
macos11-release:
|
||||
runs-on: macos-11
|
||||
timeout-minutes: 60
|
||||
env:
|
||||
CC: clang
|
||||
CXX: clang++
|
||||
BUILD_TYPE: Release
|
||||
WITH_PROJ: OFF
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
submodules: true
|
||||
- uses: ./.github/actions/install-macos
|
||||
- uses: ./.github/actions/install-protozero
|
||||
- uses: ./.github/actions/cmake
|
||||
- uses: ./.github/actions/build
|
||||
- uses: ./.github/actions/ctest
|
||||
|
||||
windows-2019-minimal:
|
||||
runs-on: windows-2019
|
||||
timeout-minutes: 40
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
submodules: true
|
||||
- uses: ./.github/actions/install-windows
|
||||
@ -280,7 +289,7 @@ jobs:
|
||||
windows-2019-full:
|
||||
runs-on: windows-2019
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
submodules: true
|
||||
- uses: ./.github/actions/install-windows
|
||||
@ -292,3 +301,16 @@ jobs:
|
||||
- uses: ./.github/actions/build-windows
|
||||
- uses: ./.github/actions/ctest-windows
|
||||
|
||||
windows-2022-minimal:
|
||||
runs-on: windows-2022
|
||||
timeout-minutes: 40
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
submodules: true
|
||||
- uses: ./.github/actions/install-windows
|
||||
- uses: ./.github/actions/install-protozero
|
||||
- uses: ./.github/actions/cmake-windows
|
||||
- uses: ./.github/actions/build-windows
|
||||
- uses: ./.github/actions/ctest-windows
|
||||
|
||||
|
@ -3,6 +3,7 @@ name: clang-tidy
|
||||
on: workflow_dispatch
|
||||
|
||||
jobs:
|
||||
|
||||
clang-tidy:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
@ -13,9 +14,9 @@ jobs:
|
||||
- image: "debian:bullseye"
|
||||
clang: 11
|
||||
- image: "debian:testing"
|
||||
clang: 15
|
||||
clang: 12
|
||||
- image: "debian:experimental"
|
||||
clang: 15
|
||||
clang: 14
|
||||
container:
|
||||
image: ${{ matrix.image }}
|
||||
env:
|
||||
@ -24,29 +25,29 @@ jobs:
|
||||
CXX: clang++-${{ matrix.clang }}
|
||||
CPP_VERSION: c++11
|
||||
WITH_PROJ: ON
|
||||
APT_LISTCHANGES_FRONTEND: none
|
||||
DEBIAN_FRONTEND: noninteractive
|
||||
steps:
|
||||
- name: Prepare container (apt)
|
||||
run: |
|
||||
export APT_LISTCHANGES_FRONTEND=none
|
||||
export DEBIAN_FRONTEND=noninteractive
|
||||
apt-get update -qq
|
||||
apt-get install -yq \
|
||||
clang-${{ matrix.clang }} \
|
||||
clang-tidy-${{ matrix.clang }} \
|
||||
cmake \
|
||||
git \
|
||||
libboost-dev \
|
||||
libbz2-dev \
|
||||
libexpat1-dev \
|
||||
libgdal-dev \
|
||||
libgeos++-dev \
|
||||
liblz4-dev \
|
||||
libproj-dev \
|
||||
libsparsehash-dev \
|
||||
make \
|
||||
zlib1g-dev
|
||||
apt-get install -y \
|
||||
clang-${{ matrix.clang }} \
|
||||
clang-tidy-${{ matrix.clang }} \
|
||||
cmake \
|
||||
git \
|
||||
libboost-dev \
|
||||
libbz2-dev \
|
||||
libexpat1-dev \
|
||||
libgdal-dev \
|
||||
libgeos++-dev \
|
||||
liblz4-dev \
|
||||
libproj-dev \
|
||||
libsparsehash-dev \
|
||||
make \
|
||||
zlib1g-dev
|
||||
shell: bash
|
||||
# Use v1 of checkout because v3 doesn't work with submodules
|
||||
# Use v1 of checkout because v2 doesn't work with submodules
|
||||
- uses: actions/checkout@v1
|
||||
with:
|
||||
submodules: true
|
||||
@ -57,7 +58,7 @@ jobs:
|
||||
shell: bash
|
||||
working-directory: build
|
||||
- name: Upload Log
|
||||
uses: actions/upload-artifact@v3
|
||||
uses: actions/upload-artifact@v2
|
||||
if: always()
|
||||
with:
|
||||
name: clang-tidy-${{ matrix.clang }}-log
|
||||
|
53
third_party/libosmium/.ycm_extra_conf.py
vendored
Normal file
53
third_party/libosmium/.ycm_extra_conf.py
vendored
Normal file
@ -0,0 +1,53 @@
|
||||
#-----------------------------------------------------------------------------
|
||||
#
|
||||
# Configuration for YouCompleteMe Vim plugin
|
||||
#
|
||||
# https://valloric.github.io/YouCompleteMe/
|
||||
#
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
from os.path import realpath, dirname
|
||||
|
||||
basedir = dirname(realpath(__file__))
|
||||
|
||||
# some default flags
|
||||
# for more information install clang-3.2-doc package and
|
||||
# check UsersManual.html
|
||||
flags = [
|
||||
'-Werror',
|
||||
'-Wall',
|
||||
'-Wextra',
|
||||
'-pedantic',
|
||||
'-Wno-return-type',
|
||||
'-Wno-unused-parameter',
|
||||
'-Wno-unused-variable',
|
||||
|
||||
'-std=c++11',
|
||||
|
||||
# '-x' and 'c++' also required
|
||||
# use 'c' for C projects
|
||||
'-x',
|
||||
'c++',
|
||||
|
||||
# workaround for https://github.com/Valloric/YouCompleteMe/issues/303
|
||||
# also see https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=800618
|
||||
'-isystem',
|
||||
'/usr/lib/ycmd/clang_includes/',
|
||||
|
||||
# libosmium include dirs
|
||||
'-I%s/include' % basedir,
|
||||
'-I%s/test/include' % basedir,
|
||||
'-I%s/test/data-test/include' % basedir,
|
||||
|
||||
# include third party libraries
|
||||
'-I/usr/include/gdal',
|
||||
]
|
||||
|
||||
# youcompleteme is calling this function to get flags
|
||||
# You can also set database for flags. Check: JSONCompilationDatabase.html in
|
||||
# clang-3.2-doc package
|
||||
def FlagsForFile( filename ):
|
||||
return {
|
||||
'flags': flags,
|
||||
'do_cache': True
|
||||
}
|
36
third_party/libosmium/CHANGELOG.md
vendored
36
third_party/libosmium/CHANGELOG.md
vendored
@ -12,38 +12,6 @@ This project adheres to [Semantic Versioning](https://semver.org/).
|
||||
|
||||
### Fixed
|
||||
|
||||
## [2.20.0] - 2023-09-20
|
||||
|
||||
### Changed
|
||||
|
||||
* Optionally allow fractional seconds in timestamps in OSM files.
|
||||
* Enable `posix_fadvise` usage on FreeBSD.
|
||||
* Make parsing PBFs a bit less picky.
|
||||
* Various small code cleanups.
|
||||
|
||||
### Fixed
|
||||
|
||||
* Don't use class template arguments on `GeometryFactory` constructor
|
||||
definition.
|
||||
|
||||
## [2.19.0] - 2023-01-19
|
||||
|
||||
### Changed
|
||||
|
||||
* Mark RapidJSON support as deprecated.
|
||||
* Update included Catch to v2.13.10.
|
||||
* Remove deprecated BoolVector class.
|
||||
* Remove deprecated NWRIdSet class.
|
||||
* Remove deprecated AssemblerConfig constructor.
|
||||
* Print start of offending string in overlong string exception.
|
||||
* Implement `set_thread_name()` on FreeBSD.
|
||||
* Some small code cleanups.
|
||||
|
||||
### Fixed
|
||||
|
||||
* Fix return type in `MembersDatabaseCommon::count_not_removed()`.
|
||||
* Make bzip2 unit tests pass on musl-based systems.
|
||||
* Fix bug in members database test case.
|
||||
|
||||
## [2.18.0] - 2022-02-07
|
||||
|
||||
@ -1285,9 +1253,7 @@ long time. These will not be part of the next version of libosmium:
|
||||
Doxygen (up to version 1.8.8). This version contains a workaround to fix
|
||||
this.
|
||||
|
||||
[unreleased]: https://github.com/osmcode/libosmium/compare/v2.20.0...HEAD
|
||||
[2.20.0]: https://github.com/osmcode/libosmium/compare/v2.19.0...v2.20.0
|
||||
[2.19.0]: https://github.com/osmcode/libosmium/compare/v2.18.9...v2.19.0
|
||||
[unreleased]: https://github.com/osmcode/libosmium/compare/v2.18.0...HEAD
|
||||
[2.18.0]: https://github.com/osmcode/libosmium/compare/v2.17.3...v2.18.0
|
||||
[2.17.3]: https://github.com/osmcode/libosmium/compare/v2.17.2...v2.17.3
|
||||
[2.17.2]: https://github.com/osmcode/libosmium/compare/v2.17.1...v2.17.2
|
||||
|
4
third_party/libosmium/CMakeLists.txt
vendored
4
third_party/libosmium/CMakeLists.txt
vendored
@ -39,7 +39,7 @@ set(CMAKE_CONFIGURATION_TYPES "Debug;Release;RelWithDebInfo;MinSizeRel;Dev;Cover
|
||||
project(libosmium)
|
||||
|
||||
set(LIBOSMIUM_VERSION_MAJOR 2)
|
||||
set(LIBOSMIUM_VERSION_MINOR 20)
|
||||
set(LIBOSMIUM_VERSION_MINOR 18)
|
||||
set(LIBOSMIUM_VERSION_PATCH 0)
|
||||
|
||||
set(LIBOSMIUM_VERSION
|
||||
@ -427,7 +427,7 @@ endif()
|
||||
#
|
||||
#-----------------------------------------------------------------------------
|
||||
message(STATUS "Looking for clang-tidy")
|
||||
find_program(CLANG_TIDY NAMES clang-tidy clang-tidy-16 clang-tidy-15 clang-tidy-14 clang-tidy-13 clang-tidy-12 clang-tidy-11)
|
||||
find_program(CLANG_TIDY NAMES clang-tidy clang-tidy-14 clang-tidy-13 clang-tidy-12 clang-tidy-11)
|
||||
|
||||
if(CLANG_TIDY)
|
||||
message(STATUS "Looking for clang-tidy - found ${CLANG_TIDY}")
|
||||
|
@ -136,7 +136,8 @@ directory, some data tests in `test/osm-testdata` and tests of the examples in
|
||||
`test/examples`. They are built by the default cmake config. Run `ctest` to
|
||||
run them. We can always use more tests.
|
||||
|
||||
Tests are run automatically using Github Actions.
|
||||
Tests are run automatically using Github Actions (Linux/macOS) and Appveyor
|
||||
(Windows) services.
|
||||
|
||||
|
||||
## Documenting the code
|
||||
|
14
third_party/libosmium/README.md
vendored
14
third_party/libosmium/README.md
vendored
@ -7,6 +7,8 @@ A fast and flexible C++ library for working with OpenStreetMap data.
|
||||
Libosmium works on Linux, macOS and Windows.
|
||||
|
||||
[](https://github.com/osmcode/libosmium/actions)
|
||||
[](https://ci.appveyor.com/project/lonvia/libosmium-eq41p/branch/master)
|
||||
[](https://codecov.io/gh/osmcode/libosmium)
|
||||
[](https://repology.org/metapackage/libosmium)
|
||||
|
||||
Please see the [Libosmium manual](https://osmcode.org/libosmium/manual.html)
|
||||
@ -15,8 +17,9 @@ for more details than this README can provide.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
You need a C++11 compiler and standard C++ library. Osmium needs at least GCC
|
||||
4.8 or clang (LLVM) 3.4. (Some parts may work with older versions.)
|
||||
Because Libosmium uses many C++11 features you need a modern compiler and
|
||||
standard C++ library. Osmium needs at least GCC 4.8 or clang (LLVM) 3.4.
|
||||
(Some parts may work with older versions.)
|
||||
|
||||
Different parts of Libosmium (and the applications built on top of it) need
|
||||
different libraries. You DO NOT NEED to install all of them, just install those
|
||||
@ -85,6 +88,13 @@ See the
|
||||
for instructions.
|
||||
|
||||
|
||||
## Switching from the old Osmium
|
||||
|
||||
If you have been using the old version of Osmium at
|
||||
https://github.com/joto/osmium you might want to read about the [changes
|
||||
needed](https://osmcode.org/libosmium/manual.html#changes-from-old-versions-of-osmium).
|
||||
|
||||
|
||||
## License
|
||||
|
||||
Libosmium is available under the Boost Software License. See LICENSE.
|
||||
|
@ -47,7 +47,7 @@ int main(int argc, char* argv[]) {
|
||||
try {
|
||||
const std::string input_filename{argv[1]};
|
||||
|
||||
const osmium::memory::Buffer buffer{osmium::io::read_file(input_filename)};
|
||||
osmium::memory::Buffer buffer{osmium::io::read_file(input_filename)};
|
||||
|
||||
const auto& map_factory = osmium::index::MapFactory<osmium::unsigned_object_id_type, osmium::Location>::instance();
|
||||
|
||||
|
@ -18,12 +18,12 @@ int main(int argc, char* argv[]) {
|
||||
}
|
||||
|
||||
try {
|
||||
const std::string input_filename{argv[1]};
|
||||
const std::string output_filename{argv[2]};
|
||||
std::string input_filename{argv[1]};
|
||||
std::string output_filename{argv[2]};
|
||||
|
||||
osmium::io::Reader reader{input_filename};
|
||||
const osmium::io::File output_file{output_filename, "pbf"};
|
||||
const osmium::io::Header header;
|
||||
osmium::io::File output_file{output_filename, "pbf"};
|
||||
osmium::io::Header header;
|
||||
osmium::io::Writer writer{output_file, header, osmium::io::overwrite::allow};
|
||||
|
||||
while (osmium::memory::Buffer buffer = reader.read()) { // NOLINT(bugprone-use-after-move) Bug in clang-tidy https://bugs.llvm.org/show_bug.cgi?id=36516
|
||||
|
9
third_party/libosmium/build-appveyor.bat
vendored
9
third_party/libosmium/build-appveyor.bat
vendored
@ -24,11 +24,6 @@ IF %ERRORLEVEL% NEQ 0 GOTO ERROR
|
||||
|
||||
SET PATH=C:/projects/bzip2.v140.1.0.6.9/build/native/bin/x64/%config%;%PATH%
|
||||
|
||||
nuget install lz4 -Version 1.3.1.2
|
||||
IF %ERRORLEVEL% NEQ 0 GOTO ERROR
|
||||
|
||||
SET PATH=C:/projects/lz4.1.3.1.2/build/native/bin/x64/%config%;%PATH%
|
||||
|
||||
CD libosmium
|
||||
|
||||
ECHO config^: %config%
|
||||
@ -57,9 +52,7 @@ SET CMAKE_CMD=cmake .. -LA -G "Visual Studio 14 Win64" ^
|
||||
-DEXPAT_INCLUDE_DIR=C:/projects/expat.v140.2.2.5/build/native/include ^
|
||||
-DEXPAT_LIBRARY=C:/projects/expat.v140.2.2.5/build/native/lib/x64/%config%/libexpat%libpostfix%.lib ^
|
||||
-DBZIP2_INCLUDE_DIR=C:/projects/bzip2.v140.1.0.6.9/build/native/include ^
|
||||
-DBZIP2_LIBRARIES=C:/projects/bzip2.v140.1.0.6.9/build/native/lib/x64/%config%/libbz2%libpostfix%.lib ^
|
||||
-DLZ4_INCLUDE_DIR=C:/projects/lz4.1.3.1.2/build/native/include ^
|
||||
-DLZ4_LIBRARY=C:/projects/lz4.1.3.1.2/build/native/lib/x64/%config%/liblz4%libpostfix%.lib
|
||||
-DBZIP2_LIBRARIES=C:/projects/bzip2.v140.1.0.6.9/build/native/lib/x64/%config%/libbz2%libpostfix%.lib
|
||||
|
||||
ECHO calling^: %CMAKE_CMD%
|
||||
%CMAKE_CMD%
|
||||
|
3
third_party/libosmium/build-msys2.bat
vendored
3
third_party/libosmium/build-msys2.bat
vendored
@ -16,9 +16,8 @@ call C:\msys64\mingw64\bin\gem.cmd install json
|
||||
REM Workaround for problem with spatialite (see https://github.com/osmcode/libosmium/issues/262)
|
||||
copy /y C:\msys64\mingw64\bin\libreadline8.dll C:\msys64\mingw64\bin\libreadline7.dll
|
||||
|
||||
echo "Setting PROJ_LIB/DATA variable for correct PROJ.4 working"
|
||||
echo "Setting PROJ_LIB variable for correct PROJ.4 working"
|
||||
set PROJ_LIB=c:\msys64\mingw64\share\proj
|
||||
set PROJ_DATA=c:\msys64\mingw64\share\proj
|
||||
|
||||
set CXXFLAGS=-Wno-stringop-overflow
|
||||
|
||||
|
@ -74,8 +74,8 @@ class AmenityHandler : public osmium::handler::Handler {
|
||||
c.y += nr.lat();
|
||||
}
|
||||
|
||||
c.x /= static_cast<double>(nr_list.size());
|
||||
c.y /= static_cast<double>(nr_list.size());
|
||||
c.x /= nr_list.size();
|
||||
c.y /= nr_list.size();
|
||||
|
||||
return c;
|
||||
}
|
||||
|
@ -122,11 +122,11 @@ int main(int argc, char* argv[]) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
const osmium::io::File input_file{argv[2]};
|
||||
osmium::io::File input_file{argv[2]};
|
||||
|
||||
// Configuration for the multipolygon assembler. Here the default settings
|
||||
// are used, but you could change multiple settings.
|
||||
const osmium::area::Assembler::config_type assembler_config;
|
||||
osmium::area::Assembler::config_type assembler_config;
|
||||
|
||||
// Set up a filter matching only forests. This will be used to only build
|
||||
// areas with matching tags.
|
||||
|
@ -153,8 +153,8 @@ int main(int argc, char* argv[]) {
|
||||
}
|
||||
|
||||
// Get input and output file names from command line.
|
||||
const std::string input_file_name{argv[1]};
|
||||
const std::string output_file_name{argv[2]};
|
||||
std::string input_file_name{argv[1]};
|
||||
std::string output_file_name{argv[2]};
|
||||
|
||||
try {
|
||||
// Initialize Reader
|
||||
|
@ -68,7 +68,7 @@ int main(int argc, char* argv[]) {
|
||||
try {
|
||||
// The Reader is initialized here with an osmium::io::File, but could
|
||||
// also be directly initialized with a file name.
|
||||
const osmium::io::File input_file{argv[1]};
|
||||
osmium::io::File input_file{argv[1]};
|
||||
osmium::io::Reader reader{input_file};
|
||||
|
||||
// Create an instance of our own CountHandler and push the data from the
|
||||
@ -88,7 +88,7 @@ int main(int argc, char* argv[]) {
|
||||
// (though not this one) can use huge amounts of data. So checking actual
|
||||
// memore usage is often useful and can be done easily with this class.
|
||||
// (Currently only works on Linux, not macOS and Windows.)
|
||||
const osmium::MemoryUsage memory;
|
||||
osmium::MemoryUsage memory;
|
||||
|
||||
std::cout << "\nMemory used: " << memory.peak() << " MBytes\n";
|
||||
} catch (const std::exception& e) {
|
||||
|
@ -40,11 +40,11 @@ int main(int argc, char* argv[]) {
|
||||
}
|
||||
|
||||
// Get output file name from command line.
|
||||
const std::string output_file_name{argv[1]};
|
||||
std::string output_file_name{argv[1]};
|
||||
|
||||
// If output file name is "-", this means STDOUT. Set the OPL file type
|
||||
// in this case. Otherwise take the file type from the file name suffix.
|
||||
const osmium::io::File output_file{output_file_name, output_file_name == "-" ? ".opl" : ""};
|
||||
osmium::io::File output_file{output_file_name, output_file_name == "-" ? ".opl" : ""};
|
||||
|
||||
try {
|
||||
// Create a buffer where all objects will live. Use a sensible initial
|
||||
|
@ -43,7 +43,7 @@ int main(int argc, char* argv[]) {
|
||||
// Get entity types from command line if there is a 2nd argument.
|
||||
if (argc == 3) {
|
||||
read_types = osmium::osm_entity_bits::nothing;
|
||||
const std::string types = argv[2];
|
||||
std::string types = argv[2];
|
||||
if (types.find('n') != std::string::npos) {
|
||||
read_types |= osmium::osm_entity_bits::node;
|
||||
}
|
||||
|
@ -165,31 +165,31 @@ int main(int argc, char* argv[]) {
|
||||
reader.close();
|
||||
|
||||
// Write out node, way, and relation offset indexes to disk.
|
||||
const IndexFile nodes_idx{output_dir + "/nodes.idx"};
|
||||
IndexFile nodes_idx{output_dir + "/nodes.idx"};
|
||||
node_index.dump_as_list(nodes_idx.fd());
|
||||
|
||||
const IndexFile ways_idx{output_dir + "/ways.idx"};
|
||||
IndexFile ways_idx{output_dir + "/ways.idx"};
|
||||
way_index.dump_as_list(ways_idx.fd());
|
||||
|
||||
const IndexFile relations_idx{output_dir + "/relations.idx"};
|
||||
IndexFile relations_idx{output_dir + "/relations.idx"};
|
||||
relation_index.dump_as_list(relations_idx.fd());
|
||||
|
||||
// Sort the maps (so later binary search will work on them) and write
|
||||
// them to disk.
|
||||
map_node2way.sort();
|
||||
const IndexFile node2way_idx{output_dir + "/node2way.map"};
|
||||
IndexFile node2way_idx{output_dir + "/node2way.map"};
|
||||
map_node2way.dump_as_list(node2way_idx.fd());
|
||||
|
||||
map_node2relation.sort();
|
||||
const IndexFile node2relation_idx{output_dir + "/node2rel.map"};
|
||||
IndexFile node2relation_idx{output_dir + "/node2rel.map"};
|
||||
map_node2relation.dump_as_list(node2relation_idx.fd());
|
||||
|
||||
map_way2relation.sort();
|
||||
const IndexFile way2relation_idx{output_dir + "/way2rel.map"};
|
||||
IndexFile way2relation_idx{output_dir + "/way2rel.map"};
|
||||
map_way2relation.dump_as_list(way2relation_idx.fd());
|
||||
|
||||
map_relation2relation.sort();
|
||||
const IndexFile relation2relation_idx{output_dir + "/rel2rel.map"};
|
||||
IndexFile relation2relation_idx{output_dir + "/rel2rel.map"};
|
||||
map_relation2relation.dump_as_list(relation2relation_idx.fd());
|
||||
} catch (const std::exception& e) {
|
||||
// All exceptions used by the Osmium library derive from std::exception.
|
||||
|
@ -47,10 +47,10 @@ int main(int argc, char* argv[]) {
|
||||
|
||||
try {
|
||||
// The input file, deduce file format from file suffix.
|
||||
const osmium::io::File input_file{argv[1]};
|
||||
osmium::io::File input_file{argv[1]};
|
||||
|
||||
// The output file, force XML OSM file format.
|
||||
const osmium::io::File output_file{argv[2], "osm"};
|
||||
osmium::io::File output_file{argv[2], "osm"};
|
||||
|
||||
// Initialize Reader for the input file.
|
||||
// Read only changesets (will ignore nodes, ways, and
|
||||
|
@ -67,8 +67,8 @@ public:
|
||||
IndexAccess(const IndexAccess&) = delete;
|
||||
IndexAccess& operator=(const IndexAccess&) = delete;
|
||||
|
||||
IndexAccess(IndexAccess&&) noexcept = delete;
|
||||
IndexAccess& operator=(IndexAccess&&) noexcept = delete;
|
||||
IndexAccess(IndexAccess&&) = delete;
|
||||
IndexAccess& operator=(IndexAccess&&) = delete;
|
||||
|
||||
virtual ~IndexAccess() noexcept = default;
|
||||
|
||||
@ -106,7 +106,7 @@ public:
|
||||
~IndexAccessDense() noexcept override = default;
|
||||
|
||||
void dump() const override {
|
||||
const index_type index{this->fd()};
|
||||
index_type index{this->fd()};
|
||||
|
||||
for (std::size_t i = 0; i < index.size(); ++i) {
|
||||
if (index.get(i) != TValue{}) {
|
||||
@ -116,7 +116,7 @@ public:
|
||||
}
|
||||
|
||||
bool search(const osmium::unsigned_object_id_type& key) const override {
|
||||
const index_type index{this->fd()};
|
||||
index_type index{this->fd()};
|
||||
|
||||
try {
|
||||
TValue value = index.get(key);
|
||||
@ -153,7 +153,7 @@ public:
|
||||
~IndexAccessSparse() noexcept override = default;
|
||||
|
||||
void dump() const override {
|
||||
const index_type index{this->fd()};
|
||||
index_type index{this->fd()};
|
||||
|
||||
for (const auto& element : index) {
|
||||
std::cout << element.first << " " << element.second << "\n";
|
||||
@ -164,7 +164,7 @@ public:
|
||||
using element_type = typename index_type::element_type;
|
||||
index_type index{this->fd()};
|
||||
|
||||
const element_type elem{key, TValue{}};
|
||||
element_type elem{key, TValue{}};
|
||||
const auto positions = std::equal_range(index.begin(),
|
||||
index.end(),
|
||||
elem,
|
||||
@ -347,7 +347,7 @@ int run(const IndexAccess<TValue>& index, const Options& options) {
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
// Parse command line options.
|
||||
const Options options{argc, argv};
|
||||
Options options{argc, argv};
|
||||
|
||||
// Open the index file.
|
||||
const int fd = ::open(options.filename(), O_RDWR);
|
||||
|
@ -27,11 +27,11 @@ int main(int argc, char* argv[]) {
|
||||
try {
|
||||
// The Reader is initialized here with an osmium::io::File, but could
|
||||
// also be directly initialized with a file name.
|
||||
const osmium::io::File input_file{argv[1]};
|
||||
osmium::io::File input_file{argv[1]};
|
||||
osmium::io::Reader reader{input_file};
|
||||
|
||||
// OSM data comes in buffers, read until there are no more.
|
||||
while (const osmium::memory::Buffer buffer = reader.read()) {
|
||||
while (osmium::memory::Buffer buffer = reader.read()) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
|
@ -34,14 +34,14 @@ int main(int argc, char* argv[]) {
|
||||
try {
|
||||
// The Reader is initialized here with an osmium::io::File, but could
|
||||
// also be directly initialized with a file name.
|
||||
const osmium::io::File input_file{argv[1]};
|
||||
osmium::io::File input_file{argv[1]};
|
||||
osmium::io::Reader reader{input_file};
|
||||
|
||||
// Initialize progress bar, enable it only if STDERR is a TTY.
|
||||
osmium::ProgressBar progress{reader.file_size(), osmium::isatty(2)};
|
||||
|
||||
// OSM data comes in buffers, read until there are no more.
|
||||
while (const osmium::memory::Buffer buffer = reader.read()) {
|
||||
while (osmium::memory::Buffer buffer = reader.read()) {
|
||||
// Update progress bar for each buffer.
|
||||
progress.update(reader.offset());
|
||||
}
|
||||
|
@ -68,7 +68,7 @@ int main(int argc, char* argv[]) {
|
||||
|
||||
// Create a tile at this location. This will also internally use the
|
||||
// Mercator projection and then calculate the tile coordinates.
|
||||
const osmium::geom::Tile tile{static_cast<uint32_t>(zoom), location};
|
||||
const osmium::geom::Tile tile{uint32_t(zoom), location};
|
||||
std::cout << "Tile: zoom=" << tile.z << " x=" << tile.x << " y=" << tile.y << "\n";
|
||||
}
|
||||
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
This file is part of Osmium (https://osmcode.org/libosmium).
|
||||
|
||||
Copyright 2013-2023 Jochen Topf <jochen@topf.org> and others (see README).
|
||||
Copyright 2013-2022 Jochen Topf <jochen@topf.org> and others (see README).
|
||||
|
||||
Boost Software License - Version 1.0 - August 17th, 2003
|
||||
|
||||
@ -213,7 +213,7 @@ namespace osmium {
|
||||
|
||||
// Now create the Area object and add the attributes and tags
|
||||
// from the relation.
|
||||
const bool okay = create_area(out_buffer, relation, members);
|
||||
bool okay = create_area(out_buffer, relation, members);
|
||||
if (okay) {
|
||||
out_buffer.commit();
|
||||
} else {
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
This file is part of Osmium (https://osmcode.org/libosmium).
|
||||
|
||||
Copyright 2013-2023 Jochen Topf <jochen@topf.org> and others (see README).
|
||||
Copyright 2013-2022 Jochen Topf <jochen@topf.org> and others (see README).
|
||||
|
||||
Boost Software License - Version 1.0 - August 17th, 2003
|
||||
|
||||
@ -124,6 +124,15 @@ namespace osmium {
|
||||
|
||||
AssemblerConfig() noexcept = default;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* @deprecated Use default constructor and set values afterwards.
|
||||
*/
|
||||
explicit AssemblerConfig(ProblemReporter* pr, bool d = false) :
|
||||
problem_reporter(pr),
|
||||
debug_level(d) {
|
||||
}
|
||||
|
||||
}; // struct AssemblerConfig
|
||||
|
||||
} // namespace area
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
This file is part of Osmium (https://osmcode.org/libosmium).
|
||||
|
||||
Copyright 2013-2023 Jochen Topf <jochen@topf.org> and others (see README).
|
||||
Copyright 2013-2022 Jochen Topf <jochen@topf.org> and others (see README).
|
||||
|
||||
Boost Software License - Version 1.0 - August 17th, 2003
|
||||
|
||||
@ -332,10 +332,10 @@ namespace osmium {
|
||||
if (!way.nodes().empty() && way.is_closed() && !way.tags().empty()) {
|
||||
const auto d = std::count_if(way.tags().cbegin(), way.tags().cend(), std::cref(filter()));
|
||||
if (d > 0) {
|
||||
const osmium::tags::KeyFilter::iterator way_fi_begin(std::cref(filter()), way.tags().cbegin(), way.tags().cend());
|
||||
const osmium::tags::KeyFilter::iterator way_fi_end(std::cref(filter()), way.tags().cend(), way.tags().cend());
|
||||
const osmium::tags::KeyFilter::iterator area_fi_begin(std::cref(filter()), area_tags.cbegin(), area_tags.cend());
|
||||
const osmium::tags::KeyFilter::iterator area_fi_end(std::cref(filter()), area_tags.cend(), area_tags.cend());
|
||||
osmium::tags::KeyFilter::iterator way_fi_begin(std::cref(filter()), way.tags().cbegin(), way.tags().cend());
|
||||
osmium::tags::KeyFilter::iterator way_fi_end(std::cref(filter()), way.tags().cend(), way.tags().cend());
|
||||
osmium::tags::KeyFilter::iterator area_fi_begin(std::cref(filter()), area_tags.cbegin(), area_tags.cend());
|
||||
osmium::tags::KeyFilter::iterator area_fi_end(std::cref(filter()), area_tags.cend(), area_tags.cend());
|
||||
#ifdef __cpp_lib_robust_nonmodifying_seq_ops
|
||||
if (!std::equal(way_fi_begin, way_fi_end, area_fi_begin, area_fi_end)) {
|
||||
#else
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
This file is part of Osmium (https://osmcode.org/libosmium).
|
||||
|
||||
Copyright 2013-2023 Jochen Topf <jochen@topf.org> and others (see README).
|
||||
Copyright 2013-2022 Jochen Topf <jochen@topf.org> and others (see README).
|
||||
|
||||
Boost Software License - Version 1.0 - August 17th, 2003
|
||||
|
||||
@ -608,7 +608,7 @@ namespace osmium {
|
||||
|
||||
void create_rings_simple_case() {
|
||||
auto count_remaining = m_segment_list.size();
|
||||
for (const slocation& sl : m_locations) {
|
||||
for (slocation& sl : m_locations) {
|
||||
const NodeRefSegment& segment = m_segment_list[sl.item];
|
||||
if (!segment.is_done()) {
|
||||
count_remaining -= add_new_ring(sl);
|
||||
@ -671,7 +671,7 @@ namespace osmium {
|
||||
std::cerr << " Trying to merge " << open_ring_its.size() << " open rings (try_to_merge)\n";
|
||||
}
|
||||
|
||||
const auto xrings = create_location_to_ring_map(open_ring_its);
|
||||
std::vector<location_to_ring_map> xrings = create_location_to_ring_map(open_ring_its);
|
||||
|
||||
auto it = xrings.cbegin();
|
||||
while (it != xrings.cend()) {
|
||||
@ -825,7 +825,7 @@ namespace osmium {
|
||||
|
||||
find_inner_outer_complex();
|
||||
ProtoRing* outer_ring = find_enclosing_ring(ring_min->ring().min_segment());
|
||||
const bool ring_min_is_outer = !outer_ring;
|
||||
bool ring_min_is_outer = !outer_ring;
|
||||
if (debug()) {
|
||||
std::cerr << " Open ring is " << (ring_min_is_outer ? "outer" : "inner") << " ring\n";
|
||||
}
|
||||
@ -924,7 +924,7 @@ namespace osmium {
|
||||
|
||||
// Now find all the rest of the rings (ie not starting at split locations)
|
||||
if (count_remaining > 0) {
|
||||
for (const slocation& sl : m_locations) {
|
||||
for (slocation& sl : m_locations) {
|
||||
const NodeRefSegment& segment = m_segment_list[sl.item];
|
||||
if (!segment.is_done()) {
|
||||
count_remaining -= add_new_ring_complex(sl);
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
This file is part of Osmium (https://osmcode.org/libosmium).
|
||||
|
||||
Copyright 2013-2023 Jochen Topf <jochen@topf.org> and others (see README).
|
||||
Copyright 2013-2022 Jochen Topf <jochen@topf.org> and others (see README).
|
||||
|
||||
Boost Software License - Version 1.0 - August 17th, 2003
|
||||
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
This file is part of Osmium (https://osmcode.org/libosmium).
|
||||
|
||||
Copyright 2013-2023 Jochen Topf <jochen@topf.org> and others (see README).
|
||||
Copyright 2013-2022 Jochen Topf <jochen@topf.org> and others (see README).
|
||||
|
||||
Boost Software License - Version 1.0 - August 17th, 2003
|
||||
|
||||
@ -193,7 +193,7 @@ namespace osmium {
|
||||
|
||||
const char* role_name() const noexcept {
|
||||
static const std::array<const char*, 4> names = {{"unknown", "outer", "inner", "empty"}};
|
||||
return names[static_cast<int>(m_role)];
|
||||
return names[int(m_role)];
|
||||
}
|
||||
|
||||
const osmium::Way* way() const noexcept {
|
||||
@ -327,9 +327,9 @@ namespace osmium {
|
||||
|
||||
if ((d > 0 && na >= 0 && na <= d && nb >= 0 && nb <= d) ||
|
||||
(d < 0 && na <= 0 && na >= d && nb <= 0 && nb >= d)) {
|
||||
const double ua = static_cast<double>(na) / static_cast<double>(d);
|
||||
const double ua = double(na) / d;
|
||||
const vec i = p0 + ua * (p1 - p0);
|
||||
return osmium::Location{static_cast<int32_t>(i.x), static_cast<int32_t>(i.y)};
|
||||
return osmium::Location{int32_t(i.x), int32_t(i.y)};
|
||||
}
|
||||
|
||||
return osmium::Location{};
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
This file is part of Osmium (https://osmcode.org/libosmium).
|
||||
|
||||
Copyright 2013-2023 Jochen Topf <jochen@topf.org> and others (see README).
|
||||
Copyright 2013-2022 Jochen Topf <jochen@topf.org> and others (see README).
|
||||
|
||||
Boost Software License - Version 1.0 - August 17th, 2003
|
||||
|
||||
@ -86,16 +86,16 @@ namespace osmium {
|
||||
int64_t m_num;
|
||||
#endif
|
||||
|
||||
int64_t m_sum = 0;
|
||||
int64_t m_sum;
|
||||
|
||||
public:
|
||||
|
||||
explicit ProtoRing(NodeRefSegment* segment) noexcept :
|
||||
m_min_segment(segment)
|
||||
m_min_segment(segment),
|
||||
#ifdef OSMIUM_DEBUG_RING_NO
|
||||
, m_num(next_num())
|
||||
m_num(next_num()),
|
||||
#endif
|
||||
{
|
||||
m_sum(0) {
|
||||
add_segment_back(segment);
|
||||
}
|
||||
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
This file is part of Osmium (https://osmcode.org/libosmium).
|
||||
|
||||
Copyright 2013-2023 Jochen Topf <jochen@topf.org> and others (see README).
|
||||
Copyright 2013-2022 Jochen Topf <jochen@topf.org> and others (see README).
|
||||
|
||||
Boost Software License - Version 1.0 - August 17th, 2003
|
||||
|
||||
@ -333,7 +333,7 @@ namespace osmium {
|
||||
}
|
||||
|
||||
if (y_range_overlap(s1, s2)) {
|
||||
const osmium::Location intersection{calculate_intersection(s1, s2)};
|
||||
osmium::Location intersection{calculate_intersection(s1, s2)};
|
||||
if (intersection) {
|
||||
++found_intersections;
|
||||
if (m_debug) {
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
This file is part of Osmium (https://osmcode.org/libosmium).
|
||||
|
||||
Copyright 2013-2023 Jochen Topf <jochen@topf.org> and others (see README).
|
||||
Copyright 2013-2022 Jochen Topf <jochen@topf.org> and others (see README).
|
||||
|
||||
Boost Software License - Version 1.0 - August 17th, 2003
|
||||
|
||||
@ -89,12 +89,12 @@ namespace osmium {
|
||||
|
||||
// scale vector
|
||||
constexpr inline vec operator*(double s, const vec& v) noexcept {
|
||||
return vec{static_cast<int64_t>(s * static_cast<double>(v.x)), static_cast<int64_t>(s * static_cast<double>(v.y))};
|
||||
return vec{int64_t(s * v.x), int64_t(s * v.y)};
|
||||
}
|
||||
|
||||
// scale vector
|
||||
constexpr inline vec operator*(const vec& v, double s) noexcept {
|
||||
return vec{static_cast<int64_t>(s * static_cast<double>(v.x)), static_cast<int64_t>(s * static_cast<double>(v.y))};
|
||||
return vec{int64_t(s * v.x), int64_t(s * v.y)};
|
||||
}
|
||||
|
||||
// equality
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
This file is part of Osmium (https://osmcode.org/libosmium).
|
||||
|
||||
Copyright 2013-2023 Jochen Topf <jochen@topf.org> and others (see README).
|
||||
Copyright 2013-2022 Jochen Topf <jochen@topf.org> and others (see README).
|
||||
|
||||
Boost Software License - Version 1.0 - August 17th, 2003
|
||||
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
This file is part of Osmium (https://osmcode.org/libosmium).
|
||||
|
||||
Copyright 2013-2023 Jochen Topf <jochen@topf.org> and others (see README).
|
||||
Copyright 2013-2022 Jochen Topf <jochen@topf.org> and others (see README).
|
||||
|
||||
Boost Software License - Version 1.0 - August 17th, 2003
|
||||
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
This file is part of Osmium (https://osmcode.org/libosmium).
|
||||
|
||||
Copyright 2013-2023 Jochen Topf <jochen@topf.org> and others (see README).
|
||||
Copyright 2013-2022 Jochen Topf <jochen@topf.org> and others (see README).
|
||||
|
||||
Boost Software License - Version 1.0 - August 17th, 2003
|
||||
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
This file is part of Osmium (https://osmcode.org/libosmium).
|
||||
|
||||
Copyright 2013-2023 Jochen Topf <jochen@topf.org> and others (see README).
|
||||
Copyright 2013-2022 Jochen Topf <jochen@topf.org> and others (see README).
|
||||
|
||||
Boost Software License - Version 1.0 - August 17th, 2003
|
||||
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
This file is part of Osmium (https://osmcode.org/libosmium).
|
||||
|
||||
Copyright 2013-2023 Jochen Topf <jochen@topf.org> and others (see README).
|
||||
Copyright 2013-2022 Jochen Topf <jochen@topf.org> and others (see README).
|
||||
|
||||
Boost Software License - Version 1.0 - August 17th, 2003
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user