Merge pull request #4456 from Project-OSRM/update/libosmium
Update libosmium to 2.13
This commit is contained in:
commit
28178b12c7
@ -10,7 +10,7 @@ set -o nounset
|
||||
# http://git.661346.n2.nabble.com/subtree-merges-lose-prefix-after-rebase-td7332850.html
|
||||
|
||||
OSMIUM_REPO="https://github.com/osmcode/libosmium.git"
|
||||
OSMIUM_TAG=v2.11.3
|
||||
OSMIUM_TAG=v2.13.1
|
||||
|
||||
VARIANT_REPO="https://github.com/mapbox/variant.git"
|
||||
VARIANT_TAG=v1.1.3
|
||||
|
7
third_party/libosmium/.codecov.yml
vendored
Normal file
7
third_party/libosmium/.codecov.yml
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
|
||||
ignore:
|
||||
- "include/gdalcpp.hpp"
|
||||
- "include/protozero"
|
||||
- "include/utf8"
|
||||
- "test/include/catch.hpp"
|
||||
|
2
third_party/libosmium/.gitignore
vendored
2
third_party/libosmium/.gitignore
vendored
@ -1,4 +1,6 @@
|
||||
*.swp
|
||||
.ycm_extra_conf.pyc
|
||||
/_build*
|
||||
/build
|
||||
/libosmium-deps
|
||||
/.vs*
|
||||
|
25
third_party/libosmium/.travis.yml
vendored
25
third_party/libosmium/.travis.yml
vendored
@ -141,6 +141,14 @@ matrix:
|
||||
packages: ['g++-6', 'libboost1.55-all-dev', 'libgdal-dev', 'libgeos++-dev', 'libproj-dev', 'libsparsehash-dev', 'spatialite-bin']
|
||||
env: COMPILER='g++-6' BUILD_TYPE='Dev'
|
||||
|
||||
- os: linux
|
||||
compiler: linux-gcc6-coverage
|
||||
addons:
|
||||
apt:
|
||||
sources: ['ubuntu-toolchain-r-test', 'boost-latest']
|
||||
packages: ['g++-6', 'libboost1.55-all-dev', 'libgdal-dev', 'libgeos++-dev', 'libproj-dev', 'libsparsehash-dev', 'spatialite-bin']
|
||||
env: COMPILER='g++-6' BUILD_TYPE='Coverage'
|
||||
|
||||
|
||||
# 3/ OSX Clang Builds
|
||||
- os: osx
|
||||
@ -166,12 +174,12 @@ matrix:
|
||||
|
||||
|
||||
- os: osx
|
||||
osx_image: xcode8
|
||||
osx_image: xcode8.3
|
||||
compiler: xcode8-clang-release
|
||||
env: COMPILER='clang++' BUILD_TYPE='Release'
|
||||
|
||||
- os: osx
|
||||
osx_image: xcode8
|
||||
osx_image: xcode8.3
|
||||
compiler: xcode8-clang-dev
|
||||
env: COMPILER='clang++' BUILD_TYPE='Dev'
|
||||
|
||||
@ -195,3 +203,16 @@ before_script:
|
||||
script:
|
||||
- make VERBOSE=1 && ctest --output-on-failure
|
||||
|
||||
after_success:
|
||||
- |
|
||||
if [ "${BUILD_TYPE}" = "Coverage" ]; then
|
||||
curl -S -f https://codecov.io/bash -o codecov
|
||||
chmod +x codecov
|
||||
gcov-${COMPILER#g++-} -p $(find test/CMakeFiles -name '*.o')
|
||||
./codecov -Z -c -F unit_tests
|
||||
gcov-${COMPILER#g++-} -p $(find test/data-tests -name '*.o')
|
||||
./codecov -Z -c -F data_tests
|
||||
gcov-${COMPILER#g++-} -p $(find examples -name '*.o')
|
||||
./codecov -Z -c -F examples
|
||||
fi
|
||||
|
||||
|
210
third_party/libosmium/CHANGELOG.md
vendored
210
third_party/libosmium/CHANGELOG.md
vendored
@ -6,9 +6,130 @@ This project adheres to [Semantic Versioning](http://semver.org/).
|
||||
|
||||
## [unreleased] -
|
||||
|
||||
### Added
|
||||
|
||||
### Changed
|
||||
|
||||
### Fixed
|
||||
|
||||
## [2.11.3] - 2017-05-03
|
||||
|
||||
## [2.13.1] - 2017-08-25
|
||||
|
||||
### Added
|
||||
|
||||
- New "blackhole" file format which throws away all data written into it.
|
||||
Used for benchmarking.
|
||||
|
||||
### Changed
|
||||
|
||||
- When reading OPL files, CRLF file endings are now handled correctly.
|
||||
- Reduce the max number of threads allowed for the `Pool` to 32. This should
|
||||
still be plenty and might help with test failures on some architectures.
|
||||
|
||||
### Fixed
|
||||
|
||||
- Tests now run correctly independent of git `core.autocrlf` setting.
|
||||
- Set binary mode for all files on Windows in example code.
|
||||
- Low-level file functions now set an invalid parameter handler on Windows
|
||||
to properly handle errors.
|
||||
- Restore earlier behaviour allowing zero-length mmap. It is important to
|
||||
allow zero-length memory mapping, because it is possible that such an index
|
||||
is empty, for instance when one type of object is missing from an input
|
||||
file as in https://github.com/osmcode/osmium-tool/issues/65. Drawback is
|
||||
that files must be opened read-write for this to work, even if we only
|
||||
want to read from them.
|
||||
- Use Approx() to compare floating point values in tests.
|
||||
- Fix broken `Item` test on 32 bit platforms.
|
||||
|
||||
|
||||
## [2.13.0] - 2017-08-15
|
||||
|
||||
### Added
|
||||
|
||||
- New `RelationsManager` class superseeds the `relations::Collector` class.
|
||||
The new class is much more modular and easier to extend. If you are using
|
||||
the Collector class, you are encouraged to switch.
|
||||
- New `MultipolygonManager` based on the `RelationsManager` class superseeds
|
||||
the `MultipolygonCollector` class. The examples have been changed to use the
|
||||
new class and all users are encouraged to switch. There is also a
|
||||
`MultipolygonManagerLegacy` class if you still need old-style multipolygon
|
||||
support (see below).
|
||||
- New `FlexMem` index class that works with input files of any size and
|
||||
stores the index in memory. This should now be used as the default index
|
||||
for node location stores. Several example programs now use this index.
|
||||
- New `CallbackBuffer` class, basically a convenient wrapper around the
|
||||
`Buffer` class with an additional callback function that is called whenever
|
||||
the buffer is full.
|
||||
- Introduce new `ItemStash` class for storing OSM objects in memory.
|
||||
- New `osmium::geom::overlaps()` function to check if two `Box` objects
|
||||
overlap.
|
||||
- Add function `IdSet::used_memory()` to get estimate of memory used in the
|
||||
set.
|
||||
- New `is_defined()` and `is_undefined()` methods on `Location` class.
|
||||
- Tests for all provided example programs. (Some tests currently fail
|
||||
on Windows for the `osmium_index_lookup` program.)
|
||||
|
||||
### Changed
|
||||
|
||||
- The area `Assembler` now doesn't work with old-style multipolygons (those
|
||||
are multipolygon relations with the tags on the outer ways(s) instead of
|
||||
on the relation) any more. Because old-style multipolygons are now (mostly)
|
||||
gone from the OSM database this is usually what you want. The new
|
||||
`AssemblerLegacy` class can be used if you actually need support for
|
||||
old-style multipolygons, for instance if you are working with historical
|
||||
data. (In that case you also need to use the `MultipolygonManagerLegacy`
|
||||
class instead of the `MultipolygonManager` class.)
|
||||
- Changes for consistent ordering of OSM data: OSM data can come in any order,
|
||||
but usual OSM files are ordered by type, ID, and version. These changes
|
||||
extend this ordering to negative IDs which are sometimes used for objects
|
||||
that have not been uploaded to the OSM server yet. The negative IDs are
|
||||
ordered now before the positive ones, both in order of their absolute value.
|
||||
This is the same ordering as JOSM uses.
|
||||
- Multipolygon assembler now checks for three or more overlapping segments
|
||||
which are always an error and can report them.
|
||||
- Enable use of user-provided `thread::Pool` instances in `Reader` and
|
||||
`Writer` for special use cases.
|
||||
- Growing a `Buffer` will now work with any capacity parameter, it is
|
||||
always rounded up for proper alignment. Buffer constructor with three
|
||||
arguments will now check that commmitted is not larger than capacity.
|
||||
- Updated embedded protozero to 1.5.2.
|
||||
- Update version of Catch unit test framework to 1.9.7.
|
||||
- And, as always, lots of small code cleanups and more tests.
|
||||
|
||||
### Fixed
|
||||
|
||||
- Buffers larger than 2^32 bytes do now work.
|
||||
- Output coordinate with value of -2^31 correctly.
|
||||
- Changeset comments with more than 2^16 characters are now allowed. The new
|
||||
maximum size is 2^32.
|
||||
- `ChangesetDiscussionBuilder::add_comment_text()` could fail silently instead
|
||||
of throwing an exception.
|
||||
- Changeset bounding boxes are now always output to OSM files (any format)
|
||||
if at least one of the corners is defined. This is needed to handle broken
|
||||
data from the main OSM database which contains such cases. The OPL reader
|
||||
has also been fixed to handle this case.
|
||||
- In the example `osmium_location_cache_create`, the index file written is
|
||||
always truncated first.
|
||||
|
||||
|
||||
## [2.12.2] - 2017-05-03
|
||||
|
||||
### Added
|
||||
|
||||
- Add two argument (key, value) overload of `TagMatcher::operator()`.
|
||||
|
||||
### Changed
|
||||
|
||||
- Detect, report, and remove duplicate ways in multipolygon relations.
|
||||
- Change EOF behaviour of Reader: The `Reader::read()` function will now
|
||||
always return an invalid buffer exactly once to signal EOF.
|
||||
- Update QGIS multipolygon project that is part of the test suite to show
|
||||
more problem types.
|
||||
- Copy multipolygon QGIS file for tests to build dir in cmake step.
|
||||
- Some code cleanups and improved debug output in multipolygon code.
|
||||
- Refactor I/O code to simplify code.
|
||||
- Disable some warnings on MSVC.
|
||||
- Various small code and build script changes.
|
||||
|
||||
### Fixed
|
||||
|
||||
@ -16,25 +137,94 @@ This project adheres to [Semantic Versioning](http://semver.org/).
|
||||
multipolygons with overlapping or nearly overlapping lines.
|
||||
- Invalid use of iterators leading to undefined behaviour in area assembler
|
||||
code.
|
||||
- Area assembler stats were not correctly counting inner rings that are
|
||||
areas in their own right.
|
||||
- Fix a thread problem valgrind found that might or might not be real.
|
||||
- Read OPL file correctly even if trailing newline in file is missing.
|
||||
- Include order for `osmium/index/map` headers and
|
||||
`osmium/index/node_locations_map.hpp` (or
|
||||
`osmium/handler/node_locations_for_ways.hpp`) doesn't matter any more.
|
||||
|
||||
|
||||
## [2.11.2] - 2017-04-10
|
||||
## [2.12.1] - 2017-04-10
|
||||
|
||||
### Added
|
||||
|
||||
- New `TagsFilter::set_default_result()` function.
|
||||
|
||||
### Changed
|
||||
|
||||
- Use larger capacity for `Buffer` if necessary for alignment instead of
|
||||
throwing an exception. Minimum buffer size is now 64 bytes.
|
||||
- Check order of input data in relations collector. The relations collector
|
||||
can not deal with history data or a changes file. This was documented as a
|
||||
requirement, but often lead to problems, because this was ignored by users.
|
||||
So it now checks that the input data it gets is ordered and throws an
|
||||
exception otherwise.
|
||||
- When writing an OSM file, set generator to libosmium if not set by app.
|
||||
|
||||
### Fixed
|
||||
|
||||
- Use minimum size of 64 bytes for buffers. This fixes an infinite loop
|
||||
when buffer size is zero.
|
||||
- Infinite loop in `Buffer::reserve_space()`. (Issue #202.)
|
||||
- `ObjectPointerCollection::unique()` now removes elements at end.
|
||||
- Tests comparing double using `==` operator.
|
||||
- Build on Cygwin.
|
||||
|
||||
|
||||
## [2.11.1] - 2017-03-07
|
||||
## [2.12.0] - 2017-03-07
|
||||
|
||||
### Added
|
||||
|
||||
- `TagMatcher` and `TagsFilter` classes for more flexibly matching tags and
|
||||
selecting objects based on tags. This obsoletes the less flexible classes
|
||||
based on `osmium::tags::Filter` classes.
|
||||
- Extended `index::RelationsMap(Stash|Index)` classes to also allow
|
||||
parent-to-member lookups.
|
||||
- New `nrw_array` helper class.
|
||||
- `ObjectPointerCollection::unique()` function.
|
||||
|
||||
### Changed
|
||||
|
||||
- Area assembler can now detect invalid locations and report them in the
|
||||
stats and through the problem reporter. If the new config option
|
||||
`ignore_invalid_locations` is set, the Assembler will pretend they weren't
|
||||
even referenced in the ways. (Issue #195.)
|
||||
- `osmium::area::Assembler::operator()` will now return a boolean reporting
|
||||
whether building of the area(s) was successful.
|
||||
- Split up area `Assembler` class into three classes: The
|
||||
`detail::BasicAssembler` is now the parent class. `Assembler` is the child
|
||||
class for usual use. The new `GeomAssembler` also derives from
|
||||
`BasicAssembler` and builds areas without taking tags into account at all.
|
||||
This is to support osm2pgsql which does tag handling itself. (Issue #194.)
|
||||
- The `Projection` class can do any projection supported by the Proj.4
|
||||
library. As a special case it now uses our own Mercator projection
|
||||
functions when the web mercator projection (EPSG 3857) is used. This is
|
||||
much faster than going through Proj.4.
|
||||
- Better error messages for low-level file utility functions.
|
||||
- Mark `build_tag_list*` functions in `builder_helper.hpp` as deprecated. You
|
||||
should use the functions from `osmium/builder/attr.hpp` instead.
|
||||
- Improved performance of the `osmium::tags::match_(any|all|none)_of`
|
||||
functions.
|
||||
- Improved performance of string comparison in `tags::Filter`.
|
||||
- Update version of Catch unit test framework to 1.8.1. This meant some
|
||||
tests had to be updated.
|
||||
- Use `get_noexcept()` in `NodeLocationsForWays` handler.
|
||||
- And lots of code and test cleanups...
|
||||
|
||||
### Fixed
|
||||
|
||||
- Terminate called on full non-auto-growing buffer. (Issue #189.)
|
||||
- When file formats were used that were not compiled into the binary, it
|
||||
terminated instead of throwing. (Issue #197.)
|
||||
- Windows build problem related to including two different winsock versions.
|
||||
- Windows build problem related to forced build for old Windows versions.
|
||||
(Issue #196.)
|
||||
- Clear stream contents in ProblemReporterException correctly.
|
||||
- Add `-pthread` compiler and linker options on Linux/OSX. This should fix
|
||||
a problem where some linker versions will not link binaries correctly when
|
||||
the `--as-needed` option is used.
|
||||
- The `Filter::count()` method didn't compile at all.
|
||||
- XML reader doesn't fail on relation member ref=0 any more.
|
||||
|
||||
|
||||
## [2.11.0] - 2017-01-14
|
||||
@ -549,10 +739,12 @@ This project adheres to [Semantic Versioning](http://semver.org/).
|
||||
Doxygen (up to version 1.8.8). This version contains a workaround to fix
|
||||
this.
|
||||
|
||||
[unreleased]: https://github.com/osmcode/libosmium/compare/v2.11.3...HEAD
|
||||
[2.11.3]: https://github.com/osmcode/libosmium/compare/v2.11.2...v2.11.3
|
||||
[2.11.2]: https://github.com/osmcode/libosmium/compare/v2.11.1...v2.11.2
|
||||
[2.11.1]: https://github.com/osmcode/libosmium/compare/v2.11.0...v2.11.1
|
||||
[unreleased]: https://github.com/osmcode/libosmium/compare/v2.13.1...HEAD
|
||||
[2.13.1]: https://github.com/osmcode/libosmium/compare/v2.13.0...v2.13.1
|
||||
[2.13.0]: https://github.com/osmcode/libosmium/compare/v2.12.2...v2.13.0
|
||||
[2.12.2]: https://github.com/osmcode/libosmium/compare/v2.12.1...v2.12.2
|
||||
[2.12.1]: https://github.com/osmcode/libosmium/compare/v2.12.0...v2.12.1
|
||||
[2.12.0]: https://github.com/osmcode/libosmium/compare/v2.11.0...v2.12.0
|
||||
[2.11.0]: https://github.com/osmcode/libosmium/compare/v2.10.3...v2.11.0
|
||||
[2.10.3]: https://github.com/osmcode/libosmium/compare/v2.10.2...v2.10.3
|
||||
[2.10.2]: https://github.com/osmcode/libosmium/compare/v2.10.1...v2.10.2
|
||||
|
59
third_party/libosmium/CMakeLists.txt
vendored
59
third_party/libosmium/CMakeLists.txt
vendored
@ -24,8 +24,8 @@ set(CMAKE_CONFIGURATION_TYPES "Debug;Release;RelWithDebInfo;MinSizeRel;Dev;Cover
|
||||
project(libosmium)
|
||||
|
||||
set(LIBOSMIUM_VERSION_MAJOR 2)
|
||||
set(LIBOSMIUM_VERSION_MINOR 11)
|
||||
set(LIBOSMIUM_VERSION_PATCH 3)
|
||||
set(LIBOSMIUM_VERSION_MINOR 13)
|
||||
set(LIBOSMIUM_VERSION_PATCH 1)
|
||||
|
||||
set(LIBOSMIUM_VERSION
|
||||
"${LIBOSMIUM_VERSION_MAJOR}.${LIBOSMIUM_VERSION_MINOR}.${LIBOSMIUM_VERSION_PATCH}")
|
||||
@ -43,8 +43,14 @@ set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
||||
|
||||
if(CMAKE_BUILD_TYPE STREQUAL "Dev")
|
||||
set(dev_build ON)
|
||||
set(data_test_build ON)
|
||||
else()
|
||||
set(dev_build OFF)
|
||||
set(data_test_build OFF)
|
||||
endif()
|
||||
|
||||
if(CMAKE_BUILD_TYPE STREQUAL "Coverage")
|
||||
set(data_test_build ON)
|
||||
endif()
|
||||
|
||||
option(BUILD_EXAMPLES "compile example programs" ON)
|
||||
@ -52,7 +58,8 @@ option(BUILD_TESTING "compile unit tests, please run them with ctest" ON)
|
||||
|
||||
option(BUILD_HEADERS "compile every header file on its own" ${dev_build})
|
||||
option(BUILD_BENCHMARKS "compile benchmark programs" ${dev_build})
|
||||
option(BUILD_DATA_TESTS "compile data tests, please run them with ctest" ${dev_build})
|
||||
|
||||
option(BUILD_DATA_TESTS "compile data tests, please run them with ctest" ${data_test_build})
|
||||
|
||||
option(INSTALL_GDALCPP "also install gdalcpp headers" OFF)
|
||||
option(INSTALL_PROTOZERO "also install protozero headers" OFF)
|
||||
@ -88,11 +95,12 @@ endif()
|
||||
#
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
include(CheckCXXCompilerFlag)
|
||||
check_cxx_compiler_flag("-fkeep-inline-functions" HAS_KEEP_INLINE_FUNCTIONS)
|
||||
if(HAS_KEEP_INLINE_FUNCTIONS)
|
||||
set(extra_coverage_flags_ "-fkeep-inline-functions")
|
||||
endif()
|
||||
## This leads to all sorts of compile problems, so disable for now
|
||||
#include(CheckCXXCompilerFlag)
|
||||
#check_cxx_compiler_flag("-fkeep-inline-functions" HAS_KEEP_INLINE_FUNCTIONS)
|
||||
#if(HAS_KEEP_INLINE_FUNCTIONS)
|
||||
# set(extra_coverage_flags_ "-fkeep-inline-functions")
|
||||
#endif()
|
||||
|
||||
set(CMAKE_CXX_FLAGS_COVERAGE
|
||||
"-g -O0 -fno-inline-functions -fno-inline --coverage ${extra_coverage_flags_}"
|
||||
@ -103,8 +111,8 @@ set(CMAKE_EXE_LINKER_FLAGS_COVERAGE
|
||||
CACHE STRING "Flags used by the linker during coverage builds.")
|
||||
|
||||
if(CMAKE_BUILD_TYPE STREQUAL "Coverage")
|
||||
if(BUILD_EXAMPLES OR BUILD_HEADERS OR BUILD_BENCHMARKS OR BUILD_DATA_TESTS)
|
||||
message(WARNING "Coverage builds don't work for anything but the unit tests")
|
||||
if(BUILD_EXAMPLES OR BUILD_HEADERS OR BUILD_BENCHMARKS)
|
||||
message(WARNING "Coverage builds don't work for anything but the tests")
|
||||
endif()
|
||||
|
||||
if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
|
||||
@ -184,8 +192,12 @@ endif()
|
||||
#-----------------------------------------------------------------------------
|
||||
if(NOT MSVC)
|
||||
if(NOT USE_CPP_VERSION)
|
||||
if(CYGWIN)
|
||||
set(USE_CPP_VERSION gnu++11)
|
||||
else()
|
||||
set(USE_CPP_VERSION c++11)
|
||||
endif()
|
||||
endif()
|
||||
message(STATUS "Use C++ version: ${USE_CPP_VERSION}")
|
||||
# following only available from cmake 2.8.12:
|
||||
# add_compile_options(-std=${USE_CPP_VERSION})
|
||||
@ -201,15 +213,15 @@ endif()
|
||||
#-----------------------------------------------------------------------------
|
||||
if(MSVC)
|
||||
set(USUAL_COMPILE_OPTIONS "/Ox")
|
||||
set(USUAL_LINK_OPTIONS "/debug")
|
||||
# do not show warnings caused by missing .pdb files for libraries
|
||||
set(USUAL_LINK_OPTIONS "/debug /ignore:4099")
|
||||
else()
|
||||
set(USUAL_COMPILE_OPTIONS "-O3 -g")
|
||||
set(USUAL_LINK_OPTIONS "")
|
||||
endif()
|
||||
|
||||
if(WIN32)
|
||||
add_definitions(-DWIN32 -D_WIN32 -DMSWIN32 -DBGDWIN32
|
||||
-DWINVER=0x0500 -D_WIN32_WINNT=0x0500 -D_WIN32_IE=0x0600)
|
||||
add_definitions(-DWIN32 -D_WIN32 -DMSWIN32 -DBGDWIN32)
|
||||
endif()
|
||||
|
||||
set(CMAKE_CXX_FLAGS_DEV "${USUAL_COMPILE_OPTIONS}"
|
||||
@ -228,6 +240,15 @@ set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${USUAL_COMPILE_OPTIONS}"
|
||||
CACHE STRING "Flags used by the compiler during RELWITHDEBINFO builds."
|
||||
FORCE)
|
||||
|
||||
set(CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO "${USUAL_LINK_OPTIONS}"
|
||||
CACHE STRING "Flags used by the linker during RELWITHDEBINFO builds."
|
||||
FORCE)
|
||||
|
||||
mark_as_advanced(
|
||||
CMAKE_CXX_FLAGS_RELWITHDEBINFO
|
||||
CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO
|
||||
)
|
||||
|
||||
if(WITH_PROFILING)
|
||||
add_definitions(-fno-omit-frame-pointer)
|
||||
endif()
|
||||
@ -301,7 +322,13 @@ find_program(CPPCHECK cppcheck)
|
||||
if(CPPCHECK)
|
||||
message(STATUS "Looking for cppcheck - found")
|
||||
set(CPPCHECK_OPTIONS
|
||||
--enable=warning,style,performance,portability,information,missingInclude --force -Uassert)
|
||||
--language=c++
|
||||
--quiet
|
||||
-j4
|
||||
--inline-suppr
|
||||
--enable=warning,style,performance,portability,information,missingInclude
|
||||
--force
|
||||
-Uassert -DPROTOZERO_STRICT_API -DPROTOZERO_USE_BUILTIN_BSWAP -UPROTOZERO_USE_VIEW)
|
||||
|
||||
# cpp doesn't find system includes for some reason, suppress that report
|
||||
set(CPPCHECK_OPTIONS ${CPPCHECK_OPTIONS} --suppress=missingIncludeSystem)
|
||||
@ -460,10 +487,12 @@ if(CLANG_TIDY)
|
||||
list(APPEND CT_CHECKS "misc-*"
|
||||
"-misc-argument-comment")
|
||||
|
||||
list(APPEND CT_CHECKS "modernize-*")
|
||||
list(APPEND CT_CHECKS "modernize-*"
|
||||
"-modernize-make-unique") # not available in C++11
|
||||
|
||||
list(APPEND CT_CHECKS "readability-*"
|
||||
"-readability-identifier-naming"
|
||||
"-readability-implicit-bool-cast"
|
||||
"-readability-named-parameter")
|
||||
|
||||
string(REPLACE ";" "," ALL_CHECKS "${CT_CHECKS}")
|
||||
|
34
third_party/libosmium/NOTES_FOR_DEVELOPERS.md
vendored
34
third_party/libosmium/NOTES_FOR_DEVELOPERS.md
vendored
@ -12,7 +12,7 @@ All Osmium code MUST be in the `osmium` namespace or one of its sub-namespaces.
|
||||
## Include-Only
|
||||
|
||||
Osmium is a include-only library. You can't compile the library itself. There
|
||||
is no libosmium.so.
|
||||
is no `libosmium.so` or `libosmium.dll`.
|
||||
|
||||
One drawback ist that you can't have static data in classes, because there
|
||||
is no place to put this data.
|
||||
@ -69,7 +69,7 @@ different.
|
||||
* Template parameters are single uppercase letters or start with uppercase `T`
|
||||
and use CamelCase.
|
||||
* Always use `typename` in templates, not `class`: `template <typename T>`.
|
||||
* The ellipsis in variadic template never has a space to the left of it and
|
||||
* The ellipsis in a variadic template never has a space to the left of it and
|
||||
always has a space to the right: `template <typename... TArgs>` etc.
|
||||
|
||||
Keep to the indentation and other styles used in the code.
|
||||
@ -92,6 +92,19 @@ between compilers due to different C++11 support.
|
||||
Usually all code must work on Linux, OSX, and Windows. Execptions are allowed
|
||||
for some minor functionality, but please discuss this first.
|
||||
|
||||
When writing code and tests, care must be taken that everything works with the
|
||||
CR line ending convention used on Linux and OSX and the CRLF line ending used
|
||||
on Windows. Note that `git` can be run with different settings regarding line
|
||||
ending rewritings on different machines making things more difficult. Some
|
||||
files have been "forced" to LF line endings using `.gitattributes` files.
|
||||
|
||||
|
||||
## 32bit systems
|
||||
|
||||
Libosmium tries to work on 32bit systems whereever possible. But there are
|
||||
some parts which will not work on 32bit systems, mainly because the amount
|
||||
of main memory available is not enough for it to work anyway.
|
||||
|
||||
|
||||
## Checking your code
|
||||
|
||||
@ -118,9 +131,20 @@ used to define mappings for iwyu. See the IWYU tool at
|
||||
|
||||
## Testing
|
||||
|
||||
There are a unit tests using the Catch Unit Test Framework in the `test`
|
||||
directory and some data tests in `test/osm-testdata`. They are built by the
|
||||
default cmake config. Run `ctest` to run them. Many more tests are needed.
|
||||
There are unit tests using the Catch Unit Test Framework in the `test`
|
||||
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 the Travis (Linux/Mac) and Appveyor (Windows)
|
||||
services. We automatically create coverage reports on Codevoc.io. Note that
|
||||
the coverage percentages reported are not always accurate, because code that
|
||||
is not used in tests at all will not necessarily end up in the binary and
|
||||
the code coverage tool will not know it is there.
|
||||
|
||||
[](https://travis-ci.org/osmcode/libosmium)
|
||||
[](https://ci.appveyor.com/project/Mapbox/libosmium)
|
||||
[](https://codecov.io/gh/osmcode/libosmium)
|
||||
|
||||
|
||||
## Documenting the code
|
||||
|
5
third_party/libosmium/README.md
vendored
5
third_party/libosmium/README.md
vendored
@ -6,8 +6,9 @@ A fast and flexible C++ library for working with OpenStreetMap data.
|
||||
|
||||
Libosmium works on Linux, Mac OSX and Windows.
|
||||
|
||||
[](https://travis-ci.org/osmcode/libosmium)
|
||||
[](https://ci.appveyor.com/project/Mapbox/libosmium)
|
||||
[](https://travis-ci.org/osmcode/libosmium)
|
||||
[](https://ci.appveyor.com/project/Mapbox/libosmium)
|
||||
[](https://codecov.io/gh/osmcode/libosmium)
|
||||
|
||||
Please see the [Libosmium manual](http://osmcode.org/libosmium/manual.html)
|
||||
for more details than this README can provide.
|
||||
|
13
third_party/libosmium/appveyor.yml
vendored
13
third_party/libosmium/appveyor.yml
vendored
@ -7,7 +7,13 @@
|
||||
environment:
|
||||
matrix:
|
||||
- config: Dev
|
||||
autocrlf: true
|
||||
- config: Dev
|
||||
autocrlf: false
|
||||
- config: RelWithDebInfo
|
||||
autocrlf: true
|
||||
- config: RelWithDebInfo
|
||||
autocrlf: false
|
||||
|
||||
shallow_clone: true
|
||||
|
||||
@ -16,6 +22,8 @@ os: Visual Studio 2015
|
||||
|
||||
# scripts that are called at very beginning, before repo cloning
|
||||
init:
|
||||
- git config --global core.autocrlf %autocrlf%
|
||||
- git config --get core.autocrlf
|
||||
|
||||
# clone directory
|
||||
clone_folder: c:\projects\libosmium
|
||||
@ -24,3 +32,8 @@ platform: x64
|
||||
|
||||
build_script:
|
||||
- build-appveyor.bat
|
||||
|
||||
# remove garbage VS messages
|
||||
# http://help.appveyor.com/discussions/problems/4569-the-target-_convertpdbfiles-listed-in-a-beforetargets-attribute-at-c-does-not-exist-in-the-project-and-will-be-ignored
|
||||
before_build:
|
||||
- del "C:\Program Files (x86)\MSBuild\14.0\Microsoft.Common.targets\ImportAfter\Xamarin.Common.targets"
|
||||
|
@ -33,6 +33,7 @@ foreach(benchmark ${BENCHMARKS})
|
||||
target_link_libraries(osmium_benchmark_${benchmark}
|
||||
${OSMIUM_IO_LIBRARIES}
|
||||
${BENCHMARK_LIBS_${benchmark}})
|
||||
set_pthread_on_target(osmium_benchmark_${benchmark})
|
||||
configure_file(run_benchmark_${benchmark}.sh
|
||||
${CMAKE_CURRENT_BINARY_DIR}/run_benchmark_${benchmark}.sh
|
||||
@ONLY)
|
||||
|
5
third_party/libosmium/build-appveyor.bat
vendored
5
third_party/libosmium/build-appveyor.bat
vendored
@ -97,11 +97,14 @@ ECHO calling^: %CMAKE_CMD%
|
||||
%CMAKE_CMD%
|
||||
IF %ERRORLEVEL% NEQ 0 GOTO ERROR
|
||||
|
||||
SET avlogger=
|
||||
IF /I "%APPVEYOR%"=="True" SET avlogger=/logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll"
|
||||
|
||||
msbuild libosmium.sln ^
|
||||
/p:Configuration=%config% ^
|
||||
/toolsversion:14.0 ^
|
||||
/p:Platform=x64 ^
|
||||
/p:PlatformToolset=v140
|
||||
/p:PlatformToolset=v140 %avlogger%
|
||||
IF %ERRORLEVEL% NEQ 0 GOTO ERROR
|
||||
|
||||
ctest --output-on-failure ^
|
||||
|
18
third_party/libosmium/cmake/FindOsmium.cmake
vendored
18
third_party/libosmium/cmake/FindOsmium.cmake
vendored
@ -296,6 +296,20 @@ find_package_handle_standard_args(Osmium
|
||||
VERSION_VAR _libosmium_version)
|
||||
unset(OSMIUM_EXTRA_FIND_VARS)
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
#
|
||||
# A function for setting the -pthread option in compilers/linkers
|
||||
#
|
||||
#----------------------------------------------------------------------
|
||||
function(set_pthread_on_target _target)
|
||||
if(NOT MSVC)
|
||||
set_target_properties(${_target} PROPERTIES COMPILE_FLAGS "-pthread")
|
||||
if(NOT APPLE)
|
||||
set_target_properties(${_target} PROPERTIES LINK_FLAGS "-pthread")
|
||||
endif()
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
#
|
||||
# Add compiler flags
|
||||
@ -319,6 +333,10 @@ if(MSVC)
|
||||
# old compilers anyway.
|
||||
add_definitions(-wd4351)
|
||||
|
||||
# Disable warning C4503: "decorated name length exceeded, name was truncated"
|
||||
# there are more than 150 of generated names in libosmium longer than 4096 symbols supported in MSVC
|
||||
add_definitions(-wd4503)
|
||||
|
||||
add_definitions(-DNOMINMAX -DWIN32_LEAN_AND_MEAN -D_CRT_SECURE_NO_WARNINGS)
|
||||
endif()
|
||||
|
||||
|
@ -58,7 +58,12 @@ message(STATUS "Configuring examples - Building these examples:")
|
||||
foreach(example ${EXAMPLES})
|
||||
message(STATUS " - osmium_${example}")
|
||||
add_executable(osmium_${example} "osmium_${example}.cpp")
|
||||
set_pthread_on_target(osmium_${example})
|
||||
target_link_libraries(osmium_${example} ${OSMIUM_IO_LIBRARIES} ${EXAMPLE_LIBS_${example}})
|
||||
add_test(NAME examples_usage_${example} COMMAND osmium_${example})
|
||||
set_tests_properties(examples_usage_${example} PROPERTIES
|
||||
PASS_REGULAR_EXPRESSION "^Usage: "
|
||||
)
|
||||
endforeach()
|
||||
|
||||
|
||||
|
@ -9,7 +9,7 @@
|
||||
DEMONSTRATES USE OF:
|
||||
* file input
|
||||
* location indexes and the NodeLocationsForWays handler
|
||||
* the MultipolygonCollector and Assembler to assemble areas (multipolygons)
|
||||
* the MultipolygonManager and Assembler to assemble areas (multipolygons)
|
||||
* your own handler that works with areas (multipolygons)
|
||||
* accessing tags
|
||||
* osmium::geom::Coordinates
|
||||
@ -29,17 +29,22 @@
|
||||
#include <iostream> // for std::cerr
|
||||
#include <string> // for std::string
|
||||
|
||||
// For memory based sparse index
|
||||
#include <osmium/index/map/sparse_mem_array.hpp>
|
||||
// For the location index. There are different types of indexes available.
|
||||
// This will work for all input files keeping the index in memory.
|
||||
#include <osmium/index/map/flex_mem.hpp>
|
||||
|
||||
// For the NodeLocationForWays handler
|
||||
#include <osmium/handler/node_locations_for_ways.hpp>
|
||||
using index_type = osmium::index::map::SparseMemArray<osmium::unsigned_object_id_type, osmium::Location>;
|
||||
|
||||
// The type of index used. This must match the include file above
|
||||
using index_type = osmium::index::map::FlexMem<osmium::unsigned_object_id_type, osmium::Location>;
|
||||
|
||||
// The location handler always depends on the index type
|
||||
using location_handler_type = osmium::handler::NodeLocationsForWays<index_type>;
|
||||
|
||||
// For assembling multipolygons
|
||||
#include <osmium/area/assembler.hpp>
|
||||
#include <osmium/area/multipolygon_collector.hpp>
|
||||
#include <osmium/area/multipolygon_manager.hpp>
|
||||
|
||||
// Allow any format of input files (XML, PBF, ...)
|
||||
#include <osmium/io/any_input.hpp>
|
||||
@ -108,8 +113,8 @@ int main(int argc, char* argv[]) {
|
||||
std::exit(1);
|
||||
}
|
||||
|
||||
// The input file name
|
||||
const std::string input_file_name{argv[1]};
|
||||
// The input file
|
||||
const osmium::io::File input_file{argv[1]};
|
||||
|
||||
// Configuration for the multipolygon assembler. We disable the option to
|
||||
// create empty areas when invalid multipolygons are encountered. This
|
||||
@ -118,21 +123,16 @@ int main(int argc, char* argv[]) {
|
||||
osmium::area::Assembler::config_type assembler_config;
|
||||
assembler_config.create_empty_areas = false;
|
||||
|
||||
// Initialize the MultipolygonCollector. Its job is to collect all
|
||||
// Initialize the MultipolygonManager. Its job is to collect all
|
||||
// relations and member ways needed for each area. It then calls an
|
||||
// instance of the osmium::area::Assembler class (with the given config)
|
||||
// to actually assemble one area.
|
||||
osmium::area::MultipolygonCollector<osmium::area::Assembler> collector{assembler_config};
|
||||
osmium::area::MultipolygonManager<osmium::area::Assembler> mp_manager{assembler_config};
|
||||
|
||||
// We read the input file twice. In the first pass, only relations are
|
||||
// read and fed into the multipolygon collector. The read_meta::no option
|
||||
// disables reading of meta data (such as version numbers, timestamps, etc.)
|
||||
// which are not needed in this case. Disabling this can speed up your
|
||||
// program.
|
||||
// read and fed into the multipolygon manager.
|
||||
std::cerr << "Pass 1...\n";
|
||||
osmium::io::Reader reader1{input_file_name, osmium::osm_entity_bits::relation, osmium::io::read_meta::no};
|
||||
collector.read_relations(reader1);
|
||||
reader1.close();
|
||||
osmium::relations::read_relations(input_file, mp_manager);
|
||||
std::cerr << "Pass 1 done\n";
|
||||
|
||||
// The index storing all node locations.
|
||||
@ -151,17 +151,21 @@ int main(int argc, char* argv[]) {
|
||||
AmenityHandler data_handler;
|
||||
|
||||
// On the second pass we read all objects and run them first through the
|
||||
// node location handler and then the multipolygon collector. The collector
|
||||
// node location handler and then the multipolygon manager. The manager
|
||||
// will put the areas it has created into the "buffer" which are then
|
||||
// fed through our handler.
|
||||
//
|
||||
// The read_meta::no option disables reading of meta data (such as version
|
||||
// numbers, timestamps, etc.) which are not needed in this case. Disabling
|
||||
// this can speed up your program.
|
||||
std::cerr << "Pass 2...\n";
|
||||
osmium::io::Reader reader2{input_file_name, osmium::io::read_meta::no};
|
||||
osmium::io::Reader reader{input_file, osmium::io::read_meta::no};
|
||||
|
||||
osmium::apply(reader2, location_handler, data_handler, collector.handler([&data_handler](const osmium::memory::Buffer& area_buffer) {
|
||||
osmium::apply(reader, location_handler, data_handler, mp_manager.handler([&data_handler](const osmium::memory::Buffer& area_buffer) {
|
||||
osmium::apply(area_buffer, data_handler);
|
||||
}));
|
||||
|
||||
reader2.close();
|
||||
reader.close();
|
||||
std::cerr << "Pass 2 done\n";
|
||||
}
|
||||
|
||||
|
@ -8,7 +8,7 @@
|
||||
DEMONSTRATES USE OF:
|
||||
* file input
|
||||
* location indexes and the NodeLocationsForWays handler
|
||||
* the MultipolygonCollector and Assembler to assemble areas (multipolygons)
|
||||
* the MultipolygonManager and Assembler to assemble areas (multipolygons)
|
||||
* your own handler that works with areas (multipolygons)
|
||||
* the WKTFactory to write geometries in WKT format
|
||||
* the Dump handler
|
||||
@ -31,7 +31,7 @@
|
||||
|
||||
// For assembling multipolygons
|
||||
#include <osmium/area/assembler.hpp>
|
||||
#include <osmium/area/multipolygon_collector.hpp>
|
||||
#include <osmium/area/multipolygon_manager.hpp>
|
||||
|
||||
// For the DynamicHandler class
|
||||
#include <osmium/dynamic_handler.hpp>
|
||||
@ -52,11 +52,11 @@
|
||||
#include <osmium/visitor.hpp>
|
||||
|
||||
// For the location index. There are different types of indexes available.
|
||||
// This will work for small and medium sized input files.
|
||||
#include <osmium/index/map/sparse_mem_array.hpp>
|
||||
// This will work for all input files keeping the index in memory.
|
||||
#include <osmium/index/map/flex_mem.hpp>
|
||||
|
||||
// The type of index used. This must match the include file above
|
||||
using index_type = osmium::index::map::SparseMemArray<osmium::unsigned_object_id_type, osmium::Location>;
|
||||
using index_type = osmium::index::map::FlexMem<osmium::unsigned_object_id_type, osmium::Location>;
|
||||
|
||||
// The location handler always depends on the index type
|
||||
using location_handler_type = osmium::handler::NodeLocationsForWays<index_type>;
|
||||
@ -93,10 +93,10 @@ void print_help() {
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
static struct option long_options[] = {
|
||||
{"help", no_argument, 0, 'h'},
|
||||
{"dump-wkt", no_argument, 0, 'w'},
|
||||
{"dump-objects", no_argument, 0, 'o'},
|
||||
{0, 0, 0, 0}
|
||||
{"help", no_argument, nullptr, 'h'},
|
||||
{"dump-wkt", no_argument, nullptr, 'w'},
|
||||
{"dump-objects", no_argument, nullptr, 'o'},
|
||||
{nullptr, 0, nullptr, 0}
|
||||
};
|
||||
|
||||
// Initialize an empty DynamicHandler. Later it will be associated
|
||||
@ -107,7 +107,7 @@ int main(int argc, char* argv[]) {
|
||||
|
||||
// Read options from command line.
|
||||
while (true) {
|
||||
const int c = getopt_long(argc, argv, "hwo", long_options, 0);
|
||||
const int c = getopt_long(argc, argv, "hwo", long_options, nullptr);
|
||||
if (c == -1) {
|
||||
break;
|
||||
}
|
||||
@ -139,24 +139,29 @@ int main(int argc, char* argv[]) {
|
||||
// are used, but you could change multiple settings.
|
||||
osmium::area::Assembler::config_type assembler_config;
|
||||
|
||||
// Initialize the MultipolygonCollector. Its job is to collect all
|
||||
// Set up a filter matching only forests. This will be used to only build
|
||||
// areas with matching tags.
|
||||
osmium::TagsFilter filter{false};
|
||||
filter.add_rule(true, "landuse", "forest");
|
||||
filter.add_rule(true, "natural", "wood");
|
||||
|
||||
// Initialize the MultipolygonManager. Its job is to collect all
|
||||
// relations and member ways needed for each area. It then calls an
|
||||
// instance of the osmium::area::Assembler class (with the given config)
|
||||
// to actually assemble one area.
|
||||
osmium::area::MultipolygonCollector<osmium::area::Assembler> collector{assembler_config};
|
||||
// to actually assemble one area. The filter parameter is optional, if
|
||||
// it is not set, all areas will be built.
|
||||
osmium::area::MultipolygonManager<osmium::area::Assembler> mp_manager{assembler_config, filter};
|
||||
|
||||
// We read the input file twice. In the first pass, only relations are
|
||||
// read and fed into the multipolygon collector.
|
||||
// read and fed into the multipolygon manager.
|
||||
std::cerr << "Pass 1...\n";
|
||||
osmium::io::Reader reader1{input_file, osmium::osm_entity_bits::relation};
|
||||
collector.read_relations(reader1);
|
||||
reader1.close();
|
||||
osmium::relations::read_relations(input_file, mp_manager);
|
||||
std::cerr << "Pass 1 done\n";
|
||||
|
||||
// Output the amount of main memory used so far. All multipolygon relations
|
||||
// are in memory now.
|
||||
std::cerr << "Memory:\n";
|
||||
collector.used_memory();
|
||||
osmium::relations::print_used_memory(std::cerr, mp_manager.used_memory());
|
||||
|
||||
// The index storing all node locations.
|
||||
index_type index;
|
||||
@ -175,26 +180,29 @@ int main(int argc, char* argv[]) {
|
||||
// will put the areas it has created into the "buffer" which are then
|
||||
// fed through our "handler".
|
||||
std::cerr << "Pass 2...\n";
|
||||
osmium::io::Reader reader2{input_file};
|
||||
osmium::apply(reader2, location_handler, collector.handler([&handler](osmium::memory::Buffer&& buffer) {
|
||||
osmium::io::Reader reader{input_file};
|
||||
osmium::apply(reader, location_handler, mp_manager.handler([&handler](osmium::memory::Buffer&& buffer) {
|
||||
osmium::apply(buffer, handler);
|
||||
}));
|
||||
reader2.close();
|
||||
reader.close();
|
||||
std::cerr << "Pass 2 done\n";
|
||||
|
||||
// Output the amount of main memory used so far. All complete multipolygon
|
||||
// relations have been cleaned up.
|
||||
std::cerr << "Memory:\n";
|
||||
collector.used_memory();
|
||||
osmium::relations::print_used_memory(std::cerr, mp_manager.used_memory());
|
||||
|
||||
// If there were multipolgyon relations in the input, but some of their
|
||||
// members are not in the input file (which often happens for extracts)
|
||||
// this will write the IDs of the incomplete relations to stderr.
|
||||
std::vector<const osmium::Relation*> incomplete_relations = collector.get_incomplete_relations();
|
||||
if (!incomplete_relations.empty()) {
|
||||
std::vector<osmium::object_id_type> incomplete_relations_ids;
|
||||
mp_manager.for_each_incomplete_relation([&](const osmium::relations::RelationHandle& handle){
|
||||
incomplete_relations_ids.push_back(handle->id());
|
||||
});
|
||||
if (!incomplete_relations_ids.empty()) {
|
||||
std::cerr << "Warning! Some member ways missing for these multipolygon relations:";
|
||||
for (const auto* relation : incomplete_relations) {
|
||||
std::cerr << " " << relation->id();
|
||||
for (const auto id : incomplete_relations_ids) {
|
||||
std::cerr << " " << id;
|
||||
}
|
||||
std::cerr << "\n";
|
||||
}
|
||||
|
@ -91,7 +91,7 @@ class RewriteHandler : public osmium::handler::Handler {
|
||||
public:
|
||||
|
||||
// Constructor. New data will be added to the given buffer.
|
||||
RewriteHandler(osmium::memory::Buffer& buffer) :
|
||||
explicit RewriteHandler(osmium::memory::Buffer& buffer) :
|
||||
m_buffer(buffer) {
|
||||
}
|
||||
|
||||
@ -119,7 +119,7 @@ public:
|
||||
m_buffer.commit();
|
||||
}
|
||||
|
||||
// The way handler is called for each node in the input data.
|
||||
// The way handler is called for each way in the input data.
|
||||
void way(const osmium::Way& way) {
|
||||
{
|
||||
osmium::builder::WayBuilder builder{m_buffer};
|
||||
@ -132,7 +132,7 @@ public:
|
||||
m_buffer.commit();
|
||||
}
|
||||
|
||||
// The relation handler is called for each node in the input data.
|
||||
// The relation handler is called for each relation in the input data.
|
||||
void relation(const osmium::Relation& relation) {
|
||||
{
|
||||
osmium::builder::RelationBuilder builder{m_buffer};
|
||||
|
@ -53,10 +53,10 @@ void print_help() {
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
static struct option long_options[] = {
|
||||
{"help", no_argument, 0, 'h'},
|
||||
{"from-format", required_argument, 0, 'f'},
|
||||
{"to-format", required_argument, 0, 't'},
|
||||
{0, 0, 0, 0}
|
||||
{"help", no_argument, nullptr, 'h'},
|
||||
{"from-format", required_argument, nullptr, 'f'},
|
||||
{"to-format", required_argument, nullptr, 't'},
|
||||
{nullptr, 0, nullptr, 0}
|
||||
};
|
||||
|
||||
// Input and output format are empty by default. Later this will mean that
|
||||
@ -67,7 +67,7 @@ int main(int argc, char* argv[]) {
|
||||
|
||||
// Read options from command line.
|
||||
while (true) {
|
||||
const int c = getopt_long(argc, argv, "dhf:t:", long_options, 0);
|
||||
const int c = getopt_long(argc, argv, "dhf:t:", long_options, nullptr);
|
||||
if (c == -1) {
|
||||
break;
|
||||
}
|
||||
@ -88,7 +88,7 @@ int main(int argc, char* argv[]) {
|
||||
}
|
||||
|
||||
const int remaining_args = argc - optind;
|
||||
if (remaining_args > 2) {
|
||||
if (remaining_args == 0 || remaining_args > 2) {
|
||||
std::cerr << "Usage: " << argv[0] << " [OPTIONS] [INFILE [OUTFILE]]\n";
|
||||
std::exit(1);
|
||||
}
|
||||
@ -108,8 +108,8 @@ int main(int argc, char* argv[]) {
|
||||
// This declares the input and output files using either the suffix of
|
||||
// the file names or the format in the 2nd argument. It does not yet open
|
||||
// the files.
|
||||
osmium::io::File input_file{input_file_name, input_format};
|
||||
osmium::io::File output_file{output_file_name, output_format};
|
||||
const osmium::io::File input_file{input_file_name, input_format};
|
||||
const osmium::io::File output_file{output_file_name, output_format};
|
||||
|
||||
// Input and output files can be OSM data files (without history) or
|
||||
// OSM history files. History files are detected if they use the '.osh'
|
||||
|
@ -46,6 +46,10 @@ int main(int argc, char* argv[]) {
|
||||
// Get output file name from command line.
|
||||
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" : ""};
|
||||
|
||||
try {
|
||||
// Create a buffer where all objects will live. Use a sensible initial
|
||||
// buffer size and set the buffer to automatically grow if needed.
|
||||
@ -78,7 +82,7 @@ int main(int argc, char* argv[]) {
|
||||
|
||||
// Initialize Writer using the header from above and tell it that it
|
||||
// is allowed to overwrite a possibly existing file.
|
||||
osmium::io::Writer writer{output_file_name, header, osmium::io::overwrite::allow};
|
||||
osmium::io::Writer writer{output_file, header, osmium::io::overwrite::allow};
|
||||
|
||||
// Write out the contents of the output buffer.
|
||||
writer(std::move(buffer));
|
||||
|
16
third_party/libosmium/examples/osmium_debug.cpp
vendored
16
third_party/libosmium/examples/osmium_debug.cpp
vendored
@ -44,10 +44,18 @@ int main(int argc, char* argv[]) {
|
||||
if (argc == 3) {
|
||||
read_types = osmium::osm_entity_bits::nothing;
|
||||
std::string types = argv[2];
|
||||
if (types.find('n') != std::string::npos) read_types |= osmium::osm_entity_bits::node;
|
||||
if (types.find('w') != std::string::npos) read_types |= osmium::osm_entity_bits::way;
|
||||
if (types.find('r') != std::string::npos) read_types |= osmium::osm_entity_bits::relation;
|
||||
if (types.find('c') != std::string::npos) read_types |= osmium::osm_entity_bits::changeset;
|
||||
if (types.find('n') != std::string::npos) {
|
||||
read_types |= osmium::osm_entity_bits::node;
|
||||
}
|
||||
if (types.find('w') != std::string::npos) {
|
||||
read_types |= osmium::osm_entity_bits::way;
|
||||
}
|
||||
if (types.find('r') != std::string::npos) {
|
||||
read_types |= osmium::osm_entity_bits::relation;
|
||||
}
|
||||
if (types.find('c') != std::string::npos) {
|
||||
read_types |= osmium::osm_entity_bits::changeset;
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize Reader with file name and the types of entities we want to
|
||||
|
@ -6,7 +6,7 @@
|
||||
indexes to find objects and object relations.
|
||||
|
||||
Note that this example programm will only work with small and medium sized
|
||||
OSM file, not with the planet.
|
||||
OSM files, not with the planet.
|
||||
|
||||
You can use the osmium_index example program to inspect the indexes.
|
||||
|
||||
@ -36,6 +36,10 @@
|
||||
#include <sys/stat.h> // for open
|
||||
#include <sys/types.h> // for open
|
||||
|
||||
#ifdef _WIN32
|
||||
# include <io.h> // for _setmode
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
# include <direct.h>
|
||||
#endif
|
||||
@ -66,12 +70,15 @@ class IndexFile {
|
||||
|
||||
public:
|
||||
|
||||
IndexFile(const std::string& filename) :
|
||||
explicit IndexFile(const std::string& filename) :
|
||||
m_fd(::open(filename.c_str(), O_WRONLY | O_CREAT | O_TRUNC, 0666)) {
|
||||
if (m_fd < 0) {
|
||||
std::cerr << "Can't open index file '" << filename << "': " << std::strerror(errno) << "\n";
|
||||
std::exit(2);
|
||||
}
|
||||
#ifdef _WIN32
|
||||
_setmode(m_fd, _O_BINARY);
|
||||
#endif
|
||||
}
|
||||
|
||||
~IndexFile() {
|
||||
@ -114,6 +121,10 @@ int main(int argc, char* argv[]) {
|
||||
std::exit(2);
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
_setmode(data_fd, _O_BINARY);
|
||||
#endif
|
||||
|
||||
// These indexes store the offset in the data file where each node, way,
|
||||
// or relation is stored.
|
||||
offset_index_type node_index;
|
||||
|
@ -33,6 +33,10 @@
|
||||
#include <sys/types.h> // for open
|
||||
#include <vector> // for std::vector
|
||||
|
||||
#ifdef _WIN32
|
||||
# include <io.h> // for _setmode
|
||||
#endif
|
||||
|
||||
// Disk-based indexes
|
||||
#include <osmium/index/map/dense_file_array.hpp>
|
||||
#include <osmium/index/map/sparse_file_array.hpp>
|
||||
@ -52,7 +56,7 @@ class IndexAccess {
|
||||
|
||||
public:
|
||||
|
||||
IndexAccess(int fd) :
|
||||
explicit IndexAccess(int fd) :
|
||||
m_fd(fd) {
|
||||
}
|
||||
|
||||
@ -83,7 +87,7 @@ class IndexAccessDense : public IndexAccess<TValue> {
|
||||
|
||||
public:
|
||||
|
||||
IndexAccessDense(int fd) :
|
||||
explicit IndexAccessDense(int fd) :
|
||||
IndexAccess<TValue>(fd) {
|
||||
}
|
||||
|
||||
@ -122,7 +126,7 @@ class IndexAccessSparse : public IndexAccess<TValue> {
|
||||
|
||||
public:
|
||||
|
||||
IndexAccessSparse(int fd) :
|
||||
explicit IndexAccessSparse(int fd) :
|
||||
IndexAccess<TValue>(fd) {
|
||||
}
|
||||
|
||||
@ -192,17 +196,17 @@ public:
|
||||
}
|
||||
|
||||
static struct option long_options[] = {
|
||||
{"array", required_argument, 0, 'a'},
|
||||
{"dump", no_argument, 0, 'd'},
|
||||
{"help", no_argument, 0, 'h'},
|
||||
{"list", required_argument, 0, 'l'},
|
||||
{"search", required_argument, 0, 's'},
|
||||
{"type", required_argument, 0, 't'},
|
||||
{0, 0, 0, 0}
|
||||
{"array", required_argument, nullptr, 'a'},
|
||||
{"dump", no_argument, nullptr, 'd'},
|
||||
{"help", no_argument, nullptr, 'h'},
|
||||
{"list", required_argument, nullptr, 'l'},
|
||||
{"search", required_argument, nullptr, 's'},
|
||||
{"type", required_argument, nullptr, 't'},
|
||||
{nullptr, 0, nullptr, 0}
|
||||
};
|
||||
|
||||
while (true) {
|
||||
const int c = getopt_long(argc, argv, "a:dhl:s:t:", long_options, 0);
|
||||
const int c = getopt_long(argc, argv, "a:dhl:s:t:", long_options, nullptr);
|
||||
if (c == -1) {
|
||||
break;
|
||||
}
|
||||
@ -243,7 +247,7 @@ public:
|
||||
std::exit(2);
|
||||
}
|
||||
|
||||
if (m_dump && !m_ids.empty()) {
|
||||
if (m_dump == !m_ids.empty()) {
|
||||
std::cerr << "Need option --dump or --search, but not both\n";
|
||||
std::exit(2);
|
||||
}
|
||||
@ -308,13 +312,18 @@ int main(int argc, char* argv[]) {
|
||||
Options options{argc, argv};
|
||||
|
||||
// Open the index file.
|
||||
const int fd = open(options.filename(), O_RDWR);
|
||||
const int fd = ::open(options.filename(), O_RDWR);
|
||||
if (fd < 0) {
|
||||
std::cerr << "Can not open file '" << options.filename()
|
||||
<< "': " << std::strerror(errno) << '\n';
|
||||
std::exit(2);
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
_setmode(fd, _O_BINARY);
|
||||
#endif
|
||||
|
||||
try {
|
||||
// Depending on the type of index, we have different implementations.
|
||||
if (options.type_is("location")) {
|
||||
// index id -> location
|
||||
@ -329,5 +338,9 @@ int main(int argc, char* argv[]) {
|
||||
const auto index = create<std::size_t>(options.dense_format(), fd);
|
||||
return run(*index, options);
|
||||
}
|
||||
} catch(const std::exception& e) {
|
||||
std::cerr << "Error: " << e.what() << '\n';
|
||||
std::exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -33,6 +33,10 @@
|
||||
#include <sys/stat.h> // for open
|
||||
#include <sys/types.h> // for open
|
||||
|
||||
#ifdef _WIN32
|
||||
# include <io.h> // for _setmode
|
||||
#endif
|
||||
|
||||
// Allow any format of input files (XML, PBF, ...)
|
||||
#include <osmium/io/any_input.hpp>
|
||||
|
||||
@ -68,11 +72,14 @@ int main(int argc, char* argv[]) {
|
||||
osmium::io::Reader reader{input_filename, osmium::osm_entity_bits::node};
|
||||
|
||||
// Initialize location index on disk creating a new file.
|
||||
const int fd = open(cache_filename.c_str(), O_RDWR | O_CREAT, 0666);
|
||||
const int fd = ::open(cache_filename.c_str(), O_RDWR | O_CREAT | O_TRUNC, 0666);
|
||||
if (fd == -1) {
|
||||
std::cerr << "Can not open location cache file '" << cache_filename << "': " << std::strerror(errno) << "\n";
|
||||
std::exit(1);
|
||||
}
|
||||
#ifdef _WIN32
|
||||
_setmode(fd, _O_BINARY);
|
||||
#endif
|
||||
index_type index{fd};
|
||||
|
||||
// The handler that stores all node locations in the index.
|
||||
|
@ -33,6 +33,10 @@
|
||||
#include <sys/stat.h> // for open
|
||||
#include <sys/types.h> // for open
|
||||
|
||||
#ifdef _WIN32
|
||||
# include <io.h> // for _setmode
|
||||
#endif
|
||||
|
||||
// Allow any format of input files (XML, PBF, ...)
|
||||
#include <osmium/io/any_input.hpp>
|
||||
|
||||
@ -81,11 +85,14 @@ int main(int argc, char* argv[]) {
|
||||
osmium::io::Reader reader{input_filename, osmium::osm_entity_bits::way};
|
||||
|
||||
// Initialize location index on disk using an existing file
|
||||
const int fd = open(cache_filename.c_str(), O_RDWR);
|
||||
const int fd = ::open(cache_filename.c_str(), O_RDWR);
|
||||
if (fd == -1) {
|
||||
std::cerr << "Can not open location cache file '" << cache_filename << "': " << std::strerror(errno) << "\n";
|
||||
return 1;
|
||||
}
|
||||
#ifdef _WIN32
|
||||
_setmode(fd, _O_BINARY);
|
||||
#endif
|
||||
index_type index{fd};
|
||||
|
||||
// The handler that adds node locations from the index to the ways.
|
||||
|
@ -33,14 +33,14 @@
|
||||
#include <osmium/visitor.hpp>
|
||||
|
||||
// For the location index. There are different types of indexes available.
|
||||
// This will work for small and medium sized input files.
|
||||
#include <osmium/index/map/sparse_mem_array.hpp>
|
||||
// This will work for all input files keeping the index in memory.
|
||||
#include <osmium/index/map/flex_mem.hpp>
|
||||
|
||||
// For the NodeLocationForWays handler
|
||||
#include <osmium/handler/node_locations_for_ways.hpp>
|
||||
|
||||
// The type of index used. This must match the include file above
|
||||
using index_type = osmium::index::map::SparseMemArray<osmium::unsigned_object_id_type, osmium::Location>;
|
||||
using index_type = osmium::index::map::FlexMem<osmium::unsigned_object_id_type, osmium::Location>;
|
||||
|
||||
// The location handler always depends on the index type
|
||||
using location_handler_type = osmium::handler::NodeLocationsForWays<index_type>;
|
||||
|
1515
third_party/libosmium/include/osmium/area/assembler.hpp
vendored
1515
third_party/libosmium/include/osmium/area/assembler.hpp
vendored
File diff suppressed because it is too large
Load Diff
154
third_party/libosmium/include/osmium/area/assembler_config.hpp
vendored
Normal file
154
third_party/libosmium/include/osmium/area/assembler_config.hpp
vendored
Normal file
@ -0,0 +1,154 @@
|
||||
#ifndef OSMIUM_AREA_ASSEMBLER_CONFIG_HPP
|
||||
#define OSMIUM_AREA_ASSEMBLER_CONFIG_HPP
|
||||
|
||||
/*
|
||||
|
||||
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||
|
||||
Copyright 2013-2017 Jochen Topf <jochen@topf.org> and others (see README).
|
||||
|
||||
Boost Software License - Version 1.0 - August 17th, 2003
|
||||
|
||||
Permission is hereby granted, free of charge, to any person or organization
|
||||
obtaining a copy of the software and accompanying documentation covered by
|
||||
this license (the "Software") to use, reproduce, display, distribute,
|
||||
execute, and transmit the Software, and to prepare derivative works of the
|
||||
Software, and to permit third-parties to whom the Software is furnished to
|
||||
do so, all subject to the following:
|
||||
|
||||
The copyright notices in the Software and this entire statement, including
|
||||
the above license grant, this restriction and the following disclaimer,
|
||||
must be included in all copies of the Software, in whole or in part, and
|
||||
all derivative works of the Software, unless such copies or derivative
|
||||
works are solely in the form of machine-executable object code generated by
|
||||
a source language processor.
|
||||
|
||||
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, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
#include <osmium/util/compatibility.hpp>
|
||||
|
||||
namespace osmium {
|
||||
|
||||
namespace area {
|
||||
|
||||
class ProblemReporter;
|
||||
|
||||
/**
|
||||
* Configuration for osmium::area::Assembler objects. Create this
|
||||
* once, set the options you want and then re-use it every time you
|
||||
* create an Assembler object.
|
||||
*/
|
||||
struct AssemblerConfig {
|
||||
|
||||
/**
|
||||
* Optional pointer to problem reporter.
|
||||
*/
|
||||
ProblemReporter* problem_reporter = nullptr;
|
||||
|
||||
/**
|
||||
* Debug level. If this is greater than zero, debug messages will
|
||||
* be printed to stderr. Available levels are 1 to 3. Note that
|
||||
* level 2 and above will generate a lot of messages!
|
||||
*/
|
||||
int debug_level = 0;
|
||||
|
||||
/**
|
||||
* The roles of multipolygon members are ignored when assembling
|
||||
* multipolygons, because they are often missing or wrong. If this
|
||||
* is set, the roles are checked after the multipolygons are built
|
||||
* against what the assembly process decided where the inner and
|
||||
* outer rings are. This slows down the processing, so it only
|
||||
* makes sense if you want to get the problem reports.
|
||||
*/
|
||||
bool check_roles = false;
|
||||
|
||||
/**
|
||||
* When the assembler can't create an area, usually because its
|
||||
* geometry would be invalid, it will create an "empty" area object
|
||||
* without rings. This allows you to detect where an area was
|
||||
* invalid.
|
||||
*
|
||||
* If this is set to false, invalid areas will simply be discarded.
|
||||
*/
|
||||
bool create_empty_areas = true;
|
||||
|
||||
/**
|
||||
* Create areas for (multi)polygons where the tags are on the
|
||||
* relation.
|
||||
*
|
||||
* If this is set to false, those areas will simply be discarded.
|
||||
*/
|
||||
bool create_new_style_polygons = true;
|
||||
|
||||
/**
|
||||
* Create areas for (multi)polygons where the tags are on the
|
||||
* outer way(s). This is ignored by the area::Assembler which
|
||||
* doesn't support old-style multipolygons any more. Use the
|
||||
* area::AssemblerLegacy if you need this.
|
||||
*
|
||||
* If this is set to false, those areas will simply be discarded.
|
||||
*/
|
||||
bool create_old_style_polygons = true;
|
||||
|
||||
/**
|
||||
* Create areas for polygons created from ways.
|
||||
*
|
||||
* If this is set to false, those areas will simply be discarded.
|
||||
*/
|
||||
bool create_way_polygons = true;
|
||||
|
||||
/**
|
||||
* Keep the type tag from multipolygon relations on the area
|
||||
* object. By default this is false, and the type tag will be
|
||||
* removed.
|
||||
*/
|
||||
bool keep_type_tag = false;
|
||||
|
||||
/**
|
||||
* If there is an invalid location in any of the ways needed for
|
||||
* assembling the multipolygon, the assembler will normally fail.
|
||||
* If this is set, the assembler will silently ignore the invalid
|
||||
* locations pretending them to be not referenced from the ways.
|
||||
* This will allow some areas to be built, others will now be
|
||||
* incorrect. This can sometimes be useful to assemble areas
|
||||
* crossing the boundary of an extract, but you will also get
|
||||
* geometrically valid but wrong (multi)polygons.
|
||||
*/
|
||||
bool ignore_invalid_locations = false;
|
||||
|
||||
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) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable or disable debug output to stderr. This is for Osmium
|
||||
* developers only.
|
||||
*
|
||||
* @deprecated Set debug_level directly.
|
||||
*/
|
||||
OSMIUM_DEPRECATED void enable_debug_output(bool d = true) {
|
||||
debug_level = d;
|
||||
}
|
||||
|
||||
}; // struct AssemblerConfig
|
||||
|
||||
} // namespace area
|
||||
|
||||
} // namespace osmium
|
||||
|
||||
#endif // OSMIUM_AREA_ASSEMBLER_CONFIG_HPP
|
382
third_party/libosmium/include/osmium/area/assembler_legacy.hpp
vendored
Normal file
382
third_party/libosmium/include/osmium/area/assembler_legacy.hpp
vendored
Normal file
@ -0,0 +1,382 @@
|
||||
#ifndef OSMIUM_AREA_ASSEMBLER_LEGACY_HPP
|
||||
#define OSMIUM_AREA_ASSEMBLER_LEGACY_HPP
|
||||
|
||||
/*
|
||||
|
||||
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||
|
||||
Copyright 2013-2017 Jochen Topf <jochen@topf.org> and others (see README).
|
||||
|
||||
Boost Software License - Version 1.0 - August 17th, 2003
|
||||
|
||||
Permission is hereby granted, free of charge, to any person or organization
|
||||
obtaining a copy of the software and accompanying documentation covered by
|
||||
this license (the "Software") to use, reproduce, display, distribute,
|
||||
execute, and transmit the Software, and to prepare derivative works of the
|
||||
Software, and to permit third-parties to whom the Software is furnished to
|
||||
do so, all subject to the following:
|
||||
|
||||
The copyright notices in the Software and this entire statement, including
|
||||
the above license grant, this restriction and the following disclaimer,
|
||||
must be included in all copies of the Software, in whole or in part, and
|
||||
all derivative works of the Software, unless such copies or derivative
|
||||
works are solely in the form of machine-executable object code generated by
|
||||
a source language processor.
|
||||
|
||||
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, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
#include <functional>
|
||||
#include <iostream>
|
||||
#include <iterator>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include <osmium/area/assembler_config.hpp>
|
||||
#include <osmium/area/detail/basic_assembler_with_tags.hpp>
|
||||
#include <osmium/area/detail/proto_ring.hpp>
|
||||
#include <osmium/area/detail/segment_list.hpp>
|
||||
#include <osmium/area/problem_reporter.hpp>
|
||||
#include <osmium/area/stats.hpp>
|
||||
#include <osmium/builder/osm_object_builder.hpp>
|
||||
#include <osmium/memory/buffer.hpp>
|
||||
#include <osmium/memory/collection.hpp>
|
||||
#include <osmium/osm/area.hpp>
|
||||
#include <osmium/osm/item_type.hpp>
|
||||
#include <osmium/osm/node_ref.hpp>
|
||||
#include <osmium/osm/relation.hpp>
|
||||
#include <osmium/osm/tag.hpp>
|
||||
#include <osmium/osm/way.hpp>
|
||||
#include <osmium/tags/filter.hpp>
|
||||
|
||||
namespace osmium {
|
||||
|
||||
namespace area {
|
||||
|
||||
/**
|
||||
* Assembles area objects from closed ways or multipolygon relations
|
||||
* and their members.
|
||||
*/
|
||||
class AssemblerLegacy : public detail::BasicAssemblerWithTags {
|
||||
|
||||
void add_tags_to_area(osmium::builder::AreaBuilder& builder, const osmium::Way& way) const {
|
||||
builder.add_item(way.tags());
|
||||
}
|
||||
|
||||
void add_common_tags(osmium::builder::TagListBuilder& tl_builder, std::set<const osmium::Way*>& ways) const {
|
||||
std::map<std::string, std::size_t> counter;
|
||||
for (const osmium::Way* way : ways) {
|
||||
for (const auto& tag : way->tags()) {
|
||||
std::string kv{tag.key()};
|
||||
kv.append(1, '\0');
|
||||
kv.append(tag.value());
|
||||
++counter[kv];
|
||||
}
|
||||
}
|
||||
|
||||
const std::size_t num_ways = ways.size();
|
||||
for (const auto& t_c : counter) {
|
||||
if (debug()) {
|
||||
std::cerr << " tag " << t_c.first << " is used " << t_c.second << " times in " << num_ways << " ways\n";
|
||||
}
|
||||
if (t_c.second == num_ways) {
|
||||
const std::size_t len = std::strlen(t_c.first.c_str());
|
||||
tl_builder.add_tag(t_c.first.c_str(), t_c.first.c_str() + len + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct MPFilter : public osmium::tags::KeyFilter {
|
||||
|
||||
MPFilter() : osmium::tags::KeyFilter(true) {
|
||||
add(false, "type");
|
||||
add(false, "created_by");
|
||||
add(false, "source");
|
||||
add(false, "note");
|
||||
add(false, "test:id");
|
||||
add(false, "test:section");
|
||||
}
|
||||
|
||||
}; // struct MPFilter
|
||||
|
||||
static const MPFilter& filter() noexcept {
|
||||
static const MPFilter filter;
|
||||
return filter;
|
||||
}
|
||||
|
||||
void add_tags_to_area(osmium::builder::AreaBuilder& builder, const osmium::Relation& relation) {
|
||||
const auto count = std::count_if(relation.tags().cbegin(), relation.tags().cend(), std::cref(filter()));
|
||||
|
||||
if (debug()) {
|
||||
std::cerr << " found " << count << " tags on relation (without ignored ones)\n";
|
||||
}
|
||||
|
||||
if (count > 0) {
|
||||
if (debug()) {
|
||||
std::cerr << " use tags from relation\n";
|
||||
}
|
||||
|
||||
if (config().keep_type_tag) {
|
||||
builder.add_item(relation.tags());
|
||||
} else {
|
||||
copy_tags_without_type(builder, relation.tags());
|
||||
}
|
||||
} else {
|
||||
++stats().no_tags_on_relation;
|
||||
if (debug()) {
|
||||
std::cerr << " use tags from outer ways\n";
|
||||
}
|
||||
std::set<const osmium::Way*> ways;
|
||||
for (const auto& ring : rings()) {
|
||||
if (ring.is_outer()) {
|
||||
ring.get_ways(ways);
|
||||
}
|
||||
}
|
||||
if (ways.size() == 1) {
|
||||
if (debug()) {
|
||||
std::cerr << " only one outer way\n";
|
||||
}
|
||||
builder.add_item((*ways.cbegin())->tags());
|
||||
} else {
|
||||
if (debug()) {
|
||||
std::cerr << " multiple outer ways, get common tags\n";
|
||||
}
|
||||
osmium::builder::TagListBuilder tl_builder{builder};
|
||||
add_common_tags(tl_builder, ways);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool create_area(osmium::memory::Buffer& out_buffer, const osmium::Way& way) {
|
||||
osmium::builder::AreaBuilder builder{out_buffer};
|
||||
builder.initialize_from_object(way);
|
||||
|
||||
const bool area_okay = create_rings();
|
||||
if (area_okay || config().create_empty_areas) {
|
||||
add_tags_to_area(builder, way);
|
||||
}
|
||||
if (area_okay) {
|
||||
add_rings_to_area(builder);
|
||||
}
|
||||
|
||||
if (report_ways()) {
|
||||
config().problem_reporter->report_way(way);
|
||||
}
|
||||
|
||||
return area_okay || config().create_empty_areas;
|
||||
}
|
||||
|
||||
bool create_area(osmium::memory::Buffer& out_buffer, const osmium::Relation& relation, const std::vector<const osmium::Way*>& members) {
|
||||
set_num_members(members.size());
|
||||
osmium::builder::AreaBuilder builder{out_buffer};
|
||||
builder.initialize_from_object(relation);
|
||||
|
||||
const bool area_okay = create_rings();
|
||||
if (area_okay || config().create_empty_areas) {
|
||||
add_tags_to_area(builder, relation);
|
||||
}
|
||||
if (area_okay) {
|
||||
add_rings_to_area(builder);
|
||||
}
|
||||
|
||||
if (report_ways()) {
|
||||
for (const osmium::Way* way : members) {
|
||||
config().problem_reporter->report_way(*way);
|
||||
}
|
||||
}
|
||||
|
||||
return area_okay || config().create_empty_areas;
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
explicit AssemblerLegacy(const config_type& config) :
|
||||
detail::BasicAssemblerWithTags(config) {
|
||||
}
|
||||
|
||||
~AssemblerLegacy() noexcept = default;
|
||||
|
||||
/**
|
||||
* Assemble an area from the given way.
|
||||
* The resulting area is put into the out_buffer.
|
||||
*
|
||||
* @returns false if there was some kind of error building the
|
||||
* area, true otherwise.
|
||||
*/
|
||||
bool operator()(const osmium::Way& way, osmium::memory::Buffer& out_buffer) {
|
||||
if (!config().create_way_polygons) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (way.tags().has_tag("area", "no")) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (config().problem_reporter) {
|
||||
config().problem_reporter->set_object(osmium::item_type::way, way.id());
|
||||
config().problem_reporter->set_nodes(way.nodes().size());
|
||||
}
|
||||
|
||||
// Ignore (but count) ways without segments.
|
||||
if (way.nodes().size() < 2) {
|
||||
++stats().short_ways;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!way.ends_have_same_id()) {
|
||||
++stats().duplicate_nodes;
|
||||
if (config().problem_reporter) {
|
||||
config().problem_reporter->report_duplicate_node(way.nodes().front().ref(), way.nodes().back().ref(), way.nodes().front().location());
|
||||
}
|
||||
}
|
||||
|
||||
++stats().from_ways;
|
||||
stats().invalid_locations = segment_list().extract_segments_from_way(config().problem_reporter,
|
||||
stats().duplicate_nodes,
|
||||
way);
|
||||
if (!config().ignore_invalid_locations && stats().invalid_locations > 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (config().debug_level > 0) {
|
||||
std::cerr << "\nAssembling way " << way.id() << " containing " << segment_list().size() << " nodes\n";
|
||||
}
|
||||
|
||||
// Now create the Area object and add the attributes and tags
|
||||
// from the way.
|
||||
const bool okay = create_area(out_buffer, way);
|
||||
if (okay) {
|
||||
out_buffer.commit();
|
||||
} else {
|
||||
out_buffer.rollback();
|
||||
}
|
||||
|
||||
if (debug()) {
|
||||
std::cerr << "Done: " << stats() << "\n";
|
||||
}
|
||||
|
||||
return okay;
|
||||
}
|
||||
|
||||
/**
|
||||
* Assemble an area from the given relation and its members.
|
||||
* The resulting area is put into the out_buffer.
|
||||
*
|
||||
* @returns false if there was some kind of error building the
|
||||
* area(s), true otherwise.
|
||||
*/
|
||||
bool operator()(const osmium::Relation& relation, const std::vector<const osmium::Way*>& members, osmium::memory::Buffer& out_buffer) {
|
||||
assert(relation.members().size() >= members.size());
|
||||
|
||||
if (config().problem_reporter) {
|
||||
config().problem_reporter->set_object(osmium::item_type::relation, relation.id());
|
||||
}
|
||||
|
||||
if (relation.members().empty()) {
|
||||
++stats().no_way_in_mp_relation;
|
||||
return false;
|
||||
}
|
||||
|
||||
++stats().from_relations;
|
||||
stats().invalid_locations = segment_list().extract_segments_from_ways(config().problem_reporter,
|
||||
stats().duplicate_nodes,
|
||||
stats().duplicate_ways,
|
||||
relation,
|
||||
members);
|
||||
if (!config().ignore_invalid_locations && stats().invalid_locations > 0) {
|
||||
return false;
|
||||
}
|
||||
stats().member_ways = members.size();
|
||||
|
||||
if (stats().member_ways == 1) {
|
||||
++stats().single_way_in_mp_relation;
|
||||
}
|
||||
|
||||
if (config().debug_level > 0) {
|
||||
std::cerr << "\nAssembling relation " << relation.id() << " containing " << members.size() << " way members with " << segment_list().size() << " nodes\n";
|
||||
}
|
||||
|
||||
const std::size_t area_offset = out_buffer.committed();
|
||||
|
||||
// Now create the Area object and add the attributes and tags
|
||||
// from the relation.
|
||||
bool okay = create_area(out_buffer, relation, members);
|
||||
if (okay) {
|
||||
if ((config().create_new_style_polygons && stats().no_tags_on_relation == 0) ||
|
||||
(config().create_old_style_polygons && stats().no_tags_on_relation != 0)) {
|
||||
out_buffer.commit();
|
||||
} else {
|
||||
out_buffer.rollback();
|
||||
}
|
||||
} else {
|
||||
out_buffer.rollback();
|
||||
}
|
||||
|
||||
const osmium::TagList& area_tags = out_buffer.get<osmium::Area>(area_offset).tags(); // tags of the area we just built
|
||||
|
||||
// Find all closed ways that are inner rings and check their
|
||||
// tags. If they are not the same as the tags of the area we
|
||||
// just built, add them to a list and later build areas for
|
||||
// them, too.
|
||||
std::vector<const osmium::Way*> ways_that_should_be_areas;
|
||||
if (stats().wrong_role == 0) {
|
||||
detail::for_each_member(relation, members, [this, &ways_that_should_be_areas, &area_tags](const osmium::RelationMember& member, const osmium::Way& way) {
|
||||
if (!std::strcmp(member.role(), "inner")) {
|
||||
if (!way.nodes().empty() && way.is_closed() && way.tags().size() > 0) {
|
||||
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());
|
||||
|
||||
if (!std::equal(way_fi_begin, way_fi_end, area_fi_begin) || d != std::distance(area_fi_begin, area_fi_end)) {
|
||||
ways_that_should_be_areas.push_back(&way);
|
||||
} else {
|
||||
++stats().inner_with_same_tags;
|
||||
if (config().problem_reporter) {
|
||||
config().problem_reporter->report_inner_with_same_tags(way);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (debug()) {
|
||||
std::cerr << "Done: " << stats() << "\n";
|
||||
}
|
||||
|
||||
// Now build areas for all ways found in the last step.
|
||||
for (const osmium::Way* way : ways_that_should_be_areas) {
|
||||
AssemblerLegacy assembler{config()};
|
||||
if (!assembler(*way, out_buffer)) {
|
||||
okay = false;
|
||||
}
|
||||
stats() += assembler.stats();
|
||||
}
|
||||
|
||||
return okay;
|
||||
}
|
||||
|
||||
}; // class AssemblerLegacy
|
||||
|
||||
} // namespace area
|
||||
|
||||
} // namespace osmium
|
||||
|
||||
#endif // OSMIUM_AREA_ASSEMBLER_LEGACY_HPP
|
1203
third_party/libosmium/include/osmium/area/detail/basic_assembler.hpp
vendored
Normal file
1203
third_party/libosmium/include/osmium/area/detail/basic_assembler.hpp
vendored
Normal file
File diff suppressed because it is too large
Load Diff
93
third_party/libosmium/include/osmium/area/detail/basic_assembler_with_tags.hpp
vendored
Normal file
93
third_party/libosmium/include/osmium/area/detail/basic_assembler_with_tags.hpp
vendored
Normal file
@ -0,0 +1,93 @@
|
||||
#ifndef OSMIUM_AREA_DETAIL_BASIC_ASSEMBLER_WITH_TAGS_HPP
|
||||
#define OSMIUM_AREA_DETAIL_BASIC_ASSEMBLER_WITH_TAGS_HPP
|
||||
|
||||
/*
|
||||
|
||||
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||
|
||||
Copyright 2013-2017 Jochen Topf <jochen@topf.org> and others (see README).
|
||||
|
||||
Boost Software License - Version 1.0 - August 17th, 2003
|
||||
|
||||
Permission is hereby granted, free of charge, to any person or organization
|
||||
obtaining a copy of the software and accompanying documentation covered by
|
||||
this license (the "Software") to use, reproduce, display, distribute,
|
||||
execute, and transmit the Software, and to prepare derivative works of the
|
||||
Software, and to permit third-parties to whom the Software is furnished to
|
||||
do so, all subject to the following:
|
||||
|
||||
The copyright notices in the Software and this entire statement, including
|
||||
the above license grant, this restriction and the following disclaimer,
|
||||
must be included in all copies of the Software, in whole or in part, and
|
||||
all derivative works of the Software, unless such copies or derivative
|
||||
works are solely in the form of machine-executable object code generated by
|
||||
a source language processor.
|
||||
|
||||
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, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
#include <cstring>
|
||||
|
||||
#include <osmium/area/assembler_config.hpp>
|
||||
#include <osmium/area/detail/basic_assembler.hpp>
|
||||
#include <osmium/area/stats.hpp>
|
||||
#include <osmium/builder/osm_object_builder.hpp>
|
||||
#include <osmium/osm/tag.hpp>
|
||||
|
||||
namespace osmium {
|
||||
|
||||
namespace area {
|
||||
|
||||
namespace detail {
|
||||
|
||||
class BasicAssemblerWithTags : public detail::BasicAssembler {
|
||||
|
||||
protected:
|
||||
|
||||
bool report_ways() const noexcept {
|
||||
if (!config().problem_reporter) {
|
||||
return false;
|
||||
}
|
||||
return stats().duplicate_nodes ||
|
||||
stats().duplicate_segments ||
|
||||
stats().intersections ||
|
||||
stats().open_rings ||
|
||||
stats().short_ways ||
|
||||
stats().touching_rings ||
|
||||
stats().ways_in_multiple_rings ||
|
||||
stats().wrong_role;
|
||||
}
|
||||
|
||||
static void copy_tags_without_type(osmium::builder::AreaBuilder& builder, const osmium::TagList& tags) {
|
||||
osmium::builder::TagListBuilder tl_builder{builder};
|
||||
for (const osmium::Tag& tag : tags) {
|
||||
if (std::strcmp(tag.key(), "type")) {
|
||||
tl_builder.add_tag(tag.key(), tag.value());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
using config_type = osmium::area::AssemblerConfig;
|
||||
|
||||
explicit BasicAssemblerWithTags(const config_type& config) :
|
||||
BasicAssembler(config) {
|
||||
}
|
||||
|
||||
}; // class BasicAssemblerWithTags
|
||||
|
||||
} // namespace detail
|
||||
|
||||
} // namespace area
|
||||
|
||||
} // namespace osmium
|
||||
|
||||
#endif // OSMIUM_AREA_DETAIL_BASIC_ASSEMBLER_WITH_TAGS_HPP
|
@ -106,7 +106,7 @@ namespace osmium {
|
||||
m_role(role_type::unknown) {
|
||||
}
|
||||
|
||||
NodeRefSegment(const osmium::NodeRef& nr1, const osmium::NodeRef& nr2, role_type role = role_type::unknown, const osmium::Way* way = nullptr) noexcept :
|
||||
NodeRefSegment(const osmium::NodeRef& nr1, const osmium::NodeRef& nr2, role_type role, const osmium::Way* way) noexcept :
|
||||
m_first(nr1),
|
||||
m_second(nr2),
|
||||
m_way(way),
|
||||
@ -262,18 +262,6 @@ namespace osmium {
|
||||
return lhs.first().location() < rhs.first().location();
|
||||
}
|
||||
|
||||
inline bool operator>(const NodeRefSegment& lhs, const NodeRefSegment& rhs) noexcept {
|
||||
return rhs < lhs;
|
||||
}
|
||||
|
||||
inline bool operator<=(const NodeRefSegment& lhs, const NodeRefSegment& rhs) noexcept {
|
||||
return ! (rhs < lhs);
|
||||
}
|
||||
|
||||
inline bool operator>=(const NodeRefSegment& lhs, const NodeRefSegment& rhs) noexcept {
|
||||
return ! (lhs < rhs);
|
||||
}
|
||||
|
||||
template <typename TChar, typename TTraits>
|
||||
inline std::basic_ostream<TChar, TTraits>& operator<<(std::basic_ostream<TChar, TTraits>& out, const NodeRefSegment& segment) {
|
||||
return out << segment.start() << "--" << segment.stop()
|
||||
@ -283,19 +271,13 @@ namespace osmium {
|
||||
}
|
||||
|
||||
inline bool outside_x_range(const NodeRefSegment& s1, const NodeRefSegment& s2) noexcept {
|
||||
if (s1.first().location().x() > s2.second().location().x()) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
return s1.first().location().x() > s2.second().location().x();
|
||||
}
|
||||
|
||||
inline bool y_range_overlap(const NodeRefSegment& s1, const NodeRefSegment& s2) noexcept {
|
||||
const std::pair<int32_t, int32_t> m1 = std::minmax(s1.first().location().y(), s1.second().location().y());
|
||||
const std::pair<int32_t, int32_t> m2 = std::minmax(s2.first().location().y(), s2.second().location().y());
|
||||
if (m1.first > m2.second || m2.first > m1.second) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
return !(m1.first > m2.second || m2.first > m1.second);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -331,7 +313,7 @@ namespace osmium {
|
||||
if ((p0 == q0 && p1 == q1) ||
|
||||
(p0 == q1 && p1 == q0)) {
|
||||
// segments are the same
|
||||
return osmium::Location();
|
||||
return osmium::Location{};
|
||||
}
|
||||
|
||||
const vec pd = p1 - p0;
|
||||
@ -342,7 +324,7 @@ namespace osmium {
|
||||
|
||||
if (p0 == q0 || p0 == q1 || p1 == q0 || p1 == q1) {
|
||||
// touching at an end point
|
||||
return osmium::Location();
|
||||
return osmium::Location{};
|
||||
}
|
||||
|
||||
// intersection in a point
|
||||
@ -357,10 +339,10 @@ namespace osmium {
|
||||
(d < 0 && na <= 0 && na >= d && nb <= 0 && nb >= d)) {
|
||||
const double ua = double(na) / d;
|
||||
const vec i = p0 + ua * (p1 - p0);
|
||||
return osmium::Location(int32_t(i.x), int32_t(i.y));
|
||||
return osmium::Location{int32_t(i.x), int32_t(i.y)};
|
||||
}
|
||||
|
||||
return osmium::Location();
|
||||
return osmium::Location{};
|
||||
}
|
||||
|
||||
// segments are collinear
|
||||
@ -390,13 +372,12 @@ namespace osmium {
|
||||
if (sl[0].segment != sl[1].segment) {
|
||||
if (sl[0].location == sl[1].location) {
|
||||
return sl[2].location;
|
||||
} else {
|
||||
}
|
||||
return sl[1].location;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return osmium::Location();
|
||||
return osmium::Location{};
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
@ -77,6 +77,15 @@ namespace osmium {
|
||||
// If this is an inner ring, points to the outer ring.
|
||||
ProtoRing* m_outer_ring;
|
||||
|
||||
#ifdef OSMIUM_DEBUG_RING_NO
|
||||
static int64_t next_num() noexcept {
|
||||
static int64_t counter = 0;
|
||||
return ++counter;
|
||||
}
|
||||
|
||||
int64_t m_num;
|
||||
#endif
|
||||
|
||||
int64_t m_sum;
|
||||
|
||||
public:
|
||||
@ -86,6 +95,9 @@ namespace osmium {
|
||||
m_inner(),
|
||||
m_min_segment(segment),
|
||||
m_outer_ring(nullptr),
|
||||
#ifdef OSMIUM_DEBUG_RING_NO
|
||||
m_num(next_num()),
|
||||
#endif
|
||||
m_sum(0) {
|
||||
add_segment_back(segment);
|
||||
}
|
||||
@ -200,7 +212,11 @@ namespace osmium {
|
||||
}
|
||||
|
||||
void print(std::ostream& out) const {
|
||||
out << "[";
|
||||
#ifdef OSMIUM_DEBUG_RING_NO
|
||||
out << "Ring #" << m_num << " [";
|
||||
#else
|
||||
out << "Ring [";
|
||||
#endif
|
||||
if (!m_segments.empty()) {
|
||||
out << m_segments.front()->start().ref();
|
||||
}
|
||||
|
@ -40,6 +40,7 @@ DEALINGS IN THE SOFTWARE.
|
||||
#include <iostream>
|
||||
#include <iterator>
|
||||
#include <numeric>
|
||||
#include <unordered_set>
|
||||
#include <vector>
|
||||
|
||||
#include <osmium/area/detail/node_ref_segment.hpp>
|
||||
@ -48,6 +49,7 @@ DEALINGS IN THE SOFTWARE.
|
||||
#include <osmium/osm/location.hpp>
|
||||
#include <osmium/osm/node_ref.hpp>
|
||||
#include <osmium/osm/relation.hpp>
|
||||
#include <osmium/osm/types.hpp>
|
||||
#include <osmium/osm/way.hpp>
|
||||
|
||||
namespace osmium {
|
||||
@ -89,9 +91,11 @@ namespace osmium {
|
||||
static role_type parse_role(const char* role) noexcept {
|
||||
if (role[0] == '\0') {
|
||||
return role_type::empty;
|
||||
} else if (!std::strcmp(role, "outer")) {
|
||||
}
|
||||
if (!std::strcmp(role, "outer")) {
|
||||
return role_type::outer;
|
||||
} else if (!std::strcmp(role, "inner")) {
|
||||
}
|
||||
if (!std::strcmp(role, "inner")) {
|
||||
return role_type::inner;
|
||||
}
|
||||
return role_type::unknown;
|
||||
@ -100,21 +104,27 @@ namespace osmium {
|
||||
/**
|
||||
* Calculate the number of segments in all the ways together.
|
||||
*/
|
||||
static size_t get_num_segments(const std::vector<const osmium::Way*>& members) noexcept {
|
||||
return std::accumulate(members.cbegin(), members.cend(), static_cast<size_t>(0), [](size_t sum, const osmium::Way* way) {
|
||||
static std::size_t get_num_segments(const std::vector<const osmium::Way*>& members) noexcept {
|
||||
return std::accumulate(members.cbegin(), members.cend(), static_cast<std::size_t>(0), [](std::size_t sum, const osmium::Way* way) {
|
||||
if (way->nodes().empty()) {
|
||||
return sum;
|
||||
} else {
|
||||
return sum + way->nodes().size() - 1;
|
||||
}
|
||||
return sum + way->nodes().size() - 1;
|
||||
});
|
||||
}
|
||||
|
||||
uint32_t extract_segments_from_way_impl(osmium::area::ProblemReporter* problem_reporter, const osmium::Way& way, role_type role) {
|
||||
uint32_t duplicate_nodes = 0;
|
||||
uint32_t extract_segments_from_way_impl(ProblemReporter* problem_reporter, uint64_t& duplicate_nodes, const osmium::Way& way, role_type role) {
|
||||
uint32_t invalid_locations = 0;
|
||||
|
||||
osmium::NodeRef previous_nr;
|
||||
for (const osmium::NodeRef& nr : way.nodes()) {
|
||||
if (!nr.location().valid()) {
|
||||
++invalid_locations;
|
||||
if (problem_reporter) {
|
||||
problem_reporter->report_invalid_location(way.id(), nr.ref());
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (previous_nr.location()) {
|
||||
if (previous_nr.location() != nr.location()) {
|
||||
m_segments.emplace_back(previous_nr, nr, role, &way);
|
||||
@ -128,7 +138,7 @@ namespace osmium {
|
||||
previous_nr = nr;
|
||||
}
|
||||
|
||||
return duplicate_nodes;
|
||||
return invalid_locations;
|
||||
}
|
||||
|
||||
public:
|
||||
@ -147,7 +157,7 @@ namespace osmium {
|
||||
SegmentList& operator=(SegmentList&&) = delete;
|
||||
|
||||
/// The number of segments in the list.
|
||||
size_t size() const noexcept {
|
||||
std::size_t size() const noexcept {
|
||||
return m_segments.size();
|
||||
}
|
||||
|
||||
@ -167,12 +177,12 @@ namespace osmium {
|
||||
return m_segments.back();
|
||||
}
|
||||
|
||||
const NodeRefSegment& operator[](size_t n) const noexcept {
|
||||
const NodeRefSegment& operator[](std::size_t n) const noexcept {
|
||||
assert(n < m_segments.size());
|
||||
return m_segments[n];
|
||||
}
|
||||
|
||||
NodeRefSegment& operator[](size_t n) noexcept {
|
||||
NodeRefSegment& operator[](std::size_t n) noexcept {
|
||||
assert(n < m_segments.size());
|
||||
return m_segments[n];
|
||||
}
|
||||
@ -213,33 +223,48 @@ namespace osmium {
|
||||
* same node or different nodes with same location) are
|
||||
* removed after reporting the duplicate node.
|
||||
*/
|
||||
uint32_t extract_segments_from_way(osmium::area::ProblemReporter* problem_reporter, const osmium::Way& way) {
|
||||
uint32_t extract_segments_from_way(ProblemReporter* problem_reporter, uint64_t& duplicate_nodes, const osmium::Way& way) {
|
||||
if (way.nodes().empty()) {
|
||||
return 0;
|
||||
}
|
||||
m_segments.reserve(way.nodes().size() - 1);
|
||||
return extract_segments_from_way_impl(problem_reporter, way, role_type::outer);
|
||||
return extract_segments_from_way_impl(problem_reporter, duplicate_nodes, way, role_type::outer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract all segments from all ways that make up this
|
||||
* multipolygon relation and add them to the list.
|
||||
*/
|
||||
uint32_t extract_segments_from_ways(osmium::area::ProblemReporter* problem_reporter, const osmium::Relation& relation, const std::vector<const osmium::Way*>& members) {
|
||||
assert(relation.members().size() >= members.size());
|
||||
uint32_t extract_segments_from_ways(ProblemReporter* problem_reporter,
|
||||
uint64_t& duplicate_nodes,
|
||||
uint64_t& duplicate_ways,
|
||||
const osmium::Relation& relation,
|
||||
const std::vector<const osmium::Way*>& members) {
|
||||
assert(relation.cmembers().size() >= members.size());
|
||||
|
||||
const size_t num_segments = get_num_segments(members);
|
||||
const std::size_t num_segments = get_num_segments(members);
|
||||
if (problem_reporter) {
|
||||
problem_reporter->set_nodes(num_segments);
|
||||
}
|
||||
m_segments.reserve(num_segments);
|
||||
|
||||
uint32_t duplicate_nodes = 0;
|
||||
for_each_member(relation, members, [this, &problem_reporter, &duplicate_nodes](const osmium::RelationMember& member, const osmium::Way& way) {
|
||||
duplicate_nodes += extract_segments_from_way_impl(problem_reporter, way, parse_role(member.role()));
|
||||
std::unordered_set<osmium::object_id_type> ids;
|
||||
ids.reserve(members.size());
|
||||
uint32_t invalid_locations = 0;
|
||||
for_each_member(relation, members, [&](const osmium::RelationMember& member, const osmium::Way& way) {
|
||||
if (ids.count(way.id()) == 0) {
|
||||
ids.insert(way.id());
|
||||
const auto role = parse_role(member.role());
|
||||
invalid_locations += extract_segments_from_way_impl(problem_reporter, duplicate_nodes, way, role);
|
||||
} else {
|
||||
++duplicate_ways;
|
||||
if (problem_reporter) {
|
||||
problem_reporter->report_duplicate_way(way);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return duplicate_nodes;
|
||||
return invalid_locations;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -248,9 +273,7 @@ namespace osmium {
|
||||
* same segment. So if there are three, for instance, two will
|
||||
* be removed and one will be left.
|
||||
*/
|
||||
uint32_t erase_duplicate_segments(osmium::area::ProblemReporter* problem_reporter) {
|
||||
uint32_t duplicate_segments = 0;
|
||||
|
||||
void erase_duplicate_segments(ProblemReporter* problem_reporter, uint64_t& duplicate_segments, uint64_t& overlapping_segments) {
|
||||
while (true) {
|
||||
auto it = std::adjacent_find(m_segments.begin(), m_segments.end());
|
||||
if (it == m_segments.end()) {
|
||||
@ -273,10 +296,16 @@ namespace osmium {
|
||||
problem_reporter->report_duplicate_segment(it->first(), it->second());
|
||||
}
|
||||
}
|
||||
m_segments.erase(it, it+2);
|
||||
|
||||
if (it+2 != m_segments.end() && *it == *(it+2)) {
|
||||
++overlapping_segments;
|
||||
if (problem_reporter) {
|
||||
problem_reporter->report_overlapping_segment(it->first(), it->second());
|
||||
}
|
||||
}
|
||||
|
||||
return duplicate_segments;
|
||||
m_segments.erase(it, it+2);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -286,14 +315,14 @@ namespace osmium {
|
||||
* reported to this object.
|
||||
* @returns true if there are intersections.
|
||||
*/
|
||||
uint32_t find_intersections(osmium::area::ProblemReporter* problem_reporter) const {
|
||||
uint32_t find_intersections(ProblemReporter* problem_reporter) const {
|
||||
if (m_segments.empty()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t found_intersections = 0;
|
||||
|
||||
for (auto it1 = m_segments.cbegin(); it1 != m_segments.cend()-1; ++it1) {
|
||||
for (auto it1 = m_segments.cbegin(); it1 != m_segments.cend() - 1; ++it1) {
|
||||
const NodeRefSegment& s1 = *it1;
|
||||
for (auto it2 = it1+1; it2 != m_segments.end(); ++it2) {
|
||||
const NodeRefSegment& s2 = *it2;
|
||||
@ -305,7 +334,7 @@ namespace osmium {
|
||||
}
|
||||
|
||||
if (y_range_overlap(s1, s2)) {
|
||||
osmium::Location intersection = calculate_intersection(s1, s2);
|
||||
osmium::Location intersection{calculate_intersection(s1, s2)};
|
||||
if (intersection) {
|
||||
++found_intersections;
|
||||
if (m_debug) {
|
||||
|
132
third_party/libosmium/include/osmium/area/geom_assembler.hpp
vendored
Normal file
132
third_party/libosmium/include/osmium/area/geom_assembler.hpp
vendored
Normal file
@ -0,0 +1,132 @@
|
||||
#ifndef OSMIUM_AREA_GEOM_ASSEMBLER_HPP
|
||||
#define OSMIUM_AREA_GEOM_ASSEMBLER_HPP
|
||||
|
||||
/*
|
||||
|
||||
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||
|
||||
Copyright 2013-2017 Jochen Topf <jochen@topf.org> and others (see README).
|
||||
|
||||
Boost Software License - Version 1.0 - August 17th, 2003
|
||||
|
||||
Permission is hereby granted, free of charge, to any person or organization
|
||||
obtaining a copy of the software and accompanying documentation covered by
|
||||
this license (the "Software") to use, reproduce, display, distribute,
|
||||
execute, and transmit the Software, and to prepare derivative works of the
|
||||
Software, and to permit third-parties to whom the Software is furnished to
|
||||
do so, all subject to the following:
|
||||
|
||||
The copyright notices in the Software and this entire statement, including
|
||||
the above license grant, this restriction and the following disclaimer,
|
||||
must be included in all copies of the Software, in whole or in part, and
|
||||
all derivative works of the Software, unless such copies or derivative
|
||||
works are solely in the form of machine-executable object code generated by
|
||||
a source language processor.
|
||||
|
||||
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, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
#include <osmium/area/assembler_config.hpp>
|
||||
#include <osmium/area/detail/basic_assembler.hpp>
|
||||
#include <osmium/area/detail/segment_list.hpp>
|
||||
#include <osmium/area/stats.hpp>
|
||||
#include <osmium/builder/osm_object_builder.hpp>
|
||||
#include <osmium/memory/buffer.hpp>
|
||||
#include <osmium/osm/relation.hpp>
|
||||
#include <osmium/osm/way.hpp>
|
||||
|
||||
namespace osmium {
|
||||
|
||||
namespace area {
|
||||
|
||||
/**
|
||||
* Assembles area objects from closed ways or multipolygon relations
|
||||
* and their members. Unlike the Assembler, this one doesn't take
|
||||
* tags into account at all. And it doesn't interpret all the config
|
||||
* settings and doesn't do all the checks and error reporting the
|
||||
* Assembler does.
|
||||
*
|
||||
* This class was developed specifically for the need of osm2pgsql.
|
||||
* Unless you know what you are doing, use the Assembler class instead
|
||||
* of this class. Contact the Libosmium developers if you want to use
|
||||
* this class.
|
||||
*/
|
||||
class GeomAssembler : public detail::BasicAssembler {
|
||||
|
||||
public:
|
||||
|
||||
using config_type = osmium::area::AssemblerConfig;
|
||||
|
||||
explicit GeomAssembler(const config_type& config) :
|
||||
detail::BasicAssembler(config) {
|
||||
}
|
||||
|
||||
~GeomAssembler() noexcept = default;
|
||||
|
||||
/**
|
||||
* Assemble an area from the given way.
|
||||
*
|
||||
* The resulting area is put into the out_buffer.
|
||||
*
|
||||
* @returns false if there was some kind of error building the
|
||||
* area, true otherwise.
|
||||
*/
|
||||
bool operator()(const osmium::Way& way, osmium::memory::Buffer& out_buffer) {
|
||||
segment_list().extract_segments_from_way(config().problem_reporter, stats().duplicate_nodes, way);
|
||||
|
||||
if (!create_rings()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
{
|
||||
osmium::builder::AreaBuilder builder{out_buffer};
|
||||
builder.initialize_from_object(way);
|
||||
add_rings_to_area(builder);
|
||||
}
|
||||
out_buffer.commit();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Assemble an area from the given relation and its member ways
|
||||
* which are in the ways_buffer.
|
||||
*
|
||||
* The resulting area is put into the out_buffer.
|
||||
*
|
||||
* @returns false if there was some kind of error building the
|
||||
* area, true otherwise.
|
||||
*/
|
||||
bool operator()(const osmium::Relation& relation, const osmium::memory::Buffer& ways_buffer, osmium::memory::Buffer& out_buffer) {
|
||||
for (const auto& way : ways_buffer.select<osmium::Way>()) {
|
||||
segment_list().extract_segments_from_way(config().problem_reporter, stats().duplicate_nodes, way);
|
||||
}
|
||||
|
||||
if (!create_rings()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
{
|
||||
osmium::builder::AreaBuilder builder{out_buffer};
|
||||
builder.initialize_from_object(relation);
|
||||
add_rings_to_area(builder);
|
||||
}
|
||||
out_buffer.commit();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}; // class GeomAssembler
|
||||
|
||||
} // namespace area
|
||||
|
||||
} // namespace osmium
|
||||
|
||||
#endif // OSMIUM_AREA_GEOM_ASSEMBLER_HPP
|
@ -81,7 +81,7 @@ namespace osmium {
|
||||
|
||||
osmium::memory::Buffer m_output_buffer;
|
||||
|
||||
osmium::area::area_stats m_stats;
|
||||
area_stats m_stats;
|
||||
|
||||
static constexpr size_t initial_output_buffer_size = 1024 * 1024;
|
||||
static constexpr size_t max_buffer_size_for_flush = 100 * 1024;
|
||||
@ -109,7 +109,7 @@ namespace osmium {
|
||||
m_output_buffer(initial_output_buffer_size, osmium::memory::Buffer::auto_grow::yes) {
|
||||
}
|
||||
|
||||
const osmium::area::area_stats& stats() const noexcept {
|
||||
const area_stats& stats() const noexcept {
|
||||
return m_stats;
|
||||
}
|
||||
|
||||
@ -127,11 +127,7 @@ namespace osmium {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((!std::strcmp(type, "multipolygon")) || (!std::strcmp(type, "boundary"))) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
return (!std::strcmp(type, "multipolygon")) || (!std::strcmp(type, "boundary"));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -155,11 +151,11 @@ namespace osmium {
|
||||
}
|
||||
try {
|
||||
if (!way.nodes().front().location() || !way.nodes().back().location()) {
|
||||
throw osmium::invalid_location("invalid location");
|
||||
throw osmium::invalid_location{"invalid location"};
|
||||
}
|
||||
if (way.ends_have_same_location()) {
|
||||
// way is closed and has enough nodes, build simple multipolygon
|
||||
TAssembler assembler(m_assembler_config);
|
||||
TAssembler assembler{m_assembler_config};
|
||||
assembler(way, m_output_buffer);
|
||||
m_stats += assembler.stats();
|
||||
possibly_flush_output_buffer();
|
||||
@ -174,6 +170,7 @@ namespace osmium {
|
||||
const osmium::memory::Buffer& buffer = this->members_buffer();
|
||||
|
||||
std::vector<const osmium::Way*> ways;
|
||||
ways.reserve(relation.members().size());
|
||||
for (const auto& member : relation.members()) {
|
||||
if (member.ref() != 0) {
|
||||
const size_t offset = this->get_offset(member.type(), member.ref());
|
||||
@ -182,7 +179,7 @@ namespace osmium {
|
||||
}
|
||||
|
||||
try {
|
||||
TAssembler assembler(m_assembler_config);
|
||||
TAssembler assembler{m_assembler_config};
|
||||
assembler(relation, ways, m_output_buffer);
|
||||
m_stats += assembler.stats();
|
||||
possibly_flush_output_buffer();
|
||||
|
189
third_party/libosmium/include/osmium/area/multipolygon_manager.hpp
vendored
Normal file
189
third_party/libosmium/include/osmium/area/multipolygon_manager.hpp
vendored
Normal file
@ -0,0 +1,189 @@
|
||||
#ifndef OSMIUM_AREA_MULTIPOLYGON_MANAGER_HPP
|
||||
#define OSMIUM_AREA_MULTIPOLYGON_MANAGER_HPP
|
||||
|
||||
/*
|
||||
|
||||
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||
|
||||
Copyright 2013-2017 Jochen Topf <jochen@topf.org> and others (see README).
|
||||
|
||||
Boost Software License - Version 1.0 - August 17th, 2003
|
||||
|
||||
Permission is hereby granted, free of charge, to any person or organization
|
||||
obtaining a copy of the software and accompanying documentation covered by
|
||||
this license (the "Software") to use, reproduce, display, distribute,
|
||||
execute, and transmit the Software, and to prepare derivative works of the
|
||||
Software, and to permit third-parties to whom the Software is furnished to
|
||||
do so, all subject to the following:
|
||||
|
||||
The copyright notices in the Software and this entire statement, including
|
||||
the above license grant, this restriction and the following disclaimer,
|
||||
must be included in all copies of the Software, in whole or in part, and
|
||||
all derivative works of the Software, unless such copies or derivative
|
||||
works are solely in the form of machine-executable object code generated by
|
||||
a source language processor.
|
||||
|
||||
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, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
#include <vector>
|
||||
|
||||
#include <osmium/area/stats.hpp>
|
||||
#include <osmium/osm/item_type.hpp>
|
||||
#include <osmium/osm/relation.hpp>
|
||||
#include <osmium/osm/tag.hpp>
|
||||
#include <osmium/osm/way.hpp>
|
||||
#include <osmium/relations/manager_util.hpp>
|
||||
#include <osmium/relations/members_database.hpp>
|
||||
#include <osmium/relations/relations_database.hpp>
|
||||
#include <osmium/relations/relations_manager.hpp>
|
||||
#include <osmium/storage/item_stash.hpp>
|
||||
#include <osmium/tags/taglist.hpp>
|
||||
#include <osmium/tags/tags_filter.hpp>
|
||||
|
||||
namespace osmium {
|
||||
|
||||
/**
|
||||
* @brief Code related to the building of areas (multipolygons) from relations.
|
||||
*/
|
||||
namespace area {
|
||||
|
||||
/**
|
||||
* This class collects all data needed for creating areas from
|
||||
* relations tagged with type=multipolygon or type=boundary.
|
||||
* Most of its functionality is derived from the parent class
|
||||
* osmium::relations::Collector.
|
||||
*
|
||||
* The actual assembling of the areas is done by the assembler
|
||||
* class given as template argument.
|
||||
*
|
||||
* @tparam TAssembler Multipolygon Assembler class.
|
||||
* @pre The Ids of all objects must be unique in the input data.
|
||||
*/
|
||||
template <typename TAssembler>
|
||||
class MultipolygonManager : public osmium::relations::RelationsManager<MultipolygonManager<TAssembler>, false, true, false> {
|
||||
|
||||
using assembler_config_type = typename TAssembler::config_type;
|
||||
const assembler_config_type m_assembler_config;
|
||||
|
||||
area_stats m_stats;
|
||||
|
||||
osmium::TagsFilter m_filter;
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Construct a MultipolygonManager.
|
||||
*
|
||||
* @param assembler_config The configuration that will be given to
|
||||
* any newly constructed area assembler.
|
||||
* @param filter An optional filter specifying what tags are
|
||||
* needed on closed ways or multipolygon relations
|
||||
* to build the area.
|
||||
*/
|
||||
explicit MultipolygonManager(const assembler_config_type& assembler_config, const osmium::TagsFilter& filter = osmium::TagsFilter{true}) :
|
||||
m_assembler_config(assembler_config),
|
||||
m_filter(filter) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Access the aggregated statistics generated by the assemblers
|
||||
* called from the manager.
|
||||
*/
|
||||
const area_stats& stats() const noexcept {
|
||||
return m_stats;
|
||||
}
|
||||
|
||||
/**
|
||||
* We are interested in all relations tagged with type=multipolygon
|
||||
* or type=boundary with at least one way member.
|
||||
*/
|
||||
bool new_relation(const osmium::Relation& relation) const {
|
||||
const char* type = relation.tags().get_value_by_key("type");
|
||||
|
||||
// ignore relations without "type" tag
|
||||
if (type == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (((!std::strcmp(type, "multipolygon")) || (!std::strcmp(type, "boundary"))) && osmium::tags::match_any_of(relation.tags(), m_filter)) {
|
||||
return std::any_of(relation.members().cbegin(), relation.members().cend(), [](const RelationMember& member) {
|
||||
return member.type() == osmium::item_type::way;
|
||||
});
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* This is called when a relation is complete, ie. all members
|
||||
* were found in the input. It will build the area using the
|
||||
* assembler.
|
||||
*/
|
||||
void complete_relation(const osmium::Relation& relation) {
|
||||
std::vector<const osmium::Way*> ways;
|
||||
ways.reserve(relation.members().size());
|
||||
for (const auto& member : relation.members()) {
|
||||
if (member.ref() != 0) {
|
||||
ways.push_back(this->get_member_way(member.ref()));
|
||||
assert(ways.back() != nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
TAssembler assembler{m_assembler_config};
|
||||
assembler(relation, ways, this->buffer());
|
||||
m_stats += assembler.stats();
|
||||
} catch (const osmium::invalid_location&) {
|
||||
// XXX ignore
|
||||
}
|
||||
}
|
||||
|
||||
void after_way(const osmium::Way& way) {
|
||||
// you need at least 4 nodes to make up a polygon
|
||||
if (way.nodes().size() <= 3) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
if (!way.nodes().front().location() || !way.nodes().back().location()) {
|
||||
throw osmium::invalid_location{"invalid location"};
|
||||
}
|
||||
if (way.ends_have_same_location()) {
|
||||
if (way.tags().has_tag("area", "no")) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (osmium::tags::match_none_of(way.tags(), m_filter)) {
|
||||
return;
|
||||
}
|
||||
|
||||
TAssembler assembler{m_assembler_config};
|
||||
assembler(way, this->buffer());
|
||||
m_stats += assembler.stats();
|
||||
this->possibly_flush();
|
||||
}
|
||||
} catch (const osmium::invalid_location&) {
|
||||
// XXX ignore
|
||||
}
|
||||
}
|
||||
|
||||
}; // class MultipolygonManager
|
||||
|
||||
} // namespace area
|
||||
|
||||
} // namespace osmium
|
||||
|
||||
#endif // OSMIUM_AREA_MULTIPOLYGON_MANAGER_HPP
|
180
third_party/libosmium/include/osmium/area/multipolygon_manager_legacy.hpp
vendored
Normal file
180
third_party/libosmium/include/osmium/area/multipolygon_manager_legacy.hpp
vendored
Normal file
@ -0,0 +1,180 @@
|
||||
#ifndef OSMIUM_AREA_MULTIPOLYGON_MANAGER_LEGACY_HPP
|
||||
#define OSMIUM_AREA_MULTIPOLYGON_MANAGER_LEGACY_HPP
|
||||
|
||||
/*
|
||||
|
||||
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||
|
||||
Copyright 2013-2017 Jochen Topf <jochen@topf.org> and others (see README).
|
||||
|
||||
Boost Software License - Version 1.0 - August 17th, 2003
|
||||
|
||||
Permission is hereby granted, free of charge, to any person or organization
|
||||
obtaining a copy of the software and accompanying documentation covered by
|
||||
this license (the "Software") to use, reproduce, display, distribute,
|
||||
execute, and transmit the Software, and to prepare derivative works of the
|
||||
Software, and to permit third-parties to whom the Software is furnished to
|
||||
do so, all subject to the following:
|
||||
|
||||
The copyright notices in the Software and this entire statement, including
|
||||
the above license grant, this restriction and the following disclaimer,
|
||||
must be included in all copies of the Software, in whole or in part, and
|
||||
all derivative works of the Software, unless such copies or derivative
|
||||
works are solely in the form of machine-executable object code generated by
|
||||
a source language processor.
|
||||
|
||||
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, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
#include <vector>
|
||||
|
||||
#include <osmium/area/stats.hpp>
|
||||
#include <osmium/handler.hpp>
|
||||
#include <osmium/handler/check_order.hpp>
|
||||
#include <osmium/memory/buffer.hpp>
|
||||
#include <osmium/memory/callback_buffer.hpp>
|
||||
#include <osmium/osm/item_type.hpp>
|
||||
#include <osmium/osm/relation.hpp>
|
||||
#include <osmium/osm/tag.hpp>
|
||||
#include <osmium/osm/way.hpp>
|
||||
#include <osmium/relations/manager_util.hpp>
|
||||
#include <osmium/relations/members_database.hpp>
|
||||
#include <osmium/relations/relations_database.hpp>
|
||||
#include <osmium/relations/relations_manager.hpp>
|
||||
#include <osmium/storage/item_stash.hpp>
|
||||
|
||||
namespace osmium {
|
||||
|
||||
/**
|
||||
* @brief Code related to the building of areas (multipolygons) from relations.
|
||||
*/
|
||||
namespace area {
|
||||
|
||||
/**
|
||||
* This class collects all data needed for creating areas from
|
||||
* relations tagged with type=multipolygon or type=boundary.
|
||||
* Most of its functionality is derived from the parent class
|
||||
* osmium::relations::Collector.
|
||||
*
|
||||
* The actual assembling of the areas is done by the assembler
|
||||
* class given as template argument.
|
||||
*
|
||||
* @tparam TAssembler Multipolygon Assembler class.
|
||||
* @pre The Ids of all objects must be unique in the input data.
|
||||
*/
|
||||
template <typename TAssembler>
|
||||
class MultipolygonManagerLegacy : public osmium::relations::RelationsManager<MultipolygonManagerLegacy<TAssembler>, false, true, false> {
|
||||
|
||||
using assembler_config_type = typename TAssembler::config_type;
|
||||
const assembler_config_type m_assembler_config;
|
||||
|
||||
area_stats m_stats;
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Construct a MultipolygonManagerLegacy.
|
||||
*
|
||||
* @param assembler_config The configuration that will be given to
|
||||
* any newly constructed area assembler.
|
||||
*/
|
||||
explicit MultipolygonManagerLegacy(const assembler_config_type& assembler_config) :
|
||||
m_assembler_config(assembler_config) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Access the aggregated statistics generated by the assemblers
|
||||
* called from the manager.
|
||||
*/
|
||||
const area_stats& stats() const noexcept {
|
||||
return m_stats;
|
||||
}
|
||||
|
||||
/**
|
||||
* We are interested in all relations tagged with type=multipolygon
|
||||
* or type=boundary with at least one way member.
|
||||
*/
|
||||
bool new_relation(const osmium::Relation& relation) const {
|
||||
const char* type = relation.tags().get_value_by_key("type");
|
||||
|
||||
// ignore relations without "type" tag
|
||||
if (!type) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((!std::strcmp(type, "multipolygon")) || (!std::strcmp(type, "boundary"))) {
|
||||
return std::any_of(relation.members().cbegin(), relation.members().cend(), [](const RelationMember& member) {
|
||||
return member.type() == osmium::item_type::way;
|
||||
});
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* This is called when a relation is complete, ie. all members
|
||||
* were found in the input. It will build the area using the
|
||||
* assembler.
|
||||
*/
|
||||
void complete_relation(const osmium::Relation& relation) {
|
||||
std::vector<const osmium::Way*> ways;
|
||||
ways.reserve(relation.members().size());
|
||||
for (const auto& member : relation.members()) {
|
||||
if (member.ref() != 0) {
|
||||
ways.push_back(this->get_member_way(member.ref()));
|
||||
assert(ways.back() != nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
TAssembler assembler{m_assembler_config};
|
||||
assembler(relation, ways, this->buffer());
|
||||
m_stats += assembler.stats();
|
||||
} catch (const osmium::invalid_location&) {
|
||||
// XXX ignore
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This is called when a way is not in any multipolygon
|
||||
* relation.
|
||||
*/
|
||||
void way_not_in_any_relation(const osmium::Way& way) {
|
||||
// you need at least 4 nodes to make up a polygon
|
||||
if (way.nodes().size() <= 3) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
if (!way.nodes().front().location() || !way.nodes().back().location()) {
|
||||
throw osmium::invalid_location{"invalid location"};
|
||||
}
|
||||
if (way.ends_have_same_location()) {
|
||||
// way is closed and has enough nodes, build simple multipolygon
|
||||
TAssembler assembler{m_assembler_config};
|
||||
assembler(way, this->buffer());
|
||||
m_stats += assembler.stats();
|
||||
}
|
||||
} catch (const osmium::invalid_location&) {
|
||||
// XXX ignore
|
||||
}
|
||||
}
|
||||
|
||||
}; // class MultipolygonManagerLegacy
|
||||
|
||||
} // namespace area
|
||||
|
||||
} // namespace osmium
|
||||
|
||||
#endif // OSMIUM_AREA_MULTIPOLYGON_MANAGER_LEGACY_HPP
|
@ -143,6 +143,18 @@ namespace osmium {
|
||||
virtual void report_duplicate_segment(const osmium::NodeRef& nr1, const osmium::NodeRef& nr2) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Report a duplicate segments. Two or more segments are directly
|
||||
* on top of each other. This can be a problem, if there is a
|
||||
* spike for instance, or it could be okay, if there are touching
|
||||
* inner rings.
|
||||
*
|
||||
* @param nr1 NodeRef of one end of the segment.
|
||||
* @param nr2 NodeRef of the other end of the segment.
|
||||
*/
|
||||
virtual void report_overlapping_segment(const osmium::NodeRef& nr1, const osmium::NodeRef& nr2) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Report an open ring.
|
||||
*
|
||||
@ -189,6 +201,23 @@ namespace osmium {
|
||||
virtual void report_inner_with_same_tags(const osmium::Way& way) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Report an invalid location in a way.
|
||||
*
|
||||
* @param way_id ID of the way the node is in.
|
||||
* @param node_id ID of the node with the invalid location.
|
||||
*/
|
||||
virtual void report_invalid_location(osmium::object_id_type way_id, osmium::object_id_type node_id) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Report a way that is more than once in a relation.
|
||||
*
|
||||
* @param way The way
|
||||
*/
|
||||
virtual void report_duplicate_way(const osmium::Way& way) {
|
||||
}
|
||||
|
||||
/**
|
||||
* In addition to reporting specific problems, this is used to
|
||||
* report all ways belonging to areas having problems.
|
||||
|
@ -60,58 +60,76 @@ namespace osmium {
|
||||
~ProblemReporterException() override = default;
|
||||
|
||||
void report_duplicate_node(osmium::object_id_type node_id1, osmium::object_id_type node_id2, osmium::Location location) override {
|
||||
m_sstream.str();
|
||||
m_sstream.str("");
|
||||
ProblemReporterStream::report_duplicate_node(node_id1, node_id2, location);
|
||||
throw std::runtime_error(m_sstream.str());
|
||||
throw std::runtime_error{m_sstream.str()};
|
||||
}
|
||||
|
||||
void report_touching_ring(osmium::object_id_type node_id, osmium::Location location) override {
|
||||
m_sstream.str();
|
||||
m_sstream.str("");
|
||||
ProblemReporterStream::report_touching_ring(node_id, location);
|
||||
throw std::runtime_error(m_sstream.str());
|
||||
throw std::runtime_error{m_sstream.str()};
|
||||
}
|
||||
|
||||
void report_intersection(osmium::object_id_type way1_id, osmium::Location way1_seg_start, osmium::Location way1_seg_end,
|
||||
osmium::object_id_type way2_id, osmium::Location way2_seg_start, osmium::Location way2_seg_end, osmium::Location intersection) override {
|
||||
m_sstream.str();
|
||||
m_sstream.str("");
|
||||
ProblemReporterStream::report_intersection(way1_id, way1_seg_start, way1_seg_end, way2_id, way2_seg_start, way2_seg_end, intersection);
|
||||
throw std::runtime_error(m_sstream.str());
|
||||
throw std::runtime_error{m_sstream.str()};
|
||||
}
|
||||
|
||||
void report_duplicate_segment(const osmium::NodeRef& nr1, const osmium::NodeRef& nr2) override {
|
||||
m_sstream.str();
|
||||
m_sstream.str("");
|
||||
ProblemReporterStream::report_duplicate_segment(nr1, nr2);
|
||||
throw std::runtime_error(m_sstream.str());
|
||||
throw std::runtime_error{m_sstream.str()};
|
||||
}
|
||||
|
||||
void report_overlapping_segment(const osmium::NodeRef& nr1, const osmium::NodeRef& nr2) override {
|
||||
m_sstream.str("");
|
||||
ProblemReporterStream::report_overlapping_segment(nr1, nr2);
|
||||
throw std::runtime_error{m_sstream.str()};
|
||||
}
|
||||
|
||||
void report_ring_not_closed(const osmium::NodeRef& nr, const osmium::Way* way = nullptr) override {
|
||||
m_sstream.str();
|
||||
m_sstream.str("");
|
||||
ProblemReporterStream::report_ring_not_closed(nr, way);
|
||||
throw std::runtime_error(m_sstream.str());
|
||||
throw std::runtime_error{m_sstream.str()};
|
||||
}
|
||||
|
||||
void report_role_should_be_outer(osmium::object_id_type way_id, osmium::Location seg_start, osmium::Location seg_end) override {
|
||||
m_sstream.str();
|
||||
m_sstream.str("");
|
||||
ProblemReporterStream::report_role_should_be_outer(way_id, seg_start, seg_end);
|
||||
throw std::runtime_error(m_sstream.str());
|
||||
throw std::runtime_error{m_sstream.str()};
|
||||
}
|
||||
|
||||
void report_role_should_be_inner(osmium::object_id_type way_id, osmium::Location seg_start, osmium::Location seg_end) override {
|
||||
m_sstream.str();
|
||||
m_sstream.str("");
|
||||
ProblemReporterStream::report_role_should_be_inner(way_id, seg_start, seg_end);
|
||||
throw std::runtime_error(m_sstream.str());
|
||||
throw std::runtime_error{m_sstream.str()};
|
||||
}
|
||||
|
||||
void report_way_in_multiple_rings(const osmium::Way& way) override {
|
||||
m_sstream.str();
|
||||
m_sstream.str("");
|
||||
ProblemReporterStream::report_way_in_multiple_rings(way);
|
||||
throw std::runtime_error(m_sstream.str());
|
||||
throw std::runtime_error{m_sstream.str()};
|
||||
}
|
||||
|
||||
void report_inner_with_same_tags(const osmium::Way& way) override {
|
||||
m_sstream.str();
|
||||
m_sstream.str("");
|
||||
ProblemReporterStream::report_inner_with_same_tags(way);
|
||||
throw std::runtime_error(m_sstream.str());
|
||||
throw std::runtime_error{m_sstream.str()};
|
||||
}
|
||||
|
||||
void report_invalid_location(osmium::object_id_type way_id, osmium::object_id_type node_id) override {
|
||||
m_sstream.str("");
|
||||
ProblemReporterStream::report_invalid_location(way_id, node_id);
|
||||
throw std::runtime_error{m_sstream.str()};
|
||||
}
|
||||
|
||||
void report_duplicate_way(const osmium::Way& way) override {
|
||||
m_sstream.str("");
|
||||
ProblemReporterStream::report_duplicate_way(way);
|
||||
throw std::runtime_error{m_sstream.str()};
|
||||
}
|
||||
|
||||
}; // class ProblemReporterException
|
||||
|
@ -73,14 +73,14 @@ namespace osmium {
|
||||
gdalcpp::Layer m_layer_ways;
|
||||
|
||||
void set_object(gdalcpp::Feature& feature) {
|
||||
const char t[2] = { osmium::item_type_to_char(m_object_type), '\0' };
|
||||
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));
|
||||
}
|
||||
|
||||
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));
|
||||
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));
|
||||
@ -93,7 +93,7 @@ namespace osmium {
|
||||
ogr_linestring->addPoint(loc1.lon(), loc1.lat());
|
||||
ogr_linestring->addPoint(loc2.lon(), loc2.lat());
|
||||
|
||||
gdalcpp::Feature feature(m_layer_lerror, std::move(ogr_linestring));
|
||||
gdalcpp::Feature feature{m_layer_lerror, std::move(ogr_linestring)};
|
||||
set_object(feature);
|
||||
feature.set_field("id1", static_cast<double>(id1));
|
||||
feature.set_field("id2", static_cast<double>(id2));
|
||||
@ -158,6 +158,10 @@ namespace osmium {
|
||||
write_line("duplicate_segment", nr1.ref(), nr2.ref(), nr1.location(), nr2.location());
|
||||
}
|
||||
|
||||
void report_overlapping_segment(const osmium::NodeRef& nr1, const osmium::NodeRef& nr2) override {
|
||||
write_line("overlapping_segment", nr1.ref(), nr2.ref(), nr1.location(), nr2.location());
|
||||
}
|
||||
|
||||
void report_ring_not_closed(const osmium::NodeRef& nr, const osmium::Way* way = nullptr) override {
|
||||
write_point("ring_not_closed", nr.ref(), way ? way->id() : 0, nr.location());
|
||||
}
|
||||
@ -175,7 +179,7 @@ namespace osmium {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
gdalcpp::Feature feature(m_layer_lerror, m_ogr_factory.create_linestring(way));
|
||||
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("id2", 0);
|
||||
@ -191,7 +195,7 @@ namespace osmium {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
gdalcpp::Feature feature(m_layer_lerror, m_ogr_factory.create_linestring(way));
|
||||
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("id2", 0);
|
||||
@ -202,6 +206,22 @@ namespace osmium {
|
||||
}
|
||||
}
|
||||
|
||||
void report_duplicate_way(const osmium::Way& way) override {
|
||||
if (way.nodes().size() < 2) {
|
||||
return;
|
||||
}
|
||||
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("id2", 0);
|
||||
feature.set_field("problem", "duplicate_way");
|
||||
feature.add_to_layer();
|
||||
} catch (const osmium::geometry_error&) {
|
||||
// XXX
|
||||
}
|
||||
}
|
||||
|
||||
void report_way(const osmium::Way& way) override {
|
||||
if (way.nodes().empty()) {
|
||||
return;
|
||||
@ -212,7 +232,7 @@ namespace osmium {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
gdalcpp::Feature feature(m_layer_ways, m_ogr_factory.create_linestring(way));
|
||||
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.add_to_layer();
|
||||
|
@ -85,6 +85,12 @@ namespace osmium {
|
||||
<< " node_id2=" << nr2.ref() << " location2=" << nr2.location() << "\n";
|
||||
}
|
||||
|
||||
void report_overlapping_segment(const osmium::NodeRef& nr1, const osmium::NodeRef& nr2) override {
|
||||
header("overlapping segment");
|
||||
*m_out << "node_id1=" << nr1.ref() << " location1=" << nr1.location()
|
||||
<< " node_id2=" << nr2.ref() << " location2=" << nr2.location() << "\n";
|
||||
}
|
||||
|
||||
void report_ring_not_closed(const osmium::NodeRef& nr, const osmium::Way* way = nullptr) override {
|
||||
header("ring not closed");
|
||||
*m_out << "node_id=" << nr.ref() << " location=" << nr.location();
|
||||
@ -114,6 +120,16 @@ namespace osmium {
|
||||
*m_out << "way_id=" << way.id() << '\n';
|
||||
}
|
||||
|
||||
void report_invalid_location(osmium::object_id_type way_id, osmium::object_id_type node_id) override {
|
||||
header("invalid location");
|
||||
*m_out << "way_id=" << way_id << " node_id=" << node_id << '\n';
|
||||
}
|
||||
|
||||
void report_duplicate_way(const osmium::Way& way) override {
|
||||
header("duplicate way");
|
||||
*m_out << "way_id=" << way.id() << '\n';
|
||||
}
|
||||
|
||||
}; // class ProblemReporterStream
|
||||
|
||||
} // namespace area
|
||||
|
@ -52,6 +52,7 @@ namespace osmium {
|
||||
uint64_t area_touching_rings_case = 0; ///< More difficult case with touching rings
|
||||
uint64_t duplicate_nodes = 0; ///< Consecutive identical nodes or consecutive nodes with same location
|
||||
uint64_t duplicate_segments = 0; ///< Segments duplicated (going back and forth)
|
||||
uint64_t duplicate_ways = 0; ///< Ways that are in relation more than once
|
||||
uint64_t from_relations = 0; ///< Area created from multipolygon relation
|
||||
uint64_t from_ways = 0; ///< Area created from way
|
||||
uint64_t inner_rings = 0; ///< Number of inner rings
|
||||
@ -63,11 +64,13 @@ namespace osmium {
|
||||
uint64_t nodes = 0; ///< Number of nodes in the area
|
||||
uint64_t open_rings = 0; ///< Number of open rings in the area
|
||||
uint64_t outer_rings = 0; ///< Number of outer rings in the area
|
||||
uint64_t overlapping_segments = 0; ///< Three or more segments with same end points
|
||||
uint64_t short_ways = 0; ///< Number of ways with less than two nodes
|
||||
uint64_t single_way_in_mp_relation = 0; ///< Multipolygon relation containing a single way
|
||||
uint64_t touching_rings = 0; ///< Rings touching in a node
|
||||
uint64_t ways_in_multiple_rings = 0; ///< Different segments of a way ended up in different rings
|
||||
uint64_t wrong_role = 0; ///< Member has wrong role (not "outer", "inner", or empty)
|
||||
uint64_t invalid_locations = 0; ///< Invalid location found
|
||||
|
||||
area_stats& operator+=(const area_stats& other) noexcept {
|
||||
area_really_complex_case += other.area_really_complex_case;
|
||||
@ -75,6 +78,7 @@ namespace osmium {
|
||||
area_touching_rings_case += other.area_touching_rings_case;
|
||||
duplicate_nodes += other.duplicate_nodes;
|
||||
duplicate_segments += other.duplicate_segments;
|
||||
duplicate_ways += other.duplicate_ways;
|
||||
from_relations += other.from_relations;
|
||||
from_ways += other.from_ways;
|
||||
inner_rings += other.inner_rings;
|
||||
@ -91,6 +95,7 @@ namespace osmium {
|
||||
touching_rings += other.touching_rings;
|
||||
ways_in_multiple_rings += other.ways_in_multiple_rings;
|
||||
wrong_role += other.wrong_role;
|
||||
invalid_locations += invalid_locations;
|
||||
return *this;
|
||||
}
|
||||
|
||||
@ -103,6 +108,7 @@ namespace osmium {
|
||||
<< " area_touching_rings_case=" << s.area_touching_rings_case
|
||||
<< " duplicate_nodes=" << s.duplicate_nodes
|
||||
<< " duplicate_segments=" << s.duplicate_segments
|
||||
<< " duplicate_ways=" << s.duplicate_ways
|
||||
<< " from_relations=" << s.from_relations
|
||||
<< " from_ways=" << s.from_ways
|
||||
<< " inner_rings=" << s.inner_rings
|
||||
@ -118,7 +124,8 @@ namespace osmium {
|
||||
<< " single_way_in_mp_relation=" << s.single_way_in_mp_relation
|
||||
<< " touching_rings=" << s.touching_rings
|
||||
<< " ways_in_multiple_rings=" << s.ways_in_multiple_rings
|
||||
<< " wrong_role=" << s.wrong_role;
|
||||
<< " wrong_role=" << s.wrong_role
|
||||
<< " invalid_locations=" << s.invalid_locations;
|
||||
}
|
||||
|
||||
} // namespace area
|
||||
|
@ -35,16 +35,12 @@ DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
#include <new>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
|
||||
#include <osmium/memory/buffer.hpp>
|
||||
#include <osmium/memory/item.hpp>
|
||||
#include <osmium/osm/types.hpp>
|
||||
#include <osmium/util/cast.hpp>
|
||||
#include <osmium/util/compatibility.hpp>
|
||||
|
||||
namespace osmium {
|
||||
@ -62,7 +58,7 @@ namespace osmium {
|
||||
|
||||
osmium::memory::Buffer& m_buffer;
|
||||
Builder* m_parent;
|
||||
size_t m_item_offset;
|
||||
std::size_t m_item_offset;
|
||||
|
||||
Builder(const Builder&) = delete;
|
||||
Builder(Builder&&) = delete;
|
||||
@ -101,7 +97,7 @@ namespace osmium {
|
||||
return *reinterpret_cast<osmium::memory::Item*>(m_buffer.data() + m_item_offset);
|
||||
}
|
||||
|
||||
unsigned char* reserve_space(size_t size) {
|
||||
unsigned char* reserve_space(std::size_t size) {
|
||||
return m_buffer.reserve_space(size);
|
||||
}
|
||||
|
||||
@ -119,7 +115,9 @@ namespace osmium {
|
||||
*
|
||||
*/
|
||||
void add_padding(bool self = false) {
|
||||
const auto padding = osmium::memory::align_bytes - (size() % osmium::memory::align_bytes);
|
||||
// We know the padding is only a very small number, so it will
|
||||
// always fit.
|
||||
const auto padding = static_cast<osmium::memory::item_size_type>(osmium::memory::align_bytes - (size() % osmium::memory::align_bytes));
|
||||
if (padding != osmium::memory::align_bytes) {
|
||||
std::fill_n(reserve_space(padding), padding, 0);
|
||||
if (self) {
|
||||
@ -131,7 +129,7 @@ namespace osmium {
|
||||
}
|
||||
}
|
||||
|
||||
void add_size(uint32_t size) {
|
||||
void add_size(osmium::memory::item_size_type size) {
|
||||
item().add_size(size);
|
||||
if (m_parent) {
|
||||
m_parent->add_size(size);
|
||||
|
@ -71,7 +71,7 @@ namespace osmium {
|
||||
* @deprecated
|
||||
* Use osmium::builder::add_tag_list() instead.
|
||||
*/
|
||||
inline const osmium::TagList& build_tag_list(osmium::memory::Buffer& buffer, const std::initializer_list<std::pair<const char*, const char*>>& tags) {
|
||||
OSMIUM_DEPRECATED inline const osmium::TagList& build_tag_list(osmium::memory::Buffer& buffer, const std::initializer_list<std::pair<const char*, const char*>>& tags) {
|
||||
const size_t pos = buffer.committed();
|
||||
{
|
||||
osmium::builder::TagListBuilder tl_builder(buffer);
|
||||
@ -87,7 +87,7 @@ namespace osmium {
|
||||
* @deprecated
|
||||
* Use osmium::builder::add_tag_list() instead.
|
||||
*/
|
||||
inline const osmium::TagList& build_tag_list_from_map(osmium::memory::Buffer& buffer, const std::map<const char*, const char*>& tags) {
|
||||
OSMIUM_DEPRECATED inline const osmium::TagList& build_tag_list_from_map(osmium::memory::Buffer& buffer, const std::map<const char*, const char*>& tags) {
|
||||
const size_t pos = buffer.committed();
|
||||
{
|
||||
osmium::builder::TagListBuilder tl_builder(buffer);
|
||||
@ -103,7 +103,7 @@ namespace osmium {
|
||||
* @deprecated
|
||||
* Use osmium::builder::add_tag_list() instead.
|
||||
*/
|
||||
inline const osmium::TagList& build_tag_list_from_func(osmium::memory::Buffer& buffer, std::function<void(osmium::builder::TagListBuilder&)> func) {
|
||||
OSMIUM_DEPRECATED inline const osmium::TagList& build_tag_list_from_func(osmium::memory::Buffer& buffer, std::function<void(osmium::builder::TagListBuilder&)> func) {
|
||||
const size_t pos = buffer.committed();
|
||||
{
|
||||
osmium::builder::TagListBuilder tl_builder(buffer);
|
||||
|
@ -33,7 +33,10 @@ DEALINGS IN THE SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <cstdint>
|
||||
#include <cstddef>
|
||||
#include <cstring>
|
||||
#include <initializer_list>
|
||||
#include <limits>
|
||||
@ -43,25 +46,25 @@ DEALINGS IN THE SOFTWARE.
|
||||
#include <utility>
|
||||
|
||||
#include <osmium/builder/builder.hpp>
|
||||
#include <osmium/memory/item.hpp>
|
||||
#include <osmium/osm/area.hpp>
|
||||
#include <osmium/osm/box.hpp>
|
||||
#include <osmium/osm/changeset.hpp>
|
||||
#include <osmium/osm/item_type.hpp>
|
||||
#include <osmium/osm/location.hpp>
|
||||
#include <osmium/osm/node.hpp>
|
||||
#include <osmium/osm/node_ref.hpp>
|
||||
#include <osmium/osm/object.hpp>
|
||||
#include <osmium/osm/tag.hpp>
|
||||
#include <osmium/osm/types.hpp>
|
||||
#include <osmium/memory/item.hpp>
|
||||
#include <osmium/osm/area.hpp>
|
||||
#include <osmium/osm/changeset.hpp>
|
||||
#include <osmium/osm/relation.hpp>
|
||||
#include <osmium/osm/tag.hpp>
|
||||
#include <osmium/osm/timestamp.hpp>
|
||||
#include <osmium/osm/types.hpp>
|
||||
#include <osmium/osm/way.hpp>
|
||||
#include <osmium/util/cast.hpp>
|
||||
#include <osmium/util/compatibility.hpp>
|
||||
|
||||
namespace osmium {
|
||||
|
||||
class Node;
|
||||
|
||||
namespace memory {
|
||||
class Buffer;
|
||||
} // namespace memory
|
||||
@ -74,12 +77,12 @@ namespace osmium {
|
||||
|
||||
explicit TagListBuilder(osmium::memory::Buffer& buffer, Builder* parent = nullptr) :
|
||||
Builder(buffer, parent, sizeof(TagList)) {
|
||||
new (&item()) TagList();
|
||||
new (&item()) TagList{};
|
||||
}
|
||||
|
||||
explicit TagListBuilder(Builder& parent) :
|
||||
Builder(parent.buffer(), &parent, sizeof(TagList)) {
|
||||
new (&item()) TagList();
|
||||
new (&item()) TagList{};
|
||||
}
|
||||
|
||||
~TagListBuilder() {
|
||||
@ -94,10 +97,10 @@ namespace osmium {
|
||||
*/
|
||||
void add_tag(const char* key, const char* value) {
|
||||
if (std::strlen(key) > osmium::max_osm_string_length) {
|
||||
throw std::length_error("OSM tag key is too long");
|
||||
throw std::length_error{"OSM tag key is too long"};
|
||||
}
|
||||
if (std::strlen(value) > osmium::max_osm_string_length) {
|
||||
throw std::length_error("OSM tag value is too long");
|
||||
throw std::length_error{"OSM tag value is too long"};
|
||||
}
|
||||
add_size(append(key));
|
||||
add_size(append(value));
|
||||
@ -111,12 +114,12 @@ namespace osmium {
|
||||
* @param value Pointer to tag value.
|
||||
* @param value_length Length of value (not including the \0 byte).
|
||||
*/
|
||||
void add_tag(const char* key, const size_t key_length, const char* value, const size_t value_length) {
|
||||
void add_tag(const char* key, const std::size_t key_length, const char* value, const std::size_t value_length) {
|
||||
if (key_length > osmium::max_osm_string_length) {
|
||||
throw std::length_error("OSM tag key is too long");
|
||||
throw std::length_error{"OSM tag key is too long"};
|
||||
}
|
||||
if (value_length > osmium::max_osm_string_length) {
|
||||
throw std::length_error("OSM tag value is too long");
|
||||
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)));
|
||||
@ -130,10 +133,10 @@ namespace osmium {
|
||||
*/
|
||||
void add_tag(const std::string& key, const std::string& value) {
|
||||
if (key.size() > osmium::max_osm_string_length) {
|
||||
throw std::length_error("OSM tag key is too long");
|
||||
throw std::length_error{"OSM tag key is too long"};
|
||||
}
|
||||
if (value.size() > osmium::max_osm_string_length) {
|
||||
throw std::length_error("OSM tag value is too long");
|
||||
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));
|
||||
@ -185,12 +188,12 @@ namespace osmium {
|
||||
|
||||
explicit NodeRefListBuilder(osmium::memory::Buffer& buffer, Builder* parent = nullptr) :
|
||||
Builder(buffer, parent, sizeof(T)) {
|
||||
new (&item()) T();
|
||||
new (&item()) T{};
|
||||
}
|
||||
|
||||
explicit NodeRefListBuilder(Builder& parent) :
|
||||
Builder(parent.buffer(), &parent, sizeof(T)) {
|
||||
new (&item()) T();
|
||||
new (&item()) T{};
|
||||
}
|
||||
|
||||
~NodeRefListBuilder() {
|
||||
@ -198,12 +201,12 @@ namespace osmium {
|
||||
}
|
||||
|
||||
void add_node_ref(const NodeRef& node_ref) {
|
||||
new (reserve_space_for<osmium::NodeRef>()) osmium::NodeRef(node_ref);
|
||||
new (reserve_space_for<osmium::NodeRef>()) osmium::NodeRef{node_ref};
|
||||
add_size(sizeof(osmium::NodeRef));
|
||||
}
|
||||
|
||||
void add_node_ref(const object_id_type ref, const osmium::Location& location = Location{}) {
|
||||
add_node_ref(NodeRef(ref, location));
|
||||
add_node_ref(NodeRef{ref, location});
|
||||
}
|
||||
|
||||
}; // class NodeRefListBuilder
|
||||
@ -223,9 +226,9 @@ namespace osmium {
|
||||
* @param length Length of role (without \0 termination).
|
||||
* @throws std:length_error If role is longer than osmium::max_osm_string_length
|
||||
*/
|
||||
void add_role(osmium::RelationMember& member, const char* role, const size_t length) {
|
||||
void add_role(osmium::RelationMember& member, const char* role, const std::size_t length) {
|
||||
if (length > osmium::max_osm_string_length) {
|
||||
throw std::length_error("OSM relation member role is too long");
|
||||
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)));
|
||||
@ -236,12 +239,12 @@ namespace osmium {
|
||||
|
||||
explicit RelationMemberListBuilder(osmium::memory::Buffer& buffer, Builder* parent = nullptr) :
|
||||
Builder(buffer, parent, sizeof(RelationMemberList)) {
|
||||
new (&item()) RelationMemberList();
|
||||
new (&item()) RelationMemberList{};
|
||||
}
|
||||
|
||||
explicit RelationMemberListBuilder(Builder& parent) :
|
||||
Builder(parent.buffer(), &parent, sizeof(RelationMemberList)) {
|
||||
new (&item()) RelationMemberList();
|
||||
new (&item()) RelationMemberList{};
|
||||
}
|
||||
|
||||
~RelationMemberListBuilder() {
|
||||
@ -261,9 +264,9 @@ namespace osmium {
|
||||
* @throws std:length_error If role_length is greater than
|
||||
* osmium::max_osm_string_length
|
||||
*/
|
||||
void add_member(osmium::item_type type, object_id_type ref, const char* role, const size_t role_length, const osmium::OSMObject* full_member = nullptr) {
|
||||
void add_member(osmium::item_type type, object_id_type ref, const char* role, const std::size_t role_length, const osmium::OSMObject* full_member = nullptr) {
|
||||
osmium::RelationMember* member = reserve_space_for<osmium::RelationMember>();
|
||||
new (member) osmium::RelationMember(ref, type, full_member != nullptr);
|
||||
new (member) osmium::RelationMember{ref, type, full_member != nullptr};
|
||||
add_size(sizeof(RelationMember));
|
||||
add_role(*member, role, role_length);
|
||||
if (full_member) {
|
||||
@ -307,23 +310,19 @@ namespace osmium {
|
||||
|
||||
osmium::ChangesetComment* m_comment = nullptr;
|
||||
|
||||
void add_user(osmium::ChangesetComment& comment, const char* user, const size_t length) {
|
||||
void add_user(osmium::ChangesetComment& comment, const char* user, const std::size_t length) {
|
||||
if (length > osmium::max_osm_string_length) {
|
||||
throw std::length_error("OSM user name is too long");
|
||||
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)));
|
||||
}
|
||||
|
||||
void add_text(osmium::ChangesetComment& comment, const char* text, const size_t length) {
|
||||
// XXX There is no limit on the length of a comment text. We
|
||||
// limit it here to 2^16-2 characters, because that's all that
|
||||
// will fit into our internal data structure. This is not ideal,
|
||||
// and will have to be discussed and cleared up.
|
||||
if (length > std::numeric_limits<osmium::string_size_type>::max() - 1) {
|
||||
throw std::length_error("OSM changeset comment is too long");
|
||||
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::string_size_type(length) + 1);
|
||||
comment.set_text_size(osmium::changeset_comment_size_type(length) + 1);
|
||||
add_size(append_with_zero(text, osmium::memory::item_size_type(length)));
|
||||
add_padding(true);
|
||||
}
|
||||
@ -332,12 +331,12 @@ namespace osmium {
|
||||
|
||||
explicit ChangesetDiscussionBuilder(osmium::memory::Buffer& buffer, Builder* parent = nullptr) :
|
||||
Builder(buffer, parent, sizeof(ChangesetDiscussion)) {
|
||||
new (&item()) ChangesetDiscussion();
|
||||
new (&item()) ChangesetDiscussion{};
|
||||
}
|
||||
|
||||
explicit ChangesetDiscussionBuilder(Builder& parent) :
|
||||
Builder(parent.buffer(), &parent, sizeof(ChangesetDiscussion)) {
|
||||
new (&item()) ChangesetDiscussion();
|
||||
new (&item()) ChangesetDiscussion{};
|
||||
}
|
||||
|
||||
~ChangesetDiscussionBuilder() {
|
||||
@ -348,21 +347,23 @@ namespace osmium {
|
||||
void add_comment(osmium::Timestamp date, osmium::user_id_type uid, const char* user) {
|
||||
assert(!m_comment && "You have to always call both add_comment() and then add_comment_text() in that order for each comment!");
|
||||
m_comment = reserve_space_for<osmium::ChangesetComment>();
|
||||
new (m_comment) osmium::ChangesetComment(date, uid);
|
||||
new (m_comment) osmium::ChangesetComment{date, uid};
|
||||
add_size(sizeof(ChangesetComment));
|
||||
add_user(*m_comment, user, std::strlen(user));
|
||||
}
|
||||
|
||||
void add_comment_text(const char* text) {
|
||||
assert(m_comment && "You have to always call both add_comment() and then add_comment_text() in that order for each comment!");
|
||||
add_text(*m_comment, text, std::strlen(text));
|
||||
osmium::ChangesetComment& comment = *m_comment;
|
||||
m_comment = nullptr;
|
||||
add_text(comment, text, std::strlen(text));
|
||||
}
|
||||
|
||||
void add_comment_text(const std::string& text) {
|
||||
assert(m_comment && "You have to always call both add_comment() and then add_comment_text() in that order for each comment!");
|
||||
add_text(*m_comment, text.c_str(), text.size());
|
||||
osmium::ChangesetComment& comment = *m_comment;
|
||||
m_comment = nullptr;
|
||||
add_text(comment, text.c_str(), text.size());
|
||||
}
|
||||
|
||||
}; // class ChangesetDiscussionBuilder
|
||||
@ -379,13 +380,13 @@ namespace osmium {
|
||||
|
||||
using type = TDerived;
|
||||
|
||||
constexpr static const size_t min_size_for_user = osmium::memory::padded_length(sizeof(string_size_type) + 1);
|
||||
constexpr static const std::size_t min_size_for_user = osmium::memory::padded_length(sizeof(string_size_type) + 1);
|
||||
|
||||
public:
|
||||
|
||||
explicit OSMObjectBuilder(osmium::memory::Buffer& buffer, Builder* parent = nullptr) :
|
||||
Builder(buffer, parent, sizeof(T) + min_size_for_user) {
|
||||
new (&item()) T();
|
||||
new (&item()) T{};
|
||||
add_size(min_size_for_user);
|
||||
std::fill_n(object().data() + sizeof(T), min_size_for_user, 0);
|
||||
object().set_user_size(1);
|
||||
@ -402,6 +403,17 @@ namespace osmium {
|
||||
return static_cast<T&>(item());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a const reference to the object buing built.
|
||||
*
|
||||
* Note that this reference will be invalidated by every action
|
||||
* on the builder that might make the buffer grow. This includes
|
||||
* calls to set_user() and any time a new sub-builder is created.
|
||||
*/
|
||||
const T& cobject() const noexcept {
|
||||
return static_cast<const T&>(item());
|
||||
}
|
||||
|
||||
/**
|
||||
* Set user name.
|
||||
*
|
||||
@ -410,7 +422,7 @@ namespace osmium {
|
||||
*/
|
||||
TDerived& set_user(const char* user, const string_size_type length) {
|
||||
const auto size_of_object = sizeof(T) + sizeof(string_size_type);
|
||||
assert(object().user_size() == 1 && (size() <= size_of_object + osmium::memory::padded_length(1))
|
||||
assert(cobject().user_size() == 1 && (size() <= size_of_object + osmium::memory::padded_length(1))
|
||||
&& "set_user() must be called at most once and before any sub-builders");
|
||||
const auto available_space = min_size_for_user - sizeof(string_size_type) - 1;
|
||||
if (length > available_space) {
|
||||
@ -558,13 +570,13 @@ namespace osmium {
|
||||
|
||||
using type = ChangesetBuilder;
|
||||
|
||||
constexpr static const size_t min_size_for_user = osmium::memory::padded_length(1);
|
||||
constexpr static const std::size_t min_size_for_user = osmium::memory::padded_length(1);
|
||||
|
||||
public:
|
||||
|
||||
explicit ChangesetBuilder(osmium::memory::Buffer& buffer, Builder* parent = nullptr) :
|
||||
Builder(buffer, parent, sizeof(Changeset) + min_size_for_user) {
|
||||
new (&item()) Changeset();
|
||||
new (&item()) Changeset{};
|
||||
add_size(min_size_for_user);
|
||||
std::fill_n(object().data() + sizeof(Changeset), min_size_for_user, 0);
|
||||
object().set_user_size(1);
|
||||
@ -581,6 +593,17 @@ namespace osmium {
|
||||
return static_cast<Changeset&>(item());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a const reference to the changeset buing built.
|
||||
*
|
||||
* Note that this reference will be invalidated by every action
|
||||
* on the builder that might make the buffer grow. This includes
|
||||
* calls to set_user() and any time a new sub-builder is created.
|
||||
*/
|
||||
const Changeset& cobject() const noexcept {
|
||||
return static_cast<const Changeset&>(item());
|
||||
}
|
||||
|
||||
OSMIUM_FORWARD(set_id)
|
||||
OSMIUM_FORWARD(set_uid)
|
||||
OSMIUM_FORWARD(set_uid_from_signed)
|
||||
@ -608,7 +631,7 @@ namespace osmium {
|
||||
* @param length Length of user name (without \0 termination).
|
||||
*/
|
||||
ChangesetBuilder& set_user(const char* user, const string_size_type length) {
|
||||
assert(object().user_size() == 1 && (size() <= sizeof(Changeset) + osmium::memory::padded_length(1))
|
||||
assert(cobject().user_size() == 1 && (size() <= sizeof(Changeset) + osmium::memory::padded_length(1))
|
||||
&& "set_user() must be called at most once and before any sub-builders");
|
||||
const auto available_space = min_size_for_user - 1;
|
||||
if (length > available_space) {
|
||||
|
@ -48,13 +48,13 @@ namespace osmium {
|
||||
|
||||
DiffHandler() = default;
|
||||
|
||||
void node(const osmium::DiffNode&) const {
|
||||
void node(const osmium::DiffNode&) const noexcept {
|
||||
}
|
||||
|
||||
void way(const osmium::DiffWay&) const {
|
||||
void way(const osmium::DiffWay&) const noexcept {
|
||||
}
|
||||
|
||||
void relation(const osmium::DiffRelation&) const {
|
||||
void relation(const osmium::DiffRelation&) const noexcept {
|
||||
}
|
||||
|
||||
}; // class DiffHandler
|
||||
|
@ -66,8 +66,8 @@ namespace osmium {
|
||||
void set_diff() const noexcept {
|
||||
assert(m_curr != m_end);
|
||||
|
||||
bool use_curr_for_prev = m_prev->type() != m_curr->type() || m_prev->id() != m_curr->id();
|
||||
bool use_curr_for_next = m_next == m_end || m_next->type() != m_curr->type() || m_next->id() != m_curr->id();
|
||||
const bool use_curr_for_prev = m_prev->type() != m_curr->type() || m_prev->id() != m_curr->id();
|
||||
const bool use_curr_for_next = m_next == m_end || m_next->type() != m_curr->type() || m_next->id() != m_curr->id();
|
||||
|
||||
m_diff = std::move(osmium::DiffObject{
|
||||
*(use_curr_for_prev ? m_curr : m_prev),
|
||||
@ -104,7 +104,7 @@ namespace osmium {
|
||||
}
|
||||
|
||||
DiffIterator operator++(int) {
|
||||
DiffIterator tmp(*this);
|
||||
DiffIterator tmp{*this};
|
||||
operator++();
|
||||
return tmp;
|
||||
}
|
||||
|
@ -56,7 +56,7 @@ namespace osmium {
|
||||
handler.relation(static_cast<const osmium::DiffRelation&>(diff));
|
||||
break;
|
||||
default:
|
||||
throw osmium::unknown_type();
|
||||
throw osmium::unknown_type{};
|
||||
}
|
||||
}
|
||||
|
||||
@ -72,8 +72,8 @@ namespace osmium {
|
||||
inline void apply_diff(TIterator it, TIterator end, THandlers&... handlers) {
|
||||
using diff_iterator = osmium::DiffIterator<TIterator>;
|
||||
|
||||
diff_iterator dit(it, end);
|
||||
diff_iterator dend(end, end);
|
||||
diff_iterator dit{it, end};
|
||||
diff_iterator dend{end, end};
|
||||
|
||||
for (; dit != dend; ++dit) {
|
||||
detail::apply_diff_iterator_recurse(*dit, handlers...);
|
||||
|
@ -54,8 +54,7 @@ namespace osmium {
|
||||
|
||||
public:
|
||||
|
||||
virtual ~HandlerWrapperBase() {
|
||||
}
|
||||
virtual ~HandlerWrapperBase() = default;
|
||||
|
||||
virtual void node(const osmium::Node&) {
|
||||
}
|
||||
@ -115,7 +114,7 @@ auto _name_##_dispatch(THandler& handler, const osmium::_type_& object, long) ->
|
||||
public:
|
||||
|
||||
template <typename... TArgs>
|
||||
HandlerWrapper(TArgs&&... args) :
|
||||
explicit HandlerWrapper(TArgs&&... args) :
|
||||
m_handler(std::forward<TArgs>(args)...) {
|
||||
}
|
||||
|
||||
@ -155,12 +154,12 @@ auto _name_##_dispatch(THandler& handler, const osmium::_type_& object, long) ->
|
||||
public:
|
||||
|
||||
DynamicHandler() :
|
||||
m_impl(impl_ptr(new osmium::handler::detail::HandlerWrapperBase)) {
|
||||
m_impl(new osmium::handler::detail::HandlerWrapperBase) {
|
||||
}
|
||||
|
||||
template <typename THandler, typename... TArgs>
|
||||
void set(TArgs&&... args) {
|
||||
m_impl = impl_ptr(new osmium::handler::detail::HandlerWrapper<THandler>(std::forward<TArgs>(args)...));
|
||||
m_impl.reset(new osmium::handler::detail::HandlerWrapper<THandler>{std::forward<TArgs>(args)...});
|
||||
}
|
||||
|
||||
void node(const osmium::Node& node) {
|
||||
|
@ -78,7 +78,7 @@ namespace osmium {
|
||||
{
|
||||
m_location_handler.ignore_errors();
|
||||
if (m_with_areas) {
|
||||
osmium::io::Reader reader(file, osmium::osm_entity_bits::relation);
|
||||
osmium::io::Reader reader{file, osmium::osm_entity_bits::relation};
|
||||
m_collector.read_relations(reader);
|
||||
reader.close();
|
||||
}
|
||||
|
@ -165,6 +165,11 @@ namespace osmium {
|
||||
|
||||
public:
|
||||
|
||||
GeometryFactory<TGeomImpl, TProjection>() :
|
||||
m_projection(),
|
||||
m_impl(m_projection.epsg()) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor for default initialized projection.
|
||||
*/
|
||||
@ -192,7 +197,7 @@ namespace osmium {
|
||||
using multipolygon_type = typename TGeomImpl::multipolygon_type;
|
||||
using ring_type = typename TGeomImpl::ring_type;
|
||||
|
||||
int epsg() const {
|
||||
int epsg() const noexcept {
|
||||
return m_projection.epsg();
|
||||
}
|
||||
|
||||
@ -380,9 +385,9 @@ namespace osmium {
|
||||
size_t num_rings = 0;
|
||||
m_impl.multipolygon_start();
|
||||
|
||||
for (auto it = area.cbegin(); it != area.cend(); ++it) {
|
||||
if (it->type() == osmium::item_type::outer_ring) {
|
||||
auto& ring = static_cast<const osmium::OuterRing&>(*it);
|
||||
for (const auto& item : area) {
|
||||
if (item.type() == osmium::item_type::outer_ring) {
|
||||
auto& ring = static_cast<const osmium::OuterRing&>(item);
|
||||
if (num_polygons > 0) {
|
||||
m_impl.multipolygon_polygon_finish();
|
||||
}
|
||||
@ -392,8 +397,8 @@ namespace osmium {
|
||||
m_impl.multipolygon_outer_ring_finish();
|
||||
++num_rings;
|
||||
++num_polygons;
|
||||
} else if (it->type() == osmium::item_type::inner_ring) {
|
||||
auto& ring = static_cast<const osmium::InnerRing&>(*it);
|
||||
} else if (item.type() == osmium::item_type::inner_ring) {
|
||||
auto& ring = static_cast<const osmium::InnerRing&>(item);
|
||||
m_impl.multipolygon_inner_ring_start();
|
||||
add_points(ring);
|
||||
m_impl.multipolygon_inner_ring_finish();
|
||||
|
@ -129,13 +129,13 @@ namespace osmium {
|
||||
*/
|
||||
OSMIUM_DEPRECATED explicit GEOSFactoryImpl(int /* srid */, int srid) :
|
||||
m_precision_model(new geos::geom::PrecisionModel),
|
||||
m_our_geos_factory(new geos::geom::GeometryFactory(m_precision_model.get(), srid)),
|
||||
m_our_geos_factory(new geos::geom::GeometryFactory{m_precision_model.get(), srid}),
|
||||
m_geos_factory(m_our_geos_factory.get()) {
|
||||
}
|
||||
|
||||
explicit GEOSFactoryImpl(int srid) :
|
||||
m_precision_model(new geos::geom::PrecisionModel),
|
||||
m_our_geos_factory(new geos::geom::GeometryFactory(m_precision_model.get(), srid)),
|
||||
m_our_geos_factory(new geos::geom::GeometryFactory{m_precision_model.get(), srid}),
|
||||
m_geos_factory(m_our_geos_factory.get()) {
|
||||
}
|
||||
|
||||
@ -143,7 +143,7 @@ namespace osmium {
|
||||
|
||||
point_type make_point(const osmium::geom::Coordinates& xy) const {
|
||||
try {
|
||||
return point_type(m_geos_factory->createPoint(geos::geom::Coordinate(xy.x, xy.y)));
|
||||
return point_type{m_geos_factory->createPoint(geos::geom::Coordinate{xy.x, xy.y})};
|
||||
} catch (const geos::util::GEOSException& e) {
|
||||
THROW(osmium::geos_geometry_error(e.what()));
|
||||
}
|
||||
@ -153,7 +153,7 @@ namespace osmium {
|
||||
|
||||
void linestring_start() {
|
||||
try {
|
||||
m_coordinate_sequence.reset(m_geos_factory->getCoordinateSequenceFactory()->create(static_cast<size_t>(0), 2));
|
||||
m_coordinate_sequence.reset(m_geos_factory->getCoordinateSequenceFactory()->create(static_cast<std::size_t>(0), 2));
|
||||
} catch (const geos::util::GEOSException& e) {
|
||||
THROW(osmium::geos_geometry_error(e.what()));
|
||||
}
|
||||
@ -161,15 +161,15 @@ namespace osmium {
|
||||
|
||||
void linestring_add_location(const osmium::geom::Coordinates& xy) {
|
||||
try {
|
||||
m_coordinate_sequence->add(geos::geom::Coordinate(xy.x, xy.y));
|
||||
m_coordinate_sequence->add(geos::geom::Coordinate{xy.x, xy.y});
|
||||
} catch (const geos::util::GEOSException& e) {
|
||||
THROW(osmium::geos_geometry_error(e.what()));
|
||||
}
|
||||
}
|
||||
|
||||
linestring_type linestring_finish(size_t /* num_points */) {
|
||||
linestring_type linestring_finish(std::size_t /* num_points */) {
|
||||
try {
|
||||
return linestring_type(m_geos_factory->createLineString(m_coordinate_sequence.release()));
|
||||
return linestring_type{m_geos_factory->createLineString(m_coordinate_sequence.release())};
|
||||
} catch (const geos::util::GEOSException& e) {
|
||||
THROW(osmium::geos_geometry_error(e.what()));
|
||||
}
|
||||
@ -201,7 +201,7 @@ namespace osmium {
|
||||
|
||||
void multipolygon_outer_ring_start() {
|
||||
try {
|
||||
m_coordinate_sequence.reset(m_geos_factory->getCoordinateSequenceFactory()->create(static_cast<size_t>(0), 2));
|
||||
m_coordinate_sequence.reset(m_geos_factory->getCoordinateSequenceFactory()->create(static_cast<std::size_t>(0), 2));
|
||||
} catch (const geos::util::GEOSException& e) {
|
||||
THROW(osmium::geos_geometry_error(e.what()));
|
||||
}
|
||||
@ -217,7 +217,7 @@ namespace osmium {
|
||||
|
||||
void multipolygon_inner_ring_start() {
|
||||
try {
|
||||
m_coordinate_sequence.reset(m_geos_factory->getCoordinateSequenceFactory()->create(static_cast<size_t>(0), 2));
|
||||
m_coordinate_sequence.reset(m_geos_factory->getCoordinateSequenceFactory()->create(static_cast<std::size_t>(0), 2));
|
||||
} catch (const geos::util::GEOSException& e) {
|
||||
THROW(osmium::geos_geometry_error(e.what()));
|
||||
}
|
||||
@ -233,7 +233,7 @@ namespace osmium {
|
||||
|
||||
void multipolygon_add_location(const osmium::geom::Coordinates& xy) {
|
||||
try {
|
||||
m_coordinate_sequence->add(geos::geom::Coordinate(xy.x, xy.y));
|
||||
m_coordinate_sequence->add(geos::geom::Coordinate{xy.x, xy.y});
|
||||
} catch (const geos::util::GEOSException& e) {
|
||||
THROW(osmium::geos_geometry_error(e.what()));
|
||||
}
|
||||
@ -246,7 +246,7 @@ namespace osmium {
|
||||
return p.release();
|
||||
});
|
||||
m_polygons.clear();
|
||||
return multipolygon_type(m_geos_factory->createMultiPolygon(polygons));
|
||||
return multipolygon_type{m_geos_factory->createMultiPolygon(polygons)};
|
||||
} catch (const geos::util::GEOSException& e) {
|
||||
THROW(osmium::geos_geometry_error(e.what()));
|
||||
}
|
||||
|
@ -118,7 +118,7 @@ namespace osmium {
|
||||
* @pre @code c.valid() @endcode
|
||||
*/
|
||||
inline Coordinates lonlat_to_mercator(const Coordinates& c) {
|
||||
return Coordinates(detail::lon_to_x(c.x), detail::lat_to_y(c.y));
|
||||
return Coordinates{detail::lon_to_x(c.x), detail::lat_to_y(c.y)};
|
||||
}
|
||||
|
||||
/**
|
||||
@ -127,7 +127,7 @@ namespace osmium {
|
||||
* @pre @code c.valid() @endcode
|
||||
*/
|
||||
inline Coordinates mercator_to_lonlat(const Coordinates& c) {
|
||||
return Coordinates(detail::x_to_lon(c.x), detail::y_to_lat(c.y));
|
||||
return Coordinates{detail::x_to_lon(c.x), detail::y_to_lat(c.y)};
|
||||
}
|
||||
|
||||
/**
|
||||
@ -138,8 +138,11 @@ namespace osmium {
|
||||
|
||||
public:
|
||||
|
||||
MercatorProjection() {
|
||||
}
|
||||
|
||||
Coordinates operator()(osmium::Location location) const {
|
||||
return Coordinates {detail::lon_to_x(location.lon()), detail::lat_to_y(location.lat())};
|
||||
return Coordinates{detail::lon_to_x(location.lon()), detail::lat_to_y(location.lat())};
|
||||
}
|
||||
|
||||
int epsg() const noexcept {
|
||||
|
@ -48,6 +48,7 @@ DEALINGS IN THE SOFTWARE.
|
||||
#include <proj_api.h>
|
||||
|
||||
#include <osmium/geom/coordinates.hpp>
|
||||
#include <osmium/geom/mercator_projection.hpp>
|
||||
#include <osmium/geom/util.hpp>
|
||||
#include <osmium/osm/location.hpp>
|
||||
|
||||
@ -70,15 +71,15 @@ namespace osmium {
|
||||
|
||||
public:
|
||||
|
||||
explicit CRS(const std::string& crs) :
|
||||
m_crs(pj_init_plus(crs.c_str()), ProjCRSDeleter()) {
|
||||
explicit CRS(const char* crs) :
|
||||
m_crs(pj_init_plus(crs), ProjCRSDeleter()) {
|
||||
if (!m_crs) {
|
||||
throw osmium::projection_error(std::string{"creation of CRS failed: "} + pj_strerrno(*pj_get_errno_ref()));
|
||||
throw osmium::projection_error{std::string{"creation of CRS failed: "} + pj_strerrno(*pj_get_errno_ref())};
|
||||
}
|
||||
}
|
||||
|
||||
explicit CRS(const char* crs) :
|
||||
CRS(std::string{crs}) {
|
||||
explicit CRS(const std::string& crs) :
|
||||
CRS(crs.c_str()) {
|
||||
}
|
||||
|
||||
explicit CRS(int epsg) :
|
||||
@ -88,15 +89,15 @@ namespace osmium {
|
||||
/**
|
||||
* Get underlying projPJ handle from proj library.
|
||||
*/
|
||||
projPJ get() const {
|
||||
projPJ get() const noexcept {
|
||||
return m_crs.get();
|
||||
}
|
||||
|
||||
bool is_latlong() const {
|
||||
bool is_latlong() const noexcept {
|
||||
return pj_is_latlong(m_crs.get()) != 0;
|
||||
}
|
||||
|
||||
bool is_geocent() const {
|
||||
bool is_geocent() const noexcept {
|
||||
return pj_is_geocent(m_crs.get()) != 0;
|
||||
}
|
||||
|
||||
@ -108,12 +109,13 @@ namespace osmium {
|
||||
*
|
||||
* Coordinates have to be in radians and are produced in radians.
|
||||
*
|
||||
* @throws osmmium::projection_error if the projection fails
|
||||
* @throws osmium::projection_error if the projection fails
|
||||
*/
|
||||
// cppcheck-suppress passedByValue (because c is small and we want to change it)
|
||||
inline Coordinates transform(const CRS& src, const CRS& dest, Coordinates c) {
|
||||
int result = pj_transform(src.get(), dest.get(), 1, 1, &c.x, &c.y, nullptr);
|
||||
const int result = pj_transform(src.get(), dest.get(), 1, 1, &c.x, &c.y, nullptr);
|
||||
if (result != 0) {
|
||||
throw osmium::projection_error(std::string("projection failed: ") + pj_strerrno(result));
|
||||
throw osmium::projection_error{std::string{"projection failed: "} + pj_strerrno(result)};
|
||||
}
|
||||
return c;
|
||||
}
|
||||
@ -121,12 +123,19 @@ namespace osmium {
|
||||
/**
|
||||
* Functor that does projection from WGS84 (EPSG:4326) to the given
|
||||
* CRS.
|
||||
*
|
||||
* If this Projection is initialized with the constructor taking
|
||||
* an integer with the epsg code 4326, no projection is done. If it
|
||||
* is initialized with epsg code 3857 the Osmium-internal
|
||||
* implementation of the Mercator projection is used, otherwise this
|
||||
* falls back to using the proj.4 library. Note that this "magic" does
|
||||
* not work if you use any of the constructors taking a string.
|
||||
*/
|
||||
class Projection {
|
||||
|
||||
int m_epsg;
|
||||
std::string m_proj_string;
|
||||
CRS m_crs_wgs84 {4326};
|
||||
CRS m_crs_wgs84{4326};
|
||||
CRS m_crs_user;
|
||||
|
||||
public:
|
||||
@ -145,20 +154,24 @@ namespace osmium {
|
||||
|
||||
explicit Projection(int epsg) :
|
||||
m_epsg(epsg),
|
||||
m_proj_string(std::string("+init=epsg:") + std::to_string(epsg)),
|
||||
m_proj_string(std::string{"+init=epsg:"} + std::to_string(epsg)),
|
||||
m_crs_user(epsg) {
|
||||
}
|
||||
|
||||
Coordinates operator()(osmium::Location location) const {
|
||||
Coordinates c {location.lon(), location.lat()};
|
||||
if (m_epsg == 4326) {
|
||||
return Coordinates{location.lon(), location.lat()};
|
||||
} else if (m_epsg == 3857) {
|
||||
return Coordinates{detail::lon_to_x(location.lon()),
|
||||
detail::lat_to_y(location.lat())};
|
||||
}
|
||||
|
||||
if (m_epsg != 4326) {
|
||||
c = transform(m_crs_wgs84, m_crs_user, Coordinates(deg_to_rad(location.lon()), deg_to_rad(location.lat())));
|
||||
Coordinates c{transform(m_crs_wgs84, m_crs_user, Coordinates{deg_to_rad(location.lon()),
|
||||
deg_to_rad(location.lat())})};
|
||||
if (m_crs_user.is_latlong()) {
|
||||
c.x = rad_to_deg(c.x);
|
||||
c.y = rad_to_deg(c.y);
|
||||
}
|
||||
}
|
||||
|
||||
return c;
|
||||
}
|
||||
|
@ -43,13 +43,23 @@ namespace osmium {
|
||||
/**
|
||||
* Check whether one geometry contains another.
|
||||
*/
|
||||
inline bool contains(const osmium::Box& lhs, const osmium::Box& rhs) {
|
||||
inline bool contains(const osmium::Box& lhs, const osmium::Box& rhs) noexcept {
|
||||
return ((lhs.bottom_left().x() >= rhs.bottom_left().x()) &&
|
||||
(lhs.top_right().x() <= rhs.top_right().x()) &&
|
||||
(lhs.bottom_left().y() >= rhs.bottom_left().y()) &&
|
||||
(lhs.top_right().y() <= rhs.top_right().y()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether one geometry overlaps another.
|
||||
*/
|
||||
inline bool overlaps(const osmium::Box& lhs, const osmium::Box& rhs) noexcept {
|
||||
return ((lhs.bottom_left().x() <= rhs.top_right().x()) &&
|
||||
(lhs.bottom_left().y() <= rhs.top_right().y()) &&
|
||||
(rhs.bottom_left().x() <= lhs.top_right().x()) &&
|
||||
(rhs.bottom_left().y() <= lhs.top_right().y()));
|
||||
}
|
||||
|
||||
} // namespace geom
|
||||
|
||||
} // namespace osmium
|
||||
|
@ -62,7 +62,7 @@ namespace osmium {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the width or hight of a tile in web mercator coordinates for
|
||||
* Returns the width or height of a tile in web mercator coordinates for
|
||||
* the given zoom level.
|
||||
*/
|
||||
inline constexpr double tile_extent_in_zoom(uint32_t zoom) noexcept {
|
||||
@ -108,7 +108,7 @@ namespace osmium {
|
||||
uint32_t z;
|
||||
|
||||
/**
|
||||
* Create a tile with the given zoom level and x any y tile
|
||||
* Create a tile with the given zoom level and x and y tile
|
||||
* coordinates.
|
||||
*
|
||||
* The values are not checked for validity.
|
||||
@ -172,22 +172,30 @@ namespace osmium {
|
||||
}; // struct Tile
|
||||
|
||||
/// Tiles are equal if all their attributes are equal.
|
||||
inline bool operator==(const Tile& lhs, const Tile& rhs) {
|
||||
inline bool operator==(const Tile& lhs, const Tile& rhs) noexcept {
|
||||
return lhs.z == rhs.z && lhs.x == rhs.x && lhs.y == rhs.y;
|
||||
}
|
||||
|
||||
inline bool operator!=(const Tile& lhs, const Tile& rhs) {
|
||||
inline bool operator!=(const Tile& lhs, const Tile& rhs) noexcept {
|
||||
return ! (lhs == rhs);
|
||||
}
|
||||
|
||||
/**
|
||||
* This defines an arbitrary order on tiles for use in std::map etc.
|
||||
*/
|
||||
inline bool operator<(const Tile& lhs, const Tile& rhs) {
|
||||
if (lhs.z < rhs.z) return true;
|
||||
if (lhs.z > rhs.z) return false;
|
||||
if (lhs.x < rhs.x) return true;
|
||||
if (lhs.x > rhs.x) return false;
|
||||
inline bool operator<(const Tile& lhs, const Tile& rhs) noexcept {
|
||||
if (lhs.z < rhs.z) {
|
||||
return true;
|
||||
}
|
||||
if (lhs.z > rhs.z) {
|
||||
return false;
|
||||
}
|
||||
if (lhs.x < rhs.x) {
|
||||
return true;
|
||||
}
|
||||
if (lhs.x > rhs.x) {
|
||||
return false;
|
||||
}
|
||||
return lhs.y < rhs.y;
|
||||
}
|
||||
|
||||
|
@ -108,19 +108,19 @@ namespace osmium {
|
||||
}; // enum class wkb_byte_order_type
|
||||
|
||||
std::string m_data;
|
||||
uint32_t m_points {0};
|
||||
uint32_t m_points = 0;
|
||||
int m_srid;
|
||||
wkb_type m_wkb_type;
|
||||
out_type m_out_type;
|
||||
|
||||
size_t m_linestring_size_offset = 0;
|
||||
size_t m_polygons = 0;
|
||||
size_t m_rings = 0;
|
||||
size_t m_multipolygon_size_offset = 0;
|
||||
size_t m_polygon_size_offset = 0;
|
||||
size_t m_ring_size_offset = 0;
|
||||
std::size_t m_linestring_size_offset = 0;
|
||||
std::size_t m_polygons = 0;
|
||||
std::size_t m_rings = 0;
|
||||
std::size_t m_multipolygon_size_offset = 0;
|
||||
std::size_t m_polygon_size_offset = 0;
|
||||
std::size_t m_ring_size_offset = 0;
|
||||
|
||||
size_t header(std::string& str, wkbGeometryType type, bool add_length) const {
|
||||
std::size_t header(std::string& str, wkbGeometryType type, bool add_length) const {
|
||||
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
||||
str_push(str, wkb_byte_order_type::NDR);
|
||||
#else
|
||||
@ -132,14 +132,14 @@ namespace osmium {
|
||||
} else {
|
||||
str_push(str, type);
|
||||
}
|
||||
const size_t offset = str.size();
|
||||
const std::size_t offset = str.size();
|
||||
if (add_length) {
|
||||
str_push(str, static_cast<uint32_t>(0));
|
||||
}
|
||||
return offset;
|
||||
}
|
||||
|
||||
void set_size(const size_t offset, const size_t size) {
|
||||
void set_size(const std::size_t offset, const std::size_t size) {
|
||||
uint32_t s = static_cast_with_assert<uint32_t>(size);
|
||||
std::copy_n(reinterpret_cast<char*>(&s), sizeof(uint32_t), &m_data[offset]);
|
||||
}
|
||||
@ -185,7 +185,7 @@ namespace osmium {
|
||||
str_push(m_data, xy.y);
|
||||
}
|
||||
|
||||
linestring_type linestring_finish(size_t num_points) {
|
||||
linestring_type linestring_finish(std::size_t num_points) {
|
||||
set_size(m_linestring_size_offset, num_points);
|
||||
std::string data;
|
||||
|
||||
|
@ -39,6 +39,7 @@ DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#include <osmium/handler.hpp>
|
||||
#include <osmium/osm/node.hpp>
|
||||
#include <osmium/osm/object_comparisons.hpp>
|
||||
#include <osmium/osm/relation.hpp>
|
||||
#include <osmium/osm/types.hpp>
|
||||
#include <osmium/osm/way.hpp>
|
||||
@ -51,12 +52,16 @@ namespace osmium {
|
||||
*/
|
||||
struct out_of_order_error : public std::runtime_error {
|
||||
|
||||
explicit out_of_order_error(const std::string& what) :
|
||||
std::runtime_error(what) {
|
||||
osmium::object_id_type object_id;
|
||||
|
||||
explicit out_of_order_error(const std::string& what, osmium::object_id_type id) :
|
||||
std::runtime_error(what),
|
||||
object_id(id) {
|
||||
}
|
||||
|
||||
explicit out_of_order_error(const char* what) :
|
||||
std::runtime_error(what) {
|
||||
explicit out_of_order_error(const char* what, osmium::object_id_type id) :
|
||||
std::runtime_error(what),
|
||||
object_id(id) {
|
||||
}
|
||||
|
||||
}; // struct out_of_order_error
|
||||
@ -67,12 +72,14 @@ namespace osmium {
|
||||
* Handler that can be used to check that an OSM file is ordered
|
||||
* correctly. Ordered in this case refers to the usual order in OSM
|
||||
* files: First nodes in the order of their IDs, then ways in the order
|
||||
* of their IDs, then relations in the order or their IDs.
|
||||
* of their IDs, then relations in the order or their IDs. Negative
|
||||
* IDs are ordered first then positive IDs, both ordered by absolute
|
||||
* value.
|
||||
*
|
||||
* IDs have to be unique for each type. This check will fail for
|
||||
* history files.
|
||||
*
|
||||
* To use this add a CheckOrder member variable to your handler and
|
||||
* To use this, add a CheckOrder member variable to your handler and
|
||||
* call the node(), way(), and relation() methods from your node(),
|
||||
* way(), and relations() handlers, respectively. An out_of_order_error
|
||||
* exception will be thrown when the input is not in order.
|
||||
@ -86,33 +93,42 @@ namespace osmium {
|
||||
public:
|
||||
|
||||
void node(const osmium::Node& node) {
|
||||
if (m_max_way_id > 0) {
|
||||
throw out_of_order_error("Found a node after a way.");
|
||||
if (m_max_way_id > std::numeric_limits<osmium::object_id_type>::min()) {
|
||||
throw out_of_order_error{"Found a node after a way.", node.id()};
|
||||
}
|
||||
if (m_max_relation_id > 0) {
|
||||
throw out_of_order_error("Found a node after a relation.");
|
||||
if (m_max_relation_id > std::numeric_limits<osmium::object_id_type>::min()) {
|
||||
throw out_of_order_error{"Found a node after a relation.", node.id()};
|
||||
}
|
||||
|
||||
if (m_max_node_id >= node.id()) {
|
||||
throw out_of_order_error("Node IDs out of order.");
|
||||
if (m_max_node_id == node.id()) {
|
||||
throw out_of_order_error{"Node ID twice in input. Maybe you are using a history or change file?", node.id()};
|
||||
}
|
||||
if (id_order{}(node.id(), m_max_node_id)) {
|
||||
throw out_of_order_error{"Node IDs out of order.", node.id()};
|
||||
}
|
||||
m_max_node_id = node.id();
|
||||
}
|
||||
|
||||
void way(const osmium::Way& way) {
|
||||
if (m_max_relation_id > 0) {
|
||||
throw out_of_order_error("Found a way after a relation.");
|
||||
if (m_max_relation_id > std::numeric_limits<osmium::object_id_type>::min()) {
|
||||
throw out_of_order_error{"Found a way after a relation.", way.id()};
|
||||
}
|
||||
|
||||
if (m_max_way_id >= way.id()) {
|
||||
throw out_of_order_error("Way IDs out of order.");
|
||||
if (m_max_way_id == way.id()) {
|
||||
throw out_of_order_error{"Way ID twice in input. Maybe you are using a history or change file?", way.id()};
|
||||
}
|
||||
if (id_order{}(way.id(), m_max_way_id)) {
|
||||
throw out_of_order_error{"Way IDs out of order.", way.id()};
|
||||
}
|
||||
m_max_way_id = way.id();
|
||||
}
|
||||
|
||||
void relation(const osmium::Relation& relation) {
|
||||
if (m_max_relation_id >= relation.id()) {
|
||||
throw out_of_order_error("Relation IDs out of order.");
|
||||
if (m_max_relation_id == relation.id()) {
|
||||
throw out_of_order_error{"Relation ID twice in input. Maybe you are using a history or change file?", relation.id()};
|
||||
}
|
||||
if (id_order{}(relation.id(), m_max_relation_id)) {
|
||||
throw out_of_order_error{"Relation IDs out of order.", relation.id()};
|
||||
}
|
||||
m_max_relation_id = relation.id();
|
||||
}
|
||||
|
@ -60,9 +60,9 @@ namespace osmium {
|
||||
*/
|
||||
class DiskStore : public osmium::handler::Handler {
|
||||
|
||||
using offset_index_type = osmium::index::map::Map<unsigned_object_id_type, size_t>;
|
||||
using offset_index_type = osmium::index::map::Map<unsigned_object_id_type, std::size_t>;
|
||||
|
||||
size_t m_offset = 0;
|
||||
std::size_t m_offset = 0;
|
||||
int m_data_fd;
|
||||
|
||||
offset_index_type& m_node_index;
|
||||
|
@ -108,7 +108,7 @@ namespace osmium {
|
||||
<< (object.visible() ? "yes" : "no")
|
||||
<< "\n";
|
||||
|
||||
Dump dump(*m_out, m_with_size, m_prefix + " ");
|
||||
Dump dump{*m_out, m_with_size, m_prefix + " "};
|
||||
osmium::apply(object.cbegin(), object.cend(), dump);
|
||||
}
|
||||
|
||||
@ -281,7 +281,7 @@ namespace osmium {
|
||||
|
||||
*m_out << "\n";
|
||||
|
||||
Dump dump(*m_out, m_with_size, m_prefix + " ");
|
||||
Dump dump{*m_out, m_with_size, m_prefix + " "};
|
||||
osmium::apply(changeset.cbegin(), changeset.cend(), dump);
|
||||
}
|
||||
|
||||
|
@ -64,9 +64,11 @@ namespace osmium {
|
||||
template <typename TStoragePosIDs, typename TStorageNegIDs = dummy_type>
|
||||
class NodeLocationsForWays : public osmium::handler::Handler {
|
||||
|
||||
static_assert(std::is_base_of<osmium::index::map::Map<osmium::unsigned_object_id_type, osmium::Location>, TStoragePosIDs>::value, "Index class must be derived from osmium::index::map::Map<osmium::unsigned_object_id_type, osmium::Location>");
|
||||
template <typename T>
|
||||
using based_on_map = std::is_base_of<osmium::index::map::Map<osmium::unsigned_object_id_type, osmium::Location>, T>;
|
||||
|
||||
static_assert(std::is_base_of<osmium::index::map::Map<osmium::unsigned_object_id_type, osmium::Location>, TStorageNegIDs>::value, "Index class must be derived from osmium::index::map::Map<osmium::unsigned_object_id_type, osmium::Location>");
|
||||
static_assert(based_on_map<TStoragePosIDs>::value, "Index class must be derived from osmium::index::map::Map<osmium::unsigned_object_id_type, osmium::Location>");
|
||||
static_assert(based_on_map<TStorageNegIDs>::value, "Index class must be derived from osmium::index::map::Map<osmium::unsigned_object_id_type, osmium::Location>");
|
||||
|
||||
public:
|
||||
|
||||
@ -81,11 +83,11 @@ namespace osmium {
|
||||
/// Object that handles the actual storage of the node locations (with negative IDs).
|
||||
TStorageNegIDs& m_storage_neg;
|
||||
|
||||
osmium::unsigned_object_id_type m_last_id{0};
|
||||
osmium::unsigned_object_id_type m_last_id = 0;
|
||||
|
||||
bool m_ignore_errors{false};
|
||||
bool m_ignore_errors = false;
|
||||
|
||||
bool m_must_sort{false};
|
||||
bool m_must_sort = false;
|
||||
|
||||
// It is okay to have this static dummy instance, even when using several threads,
|
||||
// because it is read-only.
|
||||
@ -123,7 +125,7 @@ namespace osmium {
|
||||
}
|
||||
m_last_id = node.positive_id();
|
||||
|
||||
const osmium::object_id_type id = node.id();
|
||||
const auto id = node.id();
|
||||
if (id >= 0) {
|
||||
m_storage_pos.set(static_cast<osmium::unsigned_object_id_type>( id), node.location());
|
||||
} else {
|
||||
@ -136,9 +138,9 @@ namespace osmium {
|
||||
*/
|
||||
osmium::Location get_node_location(const osmium::object_id_type id) const {
|
||||
if (id >= 0) {
|
||||
return m_storage_pos.get(static_cast<osmium::unsigned_object_id_type>( id));
|
||||
return m_storage_pos.get_noexcept(static_cast<osmium::unsigned_object_id_type>( id));
|
||||
} else {
|
||||
return m_storage_neg.get(static_cast<osmium::unsigned_object_id_type>(-id));
|
||||
return m_storage_neg.get_noexcept(static_cast<osmium::unsigned_object_id_type>(-id));
|
||||
}
|
||||
}
|
||||
|
||||
@ -155,16 +157,12 @@ namespace osmium {
|
||||
}
|
||||
bool error = false;
|
||||
for (auto& node_ref : way.nodes()) {
|
||||
try {
|
||||
node_ref.set_location(get_node_location(node_ref.ref()));
|
||||
if (!node_ref.location()) {
|
||||
error = true;
|
||||
}
|
||||
} catch (const osmium::not_found&) {
|
||||
error = true;
|
||||
}
|
||||
}
|
||||
if (error && !m_ignore_errors) {
|
||||
if (!m_ignore_errors && error) {
|
||||
throw osmium::not_found{"location for one or more nodes not found in node location index"};
|
||||
}
|
||||
}
|
||||
|
@ -50,15 +50,15 @@ namespace osmium {
|
||||
template <typename T>
|
||||
inline T* create_map_with_fd(const std::vector<std::string>& config) {
|
||||
if (config.size() == 1) {
|
||||
return new T();
|
||||
return new T{};
|
||||
}
|
||||
assert(config.size() > 1);
|
||||
const std::string& filename = config[1];
|
||||
const int fd = ::open(filename.c_str(), O_CREAT | O_RDWR, 0644);
|
||||
if (fd == -1) {
|
||||
throw std::runtime_error(std::string("can't open file '") + filename + "': " + std::strerror(errno));
|
||||
throw std::runtime_error{std::string{"can't open file '"} + filename + "': " + std::strerror(errno)};
|
||||
}
|
||||
return new T(fd);
|
||||
return new T{fd};
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
@ -53,11 +53,11 @@ namespace osmium {
|
||||
template <typename T>
|
||||
class mmap_vector_file : public mmap_vector_base<T> {
|
||||
|
||||
size_t filesize(int fd) const {
|
||||
const size_t size = osmium::util::file_size(fd);
|
||||
static std::size_t filesize(int fd) {
|
||||
const auto size = osmium::util::file_size(fd);
|
||||
|
||||
if (size % sizeof(T) != 0) {
|
||||
throw std::runtime_error("Index file has wrong size (must be multiple of " + std::to_string(sizeof(T)) + ").");
|
||||
throw std::runtime_error{"Index file has wrong size (must be multiple of " + std::to_string(sizeof(T)) + ")."};
|
||||
}
|
||||
|
||||
return size / sizeof(T);
|
||||
|
@ -50,7 +50,7 @@ namespace osmium {
|
||||
inline int create_tmp_file() {
|
||||
FILE* file = ::tmpfile();
|
||||
if (!file) {
|
||||
throw std::system_error(errno, std::system_category(), "tempfile failed");
|
||||
throw std::system_error{errno, std::system_category(), "tempfile failed"};
|
||||
}
|
||||
return fileno(file);
|
||||
}
|
||||
|
@ -35,7 +35,6 @@ DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstddef>
|
||||
#include <stdexcept>
|
||||
#include <utility>
|
||||
|
||||
#include <osmium/index/index.hpp>
|
||||
@ -70,7 +69,7 @@ namespace osmium {
|
||||
|
||||
~VectorBasedDenseMap() noexcept final = default;
|
||||
|
||||
void reserve(const size_t size) final {
|
||||
void reserve(const std::size_t size) final {
|
||||
m_vector.reserve(size);
|
||||
}
|
||||
|
||||
@ -99,15 +98,15 @@ namespace osmium {
|
||||
return m_vector[id];
|
||||
}
|
||||
|
||||
size_t size() const final {
|
||||
std::size_t size() const final {
|
||||
return m_vector.size();
|
||||
}
|
||||
|
||||
size_t byte_size() const {
|
||||
std::size_t byte_size() const {
|
||||
return m_vector.size() * sizeof(element_type);
|
||||
}
|
||||
|
||||
size_t used_memory() const final {
|
||||
std::size_t used_memory() const final {
|
||||
return sizeof(TValue) * size();
|
||||
}
|
||||
|
||||
@ -205,15 +204,15 @@ namespace osmium {
|
||||
return result->second;
|
||||
}
|
||||
|
||||
size_t size() const final {
|
||||
std::size_t size() const final {
|
||||
return m_vector.size();
|
||||
}
|
||||
|
||||
size_t byte_size() const {
|
||||
std::size_t byte_size() const {
|
||||
return m_vector.size() * sizeof(element_type);
|
||||
}
|
||||
|
||||
size_t used_memory() const final {
|
||||
std::size_t used_memory() const final {
|
||||
return sizeof(element_type) * size();
|
||||
}
|
||||
|
||||
|
@ -35,10 +35,11 @@ DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <cstddef>
|
||||
#include <cstring>
|
||||
#include <iterator>
|
||||
#include <memory>
|
||||
#include <type_traits>
|
||||
#include <unordered_set>
|
||||
#include <vector>
|
||||
|
||||
#include <osmium/osm/item_type.hpp>
|
||||
@ -57,8 +58,7 @@ namespace osmium {
|
||||
|
||||
public:
|
||||
|
||||
virtual ~IdSet() {
|
||||
}
|
||||
virtual ~IdSet() = default;
|
||||
|
||||
/**
|
||||
* Add the given Id to the set.
|
||||
@ -80,6 +80,11 @@ namespace osmium {
|
||||
*/
|
||||
virtual void clear() = 0;
|
||||
|
||||
/**
|
||||
* Get an estimate of the amount of memory used for the set.
|
||||
*/
|
||||
virtual std::size_t used_memory() const noexcept = 0;
|
||||
|
||||
}; // class IdSet
|
||||
|
||||
template <typename T>
|
||||
@ -139,7 +144,7 @@ namespace osmium {
|
||||
}
|
||||
|
||||
IdSetDenseIterator<T> operator++(int) noexcept {
|
||||
IdSetDenseIterator<T> tmp(*this);
|
||||
IdSetDenseIterator<T> tmp{*this};
|
||||
operator++();
|
||||
return tmp;
|
||||
}
|
||||
@ -178,17 +183,17 @@ namespace osmium {
|
||||
// which would mean less (but larger) memory allocations. For
|
||||
// relations Ids it could be smaller, because they would all fit
|
||||
// into a smaller allocation.
|
||||
constexpr static const size_t chunk_bits = 22;
|
||||
constexpr static const size_t chunk_size = 1 << chunk_bits;
|
||||
constexpr static const std::size_t chunk_bits = 22;
|
||||
constexpr static const std::size_t chunk_size = 1 << chunk_bits;
|
||||
|
||||
std::vector<std::unique_ptr<unsigned char[]>> m_data;
|
||||
T m_size = 0;
|
||||
|
||||
static size_t chunk_id(T id) noexcept {
|
||||
static std::size_t chunk_id(T id) noexcept {
|
||||
return id >> (chunk_bits + 3);
|
||||
}
|
||||
|
||||
static size_t offset(T id) noexcept {
|
||||
static std::size_t offset(T id) noexcept {
|
||||
return (id >> 3) & ((1 << chunk_bits) - 1);
|
||||
}
|
||||
|
||||
@ -244,7 +249,7 @@ namespace osmium {
|
||||
*
|
||||
* @param id The Id to set.
|
||||
*/
|
||||
void set(T id) override final {
|
||||
void set(T id) final {
|
||||
(void)check_and_set(id);
|
||||
}
|
||||
|
||||
@ -267,7 +272,7 @@ namespace osmium {
|
||||
*
|
||||
* @param id The Id to check.
|
||||
*/
|
||||
bool get(T id) const noexcept override final {
|
||||
bool get(T id) const noexcept final {
|
||||
if (chunk_id(id) >= m_data.size()) {
|
||||
return false;
|
||||
}
|
||||
@ -281,7 +286,7 @@ namespace osmium {
|
||||
/**
|
||||
* Is the set empty?
|
||||
*/
|
||||
bool empty() const noexcept override final {
|
||||
bool empty() const noexcept final {
|
||||
return m_size == 0;
|
||||
}
|
||||
|
||||
@ -295,17 +300,21 @@ namespace osmium {
|
||||
/**
|
||||
* Clear the set.
|
||||
*/
|
||||
void clear() override final {
|
||||
void clear() final {
|
||||
m_data.clear();
|
||||
m_size = 0;
|
||||
}
|
||||
|
||||
std::size_t used_memory() const noexcept final {
|
||||
return m_data.size() * chunk_size;
|
||||
}
|
||||
|
||||
IdSetDenseIterator<T> begin() const {
|
||||
return IdSetDenseIterator<T>{this, 0, last()};
|
||||
return {this, 0, last()};
|
||||
}
|
||||
|
||||
IdSetDenseIterator<T> end() const {
|
||||
return IdSetDenseIterator<T>{this, last(), last()};
|
||||
return {this, last(), last()};
|
||||
}
|
||||
|
||||
}; // class IdSetDense
|
||||
@ -324,7 +333,7 @@ namespace osmium {
|
||||
/**
|
||||
* Add the given Id to the set.
|
||||
*/
|
||||
void set(T id) override final {
|
||||
void set(T id) final {
|
||||
m_data.push_back(id);
|
||||
}
|
||||
|
||||
@ -333,7 +342,7 @@ namespace osmium {
|
||||
*
|
||||
* @param id The Id to check.
|
||||
*/
|
||||
bool get(T id) const noexcept override final {
|
||||
bool get(T id) const noexcept final {
|
||||
const auto it = std::find(m_data.cbegin(), m_data.cend(), id);
|
||||
return it != m_data.cend();
|
||||
}
|
||||
@ -355,14 +364,14 @@ namespace osmium {
|
||||
/**
|
||||
* Is the set empty?
|
||||
*/
|
||||
bool empty() const noexcept override final {
|
||||
bool empty() const noexcept final {
|
||||
return m_data.empty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear the set.
|
||||
*/
|
||||
void clear() override final {
|
||||
void clear() final {
|
||||
m_data.clear();
|
||||
}
|
||||
|
||||
@ -383,10 +392,14 @@ namespace osmium {
|
||||
* @pre You must have called sort_unique() before calling this
|
||||
* or be sure there are no duplicates.
|
||||
*/
|
||||
size_t size() const noexcept {
|
||||
std::size_t size() const noexcept {
|
||||
return m_data.size();
|
||||
}
|
||||
|
||||
std::size_t used_memory() const noexcept final {
|
||||
return m_data.capacity() * sizeof(T);
|
||||
}
|
||||
|
||||
/// Iterator type. There is no non-const iterator.
|
||||
using const_iterator = typename std::vector<T>::const_iterator;
|
||||
|
||||
@ -408,6 +421,7 @@ namespace osmium {
|
||||
|
||||
}; // class IdSetSmall
|
||||
|
||||
/// @deprecated Use nwr_array helper class instead.
|
||||
template <template<typename> class IdSetType>
|
||||
class NWRIdSet {
|
||||
|
||||
|
@ -34,12 +34,11 @@ DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <limits>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
|
||||
#include <osmium/util/compatibility.hpp>
|
||||
|
||||
namespace osmium {
|
||||
|
||||
/**
|
||||
|
@ -43,7 +43,6 @@ DEALINGS IN THE SOFTWARE.
|
||||
#include <type_traits>
|
||||
#include <vector>
|
||||
|
||||
#include <osmium/util/compatibility.hpp>
|
||||
#include <osmium/util/string.hpp>
|
||||
|
||||
namespace osmium {
|
||||
@ -181,14 +180,14 @@ namespace osmium {
|
||||
// but not always. It could, for instance, sort internal data.
|
||||
// This is why it is not declared const here.
|
||||
virtual void dump_as_list(const int /*fd*/) {
|
||||
throw std::runtime_error("can't dump as list");
|
||||
throw std::runtime_error{"can't dump as list"};
|
||||
}
|
||||
|
||||
// This function can usually be const in derived classes,
|
||||
// but not always. It could, for instance, sort internal data.
|
||||
// This is why it is not declared const here.
|
||||
virtual void dump_as_array(const int /*fd*/) {
|
||||
throw std::runtime_error("can't dump as array");
|
||||
throw std::runtime_error{"can't dump as array"};
|
||||
}
|
||||
|
||||
}; // class Map
|
||||
@ -245,13 +244,13 @@ namespace osmium {
|
||||
}
|
||||
|
||||
std::unique_ptr<map_type> create_map(const std::string& config_string) const {
|
||||
std::vector<std::string> config = osmium::split_string(config_string, ',');
|
||||
std::vector<std::string> config{osmium::split_string(config_string, ',')};
|
||||
|
||||
if (config.empty()) {
|
||||
throw map_factory_error{"Need non-empty map type name"};
|
||||
}
|
||||
|
||||
auto it = m_callbacks.find(config[0]);
|
||||
const auto it = m_callbacks.find(config[0]);
|
||||
if (it != m_callbacks.end()) {
|
||||
return std::unique_ptr<map_type>((it->second)(config));
|
||||
}
|
||||
|
@ -37,6 +37,7 @@ DEALINGS IN THE SOFTWARE.
|
||||
#include <osmium/index/map/dense_mem_array.hpp> // IWYU pragma: keep
|
||||
#include <osmium/index/map/dense_mmap_array.hpp> // IWYU pragma: keep
|
||||
#include <osmium/index/map/dummy.hpp> // IWYU pragma: keep
|
||||
#include <osmium/index/map/flex_mem.hpp> // IWYU pragma: keep
|
||||
#include <osmium/index/map/sparse_file_array.hpp> // IWYU pragma: keep
|
||||
#include <osmium/index/map/sparse_mem_array.hpp> // IWYU pragma: keep
|
||||
#include <osmium/index/map/sparse_mem_map.hpp> // IWYU pragma: keep
|
||||
|
@ -64,4 +64,8 @@ namespace osmium {
|
||||
|
||||
} // namespace osmium
|
||||
|
||||
#ifdef OSMIUM_WANT_NODE_LOCATION_MAPS
|
||||
REGISTER_MAP(osmium::unsigned_object_id_type, osmium::Location, osmium::index::map::DenseFileArray, dense_file_array)
|
||||
#endif
|
||||
|
||||
#endif // OSMIUM_INDEX_MAP_DENSE_FILE_ARRAY_HPP
|
||||
|
@ -54,4 +54,8 @@ namespace osmium {
|
||||
|
||||
} // namespace osmium
|
||||
|
||||
#ifdef OSMIUM_WANT_NODE_LOCATION_MAPS
|
||||
REGISTER_MAP(osmium::unsigned_object_id_type, osmium::Location, osmium::index::map::DenseMemArray, dense_mem_array)
|
||||
#endif
|
||||
|
||||
#endif // OSMIUM_INDEX_MAP_DENSE_MEM_ARRAY_HPP
|
||||
|
@ -55,6 +55,10 @@ namespace osmium {
|
||||
|
||||
} // namespace osmium
|
||||
|
||||
#ifdef OSMIUM_WANT_NODE_LOCATION_MAPS
|
||||
REGISTER_MAP(osmium::unsigned_object_id_type, osmium::Location, osmium::index::map::DenseMmapArray, dense_mmap_array)
|
||||
#endif
|
||||
|
||||
#endif // __linux__
|
||||
|
||||
#endif // OSMIUM_INDEX_MAP_DENSE_MMAP_ARRAY_HPP
|
||||
|
285
third_party/libosmium/include/osmium/index/map/flex_mem.hpp
vendored
Normal file
285
third_party/libosmium/include/osmium/index/map/flex_mem.hpp
vendored
Normal file
@ -0,0 +1,285 @@
|
||||
#ifndef OSMIUM_INDEX_MAP_FLEX_MEM_HPP
|
||||
#define OSMIUM_INDEX_MAP_FLEX_MEM_HPP
|
||||
|
||||
/*
|
||||
|
||||
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||
|
||||
Copyright 2013-2017 Jochen Topf <jochen@topf.org> and others (see README).
|
||||
|
||||
Boost Software License - Version 1.0 - August 17th, 2003
|
||||
|
||||
Permission is hereby granted, free of charge, to any person or organization
|
||||
obtaining a copy of the software and accompanying documentation covered by
|
||||
this license (the "Software") to use, reproduce, display, distribute,
|
||||
execute, and transmit the Software, and to prepare derivative works of the
|
||||
Software, and to permit third-parties to whom the Software is furnished to
|
||||
do so, all subject to the following:
|
||||
|
||||
The copyright notices in the Software and this entire statement, including
|
||||
the above license grant, this restriction and the following disclaimer,
|
||||
must be included in all copies of the Software, in whole or in part, and
|
||||
all derivative works of the Software, unless such copies or derivative
|
||||
works are solely in the form of machine-executable object code generated by
|
||||
a source language processor.
|
||||
|
||||
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, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include <osmium/index/map.hpp>
|
||||
#include <osmium/index/index.hpp>
|
||||
|
||||
#define OSMIUM_HAS_INDEX_MAP_FLEX_MEM
|
||||
|
||||
namespace osmium {
|
||||
|
||||
namespace index {
|
||||
|
||||
namespace map {
|
||||
|
||||
/**
|
||||
* This is an autoscaling index that works well with small and
|
||||
* large input data. All data will be held in memory. For small
|
||||
* input data a sparse array will be used, if this becomes
|
||||
* inefficient, the class will switch automatically to a dense
|
||||
* index.
|
||||
*/
|
||||
template <typename TId, typename TValue>
|
||||
class FlexMem : public osmium::index::map::Map<TId, TValue> {
|
||||
|
||||
// This value is based on benchmarks with a planet file and
|
||||
// some smaller files.
|
||||
enum constant_bits {
|
||||
bits = 16
|
||||
};
|
||||
|
||||
enum constant_block_size : uint64_t {
|
||||
block_size = 1ll << bits
|
||||
};
|
||||
|
||||
// Minimum number of entries in the sparse index before we
|
||||
// are considering switching to a dense index.
|
||||
enum constant_min_dense_entries : int64_t {
|
||||
min_dense_entries = 0xffffff
|
||||
};
|
||||
|
||||
// When more than a third of all Ids are in the index, we
|
||||
// switch to the dense index. This is a compromise between
|
||||
// the best memory efficiency (which we would get at a factor
|
||||
// of 2) and the performance (dense index is much faster then
|
||||
// the sparse index).
|
||||
enum constant_density_factor {
|
||||
density_factor = 3
|
||||
};
|
||||
|
||||
// An entry in the sparse index
|
||||
struct entry {
|
||||
uint64_t id;
|
||||
TValue value;
|
||||
|
||||
entry(uint64_t i, TValue v) :
|
||||
id(i),
|
||||
value(v) {
|
||||
}
|
||||
|
||||
bool operator<(const entry other) const noexcept {
|
||||
return id < other.id;
|
||||
}
|
||||
};
|
||||
|
||||
std::vector<entry> m_sparse_entries;
|
||||
|
||||
std::vector<std::vector<TValue>> m_dense_blocks;
|
||||
|
||||
// The maximum Id that was seen yet. Only set in sparse mode.
|
||||
uint64_t m_max_id = 0;
|
||||
|
||||
// Set to false in sparse mode and to true in dense mode.
|
||||
bool m_dense;
|
||||
|
||||
static uint64_t block(const uint64_t id) noexcept {
|
||||
return id >> bits;
|
||||
}
|
||||
|
||||
static uint64_t offset(const uint64_t id) noexcept {
|
||||
return id & (block_size - 1);
|
||||
}
|
||||
|
||||
// Assure that the block with the given number exists. Create
|
||||
// it if needed.
|
||||
void assure_block(const uint64_t num) {
|
||||
if (num >= m_dense_blocks.size()) {
|
||||
m_dense_blocks.resize(num + 1);
|
||||
}
|
||||
if (m_dense_blocks[num].empty()) {
|
||||
m_dense_blocks[num].assign(block_size, osmium::index::empty_value<TValue>());
|
||||
}
|
||||
}
|
||||
|
||||
void set_sparse(const uint64_t id, const TValue value) {
|
||||
m_sparse_entries.emplace_back(id, value);
|
||||
if (id > m_max_id) {
|
||||
m_max_id = id;
|
||||
|
||||
if (m_sparse_entries.size() >= min_dense_entries) {
|
||||
if (m_max_id < m_sparse_entries.size() * density_factor) {
|
||||
switch_to_dense();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TValue get_sparse(const uint64_t id) const noexcept {
|
||||
const auto it = std::lower_bound(m_sparse_entries.begin(),
|
||||
m_sparse_entries.end(),
|
||||
entry{id, osmium::index::empty_value<TValue>()});
|
||||
if (it == m_sparse_entries.end() || it->id != id) {
|
||||
return osmium::index::empty_value<TValue>();
|
||||
}
|
||||
return it->value;
|
||||
}
|
||||
|
||||
void set_dense(const uint64_t id, const TValue value) {
|
||||
assure_block(block(id));
|
||||
m_dense_blocks[block(id)][offset(id)] = value;
|
||||
}
|
||||
|
||||
TValue get_dense(const uint64_t id) const noexcept {
|
||||
if (m_dense_blocks.size() <= block(id) || m_dense_blocks[block(id)].empty()) {
|
||||
return osmium::index::empty_value<TValue>();
|
||||
}
|
||||
return m_dense_blocks[block(id)][offset(id)];
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Create FlexMem index.
|
||||
*
|
||||
* @param use_dense Usually FlexMem indexes start out as sparse
|
||||
* indexes and will switch to dense when they
|
||||
* think it is better. Set this to force dense
|
||||
* indexing from the start. This is usually
|
||||
* only useful for testing.
|
||||
*/
|
||||
explicit FlexMem(bool use_dense = false) :
|
||||
m_dense(use_dense) {
|
||||
}
|
||||
|
||||
~FlexMem() noexcept final = default;
|
||||
|
||||
bool is_dense() const noexcept {
|
||||
return m_dense;
|
||||
}
|
||||
|
||||
std::size_t size() const noexcept final {
|
||||
if (m_dense) {
|
||||
return m_dense_blocks.size() * block_size;
|
||||
}
|
||||
return m_sparse_entries.size();
|
||||
}
|
||||
|
||||
std::size_t used_memory() const noexcept final {
|
||||
return sizeof(FlexMem) +
|
||||
m_sparse_entries.size() * sizeof(entry) +
|
||||
m_dense_blocks.size() * (block_size * sizeof(TValue) + sizeof(std::vector<TValue>));
|
||||
}
|
||||
|
||||
void set(const TId id, const TValue value) final {
|
||||
if (m_dense) {
|
||||
set_dense(id, value);
|
||||
} else {
|
||||
set_sparse(id, value);
|
||||
}
|
||||
}
|
||||
|
||||
TValue get_noexcept(const TId id) const noexcept final {
|
||||
if (m_dense) {
|
||||
return get_dense(id);
|
||||
}
|
||||
return get_sparse(id);
|
||||
}
|
||||
|
||||
TValue get(const TId id) const final {
|
||||
const auto value = get_noexcept(id);
|
||||
if (value == osmium::index::empty_value<TValue>()) {
|
||||
throw osmium::not_found{id};
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
void clear() final {
|
||||
m_sparse_entries.clear();
|
||||
m_sparse_entries.shrink_to_fit();
|
||||
m_dense_blocks.clear();
|
||||
m_dense_blocks.shrink_to_fit();
|
||||
m_max_id = 0;
|
||||
m_dense = false;
|
||||
}
|
||||
|
||||
void sort() final {
|
||||
std::sort(m_sparse_entries.begin(), m_sparse_entries.end());
|
||||
}
|
||||
|
||||
/**
|
||||
* Switch from using a sparse to a dense index. Usually you
|
||||
* do not need to call this, because the FlexMem class will
|
||||
* do this automatically if it thinks the dense index is more
|
||||
* efficient.
|
||||
*
|
||||
* Does nothing if the index is already in dense mode.
|
||||
*/
|
||||
void switch_to_dense() {
|
||||
if (m_dense) {
|
||||
return;
|
||||
}
|
||||
for (const auto entry : m_sparse_entries) {
|
||||
set_dense(entry.id, entry.value);
|
||||
}
|
||||
m_sparse_entries.clear();
|
||||
m_sparse_entries.shrink_to_fit();
|
||||
m_max_id = 0;
|
||||
m_dense = true;
|
||||
}
|
||||
|
||||
std::pair<std::size_t, std::size_t> stats() const noexcept {
|
||||
std::size_t used_blocks = 0;
|
||||
std::size_t empty_blocks = 0;
|
||||
|
||||
for (const auto& block : m_dense_blocks) {
|
||||
if (block.empty()) {
|
||||
++empty_blocks;
|
||||
} else {
|
||||
++used_blocks;
|
||||
}
|
||||
}
|
||||
|
||||
return std::make_pair(used_blocks, empty_blocks);
|
||||
}
|
||||
|
||||
}; // class FlexMem
|
||||
|
||||
} // namespace map
|
||||
|
||||
} // namespace index
|
||||
|
||||
} // namespace osmium
|
||||
|
||||
#ifdef OSMIUM_WANT_NODE_LOCATION_MAPS
|
||||
REGISTER_MAP(osmium::unsigned_object_id_type, osmium::Location, osmium::index::map::FlexMem, flex_mem)
|
||||
#endif
|
||||
|
||||
#endif // OSMIUM_INDEX_MAP_FLEX_MEM_HPP
|
@ -64,4 +64,8 @@ namespace osmium {
|
||||
|
||||
} // namespace osmium
|
||||
|
||||
#ifdef OSMIUM_WANT_NODE_LOCATION_MAPS
|
||||
REGISTER_MAP(osmium::unsigned_object_id_type, osmium::Location, osmium::index::map::SparseFileArray, sparse_file_array)
|
||||
#endif
|
||||
|
||||
#endif // OSMIUM_INDEX_MAP_SPARSE_FILE_ARRAY_HPP
|
||||
|
@ -57,4 +57,8 @@ namespace osmium {
|
||||
|
||||
} // namespace osmium
|
||||
|
||||
#ifdef OSMIUM_WANT_NODE_LOCATION_MAPS
|
||||
REGISTER_MAP(osmium::unsigned_object_id_type, osmium::Location, osmium::index::map::SparseMemArray, sparse_mem_array)
|
||||
#endif
|
||||
|
||||
#endif // OSMIUM_INDEX_MAP_SPARSE_MEM_ARRAY_HPP
|
||||
|
@ -120,4 +120,8 @@ namespace osmium {
|
||||
|
||||
} // namespace osmium
|
||||
|
||||
#ifdef OSMIUM_WANT_NODE_LOCATION_MAPS
|
||||
REGISTER_MAP(osmium::unsigned_object_id_type, osmium::Location, osmium::index::map::SparseMemMap, sparse_mem_map)
|
||||
#endif
|
||||
|
||||
#endif // OSMIUM_INDEX_MAP_SPARSE_MEM_MAP_HPP
|
||||
|
@ -150,6 +150,10 @@ namespace osmium {
|
||||
|
||||
} // namespace osmium
|
||||
|
||||
#ifdef OSMIUM_WANT_NODE_LOCATION_MAPS
|
||||
REGISTER_MAP(osmium::unsigned_object_id_type, osmium::Location, osmium::index::map::SparseMemTable, sparse_mem_table)
|
||||
#endif
|
||||
|
||||
#endif // OSMIUM_WITH_SPARSEHASH
|
||||
|
||||
#endif // OSMIUM_INDEX_BYID_SPARSE_MEM_TABLE_HPP
|
||||
#endif // OSMIUM_INDEX_MAP_SPARSE_MEM_TABLE_HPP
|
||||
|
@ -55,6 +55,10 @@ namespace osmium {
|
||||
|
||||
} // namespace osmium
|
||||
|
||||
#ifdef OSMIUM_WANT_NODE_LOCATION_MAPS
|
||||
REGISTER_MAP(osmium::unsigned_object_id_type, osmium::Location, osmium::index::map::SparseMmapArray, sparse_mmap_array)
|
||||
#endif
|
||||
|
||||
#endif // __linux__
|
||||
|
||||
#endif // OSMIUM_INDEX_MAP_SPARSE_MMAP_ARRAY_HPP
|
||||
|
@ -35,6 +35,8 @@ DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#include <osmium/index/map.hpp> // IWYU pragma: keep
|
||||
|
||||
#define OSMIUM_WANT_NODE_LOCATION_MAPS
|
||||
|
||||
#ifdef OSMIUM_HAS_INDEX_MAP_DENSE_FILE_ARRAY
|
||||
REGISTER_MAP(osmium::unsigned_object_id_type, osmium::Location, osmium::index::map::DenseFileArray, dense_file_array)
|
||||
#endif
|
||||
@ -67,4 +69,8 @@ DEALINGS IN THE SOFTWARE.
|
||||
REGISTER_MAP(osmium::unsigned_object_id_type, osmium::Location, osmium::index::map::SparseMmapArray, sparse_mmap_array)
|
||||
#endif
|
||||
|
||||
#ifdef OSMIUM_HAS_INDEX_MAP_FLEX_MEM
|
||||
REGISTER_MAP(osmium::unsigned_object_id_type, osmium::Location, osmium::index::map::FlexMem, flex_mem)
|
||||
#endif
|
||||
|
||||
#endif // OSMIUM_INDEX_NODE_LOCATIONS_MAP_HPP
|
||||
|
59
third_party/libosmium/include/osmium/index/nwr_array.hpp
vendored
Normal file
59
third_party/libosmium/include/osmium/index/nwr_array.hpp
vendored
Normal file
@ -0,0 +1,59 @@
|
||||
#ifndef OSMIUM_INDEX_NWR_ARRAY_HPP
|
||||
#define OSMIUM_INDEX_NWR_ARRAY_HPP
|
||||
|
||||
/*
|
||||
|
||||
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||
|
||||
Copyright 2013-2017 Jochen Topf <jochen@topf.org> and others (see README).
|
||||
|
||||
Boost Software License - Version 1.0 - August 17th, 2003
|
||||
|
||||
Permission is hereby granted, free of charge, to any person or organization
|
||||
obtaining a copy of the software and accompanying documentation covered by
|
||||
this license (the "Software") to use, reproduce, display, distribute,
|
||||
execute, and transmit the Software, and to prepare derivative works of the
|
||||
Software, and to permit third-parties to whom the Software is furnished to
|
||||
do so, all subject to the following:
|
||||
|
||||
The copyright notices in the Software and this entire statement, including
|
||||
the above license grant, this restriction and the following disclaimer,
|
||||
must be included in all copies of the Software, in whole or in part, and
|
||||
all derivative works of the Software, unless such copies or derivative
|
||||
works are solely in the form of machine-executable object code generated by
|
||||
a source language processor.
|
||||
|
||||
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, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
#include <osmium/osm/item_type.hpp>
|
||||
|
||||
namespace osmium {
|
||||
|
||||
template <typename T>
|
||||
class nwr_array {
|
||||
|
||||
T m_sets[3];
|
||||
|
||||
public:
|
||||
|
||||
T& operator()(osmium::item_type type) noexcept {
|
||||
return m_sets[osmium::item_type_to_nwr_index(type)];
|
||||
}
|
||||
|
||||
const T& operator()(osmium::item_type type) const noexcept {
|
||||
return m_sets[osmium::item_type_to_nwr_index(type)];
|
||||
}
|
||||
|
||||
}; // class nwr_array
|
||||
|
||||
} // namespace osmium
|
||||
|
||||
#endif // OSMIUM_INDEX_NWR_ARRAY_HPP
|
@ -35,10 +35,14 @@ DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <tuple>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include <osmium/osm/item_type.hpp>
|
||||
#include <osmium/osm/relation.hpp>
|
||||
#include <osmium/osm/types.hpp>
|
||||
|
||||
@ -91,6 +95,24 @@ namespace osmium {
|
||||
m_map.emplace_back(key, value);
|
||||
}
|
||||
|
||||
typename std::enable_if<std::is_same<TKey, TValue>::value>::type flip_in_place() {
|
||||
for (auto& p : m_map) {
|
||||
using std::swap;
|
||||
swap(p.key, p.value);
|
||||
}
|
||||
}
|
||||
|
||||
flat_map<TValue, TValueInternal, TKey, TKeyInternal> flip_copy() {
|
||||
flat_map<TValue, TValueInternal, TKey, TKeyInternal> map;
|
||||
map.reserve(m_map.size());
|
||||
|
||||
for (const auto& p : m_map) {
|
||||
map.set(p.value, p.key);
|
||||
}
|
||||
|
||||
return map;
|
||||
}
|
||||
|
||||
void sort_unique() {
|
||||
std::sort(m_map.begin(), m_map.end());
|
||||
const auto last = std::unique(m_map.begin(), m_map.end());
|
||||
@ -107,19 +129,25 @@ namespace osmium {
|
||||
return m_map.empty();
|
||||
}
|
||||
|
||||
size_t size() const noexcept {
|
||||
std::size_t size() const noexcept {
|
||||
return m_map.size();
|
||||
}
|
||||
|
||||
void reserve(std::size_t size) {
|
||||
m_map.reserve(size);
|
||||
}
|
||||
|
||||
}; // class flat_map
|
||||
|
||||
} // namespace detail
|
||||
|
||||
/**
|
||||
* Index for looking up parent relation IDs given a member relation ID.
|
||||
* Index for looking up parent relation IDs given a member relation ID
|
||||
* or the other way around.
|
||||
*
|
||||
* You can not instantiate such an index yourself, instead you need to
|
||||
* instantiate a RelationsMapStash, fill it and then create an index from
|
||||
* it:
|
||||
* instantiate a RelationsMapStash, fill it and then create an index
|
||||
* from it:
|
||||
*
|
||||
* @code
|
||||
* RelationsMapStash stash;
|
||||
@ -128,10 +156,10 @@ namespace osmium {
|
||||
* stash.add_members(relation);
|
||||
* }
|
||||
* ...
|
||||
* const auto index = stash.build_index();
|
||||
* const auto index = stash.build_member_to_parent_index();
|
||||
* ...
|
||||
* osmium::unsigned_object_id_type member_id = ...;
|
||||
* index.for_each_parent(member_id, [](osmium::unsigned_object_id_type id) {
|
||||
* index.for_each(member_id, [](osmium::unsigned_object_id_type parent_id) {
|
||||
* ...
|
||||
* });
|
||||
* ...
|
||||
@ -141,13 +169,14 @@ namespace osmium {
|
||||
class RelationsMapIndex {
|
||||
|
||||
friend class RelationsMapStash;
|
||||
friend class RelationsMapIndexes;
|
||||
|
||||
using map_type = detail::flat_map<osmium::unsigned_object_id_type, uint32_t,
|
||||
osmium::unsigned_object_id_type, uint32_t>;
|
||||
|
||||
map_type m_map;
|
||||
|
||||
RelationsMapIndex(map_type&& map) :
|
||||
explicit RelationsMapIndex(map_type&& map) :
|
||||
m_map(std::move(map)) {
|
||||
}
|
||||
|
||||
@ -162,8 +191,8 @@ namespace osmium {
|
||||
RelationsMapIndex& operator=(RelationsMapIndex&&) = default;
|
||||
|
||||
/**
|
||||
* Find the given relation id in the index and call the given function
|
||||
* with all parent relation ids.
|
||||
* Find the given relation id in the index and call the given
|
||||
* function with all parent relation ids.
|
||||
*
|
||||
* @code
|
||||
* osmium::unsigned_object_id_type member_id = 17;
|
||||
@ -172,14 +201,38 @@ namespace osmium {
|
||||
* });
|
||||
* @endcode
|
||||
*
|
||||
* @deprecated Use for_each() instead.
|
||||
*
|
||||
* Complexity: Logarithmic in the number of elements in the index.
|
||||
* (Lookup uses binary search.)
|
||||
*/
|
||||
template <typename Func>
|
||||
void for_each_parent(osmium::unsigned_object_id_type member_id, Func&& func) const {
|
||||
template <typename TFunc>
|
||||
void for_each_parent(osmium::unsigned_object_id_type member_id, TFunc&& func) const {
|
||||
const auto parents = m_map.get(member_id);
|
||||
for (auto it = parents.first; it != parents.second; ++it) {
|
||||
std::forward<Func>(func)(it->value);
|
||||
std::forward<TFunc>(func)(it->value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the given relation id in the index and call the given
|
||||
* function with all related relation ids.
|
||||
*
|
||||
* @code
|
||||
* osmium::unsigned_object_id_type id = 17;
|
||||
* index.for_each(id, [](osmium::unsigned_object_id_type rid) {
|
||||
* ...
|
||||
* });
|
||||
* @endcode
|
||||
*
|
||||
* Complexity: Logarithmic in the number of elements in the index.
|
||||
* (Lookup uses binary search.)
|
||||
*/
|
||||
template <typename TFunc>
|
||||
void for_each(osmium::unsigned_object_id_type id, TFunc&& func) const {
|
||||
const auto parents = m_map.get(id);
|
||||
for (auto it = parents.first; it != parents.second; ++it) {
|
||||
std::forward<TFunc>(func)(it->value);
|
||||
}
|
||||
}
|
||||
|
||||
@ -197,16 +250,58 @@ namespace osmium {
|
||||
*
|
||||
* Complexity: Constant.
|
||||
*/
|
||||
size_t size() const noexcept {
|
||||
std::size_t size() const noexcept {
|
||||
return m_map.size();
|
||||
}
|
||||
|
||||
}; // RelationsMapIndex
|
||||
}; // class RelationsMapIndex
|
||||
|
||||
class RelationsMapIndexes {
|
||||
|
||||
friend class RelationsMapStash;
|
||||
|
||||
RelationsMapIndex m_member_to_parent;
|
||||
RelationsMapIndex m_parent_to_member;
|
||||
|
||||
RelationsMapIndexes(RelationsMapIndex::map_type&& map1, RelationsMapIndex::map_type&& map2) :
|
||||
m_member_to_parent(std::move(map1)),
|
||||
m_parent_to_member(std::move(map2)) {
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
const RelationsMapIndex& member_to_parent() const noexcept {
|
||||
return m_member_to_parent;
|
||||
}
|
||||
|
||||
const RelationsMapIndex& parent_to_member() const noexcept {
|
||||
return m_parent_to_member;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is this index empty?
|
||||
*
|
||||
* Complexity: Constant.
|
||||
*/
|
||||
bool empty() const noexcept {
|
||||
return m_member_to_parent.empty();
|
||||
}
|
||||
|
||||
/**
|
||||
* How many entries are in this index?
|
||||
*
|
||||
* Complexity: Constant.
|
||||
*/
|
||||
std::size_t size() const noexcept {
|
||||
return m_member_to_parent.size();
|
||||
}
|
||||
|
||||
}; // class RelationsMapIndexes
|
||||
|
||||
/**
|
||||
* The RelationsMapStash is used to build up the data needed to create
|
||||
* an index of member relation ID to parent relation ID. See the
|
||||
* RelationsMapIndex class for more.
|
||||
* an index of member relation ID to parent relation ID or the other
|
||||
* way around. See the RelationsMapIndex class for more.
|
||||
*/
|
||||
class RelationsMapStash {
|
||||
|
||||
@ -264,15 +359,18 @@ namespace osmium {
|
||||
*
|
||||
* Complexity: Constant.
|
||||
*/
|
||||
size_t size() const noexcept {
|
||||
std::size_t size() const noexcept {
|
||||
assert(m_valid && "You can't use the RelationsMap any more after calling build_index()");
|
||||
return m_map.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Build an index with the contents of this stash and return it.
|
||||
* Build an index for member to parent lookups from the contents
|
||||
* of this stash and return it.
|
||||
*
|
||||
* After you get the index you can not use the stash any more!
|
||||
*
|
||||
* @deprecated Use build_member_to_parent_index() instead.
|
||||
*/
|
||||
RelationsMapIndex build_index() {
|
||||
assert(m_valid && "You can't use the RelationsMap any more after calling build_index()");
|
||||
@ -283,6 +381,54 @@ namespace osmium {
|
||||
return RelationsMapIndex{std::move(m_map)};
|
||||
}
|
||||
|
||||
/**
|
||||
* Build an index for member to parent lookups from the contents
|
||||
* of this stash and return it.
|
||||
*
|
||||
* After you get the index you can not use the stash any more!
|
||||
*/
|
||||
RelationsMapIndex build_member_to_parent_index() {
|
||||
assert(m_valid && "You can't use the RelationsMap any more after calling build_member_to_parent_index()");
|
||||
m_map.sort_unique();
|
||||
#ifndef NDEBUG
|
||||
m_valid = false;
|
||||
#endif
|
||||
return RelationsMapIndex{std::move(m_map)};
|
||||
}
|
||||
|
||||
/**
|
||||
* Build an index for parent to member lookups from the contents
|
||||
* of this stash and return it.
|
||||
*
|
||||
* After you get the index you can not use the stash any more!
|
||||
*/
|
||||
RelationsMapIndex build_parent_to_member_index() {
|
||||
assert(m_valid && "You can't use the RelationsMap any more after calling build_parent_to_member_index()");
|
||||
m_map.flip_in_place();
|
||||
m_map.sort_unique();
|
||||
#ifndef NDEBUG
|
||||
m_valid = false;
|
||||
#endif
|
||||
return RelationsMapIndex{std::move(m_map)};
|
||||
}
|
||||
|
||||
/**
|
||||
* Build indexes for member-to-parent and parent-to-member lookups
|
||||
* from the contents of this stash and return them.
|
||||
*
|
||||
* After you get the index you can not use the stash any more!
|
||||
*/
|
||||
RelationsMapIndexes build_indexes() {
|
||||
assert(m_valid && "You can't use the RelationsMap any more after calling build_indexes()");
|
||||
auto reverse_map = m_map.flip_copy();
|
||||
reverse_map.sort_unique();
|
||||
m_map.sort_unique();
|
||||
#ifndef NDEBUG
|
||||
m_valid = false;
|
||||
#endif
|
||||
return RelationsMapIndexes{std::move(m_map), std::move(reverse_map)};
|
||||
}
|
||||
|
||||
}; // class RelationsMapStash
|
||||
|
||||
} // namespace index
|
||||
|
@ -85,7 +85,7 @@ namespace osmium {
|
||||
namespace detail {
|
||||
|
||||
OSMIUM_NORETURN inline void throw_bzip2_error(BZFILE* bzfile, const char* msg, int bzlib_error = 0) {
|
||||
std::string error("bzip2 error: ");
|
||||
std::string error{"bzip2 error: "};
|
||||
error += msg;
|
||||
error += ": ";
|
||||
int errnum = bzlib_error;
|
||||
@ -94,7 +94,7 @@ namespace osmium {
|
||||
} else {
|
||||
error += ::BZ2_bzerror(bzfile, &errnum);
|
||||
}
|
||||
throw osmium::bzip2_error(error, errnum);
|
||||
throw osmium::bzip2_error{error, errnum};
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
@ -143,7 +143,7 @@ namespace osmium {
|
||||
osmium::io::detail::reliable_fsync(::fileno(m_file));
|
||||
}
|
||||
if (fclose(m_file) != 0) {
|
||||
throw std::system_error(errno, std::system_category(), "Close failed");
|
||||
throw std::system_error{errno, std::system_category(), "Close failed"};
|
||||
}
|
||||
}
|
||||
if (error != BZ_OK) {
|
||||
@ -187,7 +187,7 @@ namespace osmium {
|
||||
if (!m_stream_end) {
|
||||
buffer.resize(osmium::io::Decompressor::input_buffer_size);
|
||||
int error;
|
||||
int nread = ::BZ2_bzRead(&error, m_bzfile, const_cast<char*>(buffer.data()), static_cast_with_assert<int>(buffer.size()));
|
||||
const int nread = ::BZ2_bzRead(&error, m_bzfile, const_cast<char*>(buffer.data()), static_cast_with_assert<int>(buffer.size()));
|
||||
if (error != BZ_OK && error != BZ_STREAM_END) {
|
||||
detail::throw_bzip2_error(m_bzfile, "read failed", error);
|
||||
}
|
||||
@ -227,7 +227,7 @@ namespace osmium {
|
||||
m_bzfile = nullptr;
|
||||
if (m_file) {
|
||||
if (fclose(m_file) != 0) {
|
||||
throw std::system_error(errno, std::system_category(), "Close failed");
|
||||
throw std::system_error{errno, std::system_category(), "Close failed"};
|
||||
}
|
||||
}
|
||||
if (error != BZ_OK) {
|
||||
@ -252,10 +252,10 @@ namespace osmium {
|
||||
m_bzstream() {
|
||||
m_bzstream.next_in = const_cast<char*>(buffer);
|
||||
m_bzstream.avail_in = static_cast_with_assert<unsigned int>(size);
|
||||
int result = BZ2_bzDecompressInit(&m_bzstream, 0, 0);
|
||||
const int result = BZ2_bzDecompressInit(&m_bzstream, 0, 0);
|
||||
if (result != BZ_OK) {
|
||||
std::string message("bzip2 error: decompression init failed: ");
|
||||
throw bzip2_error(message, result);
|
||||
std::string message{"bzip2 error: decompression init failed: "};
|
||||
throw bzip2_error{message, result};
|
||||
}
|
||||
}
|
||||
|
||||
@ -275,7 +275,7 @@ namespace osmium {
|
||||
output.resize(buffer_size);
|
||||
m_bzstream.next_out = const_cast<char*>(output.data());
|
||||
m_bzstream.avail_out = buffer_size;
|
||||
int result = BZ2_bzDecompress(&m_bzstream);
|
||||
const int result = BZ2_bzDecompress(&m_bzstream);
|
||||
|
||||
if (result != BZ_OK) {
|
||||
m_buffer = nullptr;
|
||||
@ -283,8 +283,8 @@ namespace osmium {
|
||||
}
|
||||
|
||||
if (result != BZ_OK && result != BZ_STREAM_END) {
|
||||
std::string message("bzip2 error: decompress failed: ");
|
||||
throw bzip2_error(message, result);
|
||||
std::string message{"bzip2 error: decompress failed: "};
|
||||
throw bzip2_error{message, result};
|
||||
}
|
||||
|
||||
output.resize(static_cast<unsigned long>(m_bzstream.next_out - output.data()));
|
||||
@ -304,9 +304,9 @@ namespace osmium {
|
||||
// we want the register_compression() function to run, setting
|
||||
// the variable is only a side-effect, it will never be used
|
||||
const bool registered_bzip2_compression = osmium::io::CompressionFactory::instance().register_compression(osmium::io::file_compression::bzip2,
|
||||
[](int fd, fsync sync) { return new osmium::io::Bzip2Compressor(fd, sync); },
|
||||
[](int fd) { return new osmium::io::Bzip2Decompressor(fd); },
|
||||
[](const char* buffer, size_t size) { return new osmium::io::Bzip2BufferDecompressor(buffer, size); }
|
||||
[](int fd, fsync sync) { return new osmium::io::Bzip2Compressor{fd, sync}; },
|
||||
[](int fd) { return new osmium::io::Bzip2Decompressor{fd}; },
|
||||
[](const char* buffer, size_t size) { return new osmium::io::Bzip2BufferDecompressor{buffer, size}; }
|
||||
);
|
||||
|
||||
// dummy function to silence the unused variable warning from above
|
||||
|
@ -54,7 +54,6 @@ DEALINGS IN THE SOFTWARE.
|
||||
#include <osmium/io/error.hpp>
|
||||
#include <osmium/io/file_compression.hpp>
|
||||
#include <osmium/io/writer_options.hpp>
|
||||
#include <osmium/util/compatibility.hpp>
|
||||
#include <osmium/util/file.hpp>
|
||||
|
||||
namespace osmium {
|
||||
@ -77,8 +76,7 @@ namespace osmium {
|
||||
m_fsync(sync) {
|
||||
}
|
||||
|
||||
virtual ~Compressor() noexcept {
|
||||
}
|
||||
virtual ~Compressor() noexcept = default;
|
||||
|
||||
virtual void write(const std::string& data) = 0;
|
||||
|
||||
@ -88,8 +86,8 @@ namespace osmium {
|
||||
|
||||
class Decompressor {
|
||||
|
||||
std::atomic<size_t> m_file_size {0};
|
||||
std::atomic<size_t> m_offset {0};
|
||||
std::atomic<std::size_t> m_file_size{0};
|
||||
std::atomic<std::size_t> m_offset{0};
|
||||
|
||||
public:
|
||||
|
||||
@ -103,26 +101,25 @@ namespace osmium {
|
||||
Decompressor(Decompressor&&) = delete;
|
||||
Decompressor& operator=(Decompressor&&) = delete;
|
||||
|
||||
virtual ~Decompressor() noexcept {
|
||||
}
|
||||
virtual ~Decompressor() noexcept = default;
|
||||
|
||||
virtual std::string read() = 0;
|
||||
|
||||
virtual void close() = 0;
|
||||
|
||||
size_t file_size() const noexcept {
|
||||
std::size_t file_size() const noexcept {
|
||||
return m_file_size;
|
||||
}
|
||||
|
||||
void set_file_size(size_t size) noexcept {
|
||||
void set_file_size(std::size_t size) noexcept {
|
||||
m_file_size = size;
|
||||
}
|
||||
|
||||
size_t offset() const noexcept {
|
||||
std::size_t offset() const noexcept {
|
||||
return m_offset;
|
||||
}
|
||||
|
||||
void set_offset(size_t offset) noexcept {
|
||||
void set_offset(std::size_t offset) noexcept {
|
||||
m_offset = offset;
|
||||
}
|
||||
|
||||
@ -141,7 +138,7 @@ namespace osmium {
|
||||
|
||||
using create_compressor_type = std::function<osmium::io::Compressor*(int, fsync)>;
|
||||
using create_decompressor_type_fd = std::function<osmium::io::Decompressor*(int)>;
|
||||
using create_decompressor_type_buffer = std::function<osmium::io::Decompressor*(const char*, size_t)>;
|
||||
using create_decompressor_type_buffer = std::function<osmium::io::Decompressor*(const char*, std::size_t)>;
|
||||
|
||||
private:
|
||||
|
||||
@ -187,10 +184,10 @@ namespace osmium {
|
||||
create_decompressor_type_fd create_decompressor_fd,
|
||||
create_decompressor_type_buffer create_decompressor_buffer) {
|
||||
|
||||
compression_map_type::value_type cc(compression,
|
||||
compression_map_type::value_type cc{compression,
|
||||
std::make_tuple(create_compressor,
|
||||
create_decompressor_fd,
|
||||
create_decompressor_buffer));
|
||||
create_decompressor_buffer)};
|
||||
|
||||
return m_callbacks.insert(cc).second;
|
||||
}
|
||||
@ -208,7 +205,7 @@ namespace osmium {
|
||||
return p;
|
||||
}
|
||||
|
||||
std::unique_ptr<osmium::io::Decompressor> create_decompressor(osmium::io::file_compression compression, const char* buffer, size_t size) const {
|
||||
std::unique_ptr<osmium::io::Decompressor> create_decompressor(osmium::io::file_compression compression, const char* buffer, std::size_t size) const {
|
||||
const auto callbacks = find_callbacks(compression);
|
||||
return std::unique_ptr<osmium::io::Decompressor>(std::get<2>(callbacks)(buffer, size));
|
||||
}
|
||||
@ -240,7 +237,7 @@ namespace osmium {
|
||||
|
||||
void close() final {
|
||||
if (m_fd >= 0) {
|
||||
int fd = m_fd;
|
||||
const int fd = m_fd;
|
||||
m_fd = -1;
|
||||
if (do_fsync()) {
|
||||
osmium::io::detail::reliable_fsync(fd);
|
||||
@ -255,8 +252,8 @@ namespace osmium {
|
||||
|
||||
int m_fd;
|
||||
const char *m_buffer;
|
||||
size_t m_buffer_size;
|
||||
size_t m_offset = 0;
|
||||
std::size_t m_buffer_size;
|
||||
std::size_t m_offset = 0;
|
||||
|
||||
public:
|
||||
|
||||
@ -267,7 +264,7 @@ namespace osmium {
|
||||
m_buffer_size(0) {
|
||||
}
|
||||
|
||||
NoDecompressor(const char* buffer, size_t size) :
|
||||
NoDecompressor(const char* buffer, std::size_t size) :
|
||||
Decompressor(),
|
||||
m_fd(-1),
|
||||
m_buffer(buffer),
|
||||
@ -287,15 +284,15 @@ namespace osmium {
|
||||
|
||||
if (m_buffer) {
|
||||
if (m_buffer_size != 0) {
|
||||
size_t size = m_buffer_size;
|
||||
const std::size_t size = m_buffer_size;
|
||||
m_buffer_size = 0;
|
||||
buffer.append(m_buffer, size);
|
||||
}
|
||||
} else {
|
||||
buffer.resize(osmium::io::Decompressor::input_buffer_size);
|
||||
auto nread = ::read(m_fd, const_cast<char*>(buffer.data()), osmium::io::Decompressor::input_buffer_size);
|
||||
const auto nread = ::read(m_fd, const_cast<char*>(buffer.data()), osmium::io::Decompressor::input_buffer_size);
|
||||
if (nread < 0) {
|
||||
throw std::system_error(errno, std::system_category(), "Read failed");
|
||||
throw std::system_error{errno, std::system_category(), "Read failed"};
|
||||
}
|
||||
buffer.resize(std::string::size_type(nread));
|
||||
}
|
||||
@ -308,7 +305,7 @@ namespace osmium {
|
||||
|
||||
void close() final {
|
||||
if (m_fd >= 0) {
|
||||
int fd = m_fd;
|
||||
const int fd = m_fd;
|
||||
m_fd = -1;
|
||||
osmium::io::detail::reliable_close(fd);
|
||||
}
|
||||
@ -321,9 +318,9 @@ namespace osmium {
|
||||
// we want the register_compression() function to run, setting
|
||||
// the variable is only a side-effect, it will never be used
|
||||
const bool registered_no_compression = osmium::io::CompressionFactory::instance().register_compression(osmium::io::file_compression::none,
|
||||
[](int fd, fsync sync) { return new osmium::io::NoCompressor(fd, sync); },
|
||||
[](int fd) { return new osmium::io::NoDecompressor(fd); },
|
||||
[](const char* buffer, size_t size) { return new osmium::io::NoDecompressor(buffer, size); }
|
||||
[](int fd, fsync sync) { return new osmium::io::NoCompressor{fd, sync}; },
|
||||
[](int fd) { return new osmium::io::NoDecompressor{fd}; },
|
||||
[](const char* buffer, std::size_t size) { return new osmium::io::NoDecompressor{buffer, size}; }
|
||||
);
|
||||
|
||||
// dummy function to silence the unused variable warning from above
|
||||
|
@ -282,15 +282,16 @@ namespace osmium {
|
||||
|
||||
void write_box(const osmium::Box& box) {
|
||||
write_fieldname("box l/b/r/t");
|
||||
if (!box) {
|
||||
if (box.bottom_left().is_undefined() &&
|
||||
box.top_right().is_undefined()) {
|
||||
write_error("BOX NOT SET!\n");
|
||||
return;
|
||||
}
|
||||
const auto& bl = box.bottom_left();
|
||||
const auto& tr = box.top_right();
|
||||
bl.as_string(std::back_inserter(*m_out));
|
||||
bl.as_string_without_check(std::back_inserter(*m_out));
|
||||
*m_out += ' ';
|
||||
tr.as_string(std::back_inserter(*m_out));
|
||||
tr.as_string_without_check(std::back_inserter(*m_out));
|
||||
if (!box.valid()) {
|
||||
write_error(" INVALID BOX!");
|
||||
}
|
||||
@ -520,8 +521,8 @@ namespace osmium {
|
||||
|
||||
public:
|
||||
|
||||
DebugOutputFormat(const osmium::io::File& file, future_string_queue_type& output_queue) :
|
||||
OutputFormat(output_queue),
|
||||
DebugOutputFormat(osmium::thread::Pool& pool, const osmium::io::File& file, future_string_queue_type& output_queue) :
|
||||
OutputFormat(pool, output_queue),
|
||||
m_options() {
|
||||
m_options.add_metadata = file.is_not_false("add_metadata");
|
||||
m_options.use_color = file.is_true("color");
|
||||
@ -576,7 +577,7 @@ namespace osmium {
|
||||
}
|
||||
|
||||
void write_buffer(osmium::memory::Buffer&& buffer) final {
|
||||
m_output_queue.push(osmium::thread::Pool::instance().submit(DebugOutputBlock{std::move(buffer), m_options}));
|
||||
m_output_queue.push(m_pool.submit(DebugOutputBlock{std::move(buffer), m_options}));
|
||||
}
|
||||
|
||||
}; // class DebugOutputFormat
|
||||
@ -584,8 +585,8 @@ namespace osmium {
|
||||
// we want the register_output_format() function to run, setting
|
||||
// the variable is only a side-effect, it will never be used
|
||||
const bool registered_debug_output = osmium::io::detail::OutputFormatFactory::instance().register_output_format(osmium::io::file_format::debug,
|
||||
[](const osmium::io::File& file, future_string_queue_type& output_queue) {
|
||||
return new osmium::io::detail::DebugOutputFormat(file, output_queue);
|
||||
[](osmium::thread::Pool& pool, const osmium::io::File& file, future_string_queue_type& output_queue) {
|
||||
return new osmium::io::detail::DebugOutputFormat(pool, file, output_queue);
|
||||
});
|
||||
|
||||
// dummy function to silence the unused variable warning from above
|
||||
|
@ -48,6 +48,7 @@ DEALINGS IN THE SOFTWARE.
|
||||
#include <osmium/io/header.hpp>
|
||||
#include <osmium/memory/buffer.hpp>
|
||||
#include <osmium/osm/entity_bits.hpp>
|
||||
#include <osmium/thread/pool.hpp>
|
||||
|
||||
namespace osmium {
|
||||
|
||||
@ -55,35 +56,37 @@ namespace osmium {
|
||||
|
||||
namespace detail {
|
||||
|
||||
struct reader_options {
|
||||
osmium::osm_entity_bits::type read_which_entities = osm_entity_bits::all;
|
||||
osmium::io::read_meta read_metadata = read_meta::yes;
|
||||
struct parser_arguments {
|
||||
osmium::thread::Pool& pool;
|
||||
future_string_queue_type& input_queue;
|
||||
future_buffer_queue_type& output_queue;
|
||||
std::promise<osmium::io::Header>& header_promise;
|
||||
osmium::osm_entity_bits::type read_which_entities;
|
||||
osmium::io::read_meta read_metadata;
|
||||
};
|
||||
|
||||
class Parser {
|
||||
|
||||
osmium::thread::Pool& m_pool;
|
||||
future_buffer_queue_type& m_output_queue;
|
||||
std::promise<osmium::io::Header>& m_header_promise;
|
||||
queue_wrapper<std::string> m_input_queue;
|
||||
reader_options m_options;
|
||||
osmium::osm_entity_bits::type m_read_which_entities;
|
||||
osmium::io::read_meta m_read_metadata;
|
||||
bool m_header_is_done;
|
||||
|
||||
protected:
|
||||
|
||||
std::string get_input() {
|
||||
return m_input_queue.pop();
|
||||
}
|
||||
|
||||
bool input_done() const {
|
||||
return m_input_queue.has_reached_end_of_data();
|
||||
osmium::thread::Pool& get_pool() {
|
||||
return m_pool;
|
||||
}
|
||||
|
||||
osmium::osm_entity_bits::type read_types() const noexcept {
|
||||
return m_options.read_which_entities;
|
||||
return m_read_which_entities;
|
||||
}
|
||||
|
||||
osmium::io::read_meta read_metadata() const noexcept {
|
||||
return m_options.read_metadata;
|
||||
return m_read_metadata;
|
||||
}
|
||||
|
||||
bool header_is_done() const noexcept {
|
||||
@ -117,14 +120,13 @@ namespace osmium {
|
||||
|
||||
public:
|
||||
|
||||
Parser(future_string_queue_type& input_queue,
|
||||
future_buffer_queue_type& output_queue,
|
||||
std::promise<osmium::io::Header>& header_promise,
|
||||
osmium::io::detail::reader_options options) :
|
||||
m_output_queue(output_queue),
|
||||
m_header_promise(header_promise),
|
||||
m_input_queue(input_queue),
|
||||
m_options(options),
|
||||
explicit Parser(parser_arguments& args) :
|
||||
m_pool(args.pool),
|
||||
m_output_queue(args.output_queue),
|
||||
m_header_promise(args.header_promise),
|
||||
m_input_queue(args.input_queue),
|
||||
m_read_which_entities(args.read_which_entities),
|
||||
m_read_metadata(args.read_metadata),
|
||||
m_header_is_done(false) {
|
||||
}
|
||||
|
||||
@ -138,6 +140,14 @@ namespace osmium {
|
||||
|
||||
virtual void run() = 0;
|
||||
|
||||
std::string get_input() {
|
||||
return m_input_queue.pop();
|
||||
}
|
||||
|
||||
bool input_done() const {
|
||||
return m_input_queue.has_reached_end_of_data();
|
||||
}
|
||||
|
||||
void parse() {
|
||||
try {
|
||||
run();
|
||||
@ -163,10 +173,7 @@ namespace osmium {
|
||||
|
||||
public:
|
||||
|
||||
using create_parser_type = std::function<std::unique_ptr<Parser>(future_string_queue_type&,
|
||||
future_buffer_queue_type&,
|
||||
std::promise<osmium::io::Header>& header_promise,
|
||||
osmium::io::detail::reader_options options)>;
|
||||
using create_parser_type = std::function<std::unique_ptr<Parser>(parser_arguments&)>;
|
||||
|
||||
private:
|
||||
|
||||
@ -185,22 +192,20 @@ namespace osmium {
|
||||
return factory;
|
||||
}
|
||||
|
||||
bool register_parser(osmium::io::file_format format, create_parser_type create_function) {
|
||||
if (! m_callbacks.insert(map_type::value_type(format, create_function)).second) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
bool register_parser(osmium::io::file_format format, create_parser_type&& create_function) {
|
||||
const auto result = m_callbacks.emplace(format, std::forward<create_parser_type>(create_function));
|
||||
return result.second;
|
||||
}
|
||||
|
||||
create_parser_type get_creator_function(const osmium::io::File& file) {
|
||||
auto it = m_callbacks.find(file.format());
|
||||
create_parser_type get_creator_function(const osmium::io::File& file) const {
|
||||
const auto it = m_callbacks.find(file.format());
|
||||
if (it == m_callbacks.end()) {
|
||||
throw unsupported_file_format_error(
|
||||
std::string("Can not open file '") +
|
||||
throw unsupported_file_format_error{
|
||||
std::string{"Can not open file '"} +
|
||||
file.filename() +
|
||||
"' with type '" +
|
||||
as_string(file.format()) +
|
||||
"'. No support for reading this format in this program.");
|
||||
"'. No support for reading this format in this program."};
|
||||
}
|
||||
return it->second;
|
||||
}
|
||||
|
@ -121,7 +121,7 @@ namespace osmium {
|
||||
current_entry = 0;
|
||||
}
|
||||
|
||||
void add(const char* string, size_t size) {
|
||||
void add(const char* string, std::size_t size) {
|
||||
if (m_table.empty()) {
|
||||
m_table.resize(entry_size * number_of_entries);
|
||||
}
|
||||
@ -162,7 +162,7 @@ namespace osmium {
|
||||
return protozero::decode_zigzag64(protozero::decode_varint(data, end));
|
||||
}
|
||||
|
||||
bool ensure_bytes_available(size_t need_bytes) {
|
||||
bool ensure_bytes_available(std::size_t need_bytes) {
|
||||
if ((m_end - m_data) >= long(need_bytes)) {
|
||||
return true;
|
||||
}
|
||||
@ -174,7 +174,7 @@ namespace osmium {
|
||||
m_input.erase(0, m_data - m_input.data());
|
||||
|
||||
while (m_input.size() < need_bytes) {
|
||||
std::string data = get_input();
|
||||
const std::string data{get_input()};
|
||||
if (input_done()) {
|
||||
return false;
|
||||
}
|
||||
@ -589,11 +589,8 @@ namespace osmium {
|
||||
|
||||
public:
|
||||
|
||||
O5mParser(future_string_queue_type& input_queue,
|
||||
future_buffer_queue_type& output_queue,
|
||||
std::promise<osmium::io::Header>& header_promise,
|
||||
osmium::io::detail::reader_options options) :
|
||||
Parser(input_queue, output_queue, header_promise, options),
|
||||
explicit O5mParser(parser_arguments& args) :
|
||||
Parser(args),
|
||||
m_header(),
|
||||
m_buffer(buffer_size),
|
||||
m_input(),
|
||||
@ -616,11 +613,8 @@ namespace osmium {
|
||||
// the variable is only a side-effect, it will never be used
|
||||
const bool registered_o5m_parser = ParserFactory::instance().register_parser(
|
||||
file_format::o5m,
|
||||
[](future_string_queue_type& input_queue,
|
||||
future_buffer_queue_type& output_queue,
|
||||
std::promise<osmium::io::Header>& header_promise,
|
||||
osmium::io::detail::reader_options options) {
|
||||
return std::unique_ptr<Parser>(new O5mParser(input_queue, output_queue, header_promise, options));
|
||||
[](parser_arguments& args) {
|
||||
return std::unique_ptr<Parser>(new O5mParser{args});
|
||||
});
|
||||
|
||||
// dummy function to silence the unused variable warning from above
|
||||
|
@ -33,19 +33,16 @@ DEALINGS IN THE SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
#include <cstdlib>
|
||||
#include <future>
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
#include <osmium/io/detail/input_format.hpp>
|
||||
#include <osmium/io/detail/opl_parser_functions.hpp>
|
||||
#include <osmium/io/detail/queue_util.hpp>
|
||||
#include <osmium/io/file_format.hpp>
|
||||
#include <osmium/io/header.hpp>
|
||||
#include <osmium/memory/buffer.hpp>
|
||||
#include <osmium/osm/entity_bits.hpp>
|
||||
#include <osmium/thread/util.hpp>
|
||||
|
||||
namespace osmium {
|
||||
@ -54,10 +51,56 @@ namespace osmium {
|
||||
|
||||
namespace detail {
|
||||
|
||||
// Feed data coming in blocks line by line to the OPL parser
|
||||
// function. This has been broken out of the OPLParser class
|
||||
// where it belongs into a standalone template function to be
|
||||
// better testable.
|
||||
template <typename T>
|
||||
void line_by_line(T& worker) {
|
||||
std::string rest;
|
||||
|
||||
while (!worker.input_done()) {
|
||||
std::string input{worker.get_input()};
|
||||
std::string::size_type ppos = 0;
|
||||
|
||||
if (!rest.empty()) {
|
||||
ppos = input.find_first_of("\n\r");
|
||||
if (ppos == std::string::npos) {
|
||||
rest.append(input);
|
||||
continue;
|
||||
}
|
||||
rest.append(input, 0, ppos);
|
||||
if (!rest.empty()) {
|
||||
worker.parse_line(rest.data());
|
||||
rest.clear();
|
||||
}
|
||||
++ppos;
|
||||
}
|
||||
|
||||
for (auto pos = input.find_first_of("\n\r", ppos);
|
||||
pos != std::string::npos;
|
||||
pos = input.find_first_of("\n\r", ppos)) {
|
||||
const char* data = &input[ppos];
|
||||
input[pos] = '\0';
|
||||
if (data[0] != '\0') {
|
||||
worker.parse_line(data);
|
||||
}
|
||||
ppos = pos + 1;
|
||||
if (ppos >= input.size()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
rest.assign(input, ppos, std::string::npos);
|
||||
}
|
||||
|
||||
if (!rest.empty()) {
|
||||
worker.parse_line(rest.data());
|
||||
}
|
||||
}
|
||||
|
||||
class OPLParser : public Parser {
|
||||
|
||||
osmium::memory::Buffer m_buffer{1024*1024};
|
||||
const char* m_data = nullptr;
|
||||
uint64_t m_line_count = 0;
|
||||
|
||||
void maybe_flush() {
|
||||
@ -70,63 +113,26 @@ namespace osmium {
|
||||
}
|
||||
}
|
||||
|
||||
void parse_line() {
|
||||
if (opl_parse_line(m_line_count, m_data, m_buffer, read_types())) {
|
||||
maybe_flush();
|
||||
}
|
||||
++m_line_count;
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
OPLParser(future_string_queue_type& input_queue,
|
||||
future_buffer_queue_type& output_queue,
|
||||
std::promise<osmium::io::Header>& header_promise,
|
||||
osmium::io::detail::reader_options options) :
|
||||
Parser(input_queue, output_queue, header_promise, options) {
|
||||
explicit OPLParser(parser_arguments& args) :
|
||||
Parser(args) {
|
||||
set_header_value(osmium::io::Header{});
|
||||
}
|
||||
|
||||
~OPLParser() noexcept final = default;
|
||||
|
||||
void parse_line(const char* data) {
|
||||
if (opl_parse_line(m_line_count, data, m_buffer, read_types())) {
|
||||
maybe_flush();
|
||||
}
|
||||
++m_line_count;
|
||||
}
|
||||
|
||||
void run() final {
|
||||
osmium::thread::set_thread_name("_osmium_opl_in");
|
||||
|
||||
std::string rest;
|
||||
while (!input_done()) {
|
||||
std::string input = get_input();
|
||||
std::string::size_type ppos = 0;
|
||||
|
||||
if (!rest.empty()) {
|
||||
ppos = input.find('\n');
|
||||
if (ppos == std::string::npos) {
|
||||
rest.append(input);
|
||||
continue;
|
||||
}
|
||||
rest.append(input.substr(0, ppos));
|
||||
m_data = rest.data();
|
||||
parse_line();
|
||||
rest.clear();
|
||||
}
|
||||
|
||||
std::string::size_type pos = input.find('\n', ppos);
|
||||
while (pos != std::string::npos) {
|
||||
m_data = &input[ppos];
|
||||
input[pos] = '\0';
|
||||
parse_line();
|
||||
ppos = pos + 1;
|
||||
if (ppos >= input.size()) {
|
||||
break;
|
||||
}
|
||||
pos = input.find('\n', ppos);
|
||||
}
|
||||
rest = input.substr(ppos);
|
||||
}
|
||||
|
||||
if (!rest.empty()) {
|
||||
m_data = rest.data();
|
||||
parse_line();
|
||||
}
|
||||
line_by_line(*this);
|
||||
|
||||
if (m_buffer.committed() > 0) {
|
||||
send_to_output_queue(std::move(m_buffer));
|
||||
@ -139,11 +145,8 @@ namespace osmium {
|
||||
// the variable is only a side-effect, it will never be used
|
||||
const bool registered_opl_parser = ParserFactory::instance().register_parser(
|
||||
file_format::opl,
|
||||
[](future_string_queue_type& input_queue,
|
||||
future_buffer_queue_type& output_queue,
|
||||
std::promise<osmium::io::Header>& header_promise,
|
||||
osmium::io::detail::reader_options options) {
|
||||
return std::unique_ptr<Parser>(new OPLParser(input_queue, output_queue, header_promise, options));
|
||||
[](parser_arguments& args) {
|
||||
return std::unique_ptr<Parser>(new OPLParser{args});
|
||||
});
|
||||
|
||||
// dummy function to silence the unused variable warning from above
|
||||
|
@ -141,14 +141,15 @@ namespace osmium {
|
||||
}
|
||||
|
||||
void write_location(const osmium::Location& location, const char x, const char y) {
|
||||
const bool not_undefined = !location.is_undefined();
|
||||
*m_out += ' ';
|
||||
*m_out += x;
|
||||
if (location) {
|
||||
if (not_undefined) {
|
||||
osmium::detail::append_location_coordinate_to_string(std::back_inserter(*m_out), location.x());
|
||||
}
|
||||
*m_out += ' ';
|
||||
*m_out += y;
|
||||
if (location) {
|
||||
if (not_undefined) {
|
||||
osmium::detail::append_location_coordinate_to_string(std::back_inserter(*m_out), location.y());
|
||||
}
|
||||
}
|
||||
@ -283,8 +284,8 @@ namespace osmium {
|
||||
|
||||
public:
|
||||
|
||||
OPLOutputFormat(const osmium::io::File& file, future_string_queue_type& output_queue) :
|
||||
OutputFormat(output_queue),
|
||||
OPLOutputFormat(osmium::thread::Pool& pool, const osmium::io::File& file, future_string_queue_type& output_queue) :
|
||||
OutputFormat(pool, output_queue),
|
||||
m_options() {
|
||||
m_options.add_metadata = file.is_not_false("add_metadata");
|
||||
m_options.locations_on_ways = file.is_true("locations_on_ways");
|
||||
@ -297,7 +298,7 @@ namespace osmium {
|
||||
~OPLOutputFormat() noexcept final = default;
|
||||
|
||||
void write_buffer(osmium::memory::Buffer&& buffer) final {
|
||||
m_output_queue.push(osmium::thread::Pool::instance().submit(OPLOutputBlock{std::move(buffer), m_options}));
|
||||
m_output_queue.push(m_pool.submit(OPLOutputBlock{std::move(buffer), m_options}));
|
||||
}
|
||||
|
||||
}; // class OPLOutputFormat
|
||||
@ -305,8 +306,8 @@ namespace osmium {
|
||||
// we want the register_output_format() function to run, setting
|
||||
// the variable is only a side-effect, it will never be used
|
||||
const bool registered_opl_output = osmium::io::detail::OutputFormatFactory::instance().register_output_format(osmium::io::file_format::opl,
|
||||
[](const osmium::io::File& file, future_string_queue_type& output_queue) {
|
||||
return new osmium::io::detail::OPLOutputFormat(file, output_queue);
|
||||
[](osmium::thread::Pool& pool, const osmium::io::File& file, future_string_queue_type& output_queue) {
|
||||
return new osmium::io::detail::OPLOutputFormat(pool, file, output_queue);
|
||||
});
|
||||
|
||||
// dummy function to silence the unused variable warning from above
|
||||
|
@ -81,7 +81,7 @@ namespace osmium {
|
||||
}
|
||||
|
||||
explicit opl_error(const char* what, const char* d = nullptr) :
|
||||
io_error(std::string("OPL error: ") + what),
|
||||
io_error(std::string{"OPL error: "} + what),
|
||||
data(d),
|
||||
msg("OPL error: ") {
|
||||
msg.append(what);
|
||||
@ -291,7 +291,7 @@ namespace osmium {
|
||||
++*data;
|
||||
return;
|
||||
}
|
||||
std::string msg = "expected '";
|
||||
std::string msg{"expected '"};
|
||||
msg += c;
|
||||
msg += "'";
|
||||
throw opl_error{msg, *data};
|
||||
@ -599,8 +599,7 @@ namespace osmium {
|
||||
|
||||
const char* tags_begin = nullptr;
|
||||
|
||||
osmium::Location location1;
|
||||
osmium::Location location2;
|
||||
osmium::Box box;
|
||||
std::string user;
|
||||
while (**data) {
|
||||
opl_parse_space(data);
|
||||
@ -630,22 +629,22 @@ namespace osmium {
|
||||
break;
|
||||
case 'x':
|
||||
if (opl_non_empty(*data)) {
|
||||
location1.set_lon_partial(data);
|
||||
box.bottom_left().set_lon_partial(data);
|
||||
}
|
||||
break;
|
||||
case 'y':
|
||||
if (opl_non_empty(*data)) {
|
||||
location1.set_lat_partial(data);
|
||||
box.bottom_left().set_lat_partial(data);
|
||||
}
|
||||
break;
|
||||
case 'X':
|
||||
if (opl_non_empty(*data)) {
|
||||
location2.set_lon_partial(data);
|
||||
box.top_right().set_lon_partial(data);
|
||||
}
|
||||
break;
|
||||
case 'Y':
|
||||
if (opl_non_empty(*data)) {
|
||||
location2.set_lat_partial(data);
|
||||
box.top_right().set_lat_partial(data);
|
||||
}
|
||||
break;
|
||||
case 'T':
|
||||
@ -661,13 +660,7 @@ namespace osmium {
|
||||
|
||||
}
|
||||
|
||||
if (location1.valid() && location2.valid()) {
|
||||
osmium::Box box;
|
||||
box.extend(location1);
|
||||
box.extend(location2);
|
||||
builder.set_bounds(box);
|
||||
}
|
||||
|
||||
builder.set_user(user);
|
||||
|
||||
if (tags_begin) {
|
||||
|
@ -46,6 +46,7 @@ DEALINGS IN THE SOFTWARE.
|
||||
#include <osmium/io/file.hpp>
|
||||
#include <osmium/io/file_format.hpp>
|
||||
#include <osmium/memory/buffer.hpp>
|
||||
#include <osmium/thread/pool.hpp>
|
||||
|
||||
namespace osmium {
|
||||
|
||||
@ -107,6 +108,7 @@ namespace osmium {
|
||||
|
||||
protected:
|
||||
|
||||
osmium::thread::Pool& m_pool;
|
||||
future_string_queue_type& m_output_queue;
|
||||
|
||||
/**
|
||||
@ -119,7 +121,8 @@ namespace osmium {
|
||||
|
||||
public:
|
||||
|
||||
explicit OutputFormat(future_string_queue_type& output_queue) :
|
||||
OutputFormat(osmium::thread::Pool& pool, future_string_queue_type& output_queue) :
|
||||
m_pool(pool),
|
||||
m_output_queue(output_queue) {
|
||||
}
|
||||
|
||||
@ -152,7 +155,7 @@ namespace osmium {
|
||||
|
||||
public:
|
||||
|
||||
using create_output_type = std::function<osmium::io::detail::OutputFormat*(const osmium::io::File&, future_string_queue_type&)>;
|
||||
using create_output_type = std::function<osmium::io::detail::OutputFormat*(osmium::thread::Pool&, const osmium::io::File&, future_string_queue_type&)>;
|
||||
|
||||
private:
|
||||
|
||||
@ -178,22 +181,52 @@ namespace osmium {
|
||||
return true;
|
||||
}
|
||||
|
||||
std::unique_ptr<osmium::io::detail::OutputFormat> create_output(const osmium::io::File& file, future_string_queue_type& output_queue) {
|
||||
auto it = m_callbacks.find(file.format());
|
||||
std::unique_ptr<osmium::io::detail::OutputFormat> create_output(osmium::thread::Pool& pool, const osmium::io::File& file, future_string_queue_type& output_queue) {
|
||||
const auto it = m_callbacks.find(file.format());
|
||||
if (it != m_callbacks.end()) {
|
||||
return std::unique_ptr<osmium::io::detail::OutputFormat>((it->second)(file, output_queue));
|
||||
return std::unique_ptr<osmium::io::detail::OutputFormat>((it->second)(pool, file, output_queue));
|
||||
}
|
||||
|
||||
throw unsupported_file_format_error(
|
||||
std::string("Can not open file '") +
|
||||
throw unsupported_file_format_error{
|
||||
std::string{"Can not open file '"} +
|
||||
file.filename() +
|
||||
"' with type '" +
|
||||
as_string(file.format()) +
|
||||
"'. No support for writing this format in this program.");
|
||||
"'. No support for writing this format in this program."};
|
||||
}
|
||||
|
||||
}; // class OutputFormatFactory
|
||||
|
||||
class BlackholeOutputFormat : public osmium::io::detail::OutputFormat {
|
||||
|
||||
public:
|
||||
|
||||
BlackholeOutputFormat(osmium::thread::Pool& pool, const osmium::io::File& /*file*/, future_string_queue_type& output_queue) :
|
||||
OutputFormat(pool, output_queue) {
|
||||
}
|
||||
|
||||
BlackholeOutputFormat(const BlackholeOutputFormat&) = delete;
|
||||
BlackholeOutputFormat& operator=(const BlackholeOutputFormat&) = delete;
|
||||
|
||||
~BlackholeOutputFormat() noexcept final = default;
|
||||
|
||||
void write_buffer(osmium::memory::Buffer&& /*buffer*/) final {
|
||||
}
|
||||
|
||||
}; // class BlackholeOutputFormat
|
||||
|
||||
// we want the register_output_format() function to run, setting
|
||||
// the variable is only a side-effect, it will never be used
|
||||
const bool registered_blackhole_output = osmium::io::detail::OutputFormatFactory::instance().register_output_format(osmium::io::file_format::blackhole,
|
||||
[](osmium::thread::Pool& pool, const osmium::io::File& file, future_string_queue_type& output_queue) {
|
||||
return new osmium::io::detail::BlackholeOutputFormat(pool, file, output_queue);
|
||||
});
|
||||
|
||||
// dummy function to silence the unused variable warning from above
|
||||
inline bool get_registered_blackhole_output() noexcept {
|
||||
return registered_blackhole_output;
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
} // namespace io
|
||||
|
@ -99,21 +99,21 @@ namespace osmium {
|
||||
|
||||
void decode_stringtable(const data_view& data) {
|
||||
if (!m_stringtable.empty()) {
|
||||
throw osmium::pbf_error("more than one stringtable in pbf file");
|
||||
throw osmium::pbf_error{"more than one stringtable in pbf file"};
|
||||
}
|
||||
|
||||
protozero::pbf_message<OSMFormat::StringTable> pbf_string_table(data);
|
||||
protozero::pbf_message<OSMFormat::StringTable> pbf_string_table{data};
|
||||
while (pbf_string_table.next(OSMFormat::StringTable::repeated_bytes_s)) {
|
||||
const auto str_view = pbf_string_table.get_view();
|
||||
if (str_view.size() > osmium::max_osm_string_length) {
|
||||
throw osmium::pbf_error("overlong string in string table");
|
||||
throw osmium::pbf_error{"overlong string in string table"};
|
||||
}
|
||||
m_stringtable.emplace_back(str_view.data(), osmium::string_size_type(str_view.size()));
|
||||
}
|
||||
}
|
||||
|
||||
void decode_primitive_block_metadata() {
|
||||
protozero::pbf_message<OSMFormat::PrimitiveBlock> pbf_primitive_block(m_data);
|
||||
protozero::pbf_message<OSMFormat::PrimitiveBlock> pbf_primitive_block{m_data};
|
||||
while (pbf_primitive_block.next()) {
|
||||
switch (pbf_primitive_block.tag()) {
|
||||
case OSMFormat::PrimitiveBlock::required_StringTable_stringtable:
|
||||
@ -138,7 +138,7 @@ namespace osmium {
|
||||
}
|
||||
|
||||
void decode_primitive_block_data() {
|
||||
protozero::pbf_message<OSMFormat::PrimitiveBlock> pbf_primitive_block(m_data);
|
||||
protozero::pbf_message<OSMFormat::PrimitiveBlock> pbf_primitive_block{m_data};
|
||||
while (pbf_primitive_block.next(OSMFormat::PrimitiveBlock::repeated_PrimitiveGroup_primitivegroup)) {
|
||||
protozero::pbf_message<OSMFormat::PrimitiveGroup> pbf_primitive_group = pbf_primitive_block.get_message();
|
||||
while (pbf_primitive_group.next()) {
|
||||
@ -187,16 +187,16 @@ namespace osmium {
|
||||
}
|
||||
|
||||
osm_string_len_type decode_info(const data_view& data, osmium::OSMObject& object) {
|
||||
osm_string_len_type user = std::make_pair("", 0);
|
||||
osm_string_len_type user{"", 0};
|
||||
|
||||
protozero::pbf_message<OSMFormat::Info> pbf_info(data);
|
||||
protozero::pbf_message<OSMFormat::Info> pbf_info{data};
|
||||
while (pbf_info.next()) {
|
||||
switch (pbf_info.tag()) {
|
||||
case OSMFormat::Info::optional_int32_version:
|
||||
{
|
||||
const auto version = pbf_info.get_int32();
|
||||
if (version < 0) {
|
||||
throw osmium::pbf_error("object version must not be negative");
|
||||
throw osmium::pbf_error{"object version must not be negative"};
|
||||
}
|
||||
object.set_version(static_cast_with_assert<object_version_type>(version));
|
||||
}
|
||||
@ -208,7 +208,7 @@ namespace osmium {
|
||||
{
|
||||
const auto changeset_id = pbf_info.get_int64();
|
||||
if (changeset_id < 0) {
|
||||
throw osmium::pbf_error("object changeset_id must not be negative");
|
||||
throw osmium::pbf_error{"object changeset_id must not be negative"};
|
||||
}
|
||||
object.set_changeset(static_cast_with_assert<changeset_id_type>(changeset_id));
|
||||
}
|
||||
@ -240,7 +240,7 @@ namespace osmium {
|
||||
while (kit != keys.end()) {
|
||||
if (vit == vals.end()) {
|
||||
// this is against the spec, must have same number of elements
|
||||
throw osmium::pbf_error("PBF format error");
|
||||
throw osmium::pbf_error{"PBF format error"};
|
||||
}
|
||||
const auto& k = m_stringtable.at(*kit++);
|
||||
const auto& v = m_stringtable.at(*vit++);
|
||||
@ -262,9 +262,9 @@ namespace osmium {
|
||||
int64_t lon = std::numeric_limits<int64_t>::max();
|
||||
int64_t lat = std::numeric_limits<int64_t>::max();
|
||||
|
||||
osm_string_len_type user = { "", 0 };
|
||||
osm_string_len_type user{"", 0};
|
||||
|
||||
protozero::pbf_message<OSMFormat::Node> pbf_node(data);
|
||||
protozero::pbf_message<OSMFormat::Node> pbf_node{data};
|
||||
while (pbf_node.next()) {
|
||||
switch (pbf_node.tag()) {
|
||||
case OSMFormat::Node::required_sint64_id:
|
||||
@ -297,12 +297,12 @@ namespace osmium {
|
||||
if (node.visible()) {
|
||||
if (lon == std::numeric_limits<int64_t>::max() ||
|
||||
lat == std::numeric_limits<int64_t>::max()) {
|
||||
throw osmium::pbf_error("illegal coordinate format");
|
||||
throw osmium::pbf_error{"illegal coordinate format"};
|
||||
}
|
||||
node.set_location(osmium::Location(
|
||||
node.set_location(osmium::Location{
|
||||
convert_pbf_coordinate(lon),
|
||||
convert_pbf_coordinate(lat)
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
builder.set_user(user.first, user.second);
|
||||
@ -319,9 +319,9 @@ namespace osmium {
|
||||
protozero::iterator_range<protozero::pbf_reader::const_sint64_iterator> lats;
|
||||
protozero::iterator_range<protozero::pbf_reader::const_sint64_iterator> lons;
|
||||
|
||||
osm_string_len_type user = { "", 0 };
|
||||
osm_string_len_type user{"", 0};
|
||||
|
||||
protozero::pbf_message<OSMFormat::Way> pbf_way(data);
|
||||
protozero::pbf_message<OSMFormat::Way> pbf_way{data};
|
||||
while (pbf_way.next()) {
|
||||
switch (pbf_way.tag()) {
|
||||
case OSMFormat::Way::required_int64_id:
|
||||
@ -391,9 +391,9 @@ namespace osmium {
|
||||
protozero::iterator_range<protozero::pbf_reader::const_sint64_iterator> refs;
|
||||
protozero::iterator_range<protozero::pbf_reader::const_int32_iterator> types;
|
||||
|
||||
osm_string_len_type user = { "", 0 };
|
||||
osm_string_len_type user{"", 0};
|
||||
|
||||
protozero::pbf_message<OSMFormat::Relation> pbf_relation(data);
|
||||
protozero::pbf_message<OSMFormat::Relation> pbf_relation{data};
|
||||
while (pbf_relation.next()) {
|
||||
switch (pbf_relation.tag()) {
|
||||
case OSMFormat::Relation::required_int64_id:
|
||||
@ -435,7 +435,7 @@ namespace osmium {
|
||||
const auto& r = m_stringtable.at(roles.front());
|
||||
const int type = types.front();
|
||||
if (type < 0 || type > 2) {
|
||||
throw osmium::pbf_error("unknown relation member type");
|
||||
throw osmium::pbf_error{"unknown relation member type"};
|
||||
}
|
||||
rml_builder.add_member(
|
||||
osmium::item_type(type + 1),
|
||||
@ -457,7 +457,7 @@ namespace osmium {
|
||||
while (it != last && *it != 0) {
|
||||
const auto& k = m_stringtable.at(*it++);
|
||||
if (it == last) {
|
||||
throw osmium::pbf_error("PBF format error"); // this is against the spec, keys/vals must come in pairs
|
||||
throw osmium::pbf_error{"PBF format error"}; // this is against the spec, keys/vals must come in pairs
|
||||
}
|
||||
const auto& v = m_stringtable.at(*it++);
|
||||
tl_builder.add_tag(k.first, k.second, v.first, v.second);
|
||||
@ -475,7 +475,7 @@ namespace osmium {
|
||||
|
||||
protozero::iterator_range<protozero::pbf_reader::const_int32_iterator> tags;
|
||||
|
||||
protozero::pbf_message<OSMFormat::DenseNodes> pbf_dense_nodes(data);
|
||||
protozero::pbf_message<OSMFormat::DenseNodes> pbf_dense_nodes{data};
|
||||
while (pbf_dense_nodes.next()) {
|
||||
switch (pbf_dense_nodes.tag()) {
|
||||
case OSMFormat::DenseNodes::packed_sint64_id:
|
||||
@ -505,7 +505,7 @@ namespace osmium {
|
||||
if (lons.empty() ||
|
||||
lats.empty()) {
|
||||
// this is against the spec, must have same number of elements
|
||||
throw osmium::pbf_error("PBF format error");
|
||||
throw osmium::pbf_error{"PBF format error"};
|
||||
}
|
||||
|
||||
osmium::builder::NodeBuilder builder{m_buffer};
|
||||
@ -547,7 +547,7 @@ namespace osmium {
|
||||
protozero::iterator_range<protozero::pbf_reader::const_sint32_iterator> user_sids;
|
||||
protozero::iterator_range<protozero::pbf_reader::const_int32_iterator> visibles;
|
||||
|
||||
protozero::pbf_message<OSMFormat::DenseNodes> pbf_dense_nodes(data);
|
||||
protozero::pbf_message<OSMFormat::DenseNodes> pbf_dense_nodes{data};
|
||||
while (pbf_dense_nodes.next()) {
|
||||
switch (pbf_dense_nodes.tag()) {
|
||||
case OSMFormat::DenseNodes::packed_sint64_id:
|
||||
@ -556,7 +556,7 @@ namespace osmium {
|
||||
case OSMFormat::DenseNodes::optional_DenseInfo_denseinfo:
|
||||
{
|
||||
has_info = true;
|
||||
protozero::pbf_message<OSMFormat::DenseInfo> pbf_dense_info = pbf_dense_nodes.get_message();
|
||||
protozero::pbf_message<OSMFormat::DenseInfo> pbf_dense_info{pbf_dense_nodes.get_message()};
|
||||
while (pbf_dense_info.next()) {
|
||||
switch (pbf_dense_info.tag()) {
|
||||
case OSMFormat::DenseInfo::packed_int32_version:
|
||||
@ -612,7 +612,7 @@ namespace osmium {
|
||||
if (lons.empty() ||
|
||||
lats.empty()) {
|
||||
// this is against the spec, must have same number of elements
|
||||
throw osmium::pbf_error("PBF format error");
|
||||
throw osmium::pbf_error{"PBF format error"};
|
||||
}
|
||||
|
||||
bool visible = true;
|
||||
@ -630,20 +630,20 @@ namespace osmium {
|
||||
uids.empty() ||
|
||||
user_sids.empty()) {
|
||||
// this is against the spec, must have same number of elements
|
||||
throw osmium::pbf_error("PBF format error");
|
||||
throw osmium::pbf_error{"PBF format error"};
|
||||
}
|
||||
|
||||
const auto version = versions.front();
|
||||
versions.drop_front();
|
||||
if (version < 0) {
|
||||
throw osmium::pbf_error("object version must not be negative");
|
||||
throw osmium::pbf_error{"object version must not be negative"};
|
||||
}
|
||||
node.set_version(static_cast<osmium::object_version_type>(version));
|
||||
|
||||
const auto changeset_id = dense_changeset.update(changesets.front());
|
||||
changesets.drop_front();
|
||||
if (changeset_id < 0) {
|
||||
throw osmium::pbf_error("object changeset_id must not be negative");
|
||||
throw osmium::pbf_error{"object changeset_id must not be negative"};
|
||||
}
|
||||
node.set_changeset(static_cast<osmium::changeset_id_type>(changeset_id));
|
||||
|
||||
@ -655,7 +655,7 @@ namespace osmium {
|
||||
if (has_visibles) {
|
||||
if (visibles.empty()) {
|
||||
// this is against the spec, must have same number of elements
|
||||
throw osmium::pbf_error("PBF format error");
|
||||
throw osmium::pbf_error{"PBF format error"};
|
||||
}
|
||||
visible = (visibles.front() != 0);
|
||||
visibles.drop_front();
|
||||
@ -674,10 +674,10 @@ namespace osmium {
|
||||
const auto lat = dense_latitude.update(lats.front());
|
||||
lats.drop_front();
|
||||
if (visible) {
|
||||
builder.object().set_location(osmium::Location(
|
||||
builder.object().set_location(osmium::Location{
|
||||
convert_pbf_coordinate(lon),
|
||||
convert_pbf_coordinate(lat)
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
if (tag_it != tags.end()) {
|
||||
@ -708,7 +708,7 @@ namespace osmium {
|
||||
decode_primitive_block_metadata();
|
||||
decode_primitive_block_data();
|
||||
} catch (const std::out_of_range&) {
|
||||
throw osmium::pbf_error("string id out of range");
|
||||
throw osmium::pbf_error{"string id out of range"};
|
||||
}
|
||||
|
||||
return std::move(m_buffer);
|
||||
@ -720,30 +720,30 @@ namespace osmium {
|
||||
int32_t raw_size = 0;
|
||||
protozero::data_view zlib_data;
|
||||
|
||||
protozero::pbf_message<FileFormat::Blob> pbf_blob(blob_data);
|
||||
protozero::pbf_message<FileFormat::Blob> pbf_blob{blob_data};
|
||||
while (pbf_blob.next()) {
|
||||
switch (pbf_blob.tag()) {
|
||||
case FileFormat::Blob::optional_bytes_raw:
|
||||
{
|
||||
auto data_len = pbf_blob.get_view();
|
||||
const auto data_len = pbf_blob.get_view();
|
||||
if (data_len.size() > max_uncompressed_blob_size) {
|
||||
throw osmium::pbf_error("illegal blob size");
|
||||
throw osmium::pbf_error{"illegal blob size"};
|
||||
}
|
||||
return data_len;
|
||||
}
|
||||
case FileFormat::Blob::optional_int32_raw_size:
|
||||
raw_size = pbf_blob.get_int32();
|
||||
if (raw_size <= 0 || uint32_t(raw_size) > max_uncompressed_blob_size) {
|
||||
throw osmium::pbf_error("illegal blob size");
|
||||
throw osmium::pbf_error{"illegal blob size"};
|
||||
}
|
||||
break;
|
||||
case FileFormat::Blob::optional_bytes_zlib_data:
|
||||
zlib_data = pbf_blob.get_view();
|
||||
break;
|
||||
case FileFormat::Blob::optional_bytes_lzma_data:
|
||||
throw osmium::pbf_error("lzma blobs not implemented");
|
||||
throw osmium::pbf_error{"lzma blobs not implemented"};
|
||||
default:
|
||||
throw osmium::pbf_error("unknown compression");
|
||||
throw osmium::pbf_error{"unknown compression"};
|
||||
}
|
||||
}
|
||||
|
||||
@ -756,7 +756,7 @@ namespace osmium {
|
||||
);
|
||||
}
|
||||
|
||||
throw osmium::pbf_error("blob contains no data");
|
||||
throw osmium::pbf_error{"blob contains no data"};
|
||||
}
|
||||
|
||||
inline osmium::Box decode_header_bbox(const data_view& data) {
|
||||
@ -765,7 +765,7 @@ namespace osmium {
|
||||
int64_t top = std::numeric_limits<int64_t>::max();
|
||||
int64_t bottom = std::numeric_limits<int64_t>::max();
|
||||
|
||||
protozero::pbf_message<OSMFormat::HeaderBBox> pbf_header_bbox(data);
|
||||
protozero::pbf_message<OSMFormat::HeaderBBox> pbf_header_bbox{data};
|
||||
while (pbf_header_bbox.next()) {
|
||||
switch (pbf_header_bbox.tag()) {
|
||||
case OSMFormat::HeaderBBox::required_sint64_left:
|
||||
@ -789,7 +789,7 @@ namespace osmium {
|
||||
right == std::numeric_limits<int64_t>::max() ||
|
||||
top == std::numeric_limits<int64_t>::max() ||
|
||||
bottom == std::numeric_limits<int64_t>::max()) {
|
||||
throw osmium::pbf_error("invalid bbox");
|
||||
throw osmium::pbf_error{"invalid bbox"};
|
||||
}
|
||||
|
||||
osmium::Box box;
|
||||
@ -803,7 +803,7 @@ namespace osmium {
|
||||
osmium::io::Header header;
|
||||
int i = 0;
|
||||
|
||||
protozero::pbf_message<OSMFormat::HeaderBlock> pbf_header_block(data);
|
||||
protozero::pbf_message<OSMFormat::HeaderBlock> pbf_header_block{data};
|
||||
while (pbf_header_block.next()) {
|
||||
switch (pbf_header_block.tag()) {
|
||||
case OSMFormat::HeaderBlock::optional_HeaderBBox_bbox:
|
||||
@ -819,9 +819,9 @@ namespace osmium {
|
||||
} else if (!std::strncmp("HistoricalInformation", feature.data(), feature.size())) {
|
||||
header.set_has_multiple_object_versions(true);
|
||||
} else {
|
||||
std::string msg("required feature not supported: ");
|
||||
std::string msg{"required feature not supported: "};
|
||||
msg.append(feature.data(), feature.size());
|
||||
throw osmium::pbf_error(msg);
|
||||
throw osmium::pbf_error{msg};
|
||||
}
|
||||
}
|
||||
break;
|
||||
@ -833,7 +833,7 @@ namespace osmium {
|
||||
break;
|
||||
case OSMFormat::HeaderBlock::optional_int64_osmosis_replication_timestamp:
|
||||
{
|
||||
const auto timestamp = osmium::Timestamp(pbf_header_block.get_int64()).to_iso();
|
||||
const auto timestamp = osmium::Timestamp{pbf_header_block.get_int64()}.to_iso();
|
||||
header.set("osmosis_replication_timestamp", timestamp);
|
||||
header.set("timestamp", timestamp);
|
||||
}
|
||||
@ -889,7 +889,7 @@ namespace osmium {
|
||||
|
||||
osmium::memory::Buffer operator()() {
|
||||
std::string output;
|
||||
PBFPrimitiveBlockDecoder decoder(decode_blob(*m_input_buffer, output), m_read_types, m_read_metadata);
|
||||
PBFPrimitiveBlockDecoder decoder{decode_blob(*m_input_buffer, output), m_read_types, m_read_metadata};
|
||||
return decoder();
|
||||
}
|
||||
|
||||
|
@ -33,15 +33,14 @@ DEALINGS IN THE SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
#include <future>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
#include <protozero/pbf_message.hpp>
|
||||
#include <protozero/types.hpp>
|
||||
@ -50,7 +49,6 @@ DEALINGS IN THE SOFTWARE.
|
||||
#include <osmium/io/detail/pbf.hpp> // IWYU pragma: export
|
||||
#include <osmium/io/detail/pbf_decoder.hpp>
|
||||
#include <osmium/io/detail/protobuf_tags.hpp>
|
||||
#include <osmium/io/detail/queue_util.hpp>
|
||||
#include <osmium/io/file_format.hpp>
|
||||
#include <osmium/io/header.hpp>
|
||||
#include <osmium/osm/entity_bits.hpp>
|
||||
@ -77,14 +75,14 @@ namespace osmium {
|
||||
*/
|
||||
std::string read_from_input_queue(size_t size) {
|
||||
while (m_input_buffer.size() < size) {
|
||||
const std::string new_data = get_input();
|
||||
const std::string new_data{get_input()};
|
||||
if (input_done()) {
|
||||
throw osmium::pbf_error("truncated data (EOF encountered)");
|
||||
throw osmium::pbf_error{"truncated data (EOF encountered)"};
|
||||
}
|
||||
m_input_buffer += new_data;
|
||||
}
|
||||
|
||||
std::string output { m_input_buffer.substr(size) };
|
||||
std::string output{m_input_buffer.substr(size)};
|
||||
m_input_buffer.resize(size);
|
||||
|
||||
using std::swap;
|
||||
@ -101,7 +99,7 @@ namespace osmium {
|
||||
uint32_t size_in_network_byte_order;
|
||||
|
||||
try {
|
||||
const std::string input_data = read_from_input_queue(sizeof(size_in_network_byte_order));
|
||||
const std::string input_data{read_from_input_queue(sizeof(size_in_network_byte_order))};
|
||||
size_in_network_byte_order = *reinterpret_cast<const uint32_t*>(input_data.data());
|
||||
} catch (const osmium::pbf_error&) {
|
||||
return 0; // EOF
|
||||
@ -109,7 +107,7 @@ namespace osmium {
|
||||
|
||||
const uint32_t size = ntohl(size_in_network_byte_order);
|
||||
if (size > static_cast<uint32_t>(max_blob_header_size)) {
|
||||
throw osmium::pbf_error("invalid BlobHeader size (> max_blob_header_size)");
|
||||
throw osmium::pbf_error{"invalid BlobHeader size (> max_blob_header_size)"};
|
||||
}
|
||||
|
||||
return size;
|
||||
@ -137,11 +135,11 @@ namespace osmium {
|
||||
}
|
||||
|
||||
if (blob_header_datasize == 0) {
|
||||
throw osmium::pbf_error("PBF format error: BlobHeader.datasize missing or zero.");
|
||||
throw osmium::pbf_error{"PBF format error: BlobHeader.datasize missing or zero."};
|
||||
}
|
||||
|
||||
if (std::strncmp(expected_type, blob_header_type.data(), blob_header_type.size())) {
|
||||
throw osmium::pbf_error("blob does not have expected type (OSMHeader in first blob, OSMData in following blobs)");
|
||||
throw osmium::pbf_error{"blob does not have expected type (OSMHeader in first blob, OSMData in following blobs)"};
|
||||
}
|
||||
|
||||
return blob_header_datasize;
|
||||
@ -155,35 +153,34 @@ namespace osmium {
|
||||
return 0;
|
||||
}
|
||||
|
||||
const std::string blob_header = read_from_input_queue(size);
|
||||
const std::string blob_header{read_from_input_queue(size)};
|
||||
|
||||
return decode_blob_header(protozero::pbf_message<FileFormat::BlobHeader>(blob_header), expected_type);
|
||||
}
|
||||
|
||||
std::string read_from_input_queue_with_check(size_t size) {
|
||||
if (size > max_uncompressed_blob_size) {
|
||||
throw osmium::pbf_error(std::string("invalid blob size: " +
|
||||
std::to_string(size)));
|
||||
throw osmium::pbf_error{std::string{"invalid blob size: "} +
|
||||
std::to_string(size)};
|
||||
}
|
||||
return read_from_input_queue(size);
|
||||
}
|
||||
|
||||
// Parse the header in the PBF OSMHeader blob.
|
||||
void parse_header_blob() {
|
||||
osmium::io::Header header;
|
||||
const auto size = check_type_and_get_blob_size("OSMHeader");
|
||||
header = decode_header(read_from_input_queue_with_check(size));
|
||||
osmium::io::Header header{decode_header(read_from_input_queue_with_check(size))};
|
||||
set_header_value(header);
|
||||
}
|
||||
|
||||
void parse_data_blobs() {
|
||||
while (const auto size = check_type_and_get_blob_size("OSMData")) {
|
||||
std::string input_buffer = read_from_input_queue_with_check(size);
|
||||
std::string input_buffer{read_from_input_queue_with_check(size)};
|
||||
|
||||
PBFDataBlobDecoder data_blob_parser{std::move(input_buffer), read_types(), read_metadata()};
|
||||
|
||||
if (osmium::config::use_pool_threads_for_pbf_parsing()) {
|
||||
send_to_output_queue(osmium::thread::Pool::instance().submit(std::move(data_blob_parser)));
|
||||
send_to_output_queue(get_pool().submit(std::move(data_blob_parser)));
|
||||
} else {
|
||||
send_to_output_queue(data_blob_parser());
|
||||
}
|
||||
@ -192,11 +189,8 @@ namespace osmium {
|
||||
|
||||
public:
|
||||
|
||||
PBFParser(future_string_queue_type& input_queue,
|
||||
future_buffer_queue_type& output_queue,
|
||||
std::promise<osmium::io::Header>& header_promise,
|
||||
osmium::io::detail::reader_options options) :
|
||||
Parser(input_queue, output_queue, header_promise, options),
|
||||
explicit PBFParser(parser_arguments& args) :
|
||||
Parser(args),
|
||||
m_input_buffer() {
|
||||
}
|
||||
|
||||
@ -218,11 +212,8 @@ namespace osmium {
|
||||
// the variable is only a side-effect, it will never be used
|
||||
const bool registered_pbf_parser = ParserFactory::instance().register_parser(
|
||||
file_format::pbf,
|
||||
[](future_string_queue_type& input_queue,
|
||||
future_buffer_queue_type& output_queue,
|
||||
std::promise<osmium::io::Header>& header_promise,
|
||||
osmium::io::detail::reader_options options) {
|
||||
return std::unique_ptr<Parser>(new PBFParser(input_queue, output_queue, header_promise, options));
|
||||
[](parser_arguments& args) {
|
||||
return std::unique_ptr<Parser>(new PBFParser{args});
|
||||
});
|
||||
|
||||
// dummy function to silence the unused variable warning from above
|
||||
|
@ -33,15 +33,14 @@ DEALINGS IN THE SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <cmath>
|
||||
#include <cstdint>
|
||||
#include <cstdlib>
|
||||
#include <iterator>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include <protozero/pbf_builder.hpp>
|
||||
#include <protozero/pbf_writer.hpp>
|
||||
@ -171,7 +170,7 @@ namespace osmium {
|
||||
assert(m_msg.size() <= max_uncompressed_blob_size);
|
||||
|
||||
std::string blob_data;
|
||||
protozero::pbf_builder<FileFormat::Blob> pbf_blob(blob_data);
|
||||
protozero::pbf_builder<FileFormat::Blob> pbf_blob{blob_data};
|
||||
|
||||
if (m_use_compression) {
|
||||
pbf_blob.add_int32(FileFormat::Blob::optional_int32_raw_size, int32_t(m_msg.size()));
|
||||
@ -181,12 +180,12 @@ namespace osmium {
|
||||
}
|
||||
|
||||
std::string blob_header_data;
|
||||
protozero::pbf_builder<FileFormat::BlobHeader> pbf_blob_header(blob_header_data);
|
||||
protozero::pbf_builder<FileFormat::BlobHeader> pbf_blob_header{blob_header_data};
|
||||
|
||||
pbf_blob_header.add_string(FileFormat::BlobHeader::required_string_type, m_blob_type == pbf_blob_type::data ? "OSMData" : "OSMHeader");
|
||||
pbf_blob_header.add_int32(FileFormat::BlobHeader::required_int32_datasize, static_cast_with_assert<int32_t>(blob_data.size()));
|
||||
|
||||
uint32_t sz = htonl(static_cast_with_assert<uint32_t>(blob_header_data.size()));
|
||||
const uint32_t sz = htonl(static_cast_with_assert<uint32_t>(blob_header_data.size()));
|
||||
|
||||
// write to output: the 4-byte BlobHeader-Size followed by the BlobHeader followed by the Blob
|
||||
std::string output;
|
||||
@ -270,7 +269,7 @@ namespace osmium {
|
||||
m_delta_lon.clear();
|
||||
}
|
||||
|
||||
size_t size() const {
|
||||
std::size_t size() const {
|
||||
return m_ids.size() * 3 * sizeof(int64_t);
|
||||
}
|
||||
|
||||
@ -300,12 +299,12 @@ namespace osmium {
|
||||
|
||||
std::string serialize() const {
|
||||
std::string data;
|
||||
protozero::pbf_builder<OSMFormat::DenseNodes> pbf_dense_nodes(data);
|
||||
protozero::pbf_builder<OSMFormat::DenseNodes> pbf_dense_nodes{data};
|
||||
|
||||
pbf_dense_nodes.add_packed_sint64(OSMFormat::DenseNodes::packed_sint64_id, m_ids.cbegin(), m_ids.cend());
|
||||
|
||||
if (m_options.add_metadata) {
|
||||
protozero::pbf_builder<OSMFormat::DenseInfo> pbf_dense_info(pbf_dense_nodes, OSMFormat::DenseNodes::optional_DenseInfo_denseinfo);
|
||||
protozero::pbf_builder<OSMFormat::DenseInfo> pbf_dense_info{pbf_dense_nodes, OSMFormat::DenseNodes::optional_DenseInfo_denseinfo};
|
||||
pbf_dense_info.add_packed_int32(OSMFormat::DenseInfo::packed_int32_version, m_versions.cbegin(), m_versions.cend());
|
||||
pbf_dense_info.add_packed_sint64(OSMFormat::DenseInfo::packed_sint64_timestamp, m_timestamps.cbegin(), m_timestamps.cend());
|
||||
pbf_dense_info.add_packed_sint64(OSMFormat::DenseInfo::packed_sint64_changeset, m_changesets.cbegin(), m_changesets.cend());
|
||||
@ -390,7 +389,7 @@ namespace osmium {
|
||||
return m_type;
|
||||
}
|
||||
|
||||
size_t size() const {
|
||||
std::size_t size() const {
|
||||
return m_pbf_primitive_group_data.size() + m_stringtable.size() + m_dense_nodes.size();
|
||||
}
|
||||
|
||||
@ -400,7 +399,7 @@ namespace osmium {
|
||||
* enough space for the string table (which typically
|
||||
* needs about 0.1 to 0.3% of the block size).
|
||||
*/
|
||||
constexpr static size_t max_used_blob_size = max_uncompressed_blob_size * 95 / 100;
|
||||
constexpr static std::size_t max_used_blob_size = max_uncompressed_blob_size * 95 / 100;
|
||||
|
||||
bool can_add(OSMFormat::PrimitiveGroup type) const {
|
||||
if (type != m_type) {
|
||||
@ -426,16 +425,16 @@ namespace osmium {
|
||||
}
|
||||
|
||||
std::string primitive_block_data;
|
||||
protozero::pbf_builder<OSMFormat::PrimitiveBlock> primitive_block(primitive_block_data);
|
||||
protozero::pbf_builder<OSMFormat::PrimitiveBlock> primitive_block{primitive_block_data};
|
||||
|
||||
{
|
||||
protozero::pbf_builder<OSMFormat::StringTable> pbf_string_table(primitive_block, OSMFormat::PrimitiveBlock::required_StringTable_stringtable);
|
||||
protozero::pbf_builder<OSMFormat::StringTable> pbf_string_table{primitive_block, OSMFormat::PrimitiveBlock::required_StringTable_stringtable};
|
||||
m_primitive_block.write_stringtable(pbf_string_table);
|
||||
}
|
||||
|
||||
primitive_block.add_message(OSMFormat::PrimitiveBlock::repeated_PrimitiveGroup_primitivegroup, m_primitive_block.group_data());
|
||||
|
||||
m_output_queue.push(osmium::thread::Pool::instance().submit(
|
||||
m_output_queue.push(m_pool.submit(
|
||||
SerializeBlob{std::move(primitive_block_data),
|
||||
pbf_blob_type::data,
|
||||
m_options.use_compression}
|
||||
@ -459,7 +458,7 @@ namespace osmium {
|
||||
}
|
||||
|
||||
if (m_options.add_metadata) {
|
||||
protozero::pbf_builder<OSMFormat::Info> pbf_info(pbf_object, T::enum_type::optional_Info_info);
|
||||
protozero::pbf_builder<OSMFormat::Info> pbf_info{pbf_object, T::enum_type::optional_Info_info};
|
||||
|
||||
pbf_info.add_int32(OSMFormat::Info::optional_int32_version, static_cast_with_assert<int32_t>(object.version()));
|
||||
pbf_info.add_int64(OSMFormat::Info::optional_int64_timestamp, uint32_t(object.timestamp()));
|
||||
@ -481,8 +480,8 @@ namespace osmium {
|
||||
|
||||
public:
|
||||
|
||||
PBFOutputFormat(const osmium::io::File& file, future_string_queue_type& output_queue) :
|
||||
OutputFormat(output_queue),
|
||||
PBFOutputFormat(osmium::thread::Pool& pool, const osmium::io::File& file, future_string_queue_type& output_queue) :
|
||||
OutputFormat(pool, output_queue),
|
||||
m_options(),
|
||||
m_primitive_block(m_options) {
|
||||
m_options.use_dense_nodes = file.is_not_false("pbf_dense_nodes");
|
||||
@ -500,10 +499,10 @@ namespace osmium {
|
||||
|
||||
void write_header(const osmium::io::Header& header) final {
|
||||
std::string data;
|
||||
protozero::pbf_builder<OSMFormat::HeaderBlock> pbf_header_block(data);
|
||||
protozero::pbf_builder<OSMFormat::HeaderBlock> pbf_header_block{data};
|
||||
|
||||
if (!header.boxes().empty()) {
|
||||
protozero::pbf_builder<OSMFormat::HeaderBBox> pbf_header_bbox(pbf_header_block, OSMFormat::HeaderBlock::optional_HeaderBBox_bbox);
|
||||
protozero::pbf_builder<OSMFormat::HeaderBBox> pbf_header_bbox{pbf_header_block, OSMFormat::HeaderBlock::optional_HeaderBBox_bbox};
|
||||
|
||||
osmium::Box box = header.joined_boxes();
|
||||
pbf_header_bbox.add_sint64(OSMFormat::HeaderBBox::required_sint64_left, int64_t(box.bottom_left().lon() * lonlat_resolution));
|
||||
@ -528,23 +527,23 @@ namespace osmium {
|
||||
|
||||
pbf_header_block.add_string(OSMFormat::HeaderBlock::optional_string_writingprogram, header.get("generator"));
|
||||
|
||||
const std::string osmosis_replication_timestamp = header.get("osmosis_replication_timestamp");
|
||||
const std::string osmosis_replication_timestamp{header.get("osmosis_replication_timestamp")};
|
||||
if (!osmosis_replication_timestamp.empty()) {
|
||||
osmium::Timestamp ts(osmosis_replication_timestamp.c_str());
|
||||
osmium::Timestamp ts{osmosis_replication_timestamp.c_str()};
|
||||
pbf_header_block.add_int64(OSMFormat::HeaderBlock::optional_int64_osmosis_replication_timestamp, uint32_t(ts));
|
||||
}
|
||||
|
||||
const std::string osmosis_replication_sequence_number = header.get("osmosis_replication_sequence_number");
|
||||
const std::string osmosis_replication_sequence_number{header.get("osmosis_replication_sequence_number")};
|
||||
if (!osmosis_replication_sequence_number.empty()) {
|
||||
pbf_header_block.add_int64(OSMFormat::HeaderBlock::optional_int64_osmosis_replication_sequence_number, std::atoll(osmosis_replication_sequence_number.c_str()));
|
||||
}
|
||||
|
||||
const std::string osmosis_replication_base_url = header.get("osmosis_replication_base_url");
|
||||
const std::string osmosis_replication_base_url{header.get("osmosis_replication_base_url")};
|
||||
if (!osmosis_replication_base_url.empty()) {
|
||||
pbf_header_block.add_string(OSMFormat::HeaderBlock::optional_string_osmosis_replication_base_url, osmosis_replication_base_url);
|
||||
}
|
||||
|
||||
m_output_queue.push(osmium::thread::Pool::instance().submit(
|
||||
m_output_queue.push(m_pool.submit(
|
||||
SerializeBlob{std::move(data),
|
||||
pbf_blob_type::header,
|
||||
m_options.use_compression}
|
||||
@ -567,7 +566,7 @@ namespace osmium {
|
||||
}
|
||||
|
||||
switch_primitive_block_type(OSMFormat::PrimitiveGroup::repeated_Node_nodes);
|
||||
protozero::pbf_builder<OSMFormat::Node> pbf_node{ m_primitive_block.group(), OSMFormat::PrimitiveGroup::repeated_Node_nodes };
|
||||
protozero::pbf_builder<OSMFormat::Node> pbf_node{m_primitive_block.group(), OSMFormat::PrimitiveGroup::repeated_Node_nodes};
|
||||
|
||||
pbf_node.add_sint64(OSMFormat::Node::required_sint64_id, node.id());
|
||||
add_meta(node, pbf_node);
|
||||
@ -578,7 +577,7 @@ namespace osmium {
|
||||
|
||||
void way(const osmium::Way& way) {
|
||||
switch_primitive_block_type(OSMFormat::PrimitiveGroup::repeated_Way_ways);
|
||||
protozero::pbf_builder<OSMFormat::Way> pbf_way{ m_primitive_block.group(), OSMFormat::PrimitiveGroup::repeated_Way_ways };
|
||||
protozero::pbf_builder<OSMFormat::Way> pbf_way{m_primitive_block.group(), OSMFormat::PrimitiveGroup::repeated_Way_ways};
|
||||
|
||||
pbf_way.add_int64(OSMFormat::Way::required_int64_id, way.id());
|
||||
add_meta(way, pbf_way);
|
||||
@ -611,7 +610,7 @@ namespace osmium {
|
||||
|
||||
void relation(const osmium::Relation& relation) {
|
||||
switch_primitive_block_type(OSMFormat::PrimitiveGroup::repeated_Relation_relations);
|
||||
protozero::pbf_builder<OSMFormat::Relation> pbf_relation { m_primitive_block.group(), OSMFormat::PrimitiveGroup::repeated_Relation_relations };
|
||||
protozero::pbf_builder<OSMFormat::Relation> pbf_relation{m_primitive_block.group(), OSMFormat::PrimitiveGroup::repeated_Relation_relations};
|
||||
|
||||
pbf_relation.add_int64(OSMFormat::Relation::required_int64_id, relation.id());
|
||||
add_meta(relation, pbf_relation);
|
||||
@ -644,8 +643,8 @@ namespace osmium {
|
||||
// we want the register_output_format() function to run, setting
|
||||
// the variable is only a side-effect, it will never be used
|
||||
const bool registered_pbf_output = osmium::io::detail::OutputFormatFactory::instance().register_output_format(osmium::io::file_format::pbf,
|
||||
[](const osmium::io::File& file, future_string_queue_type& output_queue) {
|
||||
return new osmium::io::detail::PBFOutputFormat(file, output_queue);
|
||||
[](osmium::thread::Pool& pool, const osmium::io::File& file, future_string_queue_type& output_queue) {
|
||||
return new osmium::io::detail::PBFOutputFormat{pool, file, output_queue};
|
||||
});
|
||||
|
||||
// dummy function to silence the unused variable warning from above
|
||||
|
@ -85,7 +85,7 @@ namespace osmium {
|
||||
#endif
|
||||
const int fd = ::open(filename.c_str(), flags, 0666);
|
||||
if (fd < 0) {
|
||||
throw std::system_error(errno, std::system_category(), std::string("Open failed for '") + filename + "'");
|
||||
throw std::system_error{errno, std::system_category(), std::string("Open failed for '") + filename + "'"};
|
||||
}
|
||||
return fd;
|
||||
}
|
||||
@ -109,7 +109,7 @@ namespace osmium {
|
||||
#endif
|
||||
const int fd = ::open(filename.c_str(), flags);
|
||||
if (fd < 0) {
|
||||
throw std::system_error(errno, std::system_category(), std::string("Open failed for '") + filename + "'");
|
||||
throw std::system_error{errno, std::system_category(), std::string("Open failed for '") + filename + "'"};
|
||||
}
|
||||
return fd;
|
||||
}
|
||||
@ -134,7 +134,7 @@ namespace osmium {
|
||||
}
|
||||
const auto length = ::write(fd, output_buffer + offset, static_cast<unsigned int>(write_count));
|
||||
if (length < 0) {
|
||||
throw std::system_error(errno, std::system_category(), "Write failed");
|
||||
throw std::system_error{errno, std::system_category(), "Write failed"};
|
||||
}
|
||||
offset += static_cast<size_t>(length);
|
||||
} while (offset < size);
|
||||
@ -160,13 +160,13 @@ namespace osmium {
|
||||
#else
|
||||
if (::fsync(fd) != 0) {
|
||||
#endif
|
||||
throw std::system_error(errno, std::system_category(), "Fsync failed");
|
||||
throw std::system_error{errno, std::system_category(), "Fsync failed"};
|
||||
}
|
||||
}
|
||||
|
||||
inline void reliable_close(const int fd) {
|
||||
if (::close(fd) != 0) {
|
||||
throw std::system_error(errno, std::system_category(), "Close failed");
|
||||
throw std::system_error{errno, std::system_category(), "Close failed"};
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -136,8 +136,12 @@ namespace osmium {
|
||||
const_iterator& operator++() {
|
||||
assert(m_it != m_last);
|
||||
const auto last_pos = m_it->c_str() + m_it->size();
|
||||
while (m_pos != last_pos && *m_pos) ++m_pos;
|
||||
if (m_pos != last_pos) ++m_pos;
|
||||
while (m_pos != last_pos && *m_pos) {
|
||||
++m_pos;
|
||||
}
|
||||
if (m_pos != last_pos) {
|
||||
++m_pos;
|
||||
}
|
||||
if (m_pos == last_pos) {
|
||||
++m_it;
|
||||
if (m_it != m_last) {
|
||||
@ -150,7 +154,7 @@ namespace osmium {
|
||||
}
|
||||
|
||||
const_iterator operator++(int) {
|
||||
const_iterator tmp(*this);
|
||||
const_iterator tmp{*this};
|
||||
operator++();
|
||||
return tmp;
|
||||
}
|
||||
@ -175,11 +179,11 @@ namespace osmium {
|
||||
if (m_chunks.front().empty()) {
|
||||
return end();
|
||||
}
|
||||
return const_iterator(m_chunks.begin(), m_chunks.end());
|
||||
return {m_chunks.begin(), m_chunks.end()};
|
||||
}
|
||||
|
||||
const_iterator end() const {
|
||||
return const_iterator(m_chunks.end(), m_chunks.end());
|
||||
return {m_chunks.end(), m_chunks.end()};
|
||||
}
|
||||
|
||||
// These functions get you some idea how much memory was
|
||||
@ -273,7 +277,7 @@ namespace osmium {
|
||||
m_index[cs] = ++m_size;
|
||||
|
||||
if (m_size > max_entries) {
|
||||
throw osmium::pbf_error("string table has too many entries");
|
||||
throw osmium::pbf_error{"string table has too many entries"};
|
||||
}
|
||||
|
||||
return m_size;
|
||||
|
@ -134,10 +134,10 @@ namespace osmium {
|
||||
// Write out the value with four or more hex digits.
|
||||
inline void append_min_4_hex_digits(std::string& out, uint32_t value, const char* const hex_digits) {
|
||||
auto
|
||||
v = value & 0xf0000000; if (v) out += hex_digits[v >> 28];
|
||||
v = value & 0x0f000000; if (v) out += hex_digits[v >> 24];
|
||||
v = value & 0x00f00000; if (v) out += hex_digits[v >> 20];
|
||||
v = value & 0x000f0000; if (v) out += hex_digits[v >> 16];
|
||||
v = value & 0xf0000000; if (v) { out += hex_digits[v >> 28]; }
|
||||
v = value & 0x0f000000; if (v) { out += hex_digits[v >> 24]; }
|
||||
v = value & 0x00f00000; if (v) { out += hex_digits[v >> 20]; }
|
||||
v = value & 0x000f0000; if (v) { out += hex_digits[v >> 16]; }
|
||||
|
||||
out += hex_digits[(value >> 12) & 0xf];
|
||||
out += hex_digits[(value >> 8) & 0xf];
|
||||
@ -181,7 +181,7 @@ namespace osmium {
|
||||
|
||||
inline void append_xml_encoded_string(std::string& out, const char* data) {
|
||||
for (; *data != '\0'; ++data) {
|
||||
switch(*data) {
|
||||
switch (*data) {
|
||||
case '&': out += "&"; break;
|
||||
case '\"': out += """; break;
|
||||
case '\'': out += "'"; break;
|
||||
|
@ -33,11 +33,11 @@ DEALINGS IN THE SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
#include <algorithm>
|
||||
#include <exception>
|
||||
#include <future>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
#include <osmium/io/compression.hpp>
|
||||
#include <osmium/io/detail/queue_util.hpp>
|
||||
@ -83,7 +83,7 @@ namespace osmium {
|
||||
|
||||
try {
|
||||
while (true) {
|
||||
std::string data = m_queue.pop();
|
||||
const std::string data{m_queue.pop()};
|
||||
if (at_end_of_data(data)) {
|
||||
break;
|
||||
}
|
||||
|
@ -444,12 +444,14 @@ namespace osmium {
|
||||
|
||||
item_type type = item_type::undefined;
|
||||
object_id_type ref = 0;
|
||||
bool ref_is_set = false;
|
||||
const char* role = "";
|
||||
check_attributes(attrs, [&type, &ref, &role](const XML_Char* name, const XML_Char* value) {
|
||||
check_attributes(attrs, [&](const XML_Char* name, const XML_Char* value) {
|
||||
if (!std::strcmp(name, "type")) {
|
||||
type = char_to_item_type(value[0]);
|
||||
} else if (!std::strcmp(name, "ref")) {
|
||||
ref = osmium::string_to_object_id(value);
|
||||
ref_is_set = true;
|
||||
} else if (!std::strcmp(name, "role")) {
|
||||
role = static_cast<const char*>(value);
|
||||
}
|
||||
@ -457,7 +459,7 @@ namespace osmium {
|
||||
if (type != item_type::node && type != item_type::way && type != item_type::relation) {
|
||||
throw osmium::xml_error{"Unknown type on relation member"};
|
||||
}
|
||||
if (ref == 0) {
|
||||
if (!ref_is_set) {
|
||||
throw osmium::xml_error{"Missing ref on relation member"};
|
||||
}
|
||||
m_rml_builder->add_member(type, ref, role);
|
||||
@ -625,11 +627,8 @@ namespace osmium {
|
||||
|
||||
public:
|
||||
|
||||
XMLParser(future_string_queue_type& input_queue,
|
||||
future_buffer_queue_type& output_queue,
|
||||
std::promise<osmium::io::Header>& header_promise,
|
||||
osmium::io::detail::reader_options options) :
|
||||
Parser(input_queue, output_queue, header_promise, options),
|
||||
explicit XMLParser(parser_arguments& args) :
|
||||
Parser(args),
|
||||
m_context(context::root),
|
||||
m_last_context(context::root),
|
||||
m_in_delete_section(false),
|
||||
@ -673,11 +672,8 @@ namespace osmium {
|
||||
// the variable is only a side-effect, it will never be used
|
||||
const bool registered_xml_parser = ParserFactory::instance().register_parser(
|
||||
file_format::xml,
|
||||
[](future_string_queue_type& input_queue,
|
||||
future_buffer_queue_type& output_queue,
|
||||
std::promise<osmium::io::Header>& header_promise,
|
||||
osmium::io::detail::reader_options options) {
|
||||
return std::unique_ptr<Parser>(new XMLParser{input_queue, output_queue, header_promise, options});
|
||||
[](parser_arguments& args) {
|
||||
return std::unique_ptr<Parser>(new XMLParser{args});
|
||||
});
|
||||
|
||||
// dummy function to silence the unused variable warning from above
|
||||
|
@ -33,7 +33,6 @@ DEALINGS IN THE SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
@ -397,7 +396,8 @@ namespace osmium {
|
||||
write_attribute("uid", changeset.uid());
|
||||
}
|
||||
|
||||
if (changeset.bounds()) {
|
||||
if (!changeset.bounds().bottom_left().is_undefined() ||
|
||||
!changeset.bounds().top_right().is_undefined()) {
|
||||
detail::append_lat_lon_attributes(*m_out, "min_lat", "min_lon", changeset.bounds().bottom_left());
|
||||
detail::append_lat_lon_attributes(*m_out, "max_lat", "max_lon", changeset.bounds().top_right());
|
||||
}
|
||||
@ -431,8 +431,8 @@ namespace osmium {
|
||||
|
||||
public:
|
||||
|
||||
XMLOutputFormat(const osmium::io::File& file, future_string_queue_type& output_queue) :
|
||||
OutputFormat(output_queue),
|
||||
XMLOutputFormat(osmium::thread::Pool& pool, const osmium::io::File& file, future_string_queue_type& output_queue) :
|
||||
OutputFormat(pool, output_queue),
|
||||
m_options() {
|
||||
m_options.add_metadata = file.is_not_false("add_metadata");
|
||||
m_options.use_change_ops = file.is_true("xml_change_format");
|
||||
@ -446,14 +446,14 @@ namespace osmium {
|
||||
~XMLOutputFormat() noexcept final = default;
|
||||
|
||||
void write_header(const osmium::io::Header& header) final {
|
||||
std::string out = "<?xml version='1.0' encoding='UTF-8'?>\n";
|
||||
std::string out{"<?xml version='1.0' encoding='UTF-8'?>\n"};
|
||||
|
||||
if (m_options.use_change_ops) {
|
||||
out += "<osmChange version=\"0.6\" generator=\"";
|
||||
} else {
|
||||
out += "<osm version=\"0.6\"";
|
||||
|
||||
std::string xml_josm_upload = header.get("xml_josm_upload");
|
||||
const std::string xml_josm_upload{header.get("xml_josm_upload")};
|
||||
if (xml_josm_upload == "true" || xml_josm_upload == "false") {
|
||||
out += " upload=\"";
|
||||
out += xml_josm_upload;
|
||||
@ -475,7 +475,7 @@ namespace osmium {
|
||||
}
|
||||
|
||||
void write_buffer(osmium::memory::Buffer&& buffer) final {
|
||||
m_output_queue.push(osmium::thread::Pool::instance().submit(XMLOutputBlock{std::move(buffer), m_options}));
|
||||
m_output_queue.push(m_pool.submit(XMLOutputBlock{std::move(buffer), m_options}));
|
||||
}
|
||||
|
||||
void write_end() final {
|
||||
@ -495,8 +495,8 @@ namespace osmium {
|
||||
// we want the register_output_format() function to run, setting
|
||||
// the variable is only a side-effect, it will never be used
|
||||
const bool registered_xml_output = osmium::io::detail::OutputFormatFactory::instance().register_output_format(osmium::io::file_format::xml,
|
||||
[](const osmium::io::File& file, future_string_queue_type& output_queue) {
|
||||
return new osmium::io::detail::XMLOutputFormat(file, output_queue);
|
||||
[](osmium::thread::Pool& pool, const osmium::io::File& file, future_string_queue_type& output_queue) {
|
||||
return new osmium::io::detail::XMLOutputFormat(pool, file, output_queue);
|
||||
});
|
||||
|
||||
// dummy function to silence the unused variable warning from above
|
||||
|
@ -70,7 +70,7 @@ namespace osmium {
|
||||
);
|
||||
|
||||
if (result != Z_OK) {
|
||||
throw io_error(std::string("failed to compress data: ") + zError(result));
|
||||
throw io_error{std::string{"failed to compress data: "} + zError(result)};
|
||||
}
|
||||
|
||||
output.resize(output_size);
|
||||
@ -100,7 +100,7 @@ namespace osmium {
|
||||
);
|
||||
|
||||
if (result != Z_OK) {
|
||||
throw io_error(std::string("failed to uncompress data: ") + zError(result));
|
||||
throw io_error{std::string{"failed to uncompress data: "} + zError(result)};
|
||||
}
|
||||
|
||||
return protozero::data_view{output.data(), output.size()};
|
||||
|
35
third_party/libosmium/include/osmium/io/file.hpp
vendored
35
third_party/libosmium/include/osmium/io/file.hpp
vendored
@ -113,7 +113,7 @@ namespace osmium {
|
||||
}
|
||||
|
||||
// if filename is a URL, default to XML format
|
||||
const std::string protocol = m_filename.substr(0, m_filename.find_first_of(':'));
|
||||
const std::string protocol{m_filename.substr(0, m_filename.find_first_of(':'))};
|
||||
if (protocol == "http" || protocol == "https") {
|
||||
m_file_format = file_format::xml;
|
||||
}
|
||||
@ -176,7 +176,7 @@ namespace osmium {
|
||||
if (pos == std::string::npos) {
|
||||
set(option, true);
|
||||
} else {
|
||||
std::string value = option.substr(pos+1);
|
||||
std::string value{option.substr(pos+1)};
|
||||
option.erase(pos);
|
||||
set(option, value);
|
||||
}
|
||||
@ -192,7 +192,9 @@ namespace osmium {
|
||||
void detect_format_from_suffix(const std::string& name) {
|
||||
std::vector<std::string> suffixes = detail::split(name, '.');
|
||||
|
||||
if (suffixes.empty()) return;
|
||||
if (suffixes.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// if the last suffix is one of a known set of compressions,
|
||||
// set that compression
|
||||
@ -204,7 +206,9 @@ namespace osmium {
|
||||
suffixes.pop_back();
|
||||
}
|
||||
|
||||
if (suffixes.empty()) return;
|
||||
if (suffixes.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// if the last suffix is one of a known set of formats,
|
||||
// set that format
|
||||
@ -231,19 +235,30 @@ namespace osmium {
|
||||
} else if (suffixes.back() == "debug") {
|
||||
m_file_format = file_format::debug;
|
||||
suffixes.pop_back();
|
||||
} else if (suffixes.back() == "blackhole") {
|
||||
m_file_format = file_format::blackhole;
|
||||
suffixes.pop_back();
|
||||
}
|
||||
|
||||
if (suffixes.empty()) return;
|
||||
if (suffixes.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (suffixes.back() == "osm") {
|
||||
if (m_file_format == file_format::unknown) m_file_format = file_format::xml;
|
||||
if (m_file_format == file_format::unknown) {
|
||||
m_file_format = file_format::xml;
|
||||
}
|
||||
suffixes.pop_back();
|
||||
} else if (suffixes.back() == "osh") {
|
||||
if (m_file_format == file_format::unknown) m_file_format = file_format::xml;
|
||||
if (m_file_format == file_format::unknown) {
|
||||
m_file_format = file_format::xml;
|
||||
}
|
||||
m_has_multiple_object_versions = true;
|
||||
suffixes.pop_back();
|
||||
} else if (suffixes.back() == "osc") {
|
||||
if (m_file_format == file_format::unknown) m_file_format = file_format::xml;
|
||||
if (m_file_format == file_format::unknown) {
|
||||
m_file_format = file_format::xml;
|
||||
}
|
||||
m_has_multiple_object_versions = true;
|
||||
set("xml_change_format", true);
|
||||
suffixes.pop_back();
|
||||
@ -258,7 +273,7 @@ namespace osmium {
|
||||
*/
|
||||
const File& check() const {
|
||||
if (m_file_format == file_format::unknown) {
|
||||
std::string msg = "Could not detect file format";
|
||||
std::string msg{"Could not detect file format"};
|
||||
if (!m_format_string.empty()) {
|
||||
msg += " from format string '";
|
||||
msg += m_format_string;
|
||||
@ -272,7 +287,7 @@ namespace osmium {
|
||||
msg += "'";
|
||||
}
|
||||
msg += ".";
|
||||
throw io_error(msg);
|
||||
throw io_error{msg};
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user