Merge commit '788bc67faa7738cf7c6b2a192ecf3e3567d1c20e' into develop
This commit is contained in:
commit
048be2da2c
75
third_party/libosmium/.travis.yml
vendored
75
third_party/libosmium/.travis.yml
vendored
@ -6,46 +6,49 @@
|
||||
|
||||
language: cpp
|
||||
|
||||
compiler:
|
||||
- gcc
|
||||
- clang
|
||||
sudo: false
|
||||
|
||||
env:
|
||||
- CONFIGURATION=Dev
|
||||
- CONFIGURATION=Release
|
||||
matrix:
|
||||
include:
|
||||
- os: linux
|
||||
compiler: clang
|
||||
env: BUILD_TYPE=Dev
|
||||
- os: linux
|
||||
compiler: clang
|
||||
env: BUILD_TYPE=Release
|
||||
- os: linux
|
||||
compiler: gcc
|
||||
env: BUILD_TYPE=Dev
|
||||
- os: linux
|
||||
compiler: gcc
|
||||
env: BUILD_TYPE=Release
|
||||
- os: osx
|
||||
compiler: clang
|
||||
env: BUILD_TYPE=Dev
|
||||
- os: osx
|
||||
compiler: clang
|
||||
env: BUILD_TYPE=Release
|
||||
|
||||
before_install:
|
||||
# we need at least g++-4.8 for c++11 features
|
||||
- sudo add-apt-repository --yes ppa:ubuntu-toolchain-r/test
|
||||
- sudo apt-get update --yes --quiet
|
||||
# http://docs.travis-ci.com/user/apt/
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- boost-latest
|
||||
- ubuntu-toolchain-r-test
|
||||
packages:
|
||||
- g++-4.8
|
||||
- gcc-4.8
|
||||
- libboost1.55-dev
|
||||
- libboost-program-options1.55-dev
|
||||
- libgdal-dev
|
||||
- libgeos++-dev
|
||||
- libproj-dev
|
||||
- libsparsehash-dev
|
||||
- spatialite-bin
|
||||
|
||||
install:
|
||||
- cd ..
|
||||
# upgrade compilers
|
||||
- sudo apt-get install --yes gcc-4.8 g++-4.8
|
||||
# make sure 'cpp' is the just installed current one
|
||||
- sudo rm /usr/bin/cpp
|
||||
- sudo ln -s /usr/bin/cpp-4.8 /usr/bin/cpp
|
||||
# upgrade libosmium dependencies
|
||||
- sudo apt-get install --yes make libboost-dev libboost-program-options-dev libsparsehash-dev libprotobuf-dev protobuf-compiler libgeos++-dev libproj-dev libgdal1h libgdal-dev
|
||||
- git clone https://github.com/osmcode/osm-testdata.git
|
||||
# OSMPBF is too old, install from git
|
||||
#- sudo apt-get install --yes libosmpbf-dev
|
||||
- git clone https://github.com/scrosby/OSM-binary.git
|
||||
- cd OSM-binary/src
|
||||
- make
|
||||
- sudo make install
|
||||
- cd ../..
|
||||
- cd libosmium
|
||||
|
||||
before_script:
|
||||
- true
|
||||
- scripts/travis_install.sh
|
||||
|
||||
script:
|
||||
- if [ "${CXX}" = 'g++' ]; then export CXX=g++-4.8; fi;
|
||||
- mkdir build
|
||||
- cd build
|
||||
- cmake -LA -DCMAKE_BUILD_TYPE=${CONFIGURATION} ..
|
||||
- make VERBOSE=1
|
||||
- ctest --output-on-failure
|
||||
- scripts/travis_script.sh
|
||||
|
||||
|
86
third_party/libosmium/CHANGELOG.md
vendored
86
third_party/libosmium/CHANGELOG.md
vendored
@ -6,6 +6,88 @@ This project adheres to [Semantic Versioning](http://semver.org/).
|
||||
|
||||
## [unreleased] -
|
||||
|
||||
### Added
|
||||
|
||||
### Changed
|
||||
|
||||
### Fixed
|
||||
|
||||
## [2.3.0] - 2015-08-18
|
||||
|
||||
### Added
|
||||
|
||||
- Allow instantiating osmium::geom::GEOSFactory with existing GEOS factory.
|
||||
- Low-level functions to support generating a architecture- and endian-
|
||||
independant CRC from OSM data. This is intended to be uses with boost::crc.
|
||||
- Add new debug output format. This format is not intended to be read
|
||||
automatically, but for human consumption. It formats the data nicely.
|
||||
- Make writing of metadata configurable for XML and OPL output (use
|
||||
`add_metadata=false` as file option).
|
||||
|
||||
### Changed
|
||||
|
||||
- Changed `add_user()` and `add_role()` in builders to use string length
|
||||
without the 0-termination.
|
||||
- Improved code setting file format from suffix/format argument.
|
||||
- Memory mapping utility class now supports readonly, private writable or
|
||||
shared writable operation.
|
||||
- Allow empty version (0) in PBF files.
|
||||
- Use utf8cpp header-only lib instead of boost for utf8 decoding. The library
|
||||
is included in the libosmium distribution.
|
||||
- New PBF reader and writer based on the protozero. A complete rewrite of the
|
||||
code for reading and writing OSM PBF files. It doesn't use the Google
|
||||
protobuf library and it doesn't use the OSMPBF/OSM-Binary library any more.
|
||||
Instead is uses the protozero lightweight protobuf header library which is
|
||||
included in the code. Not only does the new code have less dependencies, it
|
||||
is faster and more robust. https://github.com/mapbox/protozero
|
||||
|
||||
### Fixed
|
||||
|
||||
- Various smaller bug fixes.
|
||||
- Add encoding for relation member roles in OPL format.
|
||||
- Change character encoding to new format in OPL: variable length hex code
|
||||
between % characters instead of a % followed by 4-digit hex code. This is
|
||||
necessary because unicode characters can be longer than the 4-digit hex
|
||||
code.
|
||||
- XML writer: The linefeed, carriage return, and tab characters are now
|
||||
escaped properly.
|
||||
- Reading large XML files could block.
|
||||
|
||||
## [2.2.0] - 2015-07-04
|
||||
|
||||
### Added
|
||||
|
||||
- Conversion functions for some low-level types.
|
||||
- BoolVector index class.
|
||||
- `min_op`/`max_op` utility functions.
|
||||
- More tests here and there.
|
||||
- Helper methods `is_between()` and `is_visible_at()` to DiffObject.
|
||||
- GeoJSON factory using the RapidJSON library.
|
||||
- Support for tile calculations.
|
||||
- Create simple polygons from ways in geom factories.
|
||||
- `MemoryMapping` and `TypedMemoryMapping` helper classes.
|
||||
- `close()` function to `mmap_vector_base` class.
|
||||
- Function on `Buffer` class to get iterator to specific offset.
|
||||
- Explicit cast operator from `osmium::Timestamp` to `uint32_t`.
|
||||
|
||||
### Changed
|
||||
|
||||
- Throw exception on illegal values in functions parsing strings to get ids,
|
||||
versions, etc.
|
||||
- Improved error message for geometry exceptions.
|
||||
|
||||
### Fixed
|
||||
|
||||
- Throw exception from `dump_as_array()` and `dump_as_list()` functions if not
|
||||
implemented in an index.
|
||||
- After writing OSM files, program could stall up to a second.
|
||||
- Dense location store was written out only partially.
|
||||
- Use `uint64_t` as counter in benchmarks, so there can be no overflows.
|
||||
- Example programs now read packed XML files, too.
|
||||
- Refactoring of memory mapping code. Removes leak on Windows.
|
||||
- Better check for invalid locations.
|
||||
- Mark `cbegin()` and `cend()` of `mmap_vector_base` as const functions.
|
||||
|
||||
## [2.1.0] - 2015-03-31
|
||||
|
||||
### Added
|
||||
@ -26,6 +108,8 @@ 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.1.0...HEAD
|
||||
[unreleased]: https://github.com/osmcode/libosmium/compare/v2.3.0...HEAD
|
||||
[2.3.0]: https://github.com/osmcode/libosmium/compare/v2.3.0...v2.3.0
|
||||
[2.2.0]: https://github.com/osmcode/libosmium/compare/v2.1.0...v2.2.0
|
||||
[2.1.0]: https://github.com/osmcode/libosmium/compare/v2.0.0...v2.1.0
|
||||
|
||||
|
63
third_party/libosmium/CMakeLists.txt
vendored
63
third_party/libosmium/CMakeLists.txt
vendored
@ -18,7 +18,7 @@ set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
||||
#
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
set(CMAKE_CONFIGURATION_TYPES "Debug;Release;RelWithDebInfo;MinSizeRel;Dev"
|
||||
set(CMAKE_CONFIGURATION_TYPES "Debug;Release;RelWithDebInfo;MinSizeRel;Dev;Coverage"
|
||||
CACHE STRING
|
||||
"List of available configuration types"
|
||||
FORCE)
|
||||
@ -26,11 +26,13 @@ set(CMAKE_CONFIGURATION_TYPES "Debug;Release;RelWithDebInfo;MinSizeRel;Dev"
|
||||
project(libosmium)
|
||||
|
||||
set(LIBOSMIUM_VERSION_MAJOR 2)
|
||||
set(LIBOSMIUM_VERSION_MINOR 1)
|
||||
set(LIBOSMIUM_VERSION_MINOR 3)
|
||||
set(LIBOSMIUM_VERSION_PATCH 0)
|
||||
|
||||
set(LIBOSMIUM_VERSION
|
||||
${LIBOSMIUM_VERSION_MAJOR}.${LIBOSMIUM_VERSION_MINOR}.${LIBOSMIUM_VERSION_PATCH})
|
||||
"${LIBOSMIUM_VERSION_MAJOR}.${LIBOSMIUM_VERSION_MINOR}.${LIBOSMIUM_VERSION_PATCH}"
|
||||
CACHE STRING
|
||||
"Libosmium version")
|
||||
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
@ -55,6 +57,57 @@ option(BUILD_BENCHMARKS "compile benchmark programs" ${dev_build})
|
||||
option(BUILD_DATA_TESTS "compile data tests, please run them with ctest" ${dev_build})
|
||||
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
#
|
||||
# Coverage support
|
||||
#
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
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_}"
|
||||
CACHE STRING "Flags used by the compiler during coverage builds.")
|
||||
|
||||
set(CMAKE_EXE_LINKER_FLAGS_COVERAGE
|
||||
"--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")
|
||||
endif()
|
||||
|
||||
if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
|
||||
string(REGEX REPLACE "^([0-9]+)\\.([0-9]+).*$" "llvm-cov-\\1.\\2"
|
||||
gcov_ ${CMAKE_CXX_COMPILER_VERSION})
|
||||
else()
|
||||
set(gcov_ "gcov")
|
||||
endif()
|
||||
|
||||
find_program(GCOV ${gcov_} DOC "Coverage tool")
|
||||
find_program(GCOVR "gcovr" DOC "Coverage report tool")
|
||||
|
||||
set(coverage_report_dir "${CMAKE_BINARY_DIR}/coverage")
|
||||
file(MAKE_DIRECTORY ${coverage_report_dir})
|
||||
add_custom_target(coverage
|
||||
${GCOVR}
|
||||
${CMAKE_BINARY_DIR}
|
||||
--root=${CMAKE_SOURCE_DIR}
|
||||
--html --html-details
|
||||
#--verbose
|
||||
#--keep
|
||||
'--filter=.*include/osmium.*'
|
||||
--sort-percentage
|
||||
--gcov-executable=${GCOV}
|
||||
--output=${coverage_report_dir}/index.html)
|
||||
endif()
|
||||
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
#
|
||||
# Find external dependencies
|
||||
@ -113,8 +166,10 @@ endif()
|
||||
#-----------------------------------------------------------------------------
|
||||
if(MSVC)
|
||||
set(USUAL_COMPILE_OPTIONS "/Ox")
|
||||
set(USUAL_LINK_OPTIONS "/debug")
|
||||
else()
|
||||
set(USUAL_COMPILE_OPTIONS "-O3 -g")
|
||||
set(USUAL_LINK_OPTIONS "")
|
||||
endif()
|
||||
|
||||
if(WIN32)
|
||||
@ -126,7 +181,7 @@ set(CMAKE_CXX_FLAGS_DEV "${USUAL_COMPILE_OPTIONS}"
|
||||
CACHE STRING "Flags used by the compiler during developer builds."
|
||||
FORCE)
|
||||
|
||||
set(CMAKE_EXE_LINKER_FLAGS_DEV ""
|
||||
set(CMAKE_EXE_LINKER_FLAGS_DEV "${USUAL_LINK_OPTIONS}"
|
||||
CACHE STRING "Flags used by the linker during developer builds."
|
||||
FORCE)
|
||||
mark_as_advanced(
|
||||
|
233
third_party/libosmium/EXTERNAL_LICENSES.txt
vendored
Normal file
233
third_party/libosmium/EXTERNAL_LICENSES.txt
vendored
Normal file
@ -0,0 +1,233 @@
|
||||
|
||||
==== For protozero from https://github.com/mapbox/protozero
|
||||
|
||||
protozero copyright (c) Mapbox.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
==== For protozero from https://github.com/mapbox/protozero
|
||||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
==== For utf8.h
|
||||
|
||||
Copyright 2006 Nemanja Trifunovic
|
||||
|
||||
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.
|
||||
|
4
third_party/libosmium/README.md
vendored
4
third_party/libosmium/README.md
vendored
@ -27,6 +27,10 @@ you need for your programs.
|
||||
For details see the
|
||||
[list of dependencies](https://github.com/osmcode/libosmium/wiki/Libosmium-dependencies).
|
||||
|
||||
The [protozero](https://github.com/mapbox/protozero) and
|
||||
[utf8-cpp](http://utfcpp.sourceforge.net/) header-only libraries are included
|
||||
in the libosmium repository.
|
||||
|
||||
|
||||
## Directories
|
||||
|
||||
|
63
third_party/libosmium/appveyor.yml
vendored
63
third_party/libosmium/appveyor.yml
vendored
@ -15,6 +15,8 @@ branches:
|
||||
only:
|
||||
- master
|
||||
|
||||
shallow_clone: true
|
||||
|
||||
# Operating system (build VM template)
|
||||
os: Visual Studio 2014 CTP4
|
||||
|
||||
@ -27,7 +29,7 @@ clone_folder: c:\projects\libosmium
|
||||
platform: x64
|
||||
|
||||
install:
|
||||
# show all availble env vars
|
||||
# show all available env vars
|
||||
- set
|
||||
- echo cmake on AppVeyor
|
||||
- cmake -version
|
||||
@ -50,8 +52,8 @@ install:
|
||||
#cmake cannot find it otherwise
|
||||
- set LIBBZIP2=%LODEPSDIR%\bzip2\lib\libbz2.lib
|
||||
- set LIBBZIP2=%LIBBZIP2:\=/%
|
||||
- ps: Start-FileDownload https://mapnik.s3.amazonaws.com/deps/cmake-3.1.0-win32-x86.7z -FileName cm.7z
|
||||
- ps: Start-FileDownload https://mapnik.s3.amazonaws.com/dist/dev/libosmium-deps-win-14.0-x64.7z -FileName lodeps.7z
|
||||
- ps: Start-FileDownload https://mapbox.s3.amazonaws.com/windows-builds/windows-build-deps/cmake-3.1.0-win32-x86.7z -FileName cm.7z
|
||||
- ps: Start-FileDownload https://mapbox.s3.amazonaws.com/windows-builds/windows-build-deps/libosmium-deps-win-14.0-x64.7z -FileName lodeps.7z
|
||||
- 7z x cm.7z | %windir%\system32\find "ing archive"
|
||||
- 7z x lodeps.7z | %windir%\system32\find "ing archive"
|
||||
- echo %LODEPSDIR%
|
||||
@ -59,19 +61,64 @@ install:
|
||||
- echo our own cmake
|
||||
- cmake -version
|
||||
- cd c:\projects
|
||||
- git clone https://github.com/osmcode/osm-testdata.git
|
||||
- git clone --depth 1 https://github.com/osmcode/osm-testdata.git
|
||||
|
||||
build_script:
|
||||
- cd c:\projects\libosmium
|
||||
- mkdir build
|
||||
- cd build
|
||||
- echo %config%
|
||||
- cmake .. -LA -G "Visual Studio 14 Win64" -DOsmium_DEBUG=TRUE -DCMAKE_BUILD_TYPE=%config% -DBUILD_BENCHMARKS=OFF -DBOOST_ROOT=%LODEPSDIR%\boost -DBoost_PROGRAM_OPTIONS_LIBRARY=%LODEPSDIR%\boost\lib\libboost_program_options-vc140-mt-1_57.lib -DOSMPBF_LIBRARY=%LODEPSDIR%\osmpbf\lib\osmpbf.lib -DOSMPBF_INCLUDE_DIR=%LODEPSDIR%\osmpbf\include -DPROTOBUF_LIBRARY=%LODEPSDIR%\protobuf\lib\libprotobuf.lib -DPROTOBUF_LITE_LIBRARY=%LODEPSDIR%\protobuf\lib\libprotobuf-lite.lib -DPROTOBUF_INCLUDE_DIR=%LODEPSDIR%\protobuf\include -DZLIB_LIBRARY=%LODEPSDIR%\zlib\lib\zlibwapi.lib -DZLIB_INCLUDE_DIR=%LODEPSDIR%\zlib\include -DEXPAT_LIBRARY=%LODEPSDIR%\expat\lib\libexpat.lib -DEXPAT_INCLUDE_DIR=%LODEPSDIR%\expat\include -DBZIP2_LIBRARIES=%LIBBZIP2% -DBZIP2_INCLUDE_DIR=%LODEPSDIR%\bzip2\include -DGDAL_LIBRARY=%LODEPSDIR%\gdal\lib\gdal_i.lib -DGDAL_INCLUDE_DIR=%LODEPSDIR%\gdal\include -DGEOS_LIBRARY=%LODEPSDIR%\geos\lib\geos.lib -DGEOS_INCLUDE_DIR=%LODEPSDIR%\geos\include -DPROJ_LIBRARY=%LODEPSDIR%\proj\lib\proj.lib -DPROJ_INCLUDE_DIR=%LODEPSDIR%\proj\include -DSPARSEHASH_INCLUDE_DIR=%LODEPSDIR%\sparsehash\include -DGETOPT_LIBRARY=%LODEPSDIR%\wingetopt\lib\wingetopt.lib -DGETOPT_INCLUDE_DIR=%LODEPSDIR%\wingetopt\include
|
||||
# This will produce lots of LNK4099 warnings which can be ignored.
|
||||
# Unfortunately they can't be disabled, see
|
||||
# http://stackoverflow.com/questions/661606/visual-c-how-to-disable-specific-linker-warnings
|
||||
- cmake .. -LA -G "Visual Studio 14 Win64"
|
||||
-DOsmium_DEBUG=TRUE
|
||||
-DCMAKE_BUILD_TYPE=%config%
|
||||
-DBUILD_HEADERS=OFF
|
||||
-DBOOST_ROOT=%LODEPSDIR%\boost
|
||||
-DBoost_PROGRAM_OPTIONS_LIBRARY=%LODEPSDIR%\boost\lib\libboost_program_options-vc140-mt-1_57.lib
|
||||
-DZLIB_LIBRARY=%LODEPSDIR%\zlib\lib\zlibwapi.lib
|
||||
-DZLIB_INCLUDE_DIR=%LODEPSDIR%\zlib\include
|
||||
-DEXPAT_LIBRARY=%LODEPSDIR%\expat\lib\libexpat.lib
|
||||
-DEXPAT_INCLUDE_DIR=%LODEPSDIR%\expat\include
|
||||
-DBZIP2_LIBRARIES=%LIBBZIP2%
|
||||
-DBZIP2_INCLUDE_DIR=%LODEPSDIR%\bzip2\include
|
||||
-DGDAL_LIBRARY=%LODEPSDIR%\gdal\lib\gdal_i.lib
|
||||
-DGDAL_INCLUDE_DIR=%LODEPSDIR%\gdal\include
|
||||
-DGEOS_LIBRARY=%LODEPSDIR%\geos\lib\geos.lib
|
||||
-DGEOS_INCLUDE_DIR=%LODEPSDIR%\geos\include
|
||||
-DPROJ_LIBRARY=%LODEPSDIR%\proj\lib\proj.lib
|
||||
-DPROJ_INCLUDE_DIR=%LODEPSDIR%\proj\include
|
||||
-DSPARSEHASH_INCLUDE_DIR=%LODEPSDIR%\sparsehash\include
|
||||
-DGETOPT_LIBRARY=%LODEPSDIR%\wingetopt\lib\wingetopt.lib
|
||||
-DGETOPT_INCLUDE_DIR=%LODEPSDIR%\wingetopt\include
|
||||
- msbuild libosmium.sln /p:Configuration=%config% /toolsversion:14.0 /p:Platform=x64 /p:PlatformToolset=v140
|
||||
#- cmake .. -LA -G "NMake Makefiles" -DOsmium_DEBUG=TRUE -DCMAKE_BUILD_TYPE=%config% -DBOOST_ROOT=%LODEPSDIR%\boost -DBoost_PROGRAM_OPTIONS_LIBRARY=%LODEPSDIR%\boost\lib\libboost_program_options-vc140-mt-1_57.lib -DOSMPBF_LIBRARY=%LODEPSDIR%\osmpbf\lib\osmpbf.lib -DOSMPBF_INCLUDE_DIR=%LODEPSDIR%\osmpbf\include -DPROTOBUF_LIBRARY=%LODEPSDIR%\protobuf\lib\libprotobuf.lib -DPROTOBUF_LITE_LIBRARY=%LODEPSDIR%\protobuf\lib\libprotobuf-lite.lib -DPROTOBUF_INCLUDE_DIR=%LODEPSDIR%\protobuf\include -DZLIB_LIBRARY=%LODEPSDIR%\zlib\lib\zlibwapi.lib -DZLIB_INCLUDE_DIR=%LODEPSDIR%\zlib\include -DEXPAT_LIBRARY=%LODEPSDIR%\expat\lib\libexpat.lib -DEXPAT_INCLUDE_DIR=%LODEPSDIR%\expat\include -DBZIP2_LIBRARIES=%LIBBZIP2% -DBZIP2_INCLUDE_DIR=%LODEPSDIR%\bzip2\include -DGDAL_LIBRARY=%LODEPSDIR%\gdal\lib\gdal_i.lib -DGDAL_INCLUDE_DIR=%LODEPSDIR%\gdal\include -DGEOS_LIBRARY=%LODEPSDIR%\geos\lib\geos.lib -DGEOS_INCLUDE_DIR=%LODEPSDIR%\geos\include -DPROJ_LIBRARY=%LODEPSDIR%\proj\lib\proj.lib -DPROJ_INCLUDE_DIR=%LODEPSDIR%\proj\include -DSPARSEHASH_INCLUDE_DIR=%LODEPSDIR%\sparsehash\include -DGETOPT_LIBRARY=%LODEPSDIR%\wingetopt\lib\wingetopt.lib -DGETOPT_INCLUDE_DIR=%LODEPSDIR%\wingetopt\include
|
||||
#- cmake .. -LA -G "NMake Makefiles"
|
||||
# -DOsmium_DEBUG=TRUE
|
||||
# -DCMAKE_BUILD_TYPE=%config%
|
||||
# -DBOOST_ROOT=%LODEPSDIR%\boost
|
||||
# -DBoost_PROGRAM_OPTIONS_LIBRARY=%LODEPSDIR%\boost\lib\libboost_program_options-vc140-mt-1_57.lib
|
||||
# -DZLIB_LIBRARY=%LODEPSDIR%\zlib\lib\zlibwapi.lib
|
||||
# -DZLIB_INCLUDE_DIR=%LODEPSDIR%\zlib\include
|
||||
# -DEXPAT_LIBRARY=%LODEPSDIR%\expat\lib\libexpat.lib
|
||||
# -DEXPAT_INCLUDE_DIR=%LODEPSDIR%\expat\include
|
||||
# -DBZIP2_LIBRARIES=%LIBBZIP2%
|
||||
# -DBZIP2_INCLUDE_DIR=%LODEPSDIR%\bzip2\include
|
||||
# -DGDAL_LIBRARY=%LODEPSDIR%\gdal\lib\gdal_i.lib
|
||||
# -DGDAL_INCLUDE_DIR=%LODEPSDIR%\gdal\include
|
||||
# -DGEOS_LIBRARY=%LODEPSDIR%\geos\lib\geos.lib
|
||||
# -DGEOS_INCLUDE_DIR=%LODEPSDIR%\geos\include
|
||||
# -DPROJ_LIBRARY=%LODEPSDIR%\proj\lib\proj.lib
|
||||
# -DPROJ_INCLUDE_DIR=%LODEPSDIR%\proj\include
|
||||
# -DSPARSEHASH_INCLUDE_DIR=%LODEPSDIR%\sparsehash\include
|
||||
# -DGETOPT_LIBRARY=%LODEPSDIR%\wingetopt\lib\wingetopt.lib
|
||||
# -DGETOPT_INCLUDE_DIR=%LODEPSDIR%\wingetopt\include
|
||||
#- nmake
|
||||
|
||||
test_script:
|
||||
# -LE fails_on_windows exempts tests we know will fail
|
||||
- ctest --output-on-failure -C %config% -LE fails_on_windows
|
||||
# "-E testdata-overview" exempts one test we know fails on Appveyor
|
||||
# because we currently don't have spatialite support.
|
||||
- ctest --output-on-failure
|
||||
-C %config%
|
||||
-E testdata-overview
|
||||
|
||||
|
@ -13,6 +13,7 @@ set(BENCHMARKS
|
||||
count_tag
|
||||
index_map
|
||||
static_vs_dynamic_index
|
||||
write_pbf
|
||||
CACHE STRING "Benchmark programs"
|
||||
)
|
||||
|
||||
|
@ -4,6 +4,7 @@
|
||||
|
||||
*/
|
||||
|
||||
#include <cstdint>
|
||||
#include <iostream>
|
||||
|
||||
#include <osmium/io/any_input.hpp>
|
||||
@ -12,9 +13,9 @@
|
||||
|
||||
struct CountHandler : public osmium::handler::Handler {
|
||||
|
||||
int nodes = 0;
|
||||
int ways = 0;
|
||||
int relations = 0;
|
||||
uint64_t nodes = 0;
|
||||
uint64_t ways = 0;
|
||||
uint64_t relations = 0;
|
||||
|
||||
void node(osmium::Node&) {
|
||||
++nodes;
|
||||
@ -48,7 +49,5 @@ int main(int argc, char* argv[]) {
|
||||
std::cout << "Nodes: " << handler.nodes << "\n";
|
||||
std::cout << "Ways: " << handler.ways << "\n";
|
||||
std::cout << "Relations: " << handler.relations << "\n";
|
||||
|
||||
google::protobuf::ShutdownProtobufLibrary();
|
||||
}
|
||||
|
||||
|
@ -4,6 +4,7 @@
|
||||
|
||||
*/
|
||||
|
||||
#include <cstdint>
|
||||
#include <iostream>
|
||||
|
||||
#include <osmium/io/any_input.hpp>
|
||||
@ -12,8 +13,8 @@
|
||||
|
||||
struct CountHandler : public osmium::handler::Handler {
|
||||
|
||||
int counter = 0;
|
||||
int all = 0;
|
||||
uint64_t counter = 0;
|
||||
uint64_t all = 0;
|
||||
|
||||
void node(osmium::Node& node) {
|
||||
++all;
|
||||
@ -49,7 +50,5 @@ int main(int argc, char* argv[]) {
|
||||
reader.close();
|
||||
|
||||
std::cout << "r_all=" << handler.all << " r_counter=" << handler.counter << "\n";
|
||||
|
||||
google::protobuf::ShutdownProtobufLibrary();
|
||||
}
|
||||
|
||||
|
@ -35,7 +35,5 @@ int main(int argc, char* argv[]) {
|
||||
|
||||
osmium::apply(reader, location_handler);
|
||||
reader.close();
|
||||
|
||||
google::protobuf::ShutdownProtobufLibrary();
|
||||
}
|
||||
|
||||
|
@ -46,7 +46,6 @@ int main(int argc, char* argv[]) {
|
||||
std::string input_filename = argv[1];
|
||||
|
||||
osmium::memory::Buffer buffer = osmium::io::read_file(input_filename);
|
||||
google::protobuf::ShutdownProtobufLibrary();
|
||||
|
||||
const auto& map_factory = osmium::index::MapFactory<osmium::unsigned_object_id_type, osmium::Location>::instance();
|
||||
|
||||
|
34
third_party/libosmium/benchmarks/osmium_benchmark_write_pbf.cpp
vendored
Normal file
34
third_party/libosmium/benchmarks/osmium_benchmark_write_pbf.cpp
vendored
Normal file
@ -0,0 +1,34 @@
|
||||
/*
|
||||
|
||||
The code in this file is released into the Public Domain.
|
||||
|
||||
*/
|
||||
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
|
||||
#include <osmium/io/any_input.hpp>
|
||||
#include <osmium/io/any_output.hpp>
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
if (argc != 3) {
|
||||
std::cerr << "Usage: " << argv[0] << " INPUT-FILE OUTPUT-FILE\n";
|
||||
exit(1);
|
||||
}
|
||||
|
||||
std::string input_filename = argv[1];
|
||||
std::string output_filename = argv[2];
|
||||
|
||||
osmium::io::Reader reader(input_filename);
|
||||
osmium::io::File output_file(output_filename, "pbf");
|
||||
osmium::io::Header header;
|
||||
osmium::io::Writer writer(output_file, header, osmium::io::overwrite::allow);
|
||||
|
||||
while (osmium::memory::Buffer buffer = reader.read()) {
|
||||
writer(std::move(buffer));
|
||||
}
|
||||
|
||||
writer.close();
|
||||
reader.close();
|
||||
}
|
||||
|
28
third_party/libosmium/benchmarks/run_benchmark_write_pbf.sh
vendored
Executable file
28
third_party/libosmium/benchmarks/run_benchmark_write_pbf.sh
vendored
Executable file
@ -0,0 +1,28 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# run_benchmark_write_pbf.sh
|
||||
#
|
||||
# Will read the input file and after reading it into memory completely,
|
||||
# write it to /dev/null. Because this will need the time to read *and* write
|
||||
# the file, it will report the times for reading and writing. You can
|
||||
# subtract the times needed for the "count" benchmark to (roughly) get the
|
||||
# write times.
|
||||
#
|
||||
|
||||
set -e
|
||||
|
||||
BENCHMARK_NAME=write_pbf
|
||||
|
||||
. @CMAKE_BINARY_DIR@/benchmarks/setup.sh
|
||||
|
||||
CMD=$OB_DIR/osmium_benchmark_$BENCHMARK_NAME
|
||||
|
||||
echo "# file size num mem time cpu_kernel cpu_user cpu_percent cmd options"
|
||||
for data in $OB_DATA_FILES; do
|
||||
filename=`basename $data`
|
||||
filesize=`stat --format="%s" --dereference $data`
|
||||
for n in $OB_SEQ; do
|
||||
$OB_TIME_CMD -f "$filename $filesize $n $OB_TIME_FORMAT" $CMD $data /dev/null 2>&1 >/dev/null | sed -e "s%$DATA_DIR/%%" | sed -e "s%$OB_DIR/%%"
|
||||
done
|
||||
done
|
||||
|
50
third_party/libosmium/cmake/FindOSMPBF.cmake
vendored
50
third_party/libosmium/cmake/FindOSMPBF.cmake
vendored
@ -1,50 +0,0 @@
|
||||
#
|
||||
# Locate OSMPBF library
|
||||
#
|
||||
# This module defines
|
||||
# OSMPBF_FOUND - if false, do not try to link to OSMPBF
|
||||
# OSMPBF_LIBRARIES - full library path name
|
||||
# OSMPBF_INCLUDE_DIRS - where to find OSMPBF.hpp
|
||||
#
|
||||
# Note that the expected include convention is
|
||||
# #include <osmpbf/osmpbf.h>
|
||||
# and not
|
||||
# #include <osmpbf.h>
|
||||
#
|
||||
|
||||
find_path(OSMPBF_INCLUDE_DIR osmpbf/osmpbf.h
|
||||
HINTS $ENV{OSMPBF_DIR}
|
||||
PATH_SUFFIXES include
|
||||
PATHS
|
||||
~/Library/Frameworks
|
||||
/Library/Frameworks
|
||||
/usr/local
|
||||
/usr
|
||||
/opt/local # DarwinPorts
|
||||
/opt
|
||||
)
|
||||
|
||||
find_library(OSMPBF_LIBRARY
|
||||
NAMES osmpbf
|
||||
HINTS $ENV{OSMPBF_DIR}
|
||||
PATH_SUFFIXES lib64 lib
|
||||
PATHS
|
||||
~/Library/Frameworks
|
||||
/Library/Frameworks
|
||||
/usr/local
|
||||
/usr
|
||||
/opt/local
|
||||
/opt
|
||||
)
|
||||
|
||||
# Handle the QUIETLY and REQUIRED arguments and set OSMPBF_FOUND to TRUE if
|
||||
# all listed variables are TRUE.
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(OSMPBF DEFAULT_MSG OSMPBF_LIBRARY OSMPBF_INCLUDE_DIR)
|
||||
|
||||
# Copy the results to the output variables.
|
||||
if(OSMPBF_FOUND)
|
||||
set(OSMPBF_INCLUDE_DIRS ${OSMPBF_INCLUDE_DIR})
|
||||
set(OSMPBF_LIBRARIES ${OSMPBF_LIBRARY})
|
||||
endif()
|
||||
|
10
third_party/libosmium/cmake/FindOsmium.cmake
vendored
10
third_party/libosmium/cmake/FindOsmium.cmake
vendored
@ -110,15 +110,11 @@ endif()
|
||||
#----------------------------------------------------------------------
|
||||
# Component 'pbf'
|
||||
if(Osmium_USE_PBF)
|
||||
find_package(OSMPBF)
|
||||
find_package(Protobuf)
|
||||
find_package(ZLIB)
|
||||
find_package(Threads)
|
||||
|
||||
if(OSMPBF_FOUND AND PROTOBUF_FOUND AND ZLIB_FOUND AND Threads_FOUND)
|
||||
if(ZLIB_FOUND AND Threads_FOUND)
|
||||
list(APPEND OSMIUM_PBF_LIBRARIES
|
||||
${OSMPBF_LIBRARIES}
|
||||
${PROTOBUF_LITE_LIBRARY}
|
||||
${ZLIB_LIBRARIES}
|
||||
${CMAKE_THREAD_LIBS_INIT}
|
||||
)
|
||||
@ -126,8 +122,6 @@ if(Osmium_USE_PBF)
|
||||
list(APPEND OSMIUM_PBF_LIBRARIES ws2_32)
|
||||
endif()
|
||||
list(APPEND OSMIUM_INCLUDE_DIRS
|
||||
${OSMPBF_INCLUDE_DIRS}
|
||||
${PROTOBUF_INCLUDE_DIR}
|
||||
${ZLIB_INCLUDE_DIR}
|
||||
)
|
||||
else()
|
||||
@ -325,7 +319,7 @@ endif()
|
||||
if(MSVC)
|
||||
set(OSMIUM_WARNING_OPTIONS "/W3 /wd4514" CACHE STRING "Recommended warning options for libosmium")
|
||||
else()
|
||||
set(OSMIUM_WARNING_OPTIONS "-Wall -Wextra -pedantic -Wredundant-decls -Wdisabled-optimization -Wctor-dtor-privacy -Wnon-virtual-dtor -Woverloaded-virtual -Wsign-promo -Wold-style-cast -Wno-return-type" CACHE STRING "Recommended warning options for libosmium")
|
||||
set(OSMIUM_WARNING_OPTIONS "-Wall -Wextra -pedantic -Wredundant-decls -Wdisabled-optimization -Wctor-dtor-privacy -Wnon-virtual-dtor -Woverloaded-virtual -Wsign-promo -Wold-style-cast" CACHE STRING "Recommended warning options for libosmium")
|
||||
endif()
|
||||
|
||||
set(OSMIUM_DRACONIC_CLANG_OPTIONS "-Wdocumentation -Wunused-exception-parameter -Wmissing-declarations -Weverything -Wno-c++98-compat -Wno-c++98-compat-pedantic -Wno-unused-macros -Wno-exit-time-destructors -Wno-global-constructors -Wno-padded -Wno-switch-enum -Wno-missing-prototypes -Wno-weak-vtables -Wno-cast-align -Wno-float-equal")
|
||||
|
4
third_party/libosmium/cmake/iwyu.sh
vendored
4
third_party/libosmium/cmake/iwyu.sh
vendored
@ -10,12 +10,12 @@ cmdline="iwyu -Xiwyu --mapping_file=osmium.imp -std=c++11 -I include"
|
||||
|
||||
log=build/iwyu.log
|
||||
|
||||
mkdir -p build/check_reports
|
||||
|
||||
echo "INCLUDE WHAT YOU USE REPORT:" >$log
|
||||
|
||||
allok=yes
|
||||
|
||||
mkdir -p build/check_reports
|
||||
|
||||
for file in `find include/osmium -name \*.hpp`; do
|
||||
mkdir -p `dirname build/check_reports/$file`
|
||||
ifile="build/check_reports/${file%.hpp}.iwyu"
|
||||
|
2
third_party/libosmium/doc/CMakeLists.txt
vendored
2
third_party/libosmium/doc/CMakeLists.txt
vendored
@ -21,8 +21,6 @@ if(DOXYGEN_FOUND)
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
|
||||
COMMENT "Generating API documentation with Doxygen" VERBATIM
|
||||
)
|
||||
# install(DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/html"
|
||||
# DESTINATION "share/doc/libosmium-dev")
|
||||
else()
|
||||
message(STATUS "Looking for doxygen - not found")
|
||||
message(STATUS " Disabled making of documentation.")
|
||||
|
2
third_party/libosmium/doc/Doxyfile.in
vendored
2
third_party/libosmium/doc/Doxyfile.in
vendored
@ -1128,7 +1128,7 @@ HTML_COLORSTYLE_GAMMA = 80
|
||||
# The default value is: YES.
|
||||
# This tag requires that the tag GENERATE_HTML is set to YES.
|
||||
|
||||
HTML_TIMESTAMP = YES
|
||||
HTML_TIMESTAMP = NO
|
||||
|
||||
# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
|
||||
# documentation will contain sections that can be hidden and shown after the
|
||||
|
2
third_party/libosmium/doc/README.md
vendored
2
third_party/libosmium/doc/README.md
vendored
@ -3,6 +3,6 @@ The `header.html` is created with:
|
||||
|
||||
`doxygen -w html header.html footer.html stylesheet.css`
|
||||
|
||||
This might have to be rn again for newer Doxygen versions. After that add
|
||||
This might have to be run again for newer Doxygen versions. After that add
|
||||
changes back in.
|
||||
|
||||
|
@ -132,7 +132,5 @@ int main(int argc, char* argv[]) {
|
||||
}
|
||||
std::cerr << "\n";
|
||||
}
|
||||
|
||||
google::protobuf::ShutdownProtobufLibrary();
|
||||
}
|
||||
|
||||
|
@ -106,7 +106,6 @@ int main(int argc, char* argv[]) {
|
||||
exit_code = 1;
|
||||
}
|
||||
|
||||
google::protobuf::ShutdownProtobufLibrary();
|
||||
return exit_code;
|
||||
}
|
||||
|
||||
|
@ -7,6 +7,7 @@
|
||||
|
||||
*/
|
||||
|
||||
#include <cstdint>
|
||||
#include <iostream>
|
||||
|
||||
#include <osmium/io/any_input.hpp>
|
||||
@ -15,9 +16,9 @@
|
||||
|
||||
struct CountHandler : public osmium::handler::Handler {
|
||||
|
||||
int nodes = 0;
|
||||
int ways = 0;
|
||||
int relations = 0;
|
||||
uint64_t nodes = 0;
|
||||
uint64_t ways = 0;
|
||||
uint64_t relations = 0;
|
||||
|
||||
void node(osmium::Node&) {
|
||||
++nodes;
|
||||
@ -51,7 +52,5 @@ int main(int argc, char* argv[]) {
|
||||
std::cout << "Nodes: " << handler.nodes << "\n";
|
||||
std::cout << "Ways: " << handler.ways << "\n";
|
||||
std::cout << "Relations: " << handler.relations << "\n";
|
||||
|
||||
google::protobuf::ShutdownProtobufLibrary();
|
||||
}
|
||||
|
||||
|
@ -12,8 +12,7 @@
|
||||
#include <fcntl.h>
|
||||
#include <iostream>
|
||||
|
||||
#include <osmium/io/pbf_input.hpp>
|
||||
#include <osmium/io/xml_input.hpp>
|
||||
#include <osmium/io/any_input.hpp>
|
||||
|
||||
#include <osmium/index/map/dummy.hpp>
|
||||
#include <osmium/index/map/dense_mmap_array.hpp>
|
||||
@ -51,8 +50,6 @@ int main(int argc, char* argv[]) {
|
||||
osmium::apply(reader, location_handler);
|
||||
reader.close();
|
||||
|
||||
google::protobuf::ShutdownProtobufLibrary();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -46,7 +46,5 @@ int main(int argc, char* argv[]) {
|
||||
}
|
||||
|
||||
reader.close();
|
||||
|
||||
google::protobuf::ShutdownProtobufLibrary();
|
||||
}
|
||||
|
||||
|
@ -26,7 +26,5 @@ int main(int argc, char* argv[]) {
|
||||
}
|
||||
|
||||
reader.close();
|
||||
|
||||
google::protobuf::ShutdownProtobufLibrary();
|
||||
}
|
||||
|
||||
|
@ -19,8 +19,7 @@
|
||||
# include <direct.h>
|
||||
#endif
|
||||
|
||||
#include <osmium/io/pbf_input.hpp>
|
||||
#include <osmium/io/xml_input.hpp>
|
||||
#include <osmium/io/any_input.hpp>
|
||||
#include <osmium/handler/disk_store.hpp>
|
||||
#include <osmium/handler/object_relations.hpp>
|
||||
|
||||
@ -203,7 +202,5 @@ int main(int argc, char* argv[]) {
|
||||
map_relation2relation.dump_as_list(fd);
|
||||
close(fd);
|
||||
}
|
||||
|
||||
google::protobuf::ShutdownProtobufLibrary();
|
||||
}
|
||||
|
||||
|
@ -234,8 +234,6 @@ int main(int argc, char* argv[]) {
|
||||
osmium::apply(reader, location_handler, ogr_handler);
|
||||
reader.close();
|
||||
|
||||
google::protobuf::ShutdownProtobufLibrary();
|
||||
|
||||
int locations_fd = open("locations.dump", O_WRONLY | O_CREAT, 0644);
|
||||
if (locations_fd < 0) {
|
||||
throw std::system_error(errno, std::system_category(), "Open failed");
|
||||
|
@ -327,7 +327,5 @@ int main(int argc, char* argv[]) {
|
||||
}
|
||||
std::cerr << "\n";
|
||||
}
|
||||
|
||||
google::protobuf::ShutdownProtobufLibrary();
|
||||
}
|
||||
|
||||
|
@ -301,7 +301,5 @@ int main(int argc, char* argv[]) {
|
||||
}
|
||||
std::cerr << "\n";
|
||||
}
|
||||
|
||||
google::protobuf::ShutdownProtobufLibrary();
|
||||
}
|
||||
|
||||
|
@ -12,8 +12,7 @@
|
||||
#include <fcntl.h>
|
||||
#include <iostream>
|
||||
|
||||
#include <osmium/io/pbf_input.hpp>
|
||||
#include <osmium/io/xml_input.hpp>
|
||||
#include <osmium/io/any_input.hpp>
|
||||
|
||||
#include <osmium/index/map/dummy.hpp>
|
||||
#include <osmium/index/map/dense_file_array.hpp>
|
||||
@ -64,8 +63,6 @@ int main(int argc, char* argv[]) {
|
||||
osmium::apply(reader, location_handler, handler);
|
||||
reader.close();
|
||||
|
||||
google::protobuf::ShutdownProtobufLibrary();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1,776 +0,0 @@
|
||||
/*
|
||||
*
|
||||
* Copyright (c) 2004
|
||||
* John Maddock
|
||||
*
|
||||
* Use, modification and distribution are subject to the
|
||||
* Boost Software License, Version 1.0. (See accompanying file
|
||||
* LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* LOCATION: see http://www.boost.org for most recent version.
|
||||
* FILE unicode_iterator.hpp
|
||||
* VERSION see <boost/version.hpp>
|
||||
* DESCRIPTION: Iterator adapters for converting between different Unicode encodings.
|
||||
*/
|
||||
|
||||
/****************************************************************************
|
||||
|
||||
Contents:
|
||||
~~~~~~~~~
|
||||
|
||||
1) Read Only, Input Adapters:
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
template <class BaseIterator, class U8Type = ::boost::uint8_t>
|
||||
class u32_to_u8_iterator;
|
||||
|
||||
Adapts sequence of UTF-32 code points to "look like" a sequence of UTF-8.
|
||||
|
||||
template <class BaseIterator, class U32Type = ::boost::uint32_t>
|
||||
class u8_to_u32_iterator;
|
||||
|
||||
Adapts sequence of UTF-8 code points to "look like" a sequence of UTF-32.
|
||||
|
||||
template <class BaseIterator, class U16Type = ::boost::uint16_t>
|
||||
class u32_to_u16_iterator;
|
||||
|
||||
Adapts sequence of UTF-32 code points to "look like" a sequence of UTF-16.
|
||||
|
||||
template <class BaseIterator, class U32Type = ::boost::uint32_t>
|
||||
class u16_to_u32_iterator;
|
||||
|
||||
Adapts sequence of UTF-16 code points to "look like" a sequence of UTF-32.
|
||||
|
||||
2) Single pass output iterator adapters:
|
||||
|
||||
template <class BaseIterator>
|
||||
class utf8_output_iterator;
|
||||
|
||||
Accepts UTF-32 code points and forwards them on as UTF-8 code points.
|
||||
|
||||
template <class BaseIterator>
|
||||
class utf16_output_iterator;
|
||||
|
||||
Accepts UTF-32 code points and forwards them on as UTF-16 code points.
|
||||
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef BOOST_REGEX_UNICODE_ITERATOR_HPP
|
||||
#define BOOST_REGEX_UNICODE_ITERATOR_HPP
|
||||
#include <boost/cstdint.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/iterator/iterator_facade.hpp>
|
||||
#include <boost/static_assert.hpp>
|
||||
#include <boost/throw_exception.hpp>
|
||||
#include <stdexcept>
|
||||
#ifndef BOOST_NO_STD_LOCALE
|
||||
#include <sstream>
|
||||
#include <ios>
|
||||
#endif
|
||||
#include <limits.h> // CHAR_BIT
|
||||
|
||||
namespace boost{
|
||||
|
||||
namespace detail{
|
||||
|
||||
static const ::boost::uint16_t high_surrogate_base = 0xD7C0u;
|
||||
static const ::boost::uint16_t low_surrogate_base = 0xDC00u;
|
||||
static const ::boost::uint32_t ten_bit_mask = 0x3FFu;
|
||||
|
||||
inline bool is_high_surrogate(::boost::uint16_t v)
|
||||
{
|
||||
return (v & 0xFFFFFC00u) == 0xd800u;
|
||||
}
|
||||
inline bool is_low_surrogate(::boost::uint16_t v)
|
||||
{
|
||||
return (v & 0xFFFFFC00u) == 0xdc00u;
|
||||
}
|
||||
template <class T>
|
||||
inline bool is_surrogate(T v)
|
||||
{
|
||||
return (v & 0xFFFFF800u) == 0xd800;
|
||||
}
|
||||
|
||||
inline unsigned utf8_byte_count(boost::uint8_t c)
|
||||
{
|
||||
// if the most significant bit with a zero in it is in position
|
||||
// 8-N then there are N bytes in this UTF-8 sequence:
|
||||
boost::uint8_t mask = 0x80u;
|
||||
unsigned result = 0;
|
||||
while(c & mask)
|
||||
{
|
||||
++result;
|
||||
mask >>= 1;
|
||||
}
|
||||
return (result == 0) ? 1 : ((result > 4) ? 4 : result);
|
||||
}
|
||||
|
||||
inline unsigned utf8_trailing_byte_count(boost::uint8_t c)
|
||||
{
|
||||
return utf8_byte_count(c) - 1;
|
||||
}
|
||||
|
||||
#ifdef BOOST_MSVC
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable:4100)
|
||||
#endif
|
||||
inline void invalid_utf32_code_point(::boost::uint32_t val)
|
||||
{
|
||||
#ifndef BOOST_NO_STD_LOCALE
|
||||
std::stringstream ss;
|
||||
ss << "Invalid UTF-32 code point U+" << std::showbase << std::hex << val << " encountered while trying to encode UTF-16 sequence";
|
||||
std::out_of_range e(ss.str());
|
||||
#else
|
||||
std::out_of_range e("Invalid UTF-32 code point encountered while trying to encode UTF-16 sequence");
|
||||
#endif
|
||||
boost::throw_exception(e);
|
||||
}
|
||||
#ifdef BOOST_MSVC
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template <class BaseIterator, class U16Type = ::boost::uint16_t>
|
||||
class u32_to_u16_iterator
|
||||
: public boost::iterator_facade<u32_to_u16_iterator<BaseIterator, U16Type>, U16Type, std::bidirectional_iterator_tag, const U16Type>
|
||||
{
|
||||
typedef boost::iterator_facade<u32_to_u16_iterator<BaseIterator, U16Type>, U16Type, std::bidirectional_iterator_tag, const U16Type> base_type;
|
||||
|
||||
#if !defined(BOOST_NO_STD_ITERATOR_TRAITS) && !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
|
||||
typedef typename std::iterator_traits<BaseIterator>::value_type base_value_type;
|
||||
|
||||
BOOST_STATIC_ASSERT(sizeof(base_value_type)*CHAR_BIT == 32);
|
||||
BOOST_STATIC_ASSERT(sizeof(U16Type)*CHAR_BIT == 16);
|
||||
#endif
|
||||
|
||||
public:
|
||||
typename base_type::reference
|
||||
dereference()const
|
||||
{
|
||||
if(m_current == 2)
|
||||
extract_current();
|
||||
return m_values[m_current];
|
||||
}
|
||||
bool equal(const u32_to_u16_iterator& that)const
|
||||
{
|
||||
if(m_position == that.m_position)
|
||||
{
|
||||
// Both m_currents must be equal, or both even
|
||||
// this is the same as saying their sum must be even:
|
||||
return (m_current + that.m_current) & 1u ? false : true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
void increment()
|
||||
{
|
||||
// if we have a pending read then read now, so that we know whether
|
||||
// to skip a position, or move to a low-surrogate:
|
||||
if(m_current == 2)
|
||||
{
|
||||
// pending read:
|
||||
extract_current();
|
||||
}
|
||||
// move to the next surrogate position:
|
||||
++m_current;
|
||||
// if we've reached the end skip a position:
|
||||
if(m_values[m_current] == 0)
|
||||
{
|
||||
m_current = 2;
|
||||
++m_position;
|
||||
}
|
||||
}
|
||||
void decrement()
|
||||
{
|
||||
if(m_current != 1)
|
||||
{
|
||||
// decrementing an iterator always leads to a valid position:
|
||||
--m_position;
|
||||
extract_current();
|
||||
m_current = m_values[1] ? 1 : 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_current = 0;
|
||||
}
|
||||
}
|
||||
BaseIterator base()const
|
||||
{
|
||||
return m_position;
|
||||
}
|
||||
// construct:
|
||||
u32_to_u16_iterator() : m_position(), m_current(0)
|
||||
{
|
||||
m_values[0] = 0;
|
||||
m_values[1] = 0;
|
||||
m_values[2] = 0;
|
||||
}
|
||||
u32_to_u16_iterator(BaseIterator b) : m_position(b), m_current(2)
|
||||
{
|
||||
m_values[0] = 0;
|
||||
m_values[1] = 0;
|
||||
m_values[2] = 0;
|
||||
}
|
||||
private:
|
||||
|
||||
void extract_current()const
|
||||
{
|
||||
// begin by checking for a code point out of range:
|
||||
::boost::uint32_t v = *m_position;
|
||||
if(v >= 0x10000u)
|
||||
{
|
||||
if(v > 0x10FFFFu)
|
||||
detail::invalid_utf32_code_point(*m_position);
|
||||
// split into two surrogates:
|
||||
m_values[0] = static_cast<U16Type>(v >> 10) + detail::high_surrogate_base;
|
||||
m_values[1] = static_cast<U16Type>(v & detail::ten_bit_mask) + detail::low_surrogate_base;
|
||||
m_current = 0;
|
||||
BOOST_ASSERT(detail::is_high_surrogate(m_values[0]));
|
||||
BOOST_ASSERT(detail::is_low_surrogate(m_values[1]));
|
||||
}
|
||||
else
|
||||
{
|
||||
// 16-bit code point:
|
||||
m_values[0] = static_cast<U16Type>(*m_position);
|
||||
m_values[1] = 0;
|
||||
m_current = 0;
|
||||
// value must not be a surrogate:
|
||||
if(detail::is_surrogate(m_values[0]))
|
||||
detail::invalid_utf32_code_point(*m_position);
|
||||
}
|
||||
}
|
||||
BaseIterator m_position;
|
||||
mutable U16Type m_values[3];
|
||||
mutable unsigned m_current;
|
||||
};
|
||||
|
||||
template <class BaseIterator, class U32Type = ::boost::uint32_t>
|
||||
class u16_to_u32_iterator
|
||||
: public boost::iterator_facade<u16_to_u32_iterator<BaseIterator, U32Type>, U32Type, std::bidirectional_iterator_tag, const U32Type>
|
||||
{
|
||||
typedef boost::iterator_facade<u16_to_u32_iterator<BaseIterator, U32Type>, U32Type, std::bidirectional_iterator_tag, const U32Type> base_type;
|
||||
// special values for pending iterator reads:
|
||||
BOOST_STATIC_CONSTANT(U32Type, pending_read = 0xffffffffu);
|
||||
|
||||
#if !defined(BOOST_NO_STD_ITERATOR_TRAITS) && !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
|
||||
typedef typename std::iterator_traits<BaseIterator>::value_type base_value_type;
|
||||
|
||||
BOOST_STATIC_ASSERT(sizeof(base_value_type)*CHAR_BIT == 16);
|
||||
BOOST_STATIC_ASSERT(sizeof(U32Type)*CHAR_BIT == 32);
|
||||
#endif
|
||||
|
||||
public:
|
||||
typename base_type::reference
|
||||
dereference()const
|
||||
{
|
||||
if(m_value == pending_read)
|
||||
extract_current();
|
||||
return m_value;
|
||||
}
|
||||
bool equal(const u16_to_u32_iterator& that)const
|
||||
{
|
||||
return m_position == that.m_position;
|
||||
}
|
||||
void increment()
|
||||
{
|
||||
// skip high surrogate first if there is one:
|
||||
if(detail::is_high_surrogate(*m_position)) ++m_position;
|
||||
++m_position;
|
||||
m_value = pending_read;
|
||||
}
|
||||
void decrement()
|
||||
{
|
||||
--m_position;
|
||||
// if we have a low surrogate then go back one more:
|
||||
if(detail::is_low_surrogate(*m_position))
|
||||
--m_position;
|
||||
m_value = pending_read;
|
||||
}
|
||||
BaseIterator base()const
|
||||
{
|
||||
return m_position;
|
||||
}
|
||||
// construct:
|
||||
u16_to_u32_iterator() : m_position()
|
||||
{
|
||||
m_value = pending_read;
|
||||
}
|
||||
u16_to_u32_iterator(BaseIterator b) : m_position(b)
|
||||
{
|
||||
m_value = pending_read;
|
||||
}
|
||||
//
|
||||
// Range checked version:
|
||||
//
|
||||
u16_to_u32_iterator(BaseIterator b, BaseIterator start, BaseIterator end) : m_position(b)
|
||||
{
|
||||
m_value = pending_read;
|
||||
//
|
||||
// The range must not start with a low surrogate, or end in a high surrogate,
|
||||
// otherwise we run the risk of running outside the underlying input range.
|
||||
// Likewise b must not be located at a low surrogate.
|
||||
//
|
||||
boost::uint16_t val;
|
||||
if(start != end)
|
||||
{
|
||||
if((b != start) && (b != end))
|
||||
{
|
||||
val = *b;
|
||||
if(detail::is_surrogate(val) && ((val & 0xFC00u) == 0xDC00u))
|
||||
invalid_code_point(val);
|
||||
}
|
||||
val = *start;
|
||||
if(detail::is_surrogate(val) && ((val & 0xFC00u) == 0xDC00u))
|
||||
invalid_code_point(val);
|
||||
val = *--end;
|
||||
if(detail::is_high_surrogate(val))
|
||||
invalid_code_point(val);
|
||||
}
|
||||
}
|
||||
private:
|
||||
static void invalid_code_point(::boost::uint16_t val)
|
||||
{
|
||||
#ifndef BOOST_NO_STD_LOCALE
|
||||
std::stringstream ss;
|
||||
ss << "Misplaced UTF-16 surrogate U+" << std::showbase << std::hex << val << " encountered while trying to encode UTF-32 sequence";
|
||||
std::out_of_range e(ss.str());
|
||||
#else
|
||||
std::out_of_range e("Misplaced UTF-16 surrogate encountered while trying to encode UTF-32 sequence");
|
||||
#endif
|
||||
boost::throw_exception(e);
|
||||
}
|
||||
void extract_current()const
|
||||
{
|
||||
m_value = static_cast<U32Type>(static_cast< ::boost::uint16_t>(*m_position));
|
||||
// if the last value is a high surrogate then adjust m_position and m_value as needed:
|
||||
if(detail::is_high_surrogate(*m_position))
|
||||
{
|
||||
// precondition; next value must have be a low-surrogate:
|
||||
BaseIterator next(m_position);
|
||||
::boost::uint16_t t = *++next;
|
||||
if((t & 0xFC00u) != 0xDC00u)
|
||||
invalid_code_point(t);
|
||||
m_value = (m_value - detail::high_surrogate_base) << 10;
|
||||
m_value |= (static_cast<U32Type>(static_cast< ::boost::uint16_t>(t)) & detail::ten_bit_mask);
|
||||
}
|
||||
// postcondition; result must not be a surrogate:
|
||||
if(detail::is_surrogate(m_value))
|
||||
invalid_code_point(static_cast< ::boost::uint16_t>(m_value));
|
||||
}
|
||||
BaseIterator m_position;
|
||||
mutable U32Type m_value;
|
||||
};
|
||||
|
||||
template <class BaseIterator, class U8Type = ::boost::uint8_t>
|
||||
class u32_to_u8_iterator
|
||||
: public boost::iterator_facade<u32_to_u8_iterator<BaseIterator, U8Type>, U8Type, std::bidirectional_iterator_tag, const U8Type>
|
||||
{
|
||||
typedef boost::iterator_facade<u32_to_u8_iterator<BaseIterator, U8Type>, U8Type, std::bidirectional_iterator_tag, const U8Type> base_type;
|
||||
|
||||
#if !defined(BOOST_NO_STD_ITERATOR_TRAITS) && !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
|
||||
typedef typename std::iterator_traits<BaseIterator>::value_type base_value_type;
|
||||
|
||||
BOOST_STATIC_ASSERT(sizeof(base_value_type)*CHAR_BIT == 32);
|
||||
BOOST_STATIC_ASSERT(sizeof(U8Type)*CHAR_BIT == 8);
|
||||
#endif
|
||||
|
||||
public:
|
||||
typename base_type::reference
|
||||
dereference()const
|
||||
{
|
||||
if(m_current == 4)
|
||||
extract_current();
|
||||
return m_values[m_current];
|
||||
}
|
||||
bool equal(const u32_to_u8_iterator& that)const
|
||||
{
|
||||
if(m_position == that.m_position)
|
||||
{
|
||||
// either the m_current's must be equal, or one must be 0 and
|
||||
// the other 4: which means neither must have bits 1 or 2 set:
|
||||
return (m_current == that.m_current)
|
||||
|| (((m_current | that.m_current) & 3) == 0);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
void increment()
|
||||
{
|
||||
// if we have a pending read then read now, so that we know whether
|
||||
// to skip a position, or move to a low-surrogate:
|
||||
if(m_current == 4)
|
||||
{
|
||||
// pending read:
|
||||
extract_current();
|
||||
}
|
||||
// move to the next surrogate position:
|
||||
++m_current;
|
||||
// if we've reached the end skip a position:
|
||||
if(m_values[m_current] == 0)
|
||||
{
|
||||
m_current = 4;
|
||||
++m_position;
|
||||
}
|
||||
}
|
||||
void decrement()
|
||||
{
|
||||
if((m_current & 3) == 0)
|
||||
{
|
||||
--m_position;
|
||||
extract_current();
|
||||
m_current = 3;
|
||||
while(m_current && (m_values[m_current] == 0))
|
||||
--m_current;
|
||||
}
|
||||
else
|
||||
--m_current;
|
||||
}
|
||||
BaseIterator base()const
|
||||
{
|
||||
return m_position;
|
||||
}
|
||||
// construct:
|
||||
u32_to_u8_iterator() : m_position(), m_current(0)
|
||||
{
|
||||
m_values[0] = 0;
|
||||
m_values[1] = 0;
|
||||
m_values[2] = 0;
|
||||
m_values[3] = 0;
|
||||
m_values[4] = 0;
|
||||
}
|
||||
u32_to_u8_iterator(BaseIterator b) : m_position(b), m_current(4)
|
||||
{
|
||||
m_values[0] = 0;
|
||||
m_values[1] = 0;
|
||||
m_values[2] = 0;
|
||||
m_values[3] = 0;
|
||||
m_values[4] = 0;
|
||||
}
|
||||
private:
|
||||
|
||||
void extract_current()const
|
||||
{
|
||||
boost::uint32_t c = *m_position;
|
||||
if(c > 0x10FFFFu)
|
||||
detail::invalid_utf32_code_point(c);
|
||||
if(c < 0x80u)
|
||||
{
|
||||
m_values[0] = static_cast<unsigned char>(c);
|
||||
m_values[1] = static_cast<unsigned char>(0u);
|
||||
m_values[2] = static_cast<unsigned char>(0u);
|
||||
m_values[3] = static_cast<unsigned char>(0u);
|
||||
}
|
||||
else if(c < 0x800u)
|
||||
{
|
||||
m_values[0] = static_cast<unsigned char>(0xC0u + (c >> 6));
|
||||
m_values[1] = static_cast<unsigned char>(0x80u + (c & 0x3Fu));
|
||||
m_values[2] = static_cast<unsigned char>(0u);
|
||||
m_values[3] = static_cast<unsigned char>(0u);
|
||||
}
|
||||
else if(c < 0x10000u)
|
||||
{
|
||||
m_values[0] = static_cast<unsigned char>(0xE0u + (c >> 12));
|
||||
m_values[1] = static_cast<unsigned char>(0x80u + ((c >> 6) & 0x3Fu));
|
||||
m_values[2] = static_cast<unsigned char>(0x80u + (c & 0x3Fu));
|
||||
m_values[3] = static_cast<unsigned char>(0u);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_values[0] = static_cast<unsigned char>(0xF0u + (c >> 18));
|
||||
m_values[1] = static_cast<unsigned char>(0x80u + ((c >> 12) & 0x3Fu));
|
||||
m_values[2] = static_cast<unsigned char>(0x80u + ((c >> 6) & 0x3Fu));
|
||||
m_values[3] = static_cast<unsigned char>(0x80u + (c & 0x3Fu));
|
||||
}
|
||||
m_current= 0;
|
||||
}
|
||||
BaseIterator m_position;
|
||||
mutable U8Type m_values[5];
|
||||
mutable unsigned m_current;
|
||||
};
|
||||
|
||||
template <class BaseIterator, class U32Type = ::boost::uint32_t>
|
||||
class u8_to_u32_iterator
|
||||
: public boost::iterator_facade<u8_to_u32_iterator<BaseIterator, U32Type>, U32Type, std::bidirectional_iterator_tag, const U32Type>
|
||||
{
|
||||
typedef boost::iterator_facade<u8_to_u32_iterator<BaseIterator, U32Type>, U32Type, std::bidirectional_iterator_tag, const U32Type> base_type;
|
||||
// special values for pending iterator reads:
|
||||
BOOST_STATIC_CONSTANT(U32Type, pending_read = 0xffffffffu);
|
||||
|
||||
#if !defined(BOOST_NO_STD_ITERATOR_TRAITS) && !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
|
||||
typedef typename std::iterator_traits<BaseIterator>::value_type base_value_type;
|
||||
|
||||
BOOST_STATIC_ASSERT(sizeof(base_value_type)*CHAR_BIT == 8);
|
||||
BOOST_STATIC_ASSERT(sizeof(U32Type)*CHAR_BIT == 32);
|
||||
#endif
|
||||
|
||||
public:
|
||||
typename base_type::reference
|
||||
dereference()const
|
||||
{
|
||||
if(m_value == pending_read)
|
||||
extract_current();
|
||||
return m_value;
|
||||
}
|
||||
bool equal(const u8_to_u32_iterator& that)const
|
||||
{
|
||||
return m_position == that.m_position;
|
||||
}
|
||||
void increment()
|
||||
{
|
||||
// We must not start with a continuation character:
|
||||
if((static_cast<boost::uint8_t>(*m_position) & 0xC0) == 0x80)
|
||||
invalid_sequence();
|
||||
// skip high surrogate first if there is one:
|
||||
unsigned c = detail::utf8_byte_count(*m_position);
|
||||
if(m_value == pending_read)
|
||||
{
|
||||
// Since we haven't read in a value, we need to validate the code points:
|
||||
for(unsigned i = 0; i < c; ++i)
|
||||
{
|
||||
++m_position;
|
||||
// We must have a continuation byte:
|
||||
if((i != c - 1) && ((static_cast<boost::uint8_t>(*m_position) & 0xC0) != 0x80))
|
||||
invalid_sequence();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
std::advance(m_position, c);
|
||||
}
|
||||
m_value = pending_read;
|
||||
}
|
||||
void decrement()
|
||||
{
|
||||
// Keep backtracking until we don't have a trailing character:
|
||||
unsigned count = 0;
|
||||
while((*--m_position & 0xC0u) == 0x80u) ++count;
|
||||
// now check that the sequence was valid:
|
||||
if(count != detail::utf8_trailing_byte_count(*m_position))
|
||||
invalid_sequence();
|
||||
m_value = pending_read;
|
||||
}
|
||||
BaseIterator base()const
|
||||
{
|
||||
return m_position;
|
||||
}
|
||||
// construct:
|
||||
u8_to_u32_iterator() : m_position()
|
||||
{
|
||||
m_value = pending_read;
|
||||
}
|
||||
u8_to_u32_iterator(BaseIterator b) : m_position(b)
|
||||
{
|
||||
m_value = pending_read;
|
||||
}
|
||||
//
|
||||
// Checked constructor:
|
||||
//
|
||||
u8_to_u32_iterator(BaseIterator b, BaseIterator start, BaseIterator end) : m_position(b)
|
||||
{
|
||||
m_value = pending_read;
|
||||
//
|
||||
// We must not start with a continuation character, or end with a
|
||||
// truncated UTF-8 sequence otherwise we run the risk of going past
|
||||
// the start/end of the underlying sequence:
|
||||
//
|
||||
if(start != end)
|
||||
{
|
||||
unsigned char v = *start;
|
||||
if((v & 0xC0u) == 0x80u)
|
||||
invalid_sequence();
|
||||
if((b != start) && (b != end) && ((*b & 0xC0u) == 0x80u))
|
||||
invalid_sequence();
|
||||
BaseIterator pos = end;
|
||||
do
|
||||
{
|
||||
v = *--pos;
|
||||
}
|
||||
while((start != pos) && ((v & 0xC0u) == 0x80u));
|
||||
std::ptrdiff_t extra = detail::utf8_byte_count(v);
|
||||
if(std::distance(pos, end) < extra)
|
||||
invalid_sequence();
|
||||
}
|
||||
}
|
||||
private:
|
||||
static void invalid_sequence()
|
||||
{
|
||||
std::out_of_range e("Invalid UTF-8 sequence encountered while trying to encode UTF-32 character");
|
||||
boost::throw_exception(e);
|
||||
}
|
||||
void extract_current()const
|
||||
{
|
||||
m_value = static_cast<U32Type>(static_cast< ::boost::uint8_t>(*m_position));
|
||||
// we must not have a continuation character:
|
||||
if((m_value & 0xC0u) == 0x80u)
|
||||
invalid_sequence();
|
||||
// see how many extra bytes we have:
|
||||
unsigned extra = detail::utf8_trailing_byte_count(*m_position);
|
||||
// extract the extra bits, 6 from each extra byte:
|
||||
BaseIterator next(m_position);
|
||||
for(unsigned c = 0; c < extra; ++c)
|
||||
{
|
||||
++next;
|
||||
m_value <<= 6;
|
||||
// We must have a continuation byte:
|
||||
if((static_cast<boost::uint8_t>(*next) & 0xC0) != 0x80)
|
||||
invalid_sequence();
|
||||
m_value += static_cast<boost::uint8_t>(*next) & 0x3Fu;
|
||||
}
|
||||
// we now need to remove a few of the leftmost bits, but how many depends
|
||||
// upon how many extra bytes we've extracted:
|
||||
static const boost::uint32_t masks[4] =
|
||||
{
|
||||
0x7Fu,
|
||||
0x7FFu,
|
||||
0xFFFFu,
|
||||
0x1FFFFFu,
|
||||
};
|
||||
m_value &= masks[extra];
|
||||
// check the result:
|
||||
if(m_value > static_cast<U32Type>(0x10FFFFu))
|
||||
invalid_sequence();
|
||||
}
|
||||
BaseIterator m_position;
|
||||
mutable U32Type m_value;
|
||||
};
|
||||
|
||||
template <class BaseIterator>
|
||||
class utf16_output_iterator
|
||||
{
|
||||
public:
|
||||
typedef void difference_type;
|
||||
typedef void value_type;
|
||||
typedef boost::uint32_t* pointer;
|
||||
typedef boost::uint32_t& reference;
|
||||
typedef std::output_iterator_tag iterator_category;
|
||||
|
||||
utf16_output_iterator(const BaseIterator& b)
|
||||
: m_position(b){}
|
||||
utf16_output_iterator(const utf16_output_iterator& that)
|
||||
: m_position(that.m_position){}
|
||||
utf16_output_iterator& operator=(const utf16_output_iterator& that)
|
||||
{
|
||||
m_position = that.m_position;
|
||||
return *this;
|
||||
}
|
||||
const utf16_output_iterator& operator*()const
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
void operator=(boost::uint32_t val)const
|
||||
{
|
||||
push(val);
|
||||
}
|
||||
utf16_output_iterator& operator++()
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
utf16_output_iterator& operator++(int)
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
BaseIterator base()const
|
||||
{
|
||||
return m_position;
|
||||
}
|
||||
private:
|
||||
void push(boost::uint32_t v)const
|
||||
{
|
||||
if(v >= 0x10000u)
|
||||
{
|
||||
// begin by checking for a code point out of range:
|
||||
if(v > 0x10FFFFu)
|
||||
detail::invalid_utf32_code_point(v);
|
||||
// split into two surrogates:
|
||||
*m_position++ = static_cast<boost::uint16_t>(v >> 10) + detail::high_surrogate_base;
|
||||
*m_position++ = static_cast<boost::uint16_t>(v & detail::ten_bit_mask) + detail::low_surrogate_base;
|
||||
}
|
||||
else
|
||||
{
|
||||
// 16-bit code point:
|
||||
// value must not be a surrogate:
|
||||
if(detail::is_surrogate(v))
|
||||
detail::invalid_utf32_code_point(v);
|
||||
*m_position++ = static_cast<boost::uint16_t>(v);
|
||||
}
|
||||
}
|
||||
mutable BaseIterator m_position;
|
||||
};
|
||||
|
||||
template <class BaseIterator>
|
||||
class utf8_output_iterator
|
||||
{
|
||||
public:
|
||||
typedef void difference_type;
|
||||
typedef void value_type;
|
||||
typedef boost::uint32_t* pointer;
|
||||
typedef boost::uint32_t& reference;
|
||||
typedef std::output_iterator_tag iterator_category;
|
||||
|
||||
utf8_output_iterator(const BaseIterator& b)
|
||||
: m_position(b){}
|
||||
utf8_output_iterator(const utf8_output_iterator& that)
|
||||
: m_position(that.m_position){}
|
||||
utf8_output_iterator& operator=(const utf8_output_iterator& that)
|
||||
{
|
||||
m_position = that.m_position;
|
||||
return *this;
|
||||
}
|
||||
const utf8_output_iterator& operator*()const
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
void operator=(boost::uint32_t val)const
|
||||
{
|
||||
push(val);
|
||||
}
|
||||
utf8_output_iterator& operator++()
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
utf8_output_iterator& operator++(int)
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
BaseIterator base()const
|
||||
{
|
||||
return m_position;
|
||||
}
|
||||
private:
|
||||
void push(boost::uint32_t c)const
|
||||
{
|
||||
if(c > 0x10FFFFu)
|
||||
detail::invalid_utf32_code_point(c);
|
||||
if(c < 0x80u)
|
||||
{
|
||||
*m_position++ = static_cast<unsigned char>(c);
|
||||
}
|
||||
else if(c < 0x800u)
|
||||
{
|
||||
*m_position++ = static_cast<unsigned char>(0xC0u + (c >> 6));
|
||||
*m_position++ = static_cast<unsigned char>(0x80u + (c & 0x3Fu));
|
||||
}
|
||||
else if(c < 0x10000u)
|
||||
{
|
||||
*m_position++ = static_cast<unsigned char>(0xE0u + (c >> 12));
|
||||
*m_position++ = static_cast<unsigned char>(0x80u + ((c >> 6) & 0x3Fu));
|
||||
*m_position++ = static_cast<unsigned char>(0x80u + (c & 0x3Fu));
|
||||
}
|
||||
else
|
||||
{
|
||||
*m_position++ = static_cast<unsigned char>(0xF0u + (c >> 18));
|
||||
*m_position++ = static_cast<unsigned char>(0x80u + ((c >> 12) & 0x3Fu));
|
||||
*m_position++ = static_cast<unsigned char>(0x80u + ((c >> 6) & 0x3Fu));
|
||||
*m_position++ = static_cast<unsigned char>(0x80u + (c & 0x3Fu));
|
||||
}
|
||||
}
|
||||
mutable BaseIterator m_position;
|
||||
};
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_REGEX_UNICODE_ITERATOR_HPP
|
||||
|
103
third_party/libosmium/include/mmap_for_windows.hpp
vendored
103
third_party/libosmium/include/mmap_for_windows.hpp
vendored
@ -1,103 +0,0 @@
|
||||
#ifndef MMAP_FOR_WINDOWS_HPP
|
||||
#define MMAP_FOR_WINDOWS_HPP
|
||||
|
||||
/* mmap() replacement for Windows
|
||||
*
|
||||
* Author: Mike Frysinger <vapier@gentoo.org>
|
||||
* Placed into the public domain
|
||||
*/
|
||||
|
||||
/* References:
|
||||
* CreateFileMapping: http://msdn.microsoft.com/en-us/library/aa366537(VS.85).aspx
|
||||
* CloseHandle: http://msdn.microsoft.com/en-us/library/ms724211(VS.85).aspx
|
||||
* MapViewOfFile: http://msdn.microsoft.com/en-us/library/aa366761(VS.85).aspx
|
||||
* UnmapViewOfFile: http://msdn.microsoft.com/en-us/library/aa366882(VS.85).aspx
|
||||
*/
|
||||
|
||||
#include <io.h>
|
||||
#include <windows.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#define PROT_READ 0x1
|
||||
#define PROT_WRITE 0x2
|
||||
/* This flag is only available in WinXP+ */
|
||||
#ifdef FILE_MAP_EXECUTE
|
||||
#define PROT_EXEC 0x4
|
||||
#else
|
||||
#define PROT_EXEC 0x0
|
||||
#define FILE_MAP_EXECUTE 0
|
||||
#endif
|
||||
|
||||
#define MAP_SHARED 0x01
|
||||
#define MAP_PRIVATE 0x02
|
||||
#define MAP_ANONYMOUS 0x20
|
||||
#define MAP_ANON MAP_ANONYMOUS
|
||||
#define MAP_FAILED ((void *) -1)
|
||||
|
||||
static DWORD dword_hi(uint64_t x) {
|
||||
return static_cast<DWORD>(x >> 32);
|
||||
}
|
||||
|
||||
static DWORD dword_lo(uint64_t x) {
|
||||
return static_cast<DWORD>(x & 0xffffffff);
|
||||
}
|
||||
|
||||
static void *mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset)
|
||||
{
|
||||
if (prot & ~(PROT_READ | PROT_WRITE | PROT_EXEC))
|
||||
return MAP_FAILED;
|
||||
if (fd == -1) {
|
||||
if (!(flags & MAP_ANON) || offset)
|
||||
return MAP_FAILED;
|
||||
} else if (flags & MAP_ANON)
|
||||
return MAP_FAILED;
|
||||
|
||||
DWORD flProtect;
|
||||
if (prot & PROT_WRITE) {
|
||||
if (prot & PROT_EXEC)
|
||||
flProtect = PAGE_EXECUTE_READWRITE;
|
||||
else
|
||||
flProtect = PAGE_READWRITE;
|
||||
} else if (prot & PROT_EXEC) {
|
||||
if (prot & PROT_READ)
|
||||
flProtect = PAGE_EXECUTE_READ;
|
||||
else if (prot & PROT_EXEC)
|
||||
flProtect = PAGE_EXECUTE;
|
||||
} else
|
||||
flProtect = PAGE_READONLY;
|
||||
|
||||
uint64_t end = static_cast<uint64_t>(length) + offset;
|
||||
HANDLE mmap_fd;
|
||||
if (fd == -1)
|
||||
mmap_fd = INVALID_HANDLE_VALUE;
|
||||
else
|
||||
mmap_fd = (HANDLE)_get_osfhandle(fd);
|
||||
|
||||
HANDLE h = CreateFileMapping(mmap_fd, NULL, flProtect, dword_hi(end), dword_lo(end), NULL);
|
||||
if (h == NULL)
|
||||
return MAP_FAILED;
|
||||
|
||||
DWORD dwDesiredAccess;
|
||||
if (prot & PROT_WRITE)
|
||||
dwDesiredAccess = FILE_MAP_WRITE;
|
||||
else
|
||||
dwDesiredAccess = FILE_MAP_READ;
|
||||
if (prot & PROT_EXEC)
|
||||
dwDesiredAccess |= FILE_MAP_EXECUTE;
|
||||
if (flags & MAP_PRIVATE)
|
||||
dwDesiredAccess |= FILE_MAP_COPY;
|
||||
void *ret = MapViewOfFile(h, dwDesiredAccess, dword_hi(offset), dword_lo(offset), length);
|
||||
if (ret == NULL) {
|
||||
CloseHandle(h);
|
||||
ret = MAP_FAILED;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int munmap(void *addr, size_t length)
|
||||
{
|
||||
return UnmapViewOfFile(addr) ? 0 : -1;
|
||||
/* ruh-ro, we leaked handle from CreateFileMapping() ... */
|
||||
}
|
||||
|
||||
#endif
|
@ -171,7 +171,7 @@ namespace osmium {
|
||||
}
|
||||
|
||||
void add_tags_to_area(osmium::builder::AreaBuilder& builder, const osmium::Relation& relation) const {
|
||||
auto count = std::count_if(relation.tags().begin(), relation.tags().end(), filter());
|
||||
const auto count = std::count_if(relation.tags().begin(), relation.tags().end(), filter());
|
||||
|
||||
if (debug()) {
|
||||
std::cerr << " found " << count << " tags on relation (without ignored ones)\n";
|
||||
@ -331,7 +331,7 @@ namespace osmium {
|
||||
if (debug()) {
|
||||
std::cerr << " has_closed_subring_back()\n";
|
||||
}
|
||||
auto end = ring.segments().end();
|
||||
const auto end = ring.segments().end();
|
||||
for (auto it = ring.segments().begin() + 1; it != end - 1; ++it) {
|
||||
if (has_same_location(nr, it->first())) {
|
||||
split_off_subring(ring, it, it, end);
|
||||
@ -348,7 +348,7 @@ namespace osmium {
|
||||
if (debug()) {
|
||||
std::cerr << " has_closed_subring_front()\n";
|
||||
}
|
||||
auto end = ring.segments().end();
|
||||
const auto end = ring.segments().end();
|
||||
for (auto it = ring.segments().begin() + 1; it != end - 1; ++it) {
|
||||
if (has_same_location(nr, it->second())) {
|
||||
split_off_subring(ring, it, ring.segments().begin(), it+1);
|
||||
@ -366,22 +366,22 @@ namespace osmium {
|
||||
osmium::area::detail::ProtoRing::segments_type segments(ring.segments().size());
|
||||
std::copy(ring.segments().begin(), ring.segments().end(), segments.begin());
|
||||
std::sort(segments.begin(), segments.end());
|
||||
auto it = std::adjacent_find(segments.begin(), segments.end(), [this](const osmium::area::detail::NodeRefSegment& s1, const osmium::area::detail::NodeRefSegment& s2) {
|
||||
const auto it = std::adjacent_find(segments.begin(), segments.end(), [this](const osmium::area::detail::NodeRefSegment& s1, const osmium::area::detail::NodeRefSegment& s2) {
|
||||
return has_same_location(s1.first(), s2.first());
|
||||
});
|
||||
if (it == segments.end()) {
|
||||
return false;
|
||||
}
|
||||
auto r1 = std::find_first_of(ring.segments().begin(), ring.segments().end(), it, it+1);
|
||||
const auto r1 = std::find_first_of(ring.segments().begin(), ring.segments().end(), it, it+1);
|
||||
assert(r1 != ring.segments().end());
|
||||
auto r2 = std::find_first_of(ring.segments().begin(), ring.segments().end(), it+1, it+2);
|
||||
const auto r2 = std::find_first_of(ring.segments().begin(), ring.segments().end(), it+1, it+2);
|
||||
assert(r2 != ring.segments().end());
|
||||
|
||||
if (debug()) {
|
||||
std::cerr << " found subring in ring " << ring << " at " << it->first() << "\n";
|
||||
}
|
||||
|
||||
auto m = std::minmax(r1, r2);
|
||||
const auto m = std::minmax(r1, r2);
|
||||
|
||||
ProtoRing new_ring(m.first, m.second);
|
||||
ring.remove_segments(m.first, m.second);
|
||||
@ -537,7 +537,7 @@ namespace osmium {
|
||||
}
|
||||
|
||||
for (const auto ringptr : m_outer_rings) {
|
||||
for (const auto segment : ringptr->segments()) {
|
||||
for (const auto& segment : ringptr->segments()) {
|
||||
if (!segment.role_outer()) {
|
||||
++m_inner_outer_mismatches;
|
||||
if (debug()) {
|
||||
@ -550,7 +550,7 @@ namespace osmium {
|
||||
}
|
||||
}
|
||||
for (const auto ringptr : m_inner_rings) {
|
||||
for (const auto segment : ringptr->segments()) {
|
||||
for (const auto& segment : ringptr->segments()) {
|
||||
if (!segment.role_inner()) {
|
||||
++m_inner_outer_mismatches;
|
||||
if (debug()) {
|
||||
|
@ -41,6 +41,8 @@ DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#include <osmium/memory/buffer.hpp>
|
||||
#include <osmium/osm/item_type.hpp>
|
||||
#include <osmium/osm/location.hpp>
|
||||
#include <osmium/osm/node_ref.hpp>
|
||||
#include <osmium/osm/relation.hpp>
|
||||
#include <osmium/osm/tag.hpp>
|
||||
#include <osmium/osm/way.hpp>
|
||||
@ -49,8 +51,6 @@ DEALINGS IN THE SOFTWARE.
|
||||
|
||||
namespace osmium {
|
||||
|
||||
struct invalid_location;
|
||||
|
||||
namespace relations {
|
||||
class RelationMeta;
|
||||
}
|
||||
@ -107,8 +107,8 @@ namespace osmium {
|
||||
}
|
||||
|
||||
/**
|
||||
* We are interested in all relations tagged with type=multipolygon or
|
||||
* type=boundary.
|
||||
* We are interested in all relations tagged with type=multipolygon
|
||||
* or type=boundary.
|
||||
*
|
||||
* Overwritten from the base class.
|
||||
*/
|
||||
@ -142,17 +142,24 @@ namespace osmium {
|
||||
* Overwritten from the base class.
|
||||
*/
|
||||
void way_not_in_any_relation(const osmium::Way& way) {
|
||||
if (way.nodes().size() > 3 && way.ends_have_same_location()) {
|
||||
// way is closed and has enough nodes, build simple multipolygon
|
||||
// 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, m_output_buffer);
|
||||
possibly_flush_output_buffer();
|
||||
}
|
||||
} catch (osmium::invalid_location&) {
|
||||
// XXX ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void complete_relation(osmium::relations::RelationMeta& relation_meta) {
|
||||
const osmium::Relation& relation = this->get_relation(relation_meta);
|
||||
|
@ -147,6 +147,7 @@ namespace osmium {
|
||||
* @param length Length of data in bytes. If data is a
|
||||
* \0-terminated string, length must contain the
|
||||
* \0 byte.
|
||||
* @returns The number of bytes appended (length).
|
||||
*/
|
||||
osmium::memory::item_size_type append(const char* data, const osmium::memory::item_size_type length) {
|
||||
unsigned char* target = m_buffer.reserve_space(length);
|
||||
@ -156,11 +157,24 @@ namespace osmium {
|
||||
|
||||
/**
|
||||
* Append \0-terminated string to buffer.
|
||||
*
|
||||
* @param str \0-terminated string.
|
||||
* @returns The number of bytes appended (strlen(str) + 1).
|
||||
*/
|
||||
osmium::memory::item_size_type append(const char* str) {
|
||||
return append(str, static_cast<osmium::memory::item_size_type>(std::strlen(str) + 1));
|
||||
}
|
||||
|
||||
/**
|
||||
* Append '\0' to the buffer.
|
||||
*
|
||||
* @returns The number of bytes appended (always 1).
|
||||
*/
|
||||
osmium::memory::item_size_type append_zero() {
|
||||
*m_buffer.reserve_space(1) = '\0';
|
||||
return 1;
|
||||
}
|
||||
|
||||
/// Return the buffer this builder is using.
|
||||
osmium::memory::Buffer& buffer() noexcept {
|
||||
return m_buffer;
|
||||
@ -188,11 +202,11 @@ namespace osmium {
|
||||
* Add user name to buffer.
|
||||
*
|
||||
* @param user Pointer to user name.
|
||||
* @param length Length of user name including \0 byte.
|
||||
* @param length Length of user name (without \0 termination).
|
||||
*/
|
||||
void add_user(const char* user, const string_size_type length) {
|
||||
object().set_user_size(length);
|
||||
add_size(append(user, length));
|
||||
object().set_user_size(length + 1);
|
||||
add_size(append(user, length) + append_zero());
|
||||
add_padding(true);
|
||||
}
|
||||
|
||||
@ -202,7 +216,7 @@ namespace osmium {
|
||||
* @param user Pointer to \0-terminated user name.
|
||||
*/
|
||||
void add_user(const char* user) {
|
||||
add_user(user, static_cast_with_assert<string_size_type>(std::strlen(user) + 1));
|
||||
add_user(user, static_cast_with_assert<string_size_type>(std::strlen(user)));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -211,7 +225,7 @@ namespace osmium {
|
||||
* @param user User name.
|
||||
*/
|
||||
void add_user(const std::string& user) {
|
||||
add_user(user.data(), static_cast_with_assert<string_size_type>(user.size() + 1));
|
||||
add_user(user.data(), static_cast_with_assert<string_size_type>(user.size()));
|
||||
}
|
||||
|
||||
}; // class ObjectBuilder
|
||||
|
@ -72,13 +72,25 @@ namespace osmium {
|
||||
/**
|
||||
* Add tag to buffer.
|
||||
*
|
||||
* @param key Tag key.
|
||||
* @param value Tag value.
|
||||
* @param key Tag key (0-terminated string).
|
||||
* @param value Tag value (0-terminated string).
|
||||
*/
|
||||
void add_tag(const char* key, const char* value) {
|
||||
add_size(append(key) + append(value));
|
||||
}
|
||||
|
||||
/**
|
||||
* Add tag to buffer.
|
||||
*
|
||||
* @param key Pointer to tag key.
|
||||
* @param key_length Length of key (not including the \0 byte).
|
||||
* @param value Pointer to tag value.
|
||||
* @param value_length Length of value (not including the \0 byte).
|
||||
*/
|
||||
void add_tag(const char* key, const string_size_type key_length, const char* value, const string_size_type value_length) {
|
||||
add_size(append(key, key_length) + append_zero() + append(value, value_length) + append_zero());
|
||||
}
|
||||
|
||||
/**
|
||||
* Add tag to buffer.
|
||||
*
|
||||
@ -128,11 +140,11 @@ namespace osmium {
|
||||
* @param member Relation member object where the length of the role
|
||||
* will be set.
|
||||
* @param role The role.
|
||||
* @param length Length of role string including \0 termination.
|
||||
* @param length Length of role (without \0 termination).
|
||||
*/
|
||||
void add_role(osmium::RelationMember& member, const char* role, const string_size_type length) {
|
||||
member.set_role_size(length);
|
||||
add_size(append(role, length));
|
||||
member.set_role_size(length + 1);
|
||||
add_size(append(role, length) + append_zero());
|
||||
add_padding(true);
|
||||
}
|
||||
|
||||
@ -144,7 +156,7 @@ namespace osmium {
|
||||
* @param role \0-terminated role.
|
||||
*/
|
||||
void add_role(osmium::RelationMember& member, const char* role) {
|
||||
add_role(member, role, static_cast_with_assert<string_size_type>(std::strlen(role) + 1));
|
||||
add_role(member, role, static_cast_with_assert<string_size_type>(std::strlen(role)));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -155,7 +167,7 @@ namespace osmium {
|
||||
* @param role Role.
|
||||
*/
|
||||
void add_role(osmium::RelationMember& member, const std::string& role) {
|
||||
add_role(member, role.data(), static_cast_with_assert<string_size_type>(role.size() + 1));
|
||||
add_role(member, role.data(), static_cast_with_assert<string_size_type>(role.size()));
|
||||
}
|
||||
|
||||
public:
|
||||
@ -174,18 +186,33 @@ namespace osmium {
|
||||
* @param type The type (node, way, or relation).
|
||||
* @param ref The ID of the member.
|
||||
* @param role The role of the member.
|
||||
* @param role_length Length of the role (without \0 termination).
|
||||
* @param full_member Optional pointer to the member object. If it
|
||||
* is available a copy will be added to the
|
||||
* relation.
|
||||
*/
|
||||
void add_member(osmium::item_type type, object_id_type ref, const char* role, const string_size_type 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);
|
||||
add_size(sizeof(RelationMember));
|
||||
add_role(*member, role, role_length);
|
||||
if (full_member) {
|
||||
add_item(full_member);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a member to the relation.
|
||||
*
|
||||
* @param type The type (node, way, or relation).
|
||||
* @param ref The ID of the member.
|
||||
* @param role The role of the member (\0 terminated string).
|
||||
* @param full_member Optional pointer to the member object. If it
|
||||
* is available a copy will be added to the
|
||||
* relation.
|
||||
*/
|
||||
void add_member(osmium::item_type type, object_id_type ref, const char* role, const osmium::OSMObject* full_member = nullptr) {
|
||||
osmium::RelationMember* member = reserve_space_for<osmium::RelationMember>();
|
||||
new (member) osmium::RelationMember(ref, type, full_member != nullptr);
|
||||
add_size(sizeof(RelationMember));
|
||||
add_role(*member, role);
|
||||
if (full_member) {
|
||||
add_item(full_member);
|
||||
}
|
||||
add_member(type, ref, role, strlen(role), full_member);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -199,13 +226,7 @@ namespace osmium {
|
||||
* relation.
|
||||
*/
|
||||
void add_member(osmium::item_type type, object_id_type ref, const std::string& role, const osmium::OSMObject* full_member = nullptr) {
|
||||
osmium::RelationMember* member = reserve_space_for<osmium::RelationMember>();
|
||||
new (member) osmium::RelationMember(ref, type, full_member != nullptr);
|
||||
add_size(sizeof(RelationMember));
|
||||
add_role(*member, role);
|
||||
if (full_member) {
|
||||
add_item(full_member);
|
||||
}
|
||||
add_member(type, ref, role.data(), role.size(), full_member);
|
||||
}
|
||||
|
||||
}; // class RelationMemberListBuilder
|
||||
|
@ -54,14 +54,43 @@ namespace osmium {
|
||||
* Exception thrown when an invalid geometry is encountered. An example
|
||||
* would be a linestring with less than two points.
|
||||
*/
|
||||
struct geometry_error : public std::runtime_error {
|
||||
class geometry_error : public std::runtime_error {
|
||||
|
||||
geometry_error(const std::string& what) :
|
||||
std::runtime_error(what) {
|
||||
std::string m_message;
|
||||
osmium::object_id_type m_id;
|
||||
|
||||
public:
|
||||
|
||||
geometry_error(const std::string& message, const char* object_type = "", osmium::object_id_type id = 0) :
|
||||
std::runtime_error(message),
|
||||
m_message(message),
|
||||
m_id(id) {
|
||||
if (m_id != 0) {
|
||||
m_message += " (";
|
||||
m_message += object_type;
|
||||
m_message += "_id=";
|
||||
m_message += std::to_string(m_id);
|
||||
m_message += ")";
|
||||
}
|
||||
}
|
||||
|
||||
geometry_error(const char* what) :
|
||||
std::runtime_error(what) {
|
||||
void set_id(const char* object_type, osmium::object_id_type id) {
|
||||
if (m_id == 0 && id != 0) {
|
||||
m_message += " (";
|
||||
m_message += object_type;
|
||||
m_message += "_id=";
|
||||
m_message += std::to_string(id);
|
||||
m_message += ")";
|
||||
}
|
||||
m_id = id;
|
||||
}
|
||||
|
||||
osmium::object_id_type id() const noexcept {
|
||||
return m_id;
|
||||
}
|
||||
|
||||
virtual const char* what() const noexcept override {
|
||||
return m_message.c_str();
|
||||
}
|
||||
|
||||
}; // struct geometry_error
|
||||
@ -174,11 +203,21 @@ namespace osmium {
|
||||
}
|
||||
|
||||
point_type create_point(const osmium::Node& node) {
|
||||
try {
|
||||
return create_point(node.location());
|
||||
} catch (osmium::geometry_error& e) {
|
||||
e.set_id("node", node.id());
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
point_type create_point(const osmium::NodeRef& node_ref) {
|
||||
try {
|
||||
return create_point(node_ref.location());
|
||||
} catch (osmium::geometry_error& e) {
|
||||
e.set_id("node", node_ref.ref());
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
/* LineString */
|
||||
@ -240,14 +279,19 @@ namespace osmium {
|
||||
}
|
||||
|
||||
if (num_points < 2) {
|
||||
throw osmium::geometry_error("not enough points for linestring");
|
||||
throw osmium::geometry_error("need at least two points for linestring");
|
||||
}
|
||||
|
||||
return linestring_finish(num_points);
|
||||
}
|
||||
|
||||
linestring_type create_linestring(const osmium::Way& way, use_nodes un=use_nodes::unique, direction dir=direction::forward) {
|
||||
try {
|
||||
return create_linestring(way.nodes(), un, dir);
|
||||
} catch (osmium::geometry_error& e) {
|
||||
e.set_id("way", way.id());
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
/* Polygon */
|
||||
@ -283,9 +327,51 @@ namespace osmium {
|
||||
return m_impl.polygon_finish(num_points);
|
||||
}
|
||||
|
||||
polygon_type create_polygon(const osmium::WayNodeList& wnl, use_nodes un = use_nodes::unique, direction dir = direction::forward) {
|
||||
polygon_start();
|
||||
size_t num_points = 0;
|
||||
|
||||
if (un == use_nodes::unique) {
|
||||
osmium::Location last_location;
|
||||
switch (dir) {
|
||||
case direction::forward:
|
||||
num_points = fill_polygon_unique(wnl.cbegin(), wnl.cend());
|
||||
break;
|
||||
case direction::backward:
|
||||
num_points = fill_polygon_unique(wnl.crbegin(), wnl.crend());
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
switch (dir) {
|
||||
case direction::forward:
|
||||
num_points = fill_polygon(wnl.cbegin(), wnl.cend());
|
||||
break;
|
||||
case direction::backward:
|
||||
num_points = fill_polygon(wnl.crbegin(), wnl.crend());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (num_points < 4) {
|
||||
throw osmium::geometry_error("need at least four points for polygon");
|
||||
}
|
||||
|
||||
return polygon_finish(num_points);
|
||||
}
|
||||
|
||||
polygon_type create_polygon(const osmium::Way& way, use_nodes un=use_nodes::unique, direction dir=direction::forward) {
|
||||
try {
|
||||
return create_polygon(way.nodes(), un, dir);
|
||||
} catch (osmium::geometry_error& e) {
|
||||
e.set_id("way", way.id());
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
/* MultiPolygon */
|
||||
|
||||
multipolygon_type create_multipolygon(const osmium::Area& area) {
|
||||
try {
|
||||
size_t num_polygons = 0;
|
||||
size_t num_rings = 0;
|
||||
m_impl.multipolygon_start();
|
||||
@ -312,11 +398,15 @@ namespace osmium {
|
||||
|
||||
// if there are no rings, this area is invalid
|
||||
if (num_rings == 0) {
|
||||
throw osmium::geometry_error("invalid area");
|
||||
throw osmium::geometry_error("area contains no rings");
|
||||
}
|
||||
|
||||
m_impl.multipolygon_polygon_finish();
|
||||
return m_impl.multipolygon_finish();
|
||||
} catch (osmium::geometry_error& e) {
|
||||
e.set_id("area", area.id());
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
}; // class GeometryFactory
|
||||
|
@ -42,6 +42,8 @@ DEALINGS IN THE SOFTWARE.
|
||||
* @attention If you include this file, you'll need to link with `libgeos`.
|
||||
*/
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
#include <geos/geom/Coordinate.h>
|
||||
@ -69,8 +71,8 @@ namespace osmium {
|
||||
|
||||
struct geos_geometry_error : public geometry_error {
|
||||
|
||||
geos_geometry_error() :
|
||||
geometry_error("geometry creation failed in GEOS library, see nested exception for details") {
|
||||
geos_geometry_error(const char* message) :
|
||||
geometry_error(std::string("geometry creation failed in GEOS library: ") + message) {
|
||||
}
|
||||
|
||||
}; // struct geos_geometry_error
|
||||
@ -81,8 +83,9 @@ namespace osmium {
|
||||
|
||||
class GEOSFactoryImpl {
|
||||
|
||||
geos::geom::PrecisionModel m_precision_model;
|
||||
geos::geom::GeometryFactory m_geos_factory;
|
||||
std::unique_ptr<const geos::geom::PrecisionModel> m_precision_model;
|
||||
std::unique_ptr<geos::geom::GeometryFactory> m_our_geos_factory;
|
||||
geos::geom::GeometryFactory* m_geos_factory;
|
||||
|
||||
std::unique_ptr<geos::geom::CoordinateSequence> m_coordinate_sequence;
|
||||
std::vector<std::unique_ptr<geos::geom::LinearRing>> m_rings;
|
||||
@ -96,18 +99,25 @@ namespace osmium {
|
||||
typedef std::unique_ptr<geos::geom::MultiPolygon> multipolygon_type;
|
||||
typedef std::unique_ptr<geos::geom::LinearRing> ring_type;
|
||||
|
||||
explicit GEOSFactoryImpl(geos::geom::GeometryFactory& geos_factory) :
|
||||
m_precision_model(nullptr),
|
||||
m_our_geos_factory(nullptr),
|
||||
m_geos_factory(&geos_factory) {
|
||||
}
|
||||
|
||||
explicit GEOSFactoryImpl(int srid = -1) :
|
||||
m_precision_model(),
|
||||
m_geos_factory(&m_precision_model, srid) {
|
||||
m_precision_model(new geos::geom::PrecisionModel),
|
||||
m_our_geos_factory(new geos::geom::GeometryFactory(m_precision_model.get(), srid)),
|
||||
m_geos_factory(m_our_geos_factory.get()) {
|
||||
}
|
||||
|
||||
/* Point */
|
||||
|
||||
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)));
|
||||
} catch (geos::util::GEOSException&) {
|
||||
THROW(osmium::geos_geometry_error());
|
||||
return point_type(m_geos_factory->createPoint(geos::geom::Coordinate(xy.x, xy.y)));
|
||||
} catch (geos::util::GEOSException& e) {
|
||||
THROW(osmium::geos_geometry_error(e.what()));
|
||||
}
|
||||
}
|
||||
|
||||
@ -115,25 +125,25 @@ namespace osmium {
|
||||
|
||||
void linestring_start() {
|
||||
try {
|
||||
m_coordinate_sequence.reset(m_geos_factory.getCoordinateSequenceFactory()->create(static_cast<size_t>(0), 2));
|
||||
} catch (geos::util::GEOSException&) {
|
||||
THROW(osmium::geos_geometry_error());
|
||||
m_coordinate_sequence.reset(m_geos_factory->getCoordinateSequenceFactory()->create(static_cast<size_t>(0), 2));
|
||||
} catch (geos::util::GEOSException& e) {
|
||||
THROW(osmium::geos_geometry_error(e.what()));
|
||||
}
|
||||
}
|
||||
|
||||
void linestring_add_location(const osmium::geom::Coordinates& xy) {
|
||||
try {
|
||||
m_coordinate_sequence->add(geos::geom::Coordinate(xy.x, xy.y));
|
||||
} catch (geos::util::GEOSException&) {
|
||||
THROW(osmium::geos_geometry_error());
|
||||
} catch (geos::util::GEOSException& e) {
|
||||
THROW(osmium::geos_geometry_error(e.what()));
|
||||
}
|
||||
}
|
||||
|
||||
linestring_type linestring_finish(size_t /* num_points */) {
|
||||
try {
|
||||
return linestring_type(m_geos_factory.createLineString(m_coordinate_sequence.release()));
|
||||
} catch (geos::util::GEOSException&) {
|
||||
THROW(osmium::geos_geometry_error());
|
||||
return linestring_type(m_geos_factory->createLineString(m_coordinate_sequence.release()));
|
||||
} catch (geos::util::GEOSException& e) {
|
||||
THROW(osmium::geos_geometry_error(e.what()));
|
||||
}
|
||||
}
|
||||
|
||||
@ -154,50 +164,50 @@ namespace osmium {
|
||||
std::transform(std::next(m_rings.begin(), 1), m_rings.end(), std::back_inserter(*inner_rings), [](std::unique_ptr<geos::geom::LinearRing>& r) {
|
||||
return r.release();
|
||||
});
|
||||
m_polygons.emplace_back(m_geos_factory.createPolygon(m_rings[0].release(), inner_rings));
|
||||
m_polygons.emplace_back(m_geos_factory->createPolygon(m_rings[0].release(), inner_rings));
|
||||
m_rings.clear();
|
||||
} catch (geos::util::GEOSException&) {
|
||||
THROW(osmium::geos_geometry_error());
|
||||
} catch (geos::util::GEOSException& e) {
|
||||
THROW(osmium::geos_geometry_error(e.what()));
|
||||
}
|
||||
}
|
||||
|
||||
void multipolygon_outer_ring_start() {
|
||||
try {
|
||||
m_coordinate_sequence.reset(m_geos_factory.getCoordinateSequenceFactory()->create(static_cast<size_t>(0), 2));
|
||||
} catch (geos::util::GEOSException&) {
|
||||
THROW(osmium::geos_geometry_error());
|
||||
m_coordinate_sequence.reset(m_geos_factory->getCoordinateSequenceFactory()->create(static_cast<size_t>(0), 2));
|
||||
} catch (geos::util::GEOSException& e) {
|
||||
THROW(osmium::geos_geometry_error(e.what()));
|
||||
}
|
||||
}
|
||||
|
||||
void multipolygon_outer_ring_finish() {
|
||||
try {
|
||||
m_rings.emplace_back(m_geos_factory.createLinearRing(m_coordinate_sequence.release()));
|
||||
} catch (geos::util::GEOSException&) {
|
||||
THROW(osmium::geos_geometry_error());
|
||||
m_rings.emplace_back(m_geos_factory->createLinearRing(m_coordinate_sequence.release()));
|
||||
} catch (geos::util::GEOSException& e) {
|
||||
THROW(osmium::geos_geometry_error(e.what()));
|
||||
}
|
||||
}
|
||||
|
||||
void multipolygon_inner_ring_start() {
|
||||
try {
|
||||
m_coordinate_sequence.reset(m_geos_factory.getCoordinateSequenceFactory()->create(static_cast<size_t>(0), 2));
|
||||
} catch (geos::util::GEOSException&) {
|
||||
THROW(osmium::geos_geometry_error());
|
||||
m_coordinate_sequence.reset(m_geos_factory->getCoordinateSequenceFactory()->create(static_cast<size_t>(0), 2));
|
||||
} catch (geos::util::GEOSException& e) {
|
||||
THROW(osmium::geos_geometry_error(e.what()));
|
||||
}
|
||||
}
|
||||
|
||||
void multipolygon_inner_ring_finish() {
|
||||
try {
|
||||
m_rings.emplace_back(m_geos_factory.createLinearRing(m_coordinate_sequence.release()));
|
||||
} catch (geos::util::GEOSException&) {
|
||||
THROW(osmium::geos_geometry_error());
|
||||
m_rings.emplace_back(m_geos_factory->createLinearRing(m_coordinate_sequence.release()));
|
||||
} catch (geos::util::GEOSException& e) {
|
||||
THROW(osmium::geos_geometry_error(e.what()));
|
||||
}
|
||||
}
|
||||
|
||||
void multipolygon_add_location(const osmium::geom::Coordinates& xy) {
|
||||
try {
|
||||
m_coordinate_sequence->add(geos::geom::Coordinate(xy.x, xy.y));
|
||||
} catch (geos::util::GEOSException&) {
|
||||
THROW(osmium::geos_geometry_error());
|
||||
} catch (geos::util::GEOSException& e) {
|
||||
THROW(osmium::geos_geometry_error(e.what()));
|
||||
}
|
||||
}
|
||||
|
||||
@ -208,9 +218,9 @@ namespace osmium {
|
||||
return p.release();
|
||||
});
|
||||
m_polygons.clear();
|
||||
return multipolygon_type(m_geos_factory.createMultiPolygon(polygons));
|
||||
} catch (geos::util::GEOSException&) {
|
||||
THROW(osmium::geos_geometry_error());
|
||||
return multipolygon_type(m_geos_factory->createMultiPolygon(polygons));
|
||||
} catch (geos::util::GEOSException& e) {
|
||||
THROW(osmium::geos_geometry_error(e.what()));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -47,6 +47,7 @@ namespace osmium {
|
||||
namespace detail {
|
||||
|
||||
constexpr double earth_radius_for_epsg3857 = 6378137.0;
|
||||
constexpr double max_coordinate_epsg3857 = 20037508.34;
|
||||
|
||||
constexpr inline double lon_to_x(double lon) {
|
||||
return earth_radius_for_epsg3857 * deg_to_rad(lon);
|
||||
|
190
third_party/libosmium/include/osmium/geom/rapid_geojson.hpp
vendored
Normal file
190
third_party/libosmium/include/osmium/geom/rapid_geojson.hpp
vendored
Normal file
@ -0,0 +1,190 @@
|
||||
#ifndef OSMIUM_GEOM_RAPID_GEOJSON_HPP
|
||||
#define OSMIUM_GEOM_RAPID_GEOJSON_HPP
|
||||
|
||||
/*
|
||||
|
||||
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||
|
||||
Copyright 2013-2015 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/geom/coordinates.hpp>
|
||||
#include <osmium/geom/factory.hpp>
|
||||
|
||||
namespace osmium {
|
||||
|
||||
namespace geom {
|
||||
|
||||
namespace detail {
|
||||
|
||||
/**
|
||||
* A geometry factory implementation that can be used with the
|
||||
* RapidJSON (https://github.com/miloyip/rapidjson) JSON writer.
|
||||
*/
|
||||
template <class TWriter>
|
||||
class RapidGeoJSONFactoryImpl {
|
||||
|
||||
TWriter* m_writer;
|
||||
|
||||
public:
|
||||
|
||||
typedef void point_type;
|
||||
typedef void linestring_type;
|
||||
typedef void polygon_type;
|
||||
typedef void multipolygon_type;
|
||||
typedef void ring_type;
|
||||
|
||||
RapidGeoJSONFactoryImpl(TWriter& writer) :
|
||||
m_writer(&writer) {
|
||||
}
|
||||
|
||||
/* Point */
|
||||
|
||||
// { "type": "Point", "coordinates": [100.0, 0.0] }
|
||||
point_type make_point(const osmium::geom::Coordinates& xy) const {
|
||||
m_writer->String("geometry");
|
||||
m_writer->StartObject();
|
||||
m_writer->String("type");
|
||||
m_writer->String("Point");
|
||||
m_writer->String("coordinates");
|
||||
m_writer->StartArray();
|
||||
m_writer->Double(xy.x);
|
||||
m_writer->Double(xy.y);
|
||||
m_writer->EndArray();
|
||||
m_writer->EndObject();
|
||||
}
|
||||
|
||||
/* LineString */
|
||||
|
||||
// { "type": "LineString", "coordinates": [ [100.0, 0.0], [101.0, 1.0] ] }
|
||||
void linestring_start() {
|
||||
m_writer->String("geometry");
|
||||
m_writer->StartObject();
|
||||
m_writer->String("type");
|
||||
m_writer->String("LineString");
|
||||
m_writer->String("coordinates");
|
||||
m_writer->StartArray();
|
||||
}
|
||||
|
||||
void linestring_add_location(const osmium::geom::Coordinates& xy) {
|
||||
m_writer->StartArray();
|
||||
m_writer->Double(xy.x);
|
||||
m_writer->Double(xy.y);
|
||||
m_writer->EndArray();
|
||||
}
|
||||
|
||||
linestring_type linestring_finish(size_t /* num_points */) {
|
||||
m_writer->EndArray();
|
||||
m_writer->EndObject();
|
||||
}
|
||||
|
||||
/* Polygon */
|
||||
|
||||
// { "type": "Polygon", "coordinates": [[[100.0, 0.0], [101.0, 1.0]]] }
|
||||
void polygon_start() {
|
||||
m_writer->String("geometry");
|
||||
m_writer->StartObject();
|
||||
m_writer->String("type");
|
||||
m_writer->String("Polygon");
|
||||
m_writer->String("coordinates");
|
||||
m_writer->StartArray();
|
||||
m_writer->StartArray();
|
||||
}
|
||||
|
||||
void polygon_add_location(const osmium::geom::Coordinates& xy) {
|
||||
m_writer->StartArray();
|
||||
m_writer->Double(xy.x);
|
||||
m_writer->Double(xy.y);
|
||||
m_writer->EndArray();
|
||||
}
|
||||
|
||||
polygon_type polygon_finish(size_t /* num_points */) {
|
||||
m_writer->EndArray();
|
||||
m_writer->EndArray();
|
||||
m_writer->EndObject();
|
||||
}
|
||||
|
||||
/* MultiPolygon */
|
||||
|
||||
void multipolygon_start() {
|
||||
m_writer->String("geometry");
|
||||
m_writer->StartObject();
|
||||
m_writer->String("type");
|
||||
m_writer->String("MultiPolygon");
|
||||
m_writer->String("coordinates");
|
||||
m_writer->StartArray();
|
||||
}
|
||||
|
||||
void multipolygon_polygon_start() {
|
||||
m_writer->StartArray();
|
||||
}
|
||||
|
||||
void multipolygon_polygon_finish() {
|
||||
m_writer->EndArray();
|
||||
}
|
||||
|
||||
void multipolygon_outer_ring_start() {
|
||||
m_writer->StartArray();
|
||||
}
|
||||
|
||||
void multipolygon_outer_ring_finish() {
|
||||
m_writer->EndArray();
|
||||
}
|
||||
|
||||
void multipolygon_inner_ring_start() {
|
||||
m_writer->StartArray();
|
||||
}
|
||||
|
||||
void multipolygon_inner_ring_finish() {
|
||||
m_writer->EndArray();
|
||||
}
|
||||
|
||||
void multipolygon_add_location(const osmium::geom::Coordinates& xy) {
|
||||
m_writer->StartArray();
|
||||
m_writer->Double(xy.x);
|
||||
m_writer->Double(xy.y);
|
||||
m_writer->EndArray();
|
||||
}
|
||||
|
||||
multipolygon_type multipolygon_finish() {
|
||||
m_writer->EndArray();
|
||||
m_writer->EndObject();
|
||||
}
|
||||
|
||||
}; // class RapidGeoJSONFactoryImpl
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template <class TWriter, class TProjection = IdentityProjection>
|
||||
using RapidGeoJSONFactory = GeometryFactory<detail::RapidGeoJSONFactoryImpl<TWriter>, TProjection>;
|
||||
|
||||
} // namespace geom
|
||||
|
||||
} // namespace osmium
|
||||
|
||||
#endif // OSMIUM_GEOM_RAPID_GEOJSON_HPP
|
101
third_party/libosmium/include/osmium/geom/tile.hpp
vendored
Normal file
101
third_party/libosmium/include/osmium/geom/tile.hpp
vendored
Normal file
@ -0,0 +1,101 @@
|
||||
#ifndef OSMIUM_GEOM_TILE_HPP
|
||||
#define OSMIUM_GEOM_TILE_HPP
|
||||
|
||||
/*
|
||||
|
||||
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||
|
||||
Copyright 2013-2015 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 <cstdint>
|
||||
|
||||
#include <osmium/geom/mercator_projection.hpp>
|
||||
|
||||
namespace osmium {
|
||||
|
||||
namespace geom {
|
||||
|
||||
namespace detail {
|
||||
|
||||
template <typename T>
|
||||
inline T restrict_to_range(T value, T min, T max) {
|
||||
if (value < min) return min;
|
||||
if (value > max) return max;
|
||||
return value;
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
/**
|
||||
* A tile in the usual Mercator projection.
|
||||
*/
|
||||
struct Tile {
|
||||
|
||||
uint32_t x;
|
||||
uint32_t y;
|
||||
uint32_t z;
|
||||
|
||||
explicit Tile(uint32_t zoom, uint32_t tx, uint32_t ty) noexcept : x(tx), y(ty), z(zoom) {
|
||||
}
|
||||
|
||||
explicit Tile(uint32_t zoom, const osmium::Location& location) :
|
||||
z(zoom) {
|
||||
osmium::geom::Coordinates c = lonlat_to_mercator(location);
|
||||
const int32_t n = 1LL << zoom;
|
||||
const double scale = detail::max_coordinate_epsg3857 * 2 / n;
|
||||
x = detail::restrict_to_range<int32_t>((c.x + detail::max_coordinate_epsg3857) / scale, 0, n-1);
|
||||
y = detail::restrict_to_range<int32_t>((detail::max_coordinate_epsg3857 - c.y) / scale, 0, n-1);
|
||||
}
|
||||
|
||||
}; // struct Tile
|
||||
|
||||
inline bool operator==(const Tile& a, const Tile& b) {
|
||||
return a.z == b.z && a.x == b.x && a.y == b.y;
|
||||
}
|
||||
|
||||
inline bool operator!=(const Tile& a, const Tile& b) {
|
||||
return ! (a == b);
|
||||
}
|
||||
|
||||
/**
|
||||
* This defines an arbitrary order on tiles for use in std::map etc.
|
||||
*/
|
||||
inline bool operator<(const Tile& a, const Tile& b) {
|
||||
if (a.z < b.z) return true;
|
||||
if (a.z > b.z) return false;
|
||||
if (a.x < b.x) return true;
|
||||
if (a.x > b.x) return false;
|
||||
return a.y < b.y;
|
||||
}
|
||||
|
||||
} // namespace geom
|
||||
|
||||
} // namespace osmium
|
||||
|
||||
#endif // OSMIUM_GEOM_TILE_HPP
|
@ -37,18 +37,10 @@ DEALINGS IN THE SOFTWARE.
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
|
||||
// Windows is only available for little endian architectures
|
||||
// http://stackoverflow.com/questions/6449468/can-i-safely-assume-that-windows-installations-will-always-be-little-endian
|
||||
#if !defined(_WIN32) && !defined(__APPLE__)
|
||||
# include <endian.h>
|
||||
#else
|
||||
# define __LITTLE_ENDIAN 1234
|
||||
# define __BYTE_ORDER __LITTLE_ENDIAN
|
||||
#endif
|
||||
|
||||
#include <osmium/geom/coordinates.hpp>
|
||||
#include <osmium/geom/factory.hpp>
|
||||
#include <osmium/util/cast.hpp>
|
||||
#include <osmium/util/endian.hpp>
|
||||
|
||||
namespace osmium {
|
||||
|
||||
|
83
third_party/libosmium/include/osmium/index/bool_vector.hpp
vendored
Normal file
83
third_party/libosmium/include/osmium/index/bool_vector.hpp
vendored
Normal file
@ -0,0 +1,83 @@
|
||||
#ifndef OSMIUM_INDEX_BOOL_VECTOR_HPP
|
||||
#define OSMIUM_INDEX_BOOL_VECTOR_HPP
|
||||
|
||||
/*
|
||||
|
||||
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||
|
||||
Copyright 2013-2015 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 <type_traits>
|
||||
#include <vector>
|
||||
|
||||
namespace osmium {
|
||||
|
||||
namespace index {
|
||||
|
||||
/**
|
||||
* Index storing one bit for each Id. The index automatically scales
|
||||
* with the Ids stored. Default value is 'false'. Storage uses
|
||||
* std::vector<bool> and needs a minimum of memory if the Ids are
|
||||
* dense.
|
||||
*/
|
||||
template <typename T>
|
||||
class BoolVector {
|
||||
|
||||
static_assert(std::is_unsigned<T>::value, "Needs unsigned type");
|
||||
|
||||
std::vector<bool> m_bits;
|
||||
|
||||
public:
|
||||
|
||||
BoolVector() = default;
|
||||
BoolVector(const BoolVector&) = default;
|
||||
BoolVector(BoolVector&&) = default;
|
||||
BoolVector& operator=(const BoolVector&) = default;
|
||||
BoolVector& operator=(BoolVector&&) = default;
|
||||
~BoolVector() = default;
|
||||
|
||||
void set(T id, bool value = true) {
|
||||
if (m_bits.size() <= id) {
|
||||
m_bits.resize(id + 1024 * 1024);
|
||||
}
|
||||
|
||||
m_bits[id] = value;
|
||||
}
|
||||
|
||||
bool get(T id) const {
|
||||
return id < m_bits.size() && m_bits[id];
|
||||
}
|
||||
|
||||
}; // class BoolVector
|
||||
|
||||
} // namespace index
|
||||
|
||||
} // namespace osmium
|
||||
|
||||
#endif // OSMIUM_INDEX_BOOL_VECTOR_HPP
|
@ -39,8 +39,6 @@ DEALINGS IN THE SOFTWARE.
|
||||
#include <fcntl.h>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <vector>
|
||||
|
||||
namespace osmium {
|
||||
|
@ -35,9 +35,6 @@ DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#ifdef __linux__
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
#include <osmium/index/detail/typed_mmap.hpp>
|
||||
#include <osmium/index/detail/mmap_vector_base.hpp>
|
||||
|
||||
namespace osmium {
|
||||
@ -45,26 +42,16 @@ namespace osmium {
|
||||
namespace detail {
|
||||
|
||||
/**
|
||||
* This class looks and behaves like STL vector, but uses mmap internally.
|
||||
* This class looks and behaves like STL vector, but uses mmap
|
||||
* internally.
|
||||
*/
|
||||
template <typename T>
|
||||
class mmap_vector_anon : public mmap_vector_base<T, mmap_vector_anon> {
|
||||
class mmap_vector_anon : public mmap_vector_base<T> {
|
||||
|
||||
public:
|
||||
|
||||
mmap_vector_anon() :
|
||||
mmap_vector_base<T, osmium::detail::mmap_vector_anon>(
|
||||
-1,
|
||||
osmium::detail::mmap_vector_size_increment,
|
||||
0,
|
||||
osmium::detail::typed_mmap<T>::map(osmium::detail::mmap_vector_size_increment)) {
|
||||
}
|
||||
|
||||
void reserve(size_t new_capacity) {
|
||||
if (new_capacity > this->capacity()) {
|
||||
this->data(osmium::detail::typed_mmap<T>::remap(this->data(), this->capacity(), new_capacity));
|
||||
this->m_capacity = new_capacity;
|
||||
}
|
||||
mmap_vector_base<T>() {
|
||||
}
|
||||
|
||||
}; // class mmap_vector_anon
|
||||
|
@ -34,11 +34,10 @@ DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <cstddef>
|
||||
#include <new>
|
||||
#include <new> // IWYU pragma: keep
|
||||
#include <stdexcept>
|
||||
|
||||
#include <osmium/index/detail/typed_mmap.hpp>
|
||||
#include <osmium/util/compatibility.hpp>
|
||||
#include <osmium/util/memory_mapping.hpp>
|
||||
|
||||
namespace osmium {
|
||||
|
||||
@ -48,40 +47,29 @@ namespace osmium {
|
||||
|
||||
/**
|
||||
* This is a base class for implementing classes that look like
|
||||
* STL vector but use mmap internally. This class can not be used
|
||||
* on it's own. Use the derived classes mmap_vector_anon or
|
||||
* mmap_vector_file.
|
||||
* STL vector but use mmap internally. Do not use this class itself,
|
||||
* use the derived classes mmap_vector_anon or mmap_vector_file.
|
||||
*/
|
||||
template <typename T, template <typename> class TDerived>
|
||||
template <typename T>
|
||||
class mmap_vector_base {
|
||||
|
||||
protected:
|
||||
|
||||
int m_fd;
|
||||
size_t m_capacity;
|
||||
size_t m_size;
|
||||
T* m_data;
|
||||
|
||||
explicit mmap_vector_base(int fd, size_t capacity, size_t size, T* data) noexcept :
|
||||
m_fd(fd),
|
||||
m_capacity(capacity),
|
||||
m_size(size),
|
||||
m_data(data) {
|
||||
}
|
||||
|
||||
explicit mmap_vector_base(int fd, size_t capacity, size_t size) :
|
||||
m_fd(fd),
|
||||
m_capacity(capacity),
|
||||
m_size(size),
|
||||
m_data(osmium::detail::typed_mmap<T>::grow_and_map(capacity, m_fd)) {
|
||||
}
|
||||
|
||||
void data(T* data) {
|
||||
m_data = data;
|
||||
}
|
||||
osmium::util::TypedMemoryMapping<T> m_mapping;
|
||||
|
||||
public:
|
||||
|
||||
explicit mmap_vector_base(int fd, size_t capacity, size_t size = 0) :
|
||||
m_size(size),
|
||||
m_mapping(capacity, osmium::util::MemoryMapping::mapping_mode::write_shared, fd) {
|
||||
}
|
||||
|
||||
explicit mmap_vector_base(size_t capacity = mmap_vector_size_increment) :
|
||||
m_size(0),
|
||||
m_mapping(capacity) {
|
||||
}
|
||||
|
||||
typedef T value_type;
|
||||
typedef T& reference;
|
||||
typedef const T& const_reference;
|
||||
@ -90,12 +78,14 @@ namespace osmium {
|
||||
typedef T* iterator;
|
||||
typedef const T* const_iterator;
|
||||
|
||||
~mmap_vector_base() {
|
||||
osmium::detail::typed_mmap<T>::unmap(m_data, m_capacity);
|
||||
~mmap_vector_base() = default;
|
||||
|
||||
void close() {
|
||||
m_mapping.unmap();
|
||||
}
|
||||
|
||||
size_t capacity() const noexcept {
|
||||
return m_capacity;
|
||||
return m_mapping.size();
|
||||
}
|
||||
|
||||
size_t size() const noexcept {
|
||||
@ -106,23 +96,23 @@ namespace osmium {
|
||||
return m_size == 0;
|
||||
}
|
||||
|
||||
const T* data() const noexcept {
|
||||
return m_data;
|
||||
const T* data() const {
|
||||
return m_mapping.begin();
|
||||
}
|
||||
|
||||
T* data() noexcept {
|
||||
return m_data;
|
||||
T* data() {
|
||||
return m_mapping.begin();
|
||||
}
|
||||
|
||||
T& operator[](size_t n) {
|
||||
return m_data[n];
|
||||
return data()[n];
|
||||
}
|
||||
|
||||
T at(size_t n) const {
|
||||
if (n >= m_size) {
|
||||
throw std::out_of_range("out of range");
|
||||
}
|
||||
return m_data[n];
|
||||
return data()[n];
|
||||
}
|
||||
|
||||
void clear() noexcept {
|
||||
@ -134,16 +124,22 @@ namespace osmium {
|
||||
}
|
||||
|
||||
void push_back(const T& value) {
|
||||
if (m_size >= m_capacity) {
|
||||
if (m_size >= capacity()) {
|
||||
resize(m_size+1);
|
||||
}
|
||||
m_data[m_size] = value;
|
||||
data()[m_size] = value;
|
||||
++m_size;
|
||||
}
|
||||
|
||||
void reserve(size_t new_capacity) {
|
||||
if (new_capacity > capacity()) {
|
||||
m_mapping.resize(new_capacity);
|
||||
}
|
||||
}
|
||||
|
||||
void resize(size_t new_size) {
|
||||
if (new_size > capacity()) {
|
||||
static_cast<TDerived<T>*>(this)->reserve(new_size + osmium::detail::mmap_vector_size_increment);
|
||||
reserve(new_size + osmium::detail::mmap_vector_size_increment);
|
||||
}
|
||||
if (new_size > size()) {
|
||||
new (data() + size()) T[new_size - size()];
|
||||
@ -152,27 +148,27 @@ namespace osmium {
|
||||
}
|
||||
|
||||
iterator begin() noexcept {
|
||||
return m_data;
|
||||
return data();
|
||||
}
|
||||
|
||||
iterator end() noexcept {
|
||||
return m_data + m_size;
|
||||
return data() + m_size;
|
||||
}
|
||||
|
||||
const_iterator begin() const noexcept {
|
||||
return m_data;
|
||||
return data();
|
||||
}
|
||||
|
||||
const_iterator end() const noexcept {
|
||||
return m_data + m_size;
|
||||
return data() + m_size;
|
||||
}
|
||||
|
||||
const_iterator cbegin() noexcept {
|
||||
return m_data;
|
||||
const_iterator cbegin() const noexcept {
|
||||
return data();
|
||||
}
|
||||
|
||||
const_iterator cend() noexcept {
|
||||
return m_data + m_size;
|
||||
const_iterator cend() const noexcept {
|
||||
return data() + m_size;
|
||||
}
|
||||
|
||||
}; // class mmap_vector_base
|
||||
|
@ -33,11 +33,9 @@ DEALINGS IN THE SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
#include <osmium/index/detail/typed_mmap.hpp>
|
||||
#include <osmium/index/detail/mmap_vector_base.hpp>
|
||||
#include <osmium/index/detail/tmpfile.hpp>
|
||||
#include <osmium/util/file.hpp>
|
||||
|
||||
namespace osmium {
|
||||
|
||||
@ -48,32 +46,19 @@ namespace osmium {
|
||||
* internally.
|
||||
*/
|
||||
template <typename T>
|
||||
class mmap_vector_file : public mmap_vector_base<T, mmap_vector_file> {
|
||||
class mmap_vector_file : public mmap_vector_base<T> {
|
||||
|
||||
public:
|
||||
|
||||
explicit mmap_vector_file() :
|
||||
mmap_vector_base<T, osmium::detail::mmap_vector_file>(
|
||||
explicit mmap_vector_file() : mmap_vector_base<T>(
|
||||
osmium::detail::create_tmp_file(),
|
||||
osmium::detail::mmap_vector_size_increment,
|
||||
0) {
|
||||
osmium::detail::mmap_vector_size_increment) {
|
||||
}
|
||||
|
||||
explicit mmap_vector_file(int fd) :
|
||||
mmap_vector_base<T, osmium::detail::mmap_vector_file>(
|
||||
explicit mmap_vector_file(int fd) : mmap_vector_base<T>(
|
||||
fd,
|
||||
osmium::detail::typed_mmap<T>::file_size(fd) == 0 ?
|
||||
osmium::detail::mmap_vector_size_increment :
|
||||
osmium::detail::typed_mmap<T>::file_size(fd),
|
||||
osmium::detail::typed_mmap<T>::file_size(fd)) {
|
||||
}
|
||||
|
||||
void reserve(size_t new_capacity) {
|
||||
if (new_capacity > this->capacity()) {
|
||||
typed_mmap<T>::unmap(this->data(), this->capacity());
|
||||
this->data(typed_mmap<T>::grow_and_map(new_capacity, this->m_fd));
|
||||
this->m_capacity = new_capacity;
|
||||
}
|
||||
osmium::util::file_size(fd) / sizeof(T),
|
||||
osmium::util::file_size(fd) / sizeof(T)) {
|
||||
}
|
||||
|
||||
}; // class mmap_vector_file
|
||||
|
@ -1,229 +0,0 @@
|
||||
#ifndef OSMIUM_INDEX_DETAIL_TYPED_MMAP_HPP
|
||||
#define OSMIUM_INDEX_DETAIL_TYPED_MMAP_HPP
|
||||
|
||||
/*
|
||||
|
||||
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||
|
||||
Copyright 2013-2015 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 <cerrno>
|
||||
#include <cstddef>
|
||||
#include <stdexcept>
|
||||
#include <system_error>
|
||||
|
||||
#include <sys/stat.h>
|
||||
|
||||
#ifndef _WIN32
|
||||
# include <sys/mman.h>
|
||||
#else
|
||||
# include <mmap_for_windows.hpp>
|
||||
#endif
|
||||
|
||||
#ifndef _MSC_VER
|
||||
# include <unistd.h>
|
||||
#else
|
||||
# define ftruncate _chsize
|
||||
#endif
|
||||
|
||||
// for bsd systems
|
||||
#ifndef MAP_ANONYMOUS
|
||||
# define MAP_ANONYMOUS MAP_ANON
|
||||
#endif
|
||||
|
||||
#include <osmium/util/cast.hpp>
|
||||
|
||||
namespace osmium {
|
||||
|
||||
/**
|
||||
* @brief Namespace for Osmium internal use
|
||||
*/
|
||||
namespace detail {
|
||||
|
||||
/**
|
||||
* This is a helper class for working with memory mapped files and
|
||||
* anonymous shared memory. It wraps the necessary system calls
|
||||
* adding:
|
||||
* - error checking: all functions throw exceptions where needed
|
||||
* - internal casts and size calculations allow use with user defined
|
||||
* type T instead of void*
|
||||
*
|
||||
* This class only contains static functions. It should never be
|
||||
* instantiated.
|
||||
*
|
||||
* @tparam T Type of objects we want to store.
|
||||
*/
|
||||
template <typename T>
|
||||
class typed_mmap {
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Create anonymous private memory mapping with enough space for size
|
||||
* objects of type T.
|
||||
*
|
||||
* Note that no constructor is called for any of the objects in this memory!
|
||||
*
|
||||
* @param size Number of objects of type T that should fit into this memory
|
||||
* @returns Pointer to mapped memory
|
||||
* @throws std::system_error If mmap(2) failed
|
||||
*/
|
||||
static T* map(size_t size) {
|
||||
void* addr = ::mmap(nullptr, sizeof(T) * size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wold-style-cast"
|
||||
if (addr == MAP_FAILED) {
|
||||
throw std::system_error(errno, std::system_category(), "mmap failed");
|
||||
}
|
||||
#pragma GCC diagnostic pop
|
||||
return reinterpret_cast<T*>(addr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create shared memory mapping of a file with enough space for size
|
||||
* objects of type T. The file must already have at least the
|
||||
* required size.
|
||||
*
|
||||
* Note that no constructor is called for any of the objects in this memory!
|
||||
*
|
||||
* @param size Number of objects of type T that should fit into this memory
|
||||
* @param fd File descriptor
|
||||
* @param write True if data should be writable
|
||||
* @returns Pointer to mapped memory
|
||||
* @throws std::system_error If mmap(2) failed
|
||||
*/
|
||||
static T* map(size_t size, int fd, bool write = false) {
|
||||
int prot = PROT_READ;
|
||||
if (write) {
|
||||
prot |= PROT_WRITE;
|
||||
}
|
||||
void* addr = ::mmap(nullptr, sizeof(T) * size, prot, MAP_SHARED, fd, 0);
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wold-style-cast"
|
||||
if (addr == MAP_FAILED) {
|
||||
throw std::system_error(errno, std::system_category(), "mmap failed");
|
||||
}
|
||||
#pragma GCC diagnostic pop
|
||||
return reinterpret_cast<T*>(addr);
|
||||
}
|
||||
|
||||
// mremap(2) is only available on linux systems
|
||||
#ifdef __linux__
|
||||
/**
|
||||
* Grow memory mapping created with map().
|
||||
*
|
||||
* Note that no constructor is called for any of the objects in this memory!
|
||||
*
|
||||
* @param data Pointer to current mapping (as returned by typed_mmap())
|
||||
* @param old_size Number of objects currently stored in this memory
|
||||
* @param new_size Number of objects we want to have space for
|
||||
* @throws std::system_error If mremap(2) call failed
|
||||
*/
|
||||
static T* remap(T* data, size_t old_size, size_t new_size) {
|
||||
void* addr = ::mremap(reinterpret_cast<void*>(data), sizeof(T) * old_size, sizeof(T) * new_size, MREMAP_MAYMOVE);
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wold-style-cast"
|
||||
if (addr == MAP_FAILED) {
|
||||
throw std::system_error(errno, std::system_category(), "mremap failed");
|
||||
}
|
||||
#pragma GCC diagnostic pop
|
||||
return reinterpret_cast<T*>(addr);
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Release memory from map() call.
|
||||
*
|
||||
* Note that no destructor is called for the objects in this memory!
|
||||
*
|
||||
* @param data Pointer to the data
|
||||
* @param size Number of objects of type T stored
|
||||
* @throws std::system_error If munmap(2) call failed
|
||||
*/
|
||||
static void unmap(T* data, size_t size) {
|
||||
if (::munmap(reinterpret_cast<void*>(data), sizeof(T) * size) != 0) {
|
||||
throw std::system_error(errno, std::system_category(), "munmap failed");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get number of objects of type T that would fit into a file.
|
||||
*
|
||||
* @param fd File descriptor
|
||||
* @returns Number of objects of type T in this file
|
||||
* @throws std::system_error If fstat(2) call failed
|
||||
* @throws std::length_error If size of the file isn't a multiple of sizeof(T)
|
||||
*/
|
||||
static size_t file_size(int fd) {
|
||||
struct stat s;
|
||||
if (fstat(fd, &s) < 0) {
|
||||
throw std::system_error(errno, std::system_category(), "fstat failed");
|
||||
}
|
||||
if (static_cast<size_t>(s.st_size) % sizeof(T) != 0) {
|
||||
throw std::length_error("file size has to be multiple of object size");
|
||||
}
|
||||
return static_cast<size_t>(s.st_size) / sizeof(T);
|
||||
}
|
||||
|
||||
/**
|
||||
* Grow file so there is enough space for at least new_size objects
|
||||
* of type T. If the file is large enough already, nothing is done.
|
||||
* The file is never shrunk.
|
||||
*
|
||||
* @param new_size Number of objects of type T that should fit into this file
|
||||
* @param fd File descriptor
|
||||
* @throws std::system_error If ftruncate(2) call failed
|
||||
*/
|
||||
static void grow_file(size_t new_size, int fd) {
|
||||
if (file_size(fd) < new_size) {
|
||||
if (::ftruncate(fd, static_cast_with_assert<off_t>(sizeof(T) * new_size)) < 0) {
|
||||
throw std::system_error(errno, std::system_category(), "ftruncate failed");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Grow file to given size (if it is smaller) and mmap it.
|
||||
*
|
||||
* @param size Number of objects of type T that should fit into this file
|
||||
* @param fd File descriptor
|
||||
* @throws Errors thrown by grow_file() or map()
|
||||
*/
|
||||
static T* grow_and_map(size_t size, int fd) {
|
||||
grow_file(size, fd);
|
||||
return map(size, fd, true);
|
||||
}
|
||||
|
||||
}; // class typed_mmap
|
||||
|
||||
} // namespace detail
|
||||
|
||||
} // namespace osmium
|
||||
|
||||
#endif // OSMIUM_INDEX_DETAIL_TYPED_MMAP_HPP
|
@ -68,7 +68,7 @@ namespace osmium {
|
||||
m_vector(fd) {
|
||||
}
|
||||
|
||||
~VectorBasedDenseMap() {}
|
||||
~VectorBasedDenseMap() = default;
|
||||
|
||||
void reserve(const size_t size) override final {
|
||||
m_vector.reserve(size);
|
||||
@ -97,6 +97,10 @@ namespace osmium {
|
||||
return m_vector.size();
|
||||
}
|
||||
|
||||
size_t byte_size() const {
|
||||
return m_vector.size() * sizeof(element_type);
|
||||
}
|
||||
|
||||
size_t used_memory() const override final {
|
||||
return sizeof(TValue) * size();
|
||||
}
|
||||
@ -106,6 +110,10 @@ namespace osmium {
|
||||
m_vector.shrink_to_fit();
|
||||
}
|
||||
|
||||
void dump_as_array(const int fd) override final {
|
||||
osmium::io::detail::reliable_write(fd, reinterpret_cast<const char*>(m_vector.data()), byte_size());
|
||||
}
|
||||
|
||||
iterator begin() {
|
||||
return m_vector.begin();
|
||||
}
|
||||
|
@ -67,6 +67,16 @@ namespace osmium {
|
||||
|
||||
public:
|
||||
|
||||
VectorBasedSparseMultimap() :
|
||||
m_vector() {
|
||||
}
|
||||
|
||||
explicit VectorBasedSparseMultimap(int fd) :
|
||||
m_vector(fd) {
|
||||
}
|
||||
|
||||
~VectorBasedSparseMultimap() = default;
|
||||
|
||||
void set(const TId id, const TValue value) override final {
|
||||
m_vector.push_back(element_type(id, value));
|
||||
}
|
||||
@ -141,6 +151,30 @@ namespace osmium {
|
||||
osmium::io::detail::reliable_write(fd, reinterpret_cast<const char*>(m_vector.data()), byte_size());
|
||||
}
|
||||
|
||||
iterator begin() {
|
||||
return m_vector.begin();
|
||||
}
|
||||
|
||||
iterator end() {
|
||||
return m_vector.end();
|
||||
}
|
||||
|
||||
const_iterator cbegin() const {
|
||||
return m_vector.cbegin();
|
||||
}
|
||||
|
||||
const_iterator cend() const {
|
||||
return m_vector.cend();
|
||||
}
|
||||
|
||||
const_iterator begin() const {
|
||||
return m_vector.cbegin();
|
||||
}
|
||||
|
||||
const_iterator end() const {
|
||||
return m_vector.cend();
|
||||
}
|
||||
|
||||
}; // class VectorBasedSparseMultimap
|
||||
|
||||
} // namespace multimap
|
||||
|
@ -67,7 +67,7 @@ namespace osmium {
|
||||
template <typename TKey>
|
||||
OSMIUM_NORETURN void not_found_error(TKey key) {
|
||||
std::stringstream s;
|
||||
s << "id " << key << " no found";
|
||||
s << "id " << key << " not found";
|
||||
throw not_found(s.str());
|
||||
}
|
||||
|
||||
|
@ -148,7 +148,11 @@ namespace osmium {
|
||||
}
|
||||
|
||||
virtual void dump_as_list(const int /*fd*/) {
|
||||
std::runtime_error("can't dump as list");
|
||||
throw std::runtime_error("can't dump as list");
|
||||
}
|
||||
|
||||
virtual void dump_as_array(const int /*fd*/) {
|
||||
throw std::runtime_error("can't dump as array");
|
||||
}
|
||||
|
||||
}; // class Map
|
||||
@ -195,6 +199,10 @@ namespace osmium {
|
||||
return m_callbacks.emplace(map_type_name, func).second;
|
||||
}
|
||||
|
||||
bool has_map_type(const std::string& map_type_name) const {
|
||||
return m_callbacks.count(map_type_name);
|
||||
}
|
||||
|
||||
std::vector<std::string> map_types() const {
|
||||
std::vector<std::string> result;
|
||||
|
||||
@ -242,9 +250,13 @@ namespace osmium {
|
||||
});
|
||||
}
|
||||
|
||||
#define OSMIUM_CONCATENATE_DETAIL_(x, y) x##y
|
||||
#define OSMIUM_CONCATENATE_(x, y) OSMIUM_CONCATENATE_DETAIL_(x, y)
|
||||
#define OSMIUM_MAKE_UNIQUE_(x) OSMIUM_CONCATENATE_(x, __COUNTER__)
|
||||
|
||||
#define REGISTER_MAP(id, value, klass, name) \
|
||||
namespace { \
|
||||
const bool registered_index_map_##name = osmium::index::register_map<id, value, klass>(#name); \
|
||||
const bool OSMIUM_MAKE_UNIQUE_(registered_index_map_##name) = osmium::index::register_map<id, value, klass>(#name); \
|
||||
}
|
||||
|
||||
} // namespace index
|
||||
|
@ -35,7 +35,7 @@ DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#ifdef __linux__
|
||||
|
||||
#include <osmium/index/detail/mmap_vector_anon.hpp>
|
||||
#include <osmium/index/detail/mmap_vector_anon.hpp> // IWYU pragma: keep
|
||||
#include <osmium/index/detail/vector_map.hpp>
|
||||
|
||||
#define OSMIUM_HAS_INDEX_MAP_DENSE_MMAP_ARRAY
|
||||
|
@ -33,7 +33,7 @@ DEALINGS IN THE SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
#include <algorithm>
|
||||
#include <algorithm> // IWYU pragma: keep (for std::copy)
|
||||
#include <cstddef>
|
||||
#include <iterator>
|
||||
#include <map>
|
||||
|
@ -39,8 +39,8 @@ DEALINGS IN THE SOFTWARE.
|
||||
* Include this file if you want to read all kinds of OSM files.
|
||||
*
|
||||
* @attention If you include this file, you'll need to link with
|
||||
* `libprotobuf-lite`, `libosmpbf`, `ws2_32` (Windows only),
|
||||
* `libexpat`, `libz`, `libbz2`, and enable multithreading.
|
||||
* `ws2_32` (Windows only), `libexpat`, `libz`, `libbz2`,
|
||||
* and enable multithreading.
|
||||
*/
|
||||
|
||||
#include <osmium/io/any_compression.hpp> // IWYU pragma: export
|
||||
|
@ -39,12 +39,13 @@ DEALINGS IN THE SOFTWARE.
|
||||
* Include this file if you want to write all kinds of OSM files.
|
||||
*
|
||||
* @attention If you include this file, you'll need to link with
|
||||
* `libprotobuf-lite`, `libosmpbf`, `ws2_32` (Windows only),
|
||||
* `libz`, `libbz2`, and enable multithreading.
|
||||
* `ws2_32` (Windows only), `libz`, `libbz2`, and enable
|
||||
* multithreading.
|
||||
*/
|
||||
|
||||
#include <osmium/io/any_compression.hpp> // IWYU pragma: export
|
||||
|
||||
#include <osmium/io/debug_output.hpp> // IWYU pragma: export
|
||||
#include <osmium/io/opl_output.hpp> // IWYU pragma: export
|
||||
#include <osmium/io/pbf_output.hpp> // IWYU pragma: export
|
||||
#include <osmium/io/xml_output.hpp> // IWYU pragma: export
|
||||
|
@ -274,11 +274,16 @@ namespace osmium {
|
||||
|
||||
namespace {
|
||||
|
||||
// we want the register_compression() function to run, setting the variable
|
||||
// is only a side-effect, it will never be used
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wunused-variable"
|
||||
const bool registered_bzip2_compression = osmium::io::CompressionFactory::instance().register_compression(osmium::io::file_compression::bzip2,
|
||||
[](int fd) { return new osmium::io::Bzip2Compressor(fd); },
|
||||
[](int fd) { return new osmium::io::Bzip2Decompressor(fd); },
|
||||
[](const char* buffer, size_t size) { return new osmium::io::Bzip2BufferDecompressor(buffer, size); }
|
||||
);
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
|
@ -266,11 +266,16 @@ namespace osmium {
|
||||
|
||||
namespace {
|
||||
|
||||
// we want the register_compression() function to run, setting the variable
|
||||
// is only a side-effect, it will never be used
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wunused-variable"
|
||||
const bool registered_no_compression = osmium::io::CompressionFactory::instance().register_compression(osmium::io::file_compression::none,
|
||||
[](int fd) { return new osmium::io::NoCompressor(fd); },
|
||||
[](int fd) { return new osmium::io::NoDecompressor(fd); },
|
||||
[](const char* buffer, size_t size) { return new osmium::io::NoDecompressor(buffer, size); }
|
||||
);
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
|
39
third_party/libosmium/include/osmium/io/debug_output.hpp
vendored
Normal file
39
third_party/libosmium/include/osmium/io/debug_output.hpp
vendored
Normal file
@ -0,0 +1,39 @@
|
||||
#ifndef OSMIUM_IO_DEBUG_OUTPUT_HPP
|
||||
#define OSMIUM_IO_DEBUG_OUTPUT_HPP
|
||||
|
||||
/*
|
||||
|
||||
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||
|
||||
Copyright 2013-2015 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/io/writer.hpp> // IWYU pragma: export
|
||||
#include <osmium/io/detail/debug_output_format.hpp> // IWYU pragma: export
|
||||
|
||||
#endif // OSMIUM_IO_DEBUG_OUTPUT_HPP
|
482
third_party/libosmium/include/osmium/io/detail/debug_output_format.hpp
vendored
Normal file
482
third_party/libosmium/include/osmium/io/detail/debug_output_format.hpp
vendored
Normal file
@ -0,0 +1,482 @@
|
||||
#ifndef OSMIUM_IO_DETAIL_DEBUG_OUTPUT_FORMAT_HPP
|
||||
#define OSMIUM_IO_DETAIL_DEBUG_OUTPUT_FORMAT_HPP
|
||||
|
||||
/*
|
||||
|
||||
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||
|
||||
Copyright 2013-2015 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 <chrono>
|
||||
#include <cinttypes>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <cstdio>
|
||||
#include <future>
|
||||
#include <iterator>
|
||||
#include <memory>
|
||||
#include <ratio>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
#include <utility>
|
||||
|
||||
#include <utf8.h>
|
||||
|
||||
#include <osmium/handler.hpp>
|
||||
#include <osmium/io/detail/output_format.hpp>
|
||||
#include <osmium/io/file_format.hpp>
|
||||
#include <osmium/memory/buffer.hpp>
|
||||
#include <osmium/memory/collection.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/object.hpp>
|
||||
#include <osmium/osm/relation.hpp>
|
||||
#include <osmium/osm/tag.hpp>
|
||||
#include <osmium/osm/timestamp.hpp>
|
||||
#include <osmium/osm/way.hpp>
|
||||
#include <osmium/thread/pool.hpp>
|
||||
#include <osmium/util/minmax.hpp>
|
||||
#include <osmium/visitor.hpp>
|
||||
|
||||
namespace osmium {
|
||||
|
||||
namespace io {
|
||||
|
||||
class File;
|
||||
|
||||
namespace detail {
|
||||
|
||||
constexpr const char* color_bold = "\x1b[1m";
|
||||
constexpr const char* color_black = "\x1b[30m";
|
||||
constexpr const char* color_gray = "\x1b[30;1m";
|
||||
constexpr const char* color_red = "\x1b[31m";
|
||||
constexpr const char* color_green = "\x1b[32m";
|
||||
constexpr const char* color_yellow = "\x1b[33m";
|
||||
constexpr const char* color_blue = "\x1b[34m";
|
||||
constexpr const char* color_magenta = "\x1b[35m";
|
||||
constexpr const char* color_cyan = "\x1b[36m";
|
||||
constexpr const char* color_white = "\x1b[37m";
|
||||
constexpr const char* color_reset = "\x1b[0m";
|
||||
|
||||
/**
|
||||
* Writes out one buffer with OSM data in Debug format.
|
||||
*/
|
||||
class DebugOutputBlock : public osmium::handler::Handler {
|
||||
|
||||
static constexpr size_t tmp_buffer_size = 50;
|
||||
|
||||
std::shared_ptr<osmium::memory::Buffer> m_input_buffer;
|
||||
|
||||
std::shared_ptr<std::string> m_out;
|
||||
|
||||
char m_tmp_buffer[tmp_buffer_size+1];
|
||||
|
||||
bool m_add_metadata;
|
||||
bool m_use_color;
|
||||
|
||||
template <typename... TArgs>
|
||||
void output_formatted(const char* format, TArgs&&... args) {
|
||||
#ifndef NDEBUG
|
||||
int len =
|
||||
#endif
|
||||
#ifndef _MSC_VER
|
||||
snprintf(m_tmp_buffer, tmp_buffer_size, format, std::forward<TArgs>(args)...);
|
||||
#else
|
||||
_snprintf(m_tmp_buffer, tmp_buffer_size, format, std::forward<TArgs>(args)...);
|
||||
#endif
|
||||
assert(len > 0 && static_cast<size_t>(len) < tmp_buffer_size);
|
||||
*m_out += m_tmp_buffer;
|
||||
}
|
||||
|
||||
void append_encoded_string(const char* data) {
|
||||
const char* end = data + std::strlen(data);
|
||||
|
||||
while (data != end) {
|
||||
const char* last = data;
|
||||
uint32_t c = utf8::next(data, end);
|
||||
|
||||
// This is a list of Unicode code points that we let
|
||||
// through instead of escaping them. It is incomplete
|
||||
// and can be extended later.
|
||||
// Generally we don't want to let through any
|
||||
// non-printing characters.
|
||||
if ((0x0020 <= c && c <= 0x0021) ||
|
||||
(0x0023 <= c && c <= 0x003b) ||
|
||||
(0x003d == c) ||
|
||||
(0x003f <= c && c <= 0x007e) ||
|
||||
(0x00a1 <= c && c <= 0x00ac) ||
|
||||
(0x00ae <= c && c <= 0x05ff)) {
|
||||
m_out->append(last, data);
|
||||
} else {
|
||||
write_color(color_red);
|
||||
output_formatted("<U+%04X>", c);
|
||||
write_color(color_blue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void write_color(const char* color) {
|
||||
if (m_use_color) {
|
||||
*m_out += color;
|
||||
}
|
||||
}
|
||||
|
||||
void write_string(const char* string) {
|
||||
*m_out += '"';
|
||||
write_color(color_blue);
|
||||
append_encoded_string(string);
|
||||
write_color(color_reset);
|
||||
*m_out += '"';
|
||||
}
|
||||
|
||||
void write_object_type(const char* object_type, bool visible = true) {
|
||||
if (visible) {
|
||||
write_color(color_bold);
|
||||
} else {
|
||||
write_color(color_white);
|
||||
}
|
||||
*m_out += object_type;
|
||||
write_color(color_reset);
|
||||
*m_out += ' ';
|
||||
}
|
||||
|
||||
void write_fieldname(const char* name) {
|
||||
*m_out += " ";
|
||||
write_color(color_cyan);
|
||||
*m_out += name;
|
||||
write_color(color_reset);
|
||||
*m_out += ": ";
|
||||
}
|
||||
|
||||
void write_error(const char* msg) {
|
||||
write_color(color_red);
|
||||
*m_out += msg;
|
||||
write_color(color_reset);
|
||||
}
|
||||
|
||||
void write_meta(const osmium::OSMObject& object) {
|
||||
output_formatted("%" PRId64 "\n", object.id());
|
||||
if (m_add_metadata) {
|
||||
write_fieldname("version");
|
||||
output_formatted(" %d", object.version());
|
||||
if (object.visible()) {
|
||||
*m_out += " visible\n";
|
||||
} else {
|
||||
write_error(" deleted\n");
|
||||
}
|
||||
write_fieldname("changeset");
|
||||
output_formatted("%d\n", object.changeset());
|
||||
write_fieldname("timestamp");
|
||||
*m_out += object.timestamp().to_iso();
|
||||
output_formatted(" (%d)\n", object.timestamp());
|
||||
write_fieldname("user");
|
||||
output_formatted(" %d ", object.uid());
|
||||
write_string(object.user());
|
||||
*m_out += '\n';
|
||||
}
|
||||
}
|
||||
|
||||
void write_tags(const osmium::TagList& tags, const char* padding="") {
|
||||
if (!tags.empty()) {
|
||||
write_fieldname("tags");
|
||||
*m_out += padding;
|
||||
output_formatted(" %d\n", tags.size());
|
||||
|
||||
osmium::max_op<int> max;
|
||||
for (const auto& tag : tags) {
|
||||
max.update(std::strlen(tag.key()));
|
||||
}
|
||||
for (const auto& tag : tags) {
|
||||
*m_out += " ";
|
||||
write_string(tag.key());
|
||||
int spacing = max() - std::strlen(tag.key());
|
||||
while (spacing--) {
|
||||
*m_out += " ";
|
||||
}
|
||||
*m_out += " = ";
|
||||
write_string(tag.value());
|
||||
*m_out += '\n';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void write_location(const osmium::Location& location) {
|
||||
write_fieldname("lon/lat");
|
||||
output_formatted(" %.7f,%.7f", location.lon_without_check(), location.lat_without_check());
|
||||
if (!location.valid()) {
|
||||
write_error(" INVALID LOCATION!");
|
||||
}
|
||||
*m_out += '\n';
|
||||
}
|
||||
|
||||
void write_box(const osmium::Box& box) {
|
||||
write_fieldname("box l/b/r/t");
|
||||
if (!box) {
|
||||
write_error("BOX NOT SET!\n");
|
||||
return;
|
||||
}
|
||||
const auto& bl = box.bottom_left();
|
||||
const auto& tr = box.top_right();
|
||||
output_formatted("%.7f,%.7f %.7f,%.7f", bl.lon_without_check(), bl.lat_without_check(), tr.lon_without_check(), tr.lat_without_check());
|
||||
if (!box.valid()) {
|
||||
write_error(" INVALID BOX!");
|
||||
}
|
||||
*m_out += '\n';
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
explicit DebugOutputBlock(osmium::memory::Buffer&& buffer, bool add_metadata, bool use_color) :
|
||||
m_input_buffer(std::make_shared<osmium::memory::Buffer>(std::move(buffer))),
|
||||
m_out(std::make_shared<std::string>()),
|
||||
m_tmp_buffer(),
|
||||
m_add_metadata(add_metadata),
|
||||
m_use_color(use_color) {
|
||||
}
|
||||
|
||||
DebugOutputBlock(const DebugOutputBlock&) = default;
|
||||
DebugOutputBlock& operator=(const DebugOutputBlock&) = default;
|
||||
|
||||
DebugOutputBlock(DebugOutputBlock&&) = default;
|
||||
DebugOutputBlock& operator=(DebugOutputBlock&&) = default;
|
||||
|
||||
~DebugOutputBlock() = default;
|
||||
|
||||
std::string operator()() {
|
||||
osmium::apply(m_input_buffer->cbegin(), m_input_buffer->cend(), *this);
|
||||
|
||||
std::string out;
|
||||
std::swap(out, *m_out);
|
||||
return out;
|
||||
}
|
||||
|
||||
void node(const osmium::Node& node) {
|
||||
write_object_type("node", node.visible());
|
||||
write_meta(node);
|
||||
|
||||
if (node.visible()) {
|
||||
write_location(node.location());
|
||||
}
|
||||
|
||||
write_tags(node.tags());
|
||||
|
||||
*m_out += '\n';
|
||||
}
|
||||
|
||||
void way(const osmium::Way& way) {
|
||||
write_object_type("way", way.visible());
|
||||
write_meta(way);
|
||||
write_tags(way.tags());
|
||||
|
||||
write_fieldname("nodes");
|
||||
|
||||
output_formatted(" %d", way.nodes().size());
|
||||
if (way.nodes().size() < 2) {
|
||||
write_error(" LESS THAN 2 NODES!\n");
|
||||
} else if (way.nodes().size() > 2000) {
|
||||
write_error(" MORE THAN 2000 NODES!\n");
|
||||
} else if (way.nodes().is_closed()) {
|
||||
*m_out += " (closed)\n";
|
||||
} else {
|
||||
*m_out += " (open)\n";
|
||||
}
|
||||
|
||||
int width = int(log10(way.nodes().size())) + 1;
|
||||
int n = 0;
|
||||
for (const auto& node_ref : way.nodes()) {
|
||||
output_formatted(" %0*d: %10" PRId64, width, n++, node_ref.ref());
|
||||
if (node_ref.location().valid()) {
|
||||
output_formatted(" (%.7f,%.7f)", node_ref.location().lon_without_check(), node_ref.location().lat_without_check());
|
||||
}
|
||||
*m_out += '\n';
|
||||
}
|
||||
|
||||
*m_out += '\n';
|
||||
}
|
||||
|
||||
void relation(const osmium::Relation& relation) {
|
||||
static const char* short_typename[] = { "node", "way ", "rel " };
|
||||
write_object_type("relation", relation.visible());
|
||||
write_meta(relation);
|
||||
write_tags(relation.tags());
|
||||
|
||||
write_fieldname("members");
|
||||
output_formatted(" %d\n", relation.members().size());
|
||||
|
||||
int width = int(log10(relation.members().size())) + 1;
|
||||
int n = 0;
|
||||
for (const auto& member : relation.members()) {
|
||||
output_formatted(" %0*d: ", width, n++);
|
||||
*m_out += short_typename[item_type_to_nwr_index(member.type())];
|
||||
output_formatted(" %10" PRId64 " ", member.ref());
|
||||
write_string(member.role());
|
||||
*m_out += '\n';
|
||||
}
|
||||
|
||||
*m_out += '\n';
|
||||
}
|
||||
|
||||
void changeset(const osmium::Changeset& changeset) {
|
||||
write_object_type("changeset");
|
||||
output_formatted("%d\n", changeset.id());
|
||||
write_fieldname("num changes");
|
||||
output_formatted("%d", changeset.num_changes());
|
||||
if (changeset.num_changes() == 0) {
|
||||
write_error(" NO CHANGES!");
|
||||
}
|
||||
*m_out += '\n';
|
||||
write_fieldname("created at");
|
||||
*m_out += ' ';
|
||||
*m_out += changeset.created_at().to_iso();
|
||||
output_formatted(" (%d)\n", changeset.created_at());
|
||||
write_fieldname("closed at");
|
||||
*m_out += " ";
|
||||
if (changeset.closed()) {
|
||||
*m_out += changeset.closed_at().to_iso();
|
||||
output_formatted(" (%d)\n", changeset.closed_at());
|
||||
} else {
|
||||
write_error("OPEN!\n");
|
||||
}
|
||||
write_fieldname("user");
|
||||
output_formatted(" %d ", changeset.uid());
|
||||
write_string(changeset.user());
|
||||
*m_out += '\n';
|
||||
|
||||
write_box(changeset.bounds());
|
||||
write_tags(changeset.tags(), " ");
|
||||
|
||||
*m_out += '\n';
|
||||
}
|
||||
|
||||
}; // DebugOutputBlock
|
||||
|
||||
class DebugOutputFormat : public osmium::io::detail::OutputFormat {
|
||||
|
||||
bool m_add_metadata;
|
||||
bool m_use_color;
|
||||
|
||||
public:
|
||||
|
||||
DebugOutputFormat(const osmium::io::File& file, data_queue_type& output_queue) :
|
||||
OutputFormat(file, output_queue),
|
||||
m_add_metadata(file.get("add_metadata") != "false"),
|
||||
m_use_color(file.get("color") == "true") {
|
||||
}
|
||||
|
||||
DebugOutputFormat(const DebugOutputFormat&) = delete;
|
||||
DebugOutputFormat& operator=(const DebugOutputFormat&) = delete;
|
||||
|
||||
void write_buffer(osmium::memory::Buffer&& buffer) override final {
|
||||
m_output_queue.push(osmium::thread::Pool::instance().submit(DebugOutputBlock{std::move(buffer), m_add_metadata, m_use_color}));
|
||||
}
|
||||
|
||||
void write_fieldname(std::string& out, const char* name) {
|
||||
out += " ";
|
||||
if (m_use_color) {
|
||||
out += color_cyan;
|
||||
}
|
||||
out += name;
|
||||
if (m_use_color) {
|
||||
out += color_reset;
|
||||
}
|
||||
out += ": ";
|
||||
}
|
||||
|
||||
void write_header(const osmium::io::Header& header) override final {
|
||||
std::string out;
|
||||
|
||||
if (m_use_color) {
|
||||
out += color_bold;
|
||||
}
|
||||
out += "header\n";
|
||||
if (m_use_color) {
|
||||
out += color_reset;
|
||||
}
|
||||
|
||||
write_fieldname(out, "multiple object versions");
|
||||
out += header.has_multiple_object_versions() ? "yes" : "no";
|
||||
out += '\n';
|
||||
write_fieldname(out, "bounding boxes");
|
||||
out += '\n';
|
||||
for (const auto& box : header.boxes()) {
|
||||
out += " ";
|
||||
box.bottom_left().as_string(std::back_inserter(out), ',');
|
||||
out += " ";
|
||||
box.top_right().as_string(std::back_inserter(out), ',');
|
||||
out += '\n';
|
||||
}
|
||||
write_fieldname(out, "options");
|
||||
out += '\n';
|
||||
for (const auto& opt : header) {
|
||||
out += " ";
|
||||
out += opt.first;
|
||||
out += " = ";
|
||||
out += opt.second;
|
||||
out += '\n';
|
||||
}
|
||||
out += "\n=============================================\n\n";
|
||||
|
||||
std::promise<std::string> promise;
|
||||
m_output_queue.push(promise.get_future());
|
||||
promise.set_value(std::move(out));
|
||||
}
|
||||
|
||||
void close() override final {
|
||||
std::string out;
|
||||
std::promise<std::string> promise;
|
||||
m_output_queue.push(promise.get_future());
|
||||
promise.set_value(out);
|
||||
}
|
||||
|
||||
}; // class DebugOutputFormat
|
||||
|
||||
namespace {
|
||||
|
||||
// we want the register_output_format() function to run, setting the variable
|
||||
// is only a side-effect, it will never be used
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wunused-variable"
|
||||
const bool registered_debug_output = osmium::io::detail::OutputFormatFactory::instance().register_output_format(osmium::io::file_format::debug,
|
||||
[](const osmium::io::File& file, data_queue_type& output_queue) {
|
||||
return new osmium::io::detail::DebugOutputFormat(file, output_queue);
|
||||
});
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
} // namespace detail
|
||||
|
||||
} // namespace io
|
||||
|
||||
} // namespace osmium
|
||||
|
||||
#endif // OSMIUM_IO_DETAIL_DEBUG_OUTPUT_FORMAT_HPP
|
@ -46,23 +46,7 @@ DEALINGS IN THE SOFTWARE.
|
||||
#include <thread>
|
||||
#include <utility>
|
||||
|
||||
#include <boost/version.hpp>
|
||||
|
||||
#ifdef __clang__
|
||||
# pragma clang diagnostic push
|
||||
# pragma clang diagnostic ignored "-Wmissing-noreturn"
|
||||
# pragma clang diagnostic ignored "-Wsign-conversion"
|
||||
#endif
|
||||
|
||||
#if BOOST_VERSION >= 104800
|
||||
# include <boost/regex/pending/unicode_iterator.hpp>
|
||||
#else
|
||||
# include <boost_unicode_iterator.hpp>
|
||||
#endif
|
||||
|
||||
#ifdef __clang__
|
||||
# pragma clang diagnostic pop
|
||||
#endif
|
||||
#include <utf8.h>
|
||||
|
||||
#include <osmium/handler.hpp>
|
||||
#include <osmium/io/detail/output_format.hpp>
|
||||
@ -103,6 +87,8 @@ namespace osmium {
|
||||
|
||||
char m_tmp_buffer[tmp_buffer_size+1];
|
||||
|
||||
bool m_add_metadata;
|
||||
|
||||
template <typename... TArgs>
|
||||
void output_formatted(const char* format, TArgs&&... args) {
|
||||
#ifndef NDEBUG
|
||||
@ -117,13 +103,12 @@ namespace osmium {
|
||||
*m_out += m_tmp_buffer;
|
||||
}
|
||||
|
||||
void append_encoded_string(const std::string& data) {
|
||||
boost::u8_to_u32_iterator<std::string::const_iterator> it(data.cbegin(), data.cbegin(), data.cend());
|
||||
boost::u8_to_u32_iterator<std::string::const_iterator> end(data.cend(), data.cend(), data.cend());
|
||||
boost::utf8_output_iterator<std::back_insert_iterator<std::string>> oit(std::back_inserter(*m_out));
|
||||
void append_encoded_string(const char* data) {
|
||||
const char* end = data + std::strlen(data);
|
||||
|
||||
for (; it != end; ++it) {
|
||||
uint32_t c = *it;
|
||||
while (data != end) {
|
||||
const char* last = data;
|
||||
uint32_t c = utf8::next(data, end);
|
||||
|
||||
// This is a list of Unicode code points that we let
|
||||
// through instead of escaping them. It is incomplete
|
||||
@ -138,21 +123,29 @@ namespace osmium {
|
||||
(0x0041 <= c && c <= 0x007e) ||
|
||||
(0x00a1 <= c && c <= 0x00ac) ||
|
||||
(0x00ae <= c && c <= 0x05ff)) {
|
||||
*oit = c;
|
||||
m_out->append(last, data);
|
||||
} else {
|
||||
*m_out += '%';
|
||||
if (c <= 0xff) {
|
||||
output_formatted("%02x", c);
|
||||
} else {
|
||||
output_formatted("%04x", c);
|
||||
}
|
||||
*m_out += '%';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void write_meta(const osmium::OSMObject& object) {
|
||||
output_formatted("%" PRId64 " v%d d", object.id(), object.version());
|
||||
output_formatted("%" PRId64, object.id());
|
||||
if (m_add_metadata) {
|
||||
output_formatted(" v%d d", object.version());
|
||||
*m_out += (object.visible() ? 'V' : 'D');
|
||||
output_formatted(" c%d t", object.changeset());
|
||||
*m_out += object.timestamp().to_iso();
|
||||
output_formatted(" i%d u", object.uid());
|
||||
append_encoded_string(object.user());
|
||||
}
|
||||
*m_out += " T";
|
||||
bool first = true;
|
||||
for (const auto& tag : object.tags()) {
|
||||
@ -180,10 +173,11 @@ namespace osmium {
|
||||
|
||||
public:
|
||||
|
||||
explicit OPLOutputBlock(osmium::memory::Buffer&& buffer) :
|
||||
explicit OPLOutputBlock(osmium::memory::Buffer&& buffer, bool add_metadata) :
|
||||
m_input_buffer(std::make_shared<osmium::memory::Buffer>(std::move(buffer))),
|
||||
m_out(std::make_shared<std::string>()),
|
||||
m_tmp_buffer() {
|
||||
m_tmp_buffer(),
|
||||
m_add_metadata(add_metadata) {
|
||||
}
|
||||
|
||||
OPLOutputBlock(const OPLOutputBlock&) = default;
|
||||
@ -240,7 +234,7 @@ namespace osmium {
|
||||
}
|
||||
*m_out += item_type_to_char(member.type());
|
||||
output_formatted("%" PRId64 "@", member.ref());
|
||||
*m_out += member.role();
|
||||
append_encoded_string(member.role());
|
||||
}
|
||||
*m_out += '\n';
|
||||
}
|
||||
@ -274,17 +268,20 @@ namespace osmium {
|
||||
|
||||
class OPLOutputFormat : public osmium::io::detail::OutputFormat {
|
||||
|
||||
OPLOutputFormat(const OPLOutputFormat&) = delete;
|
||||
OPLOutputFormat& operator=(const OPLOutputFormat&) = delete;
|
||||
bool m_add_metadata;
|
||||
|
||||
public:
|
||||
|
||||
OPLOutputFormat(const osmium::io::File& file, data_queue_type& output_queue) :
|
||||
OutputFormat(file, output_queue) {
|
||||
OutputFormat(file, output_queue),
|
||||
m_add_metadata(file.get("add_metadata") != "false") {
|
||||
}
|
||||
|
||||
OPLOutputFormat(const OPLOutputFormat&) = delete;
|
||||
OPLOutputFormat& operator=(const OPLOutputFormat&) = delete;
|
||||
|
||||
void write_buffer(osmium::memory::Buffer&& buffer) override final {
|
||||
m_output_queue.push(osmium::thread::Pool::instance().submit(OPLOutputBlock{std::move(buffer)}));
|
||||
m_output_queue.push(osmium::thread::Pool::instance().submit(OPLOutputBlock{std::move(buffer), m_add_metadata}));
|
||||
}
|
||||
|
||||
void close() override final {
|
||||
@ -298,6 +295,8 @@ namespace osmium {
|
||||
|
||||
namespace {
|
||||
|
||||
// we want the register_output_format() function to run, setting the variable
|
||||
// is only a side-effect, it will never be used
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wunused-variable"
|
||||
const bool registered_opl_output = osmium::io::detail::OutputFormatFactory::instance().register_output_format(osmium::io::file_format::opl,
|
||||
|
@ -33,9 +33,7 @@ DEALINGS IN THE SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
#include <osmpbf/osmpbf.h>
|
||||
#include <string>
|
||||
|
||||
// needed for htonl and ntohl
|
||||
#ifndef _WIN32
|
||||
@ -45,38 +43,10 @@ DEALINGS IN THE SOFTWARE.
|
||||
#endif
|
||||
|
||||
#include <osmium/io/error.hpp>
|
||||
#include <osmium/osm/item_type.hpp>
|
||||
#include <osmium/osm/location.hpp>
|
||||
|
||||
namespace osmium {
|
||||
|
||||
// avoid g++ false positive
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wreturn-type"
|
||||
inline item_type osmpbf_membertype_to_item_type(const OSMPBF::Relation::MemberType mt) {
|
||||
switch (mt) {
|
||||
case OSMPBF::Relation::NODE:
|
||||
return item_type::node;
|
||||
case OSMPBF::Relation::WAY:
|
||||
return item_type::way;
|
||||
case OSMPBF::Relation::RELATION:
|
||||
return item_type::relation;
|
||||
}
|
||||
}
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
inline OSMPBF::Relation::MemberType item_type_to_osmpbf_membertype(const item_type type) {
|
||||
switch (type) {
|
||||
case item_type::node:
|
||||
return OSMPBF::Relation::NODE;
|
||||
case item_type::way:
|
||||
return OSMPBF::Relation::WAY;
|
||||
case item_type::relation:
|
||||
return OSMPBF::Relation::RELATION;
|
||||
default:
|
||||
throw std::runtime_error("Unknown relation member type");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Exception thrown when there was a problem with parsing the PBF format of
|
||||
* a file.
|
||||
@ -93,6 +63,26 @@ namespace osmium {
|
||||
|
||||
}; // struct pbf_error
|
||||
|
||||
namespace io {
|
||||
|
||||
namespace detail {
|
||||
|
||||
// the maximum size of a blob header in bytes
|
||||
const int max_blob_header_size = 64 * 1024; // 64 kB
|
||||
|
||||
// the maximum size of an uncompressed blob in bytes
|
||||
const uint64_t max_uncompressed_blob_size = 32 * 1024 * 1024; // 32 MB
|
||||
|
||||
// resolution for longitude/latitude used for conversion
|
||||
// between representation as double and as int
|
||||
const int64_t lonlat_resolution = 1000 * 1000 * 1000;
|
||||
|
||||
const int64_t resolution_convert = lonlat_resolution / osmium::Location::coordinate_precision;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} // namespace osmium
|
||||
|
||||
#endif // OSMIUM_IO_DETAIL_PBF_HPP
|
||||
|
760
third_party/libosmium/include/osmium/io/detail/pbf_decoder.hpp
vendored
Normal file
760
third_party/libosmium/include/osmium/io/detail/pbf_decoder.hpp
vendored
Normal file
@ -0,0 +1,760 @@
|
||||
#ifndef OSMIUM_IO_DETAIL_PBF_DECODER_HPP
|
||||
#define OSMIUM_IO_DETAIL_PBF_DECODER_HPP
|
||||
|
||||
/*
|
||||
|
||||
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||
|
||||
Copyright 2013-2015 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 <cstddef>
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
#include <limits>
|
||||
|
||||
#include <protozero/pbf_message.hpp>
|
||||
|
||||
#include <osmium/builder/osm_object_builder.hpp>
|
||||
#include <osmium/io/detail/pbf.hpp> // IWYU pragma: export
|
||||
#include <osmium/io/detail/protobuf_tags.hpp>
|
||||
#include <osmium/io/detail/zlib.hpp>
|
||||
#include <osmium/io/header.hpp>
|
||||
#include <osmium/osm/location.hpp>
|
||||
#include <osmium/osm/node.hpp>
|
||||
#include <osmium/osm/types.hpp>
|
||||
#include <osmium/memory/buffer.hpp>
|
||||
#include <osmium/osm/entity_bits.hpp>
|
||||
#include <osmium/util/cast.hpp>
|
||||
#include <osmium/util/delta.hpp>
|
||||
|
||||
namespace osmium {
|
||||
|
||||
namespace io {
|
||||
|
||||
namespace detail {
|
||||
|
||||
using ptr_len_type = std::pair<const char*, size_t>;
|
||||
|
||||
class PBFPrimitiveBlockDecoder {
|
||||
|
||||
static constexpr size_t initial_buffer_size = 2 * 1024 * 1024;
|
||||
|
||||
ptr_len_type m_data;
|
||||
std::vector<ptr_len_type> m_stringtable;
|
||||
|
||||
int64_t m_lon_offset = 0;
|
||||
int64_t m_lat_offset = 0;
|
||||
int64_t m_date_factor = 1000;
|
||||
int32_t m_granularity = 100;
|
||||
|
||||
osmium::osm_entity_bits::type m_read_types;
|
||||
|
||||
osmium::memory::Buffer m_buffer { initial_buffer_size };
|
||||
|
||||
void decode_stringtable(const ptr_len_type& data) {
|
||||
if (!m_stringtable.empty()) {
|
||||
throw osmium::pbf_error("more than one stringtable in pbf file");
|
||||
}
|
||||
|
||||
protozero::pbf_message<OSMFormat::StringTable> pbf_string_table(data);
|
||||
while (pbf_string_table.next(OSMFormat::StringTable::repeated_bytes_s)) {
|
||||
m_stringtable.push_back(pbf_string_table.get_data());
|
||||
}
|
||||
}
|
||||
|
||||
void decode_primitive_block_metadata() {
|
||||
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:
|
||||
decode_stringtable(pbf_primitive_block.get_data());
|
||||
break;
|
||||
case OSMFormat::PrimitiveBlock::optional_int32_granularity:
|
||||
m_granularity = pbf_primitive_block.get_int32();
|
||||
break;
|
||||
case OSMFormat::PrimitiveBlock::optional_int32_date_granularity:
|
||||
m_date_factor = pbf_primitive_block.get_int32();
|
||||
break;
|
||||
case OSMFormat::PrimitiveBlock::optional_int64_lat_offset:
|
||||
m_lat_offset = pbf_primitive_block.get_int64();
|
||||
break;
|
||||
case OSMFormat::PrimitiveBlock::optional_int64_lon_offset:
|
||||
m_lon_offset = pbf_primitive_block.get_int64();
|
||||
break;
|
||||
default:
|
||||
pbf_primitive_block.skip();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void decode_primitive_block_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()) {
|
||||
switch (pbf_primitive_group.tag()) {
|
||||
case OSMFormat::PrimitiveGroup::repeated_Node_nodes:
|
||||
if (m_read_types & osmium::osm_entity_bits::node) {
|
||||
decode_node(pbf_primitive_group.get_data());
|
||||
} else {
|
||||
pbf_primitive_group.skip();
|
||||
}
|
||||
break;
|
||||
case OSMFormat::PrimitiveGroup::optional_DenseNodes_dense:
|
||||
if (m_read_types & osmium::osm_entity_bits::node) {
|
||||
decode_dense_nodes(pbf_primitive_group.get_data());
|
||||
} else {
|
||||
pbf_primitive_group.skip();
|
||||
}
|
||||
break;
|
||||
case OSMFormat::PrimitiveGroup::repeated_Way_ways:
|
||||
if (m_read_types & osmium::osm_entity_bits::way) {
|
||||
decode_way(pbf_primitive_group.get_data());
|
||||
} else {
|
||||
pbf_primitive_group.skip();
|
||||
}
|
||||
break;
|
||||
case OSMFormat::PrimitiveGroup::repeated_Relation_relations:
|
||||
if (m_read_types & osmium::osm_entity_bits::relation) {
|
||||
decode_relation(pbf_primitive_group.get_data());
|
||||
} else {
|
||||
pbf_primitive_group.skip();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
pbf_primitive_group.skip();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ptr_len_type decode_info(const ptr_len_type& data, osmium::OSMObject& object) {
|
||||
ptr_len_type user = std::make_pair("", 0);
|
||||
|
||||
protozero::pbf_message<OSMFormat::Info> pbf_info(data);
|
||||
while (pbf_info.next()) {
|
||||
switch (pbf_info.tag()) {
|
||||
case OSMFormat::Info::optional_int32_version:
|
||||
{
|
||||
auto version = pbf_info.get_int32();
|
||||
if (version < 0) {
|
||||
throw osmium::pbf_error("object version must not be negative");
|
||||
}
|
||||
object.set_version(static_cast_with_assert<object_version_type>(version));
|
||||
}
|
||||
break;
|
||||
case OSMFormat::Info::optional_int64_timestamp:
|
||||
object.set_timestamp(pbf_info.get_int64() * m_date_factor / 1000);
|
||||
break;
|
||||
case OSMFormat::Info::optional_int64_changeset:
|
||||
{
|
||||
auto changeset_id = pbf_info.get_int64();
|
||||
if (changeset_id < 0) {
|
||||
throw osmium::pbf_error("object changeset_id must not be negative");
|
||||
}
|
||||
object.set_changeset(static_cast_with_assert<changeset_id_type>(changeset_id));
|
||||
}
|
||||
break;
|
||||
case OSMFormat::Info::optional_int32_uid:
|
||||
object.set_uid_from_signed(pbf_info.get_int32());
|
||||
break;
|
||||
case OSMFormat::Info::optional_uint32_user_sid:
|
||||
user = m_stringtable.at(pbf_info.get_uint32());
|
||||
break;
|
||||
case OSMFormat::Info::optional_bool_visible:
|
||||
object.set_visible(pbf_info.get_bool());
|
||||
break;
|
||||
default:
|
||||
pbf_info.skip();
|
||||
}
|
||||
}
|
||||
|
||||
return user;
|
||||
}
|
||||
|
||||
using kv_type = std::pair<protozero::pbf_reader::const_uint32_iterator, protozero::pbf_reader::const_uint32_iterator>;
|
||||
|
||||
void build_tag_list(osmium::builder::Builder& builder, const kv_type& keys, const kv_type& vals) {
|
||||
if (keys.first != keys.second) {
|
||||
osmium::builder::TagListBuilder tl_builder(m_buffer, &builder);
|
||||
auto kit = keys.first;
|
||||
auto vit = vals.first;
|
||||
while (kit != keys.second) {
|
||||
if (vit == vals.second) {
|
||||
// this is against the spec, must have same number of elements
|
||||
throw osmium::pbf_error("PBF format error");
|
||||
}
|
||||
const auto& k = m_stringtable.at(*kit++);
|
||||
const auto& v = m_stringtable.at(*vit++);
|
||||
tl_builder.add_tag(k.first, k.second, v.first, v.second);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int32_t convert_pbf_coordinate(int64_t c) const {
|
||||
return (c * m_granularity + m_lon_offset) / resolution_convert;
|
||||
}
|
||||
|
||||
void decode_node(const ptr_len_type& data) {
|
||||
osmium::builder::NodeBuilder builder(m_buffer);
|
||||
osmium::Node& node = builder.object();
|
||||
|
||||
kv_type keys;
|
||||
kv_type vals;
|
||||
int64_t lon = std::numeric_limits<int64_t>::max();
|
||||
int64_t lat = std::numeric_limits<int64_t>::max();
|
||||
|
||||
ptr_len_type user = { "", 0 };
|
||||
|
||||
protozero::pbf_message<OSMFormat::Node> pbf_node(data);
|
||||
while (pbf_node.next()) {
|
||||
switch (pbf_node.tag()) {
|
||||
case OSMFormat::Node::required_sint64_id:
|
||||
node.set_id(pbf_node.get_sint64());
|
||||
break;
|
||||
case OSMFormat::Node::packed_uint32_keys:
|
||||
keys = pbf_node.get_packed_uint32();
|
||||
break;
|
||||
case OSMFormat::Node::packed_uint32_vals:
|
||||
vals = pbf_node.get_packed_uint32();
|
||||
break;
|
||||
case OSMFormat::Node::optional_Info_info:
|
||||
user = decode_info(pbf_node.get_data(), builder.object());
|
||||
break;
|
||||
case OSMFormat::Node::required_sint64_lat:
|
||||
lat = pbf_node.get_sint64();
|
||||
break;
|
||||
case OSMFormat::Node::required_sint64_lon:
|
||||
lon = pbf_node.get_sint64();
|
||||
break;
|
||||
default:
|
||||
pbf_node.skip();
|
||||
}
|
||||
}
|
||||
|
||||
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");
|
||||
}
|
||||
node.set_location(osmium::Location(
|
||||
convert_pbf_coordinate(lon),
|
||||
convert_pbf_coordinate(lat)
|
||||
));
|
||||
}
|
||||
|
||||
builder.add_user(user.first, user.second);
|
||||
|
||||
build_tag_list(builder, keys, vals);
|
||||
|
||||
m_buffer.commit();
|
||||
}
|
||||
|
||||
void decode_way(const ptr_len_type& data) {
|
||||
osmium::builder::WayBuilder builder(m_buffer);
|
||||
|
||||
kv_type keys;
|
||||
kv_type vals;
|
||||
std::pair<protozero::pbf_reader::const_sint64_iterator, protozero::pbf_reader::const_sint64_iterator> refs;
|
||||
|
||||
ptr_len_type user = { "", 0 };
|
||||
|
||||
protozero::pbf_message<OSMFormat::Way> pbf_way(data);
|
||||
while (pbf_way.next()) {
|
||||
switch (pbf_way.tag()) {
|
||||
case OSMFormat::Way::required_int64_id:
|
||||
builder.object().set_id(pbf_way.get_int64());
|
||||
break;
|
||||
case OSMFormat::Way::packed_uint32_keys:
|
||||
keys = pbf_way.get_packed_uint32();
|
||||
break;
|
||||
case OSMFormat::Way::packed_uint32_vals:
|
||||
vals = pbf_way.get_packed_uint32();
|
||||
break;
|
||||
case OSMFormat::Way::optional_Info_info:
|
||||
user = decode_info(pbf_way.get_data(), builder.object());
|
||||
break;
|
||||
case OSMFormat::Way::packed_sint64_refs:
|
||||
refs = pbf_way.get_packed_sint64();
|
||||
break;
|
||||
default:
|
||||
pbf_way.skip();
|
||||
}
|
||||
}
|
||||
|
||||
builder.add_user(user.first, user.second);
|
||||
|
||||
if (refs.first != refs.second) {
|
||||
osmium::builder::WayNodeListBuilder wnl_builder(m_buffer, &builder);
|
||||
osmium::util::DeltaDecode<int64_t> ref;
|
||||
while (refs.first != refs.second) {
|
||||
wnl_builder.add_node_ref(ref.update(*refs.first++));
|
||||
}
|
||||
}
|
||||
|
||||
build_tag_list(builder, keys, vals);
|
||||
|
||||
m_buffer.commit();
|
||||
}
|
||||
|
||||
void decode_relation(const ptr_len_type& data) {
|
||||
osmium::builder::RelationBuilder builder(m_buffer);
|
||||
|
||||
kv_type keys;
|
||||
kv_type vals;
|
||||
std::pair<protozero::pbf_reader::const_int32_iterator, protozero::pbf_reader::const_int32_iterator> roles;
|
||||
std::pair<protozero::pbf_reader::const_sint64_iterator, protozero::pbf_reader::const_sint64_iterator> refs;
|
||||
std::pair<protozero::pbf_reader::const_int32_iterator, protozero::pbf_reader::const_int32_iterator> types;
|
||||
|
||||
ptr_len_type user = { "", 0 };
|
||||
|
||||
protozero::pbf_message<OSMFormat::Relation> pbf_relation(data);
|
||||
while (pbf_relation.next()) {
|
||||
switch (pbf_relation.tag()) {
|
||||
case OSMFormat::Relation::required_int64_id:
|
||||
builder.object().set_id(pbf_relation.get_int64());
|
||||
break;
|
||||
case OSMFormat::Relation::packed_uint32_keys:
|
||||
keys = pbf_relation.get_packed_uint32();
|
||||
break;
|
||||
case OSMFormat::Relation::packed_uint32_vals:
|
||||
vals = pbf_relation.get_packed_uint32();
|
||||
break;
|
||||
case OSMFormat::Relation::optional_Info_info:
|
||||
user = decode_info(pbf_relation.get_data(), builder.object());
|
||||
break;
|
||||
case OSMFormat::Relation::packed_int32_roles_sid:
|
||||
roles = pbf_relation.get_packed_int32();
|
||||
break;
|
||||
case OSMFormat::Relation::packed_sint64_memids:
|
||||
refs = pbf_relation.get_packed_sint64();
|
||||
break;
|
||||
case OSMFormat::Relation::packed_MemberType_types:
|
||||
types = pbf_relation.get_packed_enum();
|
||||
break;
|
||||
default:
|
||||
pbf_relation.skip();
|
||||
}
|
||||
}
|
||||
|
||||
builder.add_user(user.first, user.second);
|
||||
|
||||
if (refs.first != refs.second) {
|
||||
osmium::builder::RelationMemberListBuilder rml_builder(m_buffer, &builder);
|
||||
osmium::util::DeltaDecode<int64_t> ref;
|
||||
while (roles.first != roles.second && refs.first != refs.second && types.first != types.second) {
|
||||
const auto& r = m_stringtable.at(*roles.first++);
|
||||
int type = *types.first++;
|
||||
if (type < 0 || type > 2) {
|
||||
throw osmium::pbf_error("unknown relation member type");
|
||||
}
|
||||
rml_builder.add_member(
|
||||
osmium::item_type(type + 1),
|
||||
ref.update(*refs.first++),
|
||||
r.first,
|
||||
r.second
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
build_tag_list(builder, keys, vals);
|
||||
|
||||
m_buffer.commit();
|
||||
}
|
||||
|
||||
void decode_dense_nodes(const ptr_len_type& data) {
|
||||
bool has_info = false;
|
||||
bool has_visibles = false;
|
||||
|
||||
std::pair<protozero::pbf_reader::const_sint64_iterator, protozero::pbf_reader::const_sint64_iterator> ids;
|
||||
std::pair<protozero::pbf_reader::const_sint64_iterator, protozero::pbf_reader::const_sint64_iterator> lats;
|
||||
std::pair<protozero::pbf_reader::const_sint64_iterator, protozero::pbf_reader::const_sint64_iterator> lons;
|
||||
|
||||
std::pair<protozero::pbf_reader::const_int32_iterator, protozero::pbf_reader::const_int32_iterator> tags;
|
||||
|
||||
std::pair<protozero::pbf_reader::const_int32_iterator, protozero::pbf_reader::const_int32_iterator> versions;
|
||||
std::pair<protozero::pbf_reader::const_sint64_iterator, protozero::pbf_reader::const_sint64_iterator> timestamps;
|
||||
std::pair<protozero::pbf_reader::const_sint64_iterator, protozero::pbf_reader::const_sint64_iterator> changesets;
|
||||
std::pair<protozero::pbf_reader::const_sint32_iterator, protozero::pbf_reader::const_sint32_iterator> uids;
|
||||
std::pair<protozero::pbf_reader::const_sint32_iterator, protozero::pbf_reader::const_sint32_iterator> user_sids;
|
||||
std::pair<protozero::pbf_reader::const_int32_iterator, protozero::pbf_reader::const_int32_iterator> visibles;
|
||||
|
||||
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:
|
||||
ids = pbf_dense_nodes.get_packed_sint64();
|
||||
break;
|
||||
case OSMFormat::DenseNodes::optional_DenseInfo_denseinfo:
|
||||
{
|
||||
has_info = true;
|
||||
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:
|
||||
versions = pbf_dense_info.get_packed_int32();
|
||||
break;
|
||||
case OSMFormat::DenseInfo::packed_sint64_timestamp:
|
||||
timestamps = pbf_dense_info.get_packed_sint64();
|
||||
break;
|
||||
case OSMFormat::DenseInfo::packed_sint64_changeset:
|
||||
changesets = pbf_dense_info.get_packed_sint64();
|
||||
break;
|
||||
case OSMFormat::DenseInfo::packed_sint32_uid:
|
||||
uids = pbf_dense_info.get_packed_sint32();
|
||||
break;
|
||||
case OSMFormat::DenseInfo::packed_sint32_user_sid:
|
||||
user_sids = pbf_dense_info.get_packed_sint32();
|
||||
break;
|
||||
case OSMFormat::DenseInfo::packed_bool_visible:
|
||||
has_visibles = true;
|
||||
visibles = pbf_dense_info.get_packed_bool();
|
||||
break;
|
||||
default:
|
||||
pbf_dense_info.skip();
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case OSMFormat::DenseNodes::packed_sint64_lat:
|
||||
lats = pbf_dense_nodes.get_packed_sint64();
|
||||
break;
|
||||
case OSMFormat::DenseNodes::packed_sint64_lon:
|
||||
lons = pbf_dense_nodes.get_packed_sint64();
|
||||
break;
|
||||
case OSMFormat::DenseNodes::packed_int32_keys_vals:
|
||||
tags = pbf_dense_nodes.get_packed_int32();
|
||||
break;
|
||||
default:
|
||||
pbf_dense_nodes.skip();
|
||||
}
|
||||
}
|
||||
|
||||
osmium::util::DeltaDecode<int64_t> dense_id;
|
||||
osmium::util::DeltaDecode<int64_t> dense_latitude;
|
||||
osmium::util::DeltaDecode<int64_t> dense_longitude;
|
||||
osmium::util::DeltaDecode<int64_t> dense_uid;
|
||||
osmium::util::DeltaDecode<int64_t> dense_user_sid;
|
||||
osmium::util::DeltaDecode<int64_t> dense_changeset;
|
||||
osmium::util::DeltaDecode<int64_t> dense_timestamp;
|
||||
|
||||
auto tag_it = tags.first;
|
||||
|
||||
while (ids.first != ids.second) {
|
||||
if (lons.first == lons.second ||
|
||||
lats.first == lats.second) {
|
||||
// this is against the spec, must have same number of elements
|
||||
throw osmium::pbf_error("PBF format error");
|
||||
}
|
||||
|
||||
bool visible = true;
|
||||
|
||||
osmium::builder::NodeBuilder builder(m_buffer);
|
||||
osmium::Node& node = builder.object();
|
||||
|
||||
node.set_id(dense_id.update(*ids.first++));
|
||||
|
||||
if (has_info) {
|
||||
if (versions.first == versions.second ||
|
||||
changesets.first == changesets.second ||
|
||||
timestamps.first == timestamps.second ||
|
||||
uids.first == uids.second ||
|
||||
user_sids.first == user_sids.second) {
|
||||
// this is against the spec, must have same number of elements
|
||||
throw osmium::pbf_error("PBF format error");
|
||||
}
|
||||
|
||||
auto version = *versions.first++;
|
||||
if (version < 0) {
|
||||
throw osmium::pbf_error("object version must not be negative");
|
||||
}
|
||||
node.set_version(static_cast<osmium::object_version_type>(version));
|
||||
|
||||
auto changeset_id = dense_changeset.update(*changesets.first++);
|
||||
if (changeset_id < 0) {
|
||||
throw osmium::pbf_error("object changeset_id must not be negative");
|
||||
}
|
||||
node.set_changeset(static_cast<osmium::changeset_id_type>(changeset_id));
|
||||
|
||||
node.set_timestamp(dense_timestamp.update(*timestamps.first++) * m_date_factor / 1000);
|
||||
node.set_uid_from_signed(static_cast<osmium::signed_user_id_type>(dense_uid.update(*uids.first++)));
|
||||
|
||||
if (has_visibles) {
|
||||
if (visibles.first == visibles.second) {
|
||||
// this is against the spec, must have same number of elements
|
||||
throw osmium::pbf_error("PBF format error");
|
||||
}
|
||||
visible = *visibles.first++;
|
||||
}
|
||||
node.set_visible(visible);
|
||||
|
||||
const auto& u = m_stringtable.at(dense_user_sid.update(*user_sids.first++));
|
||||
builder.add_user(u.first, u.second);
|
||||
} else {
|
||||
builder.add_user("");
|
||||
}
|
||||
|
||||
if (visible) {
|
||||
builder.object().set_location(osmium::Location(
|
||||
convert_pbf_coordinate(dense_longitude.update(*lons.first++)),
|
||||
convert_pbf_coordinate(dense_latitude.update(*lats.first++))
|
||||
));
|
||||
}
|
||||
|
||||
if (tag_it != tags.second) {
|
||||
osmium::builder::TagListBuilder tl_builder(m_buffer, &builder);
|
||||
while (tag_it != tags.second && *tag_it != 0) {
|
||||
const auto& k = m_stringtable.at(*tag_it++);
|
||||
if (tag_it == tags.second) {
|
||||
throw osmium::pbf_error("PBF format error"); // this is against the spec, keys/vals must come in pairs
|
||||
}
|
||||
const auto& v = m_stringtable.at(*tag_it++);
|
||||
tl_builder.add_tag(k.first, k.second, v.first, v.second);
|
||||
}
|
||||
|
||||
if (tag_it != tags.second) {
|
||||
++tag_it;
|
||||
}
|
||||
}
|
||||
|
||||
m_buffer.commit();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
explicit PBFPrimitiveBlockDecoder(const ptr_len_type& data, osmium::osm_entity_bits::type read_types) :
|
||||
m_data(data),
|
||||
m_read_types(read_types) {
|
||||
}
|
||||
|
||||
PBFPrimitiveBlockDecoder(const PBFPrimitiveBlockDecoder&) = delete;
|
||||
PBFPrimitiveBlockDecoder& operator=(const PBFPrimitiveBlockDecoder&) = delete;
|
||||
|
||||
PBFPrimitiveBlockDecoder(PBFPrimitiveBlockDecoder&&) = delete;
|
||||
PBFPrimitiveBlockDecoder& operator=(PBFPrimitiveBlockDecoder&&) = delete;
|
||||
|
||||
~PBFPrimitiveBlockDecoder() = default;
|
||||
|
||||
osmium::memory::Buffer operator()() {
|
||||
try {
|
||||
decode_primitive_block_metadata();
|
||||
decode_primitive_block_data();
|
||||
} catch (std::out_of_range&) {
|
||||
throw osmium::pbf_error("string id out of range");
|
||||
}
|
||||
|
||||
return std::move(m_buffer);
|
||||
}
|
||||
|
||||
}; // class PBFPrimitiveBlockDecoder
|
||||
|
||||
inline ptr_len_type decode_blob(const std::string& blob_data, std::string& output) {
|
||||
int32_t raw_size;
|
||||
std::pair<const char*, protozero::pbf_length_type> zlib_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_data();
|
||||
if (data_len.second > max_uncompressed_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");
|
||||
}
|
||||
break;
|
||||
case FileFormat::Blob::optional_bytes_zlib_data:
|
||||
zlib_data = pbf_blob.get_data();
|
||||
break;
|
||||
case FileFormat::Blob::optional_bytes_lzma_data:
|
||||
throw osmium::pbf_error("lzma blobs not implemented");
|
||||
default:
|
||||
throw osmium::pbf_error("unknown compression");
|
||||
}
|
||||
}
|
||||
|
||||
if (zlib_data.second != 0) {
|
||||
return osmium::io::detail::zlib_uncompress_string(
|
||||
zlib_data.first,
|
||||
static_cast<unsigned long>(zlib_data.second),
|
||||
static_cast<unsigned long>(raw_size),
|
||||
output
|
||||
);
|
||||
}
|
||||
|
||||
throw osmium::pbf_error("blob contains no data");
|
||||
}
|
||||
|
||||
inline osmium::Box decode_header_bbox(const ptr_len_type& data) {
|
||||
int64_t left = std::numeric_limits<int64_t>::max();
|
||||
int64_t right = std::numeric_limits<int64_t>::max();
|
||||
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);
|
||||
while (pbf_header_bbox.next()) {
|
||||
switch (pbf_header_bbox.tag()) {
|
||||
case OSMFormat::HeaderBBox::required_sint64_left:
|
||||
left = pbf_header_bbox.get_sint64();
|
||||
break;
|
||||
case OSMFormat::HeaderBBox::required_sint64_right:
|
||||
right = pbf_header_bbox.get_sint64();
|
||||
break;
|
||||
case OSMFormat::HeaderBBox::required_sint64_top:
|
||||
top = pbf_header_bbox.get_sint64();
|
||||
break;
|
||||
case OSMFormat::HeaderBBox::required_sint64_bottom:
|
||||
bottom = pbf_header_bbox.get_sint64();
|
||||
break;
|
||||
default:
|
||||
pbf_header_bbox.skip();
|
||||
}
|
||||
}
|
||||
|
||||
if (left == std::numeric_limits<int64_t>::max() ||
|
||||
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");
|
||||
}
|
||||
|
||||
osmium::Box box;
|
||||
box.extend(osmium::Location(left / resolution_convert, bottom / resolution_convert));
|
||||
box.extend(osmium::Location(right / resolution_convert, top / resolution_convert));
|
||||
|
||||
return box;
|
||||
}
|
||||
|
||||
inline osmium::io::Header decode_header_block(const ptr_len_type& data) {
|
||||
osmium::io::Header header;
|
||||
int i = 0;
|
||||
|
||||
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:
|
||||
header.add_box(decode_header_bbox(pbf_header_block.get_data()));
|
||||
break;
|
||||
case OSMFormat::HeaderBlock::repeated_string_required_features:
|
||||
{
|
||||
auto feature = pbf_header_block.get_data();
|
||||
if (!strncmp("OsmSchema-V0.6", feature.first, feature.second)) {
|
||||
// intentionally left blank
|
||||
} else if (!strncmp("DenseNodes", feature.first, feature.second)) {
|
||||
header.set("pbf_dense_nodes", true);
|
||||
} else if (!strncmp("HistoricalInformation", feature.first, feature.second)) {
|
||||
header.set_has_multiple_object_versions(true);
|
||||
} else {
|
||||
std::string msg("required feature not supported: ");
|
||||
msg.append(feature.first, feature.second);
|
||||
throw osmium::pbf_error(msg);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case OSMFormat::HeaderBlock::repeated_string_optional_features:
|
||||
header.set("pbf_optional_feature_" + std::to_string(i++), pbf_header_block.get_string());
|
||||
break;
|
||||
case OSMFormat::HeaderBlock::optional_string_writingprogram:
|
||||
header.set("generator", pbf_header_block.get_string());
|
||||
break;
|
||||
case OSMFormat::HeaderBlock::optional_int64_osmosis_replication_timestamp:
|
||||
header.set("osmosis_replication_timestamp", osmium::Timestamp(pbf_header_block.get_int64()).to_iso());
|
||||
break;
|
||||
case OSMFormat::HeaderBlock::optional_int64_osmosis_replication_sequence_number:
|
||||
header.set("osmosis_replication_sequence_number", std::to_string(pbf_header_block.get_int64()));
|
||||
break;
|
||||
case OSMFormat::HeaderBlock::optional_string_osmosis_replication_base_url:
|
||||
header.set("osmosis_replication_base_url", pbf_header_block.get_string());
|
||||
break;
|
||||
default:
|
||||
pbf_header_block.skip();
|
||||
}
|
||||
}
|
||||
|
||||
return header;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode HeaderBlock.
|
||||
*
|
||||
* @param header_block_data Input data
|
||||
* @returns Header object
|
||||
* @throws osmium::pbf_error If there was a parsing error
|
||||
*/
|
||||
inline osmium::io::Header decode_header(const std::string& header_block_data) {
|
||||
std::string output;
|
||||
|
||||
return decode_header_block(decode_blob(header_block_data, output));
|
||||
}
|
||||
|
||||
class PBFDataBlobDecoder {
|
||||
|
||||
std::shared_ptr<std::string> m_input_buffer;
|
||||
osmium::osm_entity_bits::type m_read_types;
|
||||
|
||||
public:
|
||||
|
||||
PBFDataBlobDecoder(std::string&& input_buffer, osmium::osm_entity_bits::type read_types) :
|
||||
m_input_buffer(std::make_shared<std::string>(std::move(input_buffer))),
|
||||
m_read_types(read_types) {
|
||||
}
|
||||
|
||||
PBFDataBlobDecoder(const PBFDataBlobDecoder&) = default;
|
||||
PBFDataBlobDecoder& operator=(const PBFDataBlobDecoder&) = default;
|
||||
|
||||
PBFDataBlobDecoder(PBFDataBlobDecoder&&) = default;
|
||||
PBFDataBlobDecoder& operator=(PBFDataBlobDecoder&&) = default;
|
||||
|
||||
~PBFDataBlobDecoder() = default;
|
||||
|
||||
osmium::memory::Buffer operator()() {
|
||||
std::string output;
|
||||
PBFPrimitiveBlockDecoder decoder(decode_blob(*m_input_buffer, output), m_read_types);
|
||||
return decoder();
|
||||
}
|
||||
|
||||
}; // class PBFDataBlobDecoder
|
||||
|
||||
} // namespace detail
|
||||
|
||||
} // namespace io
|
||||
|
||||
} // namespace osmium
|
||||
|
||||
#endif // OSMIUM_IO_DETAIL_PBF_DECODER_HPP
|
@ -49,9 +49,12 @@ DEALINGS IN THE SOFTWARE.
|
||||
#include <thread>
|
||||
#include <type_traits>
|
||||
|
||||
#include <protozero/pbf_message.hpp>
|
||||
|
||||
#include <osmium/io/detail/input_format.hpp>
|
||||
#include <osmium/io/detail/pbf.hpp> // IWYU pragma: export
|
||||
#include <osmium/io/detail/pbf_parser.hpp>
|
||||
#include <osmium/io/detail/pbf_decoder.hpp>
|
||||
#include <osmium/io/detail/protobuf_tags.hpp>
|
||||
#include <osmium/io/error.hpp>
|
||||
#include <osmium/io/file.hpp>
|
||||
#include <osmium/io/file_format.hpp>
|
||||
@ -76,13 +79,13 @@ namespace osmium {
|
||||
|
||||
namespace detail {
|
||||
|
||||
typedef osmium::thread::Queue<std::future<osmium::memory::Buffer>> queue_type;
|
||||
|
||||
/**
|
||||
* Class for parsing PBF files.
|
||||
*/
|
||||
class PBFInputFormat : public osmium::io::detail::InputFormat {
|
||||
|
||||
typedef osmium::thread::Queue<std::future<osmium::memory::Buffer>> queue_type;
|
||||
|
||||
bool m_use_thread_pool;
|
||||
bool m_eof { false };
|
||||
queue_type m_queue;
|
||||
@ -115,15 +118,10 @@ namespace osmium {
|
||||
}
|
||||
|
||||
/**
|
||||
* Read BlobHeader by first reading the size and then the
|
||||
* BlobHeader. The BlobHeader contains a type field (which is
|
||||
* checked against the expected type) and a size field.
|
||||
*
|
||||
* @param expected_type Expected type of data ("OSMHeader" or
|
||||
* "OSMData").
|
||||
* @returns Size of the data read from BlobHeader (0 on EOF).
|
||||
* Read 4 bytes in network byte order from file. They contain
|
||||
* the length of the following BlobHeader.
|
||||
*/
|
||||
size_t read_blob_header(const char* expected_type) {
|
||||
uint32_t read_blob_header_size_from_file() {
|
||||
uint32_t size_in_network_byte_order;
|
||||
|
||||
try {
|
||||
@ -133,37 +131,76 @@ namespace osmium {
|
||||
return 0; // EOF
|
||||
}
|
||||
|
||||
uint32_t size = ntohl(size_in_network_byte_order);
|
||||
if (size > static_cast<uint32_t>(OSMPBF::max_blob_header_size)) {
|
||||
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)");
|
||||
}
|
||||
|
||||
OSMPBF::BlobHeader blob_header;
|
||||
if (!blob_header.ParseFromString(read_from_input_queue(size))) {
|
||||
throw osmium::pbf_error("failed to parse BlobHeader");
|
||||
return size;
|
||||
}
|
||||
|
||||
if (blob_header.type() != expected_type) {
|
||||
/**
|
||||
* Decode the BlobHeader. Make sure it contains the expected
|
||||
* type. Return the size of the following Blob.
|
||||
*/
|
||||
size_t decode_blob_header(protozero::pbf_message<FileFormat::BlobHeader>&& pbf_blob_header, const char* expected_type) {
|
||||
std::pair<const char*, size_t> blob_header_type;
|
||||
size_t blob_header_datasize = 0;
|
||||
|
||||
while (pbf_blob_header.next()) {
|
||||
switch (pbf_blob_header.tag()) {
|
||||
case FileFormat::BlobHeader::required_string_type:
|
||||
blob_header_type = pbf_blob_header.get_data();
|
||||
break;
|
||||
case FileFormat::BlobHeader::required_int32_datasize:
|
||||
blob_header_datasize = pbf_blob_header.get_int32();
|
||||
break;
|
||||
default:
|
||||
pbf_blob_header.skip();
|
||||
}
|
||||
}
|
||||
|
||||
if (blob_header_datasize == 0) {
|
||||
throw osmium::pbf_error("PBF format error: BlobHeader.datasize missing or zero.");
|
||||
}
|
||||
|
||||
if (strncmp(expected_type, blob_header_type.first, blob_header_type.second)) {
|
||||
throw osmium::pbf_error("blob does not have expected type (OSMHeader in first blob, OSMData in following blobs)");
|
||||
}
|
||||
|
||||
return static_cast<size_t>(blob_header.datasize());
|
||||
return blob_header_datasize;
|
||||
}
|
||||
|
||||
size_t check_type_and_get_blob_size(const char* expected_type) {
|
||||
assert(expected_type);
|
||||
|
||||
auto size = read_blob_header_size_from_file();
|
||||
if (size == 0) { // EOF
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::string blob_header = read_from_input_queue(size);
|
||||
|
||||
return decode_blob_header(protozero::pbf_message<FileFormat::BlobHeader>(blob_header), expected_type);
|
||||
}
|
||||
|
||||
void parse_osm_data(osmium::osm_entity_bits::type read_types) {
|
||||
osmium::thread::set_thread_name("_osmium_pbf_in");
|
||||
int n = 0;
|
||||
while (auto size = read_blob_header("OSMData")) {
|
||||
|
||||
while (auto size = check_type_and_get_blob_size("OSMData")) {
|
||||
std::string input_buffer = read_from_input_queue(size);
|
||||
if (input_buffer.size() > max_uncompressed_blob_size) {
|
||||
throw osmium::pbf_error(std::string("invalid blob size: " + std::to_string(input_buffer.size())));
|
||||
}
|
||||
|
||||
if (m_use_thread_pool) {
|
||||
m_queue.push(osmium::thread::Pool::instance().submit(DataBlobParser{read_from_input_queue(size), read_types}));
|
||||
m_queue.push(osmium::thread::Pool::instance().submit(PBFDataBlobDecoder{ std::move(input_buffer), read_types }));
|
||||
} else {
|
||||
std::promise<osmium::memory::Buffer> promise;
|
||||
m_queue.push(promise.get_future());
|
||||
DataBlobParser data_blob_parser{read_from_input_queue(size), read_types};
|
||||
PBFDataBlobDecoder data_blob_parser{ std::move(input_buffer), read_types };
|
||||
promise.set_value(data_blob_parser());
|
||||
}
|
||||
++n;
|
||||
|
||||
if (m_quit_input_thread) {
|
||||
return;
|
||||
@ -197,11 +234,10 @@ namespace osmium {
|
||||
m_quit_input_thread(false),
|
||||
m_input_queue(input_queue),
|
||||
m_input_buffer() {
|
||||
GOOGLE_PROTOBUF_VERIFY_VERSION;
|
||||
|
||||
// handle OSMHeader
|
||||
auto size = read_blob_header("OSMHeader");
|
||||
m_header = parse_header_blob(read_from_input_queue(size));
|
||||
const auto size = check_type_and_get_blob_size("OSMHeader");
|
||||
m_header = decode_header(read_from_input_queue(size));
|
||||
|
||||
if (m_read_which_entities != osmium::osm_entity_bits::nothing) {
|
||||
m_reader = std::thread(&PBFInputFormat::parse_osm_data, this, m_read_which_entities);
|
||||
@ -246,10 +282,15 @@ namespace osmium {
|
||||
|
||||
namespace {
|
||||
|
||||
// we want the register_input_format() function to run, setting the variable
|
||||
// is only a side-effect, it will never be used
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wunused-variable"
|
||||
const bool registered_pbf_input = osmium::io::detail::InputFormatFactory::instance().register_input_format(osmium::io::file_format::pbf,
|
||||
[](const osmium::io::File& file, osmium::osm_entity_bits::type read_which_entities, osmium::thread::Queue<std::string>& input_queue) {
|
||||
return new osmium::io::detail::PBFInputFormat(file, read_which_entities, input_queue);
|
||||
});
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,455 +0,0 @@
|
||||
#ifndef OSMIUM_IO_DETAIL_PBF_PRIMITIVE_BLOCK_PARSER_HPP
|
||||
#define OSMIUM_IO_DETAIL_PBF_PRIMITIVE_BLOCK_PARSER_HPP
|
||||
|
||||
/*
|
||||
|
||||
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||
|
||||
Copyright 2013-2015 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 <cassert>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <algorithm>
|
||||
|
||||
#include <osmpbf/osmpbf.h>
|
||||
|
||||
#include <osmium/builder/osm_object_builder.hpp>
|
||||
#include <osmium/io/detail/pbf.hpp> // IWYU pragma: export
|
||||
#include <osmium/io/detail/zlib.hpp>
|
||||
#include <osmium/io/header.hpp>
|
||||
#include <osmium/osm/location.hpp>
|
||||
#include <osmium/osm/node.hpp>
|
||||
#include <osmium/osm/types.hpp>
|
||||
#include <osmium/memory/buffer.hpp>
|
||||
#include <osmium/osm/entity_bits.hpp>
|
||||
#include <osmium/util/cast.hpp>
|
||||
|
||||
namespace osmium {
|
||||
|
||||
namespace io {
|
||||
|
||||
namespace detail {
|
||||
|
||||
class PBFPrimitiveBlockParser {
|
||||
|
||||
static constexpr size_t initial_buffer_size = 2 * 1024 * 1024;
|
||||
|
||||
const std::string& m_data;
|
||||
|
||||
const OSMPBF::StringTable* m_stringtable;
|
||||
int64_t m_lon_offset;
|
||||
int64_t m_lat_offset;
|
||||
int64_t m_date_factor;
|
||||
int32_t m_granularity;
|
||||
|
||||
osmium::osm_entity_bits::type m_read_types;
|
||||
|
||||
osmium::memory::Buffer m_buffer;
|
||||
|
||||
PBFPrimitiveBlockParser(const PBFPrimitiveBlockParser&) = delete;
|
||||
PBFPrimitiveBlockParser(PBFPrimitiveBlockParser&&) = delete;
|
||||
|
||||
PBFPrimitiveBlockParser& operator=(const PBFPrimitiveBlockParser&) = delete;
|
||||
PBFPrimitiveBlockParser& operator=(PBFPrimitiveBlockParser&&) = delete;
|
||||
|
||||
public:
|
||||
|
||||
explicit PBFPrimitiveBlockParser(const std::string& data, osmium::osm_entity_bits::type read_types) :
|
||||
m_data(data),
|
||||
m_stringtable(nullptr),
|
||||
m_lon_offset(0),
|
||||
m_lat_offset(0),
|
||||
m_date_factor(1000),
|
||||
m_granularity(100),
|
||||
m_read_types(read_types),
|
||||
m_buffer(initial_buffer_size) {
|
||||
}
|
||||
|
||||
~PBFPrimitiveBlockParser() = default;
|
||||
|
||||
osmium::memory::Buffer operator()() {
|
||||
OSMPBF::PrimitiveBlock pbf_primitive_block;
|
||||
if (!pbf_primitive_block.ParseFromString(m_data)) {
|
||||
throw osmium::pbf_error("failed to parse PrimitiveBlock");
|
||||
}
|
||||
|
||||
m_stringtable = &pbf_primitive_block.stringtable();
|
||||
m_lon_offset = pbf_primitive_block.lon_offset();
|
||||
m_lat_offset = pbf_primitive_block.lat_offset();
|
||||
m_date_factor = pbf_primitive_block.date_granularity() / 1000;
|
||||
m_granularity = pbf_primitive_block.granularity();
|
||||
|
||||
for (int i = 0; i < pbf_primitive_block.primitivegroup_size(); ++i) {
|
||||
const OSMPBF::PrimitiveGroup& group = pbf_primitive_block.primitivegroup(i);
|
||||
|
||||
if (group.has_dense()) {
|
||||
if (m_read_types & osmium::osm_entity_bits::node) parse_dense_node_group(group);
|
||||
} else if (group.ways_size() != 0) {
|
||||
if (m_read_types & osmium::osm_entity_bits::way) parse_way_group(group);
|
||||
} else if (group.relations_size() != 0) {
|
||||
if (m_read_types & osmium::osm_entity_bits::relation) parse_relation_group(group);
|
||||
} else if (group.nodes_size() != 0) {
|
||||
if (m_read_types & osmium::osm_entity_bits::node) parse_node_group(group);
|
||||
} else {
|
||||
throw osmium::pbf_error("group of unknown type");
|
||||
}
|
||||
}
|
||||
|
||||
return std::move(m_buffer);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
template <class TBuilder, class TPBFObject>
|
||||
void parse_attributes(TBuilder& builder, const TPBFObject& pbf_object) {
|
||||
auto& object = builder.object();
|
||||
|
||||
object.set_id(pbf_object.id());
|
||||
|
||||
if (pbf_object.has_info()) {
|
||||
object.set_version(static_cast_with_assert<object_version_type>(pbf_object.info().version()))
|
||||
.set_changeset(static_cast_with_assert<changeset_id_type>(pbf_object.info().changeset()))
|
||||
.set_timestamp(pbf_object.info().timestamp() * m_date_factor)
|
||||
.set_uid_from_signed(pbf_object.info().uid());
|
||||
if (pbf_object.info().has_visible()) {
|
||||
object.set_visible(pbf_object.info().visible());
|
||||
}
|
||||
builder.add_user(m_stringtable->s(static_cast_with_assert<int>(pbf_object.info().user_sid())));
|
||||
} else {
|
||||
builder.add_user("", 1);
|
||||
}
|
||||
}
|
||||
|
||||
void parse_node_group(const OSMPBF::PrimitiveGroup& group) {
|
||||
for (int i = 0; i < group.nodes_size(); ++i) {
|
||||
osmium::builder::NodeBuilder builder(m_buffer);
|
||||
const OSMPBF::Node& pbf_node = group.nodes(i);
|
||||
parse_attributes(builder, pbf_node);
|
||||
|
||||
if (builder.object().visible()) {
|
||||
builder.object().set_location(osmium::Location(
|
||||
(pbf_node.lon() * m_granularity + m_lon_offset) / (OSMPBF::lonlat_resolution / osmium::Location::coordinate_precision),
|
||||
(pbf_node.lat() * m_granularity + m_lat_offset) / (OSMPBF::lonlat_resolution / osmium::Location::coordinate_precision)));
|
||||
}
|
||||
|
||||
if (pbf_node.keys_size() > 0) {
|
||||
osmium::builder::TagListBuilder tl_builder(m_buffer, &builder);
|
||||
for (int tag = 0; tag < pbf_node.keys_size(); ++tag) {
|
||||
tl_builder.add_tag(m_stringtable->s(static_cast<int>(pbf_node.keys(tag))),
|
||||
m_stringtable->s(static_cast<int>(pbf_node.vals(tag))));
|
||||
}
|
||||
}
|
||||
|
||||
m_buffer.commit();
|
||||
}
|
||||
}
|
||||
|
||||
void parse_way_group(const OSMPBF::PrimitiveGroup& group) {
|
||||
for (int i = 0; i < group.ways_size(); ++i) {
|
||||
osmium::builder::WayBuilder builder(m_buffer);
|
||||
const OSMPBF::Way& pbf_way = group.ways(i);
|
||||
parse_attributes(builder, pbf_way);
|
||||
|
||||
if (pbf_way.refs_size() > 0) {
|
||||
osmium::builder::WayNodeListBuilder wnl_builder(m_buffer, &builder);
|
||||
int64_t ref = 0;
|
||||
for (int n = 0; n < pbf_way.refs_size(); ++n) {
|
||||
ref += pbf_way.refs(n);
|
||||
wnl_builder.add_node_ref(ref);
|
||||
}
|
||||
}
|
||||
|
||||
if (pbf_way.keys_size() > 0) {
|
||||
osmium::builder::TagListBuilder tl_builder(m_buffer, &builder);
|
||||
for (int tag = 0; tag < pbf_way.keys_size(); ++tag) {
|
||||
tl_builder.add_tag(m_stringtable->s(static_cast<int>(pbf_way.keys(tag))),
|
||||
m_stringtable->s(static_cast<int>(pbf_way.vals(tag))));
|
||||
}
|
||||
}
|
||||
|
||||
m_buffer.commit();
|
||||
}
|
||||
}
|
||||
|
||||
void parse_relation_group(const OSMPBF::PrimitiveGroup& group) {
|
||||
for (int i = 0; i < group.relations_size(); ++i) {
|
||||
osmium::builder::RelationBuilder builder(m_buffer);
|
||||
const OSMPBF::Relation& pbf_relation = group.relations(i);
|
||||
parse_attributes(builder, pbf_relation);
|
||||
|
||||
if (pbf_relation.types_size() > 0) {
|
||||
osmium::builder::RelationMemberListBuilder rml_builder(m_buffer, &builder);
|
||||
int64_t ref = 0;
|
||||
for (int n = 0; n < pbf_relation.types_size(); ++n) {
|
||||
ref += pbf_relation.memids(n);
|
||||
rml_builder.add_member(osmpbf_membertype_to_item_type(pbf_relation.types(n)), ref, m_stringtable->s(pbf_relation.roles_sid(n)));
|
||||
}
|
||||
}
|
||||
|
||||
if (pbf_relation.keys_size() > 0) {
|
||||
osmium::builder::TagListBuilder tl_builder(m_buffer, &builder);
|
||||
for (int tag = 0; tag < pbf_relation.keys_size(); ++tag) {
|
||||
tl_builder.add_tag(m_stringtable->s(static_cast<int>(pbf_relation.keys(tag))),
|
||||
m_stringtable->s(static_cast<int>(pbf_relation.vals(tag))));
|
||||
}
|
||||
}
|
||||
|
||||
m_buffer.commit();
|
||||
}
|
||||
}
|
||||
|
||||
int add_tags(const OSMPBF::DenseNodes& dense, int n, osmium::builder::NodeBuilder* builder) {
|
||||
if (n >= dense.keys_vals_size()) {
|
||||
return n;
|
||||
}
|
||||
|
||||
if (dense.keys_vals(n) == 0) {
|
||||
return n+1;
|
||||
}
|
||||
|
||||
osmium::builder::TagListBuilder tl_builder(m_buffer, builder);
|
||||
|
||||
while (n < dense.keys_vals_size()) {
|
||||
int tag_key_pos = dense.keys_vals(n++);
|
||||
|
||||
if (tag_key_pos == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
tl_builder.add_tag(m_stringtable->s(tag_key_pos),
|
||||
m_stringtable->s(dense.keys_vals(n)));
|
||||
|
||||
++n;
|
||||
}
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
void parse_dense_node_group(const OSMPBF::PrimitiveGroup& group) {
|
||||
int64_t last_dense_id = 0;
|
||||
int64_t last_dense_latitude = 0;
|
||||
int64_t last_dense_longitude = 0;
|
||||
int64_t last_dense_uid = 0;
|
||||
int64_t last_dense_user_sid = 0;
|
||||
int64_t last_dense_changeset = 0;
|
||||
int64_t last_dense_timestamp = 0;
|
||||
int last_dense_tag = 0;
|
||||
|
||||
const OSMPBF::DenseNodes& dense = group.dense();
|
||||
|
||||
for (int i = 0; i < dense.id_size(); ++i) {
|
||||
bool visible = true;
|
||||
|
||||
last_dense_id += dense.id(i);
|
||||
last_dense_latitude += dense.lat(i);
|
||||
last_dense_longitude += dense.lon(i);
|
||||
|
||||
if (dense.has_denseinfo()) {
|
||||
last_dense_changeset += dense.denseinfo().changeset(i);
|
||||
last_dense_timestamp += dense.denseinfo().timestamp(i);
|
||||
last_dense_uid += dense.denseinfo().uid(i);
|
||||
last_dense_user_sid += dense.denseinfo().user_sid(i);
|
||||
if (dense.denseinfo().visible_size() > 0) {
|
||||
visible = dense.denseinfo().visible(i);
|
||||
}
|
||||
assert(last_dense_changeset >= 0);
|
||||
assert(last_dense_timestamp >= 0);
|
||||
assert(last_dense_uid >= -1);
|
||||
assert(last_dense_user_sid >= 0);
|
||||
}
|
||||
|
||||
osmium::builder::NodeBuilder builder(m_buffer);
|
||||
osmium::Node& node = builder.object();
|
||||
|
||||
node.set_id(last_dense_id);
|
||||
|
||||
if (dense.has_denseinfo()) {
|
||||
auto v = dense.denseinfo().version(i);
|
||||
assert(v > 0);
|
||||
node.set_version(static_cast<osmium::object_version_type>(v));
|
||||
node.set_changeset(static_cast<osmium::changeset_id_type>(last_dense_changeset));
|
||||
node.set_timestamp(last_dense_timestamp * m_date_factor);
|
||||
node.set_uid_from_signed(static_cast<osmium::signed_user_id_type>(last_dense_uid));
|
||||
node.set_visible(visible);
|
||||
builder.add_user(m_stringtable->s(static_cast<int>(last_dense_user_sid)));
|
||||
} else {
|
||||
builder.add_user("", 1);
|
||||
}
|
||||
|
||||
if (visible) {
|
||||
builder.object().set_location(osmium::Location(
|
||||
(last_dense_longitude * m_granularity + m_lon_offset) / (OSMPBF::lonlat_resolution / osmium::Location::coordinate_precision),
|
||||
(last_dense_latitude * m_granularity + m_lat_offset) / (OSMPBF::lonlat_resolution / osmium::Location::coordinate_precision)));
|
||||
}
|
||||
|
||||
last_dense_tag = add_tags(dense, last_dense_tag, &builder);
|
||||
m_buffer.commit();
|
||||
}
|
||||
}
|
||||
|
||||
}; // class PBFPrimitiveBlockParser
|
||||
|
||||
/**
|
||||
* PBF blobs can optionally be packed with the zlib algorithm.
|
||||
* This function returns the raw data (if it was unpacked) or
|
||||
* the unpacked data (if it was packed).
|
||||
*
|
||||
* @param input_data Reference to input data.
|
||||
* @returns Unpacked data
|
||||
* @throws osmium::pbf_error If there was a problem parsing the PBF
|
||||
*/
|
||||
inline std::unique_ptr<const std::string> unpack_blob(const std::string& input_data) {
|
||||
OSMPBF::Blob pbf_blob;
|
||||
if (!pbf_blob.ParseFromString(input_data)) {
|
||||
throw osmium::pbf_error("failed to parse blob");
|
||||
}
|
||||
|
||||
if (pbf_blob.has_raw()) {
|
||||
return std::unique_ptr<std::string>(pbf_blob.release_raw());
|
||||
} else if (pbf_blob.has_zlib_data()) {
|
||||
auto raw_size = pbf_blob.raw_size();
|
||||
assert(raw_size >= 0);
|
||||
assert(raw_size <= OSMPBF::max_uncompressed_blob_size);
|
||||
return osmium::io::detail::zlib_uncompress(pbf_blob.zlib_data(), static_cast<unsigned long>(raw_size));
|
||||
} else if (pbf_blob.has_lzma_data()) {
|
||||
throw osmium::pbf_error("lzma blobs not implemented");
|
||||
} else {
|
||||
throw osmium::pbf_error("blob contains no data");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse blob as a HeaderBlock.
|
||||
*
|
||||
* @param input_buffer Blob data
|
||||
* @returns Header object
|
||||
* @throws osmium::pbf_error If there was a parsing error
|
||||
*/
|
||||
inline osmium::io::Header parse_header_blob(const std::string& input_buffer) {
|
||||
const std::unique_ptr<const std::string> data = unpack_blob(input_buffer);
|
||||
|
||||
OSMPBF::HeaderBlock pbf_header_block;
|
||||
if (!pbf_header_block.ParseFromString(*data)) {
|
||||
throw osmium::pbf_error("failed to parse HeaderBlock");
|
||||
}
|
||||
|
||||
osmium::io::Header header;
|
||||
for (int i = 0; i < pbf_header_block.required_features_size(); ++i) {
|
||||
const std::string& feature = pbf_header_block.required_features(i);
|
||||
|
||||
if (feature == "OsmSchema-V0.6") continue;
|
||||
if (feature == "DenseNodes") {
|
||||
header.set("pbf_dense_nodes", true);
|
||||
continue;
|
||||
}
|
||||
if (feature == "HistoricalInformation") {
|
||||
header.set_has_multiple_object_versions(true);
|
||||
continue;
|
||||
}
|
||||
|
||||
throw osmium::pbf_error(std::string("required feature not supported: ") + feature);
|
||||
}
|
||||
|
||||
for (int i = 0; i < pbf_header_block.optional_features_size(); ++i) {
|
||||
const std::string& feature = pbf_header_block.optional_features(i);
|
||||
header.set("pbf_optional_feature_" + std::to_string(i), feature);
|
||||
}
|
||||
|
||||
if (pbf_header_block.has_writingprogram()) {
|
||||
header.set("generator", pbf_header_block.writingprogram());
|
||||
}
|
||||
|
||||
if (pbf_header_block.has_bbox()) {
|
||||
const OSMPBF::HeaderBBox& pbf_bbox = pbf_header_block.bbox();
|
||||
const int64_t resolution_convert = OSMPBF::lonlat_resolution / osmium::Location::coordinate_precision;
|
||||
osmium::Box box;
|
||||
box.extend(osmium::Location(pbf_bbox.left() / resolution_convert, pbf_bbox.bottom() / resolution_convert));
|
||||
box.extend(osmium::Location(pbf_bbox.right() / resolution_convert, pbf_bbox.top() / resolution_convert));
|
||||
header.add_box(box);
|
||||
}
|
||||
|
||||
if (pbf_header_block.has_osmosis_replication_timestamp()) {
|
||||
header.set("osmosis_replication_timestamp", osmium::Timestamp(pbf_header_block.osmosis_replication_timestamp()).to_iso());
|
||||
}
|
||||
|
||||
if (pbf_header_block.has_osmosis_replication_sequence_number()) {
|
||||
header.set("osmosis_replication_sequence_number", std::to_string(pbf_header_block.osmosis_replication_sequence_number()));
|
||||
}
|
||||
|
||||
if (pbf_header_block.has_osmosis_replication_base_url()) {
|
||||
header.set("osmosis_replication_base_url", pbf_header_block.osmosis_replication_base_url());
|
||||
}
|
||||
|
||||
return header;
|
||||
}
|
||||
|
||||
class DataBlobParser {
|
||||
|
||||
std::shared_ptr<std::string> m_input_buffer;
|
||||
osmium::osm_entity_bits::type m_read_types;
|
||||
|
||||
public:
|
||||
|
||||
DataBlobParser(std::string&& input_buffer, osmium::osm_entity_bits::type read_types) :
|
||||
m_input_buffer(std::make_shared<std::string>(std::move(input_buffer))),
|
||||
m_read_types(read_types) {
|
||||
if (input_buffer.size() > OSMPBF::max_uncompressed_blob_size) {
|
||||
throw osmium::pbf_error(std::string("invalid blob size: " + std::to_string(input_buffer.size())));
|
||||
}
|
||||
}
|
||||
/*
|
||||
DataBlobParser(const DataBlobParser& other) :
|
||||
m_input_buffer(std::move(other.m_input_buffer)),
|
||||
m_read_types(other.m_read_types) {
|
||||
}*/
|
||||
|
||||
DataBlobParser(const DataBlobParser&) = default;
|
||||
DataBlobParser& operator=(const DataBlobParser&) = default;
|
||||
|
||||
DataBlobParser(DataBlobParser&&) = default;
|
||||
DataBlobParser& operator=(DataBlobParser&&) = default;
|
||||
|
||||
~DataBlobParser() = default;
|
||||
|
||||
osmium::memory::Buffer operator()() {
|
||||
const std::unique_ptr<const std::string> data = unpack_blob(*m_input_buffer);
|
||||
PBFPrimitiveBlockParser parser(*data, m_read_types);
|
||||
return parser();
|
||||
}
|
||||
|
||||
}; // class DataBlobParser
|
||||
|
||||
} // namespace detail
|
||||
|
||||
} // namespace io
|
||||
|
||||
} // namespace osmium
|
||||
|
||||
#endif // OSMIUM_IO_DETAIL_PBF_PRIMITIVE_BLOCK_PARSER_HPP
|
@ -1,218 +0,0 @@
|
||||
#ifndef OSMIUM_IO_DETAIL_PBF_STRINGTABLE_HPP
|
||||
#define OSMIUM_IO_DETAIL_PBF_STRINGTABLE_HPP
|
||||
|
||||
/*
|
||||
|
||||
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||
|
||||
Copyright 2013-2015 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 <cstdint>
|
||||
#include <iterator>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include <osmpbf/osmpbf.h>
|
||||
|
||||
#include <osmium/util/cast.hpp>
|
||||
|
||||
namespace osmium {
|
||||
|
||||
namespace io {
|
||||
|
||||
namespace detail {
|
||||
|
||||
/**
|
||||
* StringTable management for PBF writer
|
||||
*
|
||||
* All strings are stored as indexes to rows in a StringTable. The StringTable contains
|
||||
* one row for each used string, so strings that are used multiple times need to be
|
||||
* stored only once. The StringTable is sorted by usage-count, so the most often used
|
||||
* string is stored at index 1.
|
||||
*/
|
||||
class StringTable {
|
||||
|
||||
public:
|
||||
|
||||
/// type for string IDs (interim and final)
|
||||
typedef uint16_t string_id_type;
|
||||
|
||||
private:
|
||||
|
||||
/**
|
||||
* this is the struct used to build the StringTable. It is stored as
|
||||
* the value-part in the strings-map.
|
||||
*
|
||||
* when a new string is added to the map, its count is set to 0 and
|
||||
* the interim_id is set to the current size of the map. This interim_id
|
||||
* is then stored into the pbf-objects.
|
||||
*
|
||||
* before the PrimitiveBlock is serialized, the map is sorted by count
|
||||
* and stored into the pbf-StringTable. Afterwards the interim-ids are
|
||||
* mapped to the "real" id in the StringTable.
|
||||
*
|
||||
* this way often used strings get lower ids in the StringTable. As the
|
||||
* protobuf-serializer stores numbers in variable bit-lengths, lower
|
||||
* IDs means less used space in the resulting file.
|
||||
*/
|
||||
struct string_info {
|
||||
|
||||
/// number of occurrences of this string
|
||||
uint16_t count;
|
||||
|
||||
/// an intermediate-id
|
||||
string_id_type interim_id;
|
||||
|
||||
}; // struct string_info
|
||||
|
||||
/**
|
||||
* Interim StringTable, storing all strings that should be written to
|
||||
* the StringTable once the block is written to disk.
|
||||
*/
|
||||
typedef std::map<std::string, string_info> string2string_info_type;
|
||||
string2string_info_type m_strings;
|
||||
|
||||
/**
|
||||
* This vector is used to map the interim IDs to real StringTable IDs after
|
||||
* writing all strings to the StringTable.
|
||||
*/
|
||||
typedef std::vector<string_id_type> interim_id2id_type;
|
||||
interim_id2id_type m_id2id_map;
|
||||
|
||||
size_t m_size = 0;
|
||||
|
||||
public:
|
||||
|
||||
StringTable() {
|
||||
}
|
||||
|
||||
friend bool operator<(const string_info& lhs, const string_info& rhs) {
|
||||
return lhs.count > rhs.count;
|
||||
}
|
||||
|
||||
/**
|
||||
* record a string in the interim StringTable if it's missing, otherwise just increase its counter,
|
||||
* return the interim-id assigned to the string.
|
||||
*/
|
||||
string_id_type record_string(const std::string& string) {
|
||||
string_info& info = m_strings[string];
|
||||
if (info.interim_id == 0) {
|
||||
++m_size;
|
||||
info.interim_id = static_cast_with_assert<string_id_type>(m_size);
|
||||
} else {
|
||||
info.count++;
|
||||
}
|
||||
return info.interim_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sort the interim StringTable and store it to the real protobuf StringTable.
|
||||
* while storing to the real table, this function fills the id2id_map with
|
||||
* pairs, mapping the interim-ids to final and real StringTable ids.
|
||||
*
|
||||
* Note that the m_strings table is a std::map and as such is sorted lexicographically.
|
||||
* When the transformation into the sortedby multimap is done, it gets sorted by
|
||||
* the count. The end result (at least with the glibc standard container/algorithm
|
||||
* implementation) is that the string table is sorted first by reverse count (ie descending)
|
||||
* and then by reverse lexicographic order.
|
||||
*/
|
||||
void store_stringtable(OSMPBF::StringTable* st, bool sort) {
|
||||
// add empty StringTable entry at index 0
|
||||
// StringTable index 0 is reserved as delimiter in the densenodes key/value list
|
||||
// this line also ensures that there's always a valid StringTable
|
||||
st->add_s("");
|
||||
|
||||
if (sort) {
|
||||
std::multimap<string_info, std::string> sortedbycount;
|
||||
|
||||
m_id2id_map.resize(m_size+1);
|
||||
|
||||
std::transform(m_strings.begin(), m_strings.end(),
|
||||
std::inserter(sortedbycount, sortedbycount.begin()),
|
||||
[](const std::pair<std::string, string_info>& p) {
|
||||
return std::pair<string_info, std::string>(p.second, p.first);
|
||||
});
|
||||
|
||||
string_id_type n = 0;
|
||||
|
||||
for (const auto& mapping : sortedbycount) {
|
||||
// add the string of the current item to the pbf StringTable
|
||||
st->add_s(mapping.second);
|
||||
|
||||
// store the mapping from the interim-id to the real id
|
||||
m_id2id_map[mapping.first.interim_id] = ++n;
|
||||
}
|
||||
} else {
|
||||
std::vector<std::pair<string_id_type, const char*>> sortedbyid;
|
||||
sortedbyid.reserve(m_strings.size());
|
||||
|
||||
for (const auto& p : m_strings) {
|
||||
sortedbyid.emplace_back(p.second.interim_id, p.first.c_str());
|
||||
}
|
||||
|
||||
std::sort(sortedbyid.begin(), sortedbyid.end());
|
||||
for (const auto& mapping : sortedbyid) {
|
||||
st->add_s(mapping.second);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Map from an interim ID to a real string ID.
|
||||
*/
|
||||
string_id_type map_string_id(const string_id_type interim_id) const {
|
||||
return m_id2id_map[interim_id];
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
string_id_type map_string_id(const T interim_id) const {
|
||||
return map_string_id(static_cast_with_assert<string_id_type>(interim_id));
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear the stringtable, preparing for the next block.
|
||||
*/
|
||||
void clear() {
|
||||
m_strings.clear();
|
||||
m_id2id_map.clear();
|
||||
m_size = 0;
|
||||
}
|
||||
|
||||
}; // class StringTable
|
||||
|
||||
} // namespace detail
|
||||
|
||||
} // namespace io
|
||||
|
||||
} // namespace osmium
|
||||
|
||||
#endif // OSMIUM_IO_DETAIL_PBF_STRINGTABLE_HPP
|
170
third_party/libosmium/include/osmium/io/detail/protobuf_tags.hpp
vendored
Normal file
170
third_party/libosmium/include/osmium/io/detail/protobuf_tags.hpp
vendored
Normal file
@ -0,0 +1,170 @@
|
||||
#ifndef OSMIUM_IO_DETAIL_PROTOBUF_TAGS_HPP
|
||||
#define OSMIUM_IO_DETAIL_PROTOBUF_TAGS_HPP
|
||||
|
||||
/*
|
||||
|
||||
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||
|
||||
Copyright 2013-2015 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 <protozero/pbf_types.hpp>
|
||||
|
||||
namespace osmium {
|
||||
|
||||
namespace io {
|
||||
|
||||
namespace detail {
|
||||
|
||||
// directly translated from
|
||||
// https://github.com/scrosby/OSM-binary/blob/master/src/fileformat.proto
|
||||
|
||||
namespace FileFormat {
|
||||
|
||||
enum class Blob : protozero::pbf_tag_type {
|
||||
optional_bytes_raw = 1,
|
||||
optional_int32_raw_size = 2,
|
||||
optional_bytes_zlib_data = 3,
|
||||
optional_bytes_lzma_data = 4
|
||||
};
|
||||
|
||||
enum class BlobHeader : protozero::pbf_tag_type {
|
||||
required_string_type = 1,
|
||||
optional_bytes_indexdata = 2,
|
||||
required_int32_datasize = 3
|
||||
};
|
||||
|
||||
} // namespace FileFormat
|
||||
|
||||
// directly translated from
|
||||
// https://github.com/scrosby/OSM-binary/blob/master/src/osmformat.proto
|
||||
|
||||
namespace OSMFormat {
|
||||
|
||||
enum class HeaderBlock : protozero::pbf_tag_type {
|
||||
optional_HeaderBBox_bbox = 1,
|
||||
repeated_string_required_features = 4,
|
||||
repeated_string_optional_features = 5,
|
||||
optional_string_writingprogram = 16,
|
||||
optional_string_source = 17,
|
||||
optional_int64_osmosis_replication_timestamp = 32,
|
||||
optional_int64_osmosis_replication_sequence_number = 33,
|
||||
optional_string_osmosis_replication_base_url = 34
|
||||
};
|
||||
|
||||
enum class HeaderBBox : protozero::pbf_tag_type {
|
||||
required_sint64_left = 1,
|
||||
required_sint64_right = 2,
|
||||
required_sint64_top = 3,
|
||||
required_sint64_bottom = 4
|
||||
};
|
||||
|
||||
enum class PrimitiveBlock : protozero::pbf_tag_type {
|
||||
required_StringTable_stringtable = 1,
|
||||
repeated_PrimitiveGroup_primitivegroup = 2,
|
||||
optional_int32_granularity = 17,
|
||||
optional_int32_date_granularity = 18,
|
||||
optional_int64_lat_offset = 19,
|
||||
optional_int64_lon_offset = 20
|
||||
};
|
||||
|
||||
enum class PrimitiveGroup : protozero::pbf_tag_type {
|
||||
unknown = 0,
|
||||
repeated_Node_nodes = 1,
|
||||
optional_DenseNodes_dense = 2,
|
||||
repeated_Way_ways = 3,
|
||||
repeated_Relation_relations = 4,
|
||||
repeated_ChangeSet_changesets = 5
|
||||
};
|
||||
|
||||
enum class StringTable : protozero::pbf_tag_type {
|
||||
repeated_bytes_s = 1
|
||||
};
|
||||
|
||||
enum class Info : protozero::pbf_tag_type {
|
||||
optional_int32_version = 1,
|
||||
optional_int64_timestamp = 2,
|
||||
optional_int64_changeset = 3,
|
||||
optional_int32_uid = 4,
|
||||
optional_uint32_user_sid = 5,
|
||||
optional_bool_visible = 6
|
||||
};
|
||||
|
||||
enum class DenseInfo : protozero::pbf_tag_type {
|
||||
packed_int32_version = 1,
|
||||
packed_sint64_timestamp = 2,
|
||||
packed_sint64_changeset = 3,
|
||||
packed_sint32_uid = 4,
|
||||
packed_sint32_user_sid = 5,
|
||||
packed_bool_visible = 6
|
||||
};
|
||||
|
||||
enum class Node : protozero::pbf_tag_type {
|
||||
required_sint64_id = 1,
|
||||
packed_uint32_keys = 2,
|
||||
packed_uint32_vals = 3,
|
||||
optional_Info_info = 4,
|
||||
required_sint64_lat = 8,
|
||||
required_sint64_lon = 9
|
||||
};
|
||||
|
||||
enum class DenseNodes : protozero::pbf_tag_type {
|
||||
packed_sint64_id = 1,
|
||||
optional_DenseInfo_denseinfo = 5,
|
||||
packed_sint64_lat = 8,
|
||||
packed_sint64_lon = 9,
|
||||
packed_int32_keys_vals = 10
|
||||
};
|
||||
|
||||
enum class Way : protozero::pbf_tag_type {
|
||||
required_int64_id = 1,
|
||||
packed_uint32_keys = 2,
|
||||
packed_uint32_vals = 3,
|
||||
optional_Info_info = 4,
|
||||
packed_sint64_refs = 8
|
||||
};
|
||||
|
||||
enum class Relation : protozero::pbf_tag_type {
|
||||
required_int64_id = 1,
|
||||
packed_uint32_keys = 2,
|
||||
packed_uint32_vals = 3,
|
||||
optional_Info_info = 4,
|
||||
packed_int32_roles_sid = 8,
|
||||
packed_sint64_memids = 9,
|
||||
packed_MemberType_types = 10
|
||||
};
|
||||
|
||||
} // namespace OSMFormat
|
||||
|
||||
} // namespace detail
|
||||
|
||||
} // namespace io
|
||||
|
||||
} // namespace osmium
|
||||
|
||||
#endif // OSMIUM_IO_DETAIL_PROTOBUF_TAGS_HPP
|
@ -122,7 +122,7 @@ namespace osmium {
|
||||
* @throws std::system_error On error.
|
||||
*/
|
||||
inline void reliable_write(const int fd, const unsigned char* output_buffer, const size_t size) {
|
||||
constexpr size_t max_write = 100 * 1024 * 1024; // Max 100 MByte per write
|
||||
constexpr size_t max_write = 100L * 1024L * 1024L; // Max 100 MByte per write
|
||||
size_t offset = 0;
|
||||
do {
|
||||
auto write_count = size - offset;
|
||||
|
250
third_party/libosmium/include/osmium/io/detail/string_table.hpp
vendored
Normal file
250
third_party/libosmium/include/osmium/io/detail/string_table.hpp
vendored
Normal file
@ -0,0 +1,250 @@
|
||||
#ifndef OSMIUM_IO_DETAIL_STRING_TABLE_HPP
|
||||
#define OSMIUM_IO_DETAIL_STRING_TABLE_HPP
|
||||
|
||||
/*
|
||||
|
||||
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||
|
||||
Copyright 2013-2015 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 <cassert>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <iterator>
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
namespace osmium {
|
||||
|
||||
namespace io {
|
||||
|
||||
namespace detail {
|
||||
|
||||
/**
|
||||
* class StringStore
|
||||
*
|
||||
* Storage of lots of strings (const char *). Memory is allocated in chunks.
|
||||
* If a string is added and there is no space in the current chunk, a new
|
||||
* chunk will be allocated. Strings added to the store must not be larger
|
||||
* than the chunk size.
|
||||
*
|
||||
* All memory is released when the destructor is called. There is no other way
|
||||
* to release all or part of the memory.
|
||||
*
|
||||
*/
|
||||
class StringStore {
|
||||
|
||||
size_t m_chunk_size;
|
||||
|
||||
std::list<std::string> m_chunks;
|
||||
|
||||
void add_chunk() {
|
||||
m_chunks.push_front(std::string());
|
||||
m_chunks.front().reserve(m_chunk_size);
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
StringStore(size_t chunk_size) :
|
||||
m_chunk_size(chunk_size),
|
||||
m_chunks() {
|
||||
add_chunk();
|
||||
}
|
||||
|
||||
void clear() noexcept {
|
||||
m_chunks.erase(std::next(m_chunks.begin()), m_chunks.end());
|
||||
m_chunks.front().clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a null terminated string to the store. This will
|
||||
* automatically get more memory if we are out.
|
||||
* Returns a pointer to the copy of the string we have
|
||||
* allocated.
|
||||
*/
|
||||
const char* add(const char* string) {
|
||||
size_t len = std::strlen(string) + 1;
|
||||
|
||||
assert(len <= m_chunk_size);
|
||||
|
||||
size_t chunk_len = m_chunks.front().size();
|
||||
if (chunk_len + len > m_chunks.front().capacity()) {
|
||||
add_chunk();
|
||||
chunk_len = 0;
|
||||
}
|
||||
|
||||
m_chunks.front().append(string);
|
||||
m_chunks.front().append(1, '\0');
|
||||
|
||||
return m_chunks.front().c_str() + chunk_len;
|
||||
}
|
||||
|
||||
class const_iterator : public std::iterator<std::forward_iterator_tag, const char*> {
|
||||
|
||||
typedef std::list<std::string>::const_iterator it_type;
|
||||
it_type m_it;
|
||||
const it_type m_last;
|
||||
const char* m_pos;
|
||||
|
||||
public:
|
||||
|
||||
const_iterator(it_type it, it_type last) :
|
||||
m_it(it),
|
||||
m_last(last),
|
||||
m_pos(it == last ? nullptr : m_it->c_str()) {
|
||||
}
|
||||
|
||||
const_iterator& operator++() {
|
||||
assert(m_it != m_last);
|
||||
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;
|
||||
if (m_pos == last_pos) {
|
||||
++m_it;
|
||||
if (m_it != m_last) {
|
||||
m_pos = m_it->c_str();
|
||||
} else {
|
||||
m_pos = nullptr;
|
||||
}
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
const_iterator operator++(int) {
|
||||
const_iterator tmp(*this);
|
||||
operator++();
|
||||
return tmp;
|
||||
}
|
||||
|
||||
bool operator==(const const_iterator& rhs) const {
|
||||
return m_it == rhs.m_it && m_pos == rhs.m_pos;
|
||||
}
|
||||
|
||||
bool operator!=(const const_iterator& rhs) const {
|
||||
return !(*this == rhs);
|
||||
}
|
||||
|
||||
const char* operator*() const {
|
||||
assert(m_it != m_last);
|
||||
assert(m_pos != nullptr);
|
||||
return m_pos;
|
||||
}
|
||||
|
||||
}; // class const_iterator
|
||||
|
||||
const_iterator begin() const {
|
||||
if (m_chunks.front().empty()) {
|
||||
return end();
|
||||
}
|
||||
return const_iterator(m_chunks.begin(), m_chunks.end());
|
||||
}
|
||||
|
||||
const_iterator end() const {
|
||||
return const_iterator(m_chunks.end(), m_chunks.end());
|
||||
}
|
||||
|
||||
// These functions get you some idea how much memory was
|
||||
// used.
|
||||
int get_chunk_size() const noexcept {
|
||||
return m_chunk_size;
|
||||
}
|
||||
|
||||
int get_chunk_count() const noexcept {
|
||||
return m_chunks.size();
|
||||
}
|
||||
|
||||
int get_used_bytes_in_last_chunk() const noexcept {
|
||||
return m_chunks.front().size();
|
||||
}
|
||||
|
||||
}; // class StringStore
|
||||
|
||||
struct StrComp {
|
||||
|
||||
bool operator()(const char* lhs, const char* rhs) const {
|
||||
return strcmp(lhs, rhs) < 0;
|
||||
}
|
||||
|
||||
}; // struct StrComp
|
||||
|
||||
class StringTable {
|
||||
|
||||
StringStore m_strings;
|
||||
std::map<const char*, size_t, StrComp> m_index;
|
||||
size_t m_size;
|
||||
|
||||
public:
|
||||
|
||||
StringTable() :
|
||||
m_strings(1024 * 1024),
|
||||
m_index(),
|
||||
m_size(0) {
|
||||
m_strings.add("");
|
||||
}
|
||||
|
||||
void clear() {
|
||||
m_strings.clear();
|
||||
m_index.clear();
|
||||
m_size = 0;
|
||||
m_strings.add("");
|
||||
}
|
||||
|
||||
size_t size() const noexcept {
|
||||
return m_size + 1;
|
||||
}
|
||||
|
||||
size_t add(const char* s) {
|
||||
auto f = m_index.find(s);
|
||||
if (f != m_index.end()) {
|
||||
return f->second;
|
||||
}
|
||||
|
||||
const char* cs = m_strings.add(s);
|
||||
m_index[cs] = ++m_size;
|
||||
return m_size;
|
||||
}
|
||||
|
||||
StringStore::const_iterator begin() const {
|
||||
return m_strings.begin();
|
||||
}
|
||||
|
||||
StringStore::const_iterator end() const {
|
||||
return m_strings.end();
|
||||
}
|
||||
|
||||
}; // class StringTable
|
||||
|
||||
} // namespace detail
|
||||
|
||||
} // namespace io
|
||||
|
||||
} // namespace osmium
|
||||
|
||||
#endif // OSMIUM_IO_DETAIL_STRING_TABLE_HPP
|
@ -66,6 +66,7 @@ DEALINGS IN THE SOFTWARE.
|
||||
#include <osmium/osm/location.hpp>
|
||||
#include <osmium/osm/object.hpp>
|
||||
#include <osmium/osm/types.hpp>
|
||||
#include <osmium/osm/types_from_string.hpp>
|
||||
#include <osmium/thread/queue.hpp>
|
||||
#include <osmium/thread/util.hpp>
|
||||
#include <osmium/util/cast.hpp>
|
||||
@ -191,6 +192,8 @@ namespace osmium {
|
||||
|
||||
std::atomic<bool>& m_done;
|
||||
|
||||
bool m_header_is_done;
|
||||
|
||||
/**
|
||||
* A C++ wrapper for the Expat parser that makes sure no memory is leaked.
|
||||
*/
|
||||
@ -246,16 +249,25 @@ namespace osmium {
|
||||
|
||||
T& m_data;
|
||||
std::promise<T>& m_promise;
|
||||
bool m_done;
|
||||
|
||||
public:
|
||||
|
||||
PromiseKeeper(T& data, std::promise<T>& promise) :
|
||||
m_data(data),
|
||||
m_promise(promise) {
|
||||
m_promise(promise),
|
||||
m_done(false) {
|
||||
}
|
||||
|
||||
void fullfill_promise() {
|
||||
if (!m_done) {
|
||||
m_promise.set_value(m_data);
|
||||
m_done = true;
|
||||
}
|
||||
}
|
||||
|
||||
~PromiseKeeper() {
|
||||
m_promise.set_value(m_data);
|
||||
fullfill_promise();
|
||||
}
|
||||
|
||||
}; // class PromiseKeeper
|
||||
@ -279,7 +291,8 @@ namespace osmium {
|
||||
m_queue(queue),
|
||||
m_header_promise(header_promise),
|
||||
m_read_types(read_types),
|
||||
m_done(done) {
|
||||
m_done(done),
|
||||
m_header_is_done(false) {
|
||||
}
|
||||
|
||||
/**
|
||||
@ -305,7 +318,8 @@ namespace osmium {
|
||||
m_queue(other.m_queue),
|
||||
m_header_promise(other.m_header_promise),
|
||||
m_read_types(other.m_read_types),
|
||||
m_done(other.m_done) {
|
||||
m_done(other.m_done),
|
||||
m_header_is_done(other.m_header_is_done) {
|
||||
}
|
||||
|
||||
XMLParser(XMLParser&&) = default;
|
||||
@ -326,6 +340,9 @@ namespace osmium {
|
||||
last = data.empty();
|
||||
try {
|
||||
parser(data, last);
|
||||
if (m_header_is_done) {
|
||||
promise_keeper.fullfill_promise();
|
||||
}
|
||||
} catch (ParserIsDone&) {
|
||||
return true;
|
||||
} catch (...) {
|
||||
@ -343,8 +360,7 @@ namespace osmium {
|
||||
private:
|
||||
|
||||
const char* init_object(osmium::OSMObject& object, const XML_Char** attrs) {
|
||||
static const char* empty = "";
|
||||
const char* user = empty;
|
||||
const char* user = "";
|
||||
|
||||
if (m_in_delete_section) {
|
||||
object.set_visible(false);
|
||||
@ -371,8 +387,7 @@ namespace osmium {
|
||||
}
|
||||
|
||||
void init_changeset(osmium::builder::ChangesetBuilder* builder, const XML_Char** attrs) {
|
||||
static const char* empty = "";
|
||||
const char* user = empty;
|
||||
const char* user = "";
|
||||
osmium::Changeset& new_changeset = builder->object();
|
||||
|
||||
osmium::Location min;
|
||||
@ -421,6 +436,7 @@ namespace osmium {
|
||||
}
|
||||
|
||||
void header_is_done() {
|
||||
m_header_is_done = true;
|
||||
if (m_read_types == osmium::osm_entity_bits::nothing) {
|
||||
throw ParserIsDone();
|
||||
}
|
||||
@ -722,10 +738,15 @@ namespace osmium {
|
||||
|
||||
namespace {
|
||||
|
||||
// we want the register_input_format() function to run, setting the variable
|
||||
// is only a side-effect, it will never be used
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wunused-variable"
|
||||
const bool registered_xml_input = osmium::io::detail::InputFormatFactory::instance().register_input_format(osmium::io::file_format::xml,
|
||||
[](const osmium::io::File& file, osmium::osm_entity_bits::type read_which_entities, osmium::thread::Queue<std::string>& input_queue) {
|
||||
return new osmium::io::detail::XMLInputFormat(file, read_which_entities, input_queue);
|
||||
});
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
|
@ -85,6 +85,9 @@ namespace osmium {
|
||||
case '\'': out += "'"; break;
|
||||
case '<': out += "<"; break;
|
||||
case '>': out += ">"; break;
|
||||
case '\n': out += "
"; break;
|
||||
case '\r': out += "
"; break;
|
||||
case '\t': out += "	"; break;
|
||||
default: out += *in; break;
|
||||
}
|
||||
}
|
||||
@ -126,6 +129,7 @@ namespace osmium {
|
||||
|
||||
operation m_last_op {operation::op_none};
|
||||
|
||||
const bool m_add_metadata;
|
||||
const bool m_write_visible_flag;
|
||||
const bool m_write_change_ops;
|
||||
|
||||
@ -146,6 +150,7 @@ namespace osmium {
|
||||
void write_meta(const osmium::OSMObject& object) {
|
||||
oprintf(*m_out, " id=\"%" PRId64 "\"", object.id());
|
||||
|
||||
if (m_add_metadata) {
|
||||
if (object.version()) {
|
||||
oprintf(*m_out, " version=\"%d\"", object.version());
|
||||
}
|
||||
@ -174,6 +179,7 @@ namespace osmium {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void write_tags(const osmium::TagList& tags) {
|
||||
for (const auto& tag : tags) {
|
||||
@ -224,9 +230,10 @@ namespace osmium {
|
||||
|
||||
public:
|
||||
|
||||
explicit XMLOutputBlock(osmium::memory::Buffer&& buffer, bool write_visible_flag, bool write_change_ops) :
|
||||
explicit XMLOutputBlock(osmium::memory::Buffer&& buffer, bool add_metadata, bool write_visible_flag, bool write_change_ops) :
|
||||
m_input_buffer(std::make_shared<osmium::memory::Buffer>(std::move(buffer))),
|
||||
m_out(std::make_shared<std::string>()),
|
||||
m_add_metadata(add_metadata),
|
||||
m_write_visible_flag(write_visible_flag && !write_change_ops),
|
||||
m_write_change_ops(write_change_ops) {
|
||||
}
|
||||
@ -392,12 +399,14 @@ namespace osmium {
|
||||
|
||||
class XMLOutputFormat : public osmium::io::detail::OutputFormat, public osmium::handler::Handler {
|
||||
|
||||
bool m_add_metadata;
|
||||
bool m_write_visible_flag;
|
||||
|
||||
public:
|
||||
|
||||
XMLOutputFormat(const osmium::io::File& file, data_queue_type& output_queue) :
|
||||
OutputFormat(file, output_queue),
|
||||
m_add_metadata(file.get("add_metadata") != "false"),
|
||||
m_write_visible_flag(file.has_multiple_object_versions() || m_file.is_true("force_visible_flag")) {
|
||||
}
|
||||
|
||||
@ -408,7 +417,7 @@ namespace osmium {
|
||||
}
|
||||
|
||||
void write_buffer(osmium::memory::Buffer&& buffer) override final {
|
||||
m_output_queue.push(osmium::thread::Pool::instance().submit(XMLOutputBlock{std::move(buffer), m_write_visible_flag, m_file.is_true("xml_change_format")}));
|
||||
m_output_queue.push(osmium::thread::Pool::instance().submit(XMLOutputBlock{std::move(buffer), m_add_metadata, m_write_visible_flag, m_file.is_true("xml_change_format")}));
|
||||
}
|
||||
|
||||
void write_header(const osmium::io::Header& header) override final {
|
||||
@ -468,10 +477,15 @@ namespace osmium {
|
||||
|
||||
namespace {
|
||||
|
||||
// we want the register_output_format() function to run, setting the variable
|
||||
// is only a side-effect, it will never be used
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wunused-variable"
|
||||
const bool registered_xml_output = osmium::io::detail::OutputFormatFactory::instance().register_output_format(osmium::io::file_format::xml,
|
||||
[](const osmium::io::File& file, data_queue_type& output_queue) {
|
||||
return new osmium::io::detail::XMLOutputFormat(file, output_queue);
|
||||
});
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
|
@ -85,23 +85,24 @@ namespace osmium {
|
||||
*
|
||||
* @param input Compressed input data.
|
||||
* @param raw_size Size of uncompressed data.
|
||||
* @returns Uncompressed data.
|
||||
* @param output Uncompressed result data.
|
||||
* @returns Pointer and size to incompressed data.
|
||||
*/
|
||||
inline std::unique_ptr<std::string> zlib_uncompress(const std::string& input, unsigned long raw_size) {
|
||||
auto output = std::unique_ptr<std::string>(new std::string(raw_size, '\0'));
|
||||
inline std::pair<const char*, size_t> zlib_uncompress_string(const char* input, unsigned long input_size, unsigned long raw_size, std::string& output) {
|
||||
output.resize(raw_size);
|
||||
|
||||
auto result = ::uncompress(
|
||||
reinterpret_cast<unsigned char*>(const_cast<char *>(output->data())),
|
||||
reinterpret_cast<unsigned char*>(&*output.begin()),
|
||||
&raw_size,
|
||||
reinterpret_cast<const unsigned char*>(input.data()),
|
||||
osmium::static_cast_with_assert<unsigned long>(input.size())
|
||||
reinterpret_cast<const unsigned char*>(input),
|
||||
input_size
|
||||
);
|
||||
|
||||
if (result != Z_OK) {
|
||||
throw std::runtime_error(std::string("failed to uncompress data: ") + zError(result));
|
||||
}
|
||||
|
||||
return output;
|
||||
return std::make_pair(output.data(), output.size());
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
66
third_party/libosmium/include/osmium/io/file.hpp
vendored
66
third_party/libosmium/include/osmium/io/file.hpp
vendored
@ -97,7 +97,9 @@ namespace osmium {
|
||||
* of the file will be taken from the suffix.
|
||||
* An empty filename or "-" means stdin or stdout.
|
||||
* @param format File format as string. See the description of the
|
||||
* parse_format() function for details.
|
||||
* parse_format() function for details. If this is
|
||||
* empty the format will be deduced from the suffix
|
||||
* of the filename.
|
||||
*/
|
||||
explicit File(const std::string& filename = "", const std::string& format = "") :
|
||||
Options(),
|
||||
@ -107,20 +109,19 @@ namespace osmium {
|
||||
m_format_string(format) {
|
||||
|
||||
// stdin/stdout
|
||||
if (filename == "" || filename == "-") {
|
||||
if (m_filename == "-") {
|
||||
m_filename = "";
|
||||
default_settings_for_stdinout();
|
||||
}
|
||||
|
||||
// filename is actually a URL
|
||||
// if filename is a URL, default to XML format
|
||||
std::string protocol = m_filename.substr(0, m_filename.find_first_of(':'));
|
||||
if (protocol == "http" || protocol == "https") {
|
||||
default_settings_for_url();
|
||||
m_file_format = file_format::xml;
|
||||
}
|
||||
|
||||
if (format.empty()) {
|
||||
detect_format_from_suffix(m_filename);
|
||||
|
||||
if (format != "") {
|
||||
} else {
|
||||
parse_format(format);
|
||||
}
|
||||
}
|
||||
@ -140,9 +141,6 @@ namespace osmium {
|
||||
m_buffer(buffer),
|
||||
m_buffer_size(size),
|
||||
m_format_string(format) {
|
||||
|
||||
default_settings_for_stdinout();
|
||||
|
||||
if (format != "") {
|
||||
parse_format(format);
|
||||
}
|
||||
@ -220,6 +218,20 @@ namespace osmium {
|
||||
} else if (suffixes.back() == "opl") {
|
||||
m_file_format = file_format::opl;
|
||||
suffixes.pop_back();
|
||||
} else if (suffixes.back() == "json") {
|
||||
m_file_format = file_format::json;
|
||||
suffixes.pop_back();
|
||||
} else if (suffixes.back() == "o5m") {
|
||||
m_file_format = file_format::o5m;
|
||||
suffixes.pop_back();
|
||||
} else if (suffixes.back() == "o5c") {
|
||||
m_file_format = file_format::o5m;
|
||||
m_has_multiple_object_versions = true;
|
||||
set("o5c_change_format", true);
|
||||
suffixes.pop_back();
|
||||
} else if (suffixes.back() == "debug") {
|
||||
m_file_format = file_format::debug;
|
||||
suffixes.pop_back();
|
||||
}
|
||||
|
||||
if (suffixes.empty()) return;
|
||||
@ -240,8 +252,8 @@ namespace osmium {
|
||||
}
|
||||
|
||||
/**
|
||||
* Check file format etc. for consistency and throw exception if there
|
||||
* is a problem.
|
||||
* Check file format etc. for consistency and throw exception if
|
||||
* there is a problem.
|
||||
*
|
||||
* @throws std::runtime_error
|
||||
*/
|
||||
@ -265,36 +277,6 @@ namespace osmium {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set default settings for type and encoding when the filename is
|
||||
* empty or "-". If you want to have a different default setting
|
||||
* override this in a subclass.
|
||||
*/
|
||||
void default_settings_for_stdinout() {
|
||||
m_file_format = file_format::unknown;
|
||||
m_file_compression = file_compression::none;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set default settings for type and encoding when the filename is
|
||||
* a normal file. If you want to have a different default setting
|
||||
* override this in a subclass.
|
||||
*/
|
||||
void default_settings_for_file() {
|
||||
m_file_format = file_format::unknown;
|
||||
m_file_compression = file_compression::none;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set default settings for type and encoding when the filename is a URL.
|
||||
* If you want to have a different default setting override this in a
|
||||
* subclass.
|
||||
*/
|
||||
void default_settings_for_url() {
|
||||
m_file_format = file_format::xml;
|
||||
m_file_compression = file_compression::none;
|
||||
}
|
||||
|
||||
file_format format() const noexcept {
|
||||
return m_file_format;
|
||||
}
|
||||
|
@ -44,7 +44,9 @@ namespace osmium {
|
||||
xml = 1,
|
||||
pbf = 2,
|
||||
opl = 3,
|
||||
json = 4
|
||||
json = 4,
|
||||
o5m = 5,
|
||||
debug = 6
|
||||
};
|
||||
|
||||
// avoid g++ false positive
|
||||
@ -62,6 +64,10 @@ namespace osmium {
|
||||
return "OPL";
|
||||
case file_format::json:
|
||||
return "JSON";
|
||||
case file_format::o5m:
|
||||
return "O5M";
|
||||
case file_format::debug:
|
||||
return "DEBUG";
|
||||
}
|
||||
}
|
||||
#pragma GCC diagnostic pop
|
||||
|
@ -231,11 +231,16 @@ namespace osmium {
|
||||
|
||||
namespace {
|
||||
|
||||
// we want the register_compression() function to run, setting the variable
|
||||
// is only a side-effect, it will never be used
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wunused-variable"
|
||||
const bool registered_gzip_compression = osmium::io::CompressionFactory::instance().register_compression(osmium::io::file_compression::gzip,
|
||||
[](int fd) { return new osmium::io::GzipCompressor(fd); },
|
||||
[](int fd) { return new osmium::io::GzipDecompressor(fd); },
|
||||
[](const char* buffer, size_t size) { return new osmium::io::GzipBufferDecompressor(buffer, size); }
|
||||
);
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
|
@ -39,7 +39,6 @@ DEALINGS IN THE SOFTWARE.
|
||||
* Include this file if you want to read OSM PBF files.
|
||||
*
|
||||
* @attention If you include this file, you'll need to link with
|
||||
* `libprotobuf-lite`, `libosmpbf`, `ws2_32` (Windows only),
|
||||
* `libz`, and enable multithreading.
|
||||
*/
|
||||
|
||||
|
@ -39,7 +39,6 @@ DEALINGS IN THE SOFTWARE.
|
||||
* Include this file if you want to write OSM PBF files.
|
||||
*
|
||||
* @attention If you include this file, you'll need to link with
|
||||
* `libprotobuf-lite`, `libosmpbf`, `ws2_32` (Windows only),
|
||||
* `libz`, and enable multithreading.
|
||||
*/
|
||||
|
||||
|
@ -37,7 +37,6 @@ DEALINGS IN THE SOFTWARE.
|
||||
#include <cassert>
|
||||
#include <cstddef>
|
||||
#include <cstring>
|
||||
#include <exception>
|
||||
#include <functional>
|
||||
#include <iterator>
|
||||
#include <stdexcept>
|
||||
@ -83,7 +82,7 @@ namespace osmium {
|
||||
* Buffers exist in two flavours, those with external memory management and
|
||||
* those with internal memory management. If you already have some memory
|
||||
* with data in it (for instance read from disk), you create a Buffer with
|
||||
* external memory managment. It is your job then to free the memory once
|
||||
* external memory management. It is your job then to free the memory once
|
||||
* the buffer isn't used any more. If you don't have memory already, you can
|
||||
* create a Buffer object and have it manage the memory internally. It will
|
||||
* dynamically allocate memory and free it again after use.
|
||||
@ -413,6 +412,15 @@ namespace osmium {
|
||||
return iterator(m_data, m_data + m_committed);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
t_iterator<T> get_iterator(size_t offset) {
|
||||
return t_iterator<T>(m_data + offset, m_data + m_committed);
|
||||
}
|
||||
|
||||
iterator get_iterator(size_t offset) {
|
||||
return iterator(m_data + offset, m_data + m_committed);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
t_iterator<T> end() {
|
||||
return t_iterator<T>(m_data + m_committed, m_data + m_committed);
|
||||
@ -431,6 +439,15 @@ namespace osmium {
|
||||
return const_iterator(m_data, m_data + m_committed);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
t_const_iterator<T> get_iterator(size_t offset) const {
|
||||
return t_const_iterator<T>(m_data + offset, m_data + m_committed);
|
||||
}
|
||||
|
||||
const_iterator get_iterator(size_t offset) const {
|
||||
return const_iterator(m_data + offset, m_data + m_committed);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
t_const_iterator<T> cend() const {
|
||||
return t_const_iterator<T>(m_data + m_committed, m_data + m_committed);
|
||||
|
@ -38,7 +38,6 @@ DEALINGS IN THE SOFTWARE.
|
||||
#include <type_traits>
|
||||
|
||||
#include <osmium/memory/item.hpp>
|
||||
#include <osmium/util/compatibility.hpp>
|
||||
|
||||
namespace osmium {
|
||||
|
||||
|
@ -33,7 +33,6 @@ DEALINGS IN THE SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <type_traits>
|
||||
|
||||
|
@ -33,7 +33,6 @@ DEALINGS IN THE SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
|
||||
#include <osmium/memory/collection.hpp>
|
||||
@ -44,6 +43,7 @@ DEALINGS IN THE SOFTWARE.
|
||||
#include <osmium/osm/tag.hpp>
|
||||
#include <osmium/osm/timestamp.hpp>
|
||||
#include <osmium/osm/types.hpp>
|
||||
#include <osmium/osm/types_from_string.hpp>
|
||||
|
||||
namespace osmium {
|
||||
|
||||
|
223
third_party/libosmium/include/osmium/osm/crc.hpp
vendored
Normal file
223
third_party/libosmium/include/osmium/osm/crc.hpp
vendored
Normal file
@ -0,0 +1,223 @@
|
||||
#ifndef OSMIUM_OSM_CRC_HPP
|
||||
#define OSMIUM_OSM_CRC_HPP
|
||||
|
||||
/*
|
||||
|
||||
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||
|
||||
Copyright 2013-2015 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 <cstdint>
|
||||
|
||||
#include <osmium/osm/area.hpp>
|
||||
#include <osmium/osm/changeset.hpp>
|
||||
#include <osmium/osm/location.hpp>
|
||||
#include <osmium/osm/node.hpp>
|
||||
#include <osmium/osm/node_ref_list.hpp>
|
||||
#include <osmium/osm/relation.hpp>
|
||||
#include <osmium/osm/way.hpp>
|
||||
#include <osmium/util/endian.hpp>
|
||||
|
||||
namespace osmium {
|
||||
|
||||
template <class TCRC>
|
||||
class CRC {
|
||||
|
||||
static inline uint16_t byte_swap_16(uint16_t value) noexcept {
|
||||
# if defined(__GNUC__) || defined(__clang__)
|
||||
return __builtin_bswap16(value);
|
||||
# else
|
||||
return (value >> 8) | (value << 8);
|
||||
# endif
|
||||
}
|
||||
|
||||
static inline uint32_t byte_swap_32(uint32_t value) noexcept {
|
||||
# if defined(__GNUC__) || defined(__clang__)
|
||||
return __builtin_bswap32(value);
|
||||
# else
|
||||
return (value >> 24) |
|
||||
((value >> 8) & 0x0000FF00) |
|
||||
((value << 8) & 0x00FF0000) |
|
||||
(value << 24);
|
||||
# endif
|
||||
}
|
||||
|
||||
static inline uint64_t byte_swap_64(uint64_t value) noexcept {
|
||||
# if defined(__GNUC__) || defined(__clang__)
|
||||
return __builtin_bswap64(value);
|
||||
# else
|
||||
uint64_t val1 = byte_swap_32(value & 0xFFFFFFFF);
|
||||
uint64_t val2 = byte_swap_32(value >> 32);
|
||||
return (val1 << 32) & val2;
|
||||
# endif
|
||||
}
|
||||
|
||||
TCRC m_crc;
|
||||
|
||||
public:
|
||||
|
||||
TCRC& operator()() {
|
||||
return m_crc;
|
||||
}
|
||||
|
||||
const TCRC& operator()() const {
|
||||
return m_crc;
|
||||
}
|
||||
|
||||
void update_bool(bool value) {
|
||||
m_crc.process_byte(value);
|
||||
}
|
||||
|
||||
void update_int8(uint8_t value) {
|
||||
m_crc.process_byte(value);
|
||||
}
|
||||
|
||||
void update_int16(uint16_t value) {
|
||||
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
||||
m_crc.process_bytes(&value, sizeof(uint16_t));
|
||||
#else
|
||||
uint16_t v = byte_swap_16(value);
|
||||
m_crc.process_bytes(&v, sizeof(uint16_t));
|
||||
#endif
|
||||
}
|
||||
|
||||
void update_int32(uint32_t value) {
|
||||
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
||||
m_crc.process_bytes(&value, sizeof(uint32_t));
|
||||
#else
|
||||
uint32_t v = byte_swap_32(value);
|
||||
m_crc.process_bytes(&v, sizeof(uint32_t));
|
||||
#endif
|
||||
}
|
||||
|
||||
void update_int64(uint64_t value) {
|
||||
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
||||
m_crc.process_bytes(&value, sizeof(uint64_t));
|
||||
#else
|
||||
uint64_t v = byte_swap_64(value);
|
||||
m_crc.process_bytes(&v, sizeof(uint64_t));
|
||||
#endif
|
||||
}
|
||||
|
||||
void update_string(const char* str) {
|
||||
while (*str) {
|
||||
m_crc.process_byte(*str++);
|
||||
}
|
||||
}
|
||||
|
||||
void update(const Timestamp& timestamp) {
|
||||
update_int32(uint32_t(timestamp));
|
||||
}
|
||||
|
||||
void update(const osmium::Location& location) {
|
||||
update_int32(location.x());
|
||||
update_int32(location.y());
|
||||
}
|
||||
|
||||
void update(const osmium::Box& box) {
|
||||
update(box.bottom_left());
|
||||
update(box.top_right());
|
||||
}
|
||||
|
||||
void update(const NodeRef& node_ref) {
|
||||
update_int64(node_ref.ref());
|
||||
}
|
||||
|
||||
void update(const NodeRefList& node_refs) {
|
||||
for (const NodeRef& node_ref : node_refs) {
|
||||
update(node_ref);
|
||||
}
|
||||
}
|
||||
|
||||
void update(const TagList& tags) {
|
||||
m_crc.process_bytes(tags.data(), tags.byte_size());
|
||||
}
|
||||
|
||||
void update(const osmium::RelationMember& member) {
|
||||
update_int64(member.ref());
|
||||
update_int16(uint16_t(member.type()));
|
||||
update_string(member.role());
|
||||
}
|
||||
|
||||
void update(const osmium::RelationMemberList& members) {
|
||||
for (const RelationMember& member : members) {
|
||||
update(member);
|
||||
}
|
||||
}
|
||||
|
||||
void update(const osmium::OSMObject& object) {
|
||||
update_int64(object.id());
|
||||
update_bool(object.visible());
|
||||
update_int32(object.version());
|
||||
update(object.timestamp());
|
||||
update_int32(object.uid());
|
||||
update_string(object.user());
|
||||
update(object.tags());
|
||||
}
|
||||
|
||||
void update(const osmium::Node& node) {
|
||||
update(static_cast<const osmium::OSMObject&>(node));
|
||||
update(node.location());
|
||||
}
|
||||
|
||||
void update(const osmium::Way& way) {
|
||||
update(static_cast<const osmium::OSMObject&>(way));
|
||||
update(way.nodes());
|
||||
}
|
||||
|
||||
void update(const osmium::Relation& relation) {
|
||||
update(static_cast<const osmium::OSMObject&>(relation));
|
||||
update(relation.members());
|
||||
}
|
||||
|
||||
void update(const osmium::Area& area) {
|
||||
update(static_cast<const osmium::OSMObject&>(area));
|
||||
for (auto it = area.cbegin(); it != area.cend(); ++it) {
|
||||
if (it->type() == osmium::item_type::outer_ring ||
|
||||
it->type() == osmium::item_type::inner_ring) {
|
||||
update(static_cast<const osmium::NodeRefList&>(*it));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void update(const osmium::Changeset& changeset) {
|
||||
update_int64(changeset.id());
|
||||
update(changeset.created_at());
|
||||
update(changeset.closed_at());
|
||||
update(changeset.bounds());
|
||||
update_int32(changeset.num_changes());
|
||||
update_int32(changeset.uid());
|
||||
update_string(changeset.user());
|
||||
}
|
||||
|
||||
}; // class CRC
|
||||
|
||||
} // namespace osmium
|
||||
|
||||
#endif // OSMIUM_OSM_CRC
|
@ -112,8 +112,35 @@ namespace osmium {
|
||||
return m_curr->timestamp();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the timestamp when the current version of the object is
|
||||
* not valid any more, ie the time when the next version of the object
|
||||
* is valid. If this is the last version of the object, this will
|
||||
* return a special "end of time" timestamp that is guaranteed to
|
||||
* be larger than any normal timestamp.
|
||||
*/
|
||||
const osmium::Timestamp end_time() const noexcept {
|
||||
return last() ? osmium::Timestamp() : m_next->timestamp();
|
||||
return last() ? osmium::end_of_time() : m_next->timestamp();
|
||||
}
|
||||
|
||||
/**
|
||||
* Current object version is valid between time "from" (inclusive) and
|
||||
* time "to" (not inclusive).
|
||||
*
|
||||
* This is a bit more complex than you'd think, because we have to
|
||||
* handle the case properly where the start_time() == end_time().
|
||||
*/
|
||||
bool is_between(const osmium::Timestamp& from, const osmium::Timestamp& to) const noexcept {
|
||||
return start_time() < to &&
|
||||
((start_time() != end_time() && end_time() > from) ||
|
||||
(start_time() == end_time() && end_time() >= from));
|
||||
}
|
||||
|
||||
/**
|
||||
* Current object version is visible at the given timestamp.
|
||||
*/
|
||||
bool is_visible_at(const osmium::Timestamp& timestamp) const noexcept {
|
||||
return start_time() <= timestamp && end_time() > timestamp && m_curr->visible();
|
||||
}
|
||||
|
||||
}; // class DiffObject
|
||||
|
@ -35,6 +35,7 @@ DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#include <osmium/memory/item.hpp>
|
||||
#include <osmium/osm/entity_bits.hpp>
|
||||
#include <osmium/osm/item_type.hpp>
|
||||
|
||||
namespace osmium {
|
||||
|
||||
|
@ -33,6 +33,7 @@ DEALINGS IN THE SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
#include <cassert>
|
||||
#include <cstdint> // IWYU pragma: keep
|
||||
#include <iosfwd>
|
||||
#include <stdexcept>
|
||||
@ -56,6 +57,25 @@ namespace osmium {
|
||||
|
||||
}; // enum class item_type
|
||||
|
||||
/**
|
||||
* Return item_type for index:
|
||||
* 0 -> node, 1 -> way, 2 -> relation
|
||||
*/
|
||||
inline item_type nwr_index_to_item_type(unsigned int i) noexcept {
|
||||
assert(i <= 2);
|
||||
return item_type(i+1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return index for item_type:
|
||||
* node -> 0, way -> 1, relation -> 2
|
||||
*/
|
||||
inline unsigned int item_type_to_nwr_index(item_type type) noexcept {
|
||||
unsigned int i = static_cast<unsigned int>(type);
|
||||
assert(i >= 1 && i <= 3);
|
||||
return i - 1;
|
||||
}
|
||||
|
||||
inline item_type char_to_item_type(const char c) noexcept {
|
||||
switch (c) {
|
||||
case 'X':
|
||||
|
@ -33,11 +33,11 @@ DEALINGS IN THE SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstdlib>
|
||||
#include <iosfwd>
|
||||
|
||||
#include <osmium/memory/item.hpp>
|
||||
#include <osmium/osm/item_type.hpp>
|
||||
#include <osmium/osm/location.hpp>
|
||||
#include <osmium/osm/types.hpp>
|
||||
|
||||
|
@ -48,6 +48,7 @@ DEALINGS IN THE SOFTWARE.
|
||||
#include <osmium/osm/tag.hpp>
|
||||
#include <osmium/osm/timestamp.hpp>
|
||||
#include <osmium/osm/types.hpp>
|
||||
#include <osmium/osm/types_from_string.hpp>
|
||||
|
||||
namespace osmium {
|
||||
|
||||
|
@ -120,6 +120,11 @@ namespace osmium {
|
||||
return static_cast<unsigned_object_id_type>(std::abs(m_ref));
|
||||
}
|
||||
|
||||
RelationMember& set_ref(const osmium::object_id_type ref) noexcept {
|
||||
m_ref = ref;
|
||||
return *this;
|
||||
}
|
||||
|
||||
item_type type() const noexcept {
|
||||
return m_type;
|
||||
}
|
||||
|
@ -39,9 +39,9 @@ DEALINGS IN THE SOFTWARE.
|
||||
#include <limits>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <time.h>
|
||||
|
||||
#include <osmium/util/compatibility.hpp>
|
||||
#include <osmium/util/minmax.hpp> // IWYU pragma: keep
|
||||
|
||||
namespace osmium {
|
||||
|
||||
@ -170,6 +170,16 @@ namespace osmium {
|
||||
return out;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline osmium::Timestamp min_op_start_value<osmium::Timestamp>() {
|
||||
return end_of_time();
|
||||
}
|
||||
|
||||
template <>
|
||||
inline osmium::Timestamp max_op_start_value<osmium::Timestamp>() {
|
||||
return start_of_time();
|
||||
}
|
||||
|
||||
} // namespace osmium
|
||||
|
||||
#endif // OSMIUM_OSM_TIMESTAMP_HPP
|
||||
|
@ -34,7 +34,6 @@ DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstdlib>
|
||||
|
||||
namespace osmium {
|
||||
|
||||
@ -58,26 +57,6 @@ namespace osmium {
|
||||
*/
|
||||
typedef uint16_t string_size_type;
|
||||
|
||||
inline object_id_type string_to_object_id(const char* string) {
|
||||
return std::atoll(string);
|
||||
}
|
||||
|
||||
inline object_version_type string_to_object_version(const char* string) {
|
||||
return static_cast<object_version_type>(std::atol(string));
|
||||
}
|
||||
|
||||
inline changeset_id_type string_to_changeset_id(const char* string) {
|
||||
return static_cast<changeset_id_type>(std::atol(string));
|
||||
}
|
||||
|
||||
inline signed_user_id_type string_to_user_id(const char* string) {
|
||||
return static_cast<signed_user_id_type>(std::atol(string));
|
||||
}
|
||||
|
||||
inline num_changes_type string_to_num_changes(const char* string) {
|
||||
return static_cast<num_changes_type>(std::atol(string));
|
||||
}
|
||||
|
||||
} // namespace osmium
|
||||
|
||||
#endif // OSMIUM_OSM_TYPES_HPP
|
||||
|
116
third_party/libosmium/include/osmium/osm/types_from_string.hpp
vendored
Normal file
116
third_party/libosmium/include/osmium/osm/types_from_string.hpp
vendored
Normal file
@ -0,0 +1,116 @@
|
||||
#ifndef OSMIUM_OSM_TYPES_FROM_STRING_HPP
|
||||
#define OSMIUM_OSM_TYPES_FROM_STRING_HPP
|
||||
|
||||
/*
|
||||
|
||||
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||
|
||||
Copyright 2013-2015 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 <cassert>
|
||||
#include <cctype>
|
||||
#include <cstdint>
|
||||
#include <cstdlib>
|
||||
#include <limits>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
#include <osmium/osm/entity_bits.hpp>
|
||||
#include <osmium/osm/types.hpp>
|
||||
|
||||
namespace osmium {
|
||||
|
||||
inline object_id_type string_to_object_id(const char* input) {
|
||||
assert(input);
|
||||
if (*input != '\0' && !std::isspace(*input)) {
|
||||
char* end;
|
||||
auto id = std::strtoll(input, &end, 10);
|
||||
if (id != std::numeric_limits<long long>::min() && id != std::numeric_limits<long long>::max() && *end == '\0') {
|
||||
return id;
|
||||
}
|
||||
}
|
||||
throw std::range_error(std::string("illegal id: '") + input + "'");
|
||||
}
|
||||
|
||||
inline std::pair<osmium::item_type, osmium::object_id_type> string_to_object_id(const char* input, osmium::osm_entity_bits::type types) {
|
||||
assert(input);
|
||||
assert(types != osmium::osm_entity_bits::nothing);
|
||||
if (*input != '\0') {
|
||||
if (std::isdigit(*input)) {
|
||||
return std::make_pair(osmium::item_type::undefined, string_to_object_id(input));
|
||||
}
|
||||
osmium::item_type t = osmium::char_to_item_type(*input);
|
||||
if (osmium::osm_entity_bits::from_item_type(t) & types) {
|
||||
return std::make_pair(t, string_to_object_id(input+1));
|
||||
}
|
||||
}
|
||||
throw std::range_error(std::string("not a valid id: '") + input + "'");
|
||||
}
|
||||
|
||||
namespace detail {
|
||||
|
||||
inline long string_to_ulong(const char* input, const char *name) {
|
||||
if (*input != '\0' && *input != '-' && !std::isspace(*input)) {
|
||||
char* end;
|
||||
auto value = std::strtoul(input, &end, 10);
|
||||
if (value != std::numeric_limits<unsigned long>::max() && *end == '\0') {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
throw std::range_error(std::string("illegal ") + name + ": '" + input + "'");
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
inline object_version_type string_to_object_version(const char* input) {
|
||||
assert(input);
|
||||
return static_cast<object_version_type>(detail::string_to_ulong(input, "version"));
|
||||
}
|
||||
|
||||
inline changeset_id_type string_to_changeset_id(const char* input) {
|
||||
assert(input);
|
||||
return static_cast<changeset_id_type>(detail::string_to_ulong(input, "changeset"));
|
||||
}
|
||||
|
||||
inline signed_user_id_type string_to_user_id(const char* input) {
|
||||
assert(input);
|
||||
if (input[0] == '-' && input[1] == '1' && input[2] == '\0') {
|
||||
return -1;
|
||||
}
|
||||
return static_cast<signed_user_id_type>(detail::string_to_ulong(input, "user id"));
|
||||
}
|
||||
|
||||
inline num_changes_type string_to_num_changes(const char* input) {
|
||||
assert(input);
|
||||
return static_cast<num_changes_type>(detail::string_to_ulong(input, "value for num changes"));
|
||||
}
|
||||
|
||||
} // namespace osmium
|
||||
|
||||
#endif // OSMIUM_OSM_TYPES_FROM_STRING_HPP
|
@ -512,7 +512,7 @@ namespace osmium {
|
||||
double percent = static_cast<double>(size_before - size_after);
|
||||
percent /= size_before;
|
||||
percent *= 100;
|
||||
std::cerr << "PURGE (size before=" << size_before << " after=" << size_after << " purged=" << (size_before - size_after) << " / " << static_cast<int>(percent) << "%)\n";
|
||||
// std::cerr << "PURGE (size before=" << size_before << " after=" << size_after << " purged=" << (size_before - size_after) << " / " << static_cast<int>(percent) << "%)\n";
|
||||
m_count_complete = 0;
|
||||
}
|
||||
}
|
||||
|
@ -149,6 +149,7 @@ namespace osmium {
|
||||
|
||||
~Pool() {
|
||||
m_done = true;
|
||||
m_work_queue.shutdown();
|
||||
}
|
||||
|
||||
size_t queue_size() const {
|
||||
|
@ -41,9 +41,7 @@ DEALINGS IN THE SOFTWARE.
|
||||
#include <queue>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
#include <utility>
|
||||
|
||||
#include <osmium/util/compatibility.hpp>
|
||||
#include <utility> // IWYU pragma: keep (for std::move)
|
||||
|
||||
namespace osmium {
|
||||
|
||||
@ -71,6 +69,8 @@ namespace osmium {
|
||||
/// Used to signal readers when data is available in the queue.
|
||||
std::condition_variable m_data_available;
|
||||
|
||||
std::atomic<bool> m_done;
|
||||
|
||||
#ifdef OSMIUM_DEBUG_QUEUE_SIZE
|
||||
/// The largest size the queue has been so far.
|
||||
size_t m_largest_size;
|
||||
@ -94,7 +94,8 @@ namespace osmium {
|
||||
m_name(name),
|
||||
m_mutex(),
|
||||
m_queue(),
|
||||
m_data_available()
|
||||
m_data_available(),
|
||||
m_done(false)
|
||||
#ifdef OSMIUM_DEBUG_QUEUE_SIZE
|
||||
,
|
||||
m_largest_size(0),
|
||||
@ -104,6 +105,7 @@ namespace osmium {
|
||||
}
|
||||
|
||||
~Queue() {
|
||||
shutdown();
|
||||
#ifdef OSMIUM_DEBUG_QUEUE_SIZE
|
||||
std::cerr << "queue '" << m_name << "' with max_size=" << m_max_size << " had largest size " << m_largest_size << " and was full " << m_full_counter << " times\n";
|
||||
#endif
|
||||
@ -132,25 +134,34 @@ namespace osmium {
|
||||
m_data_available.notify_one();
|
||||
}
|
||||
|
||||
void shutdown() {
|
||||
m_done = true;
|
||||
m_data_available.notify_all();
|
||||
}
|
||||
|
||||
void wait_and_pop(T& value) {
|
||||
std::unique_lock<std::mutex> lock(m_mutex);
|
||||
m_data_available.wait(lock, [this] {
|
||||
return !m_queue.empty();
|
||||
return !m_queue.empty() || m_done;
|
||||
});
|
||||
if (!m_queue.empty()) {
|
||||
value = std::move(m_queue.front());
|
||||
m_queue.pop();
|
||||
}
|
||||
}
|
||||
|
||||
void wait_and_pop_with_timeout(T& value) {
|
||||
std::unique_lock<std::mutex> lock(m_mutex);
|
||||
if (!m_data_available.wait_for(lock, std::chrono::seconds(1), [this] {
|
||||
return !m_queue.empty();
|
||||
return !m_queue.empty() || m_done;
|
||||
})) {
|
||||
return;
|
||||
}
|
||||
if (!m_queue.empty()) {
|
||||
value = std::move(m_queue.front());
|
||||
m_queue.pop();
|
||||
}
|
||||
}
|
||||
|
||||
bool try_pop(T& value) {
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
|
@ -58,7 +58,7 @@ namespace osmium {
|
||||
|
||||
/**
|
||||
* Wait until the given future becomes ready. Will block if the future
|
||||
* is not ready. Can be called more than once unless future.get().
|
||||
* is not ready. Can be called more than once unlike future.get().
|
||||
*/
|
||||
template <class T>
|
||||
inline void wait_until_done(std::future<T>& future) {
|
||||
|
194
third_party/libosmium/include/osmium/util/data_file.hpp
vendored
Normal file
194
third_party/libosmium/include/osmium/util/data_file.hpp
vendored
Normal file
@ -0,0 +1,194 @@
|
||||
#ifndef OSMIUM_UTIL_DATA_FILE_HPP
|
||||
#define OSMIUM_UTIL_DATA_FILE_HPP
|
||||
|
||||
/*
|
||||
|
||||
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||
|
||||
Copyright 2013-2015 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 <cerrno>
|
||||
#include <cstddef>
|
||||
#include <cstdio>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <system_error>
|
||||
|
||||
#ifdef _WIN32
|
||||
# include <io.h>
|
||||
# include <windows.h>
|
||||
#endif
|
||||
|
||||
#include <osmium/util/file.hpp>
|
||||
|
||||
namespace osmium {
|
||||
|
||||
namespace util {
|
||||
|
||||
/**
|
||||
* Class wrapper for convenient access to some low-level file
|
||||
* functions.
|
||||
*/
|
||||
class DataFile {
|
||||
|
||||
FILE* m_file;
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Create and open a temporary file. It is removed after opening.
|
||||
*
|
||||
* @throws std::system_error if something went wrong.
|
||||
*/
|
||||
DataFile() :
|
||||
m_file(::tmpfile()) {
|
||||
if (!m_file) {
|
||||
throw std::system_error(errno, std::system_category(), "tmpfile failed");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create and open a temporary file with the specified size. It
|
||||
* is removed after opening.
|
||||
*
|
||||
* @throws std::system_error if something went wrong.
|
||||
*/
|
||||
explicit DataFile(size_t size) :
|
||||
DataFile() {
|
||||
grow(size);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create and open a named file.
|
||||
*
|
||||
* @param filename the name of the file
|
||||
* @param writable should the file be writable?
|
||||
* @throws std::system_error if something went wrong.
|
||||
*/
|
||||
DataFile(const char* filename, bool writable) :
|
||||
m_file(::fopen(filename, writable ? "wb+" : "rb" )) {
|
||||
if (!m_file) {
|
||||
throw std::system_error(errno, std::system_category(), "fopen failed");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create and open a named file.
|
||||
*
|
||||
* @param filename the name of the file
|
||||
* @param writable should the file be writable?
|
||||
* @throws std::system_error if something went wrong.
|
||||
*/
|
||||
DataFile(const std::string& filename, bool writable) :
|
||||
DataFile(filename.c_str(), writable) {
|
||||
}
|
||||
|
||||
/**
|
||||
* In boolean context the DataFile class returns true if the file
|
||||
* is open.
|
||||
*/
|
||||
operator bool() const noexcept {
|
||||
return m_file != nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Close the file.
|
||||
*
|
||||
* Does nothing if the file is already closed.
|
||||
*
|
||||
* @throws std::system_error if file could not be closed
|
||||
*/
|
||||
void close() {
|
||||
if (m_file) {
|
||||
if (::fclose(m_file) != 0) {
|
||||
throw std::system_error(errno, std::system_category(), "fclose failed");
|
||||
}
|
||||
m_file = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
~DataFile() noexcept {
|
||||
try {
|
||||
close();
|
||||
} catch (std::system_error&) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get file descriptor of underlying file.
|
||||
*
|
||||
* @throws std::runtime_errro if file is not open
|
||||
* @throws std::system_error if fileno(3) call failed
|
||||
*/
|
||||
int fd() const {
|
||||
if (!m_file) {
|
||||
throw std::runtime_error("no open file");
|
||||
}
|
||||
|
||||
int fd = ::fileno(m_file);
|
||||
|
||||
if (fd == -1) {
|
||||
throw std::system_error(errno, std::system_category(), "fileno failed");
|
||||
}
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ask the operating system for the size of this file.
|
||||
*
|
||||
* @throws std::system_error if fstat(2) call failed
|
||||
*/
|
||||
size_t size() const {
|
||||
return osmium::util::file_size(fd());
|
||||
}
|
||||
|
||||
/**
|
||||
* Grow file to given size.
|
||||
*
|
||||
* If the file is large enough already, nothing is done.
|
||||
* The file is never shrunk.
|
||||
*
|
||||
* @throws std::system_error if ftruncate(2) call failed
|
||||
*/
|
||||
void grow(size_t new_size) const {
|
||||
if (size() < new_size) {
|
||||
osmium::util::resize_file(fd(), new_size);
|
||||
}
|
||||
}
|
||||
|
||||
}; // class DataFile
|
||||
|
||||
} // namespace util
|
||||
|
||||
} // namespace osmium
|
||||
|
||||
|
||||
#endif // OSMIUM_UTIL_DATA_FILE_HPP
|
147
third_party/libosmium/include/osmium/util/delta.hpp
vendored
Normal file
147
third_party/libosmium/include/osmium/util/delta.hpp
vendored
Normal file
@ -0,0 +1,147 @@
|
||||
#ifndef OSMIUM_UTIL_DELTA_HPP
|
||||
#define OSMIUM_UTIL_DELTA_HPP
|
||||
|
||||
/*
|
||||
|
||||
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||
|
||||
Copyright 2013-2015 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 <iterator>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
namespace osmium {
|
||||
|
||||
namespace util {
|
||||
|
||||
/**
|
||||
* Helper class for delta encoding.
|
||||
*/
|
||||
template <typename T>
|
||||
class DeltaEncode {
|
||||
|
||||
T m_value;
|
||||
|
||||
public:
|
||||
|
||||
DeltaEncode(T value = 0) :
|
||||
m_value(value) {
|
||||
}
|
||||
|
||||
void clear() {
|
||||
m_value = 0;
|
||||
}
|
||||
|
||||
T update(T new_value) {
|
||||
using std::swap;
|
||||
swap(m_value, new_value);
|
||||
return m_value - new_value;
|
||||
}
|
||||
|
||||
}; // class DeltaEncode
|
||||
|
||||
/**
|
||||
* Helper class for delta decoding.
|
||||
*/
|
||||
template <typename T>
|
||||
class DeltaDecode {
|
||||
|
||||
T m_value;
|
||||
|
||||
public:
|
||||
|
||||
DeltaDecode() :
|
||||
m_value(0) {
|
||||
}
|
||||
|
||||
void clear() {
|
||||
m_value = 0;
|
||||
}
|
||||
|
||||
T update(T delta) {
|
||||
m_value += delta;
|
||||
return m_value;
|
||||
}
|
||||
|
||||
}; // class DeltaDecode
|
||||
|
||||
template <typename TBaseIterator, typename TTransform, typename TValue>
|
||||
class DeltaEncodeIterator : public std::iterator<std::input_iterator_tag, TValue> {
|
||||
|
||||
typedef TValue value_type;
|
||||
|
||||
TBaseIterator m_it;
|
||||
TBaseIterator m_end;
|
||||
value_type m_delta;
|
||||
DeltaEncode<value_type> m_value;
|
||||
TTransform m_trans;
|
||||
|
||||
public:
|
||||
|
||||
DeltaEncodeIterator(TBaseIterator first, TBaseIterator last, TTransform& trans) :
|
||||
m_it(first),
|
||||
m_end(last),
|
||||
m_delta(m_trans(m_it)),
|
||||
m_value(m_delta),
|
||||
m_trans(trans) {
|
||||
}
|
||||
|
||||
DeltaEncodeIterator& operator++() {
|
||||
if (m_it != m_end) {
|
||||
m_delta = m_value.update(m_trans(++m_it));
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
DeltaEncodeIterator operator++(int) {
|
||||
DeltaEncodeIterator tmp(*this);
|
||||
operator++();
|
||||
return tmp;
|
||||
}
|
||||
|
||||
value_type operator*() {
|
||||
return m_delta;
|
||||
}
|
||||
|
||||
bool operator==(const DeltaEncodeIterator& rhs) const {
|
||||
return m_it == rhs.m_it && m_end == rhs.m_end;
|
||||
}
|
||||
|
||||
bool operator!=(const DeltaEncodeIterator& rhs) const {
|
||||
return !(*this == rhs);
|
||||
}
|
||||
|
||||
}; // class DeltaEncodeIterator
|
||||
|
||||
} // namespace util
|
||||
|
||||
} // namespace osmium
|
||||
|
||||
#endif // OSMIUM_UTIL_DELTA_HPP
|
45
third_party/libosmium/include/osmium/util/endian.hpp
vendored
Normal file
45
third_party/libosmium/include/osmium/util/endian.hpp
vendored
Normal file
@ -0,0 +1,45 @@
|
||||
#ifndef OSMIUM_UTIL_ENDIAN_HPP
|
||||
#define OSMIUM_UTIL_ENDIAN_HPP
|
||||
|
||||
/*
|
||||
|
||||
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||
|
||||
Copyright 2013-2015 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.
|
||||
|
||||
*/
|
||||
|
||||
// Windows is only available for little endian architectures
|
||||
// http://stackoverflow.com/questions/6449468/can-i-safely-assume-that-windows-installations-will-always-be-little-endian
|
||||
#if !defined(_WIN32) && !defined(__APPLE__)
|
||||
# include <endian.h>
|
||||
#else
|
||||
# define __LITTLE_ENDIAN 1234
|
||||
# define __BYTE_ORDER __LITTLE_ENDIAN
|
||||
#endif
|
||||
|
||||
#endif // OSMIUM_UTIL_ENDIAN_HPP
|
119
third_party/libosmium/include/osmium/util/file.hpp
vendored
Normal file
119
third_party/libosmium/include/osmium/util/file.hpp
vendored
Normal file
@ -0,0 +1,119 @@
|
||||
#ifndef OSMIUM_UTIL_FILE_HPP
|
||||
#define OSMIUM_UTIL_FILE_HPP
|
||||
|
||||
/*
|
||||
|
||||
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||
|
||||
Copyright 2013-2015 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 <cerrno>
|
||||
#include <cstddef>
|
||||
#include <cstdio>
|
||||
#include <system_error>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
# include <io.h>
|
||||
# include <windows.h>
|
||||
#endif
|
||||
|
||||
#ifndef _MSC_VER
|
||||
# include <unistd.h>
|
||||
#else
|
||||
// https://msdn.microsoft.com/en-us/library/whx354w1.aspx
|
||||
# define ftruncate _chsize_s
|
||||
#endif
|
||||
|
||||
namespace osmium {
|
||||
|
||||
namespace util {
|
||||
|
||||
/**
|
||||
* Get file size.
|
||||
* This is a small wrapper around a system call.
|
||||
*
|
||||
* @param fd File descriptor
|
||||
* @returns file size
|
||||
* @throws std::system_error If system call failed
|
||||
*/
|
||||
inline size_t file_size(int fd) {
|
||||
#ifdef _MSC_VER
|
||||
// Windows implementation
|
||||
// https://msdn.microsoft.com/en-us/library/dfbc2kec.aspx
|
||||
auto size = ::_filelengthi64(fd);
|
||||
if (size == -1L) {
|
||||
throw std::system_error(errno, std::system_category(), "_filelengthi64 failed");
|
||||
}
|
||||
return size_t(size);
|
||||
#else
|
||||
// Unix implementation
|
||||
struct stat s;
|
||||
if (::fstat(fd, &s) != 0) {
|
||||
throw std::system_error(errno, std::system_category(), "fstat failed");
|
||||
}
|
||||
return size_t(s.st_size);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Resize file.
|
||||
* Small wrapper around ftruncate(2) system call.
|
||||
*
|
||||
* @param fd File descriptor
|
||||
* @param new_size New size
|
||||
* @throws std::system_error If ftruncate(2) call failed
|
||||
*/
|
||||
inline void resize_file(int fd, size_t new_size) {
|
||||
if (::ftruncate(fd, new_size) != 0) {
|
||||
throw std::system_error(errno, std::system_category(), "ftruncate failed");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the page size for this system.
|
||||
*/
|
||||
inline size_t get_pagesize() {
|
||||
#ifdef _WIN32
|
||||
// Windows implementation
|
||||
SYSTEM_INFO si;
|
||||
GetSystemInfo(&si);
|
||||
return si.dwPageSize;
|
||||
#else
|
||||
// Unix implementation
|
||||
return ::sysconf(_SC_PAGESIZE);
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace util
|
||||
|
||||
} // namespace osmium
|
||||
|
||||
#endif // OSMIUM_UTIL_FILE_HPP
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user