Merge branch 'master' into sf-bye-bye-mason
This commit is contained in:
commit
9ee33aff79
30
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
30
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
@ -0,0 +1,30 @@
|
||||
---
|
||||
name: Bug Report
|
||||
about: Report issue with osrm-backend
|
||||
labels: Bug Report
|
||||
---
|
||||
|
||||
# Issue
|
||||
|
||||
Please describe the issue you are seeing with OSRM.
|
||||
Images are a good way to illustrate your problem.
|
||||
|
||||
**Note**: If your issue relates to the demo site (https://map.project-osrm.org) or routing provided on openstreetmap.org, be aware that they use separate [profile settings](https://github.com/fossgis-routing-server/cbf-routing-profiles) from those provided by default in `osrm-backend`.
|
||||
If your issue relates to the demo site or openstreetmap.org behaviour, please check these profiles first to see if they explain the behaviour before creating an issue here.
|
||||
|
||||
# Steps to reproduce
|
||||
|
||||
Please provide the steps required to reproduce your problem.
|
||||
- `osrm-backend` version being used
|
||||
- OSM extract that was processed
|
||||
- Processing commands (e.g. CH vs MLD processing)
|
||||
- Server queries
|
||||
|
||||
If you're reporting an issue with https://map.project-osrm.org, please provide a link to the problematic request.
|
||||
|
||||
# Specifications
|
||||
|
||||
Please provide details of your development environment.
|
||||
- Library/dependency versions
|
||||
- Operating system
|
||||
- Hardware
|
||||
10
.github/ISSUE_TEMPLATE/feature.md
vendored
Normal file
10
.github/ISSUE_TEMPLATE/feature.md
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
---
|
||||
name: Feature Request
|
||||
about: Request a new feature in osrm-backend
|
||||
labels: Feature Request
|
||||
---
|
||||
|
||||
# Feature
|
||||
|
||||
Please describe the feature you would like to see in OSRM.
|
||||
Images are often a good way to illustrate your requested feature.
|
||||
5
.github/ISSUE_TEMPLATE/question.md
vendored
Normal file
5
.github/ISSUE_TEMPLATE/question.md
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
---
|
||||
name: Question
|
||||
about: Ask a question about OSRM
|
||||
labels: question
|
||||
---
|
||||
6
.github/workflows/osrm-backend.yml
vendored
6
.github/workflows/osrm-backend.yml
vendored
@ -88,10 +88,7 @@ jobs:
|
||||
- name: Prepare environment
|
||||
run: |
|
||||
npm ci --ignore-scripts
|
||||
wget https://github.com/muttleyxd/clang-tools-static-binaries/releases/download/master-208096c1/clang-format-10_linux-amd64 -O /usr/local/bin/clang-format-10.0.0
|
||||
echo "8c5c5499d53eb004c81027046098895ba019ff6d020c09f1d49f017d32e0430aaf04a3dcef949528c097d45f0fe1a2d92019a760077e2a347b1fe5f244e05e97 /usr/local/bin/clang-format-10.0.0" | sha512sum --check --status
|
||||
chmod +x /usr/local/bin/clang-format-10.0.0
|
||||
clang-format-10.0.0 --version
|
||||
clang-format-10 --version
|
||||
- name: Run checks
|
||||
run: |
|
||||
./scripts/check_taginfo.py taginfo.json profiles/car.lua
|
||||
@ -701,6 +698,7 @@ jobs:
|
||||
pushd ${OSRM_BUILD_DIR}
|
||||
make --jobs=${JOBS} benchmarks
|
||||
./src/benchmarks/alias-bench
|
||||
./src/benchmarks/json-render-bench ../src/benchmarks/portugal_to_korea.json
|
||||
./src/benchmarks/match-bench ../test/data/ch/monaco.osrm
|
||||
./src/benchmarks/packedvector-bench
|
||||
./src/benchmarks/rtree-bench ../test/data/monaco.osrm.ramIndex ../test/data/monaco.osrm.fileIndex ../test/data/monaco.osrm.nbg_nodes
|
||||
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@ -62,6 +62,7 @@ Thumbs.db
|
||||
/.vs*
|
||||
/*.local.bat
|
||||
/CMakeSettings.json
|
||||
/.cache
|
||||
|
||||
# Jetbrains related files #
|
||||
###########################
|
||||
|
||||
@ -9,6 +9,8 @@
|
||||
- NodeJS:
|
||||
- FIXED: Support `skip_waypoints` in Node bindings [#6060](https://github.com/Project-OSRM/osrm-backend/pull/6060)
|
||||
- Misc:
|
||||
- ADDED: conanbuildinfo.json for easy reading of dependencies [#6388](https://github.com/Project-OSRM/osrm-backend/pull/6388)
|
||||
- CHANGED: Improve performance of JSON rendering. Fix undefined behaviour in JSON numbers formatting. [#6380](https://github.com/Project-OSRM/osrm-backend/pull/6380)
|
||||
- ADDED: Add timestamps for logs. [#6375](https://github.com/Project-OSRM/osrm-backend/pull/6375)
|
||||
- CHANGED: Improve performance of map matching via getPathDistance optimization. [#6378](https://github.com/Project-OSRM/osrm-backend/pull/6378)
|
||||
- CHANGED: Optimize RestrictionParser performance. [#6344](https://github.com/Project-OSRM/osrm-backend/pull/6344)
|
||||
@ -23,8 +25,10 @@
|
||||
- FIXED: Fix bug with reading Set values from Lua scripts. [#6285](https://github.com/Project-OSRM/osrm-backend/pull/6285)
|
||||
- FIXED: Bug in bicycle profile that caused exceptions if there is a highway=bicycle in the data. [#6296](https://github.com/Project-OSRM/osrm-backend/pull/6296)
|
||||
- FIXED: Internal refactoring of identifier types used in data facade [#6044](https://github.com/Project-OSRM/osrm-backend/pull/6044)
|
||||
- CHANGED: Update docs to reflect recent build and dependency changes [#6383](https://github.com/Project-OSRM/osrm-backend/issues/6383)
|
||||
- Build:
|
||||
- REMOVED: Get rid of Mason. [#6387](https://github.com/Project-OSRM/osrm-backend/pull/6387)
|
||||
- CHANGED: Use clang-format from CI base image. [#6391](https://github.com/Project-OSRM/osrm-backend/pull/6391)
|
||||
- ADDED: Build Node bindings on Windows. [#6334](https://github.com/Project-OSRM/osrm-backend/pull/6334)
|
||||
- ADDED: Configure cross-compilation for Apple Silicon. [#6360](https://github.com/Project-OSRM/osrm-backend/pull/6360)
|
||||
- CHANGED: Use apt-get to install Clang on CI. [#6345](https://github.com/Project-OSRM/osrm-backend/pull/6345)
|
||||
@ -63,6 +67,7 @@
|
||||
- FIXED: Fix snapping target locations to ways used in turn restrictions. [#6339](https://github.com/Project-OSRM/osrm-backend/pull/6339)
|
||||
- ADDED: Support OSM traffic signal directions. [#6153](https://github.com/Project-OSRM/osrm-backend/pull/6153)
|
||||
- FIXED: Ensure u-turn exists in intersection view. [#6376](https://github.com/Project-OSRM/osrm-backend/pull/6376)
|
||||
- FIXED: Gracefully handle no-turn intersections in guidance processing. [#6382](https://github.com/Project-OSRM/osrm-backend/issues/6382)
|
||||
- Profile:
|
||||
- CHANGED: Bicycle surface speeds [#6212](https://github.com/Project-OSRM/osrm-backend/pull/6212)
|
||||
- Tools:
|
||||
|
||||
@ -500,7 +500,7 @@ if(ENABLE_CONAN)
|
||||
"lua/${CONAN_LUA_VERSION}"
|
||||
"onetbb/${CONAN_TBB_VERSION}"
|
||||
BASIC_SETUP
|
||||
GENERATORS cmake_find_package
|
||||
GENERATORS cmake_find_package json # json generator generates a conanbuildinfo.json in the build folder so (non-CMake) projects can easily parse OSRM's dependencies
|
||||
KEEP_RPATHS
|
||||
NO_OUTPUT_DIRS
|
||||
OPTIONS boost:filesystem_version=3 # https://stackoverflow.com/questions/73392648/error-with-boost-filesystem-version-in-cmake
|
||||
|
||||
14
README.md
14
README.md
@ -50,7 +50,7 @@ If you want to use the CH pipeline instead replace `osrm-partition` and `osrm-cu
|
||||
|
||||
### Using Docker
|
||||
|
||||
We base our Docker images ([backend](https://hub.docker.com/r/osrm/osrm-backend/), [frontend](https://hub.docker.com/r/osrm/osrm-frontend/)) on Debian and make sure they are as lightweight as possible.
|
||||
We base our Docker images ([backend](https://github.com/Project-OSRM/osrm-backend/pkgs/container/osrm-backend), [frontend](https://hub.docker.com/r/osrm/osrm-frontend/)) on Debian and make sure they are as lightweight as possible. Older backend versions can be found on [Docker Hub](https://hub.docker.com/r/osrm/osrm-backend/).
|
||||
|
||||
Download OpenStreetMap extracts for example from [Geofabrik](http://download.geofabrik.de/)
|
||||
|
||||
@ -65,7 +65,7 @@ The flag `-v "${PWD}:/data"` creates the directory `/data` inside the docker con
|
||||
docker run -t -v "${PWD}:/data" osrm/osrm-backend osrm-partition /data/berlin-latest.osrm
|
||||
docker run -t -v "${PWD}:/data" osrm/osrm-backend osrm-customize /data/berlin-latest.osrm
|
||||
|
||||
Note there is no `berlin-latest.osrm` file, but multiple `berlin-latest.osrm.*` files, i.e. `berlin-latest.osrm` is not file path, but "base" path referring to set of files and there is an option to omit this `.osrm` suffix completely(e.g. `osrm-partition /data/berlin-latest`).
|
||||
Note there is no `berlin-latest.osrm` file, but multiple `berlin-latest.osrm.*` files, i.e. `berlin-latest.osrm` is not file path, but "base" path referring to set of files and there is an option to omit this `.osrm` suffix completely(e.g. `osrm-partition /data/berlin-latest`).
|
||||
|
||||
docker run -t -i -p 5000:5000 -v "${PWD}:/data" osrm/osrm-backend osrm-routed --algorithm mld /data/berlin-latest.osrm
|
||||
|
||||
@ -84,7 +84,7 @@ In case Docker complains about not being able to connect to the Docker daemon ma
|
||||
|
||||
After adding yourself to the `docker` group make sure to log out and back in again with your terminal.
|
||||
|
||||
We support the following images on Docker Cloud:
|
||||
We support the following images in the Container Registry:
|
||||
|
||||
Name | Description
|
||||
-----|------
|
||||
@ -96,7 +96,7 @@ Name | Description
|
||||
|
||||
### Building from Source
|
||||
|
||||
The following targets Ubuntu 16.04.
|
||||
The following targets Ubuntu 22.04.
|
||||
For instructions how to build on different distributions, macOS or Windows see our [Wiki](https://github.com/Project-OSRM/osrm-backend/wiki).
|
||||
|
||||
Install dependencies
|
||||
@ -132,13 +132,13 @@ curl "https://router.project-osrm.org/route/v1/driving/13.388860,52.517037;13.38
|
||||
The Node.js bindings provide read-only access to the routing engine.
|
||||
We provide API documentation and examples [here](docs/nodejs/api.md).
|
||||
|
||||
You will need a modern `libstdc++` toolchain (`>= GLIBCXX_3.4.20`) for binary compatibility if you want to use the pre-built binaries.
|
||||
You will need a modern `libstdc++` toolchain (`>= GLIBCXX_3.4.26`) for binary compatibility if you want to use the pre-built binaries.
|
||||
For older Ubuntu systems you can upgrade your standard library for example with:
|
||||
|
||||
```
|
||||
sudo add-apt-repository ppa:ubuntu-toolchain-r/test
|
||||
sudo apt-get update -y
|
||||
sudo apt-get install -y libstdc++-5-dev
|
||||
sudo apt-get install -y libstdc++-9-dev
|
||||
```
|
||||
|
||||
You can install the Node.js bindings via `npm install osrm` or from this repository either via
|
||||
@ -151,7 +151,7 @@ which will check and use pre-built binaries if they're available for this releas
|
||||
|
||||
to always force building the Node.js bindings from source.
|
||||
|
||||
For usage details have a look [these API docs](docs/nodejs/api.md).
|
||||
For usage details have a look [these API docs](docs/nodejs/api.md).
|
||||
|
||||
An exemplary implementation by a 3rd party with Docker and Node.js can be found [here](https://github.com/door2door-io/osrm-express-server-demo).
|
||||
|
||||
|
||||
@ -1,86 +0,0 @@
|
||||
# Releasing
|
||||
|
||||
Releasing a new version of `node-osrm` is mostly automated using Travis CI.
|
||||
|
||||
The version of `node-osrm` is locked to the same version as `osrm-backend`. Every `node-osrm` should have a `osrm-backend` release of the same version. Of course, only release a `node-osrm` after the release has been tagged in `osrm-backend`.
|
||||
|
||||
These steps all happen on `master`. After the release is out, create a branch using the MAJOR.MINOR version of the release to document code changes made for that version.
|
||||
|
||||
### Steps to release
|
||||
|
||||
1. Update the `osrm_release` field in `package.json` to the corresonding git tag in `osrm-backend.`
|
||||
|
||||
Confirm the desired OSRM branch and commit to `master`.
|
||||
|
||||
1. Bump node-osrm version
|
||||
|
||||
Update the `CHANGELOG.md` and the `package.json` version if needed.
|
||||
|
||||
1. Check that Travis CI [builds are passing](https://travis-ci.org/Project-OSRM/node-osrm) for the latest commit on `master`.
|
||||
|
||||
1. Publishing binaries
|
||||
|
||||
If travis builds are passing then it's time to publish binaries by committing with a message containing `[publish binary]`. Use an empty commit for this.
|
||||
|
||||
```
|
||||
git commit --allow-empty -m "[publish binary] vMAJOR.MINOR.PATCH"
|
||||
```
|
||||
|
||||
1. Test
|
||||
|
||||
Locally you can now test binaries. Cleanup, re-install, and run the tests like:
|
||||
|
||||
```
|
||||
make clean
|
||||
npm install # will pull remote binaries
|
||||
npm ls # confirm deps are correct
|
||||
make test
|
||||
```
|
||||
|
||||
1. Tag
|
||||
|
||||
Once binaries are published for Linux and OS X then its time to tag a new release and add the changelog to the tag:
|
||||
|
||||
```
|
||||
git tag vMAJOR.MINOR.PATCH -a
|
||||
git push --tags
|
||||
```
|
||||
|
||||
1. Publish node-osrm. **we only do this for stable releases**
|
||||
|
||||
First ensure your local `node-pre-gyp` is up to date:
|
||||
|
||||
```
|
||||
npm ls
|
||||
```
|
||||
|
||||
This is important because it is bundled during packaging.
|
||||
|
||||
If you see any errors then do:
|
||||
|
||||
```
|
||||
rm -rf node_modules/node-pre-gyp
|
||||
npm install node-pre-gyp
|
||||
```
|
||||
|
||||
Now we're ready to publish `node-osrm` to <https://www.npmjs.org/package/osrm>:
|
||||
|
||||
```
|
||||
npm publish
|
||||
```
|
||||
|
||||
Dependent apps can now pull from the npm registry like:
|
||||
|
||||
```
|
||||
"dependencies": {
|
||||
"osrm": "^MAJOR.MINOR.PATCH"
|
||||
}
|
||||
```
|
||||
|
||||
Or can still pull from the github tag like:
|
||||
|
||||
```
|
||||
"dependencies": {
|
||||
"osrm": "https://github.com/Project-OSRM/node-osrm/archive/vMAJOR.MINOR.PATCH.tar.gz"
|
||||
}
|
||||
```
|
||||
@ -44,16 +44,16 @@ We may introduce forward-compatible changes: query parameters and response prope
|
||||
1. Check out the appropriate release branch `x.y`
|
||||
2. Make sure `CHANGELOG.md` is up to date.
|
||||
3. Make sure the `package.json` on branch `x.y` has been committed.
|
||||
4. Make sure all tests are passing (e.g. Travis CI gives you a :green_apple:)
|
||||
4. Make sure all tests are passing (e.g. Github Actions CI gives you a :heavy_check_mark:)
|
||||
5. Use an annotated tag to mark the release: `git tag vx.y.z -a` Body of the tag description should be the changelog entries. Commit should be one in which the `package.json` version matches the version you want to release.
|
||||
6. Use `npm run docs` to generate the API documentation. Copy `build/docs/*` to `https://github.com/Project-OSRM/project-osrm.github.com` in the `docs/vN.N.N/api` directory
|
||||
7. Push tags and commits: `git push; git push --tags`
|
||||
8. On https://github.com/Project-OSRM/osrm-backend/releases press `Draft a new release`,
|
||||
write the release tag `vx.y.z` in the `Tag version` field, write the changelog entries in the `Describe this release` field
|
||||
and press `Publish release`. Note that Travis deployments will create a release when publishing node binaries, so the release
|
||||
and press `Publish release`. Note that Github Actions CI deployments will create a release when publishing node binaries, so the release
|
||||
may already exist. In which case the description should be updated with the changelog entries.
|
||||
9. If not a release-candidate: Write a mailing-list post to osrm-talk@openstreetmap.org to announce the release
|
||||
10. Wait until the travis build has been completed and check if the node binaries were published by doing:
|
||||
10. Wait until the Github Actions build has been completed and check if the node binaries were published by doing:
|
||||
`rm -rf node_modules && npm install` locally.
|
||||
11. For final releases run `npm publish` or `npm publish --tag next` for release candidates.
|
||||
12. Bump version in `package.json` to `{MAJOR}.{MINOR+1}.0-latest.1` on the `master` branch after the release.
|
||||
12. Bump version in `package.json` to `{MAJOR}.{MINOR+1}.0-unreleased` on the `master` branch after the release.
|
||||
|
||||
@ -1,80 +1,31 @@
|
||||
# Building OSRM for Windows
|
||||
|
||||
There is experimental support for building OSRM on Windows.
|
||||
|
||||
## Dependencies
|
||||
|
||||
Get a decent Windows with decent Visual Studio (14 at least for C++11 support). The published binaries are build with
|
||||
VS2019 and Windows SDK8.1.
|
||||
You will need a modern Windows development stack (e.g. Visual Studio 17). The published binaries are built with
|
||||
[Windows Server 2022](https://github.com/actions/runner-images/blob/main/images/win/Windows2022-Readme.md) Github hosted runners.
|
||||
|
||||
In case you are using [prepacked Windows VM with VS2019](https://developer.microsoft.com/en-us/windows/downloads/virtual-machines/), you
|
||||
have to install [Windows SDK 8.1](https://go.microsoft.com/fwlink/p/?LinkId=323507)
|
||||
Dependencies are managed via [Conan](https://conan.io/) and built with [CMake](https://cmake.org/).
|
||||
|
||||
Prepare directories for dependencies, build and target file location.Target directory ($target starting from that moment) should have /include and /lib subdirectories.
|
||||
## Building
|
||||
|
||||
### Bzip2
|
||||
```bat
|
||||
cmake -DENABLE_CONAN=ON -DENABLE_NODE_BINDINGS=ON -DCMAKE_BUILD_TYPE=%CONFIGURATION% -G "Visual Studio 17 2022" ..
|
||||
|
||||
1. Download from https://sourceware.org/pub/bzip2/bzip2-1.0.8.tar.gz
|
||||
2. Start 'x64 Native Tools Command Prompt for VS2019' and change directory to unpacked source tree.
|
||||
3. Issue `nmake /f makefile.msc`
|
||||
4. Copy bzlib.h to $target\include and libbz2.lib to $target\lib
|
||||
msbuild OSRM.sln ^
|
||||
/p:Configuration=%CONFIGURATION% ^
|
||||
/p:Platform=x64 ^
|
||||
/t:rebuild ^
|
||||
/p:BuildInParallel=true ^
|
||||
/m:%NUMBER_OF_PROCESSORS% ^
|
||||
/toolsversion:Current ^
|
||||
/clp:Verbosity=normal ^
|
||||
/nologo
|
||||
```
|
||||
|
||||
### ZLib
|
||||
|
||||
1. Download https://www.zlib.net/zlib-1.2.11.tar.gz
|
||||
2. Start 'x64 Native Tools Command Prompt for VS2019' and change directory to unpacked source tree.
|
||||
3. Switch to `contrib\vstudio\vc14`
|
||||
4. If needed, open `zlibvc.sln` with Visual Studio and retarget to your version of compiler and SDK.
|
||||
5. Issue `msbuild zlibvc.sln /p:BuildInParallel=true /p:Configuration=Release /p:Platform=x64 /m:<Number of cpu cores>`
|
||||
6. Copy x64\ZlibStatRelease\zlibstat.lib to $target\lib\libz.lib, copy zlib.h and zconf.h to $target\include
|
||||
|
||||
### ICU
|
||||
|
||||
1. Download and unpack.
|
||||
* https://github.com/unicode-org/icu/releases/download/release-66-1/icu4c-66_1-src.zip
|
||||
* https://github.com/unicode-org/icu/releases/download/release-66-1/icu4c-66_1-data.zip
|
||||
2. Do retarget if neededby openinig .\source\allinone\allinone.sln and editing projects
|
||||
3. Start 'x64 Native Tools Command Prompt for VS2019' and change directory to unpacked source tree.
|
||||
4. Run build:
|
||||
msbuild .\source\allinone\allinone.sln /nologo /p:BuildInParallel=true /p:Configuration=Release /p:Platform=x64 /m:<Number of cpu cores>
|
||||
5. Copy lib64\*.lib to $target\lib, copy include contents to $target\include
|
||||
6. Copy bin64\*dll to any dir withing your $PATH. At the same time copy them to $target\lib
|
||||
|
||||
### Boost
|
||||
|
||||
1. Download and unpack https://dl.bintray.com/boostorg/release/1.73.0/source/boost_1_73_0.zip
|
||||
2. Start 'x64 Native Tools Command Prompt for VS2019' and change directory to unpacked source tree.
|
||||
3. Build b2:
|
||||
bootstrap.bat --with-toolset=msvc-14.2
|
||||
4. Build boost:
|
||||
b2 -a -d release state --build-type=minimal toolset=msvc-14.2 -q runtime-link=shared link=static address-model=64 --with-iostreams --with-test --with-thread --with-filesystem --with-date_time --with-system --with-program_options --with-regex --disable-filesystem2 -sHAVE_ICU=1 include=<target>\include library-path=<target>\lib -sZLIB_SOURCE=<builddir>/zlib -zBZIP2_BINARY=libbz2 -sBZIP2_INCLUDE=<target>\include -sBZIP2_LIBPATH=<target>\lib -sICU_ICUUC_NAME=icuuc -sICU_ICUDT_NAME=icudt -sICU_ICUIN_NAME=icuin -sBUILD=boost_unit_test_framework -j<number of cpu cores>
|
||||
5. Copy `boost` subdirectory to <target>\include and contents of `stage` to <target>\lib
|
||||
|
||||
### Expat
|
||||
|
||||
1. Download and unpack https://github.com/libexpat/libexpat/archive/R_2_2_9.zip
|
||||
2. Start 'x64 Native Tools Command Prompt for VS2019' and change directory to unpacked source tree.
|
||||
3. Configure build my calling cmake:
|
||||
mkdir expat\build
|
||||
cd expat\build
|
||||
cmake -G"Visual Studio 16 2019" -DCMAKE_BUILD_TYPE=Release -DEXPAT_MSVC_STATIC_CRT=ON -DEXPAT_BUILD_EXAMPLES=OFF -DEXPAT_BUILD_TESTS=OFF -DEXPAT_SHARED_LIBS=OFF ..
|
||||
4. Build expat: `msbuild expat.sln /nologo /p:Configuration=Release /p:Platform=x64`
|
||||
5. Copy `Release\libexpat.*` to <target>/lib. Copy `expat/lib/expat.h` and `expat/lib/expat_external.h` to <target>/include
|
||||
|
||||
### LUA
|
||||
|
||||
1. Download and unpack https://www.lua.org/ftp/lua-5.3.5.tar.gz
|
||||
2. Start 'x64 Native Tools Command Prompt for VS2019' and change directory to unpacked source tree.
|
||||
3. Lua doesn't have native MSVC support, so you have to compile it by hand:
|
||||
cd src
|
||||
cl /MD /O2 /c /DLUA_COMPAT_5_2 *.c
|
||||
ren lua.obj lua.o
|
||||
ren luac.obj luac.o
|
||||
link /LIB /OUT:lua5.3.5.dll *.obj
|
||||
4. Copy `lua5.3.5.lib` to <target>/lib. Copy `lua.h`,`lauxlib,h`,`lua.hpp`,`lualib.h`,`luaconf.h` to <target>/include
|
||||
|
||||
### TBB
|
||||
|
||||
1. Download and unpack https://github.com/oneapi-src/oneTBB/archive/v2020.2.zip
|
||||
2. Retarget by opening build\vs2013\makefile.sln
|
||||
3. Start 'x64 Native Tools Command Prompt for VS2019' and change directory to unpacked source tree.
|
||||
4. Switch to build\vs2013 and build: `msbuild makefle.sln /nologo /p:Configuration=Release /p:Platform=x64`
|
||||
5. Copy x64/Release/*.{dll,lib} files to <target>/lib and copy contents of include directory to <target>/include
|
||||
|
||||
@ -67,3 +67,37 @@ Feature: Features related to bugs
|
||||
When I route I should get
|
||||
| waypoints | route | intersections |
|
||||
| a,c | Pear to Merrit,Merritt to Apricot,Merritt to Apricot | true:0;true:0 false:180;true:180 |
|
||||
|
||||
|
||||
# https://github.com/Project-OSRM/osrm-backend/issues/6373
|
||||
Scenario: Segregated intersection with no second intersection turns
|
||||
Given the node map
|
||||
"""
|
||||
a b
|
||||
| |
|
||||
c--d--e--f
|
||||
| |
|
||||
g--h--i--j
|
||||
|
||||
"""
|
||||
|
||||
And the ways
|
||||
| nodes | oneway | lanes | turn:lanes |
|
||||
| dc | yes | 4 | |
|
||||
| ed | yes | 4 | |
|
||||
| fe | yes | 3 | |
|
||||
| gh | yes | 4 | left\|left\|through\|through;right |
|
||||
| hi | yes | 2 | |
|
||||
| ij | yes | 3 | |
|
||||
| ie | yes | 4 | |
|
||||
| eb | yes | 2 | |
|
||||
| ad | yes | 4 | reverse\|right\|right\|right |
|
||||
| dh | yes | | |
|
||||
|
||||
And the relations
|
||||
| type | way:from | way:to | node:via | restriction |
|
||||
| restriction | dh | hi | h | no_left_turn |
|
||||
|
||||
And the data has been saved to disk
|
||||
When I try to run "osrm-extract {osm_file} --profile {profile_file}"
|
||||
Then it should exit successfully
|
||||
|
||||
@ -115,4 +115,4 @@ Feature: Annotations
|
||||
|
||||
When I route I should get
|
||||
| from | to | route | a:speed | a:distance | a:duration | a:nodes |
|
||||
| a | c | abc,abc | 10:10 | 249.987619:299.962882 | 25:30 | 1:2:3 |
|
||||
| a | c | abc,abc | 10:10 | 249.987618946:299.962882039 | 25:30 | 1:2:3 |
|
||||
|
||||
@ -809,7 +809,7 @@ Feature: Basic Map Matching
|
||||
|
||||
# These should have the same weights/duration in either direction
|
||||
When I match I should get
|
||||
| trace | geometry | a:distance | a:duration | a:weight | duration |
|
||||
| 2345 | 1.00018,1,1.000314,1 | 14.914666 | 1.4 | 1.4 | 1.4 |
|
||||
| 4321 | 1.00027,1,1.000135,1 | 15.02597 | 1.5 | 1.5 | 1.5 |
|
||||
| trace | geometry | a:distance | a:duration | a:weight | duration |
|
||||
| 2345 | 1.00018,1,1.000314,1 | 14.914666491 | 1.4 | 1.4 | 1.4 |
|
||||
| 4321 | 1.00027,1,1.000135,1 | 15.025969972 | 1.5 | 1.5 | 1.5 |
|
||||
|
||||
|
||||
@ -570,7 +570,7 @@ Feature: Snapping at intersections
|
||||
| a,f,k | ac,cf,cf,fj,kj,kj | 132.8s | 132.8 |
|
||||
| k,f | ik,fi,fi | 54.3s | 54.3 |
|
||||
| f,a | ef,ae,ae | 66.6s | 66.6 |
|
||||
| k,f,a | kj,fj,fj,ef,ae,ae | 141.4s | 141.4 |
|
||||
| k,f,a | kj,fj,fj,ef,ae,ae | 141.399999999s | 141.399999999 |
|
||||
|
||||
When I request a travel time matrix I should get
|
||||
| | a | f | k |
|
||||
@ -626,4 +626,4 @@ Feature: Snapping at intersections
|
||||
| a,f,k | ad,df,df,fj,kj,kj | 105.6s | 105.6 |
|
||||
| k,f | ik,fi,fi | 54.3s | 54.3 |
|
||||
| f,a | ef,ae,ae | 66.6s | 66.6 |
|
||||
| k,f,a | ik,fi,fi,ef,ae,ae | 120.9s | 120.9 |
|
||||
| k,f,a | ik,fi,fi,ef,ae,ae | 120.899999999s | 120.899999999 |
|
||||
|
||||
@ -52,11 +52,11 @@ Feature: Weight tests
|
||||
| abc |
|
||||
|
||||
When I route I should get
|
||||
| waypoints | route | distances | weights | times | a:distance | a:duration | a:weight | a:speed |
|
||||
| s,t | abc,abc | 20m,0m | 2,0 | 2s,0s | 20.034627 | 2 | 2 | 10 |
|
||||
| t,s | abc,abc | 20m,0m | 2,0 | 2s,0s | 20.034627 | 2 | 2 | 10 |
|
||||
| s,e | abc,abc | 40m,0m | 3.9,0 | 3.9s,0s | 29.940636:10.017313 | 3:0.9 | 3:0.9 | 10:11.1 |
|
||||
| e,s | abc,abc | 40m,0m | 3.9,0 | 3.9s,0s | 10.017313:29.940636 | 0.9:3 | 0.9:3 | 11.1:10 |
|
||||
| waypoints | route | distances | weights | times | a:distance | a:duration | a:weight | a:speed |
|
||||
| s,t | abc,abc | 20m,0m | 2,0 | 2s,0s | 20.034626629 | 2 | 2 | 10 |
|
||||
| t,s | abc,abc | 20m,0m | 2,0 | 2s,0s | 20.034626629 | 2 | 2 | 10 |
|
||||
| s,e | abc,abc | 40m,0m | 3.9,0 | 3.9s,0s | 29.940636463:10.017313314 | 3:0.9 | 3:0.9 | 10:11.1 |
|
||||
| e,s | abc,abc | 40m,0m | 3.9,0 | 3.9s,0s | 10.017313314:29.940636463 | 0.9:3 | 0.9:3 | 11.1:10 |
|
||||
|
||||
|
||||
Scenario: Step weights -- way_function: fail if no weight or weight_per_meter property
|
||||
|
||||
@ -5,13 +5,14 @@
|
||||
#include <iterator>
|
||||
#include <string>
|
||||
|
||||
using osrm::util::escape_JSON;
|
||||
using osrm::util::EscapeJSONString;
|
||||
|
||||
extern "C" int LLVMFuzzerTestOneInput(const unsigned char *data, unsigned long size)
|
||||
{
|
||||
const std::string in(reinterpret_cast<const char *>(data), size);
|
||||
|
||||
const auto escaped = escape_JSON(in);
|
||||
std::string escaped;
|
||||
EscapeJSONString(in, escaped);
|
||||
escape(escaped.data());
|
||||
|
||||
return 0;
|
||||
|
||||
@ -60,8 +60,8 @@ struct V8Renderer
|
||||
|
||||
inline void renderToV8(v8::Local<v8::Value> &out, const osrm::json::Object &object)
|
||||
{
|
||||
osrm::json::Value value = object;
|
||||
mapbox::util::apply_visitor(V8Renderer(out), value);
|
||||
V8Renderer renderer(out);
|
||||
renderer(object);
|
||||
}
|
||||
} // namespace node_osrm
|
||||
|
||||
|
||||
@ -1,49 +0,0 @@
|
||||
#ifndef CAST_HPP
|
||||
#define CAST_HPP
|
||||
|
||||
#include <iomanip>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
|
||||
#include <boost/algorithm/string/classification.hpp>
|
||||
#include <boost/algorithm/string/trim.hpp>
|
||||
|
||||
namespace osrm
|
||||
{
|
||||
namespace util
|
||||
{
|
||||
|
||||
namespace cast
|
||||
{
|
||||
template <typename Enumeration>
|
||||
inline auto enum_to_underlying(Enumeration const value) ->
|
||||
typename std::underlying_type<Enumeration>::type
|
||||
{
|
||||
return static_cast<typename std::underlying_type<Enumeration>::type>(value);
|
||||
}
|
||||
|
||||
template <typename T, int Precision = 6> inline std::string to_string_with_precision(const T x)
|
||||
{
|
||||
static_assert(std::is_arithmetic<T>::value, "integral or floating point type required");
|
||||
|
||||
std::ostringstream out;
|
||||
out << std::fixed << std::setprecision(Precision) << x;
|
||||
auto rv = out.str();
|
||||
|
||||
// Javascript has no separation of float / int, digits without a '.' are integral typed
|
||||
// X.Y.0 -> X.Y
|
||||
// X.0 -> X
|
||||
boost::trim_right_if(rv, boost::is_any_of("0"));
|
||||
boost::trim_right_if(rv, boost::is_any_of("."));
|
||||
// Note:
|
||||
// - assumes the locale to use '.' as digit separator
|
||||
// - this is not identical to: trim_right_if(rv, is_any_of('0 .'))
|
||||
|
||||
return rv;
|
||||
}
|
||||
} // namespace cast
|
||||
} // namespace util
|
||||
} // namespace osrm
|
||||
|
||||
#endif // CAST_HPP
|
||||
@ -1,520 +0,0 @@
|
||||
#ifndef IEEE754_HPP
|
||||
#define IEEE754_HPP
|
||||
/**
|
||||
Copyright (C) 2014 Milo Yip
|
||||
|
||||
Imported from:
|
||||
https://github.com/miloyip/dtoa-benchmark/blob/c4020c62754950d38a1aaaed2975b05b441d1e7d/src/milo/dtoa_milo.h
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
**/
|
||||
|
||||
#include <assert.h>
|
||||
#include <math.h>
|
||||
#include <memory.h>
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#include "rapidjson/msinttypes/stdint.h"
|
||||
#include <intrin.h>
|
||||
#else
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
|
||||
#define UINT64_C2(h, l) ((static_cast<uint64_t>(h) << 32) | static_cast<uint64_t>(l))
|
||||
|
||||
namespace osrm
|
||||
{
|
||||
namespace util
|
||||
{
|
||||
namespace ieee754
|
||||
{
|
||||
|
||||
struct DiyFp
|
||||
{
|
||||
DiyFp() {}
|
||||
|
||||
DiyFp(uint64_t f, int e) : f(f), e(e) {}
|
||||
|
||||
DiyFp(double d)
|
||||
{
|
||||
union
|
||||
{
|
||||
double d;
|
||||
uint64_t u64;
|
||||
} u = {d};
|
||||
|
||||
int biased_e = (u.u64 & kDpExponentMask) >> kDpSignificandSize;
|
||||
uint64_t significand = (u.u64 & kDpSignificandMask);
|
||||
if (biased_e != 0)
|
||||
{
|
||||
f = significand + kDpHiddenBit;
|
||||
e = biased_e - kDpExponentBias;
|
||||
}
|
||||
else
|
||||
{
|
||||
f = significand;
|
||||
e = kDpMinExponent + 1;
|
||||
}
|
||||
}
|
||||
|
||||
DiyFp operator-(const DiyFp &rhs) const
|
||||
{
|
||||
assert(e == rhs.e);
|
||||
assert(f >= rhs.f);
|
||||
return DiyFp(f - rhs.f, e);
|
||||
}
|
||||
|
||||
DiyFp operator*(const DiyFp &rhs) const
|
||||
{
|
||||
#if defined(_MSC_VER) && defined(_M_AMD64)
|
||||
uint64_t h;
|
||||
uint64_t l = _umul128(f, rhs.f, &h);
|
||||
if (l & (uint64_t(1) << 63)) // rounding
|
||||
h++;
|
||||
return DiyFp(h, e + rhs.e + 64);
|
||||
#elif (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) && defined(__x86_64__)
|
||||
__extension__ using uint128 = unsigned __int128;
|
||||
uint128 p = static_cast<uint128>(f) * static_cast<uint128>(rhs.f);
|
||||
uint64_t h = p >> 64;
|
||||
uint64_t l = static_cast<uint64_t>(p);
|
||||
if (l & (uint64_t(1) << 63)) // rounding
|
||||
h++;
|
||||
return DiyFp(h, e + rhs.e + 64);
|
||||
#else
|
||||
const uint64_t M32 = 0xFFFFFFFF;
|
||||
const uint64_t a = f >> 32;
|
||||
const uint64_t b = f & M32;
|
||||
const uint64_t c = rhs.f >> 32;
|
||||
const uint64_t d = rhs.f & M32;
|
||||
const uint64_t ac = a * c;
|
||||
const uint64_t bc = b * c;
|
||||
const uint64_t ad = a * d;
|
||||
const uint64_t bd = b * d;
|
||||
uint64_t tmp = (bd >> 32) + (ad & M32) + (bc & M32);
|
||||
tmp += 1U << 31; /// mult_round
|
||||
return DiyFp(ac + (ad >> 32) + (bc >> 32) + (tmp >> 32), e + rhs.e + 64);
|
||||
#endif
|
||||
}
|
||||
|
||||
DiyFp Normalize() const
|
||||
{
|
||||
#if defined(_MSC_VER) && defined(_M_AMD64)
|
||||
unsigned long index;
|
||||
_BitScanReverse64(&index, f);
|
||||
return DiyFp(f << (63 - index), e - (63 - index));
|
||||
#elif defined(__GNUC__)
|
||||
int s = __builtin_clzll(f);
|
||||
return DiyFp(f << s, e - s);
|
||||
#else
|
||||
DiyFp res = *this;
|
||||
while (!(res.f & kDpHiddenBit))
|
||||
{
|
||||
res.f <<= 1;
|
||||
res.e--;
|
||||
}
|
||||
res.f <<= (kDiySignificandSize - kDpSignificandSize - 1);
|
||||
res.e = res.e - (kDiySignificandSize - kDpSignificandSize - 1);
|
||||
return res;
|
||||
#endif
|
||||
}
|
||||
|
||||
DiyFp NormalizeBoundary() const
|
||||
{
|
||||
#if defined(_MSC_VER) && defined(_M_AMD64)
|
||||
unsigned long index;
|
||||
_BitScanReverse64(&index, f);
|
||||
return DiyFp(f << (63 - index), e - (63 - index));
|
||||
#else
|
||||
DiyFp res = *this;
|
||||
while (!(res.f & (kDpHiddenBit << 1)))
|
||||
{
|
||||
res.f <<= 1;
|
||||
res.e--;
|
||||
}
|
||||
res.f <<= (kDiySignificandSize - kDpSignificandSize - 2);
|
||||
res.e = res.e - (kDiySignificandSize - kDpSignificandSize - 2);
|
||||
return res;
|
||||
#endif
|
||||
}
|
||||
|
||||
void NormalizedBoundaries(DiyFp *minus, DiyFp *plus) const
|
||||
{
|
||||
DiyFp pl = DiyFp((f << 1) + 1, e - 1).NormalizeBoundary();
|
||||
DiyFp mi = (f == kDpHiddenBit) ? DiyFp((f << 2) - 1, e - 2) : DiyFp((f << 1) - 1, e - 1);
|
||||
mi.f <<= mi.e - pl.e;
|
||||
mi.e = pl.e;
|
||||
*plus = pl;
|
||||
*minus = mi;
|
||||
}
|
||||
|
||||
static const int kDiySignificandSize = 64;
|
||||
static const int kDpSignificandSize = 52;
|
||||
static const int kDpExponentBias = 0x3FF + kDpSignificandSize;
|
||||
static const int kDpMinExponent = -kDpExponentBias;
|
||||
static const uint64_t kDpExponentMask = UINT64_C2(0x7FF00000, 0x00000000);
|
||||
static const uint64_t kDpSignificandMask = UINT64_C2(0x000FFFFF, 0xFFFFFFFF);
|
||||
static const uint64_t kDpHiddenBit = UINT64_C2(0x00100000, 0x00000000);
|
||||
|
||||
uint64_t f;
|
||||
int e;
|
||||
};
|
||||
|
||||
inline DiyFp GetCachedPower(int e, int *K)
|
||||
{
|
||||
// 10^-348, 10^-340, ..., 10^340
|
||||
static const uint64_t kCachedPowers_F[] = {
|
||||
UINT64_C2(0xfa8fd5a0, 0x081c0288), UINT64_C2(0xbaaee17f, 0xa23ebf76),
|
||||
UINT64_C2(0x8b16fb20, 0x3055ac76), UINT64_C2(0xcf42894a, 0x5dce35ea),
|
||||
UINT64_C2(0x9a6bb0aa, 0x55653b2d), UINT64_C2(0xe61acf03, 0x3d1a45df),
|
||||
UINT64_C2(0xab70fe17, 0xc79ac6ca), UINT64_C2(0xff77b1fc, 0xbebcdc4f),
|
||||
UINT64_C2(0xbe5691ef, 0x416bd60c), UINT64_C2(0x8dd01fad, 0x907ffc3c),
|
||||
UINT64_C2(0xd3515c28, 0x31559a83), UINT64_C2(0x9d71ac8f, 0xada6c9b5),
|
||||
UINT64_C2(0xea9c2277, 0x23ee8bcb), UINT64_C2(0xaecc4991, 0x4078536d),
|
||||
UINT64_C2(0x823c1279, 0x5db6ce57), UINT64_C2(0xc2109436, 0x4dfb5637),
|
||||
UINT64_C2(0x9096ea6f, 0x3848984f), UINT64_C2(0xd77485cb, 0x25823ac7),
|
||||
UINT64_C2(0xa086cfcd, 0x97bf97f4), UINT64_C2(0xef340a98, 0x172aace5),
|
||||
UINT64_C2(0xb23867fb, 0x2a35b28e), UINT64_C2(0x84c8d4df, 0xd2c63f3b),
|
||||
UINT64_C2(0xc5dd4427, 0x1ad3cdba), UINT64_C2(0x936b9fce, 0xbb25c996),
|
||||
UINT64_C2(0xdbac6c24, 0x7d62a584), UINT64_C2(0xa3ab6658, 0x0d5fdaf6),
|
||||
UINT64_C2(0xf3e2f893, 0xdec3f126), UINT64_C2(0xb5b5ada8, 0xaaff80b8),
|
||||
UINT64_C2(0x87625f05, 0x6c7c4a8b), UINT64_C2(0xc9bcff60, 0x34c13053),
|
||||
UINT64_C2(0x964e858c, 0x91ba2655), UINT64_C2(0xdff97724, 0x70297ebd),
|
||||
UINT64_C2(0xa6dfbd9f, 0xb8e5b88f), UINT64_C2(0xf8a95fcf, 0x88747d94),
|
||||
UINT64_C2(0xb9447093, 0x8fa89bcf), UINT64_C2(0x8a08f0f8, 0xbf0f156b),
|
||||
UINT64_C2(0xcdb02555, 0x653131b6), UINT64_C2(0x993fe2c6, 0xd07b7fac),
|
||||
UINT64_C2(0xe45c10c4, 0x2a2b3b06), UINT64_C2(0xaa242499, 0x697392d3),
|
||||
UINT64_C2(0xfd87b5f2, 0x8300ca0e), UINT64_C2(0xbce50864, 0x92111aeb),
|
||||
UINT64_C2(0x8cbccc09, 0x6f5088cc), UINT64_C2(0xd1b71758, 0xe219652c),
|
||||
UINT64_C2(0x9c400000, 0x00000000), UINT64_C2(0xe8d4a510, 0x00000000),
|
||||
UINT64_C2(0xad78ebc5, 0xac620000), UINT64_C2(0x813f3978, 0xf8940984),
|
||||
UINT64_C2(0xc097ce7b, 0xc90715b3), UINT64_C2(0x8f7e32ce, 0x7bea5c70),
|
||||
UINT64_C2(0xd5d238a4, 0xabe98068), UINT64_C2(0x9f4f2726, 0x179a2245),
|
||||
UINT64_C2(0xed63a231, 0xd4c4fb27), UINT64_C2(0xb0de6538, 0x8cc8ada8),
|
||||
UINT64_C2(0x83c7088e, 0x1aab65db), UINT64_C2(0xc45d1df9, 0x42711d9a),
|
||||
UINT64_C2(0x924d692c, 0xa61be758), UINT64_C2(0xda01ee64, 0x1a708dea),
|
||||
UINT64_C2(0xa26da399, 0x9aef774a), UINT64_C2(0xf209787b, 0xb47d6b85),
|
||||
UINT64_C2(0xb454e4a1, 0x79dd1877), UINT64_C2(0x865b8692, 0x5b9bc5c2),
|
||||
UINT64_C2(0xc83553c5, 0xc8965d3d), UINT64_C2(0x952ab45c, 0xfa97a0b3),
|
||||
UINT64_C2(0xde469fbd, 0x99a05fe3), UINT64_C2(0xa59bc234, 0xdb398c25),
|
||||
UINT64_C2(0xf6c69a72, 0xa3989f5c), UINT64_C2(0xb7dcbf53, 0x54e9bece),
|
||||
UINT64_C2(0x88fcf317, 0xf22241e2), UINT64_C2(0xcc20ce9b, 0xd35c78a5),
|
||||
UINT64_C2(0x98165af3, 0x7b2153df), UINT64_C2(0xe2a0b5dc, 0x971f303a),
|
||||
UINT64_C2(0xa8d9d153, 0x5ce3b396), UINT64_C2(0xfb9b7cd9, 0xa4a7443c),
|
||||
UINT64_C2(0xbb764c4c, 0xa7a44410), UINT64_C2(0x8bab8eef, 0xb6409c1a),
|
||||
UINT64_C2(0xd01fef10, 0xa657842c), UINT64_C2(0x9b10a4e5, 0xe9913129),
|
||||
UINT64_C2(0xe7109bfb, 0xa19c0c9d), UINT64_C2(0xac2820d9, 0x623bf429),
|
||||
UINT64_C2(0x80444b5e, 0x7aa7cf85), UINT64_C2(0xbf21e440, 0x03acdd2d),
|
||||
UINT64_C2(0x8e679c2f, 0x5e44ff8f), UINT64_C2(0xd433179d, 0x9c8cb841),
|
||||
UINT64_C2(0x9e19db92, 0xb4e31ba9), UINT64_C2(0xeb96bf6e, 0xbadf77d9),
|
||||
UINT64_C2(0xaf87023b, 0x9bf0ee6b)};
|
||||
static const int16_t kCachedPowers_E[] = {
|
||||
-1220, -1193, -1166, -1140, -1113, -1087, -1060, -1034, -1007, -980, -954, -927, -901,
|
||||
-874, -847, -821, -794, -768, -741, -715, -688, -661, -635, -608, -582, -555,
|
||||
-529, -502, -475, -449, -422, -396, -369, -343, -316, -289, -263, -236, -210,
|
||||
-183, -157, -130, -103, -77, -50, -24, 3, 30, 56, 83, 109, 136,
|
||||
162, 189, 216, 242, 269, 295, 322, 348, 375, 402, 428, 455, 481,
|
||||
508, 534, 561, 588, 614, 641, 667, 694, 720, 747, 774, 800, 827,
|
||||
853, 880, 907, 933, 960, 986, 1013, 1039, 1066};
|
||||
|
||||
// int k = static_cast<int>(ceil((-61 - e) * 0.30102999566398114)) + 374;
|
||||
double dk =
|
||||
(-61 - e) * 0.30102999566398114 + 347; // dk must be positive, so can do ceiling in positive
|
||||
int k = static_cast<int>(dk);
|
||||
if (k != dk)
|
||||
k++;
|
||||
|
||||
unsigned index = static_cast<unsigned>((k >> 3) + 1);
|
||||
*K = -(-348 + static_cast<int>(index << 3)); // decimal exponent no need lookup table
|
||||
|
||||
assert(index < sizeof(kCachedPowers_F) / sizeof(kCachedPowers_F[0]));
|
||||
return DiyFp(kCachedPowers_F[index], kCachedPowers_E[index]);
|
||||
}
|
||||
|
||||
inline void
|
||||
GrisuRound(char *buffer, int len, uint64_t delta, uint64_t rest, uint64_t ten_kappa, uint64_t wp_w)
|
||||
{
|
||||
while (rest < wp_w && delta - rest >= ten_kappa &&
|
||||
(rest + ten_kappa < wp_w || /// closer
|
||||
wp_w - rest > rest + ten_kappa - wp_w))
|
||||
{
|
||||
buffer[len - 1]--;
|
||||
rest += ten_kappa;
|
||||
}
|
||||
}
|
||||
|
||||
inline unsigned CountDecimalDigit32(uint32_t n)
|
||||
{
|
||||
// Simple pure C++ implementation was faster than __builtin_clz version in this situation.
|
||||
if (n < 10)
|
||||
return 1;
|
||||
if (n < 100)
|
||||
return 2;
|
||||
if (n < 1000)
|
||||
return 3;
|
||||
if (n < 10000)
|
||||
return 4;
|
||||
if (n < 100000)
|
||||
return 5;
|
||||
if (n < 1000000)
|
||||
return 6;
|
||||
if (n < 10000000)
|
||||
return 7;
|
||||
if (n < 100000000)
|
||||
return 8;
|
||||
if (n < 1000000000)
|
||||
return 9;
|
||||
return 10;
|
||||
}
|
||||
|
||||
inline void
|
||||
DigitGen(const DiyFp &W, const DiyFp &Mp, uint64_t delta, char *buffer, int *len, int *K)
|
||||
{
|
||||
static const uint32_t kPow10[] = {
|
||||
1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000};
|
||||
const DiyFp one(uint64_t(1) << -Mp.e, Mp.e);
|
||||
const DiyFp wp_w = Mp - W;
|
||||
uint32_t p1 = static_cast<uint32_t>(Mp.f >> -one.e);
|
||||
uint64_t p2 = Mp.f & (one.f - 1);
|
||||
int kappa = static_cast<int>(CountDecimalDigit32(p1));
|
||||
*len = 0;
|
||||
|
||||
while (kappa > 0)
|
||||
{
|
||||
uint32_t d;
|
||||
switch (kappa)
|
||||
{
|
||||
case 10:
|
||||
d = p1 / 1000000000;
|
||||
p1 %= 1000000000;
|
||||
break;
|
||||
case 9:
|
||||
d = p1 / 100000000;
|
||||
p1 %= 100000000;
|
||||
break;
|
||||
case 8:
|
||||
d = p1 / 10000000;
|
||||
p1 %= 10000000;
|
||||
break;
|
||||
case 7:
|
||||
d = p1 / 1000000;
|
||||
p1 %= 1000000;
|
||||
break;
|
||||
case 6:
|
||||
d = p1 / 100000;
|
||||
p1 %= 100000;
|
||||
break;
|
||||
case 5:
|
||||
d = p1 / 10000;
|
||||
p1 %= 10000;
|
||||
break;
|
||||
case 4:
|
||||
d = p1 / 1000;
|
||||
p1 %= 1000;
|
||||
break;
|
||||
case 3:
|
||||
d = p1 / 100;
|
||||
p1 %= 100;
|
||||
break;
|
||||
case 2:
|
||||
d = p1 / 10;
|
||||
p1 %= 10;
|
||||
break;
|
||||
case 1:
|
||||
d = p1;
|
||||
p1 = 0;
|
||||
break;
|
||||
default:
|
||||
#if defined(_MSC_VER)
|
||||
__assume(0);
|
||||
#elif __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5)
|
||||
__builtin_unreachable();
|
||||
#else
|
||||
d = 0;
|
||||
#endif
|
||||
}
|
||||
if (d || *len)
|
||||
buffer[(*len)++] = '0' + static_cast<char>(d);
|
||||
kappa--;
|
||||
uint64_t tmp = (static_cast<uint64_t>(p1) << -one.e) + p2;
|
||||
if (tmp <= delta)
|
||||
{
|
||||
*K += kappa;
|
||||
GrisuRound(
|
||||
buffer, *len, delta, tmp, static_cast<uint64_t>(kPow10[kappa]) << -one.e, wp_w.f);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// kappa = 0
|
||||
for (;;)
|
||||
{
|
||||
p2 *= 10;
|
||||
delta *= 10;
|
||||
char d = static_cast<char>(p2 >> -one.e);
|
||||
if (d || *len)
|
||||
buffer[(*len)++] = '0' + d;
|
||||
p2 &= one.f - 1;
|
||||
kappa--;
|
||||
if (p2 < delta)
|
||||
{
|
||||
*K += kappa;
|
||||
GrisuRound(buffer, *len, delta, p2, one.f, wp_w.f * kPow10[-kappa]);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline void Grisu2(double value, char *buffer, int *length, int *K)
|
||||
{
|
||||
const DiyFp v(value);
|
||||
DiyFp w_m, w_p;
|
||||
v.NormalizedBoundaries(&w_m, &w_p);
|
||||
|
||||
const DiyFp c_mk = GetCachedPower(w_p.e, K);
|
||||
const DiyFp W = v.Normalize() * c_mk;
|
||||
DiyFp Wp = w_p * c_mk;
|
||||
DiyFp Wm = w_m * c_mk;
|
||||
Wm.f++;
|
||||
Wp.f--;
|
||||
DigitGen(W, Wp, Wp.f - Wm.f, buffer, length, K);
|
||||
}
|
||||
|
||||
inline const char *GetDigitsLut()
|
||||
{
|
||||
static const char cDigitsLut[200] = {
|
||||
'0', '0', '0', '1', '0', '2', '0', '3', '0', '4', '0', '5', '0', '6', '0', '7', '0',
|
||||
'8', '0', '9', '1', '0', '1', '1', '1', '2', '1', '3', '1', '4', '1', '5', '1', '6',
|
||||
'1', '7', '1', '8', '1', '9', '2', '0', '2', '1', '2', '2', '2', '3', '2', '4', '2',
|
||||
'5', '2', '6', '2', '7', '2', '8', '2', '9', '3', '0', '3', '1', '3', '2', '3', '3',
|
||||
'3', '4', '3', '5', '3', '6', '3', '7', '3', '8', '3', '9', '4', '0', '4', '1', '4',
|
||||
'2', '4', '3', '4', '4', '4', '5', '4', '6', '4', '7', '4', '8', '4', '9', '5', '0',
|
||||
'5', '1', '5', '2', '5', '3', '5', '4', '5', '5', '5', '6', '5', '7', '5', '8', '5',
|
||||
'9', '6', '0', '6', '1', '6', '2', '6', '3', '6', '4', '6', '5', '6', '6', '6', '7',
|
||||
'6', '8', '6', '9', '7', '0', '7', '1', '7', '2', '7', '3', '7', '4', '7', '5', '7',
|
||||
'6', '7', '7', '7', '8', '7', '9', '8', '0', '8', '1', '8', '2', '8', '3', '8', '4',
|
||||
'8', '5', '8', '6', '8', '7', '8', '8', '8', '9', '9', '0', '9', '1', '9', '2', '9',
|
||||
'3', '9', '4', '9', '5', '9', '6', '9', '7', '9', '8', '9', '9'};
|
||||
return cDigitsLut;
|
||||
}
|
||||
|
||||
inline void WriteExponent(int K, char *buffer)
|
||||
{
|
||||
if (K < 0)
|
||||
{
|
||||
*buffer++ = '-';
|
||||
K = -K;
|
||||
}
|
||||
|
||||
if (K >= 100)
|
||||
{
|
||||
*buffer++ = '0' + static_cast<char>(K / 100);
|
||||
K %= 100;
|
||||
const char *d = GetDigitsLut() + K * 2;
|
||||
*buffer++ = d[0];
|
||||
*buffer++ = d[1];
|
||||
}
|
||||
else if (K >= 10)
|
||||
{
|
||||
const char *d = GetDigitsLut() + K * 2;
|
||||
*buffer++ = d[0];
|
||||
*buffer++ = d[1];
|
||||
}
|
||||
else
|
||||
*buffer++ = '0' + static_cast<char>(K);
|
||||
|
||||
*buffer = '\0';
|
||||
}
|
||||
|
||||
inline void Prettify(char *buffer, int length, int k)
|
||||
{
|
||||
const int kk = length + k; // 10^(kk-1) <= v < 10^kk
|
||||
|
||||
if (length <= kk && kk <= 21)
|
||||
{
|
||||
// 1234e7 -> 12340000000
|
||||
for (int i = length; i < kk; i++)
|
||||
buffer[i] = '0';
|
||||
buffer[kk] = '.';
|
||||
buffer[kk + 1] = '0';
|
||||
buffer[kk + 2] = '\0';
|
||||
}
|
||||
else if (0 < kk && kk <= 21)
|
||||
{
|
||||
// 1234e-2 -> 12.34
|
||||
memmove(&buffer[kk + 1], &buffer[kk], length - kk);
|
||||
buffer[kk] = '.';
|
||||
buffer[length + 1] = '\0';
|
||||
}
|
||||
else if (-6 < kk && kk <= 0)
|
||||
{
|
||||
// 1234e-6 -> 0.001234
|
||||
const int offset = 2 - kk;
|
||||
memmove(&buffer[offset], &buffer[0], length);
|
||||
buffer[0] = '0';
|
||||
buffer[1] = '.';
|
||||
for (int i = 2; i < offset; i++)
|
||||
buffer[i] = '0';
|
||||
buffer[length + offset] = '\0';
|
||||
}
|
||||
else if (length == 1)
|
||||
{
|
||||
// 1e30
|
||||
buffer[1] = 'e';
|
||||
WriteExponent(kk - 1, &buffer[2]);
|
||||
}
|
||||
else
|
||||
{
|
||||
// 1234e30 -> 1.234e33
|
||||
memmove(&buffer[2], &buffer[1], length - 1);
|
||||
buffer[1] = '.';
|
||||
buffer[length + 1] = 'e';
|
||||
WriteExponent(kk - 1, &buffer[0 + length + 2]);
|
||||
}
|
||||
}
|
||||
|
||||
inline void dtoa_milo(double value, char *buffer)
|
||||
{
|
||||
// Not handling NaN and inf
|
||||
assert(!isnan(value));
|
||||
assert(!isinf(value));
|
||||
|
||||
if (value == 0)
|
||||
{
|
||||
buffer[0] = '0';
|
||||
buffer[1] = '.';
|
||||
buffer[2] = '0';
|
||||
buffer[3] = '\0';
|
||||
}
|
||||
else
|
||||
{
|
||||
if (value < 0)
|
||||
{
|
||||
*buffer++ = '-';
|
||||
value = -value;
|
||||
}
|
||||
int length, K;
|
||||
Grisu2(value, buffer, &length, &K);
|
||||
Prettify(buffer, length, K);
|
||||
}
|
||||
}
|
||||
} // namespace ieee754
|
||||
} // namespace util
|
||||
} // namespace osrm
|
||||
|
||||
#endif // IEEE754_HPP
|
||||
@ -4,17 +4,18 @@
|
||||
#ifndef JSON_RENDERER_HPP
|
||||
#define JSON_RENDERER_HPP
|
||||
|
||||
#include "util/cast.hpp"
|
||||
#include "util/ieee754.hpp"
|
||||
#include "util/string_util.hpp"
|
||||
|
||||
#include "osrm/json_container.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
#include <ostream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <fmt/compile.h>
|
||||
|
||||
namespace osrm
|
||||
{
|
||||
namespace util
|
||||
@ -22,173 +23,146 @@ namespace util
|
||||
namespace json
|
||||
{
|
||||
|
||||
namespace
|
||||
template <typename Out> struct Renderer
|
||||
{
|
||||
constexpr int MAX_FLOAT_STRING_LENGTH = 256;
|
||||
}
|
||||
explicit Renderer(Out &_out) : out(_out) {}
|
||||
|
||||
struct Renderer
|
||||
{
|
||||
explicit Renderer(std::ostream &_out) : out(_out) {}
|
||||
|
||||
void operator()(const String &string) const
|
||||
void operator()(const String &string)
|
||||
{
|
||||
out << "\"";
|
||||
out << escape_JSON(string.value);
|
||||
out << "\"";
|
||||
write('"');
|
||||
// here we assume that vast majority of strings don't need to be escaped,
|
||||
// so we check it first and escape only if needed
|
||||
if (RequiresJSONStringEscaping(string.value))
|
||||
{
|
||||
std::string escaped;
|
||||
// just a guess that 16 bytes for escaped characters will be enough to avoid
|
||||
// reallocations
|
||||
escaped.reserve(string.value.size() + 16);
|
||||
EscapeJSONString(string.value, escaped);
|
||||
|
||||
write(escaped);
|
||||
}
|
||||
else
|
||||
{
|
||||
write(string.value);
|
||||
}
|
||||
write('"');
|
||||
}
|
||||
|
||||
void operator()(const Number &number) const
|
||||
void operator()(const Number &number)
|
||||
{
|
||||
char buffer[MAX_FLOAT_STRING_LENGTH] = {'\0'};
|
||||
ieee754::dtoa_milo(number.value, buffer);
|
||||
// `fmt::memory_buffer` stores first 500 bytes in the object itself(i.e. on stack in this
|
||||
// case) and then grows using heap if needed
|
||||
fmt::memory_buffer buffer;
|
||||
fmt::format_to(std::back_inserter(buffer), FMT_COMPILE("{}"), number.value);
|
||||
|
||||
// Trucate to 10 decimal places
|
||||
int pos = 0;
|
||||
int decimalpos = 0;
|
||||
while (decimalpos == 0 && pos < MAX_FLOAT_STRING_LENGTH && buffer[pos] != 0)
|
||||
// Truncate to 10 decimal places
|
||||
size_t decimalpos = std::find(buffer.begin(), buffer.end(), '.') - buffer.begin();
|
||||
if (buffer.size() > (decimalpos + 10))
|
||||
{
|
||||
if (buffer[pos] == '.')
|
||||
{
|
||||
decimalpos = pos;
|
||||
break;
|
||||
}
|
||||
++pos;
|
||||
buffer.resize(decimalpos + 10);
|
||||
}
|
||||
while (pos < MAX_FLOAT_STRING_LENGTH && buffer[pos] != 0)
|
||||
{
|
||||
if (pos - decimalpos == 10)
|
||||
{
|
||||
buffer[pos] = '\0';
|
||||
break;
|
||||
}
|
||||
++pos;
|
||||
}
|
||||
out << buffer;
|
||||
|
||||
write(buffer.data(), buffer.size());
|
||||
}
|
||||
|
||||
void operator()(const Object &object) const
|
||||
void operator()(const Object &object)
|
||||
{
|
||||
out << "{";
|
||||
write('{');
|
||||
for (auto it = object.values.begin(), end = object.values.end(); it != end;)
|
||||
{
|
||||
out << "\"" << it->first << "\":";
|
||||
write('\"');
|
||||
write(it->first);
|
||||
write<>("\":");
|
||||
mapbox::util::apply_visitor(Renderer(out), it->second);
|
||||
if (++it != end)
|
||||
{
|
||||
out << ",";
|
||||
write(',');
|
||||
}
|
||||
}
|
||||
out << "}";
|
||||
write('}');
|
||||
}
|
||||
|
||||
void operator()(const Array &array) const
|
||||
void operator()(const Array &array)
|
||||
{
|
||||
out << "[";
|
||||
write('[');
|
||||
for (auto it = array.values.cbegin(), end = array.values.cend(); it != end;)
|
||||
{
|
||||
mapbox::util::apply_visitor(Renderer(out), *it);
|
||||
if (++it != end)
|
||||
{
|
||||
out << ",";
|
||||
write(',');
|
||||
}
|
||||
}
|
||||
out << "]";
|
||||
write(']');
|
||||
}
|
||||
|
||||
void operator()(const True &) const { out << "true"; }
|
||||
void operator()(const True &) { write<>("true"); }
|
||||
|
||||
void operator()(const False &) const { out << "false"; }
|
||||
void operator()(const False &) { write<>("false"); }
|
||||
|
||||
void operator()(const Null &) const { out << "null"; }
|
||||
void operator()(const Null &) { write<>("null"); }
|
||||
|
||||
private:
|
||||
std::ostream &out;
|
||||
void write(const std::string &str);
|
||||
void write(const char *str, size_t size);
|
||||
void write(char ch);
|
||||
|
||||
template <size_t StrLength> void write(const char (&str)[StrLength])
|
||||
{
|
||||
write(str, StrLength - 1);
|
||||
}
|
||||
|
||||
private:
|
||||
Out &out;
|
||||
};
|
||||
|
||||
struct ArrayRenderer
|
||||
template <> void Renderer<std::vector<char>>::write(const std::string &str)
|
||||
{
|
||||
explicit ArrayRenderer(std::vector<char> &_out) : out(_out) {}
|
||||
out.insert(out.end(), str.begin(), str.end());
|
||||
}
|
||||
|
||||
void operator()(const String &string) const
|
||||
{
|
||||
out.push_back('\"');
|
||||
const auto string_to_insert = escape_JSON(string.value);
|
||||
out.insert(std::end(out), std::begin(string_to_insert), std::end(string_to_insert));
|
||||
out.push_back('\"');
|
||||
}
|
||||
template <> void Renderer<std::vector<char>>::write(const char *str, size_t size)
|
||||
{
|
||||
out.insert(out.end(), str, str + size);
|
||||
}
|
||||
|
||||
void operator()(const Number &number) const
|
||||
{
|
||||
const std::string number_string = cast::to_string_with_precision(number.value);
|
||||
out.insert(out.end(), number_string.begin(), number_string.end());
|
||||
}
|
||||
template <> void Renderer<std::vector<char>>::write(char ch) { out.push_back(ch); }
|
||||
|
||||
void operator()(const Object &object) const
|
||||
{
|
||||
out.push_back('{');
|
||||
for (auto it = object.values.begin(), end = object.values.end(); it != end;)
|
||||
{
|
||||
out.push_back('\"');
|
||||
out.insert(out.end(), it->first.begin(), it->first.end());
|
||||
out.push_back('\"');
|
||||
out.push_back(':');
|
||||
template <> void Renderer<std::ostream>::write(const std::string &str) { out << str; }
|
||||
|
||||
mapbox::util::apply_visitor(ArrayRenderer(out), it->second);
|
||||
if (++it != end)
|
||||
{
|
||||
out.push_back(',');
|
||||
}
|
||||
}
|
||||
out.push_back('}');
|
||||
}
|
||||
template <> void Renderer<std::ostream>::write(const char *str, size_t size)
|
||||
{
|
||||
out.write(str, size);
|
||||
}
|
||||
|
||||
void operator()(const Array &array) const
|
||||
{
|
||||
out.push_back('[');
|
||||
for (auto it = array.values.cbegin(), end = array.values.cend(); it != end;)
|
||||
{
|
||||
mapbox::util::apply_visitor(ArrayRenderer(out), *it);
|
||||
if (++it != end)
|
||||
{
|
||||
out.push_back(',');
|
||||
}
|
||||
}
|
||||
out.push_back(']');
|
||||
}
|
||||
template <> void Renderer<std::ostream>::write(char ch) { out << ch; }
|
||||
|
||||
void operator()(const True &) const
|
||||
{
|
||||
const std::string temp("true");
|
||||
out.insert(out.end(), temp.begin(), temp.end());
|
||||
}
|
||||
template <> void Renderer<std::string>::write(const std::string &str) { out += str; }
|
||||
|
||||
void operator()(const False &) const
|
||||
{
|
||||
const std::string temp("false");
|
||||
out.insert(out.end(), temp.begin(), temp.end());
|
||||
}
|
||||
template <> void Renderer<std::string>::write(const char *str, size_t size)
|
||||
{
|
||||
out.append(str, size);
|
||||
}
|
||||
|
||||
void operator()(const Null &) const
|
||||
{
|
||||
const std::string temp("null");
|
||||
out.insert(out.end(), temp.begin(), temp.end());
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<char> &out;
|
||||
};
|
||||
template <> void Renderer<std::string>::write(char ch) { out += ch; }
|
||||
|
||||
inline void render(std::ostream &out, const Object &object)
|
||||
{
|
||||
Value value = object;
|
||||
mapbox::util::apply_visitor(Renderer(out), value);
|
||||
Renderer renderer(out);
|
||||
renderer(object);
|
||||
}
|
||||
|
||||
inline void render(std::string &out, const Object &object)
|
||||
{
|
||||
Renderer renderer(out);
|
||||
renderer(object);
|
||||
}
|
||||
|
||||
inline void render(std::vector<char> &out, const Object &object)
|
||||
{
|
||||
Value value = object;
|
||||
mapbox::util::apply_visitor(ArrayRenderer(out), value);
|
||||
Renderer renderer(out);
|
||||
renderer(object);
|
||||
}
|
||||
|
||||
} // namespace json
|
||||
|
||||
@ -58,11 +58,30 @@ template <int length, int precision> char *printInt(char *buffer, int value)
|
||||
return buffer;
|
||||
}
|
||||
|
||||
inline std::string escape_JSON(const std::string &input)
|
||||
inline bool RequiresJSONStringEscaping(const std::string &string)
|
||||
{
|
||||
for (const char letter : string)
|
||||
{
|
||||
switch (letter)
|
||||
{
|
||||
case '\\':
|
||||
case '"':
|
||||
case '/':
|
||||
case '\b':
|
||||
case '\f':
|
||||
case '\n':
|
||||
case '\r':
|
||||
case '\t':
|
||||
return true;
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
inline void EscapeJSONString(const std::string &input, std::string &output)
|
||||
{
|
||||
// escape and skip reallocations if possible
|
||||
std::string output;
|
||||
output.reserve(input.size() + 4); // +4 assumes two backslashes on avg
|
||||
for (const char letter : input)
|
||||
{
|
||||
switch (letter)
|
||||
@ -96,7 +115,6 @@ inline std::string escape_JSON(const std::string &input)
|
||||
break;
|
||||
}
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
inline std::size_t URIDecode(const std::string &input, std::string &output)
|
||||
|
||||
@ -19,8 +19,8 @@ elif [[ ${OS} = "Darwin" ]] ; then
|
||||
fi
|
||||
|
||||
# Discover clang-format
|
||||
if type clang-format-10.0.0 2> /dev/null ; then
|
||||
CLANG_FORMAT=clang-format-10.0.0
|
||||
if type clang-format-10 2> /dev/null ; then
|
||||
CLANG_FORMAT=clang-format-10
|
||||
elif type clang-format 2> /dev/null ; then
|
||||
# Clang format found, but need to check version
|
||||
CLANG_FORMAT=clang-format
|
||||
@ -30,7 +30,7 @@ elif type clang-format 2> /dev/null ; then
|
||||
#exit 1
|
||||
fi
|
||||
else
|
||||
echo "No appropriate clang-format found (expected clang-format-10.0.0, or clang-format)"
|
||||
echo "No appropriate clang-format found (expected clang-format-10, or clang-format)"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
|
||||
@ -30,6 +30,18 @@ target_link_libraries(match-bench
|
||||
${TBB_LIBRARIES}
|
||||
${MAYBE_SHAPEFILE})
|
||||
|
||||
add_executable(json-render-bench
|
||||
EXCLUDE_FROM_ALL
|
||||
json_render.cpp
|
||||
$<TARGET_OBJECTS:UTIL>)
|
||||
|
||||
target_link_libraries(json-render-bench
|
||||
osrm
|
||||
${BOOST_BASE_LIBRARIES}
|
||||
${CMAKE_THREAD_LIBS_INIT}
|
||||
${TBB_LIBRARIES}
|
||||
${MAYBE_SHAPEFILE})
|
||||
|
||||
add_executable(alias-bench
|
||||
EXCLUDE_FROM_ALL
|
||||
${AliasBenchmarkSources}
|
||||
@ -41,6 +53,8 @@ target_link_libraries(alias-bench
|
||||
${TBB_LIBRARIES}
|
||||
${MAYBE_SHAPEFILE})
|
||||
|
||||
|
||||
|
||||
add_executable(packedvector-bench
|
||||
EXCLUDE_FROM_ALL
|
||||
${PackedVectorBenchmarkSources}
|
||||
@ -58,4 +72,5 @@ add_custom_target(benchmarks
|
||||
rtree-bench
|
||||
packedvector-bench
|
||||
match-bench
|
||||
json-render-bench
|
||||
alias-bench)
|
||||
|
||||
128
src/benchmarks/json_render.cpp
Normal file
128
src/benchmarks/json_render.cpp
Normal file
@ -0,0 +1,128 @@
|
||||
|
||||
#include "osrm/json_container.hpp"
|
||||
#include "util/json_container.hpp"
|
||||
#include "util/json_renderer.hpp"
|
||||
#include "util/timing_util.hpp"
|
||||
#include <cstdlib>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <rapidjson/document.h>
|
||||
#include <sstream>
|
||||
#include <stdexcept>
|
||||
|
||||
using namespace osrm;
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
void convert(const rapidjson::Value &value, json::Value &result)
|
||||
{
|
||||
if (value.IsString())
|
||||
{
|
||||
result = json::String{value.GetString()};
|
||||
}
|
||||
else if (value.IsNumber())
|
||||
{
|
||||
result = json::Number{value.GetDouble()};
|
||||
}
|
||||
else if (value.IsObject())
|
||||
{
|
||||
json::Object object;
|
||||
for (auto itr = value.MemberBegin(); itr != value.MemberEnd(); ++itr)
|
||||
{
|
||||
json::Value member;
|
||||
convert(itr->value, member);
|
||||
object.values.emplace(itr->name.GetString(), std::move(member));
|
||||
}
|
||||
result = std::move(object);
|
||||
}
|
||||
else if (value.IsArray())
|
||||
{
|
||||
json::Array array;
|
||||
for (auto itr = value.Begin(); itr != value.End(); ++itr)
|
||||
{
|
||||
json::Value member;
|
||||
convert(*itr, member);
|
||||
array.values.push_back(std::move(member));
|
||||
}
|
||||
result = std::move(array);
|
||||
}
|
||||
else if (value.IsBool())
|
||||
{
|
||||
if (value.GetBool())
|
||||
{
|
||||
result = json::True{};
|
||||
}
|
||||
else
|
||||
{
|
||||
result = json::False{};
|
||||
}
|
||||
}
|
||||
else if (value.IsNull())
|
||||
{
|
||||
result = json::Null{};
|
||||
}
|
||||
else
|
||||
{
|
||||
throw std::runtime_error("unknown type");
|
||||
}
|
||||
}
|
||||
|
||||
json::Object load(const char *filename)
|
||||
{
|
||||
// load file to std string
|
||||
std::ifstream file(filename);
|
||||
std::stringstream buffer;
|
||||
buffer << file.rdbuf();
|
||||
std::string json = buffer.str();
|
||||
|
||||
// load rapidjson document
|
||||
rapidjson::Document document;
|
||||
document.Parse(json.c_str());
|
||||
if (document.HasParseError())
|
||||
{
|
||||
throw std::runtime_error("Failed to parse JSON");
|
||||
}
|
||||
|
||||
json::Value result;
|
||||
convert(document, result);
|
||||
return result.get<json::Object>();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
if (argc < 2)
|
||||
{
|
||||
std::cerr << "Usage: " << argv[0] << " file.json\n";
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
const auto obj = load(argv[1]);
|
||||
|
||||
TIMER_START(string);
|
||||
std::string out_str;
|
||||
json::render(out_str, obj);
|
||||
TIMER_STOP(string);
|
||||
std::cout << "String: " << TIMER_MSEC(string) << "ms" << std::endl;
|
||||
|
||||
TIMER_START(stringstream);
|
||||
std::stringstream ss;
|
||||
json::render(ss, obj);
|
||||
std::string out_ss_str{ss.str()};
|
||||
TIMER_STOP(stringstream);
|
||||
|
||||
std::cout << "Stringstream: " << TIMER_MSEC(stringstream) << "ms" << std::endl;
|
||||
TIMER_START(vector);
|
||||
std::vector<char> out_vec;
|
||||
json::render(out_vec, obj);
|
||||
TIMER_STOP(vector);
|
||||
std::cout << "Vector: " << TIMER_MSEC(vector) << "ms" << std::endl;
|
||||
|
||||
if (std::string{out_vec.begin(), out_vec.end()} != out_str || out_str != out_ss_str)
|
||||
{
|
||||
throw std::logic_error("Vector/stringstream/string results are not equal");
|
||||
}
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
1
src/benchmarks/portugal_to_korea.json
Normal file
1
src/benchmarks/portugal_to_korea.json
Normal file
File diff suppressed because one or more lines are too long
@ -329,7 +329,7 @@ TurnLaneScenario TurnLaneHandler::deduceScenario(const NodeID at,
|
||||
intersection)
|
||||
.first;
|
||||
|
||||
// check if we were successfull in trimming
|
||||
// check if we were successful in trimming
|
||||
if (lane_data.size() == possible_entries &&
|
||||
isSimpleIntersection(lane_data, intersection))
|
||||
return TurnLaneScenario::PARTITION_LOCAL;
|
||||
@ -556,7 +556,7 @@ std::pair<LaneDataVector, LaneDataVector> TurnLaneHandler::partitionLaneData(
|
||||
* into two parts, one for the first and one for the second intersection.
|
||||
*/
|
||||
|
||||
// Try and maitch lanes to available turns. For Turns that are not directly matchable, check
|
||||
// Try and match lanes to available turns. For Turns that are not directly matchable, check
|
||||
// whether we can match them at the upcoming intersection.
|
||||
|
||||
const auto straightmost = intersection.findClosestTurn(STRAIGHT_ANGLE);
|
||||
@ -675,10 +675,11 @@ std::pair<LaneDataVector, LaneDataVector> TurnLaneHandler::partitionLaneData(
|
||||
first.push_back(turn_lane_data[lane]);
|
||||
}
|
||||
|
||||
if (straightmost_tag_index == turn_lane_data.size() &&
|
||||
std::size_t num_next_intersection_turns = getNumberOfTurns(next_intersection);
|
||||
if (straightmost_tag_index == turn_lane_data.size() && num_next_intersection_turns > 0 &&
|
||||
static_cast<std::size_t>(
|
||||
std::count(matched_at_second.begin(), matched_at_second.end(), true)) ==
|
||||
getNumberOfTurns(next_intersection))
|
||||
num_next_intersection_turns)
|
||||
{
|
||||
TurnLaneData data = {TurnLaneType::straight, 255, 0};
|
||||
augmentEntry(data);
|
||||
|
||||
@ -167,13 +167,13 @@ inline void async(const Nan::FunctionCallbackInfo<v8::Value> &info,
|
||||
ParseResult(status, json_result);
|
||||
if (pluginParams.renderToBuffer)
|
||||
{
|
||||
std::ostringstream buf;
|
||||
osrm::util::json::render(buf, json_result);
|
||||
result = buf.str();
|
||||
std::string json_string;
|
||||
osrm::util::json::render(json_string, json_result);
|
||||
result = std::move(json_string);
|
||||
}
|
||||
else
|
||||
{
|
||||
result = json_result;
|
||||
result = std::move(json_result);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
30
unit_tests/util/json_render.cpp
Normal file
30
unit_tests/util/json_render.cpp
Normal file
@ -0,0 +1,30 @@
|
||||
#include "util/json_container.hpp"
|
||||
#include "util/json_renderer.hpp"
|
||||
|
||||
#include <boost/test/unit_test.hpp>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
BOOST_AUTO_TEST_SUITE(json_renderer)
|
||||
|
||||
using namespace osrm::util::json;
|
||||
|
||||
BOOST_AUTO_TEST_CASE(number_truncating)
|
||||
{
|
||||
std::string str;
|
||||
Renderer<std::string> renderer(str);
|
||||
|
||||
// this number would have more than 10 decimals if not truncated
|
||||
renderer(Number{42.9995999594999399299});
|
||||
BOOST_CHECK_EQUAL(str, "42.999599959");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(integer)
|
||||
{
|
||||
std::string str;
|
||||
Renderer<std::string> renderer(str);
|
||||
renderer(Number{42.0});
|
||||
BOOST_CHECK_EQUAL(str, "42");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
||||
@ -12,13 +12,19 @@ using namespace osrm::util;
|
||||
BOOST_AUTO_TEST_CASE(json_escaping)
|
||||
{
|
||||
std::string input{"\b\\"};
|
||||
std::string output{escape_JSON(input)};
|
||||
std::string output;
|
||||
EscapeJSONString(input, output);
|
||||
|
||||
BOOST_CHECK(RequiresJSONStringEscaping(input));
|
||||
BOOST_CHECK_EQUAL(output, "\\b\\\\");
|
||||
|
||||
input = "Aleja \"Solidarnosci\"";
|
||||
output = escape_JSON(input);
|
||||
output.clear();
|
||||
EscapeJSONString(input, output);
|
||||
BOOST_CHECK(RequiresJSONStringEscaping(input));
|
||||
BOOST_CHECK_EQUAL(output, "Aleja \\\"Solidarnosci\\\"");
|
||||
|
||||
BOOST_CHECK(!RequiresJSONStringEscaping("Aleja Solidarnosci"));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(print_int)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user