Compare commits

..

15 Commits

Author SHA1 Message Date
Siarhei Fedartsou 07746de667 Try to get rid of std::variant in json_container.hpp 2024-09-29 09:12:35 +02:00
Siarhei Fedartsou feb8da25cd Try to get rid of std::variant in json_container.hpp 2024-09-28 21:51:59 +02:00
Siarhei Fedartsou 150c792f76 Try to get rid of std::variant in json_container.hpp 2024-09-28 21:38:46 +02:00
Siarhei Fedartsou dbc52728c3 Try to get rid of std::variant in json_container.hpp 2024-09-28 21:34:24 +02:00
Siarhei Fedartsou 4f1c62a768 Bump version of protozero to 1.7.1 (#6999) 2024-09-28 20:35:20 +02:00
Siarhei Fedartsou 09a716a9e5 Bump osmium to version 2.20.0 (#6997) 2024-09-28 20:35:05 +02:00
Siarhei Fedartsou 676f6d4704 Use std::popcount instead of __builtin_popcount (#7026) 2024-09-28 20:34:39 +02:00
Siarhei Fedartsou f636dbfd44 Use std::countl_zero instead of __builtin_clzll (#7025) 2024-09-28 20:34:23 +02:00
Siarhei Fedartsou 5f67e715af Add std::vector<...>::reserve in ContiguousInternalMemoryDataFacadeBase::GetOverridesThatStartAt (#7024) 2024-09-28 20:33:33 +02:00
Siarhei Fedartsou 203314b1aa Remove unused middle_nodes_table vector (#7012) 2024-08-03 22:32:37 +02:00
Siarhei Fedartsou e5e25a1aca Configure self-hosted runner for benchmarks job (#6975) 2024-07-26 21:19:47 +02:00
Siarhei Fedartsou 84f12c7c6d Add NodeJs bindings benchmarks (#7004) 2024-07-26 19:36:43 +02:00
Siarhei Fedartsou 7802f86bd6 Measure peak RAM in benchmarks (#6995) 2024-07-25 21:27:37 +02:00
Siarhei Fedartsou 43afec3b39 Move flatbuffers non-generated files back to include/engine/api/flatbuffers/ (#6996) 2024-07-13 13:43:56 +02:00
Dennis Luxen 2da7ca5338 Route pedestrians over highway=platform (#6993) 2024-07-12 20:12:19 +02:00
632 changed files with 2420 additions and 31568 deletions
+43 -46
View File
@@ -653,7 +653,7 @@ jobs:
benchmarks:
if: github.event_name == 'pull_request'
needs: [format-taginfo-docs]
runs-on: ubuntu-24.04
runs-on: self-hosted
env:
CCOMPILER: clang-16
CXXCOMPILER: clang++-16
@@ -664,37 +664,17 @@ 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: 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: 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: Prepare data
run: |
if [ "$RUN_BIG_BENCHMARK" = "true" ]; then
@@ -722,50 +702,67 @@ 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 ..
cmake -DENABLE_CONAN=ON -DCMAKE_BUILD_TYPE=Release -DENABLE_NODE_BINDINGS=ON ..
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 ..
cmake -DENABLE_CONAN=ON -DCMAKE_BUILD_TYPE=Release -DENABLE_NODE_BINDINGS=ON ..
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: mkdir -p /opt/benchmarks
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
- name: Run PR Benchmarks
run: |
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 -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
./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
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
- name: Run Base Benchmarks
run: |
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
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
# TODO: remove it when base branch will have this file at needed location
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
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
fi
# we intentionally use scripts from PR branch to be able to update them and see results in the same PR
./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
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
- name: Post Benchmark Results
run: |
python3 pr/scripts/ci/post_benchmark_results.py base_results pr_results
-1
View File
@@ -48,7 +48,6 @@ Thumbs.db
/test/data/ch
/test/data/mld
/cmake/postinst
/target
# Eclipse related files #
#########################
+1
View File
@@ -1,6 +1,7 @@
# 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)
Generated
-2582
View File
File diff suppressed because it is too large Load Diff
-37
View File
@@ -1,37 +0,0 @@
[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
View File
@@ -1,117 +0,0 @@
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 -1
View File
@@ -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}&continue_straight={default|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}
```
In addition to the [general options](#general-options) the following options are supported for this service:
+2 -2
View File
@@ -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.4 km/h | depart,arrive |
| e | c | cde,cde | driving,driving | 2.4 km/h | depart,arrive |
| c | e | cde,cde | driving,driving | 2 km/h | depart,arrive |
| e | c | cde,cde | driving,driving | 2 km/h | depart,arrive |
+18 -18
View File
@@ -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
+9 -1
View File
@@ -26,7 +26,15 @@ 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
+1 -1
View File
@@ -46,7 +46,7 @@ class OSRMBaseLoader{
let retry = (err) => {
if (err) {
if (retryCount < this.scope.OSRM_CONNECTION_RETRIES) {
const timeoutMs = 10 * Math.pow(1.1, retryCount);
const timeoutMs = 10 * Math.pow(this.scope.OSRM_CONNECTION_EXP_BACKOFF_COEF, retryCount);
retryCount++;
setTimeout(() => { tryConnect(this.scope.OSRM_IP, this.scope.OSRM_PORT, retry); }, timeoutMs);
} else {
@@ -603,6 +603,8 @@ 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)
+2 -32
View File
@@ -2,43 +2,13 @@
#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>
@@ -70,7 +40,7 @@ class BitIterator : public boost::iterator_facade<BitIterator<DataT>,
difference_type distance_to(const BitIterator &other) const
{
return detail::countOnes(m_value) - detail::countOnes(other.m_value);
return std::popcount(m_value) - std::popcount(other.m_value);
}
bool equal(const BitIterator &other) const { return m_value == other.m_value; }
+142 -11
View File
@@ -90,33 +90,164 @@ struct Null
{
};
/**
* Typed Value sum-type implemented as a variant able to represent tree-like JSON structures.
*
* Dispatch on its type by either by using apply_visitor or its get function.
*/
using Value = std::variant<String, Number, Object, Array, True, False, Null>;
/**
* Typed Object.
*
* Unwrap the key-value pairs holding type via its values member attribute.
*/
struct Object
{
std::unordered_map<std::string, Value> values;
};
struct Object;
/**
* Typed Array.
*
* Unwrap the Value holding type via its values member attribute.
*/
struct Array;
struct Value;
// Definitions of Object and Array (must come after Value is defined)
struct Object
{
std::unordered_map<std::string, Value> values;
};
struct Array
{
std::vector<Value> values;
};
struct Value
{
enum class Type
{
Invalid,
String,
Number,
Object,
Array,
True,
False,
Null
};
String string;
Number number;
Object object;
Array array;
Type type;
Value() noexcept : type(Type::Invalid) {}
Value(const Null &) noexcept : type(Type::Null) {}
Value(const True &) noexcept : type(Type::True) {}
Value(const False &) noexcept : type(Type::False) {}
Value(String &&string_) noexcept : string(std::move(string_)), type(Type::String) {}
Value(Number &&number_) noexcept : number(number_), type(Type::Number) {}
Value(Object &&object_) noexcept : object(std::move(object_)), type(Type::Object) {}
Value(Array &&array_) noexcept : array(std::move(array_)), type(Type::Array) {}
Value(const String &string_) noexcept : string(string_), type(Type::String) {}
Value(const Number &number_) noexcept : number(number_), type(Type::Number) {}
Value(const Object &object_) noexcept : object(object_), type(Type::Object) {}
Value(const Array &array_) noexcept : array(array_), type(Type::Array) {}
Value(double number) noexcept : number(number), type(Type::Number) {}
Value(std::string string) noexcept : string(std::move(string)), type(Type::String) {}
Value(const char *string) noexcept : string(string), type(Type::String) {}
};
} // namespace osrm::util::json
namespace std
{
template <typename T> inline T &get(osrm::util::json::Value &value) noexcept;
template <>
inline osrm::util::json::String &
get<osrm::util::json::String>(osrm::util::json::Value &value) noexcept
{
return value.string;
}
template <>
inline osrm::util::json::Number &
get<osrm::util::json::Number>(osrm::util::json::Value &value) noexcept
{
return value.number;
}
template <>
inline osrm::util::json::Object &
get<osrm::util::json::Object>(osrm::util::json::Value &value) noexcept
{
return value.object;
}
template <>
inline osrm::util::json::Array &
get<osrm::util::json::Array>(osrm::util::json::Value &value) noexcept
{
return value.array;
}
template <typename T> inline const T &get(const osrm::util::json::Value &value) noexcept;
template <>
inline const osrm::util::json::String &
get<osrm::util::json::String>(const osrm::util::json::Value &value) noexcept
{
return value.string;
}
template <>
inline const osrm::util::json::Number &
get<osrm::util::json::Number>(const osrm::util::json::Value &value) noexcept
{
return value.number;
}
template <>
inline const osrm::util::json::Object &
get<osrm::util::json::Object>(const osrm::util::json::Value &value) noexcept
{
return value.object;
}
template <>
inline const osrm::util::json::Array &
get<osrm::util::json::Array>(const osrm::util::json::Value &value) noexcept
{
return value.array;
}
template <typename Visitor>
inline void visit(Visitor &&visitor, const osrm::util::json::Value &value)
{
switch (value.type)
{
case osrm::util::json::Value::Type::String:
visitor(value.string);
break;
case osrm::util::json::Value::Type::Number:
visitor(value.number);
break;
case osrm::util::json::Value::Type::Object:
visitor(value.object);
break;
case osrm::util::json::Value::Type::Array:
visitor(value.array);
break;
case osrm::util::json::Value::Type::True:
visitor(osrm::util::json::True{});
break;
case osrm::util::json::Value::Type::False:
visitor(osrm::util::json::False{});
break;
case osrm::util::json::Value::Type::Null:
visitor(osrm::util::json::Null{});
break;
case osrm::util::json::Value::Type::Invalid:
break;
}
}
} // namespace std
#endif // JSON_CONTAINER_HPP
+137 -135
View File
@@ -1,157 +1,159 @@
#ifndef UTIL_JSON_DEEP_COMPARE_HPP
#define UTIL_JSON_DEEP_COMPARE_HPP
// #ifndef UTIL_JSON_DEEP_COMPARE_HPP
// #define UTIL_JSON_DEEP_COMPARE_HPP
#include "util/integer_range.hpp"
#include "util/json_container.hpp"
// #include "util/integer_range.hpp"
// #include "util/json_container.hpp"
#include <boost/assert.hpp>
// #include <boost/assert.hpp>
#include <algorithm>
#include <functional>
#include <set>
// #include <algorithm>
// #include <functional>
// #include <set>
namespace osrm::util::json
{
// namespace osrm::util::json
// {
struct Comparator
{
Comparator(std::string &reason_, const std::string &lhs_path_, const std::string &rhs_path_)
: reason(reason_), lhs_path(lhs_path_), rhs_path(rhs_path_)
{
}
// struct Comparator
// {
// Comparator(std::string &reason_, const std::string &lhs_path_, const std::string &rhs_path_)
// : reason(reason_), lhs_path(lhs_path_), rhs_path(rhs_path_)
// {
// }
bool operator()(const String &lhs, const String &rhs) const
{
bool is_same = lhs.value == rhs.value;
if (!is_same)
{
reason = lhs_path + " (= \"" + lhs.value + "\") != " + rhs_path + " (= \"" + rhs.value +
"\")";
}
return is_same;
}
// bool operator()(const String &lhs, const String &rhs) const
// {
// bool is_same = lhs.value == rhs.value;
// if (!is_same)
// {
// reason = lhs_path + " (= \"" + lhs.value + "\") != " + rhs_path + " (= \"" +
// rhs.value +
// "\")";
// }
// return is_same;
// }
bool operator()(const Number &lhs, const Number &rhs) const
{
bool is_same = lhs.value == rhs.value;
if (!is_same)
{
reason = lhs_path + " (= " + std::to_string(lhs.value) + ") != " + rhs_path +
" (= " + std::to_string(rhs.value) + ")";
}
return is_same;
}
// bool operator()(const Number &lhs, const Number &rhs) const
// {
// bool is_same = lhs.value == rhs.value;
// if (!is_same)
// {
// reason = lhs_path + " (= " + std::to_string(lhs.value) + ") != " + rhs_path +
// " (= " + std::to_string(rhs.value) + ")";
// }
// return is_same;
// }
bool operator()(const Object &lhs, const Object &rhs) const
{
std::set<std::string> lhs_keys;
for (const auto &key_value : lhs.values)
{
lhs_keys.insert(key_value.first);
}
// bool operator()(const Object &lhs, const Object &rhs) const
// {
// std::set<std::string> lhs_keys;
// for (const auto &key_value : lhs.values)
// {
// lhs_keys.insert(key_value.first);
// }
std::set<std::string> rhs_keys;
for (const auto &key_value : rhs.values)
{
rhs_keys.insert(key_value.first);
}
// std::set<std::string> rhs_keys;
// for (const auto &key_value : rhs.values)
// {
// rhs_keys.insert(key_value.first);
// }
for (const auto &key : lhs_keys)
{
if (rhs_keys.find(key) == rhs_keys.end())
{
reason = rhs_path + " doesn't have key \"" + key + "\"";
return false;
}
}
// for (const auto &key : lhs_keys)
// {
// if (rhs_keys.find(key) == rhs_keys.end())
// {
// reason = rhs_path + " doesn't have key \"" + key + "\"";
// return false;
// }
// }
for (const auto &key : rhs_keys)
{
if (lhs_keys.find(key) == lhs_keys.end())
{
reason = lhs_path + " doesn't have key \"" + key + "\"";
return false;
}
}
// for (const auto &key : rhs_keys)
// {
// if (lhs_keys.find(key) == lhs_keys.end())
// {
// reason = lhs_path + " doesn't have key \"" + key + "\"";
// return false;
// }
// }
for (const auto &key : lhs_keys)
{
BOOST_ASSERT(rhs.values.find(key) != rhs.values.end());
BOOST_ASSERT(lhs.values.find(key) != lhs.values.end());
// for (const auto &key : lhs_keys)
// {
// BOOST_ASSERT(rhs.values.find(key) != rhs.values.end());
// BOOST_ASSERT(lhs.values.find(key) != lhs.values.end());
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 + "." + key, rhs_path + "." + key),
lhs_child,
rhs_child);
if (!is_same)
{
return false;
}
}
return true;
}
// 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 + "." + key, rhs_path + "." + key),
// lhs_child,
// rhs_child);
// if (!is_same)
// {
// return false;
// }
// }
// return true;
// }
bool operator()(const Array &lhs, const Array &rhs) const
{
if (lhs.values.size() != rhs.values.size())
{
reason = lhs_path + ".length " + std::to_string(lhs.values.size()) + " != " + rhs_path +
".length " + std::to_string(rhs.values.size());
return false;
}
// bool operator()(const Array &lhs, const Array &rhs) const
// {
// if (lhs.values.size() != rhs.values.size())
// {
// reason = lhs_path + ".length " + std::to_string(lhs.values.size()) + " != " +
// rhs_path +
// ".length " + std::to_string(rhs.values.size());
// return false;
// }
for (auto i = 0UL; i < lhs.values.size(); ++i)
{
auto is_same = std::visit(Comparator(reason,
lhs_path + "[" + std::to_string(i) + "]",
rhs_path + "[" + std::to_string(i) + "]"),
lhs.values[i],
rhs.values[i]);
if (!is_same)
{
return false;
}
}
// for (auto i = 0UL; i < lhs.values.size(); ++i)
// {
// auto is_same = std::visit(Comparator(reason,
// lhs_path + "[" + std::to_string(i) + "]",
// rhs_path + "[" + std::to_string(i) + "]"),
// lhs.values[i],
// rhs.values[i]);
// if (!is_same)
// {
// return false;
// }
// }
return true;
}
// return true;
// }
bool operator()(const True &, const True &) const { return true; }
bool operator()(const False &, const False &) const { return true; }
bool operator()(const Null &, const Null &) const { return true; }
// bool operator()(const True &, const True &) const { return true; }
// bool operator()(const False &, const False &) const { return true; }
// bool operator()(const Null &, const Null &) const { return true; }
bool operator()(const False &, const True &) const
{
reason = lhs_path + " is false but " + rhs_path + " is true";
return false;
}
bool operator()(const True &, const False &) const
{
reason = lhs_path + " is true but " + rhs_path + " is false";
return false;
}
// bool operator()(const False &, const True &) const
// {
// reason = lhs_path + " is false but " + rhs_path + " is true";
// return false;
// }
// bool operator()(const True &, const False &) const
// {
// reason = lhs_path + " is true but " + rhs_path + " is false";
// return false;
// }
template <typename T1,
typename T2,
typename = typename std::enable_if<!std::is_same<T1, T2>::value>::type>
bool operator()(const T1 &, const T2 &)
{
reason = lhs_path + " and " + rhs_path + " have different types";
return false;
}
// template <typename T1,
// typename T2,
// typename = typename std::enable_if<!std::is_same<T1, T2>::value>::type>
// bool operator()(const T1 &, const T2 &)
// {
// reason = lhs_path + " and " + rhs_path + " have different types";
// return false;
// }
private:
std::string &reason;
const std::string &lhs_path;
const std::string &rhs_path;
};
// private:
// std::string &reason;
// const std::string &lhs_path;
// const std::string &rhs_path;
// };
inline bool compare(const Value &reference, const Value &result, std::string &reason)
{
return std::visit(Comparator(reason, "reference", "result"), reference, result);
}
} // namespace osrm::util::json
// inline bool compare(const Value &reference, const Value &result, std::string &reason)
// {
// return std::visit(Comparator(reason, "reference", "result"), reference, result);
// }
// } // namespace osrm::util::json
#endif
// #endif
+14 -4
View File
@@ -2,6 +2,7 @@
#define MEMINFO_HPP
#include "util/log.hpp"
#include <cstddef>
#ifndef _WIN32
#include <sys/resource.h>
@@ -10,22 +11,31 @@
namespace osrm::util
{
inline void DumpMemoryStats()
inline size_t PeakRAMUsedInBytes()
{
#ifndef _WIN32
rusage usage;
getrusage(RUSAGE_SELF, &usage);
#ifdef __linux__
// Under linux, ru.maxrss is in kb
util::Log() << "RAM: peak bytes used: " << usage.ru_maxrss * 1024;
return usage.ru_maxrss * 1024;
#else // __linux__
// Under BSD systems (OSX), it's in bytes
util::Log() << "RAM: peak bytes used: " << usage.ru_maxrss;
return 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
+7 -33
View File
@@ -1,50 +1,24 @@
#ifndef OSRM_UTIL_MSB_HPP
#define OSRM_UTIL_MSB_HPP
#include <bit>
#include <boost/assert.hpp>
#include <climits>
#include <cstdint>
#include <utility>
#include <limits>
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.");
std::size_t msb = 0;
while (value > 0)
{
value >>= 1u;
msb++;
}
BOOST_ASSERT(msb > 0);
return msb - 1;
constexpr auto MSB_INDEX = std::numeric_limits<unsigned char>::digits * sizeof(T) - 1;
return MSB_INDEX - std::countl_zero(value);
}
#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
+12 -1
View File
@@ -10,7 +10,8 @@
"hasInstallScript": true,
"license": "BSD-2-Clause",
"dependencies": {
"@mapbox/node-pre-gyp": "^1.0.11"
"@mapbox/node-pre-gyp": "^1.0.11",
"seedrandom": "^3.0.5"
},
"devDependencies": {
"@babel/cli": "^7.18.10",
@@ -14652,6 +14653,11 @@
"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",
@@ -30296,6 +30302,11 @@
"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",
+7 -4
View File
@@ -4,7 +4,8 @@
"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"
"@mapbox/node-pre-gyp": "^1.0.11",
"seedrandom": "^3.0.5"
},
"browserify": {
"transform": [
@@ -57,6 +58,7 @@
"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",
@@ -64,12 +66,13 @@
"tape": "^4.16.0",
"turf": "^3.0.14",
"uglify-js": "^3.17.0",
"xmlbuilder": "^4.2.1",
"node-cmake": "^2.5.1"
"xmlbuilder": "^4.2.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",
+1
View File
@@ -90,6 +90,7 @@ function setup()
path = walking_speed,
steps = walking_speed,
pedestrian = walking_speed,
platform = walking_speed,
footway = walking_speed,
pier = walking_speed,
},
+211
View File
@@ -0,0 +1,211 @@
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();
+13
View File
@@ -53,6 +53,7 @@ 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"
@@ -81,6 +82,18 @@ 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"
+2 -2
View File
@@ -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.14.0
OSMIUM_TAG=v2.20.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.6.2
PROTOZERO_TAG=v1.7.1
VTZERO_PATH="mapbox/vtzero"
VTZERO_TAG=v1.1.0
+7 -1
View File
@@ -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,6 +655,12 @@ 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)
+2 -2
View File
@@ -143,8 +143,8 @@ util::json::Object makeIntersection(const guidance::IntermediateIntersection &in
});
result.values.emplace("location", detail::coordinateToLonLat(intersection.location));
result.values.emplace("bearings", bearings);
result.values.emplace("entry", entry);
result.values.emplace("bearings", std::move(bearings));
result.values.emplace("entry", std::move(entry));
if (intersection.in != guidance::IntermediateIntersection::NO_INDEX)
result.values.emplace("in", intersection.in);
if (intersection.out != guidance::IntermediateIntersection::NO_INDEX)
@@ -222,7 +222,6 @@ 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>>
@@ -307,7 +306,6 @@ 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
View File
@@ -1,3 +0,0 @@
fn main() {
println!("Hello, world!");
}
+1 -2
View File
@@ -7,7 +7,6 @@
#include "util/json_container.hpp"
#include <boost/format.hpp>
#include <iostream>
namespace osrm::server::service
{
@@ -31,11 +30,11 @@ std::string getWrongOptionHelp(const engine::api::NearestParameters &parameters)
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
View File
@@ -1,51 +0,0 @@
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
View File
@@ -1,17 +0,0 @@
#[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
View File
@@ -1,101 +0,0 @@
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
View File
@@ -1,24 +0,0 @@
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
View File
@@ -1,20 +0,0 @@
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
View File
@@ -1,80 +0,0 @@
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
View File
@@ -1,24 +0,0 @@
// 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
View File
@@ -1,55 +0,0 @@
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
View File
@@ -1,68 +0,0 @@
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
View File
@@ -1,8 +0,0 @@
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
View File
@@ -1,37 +0,0 @@
#![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
View File
@@ -1,88 +0,0 @@
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
View File
@@ -1,143 +0,0 @@
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
View File
@@ -1,131 +0,0 @@
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
View File
@@ -1,17 +0,0 @@
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
View File
@@ -1,335 +0,0 @@
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
View File
@@ -1,105 +0,0 @@
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
View File
@@ -1,24 +0,0 @@
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
View File
File diff suppressed because it is too large Load Diff
+4 -1
View File
@@ -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-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-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'
#
# For a list of check options, see:
# https://clang.llvm.org/extra/clang-tidy/checks/list.html
@@ -137,6 +137,9 @@ 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,7 +7,13 @@ 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 -q
sudo apt-get update -qq
sudo apt-get install -yq \
doxygen \
libboost-dev \
@@ -16,8 +16,5 @@ 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
+109 -131
View File
@@ -3,14 +3,13 @@ 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-21, Debian-9, Debian-10, Debian-11, Debian-Testing, Debian-Experimental, Fedora-34]
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]
build_type: [Dev]
cpp_compiler: [g++]
cpp_version: [c++11]
@@ -19,122 +18,136 @@ 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
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: 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
- 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"
installer: apt
c_compiler: clang
cpp_compiler: clang++
- name: Debian-11
image: "debian:bullseye"
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++
- 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,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"
installer: apt
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"
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
- name: Debian-Testing
image: "debian:testing"
CXXFLAGS: -Wno-stringop-overread -Wno-dangling-reference
- 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"
installer: apt
CXXFLAGS: -Wno-stringop-overread
CXXFLAGS: -Wno-stringop-overread -Wno-dangling-reference
- name: Debian-Experimental
# Uses gcc 11, clang 14, cmake 3.21.3
image: "debian:experimental"
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
c_compiler: clang
cpp_compiler: clang++
- 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 }}
CXXFLAGS: ${{ matrix.CXXFLAGS }}
LDFLAGS: ${{ matrix.LDFLAGS }}
CC: ${{ matrix.c_compiler }}
CXX: ${{ matrix.cpp_compiler }}
CXXFLAGS: ${{ matrix.CXXFLAGS }}
LDFLAGS: ${{ matrix.LDFLAGS }}
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 -y \
apt-get install -yq \
clang \
cmake \
doxygen \
@@ -154,16 +167,13 @@ 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 \
@@ -185,9 +195,7 @@ jobs:
sparsehash-devel \
spatialite-tools \
zlib-devel
shell: bash
if: matrix.installer == 'dnf'
# Use v1 of checkout because v2 doesn't work with submodules
# Use v1 of checkout because v3 doesn't work with submodules
- uses: actions/checkout@v1
with:
submodules: true
@@ -197,21 +205,23 @@ jobs:
- uses: ./.github/actions/ctest
ubuntu-latest:
runs-on: ubuntu-20.04
runs-on: ubuntu-22.04
timeout-minutes: 40
env:
CC: clang-13
CXX: clang++-13
CC: clang-15
CXX: clang++-15
BUILD_TYPE: Dev
WITH_PROJ: ON
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
with:
submodules: true
- name: Install new clang
run: |
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'
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
shell: bash
- uses: ./.github/actions/install-ubuntu
- uses: ./.github/actions/install-protozero
@@ -219,16 +229,27 @@ jobs:
- uses: ./.github/actions/build
- uses: ./.github/actions/ctest
macos10-dev:
runs-on: macos-10.15
macos:
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: Dev
BUILD_TYPE: ${{ matrix.build_type }}
WITH_PROJ: OFF
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
with:
submodules: true
- uses: ./.github/actions/install-macos
@@ -237,47 +258,17 @@ jobs:
- uses: ./.github/actions/build
- uses: ./.github/actions/ctest
macos11-dev:
runs-on: macos-11
timeout-minutes: 60
env:
CC: clang
CXX: clang++
BUILD_TYPE: Dev
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
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
windows-minimal:
timeout-minutes: 40
strategy:
fail-fast: false
matrix:
os:
- windows-2019
- windows-2022
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
with:
submodules: true
- uses: ./.github/actions/install-windows
@@ -289,7 +280,7 @@ jobs:
windows-2019-full:
runs-on: windows-2019
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
with:
submodules: true
- uses: ./.github/actions/install-windows
@@ -301,16 +292,3 @@ 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
+21 -22
View File
@@ -3,7 +3,6 @@ name: clang-tidy
on: workflow_dispatch
jobs:
clang-tidy:
runs-on: ubuntu-latest
strategy:
@@ -14,9 +13,9 @@ jobs:
- image: "debian:bullseye"
clang: 11
- image: "debian:testing"
clang: 12
clang: 15
- image: "debian:experimental"
clang: 14
clang: 15
container:
image: ${{ matrix.image }}
env:
@@ -25,29 +24,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 -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
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
shell: bash
# Use v1 of checkout because v2 doesn't work with submodules
# Use v1 of checkout because v3 doesn't work with submodules
- uses: actions/checkout@v1
with:
submodules: true
@@ -58,7 +57,7 @@ jobs:
shell: bash
working-directory: build
- name: Upload Log
uses: actions/upload-artifact@v2
uses: actions/upload-artifact@v3
if: always()
with:
name: clang-tidy-${{ matrix.clang }}-log
-53
View File
@@ -1,53 +0,0 @@
#-----------------------------------------------------------------------------
#
# 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
}
+35 -1
View File
@@ -12,6 +12,38 @@ 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
@@ -1253,7 +1285,9 @@ 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.18.0...HEAD
[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
[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
+2 -2
View File
@@ -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 18)
set(LIBOSMIUM_VERSION_MINOR 20)
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-14 clang-tidy-13 clang-tidy-12 clang-tidy-11)
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)
if(CLANG_TIDY)
message(STATUS "Looking for clang-tidy - found ${CLANG_TIDY}")
+1 -2
View File
@@ -136,8 +136,7 @@ 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 (Linux/macOS) and Appveyor
(Windows) services.
Tests are run automatically using Github Actions.
## Documenting the code
+2 -12
View File
@@ -7,8 +7,6 @@ A fast and flexible C++ library for working with OpenStreetMap data.
Libosmium works on Linux, macOS and Windows.
[![Github Build Status](https://github.com/osmcode/libosmium/workflows/CI/badge.svg?branch=master)](https://github.com/osmcode/libosmium/actions)
[![Appveyor Build status](https://ci.appveyor.com/api/projects/status/yy099a4vxcb604rn/branch/master?svg=true)](https://ci.appveyor.com/project/lonvia/libosmium-eq41p/branch/master)
[![Coverage Status](https://codecov.io/gh/osmcode/libosmium/branch/master/graph/badge.svg)](https://codecov.io/gh/osmcode/libosmium)
[![Packaging status](https://repology.org/badge/tiny-repos/libosmium.svg)](https://repology.org/metapackage/libosmium)
Please see the [Libosmium manual](https://osmcode.org/libosmium/manual.html)
@@ -17,9 +15,8 @@ for more details than this README can provide.
## Prerequisites
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.)
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.)
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
@@ -88,13 +85,6 @@ 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]};
osmium::memory::Buffer buffer{osmium::io::read_file(input_filename)};
const 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 {
std::string input_filename{argv[1]};
std::string output_filename{argv[2]};
const std::string input_filename{argv[1]};
const std::string output_filename{argv[2]};
osmium::io::Reader reader{input_filename};
osmium::io::File output_file{output_filename, "pbf"};
osmium::io::Header header;
const osmium::io::File output_file{output_filename, "pbf"};
const 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
+8 -1
View File
@@ -24,6 +24,11 @@ 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%
@@ -52,7 +57,9 @@ 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
-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
ECHO calling^: %CMAKE_CMD%
%CMAKE_CMD%
+2 -1
View File
@@ -16,8 +16,9 @@ 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 variable for correct PROJ.4 working"
echo "Setting PROJ_LIB/DATA 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
+2 -2
View File
@@ -74,8 +74,8 @@ class AmenityHandler : public osmium::handler::Handler {
c.y += nr.lat();
}
c.x /= nr_list.size();
c.y /= nr_list.size();
c.x /= static_cast<double>(nr_list.size());
c.y /= static_cast<double>(nr_list.size());
return c;
}
+2 -2
View File
@@ -122,11 +122,11 @@ int main(int argc, char* argv[]) {
return 1;
}
osmium::io::File input_file{argv[2]};
const osmium::io::File input_file{argv[2]};
// Configuration for the multipolygon assembler. Here the default settings
// are used, but you could change multiple settings.
osmium::area::Assembler::config_type assembler_config;
const 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.
+2 -2
View File
@@ -153,8 +153,8 @@ int main(int argc, char* argv[]) {
}
// Get input and output file names from command line.
std::string input_file_name{argv[1]};
std::string output_file_name{argv[2]};
const std::string input_file_name{argv[1]};
const std::string output_file_name{argv[2]};
try {
// Initialize Reader
+2 -2
View File
@@ -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.
osmium::io::File input_file{argv[1]};
const 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.)
osmium::MemoryUsage memory;
const osmium::MemoryUsage memory;
std::cout << "\nMemory used: " << memory.peak() << " MBytes\n";
} catch (const std::exception& e) {
+2 -2
View File
@@ -40,11 +40,11 @@ int main(int argc, char* argv[]) {
}
// Get output file name from command line.
std::string output_file_name{argv[1]};
const 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.
osmium::io::File output_file{output_file_name, output_file_name == "-" ? ".opl" : ""};
const 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
+1 -1
View File
@@ -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;
std::string types = argv[2];
const std::string types = argv[2];
if (types.find('n') != std::string::npos) {
read_types |= osmium::osm_entity_bits::node;
}
+7 -7
View File
@@ -165,31 +165,31 @@ int main(int argc, char* argv[]) {
reader.close();
// Write out node, way, and relation offset indexes to disk.
IndexFile nodes_idx{output_dir + "/nodes.idx"};
const IndexFile nodes_idx{output_dir + "/nodes.idx"};
node_index.dump_as_list(nodes_idx.fd());
IndexFile ways_idx{output_dir + "/ways.idx"};
const IndexFile ways_idx{output_dir + "/ways.idx"};
way_index.dump_as_list(ways_idx.fd());
IndexFile relations_idx{output_dir + "/relations.idx"};
const 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();
IndexFile node2way_idx{output_dir + "/node2way.map"};
const IndexFile node2way_idx{output_dir + "/node2way.map"};
map_node2way.dump_as_list(node2way_idx.fd());
map_node2relation.sort();
IndexFile node2relation_idx{output_dir + "/node2rel.map"};
const IndexFile node2relation_idx{output_dir + "/node2rel.map"};
map_node2relation.dump_as_list(node2relation_idx.fd());
map_way2relation.sort();
IndexFile way2relation_idx{output_dir + "/way2rel.map"};
const IndexFile way2relation_idx{output_dir + "/way2rel.map"};
map_way2relation.dump_as_list(way2relation_idx.fd());
map_relation2relation.sort();
IndexFile relation2relation_idx{output_dir + "/rel2rel.map"};
const 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.
osmium::io::File input_file{argv[1]};
const osmium::io::File input_file{argv[1]};
// The output file, force XML OSM file format.
osmium::io::File output_file{argv[2], "osm"};
const osmium::io::File output_file{argv[2], "osm"};
// Initialize Reader for the input file.
// Read only changesets (will ignore nodes, ways, and
+7 -7
View File
@@ -67,8 +67,8 @@ public:
IndexAccess(const IndexAccess&) = delete;
IndexAccess& operator=(const IndexAccess&) = delete;
IndexAccess(IndexAccess&&) = delete;
IndexAccess& operator=(IndexAccess&&) = delete;
IndexAccess(IndexAccess&&) noexcept = delete;
IndexAccess& operator=(IndexAccess&&) noexcept = delete;
virtual ~IndexAccess() noexcept = default;
@@ -106,7 +106,7 @@ public:
~IndexAccessDense() noexcept override = default;
void dump() const override {
index_type index{this->fd()};
const 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 {
index_type index{this->fd()};
const index_type index{this->fd()};
try {
TValue value = index.get(key);
@@ -153,7 +153,7 @@ public:
~IndexAccessSparse() noexcept override = default;
void dump() const override {
index_type index{this->fd()};
const 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()};
element_type elem{key, TValue{}};
const 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.
Options options{argc, argv};
const Options options{argc, argv};
// Open the index file.
const int fd = ::open(options.filename(), O_RDWR);
+2 -2
View File
@@ -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.
osmium::io::File input_file{argv[1]};
const 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 (osmium::memory::Buffer buffer = reader.read()) {
while (const 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.
osmium::io::File input_file{argv[1]};
const 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 (osmium::memory::Buffer buffer = reader.read()) {
while (const osmium::memory::Buffer buffer = reader.read()) {
// Update progress bar for each buffer.
progress.update(reader.offset());
}
+1 -1
View File
@@ -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{uint32_t(zoom), location};
const osmium::geom::Tile tile{static_cast<uint32_t>(zoom), location};
std::cout << "Tile: zoom=" << tile.z << " x=" << tile.x << " y=" << tile.y << "\n";
}
+2 -2
View File
@@ -5,7 +5,7 @@
This file is part of Osmium (https://osmcode.org/libosmium).
Copyright 2013-2022 Jochen Topf <jochen@topf.org> and others (see README).
Copyright 2013-2023 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.
bool okay = create_area(out_buffer, relation, members);
const 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-2022 Jochen Topf <jochen@topf.org> and others (see README).
Copyright 2013-2023 Jochen Topf <jochen@topf.org> and others (see README).
Boost Software License - Version 1.0 - August 17th, 2003
@@ -124,15 +124,6 @@ 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-2022 Jochen Topf <jochen@topf.org> and others (see README).
Copyright 2013-2023 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) {
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());
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());
#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-2022 Jochen Topf <jochen@topf.org> and others (see README).
Copyright 2013-2023 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 (slocation& sl : m_locations) {
for (const 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";
}
std::vector<location_to_ring_map> xrings = create_location_to_ring_map(open_ring_its);
const auto 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());
bool ring_min_is_outer = !outer_ring;
const 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 (slocation& sl : m_locations) {
for (const 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-2022 Jochen Topf <jochen@topf.org> and others (see README).
Copyright 2013-2023 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-2022 Jochen Topf <jochen@topf.org> and others (see README).
Copyright 2013-2023 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[int(m_role)];
return names[static_cast<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 = double(na) / d;
const double ua = static_cast<double>(na) / static_cast<double>(d);
const vec i = p0 + ua * (p1 - p0);
return osmium::Location{int32_t(i.x), int32_t(i.y)};
return osmium::Location{static_cast<int32_t>(i.x), static_cast<int32_t>(i.y)};
}
return osmium::Location{};
@@ -5,7 +5,7 @@
This file is part of Osmium (https://osmcode.org/libosmium).
Copyright 2013-2022 Jochen Topf <jochen@topf.org> and others (see README).
Copyright 2013-2023 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;
int64_t m_sum = 0;
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-2022 Jochen Topf <jochen@topf.org> and others (see README).
Copyright 2013-2023 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)) {
osmium::Location intersection{calculate_intersection(s1, s2)};
const 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-2022 Jochen Topf <jochen@topf.org> and others (see README).
Copyright 2013-2023 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{int64_t(s * v.x), int64_t(s * v.y)};
return vec{static_cast<int64_t>(s * static_cast<double>(v.x)), static_cast<int64_t>(s * static_cast<double>(v.y))};
}
// scale vector
constexpr inline vec operator*(const vec& v, double s) noexcept {
return vec{int64_t(s * v.x), int64_t(s * v.y)};
return vec{static_cast<int64_t>(s * static_cast<double>(v.x)), static_cast<int64_t>(s * static_cast<double>(v.y))};
}
// equality
@@ -5,7 +5,7 @@
This file is part of Osmium (https://osmcode.org/libosmium).
Copyright 2013-2022 Jochen Topf <jochen@topf.org> and others (see README).
Copyright 2013-2023 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-2022 Jochen Topf <jochen@topf.org> and others (see README).
Copyright 2013-2023 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-2022 Jochen Topf <jochen@topf.org> and others (see README).
Copyright 2013-2023 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-2022 Jochen Topf <jochen@topf.org> and others (see README).
Copyright 2013-2023 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-2022 Jochen Topf <jochen@topf.org> and others (see README).
Copyright 2013-2023 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-2022 Jochen Topf <jochen@topf.org> and others (see README).
Copyright 2013-2023 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-2022 Jochen Topf <jochen@topf.org> and others (see README).
Copyright 2013-2023 Jochen Topf <jochen@topf.org> and others (see README).
Boost Software License - Version 1.0 - August 17th, 2003
@@ -75,15 +75,15 @@ namespace osmium {
void set_object(gdalcpp::Feature& feature) {
const char t[2] = {osmium::item_type_to_char(m_object_type), '\0'};
feature.set_field("obj_type", t);
feature.set_field("obj_id", int32_t(m_object_id));
feature.set_field("nodes", int32_t(m_nodes));
feature.set_field("obj_id", static_cast<int32_t>(m_object_id));
feature.set_field("nodes", static_cast<int32_t>(m_nodes));
}
void write_point(const char* problem_type, osmium::object_id_type id1, osmium::object_id_type id2, osmium::Location location) {
gdalcpp::Feature feature{m_layer_perror, m_ogr_factory.create_point(location)};
set_object(feature);
feature.set_field("id1", double(id1));
feature.set_field("id2", double(id2));
feature.set_field("id1", static_cast<double>(id1));
feature.set_field("id2", static_cast<double>(id2));
feature.set_field("problem", problem_type);
feature.add_to_layer();
}
@@ -176,7 +176,7 @@ namespace osmium {
try {
gdalcpp::Feature feature{m_layer_lerror, m_ogr_factory.create_linestring(way)};
set_object(feature);
feature.set_field("id1", int32_t(way.id()));
feature.set_field("id1", static_cast<int32_t>(way.id()));
feature.set_field("id2", 0);
feature.set_field("problem", "way_in_multiple_rings");
feature.add_to_layer();
@@ -192,7 +192,7 @@ namespace osmium {
try {
gdalcpp::Feature feature{m_layer_lerror, m_ogr_factory.create_linestring(way)};
set_object(feature);
feature.set_field("id1", int32_t(way.id()));
feature.set_field("id1", static_cast<int32_t>(way.id()));
feature.set_field("id2", 0);
feature.set_field("problem", "inner_with_same_tags");
feature.add_to_layer();
@@ -208,7 +208,7 @@ namespace osmium {
try {
gdalcpp::Feature feature{m_layer_lerror, m_ogr_factory.create_linestring(way)};
set_object(feature);
feature.set_field("id1", int32_t(way.id()));
feature.set_field("id1", static_cast<int32_t>(way.id()));
feature.set_field("id2", 0);
feature.set_field("problem", "duplicate_way");
feature.add_to_layer();
@@ -229,7 +229,7 @@ namespace osmium {
try {
gdalcpp::Feature feature{m_layer_ways, m_ogr_factory.create_linestring(way)};
set_object(feature);
feature.set_field("way_id", int32_t(way.id()));
feature.set_field("way_id", static_cast<int32_t>(way.id()));
feature.add_to_layer();
} catch (const osmium::geometry_error&) {
// XXX
@@ -5,7 +5,7 @@
This file is part of Osmium (https://osmcode.org/libosmium).
Copyright 2013-2022 Jochen Topf <jochen@topf.org> and others (see README).
Copyright 2013-2023 Jochen Topf <jochen@topf.org> and others (see README).
Boost Software License - Version 1.0 - August 17th, 2003
+1 -1
View File
@@ -5,7 +5,7 @@
This file is part of Osmium (https://osmcode.org/libosmium).
Copyright 2013-2022 Jochen Topf <jochen@topf.org> and others (see README).
Copyright 2013-2023 Jochen Topf <jochen@topf.org> and others (see README).
Boost Software License - Version 1.0 - August 17th, 2003
+1 -1
View File
@@ -5,7 +5,7 @@
This file is part of Osmium (https://osmcode.org/libosmium).
Copyright 2013-2022 Jochen Topf <jochen@topf.org> and others (see README).
Copyright 2013-2023 Jochen Topf <jochen@topf.org> and others (see README).
Boost Software License - Version 1.0 - August 17th, 2003
+1 -1
View File
@@ -5,7 +5,7 @@
This file is part of Osmium (https://osmcode.org/libosmium).
Copyright 2013-2022 Jochen Topf <jochen@topf.org> and others (see README).
Copyright 2013-2023 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-2022 Jochen Topf <jochen@topf.org> and others (see README).
Copyright 2013-2023 Jochen Topf <jochen@topf.org> and others (see README).
Boost Software License - Version 1.0 - August 17th, 2003
@@ -125,8 +125,8 @@ namespace osmium {
if (value_length > osmium::max_osm_string_length) {
throw std::length_error{"OSM tag value is too long"};
}
add_size(append_with_zero(key, osmium::memory::item_size_type(key_length)));
add_size(append_with_zero(value, osmium::memory::item_size_type(value_length)));
add_size(append_with_zero(key, static_cast<osmium::memory::item_size_type>(key_length)));
add_size(append_with_zero(value, static_cast<osmium::memory::item_size_type>(value_length)));
}
/**
@@ -142,8 +142,8 @@ namespace osmium {
if (value.size() > osmium::max_osm_string_length) {
throw std::length_error{"OSM tag value is too long"};
}
add_size(append(key.data(), osmium::memory::item_size_type(key.size()) + 1));
add_size(append(value.data(), osmium::memory::item_size_type(value.size()) + 1));
add_size(append(key.data(), static_cast<osmium::memory::item_size_type>(key.size()) + 1));
add_size(append(value.data(), static_cast<osmium::memory::item_size_type>(value.size()) + 1));
}
/**
@@ -240,8 +240,8 @@ namespace osmium {
if (length > osmium::max_osm_string_length) {
throw std::length_error{"OSM relation member role is too long"};
}
member.set_role_size(osmium::string_size_type(length) + 1);
add_size(append_with_zero(role, osmium::memory::item_size_type(length)));
member.set_role_size(static_cast<osmium::string_size_type>(length) + 1);
add_size(append_with_zero(role, static_cast<osmium::memory::item_size_type>(length)));
add_padding(true);
}
@@ -330,16 +330,16 @@ namespace osmium {
if (length > osmium::max_osm_string_length) {
throw std::length_error{"OSM user name is too long"};
}
comment.set_user_size(osmium::string_size_type(length) + 1);
add_size(append_with_zero(user, osmium::memory::item_size_type(length)));
comment.set_user_size(static_cast<osmium::string_size_type>(length) + 1);
add_size(append_with_zero(user, static_cast<osmium::memory::item_size_type>(length)));
}
void add_text(osmium::ChangesetComment& comment, const char* text, const std::size_t length) {
if (length > std::numeric_limits<osmium::changeset_comment_size_type>::max() - 1) {
throw std::length_error{"OSM changeset comment is too long"};
}
comment.set_text_size(osmium::changeset_comment_size_type(length) + 1);
add_size(append_with_zero(text, osmium::memory::item_size_type(length)));
comment.set_text_size(static_cast<osmium::changeset_comment_size_type>(length) + 1);
add_size(append_with_zero(text, static_cast<osmium::memory::item_size_type>(length)));
add_padding(true);
}
+1 -1
View File
@@ -5,7 +5,7 @@
This file is part of Osmium (https://osmcode.org/libosmium).
Copyright 2013-2022 Jochen Topf <jochen@topf.org> and others (see README).
Copyright 2013-2023 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