Merge pull request #3296 from Project-OSRM/libosmium-2.10.0
Osmium 2.10
This commit is contained in:
commit
5a293e891b
@ -10,7 +10,7 @@ set -o nounset
|
|||||||
# http://git.661346.n2.nabble.com/subtree-merges-lose-prefix-after-rebase-td7332850.html
|
# http://git.661346.n2.nabble.com/subtree-merges-lose-prefix-after-rebase-td7332850.html
|
||||||
|
|
||||||
OSMIUM_REPO=https://github.com/osmcode/libosmium.git
|
OSMIUM_REPO=https://github.com/osmcode/libosmium.git
|
||||||
OSMIUM_TAG=v2.9.0
|
OSMIUM_TAG=v2.10.0
|
||||||
|
|
||||||
VARIANT_REPO=https://github.com/mapbox/variant.git
|
VARIANT_REPO=https://github.com/mapbox/variant.git
|
||||||
VARIANT_TAG=v1.1.0
|
VARIANT_TAG=v1.1.0
|
||||||
|
@ -127,7 +127,7 @@ int Extractor::run(ScriptingEnvironment &scripting_environment)
|
|||||||
auto extractor_callbacks = std::make_unique<ExtractorCallbacks>(extraction_containers);
|
auto extractor_callbacks = std::make_unique<ExtractorCallbacks>(extraction_containers);
|
||||||
|
|
||||||
const osmium::io::File input_file(config.input_path.string());
|
const osmium::io::File input_file(config.input_path.string());
|
||||||
osmium::io::Reader reader(input_file);
|
osmium::io::Reader reader(input_file, osmium::io::read_meta::no);
|
||||||
const osmium::io::Header header = reader.header();
|
const osmium::io::Header header = reader.header();
|
||||||
|
|
||||||
unsigned number_of_nodes = 0;
|
unsigned number_of_nodes = 0;
|
||||||
|
58
third_party/libosmium/CHANGELOG.md
vendored
58
third_party/libosmium/CHANGELOG.md
vendored
@ -13,6 +13,53 @@ This project adheres to [Semantic Versioning](http://semver.org/).
|
|||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
|
|
||||||
|
## [2.10.0] - 2016-11-11
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- The `Reader` can take an additional optional `read_meta` flag. If this is
|
||||||
|
set to false the PBF input will ignore metadata on OSM objects (like version,
|
||||||
|
timestamp, uid, ...) which speeds up file reading by 10 to 20%.
|
||||||
|
- New `IdSet` virtual class with two implementations: `IdSetDense` and
|
||||||
|
`IdSetSmall`. Used to efficiently store a set of Ids. This is often needed
|
||||||
|
to track, for instance, which nodes are needed for ways, etc.
|
||||||
|
- Added more examples and better documented existing examples.
|
||||||
|
- Add a benchmark "mercator" converting all node locations in a file to
|
||||||
|
WebMercator and creating geometries in WKB format.
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Better queue handling makes I/O faster in some circumstances.
|
||||||
|
- The `FindOsmium.cmake` CMake script can now check a current enough libosmium
|
||||||
|
version is found.
|
||||||
|
- Builders can now be constructed with a reference to parent builder.
|
||||||
|
- Made builders more robust by adding asserts that will catch common usage
|
||||||
|
problems.
|
||||||
|
- Calling `OSMObjectBuilder::add_user()` is now optional, and the method was
|
||||||
|
renamed to `set_user()`. (`add_user()` is marked as deprecated.)
|
||||||
|
- Benchmarks now show compiler and compiler options used.
|
||||||
|
- `Builder::add_item()` now takes a reference instead of pointer (old version
|
||||||
|
of the function marked as deprecated).
|
||||||
|
- GEOS support is deprecated. It does not work any more for GEOS 3.6 or newer.
|
||||||
|
Reason is the changed interface in GEOS 3.6. If there is interest for the
|
||||||
|
GEOS support, we can add support back in later (but probably using the
|
||||||
|
GEOS C API which is more stable than the C++ API). Some tests using GEOS
|
||||||
|
were rewritten to work without it.
|
||||||
|
- The `BoolVector` has been deprecated in favour of the new `IdSet` classes.
|
||||||
|
- Lots of code cleanups and improved API documentation in many places.
|
||||||
|
- The relations collector can now tell you whether a relation member was in
|
||||||
|
the input data. See the new `is_available()` and
|
||||||
|
`get_availability_and_offset()` methods.
|
||||||
|
- Updated embedded Catch unit test header to version 1.5.8.
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- Parsing of coordinates starting with decimal dot and coordinates in
|
||||||
|
scientific notation.
|
||||||
|
- `~` operator for `entity_bits` doesn't set unused bits any more.
|
||||||
|
- Progress bar can now be (temporarily) removed, to allow other output.
|
||||||
|
|
||||||
|
|
||||||
## [2.9.0] - 2016-09-15
|
## [2.9.0] - 2016-09-15
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
@ -110,7 +157,7 @@ This project adheres to [Semantic Versioning](http://semver.org/).
|
|||||||
- New functions for iterating over specific item types in buffers
|
- New functions for iterating over specific item types in buffers
|
||||||
(`osmium::memory::Buffer::select()`), over specific subitems
|
(`osmium::memory::Buffer::select()`), over specific subitems
|
||||||
(`osmium::OSMObject::subitems()`), and for iterating over all rings of
|
(`osmium::OSMObject::subitems()`), and for iterating over all rings of
|
||||||
an area (`osmium::Areas::outer_rings(`), `inner_rings()`).
|
an area (`osmium::Areas::outer_rings()`, `inner_rings()`).
|
||||||
- Debug output optionally prints CRC32 when `add_crc32` file option is set.
|
- Debug output optionally prints CRC32 when `add_crc32` file option is set.
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
@ -267,9 +314,9 @@ This project adheres to [Semantic Versioning](http://semver.org/).
|
|||||||
one in Writer. Calling flush() on the OutputIterator isn't needed any
|
one in Writer. Calling flush() on the OutputIterator isn't needed any
|
||||||
more.
|
more.
|
||||||
- Reader now throws when trying to read after eof or an error.
|
- Reader now throws when trying to read after eof or an error.
|
||||||
- I/O functions that used to throw std::runtime_error now throw
|
- I/O functions that used to throw `std::runtime_error` now throw
|
||||||
osmium::io_error or derived.
|
`osmium::io_error` or derived.
|
||||||
- Optional parameters on osmium::io::Writer now work in any order.
|
- Optional parameters on `osmium::io::Writer` now work in any order.
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
@ -410,7 +457,8 @@ This project adheres to [Semantic Versioning](http://semver.org/).
|
|||||||
Doxygen (up to version 1.8.8). This version contains a workaround to fix
|
Doxygen (up to version 1.8.8). This version contains a workaround to fix
|
||||||
this.
|
this.
|
||||||
|
|
||||||
[unreleased]: https://github.com/osmcode/libosmium/compare/v2.9.0...HEAD
|
[unreleased]: https://github.com/osmcode/libosmium/compare/v2.10.0...HEAD
|
||||||
|
[2.10.0]: https://github.com/osmcode/libosmium/compare/v2.9.0...v2.10.0
|
||||||
[2.9.0]: https://github.com/osmcode/libosmium/compare/v2.8.0...v2.9.0
|
[2.9.0]: https://github.com/osmcode/libosmium/compare/v2.8.0...v2.9.0
|
||||||
[2.8.0]: https://github.com/osmcode/libosmium/compare/v2.7.2...v2.8.0
|
[2.8.0]: https://github.com/osmcode/libosmium/compare/v2.7.2...v2.8.0
|
||||||
[2.7.2]: https://github.com/osmcode/libosmium/compare/v2.7.1...v2.7.2
|
[2.7.2]: https://github.com/osmcode/libosmium/compare/v2.7.1...v2.7.2
|
||||||
|
6
third_party/libosmium/CMakeLists.txt
vendored
6
third_party/libosmium/CMakeLists.txt
vendored
@ -24,7 +24,7 @@ set(CMAKE_CONFIGURATION_TYPES "Debug;Release;RelWithDebInfo;MinSizeRel;Dev;Cover
|
|||||||
project(libosmium)
|
project(libosmium)
|
||||||
|
|
||||||
set(LIBOSMIUM_VERSION_MAJOR 2)
|
set(LIBOSMIUM_VERSION_MAJOR 2)
|
||||||
set(LIBOSMIUM_VERSION_MINOR 9)
|
set(LIBOSMIUM_VERSION_MINOR 10)
|
||||||
set(LIBOSMIUM_VERSION_PATCH 0)
|
set(LIBOSMIUM_VERSION_PATCH 0)
|
||||||
|
|
||||||
set(LIBOSMIUM_VERSION
|
set(LIBOSMIUM_VERSION
|
||||||
@ -285,6 +285,10 @@ if(BUILD_DATA_TESTS)
|
|||||||
add_subdirectory(test/data-tests)
|
add_subdirectory(test/data-tests)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if(BUILD_EXAMPLES)
|
||||||
|
add_subdirectory(test/examples)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
|
||||||
#-----------------------------------------------------------------------------
|
#-----------------------------------------------------------------------------
|
||||||
#
|
#
|
||||||
|
4
third_party/libosmium/README.md
vendored
4
third_party/libosmium/README.md
vendored
@ -4,8 +4,8 @@ http://osmcode.org/libosmium
|
|||||||
|
|
||||||
A fast and flexible C++ library for working with OpenStreetMap data.
|
A fast and flexible C++ library for working with OpenStreetMap data.
|
||||||
|
|
||||||
[](https://travis-ci.org/osmcode/libosmium)
|
[](https://travis-ci.org/osmcode/libosmium)
|
||||||
[](https://ci.appveyor.com/project/Mapbox/libosmium)
|
[](https://ci.appveyor.com/project/Mapbox/libosmium)
|
||||||
|
|
||||||
Libosmium is developed on Linux, but also works on OSX and Windows (with some
|
Libosmium is developed on Linux, but also works on OSX and Windows (with some
|
||||||
limitations).
|
limitations).
|
||||||
|
@ -12,6 +12,7 @@ set(BENCHMARKS
|
|||||||
count
|
count
|
||||||
count_tag
|
count_tag
|
||||||
index_map
|
index_map
|
||||||
|
mercator
|
||||||
static_vs_dynamic_index
|
static_vs_dynamic_index
|
||||||
write_pbf
|
write_pbf
|
||||||
CACHE STRING "Benchmark programs"
|
CACHE STRING "Benchmark programs"
|
||||||
@ -37,6 +38,8 @@ foreach(benchmark ${BENCHMARKS})
|
|||||||
@ONLY)
|
@ONLY)
|
||||||
endforeach()
|
endforeach()
|
||||||
|
|
||||||
|
string(TOUPPER "${CMAKE_BUILD_TYPE}" _cmake_build_type)
|
||||||
|
set(_cxx_flags "${CMAKE_CXX_FLAGS_${_cmake_build_type}}")
|
||||||
foreach(file setup run_benchmarks)
|
foreach(file setup run_benchmarks)
|
||||||
configure_file(${file}.sh ${CMAKE_CURRENT_BINARY_DIR}/${file}.sh @ONLY)
|
configure_file(${file}.sh ${CMAKE_CURRENT_BINARY_DIR}/${file}.sh @ONLY)
|
||||||
endforeach()
|
endforeach()
|
||||||
|
@ -4,9 +4,9 @@
|
|||||||
#
|
#
|
||||||
|
|
||||||
cd $DATA_DIR
|
cd $DATA_DIR
|
||||||
curl --location --output 1_liechtenstein.osm.pbf http://download.geofabrik.de/europe/liechtenstein-latest.osm.pbf # about 1 MB
|
curl --location --output 1_liechtenstein.osm.pbf http://download.geofabrik.de/europe/liechtenstein-latest.osm.pbf # about 2 MB
|
||||||
curl --location --output 2_bremen.osm.pbf http://download.geofabrik.de/europe/germany/bremen-latest.osm.pbf # about 13 MB
|
curl --location --output 2_bremen.osm.pbf http://download.geofabrik.de/europe/germany/bremen-latest.osm.pbf # about 16 MB
|
||||||
curl --location --output 3_sachsen.osm.pbf http://download.geofabrik.de/europe/germany/sachsen-latest.osm.pbf # about 120 MB
|
curl --location --output 3_sachsen.osm.pbf http://download.geofabrik.de/europe/germany/sachsen-latest.osm.pbf # about 160 MB
|
||||||
curl --location --output 4_germany.osm.pbf http://download.geofabrik.de/europe/germany-latest.osm.pbf # about 2 GB
|
curl --location --output 4_germany.osm.pbf http://download.geofabrik.de/europe/germany-latest.osm.pbf # about 3 GB
|
||||||
curl --location --output 5_planet.osm.pbf http://planet.osm.org/pbf/planet-latest.osm.pbf # about 26 GB
|
curl --location --output 5_planet.osm.pbf http://planet.osm.org/pbf/planet-latest.osm.pbf # about 35 GB
|
||||||
|
|
||||||
|
@ -19,15 +19,15 @@ struct CountHandler : public osmium::handler::Handler {
|
|||||||
uint64_t ways = 0;
|
uint64_t ways = 0;
|
||||||
uint64_t relations = 0;
|
uint64_t relations = 0;
|
||||||
|
|
||||||
void node(osmium::Node&) {
|
void node(const osmium::Node&) {
|
||||||
++nodes;
|
++nodes;
|
||||||
}
|
}
|
||||||
|
|
||||||
void way(osmium::Way&) {
|
void way(const osmium::Way&) {
|
||||||
++ways;
|
++ways;
|
||||||
}
|
}
|
||||||
|
|
||||||
void relation(osmium::Relation&) {
|
void relation(const osmium::Relation&) {
|
||||||
++relations;
|
++relations;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@ struct CountHandler : public osmium::handler::Handler {
|
|||||||
uint64_t counter = 0;
|
uint64_t counter = 0;
|
||||||
uint64_t all = 0;
|
uint64_t all = 0;
|
||||||
|
|
||||||
void node(osmium::Node& node) {
|
void node(const osmium::Node& node) {
|
||||||
++all;
|
++all;
|
||||||
const char* amenity = node.tags().get_value_by_key("amenity");
|
const char* amenity = node.tags().get_value_by_key("amenity");
|
||||||
if (amenity && !strcmp(amenity, "post_box")) {
|
if (amenity && !strcmp(amenity, "post_box")) {
|
||||||
@ -26,11 +26,11 @@ struct CountHandler : public osmium::handler::Handler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void way(osmium::Way&) {
|
void way(const osmium::Way&) {
|
||||||
++all;
|
++all;
|
||||||
}
|
}
|
||||||
|
|
||||||
void relation(osmium::Relation&) {
|
void relation(const osmium::Relation&) {
|
||||||
++all;
|
++all;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
43
third_party/libosmium/benchmarks/osmium_benchmark_mercator.cpp
vendored
Normal file
43
third_party/libosmium/benchmarks/osmium_benchmark_mercator.cpp
vendored
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
The code in this file is released into the Public Domain.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <iostream>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include <osmium/io/any_input.hpp>
|
||||||
|
#include <osmium/handler.hpp>
|
||||||
|
#include <osmium/visitor.hpp>
|
||||||
|
#include <osmium/geom/wkb.hpp>
|
||||||
|
#include <osmium/geom/mercator_projection.hpp>
|
||||||
|
|
||||||
|
struct GeomHandler : public osmium::handler::Handler {
|
||||||
|
|
||||||
|
osmium::geom::WKBFactory<osmium::geom::MercatorProjection> factory;
|
||||||
|
|
||||||
|
void node(const osmium::Node& node) {
|
||||||
|
const std::string geom = factory.create_point(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
int main(int argc, char* argv[]) {
|
||||||
|
if (argc != 2) {
|
||||||
|
std::cerr << "Usage: " << argv[0] << " OSMFILE\n";
|
||||||
|
std::exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string input_filename{argv[1]};
|
||||||
|
|
||||||
|
osmium::io::Reader reader{input_filename};
|
||||||
|
|
||||||
|
GeomHandler handler;
|
||||||
|
osmium::apply(reader, handler);
|
||||||
|
reader.close();
|
||||||
|
}
|
||||||
|
|
22
third_party/libosmium/benchmarks/run_benchmark_mercator.sh
vendored
Executable file
22
third_party/libosmium/benchmarks/run_benchmark_mercator.sh
vendored
Executable file
@ -0,0 +1,22 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
#
|
||||||
|
# run_benchmark_mercator.sh
|
||||||
|
#
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
BENCHMARK_NAME=mercator
|
||||||
|
|
||||||
|
. @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 2>&1 >/dev/null | sed -e "s%$DATA_DIR/%%" | sed -e "s%$OB_DIR/%%"
|
||||||
|
done
|
||||||
|
done
|
||||||
|
|
16
third_party/libosmium/benchmarks/setup.sh
vendored
16
third_party/libosmium/benchmarks/setup.sh
vendored
@ -9,6 +9,10 @@ if [ -z $DATA_DIR ]; then
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
OB_DIR=@CMAKE_BINARY_DIR@/benchmarks
|
OB_DIR=@CMAKE_BINARY_DIR@/benchmarks
|
||||||
|
OB_BUILD_TYPE=@CMAKE_BUILD_TYPE@
|
||||||
|
OB_COMPILER=@CMAKE_CXX_COMPILER@
|
||||||
|
OB_COMPILER_VERSION=`$OB_COMPILER --version | head -1`
|
||||||
|
OB_CXXFLAGS="@_cxx_flags@"
|
||||||
|
|
||||||
OB_RUNS=3
|
OB_RUNS=3
|
||||||
OB_SEQ=`seq -s' ' 1 $OB_RUNS`
|
OB_SEQ=`seq -s' ' 1 $OB_RUNS`
|
||||||
@ -20,11 +24,17 @@ OB_DATA_FILES=`find -L $DATA_DIR -mindepth 1 -maxdepth 1 -type f | sort`
|
|||||||
|
|
||||||
echo "BENCHMARK: $BENCHMARK_NAME"
|
echo "BENCHMARK: $BENCHMARK_NAME"
|
||||||
echo "---------------------"
|
echo "---------------------"
|
||||||
|
echo "BUILD:"
|
||||||
|
echo "build type\t: $OB_BUILD_TYPE"
|
||||||
|
echo "compiler\t: $OB_COMPILER"
|
||||||
|
echo "CXX version\t: $OB_COMPILER_VERSION"
|
||||||
|
echo "CXX flags\t: $OB_CXXFLAGS"
|
||||||
|
echo "---------------------"
|
||||||
echo "CPU:"
|
echo "CPU:"
|
||||||
grep '^model name' /proc/cpuinfo | tail -1
|
grep '^model name' /proc/cpuinfo | tail -1
|
||||||
grep '^cpu MHz' /proc/cpuinfo | tail -1
|
grep '^cpu MHz' /proc/cpuinfo | tail -1
|
||||||
grep '^cpu cores' /proc/cpuinfo | tail -1
|
grep '^cpu cores' /proc/cpuinfo | tail -1
|
||||||
grep '^siblings' /proc/cpuinfo | tail -1
|
grep '^siblings' /proc/cpuinfo | tail -1
|
||||||
|
|
||||||
echo "---------------------"
|
echo "---------------------"
|
||||||
echo "MEMORY:"
|
echo "MEMORY:"
|
||||||
|
62
third_party/libosmium/cmake/FindOsmium.cmake
vendored
62
third_party/libosmium/cmake/FindOsmium.cmake
vendored
@ -2,8 +2,8 @@
|
|||||||
#
|
#
|
||||||
# FindOsmium.cmake
|
# FindOsmium.cmake
|
||||||
#
|
#
|
||||||
# Find the Libosmium headers and, optionally, several components needed for
|
# Find the Libosmium headers and, optionally, several components needed
|
||||||
# different Libosmium functions.
|
# for different Libosmium functions.
|
||||||
#
|
#
|
||||||
#----------------------------------------------------------------------
|
#----------------------------------------------------------------------
|
||||||
#
|
#
|
||||||
@ -18,9 +18,12 @@
|
|||||||
#
|
#
|
||||||
# Then add the following in your CMakeLists.txt:
|
# Then add the following in your CMakeLists.txt:
|
||||||
#
|
#
|
||||||
# find_package(Osmium REQUIRED COMPONENTS <XXX>)
|
# find_package(Osmium [version] REQUIRED COMPONENTS <XXX>)
|
||||||
# include_directories(SYSTEM ${OSMIUM_INCLUDE_DIRS})
|
# include_directories(SYSTEM ${OSMIUM_INCLUDE_DIRS})
|
||||||
#
|
#
|
||||||
|
# The version number is optional. If it is not set, any version of
|
||||||
|
# libosmium will do.
|
||||||
|
#
|
||||||
# For the <XXX> substitute a space separated list of one or more of the
|
# For the <XXX> substitute a space separated list of one or more of the
|
||||||
# following components:
|
# following components:
|
||||||
#
|
#
|
||||||
@ -51,10 +54,9 @@
|
|||||||
#
|
#
|
||||||
#----------------------------------------------------------------------
|
#----------------------------------------------------------------------
|
||||||
|
|
||||||
# Look for the header file.
|
# This is the list of directories where we look for osmium and protozero
|
||||||
find_path(OSMIUM_INCLUDE_DIR osmium/osm.hpp
|
# includes.
|
||||||
PATH_SUFFIXES include
|
set(_osmium_include_path
|
||||||
PATHS
|
|
||||||
../libosmium
|
../libosmium
|
||||||
~/Library/Frameworks
|
~/Library/Frameworks
|
||||||
/Library/Frameworks
|
/Library/Frameworks
|
||||||
@ -62,6 +64,22 @@ find_path(OSMIUM_INCLUDE_DIR osmium/osm.hpp
|
|||||||
/opt
|
/opt
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Look for the header file.
|
||||||
|
find_path(OSMIUM_INCLUDE_DIR osmium/version.hpp
|
||||||
|
PATH_SUFFIXES include
|
||||||
|
PATHS ${_osmium_include_path}
|
||||||
|
)
|
||||||
|
|
||||||
|
# Check libosmium version number
|
||||||
|
if(Osmium_FIND_VERSION)
|
||||||
|
file(STRINGS "${OSMIUM_INCLUDE_DIR}/osmium/version.hpp" _libosmium_version_define REGEX "#define LIBOSMIUM_VERSION_STRING")
|
||||||
|
if("${_libosmium_version_define}" MATCHES "#define LIBOSMIUM_VERSION_STRING \"([0-9.]+)\"")
|
||||||
|
set(_libosmium_version "${CMAKE_MATCH_1}")
|
||||||
|
else()
|
||||||
|
set(_libosmium_version "unknown")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
set(OSMIUM_INCLUDE_DIRS "${OSMIUM_INCLUDE_DIR}")
|
set(OSMIUM_INCLUDE_DIRS "${OSMIUM_INCLUDE_DIR}")
|
||||||
|
|
||||||
#----------------------------------------------------------------------
|
#----------------------------------------------------------------------
|
||||||
@ -95,17 +113,31 @@ if(Osmium_USE_PBF)
|
|||||||
find_package(ZLIB)
|
find_package(ZLIB)
|
||||||
find_package(Threads)
|
find_package(Threads)
|
||||||
|
|
||||||
list(APPEND OSMIUM_EXTRA_FIND_VARS ZLIB_FOUND Threads_FOUND)
|
message(STATUS "Looking for protozero")
|
||||||
if(ZLIB_FOUND AND Threads_FOUND)
|
find_path(PROTOZERO_INCLUDE_DIR protozero/version.hpp
|
||||||
|
PATH_SUFFIXES include
|
||||||
|
PATHS ${_osmium_include_path}
|
||||||
|
${OSMIUM_INCLUDE_DIR}
|
||||||
|
)
|
||||||
|
if(PROTOZERO_INCLUDE_DIR)
|
||||||
|
message(STATUS "Looking for protozero - found")
|
||||||
|
else()
|
||||||
|
message(STATUS "Looking for protozero - not found")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
list(APPEND OSMIUM_EXTRA_FIND_VARS ZLIB_FOUND Threads_FOUND PROTOZERO_INCLUDE_DIR)
|
||||||
|
if(ZLIB_FOUND AND Threads_FOUND AND PROTOZERO_INCLUDE_DIR)
|
||||||
list(APPEND OSMIUM_PBF_LIBRARIES
|
list(APPEND OSMIUM_PBF_LIBRARIES
|
||||||
${ZLIB_LIBRARIES}
|
${ZLIB_LIBRARIES}
|
||||||
${CMAKE_THREAD_LIBS_INIT}
|
${CMAKE_THREAD_LIBS_INIT}
|
||||||
)
|
)
|
||||||
if(WIN32)
|
if(WIN32)
|
||||||
|
# This is needed for the ntohl() function
|
||||||
list(APPEND OSMIUM_PBF_LIBRARIES ws2_32)
|
list(APPEND OSMIUM_PBF_LIBRARIES ws2_32)
|
||||||
endif()
|
endif()
|
||||||
list(APPEND OSMIUM_INCLUDE_DIRS
|
list(APPEND OSMIUM_INCLUDE_DIRS
|
||||||
${ZLIB_INCLUDE_DIR}
|
${ZLIB_INCLUDE_DIR}
|
||||||
|
${PROTOZERO_INCLUDE_DIR}
|
||||||
)
|
)
|
||||||
else()
|
else()
|
||||||
message(WARNING "Osmium: Can not find some libraries for PBF input/output, please install them or configure the paths.")
|
message(WARNING "Osmium: Can not find some libraries for PBF input/output, please install them or configure the paths.")
|
||||||
@ -203,7 +235,7 @@ if(Osmium_USE_SPARSEHASH)
|
|||||||
if(SPARSEHASH_INCLUDE_DIR)
|
if(SPARSEHASH_INCLUDE_DIR)
|
||||||
# Find size of sparsetable::size_type. This does not work on older
|
# Find size of sparsetable::size_type. This does not work on older
|
||||||
# CMake versions because they can do this check only in C, not in C++.
|
# CMake versions because they can do this check only in C, not in C++.
|
||||||
if (NOT CMAKE_VERSION VERSION_LESS 3.0)
|
if(NOT CMAKE_VERSION VERSION_LESS 3.0)
|
||||||
include(CheckTypeSize)
|
include(CheckTypeSize)
|
||||||
set(CMAKE_REQUIRED_INCLUDES ${SPARSEHASH_INCLUDE_DIR})
|
set(CMAKE_REQUIRED_INCLUDES ${SPARSEHASH_INCLUDE_DIR})
|
||||||
set(CMAKE_EXTRA_INCLUDE_FILES "google/sparsetable")
|
set(CMAKE_EXTRA_INCLUDE_FILES "google/sparsetable")
|
||||||
@ -253,13 +285,15 @@ endif()
|
|||||||
# Check that all required libraries are available
|
# Check that all required libraries are available
|
||||||
#
|
#
|
||||||
#----------------------------------------------------------------------
|
#----------------------------------------------------------------------
|
||||||
if (OSMIUM_EXTRA_FIND_VARS)
|
if(OSMIUM_EXTRA_FIND_VARS)
|
||||||
list(REMOVE_DUPLICATES OSMIUM_EXTRA_FIND_VARS)
|
list(REMOVE_DUPLICATES OSMIUM_EXTRA_FIND_VARS)
|
||||||
endif()
|
endif()
|
||||||
# Handle the QUIETLY and REQUIRED arguments and set OSMIUM_FOUND to TRUE if
|
# Handle the QUIETLY and REQUIRED arguments and the optional version check
|
||||||
# all listed variables are TRUE.
|
# and set OSMIUM_FOUND to TRUE if all listed variables are TRUE.
|
||||||
include(FindPackageHandleStandardArgs)
|
include(FindPackageHandleStandardArgs)
|
||||||
find_package_handle_standard_args(Osmium REQUIRED_VARS OSMIUM_INCLUDE_DIR ${OSMIUM_EXTRA_FIND_VARS})
|
find_package_handle_standard_args(Osmium
|
||||||
|
REQUIRED_VARS OSMIUM_INCLUDE_DIR ${OSMIUM_EXTRA_FIND_VARS}
|
||||||
|
VERSION_VAR _libosmium_version)
|
||||||
unset(OSMIUM_EXTRA_FIND_VARS)
|
unset(OSMIUM_EXTRA_FIND_VARS)
|
||||||
|
|
||||||
#----------------------------------------------------------------------
|
#----------------------------------------------------------------------
|
||||||
|
@ -10,18 +10,20 @@ message(STATUS "Configuring examples")
|
|||||||
|
|
||||||
set(EXAMPLES
|
set(EXAMPLES
|
||||||
area_test
|
area_test
|
||||||
|
change_tags
|
||||||
convert
|
convert
|
||||||
count
|
count
|
||||||
|
create_pois
|
||||||
debug
|
debug
|
||||||
|
dump_internal
|
||||||
filter_discussions
|
filter_discussions
|
||||||
index
|
index_lookup
|
||||||
location_cache_create
|
location_cache_create
|
||||||
location_cache_use
|
location_cache_use
|
||||||
pub_names
|
pub_names
|
||||||
read
|
read
|
||||||
read_with_progress
|
read_with_progress
|
||||||
road_length
|
road_length
|
||||||
serdump
|
|
||||||
tiles
|
tiles
|
||||||
CACHE STRING "Example programs"
|
CACHE STRING "Example programs"
|
||||||
)
|
)
|
||||||
@ -32,7 +34,7 @@ set(EXAMPLES
|
|||||||
# Examples depending on wingetopt
|
# Examples depending on wingetopt
|
||||||
#
|
#
|
||||||
#-----------------------------------------------------------------------------
|
#-----------------------------------------------------------------------------
|
||||||
set(GETOPT_EXAMPLES area_test convert index serdump)
|
set(GETOPT_EXAMPLES area_test convert index_lookup)
|
||||||
if(NOT GETOPT_MISSING)
|
if(NOT GETOPT_MISSING)
|
||||||
foreach(example ${GETOPT_EXAMPLES})
|
foreach(example ${GETOPT_EXAMPLES})
|
||||||
list(APPEND EXAMPLE_LIBS_${example} ${GETOPT_LIBRARY})
|
list(APPEND EXAMPLE_LIBS_${example} ${GETOPT_LIBRARY})
|
||||||
|
12
third_party/libosmium/examples/README.md
vendored
12
third_party/libosmium/examples/README.md
vendored
@ -18,12 +18,24 @@ them.
|
|||||||
|
|
||||||
## Still reasonably simple examples
|
## Still reasonably simple examples
|
||||||
|
|
||||||
|
* `osmium_read_with_progress`
|
||||||
* `osmium_filter_discussions`
|
* `osmium_filter_discussions`
|
||||||
* `osmium_convert`
|
* `osmium_convert`
|
||||||
|
* `osmium_pub_names`
|
||||||
|
* `osmium_road_length`
|
||||||
|
|
||||||
## More advanced examples
|
## More advanced examples
|
||||||
|
|
||||||
* `osmium_area_test`
|
* `osmium_area_test`
|
||||||
|
* `osmium_create_pois`
|
||||||
|
|
||||||
|
## Even more advanced examples
|
||||||
|
|
||||||
|
* `osmium_change_tags`
|
||||||
|
* `osmium_location_cache_create`
|
||||||
|
* `osmium_location_cache_use`
|
||||||
|
* `osmium_dump_internal`
|
||||||
|
* `osmium_index_lookup`
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
|
@ -106,7 +106,7 @@ int main(int argc, char* argv[]) {
|
|||||||
|
|
||||||
// Read options from command line.
|
// Read options from command line.
|
||||||
while (true) {
|
while (true) {
|
||||||
int c = getopt_long(argc, argv, "hwo", long_options, 0);
|
const int c = getopt_long(argc, argv, "hwo", long_options, 0);
|
||||||
if (c == -1) {
|
if (c == -1) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -126,7 +126,7 @@ int main(int argc, char* argv[]) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int remaining_args = argc - optind;
|
const int remaining_args = argc - optind;
|
||||||
if (remaining_args != 1) {
|
if (remaining_args != 1) {
|
||||||
std::cerr << "Usage: " << argv[0] << " [OPTIONS] OSMFILE\n";
|
std::cerr << "Usage: " << argv[0] << " [OPTIONS] OSMFILE\n";
|
||||||
std::exit(1);
|
std::exit(1);
|
||||||
|
203
third_party/libosmium/examples/osmium_change_tags.cpp
vendored
Normal file
203
third_party/libosmium/examples/osmium_change_tags.cpp
vendored
Normal file
@ -0,0 +1,203 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
EXAMPLE osmium_change_tags
|
||||||
|
|
||||||
|
An example how tags in OSM files can be removed or changed. Removes
|
||||||
|
"created_by" tags and changes tag "landuse=forest" into "natural_wood".
|
||||||
|
|
||||||
|
DEMONSTRATES USE OF:
|
||||||
|
* file input and output
|
||||||
|
* Osmium buffers
|
||||||
|
* your own handler
|
||||||
|
* access to tags
|
||||||
|
* using builders to write data
|
||||||
|
|
||||||
|
SIMPLER EXAMPLES you might want to understand first:
|
||||||
|
* osmium_read
|
||||||
|
* osmium_count
|
||||||
|
* osmium_pub_names
|
||||||
|
|
||||||
|
LICENSE
|
||||||
|
The code in this example file is released into the Public Domain.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <cstdlib> // for std::exit
|
||||||
|
#include <cstring> // for std::strcmp
|
||||||
|
#include <exception> // for std::exception
|
||||||
|
#include <iostream> // for std::cout, std::cerr
|
||||||
|
#include <string> // for std::string
|
||||||
|
#include <utility> // for std::move
|
||||||
|
|
||||||
|
// Allow any format of input files (XML, PBF, ...)
|
||||||
|
#include <osmium/io/any_input.hpp>
|
||||||
|
|
||||||
|
// Allow any format of output files (XML, PBF, ...)
|
||||||
|
#include <osmium/io/any_output.hpp>
|
||||||
|
|
||||||
|
// We want to use the builder interface
|
||||||
|
#include <osmium/builder/osm_object_builder.hpp>
|
||||||
|
|
||||||
|
// We want to use the handler interface
|
||||||
|
#include <osmium/handler.hpp>
|
||||||
|
|
||||||
|
// For osmium::apply()
|
||||||
|
#include <osmium/visitor.hpp>
|
||||||
|
|
||||||
|
// The functions in this class will be called for each object in the input
|
||||||
|
// and will write a (changed) copy of those objects to the given buffer.
|
||||||
|
class RewriteHandler : public osmium::handler::Handler {
|
||||||
|
|
||||||
|
osmium::memory::Buffer& m_buffer;
|
||||||
|
|
||||||
|
// Copy attributes common to all OSM objects (nodes, ways, and relations).
|
||||||
|
template <typename T>
|
||||||
|
void copy_attributes(T& builder, const osmium::OSMObject& object) {
|
||||||
|
// The setter functions on the builder object all return the same
|
||||||
|
// builder object so they can be chained.
|
||||||
|
builder.set_id(object.id())
|
||||||
|
.set_version(object.version())
|
||||||
|
.set_changeset(object.changeset())
|
||||||
|
.set_timestamp(object.timestamp())
|
||||||
|
.set_uid(object.uid())
|
||||||
|
.set_user(object.user());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy all tags with two changes:
|
||||||
|
// * Do not copy "created_by" tags
|
||||||
|
// * Change "landuse=forest" into "natural=wood"
|
||||||
|
void copy_tags(osmium::builder::Builder& parent, const osmium::TagList& tags) {
|
||||||
|
|
||||||
|
// The TagListBuilder is used to create a list of tags. The parameter
|
||||||
|
// to create it is a reference to the builder of the object that
|
||||||
|
// should have those tags.
|
||||||
|
osmium::builder::TagListBuilder builder{parent};
|
||||||
|
|
||||||
|
// Iterate over all tags and build new tags using the new builder
|
||||||
|
// based on the old ones.
|
||||||
|
for (const auto& tag : tags) {
|
||||||
|
if (std::strcmp(tag.key(), "created_by")) {
|
||||||
|
if (!std::strcmp(tag.key(), "landuse") && !std::strcmp(tag.value(), "forest")) {
|
||||||
|
// add_tag() can be called with key and value C strings
|
||||||
|
builder.add_tag("natural", "wood");
|
||||||
|
} else {
|
||||||
|
// add_tag() can also be called with an osmium::Tag
|
||||||
|
builder.add_tag(tag);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
// Constructor. New data will be added to the given buffer.
|
||||||
|
RewriteHandler(osmium::memory::Buffer& buffer) :
|
||||||
|
m_buffer(buffer) {
|
||||||
|
}
|
||||||
|
|
||||||
|
// The node handler is called for each node in the input data.
|
||||||
|
void node(const osmium::Node& node) {
|
||||||
|
// Open a new scope, because the NodeBuilder we are creating has to
|
||||||
|
// be destructed, before we can call commit() below.
|
||||||
|
{
|
||||||
|
// To create a node, we need a NodeBuilder object. It will create
|
||||||
|
// the node in the given buffer.
|
||||||
|
osmium::builder::NodeBuilder builder{m_buffer};
|
||||||
|
|
||||||
|
// Copy common object attributes over to the new node.
|
||||||
|
copy_attributes(builder, node);
|
||||||
|
|
||||||
|
// Copy the location over to the new node.
|
||||||
|
builder.set_location(node.location());
|
||||||
|
|
||||||
|
// Copy (changed) tags.
|
||||||
|
copy_tags(builder, node.tags());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Once the object is written to the buffer completely, we have to call
|
||||||
|
// commit().
|
||||||
|
m_buffer.commit();
|
||||||
|
}
|
||||||
|
|
||||||
|
// The way handler is called for each node in the input data.
|
||||||
|
void way(const osmium::Way& way) {
|
||||||
|
{
|
||||||
|
osmium::builder::WayBuilder builder{m_buffer};
|
||||||
|
copy_attributes(builder, way);
|
||||||
|
copy_tags(builder, way.tags());
|
||||||
|
|
||||||
|
// Copy the node list over to the new way.
|
||||||
|
builder.add_item(way.nodes());
|
||||||
|
}
|
||||||
|
m_buffer.commit();
|
||||||
|
}
|
||||||
|
|
||||||
|
// The relation handler is called for each node in the input data.
|
||||||
|
void relation(const osmium::Relation& relation) {
|
||||||
|
{
|
||||||
|
osmium::builder::RelationBuilder builder{m_buffer};
|
||||||
|
copy_attributes(builder, relation);
|
||||||
|
copy_tags(builder, relation.tags());
|
||||||
|
|
||||||
|
// Copy the relation member list over to the new way.
|
||||||
|
builder.add_item(relation.members());
|
||||||
|
}
|
||||||
|
m_buffer.commit();
|
||||||
|
}
|
||||||
|
|
||||||
|
}; // class RewriteHandler
|
||||||
|
|
||||||
|
int main(int argc, char* argv[]) {
|
||||||
|
if (argc != 3) {
|
||||||
|
std::cerr << "Usage: " << argv[0] << " INFILE OUTFILE\n";
|
||||||
|
std::exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get input and output file names from command line.
|
||||||
|
std::string input_file_name{argv[1]};
|
||||||
|
std::string output_file_name{argv[2]};
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Initialize Reader
|
||||||
|
osmium::io::Reader reader{input_file_name};
|
||||||
|
|
||||||
|
// Get header from input file and change the "generator" setting to
|
||||||
|
// ourselves.
|
||||||
|
osmium::io::Header header = reader.header();
|
||||||
|
header.set("generator", "osmium_change_tags");
|
||||||
|
|
||||||
|
// Initialize Writer using the header from above and tell it that it
|
||||||
|
// is allowed to overwrite a possibly existing file.
|
||||||
|
osmium::io::Writer writer{output_file_name, header, osmium::io::overwrite::allow};
|
||||||
|
|
||||||
|
// Read in buffers with OSM objects until there are no more.
|
||||||
|
while (osmium::memory::Buffer input_buffer = reader.read()) {
|
||||||
|
// Create an empty buffer with the same size as the input buffer.
|
||||||
|
// We'll copy the changed data into output buffer, the changes
|
||||||
|
// are small, so the output buffer needs to be about the same size.
|
||||||
|
// In case it has to be bigger, we allow it to grow automatically
|
||||||
|
// by adding the auto_grow::yes parameter.
|
||||||
|
osmium::memory::Buffer output_buffer{input_buffer.committed(), osmium::memory::Buffer::auto_grow::yes};
|
||||||
|
|
||||||
|
// Construct a handler as defined above and feed the input buffer
|
||||||
|
// to it.
|
||||||
|
RewriteHandler handler{output_buffer};
|
||||||
|
osmium::apply(input_buffer, handler);
|
||||||
|
|
||||||
|
// Write out the contents of the output buffer.
|
||||||
|
writer(std::move(output_buffer));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Explicitly close the writer and reader. Will throw an exception if
|
||||||
|
// there is a problem. If you wait for the destructor to close the writer
|
||||||
|
// and reader, you will not notice the problem, because destructors must
|
||||||
|
// not throw.
|
||||||
|
writer.close();
|
||||||
|
reader.close();
|
||||||
|
} catch (const std::exception& e) {
|
||||||
|
// All exceptions used by the Osmium library derive from std::exception.
|
||||||
|
std::cerr << e.what() << "\n";
|
||||||
|
std::exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -67,7 +67,7 @@ int main(int argc, char* argv[]) {
|
|||||||
|
|
||||||
// Read options from command line.
|
// Read options from command line.
|
||||||
while (true) {
|
while (true) {
|
||||||
int c = getopt_long(argc, argv, "dhf:t:", long_options, 0);
|
const int c = getopt_long(argc, argv, "dhf:t:", long_options, 0);
|
||||||
if (c == -1) {
|
if (c == -1) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -87,7 +87,7 @@ int main(int argc, char* argv[]) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int remaining_args = argc - optind;
|
const int remaining_args = argc - optind;
|
||||||
if (remaining_args > 2) {
|
if (remaining_args > 2) {
|
||||||
std::cerr << "Usage: " << argv[0] << " [OPTIONS] [INFILE [OUTFILE]]\n";
|
std::cerr << "Usage: " << argv[0] << " [OPTIONS] [INFILE [OUTFILE]]\n";
|
||||||
std::exit(1);
|
std::exit(1);
|
||||||
@ -124,13 +124,13 @@ int main(int argc, char* argv[]) {
|
|||||||
osmium::io::Reader reader{input_file};
|
osmium::io::Reader reader{input_file};
|
||||||
|
|
||||||
// Get header from input file and change the "generator" setting to
|
// Get header from input file and change the "generator" setting to
|
||||||
// outselves.
|
// ourselves.
|
||||||
osmium::io::Header header = reader.header();
|
osmium::io::Header header = reader.header();
|
||||||
header.set("generator", "osmium_convert");
|
header.set("generator", "osmium_convert");
|
||||||
|
|
||||||
// Initialize Writer using the header from above and tell it that it
|
// Initialize Writer using the header from above and tell it that it
|
||||||
// is allowed to overwrite a possibly existing file.
|
// is allowed to overwrite a possibly existing file.
|
||||||
osmium::io::Writer writer(output_file, header, osmium::io::overwrite::allow);
|
osmium::io::Writer writer{output_file, header, osmium::io::overwrite::allow};
|
||||||
|
|
||||||
// Copy the contents from the input to the output file one buffer at
|
// Copy the contents from the input to the output file one buffer at
|
||||||
// a time. This is much easier and faster than copying each object
|
// a time. This is much easier and faster than copying each object
|
||||||
|
96
third_party/libosmium/examples/osmium_create_pois.cpp
vendored
Normal file
96
third_party/libosmium/examples/osmium_create_pois.cpp
vendored
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
EXAMPLE osmium_create_pois
|
||||||
|
|
||||||
|
Showing how to create nodes for points of interest out of thin air.
|
||||||
|
|
||||||
|
DEMONSTRATES USE OF:
|
||||||
|
* file output
|
||||||
|
* Osmium buffers
|
||||||
|
* using builders to write data
|
||||||
|
|
||||||
|
SIMPLER EXAMPLES you might want to understand first:
|
||||||
|
* osmium_read
|
||||||
|
* osmium_count
|
||||||
|
* osmium_pub_names
|
||||||
|
|
||||||
|
LICENSE
|
||||||
|
The code in this example file is released into the Public Domain.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <cstdlib> // for std::exit
|
||||||
|
#include <cstring> // for std::strcmp
|
||||||
|
#include <ctime> // for std::time
|
||||||
|
#include <exception> // for std::exception
|
||||||
|
#include <iostream> // for std::cout, std::cerr
|
||||||
|
#include <string> // for std::string
|
||||||
|
#include <utility> // for std::move
|
||||||
|
|
||||||
|
// Allow any format of output files (XML, PBF, ...)
|
||||||
|
#include <osmium/io/any_output.hpp>
|
||||||
|
|
||||||
|
// We want to use the builder interface
|
||||||
|
#include <osmium/builder/osm_object_builder.hpp>
|
||||||
|
#include <osmium/builder/attr.hpp>
|
||||||
|
|
||||||
|
// Declare this to use the functions starting with the underscore (_) below.
|
||||||
|
using namespace osmium::builder::attr;
|
||||||
|
|
||||||
|
int main(int argc, char* argv[]) {
|
||||||
|
if (argc != 2) {
|
||||||
|
std::cerr << "Usage: " << argv[0] << " OUTFILE\n";
|
||||||
|
std::exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get output file name from command line.
|
||||||
|
std::string output_file_name{argv[1]};
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Create a buffer where all objects will live. Use a sensible initial
|
||||||
|
// buffer size and set the buffer to automatically grow if needed.
|
||||||
|
const size_t initial_buffer_size = 10000;
|
||||||
|
osmium::memory::Buffer buffer{initial_buffer_size, osmium::memory::Buffer::auto_grow::yes};
|
||||||
|
|
||||||
|
// Add nodes to the buffer. This is, of course, only an example.
|
||||||
|
// You can set any of the attributes and more tags, etc. Ways and
|
||||||
|
// relations can be added in a similar way.
|
||||||
|
osmium::builder::add_node(buffer,
|
||||||
|
_id(-1),
|
||||||
|
_version(1),
|
||||||
|
_timestamp(std::time(nullptr)),
|
||||||
|
_location(osmium::Location{1.23, 3.45}),
|
||||||
|
_tag("amenity", "post_box")
|
||||||
|
);
|
||||||
|
|
||||||
|
osmium::builder::add_node(buffer,
|
||||||
|
_id(-2),
|
||||||
|
_version(1),
|
||||||
|
_timestamp(std::time(nullptr)),
|
||||||
|
_location(1.24, 3.46),
|
||||||
|
_tags({{"amenity", "restaurant"},
|
||||||
|
{"name", "Chez OSM"}})
|
||||||
|
);
|
||||||
|
|
||||||
|
// Create header and set generator.
|
||||||
|
osmium::io::Header header;
|
||||||
|
header.set("generator", "osmium_create_pois");
|
||||||
|
|
||||||
|
// Initialize Writer using the header from above and tell it that it
|
||||||
|
// is allowed to overwrite a possibly existing file.
|
||||||
|
osmium::io::Writer writer{output_file_name, header, osmium::io::overwrite::allow};
|
||||||
|
|
||||||
|
// Write out the contents of the output buffer.
|
||||||
|
writer(std::move(buffer));
|
||||||
|
|
||||||
|
// Explicitly close the writer. Will throw an exception if there is
|
||||||
|
// a problem. If you wait for the destructor to close the writer, you
|
||||||
|
// will not notice the problem, because destructors must not throw.
|
||||||
|
writer.close();
|
||||||
|
} catch (const std::exception& e) {
|
||||||
|
// All exceptions used by the Osmium library derive from std::exception.
|
||||||
|
std::cerr << e.what() << "\n";
|
||||||
|
std::exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
179
third_party/libosmium/examples/osmium_dump_internal.cpp
vendored
Normal file
179
third_party/libosmium/examples/osmium_dump_internal.cpp
vendored
Normal file
@ -0,0 +1,179 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
EXAMPLE osmium_dump_internal
|
||||||
|
|
||||||
|
Reads an OSM file and dumps the internal datastructure to disk including
|
||||||
|
indexes to find objects and object relations.
|
||||||
|
|
||||||
|
Note that this example programm will only work with small and medium sized
|
||||||
|
OSM file, not with the planet.
|
||||||
|
|
||||||
|
You can use the osmium_index example program to inspect the indexes.
|
||||||
|
|
||||||
|
DEMONSTRATES USE OF:
|
||||||
|
* file input
|
||||||
|
* indexes and maps
|
||||||
|
* use of the DiskStore handler
|
||||||
|
* use of the ObjectRelations handler
|
||||||
|
|
||||||
|
SIMPLER EXAMPLES you might want to understand first:
|
||||||
|
* osmium_read
|
||||||
|
* osmium_count
|
||||||
|
* osmium_road_length
|
||||||
|
* osmium_location_cache_create
|
||||||
|
* osmium_location_cache_use
|
||||||
|
|
||||||
|
LICENSE
|
||||||
|
The code in this example file is released into the Public Domain.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <cerrno> // for errno
|
||||||
|
#include <cstring> // for std::strerror
|
||||||
|
#include <cstdlib> // for std::exit
|
||||||
|
#include <iostream> // for std::cout, std::cerr
|
||||||
|
#include <string> // for std::string
|
||||||
|
#include <sys/stat.h> // for open
|
||||||
|
#include <sys/types.h> // for open
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
# include <direct.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Allow any format of input files (XML, PBF, ...)
|
||||||
|
#include <osmium/io/any_input.hpp>
|
||||||
|
|
||||||
|
// The DiskStore handler
|
||||||
|
#include <osmium/handler/disk_store.hpp>
|
||||||
|
|
||||||
|
// The ObjectRelations handler
|
||||||
|
#include <osmium/handler/object_relations.hpp>
|
||||||
|
|
||||||
|
// The indexes
|
||||||
|
#include <osmium/index/map/sparse_mem_array.hpp>
|
||||||
|
#include <osmium/index/multimap/sparse_mem_array.hpp>
|
||||||
|
|
||||||
|
using offset_index_type = osmium::index::map::SparseMemArray<osmium::unsigned_object_id_type, size_t>;
|
||||||
|
using map_type = osmium::index::multimap::SparseMemArray<osmium::unsigned_object_id_type, osmium::unsigned_object_id_type>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Small class wrapping index files, basically making sure errors are handled
|
||||||
|
* and the files are closed on destruction.
|
||||||
|
*/
|
||||||
|
class IndexFile {
|
||||||
|
|
||||||
|
int m_fd;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
IndexFile(const std::string& filename) :
|
||||||
|
m_fd(::open(filename.c_str(), O_WRONLY | O_CREAT | O_TRUNC, 0666)) {
|
||||||
|
if (m_fd < 0) {
|
||||||
|
std::cerr << "Can't open index file '" << filename << "': " << std::strerror(errno) << "\n";
|
||||||
|
std::exit(2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
~IndexFile() {
|
||||||
|
if (m_fd >= 0) {
|
||||||
|
close(m_fd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int fd() const noexcept {
|
||||||
|
return m_fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
}; // class IndexFile
|
||||||
|
|
||||||
|
int main(int argc, char* argv[]) {
|
||||||
|
if (argc != 3) {
|
||||||
|
std::cerr << "Usage: " << argv[0] << " OSMFILE DIR\n";
|
||||||
|
std::exit(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string input_file_name{argv[1]};
|
||||||
|
const std::string output_dir{argv[2]};
|
||||||
|
|
||||||
|
// Create output directory. Ignore the error if it already exists.
|
||||||
|
#ifndef _WIN32
|
||||||
|
const int result = ::mkdir(output_dir.c_str(), 0777);
|
||||||
|
#else
|
||||||
|
const int result = mkdir(output_dir.c_str());
|
||||||
|
#endif
|
||||||
|
if (result == -1 && errno != EEXIST) {
|
||||||
|
std::cerr << "Problem creating directory '" << output_dir << "': " << std::strerror(errno) << "\n";
|
||||||
|
std::exit(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create the output file which will contain our serialized OSM data
|
||||||
|
const std::string data_file{output_dir + "/data.osm.ser"};
|
||||||
|
const int data_fd = ::open(data_file.c_str(), O_WRONLY | O_CREAT | O_TRUNC, 0666);
|
||||||
|
if (data_fd < 0) {
|
||||||
|
std::cerr << "Can't open data file '" << data_file << "': " << std::strerror(errno) << "\n";
|
||||||
|
std::exit(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
// These indexes store the offset in the data file where each node, way,
|
||||||
|
// or relation is stored.
|
||||||
|
offset_index_type node_index;
|
||||||
|
offset_index_type way_index;
|
||||||
|
offset_index_type relation_index;
|
||||||
|
|
||||||
|
// This handler will dump the internal data to disk using the given file
|
||||||
|
// descriptor while updating the indexes.
|
||||||
|
osmium::handler::DiskStore disk_store_handler{data_fd, node_index, way_index, relation_index};
|
||||||
|
|
||||||
|
// These indexes store the mapping from node id to the ids of the ways
|
||||||
|
// containing this node, and from node/way/relation ids to the ids of the
|
||||||
|
// relations containing those objects.
|
||||||
|
map_type map_node2way;
|
||||||
|
map_type map_node2relation;
|
||||||
|
map_type map_way2relation;
|
||||||
|
map_type map_relation2relation;
|
||||||
|
|
||||||
|
// This handler will update the map indexes.
|
||||||
|
osmium::handler::ObjectRelations object_relations_handler{map_node2way, map_node2relation, map_way2relation, map_relation2relation};
|
||||||
|
|
||||||
|
// Read OSM data buffer by buffer.
|
||||||
|
osmium::io::Reader reader{input_file_name};
|
||||||
|
|
||||||
|
while (osmium::memory::Buffer buffer = reader.read()) {
|
||||||
|
// Write buffer to disk and update indexes.
|
||||||
|
disk_store_handler(buffer);
|
||||||
|
|
||||||
|
// Update object relation index maps.
|
||||||
|
osmium::apply(buffer, object_relations_handler);
|
||||||
|
}
|
||||||
|
|
||||||
|
reader.close();
|
||||||
|
|
||||||
|
// Write out node, way, and relation offset indexes to disk.
|
||||||
|
IndexFile nodes_idx{output_dir + "/nodes.idx"};
|
||||||
|
node_index.dump_as_list(nodes_idx.fd());
|
||||||
|
|
||||||
|
IndexFile ways_idx{output_dir + "/ways.idx"};
|
||||||
|
way_index.dump_as_list(ways_idx.fd());
|
||||||
|
|
||||||
|
IndexFile relations_idx{output_dir + "/relations.idx"};
|
||||||
|
relation_index.dump_as_list(relations_idx.fd());
|
||||||
|
|
||||||
|
// Sort the maps (so later binary search will work on them) and write
|
||||||
|
// them to disk.
|
||||||
|
map_node2way.sort();
|
||||||
|
IndexFile node2way_idx{output_dir + "/node2way.map"};
|
||||||
|
map_node2way.dump_as_list(node2way_idx.fd());
|
||||||
|
|
||||||
|
map_node2relation.sort();
|
||||||
|
IndexFile node2relation_idx{output_dir + "/node2rel.map"};
|
||||||
|
map_node2relation.dump_as_list(node2relation_idx.fd());
|
||||||
|
|
||||||
|
map_way2relation.sort();
|
||||||
|
IndexFile way2relation_idx{output_dir + "/way2rel.map"};
|
||||||
|
map_way2relation.dump_as_list(way2relation_idx.fd());
|
||||||
|
|
||||||
|
map_relation2relation.sort();
|
||||||
|
IndexFile relation2relation_idx{output_dir + "/rel2rel.map"};
|
||||||
|
map_relation2relation.dump_as_list(relation2relation_idx.fd());
|
||||||
|
}
|
||||||
|
|
@ -67,7 +67,7 @@ int main(int argc, char* argv[]) {
|
|||||||
// file for the output file. This will copy over some header information.
|
// file for the output file. This will copy over some header information.
|
||||||
// The last parameter will tell the writer that it is allowed to overwrite
|
// The last parameter will tell the writer that it is allowed to overwrite
|
||||||
// an existing file. Without it, it will refuse to do so.
|
// an existing file. Without it, it will refuse to do so.
|
||||||
osmium::io::Writer writer(output_file, header, osmium::io::overwrite::allow);
|
osmium::io::Writer writer{output_file, header, osmium::io::overwrite::allow};
|
||||||
|
|
||||||
// Create range of input iterators that will iterator over all changesets
|
// Create range of input iterators that will iterator over all changesets
|
||||||
// delivered from input file through the "reader".
|
// delivered from input file through the "reader".
|
||||||
|
260
third_party/libosmium/examples/osmium_index.cpp
vendored
260
third_party/libosmium/examples/osmium_index.cpp
vendored
@ -1,260 +0,0 @@
|
|||||||
/*
|
|
||||||
|
|
||||||
Example program to look at Osmium indexes on disk.
|
|
||||||
|
|
||||||
The code in this example file is released into the Public Domain.
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <iomanip>
|
|
||||||
#include <iostream>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
|
|
||||||
#include <getopt.h>
|
|
||||||
|
|
||||||
#include <osmium/index/map/dense_file_array.hpp>
|
|
||||||
#include <osmium/index/map/sparse_file_array.hpp>
|
|
||||||
#include <osmium/osm/location.hpp>
|
|
||||||
#include <osmium/osm/types.hpp>
|
|
||||||
|
|
||||||
template <typename TKey, typename TValue>
|
|
||||||
class IndexSearch {
|
|
||||||
|
|
||||||
typedef typename osmium::index::map::DenseFileArray<TKey, TValue> dense_index_type;
|
|
||||||
typedef typename osmium::index::map::SparseFileArray<TKey, TValue> sparse_index_type;
|
|
||||||
|
|
||||||
int m_fd;
|
|
||||||
bool m_dense_format;
|
|
||||||
|
|
||||||
void dump_dense() {
|
|
||||||
dense_index_type index(m_fd);
|
|
||||||
|
|
||||||
for (std::size_t i = 0; i < index.size(); ++i) {
|
|
||||||
if (index.get(i) != TValue()) {
|
|
||||||
std::cout << i << " " << index.get(i) << "\n";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void dump_sparse() {
|
|
||||||
sparse_index_type index(m_fd);
|
|
||||||
|
|
||||||
for (auto& element : index) {
|
|
||||||
std::cout << element.first << " " << element.second << "\n";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool search_dense(TKey key) {
|
|
||||||
dense_index_type index(m_fd);
|
|
||||||
|
|
||||||
try {
|
|
||||||
TValue value = index.get(key);
|
|
||||||
std::cout << key << " " << value << "\n";
|
|
||||||
} catch (...) {
|
|
||||||
std::cout << key << " not found\n";
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool search_sparse(TKey key) {
|
|
||||||
typedef typename sparse_index_type::element_type element_type;
|
|
||||||
sparse_index_type index(m_fd);
|
|
||||||
|
|
||||||
element_type elem {key, TValue()};
|
|
||||||
auto positions = std::equal_range(index.begin(), index.end(), elem, [](const element_type& lhs, const element_type& rhs) {
|
|
||||||
return lhs.first < rhs.first;
|
|
||||||
});
|
|
||||||
if (positions.first == positions.second) {
|
|
||||||
std::cout << key << " not found\n";
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto& it = positions.first; it != positions.second; ++it) {
|
|
||||||
std::cout << it->first << " " << it->second << "\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
IndexSearch(int fd, bool dense_format) :
|
|
||||||
m_fd(fd),
|
|
||||||
m_dense_format(dense_format) {
|
|
||||||
}
|
|
||||||
|
|
||||||
void dump() {
|
|
||||||
if (m_dense_format) {
|
|
||||||
dump_dense();
|
|
||||||
} else {
|
|
||||||
dump_sparse();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool search(TKey key) {
|
|
||||||
if (m_dense_format) {
|
|
||||||
return search_dense(key);
|
|
||||||
} else {
|
|
||||||
return search_sparse(key);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool search(const std::vector<TKey>& keys) {
|
|
||||||
bool found_all = true;
|
|
||||||
|
|
||||||
for (const auto key : keys) {
|
|
||||||
if (!search(key)) {
|
|
||||||
found_all = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return found_all;
|
|
||||||
}
|
|
||||||
|
|
||||||
}; // class IndexSearch
|
|
||||||
|
|
||||||
enum return_code : int {
|
|
||||||
okay = 0,
|
|
||||||
not_found = 1,
|
|
||||||
error = 2,
|
|
||||||
fatal = 3
|
|
||||||
};
|
|
||||||
|
|
||||||
class Options {
|
|
||||||
|
|
||||||
std::vector<osmium::unsigned_object_id_type> m_ids;
|
|
||||||
std::string m_type;
|
|
||||||
std::string m_filename;
|
|
||||||
bool m_dump = false;
|
|
||||||
bool m_array_format = false;
|
|
||||||
bool m_list_format = false;
|
|
||||||
|
|
||||||
void print_help() {
|
|
||||||
std::cout << "Usage: osmium_index [OPTIONS]\n\n"
|
|
||||||
<< "-h, --help Print this help message\n"
|
|
||||||
<< "-a, --array=FILE Read given index file in array format\n"
|
|
||||||
<< "-l, --list=FILE Read given index file in list format\n"
|
|
||||||
<< "-d, --dump Dump contents of index file to STDOUT\n"
|
|
||||||
<< "-s, --search=ID Search for given id (Option can appear multiple times)\n"
|
|
||||||
<< "-t, --type=TYPE Type of value ('location' or 'offset')\n"
|
|
||||||
;
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
Options(int argc, char* argv[]) {
|
|
||||||
static struct option long_options[] = {
|
|
||||||
{"array", required_argument, 0, 'a'},
|
|
||||||
{"dump", no_argument, 0, 'd'},
|
|
||||||
{"help", no_argument, 0, 'h'},
|
|
||||||
{"list", required_argument, 0, 'l'},
|
|
||||||
{"search", required_argument, 0, 's'},
|
|
||||||
{"type", required_argument, 0, 't'},
|
|
||||||
{0, 0, 0, 0}
|
|
||||||
};
|
|
||||||
|
|
||||||
while (true) {
|
|
||||||
int c = getopt_long(argc, argv, "a:dhl:s:t:", long_options, 0);
|
|
||||||
if (c == -1) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (c) {
|
|
||||||
case 'a':
|
|
||||||
m_array_format = true;
|
|
||||||
m_filename = optarg;
|
|
||||||
break;
|
|
||||||
case 'd':
|
|
||||||
m_dump = true;
|
|
||||||
break;
|
|
||||||
case 'h':
|
|
||||||
print_help();
|
|
||||||
std::exit(return_code::okay);
|
|
||||||
case 'l':
|
|
||||||
m_list_format = true;
|
|
||||||
m_filename = optarg;
|
|
||||||
break;
|
|
||||||
case 's':
|
|
||||||
m_ids.push_back(std::atoll(optarg));
|
|
||||||
break;
|
|
||||||
case 't':
|
|
||||||
m_type = optarg;
|
|
||||||
if (m_type != "location" && m_type != "offset") {
|
|
||||||
std::cerr << "Unknown type '" << m_type << "'. Must be 'location' or 'offset'.\n";
|
|
||||||
std::exit(return_code::fatal);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
std::exit(return_code::fatal);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_array_format == m_list_format) {
|
|
||||||
std::cerr << "Need option --array or --list, but not both\n";
|
|
||||||
std::exit(return_code::fatal);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_type.empty()) {
|
|
||||||
std::cerr << "Need --type argument.\n";
|
|
||||||
std::exit(return_code::fatal);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
const std::string& filename() const noexcept {
|
|
||||||
return m_filename;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool dense_format() const noexcept {
|
|
||||||
return m_array_format;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool do_dump() const noexcept {
|
|
||||||
return m_dump;
|
|
||||||
}
|
|
||||||
|
|
||||||
const std::vector<osmium::unsigned_object_id_type>& search_keys() const noexcept {
|
|
||||||
return m_ids;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool type_is(const char* type) const noexcept {
|
|
||||||
return m_type == type;
|
|
||||||
}
|
|
||||||
|
|
||||||
}; // class Options
|
|
||||||
|
|
||||||
int main(int argc, char* argv[]) {
|
|
||||||
std::ios_base::sync_with_stdio(false);
|
|
||||||
|
|
||||||
Options options(argc, argv);
|
|
||||||
|
|
||||||
std::cout << std::fixed << std::setprecision(7);
|
|
||||||
int fd = open(options.filename().c_str(), O_RDWR);
|
|
||||||
|
|
||||||
bool result_okay = true;
|
|
||||||
|
|
||||||
if (options.type_is("location")) {
|
|
||||||
IndexSearch<osmium::unsigned_object_id_type, osmium::Location> is(fd, options.dense_format());
|
|
||||||
|
|
||||||
if (options.do_dump()) {
|
|
||||||
is.dump();
|
|
||||||
} else {
|
|
||||||
result_okay = is.search(options.search_keys());
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
IndexSearch<osmium::unsigned_object_id_type, size_t> is(fd, options.dense_format());
|
|
||||||
|
|
||||||
if (options.do_dump()) {
|
|
||||||
is.dump();
|
|
||||||
} else {
|
|
||||||
result_okay = is.search(options.search_keys());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::exit(result_okay ? return_code::okay : return_code::not_found);
|
|
||||||
}
|
|
||||||
|
|
333
third_party/libosmium/examples/osmium_index_lookup.cpp
vendored
Normal file
333
third_party/libosmium/examples/osmium_index_lookup.cpp
vendored
Normal file
@ -0,0 +1,333 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
EXAMPLE osmium_index
|
||||||
|
|
||||||
|
Example program to look at Osmium indexes on disk.
|
||||||
|
|
||||||
|
You can use the osmium_dump_internal example program to create the offset
|
||||||
|
indexes or osmium_location_cache_create to create a node location index.
|
||||||
|
|
||||||
|
DEMONSTRATES USE OF:
|
||||||
|
* access to indexes on disk
|
||||||
|
|
||||||
|
SIMPLER EXAMPLES you might want to understand first:
|
||||||
|
* osmium_read
|
||||||
|
* osmium_count
|
||||||
|
* osmium_road_length
|
||||||
|
* osmium_location_cache_create
|
||||||
|
* osmium_location_cache_use
|
||||||
|
|
||||||
|
LICENSE
|
||||||
|
The code in this example file is released into the Public Domain.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <algorithm> // for std::all_of, std::equal_range
|
||||||
|
#include <cstdlib> // for std::exit
|
||||||
|
#include <fcntl.h> // for open
|
||||||
|
#include <getopt.h> // for getopt_long
|
||||||
|
#include <iostream> // for std::cout, std::cerr
|
||||||
|
#include <memory> // for std::unique_ptr
|
||||||
|
#include <string> // for std::string
|
||||||
|
#include <sys/stat.h> // for open
|
||||||
|
#include <sys/types.h> // for open
|
||||||
|
#include <vector> // for std::vector
|
||||||
|
|
||||||
|
// Disk-based indexes
|
||||||
|
#include <osmium/index/map/dense_file_array.hpp>
|
||||||
|
#include <osmium/index/map/sparse_file_array.hpp>
|
||||||
|
|
||||||
|
// osmium::Location
|
||||||
|
#include <osmium/osm/location.hpp>
|
||||||
|
|
||||||
|
// Basic Osmium types
|
||||||
|
#include <osmium/osm/types.hpp>
|
||||||
|
|
||||||
|
// Virtual class for disk index access. If offers functions to dump the
|
||||||
|
// indexes and to search for ids in the index.
|
||||||
|
template <typename TValue>
|
||||||
|
class IndexAccess {
|
||||||
|
|
||||||
|
int m_fd;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
IndexAccess(int fd) :
|
||||||
|
m_fd(fd) {
|
||||||
|
}
|
||||||
|
|
||||||
|
int fd() const noexcept {
|
||||||
|
return m_fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual ~IndexAccess() = default;
|
||||||
|
|
||||||
|
virtual void dump() const = 0;
|
||||||
|
|
||||||
|
virtual bool search(const osmium::unsigned_object_id_type& key) const = 0;
|
||||||
|
|
||||||
|
bool search(const std::vector<osmium::unsigned_object_id_type>& keys) const {
|
||||||
|
return std::all_of(keys.cbegin(), keys.cend(), [this](const osmium::unsigned_object_id_type& key) {
|
||||||
|
return search(key);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}; // class IndexAccess
|
||||||
|
|
||||||
|
// Implementation of IndexAccess for dense indexes usually used for very large
|
||||||
|
// extracts or the planet.
|
||||||
|
template <typename TValue>
|
||||||
|
class IndexAccessDense : public IndexAccess<TValue> {
|
||||||
|
|
||||||
|
using index_type = typename osmium::index::map::DenseFileArray<osmium::unsigned_object_id_type, TValue>;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
IndexAccessDense(int fd) :
|
||||||
|
IndexAccess<TValue>(fd) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void dump() const override {
|
||||||
|
index_type index{this->fd()};
|
||||||
|
|
||||||
|
for (std::size_t i = 0; i < index.size(); ++i) {
|
||||||
|
if (index.get(i) != TValue{}) {
|
||||||
|
std::cout << i << " " << index.get(i) << "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool search(const osmium::unsigned_object_id_type& key) const override {
|
||||||
|
index_type index{this->fd()};
|
||||||
|
|
||||||
|
try {
|
||||||
|
TValue value = index.get(key);
|
||||||
|
std::cout << key << " " << value << "\n";
|
||||||
|
} catch (...) {
|
||||||
|
std::cout << key << " not found\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}; // class IndexAccessDense
|
||||||
|
|
||||||
|
// Implementation of IndexAccess for sparse indexes usually used for small or
|
||||||
|
// medium sized extracts or for "multimap" type indexes.
|
||||||
|
template <typename TValue>
|
||||||
|
class IndexAccessSparse : public IndexAccess<TValue> {
|
||||||
|
|
||||||
|
using index_type = typename osmium::index::map::SparseFileArray<osmium::unsigned_object_id_type, TValue>;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
IndexAccessSparse(int fd) :
|
||||||
|
IndexAccess<TValue>(fd) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void dump() const override {
|
||||||
|
index_type index{this->fd()};
|
||||||
|
|
||||||
|
for (const auto& element : index) {
|
||||||
|
std::cout << element.first << " " << element.second << "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool search(const osmium::unsigned_object_id_type& key) const override {
|
||||||
|
using element_type = typename index_type::element_type;
|
||||||
|
index_type index{this->fd()};
|
||||||
|
|
||||||
|
element_type elem{key, TValue{}};
|
||||||
|
const auto positions = std::equal_range(index.begin(),
|
||||||
|
index.end(),
|
||||||
|
elem,
|
||||||
|
[](const element_type& lhs,
|
||||||
|
const element_type& rhs) {
|
||||||
|
return lhs.first < rhs.first;
|
||||||
|
});
|
||||||
|
if (positions.first == positions.second) {
|
||||||
|
std::cout << key << " not found\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto it = positions.first; it != positions.second; ++it) {
|
||||||
|
std::cout << it->first << " " << it->second << "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}; // class IndexAccessSparse
|
||||||
|
|
||||||
|
// This class contains the code to parse the command line arguments, check
|
||||||
|
// them and present the results to the rest of the program in an easy-to-use
|
||||||
|
// way.
|
||||||
|
class Options {
|
||||||
|
|
||||||
|
std::vector<osmium::unsigned_object_id_type> m_ids;
|
||||||
|
std::string m_type;
|
||||||
|
std::string m_filename;
|
||||||
|
bool m_dump = false;
|
||||||
|
bool m_array_format = false;
|
||||||
|
bool m_list_format = false;
|
||||||
|
|
||||||
|
void print_help() {
|
||||||
|
std::cout << "Usage: osmium_index_lookup [OPTIONS]\n\n"
|
||||||
|
<< "-h, --help Print this help message\n"
|
||||||
|
<< "-a, --array=FILE Read given index file in array format\n"
|
||||||
|
<< "-l, --list=FILE Read given index file in list format\n"
|
||||||
|
<< "-d, --dump Dump contents of index file to STDOUT\n"
|
||||||
|
<< "-s, --search=ID Search for given id (Option can appear multiple times)\n"
|
||||||
|
<< "-t, --type=TYPE Type of value ('location', 'id', or 'offset')\n"
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
Options(int argc, char* argv[]) {
|
||||||
|
if (argc == 1) {
|
||||||
|
print_help();
|
||||||
|
std::exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct option long_options[] = {
|
||||||
|
{"array", required_argument, 0, 'a'},
|
||||||
|
{"dump", no_argument, 0, 'd'},
|
||||||
|
{"help", no_argument, 0, 'h'},
|
||||||
|
{"list", required_argument, 0, 'l'},
|
||||||
|
{"search", required_argument, 0, 's'},
|
||||||
|
{"type", required_argument, 0, 't'},
|
||||||
|
{0, 0, 0, 0}
|
||||||
|
};
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
const int c = getopt_long(argc, argv, "a:dhl:s:t:", long_options, 0);
|
||||||
|
if (c == -1) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (c) {
|
||||||
|
case 'a':
|
||||||
|
m_array_format = true;
|
||||||
|
m_filename = optarg;
|
||||||
|
break;
|
||||||
|
case 'd':
|
||||||
|
m_dump = true;
|
||||||
|
break;
|
||||||
|
case 'h':
|
||||||
|
print_help();
|
||||||
|
std::exit(0);
|
||||||
|
case 'l':
|
||||||
|
m_list_format = true;
|
||||||
|
m_filename = optarg;
|
||||||
|
break;
|
||||||
|
case 's':
|
||||||
|
m_ids.push_back(std::atoll(optarg));
|
||||||
|
break;
|
||||||
|
case 't':
|
||||||
|
m_type = optarg;
|
||||||
|
if (m_type != "location" && m_type != "id" && m_type != "offset") {
|
||||||
|
std::cerr << "Unknown type '" << m_type
|
||||||
|
<< "'. Must be 'location', 'id', or 'offset'.\n";
|
||||||
|
std::exit(2);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
std::exit(2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_array_format == m_list_format) {
|
||||||
|
std::cerr << "Need option --array or --list, but not both\n";
|
||||||
|
std::exit(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_dump && !m_ids.empty()) {
|
||||||
|
std::cerr << "Need option --dump or --search, but not both\n";
|
||||||
|
std::exit(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_type.empty()) {
|
||||||
|
std::cerr << "Need --type argument.\n";
|
||||||
|
std::exit(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* filename() const noexcept {
|
||||||
|
return m_filename.c_str();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool dense_format() const noexcept {
|
||||||
|
return m_array_format;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool do_dump() const noexcept {
|
||||||
|
return m_dump;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::vector<osmium::unsigned_object_id_type>& search_keys() const noexcept {
|
||||||
|
return m_ids;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool type_is(const char* type) const noexcept {
|
||||||
|
return m_type == type;
|
||||||
|
}
|
||||||
|
|
||||||
|
}; // class Options
|
||||||
|
|
||||||
|
|
||||||
|
// Factory function to create the right IndexAccess-derived class.
|
||||||
|
template <typename TValue>
|
||||||
|
std::unique_ptr<IndexAccess<TValue>> create(bool dense, int fd) {
|
||||||
|
std::unique_ptr<IndexAccess<TValue>> ptr;
|
||||||
|
|
||||||
|
if (dense) {
|
||||||
|
ptr.reset(new IndexAccessDense<TValue>{fd});
|
||||||
|
} else {
|
||||||
|
ptr.reset(new IndexAccessSparse<TValue>{fd});
|
||||||
|
}
|
||||||
|
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Do the actual work: Either dump the index or search in the index.
|
||||||
|
template <typename TValue>
|
||||||
|
int run(const IndexAccess<TValue>& index, const Options& options) {
|
||||||
|
if (options.do_dump()) {
|
||||||
|
index.dump();
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
return index.search(options.search_keys()) ? 0 : 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char* argv[]) {
|
||||||
|
// Parse command line options.
|
||||||
|
Options options{argc, argv};
|
||||||
|
|
||||||
|
// Open the index file.
|
||||||
|
const int fd = open(options.filename(), O_RDWR);
|
||||||
|
if (fd < 0) {
|
||||||
|
std::cerr << "Can not open file '" << options.filename()
|
||||||
|
<< "': " << std::strerror(errno) << '\n';
|
||||||
|
std::exit(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Depending on the type of index, we have different implementations.
|
||||||
|
if (options.type_is("location")) {
|
||||||
|
// index id -> location
|
||||||
|
const auto index = create<osmium::Location>(options.dense_format(), fd);
|
||||||
|
return run(*index, options);
|
||||||
|
} else if (options.type_is("id")) {
|
||||||
|
// index id -> id
|
||||||
|
const auto index = create<osmium::unsigned_object_id_type>(options.dense_format(), fd);
|
||||||
|
return run(*index, options);
|
||||||
|
} else {
|
||||||
|
// index id -> offset
|
||||||
|
const auto index = create<std::size_t>(options.dense_format(), fd);
|
||||||
|
return run(*index, options);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
0
third_party/libosmium/examples/osmium_pub_names.cpp
vendored
Executable file → Normal file
0
third_party/libosmium/examples/osmium_pub_names.cpp
vendored
Executable file → Normal file
0
third_party/libosmium/examples/osmium_road_length.cpp
vendored
Executable file → Normal file
0
third_party/libosmium/examples/osmium_road_length.cpp
vendored
Executable file → Normal file
206
third_party/libosmium/examples/osmium_serdump.cpp
vendored
206
third_party/libosmium/examples/osmium_serdump.cpp
vendored
@ -1,206 +0,0 @@
|
|||||||
/*
|
|
||||||
|
|
||||||
This is a small tool to dump the contents of the input file
|
|
||||||
in serialized format to stdout.
|
|
||||||
|
|
||||||
The code in this example file is released into the Public Domain.
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <cerrno>
|
|
||||||
#include <cstring>
|
|
||||||
#include <getopt.h>
|
|
||||||
#include <iostream>
|
|
||||||
#include <string>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
|
||||||
# include <direct.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <osmium/io/any_input.hpp>
|
|
||||||
#include <osmium/handler/disk_store.hpp>
|
|
||||||
#include <osmium/handler/object_relations.hpp>
|
|
||||||
|
|
||||||
#include <osmium/index/map/sparse_mem_array.hpp>
|
|
||||||
#include <osmium/index/multimap/sparse_mem_multimap.hpp>
|
|
||||||
#include <osmium/index/multimap/sparse_mem_array.hpp>
|
|
||||||
#include <osmium/index/multimap/hybrid.hpp>
|
|
||||||
|
|
||||||
// ==============================================================================
|
|
||||||
// Choose the following depending on the size of the input OSM files:
|
|
||||||
// ==============================================================================
|
|
||||||
// for smaller OSM files (extracts)
|
|
||||||
typedef osmium::index::map::SparseMemArray<osmium::unsigned_object_id_type, size_t> offset_index_type;
|
|
||||||
//typedef osmium::index::map::SparseMapMmap<osmium::unsigned_object_id_type, size_t> offset_index_type;
|
|
||||||
//typedef osmium::index::map::SparseMapFile<osmium::unsigned_object_id_type, size_t> offset_index_type;
|
|
||||||
|
|
||||||
typedef osmium::index::multimap::SparseMemArray<osmium::unsigned_object_id_type, osmium::unsigned_object_id_type> map_type;
|
|
||||||
//typedef osmium::index::multimap::SparseMemMultimap<osmium::unsigned_object_id_type, osmium::unsigned_object_id_type> map_type;
|
|
||||||
//typedef osmium::index::multimap::Hybrid<osmium::unsigned_object_id_type, osmium::unsigned_object_id_type> map_type;
|
|
||||||
|
|
||||||
// ==============================================================================
|
|
||||||
// for very large OSM files (planet)
|
|
||||||
//typedef osmium::index::map::DenseMmapArray<osmium::unsigned_object_id_type, size_t> offset_index_type;
|
|
||||||
// ==============================================================================
|
|
||||||
|
|
||||||
void print_help() {
|
|
||||||
std::cout << "osmium_serdump OSMFILE DIR\n" \
|
|
||||||
<< "Serialize content of OSMFILE into data file in DIR.\n" \
|
|
||||||
<< "\nOptions:\n" \
|
|
||||||
<< " -h, --help This help message\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(int argc, char* argv[]) {
|
|
||||||
std::ios_base::sync_with_stdio(false);
|
|
||||||
|
|
||||||
static struct option long_options[] = {
|
|
||||||
{"help", no_argument, 0, 'h'},
|
|
||||||
{0, 0, 0, 0}
|
|
||||||
};
|
|
||||||
|
|
||||||
while (true) {
|
|
||||||
int c = getopt_long(argc, argv, "h", long_options, 0);
|
|
||||||
if (c == -1) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (c) {
|
|
||||||
case 'h':
|
|
||||||
print_help();
|
|
||||||
std::exit(0);
|
|
||||||
default:
|
|
||||||
std::exit(2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int remaining_args = argc - optind;
|
|
||||||
|
|
||||||
if (remaining_args != 2) {
|
|
||||||
std::cerr << "Usage: " << argv[0] << " OSMFILE DIR\n";
|
|
||||||
std::exit(2);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string dir(argv[optind+1]);
|
|
||||||
#ifndef _WIN32
|
|
||||||
int result = ::mkdir(dir.c_str(), 0777);
|
|
||||||
#else
|
|
||||||
int result = mkdir(dir.c_str());
|
|
||||||
#endif
|
|
||||||
if (result == -1 && errno != EEXIST) {
|
|
||||||
std::cerr << "Problem creating directory '" << dir << "': " << strerror(errno) << "\n";
|
|
||||||
std::exit(2);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string data_file(dir + "/data.osm.ser");
|
|
||||||
int data_fd = ::open(data_file.c_str(), O_WRONLY | O_CREAT | O_TRUNC, 0666);
|
|
||||||
if (data_fd < 0) {
|
|
||||||
std::cerr << "Can't open data file '" << data_file << "': " << strerror(errno) << "\n";
|
|
||||||
std::exit(2);
|
|
||||||
}
|
|
||||||
|
|
||||||
offset_index_type node_index;
|
|
||||||
offset_index_type way_index;
|
|
||||||
offset_index_type relation_index;
|
|
||||||
|
|
||||||
osmium::handler::DiskStore disk_store_handler(data_fd, node_index, way_index, relation_index);
|
|
||||||
|
|
||||||
map_type map_node2way;
|
|
||||||
map_type map_node2relation;
|
|
||||||
map_type map_way2relation;
|
|
||||||
map_type map_relation2relation;
|
|
||||||
|
|
||||||
osmium::handler::ObjectRelations object_relations_handler(map_node2way, map_node2relation, map_way2relation, map_relation2relation);
|
|
||||||
|
|
||||||
osmium::io::Reader reader(argv[1]);
|
|
||||||
|
|
||||||
while (osmium::memory::Buffer buffer = reader.read()) {
|
|
||||||
disk_store_handler(buffer); // XXX
|
|
||||||
osmium::apply(buffer, object_relations_handler);
|
|
||||||
}
|
|
||||||
|
|
||||||
reader.close();
|
|
||||||
|
|
||||||
{
|
|
||||||
std::string index_file(dir + "/nodes.idx");
|
|
||||||
int fd = ::open(index_file.c_str(), O_WRONLY | O_CREAT | O_TRUNC, 0666);
|
|
||||||
if (fd < 0) {
|
|
||||||
std::cerr << "Can't open nodes index file '" << index_file << "': " << strerror(errno) << "\n";
|
|
||||||
std::exit(2);
|
|
||||||
}
|
|
||||||
node_index.dump_as_list(fd);
|
|
||||||
close(fd);
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
std::string index_file(dir + "/ways.idx");
|
|
||||||
int fd = ::open(index_file.c_str(), O_WRONLY | O_CREAT | O_TRUNC, 0666);
|
|
||||||
if (fd < 0) {
|
|
||||||
std::cerr << "Can't open ways index file '" << index_file << "': " << strerror(errno) << "\n";
|
|
||||||
std::exit(2);
|
|
||||||
}
|
|
||||||
way_index.dump_as_list(fd);
|
|
||||||
close(fd);
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
std::string index_file(dir + "/relations.idx");
|
|
||||||
int fd = ::open(index_file.c_str(), O_WRONLY | O_CREAT | O_TRUNC, 0666);
|
|
||||||
if (fd < 0) {
|
|
||||||
std::cerr << "Can't open relations index file '" << index_file << "': " << strerror(errno) << "\n";
|
|
||||||
std::exit(2);
|
|
||||||
}
|
|
||||||
relation_index.dump_as_list(fd);
|
|
||||||
close(fd);
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
map_node2way.sort();
|
|
||||||
std::string index_file(dir + "/node2way.map");
|
|
||||||
int fd = ::open(index_file.c_str(), O_WRONLY | O_CREAT | O_TRUNC, 0666);
|
|
||||||
if (fd < 0) {
|
|
||||||
std::cerr << "Can't open node->way map file '" << index_file << "': " << strerror(errno) << "\n";
|
|
||||||
std::exit(2);
|
|
||||||
}
|
|
||||||
map_node2way.dump_as_list(fd);
|
|
||||||
close(fd);
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
map_node2relation.sort();
|
|
||||||
std::string index_file(dir + "/node2rel.map");
|
|
||||||
int fd = ::open(index_file.c_str(), O_WRONLY | O_CREAT | O_TRUNC, 0666);
|
|
||||||
if (fd < 0) {
|
|
||||||
std::cerr << "Can't open node->rel map file '" << index_file << "': " << strerror(errno) << "\n";
|
|
||||||
std::exit(2);
|
|
||||||
}
|
|
||||||
map_node2relation.dump_as_list(fd);
|
|
||||||
close(fd);
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
map_way2relation.sort();
|
|
||||||
std::string index_file(dir + "/way2rel.map");
|
|
||||||
int fd = ::open(index_file.c_str(), O_WRONLY | O_CREAT | O_TRUNC, 0666);
|
|
||||||
if (fd < 0) {
|
|
||||||
std::cerr << "Can't open way->rel map file '" << index_file << "': " << strerror(errno) << "\n";
|
|
||||||
std::exit(2);
|
|
||||||
}
|
|
||||||
map_way2relation.dump_as_list(fd);
|
|
||||||
close(fd);
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
map_relation2relation.sort();
|
|
||||||
std::string index_file(dir + "/rel2rel.map");
|
|
||||||
int fd = ::open(index_file.c_str(), O_WRONLY | O_CREAT | O_TRUNC, 0666);
|
|
||||||
if (fd < 0) {
|
|
||||||
std::cerr << "Can't open rel->rel map file '" << index_file << "': " << strerror(errno) << "\n";
|
|
||||||
std::exit(2);
|
|
||||||
}
|
|
||||||
map_relation2relation.dump_as_list(fd);
|
|
||||||
close(fd);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -193,12 +193,12 @@ namespace osmium {
|
|||||||
|
|
||||||
}; // struct location_to_ring_map
|
}; // struct location_to_ring_map
|
||||||
|
|
||||||
inline bool operator==(const location_to_ring_map& a, const location_to_ring_map& b) noexcept {
|
inline bool operator==(const location_to_ring_map& lhs, const location_to_ring_map& rhs) noexcept {
|
||||||
return a.location == b.location;
|
return lhs.location == rhs.location;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool operator<(const location_to_ring_map& a, const location_to_ring_map& b) noexcept {
|
inline bool operator<(const location_to_ring_map& lhs, const location_to_ring_map& rhs) noexcept {
|
||||||
return a.location < b.location;
|
return lhs.location < rhs.location;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
@ -288,7 +288,7 @@ namespace osmium {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void add_tags_to_area(osmium::builder::AreaBuilder& builder, const osmium::Way& way) const {
|
void add_tags_to_area(osmium::builder::AreaBuilder& builder, const osmium::Way& way) const {
|
||||||
builder.add_item(&way.tags());
|
builder.add_item(way.tags());
|
||||||
}
|
}
|
||||||
|
|
||||||
void add_common_tags(osmium::builder::TagListBuilder& tl_builder, std::set<const osmium::Way*>& ways) const {
|
void add_common_tags(osmium::builder::TagListBuilder& tl_builder, std::set<const osmium::Way*>& ways) const {
|
||||||
@ -333,7 +333,7 @@ namespace osmium {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void copy_tags_without_type(osmium::builder::AreaBuilder& builder, const osmium::TagList& tags) {
|
static void copy_tags_without_type(osmium::builder::AreaBuilder& builder, const osmium::TagList& tags) {
|
||||||
osmium::builder::TagListBuilder tl_builder(builder.buffer(), &builder);
|
osmium::builder::TagListBuilder tl_builder{builder};
|
||||||
for (const osmium::Tag& tag : tags) {
|
for (const osmium::Tag& tag : tags) {
|
||||||
if (std::strcmp(tag.key(), "type")) {
|
if (std::strcmp(tag.key(), "type")) {
|
||||||
tl_builder.add_tag(tag.key(), tag.value());
|
tl_builder.add_tag(tag.key(), tag.value());
|
||||||
@ -354,7 +354,7 @@ namespace osmium {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (m_config.keep_type_tag) {
|
if (m_config.keep_type_tag) {
|
||||||
builder.add_item(&relation.tags());
|
builder.add_item(relation.tags());
|
||||||
} else {
|
} else {
|
||||||
copy_tags_without_type(builder, relation.tags());
|
copy_tags_without_type(builder, relation.tags());
|
||||||
}
|
}
|
||||||
@ -373,12 +373,12 @@ namespace osmium {
|
|||||||
if (debug()) {
|
if (debug()) {
|
||||||
std::cerr << " only one outer way\n";
|
std::cerr << " only one outer way\n";
|
||||||
}
|
}
|
||||||
builder.add_item(&(*ways.cbegin())->tags());
|
builder.add_item((*ways.cbegin())->tags());
|
||||||
} else {
|
} else {
|
||||||
if (debug()) {
|
if (debug()) {
|
||||||
std::cerr << " multiple outer ways, get common tags\n";
|
std::cerr << " multiple outer ways, get common tags\n";
|
||||||
}
|
}
|
||||||
osmium::builder::TagListBuilder tl_builder(builder.buffer(), &builder);
|
osmium::builder::TagListBuilder tl_builder{builder};
|
||||||
add_common_tags(tl_builder, ways);
|
add_common_tags(tl_builder, ways);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -386,7 +386,7 @@ namespace osmium {
|
|||||||
|
|
||||||
template <typename TBuilder>
|
template <typename TBuilder>
|
||||||
static void build_ring_from_proto_ring(osmium::builder::AreaBuilder& builder, const detail::ProtoRing& ring) {
|
static void build_ring_from_proto_ring(osmium::builder::AreaBuilder& builder, const detail::ProtoRing& ring) {
|
||||||
TBuilder ring_builder(builder.buffer(), &builder);
|
TBuilder ring_builder{builder};
|
||||||
ring_builder.add_node_ref(ring.get_node_ref_start());
|
ring_builder.add_node_ref(ring.get_node_ref_start());
|
||||||
for (const auto& segment : ring.segments()) {
|
for (const auto& segment : ring.segments()) {
|
||||||
ring_builder.add_node_ref(segment->stop());
|
ring_builder.add_node_ref(segment->stop());
|
||||||
@ -458,8 +458,8 @@ namespace osmium {
|
|||||||
}
|
}
|
||||||
|
|
||||||
detail::NodeRefSegment* get_next_segment(const osmium::Location& location) {
|
detail::NodeRefSegment* get_next_segment(const osmium::Location& location) {
|
||||||
auto it = std::lower_bound(m_locations.begin(), m_locations.end(), slocation{}, [this, &location](const slocation& a, const slocation& b) {
|
auto it = std::lower_bound(m_locations.begin(), m_locations.end(), slocation{}, [this, &location](const slocation& lhs, const slocation& rhs) {
|
||||||
return a.location(m_segment_list, location) < b.location(m_segment_list, location);
|
return lhs.location(m_segment_list, location) < rhs.location(m_segment_list, location);
|
||||||
});
|
});
|
||||||
|
|
||||||
assert(it != m_locations.end());
|
assert(it != m_locations.end());
|
||||||
@ -744,8 +744,8 @@ namespace osmium {
|
|||||||
m_locations.emplace_back(n, true);
|
m_locations.emplace_back(n, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::stable_sort(m_locations.begin(), m_locations.end(), [this](const slocation& a, const slocation& b) {
|
std::stable_sort(m_locations.begin(), m_locations.end(), [this](const slocation& lhs, const slocation& rhs) {
|
||||||
return a.location(m_segment_list) < b.location(m_segment_list);
|
return lhs.location(m_segment_list) < rhs.location(m_segment_list);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1015,8 +1015,8 @@ namespace osmium {
|
|||||||
|
|
||||||
std::vector<location_to_ring_map> xrings = create_location_to_ring_map(open_ring_its);
|
std::vector<location_to_ring_map> xrings = create_location_to_ring_map(open_ring_its);
|
||||||
|
|
||||||
const auto ring_min = std::min_element(xrings.begin(), xrings.end(), [](const location_to_ring_map& a, const location_to_ring_map& b) {
|
const auto ring_min = std::min_element(xrings.begin(), xrings.end(), [](const location_to_ring_map& lhs, const location_to_ring_map& rhs) {
|
||||||
return a.ring().min_segment() < b.ring().min_segment();
|
return lhs.ring().min_segment() < rhs.ring().min_segment();
|
||||||
});
|
});
|
||||||
|
|
||||||
find_inner_outer_complex();
|
find_inner_outer_complex();
|
||||||
@ -1068,11 +1068,11 @@ namespace osmium {
|
|||||||
|
|
||||||
// Find the candidate with the smallest/largest area
|
// Find the candidate with the smallest/largest area
|
||||||
const auto chosen_cand = ring_min_is_outer ?
|
const auto chosen_cand = ring_min_is_outer ?
|
||||||
std::min_element(candidates.cbegin(), candidates.cend(), [](const candidate& a, const candidate& b) {
|
std::min_element(candidates.cbegin(), candidates.cend(), [](const candidate& lhs, const candidate& rhs) {
|
||||||
return std::abs(a.sum) < std::abs(b.sum);
|
return std::abs(lhs.sum) < std::abs(rhs.sum);
|
||||||
}) :
|
}) :
|
||||||
std::max_element(candidates.cbegin(), candidates.cend(), [](const candidate& a, const candidate& b) {
|
std::max_element(candidates.cbegin(), candidates.cend(), [](const candidate& lhs, const candidate& rhs) {
|
||||||
return std::abs(a.sum) < std::abs(b.sum);
|
return std::abs(lhs.sum) < std::abs(rhs.sum);
|
||||||
});
|
});
|
||||||
|
|
||||||
if (debug()) {
|
if (debug()) {
|
||||||
@ -1103,8 +1103,8 @@ namespace osmium {
|
|||||||
const auto locs = make_range(std::equal_range(m_locations.begin(),
|
const auto locs = make_range(std::equal_range(m_locations.begin(),
|
||||||
m_locations.end(),
|
m_locations.end(),
|
||||||
slocation{},
|
slocation{},
|
||||||
[this, &location](const slocation& a, const slocation& b) {
|
[this, &location](const slocation& lhs, const slocation& rhs) {
|
||||||
return a.location(m_segment_list, location) < b.location(m_segment_list, location);
|
return lhs.location(m_segment_list, location) < rhs.location(m_segment_list, location);
|
||||||
}));
|
}));
|
||||||
for (auto& loc : locs) {
|
for (auto& loc : locs) {
|
||||||
if (!m_segment_list[loc.item].is_done()) {
|
if (!m_segment_list[loc.item].is_done()) {
|
||||||
@ -1267,8 +1267,8 @@ namespace osmium {
|
|||||||
}
|
}
|
||||||
for (const auto& location : m_split_locations) {
|
for (const auto& location : m_split_locations) {
|
||||||
if (m_config.problem_reporter) {
|
if (m_config.problem_reporter) {
|
||||||
auto it = std::lower_bound(m_locations.cbegin(), m_locations.cend(), slocation{}, [this, &location](const slocation& a, const slocation& b) {
|
auto it = std::lower_bound(m_locations.cbegin(), m_locations.cend(), slocation{}, [this, &location](const slocation& lhs, const slocation& rhs) {
|
||||||
return a.location(m_segment_list, location) < b.location(m_segment_list, location);
|
return lhs.location(m_segment_list, location) < rhs.location(m_segment_list, location);
|
||||||
});
|
});
|
||||||
assert(it != m_locations.cend());
|
assert(it != m_locations.cend());
|
||||||
const osmium::object_id_type id = it->node_ref(m_segment_list).ref();
|
const osmium::object_id_type id = it->node_ref(m_segment_list).ref();
|
||||||
@ -1362,7 +1362,7 @@ namespace osmium {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
bool create_area(osmium::memory::Buffer& out_buffer, const osmium::Way& way) {
|
bool create_area(osmium::memory::Buffer& out_buffer, const osmium::Way& way) {
|
||||||
osmium::builder::AreaBuilder builder(out_buffer);
|
osmium::builder::AreaBuilder builder{out_buffer};
|
||||||
builder.initialize_from_object(way);
|
builder.initialize_from_object(way);
|
||||||
|
|
||||||
const bool area_okay = create_rings();
|
const bool area_okay = create_rings();
|
||||||
@ -1382,7 +1382,7 @@ namespace osmium {
|
|||||||
|
|
||||||
bool create_area(osmium::memory::Buffer& out_buffer, const osmium::Relation& relation, const std::vector<const osmium::Way*>& members) {
|
bool create_area(osmium::memory::Buffer& out_buffer, const osmium::Relation& relation, const std::vector<const osmium::Way*>& members) {
|
||||||
m_num_members = members.size();
|
m_num_members = members.size();
|
||||||
osmium::builder::AreaBuilder builder(out_buffer);
|
osmium::builder::AreaBuilder builder{out_buffer};
|
||||||
builder.initialize_from_object(relation);
|
builder.initialize_from_object(relation);
|
||||||
|
|
||||||
const bool area_okay = create_rings();
|
const bool area_okay = create_rings();
|
||||||
|
@ -379,8 +379,8 @@ namespace osmium {
|
|||||||
sl[2] = {1, s2.first().location() };
|
sl[2] = {1, s2.first().location() };
|
||||||
sl[3] = {1, s2.second().location()};
|
sl[3] = {1, s2.second().location()};
|
||||||
|
|
||||||
std::sort(sl, sl+4, [](const seg_loc& a, const seg_loc& b) {
|
std::sort(sl, sl+4, [](const seg_loc& lhs, const seg_loc& rhs) {
|
||||||
return a.location < b.location;
|
return lhs.location < rhs.location;
|
||||||
});
|
});
|
||||||
|
|
||||||
if (sl[1].location == sl[2].location) {
|
if (sl[1].location == sl[2].location) {
|
||||||
|
@ -101,7 +101,7 @@ namespace osmium {
|
|||||||
* Calculate the number of segments in all the ways together.
|
* Calculate the number of segments in all the ways together.
|
||||||
*/
|
*/
|
||||||
static size_t get_num_segments(const std::vector<const osmium::Way*>& members) noexcept {
|
static size_t get_num_segments(const std::vector<const osmium::Way*>& members) noexcept {
|
||||||
return std::accumulate(members.cbegin(), members.cend(), 0, [](size_t sum, const osmium::Way* way) {
|
return std::accumulate(members.cbegin(), members.cend(), static_cast<size_t>(0), [](size_t sum, const osmium::Way* way) {
|
||||||
if (way->nodes().empty()) {
|
if (way->nodes().empty()) {
|
||||||
return sum;
|
return sum;
|
||||||
} else {
|
} else {
|
||||||
|
@ -73,18 +73,18 @@ namespace osmium {
|
|||||||
}; // struct vec
|
}; // struct vec
|
||||||
|
|
||||||
// addition
|
// addition
|
||||||
constexpr inline vec operator+(const vec& a, const vec& b) noexcept {
|
constexpr inline vec operator+(const vec& lhs, const vec& rhs) noexcept {
|
||||||
return vec{a.x + b.x, a.y + b.y};
|
return vec{lhs.x + rhs.x, lhs.y + rhs.y};
|
||||||
}
|
}
|
||||||
|
|
||||||
// subtraction
|
// subtraction
|
||||||
constexpr inline vec operator-(const vec& a, const vec& b) noexcept {
|
constexpr inline vec operator-(const vec& lhs, const vec& rhs) noexcept {
|
||||||
return vec{a.x - b.x, a.y - b.y};
|
return vec{lhs.x - rhs.x, lhs.y - rhs.y};
|
||||||
}
|
}
|
||||||
|
|
||||||
// cross product
|
// cross product
|
||||||
constexpr inline int64_t operator*(const vec& a, const vec& b) noexcept {
|
constexpr inline int64_t operator*(const vec& lhs, const vec& rhs) noexcept {
|
||||||
return a.x * b.y - a.y * b.x;
|
return lhs.x * rhs.y - lhs.y * rhs.x;
|
||||||
}
|
}
|
||||||
|
|
||||||
// scale vector
|
// scale vector
|
||||||
@ -98,13 +98,13 @@ namespace osmium {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// equality
|
// equality
|
||||||
constexpr inline bool operator==(const vec& a, const vec& b) noexcept {
|
constexpr inline bool operator==(const vec& lhs, const vec& rhs) noexcept {
|
||||||
return a.x == b.x && a.y == b.y;
|
return lhs.x == rhs.x && lhs.y == rhs.y;
|
||||||
}
|
}
|
||||||
|
|
||||||
// inequality
|
// inequality
|
||||||
constexpr inline bool operator!=(const vec& a, const vec& b) noexcept {
|
constexpr inline bool operator!=(const vec& lhs, const vec& rhs) noexcept {
|
||||||
return !(a == b);
|
return !(lhs == rhs);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename TChar, typename TTraits>
|
template <typename TChar, typename TTraits>
|
||||||
|
@ -617,7 +617,7 @@ namespace osmium {
|
|||||||
|
|
||||||
template <typename TBuilder, typename... TArgs>
|
template <typename TBuilder, typename... TArgs>
|
||||||
inline void add_user(TBuilder& builder, const TArgs&... args) {
|
inline void add_user(TBuilder& builder, const TArgs&... args) {
|
||||||
builder.add_user(get_user(args...));
|
builder.set_user(get_user(args...));
|
||||||
}
|
}
|
||||||
|
|
||||||
// ==============================================================
|
// ==============================================================
|
||||||
@ -761,11 +761,13 @@ namespace osmium {
|
|||||||
static_assert(sizeof...(args) > 0, "add_node() must have buffer and at least one additional argument");
|
static_assert(sizeof...(args) > 0, "add_node() must have buffer and at least one additional argument");
|
||||||
static_assert(detail::are_all_handled_by<detail::any_node_handlers, TArgs...>::value, "Attribute not allowed in add_node()");
|
static_assert(detail::are_all_handled_by<detail::any_node_handlers, TArgs...>::value, "Attribute not allowed in add_node()");
|
||||||
|
|
||||||
NodeBuilder builder(buffer);
|
{
|
||||||
|
NodeBuilder builder(buffer);
|
||||||
|
|
||||||
detail::add_basic<detail::node_handler>(builder, args...);
|
detail::add_basic<detail::node_handler>(builder, args...);
|
||||||
detail::add_user(builder, args...);
|
detail::add_user(builder, args...);
|
||||||
detail::add_list<TagListBuilder, detail::tags_handler>(builder, args...);
|
detail::add_list<TagListBuilder, detail::tags_handler>(builder, args...);
|
||||||
|
}
|
||||||
|
|
||||||
return buffer.commit();
|
return buffer.commit();
|
||||||
}
|
}
|
||||||
@ -782,12 +784,14 @@ namespace osmium {
|
|||||||
static_assert(sizeof...(args) > 0, "add_way() must have buffer and at least one additional argument");
|
static_assert(sizeof...(args) > 0, "add_way() must have buffer and at least one additional argument");
|
||||||
static_assert(detail::are_all_handled_by<detail::any_way_handlers, TArgs...>::value, "Attribute not allowed in add_way()");
|
static_assert(detail::are_all_handled_by<detail::any_way_handlers, TArgs...>::value, "Attribute not allowed in add_way()");
|
||||||
|
|
||||||
WayBuilder builder(buffer);
|
{
|
||||||
|
WayBuilder builder(buffer);
|
||||||
|
|
||||||
detail::add_basic<detail::object_handler>(builder, args...);
|
detail::add_basic<detail::object_handler>(builder, args...);
|
||||||
detail::add_user(builder, args...);
|
detail::add_user(builder, args...);
|
||||||
detail::add_list<TagListBuilder, detail::tags_handler>(builder, args...);
|
detail::add_list<TagListBuilder, detail::tags_handler>(builder, args...);
|
||||||
detail::add_list<WayNodeListBuilder, detail::nodes_handler>(builder, args...);
|
detail::add_list<WayNodeListBuilder, detail::nodes_handler>(builder, args...);
|
||||||
|
}
|
||||||
|
|
||||||
return buffer.commit();
|
return buffer.commit();
|
||||||
}
|
}
|
||||||
@ -804,12 +808,14 @@ namespace osmium {
|
|||||||
static_assert(sizeof...(args) > 0, "add_relation() must have buffer and at least one additional argument");
|
static_assert(sizeof...(args) > 0, "add_relation() must have buffer and at least one additional argument");
|
||||||
static_assert(detail::are_all_handled_by<detail::any_relation_handlers, TArgs...>::value, "Attribute not allowed in add_relation()");
|
static_assert(detail::are_all_handled_by<detail::any_relation_handlers, TArgs...>::value, "Attribute not allowed in add_relation()");
|
||||||
|
|
||||||
RelationBuilder builder(buffer);
|
{
|
||||||
|
RelationBuilder builder(buffer);
|
||||||
|
|
||||||
detail::add_basic<detail::object_handler>(builder, args...);
|
detail::add_basic<detail::object_handler>(builder, args...);
|
||||||
detail::add_user(builder, args...);
|
detail::add_user(builder, args...);
|
||||||
detail::add_list<TagListBuilder, detail::tags_handler>(builder, args...);
|
detail::add_list<TagListBuilder, detail::tags_handler>(builder, args...);
|
||||||
detail::add_list<RelationMemberListBuilder, detail::members_handler>(builder, args...);
|
detail::add_list<RelationMemberListBuilder, detail::members_handler>(builder, args...);
|
||||||
|
}
|
||||||
|
|
||||||
return buffer.commit();
|
return buffer.commit();
|
||||||
}
|
}
|
||||||
@ -826,12 +832,14 @@ namespace osmium {
|
|||||||
static_assert(sizeof...(args) > 0, "add_changeset() must have buffer and at least one additional argument");
|
static_assert(sizeof...(args) > 0, "add_changeset() must have buffer and at least one additional argument");
|
||||||
static_assert(detail::are_all_handled_by<detail::any_changeset_handlers, TArgs...>::value, "Attribute not allowed in add_changeset()");
|
static_assert(detail::are_all_handled_by<detail::any_changeset_handlers, TArgs...>::value, "Attribute not allowed in add_changeset()");
|
||||||
|
|
||||||
ChangesetBuilder builder(buffer);
|
{
|
||||||
|
ChangesetBuilder builder(buffer);
|
||||||
|
|
||||||
detail::add_basic<detail::changeset_handler>(builder, args...);
|
detail::add_basic<detail::changeset_handler>(builder, args...);
|
||||||
detail::add_user(builder, args...);
|
detail::add_user(builder, args...);
|
||||||
detail::add_list<TagListBuilder, detail::tags_handler>(builder, args...);
|
detail::add_list<TagListBuilder, detail::tags_handler>(builder, args...);
|
||||||
detail::add_list<ChangesetDiscussionBuilder, detail::discussion_handler>(builder, args...);
|
detail::add_list<ChangesetDiscussionBuilder, detail::discussion_handler>(builder, args...);
|
||||||
|
}
|
||||||
|
|
||||||
return buffer.commit();
|
return buffer.commit();
|
||||||
}
|
}
|
||||||
@ -848,15 +856,17 @@ namespace osmium {
|
|||||||
static_assert(sizeof...(args) > 0, "add_area() must have buffer and at least one additional argument");
|
static_assert(sizeof...(args) > 0, "add_area() must have buffer and at least one additional argument");
|
||||||
static_assert(detail::are_all_handled_by<detail::any_area_handlers, TArgs...>::value, "Attribute not allowed in add_area()");
|
static_assert(detail::are_all_handled_by<detail::any_area_handlers, TArgs...>::value, "Attribute not allowed in add_area()");
|
||||||
|
|
||||||
AreaBuilder builder(buffer);
|
{
|
||||||
|
AreaBuilder builder(buffer);
|
||||||
|
|
||||||
detail::add_basic<detail::object_handler>(builder, args...);
|
detail::add_basic<detail::object_handler>(builder, args...);
|
||||||
detail::add_user(builder, args...);
|
detail::add_user(builder, args...);
|
||||||
detail::add_list<TagListBuilder, detail::tags_handler>(builder, args...);
|
detail::add_list<TagListBuilder, detail::tags_handler>(builder, args...);
|
||||||
|
|
||||||
(void)std::initializer_list<int>{
|
(void)std::initializer_list<int>{
|
||||||
(detail::ring_handler::set_value(builder, args), 0)...
|
(detail::ring_handler::set_value(builder, args), 0)...
|
||||||
};
|
};
|
||||||
|
}
|
||||||
|
|
||||||
return buffer.commit();
|
return buffer.commit();
|
||||||
}
|
}
|
||||||
|
@ -45,6 +45,7 @@ DEALINGS IN THE SOFTWARE.
|
|||||||
#include <osmium/memory/item.hpp>
|
#include <osmium/memory/item.hpp>
|
||||||
#include <osmium/osm/types.hpp>
|
#include <osmium/osm/types.hpp>
|
||||||
#include <osmium/util/cast.hpp>
|
#include <osmium/util/cast.hpp>
|
||||||
|
#include <osmium/util/compatibility.hpp>
|
||||||
|
|
||||||
namespace osmium {
|
namespace osmium {
|
||||||
|
|
||||||
@ -53,6 +54,10 @@ namespace osmium {
|
|||||||
*/
|
*/
|
||||||
namespace builder {
|
namespace builder {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parent class for individual builder classes. Instantiate one of
|
||||||
|
* its derived classes.
|
||||||
|
*/
|
||||||
class Builder {
|
class Builder {
|
||||||
|
|
||||||
osmium::memory::Buffer& m_buffer;
|
osmium::memory::Buffer& m_buffer;
|
||||||
@ -71,20 +76,34 @@ namespace osmium {
|
|||||||
m_buffer(buffer),
|
m_buffer(buffer),
|
||||||
m_parent(parent),
|
m_parent(parent),
|
||||||
m_item_offset(buffer.written()) {
|
m_item_offset(buffer.written()) {
|
||||||
m_buffer.reserve_space(size);
|
reserve_space(size);
|
||||||
assert(buffer.is_aligned());
|
assert(buffer.is_aligned());
|
||||||
if (m_parent) {
|
if (m_parent) {
|
||||||
|
assert(m_buffer.builder_count() == 1 && "Only one sub-builder can be open at any time.");
|
||||||
m_parent->add_size(size);
|
m_parent->add_size(size);
|
||||||
|
} else {
|
||||||
|
assert(m_buffer.builder_count() == 0 && "Only one builder can be open at any time.");
|
||||||
}
|
}
|
||||||
|
#ifndef NDEBUG
|
||||||
|
m_buffer.increment_builder_count();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef NDEBUG
|
||||||
~Builder() = default;
|
~Builder() = default;
|
||||||
|
#else
|
||||||
|
~Builder() noexcept {
|
||||||
|
m_buffer.decrement_builder_count();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
osmium::memory::Item& item() const {
|
osmium::memory::Item& item() const {
|
||||||
return *reinterpret_cast<osmium::memory::Item*>(m_buffer.data() + m_item_offset);
|
return *reinterpret_cast<osmium::memory::Item*>(m_buffer.data() + m_item_offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
unsigned char* reserve_space(size_t size) {
|
||||||
|
return m_buffer.reserve_space(size);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add padding to buffer (if needed) to align data properly.
|
* Add padding to buffer (if needed) to align data properly.
|
||||||
@ -102,7 +121,7 @@ namespace osmium {
|
|||||||
void add_padding(bool self = false) {
|
void add_padding(bool self = false) {
|
||||||
const auto padding = osmium::memory::align_bytes - (size() % osmium::memory::align_bytes);
|
const auto padding = osmium::memory::align_bytes - (size() % osmium::memory::align_bytes);
|
||||||
if (padding != osmium::memory::align_bytes) {
|
if (padding != osmium::memory::align_bytes) {
|
||||||
std::fill_n(m_buffer.reserve_space(padding), padding, 0);
|
std::fill_n(reserve_space(padding), padding, 0);
|
||||||
if (self) {
|
if (self) {
|
||||||
add_size(padding);
|
add_size(padding);
|
||||||
} else if (m_parent) {
|
} else if (m_parent) {
|
||||||
@ -123,12 +142,6 @@ namespace osmium {
|
|||||||
return item().byte_size();
|
return item().byte_size();
|
||||||
}
|
}
|
||||||
|
|
||||||
void add_item(const osmium::memory::Item* item) {
|
|
||||||
unsigned char* target = m_buffer.reserve_space(item->padded_size());
|
|
||||||
std::copy_n(reinterpret_cast<const unsigned char*>(item), item->padded_size(), target);
|
|
||||||
add_size(item->padded_size());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reserve space for an object of class T in buffer and return
|
* Reserve space for an object of class T in buffer and return
|
||||||
* pointer to it.
|
* pointer to it.
|
||||||
@ -136,7 +149,7 @@ namespace osmium {
|
|||||||
template <typename T>
|
template <typename T>
|
||||||
T* reserve_space_for() {
|
T* reserve_space_for() {
|
||||||
assert(m_buffer.is_aligned());
|
assert(m_buffer.is_aligned());
|
||||||
return reinterpret_cast<T*>(m_buffer.reserve_space(sizeof(T)));
|
return reinterpret_cast<T*>(reserve_space(sizeof(T)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -149,7 +162,7 @@ namespace osmium {
|
|||||||
* @returns The number of bytes appended (length).
|
* @returns The number of bytes appended (length).
|
||||||
*/
|
*/
|
||||||
osmium::memory::item_size_type append(const char* data, const osmium::memory::item_size_type 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);
|
unsigned char* target = reserve_space(length);
|
||||||
std::copy_n(reinterpret_cast<const unsigned char*>(data), length, target);
|
std::copy_n(reinterpret_cast<const unsigned char*>(data), length, target);
|
||||||
return length;
|
return length;
|
||||||
}
|
}
|
||||||
@ -170,65 +183,37 @@ namespace osmium {
|
|||||||
* @returns The number of bytes appended (always 1).
|
* @returns The number of bytes appended (always 1).
|
||||||
*/
|
*/
|
||||||
osmium::memory::item_size_type append_zero() {
|
osmium::memory::item_size_type append_zero() {
|
||||||
*m_buffer.reserve_space(1) = '\0';
|
*reserve_space(1) = '\0';
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
/// Return the buffer this builder is using.
|
/// Return the buffer this builder is using.
|
||||||
osmium::memory::Buffer& buffer() noexcept {
|
osmium::memory::Buffer& buffer() noexcept {
|
||||||
return m_buffer;
|
return m_buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a subitem to the object being built. This can be something
|
||||||
|
* like a TagList or RelationMemberList.
|
||||||
|
*/
|
||||||
|
void add_item(const osmium::memory::Item& item) {
|
||||||
|
m_buffer.add_item(item);
|
||||||
|
add_size(item.padded_size());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated Use the version of add_item() taking a
|
||||||
|
* reference instead.
|
||||||
|
*/
|
||||||
|
OSMIUM_DEPRECATED void add_item(const osmium::memory::Item* item) {
|
||||||
|
assert(item);
|
||||||
|
add_item(*item);
|
||||||
|
}
|
||||||
|
|
||||||
}; // class Builder
|
}; // class Builder
|
||||||
|
|
||||||
template <typename TItem>
|
|
||||||
class ObjectBuilder : public Builder {
|
|
||||||
|
|
||||||
static_assert(std::is_base_of<osmium::memory::Item, TItem>::value, "ObjectBuilder can only build objects derived from osmium::memory::Item");
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
explicit ObjectBuilder(osmium::memory::Buffer& buffer, Builder* parent = nullptr) :
|
|
||||||
Builder(buffer, parent, sizeof(TItem)) {
|
|
||||||
new (&item()) TItem();
|
|
||||||
}
|
|
||||||
|
|
||||||
TItem& object() noexcept {
|
|
||||||
return static_cast<TItem&>(item());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add user name to buffer.
|
|
||||||
*
|
|
||||||
* @param user Pointer to user name.
|
|
||||||
* @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 + 1);
|
|
||||||
add_size(append(user, length) + append_zero());
|
|
||||||
add_padding(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add user name to buffer.
|
|
||||||
*
|
|
||||||
* @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)));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add user name to buffer.
|
|
||||||
*
|
|
||||||
* @param user User name.
|
|
||||||
*/
|
|
||||||
void add_user(const std::string& user) {
|
|
||||||
add_user(user.data(), static_cast_with_assert<string_size_type>(user.size()));
|
|
||||||
}
|
|
||||||
|
|
||||||
}; // class ObjectBuilder
|
|
||||||
|
|
||||||
} // namespace builder
|
} // namespace builder
|
||||||
|
|
||||||
} // namespace osmium
|
} // namespace osmium
|
||||||
|
@ -45,6 +45,7 @@ DEALINGS IN THE SOFTWARE.
|
|||||||
#include <osmium/builder/builder.hpp>
|
#include <osmium/builder/builder.hpp>
|
||||||
#include <osmium/osm/item_type.hpp>
|
#include <osmium/osm/item_type.hpp>
|
||||||
#include <osmium/osm/location.hpp>
|
#include <osmium/osm/location.hpp>
|
||||||
|
#include <osmium/osm/node.hpp>
|
||||||
#include <osmium/osm/node_ref.hpp>
|
#include <osmium/osm/node_ref.hpp>
|
||||||
#include <osmium/osm/object.hpp>
|
#include <osmium/osm/object.hpp>
|
||||||
#include <osmium/osm/tag.hpp>
|
#include <osmium/osm/tag.hpp>
|
||||||
@ -55,6 +56,7 @@ DEALINGS IN THE SOFTWARE.
|
|||||||
#include <osmium/osm/relation.hpp>
|
#include <osmium/osm/relation.hpp>
|
||||||
#include <osmium/osm/timestamp.hpp>
|
#include <osmium/osm/timestamp.hpp>
|
||||||
#include <osmium/osm/way.hpp>
|
#include <osmium/osm/way.hpp>
|
||||||
|
#include <osmium/util/compatibility.hpp>
|
||||||
|
|
||||||
namespace osmium {
|
namespace osmium {
|
||||||
|
|
||||||
@ -66,12 +68,18 @@ namespace osmium {
|
|||||||
|
|
||||||
namespace builder {
|
namespace builder {
|
||||||
|
|
||||||
class TagListBuilder : public ObjectBuilder<TagList> {
|
class TagListBuilder : public Builder {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
explicit TagListBuilder(osmium::memory::Buffer& buffer, Builder* parent = nullptr) :
|
explicit TagListBuilder(osmium::memory::Buffer& buffer, Builder* parent = nullptr) :
|
||||||
ObjectBuilder<TagList>(buffer, parent) {
|
Builder(buffer, parent, sizeof(TagList)) {
|
||||||
|
new (&item()) TagList();
|
||||||
|
}
|
||||||
|
|
||||||
|
explicit TagListBuilder(Builder& parent) :
|
||||||
|
Builder(parent.buffer(), &parent, sizeof(TagList)) {
|
||||||
|
new (&item()) TagList();
|
||||||
}
|
}
|
||||||
|
|
||||||
~TagListBuilder() {
|
~TagListBuilder() {
|
||||||
@ -169,21 +177,27 @@ namespace osmium {
|
|||||||
}; // class TagListBuilder
|
}; // class TagListBuilder
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
class NodeRefListBuilder : public ObjectBuilder<T> {
|
class NodeRefListBuilder : public Builder {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
explicit NodeRefListBuilder(osmium::memory::Buffer& buffer, Builder* parent = nullptr) :
|
explicit NodeRefListBuilder(osmium::memory::Buffer& buffer, Builder* parent = nullptr) :
|
||||||
ObjectBuilder<T>(buffer, parent) {
|
Builder(buffer, parent, sizeof(T)) {
|
||||||
|
new (&item()) T();
|
||||||
|
}
|
||||||
|
|
||||||
|
explicit NodeRefListBuilder(Builder& parent) :
|
||||||
|
Builder(parent.buffer(), &parent, sizeof(T)) {
|
||||||
|
new (&item()) T();
|
||||||
}
|
}
|
||||||
|
|
||||||
~NodeRefListBuilder() {
|
~NodeRefListBuilder() {
|
||||||
static_cast<Builder*>(this)->add_padding();
|
add_padding();
|
||||||
}
|
}
|
||||||
|
|
||||||
void add_node_ref(const NodeRef& node_ref) {
|
void add_node_ref(const NodeRef& node_ref) {
|
||||||
new (static_cast<Builder*>(this)->reserve_space_for<osmium::NodeRef>()) osmium::NodeRef(node_ref);
|
new (reserve_space_for<osmium::NodeRef>()) osmium::NodeRef(node_ref);
|
||||||
static_cast<Builder*>(this)->add_size(sizeof(osmium::NodeRef));
|
add_size(sizeof(osmium::NodeRef));
|
||||||
}
|
}
|
||||||
|
|
||||||
void add_node_ref(const object_id_type ref, const osmium::Location& location = Location{}) {
|
void add_node_ref(const object_id_type ref, const osmium::Location& location = Location{}) {
|
||||||
@ -196,7 +210,7 @@ namespace osmium {
|
|||||||
using OuterRingBuilder = NodeRefListBuilder<OuterRing>;
|
using OuterRingBuilder = NodeRefListBuilder<OuterRing>;
|
||||||
using InnerRingBuilder = NodeRefListBuilder<InnerRing>;
|
using InnerRingBuilder = NodeRefListBuilder<InnerRing>;
|
||||||
|
|
||||||
class RelationMemberListBuilder : public ObjectBuilder<RelationMemberList> {
|
class RelationMemberListBuilder : public Builder {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add role to buffer.
|
* Add role to buffer.
|
||||||
@ -219,7 +233,13 @@ namespace osmium {
|
|||||||
public:
|
public:
|
||||||
|
|
||||||
explicit RelationMemberListBuilder(osmium::memory::Buffer& buffer, Builder* parent = nullptr) :
|
explicit RelationMemberListBuilder(osmium::memory::Buffer& buffer, Builder* parent = nullptr) :
|
||||||
ObjectBuilder<RelationMemberList>(buffer, parent) {
|
Builder(buffer, parent, sizeof(RelationMemberList)) {
|
||||||
|
new (&item()) RelationMemberList();
|
||||||
|
}
|
||||||
|
|
||||||
|
explicit RelationMemberListBuilder(Builder& parent) :
|
||||||
|
Builder(parent.buffer(), &parent, sizeof(RelationMemberList)) {
|
||||||
|
new (&item()) RelationMemberList();
|
||||||
}
|
}
|
||||||
|
|
||||||
~RelationMemberListBuilder() {
|
~RelationMemberListBuilder() {
|
||||||
@ -245,7 +265,7 @@ namespace osmium {
|
|||||||
add_size(sizeof(RelationMember));
|
add_size(sizeof(RelationMember));
|
||||||
add_role(*member, role, role_length);
|
add_role(*member, role, role_length);
|
||||||
if (full_member) {
|
if (full_member) {
|
||||||
add_item(full_member);
|
add_item(*full_member);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -281,7 +301,7 @@ namespace osmium {
|
|||||||
|
|
||||||
}; // class RelationMemberListBuilder
|
}; // class RelationMemberListBuilder
|
||||||
|
|
||||||
class ChangesetDiscussionBuilder : public ObjectBuilder<ChangesetDiscussion> {
|
class ChangesetDiscussionBuilder : public Builder {
|
||||||
|
|
||||||
osmium::ChangesetComment* m_comment = nullptr;
|
osmium::ChangesetComment* m_comment = nullptr;
|
||||||
|
|
||||||
@ -309,7 +329,13 @@ namespace osmium {
|
|||||||
public:
|
public:
|
||||||
|
|
||||||
explicit ChangesetDiscussionBuilder(osmium::memory::Buffer& buffer, Builder* parent = nullptr) :
|
explicit ChangesetDiscussionBuilder(osmium::memory::Buffer& buffer, Builder* parent = nullptr) :
|
||||||
ObjectBuilder<ChangesetDiscussion>(buffer, parent) {
|
Builder(buffer, parent, sizeof(ChangesetDiscussion)) {
|
||||||
|
new (&item()) ChangesetDiscussion();
|
||||||
|
}
|
||||||
|
|
||||||
|
explicit ChangesetDiscussionBuilder(Builder& parent) :
|
||||||
|
Builder(parent.buffer(), &parent, sizeof(ChangesetDiscussion)) {
|
||||||
|
new (&item()) ChangesetDiscussion();
|
||||||
}
|
}
|
||||||
|
|
||||||
~ChangesetDiscussionBuilder() {
|
~ChangesetDiscussionBuilder() {
|
||||||
@ -339,19 +365,101 @@ namespace osmium {
|
|||||||
|
|
||||||
}; // class ChangesetDiscussionBuilder
|
}; // class ChangesetDiscussionBuilder
|
||||||
|
|
||||||
template <typename T>
|
#define OSMIUM_FORWARD(setter) \
|
||||||
class OSMObjectBuilder : public ObjectBuilder<T> {
|
template <typename... TArgs> \
|
||||||
|
type& setter(TArgs&&... args) { \
|
||||||
|
object().setter(std::forward<TArgs>(args)...); \
|
||||||
|
return static_cast<type&>(*this); \
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename TDerived, typename T>
|
||||||
|
class OSMObjectBuilder : public Builder {
|
||||||
|
|
||||||
|
using type = TDerived;
|
||||||
|
|
||||||
|
constexpr static const size_t min_size_for_user = osmium::memory::padded_length(sizeof(string_size_type) + 1);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
explicit OSMObjectBuilder(osmium::memory::Buffer& buffer, Builder* parent = nullptr) :
|
explicit OSMObjectBuilder(osmium::memory::Buffer& buffer, Builder* parent = nullptr) :
|
||||||
ObjectBuilder<T>(buffer, parent) {
|
Builder(buffer, parent, sizeof(T) + min_size_for_user) {
|
||||||
static_cast<Builder*>(this)->reserve_space_for<string_size_type>();
|
new (&item()) T();
|
||||||
static_cast<Builder*>(this)->add_size(sizeof(string_size_type));
|
add_size(min_size_for_user);
|
||||||
|
std::fill_n(object().data() + sizeof(T), min_size_for_user, 0);
|
||||||
|
object().set_user_size(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a reference to the object buing built.
|
||||||
|
*
|
||||||
|
* Note that this reference will be invalidated by every action
|
||||||
|
* on the builder that might make the buffer grow. This includes
|
||||||
|
* calls to set_user() and any time a new sub-builder is created.
|
||||||
|
*/
|
||||||
|
T& object() noexcept {
|
||||||
|
return static_cast<T&>(item());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set user name.
|
||||||
|
*
|
||||||
|
* @param user Pointer to user name.
|
||||||
|
* @param length Length of user name (without \0 termination).
|
||||||
|
*/
|
||||||
|
TDerived& set_user(const char* user, const string_size_type length) {
|
||||||
|
const auto size_of_object = sizeof(T) + sizeof(string_size_type);
|
||||||
|
assert(object().user_size() == 1 && (size() <= size_of_object + osmium::memory::padded_length(1))
|
||||||
|
&& "set_user() must be called at most once and before any sub-builders");
|
||||||
|
const auto available_space = min_size_for_user - sizeof(string_size_type) - 1;
|
||||||
|
if (length > available_space) {
|
||||||
|
const auto space_needed = osmium::memory::padded_length(length - available_space);
|
||||||
|
reserve_space(space_needed);
|
||||||
|
add_size(static_cast<uint32_t>(space_needed));
|
||||||
|
}
|
||||||
|
std::copy_n(user, length, object().data() + size_of_object);
|
||||||
|
std::fill_n(object().data() + size_of_object + length, osmium::memory::padded_length(length + 1) - length, 0);
|
||||||
|
object().set_user_size(length + 1);
|
||||||
|
|
||||||
|
return static_cast<TDerived&>(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set user name.
|
||||||
|
*
|
||||||
|
* @param user Pointer to \0-terminated user name.
|
||||||
|
*/
|
||||||
|
TDerived& set_user(const char* user) {
|
||||||
|
return set_user(user, static_cast_with_assert<string_size_type>(std::strlen(user)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set user name.
|
||||||
|
*
|
||||||
|
* @param user User name.
|
||||||
|
*/
|
||||||
|
TDerived& set_user(const std::string& user) {
|
||||||
|
return set_user(user.data(), static_cast_with_assert<string_size_type>(user.size()));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @deprecated Use set_user(...) instead.
|
||||||
|
template <typename... TArgs>
|
||||||
|
OSMIUM_DEPRECATED void add_user(TArgs&&... args) {
|
||||||
|
set_user(std::forward<TArgs>(args)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
OSMIUM_FORWARD(set_id)
|
||||||
|
OSMIUM_FORWARD(set_visible)
|
||||||
|
OSMIUM_FORWARD(set_deleted)
|
||||||
|
OSMIUM_FORWARD(set_version)
|
||||||
|
OSMIUM_FORWARD(set_changeset)
|
||||||
|
OSMIUM_FORWARD(set_uid)
|
||||||
|
OSMIUM_FORWARD(set_uid_from_signed)
|
||||||
|
OSMIUM_FORWARD(set_timestamp)
|
||||||
|
OSMIUM_FORWARD(set_attribute)
|
||||||
|
OSMIUM_FORWARD(set_removed)
|
||||||
|
|
||||||
void add_tags(const std::initializer_list<std::pair<const char*, const char*>>& tags) {
|
void add_tags(const std::initializer_list<std::pair<const char*, const char*>>& tags) {
|
||||||
osmium::builder::TagListBuilder tl_builder(static_cast<Builder*>(this)->buffer(), this);
|
osmium::builder::TagListBuilder tl_builder{buffer(), this};
|
||||||
for (const auto& p : tags) {
|
for (const auto& p : tags) {
|
||||||
tl_builder.add_tag(p.first, p.second);
|
tl_builder.add_tag(p.first, p.second);
|
||||||
}
|
}
|
||||||
@ -359,19 +467,40 @@ namespace osmium {
|
|||||||
|
|
||||||
}; // class OSMObjectBuilder
|
}; // class OSMObjectBuilder
|
||||||
|
|
||||||
using NodeBuilder = OSMObjectBuilder<osmium::Node>;
|
class NodeBuilder : public OSMObjectBuilder<NodeBuilder, Node> {
|
||||||
using RelationBuilder = OSMObjectBuilder<osmium::Relation>;
|
|
||||||
|
|
||||||
class WayBuilder : public OSMObjectBuilder<osmium::Way> {
|
using type = NodeBuilder;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
explicit NodeBuilder(osmium::memory::Buffer& buffer, Builder* parent = nullptr) :
|
||||||
|
OSMObjectBuilder<NodeBuilder, Node>(buffer, parent) {
|
||||||
|
}
|
||||||
|
|
||||||
|
explicit NodeBuilder(Builder& parent) :
|
||||||
|
OSMObjectBuilder<NodeBuilder, Node>(parent.buffer(), &parent) {
|
||||||
|
}
|
||||||
|
|
||||||
|
OSMIUM_FORWARD(set_location)
|
||||||
|
|
||||||
|
}; // class NodeBuilder
|
||||||
|
|
||||||
|
class WayBuilder : public OSMObjectBuilder<WayBuilder, Way> {
|
||||||
|
|
||||||
|
using type = WayBuilder;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
explicit WayBuilder(osmium::memory::Buffer& buffer, Builder* parent = nullptr) :
|
explicit WayBuilder(osmium::memory::Buffer& buffer, Builder* parent = nullptr) :
|
||||||
OSMObjectBuilder<osmium::Way>(buffer, parent) {
|
OSMObjectBuilder<WayBuilder, Way>(buffer, parent) {
|
||||||
|
}
|
||||||
|
|
||||||
|
explicit WayBuilder(Builder& parent) :
|
||||||
|
OSMObjectBuilder<WayBuilder, Way>(parent.buffer(), &parent) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void add_node_refs(const std::initializer_list<osmium::NodeRef>& nodes) {
|
void add_node_refs(const std::initializer_list<osmium::NodeRef>& nodes) {
|
||||||
osmium::builder::WayNodeListBuilder builder(buffer(), this);
|
osmium::builder::WayNodeListBuilder builder{buffer(), this};
|
||||||
for (const auto& node_ref : nodes) {
|
for (const auto& node_ref : nodes) {
|
||||||
builder.add_node_ref(node_ref);
|
builder.add_node_ref(node_ref);
|
||||||
}
|
}
|
||||||
@ -379,32 +508,147 @@ namespace osmium {
|
|||||||
|
|
||||||
}; // class WayBuilder
|
}; // class WayBuilder
|
||||||
|
|
||||||
class AreaBuilder : public OSMObjectBuilder<osmium::Area> {
|
class RelationBuilder : public OSMObjectBuilder<RelationBuilder, Relation> {
|
||||||
|
|
||||||
|
using type = RelationBuilder;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
explicit RelationBuilder(osmium::memory::Buffer& buffer, Builder* parent = nullptr) :
|
||||||
|
OSMObjectBuilder<RelationBuilder, Relation>(buffer, parent) {
|
||||||
|
}
|
||||||
|
|
||||||
|
explicit RelationBuilder(Builder& parent) :
|
||||||
|
OSMObjectBuilder<RelationBuilder, Relation>(parent.buffer(), &parent) {
|
||||||
|
}
|
||||||
|
|
||||||
|
}; // class RelationBuilder
|
||||||
|
|
||||||
|
class AreaBuilder : public OSMObjectBuilder<AreaBuilder, Area> {
|
||||||
|
|
||||||
|
using type = AreaBuilder;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
explicit AreaBuilder(osmium::memory::Buffer& buffer, Builder* parent = nullptr) :
|
explicit AreaBuilder(osmium::memory::Buffer& buffer, Builder* parent = nullptr) :
|
||||||
OSMObjectBuilder<osmium::Area>(buffer, parent) {
|
OSMObjectBuilder<AreaBuilder, Area>(buffer, parent) {
|
||||||
|
}
|
||||||
|
|
||||||
|
explicit AreaBuilder(Builder& parent) :
|
||||||
|
OSMObjectBuilder<AreaBuilder, Area>(parent.buffer(), &parent) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize area attributes from the attributes of the given object.
|
* Initialize area attributes from the attributes of the given object.
|
||||||
*/
|
*/
|
||||||
void initialize_from_object(const osmium::OSMObject& source) {
|
void initialize_from_object(const osmium::OSMObject& source) {
|
||||||
osmium::Area& area = object();
|
set_id(osmium::object_id_to_area_id(source.id(), source.type()));
|
||||||
area.set_id(osmium::object_id_to_area_id(source.id(), source.type()));
|
set_version(source.version());
|
||||||
area.set_version(source.version());
|
set_changeset(source.changeset());
|
||||||
area.set_changeset(source.changeset());
|
set_timestamp(source.timestamp());
|
||||||
area.set_timestamp(source.timestamp());
|
set_visible(source.visible());
|
||||||
area.set_visible(source.visible());
|
set_uid(source.uid());
|
||||||
area.set_uid(source.uid());
|
set_user(source.user());
|
||||||
|
|
||||||
add_user(source.user());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}; // class AreaBuilder
|
}; // class AreaBuilder
|
||||||
|
|
||||||
using ChangesetBuilder = ObjectBuilder<osmium::Changeset>;
|
class ChangesetBuilder : public Builder {
|
||||||
|
|
||||||
|
using type = ChangesetBuilder;
|
||||||
|
|
||||||
|
constexpr static const size_t min_size_for_user = osmium::memory::padded_length(1);
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
explicit ChangesetBuilder(osmium::memory::Buffer& buffer, Builder* parent = nullptr) :
|
||||||
|
Builder(buffer, parent, sizeof(Changeset) + min_size_for_user) {
|
||||||
|
new (&item()) Changeset();
|
||||||
|
add_size(min_size_for_user);
|
||||||
|
std::fill_n(object().data() + sizeof(Changeset), min_size_for_user, 0);
|
||||||
|
object().set_user_size(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a reference to the changeset buing built.
|
||||||
|
*
|
||||||
|
* Note that this reference will be invalidated by every action
|
||||||
|
* on the builder that might make the buffer grow. This includes
|
||||||
|
* calls to set_user() and any time a new sub-builder is created.
|
||||||
|
*/
|
||||||
|
Changeset& object() noexcept {
|
||||||
|
return static_cast<Changeset&>(item());
|
||||||
|
}
|
||||||
|
|
||||||
|
OSMIUM_FORWARD(set_id)
|
||||||
|
OSMIUM_FORWARD(set_uid)
|
||||||
|
OSMIUM_FORWARD(set_uid_from_signed)
|
||||||
|
OSMIUM_FORWARD(set_created_at)
|
||||||
|
OSMIUM_FORWARD(set_closed_at)
|
||||||
|
OSMIUM_FORWARD(set_num_changes)
|
||||||
|
OSMIUM_FORWARD(set_num_comments)
|
||||||
|
OSMIUM_FORWARD(set_attribute)
|
||||||
|
OSMIUM_FORWARD(set_removed)
|
||||||
|
|
||||||
|
// @deprecated Use set_bounds() instead.
|
||||||
|
OSMIUM_DEPRECATED osmium::Box& bounds() noexcept {
|
||||||
|
return object().bounds();
|
||||||
|
}
|
||||||
|
|
||||||
|
ChangesetBuilder& set_bounds(const osmium::Box& box) noexcept {
|
||||||
|
object().bounds() = box;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set user name.
|
||||||
|
*
|
||||||
|
* @param user Pointer to user name.
|
||||||
|
* @param length Length of user name (without \0 termination).
|
||||||
|
*/
|
||||||
|
ChangesetBuilder& set_user(const char* user, const string_size_type length) {
|
||||||
|
assert(object().user_size() == 1 && (size() <= sizeof(Changeset) + osmium::memory::padded_length(1))
|
||||||
|
&& "set_user() must be called at most once and before any sub-builders");
|
||||||
|
const auto available_space = min_size_for_user - 1;
|
||||||
|
if (length > available_space) {
|
||||||
|
const auto space_needed = osmium::memory::padded_length(length - available_space);
|
||||||
|
reserve_space(space_needed);
|
||||||
|
add_size(static_cast<uint32_t>(space_needed));
|
||||||
|
}
|
||||||
|
std::copy_n(user, length, object().data() + sizeof(Changeset));
|
||||||
|
std::fill_n(object().data() + sizeof(Changeset) + length, osmium::memory::padded_length(length + 1) - length, 0);
|
||||||
|
object().set_user_size(length + 1);
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set user name.
|
||||||
|
*
|
||||||
|
* @param user Pointer to \0-terminated user name.
|
||||||
|
*/
|
||||||
|
ChangesetBuilder& set_user(const char* user) {
|
||||||
|
return set_user(user, static_cast_with_assert<string_size_type>(std::strlen(user)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set user name.
|
||||||
|
*
|
||||||
|
* @param user User name.
|
||||||
|
*/
|
||||||
|
ChangesetBuilder& set_user(const std::string& user) {
|
||||||
|
return set_user(user.data(), static_cast_with_assert<string_size_type>(user.size()));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @deprecated Use set_user(...) instead.
|
||||||
|
template <typename... TArgs>
|
||||||
|
OSMIUM_DEPRECATED void add_user(TArgs&&... args) {
|
||||||
|
set_user(std::forward<TArgs>(args)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
}; // class ChangesetBuilder
|
||||||
|
|
||||||
|
#undef OSMIUM_FORWARD
|
||||||
|
|
||||||
} // namespace builder
|
} // namespace builder
|
||||||
|
|
||||||
|
@ -95,7 +95,7 @@ namespace osmium {
|
|||||||
return m_message.c_str();
|
return m_message.c_str();
|
||||||
}
|
}
|
||||||
|
|
||||||
}; // struct geometry_error
|
}; // class geometry_error
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Everything related to geometry handling.
|
* @brief Everything related to geometry handling.
|
||||||
|
@ -33,12 +33,22 @@ DEALINGS IN THE SOFTWARE.
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <geos/version.h>
|
||||||
|
#if defined(GEOS_VERSION_MAJOR) && defined(GEOS_VERSION_MINOR) && (GEOS_VERSION_MAJOR < 3 || (GEOS_VERSION_MAJOR == 3 && GEOS_VERSION_MINOR <= 5))
|
||||||
|
|
||||||
|
#define OSMIUM_WITH_GEOS
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @file
|
* @file
|
||||||
*
|
*
|
||||||
* This file contains code for conversion of OSM geometries into GDAL
|
* This file contains code for conversion of OSM geometries into GEOS
|
||||||
* geometries.
|
* geometries.
|
||||||
*
|
*
|
||||||
|
* Note that everything in this file is deprecated and only works up to
|
||||||
|
* GEOS 3.5. It uses the GEOS C++ API which the GEOS project does not consider
|
||||||
|
* to be a stable, external API. We probably should have used the GEOS C API
|
||||||
|
* instead.
|
||||||
|
*
|
||||||
* @attention If you include this file, you'll need to link with `libgeos`.
|
* @attention If you include this file, you'll need to link with `libgeos`.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -88,6 +98,7 @@ namespace osmium {
|
|||||||
|
|
||||||
namespace detail {
|
namespace detail {
|
||||||
|
|
||||||
|
/// @deprecated
|
||||||
class GEOSFactoryImpl {
|
class GEOSFactoryImpl {
|
||||||
|
|
||||||
std::unique_ptr<const geos::geom::PrecisionModel> m_precision_model;
|
std::unique_ptr<const geos::geom::PrecisionModel> m_precision_model;
|
||||||
@ -245,6 +256,7 @@ namespace osmium {
|
|||||||
|
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
|
|
||||||
|
/// @deprecated
|
||||||
template <typename TProjection = IdentityProjection>
|
template <typename TProjection = IdentityProjection>
|
||||||
using GEOSFactory = GeometryFactory<osmium::geom::detail::GEOSFactoryImpl, TProjection>;
|
using GEOSFactory = GeometryFactory<osmium::geom::detail::GEOSFactoryImpl, TProjection>;
|
||||||
|
|
||||||
@ -254,4 +266,6 @@ namespace osmium {
|
|||||||
|
|
||||||
#undef THROW
|
#undef THROW
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif // OSMIUM_GEOM_GEOS_HPP
|
#endif // OSMIUM_GEOM_GEOS_HPP
|
||||||
|
@ -43,11 +43,11 @@ namespace osmium {
|
|||||||
/**
|
/**
|
||||||
* Check whether one geometry contains another.
|
* Check whether one geometry contains another.
|
||||||
*/
|
*/
|
||||||
inline bool contains(const osmium::Box& a, const osmium::Box& b) {
|
inline bool contains(const osmium::Box& lhs, const osmium::Box& rhs) {
|
||||||
return ((a.bottom_left().x() >= b.bottom_left().x()) &&
|
return ((lhs.bottom_left().x() >= rhs.bottom_left().x()) &&
|
||||||
(a.top_right().x() <= b.top_right().x()) &&
|
(lhs.top_right().x() <= rhs.top_right().x()) &&
|
||||||
(a.bottom_left().y() >= b.bottom_left().y()) &&
|
(lhs.bottom_left().y() >= rhs.bottom_left().y()) &&
|
||||||
(a.top_right().y() <= b.top_right().y()));
|
(lhs.top_right().y() <= rhs.top_right().y()));
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace geom
|
} // namespace geom
|
||||||
|
@ -118,23 +118,23 @@ namespace osmium {
|
|||||||
}; // struct Tile
|
}; // struct Tile
|
||||||
|
|
||||||
/// Tiles are equal if all their attributes are equal.
|
/// Tiles are equal if all their attributes are equal.
|
||||||
inline bool operator==(const Tile& a, const Tile& b) {
|
inline bool operator==(const Tile& lhs, const Tile& rhs) {
|
||||||
return a.z == b.z && a.x == b.x && a.y == b.y;
|
return lhs.z == rhs.z && lhs.x == rhs.x && lhs.y == rhs.y;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool operator!=(const Tile& a, const Tile& b) {
|
inline bool operator!=(const Tile& lhs, const Tile& rhs) {
|
||||||
return ! (a == b);
|
return ! (lhs == rhs);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This defines an arbitrary order on tiles for use in std::map etc.
|
* This defines an arbitrary order on tiles for use in std::map etc.
|
||||||
*/
|
*/
|
||||||
inline bool operator<(const Tile& a, const Tile& b) {
|
inline bool operator<(const Tile& lhs, const Tile& rhs) {
|
||||||
if (a.z < b.z) return true;
|
if (lhs.z < rhs.z) return true;
|
||||||
if (a.z > b.z) return false;
|
if (lhs.z > rhs.z) return false;
|
||||||
if (a.x < b.x) return true;
|
if (lhs.x < rhs.x) return true;
|
||||||
if (a.x > b.x) return false;
|
if (lhs.x > rhs.x) return false;
|
||||||
return a.y < b.y;
|
return lhs.y < rhs.y;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace geom
|
} // namespace geom
|
||||||
|
@ -51,6 +51,9 @@ namespace osmium {
|
|||||||
namespace handler {
|
namespace handler {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Writes OSM data in the Osmium-internal serialized format to disk
|
||||||
|
* keeping track of object offsets in the indexes given to the
|
||||||
|
* constructor.
|
||||||
*
|
*
|
||||||
* Note: This handler will only work if either all object IDs are
|
* Note: This handler will only work if either all object IDs are
|
||||||
* positive or all object IDs are negative.
|
* positive or all object IDs are negative.
|
||||||
@ -95,10 +98,8 @@ namespace osmium {
|
|||||||
m_offset += relation.byte_size();
|
m_offset += relation.byte_size();
|
||||||
}
|
}
|
||||||
|
|
||||||
// XXX
|
|
||||||
void operator()(const osmium::memory::Buffer& buffer) {
|
void operator()(const osmium::memory::Buffer& buffer) {
|
||||||
osmium::io::detail::reliable_write(m_data_fd, buffer.data(), buffer.committed());
|
osmium::io::detail::reliable_write(m_data_fd, buffer.data(), buffer.committed());
|
||||||
|
|
||||||
osmium::apply(buffer.begin(), buffer.end(), *this);
|
osmium::apply(buffer.begin(), buffer.end(), *this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -165,7 +165,7 @@ namespace osmium {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (error && !m_ignore_errors) {
|
if (error && !m_ignore_errors) {
|
||||||
throw osmium::not_found("location for one or more nodes not found in node location index");
|
throw osmium::not_found{"location for one or more nodes not found in node location index"};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -46,6 +46,8 @@ namespace osmium {
|
|||||||
namespace handler {
|
namespace handler {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* This handler updates the indexes given to the constructor with
|
||||||
|
* the relations between objects.
|
||||||
*
|
*
|
||||||
* Note: This handler will only work if either all object IDs are
|
* Note: This handler will only work if either all object IDs are
|
||||||
* positive or all object IDs are negative.
|
* positive or all object IDs are negative.
|
||||||
|
@ -33,50 +33,15 @@ DEALINGS IN THE SOFTWARE.
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <type_traits>
|
#include <osmium/index/id_set.hpp>
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
namespace osmium {
|
namespace osmium {
|
||||||
|
|
||||||
namespace index {
|
namespace index {
|
||||||
|
|
||||||
/**
|
/// @deprecated Use osmium::index::IdSet instead.
|
||||||
* 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>
|
template <typename T>
|
||||||
class BoolVector {
|
using BoolVector = IdSet<T>;
|
||||||
|
|
||||||
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() noexcept = 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 index
|
||||||
|
|
||||||
|
@ -85,11 +85,11 @@ namespace osmium {
|
|||||||
try {
|
try {
|
||||||
const TValue& value = m_vector.at(id);
|
const TValue& value = m_vector.at(id);
|
||||||
if (value == osmium::index::empty_value<TValue>()) {
|
if (value == osmium::index::empty_value<TValue>()) {
|
||||||
not_found_error(id);
|
throw osmium::not_found{id};
|
||||||
}
|
}
|
||||||
return value;
|
return value;
|
||||||
} catch (const std::out_of_range&) {
|
} catch (const std::out_of_range&) {
|
||||||
not_found_error(id);
|
throw osmium::not_found{id};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -180,7 +180,7 @@ namespace osmium {
|
|||||||
return a.first < b.first;
|
return a.first < b.first;
|
||||||
});
|
});
|
||||||
if (result == m_vector.end() || result->first != id) {
|
if (result == m_vector.end() || result->first != id) {
|
||||||
not_found_error(id);
|
throw osmium::not_found{id};
|
||||||
} else {
|
} else {
|
||||||
return result->second;
|
return result->second;
|
||||||
}
|
}
|
||||||
|
431
third_party/libosmium/include/osmium/index/id_set.hpp
vendored
Normal file
431
third_party/libosmium/include/osmium/index/id_set.hpp
vendored
Normal file
@ -0,0 +1,431 @@
|
|||||||
|
#ifndef OSMIUM_INDEX_ID_SET_HPP
|
||||||
|
#define OSMIUM_INDEX_ID_SET_HPP
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||||
|
|
||||||
|
Copyright 2013-2016 Jochen Topf <jochen@topf.org> and others (see README).
|
||||||
|
|
||||||
|
Boost Software License - Version 1.0 - August 17th, 2003
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person or organization
|
||||||
|
obtaining a copy of the software and accompanying documentation covered by
|
||||||
|
this license (the "Software") to use, reproduce, display, distribute,
|
||||||
|
execute, and transmit the Software, and to prepare derivative works of the
|
||||||
|
Software, and to permit third-parties to whom the Software is furnished to
|
||||||
|
do so, all subject to the following:
|
||||||
|
|
||||||
|
The copyright notices in the Software and this entire statement, including
|
||||||
|
the above license grant, this restriction and the following disclaimer,
|
||||||
|
must be included in all copies of the Software, in whole or in part, and
|
||||||
|
all derivative works of the Software, unless such copies or derivative
|
||||||
|
works are solely in the form of machine-executable object code generated by
|
||||||
|
a source language processor.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||||
|
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||||
|
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||||
|
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <cassert>
|
||||||
|
#include <cstring>
|
||||||
|
#include <memory>
|
||||||
|
#include <type_traits>
|
||||||
|
#include <unordered_set>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include <osmium/osm/item_type.hpp>
|
||||||
|
#include <osmium/osm/types.hpp>
|
||||||
|
|
||||||
|
namespace osmium {
|
||||||
|
|
||||||
|
namespace index {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Virtual parent class for IdSets. Use one of the implementations
|
||||||
|
* provided.
|
||||||
|
*/
|
||||||
|
template <typename T>
|
||||||
|
class IdSet {
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
virtual ~IdSet() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add the given Id to the set.
|
||||||
|
*/
|
||||||
|
virtual void set(T id) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is the Id in the set?
|
||||||
|
*/
|
||||||
|
virtual bool get(T id) const noexcept = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is the set empty?
|
||||||
|
*/
|
||||||
|
virtual bool empty() const = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clear the set.
|
||||||
|
*/
|
||||||
|
virtual void clear() = 0;
|
||||||
|
|
||||||
|
}; // class IdSet
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
class IdSetDense;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Const_iterator for iterating over a IdSetDense.
|
||||||
|
*/
|
||||||
|
template <typename T>
|
||||||
|
class IdSetDenseIterator {
|
||||||
|
|
||||||
|
const IdSetDense<T>* m_set;
|
||||||
|
T m_value;
|
||||||
|
T m_last;
|
||||||
|
|
||||||
|
void next() noexcept {
|
||||||
|
while (m_value != m_last && !m_set->get(m_value)) {
|
||||||
|
const auto cid = IdSetDense<T>::chunk_id(m_value);
|
||||||
|
assert(cid < m_set->m_data.size());
|
||||||
|
if (!m_set->m_data[cid]) {
|
||||||
|
m_value = (cid + 1) << (IdSetDense<T>::chunk_bits + 3);
|
||||||
|
} else {
|
||||||
|
const auto slot = m_set->m_data[cid][IdSetDense<T>::offset(m_value)];
|
||||||
|
if (slot == 0) {
|
||||||
|
m_value += 8;
|
||||||
|
m_value &= ~0x7;
|
||||||
|
} else {
|
||||||
|
++m_value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
using iterator_category = std::forward_iterator_tag;
|
||||||
|
using value_type = T;
|
||||||
|
using pointer = value_type*;
|
||||||
|
using reference = value_type&;
|
||||||
|
|
||||||
|
IdSetDenseIterator(const IdSetDense<T>* set, T value, T last) noexcept :
|
||||||
|
m_set(set),
|
||||||
|
m_value(value),
|
||||||
|
m_last(last) {
|
||||||
|
next();
|
||||||
|
}
|
||||||
|
|
||||||
|
IdSetDenseIterator<T>& operator++() noexcept {
|
||||||
|
if (m_value != m_last) {
|
||||||
|
++m_value;
|
||||||
|
next();
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
IdSetDenseIterator<T> operator++(int) noexcept {
|
||||||
|
IdSetDenseIterator<T> tmp(*this);
|
||||||
|
operator++();
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator==(const IdSetDenseIterator<T>& rhs) const noexcept {
|
||||||
|
return m_set == rhs.m_set && m_value == rhs.m_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator!=(const IdSetDenseIterator<T>& rhs) const noexcept {
|
||||||
|
return ! (*this == rhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
T operator*() const noexcept {
|
||||||
|
assert(m_value < m_last);
|
||||||
|
return m_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
}; // class IdSetDenseIterator
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A set of Ids of the given type. Internal storage is in chunks of
|
||||||
|
* arrays used as bit fields. Internally those chunks will be allocated
|
||||||
|
* as needed, so it works relatively efficiently with both smaller
|
||||||
|
* and larger Id sets. If it is not used, no memory is allocated at
|
||||||
|
* all.
|
||||||
|
*/
|
||||||
|
template <typename T>
|
||||||
|
class IdSetDense : public IdSet<T> {
|
||||||
|
|
||||||
|
static_assert(std::is_unsigned<T>::value, "Needs unsigned type");
|
||||||
|
static_assert(sizeof(T) >= 4, "Needs at least 32bit type");
|
||||||
|
|
||||||
|
friend class IdSetDenseIterator<T>;
|
||||||
|
|
||||||
|
// This value is a compromise. For node Ids it could be bigger
|
||||||
|
// which would mean less (but larger) memory allocations. For
|
||||||
|
// relations Ids it could be smaller, because they would all fit
|
||||||
|
// into a smaller allocation.
|
||||||
|
constexpr static const size_t chunk_bits = 22;
|
||||||
|
constexpr static const size_t chunk_size = 1 << chunk_bits;
|
||||||
|
|
||||||
|
std::vector<std::unique_ptr<unsigned char[]>> m_data;
|
||||||
|
size_t m_size = 0;
|
||||||
|
|
||||||
|
static size_t chunk_id(T id) noexcept {
|
||||||
|
return id >> (chunk_bits + 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
static size_t offset(T id) noexcept {
|
||||||
|
return (id >> 3) & ((1 << chunk_bits) - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned char bitmask(T id) noexcept {
|
||||||
|
return 1 << (id & 0x7);
|
||||||
|
}
|
||||||
|
|
||||||
|
T last() const noexcept {
|
||||||
|
return m_data.size() * chunk_size * 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char& get_element(T id) {
|
||||||
|
const auto cid = chunk_id(id);
|
||||||
|
if (cid >= m_data.size()) {
|
||||||
|
m_data.resize(cid + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto& chunk = m_data[cid];
|
||||||
|
if (!chunk) {
|
||||||
|
chunk.reset(new unsigned char[chunk_size]);
|
||||||
|
::memset(chunk.get(), 0, chunk_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
return chunk[offset(id)];
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
using const_iterator = IdSetDenseIterator<T>;
|
||||||
|
|
||||||
|
IdSetDense() = default;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add the Id to the set if it is not already in there.
|
||||||
|
*
|
||||||
|
* @param id The Id to set.
|
||||||
|
* @returns true if the Id was added, false if it was already set.
|
||||||
|
*/
|
||||||
|
bool check_and_set(T id) {
|
||||||
|
auto& element = get_element(id);
|
||||||
|
|
||||||
|
if ((element & bitmask(id)) == 0) {
|
||||||
|
element |= bitmask(id);
|
||||||
|
++m_size;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add the given Id to the set.
|
||||||
|
*
|
||||||
|
* @param id The Id to set.
|
||||||
|
*/
|
||||||
|
void set(T id) override final {
|
||||||
|
(void)check_and_set(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove the given Id from the set.
|
||||||
|
*
|
||||||
|
* @param id The Id to set.
|
||||||
|
*/
|
||||||
|
void unset(T id) {
|
||||||
|
auto& element = get_element(id);
|
||||||
|
|
||||||
|
if ((element & bitmask(id)) != 0) {
|
||||||
|
element &= ~bitmask(id);
|
||||||
|
--m_size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is the Id in the set?
|
||||||
|
*
|
||||||
|
* @param id The Id to check.
|
||||||
|
*/
|
||||||
|
bool get(T id) const noexcept override final {
|
||||||
|
if (chunk_id(id) >= m_data.size()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
auto* r = m_data[chunk_id(id)].get();
|
||||||
|
if (!r) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return (r[offset(id)] & bitmask(id)) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is the set empty?
|
||||||
|
*/
|
||||||
|
bool empty() const noexcept override final {
|
||||||
|
return m_size == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The number of Ids stored in the set.
|
||||||
|
*/
|
||||||
|
size_t size() const noexcept {
|
||||||
|
return m_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clear the set.
|
||||||
|
*/
|
||||||
|
void clear() override final {
|
||||||
|
m_data.clear();
|
||||||
|
m_size = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
IdSetDenseIterator<T> begin() const {
|
||||||
|
return IdSetDenseIterator<T>{this, 0, last()};
|
||||||
|
}
|
||||||
|
|
||||||
|
IdSetDenseIterator<T> end() const {
|
||||||
|
return IdSetDenseIterator<T>{this, last(), last()};
|
||||||
|
}
|
||||||
|
|
||||||
|
}; // class IdSetDense
|
||||||
|
|
||||||
|
/**
|
||||||
|
* IdSet implementation for small Id sets. It writes the Ids
|
||||||
|
* into a vector and uses linear search.
|
||||||
|
*/
|
||||||
|
template <typename T>
|
||||||
|
class IdSetSmall : public IdSet<T> {
|
||||||
|
|
||||||
|
std::vector<T> m_data;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add the given Id to the set.
|
||||||
|
*/
|
||||||
|
void set(T id) override final {
|
||||||
|
m_data.push_back(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is the Id in the set? Uses linear search.
|
||||||
|
*
|
||||||
|
* @param id The Id to check.
|
||||||
|
*/
|
||||||
|
bool get(T id) const noexcept override final {
|
||||||
|
const auto it = std::find(m_data.cbegin(), m_data.cend(), id);
|
||||||
|
return it != m_data.cend();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is the Id in the set? Uses a binary search. For larger sets
|
||||||
|
* this might be more efficient than calling get(), the set
|
||||||
|
* must be sorted.
|
||||||
|
*
|
||||||
|
* @param id The Id to check.
|
||||||
|
* @pre You must have called sort_unique() before calling this
|
||||||
|
* or be sure there are no duplicates and the Ids have been
|
||||||
|
* set in order.
|
||||||
|
*/
|
||||||
|
bool get_binary_search(T id) const noexcept {
|
||||||
|
return std::binary_search(m_data.cbegin(), m_data.cend(), id);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is the set empty?
|
||||||
|
*/
|
||||||
|
bool empty() const noexcept override final {
|
||||||
|
return m_data.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clear the set.
|
||||||
|
*/
|
||||||
|
void clear() override final {
|
||||||
|
m_data.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sort the internal vector and remove any duplicates. Call this
|
||||||
|
* before using size(), get_binary_search() or using an iterator.
|
||||||
|
*/
|
||||||
|
void sort_unique() {
|
||||||
|
std::sort(m_data.begin(), m_data.end());
|
||||||
|
const auto last = std::unique(m_data.begin(), m_data.end());
|
||||||
|
m_data.erase(last, m_data.end());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The number of Ids stored in the set.
|
||||||
|
*
|
||||||
|
* @pre You must have called sort_unique() before calling this
|
||||||
|
* or be sure there are no duplicates.
|
||||||
|
*/
|
||||||
|
size_t size() const noexcept {
|
||||||
|
return m_data.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Iterator type. There is no non-const iterator.
|
||||||
|
using const_iterator = typename std::vector<T>::const_iterator;
|
||||||
|
|
||||||
|
const_iterator begin() const noexcept {
|
||||||
|
return m_data.cbegin();
|
||||||
|
}
|
||||||
|
|
||||||
|
const_iterator end() const noexcept {
|
||||||
|
return m_data.cend();
|
||||||
|
}
|
||||||
|
|
||||||
|
const_iterator cbegin() const noexcept {
|
||||||
|
return m_data.cbegin();
|
||||||
|
}
|
||||||
|
|
||||||
|
const_iterator cend() const noexcept {
|
||||||
|
return m_data.cend();
|
||||||
|
}
|
||||||
|
|
||||||
|
}; // class IdSetSmall
|
||||||
|
|
||||||
|
template <template<typename> class IdSetType>
|
||||||
|
class NWRIdSet {
|
||||||
|
|
||||||
|
using id_set_type = IdSetType<osmium::unsigned_object_id_type>;
|
||||||
|
|
||||||
|
id_set_type m_sets[3];
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
id_set_type& operator()(osmium::item_type type) noexcept {
|
||||||
|
return m_sets[osmium::item_type_to_nwr_index(type)];
|
||||||
|
}
|
||||||
|
|
||||||
|
const id_set_type& operator()(osmium::item_type type) const noexcept {
|
||||||
|
return m_sets[osmium::item_type_to_nwr_index(type)];
|
||||||
|
}
|
||||||
|
|
||||||
|
}; // class NWRIdSet
|
||||||
|
|
||||||
|
} // namespace index
|
||||||
|
|
||||||
|
} // namespace osmium
|
||||||
|
|
||||||
|
#endif // OSMIUM_INDEX_ID_SET_HPP
|
@ -35,7 +35,6 @@ DEALINGS IN THE SOFTWARE.
|
|||||||
|
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
#include <sstream>
|
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
@ -57,6 +56,10 @@ namespace osmium {
|
|||||||
std::runtime_error(what) {
|
std::runtime_error(what) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
explicit not_found(uint64_t id) :
|
||||||
|
std::runtime_error(std::string{"id "} + std::to_string(id) + " not found") {
|
||||||
|
}
|
||||||
|
|
||||||
}; // struct not_found
|
}; // struct not_found
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -64,13 +67,6 @@ namespace osmium {
|
|||||||
*/
|
*/
|
||||||
namespace index {
|
namespace index {
|
||||||
|
|
||||||
template <typename TKey>
|
|
||||||
OSMIUM_NORETURN void not_found_error(TKey key) {
|
|
||||||
std::stringstream s;
|
|
||||||
s << "id " << key << " not found";
|
|
||||||
throw not_found(s.str());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Some of the index classes need an "empty" value that can
|
* Some of the index classes need an "empty" value that can
|
||||||
* never appear in real data. This function must return this
|
* never appear in real data. This function must return this
|
||||||
|
@ -48,6 +48,18 @@ DEALINGS IN THE SOFTWARE.
|
|||||||
|
|
||||||
namespace osmium {
|
namespace osmium {
|
||||||
|
|
||||||
|
struct map_factory_error : public std::runtime_error {
|
||||||
|
|
||||||
|
explicit map_factory_error(const char* message) :
|
||||||
|
std::runtime_error(message) {
|
||||||
|
}
|
||||||
|
|
||||||
|
explicit map_factory_error(const std::string& message) :
|
||||||
|
std::runtime_error(message) {
|
||||||
|
}
|
||||||
|
|
||||||
|
}; // struct map_factory_error
|
||||||
|
|
||||||
namespace index {
|
namespace index {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -148,14 +160,14 @@ namespace osmium {
|
|||||||
// default implementation is empty
|
// default implementation is empty
|
||||||
}
|
}
|
||||||
|
|
||||||
// This function could usually be const in derived classes,
|
// This function can usually be const in derived classes,
|
||||||
// but not always. It could, for instance, sort internal data.
|
// but not always. It could, for instance, sort internal data.
|
||||||
// This is why it is not declared const here.
|
// This is why it is not declared const here.
|
||||||
virtual void dump_as_list(const int /*fd*/) {
|
virtual void dump_as_list(const int /*fd*/) {
|
||||||
throw std::runtime_error("can't dump as list");
|
throw std::runtime_error("can't dump as list");
|
||||||
}
|
}
|
||||||
|
|
||||||
// This function could usually be const in derived classes,
|
// This function can usually be const in derived classes,
|
||||||
// but not always. It could, for instance, sort internal data.
|
// but not always. It could, for instance, sort internal data.
|
||||||
// This is why it is not declared const here.
|
// This is why it is not declared const here.
|
||||||
virtual void dump_as_array(const int /*fd*/) {
|
virtual void dump_as_array(const int /*fd*/) {
|
||||||
@ -188,13 +200,6 @@ namespace osmium {
|
|||||||
MapFactory(MapFactory&&) = delete;
|
MapFactory(MapFactory&&) = delete;
|
||||||
MapFactory& operator=(MapFactory&&) = delete;
|
MapFactory& operator=(MapFactory&&) = delete;
|
||||||
|
|
||||||
OSMIUM_NORETURN static void error(const std::string& map_type_name) {
|
|
||||||
std::string error_message {"Support for map type '"};
|
|
||||||
error_message += map_type_name;
|
|
||||||
error_message += "' not compiled into this binary.";
|
|
||||||
throw std::runtime_error(error_message);
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
static MapFactory<id_type, value_type>& instance() {
|
static MapFactory<id_type, value_type>& instance() {
|
||||||
@ -226,7 +231,7 @@ namespace osmium {
|
|||||||
std::vector<std::string> config = osmium::split_string(config_string, ',');
|
std::vector<std::string> config = osmium::split_string(config_string, ',');
|
||||||
|
|
||||||
if (config.empty()) {
|
if (config.empty()) {
|
||||||
throw std::runtime_error("Need non-empty map type name.");
|
throw map_factory_error{"Need non-empty map type name"};
|
||||||
}
|
}
|
||||||
|
|
||||||
auto it = m_callbacks.find(config[0]);
|
auto it = m_callbacks.find(config[0]);
|
||||||
@ -234,7 +239,7 @@ namespace osmium {
|
|||||||
return std::unique_ptr<map_type>((it->second)(config));
|
return std::unique_ptr<map_type>((it->second)(config));
|
||||||
}
|
}
|
||||||
|
|
||||||
error(config[0]);
|
throw map_factory_error{std::string{"Support for map type '"} + config[0] + "' not compiled into this binary"};
|
||||||
}
|
}
|
||||||
|
|
||||||
}; // class MapFactory
|
}; // class MapFactory
|
||||||
|
@ -63,7 +63,7 @@ namespace osmium {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const TValue get(const TId id) const final {
|
const TValue get(const TId id) const final {
|
||||||
not_found_error(id);
|
throw osmium::not_found{id};
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t size() const final {
|
size_t size() const final {
|
||||||
|
@ -79,7 +79,7 @@ namespace osmium {
|
|||||||
const TValue get(const TId id) const final {
|
const TValue get(const TId id) const final {
|
||||||
auto it = m_elements.find(id);
|
auto it = m_elements.find(id);
|
||||||
if (it == m_elements.end()) {
|
if (it == m_elements.end()) {
|
||||||
not_found_error(id);
|
throw osmium::not_found{id};
|
||||||
}
|
}
|
||||||
return it->second;
|
return it->second;
|
||||||
}
|
}
|
||||||
|
@ -99,10 +99,10 @@ namespace osmium {
|
|||||||
|
|
||||||
const TValue get(const TId id) const final {
|
const TValue get(const TId id) const final {
|
||||||
if (id >= m_elements.size()) {
|
if (id >= m_elements.size()) {
|
||||||
not_found_error(id);
|
throw osmium::not_found{id};
|
||||||
}
|
}
|
||||||
if (m_elements[id] == osmium::index::empty_value<TValue>()) {
|
if (m_elements[id] == osmium::index::empty_value<TValue>()) {
|
||||||
not_found_error(id);
|
throw osmium::not_found{id};
|
||||||
}
|
}
|
||||||
return m_elements[id];
|
return m_elements[id];
|
||||||
}
|
}
|
||||||
|
@ -145,10 +145,11 @@ namespace osmium {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
using compression_map_type = std::map<const osmium::io::file_compression,
|
using callbacks_type = std::tuple<create_compressor_type,
|
||||||
std::tuple<create_compressor_type,
|
create_decompressor_type_fd,
|
||||||
create_decompressor_type_fd,
|
create_decompressor_type_buffer>;
|
||||||
create_decompressor_type_buffer>>;
|
|
||||||
|
using compression_map_type = std::map<const osmium::io::file_compression, callbacks_type>;
|
||||||
|
|
||||||
compression_map_type m_callbacks;
|
compression_map_type m_callbacks;
|
||||||
|
|
||||||
@ -160,11 +161,17 @@ namespace osmium {
|
|||||||
CompressionFactory(CompressionFactory&&) = delete;
|
CompressionFactory(CompressionFactory&&) = delete;
|
||||||
CompressionFactory& operator=(CompressionFactory&&) = delete;
|
CompressionFactory& operator=(CompressionFactory&&) = delete;
|
||||||
|
|
||||||
OSMIUM_NORETURN void error(osmium::io::file_compression compression) {
|
const callbacks_type& find_callbacks(osmium::io::file_compression compression) const {
|
||||||
std::string error_message {"Support for compression '"};
|
const auto it = m_callbacks.find(compression);
|
||||||
|
|
||||||
|
if (it != m_callbacks.end()) {
|
||||||
|
return it->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string error_message{"Support for compression '"};
|
||||||
error_message += as_string(compression);
|
error_message += as_string(compression);
|
||||||
error_message += "' not compiled into this binary.";
|
error_message += "' not compiled into this binary";
|
||||||
throw unsupported_file_format_error(error_message);
|
throw unsupported_file_format_error{error_message};
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -189,36 +196,21 @@ namespace osmium {
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename... TArgs>
|
template <typename... TArgs>
|
||||||
std::unique_ptr<osmium::io::Compressor> create_compressor(osmium::io::file_compression compression, TArgs&&... args) {
|
std::unique_ptr<osmium::io::Compressor> create_compressor(osmium::io::file_compression compression, TArgs&&... args) const {
|
||||||
auto it = m_callbacks.find(compression);
|
const auto callbacks = find_callbacks(compression);
|
||||||
|
return std::unique_ptr<osmium::io::Compressor>(std::get<0>(callbacks)(std::forward<TArgs>(args)...));
|
||||||
if (it != m_callbacks.end()) {
|
|
||||||
return std::unique_ptr<osmium::io::Compressor>(std::get<0>(it->second)(std::forward<TArgs>(args)...));
|
|
||||||
}
|
|
||||||
|
|
||||||
error(compression);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<osmium::io::Decompressor> create_decompressor(osmium::io::file_compression compression, int fd) {
|
std::unique_ptr<osmium::io::Decompressor> create_decompressor(osmium::io::file_compression compression, int fd) const {
|
||||||
auto it = m_callbacks.find(compression);
|
const auto callbacks = find_callbacks(compression);
|
||||||
|
auto p = std::unique_ptr<osmium::io::Decompressor>(std::get<1>(callbacks)(fd));
|
||||||
if (it != m_callbacks.end()) {
|
p->set_file_size(osmium::util::file_size(fd));
|
||||||
auto p = std::unique_ptr<osmium::io::Decompressor>(std::get<1>(it->second)(fd));
|
return p;
|
||||||
p->set_file_size(osmium::util::file_size(fd));
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
|
|
||||||
error(compression);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<osmium::io::Decompressor> create_decompressor(osmium::io::file_compression compression, const char* buffer, size_t size) {
|
std::unique_ptr<osmium::io::Decompressor> create_decompressor(osmium::io::file_compression compression, const char* buffer, size_t size) const {
|
||||||
auto it = m_callbacks.find(compression);
|
const auto callbacks = find_callbacks(compression);
|
||||||
|
return std::unique_ptr<osmium::io::Decompressor>(std::get<2>(callbacks)(buffer, size));
|
||||||
if (it != m_callbacks.end()) {
|
|
||||||
return std::unique_ptr<osmium::io::Decompressor>(std::get<2>(it->second)(buffer, size));
|
|
||||||
}
|
|
||||||
|
|
||||||
error(compression);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}; // class CompressionFactory
|
}; // class CompressionFactory
|
||||||
|
@ -55,12 +55,17 @@ namespace osmium {
|
|||||||
|
|
||||||
namespace detail {
|
namespace detail {
|
||||||
|
|
||||||
|
struct reader_options {
|
||||||
|
osmium::osm_entity_bits::type read_which_entities = osm_entity_bits::all;
|
||||||
|
osmium::io::read_meta read_metadata = read_meta::yes;
|
||||||
|
};
|
||||||
|
|
||||||
class Parser {
|
class Parser {
|
||||||
|
|
||||||
future_buffer_queue_type& m_output_queue;
|
future_buffer_queue_type& m_output_queue;
|
||||||
std::promise<osmium::io::Header>& m_header_promise;
|
std::promise<osmium::io::Header>& m_header_promise;
|
||||||
queue_wrapper<std::string> m_input_queue;
|
queue_wrapper<std::string> m_input_queue;
|
||||||
osmium::osm_entity_bits::type m_read_types;
|
reader_options m_options;
|
||||||
bool m_header_is_done;
|
bool m_header_is_done;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
@ -73,11 +78,15 @@ namespace osmium {
|
|||||||
return m_input_queue.has_reached_end_of_data();
|
return m_input_queue.has_reached_end_of_data();
|
||||||
}
|
}
|
||||||
|
|
||||||
osmium::osm_entity_bits::type read_types() const {
|
osmium::osm_entity_bits::type read_types() const noexcept {
|
||||||
return m_read_types;
|
return m_options.read_which_entities;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool header_is_done() const {
|
osmium::io::read_meta read_metadata() const noexcept {
|
||||||
|
return m_options.read_metadata;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool header_is_done() const noexcept {
|
||||||
return m_header_is_done;
|
return m_header_is_done;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -111,11 +120,11 @@ namespace osmium {
|
|||||||
Parser(future_string_queue_type& input_queue,
|
Parser(future_string_queue_type& input_queue,
|
||||||
future_buffer_queue_type& output_queue,
|
future_buffer_queue_type& output_queue,
|
||||||
std::promise<osmium::io::Header>& header_promise,
|
std::promise<osmium::io::Header>& header_promise,
|
||||||
osmium::osm_entity_bits::type read_types) :
|
osmium::io::detail::reader_options options) :
|
||||||
m_output_queue(output_queue),
|
m_output_queue(output_queue),
|
||||||
m_header_promise(header_promise),
|
m_header_promise(header_promise),
|
||||||
m_input_queue(input_queue),
|
m_input_queue(input_queue),
|
||||||
m_read_types(read_types),
|
m_options(options),
|
||||||
m_header_is_done(false) {
|
m_header_is_done(false) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -157,7 +166,7 @@ namespace osmium {
|
|||||||
using create_parser_type = std::function<std::unique_ptr<Parser>(future_string_queue_type&,
|
using create_parser_type = std::function<std::unique_ptr<Parser>(future_string_queue_type&,
|
||||||
future_buffer_queue_type&,
|
future_buffer_queue_type&,
|
||||||
std::promise<osmium::io::Header>& header_promise,
|
std::promise<osmium::io::Header>& header_promise,
|
||||||
osmium::osm_entity_bits::type read_which_entities)>;
|
osmium::io::detail::reader_options options)>;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
@ -80,7 +80,7 @@ namespace osmium {
|
|||||||
struct o5m_error : public io_error {
|
struct o5m_error : public io_error {
|
||||||
|
|
||||||
explicit o5m_error(const char* what) :
|
explicit o5m_error(const char* what) :
|
||||||
io_error(std::string("o5m format error: ") + what) {
|
io_error(std::string{"o5m format error: "} + what) {
|
||||||
}
|
}
|
||||||
|
|
||||||
}; // struct o5m_error
|
}; // struct o5m_error
|
||||||
@ -135,7 +135,7 @@ namespace osmium {
|
|||||||
|
|
||||||
const char* get(uint64_t index) const {
|
const char* get(uint64_t index) const {
|
||||||
if (m_table.empty() || index == 0 || index > number_of_entries) {
|
if (m_table.empty() || index == 0 || index > number_of_entries) {
|
||||||
throw o5m_error("reference to non-existing string in table");
|
throw o5m_error{"reference to non-existing string in table"};
|
||||||
}
|
}
|
||||||
auto entry = (current_entry + number_of_entries - index) % number_of_entries;
|
auto entry = (current_entry + number_of_entries - index) % number_of_entries;
|
||||||
return &m_table[entry * entry_size];
|
return &m_table[entry * entry_size];
|
||||||
@ -191,7 +191,7 @@ namespace osmium {
|
|||||||
static const unsigned char header_magic[] = { 0xff, 0xe0, 0x04, 'o', '5' };
|
static const unsigned char header_magic[] = { 0xff, 0xe0, 0x04, 'o', '5' };
|
||||||
|
|
||||||
if (std::strncmp(reinterpret_cast<const char*>(header_magic), m_data, sizeof(header_magic))) {
|
if (std::strncmp(reinterpret_cast<const char*>(header_magic), m_data, sizeof(header_magic))) {
|
||||||
throw o5m_error("wrong header magic");
|
throw o5m_error{"wrong header magic"};
|
||||||
}
|
}
|
||||||
|
|
||||||
m_data += sizeof(header_magic);
|
m_data += sizeof(header_magic);
|
||||||
@ -203,7 +203,7 @@ namespace osmium {
|
|||||||
} else if (*m_data == 'c') { // o5c change file
|
} else if (*m_data == 'c') { // o5c change file
|
||||||
m_header.set_has_multiple_object_versions(true);
|
m_header.set_has_multiple_object_versions(true);
|
||||||
} else {
|
} else {
|
||||||
throw o5m_error("wrong header magic");
|
throw o5m_error{"wrong header magic"};
|
||||||
}
|
}
|
||||||
|
|
||||||
m_data++;
|
m_data++;
|
||||||
@ -211,7 +211,7 @@ namespace osmium {
|
|||||||
|
|
||||||
void check_file_format_version() {
|
void check_file_format_version() {
|
||||||
if (*m_data != '2') {
|
if (*m_data != '2') {
|
||||||
throw o5m_error("wrong header magic");
|
throw o5m_error{"wrong header magic"};
|
||||||
}
|
}
|
||||||
|
|
||||||
m_data++;
|
m_data++;
|
||||||
@ -219,7 +219,7 @@ namespace osmium {
|
|||||||
|
|
||||||
void decode_header() {
|
void decode_header() {
|
||||||
if (! ensure_bytes_available(7)) { // overall length of header
|
if (! ensure_bytes_available(7)) { // overall length of header
|
||||||
throw o5m_error("file too short (incomplete header info)");
|
throw o5m_error{"file too short (incomplete header info)"};
|
||||||
}
|
}
|
||||||
|
|
||||||
check_header_magic();
|
check_header_magic();
|
||||||
@ -260,7 +260,7 @@ namespace osmium {
|
|||||||
if (**dataptr == 0x00) { // get inline string
|
if (**dataptr == 0x00) { // get inline string
|
||||||
(*dataptr)++;
|
(*dataptr)++;
|
||||||
if (*dataptr == end) {
|
if (*dataptr == end) {
|
||||||
throw o5m_error("string format error");
|
throw o5m_error{"string format error"};
|
||||||
}
|
}
|
||||||
return *dataptr;
|
return *dataptr;
|
||||||
} else { // get from reference table
|
} else { // get from reference table
|
||||||
@ -277,7 +277,7 @@ namespace osmium {
|
|||||||
auto uid = protozero::decode_varint(&data, end);
|
auto uid = protozero::decode_varint(&data, end);
|
||||||
|
|
||||||
if (data == end) {
|
if (data == end) {
|
||||||
throw o5m_error("missing user name");
|
throw o5m_error{"missing user name"};
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* user = ++data;
|
const char* user = ++data;
|
||||||
@ -290,7 +290,7 @@ namespace osmium {
|
|||||||
|
|
||||||
while (*data++) {
|
while (*data++) {
|
||||||
if (data == end) {
|
if (data == end) {
|
||||||
throw o5m_error("no null byte in user name");
|
throw o5m_error{"no null byte in user name"};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -302,24 +302,24 @@ namespace osmium {
|
|||||||
return std::make_pair(static_cast_with_assert<osmium::user_id_type>(uid), user);
|
return std::make_pair(static_cast_with_assert<osmium::user_id_type>(uid), user);
|
||||||
}
|
}
|
||||||
|
|
||||||
void decode_tags(osmium::builder::Builder* builder, const char** dataptr, const char* const end) {
|
void decode_tags(osmium::builder::Builder& parent, const char** dataptr, const char* const end) {
|
||||||
osmium::builder::TagListBuilder tl_builder(m_buffer, builder);
|
osmium::builder::TagListBuilder builder{parent};
|
||||||
|
|
||||||
while(*dataptr != end) {
|
while (*dataptr != end) {
|
||||||
bool update_pointer = (**dataptr == 0x00);
|
bool update_pointer = (**dataptr == 0x00);
|
||||||
const char* data = decode_string(dataptr, end);
|
const char* data = decode_string(dataptr, end);
|
||||||
const char* start = data;
|
const char* start = data;
|
||||||
|
|
||||||
while (*data++) {
|
while (*data++) {
|
||||||
if (data == end) {
|
if (data == end) {
|
||||||
throw o5m_error("no null byte in tag key");
|
throw o5m_error{"no null byte in tag key"};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* value = data;
|
const char* value = data;
|
||||||
while (*data++) {
|
while (*data++) {
|
||||||
if (data == end) {
|
if (data == end) {
|
||||||
throw o5m_error("no null byte in tag value");
|
throw o5m_error{"no null byte in tag value"};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -328,7 +328,7 @@ namespace osmium {
|
|||||||
*dataptr = data;
|
*dataptr = data;
|
||||||
}
|
}
|
||||||
|
|
||||||
tl_builder.add_tag(start, value);
|
builder.add_tag(start, value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -357,50 +357,46 @@ namespace osmium {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void decode_node(const char* data, const char* const end) {
|
void decode_node(const char* data, const char* const end) {
|
||||||
osmium::builder::NodeBuilder builder(m_buffer);
|
osmium::builder::NodeBuilder builder{m_buffer};
|
||||||
osmium::Node& node = builder.object();
|
|
||||||
|
|
||||||
node.set_id(m_delta_id.update(zvarint(&data, end)));
|
builder.set_id(m_delta_id.update(zvarint(&data, end)));
|
||||||
|
|
||||||
builder.add_user(decode_info(node, &data, end));
|
builder.set_user(decode_info(builder.object(), &data, end));
|
||||||
|
|
||||||
if (data == end) {
|
if (data == end) {
|
||||||
// no location, object is deleted
|
// no location, object is deleted
|
||||||
builder.object().set_visible(false);
|
builder.set_visible(false);
|
||||||
builder.object().set_location(osmium::Location{});
|
builder.set_location(osmium::Location{});
|
||||||
} else {
|
} else {
|
||||||
auto lon = m_delta_lon.update(zvarint(&data, end));
|
auto lon = m_delta_lon.update(zvarint(&data, end));
|
||||||
auto lat = m_delta_lat.update(zvarint(&data, end));
|
auto lat = m_delta_lat.update(zvarint(&data, end));
|
||||||
builder.object().set_location(osmium::Location{lon, lat});
|
builder.set_location(osmium::Location{lon, lat});
|
||||||
|
|
||||||
if (data != end) {
|
if (data != end) {
|
||||||
decode_tags(&builder, &data, end);
|
decode_tags(builder, &data, end);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
m_buffer.commit();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void decode_way(const char* data, const char* const end) {
|
void decode_way(const char* data, const char* const end) {
|
||||||
osmium::builder::WayBuilder builder(m_buffer);
|
osmium::builder::WayBuilder builder{m_buffer};
|
||||||
osmium::Way& way = builder.object();
|
|
||||||
|
|
||||||
way.set_id(m_delta_id.update(zvarint(&data, end)));
|
builder.set_id(m_delta_id.update(zvarint(&data, end)));
|
||||||
|
|
||||||
builder.add_user(decode_info(way, &data, end));
|
builder.set_user(decode_info(builder.object(), &data, end));
|
||||||
|
|
||||||
if (data == end) {
|
if (data == end) {
|
||||||
// no reference section, object is deleted
|
// no reference section, object is deleted
|
||||||
builder.object().set_visible(false);
|
builder.set_visible(false);
|
||||||
} else {
|
} else {
|
||||||
auto reference_section_length = protozero::decode_varint(&data, end);
|
auto reference_section_length = protozero::decode_varint(&data, end);
|
||||||
if (reference_section_length > 0) {
|
if (reference_section_length > 0) {
|
||||||
const char* const end_refs = data + reference_section_length;
|
const char* const end_refs = data + reference_section_length;
|
||||||
if (end_refs > end) {
|
if (end_refs > end) {
|
||||||
throw o5m_error("way nodes ref section too long");
|
throw o5m_error{"way nodes ref section too long"};
|
||||||
}
|
}
|
||||||
|
|
||||||
osmium::builder::WayNodeListBuilder wn_builder(m_buffer, &builder);
|
osmium::builder::WayNodeListBuilder wn_builder{builder};
|
||||||
|
|
||||||
while (data < end_refs) {
|
while (data < end_refs) {
|
||||||
wn_builder.add_node_ref(m_delta_way_node_id.update(zvarint(&data, end)));
|
wn_builder.add_node_ref(m_delta_way_node_id.update(zvarint(&data, end)));
|
||||||
@ -408,16 +404,14 @@ namespace osmium {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (data != end) {
|
if (data != end) {
|
||||||
decode_tags(&builder, &data, end);
|
decode_tags(builder, &data, end);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
m_buffer.commit();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
osmium::item_type decode_member_type(char c) {
|
osmium::item_type decode_member_type(char c) {
|
||||||
if (c < '0' || c > '2') {
|
if (c < '0' || c > '2') {
|
||||||
throw o5m_error("unknown member type");
|
throw o5m_error{"unknown member type"};
|
||||||
}
|
}
|
||||||
return osmium::nwr_index_to_item_type(c - '0');
|
return osmium::nwr_index_to_item_type(c - '0');
|
||||||
}
|
}
|
||||||
@ -429,13 +423,13 @@ namespace osmium {
|
|||||||
|
|
||||||
auto member_type = decode_member_type(*data++);
|
auto member_type = decode_member_type(*data++);
|
||||||
if (data == end) {
|
if (data == end) {
|
||||||
throw o5m_error("missing role");
|
throw o5m_error{"missing role"};
|
||||||
}
|
}
|
||||||
const char* role = data;
|
const char* role = data;
|
||||||
|
|
||||||
while (*data++) {
|
while (*data++) {
|
||||||
if (data == end) {
|
if (data == end) {
|
||||||
throw o5m_error("no null byte in role");
|
throw o5m_error{"no null byte in role"};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -448,30 +442,29 @@ namespace osmium {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void decode_relation(const char* data, const char* const end) {
|
void decode_relation(const char* data, const char* const end) {
|
||||||
osmium::builder::RelationBuilder builder(m_buffer);
|
osmium::builder::RelationBuilder builder{m_buffer};
|
||||||
osmium::Relation& relation = builder.object();
|
|
||||||
|
|
||||||
relation.set_id(m_delta_id.update(zvarint(&data, end)));
|
builder.set_id(m_delta_id.update(zvarint(&data, end)));
|
||||||
|
|
||||||
builder.add_user(decode_info(relation, &data, end));
|
builder.set_user(decode_info(builder.object(), &data, end));
|
||||||
|
|
||||||
if (data == end) {
|
if (data == end) {
|
||||||
// no reference section, object is deleted
|
// no reference section, object is deleted
|
||||||
builder.object().set_visible(false);
|
builder.set_visible(false);
|
||||||
} else {
|
} else {
|
||||||
auto reference_section_length = protozero::decode_varint(&data, end);
|
auto reference_section_length = protozero::decode_varint(&data, end);
|
||||||
if (reference_section_length > 0) {
|
if (reference_section_length > 0) {
|
||||||
const char* const end_refs = data + reference_section_length;
|
const char* const end_refs = data + reference_section_length;
|
||||||
if (end_refs > end) {
|
if (end_refs > end) {
|
||||||
throw o5m_error("relation format error");
|
throw o5m_error{"relation format error"};
|
||||||
}
|
}
|
||||||
|
|
||||||
osmium::builder::RelationMemberListBuilder rml_builder(m_buffer, &builder);
|
osmium::builder::RelationMemberListBuilder rml_builder{builder};
|
||||||
|
|
||||||
while (data < end_refs) {
|
while (data < end_refs) {
|
||||||
auto delta_id = zvarint(&data, end);
|
auto delta_id = zvarint(&data, end);
|
||||||
if (data == end) {
|
if (data == end) {
|
||||||
throw o5m_error("relation member format error");
|
throw o5m_error{"relation member format error"};
|
||||||
}
|
}
|
||||||
auto type_role = decode_role(&data, end);
|
auto type_role = decode_role(&data, end);
|
||||||
auto i = osmium::item_type_to_nwr_index(type_role.first);
|
auto i = osmium::item_type_to_nwr_index(type_role.first);
|
||||||
@ -481,11 +474,9 @@ namespace osmium {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (data != end) {
|
if (data != end) {
|
||||||
decode_tags(&builder, &data, end);
|
decode_tags(builder, &data, end);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
m_buffer.commit();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void decode_bbox(const char* data, const char* const end) {
|
void decode_bbox(const char* data, const char* const end) {
|
||||||
@ -537,11 +528,11 @@ namespace osmium {
|
|||||||
try {
|
try {
|
||||||
length = protozero::decode_varint(&m_data, m_end);
|
length = protozero::decode_varint(&m_data, m_end);
|
||||||
} catch (const protozero::end_of_buffer_exception&) {
|
} catch (const protozero::end_of_buffer_exception&) {
|
||||||
throw o5m_error("premature end of file");
|
throw o5m_error{"premature end of file"};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (! ensure_bytes_available(length)) {
|
if (! ensure_bytes_available(length)) {
|
||||||
throw o5m_error("premature end of file");
|
throw o5m_error{"premature end of file"};
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (ds_type) {
|
switch (ds_type) {
|
||||||
@ -549,18 +540,21 @@ namespace osmium {
|
|||||||
mark_header_as_done();
|
mark_header_as_done();
|
||||||
if (read_types() & osmium::osm_entity_bits::node) {
|
if (read_types() & osmium::osm_entity_bits::node) {
|
||||||
decode_node(m_data, m_data + length);
|
decode_node(m_data, m_data + length);
|
||||||
|
m_buffer.commit();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case dataset_type::way:
|
case dataset_type::way:
|
||||||
mark_header_as_done();
|
mark_header_as_done();
|
||||||
if (read_types() & osmium::osm_entity_bits::way) {
|
if (read_types() & osmium::osm_entity_bits::way) {
|
||||||
decode_way(m_data, m_data + length);
|
decode_way(m_data, m_data + length);
|
||||||
|
m_buffer.commit();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case dataset_type::relation:
|
case dataset_type::relation:
|
||||||
mark_header_as_done();
|
mark_header_as_done();
|
||||||
if (read_types() & osmium::osm_entity_bits::relation) {
|
if (read_types() & osmium::osm_entity_bits::relation) {
|
||||||
decode_relation(m_data, m_data + length);
|
decode_relation(m_data, m_data + length);
|
||||||
|
m_buffer.commit();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case dataset_type::bounding_box:
|
case dataset_type::bounding_box:
|
||||||
@ -598,8 +592,8 @@ namespace osmium {
|
|||||||
O5mParser(future_string_queue_type& input_queue,
|
O5mParser(future_string_queue_type& input_queue,
|
||||||
future_buffer_queue_type& output_queue,
|
future_buffer_queue_type& output_queue,
|
||||||
std::promise<osmium::io::Header>& header_promise,
|
std::promise<osmium::io::Header>& header_promise,
|
||||||
osmium::osm_entity_bits::type read_types) :
|
osmium::io::detail::reader_options options) :
|
||||||
Parser(input_queue, output_queue, header_promise, read_types),
|
Parser(input_queue, output_queue, header_promise, options),
|
||||||
m_header(),
|
m_header(),
|
||||||
m_buffer(buffer_size),
|
m_buffer(buffer_size),
|
||||||
m_input(),
|
m_input(),
|
||||||
@ -625,8 +619,8 @@ namespace osmium {
|
|||||||
[](future_string_queue_type& input_queue,
|
[](future_string_queue_type& input_queue,
|
||||||
future_buffer_queue_type& output_queue,
|
future_buffer_queue_type& output_queue,
|
||||||
std::promise<osmium::io::Header>& header_promise,
|
std::promise<osmium::io::Header>& header_promise,
|
||||||
osmium::osm_entity_bits::type read_which_entities) {
|
osmium::io::detail::reader_options options) {
|
||||||
return std::unique_ptr<Parser>(new O5mParser(input_queue, output_queue, header_promise, read_which_entities));
|
return std::unique_ptr<Parser>(new O5mParser(input_queue, output_queue, header_promise, options));
|
||||||
});
|
});
|
||||||
|
|
||||||
// dummy function to silence the unused variable warning from above
|
// dummy function to silence the unused variable warning from above
|
||||||
|
@ -82,8 +82,8 @@ namespace osmium {
|
|||||||
OPLParser(future_string_queue_type& input_queue,
|
OPLParser(future_string_queue_type& input_queue,
|
||||||
future_buffer_queue_type& output_queue,
|
future_buffer_queue_type& output_queue,
|
||||||
std::promise<osmium::io::Header>& header_promise,
|
std::promise<osmium::io::Header>& header_promise,
|
||||||
osmium::osm_entity_bits::type read_types) :
|
osmium::io::detail::reader_options options) :
|
||||||
Parser(input_queue, output_queue, header_promise, read_types) {
|
Parser(input_queue, output_queue, header_promise, options) {
|
||||||
set_header_value(osmium::io::Header{});
|
set_header_value(osmium::io::Header{});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -137,8 +137,8 @@ namespace osmium {
|
|||||||
[](future_string_queue_type& input_queue,
|
[](future_string_queue_type& input_queue,
|
||||||
future_buffer_queue_type& output_queue,
|
future_buffer_queue_type& output_queue,
|
||||||
std::promise<osmium::io::Header>& header_promise,
|
std::promise<osmium::io::Header>& header_promise,
|
||||||
osmium::osm_entity_bits::type read_which_entities) {
|
osmium::io::detail::reader_options options) {
|
||||||
return std::unique_ptr<Parser>(new OPLParser(input_queue, output_queue, header_promise, read_which_entities));
|
return std::unique_ptr<Parser>(new OPLParser(input_queue, output_queue, header_promise, options));
|
||||||
});
|
});
|
||||||
|
|
||||||
// dummy function to silence the unused variable warning from above
|
// dummy function to silence the unused variable warning from above
|
||||||
|
@ -365,9 +365,8 @@ namespace osmium {
|
|||||||
|
|
||||||
inline void opl_parse_node(const char** data, osmium::memory::Buffer& buffer) {
|
inline void opl_parse_node(const char** data, osmium::memory::Buffer& buffer) {
|
||||||
osmium::builder::NodeBuilder builder{buffer};
|
osmium::builder::NodeBuilder builder{buffer};
|
||||||
osmium::Node& node = builder.object();
|
|
||||||
|
|
||||||
node.set_id(opl_parse_id(data));
|
builder.set_id(opl_parse_id(data));
|
||||||
|
|
||||||
const char* tags_begin = nullptr;
|
const char* tags_begin = nullptr;
|
||||||
|
|
||||||
@ -382,19 +381,19 @@ namespace osmium {
|
|||||||
++(*data);
|
++(*data);
|
||||||
switch (c) {
|
switch (c) {
|
||||||
case 'v':
|
case 'v':
|
||||||
node.set_version(opl_parse_version(data));
|
builder.set_version(opl_parse_version(data));
|
||||||
break;
|
break;
|
||||||
case 'd':
|
case 'd':
|
||||||
node.set_visible(opl_parse_visible(data));
|
builder.set_visible(opl_parse_visible(data));
|
||||||
break;
|
break;
|
||||||
case 'c':
|
case 'c':
|
||||||
node.set_changeset(opl_parse_changeset_id(data));
|
builder.set_changeset(opl_parse_changeset_id(data));
|
||||||
break;
|
break;
|
||||||
case 't':
|
case 't':
|
||||||
node.set_timestamp(opl_parse_timestamp(data));
|
builder.set_timestamp(opl_parse_timestamp(data));
|
||||||
break;
|
break;
|
||||||
case 'i':
|
case 'i':
|
||||||
node.set_uid(opl_parse_uid(data));
|
builder.set_uid(opl_parse_uid(data));
|
||||||
break;
|
break;
|
||||||
case 'u':
|
case 'u':
|
||||||
opl_parse_string(data, user);
|
opl_parse_string(data, user);
|
||||||
@ -422,23 +421,20 @@ namespace osmium {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (location.valid()) {
|
if (location.valid()) {
|
||||||
node.set_location(location);
|
builder.set_location(location);
|
||||||
}
|
}
|
||||||
|
|
||||||
builder.add_user(user);
|
builder.set_user(user);
|
||||||
|
|
||||||
if (tags_begin) {
|
if (tags_begin) {
|
||||||
opl_parse_tags(tags_begin, buffer, &builder);
|
opl_parse_tags(tags_begin, buffer, &builder);
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer.commit();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void opl_parse_way(const char** data, osmium::memory::Buffer& buffer) {
|
inline void opl_parse_way(const char** data, osmium::memory::Buffer& buffer) {
|
||||||
osmium::builder::WayBuilder builder{buffer};
|
osmium::builder::WayBuilder builder{buffer};
|
||||||
osmium::Way& way = builder.object();
|
|
||||||
|
|
||||||
way.set_id(opl_parse_id(data));
|
builder.set_id(opl_parse_id(data));
|
||||||
|
|
||||||
const char* tags_begin = nullptr;
|
const char* tags_begin = nullptr;
|
||||||
|
|
||||||
@ -455,19 +451,19 @@ namespace osmium {
|
|||||||
++(*data);
|
++(*data);
|
||||||
switch (c) {
|
switch (c) {
|
||||||
case 'v':
|
case 'v':
|
||||||
way.set_version(opl_parse_version(data));
|
builder.set_version(opl_parse_version(data));
|
||||||
break;
|
break;
|
||||||
case 'd':
|
case 'd':
|
||||||
way.set_visible(opl_parse_visible(data));
|
builder.set_visible(opl_parse_visible(data));
|
||||||
break;
|
break;
|
||||||
case 'c':
|
case 'c':
|
||||||
way.set_changeset(opl_parse_changeset_id(data));
|
builder.set_changeset(opl_parse_changeset_id(data));
|
||||||
break;
|
break;
|
||||||
case 't':
|
case 't':
|
||||||
way.set_timestamp(opl_parse_timestamp(data));
|
builder.set_timestamp(opl_parse_timestamp(data));
|
||||||
break;
|
break;
|
||||||
case 'i':
|
case 'i':
|
||||||
way.set_uid(opl_parse_uid(data));
|
builder.set_uid(opl_parse_uid(data));
|
||||||
break;
|
break;
|
||||||
case 'u':
|
case 'u':
|
||||||
opl_parse_string(data, user);
|
opl_parse_string(data, user);
|
||||||
@ -488,15 +484,13 @@ namespace osmium {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
builder.add_user(user);
|
builder.set_user(user);
|
||||||
|
|
||||||
if (tags_begin) {
|
if (tags_begin) {
|
||||||
opl_parse_tags(tags_begin, buffer, &builder);
|
opl_parse_tags(tags_begin, buffer, &builder);
|
||||||
}
|
}
|
||||||
|
|
||||||
opl_parse_way_nodes(nodes_begin, nodes_end, buffer, &builder);
|
opl_parse_way_nodes(nodes_begin, nodes_end, buffer, &builder);
|
||||||
|
|
||||||
buffer.commit();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void opl_parse_relation_members(const char* s, const char* e, osmium::memory::Buffer& buffer, osmium::builder::RelationBuilder* parent_builder = nullptr) {
|
inline void opl_parse_relation_members(const char* s, const char* e, osmium::memory::Buffer& buffer, osmium::builder::RelationBuilder* parent_builder = nullptr) {
|
||||||
@ -536,9 +530,8 @@ namespace osmium {
|
|||||||
|
|
||||||
inline void opl_parse_relation(const char** data, osmium::memory::Buffer& buffer) {
|
inline void opl_parse_relation(const char** data, osmium::memory::Buffer& buffer) {
|
||||||
osmium::builder::RelationBuilder builder{buffer};
|
osmium::builder::RelationBuilder builder{buffer};
|
||||||
osmium::Relation& relation = builder.object();
|
|
||||||
|
|
||||||
relation.set_id(opl_parse_id(data));
|
builder.set_id(opl_parse_id(data));
|
||||||
|
|
||||||
const char* tags_begin = nullptr;
|
const char* tags_begin = nullptr;
|
||||||
|
|
||||||
@ -555,19 +548,19 @@ namespace osmium {
|
|||||||
++(*data);
|
++(*data);
|
||||||
switch (c) {
|
switch (c) {
|
||||||
case 'v':
|
case 'v':
|
||||||
relation.set_version(opl_parse_version(data));
|
builder.set_version(opl_parse_version(data));
|
||||||
break;
|
break;
|
||||||
case 'd':
|
case 'd':
|
||||||
relation.set_visible(opl_parse_visible(data));
|
builder.set_visible(opl_parse_visible(data));
|
||||||
break;
|
break;
|
||||||
case 'c':
|
case 'c':
|
||||||
relation.set_changeset(opl_parse_changeset_id(data));
|
builder.set_changeset(opl_parse_changeset_id(data));
|
||||||
break;
|
break;
|
||||||
case 't':
|
case 't':
|
||||||
relation.set_timestamp(opl_parse_timestamp(data));
|
builder.set_timestamp(opl_parse_timestamp(data));
|
||||||
break;
|
break;
|
||||||
case 'i':
|
case 'i':
|
||||||
relation.set_uid(opl_parse_uid(data));
|
builder.set_uid(opl_parse_uid(data));
|
||||||
break;
|
break;
|
||||||
case 'u':
|
case 'u':
|
||||||
opl_parse_string(data, user);
|
opl_parse_string(data, user);
|
||||||
@ -588,7 +581,7 @@ namespace osmium {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
builder.add_user(user);
|
builder.set_user(user);
|
||||||
|
|
||||||
if (tags_begin) {
|
if (tags_begin) {
|
||||||
opl_parse_tags(tags_begin, buffer, &builder);
|
opl_parse_tags(tags_begin, buffer, &builder);
|
||||||
@ -597,15 +590,12 @@ namespace osmium {
|
|||||||
if (members_begin != members_end) {
|
if (members_begin != members_end) {
|
||||||
opl_parse_relation_members(members_begin, members_end, buffer, &builder);
|
opl_parse_relation_members(members_begin, members_end, buffer, &builder);
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer.commit();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void opl_parse_changeset(const char** data, osmium::memory::Buffer& buffer) {
|
inline void opl_parse_changeset(const char** data, osmium::memory::Buffer& buffer) {
|
||||||
osmium::builder::ChangesetBuilder builder{buffer};
|
osmium::builder::ChangesetBuilder builder{buffer};
|
||||||
osmium::Changeset& changeset = builder.object();
|
|
||||||
|
|
||||||
changeset.set_id(opl_parse_changeset_id(data));
|
builder.set_id(opl_parse_changeset_id(data));
|
||||||
|
|
||||||
const char* tags_begin = nullptr;
|
const char* tags_begin = nullptr;
|
||||||
|
|
||||||
@ -621,19 +611,19 @@ namespace osmium {
|
|||||||
++(*data);
|
++(*data);
|
||||||
switch (c) {
|
switch (c) {
|
||||||
case 'k':
|
case 'k':
|
||||||
changeset.set_num_changes(opl_parse_int<osmium::num_changes_type>(data));
|
builder.set_num_changes(opl_parse_int<osmium::num_changes_type>(data));
|
||||||
break;
|
break;
|
||||||
case 's':
|
case 's':
|
||||||
changeset.set_created_at(opl_parse_timestamp(data));
|
builder.set_created_at(opl_parse_timestamp(data));
|
||||||
break;
|
break;
|
||||||
case 'e':
|
case 'e':
|
||||||
changeset.set_closed_at(opl_parse_timestamp(data));
|
builder.set_closed_at(opl_parse_timestamp(data));
|
||||||
break;
|
break;
|
||||||
case 'd':
|
case 'd':
|
||||||
changeset.set_num_comments(opl_parse_int<osmium::num_comments_type>(data));
|
builder.set_num_comments(opl_parse_int<osmium::num_comments_type>(data));
|
||||||
break;
|
break;
|
||||||
case 'i':
|
case 'i':
|
||||||
changeset.set_uid(opl_parse_uid(data));
|
builder.set_uid(opl_parse_uid(data));
|
||||||
break;
|
break;
|
||||||
case 'u':
|
case 'u':
|
||||||
opl_parse_string(data, user);
|
opl_parse_string(data, user);
|
||||||
@ -672,17 +662,17 @@ namespace osmium {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (location1.valid() && location2.valid()) {
|
if (location1.valid() && location2.valid()) {
|
||||||
changeset.bounds().extend(location1);
|
osmium::Box box;
|
||||||
changeset.bounds().extend(location2);
|
box.extend(location1);
|
||||||
|
box.extend(location2);
|
||||||
|
builder.set_bounds(box);
|
||||||
}
|
}
|
||||||
|
|
||||||
builder.add_user(user);
|
builder.set_user(user);
|
||||||
|
|
||||||
if (tags_begin) {
|
if (tags_begin) {
|
||||||
opl_parse_tags(tags_begin, buffer, &builder);
|
opl_parse_tags(tags_begin, buffer, &builder);
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer.commit();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool opl_parse_line(uint64_t line_count,
|
inline bool opl_parse_line(uint64_t line_count,
|
||||||
@ -702,6 +692,7 @@ namespace osmium {
|
|||||||
if (read_types & osmium::osm_entity_bits::node) {
|
if (read_types & osmium::osm_entity_bits::node) {
|
||||||
++data;
|
++data;
|
||||||
opl_parse_node(&data, buffer);
|
opl_parse_node(&data, buffer);
|
||||||
|
buffer.commit();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -709,6 +700,7 @@ namespace osmium {
|
|||||||
if (read_types & osmium::osm_entity_bits::way) {
|
if (read_types & osmium::osm_entity_bits::way) {
|
||||||
++data;
|
++data;
|
||||||
opl_parse_way(&data, buffer);
|
opl_parse_way(&data, buffer);
|
||||||
|
buffer.commit();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -716,6 +708,7 @@ namespace osmium {
|
|||||||
if (read_types & osmium::osm_entity_bits::relation) {
|
if (read_types & osmium::osm_entity_bits::relation) {
|
||||||
++data;
|
++data;
|
||||||
opl_parse_relation(&data, buffer);
|
opl_parse_relation(&data, buffer);
|
||||||
|
buffer.commit();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -723,6 +716,7 @@ namespace osmium {
|
|||||||
if (read_types & osmium::osm_entity_bits::changeset) {
|
if (read_types & osmium::osm_entity_bits::changeset) {
|
||||||
++data;
|
++data;
|
||||||
opl_parse_changeset(&data, buffer);
|
opl_parse_changeset(&data, buffer);
|
||||||
|
buffer.commit();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -50,6 +50,7 @@ DEALINGS IN THE SOFTWARE.
|
|||||||
#include <osmium/io/detail/pbf.hpp> // IWYU pragma: export
|
#include <osmium/io/detail/pbf.hpp> // IWYU pragma: export
|
||||||
#include <osmium/io/detail/protobuf_tags.hpp>
|
#include <osmium/io/detail/protobuf_tags.hpp>
|
||||||
#include <osmium/io/detail/zlib.hpp>
|
#include <osmium/io/detail/zlib.hpp>
|
||||||
|
#include <osmium/io/file_format.hpp>
|
||||||
#include <osmium/io/header.hpp>
|
#include <osmium/io/header.hpp>
|
||||||
#include <osmium/memory/buffer.hpp>
|
#include <osmium/memory/buffer.hpp>
|
||||||
#include <osmium/osm/box.hpp>
|
#include <osmium/osm/box.hpp>
|
||||||
@ -94,6 +95,8 @@ namespace osmium {
|
|||||||
|
|
||||||
osmium::memory::Buffer m_buffer { initial_buffer_size };
|
osmium::memory::Buffer m_buffer { initial_buffer_size };
|
||||||
|
|
||||||
|
osmium::io::read_meta m_read_metadata;
|
||||||
|
|
||||||
void decode_stringtable(const data_view& data) {
|
void decode_stringtable(const data_view& data) {
|
||||||
if (!m_stringtable.empty()) {
|
if (!m_stringtable.empty()) {
|
||||||
throw osmium::pbf_error("more than one stringtable in pbf file");
|
throw osmium::pbf_error("more than one stringtable in pbf file");
|
||||||
@ -143,13 +146,19 @@ namespace osmium {
|
|||||||
case OSMFormat::PrimitiveGroup::repeated_Node_nodes:
|
case OSMFormat::PrimitiveGroup::repeated_Node_nodes:
|
||||||
if (m_read_types & osmium::osm_entity_bits::node) {
|
if (m_read_types & osmium::osm_entity_bits::node) {
|
||||||
decode_node(pbf_primitive_group.get_view());
|
decode_node(pbf_primitive_group.get_view());
|
||||||
|
m_buffer.commit();
|
||||||
} else {
|
} else {
|
||||||
pbf_primitive_group.skip();
|
pbf_primitive_group.skip();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case OSMFormat::PrimitiveGroup::optional_DenseNodes_dense:
|
case OSMFormat::PrimitiveGroup::optional_DenseNodes_dense:
|
||||||
if (m_read_types & osmium::osm_entity_bits::node) {
|
if (m_read_types & osmium::osm_entity_bits::node) {
|
||||||
decode_dense_nodes(pbf_primitive_group.get_view());
|
if (m_read_metadata == osmium::io::read_meta::yes) {
|
||||||
|
decode_dense_nodes(pbf_primitive_group.get_view());
|
||||||
|
} else {
|
||||||
|
decode_dense_nodes_without_metadata(pbf_primitive_group.get_view());
|
||||||
|
}
|
||||||
|
m_buffer.commit();
|
||||||
} else {
|
} else {
|
||||||
pbf_primitive_group.skip();
|
pbf_primitive_group.skip();
|
||||||
}
|
}
|
||||||
@ -157,6 +166,7 @@ namespace osmium {
|
|||||||
case OSMFormat::PrimitiveGroup::repeated_Way_ways:
|
case OSMFormat::PrimitiveGroup::repeated_Way_ways:
|
||||||
if (m_read_types & osmium::osm_entity_bits::way) {
|
if (m_read_types & osmium::osm_entity_bits::way) {
|
||||||
decode_way(pbf_primitive_group.get_view());
|
decode_way(pbf_primitive_group.get_view());
|
||||||
|
m_buffer.commit();
|
||||||
} else {
|
} else {
|
||||||
pbf_primitive_group.skip();
|
pbf_primitive_group.skip();
|
||||||
}
|
}
|
||||||
@ -164,6 +174,7 @@ namespace osmium {
|
|||||||
case OSMFormat::PrimitiveGroup::repeated_Relation_relations:
|
case OSMFormat::PrimitiveGroup::repeated_Relation_relations:
|
||||||
if (m_read_types & osmium::osm_entity_bits::relation) {
|
if (m_read_types & osmium::osm_entity_bits::relation) {
|
||||||
decode_relation(pbf_primitive_group.get_view());
|
decode_relation(pbf_primitive_group.get_view());
|
||||||
|
m_buffer.commit();
|
||||||
} else {
|
} else {
|
||||||
pbf_primitive_group.skip();
|
pbf_primitive_group.skip();
|
||||||
}
|
}
|
||||||
@ -221,9 +232,9 @@ namespace osmium {
|
|||||||
|
|
||||||
using kv_type = protozero::iterator_range<protozero::pbf_reader::const_uint32_iterator>;
|
using kv_type = protozero::iterator_range<protozero::pbf_reader::const_uint32_iterator>;
|
||||||
|
|
||||||
void build_tag_list(osmium::builder::Builder& builder, const kv_type& keys, const kv_type& vals) {
|
void build_tag_list(osmium::builder::Builder& parent, const kv_type& keys, const kv_type& vals) {
|
||||||
if (!keys.empty()) {
|
if (!keys.empty()) {
|
||||||
osmium::builder::TagListBuilder tl_builder(m_buffer, &builder);
|
osmium::builder::TagListBuilder builder{parent};
|
||||||
auto kit = keys.begin();
|
auto kit = keys.begin();
|
||||||
auto vit = vals.begin();
|
auto vit = vals.begin();
|
||||||
while (kit != keys.end()) {
|
while (kit != keys.end()) {
|
||||||
@ -233,7 +244,7 @@ namespace osmium {
|
|||||||
}
|
}
|
||||||
const auto& k = m_stringtable.at(*kit++);
|
const auto& k = m_stringtable.at(*kit++);
|
||||||
const auto& v = m_stringtable.at(*vit++);
|
const auto& v = m_stringtable.at(*vit++);
|
||||||
tl_builder.add_tag(k.first, k.second, v.first, v.second);
|
builder.add_tag(k.first, k.second, v.first, v.second);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -243,7 +254,7 @@ namespace osmium {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void decode_node(const data_view& data) {
|
void decode_node(const data_view& data) {
|
||||||
osmium::builder::NodeBuilder builder(m_buffer);
|
osmium::builder::NodeBuilder builder{m_buffer};
|
||||||
osmium::Node& node = builder.object();
|
osmium::Node& node = builder.object();
|
||||||
|
|
||||||
kv_type keys;
|
kv_type keys;
|
||||||
@ -266,7 +277,11 @@ namespace osmium {
|
|||||||
vals = pbf_node.get_packed_uint32();
|
vals = pbf_node.get_packed_uint32();
|
||||||
break;
|
break;
|
||||||
case OSMFormat::Node::optional_Info_info:
|
case OSMFormat::Node::optional_Info_info:
|
||||||
user = decode_info(pbf_node.get_view(), builder.object());
|
if (m_read_metadata == osmium::io::read_meta::yes) {
|
||||||
|
user = decode_info(pbf_node.get_view(), builder.object());
|
||||||
|
} else {
|
||||||
|
pbf_node.skip();
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case OSMFormat::Node::required_sint64_lat:
|
case OSMFormat::Node::required_sint64_lat:
|
||||||
lat = pbf_node.get_sint64();
|
lat = pbf_node.get_sint64();
|
||||||
@ -290,15 +305,13 @@ namespace osmium {
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
builder.add_user(user.first, user.second);
|
builder.set_user(user.first, user.second);
|
||||||
|
|
||||||
build_tag_list(builder, keys, vals);
|
build_tag_list(builder, keys, vals);
|
||||||
|
|
||||||
m_buffer.commit();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void decode_way(const data_view& data) {
|
void decode_way(const data_view& data) {
|
||||||
osmium::builder::WayBuilder builder(m_buffer);
|
osmium::builder::WayBuilder builder{m_buffer};
|
||||||
|
|
||||||
kv_type keys;
|
kv_type keys;
|
||||||
kv_type vals;
|
kv_type vals;
|
||||||
@ -321,7 +334,11 @@ namespace osmium {
|
|||||||
vals = pbf_way.get_packed_uint32();
|
vals = pbf_way.get_packed_uint32();
|
||||||
break;
|
break;
|
||||||
case OSMFormat::Way::optional_Info_info:
|
case OSMFormat::Way::optional_Info_info:
|
||||||
user = decode_info(pbf_way.get_view(), builder.object());
|
if (m_read_metadata == osmium::io::read_meta::yes) {
|
||||||
|
user = decode_info(pbf_way.get_view(), builder.object());
|
||||||
|
} else {
|
||||||
|
pbf_way.skip();
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case OSMFormat::Way::packed_sint64_refs:
|
case OSMFormat::Way::packed_sint64_refs:
|
||||||
refs = pbf_way.get_packed_sint64();
|
refs = pbf_way.get_packed_sint64();
|
||||||
@ -337,10 +354,10 @@ namespace osmium {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
builder.add_user(user.first, user.second);
|
builder.set_user(user.first, user.second);
|
||||||
|
|
||||||
if (!refs.empty()) {
|
if (!refs.empty()) {
|
||||||
osmium::builder::WayNodeListBuilder wnl_builder(m_buffer, &builder);
|
osmium::builder::WayNodeListBuilder wnl_builder{builder};
|
||||||
osmium::util::DeltaDecode<int64_t> ref;
|
osmium::util::DeltaDecode<int64_t> ref;
|
||||||
if (lats.empty()) {
|
if (lats.empty()) {
|
||||||
for (const auto& ref_value : refs) {
|
for (const auto& ref_value : refs) {
|
||||||
@ -363,12 +380,10 @@ namespace osmium {
|
|||||||
}
|
}
|
||||||
|
|
||||||
build_tag_list(builder, keys, vals);
|
build_tag_list(builder, keys, vals);
|
||||||
|
|
||||||
m_buffer.commit();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void decode_relation(const data_view& data) {
|
void decode_relation(const data_view& data) {
|
||||||
osmium::builder::RelationBuilder builder(m_buffer);
|
osmium::builder::RelationBuilder builder{m_buffer};
|
||||||
|
|
||||||
kv_type keys;
|
kv_type keys;
|
||||||
kv_type vals;
|
kv_type vals;
|
||||||
@ -391,7 +406,11 @@ namespace osmium {
|
|||||||
vals = pbf_relation.get_packed_uint32();
|
vals = pbf_relation.get_packed_uint32();
|
||||||
break;
|
break;
|
||||||
case OSMFormat::Relation::optional_Info_info:
|
case OSMFormat::Relation::optional_Info_info:
|
||||||
user = decode_info(pbf_relation.get_view(), builder.object());
|
if (m_read_metadata == osmium::io::read_meta::yes) {
|
||||||
|
user = decode_info(pbf_relation.get_view(), builder.object());
|
||||||
|
} else {
|
||||||
|
pbf_relation.skip();
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case OSMFormat::Relation::packed_int32_roles_sid:
|
case OSMFormat::Relation::packed_int32_roles_sid:
|
||||||
roles = pbf_relation.get_packed_int32();
|
roles = pbf_relation.get_packed_int32();
|
||||||
@ -407,10 +426,10 @@ namespace osmium {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
builder.add_user(user.first, user.second);
|
builder.set_user(user.first, user.second);
|
||||||
|
|
||||||
if (!refs.empty()) {
|
if (!refs.empty()) {
|
||||||
osmium::builder::RelationMemberListBuilder rml_builder(m_buffer, &builder);
|
osmium::builder::RelationMemberListBuilder rml_builder{builder};
|
||||||
osmium::util::DeltaDecode<int64_t> ref;
|
osmium::util::DeltaDecode<int64_t> ref;
|
||||||
while (!roles.empty() && !refs.empty() && !types.empty()) {
|
while (!roles.empty() && !refs.empty() && !types.empty()) {
|
||||||
const auto& r = m_stringtable.at(roles.front());
|
const auto& r = m_stringtable.at(roles.front());
|
||||||
@ -431,8 +450,84 @@ namespace osmium {
|
|||||||
}
|
}
|
||||||
|
|
||||||
build_tag_list(builder, keys, vals);
|
build_tag_list(builder, keys, vals);
|
||||||
|
}
|
||||||
|
|
||||||
|
void build_tag_list_from_dense_nodes(osmium::builder::NodeBuilder& builder, protozero::pbf_reader::const_int32_iterator& it, protozero::pbf_reader::const_int32_iterator last) {
|
||||||
|
osmium::builder::TagListBuilder tl_builder{builder};
|
||||||
|
while (it != last && *it != 0) {
|
||||||
|
const auto& k = m_stringtable.at(*it++);
|
||||||
|
if (it == last) {
|
||||||
|
throw osmium::pbf_error("PBF format error"); // this is against the spec, keys/vals must come in pairs
|
||||||
|
}
|
||||||
|
const auto& v = m_stringtable.at(*it++);
|
||||||
|
tl_builder.add_tag(k.first, k.second, v.first, v.second);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (it != last) {
|
||||||
|
++it;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void decode_dense_nodes_without_metadata(const data_view& data) {
|
||||||
|
protozero::iterator_range<protozero::pbf_reader::const_sint64_iterator> ids;
|
||||||
|
protozero::iterator_range<protozero::pbf_reader::const_sint64_iterator> lats;
|
||||||
|
protozero::iterator_range<protozero::pbf_reader::const_sint64_iterator> lons;
|
||||||
|
|
||||||
|
protozero::iterator_range<protozero::pbf_reader::const_int32_iterator> tags;
|
||||||
|
|
||||||
|
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::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;
|
||||||
|
|
||||||
|
auto tag_it = tags.begin();
|
||||||
|
|
||||||
|
while (!ids.empty()) {
|
||||||
|
if (lons.empty() ||
|
||||||
|
lats.empty()) {
|
||||||
|
// this is against the spec, must have same number of elements
|
||||||
|
throw osmium::pbf_error("PBF format error");
|
||||||
|
}
|
||||||
|
|
||||||
|
osmium::builder::NodeBuilder builder{m_buffer};
|
||||||
|
osmium::Node& node = builder.object();
|
||||||
|
|
||||||
|
node.set_id(dense_id.update(ids.front()));
|
||||||
|
ids.drop_front();
|
||||||
|
|
||||||
|
const auto lon = dense_longitude.update(lons.front());
|
||||||
|
lons.drop_front();
|
||||||
|
const auto lat = dense_latitude.update(lats.front());
|
||||||
|
lats.drop_front();
|
||||||
|
builder.object().set_location(osmium::Location(
|
||||||
|
convert_pbf_coordinate(lon),
|
||||||
|
convert_pbf_coordinate(lat)
|
||||||
|
));
|
||||||
|
|
||||||
|
if (tag_it != tags.end()) {
|
||||||
|
build_tag_list_from_dense_nodes(builder, tag_it, tags.end());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
m_buffer.commit();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void decode_dense_nodes(const data_view& data) {
|
void decode_dense_nodes(const data_view& data) {
|
||||||
@ -522,7 +617,7 @@ namespace osmium {
|
|||||||
|
|
||||||
bool visible = true;
|
bool visible = true;
|
||||||
|
|
||||||
osmium::builder::NodeBuilder builder(m_buffer);
|
osmium::builder::NodeBuilder builder{m_buffer};
|
||||||
osmium::Node& node = builder.object();
|
osmium::Node& node = builder.object();
|
||||||
|
|
||||||
node.set_id(dense_id.update(ids.front()));
|
node.set_id(dense_id.update(ids.front()));
|
||||||
@ -569,9 +664,7 @@ namespace osmium {
|
|||||||
|
|
||||||
const auto& u = m_stringtable.at(dense_user_sid.update(user_sids.front()));
|
const auto& u = m_stringtable.at(dense_user_sid.update(user_sids.front()));
|
||||||
user_sids.drop_front();
|
user_sids.drop_front();
|
||||||
builder.add_user(u.first, u.second);
|
builder.set_user(u.first, u.second);
|
||||||
} else {
|
|
||||||
builder.add_user("");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// even if the node isn't visible, there's still a record
|
// even if the node isn't visible, there's still a record
|
||||||
@ -588,31 +681,18 @@ namespace osmium {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (tag_it != tags.end()) {
|
if (tag_it != tags.end()) {
|
||||||
osmium::builder::TagListBuilder tl_builder(m_buffer, &builder);
|
build_tag_list_from_dense_nodes(builder, tag_it, tags.end());
|
||||||
while (tag_it != tags.end() && *tag_it != 0) {
|
|
||||||
const auto& k = m_stringtable.at(*tag_it++);
|
|
||||||
if (tag_it == tags.end()) {
|
|
||||||
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.end()) {
|
|
||||||
++tag_it;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
m_buffer.commit();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
PBFPrimitiveBlockDecoder(const data_view& data, osmium::osm_entity_bits::type read_types) :
|
PBFPrimitiveBlockDecoder(const data_view& data, osmium::osm_entity_bits::type read_types, osmium::io::read_meta read_metadata) :
|
||||||
m_data(data),
|
m_data(data),
|
||||||
m_read_types(read_types) {
|
m_read_types(read_types),
|
||||||
|
m_read_metadata(read_metadata) {
|
||||||
}
|
}
|
||||||
|
|
||||||
PBFPrimitiveBlockDecoder(const PBFPrimitiveBlockDecoder&) = delete;
|
PBFPrimitiveBlockDecoder(const PBFPrimitiveBlockDecoder&) = delete;
|
||||||
@ -789,12 +869,14 @@ namespace osmium {
|
|||||||
|
|
||||||
std::shared_ptr<std::string> m_input_buffer;
|
std::shared_ptr<std::string> m_input_buffer;
|
||||||
osmium::osm_entity_bits::type m_read_types;
|
osmium::osm_entity_bits::type m_read_types;
|
||||||
|
osmium::io::read_meta m_read_metadata;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
PBFDataBlobDecoder(std::string&& input_buffer, osmium::osm_entity_bits::type read_types) :
|
PBFDataBlobDecoder(std::string&& input_buffer, osmium::osm_entity_bits::type read_types, osmium::io::read_meta read_metadata) :
|
||||||
m_input_buffer(std::make_shared<std::string>(std::move(input_buffer))),
|
m_input_buffer(std::make_shared<std::string>(std::move(input_buffer))),
|
||||||
m_read_types(read_types) {
|
m_read_types(read_types),
|
||||||
|
m_read_metadata(read_metadata) {
|
||||||
}
|
}
|
||||||
|
|
||||||
PBFDataBlobDecoder(const PBFDataBlobDecoder&) = default;
|
PBFDataBlobDecoder(const PBFDataBlobDecoder&) = default;
|
||||||
@ -807,7 +889,7 @@ namespace osmium {
|
|||||||
|
|
||||||
osmium::memory::Buffer operator()() {
|
osmium::memory::Buffer operator()() {
|
||||||
std::string output;
|
std::string output;
|
||||||
PBFPrimitiveBlockDecoder decoder(decode_blob(*m_input_buffer, output), m_read_types);
|
PBFPrimitiveBlockDecoder decoder(decode_blob(*m_input_buffer, output), m_read_types, m_read_metadata);
|
||||||
return decoder();
|
return decoder();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -180,7 +180,7 @@ namespace osmium {
|
|||||||
while (const auto size = check_type_and_get_blob_size("OSMData")) {
|
while (const auto size = check_type_and_get_blob_size("OSMData")) {
|
||||||
std::string input_buffer = read_from_input_queue_with_check(size);
|
std::string input_buffer = read_from_input_queue_with_check(size);
|
||||||
|
|
||||||
PBFDataBlobDecoder data_blob_parser{ std::move(input_buffer), read_types() };
|
PBFDataBlobDecoder data_blob_parser{std::move(input_buffer), read_types(), read_metadata()};
|
||||||
|
|
||||||
if (osmium::config::use_pool_threads_for_pbf_parsing()) {
|
if (osmium::config::use_pool_threads_for_pbf_parsing()) {
|
||||||
send_to_output_queue(osmium::thread::Pool::instance().submit(std::move(data_blob_parser)));
|
send_to_output_queue(osmium::thread::Pool::instance().submit(std::move(data_blob_parser)));
|
||||||
@ -195,8 +195,8 @@ namespace osmium {
|
|||||||
PBFParser(future_string_queue_type& input_queue,
|
PBFParser(future_string_queue_type& input_queue,
|
||||||
future_buffer_queue_type& output_queue,
|
future_buffer_queue_type& output_queue,
|
||||||
std::promise<osmium::io::Header>& header_promise,
|
std::promise<osmium::io::Header>& header_promise,
|
||||||
osmium::osm_entity_bits::type read_types) :
|
osmium::io::detail::reader_options options) :
|
||||||
Parser(input_queue, output_queue, header_promise, read_types),
|
Parser(input_queue, output_queue, header_promise, options),
|
||||||
m_input_buffer() {
|
m_input_buffer() {
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -221,8 +221,8 @@ namespace osmium {
|
|||||||
[](future_string_queue_type& input_queue,
|
[](future_string_queue_type& input_queue,
|
||||||
future_buffer_queue_type& output_queue,
|
future_buffer_queue_type& output_queue,
|
||||||
std::promise<osmium::io::Header>& header_promise,
|
std::promise<osmium::io::Header>& header_promise,
|
||||||
osmium::osm_entity_bits::type read_which_entities) {
|
osmium::io::detail::reader_options options) {
|
||||||
return std::unique_ptr<Parser>(new PBFParser(input_queue, output_queue, header_promise, read_which_entities));
|
return std::unique_ptr<Parser>(new PBFParser(input_queue, output_queue, header_promise, options));
|
||||||
});
|
});
|
||||||
|
|
||||||
// dummy function to silence the unused variable warning from above
|
// dummy function to silence the unused variable warning from above
|
||||||
|
@ -33,10 +33,10 @@ DEALINGS IN THE SOFTWARE.
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <algorithm>
|
|
||||||
#include <exception>
|
#include <exception>
|
||||||
#include <future>
|
#include <future>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
#include <osmium/memory/buffer.hpp>
|
#include <osmium/memory/buffer.hpp>
|
||||||
#include <osmium/thread/queue.hpp>
|
#include <osmium/thread/queue.hpp>
|
||||||
@ -59,13 +59,6 @@ namespace osmium {
|
|||||||
*/
|
*/
|
||||||
using future_buffer_queue_type = future_queue_type<osmium::memory::Buffer>;
|
using future_buffer_queue_type = future_queue_type<osmium::memory::Buffer>;
|
||||||
|
|
||||||
/**
|
|
||||||
* This type of queue contains OSM file data in the form it is
|
|
||||||
* stored on disk, ie encoded as XML, PBF, etc.
|
|
||||||
* The "end of file" is marked by an empty string.
|
|
||||||
*/
|
|
||||||
using string_queue_type = osmium::thread::Queue<std::string>;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This type of queue contains OSM file data in the form it is
|
* This type of queue contains OSM file data in the form it is
|
||||||
* stored on disk, ie encoded as XML, PBF, etc.
|
* stored on disk, ie encoded as XML, PBF, etc.
|
||||||
@ -95,11 +88,11 @@ namespace osmium {
|
|||||||
add_to_queue<T>(queue, T{});
|
add_to_queue<T>(queue, T{});
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool at_end_of_data(const std::string& data) {
|
inline bool at_end_of_data(const std::string& data) noexcept {
|
||||||
return data.empty();
|
return data.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool at_end_of_data(osmium::memory::Buffer& buffer) {
|
inline bool at_end_of_data(osmium::memory::Buffer& buffer) noexcept {
|
||||||
return !buffer;
|
return !buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -80,8 +80,8 @@ namespace osmium {
|
|||||||
XML_Error error_code;
|
XML_Error error_code;
|
||||||
std::string error_string;
|
std::string error_string;
|
||||||
|
|
||||||
explicit xml_error(XML_Parser parser) :
|
explicit xml_error(const XML_Parser& parser) :
|
||||||
io_error(std::string("XML parsing error at line ")
|
io_error(std::string{"XML parsing error at line "}
|
||||||
+ std::to_string(XML_GetCurrentLineNumber(parser))
|
+ std::to_string(XML_GetCurrentLineNumber(parser))
|
||||||
+ ", column "
|
+ ", column "
|
||||||
+ std::to_string(XML_GetCurrentColumnNumber(parser))
|
+ std::to_string(XML_GetCurrentColumnNumber(parser))
|
||||||
@ -117,7 +117,7 @@ namespace osmium {
|
|||||||
}
|
}
|
||||||
|
|
||||||
explicit format_version_error(const char* v) :
|
explicit format_version_error(const char* v) :
|
||||||
io_error(std::string("Can not read file with version ") + v),
|
io_error(std::string{"Can not read file with version "} + v),
|
||||||
version(v) {
|
version(v) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -201,7 +201,7 @@ namespace osmium {
|
|||||||
static void entity_declaration_handler(void*,
|
static void entity_declaration_handler(void*,
|
||||||
const XML_Char*, int, const XML_Char*, int, const XML_Char*,
|
const XML_Char*, int, const XML_Char*, int, const XML_Char*,
|
||||||
const XML_Char*, const XML_Char*, const XML_Char*) {
|
const XML_Char*, const XML_Char*, const XML_Char*) {
|
||||||
throw osmium::xml_error("XML entities are not supported");
|
throw osmium::xml_error{"XML entities are not supported"};
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -209,7 +209,7 @@ namespace osmium {
|
|||||||
explicit ExpatXMLParser(T* callback_object) :
|
explicit ExpatXMLParser(T* callback_object) :
|
||||||
m_parser(XML_ParserCreate(nullptr)) {
|
m_parser(XML_ParserCreate(nullptr)) {
|
||||||
if (!m_parser) {
|
if (!m_parser) {
|
||||||
throw osmium::io_error("Internal error: Can not create parser");
|
throw osmium::io_error{"Internal error: Can not create parser"};
|
||||||
}
|
}
|
||||||
XML_SetUserData(m_parser, callback_object);
|
XML_SetUserData(m_parser, callback_object);
|
||||||
XML_SetElementHandler(m_parser, start_element_wrapper, end_element_wrapper);
|
XML_SetElementHandler(m_parser, start_element_wrapper, end_element_wrapper);
|
||||||
@ -229,7 +229,7 @@ namespace osmium {
|
|||||||
|
|
||||||
void operator()(const std::string& data, bool last) {
|
void operator()(const std::string& data, bool last) {
|
||||||
if (XML_Parse(m_parser, data.data(), static_cast_with_assert<int>(data.size()), last) == XML_STATUS_ERROR) {
|
if (XML_Parse(m_parser, data.data(), static_cast_with_assert<int>(data.size()), last) == XML_STATUS_ERROR) {
|
||||||
throw osmium::xml_error(m_parser);
|
throw osmium::xml_error{m_parser};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -271,37 +271,32 @@ namespace osmium {
|
|||||||
return user;
|
return user;
|
||||||
}
|
}
|
||||||
|
|
||||||
void init_changeset(osmium::builder::ChangesetBuilder* builder, const XML_Char** attrs) {
|
void init_changeset(osmium::builder::ChangesetBuilder& builder, const XML_Char** attrs) {
|
||||||
const char* user = "";
|
osmium::Box box;
|
||||||
osmium::Changeset& new_changeset = builder->object();
|
|
||||||
|
|
||||||
osmium::Location min;
|
check_attributes(attrs, [&builder, &box](const XML_Char* name, const XML_Char* value) {
|
||||||
osmium::Location max;
|
|
||||||
check_attributes(attrs, [&min, &max, &user, &new_changeset](const XML_Char* name, const XML_Char* value) {
|
|
||||||
if (!std::strcmp(name, "min_lon")) {
|
if (!std::strcmp(name, "min_lon")) {
|
||||||
min.set_lon(value);
|
box.bottom_left().set_lon(value);
|
||||||
} else if (!std::strcmp(name, "min_lat")) {
|
} else if (!std::strcmp(name, "min_lat")) {
|
||||||
min.set_lat(value);
|
box.bottom_left().set_lat(value);
|
||||||
} else if (!std::strcmp(name, "max_lon")) {
|
} else if (!std::strcmp(name, "max_lon")) {
|
||||||
max.set_lon(value);
|
box.top_right().set_lon(value);
|
||||||
} else if (!std::strcmp(name, "max_lat")) {
|
} else if (!std::strcmp(name, "max_lat")) {
|
||||||
max.set_lat(value);
|
box.top_right().set_lat(value);
|
||||||
} else if (!std::strcmp(name, "user")) {
|
} else if (!std::strcmp(name, "user")) {
|
||||||
user = value;
|
builder.set_user(value);
|
||||||
} else {
|
} else {
|
||||||
new_changeset.set_attribute(name, value);
|
builder.set_attribute(name, value);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
new_changeset.bounds().extend(min);
|
builder.set_bounds(box);
|
||||||
new_changeset.bounds().extend(max);
|
|
||||||
|
|
||||||
builder->add_user(user);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void get_tag(osmium::builder::Builder* builder, const XML_Char** attrs) {
|
void get_tag(osmium::builder::Builder& builder, const XML_Char** attrs) {
|
||||||
const char* k = "";
|
const char* k = "";
|
||||||
const char* v = "";
|
const char* v = "";
|
||||||
|
|
||||||
check_attributes(attrs, [&k, &v](const XML_Char* name, const XML_Char* value) {
|
check_attributes(attrs, [&k, &v](const XML_Char* name, const XML_Char* value) {
|
||||||
if (name[0] == 'k' && name[1] == 0) {
|
if (name[0] == 'k' && name[1] == 0) {
|
||||||
k = value;
|
k = value;
|
||||||
@ -309,8 +304,9 @@ namespace osmium {
|
|||||||
v = value;
|
v = value;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!m_tl_builder) {
|
if (!m_tl_builder) {
|
||||||
m_tl_builder = std::unique_ptr<osmium::builder::TagListBuilder>(new osmium::builder::TagListBuilder(m_buffer, builder));
|
m_tl_builder.reset(new osmium::builder::TagListBuilder{builder});
|
||||||
}
|
}
|
||||||
m_tl_builder->add_tag(k, v);
|
m_tl_builder->add_tag(k, v);
|
||||||
}
|
}
|
||||||
@ -330,17 +326,17 @@ namespace osmium {
|
|||||||
if (!std::strcmp(name, "version")) {
|
if (!std::strcmp(name, "version")) {
|
||||||
m_header.set("version", value);
|
m_header.set("version", value);
|
||||||
if (std::strcmp(value, "0.6")) {
|
if (std::strcmp(value, "0.6")) {
|
||||||
throw osmium::format_version_error(value);
|
throw osmium::format_version_error{value};
|
||||||
}
|
}
|
||||||
} else if (!std::strcmp(name, "generator")) {
|
} else if (!std::strcmp(name, "generator")) {
|
||||||
m_header.set("generator", value);
|
m_header.set("generator", value);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
if (m_header.get("version") == "") {
|
if (m_header.get("version") == "") {
|
||||||
throw osmium::format_version_error();
|
throw osmium::format_version_error{};
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
throw osmium::xml_error(std::string("Unknown top-level element: ") + element);
|
throw osmium::xml_error{std::string{"Unknown top-level element: "} + element};
|
||||||
}
|
}
|
||||||
m_context = context::top;
|
m_context = context::top;
|
||||||
break;
|
break;
|
||||||
@ -349,8 +345,8 @@ namespace osmium {
|
|||||||
if (!std::strcmp(element, "node")) {
|
if (!std::strcmp(element, "node")) {
|
||||||
mark_header_as_done();
|
mark_header_as_done();
|
||||||
if (read_types() & osmium::osm_entity_bits::node) {
|
if (read_types() & osmium::osm_entity_bits::node) {
|
||||||
m_node_builder = std::unique_ptr<osmium::builder::NodeBuilder>(new osmium::builder::NodeBuilder(m_buffer));
|
m_node_builder.reset(new osmium::builder::NodeBuilder{m_buffer});
|
||||||
m_node_builder->add_user(init_object(m_node_builder->object(), attrs));
|
m_node_builder->set_user(init_object(m_node_builder->object(), attrs));
|
||||||
m_context = context::node;
|
m_context = context::node;
|
||||||
} else {
|
} else {
|
||||||
m_context = context::ignored_node;
|
m_context = context::ignored_node;
|
||||||
@ -358,8 +354,8 @@ namespace osmium {
|
|||||||
} else if (!std::strcmp(element, "way")) {
|
} else if (!std::strcmp(element, "way")) {
|
||||||
mark_header_as_done();
|
mark_header_as_done();
|
||||||
if (read_types() & osmium::osm_entity_bits::way) {
|
if (read_types() & osmium::osm_entity_bits::way) {
|
||||||
m_way_builder = std::unique_ptr<osmium::builder::WayBuilder>(new osmium::builder::WayBuilder(m_buffer));
|
m_way_builder.reset(new osmium::builder::WayBuilder{m_buffer});
|
||||||
m_way_builder->add_user(init_object(m_way_builder->object(), attrs));
|
m_way_builder->set_user(init_object(m_way_builder->object(), attrs));
|
||||||
m_context = context::way;
|
m_context = context::way;
|
||||||
} else {
|
} else {
|
||||||
m_context = context::ignored_way;
|
m_context = context::ignored_way;
|
||||||
@ -367,8 +363,8 @@ namespace osmium {
|
|||||||
} else if (!std::strcmp(element, "relation")) {
|
} else if (!std::strcmp(element, "relation")) {
|
||||||
mark_header_as_done();
|
mark_header_as_done();
|
||||||
if (read_types() & osmium::osm_entity_bits::relation) {
|
if (read_types() & osmium::osm_entity_bits::relation) {
|
||||||
m_relation_builder = std::unique_ptr<osmium::builder::RelationBuilder>(new osmium::builder::RelationBuilder(m_buffer));
|
m_relation_builder.reset(new osmium::builder::RelationBuilder{m_buffer});
|
||||||
m_relation_builder->add_user(init_object(m_relation_builder->object(), attrs));
|
m_relation_builder->set_user(init_object(m_relation_builder->object(), attrs));
|
||||||
m_context = context::relation;
|
m_context = context::relation;
|
||||||
} else {
|
} else {
|
||||||
m_context = context::ignored_relation;
|
m_context = context::ignored_relation;
|
||||||
@ -376,8 +372,8 @@ namespace osmium {
|
|||||||
} else if (!std::strcmp(element, "changeset")) {
|
} else if (!std::strcmp(element, "changeset")) {
|
||||||
mark_header_as_done();
|
mark_header_as_done();
|
||||||
if (read_types() & osmium::osm_entity_bits::changeset) {
|
if (read_types() & osmium::osm_entity_bits::changeset) {
|
||||||
m_changeset_builder = std::unique_ptr<osmium::builder::ChangesetBuilder>(new osmium::builder::ChangesetBuilder(m_buffer));
|
m_changeset_builder.reset(new osmium::builder::ChangesetBuilder{m_buffer});
|
||||||
init_changeset(m_changeset_builder.get(), attrs);
|
init_changeset(*m_changeset_builder, attrs);
|
||||||
m_context = context::changeset;
|
m_context = context::changeset;
|
||||||
} else {
|
} else {
|
||||||
m_context = context::ignored_changeset;
|
m_context = context::ignored_changeset;
|
||||||
@ -407,7 +403,7 @@ namespace osmium {
|
|||||||
m_last_context = context::node;
|
m_last_context = context::node;
|
||||||
m_context = context::in_object;
|
m_context = context::in_object;
|
||||||
if (!std::strcmp(element, "tag")) {
|
if (!std::strcmp(element, "tag")) {
|
||||||
get_tag(m_node_builder.get(), attrs);
|
get_tag(*m_node_builder, attrs);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case context::way:
|
case context::way:
|
||||||
@ -417,7 +413,7 @@ namespace osmium {
|
|||||||
m_tl_builder.reset();
|
m_tl_builder.reset();
|
||||||
|
|
||||||
if (!m_wnl_builder) {
|
if (!m_wnl_builder) {
|
||||||
m_wnl_builder = std::unique_ptr<osmium::builder::WayNodeListBuilder>(new osmium::builder::WayNodeListBuilder(m_buffer, m_way_builder.get()));
|
m_wnl_builder.reset(new osmium::builder::WayNodeListBuilder{*m_way_builder});
|
||||||
}
|
}
|
||||||
|
|
||||||
NodeRef nr;
|
NodeRef nr;
|
||||||
@ -433,7 +429,7 @@ namespace osmium {
|
|||||||
m_wnl_builder->add_node_ref(nr);
|
m_wnl_builder->add_node_ref(nr);
|
||||||
} else if (!std::strcmp(element, "tag")) {
|
} else if (!std::strcmp(element, "tag")) {
|
||||||
m_wnl_builder.reset();
|
m_wnl_builder.reset();
|
||||||
get_tag(m_way_builder.get(), attrs);
|
get_tag(*m_way_builder, attrs);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case context::relation:
|
case context::relation:
|
||||||
@ -443,7 +439,7 @@ namespace osmium {
|
|||||||
m_tl_builder.reset();
|
m_tl_builder.reset();
|
||||||
|
|
||||||
if (!m_rml_builder) {
|
if (!m_rml_builder) {
|
||||||
m_rml_builder = std::unique_ptr<osmium::builder::RelationMemberListBuilder>(new osmium::builder::RelationMemberListBuilder(m_buffer, m_relation_builder.get()));
|
m_rml_builder.reset(new osmium::builder::RelationMemberListBuilder{*m_relation_builder});
|
||||||
}
|
}
|
||||||
|
|
||||||
item_type type = item_type::undefined;
|
item_type type = item_type::undefined;
|
||||||
@ -459,15 +455,15 @@ namespace osmium {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
if (type != item_type::node && type != item_type::way && type != item_type::relation) {
|
if (type != item_type::node && type != item_type::way && type != item_type::relation) {
|
||||||
throw osmium::xml_error("Unknown type on relation member");
|
throw osmium::xml_error{"Unknown type on relation member"};
|
||||||
}
|
}
|
||||||
if (ref == 0) {
|
if (ref == 0) {
|
||||||
throw osmium::xml_error("Missing ref on relation member");
|
throw osmium::xml_error{"Missing ref on relation member"};
|
||||||
}
|
}
|
||||||
m_rml_builder->add_member(type, ref, role);
|
m_rml_builder->add_member(type, ref, role);
|
||||||
} else if (!std::strcmp(element, "tag")) {
|
} else if (!std::strcmp(element, "tag")) {
|
||||||
m_rml_builder.reset();
|
m_rml_builder.reset();
|
||||||
get_tag(m_relation_builder.get(), attrs);
|
get_tag(*m_relation_builder, attrs);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case context::changeset:
|
case context::changeset:
|
||||||
@ -476,12 +472,12 @@ namespace osmium {
|
|||||||
m_context = context::discussion;
|
m_context = context::discussion;
|
||||||
m_tl_builder.reset();
|
m_tl_builder.reset();
|
||||||
if (!m_changeset_discussion_builder) {
|
if (!m_changeset_discussion_builder) {
|
||||||
m_changeset_discussion_builder = std::unique_ptr<osmium::builder::ChangesetDiscussionBuilder>(new osmium::builder::ChangesetDiscussionBuilder(m_buffer, m_changeset_builder.get()));
|
m_changeset_discussion_builder.reset(new osmium::builder::ChangesetDiscussionBuilder{*m_changeset_builder});
|
||||||
}
|
}
|
||||||
} else if (!std::strcmp(element, "tag")) {
|
} else if (!std::strcmp(element, "tag")) {
|
||||||
m_context = context::in_object;
|
m_context = context::in_object;
|
||||||
m_changeset_discussion_builder.reset();
|
m_changeset_discussion_builder.reset();
|
||||||
get_tag(m_changeset_builder.get(), attrs);
|
get_tag(*m_changeset_builder, attrs);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case context::discussion:
|
case context::discussion:
|
||||||
@ -632,8 +628,8 @@ namespace osmium {
|
|||||||
XMLParser(future_string_queue_type& input_queue,
|
XMLParser(future_string_queue_type& input_queue,
|
||||||
future_buffer_queue_type& output_queue,
|
future_buffer_queue_type& output_queue,
|
||||||
std::promise<osmium::io::Header>& header_promise,
|
std::promise<osmium::io::Header>& header_promise,
|
||||||
osmium::osm_entity_bits::type read_types) :
|
osmium::io::detail::reader_options options) :
|
||||||
Parser(input_queue, output_queue, header_promise, read_types),
|
Parser(input_queue, output_queue, header_promise, options),
|
||||||
m_context(context::root),
|
m_context(context::root),
|
||||||
m_last_context(context::root),
|
m_last_context(context::root),
|
||||||
m_in_delete_section(false),
|
m_in_delete_section(false),
|
||||||
@ -657,7 +653,7 @@ namespace osmium {
|
|||||||
ExpatXMLParser<XMLParser> parser(this);
|
ExpatXMLParser<XMLParser> parser(this);
|
||||||
|
|
||||||
while (!input_done()) {
|
while (!input_done()) {
|
||||||
std::string data = get_input();
|
const std::string data{get_input()};
|
||||||
parser(data, input_done());
|
parser(data, input_done());
|
||||||
if (read_types() == osmium::osm_entity_bits::nothing && header_is_done()) {
|
if (read_types() == osmium::osm_entity_bits::nothing && header_is_done()) {
|
||||||
break;
|
break;
|
||||||
@ -680,8 +676,8 @@ namespace osmium {
|
|||||||
[](future_string_queue_type& input_queue,
|
[](future_string_queue_type& input_queue,
|
||||||
future_buffer_queue_type& output_queue,
|
future_buffer_queue_type& output_queue,
|
||||||
std::promise<osmium::io::Header>& header_promise,
|
std::promise<osmium::io::Header>& header_promise,
|
||||||
osmium::osm_entity_bits::type read_which_entities) {
|
osmium::io::detail::reader_options options) {
|
||||||
return std::unique_ptr<Parser>(new XMLParser(input_queue, output_queue, header_promise, read_which_entities));
|
return std::unique_ptr<Parser>(new XMLParser{input_queue, output_queue, header_promise, options});
|
||||||
});
|
});
|
||||||
|
|
||||||
// dummy function to silence the unused variable warning from above
|
// dummy function to silence the unused variable warning from above
|
||||||
|
@ -49,6 +49,11 @@ namespace osmium {
|
|||||||
debug = 6
|
debug = 6
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum class read_meta {
|
||||||
|
no = 0,
|
||||||
|
yes = 1
|
||||||
|
};
|
||||||
|
|
||||||
// avoid g++ false positive
|
// avoid g++ false positive
|
||||||
#pragma GCC diagnostic push
|
#pragma GCC diagnostic push
|
||||||
#pragma GCC diagnostic ignored "-Wreturn-type"
|
#pragma GCC diagnostic ignored "-Wreturn-type"
|
||||||
|
@ -44,17 +44,37 @@ namespace osmium {
|
|||||||
namespace io {
|
namespace io {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Meta information from the header of an OSM file.
|
* Meta information from the header of an OSM file.
|
||||||
*/
|
*
|
||||||
|
* The header can contain any number of bounding boxes, although
|
||||||
|
* usually there is only a single one (or none). PBF files only
|
||||||
|
* allow a single bounding box, but XML files can have multiple ones,
|
||||||
|
* although it is unusual and the semantics are unclear, so it is
|
||||||
|
* discouraged to create files with multiple bounding boxes.
|
||||||
|
*
|
||||||
|
* The header contains a flag telling you whether this file can
|
||||||
|
* contain multiple versions of the same object. This is true for
|
||||||
|
* history files and for change files, but not for normal OSM data
|
||||||
|
* files. Not all OSM file formats can distinguish between those
|
||||||
|
* cases, so the flag might be wrong.
|
||||||
|
*
|
||||||
|
* In addition the header can contain any number of key-value pairs
|
||||||
|
* with additional information. Most often this is used to set the
|
||||||
|
* "generator", the program that generated the file. Depending on
|
||||||
|
* the file format some of these key-value pairs are handled
|
||||||
|
* specially. The the Options parent class for details on how to
|
||||||
|
* set and get those key-value pairs.
|
||||||
|
*/
|
||||||
class Header : public osmium::util::Options {
|
class Header : public osmium::util::Options {
|
||||||
|
|
||||||
/// Bounding boxes
|
/// Bounding boxes
|
||||||
std::vector<osmium::Box> m_boxes;
|
std::vector<osmium::Box> m_boxes;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Are there possibly multiple versions of the same object in this stream of objects?
|
* Are there possibly multiple versions of the same object in
|
||||||
* This is true for history files and for change files, but not for normal OSM files.
|
* this stream of objects? This should be true for history files
|
||||||
*/
|
* and for change files, but not for normal OSM data files.
|
||||||
|
*/
|
||||||
bool m_has_multiple_object_versions = false;
|
bool m_has_multiple_object_versions = false;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -65,49 +85,76 @@ namespace osmium {
|
|||||||
Options(values) {
|
Options(values) {
|
||||||
}
|
}
|
||||||
|
|
||||||
Header(const Header&) = default;
|
/**
|
||||||
Header& operator=(const Header&) = default;
|
* Get the bounding boxes defined in the header.
|
||||||
|
*/
|
||||||
Header(Header&&) = default;
|
|
||||||
Header& operator=(Header&&) = default;
|
|
||||||
|
|
||||||
~Header() = default;
|
|
||||||
|
|
||||||
std::vector<osmium::Box>& boxes() noexcept {
|
std::vector<osmium::Box>& boxes() noexcept {
|
||||||
return m_boxes;
|
return m_boxes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the bounding boxes defined in the header.
|
||||||
|
*/
|
||||||
const std::vector<osmium::Box>& boxes() const noexcept {
|
const std::vector<osmium::Box>& boxes() const noexcept {
|
||||||
return m_boxes;
|
return m_boxes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set all the bounding boxes in the header.
|
||||||
|
*/
|
||||||
Header& boxes(const std::vector<osmium::Box>& boxes) noexcept {
|
Header& boxes(const std::vector<osmium::Box>& boxes) noexcept {
|
||||||
m_boxes = boxes;
|
m_boxes = boxes;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the first (or only if there is only one) bounding box.
|
||||||
|
*
|
||||||
|
* Returns an empty, invalid box if there is none.
|
||||||
|
*/
|
||||||
osmium::Box box() const {
|
osmium::Box box() const {
|
||||||
return m_boxes.empty() ? osmium::Box() : m_boxes.front();
|
return m_boxes.empty() ? osmium::Box{} : m_boxes.front();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Join up all the bounding boxes in the header into one and return
|
||||||
|
* it. This method is what you probably want to use unless you want
|
||||||
|
* to handle the possibly multiple bounding boxes yourself.
|
||||||
|
*
|
||||||
|
* Returns an empty, invalid box if there is none.
|
||||||
|
*/
|
||||||
osmium::Box joined_boxes() const {
|
osmium::Box joined_boxes() const {
|
||||||
osmium::Box box;
|
osmium::Box box;
|
||||||
for (const auto& b : m_boxes) {
|
for (const auto& b : m_boxes) {
|
||||||
box.extend(b.bottom_left());
|
box.extend(b);
|
||||||
box.extend(b.top_right());
|
|
||||||
}
|
}
|
||||||
return box;
|
return box;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add the given bounding box to the list of bounding boxes in the
|
||||||
|
* header.
|
||||||
|
*
|
||||||
|
* @returns The header itself to allow chaining.
|
||||||
|
*/
|
||||||
Header& add_box(const osmium::Box& box) {
|
Header& add_box(const osmium::Box& box) {
|
||||||
m_boxes.push_back(box);
|
m_boxes.push_back(box);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Can this file contain multiple versions of the same object?
|
||||||
|
*/
|
||||||
bool has_multiple_object_versions() const noexcept {
|
bool has_multiple_object_versions() const noexcept {
|
||||||
return m_has_multiple_object_versions;
|
return m_has_multiple_object_versions;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the flag that tells us whether this file can contain
|
||||||
|
* multiple versions of the same object?
|
||||||
|
*
|
||||||
|
* @returns The header itself to allow chaining.
|
||||||
|
*/
|
||||||
Header& set_has_multiple_object_versions(bool value) noexcept {
|
Header& set_has_multiple_object_versions(bool value) noexcept {
|
||||||
m_has_multiple_object_versions = value;
|
m_has_multiple_object_versions = value;
|
||||||
return *this;
|
return *this;
|
||||||
|
@ -91,7 +91,6 @@ namespace osmium {
|
|||||||
class Reader {
|
class Reader {
|
||||||
|
|
||||||
osmium::io::File m_file;
|
osmium::io::File m_file;
|
||||||
osmium::osm_entity_bits::type m_read_which_entities;
|
|
||||||
|
|
||||||
enum class status {
|
enum class status {
|
||||||
okay = 0, // normal reading
|
okay = 0, // normal reading
|
||||||
@ -118,15 +117,25 @@ namespace osmium {
|
|||||||
|
|
||||||
size_t m_file_size;
|
size_t m_file_size;
|
||||||
|
|
||||||
|
osmium::io::detail::reader_options m_options;
|
||||||
|
|
||||||
|
void set_option(osmium::osm_entity_bits::type value) noexcept {
|
||||||
|
m_options.read_which_entities = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_option(osmium::io::read_meta value) noexcept {
|
||||||
|
m_options.read_metadata = value;
|
||||||
|
}
|
||||||
|
|
||||||
// This function will run in a separate thread.
|
// This function will run in a separate thread.
|
||||||
static void parser_thread(const osmium::io::File& file,
|
static void parser_thread(const osmium::io::File& file,
|
||||||
detail::future_string_queue_type& input_queue,
|
detail::future_string_queue_type& input_queue,
|
||||||
detail::future_buffer_queue_type& osmdata_queue,
|
detail::future_buffer_queue_type& osmdata_queue,
|
||||||
std::promise<osmium::io::Header>&& header_promise,
|
std::promise<osmium::io::Header>&& header_promise,
|
||||||
osmium::osm_entity_bits::type read_which_entities) {
|
osmium::io::detail::reader_options options) {
|
||||||
std::promise<osmium::io::Header> promise = std::move(header_promise);
|
std::promise<osmium::io::Header> promise = std::move(header_promise);
|
||||||
const auto creator = detail::ParserFactory::instance().get_creator_function(file);
|
const auto creator = detail::ParserFactory::instance().get_creator_function(file);
|
||||||
const auto parser = creator(input_queue, osmdata_queue, promise, read_which_entities);
|
const auto parser = creator(input_queue, osmdata_queue, promise, options);
|
||||||
parser->parse();
|
parser->parse();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -205,15 +214,28 @@ namespace osmium {
|
|||||||
/**
|
/**
|
||||||
* Create new Reader object.
|
* Create new Reader object.
|
||||||
*
|
*
|
||||||
* @param file The file we want to open.
|
* @param file The file (contains name and format info) to open.
|
||||||
* @param read_which_entities Which OSM entities (nodes, ways, relations, and/or changesets)
|
* @param args All further arguments are optional and can appear
|
||||||
* should be read from the input file. It can speed the read up
|
* in any order:
|
||||||
* significantly if objects that are not needed anyway are not
|
*
|
||||||
* parsed.
|
* * osmium::osm_entities::bits: Which OSM entities (nodes, ways,
|
||||||
|
* relations, and/or changesets) should be read from the
|
||||||
|
* input file. It can speed the read up significantly if
|
||||||
|
* objects that are not needed anyway are not parsed.
|
||||||
|
*
|
||||||
|
* * osmium::io::read_meta: Read meta data or not. The default is
|
||||||
|
* osmium::io::read_meta::yes which means that meta data
|
||||||
|
* is read normally. If you set this to
|
||||||
|
* osmium::io::read_meta::no, meta data (like version, uid,
|
||||||
|
* etc.) is not read possibly speeding up the read. Not all
|
||||||
|
* file formats use this setting.
|
||||||
|
*
|
||||||
|
* @throws osmium::io_error If there was an error.
|
||||||
|
* @throws std::system_error If the file could not be opened.
|
||||||
*/
|
*/
|
||||||
explicit Reader(const osmium::io::File& file, osmium::osm_entity_bits::type read_which_entities = osmium::osm_entity_bits::all) :
|
template <typename... TArgs>
|
||||||
|
explicit Reader(const osmium::io::File& file, TArgs&&... args) :
|
||||||
m_file(file.check()),
|
m_file(file.check()),
|
||||||
m_read_which_entities(read_which_entities),
|
|
||||||
m_status(status::okay),
|
m_status(status::okay),
|
||||||
m_childpid(0),
|
m_childpid(0),
|
||||||
m_input_queue(detail::get_input_queue_size(), "raw_input"),
|
m_input_queue(detail::get_input_queue_size(), "raw_input"),
|
||||||
@ -227,17 +249,24 @@ namespace osmium {
|
|||||||
m_header(),
|
m_header(),
|
||||||
m_thread(),
|
m_thread(),
|
||||||
m_file_size(m_decompressor->file_size()) {
|
m_file_size(m_decompressor->file_size()) {
|
||||||
|
|
||||||
|
(void)std::initializer_list<int>{
|
||||||
|
(set_option(args), 0)...
|
||||||
|
};
|
||||||
|
|
||||||
std::promise<osmium::io::Header> header_promise;
|
std::promise<osmium::io::Header> header_promise;
|
||||||
m_header_future = header_promise.get_future();
|
m_header_future = header_promise.get_future();
|
||||||
m_thread = osmium::thread::thread_handler{parser_thread, std::ref(m_file), std::ref(m_input_queue), std::ref(m_osmdata_queue), std::move(header_promise), read_which_entities};
|
m_thread = osmium::thread::thread_handler{parser_thread, std::ref(m_file), std::ref(m_input_queue), std::ref(m_osmdata_queue), std::move(header_promise), m_options};
|
||||||
}
|
}
|
||||||
|
|
||||||
explicit Reader(const std::string& filename, osmium::osm_entity_bits::type read_types = osmium::osm_entity_bits::all) :
|
template <typename... TArgs>
|
||||||
Reader(osmium::io::File(filename), read_types) {
|
explicit Reader(const std::string& filename, TArgs&&... args) :
|
||||||
|
Reader(osmium::io::File(filename), std::forward<TArgs>(args)...) {
|
||||||
}
|
}
|
||||||
|
|
||||||
explicit Reader(const char* filename, osmium::osm_entity_bits::type read_types = osmium::osm_entity_bits::all) :
|
template <typename... TArgs>
|
||||||
Reader(osmium::io::File(filename), read_types) {
|
explicit Reader(const char* filename, TArgs&&... args) :
|
||||||
|
Reader(osmium::io::File(filename), std::forward<TArgs>(args)...) {
|
||||||
}
|
}
|
||||||
|
|
||||||
Reader(const Reader&) = delete;
|
Reader(const Reader&) = delete;
|
||||||
@ -304,7 +333,7 @@ namespace osmium {
|
|||||||
try {
|
try {
|
||||||
if (m_header_future.valid()) {
|
if (m_header_future.valid()) {
|
||||||
m_header = m_header_future.get();
|
m_header = m_header_future.get();
|
||||||
if (m_read_which_entities == osmium::osm_entity_bits::nothing) {
|
if (m_options.read_which_entities == osmium::osm_entity_bits::nothing) {
|
||||||
m_status = status::eof;
|
m_status = status::eof;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -330,7 +359,7 @@ namespace osmium {
|
|||||||
osmium::memory::Buffer buffer;
|
osmium::memory::Buffer buffer;
|
||||||
|
|
||||||
if (m_status != status::okay ||
|
if (m_status != status::okay ||
|
||||||
m_read_which_entities == osmium::osm_entity_bits::nothing) {
|
m_options.read_which_entities == osmium::osm_entity_bits::nothing) {
|
||||||
throw io_error("Can not read from reader when in status 'closed', 'eof', or 'error'");
|
throw io_error("Can not read from reader when in status 'closed', 'eof', or 'error'");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -113,6 +113,9 @@ namespace osmium {
|
|||||||
size_t m_capacity;
|
size_t m_capacity;
|
||||||
size_t m_written;
|
size_t m_written;
|
||||||
size_t m_committed;
|
size_t m_committed;
|
||||||
|
#ifndef NDEBUG
|
||||||
|
uint8_t m_builder_count{0};
|
||||||
|
#endif
|
||||||
auto_grow m_auto_grow {auto_grow::no};
|
auto_grow m_auto_grow {auto_grow::no};
|
||||||
std::function<void(Buffer&)> m_full;
|
std::function<void(Buffer&)> m_full;
|
||||||
|
|
||||||
@ -216,13 +219,28 @@ namespace osmium {
|
|||||||
|
|
||||||
~Buffer() = default;
|
~Buffer() = default;
|
||||||
|
|
||||||
|
#ifndef NDEBUG
|
||||||
|
void increment_builder_count() noexcept {
|
||||||
|
++m_builder_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
void decrement_builder_count() noexcept {
|
||||||
|
assert(m_builder_count > 0);
|
||||||
|
--m_builder_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t builder_count() const noexcept {
|
||||||
|
return m_builder_count;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return a pointer to data inside the buffer.
|
* Return a pointer to data inside the buffer.
|
||||||
*
|
*
|
||||||
* @pre The buffer must be valid.
|
* @pre The buffer must be valid.
|
||||||
*/
|
*/
|
||||||
unsigned char* data() const noexcept {
|
unsigned char* data() const noexcept {
|
||||||
assert(m_data);
|
assert(m_data && "This must be a valid buffer");
|
||||||
return m_data;
|
return m_data;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -258,7 +276,7 @@ namespace osmium {
|
|||||||
* @pre The buffer must be valid.
|
* @pre The buffer must be valid.
|
||||||
*/
|
*/
|
||||||
bool is_aligned() const noexcept {
|
bool is_aligned() const noexcept {
|
||||||
assert(m_data);
|
assert(m_data && "This must be a valid buffer");
|
||||||
return (m_written % align_bytes == 0) && (m_committed % align_bytes == 0);
|
return (m_written % align_bytes == 0) && (m_committed % align_bytes == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -283,7 +301,7 @@ namespace osmium {
|
|||||||
* than the difference between committed() and capacity().
|
* than the difference between committed() and capacity().
|
||||||
*/
|
*/
|
||||||
OSMIUM_DEPRECATED void set_full_callback(std::function<void(Buffer&)> full) {
|
OSMIUM_DEPRECATED void set_full_callback(std::function<void(Buffer&)> full) {
|
||||||
assert(m_data);
|
assert(m_data && "This must be a valid buffer");
|
||||||
m_full = full;
|
m_full = full;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -292,7 +310,6 @@ namespace osmium {
|
|||||||
* This works only with internally memory-managed buffers.
|
* This works only with internally memory-managed buffers.
|
||||||
* If the given size is not larger than the current capacity,
|
* If the given size is not larger than the current capacity,
|
||||||
* nothing is done.
|
* nothing is done.
|
||||||
* Already written but not committed data is discarded.
|
|
||||||
*
|
*
|
||||||
* @pre The buffer must be valid.
|
* @pre The buffer must be valid.
|
||||||
*
|
*
|
||||||
@ -305,7 +322,7 @@ namespace osmium {
|
|||||||
* @throws std::bad_alloc if there isn't enough memory available.
|
* @throws std::bad_alloc if there isn't enough memory available.
|
||||||
*/
|
*/
|
||||||
void grow(size_t size) {
|
void grow(size_t size) {
|
||||||
assert(m_data);
|
assert(m_data && "This must be a valid buffer");
|
||||||
if (!m_memory) {
|
if (!m_memory) {
|
||||||
throw std::logic_error("Can't grow Buffer if it doesn't use internal memory management.");
|
throw std::logic_error("Can't grow Buffer if it doesn't use internal memory management.");
|
||||||
}
|
}
|
||||||
@ -325,15 +342,18 @@ namespace osmium {
|
|||||||
/**
|
/**
|
||||||
* Mark currently written bytes in the buffer as committed.
|
* Mark currently written bytes in the buffer as committed.
|
||||||
*
|
*
|
||||||
* @pre The buffer must be valid and aligned properly (as indicated
|
* @pre The buffer must be valid.
|
||||||
|
* @pre The buffer must be aligned properly (as indicated
|
||||||
* by is_aligned().
|
* by is_aligned().
|
||||||
|
* @pre No builder can be open on this buffer.
|
||||||
*
|
*
|
||||||
* @returns Number of committed bytes before this commit. Can be
|
* @returns Number of committed bytes before this commit. Can be
|
||||||
* used as an offset into the buffer to get to the
|
* used as an offset into the buffer to get to the
|
||||||
* object being committed by this call.
|
* object being committed by this call.
|
||||||
*/
|
*/
|
||||||
size_t commit() {
|
size_t commit() {
|
||||||
assert(m_data);
|
assert(m_data && "This must be a valid buffer");
|
||||||
|
assert(m_builder_count == 0 && "Make sure there are no Builder objects still in scope");
|
||||||
assert(is_aligned());
|
assert(is_aligned());
|
||||||
|
|
||||||
const size_t offset = m_committed;
|
const size_t offset = m_committed;
|
||||||
@ -345,9 +365,11 @@ namespace osmium {
|
|||||||
* Roll back changes in buffer to last committed state.
|
* Roll back changes in buffer to last committed state.
|
||||||
*
|
*
|
||||||
* @pre The buffer must be valid.
|
* @pre The buffer must be valid.
|
||||||
|
* @pre No builder can be open on this buffer.
|
||||||
*/
|
*/
|
||||||
void rollback() {
|
void rollback() {
|
||||||
assert(m_data);
|
assert(m_data && "This must be a valid buffer");
|
||||||
|
assert(m_builder_count == 0 && "Make sure there are no Builder objects still in scope");
|
||||||
m_written = m_committed;
|
m_written = m_committed;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -356,9 +378,12 @@ namespace osmium {
|
|||||||
*
|
*
|
||||||
* No-op on an invalid buffer.
|
* No-op on an invalid buffer.
|
||||||
*
|
*
|
||||||
|
* @pre No builder can be open on this buffer.
|
||||||
|
*
|
||||||
* @returns Number of bytes in the buffer before it was cleared.
|
* @returns Number of bytes in the buffer before it was cleared.
|
||||||
*/
|
*/
|
||||||
size_t clear() {
|
size_t clear() {
|
||||||
|
assert(m_builder_count == 0 && "Make sure there are no Builder objects still in scope");
|
||||||
const size_t committed = m_committed;
|
const size_t committed = m_committed;
|
||||||
m_written = 0;
|
m_written = 0;
|
||||||
m_committed = 0;
|
m_committed = 0;
|
||||||
@ -377,7 +402,7 @@ namespace osmium {
|
|||||||
*/
|
*/
|
||||||
template <typename T>
|
template <typename T>
|
||||||
T& get(const size_t offset) const {
|
T& get(const size_t offset) const {
|
||||||
assert(m_data);
|
assert(m_data && "This must be a valid buffer");
|
||||||
return *reinterpret_cast<T*>(&m_data[offset]);
|
return *reinterpret_cast<T*>(&m_data[offset]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -415,7 +440,7 @@ namespace osmium {
|
|||||||
* no callback defined and the buffer isn't auto-growing.
|
* no callback defined and the buffer isn't auto-growing.
|
||||||
*/
|
*/
|
||||||
unsigned char* reserve_space(const size_t size) {
|
unsigned char* reserve_space(const size_t size) {
|
||||||
assert(m_data);
|
assert(m_data && "This must be a valid buffer");
|
||||||
// try to flush the buffer empty first.
|
// try to flush the buffer empty first.
|
||||||
if (m_written + size > m_capacity && m_full) {
|
if (m_written + size > m_capacity && m_full) {
|
||||||
m_full(*this);
|
m_full(*this);
|
||||||
@ -455,7 +480,7 @@ namespace osmium {
|
|||||||
*/
|
*/
|
||||||
template <typename T>
|
template <typename T>
|
||||||
T& add_item(const T& item) {
|
T& add_item(const T& item) {
|
||||||
assert(m_data);
|
assert(m_data && "This must be a valid buffer");
|
||||||
unsigned char* target = reserve_space(item.padded_size());
|
unsigned char* target = reserve_space(item.padded_size());
|
||||||
std::copy_n(reinterpret_cast<const unsigned char*>(&item), item.padded_size(), target);
|
std::copy_n(reinterpret_cast<const unsigned char*>(&item), item.padded_size(), target);
|
||||||
return *reinterpret_cast<T*>(target);
|
return *reinterpret_cast<T*>(target);
|
||||||
@ -465,6 +490,7 @@ namespace osmium {
|
|||||||
* Add committed contents of the given buffer to this buffer.
|
* Add committed contents of the given buffer to this buffer.
|
||||||
*
|
*
|
||||||
* @pre The buffer must be valid.
|
* @pre The buffer must be valid.
|
||||||
|
* @pre No builder can be open on this buffer.
|
||||||
*
|
*
|
||||||
* Note that you have to eventually call commit() to actually
|
* Note that you have to eventually call commit() to actually
|
||||||
* commit this data.
|
* commit this data.
|
||||||
@ -472,7 +498,9 @@ namespace osmium {
|
|||||||
* @param buffer The source of the copy. Must be valid.
|
* @param buffer The source of the copy. Must be valid.
|
||||||
*/
|
*/
|
||||||
void add_buffer(const Buffer& buffer) {
|
void add_buffer(const Buffer& buffer) {
|
||||||
assert(m_data && buffer);
|
assert(m_data && "This must be a valid buffer");
|
||||||
|
assert(buffer && "Buffer parameter must be a valid buffer");
|
||||||
|
assert(m_builder_count == 0 && "Make sure there are no Builder objects still in scope");
|
||||||
unsigned char* target = reserve_space(buffer.committed());
|
unsigned char* target = reserve_space(buffer.committed());
|
||||||
std::copy_n(buffer.data(), buffer.committed(), target);
|
std::copy_n(buffer.data(), buffer.committed(), target);
|
||||||
}
|
}
|
||||||
@ -482,11 +510,13 @@ namespace osmium {
|
|||||||
* you can use std::back_inserter.
|
* you can use std::back_inserter.
|
||||||
*
|
*
|
||||||
* @pre The buffer must be valid.
|
* @pre The buffer must be valid.
|
||||||
|
* @pre No builder can be open on this buffer.
|
||||||
*
|
*
|
||||||
* @param item The item to be added.
|
* @param item The item to be added.
|
||||||
*/
|
*/
|
||||||
void push_back(const osmium::memory::Item& item) {
|
void push_back(const osmium::memory::Item& item) {
|
||||||
assert(m_data);
|
assert(m_data && "This must be a valid buffer");
|
||||||
|
assert(m_builder_count == 0 && "Make sure there are no Builder objects still in scope");
|
||||||
add_item(item);
|
add_item(item);
|
||||||
commit();
|
commit();
|
||||||
}
|
}
|
||||||
@ -537,7 +567,7 @@ namespace osmium {
|
|||||||
*/
|
*/
|
||||||
template <typename T>
|
template <typename T>
|
||||||
t_iterator<T> begin() {
|
t_iterator<T> begin() {
|
||||||
assert(m_data);
|
assert(m_data && "This must be a valid buffer");
|
||||||
return t_iterator<T>(m_data, m_data + m_committed);
|
return t_iterator<T>(m_data, m_data + m_committed);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -550,7 +580,7 @@ namespace osmium {
|
|||||||
* @returns Iterator to first OSMEntity in the buffer.
|
* @returns Iterator to first OSMEntity in the buffer.
|
||||||
*/
|
*/
|
||||||
iterator begin() {
|
iterator begin() {
|
||||||
assert(m_data);
|
assert(m_data && "This must be a valid buffer");
|
||||||
return iterator(m_data, m_data + m_committed);
|
return iterator(m_data, m_data + m_committed);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -565,7 +595,7 @@ namespace osmium {
|
|||||||
*/
|
*/
|
||||||
template <typename T>
|
template <typename T>
|
||||||
t_iterator<T> get_iterator(size_t offset) {
|
t_iterator<T> get_iterator(size_t offset) {
|
||||||
assert(m_data);
|
assert(m_data && "This must be a valid buffer");
|
||||||
return t_iterator<T>(m_data + offset, m_data + m_committed);
|
return t_iterator<T>(m_data + offset, m_data + m_committed);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -579,7 +609,7 @@ namespace osmium {
|
|||||||
* buffer.
|
* buffer.
|
||||||
*/
|
*/
|
||||||
iterator get_iterator(size_t offset) {
|
iterator get_iterator(size_t offset) {
|
||||||
assert(m_data);
|
assert(m_data && "This must be a valid buffer");
|
||||||
return iterator(m_data + offset, m_data + m_committed);
|
return iterator(m_data + offset, m_data + m_committed);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -593,7 +623,7 @@ namespace osmium {
|
|||||||
*/
|
*/
|
||||||
template <typename T>
|
template <typename T>
|
||||||
t_iterator<T> end() {
|
t_iterator<T> end() {
|
||||||
assert(m_data);
|
assert(m_data && "This must be a valid buffer");
|
||||||
return t_iterator<T>(m_data + m_committed, m_data + m_committed);
|
return t_iterator<T>(m_data + m_committed, m_data + m_committed);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -606,40 +636,40 @@ namespace osmium {
|
|||||||
* @returns End iterator.
|
* @returns End iterator.
|
||||||
*/
|
*/
|
||||||
iterator end() {
|
iterator end() {
|
||||||
assert(m_data);
|
assert(m_data && "This must be a valid buffer");
|
||||||
return iterator(m_data + m_committed, m_data + m_committed);
|
return iterator(m_data + m_committed, m_data + m_committed);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
t_const_iterator<T> cbegin() const {
|
t_const_iterator<T> cbegin() const {
|
||||||
assert(m_data);
|
assert(m_data && "This must be a valid buffer");
|
||||||
return t_const_iterator<T>(m_data, m_data + m_committed);
|
return t_const_iterator<T>(m_data, m_data + m_committed);
|
||||||
}
|
}
|
||||||
|
|
||||||
const_iterator cbegin() const {
|
const_iterator cbegin() const {
|
||||||
assert(m_data);
|
assert(m_data && "This must be a valid buffer");
|
||||||
return const_iterator(m_data, m_data + m_committed);
|
return const_iterator(m_data, m_data + m_committed);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
t_const_iterator<T> get_iterator(size_t offset) const {
|
t_const_iterator<T> get_iterator(size_t offset) const {
|
||||||
assert(m_data);
|
assert(m_data && "This must be a valid buffer");
|
||||||
return t_const_iterator<T>(m_data + offset, m_data + m_committed);
|
return t_const_iterator<T>(m_data + offset, m_data + m_committed);
|
||||||
}
|
}
|
||||||
|
|
||||||
const_iterator get_iterator(size_t offset) const {
|
const_iterator get_iterator(size_t offset) const {
|
||||||
assert(m_data);
|
assert(m_data && "This must be a valid buffer");
|
||||||
return const_iterator(m_data + offset, m_data + m_committed);
|
return const_iterator(m_data + offset, m_data + m_committed);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
t_const_iterator<T> cend() const {
|
t_const_iterator<T> cend() const {
|
||||||
assert(m_data);
|
assert(m_data && "This must be a valid buffer");
|
||||||
return t_const_iterator<T>(m_data + m_committed, m_data + m_committed);
|
return t_const_iterator<T>(m_data + m_committed, m_data + m_committed);
|
||||||
}
|
}
|
||||||
|
|
||||||
const_iterator cend() const {
|
const_iterator cend() const {
|
||||||
assert(m_data);
|
assert(m_data && "This must be a valid buffer");
|
||||||
return const_iterator(m_data + m_committed, m_data + m_committed);
|
return const_iterator(m_data + m_committed, m_data + m_committed);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -698,7 +728,7 @@ namespace osmium {
|
|||||||
*/
|
*/
|
||||||
template <typename TCallbackClass>
|
template <typename TCallbackClass>
|
||||||
void purge_removed(TCallbackClass* callback) {
|
void purge_removed(TCallbackClass* callback) {
|
||||||
assert(m_data);
|
assert(m_data && "This must be a valid buffer");
|
||||||
if (begin() == end()) {
|
if (begin() == end()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -46,9 +46,9 @@ namespace osmium {
|
|||||||
template <typename TMember>
|
template <typename TMember>
|
||||||
class CollectionIterator {
|
class CollectionIterator {
|
||||||
|
|
||||||
// This data_type is either 'unsigned char*' or 'const unsigned char*' depending
|
// This data_type is either 'unsigned char*' or 'const unsigned
|
||||||
// on whether TMember is const. This allows this class to be used as an iterator and
|
// char*' depending on whether TMember is const. This allows this
|
||||||
// as a const_iterator.
|
// class to be used as an iterator and as a const_iterator.
|
||||||
using data_type = typename std::conditional<std::is_const<TMember>::value, const unsigned char*, unsigned char*>::type;
|
using data_type = typename std::conditional<std::is_const<TMember>::value, const unsigned char*, unsigned char*>::type;
|
||||||
|
|
||||||
data_type m_data;
|
data_type m_data;
|
||||||
@ -92,11 +92,11 @@ namespace osmium {
|
|||||||
return m_data;
|
return m_data;
|
||||||
}
|
}
|
||||||
|
|
||||||
TMember& operator*() const {
|
TMember& operator*() const noexcept {
|
||||||
return *reinterpret_cast<TMember*>(m_data);
|
return *reinterpret_cast<TMember*>(m_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
TMember* operator->() const {
|
TMember* operator->() const noexcept {
|
||||||
return reinterpret_cast<TMember*>(m_data);
|
return reinterpret_cast<TMember*>(m_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -118,9 +118,12 @@ namespace osmium {
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
using iterator = CollectionIterator<TMember>;
|
using value_type = TMember;
|
||||||
using const_iterator = CollectionIterator<const TMember>;
|
using reference = TMember&;
|
||||||
using value_type = TMember;
|
using const_reference = const TMember&;
|
||||||
|
using iterator = CollectionIterator<TMember>;
|
||||||
|
using const_iterator = CollectionIterator<const TMember>;
|
||||||
|
using size_type = size_t;
|
||||||
|
|
||||||
static constexpr osmium::item_type itemtype = TCollectionItemType;
|
static constexpr osmium::item_type itemtype = TCollectionItemType;
|
||||||
|
|
||||||
@ -128,31 +131,45 @@ namespace osmium {
|
|||||||
Item(sizeof(Collection<TMember, TCollectionItemType>), TCollectionItemType) {
|
Item(sizeof(Collection<TMember, TCollectionItemType>), TCollectionItemType) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool empty() const {
|
/**
|
||||||
|
* Does this collection contain any items?
|
||||||
|
*
|
||||||
|
* Complexity: Constant.
|
||||||
|
*/
|
||||||
|
bool empty() const noexcept {
|
||||||
return sizeof(Collection<TMember, TCollectionItemType>) == byte_size();
|
return sizeof(Collection<TMember, TCollectionItemType>) == byte_size();
|
||||||
}
|
}
|
||||||
|
|
||||||
iterator begin() {
|
/**
|
||||||
|
* Returns the number of items in this collection.
|
||||||
|
*
|
||||||
|
* Complexity: Linear in the number of items.
|
||||||
|
*/
|
||||||
|
size_type size() const noexcept {
|
||||||
|
return static_cast<size_type>(std::distance(begin(), end()));
|
||||||
|
}
|
||||||
|
|
||||||
|
iterator begin() noexcept {
|
||||||
return iterator(data() + sizeof(Collection<TMember, TCollectionItemType>));
|
return iterator(data() + sizeof(Collection<TMember, TCollectionItemType>));
|
||||||
}
|
}
|
||||||
|
|
||||||
iterator end() {
|
iterator end() noexcept {
|
||||||
return iterator(data() + byte_size());
|
return iterator(data() + byte_size());
|
||||||
}
|
}
|
||||||
|
|
||||||
const_iterator cbegin() const {
|
const_iterator cbegin() const noexcept {
|
||||||
return const_iterator(data() + sizeof(Collection<TMember, TCollectionItemType>));
|
return const_iterator(data() + sizeof(Collection<TMember, TCollectionItemType>));
|
||||||
}
|
}
|
||||||
|
|
||||||
const_iterator cend() const {
|
const_iterator cend() const noexcept {
|
||||||
return const_iterator(data() + byte_size());
|
return const_iterator(data() + byte_size());
|
||||||
}
|
}
|
||||||
|
|
||||||
const_iterator begin() const {
|
const_iterator begin() const noexcept {
|
||||||
return cbegin();
|
return cbegin();
|
||||||
}
|
}
|
||||||
|
|
||||||
const_iterator end() const {
|
const_iterator end() const noexcept {
|
||||||
return cend();
|
return cend();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -59,9 +59,9 @@ namespace osmium {
|
|||||||
using item_size_type = uint32_t;
|
using item_size_type = uint32_t;
|
||||||
|
|
||||||
// align datastructures to this many bytes
|
// align datastructures to this many bytes
|
||||||
constexpr item_size_type align_bytes = 8;
|
constexpr const item_size_type align_bytes = 8;
|
||||||
|
|
||||||
inline std::size_t padded_length(std::size_t length) noexcept {
|
inline constexpr std::size_t padded_length(std::size_t length) noexcept {
|
||||||
return (length + align_bytes - 1) & ~(align_bytes - 1);
|
return (length + align_bytes - 1) & ~(align_bytes - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -50,7 +50,8 @@ DEALINGS IN THE SOFTWARE.
|
|||||||
namespace osmium {
|
namespace osmium {
|
||||||
|
|
||||||
namespace builder {
|
namespace builder {
|
||||||
template <class T> class ObjectBuilder;
|
template <typename TDerived, typename T>
|
||||||
|
class OSMObjectBuilder;
|
||||||
} // namespace builder
|
} // namespace builder
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -117,7 +118,8 @@ namespace osmium {
|
|||||||
*/
|
*/
|
||||||
class Area : public OSMObject {
|
class Area : public OSMObject {
|
||||||
|
|
||||||
friend class osmium::builder::ObjectBuilder<osmium::Area>;
|
template <typename TDerived, typename T>
|
||||||
|
friend class osmium::builder::OSMObjectBuilder;
|
||||||
|
|
||||||
Area() :
|
Area() :
|
||||||
OSMObject(sizeof(Area), osmium::item_type::area) {
|
OSMObject(sizeof(Area), osmium::item_type::area) {
|
||||||
@ -130,6 +132,8 @@ namespace osmium {
|
|||||||
/**
|
/**
|
||||||
* Was this area created from a way? (In contrast to areas
|
* Was this area created from a way? (In contrast to areas
|
||||||
* created from a relation and their members.)
|
* created from a relation and their members.)
|
||||||
|
*
|
||||||
|
* Complexity: Constant.
|
||||||
*/
|
*/
|
||||||
bool from_way() const noexcept {
|
bool from_way() const noexcept {
|
||||||
return (positive_id() & 0x1) == 0;
|
return (positive_id() & 0x1) == 0;
|
||||||
@ -137,6 +141,8 @@ namespace osmium {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the Id of the way or relation this area was created from.
|
* Return the Id of the way or relation this area was created from.
|
||||||
|
*
|
||||||
|
* Complexity: Constant.
|
||||||
*/
|
*/
|
||||||
osmium::object_id_type orig_id() const noexcept {
|
osmium::object_id_type orig_id() const noexcept {
|
||||||
return osmium::area_id_to_object_id(id());
|
return osmium::area_id_to_object_id(id());
|
||||||
@ -145,6 +151,8 @@ namespace osmium {
|
|||||||
/**
|
/**
|
||||||
* Count the number of outer and inner rings of this area.
|
* Count the number of outer and inner rings of this area.
|
||||||
*
|
*
|
||||||
|
* Complexity: Linear in the number of rings.
|
||||||
|
*
|
||||||
* @returns Pair (number outer rings, number inner rings)
|
* @returns Pair (number outer rings, number inner rings)
|
||||||
*/
|
*/
|
||||||
std::pair<size_t, size_t> num_rings() const {
|
std::pair<size_t, size_t> num_rings() const {
|
||||||
|
@ -51,7 +51,7 @@ namespace osmium {
|
|||||||
|
|
||||||
namespace builder {
|
namespace builder {
|
||||||
class ChangesetDiscussionBuilder;
|
class ChangesetDiscussionBuilder;
|
||||||
template <typename T> class ObjectBuilder;
|
class ChangesetBuilder;
|
||||||
} // namespace builder
|
} // namespace builder
|
||||||
|
|
||||||
class Changeset;
|
class Changeset;
|
||||||
@ -129,20 +129,12 @@ namespace osmium {
|
|||||||
|
|
||||||
class ChangesetDiscussion : public osmium::memory::Collection<ChangesetComment, osmium::item_type::changeset_discussion> {
|
class ChangesetDiscussion : public osmium::memory::Collection<ChangesetComment, osmium::item_type::changeset_discussion> {
|
||||||
|
|
||||||
friend class osmium::builder::ObjectBuilder<osmium::Changeset>;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
using size_type = size_t;
|
|
||||||
|
|
||||||
ChangesetDiscussion() :
|
ChangesetDiscussion() :
|
||||||
osmium::memory::Collection<ChangesetComment, osmium::item_type::changeset_discussion>() {
|
osmium::memory::Collection<ChangesetComment, osmium::item_type::changeset_discussion>() {
|
||||||
}
|
}
|
||||||
|
|
||||||
size_type size() const noexcept {
|
|
||||||
return static_cast<size_type>(std::distance(begin(), end()));
|
|
||||||
}
|
|
||||||
|
|
||||||
}; // class ChangesetDiscussion
|
}; // class ChangesetDiscussion
|
||||||
|
|
||||||
static_assert(sizeof(ChangesetDiscussion) % osmium::memory::align_bytes == 0, "Class osmium::ChangesetDiscussion has wrong size to be aligned properly!");
|
static_assert(sizeof(ChangesetDiscussion) % osmium::memory::align_bytes == 0, "Class osmium::ChangesetDiscussion has wrong size to be aligned properly!");
|
||||||
@ -156,7 +148,7 @@ namespace osmium {
|
|||||||
*/
|
*/
|
||||||
class Changeset : public osmium::OSMEntity {
|
class Changeset : public osmium::OSMEntity {
|
||||||
|
|
||||||
friend class osmium::builder::ObjectBuilder<osmium::Changeset>;
|
friend class osmium::builder::ChangesetBuilder;
|
||||||
|
|
||||||
osmium::Box m_bounds;
|
osmium::Box m_bounds;
|
||||||
osmium::Timestamp m_created_at;
|
osmium::Timestamp m_created_at;
|
||||||
@ -173,10 +165,14 @@ namespace osmium {
|
|||||||
OSMEntity(sizeof(Changeset), osmium::item_type::changeset) {
|
OSMEntity(sizeof(Changeset), osmium::item_type::changeset) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_user_size(string_size_type size) {
|
void set_user_size(string_size_type size) noexcept {
|
||||||
m_user_size = size;
|
m_user_size = size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
string_size_type user_size() const noexcept {
|
||||||
|
return m_user_size;
|
||||||
|
}
|
||||||
|
|
||||||
unsigned char* subitems_position() {
|
unsigned char* subitems_position() {
|
||||||
return data() + osmium::memory::padded_length(sizeof(Changeset) + m_user_size);
|
return data() + osmium::memory::padded_length(sizeof(Changeset) + m_user_size);
|
||||||
}
|
}
|
||||||
|
42
third_party/libosmium/include/osmium/osm/crc.hpp
vendored
42
third_party/libosmium/include/osmium/osm/crc.hpp
vendored
@ -100,15 +100,15 @@ namespace osmium {
|
|||||||
return m_crc;
|
return m_crc;
|
||||||
}
|
}
|
||||||
|
|
||||||
void update_bool(const bool value) {
|
void update_bool(const bool value) noexcept {
|
||||||
m_crc.process_byte(value);
|
m_crc.process_byte(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void update_int8(const uint8_t value) {
|
void update_int8(const uint8_t value) noexcept {
|
||||||
m_crc.process_byte(value);
|
m_crc.process_byte(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void update_int16(const uint16_t value) {
|
void update_int16(const uint16_t value) noexcept {
|
||||||
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
||||||
m_crc.process_bytes(&value, sizeof(uint16_t));
|
m_crc.process_bytes(&value, sizeof(uint16_t));
|
||||||
#else
|
#else
|
||||||
@ -117,7 +117,7 @@ namespace osmium {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void update_int32(const uint32_t value) {
|
void update_int32(const uint32_t value) noexcept {
|
||||||
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
||||||
m_crc.process_bytes(&value, sizeof(uint32_t));
|
m_crc.process_bytes(&value, sizeof(uint32_t));
|
||||||
#else
|
#else
|
||||||
@ -126,7 +126,7 @@ namespace osmium {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void update_int64(const uint64_t value) {
|
void update_int64(const uint64_t value) noexcept {
|
||||||
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
||||||
m_crc.process_bytes(&value, sizeof(uint64_t));
|
m_crc.process_bytes(&value, sizeof(uint64_t));
|
||||||
#else
|
#else
|
||||||
@ -135,57 +135,57 @@ namespace osmium {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void update_string(const char* str) {
|
void update_string(const char* str) noexcept {
|
||||||
while (*str) {
|
while (*str) {
|
||||||
m_crc.process_byte(*str++);
|
m_crc.process_byte(*str++);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void update(const Timestamp& timestamp) {
|
void update(const Timestamp& timestamp) noexcept {
|
||||||
update_int32(uint32_t(timestamp));
|
update_int32(uint32_t(timestamp));
|
||||||
}
|
}
|
||||||
|
|
||||||
void update(const osmium::Location& location) {
|
void update(const osmium::Location& location) noexcept {
|
||||||
update_int32(location.x());
|
update_int32(location.x());
|
||||||
update_int32(location.y());
|
update_int32(location.y());
|
||||||
}
|
}
|
||||||
|
|
||||||
void update(const osmium::Box& box) {
|
void update(const osmium::Box& box) noexcept {
|
||||||
update(box.bottom_left());
|
update(box.bottom_left());
|
||||||
update(box.top_right());
|
update(box.top_right());
|
||||||
}
|
}
|
||||||
|
|
||||||
void update(const NodeRef& node_ref) {
|
void update(const NodeRef& node_ref) noexcept {
|
||||||
update_int64(node_ref.ref());
|
update_int64(node_ref.ref());
|
||||||
update(node_ref.location());
|
update(node_ref.location());
|
||||||
}
|
}
|
||||||
|
|
||||||
void update(const NodeRefList& node_refs) {
|
void update(const NodeRefList& node_refs) noexcept {
|
||||||
for (const NodeRef& node_ref : node_refs) {
|
for (const NodeRef& node_ref : node_refs) {
|
||||||
update(node_ref);
|
update(node_ref);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void update(const TagList& tags) {
|
void update(const TagList& tags) noexcept {
|
||||||
for (const Tag& tag : tags) {
|
for (const Tag& tag : tags) {
|
||||||
update_string(tag.key());
|
update_string(tag.key());
|
||||||
update_string(tag.value());
|
update_string(tag.value());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void update(const osmium::RelationMember& member) {
|
void update(const osmium::RelationMember& member) noexcept {
|
||||||
update_int64(member.ref());
|
update_int64(member.ref());
|
||||||
update_int16(uint16_t(member.type()));
|
update_int16(uint16_t(member.type()));
|
||||||
update_string(member.role());
|
update_string(member.role());
|
||||||
}
|
}
|
||||||
|
|
||||||
void update(const osmium::RelationMemberList& members) {
|
void update(const osmium::RelationMemberList& members) noexcept {
|
||||||
for (const RelationMember& member : members) {
|
for (const RelationMember& member : members) {
|
||||||
update(member);
|
update(member);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void update(const osmium::OSMObject& object) {
|
void update(const osmium::OSMObject& object) noexcept {
|
||||||
update_int64(object.id());
|
update_int64(object.id());
|
||||||
update_bool(object.visible());
|
update_bool(object.visible());
|
||||||
update_int32(object.version());
|
update_int32(object.version());
|
||||||
@ -195,22 +195,22 @@ namespace osmium {
|
|||||||
update(object.tags());
|
update(object.tags());
|
||||||
}
|
}
|
||||||
|
|
||||||
void update(const osmium::Node& node) {
|
void update(const osmium::Node& node) noexcept {
|
||||||
update(static_cast<const osmium::OSMObject&>(node));
|
update(static_cast<const osmium::OSMObject&>(node));
|
||||||
update(node.location());
|
update(node.location());
|
||||||
}
|
}
|
||||||
|
|
||||||
void update(const osmium::Way& way) {
|
void update(const osmium::Way& way) noexcept {
|
||||||
update(static_cast<const osmium::OSMObject&>(way));
|
update(static_cast<const osmium::OSMObject&>(way));
|
||||||
update(way.nodes());
|
update(way.nodes());
|
||||||
}
|
}
|
||||||
|
|
||||||
void update(const osmium::Relation& relation) {
|
void update(const osmium::Relation& relation) noexcept {
|
||||||
update(static_cast<const osmium::OSMObject&>(relation));
|
update(static_cast<const osmium::OSMObject&>(relation));
|
||||||
update(relation.members());
|
update(relation.members());
|
||||||
}
|
}
|
||||||
|
|
||||||
void update(const osmium::Area& area) {
|
void update(const osmium::Area& area) noexcept {
|
||||||
update(static_cast<const osmium::OSMObject&>(area));
|
update(static_cast<const osmium::OSMObject&>(area));
|
||||||
for (const auto& subitem : area) {
|
for (const auto& subitem : area) {
|
||||||
if (subitem.type() == osmium::item_type::outer_ring ||
|
if (subitem.type() == osmium::item_type::outer_ring ||
|
||||||
@ -220,7 +220,7 @@ namespace osmium {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void update(const osmium::ChangesetDiscussion& discussion) {
|
void update(const osmium::ChangesetDiscussion& discussion) noexcept {
|
||||||
for (const auto& comment : discussion) {
|
for (const auto& comment : discussion) {
|
||||||
update(comment.date());
|
update(comment.date());
|
||||||
update_int32(comment.uid());
|
update_int32(comment.uid());
|
||||||
@ -229,7 +229,7 @@ namespace osmium {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void update(const osmium::Changeset& changeset) {
|
void update(const osmium::Changeset& changeset) noexcept {
|
||||||
update_int64(changeset.id());
|
update_int64(changeset.id());
|
||||||
update(changeset.created_at());
|
update(changeset.created_at());
|
||||||
update(changeset.closed_at());
|
update(changeset.closed_at());
|
||||||
|
@ -60,7 +60,9 @@ namespace osmium {
|
|||||||
* assert(! (entities & osmium::osm_entity_bits::changeset));
|
* assert(! (entities & osmium::osm_entity_bits::changeset));
|
||||||
* @endcode
|
* @endcode
|
||||||
*/
|
*/
|
||||||
enum type : unsigned char {
|
enum type : unsigned char { // this should have been an enum class
|
||||||
|
// but now we can't change it any more
|
||||||
|
// without breaking lots of code
|
||||||
|
|
||||||
nothing = 0x00,
|
nothing = 0x00,
|
||||||
node = 0x01,
|
node = 0x01,
|
||||||
@ -75,8 +77,16 @@ namespace osmium {
|
|||||||
|
|
||||||
}; // enum type
|
}; // enum type
|
||||||
|
|
||||||
inline type operator|(const type lhs, const type rhs) noexcept {
|
inline constexpr type operator|(const type lhs, const type rhs) noexcept {
|
||||||
return static_cast<type>(static_cast<int>(lhs) | static_cast<int> (rhs));
|
return static_cast<type>(static_cast<int>(lhs) | static_cast<int>(rhs));
|
||||||
|
}
|
||||||
|
|
||||||
|
inline constexpr type operator&(const type lhs, const type rhs) noexcept {
|
||||||
|
return static_cast<type>(static_cast<int>(lhs) & static_cast<int>(rhs));
|
||||||
|
}
|
||||||
|
|
||||||
|
inline constexpr type operator~(const type value) noexcept {
|
||||||
|
return all & static_cast<type>(~static_cast<int>(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
inline type& operator|=(type& lhs, const type rhs) noexcept {
|
inline type& operator|=(type& lhs, const type rhs) noexcept {
|
||||||
@ -84,14 +94,6 @@ namespace osmium {
|
|||||||
return lhs;
|
return lhs;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline type operator&(const type lhs, const type rhs) noexcept {
|
|
||||||
return static_cast<type>(static_cast<int>(lhs) & static_cast<int> (rhs));
|
|
||||||
}
|
|
||||||
|
|
||||||
inline type operator~(const type value) noexcept {
|
|
||||||
return static_cast<type>(~static_cast<int>(value));
|
|
||||||
}
|
|
||||||
|
|
||||||
inline type operator&=(type& lhs, const type rhs) noexcept {
|
inline type operator&=(type& lhs, const type rhs) noexcept {
|
||||||
lhs = lhs & rhs;
|
lhs = lhs & rhs;
|
||||||
return lhs;
|
return lhs;
|
||||||
@ -104,7 +106,7 @@ namespace osmium {
|
|||||||
* changeset.
|
* changeset.
|
||||||
*/
|
*/
|
||||||
inline type from_item_type(osmium::item_type item_type) noexcept {
|
inline type from_item_type(osmium::item_type item_type) noexcept {
|
||||||
auto ut = static_cast<std::underlying_type<osmium::item_type>::type>(item_type);
|
const auto ut = static_cast<std::underlying_type<osmium::item_type>::type>(item_type);
|
||||||
assert(ut <= 0x05);
|
assert(ut <= 0x05);
|
||||||
if (ut == 0) {
|
if (ut == 0) {
|
||||||
return nothing;
|
return nothing;
|
||||||
|
@ -86,23 +86,31 @@ namespace osmium {
|
|||||||
++str;
|
++str;
|
||||||
}
|
}
|
||||||
|
|
||||||
// there has to be at least one digit
|
if (*str != '.') {
|
||||||
if (*str >= '0' && *str <= '9') {
|
// there has to be at least one digit
|
||||||
result = *str - '0';
|
if (*str >= '0' && *str <= '9') {
|
||||||
++str;
|
result = *str - '0';
|
||||||
|
++str;
|
||||||
|
} else {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
// optional additional digits before decimal point
|
||||||
|
while (*str >= '0' && *str <= '9' && max_digits > 0) {
|
||||||
|
result = result * 10 + (*str - '0');
|
||||||
|
++str;
|
||||||
|
--max_digits;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (max_digits == 0) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
goto error;
|
// need at least one digit after decimal dot if there was no
|
||||||
}
|
// digit before decimal dot
|
||||||
|
if (*(str + 1) < '0' || *(str + 1) > '9') {
|
||||||
// optional additional digits before decimal point
|
goto error;
|
||||||
while (*str >= '0' && *str <= '9' && max_digits > 0) {
|
}
|
||||||
result = result * 10 + (*str - '0');
|
|
||||||
++str;
|
|
||||||
--max_digits;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (max_digits == 0) {
|
|
||||||
goto error;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// optional decimal point
|
// optional decimal point
|
||||||
@ -163,18 +171,20 @@ namespace osmium {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (scale < 0) {
|
if (scale < 0) {
|
||||||
result = 0;
|
for (; scale < 0 && result > 0; ++scale) {
|
||||||
|
result /= 10;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
for (; scale > 0; --scale) {
|
for (; scale > 0; --scale) {
|
||||||
result *= 10;
|
result *= 10;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
result = (result + 5) / 10 * sign;
|
result = (result + 5) / 10 * sign;
|
||||||
|
|
||||||
if (result > std::numeric_limits<int32_t>::max() ||
|
if (result > std::numeric_limits<int32_t>::max() ||
|
||||||
result < std::numeric_limits<int32_t>::min()) {
|
result < std::numeric_limits<int32_t>::min()) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
*data = str;
|
*data = str;
|
||||||
|
@ -41,12 +41,14 @@ DEALINGS IN THE SOFTWARE.
|
|||||||
namespace osmium {
|
namespace osmium {
|
||||||
|
|
||||||
namespace builder {
|
namespace builder {
|
||||||
template <typename T> class ObjectBuilder;
|
template <typename TDerived, typename T>
|
||||||
|
class OSMObjectBuilder;
|
||||||
} // namespace builder
|
} // namespace builder
|
||||||
|
|
||||||
class Node : public OSMObject {
|
class Node : public OSMObject {
|
||||||
|
|
||||||
friend class osmium::builder::ObjectBuilder<osmium::Node>;
|
template <typename TDerived, typename T>
|
||||||
|
friend class osmium::builder::OSMObjectBuilder;
|
||||||
|
|
||||||
osmium::Location m_location;
|
osmium::Location m_location;
|
||||||
|
|
||||||
@ -62,7 +64,7 @@ namespace osmium {
|
|||||||
return m_location;
|
return m_location;
|
||||||
}
|
}
|
||||||
|
|
||||||
Node& set_location(const osmium::Location& location) {
|
Node& set_location(const osmium::Location& location) noexcept {
|
||||||
m_location = location;
|
m_location = location;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
@ -52,12 +52,23 @@ namespace osmium {
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
using value_type = NodeRef;
|
||||||
|
using reference = NodeRef&;
|
||||||
|
using const_reference = const NodeRef&;
|
||||||
|
using iterator = NodeRef*;
|
||||||
|
using const_iterator = const NodeRef*;
|
||||||
|
using const_reverse_iterator = std::reverse_iterator<const NodeRef*>;
|
||||||
|
using difference_type = std::ptrdiff_t;
|
||||||
|
using size_type = std::size_t;
|
||||||
|
|
||||||
explicit NodeRefList(osmium::item_type itemtype) noexcept :
|
explicit NodeRefList(osmium::item_type itemtype) noexcept :
|
||||||
osmium::memory::Item(sizeof(NodeRefList), itemtype) {
|
osmium::memory::Item(sizeof(NodeRefList), itemtype) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks whether the collection is empty.
|
* Checks whether the collection is empty.
|
||||||
|
*
|
||||||
|
* Complexity: Constant.
|
||||||
*/
|
*/
|
||||||
bool empty() const noexcept {
|
bool empty() const noexcept {
|
||||||
return sizeof(NodeRefList) == byte_size();
|
return sizeof(NodeRefList) == byte_size();
|
||||||
@ -65,8 +76,10 @@ namespace osmium {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the number of NodeRefs in the collection.
|
* Returns the number of NodeRefs in the collection.
|
||||||
|
*
|
||||||
|
* Complexity: Constant.
|
||||||
*/
|
*/
|
||||||
size_t size() const noexcept {
|
size_type size() const noexcept {
|
||||||
const auto size_node_refs = byte_size() - sizeof(NodeRefList);
|
const auto size_node_refs = byte_size() - sizeof(NodeRefList);
|
||||||
assert(size_node_refs % sizeof(NodeRef) == 0);
|
assert(size_node_refs % sizeof(NodeRef) == 0);
|
||||||
return size_node_refs / sizeof(NodeRef);
|
return size_node_refs / sizeof(NodeRef);
|
||||||
@ -75,11 +88,13 @@ namespace osmium {
|
|||||||
/**
|
/**
|
||||||
* Access specified element.
|
* Access specified element.
|
||||||
*
|
*
|
||||||
|
* Complexity: Constant.
|
||||||
|
*
|
||||||
* @pre @code n < size() @endcode
|
* @pre @code n < size() @endcode
|
||||||
*
|
*
|
||||||
* @param n Get the n-th element of the collection.
|
* @param n Get the n-th element of the collection.
|
||||||
*/
|
*/
|
||||||
const NodeRef& operator[](size_t n) const noexcept {
|
const NodeRef& operator[](size_type n) const noexcept {
|
||||||
assert(n < size());
|
assert(n < size());
|
||||||
const NodeRef* node_ref = &*(cbegin());
|
const NodeRef* node_ref = &*(cbegin());
|
||||||
return node_ref[n];
|
return node_ref[n];
|
||||||
@ -88,6 +103,8 @@ namespace osmium {
|
|||||||
/**
|
/**
|
||||||
* Access the first element.
|
* Access the first element.
|
||||||
*
|
*
|
||||||
|
* Complexity: Constant.
|
||||||
|
*
|
||||||
* @pre @code !empty() @endcode
|
* @pre @code !empty() @endcode
|
||||||
*/
|
*/
|
||||||
const NodeRef& front() const noexcept {
|
const NodeRef& front() const noexcept {
|
||||||
@ -98,6 +115,8 @@ namespace osmium {
|
|||||||
/**
|
/**
|
||||||
* Access the last element.
|
* Access the last element.
|
||||||
*
|
*
|
||||||
|
* Complexity: Constant.
|
||||||
|
*
|
||||||
* @pre @code !empty() @endcode
|
* @pre @code !empty() @endcode
|
||||||
*/
|
*/
|
||||||
const NodeRef& back() const noexcept {
|
const NodeRef& back() const noexcept {
|
||||||
@ -109,6 +128,8 @@ namespace osmium {
|
|||||||
* Checks whether the first and last node in the collection have the
|
* Checks whether the first and last node in the collection have the
|
||||||
* same ID. The locations are not checked.
|
* same ID. The locations are not checked.
|
||||||
*
|
*
|
||||||
|
* Complexity: Constant.
|
||||||
|
*
|
||||||
* @pre @code !empty() @endcode
|
* @pre @code !empty() @endcode
|
||||||
*/
|
*/
|
||||||
bool is_closed() const noexcept {
|
bool is_closed() const noexcept {
|
||||||
@ -119,6 +140,8 @@ namespace osmium {
|
|||||||
* Checks whether the first and last node in the collection have the
|
* Checks whether the first and last node in the collection have the
|
||||||
* same ID. The locations are not checked.
|
* same ID. The locations are not checked.
|
||||||
*
|
*
|
||||||
|
* Complexity: Constant.
|
||||||
|
*
|
||||||
* @pre @code !empty() @endcode
|
* @pre @code !empty() @endcode
|
||||||
*/
|
*/
|
||||||
bool ends_have_same_id() const noexcept {
|
bool ends_have_same_id() const noexcept {
|
||||||
@ -129,6 +152,8 @@ namespace osmium {
|
|||||||
* Checks whether the first and last node in the collection have the
|
* Checks whether the first and last node in the collection have the
|
||||||
* same location. The IDs are not checked.
|
* same location. The IDs are not checked.
|
||||||
*
|
*
|
||||||
|
* Complexity: Constant.
|
||||||
|
*
|
||||||
* @pre @code !empty() @endcode
|
* @pre @code !empty() @endcode
|
||||||
* @pre @code front().location() && back().location() @endcode
|
* @pre @code front().location() && back().location() @endcode
|
||||||
*/
|
*/
|
||||||
@ -137,10 +162,6 @@ namespace osmium {
|
|||||||
return front().location() == back().location();
|
return front().location() == back().location();
|
||||||
}
|
}
|
||||||
|
|
||||||
using iterator = NodeRef*;
|
|
||||||
using const_iterator = const NodeRef*;
|
|
||||||
using const_reverse_iterator = std::reverse_iterator<const NodeRef*>;
|
|
||||||
|
|
||||||
/// Returns an iterator to the beginning.
|
/// Returns an iterator to the beginning.
|
||||||
iterator begin() noexcept {
|
iterator begin() noexcept {
|
||||||
return iterator(data() + sizeof(NodeRefList));
|
return iterator(data() + sizeof(NodeRefList));
|
||||||
|
@ -52,11 +52,19 @@ DEALINGS IN THE SOFTWARE.
|
|||||||
|
|
||||||
namespace osmium {
|
namespace osmium {
|
||||||
|
|
||||||
|
namespace builder {
|
||||||
|
template <typename TDerived, typename T>
|
||||||
|
class OSMObjectBuilder;
|
||||||
|
} // namespace builder
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* OSMObject (Node, Way, Relation, or Area).
|
* OSMObject (Node, Way, Relation, or Area).
|
||||||
*/
|
*/
|
||||||
class OSMObject : public osmium::OSMEntity {
|
class OSMObject : public osmium::OSMEntity {
|
||||||
|
|
||||||
|
template <typename TDerived, typename T>
|
||||||
|
friend class osmium::builder::OSMObjectBuilder;
|
||||||
|
|
||||||
object_id_type m_id;
|
object_id_type m_id;
|
||||||
bool m_deleted : 1;
|
bool m_deleted : 1;
|
||||||
object_version_type m_version : 31;
|
object_version_type m_version : 31;
|
||||||
|
@ -43,11 +43,14 @@ DEALINGS IN THE SOFTWARE.
|
|||||||
#include <osmium/osm/item_type.hpp>
|
#include <osmium/osm/item_type.hpp>
|
||||||
#include <osmium/osm/object.hpp>
|
#include <osmium/osm/object.hpp>
|
||||||
#include <osmium/osm/types.hpp>
|
#include <osmium/osm/types.hpp>
|
||||||
|
#include <osmium/util/compatibility.hpp>
|
||||||
|
|
||||||
namespace osmium {
|
namespace osmium {
|
||||||
|
|
||||||
namespace builder {
|
namespace builder {
|
||||||
template <typename> class ObjectBuilder;
|
template <typename TDerived, typename T>
|
||||||
|
class OSMObjectBuilder;
|
||||||
|
|
||||||
class RelationMemberListBuilder;
|
class RelationMemberListBuilder;
|
||||||
} // namespace builder
|
} // namespace builder
|
||||||
|
|
||||||
@ -109,7 +112,8 @@ namespace osmium {
|
|||||||
return m_ref;
|
return m_ref;
|
||||||
}
|
}
|
||||||
|
|
||||||
RelationMember& ref(object_id_type ref) noexcept {
|
/// @deprecated Use set_ref() instead.
|
||||||
|
OSMIUM_DEPRECATED RelationMember& ref(object_id_type ref) noexcept {
|
||||||
m_ref = ref;
|
m_ref = ref;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
@ -149,23 +153,18 @@ namespace osmium {
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
using size_type = size_t;
|
|
||||||
|
|
||||||
RelationMemberList() :
|
RelationMemberList() :
|
||||||
osmium::memory::Collection<RelationMember, osmium::item_type::relation_member_list>() {
|
osmium::memory::Collection<RelationMember, osmium::item_type::relation_member_list>() {
|
||||||
}
|
}
|
||||||
|
|
||||||
size_type size() const noexcept {
|
|
||||||
return static_cast<size_type>(std::distance(begin(), end()));
|
|
||||||
}
|
|
||||||
|
|
||||||
}; // class RelationMemberList
|
}; // class RelationMemberList
|
||||||
|
|
||||||
static_assert(sizeof(RelationMemberList) % osmium::memory::align_bytes == 0, "Class osmium::RelationMemberList has wrong size to be aligned properly!");
|
static_assert(sizeof(RelationMemberList) % osmium::memory::align_bytes == 0, "Class osmium::RelationMemberList has wrong size to be aligned properly!");
|
||||||
|
|
||||||
class Relation : public OSMObject {
|
class Relation : public OSMObject {
|
||||||
|
|
||||||
friend class osmium::builder::ObjectBuilder<osmium::Relation>;
|
template <typename TDerived, typename T>
|
||||||
|
friend class osmium::builder::OSMObjectBuilder;
|
||||||
|
|
||||||
Relation() noexcept :
|
Relation() noexcept :
|
||||||
OSMObject(sizeof(Relation), osmium::item_type::relation) {
|
OSMObject(sizeof(Relation), osmium::item_type::relation) {
|
||||||
|
19
third_party/libosmium/include/osmium/osm/tag.hpp
vendored
19
third_party/libosmium/include/osmium/osm/tag.hpp
vendored
@ -86,12 +86,14 @@ namespace osmium {
|
|||||||
|
|
||||||
}; // class Tag
|
}; // class Tag
|
||||||
|
|
||||||
inline bool operator==(const Tag& a, const Tag& b) {
|
inline bool operator==(const Tag& lhs, const Tag& rhs) {
|
||||||
return !std::strcmp(a.key(), b.key()) && !std::strcmp(a.value(), b.value());
|
return !std::strcmp(lhs.key(), rhs.key()) &&
|
||||||
|
!std::strcmp(lhs.value(), rhs.value());
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool operator<(const Tag& a, const Tag& b) {
|
inline bool operator<(const Tag& lhs, const Tag& rhs) {
|
||||||
return (!std::strcmp(a.key(), b.key()) && (std::strcmp(a.value(), b.value()) < 0)) || (std::strcmp(a.key(), b.key()) < 0);
|
const auto c = std::strcmp(lhs.key(), rhs.key());
|
||||||
|
return (c == 0 ? std::strcmp(lhs.value(), rhs.value()) : c) < 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -112,19 +114,10 @@ namespace osmium {
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
using size_type = size_t;
|
|
||||||
|
|
||||||
TagList() :
|
TagList() :
|
||||||
osmium::memory::Collection<Tag, osmium::item_type::tag_list>() {
|
osmium::memory::Collection<Tag, osmium::item_type::tag_list>() {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the number of tags in this tag list.
|
|
||||||
*/
|
|
||||||
size_type size() const noexcept {
|
|
||||||
return static_cast<size_type>(std::distance(begin(), end()));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get tag value for the given tag key. If the key is not set, returns
|
* Get tag value for the given tag key. If the key is not set, returns
|
||||||
* the default_value.
|
* the default_value.
|
||||||
|
@ -44,7 +44,8 @@ DEALINGS IN THE SOFTWARE.
|
|||||||
namespace osmium {
|
namespace osmium {
|
||||||
|
|
||||||
namespace builder {
|
namespace builder {
|
||||||
template <typename T> class ObjectBuilder;
|
template <typename TDerived, typename T>
|
||||||
|
class OSMObjectBuilder;
|
||||||
} // namespace builder
|
} // namespace builder
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -66,7 +67,8 @@ namespace osmium {
|
|||||||
|
|
||||||
class Way : public OSMObject {
|
class Way : public OSMObject {
|
||||||
|
|
||||||
friend class osmium::builder::ObjectBuilder<osmium::Way>;
|
template <typename TDerived, typename T>
|
||||||
|
friend class osmium::builder::OSMObjectBuilder;
|
||||||
|
|
||||||
Way() noexcept :
|
Way() noexcept :
|
||||||
OSMObject(sizeof(Way), osmium::item_type::way) {
|
OSMObject(sizeof(Way), osmium::item_type::way) {
|
||||||
|
@ -40,6 +40,7 @@ DEALINGS IN THE SOFTWARE.
|
|||||||
#include <functional>
|
#include <functional>
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include <osmium/osm/item_type.hpp>
|
#include <osmium/osm/item_type.hpp>
|
||||||
@ -353,7 +354,7 @@ namespace osmium {
|
|||||||
member_meta(member.type()).emplace_back(member.ref(), m_relations.size(), n);
|
member_meta(member.type()).emplace_back(member.ref(), m_relations.size(), n);
|
||||||
relation_meta.increment_need_members();
|
relation_meta.increment_need_members();
|
||||||
} else {
|
} else {
|
||||||
member.ref(0); // set member id to zero to indicate we are not interested
|
member.set_ref(0); // set member id to zero to indicate we are not interested
|
||||||
}
|
}
|
||||||
++n;
|
++n;
|
||||||
}
|
}
|
||||||
@ -494,12 +495,65 @@ namespace osmium {
|
|||||||
return m_members_buffer;
|
return m_members_buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is the given member available in the members buffer?
|
||||||
|
*
|
||||||
|
* If you also need the offset of the object, use
|
||||||
|
* get_availability_and_offset() instead, it is more efficient
|
||||||
|
* that way.
|
||||||
|
*
|
||||||
|
* @param type Item type
|
||||||
|
* @param id Object Id
|
||||||
|
* @returns True if the object is available, false otherwise.
|
||||||
|
*/
|
||||||
|
bool is_available(osmium::item_type type, osmium::object_id_type id) {
|
||||||
|
const auto range = find_member_meta(type, id);
|
||||||
|
assert(!range.empty());
|
||||||
|
return range.begin()->is_available();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get offset of a member in the members buffer.
|
||||||
|
*
|
||||||
|
* @pre The member must be available. If you are not sure, call
|
||||||
|
* get_availability_and_offset() instead.
|
||||||
|
* @param type Item type
|
||||||
|
* @param id Object Id
|
||||||
|
* @returns The offset of the object in the members buffer.
|
||||||
|
*/
|
||||||
size_t get_offset(osmium::item_type type, osmium::object_id_type id) {
|
size_t get_offset(osmium::item_type type, osmium::object_id_type id) {
|
||||||
const auto range = find_member_meta(type, id);
|
const auto range = find_member_meta(type, id);
|
||||||
assert(!range.empty());
|
assert(!range.empty());
|
||||||
|
assert(range.begin()->is_available());
|
||||||
return range.begin()->buffer_offset();
|
return range.begin()->buffer_offset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether a member is available in the members buffer
|
||||||
|
* and returns its offset.
|
||||||
|
*
|
||||||
|
* If the member is not available, the boolean returned as the
|
||||||
|
* first element in the pair is false. In that case the offset
|
||||||
|
* in the second element is undefined.
|
||||||
|
*
|
||||||
|
* If the member is available, the boolean returned as the first
|
||||||
|
* element in the pair is true and the second element of the
|
||||||
|
* pair contains the offset into the members buffer.
|
||||||
|
*
|
||||||
|
* @param type Item type
|
||||||
|
* @param id Object Id
|
||||||
|
* @returns Pair of bool (showing availability) and the offset.
|
||||||
|
*/
|
||||||
|
std::pair<bool, size_t> get_availability_and_offset(osmium::item_type type, osmium::object_id_type id) {
|
||||||
|
const auto range = find_member_meta(type, id);
|
||||||
|
assert(!range.empty());
|
||||||
|
if (range.begin()->is_available()) {
|
||||||
|
return std::make_pair(true, range.begin()->buffer_offset());
|
||||||
|
} else {
|
||||||
|
return std::make_pair(false, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
template <typename TIter>
|
template <typename TIter>
|
||||||
void read_relations(TIter begin, TIter end) {
|
void read_relations(TIter begin, TIter end) {
|
||||||
HandlerPass1 handler(*static_cast<TCollector*>(this));
|
HandlerPass1 handler(*static_cast<TCollector*>(this));
|
||||||
@ -525,7 +579,7 @@ namespace osmium {
|
|||||||
/**
|
/**
|
||||||
* Decide whether to purge removed members and then do it.
|
* Decide whether to purge removed members and then do it.
|
||||||
*
|
*
|
||||||
* Currently the purging is done every thousand calls.
|
* Currently the purging is done every 10000 calls.
|
||||||
* This could probably be improved upon.
|
* This could probably be improved upon.
|
||||||
*/
|
*/
|
||||||
void possibly_purge_removed_members() {
|
void possibly_purge_removed_members() {
|
||||||
|
@ -35,6 +35,7 @@ DEALINGS IN THE SOFTWARE.
|
|||||||
|
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <iosfwd>
|
#include <iosfwd>
|
||||||
|
#include <limits>
|
||||||
|
|
||||||
#include <osmium/osm/types.hpp>
|
#include <osmium/osm/types.hpp>
|
||||||
|
|
||||||
@ -71,24 +72,44 @@ namespace osmium {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Offset in the buffer where the object is stored.
|
* Offset in the buffer where the object is stored.
|
||||||
|
*
|
||||||
|
* The default value is one that will never be valid, so it is
|
||||||
|
* easier to catch problems.
|
||||||
*/
|
*/
|
||||||
size_t m_buffer_offset { 0 };
|
size_t m_buffer_offset = std::numeric_limits<size_t>::max();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Has this member been found in the input data.
|
||||||
|
*/
|
||||||
|
bool m_available = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Marks this member as removed. It can not be used any more.
|
||||||
|
*/
|
||||||
bool m_removed = false;
|
bool m_removed = false;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create new MemberMeta. The variant with zeros for relation_pos and
|
* Create new MemberMeta.
|
||||||
* member_pos is used to create dummy MemberMeta that can be compared
|
|
||||||
* to the MemberMeta in the vectors using the equal_range algorithm.
|
|
||||||
*/
|
*/
|
||||||
explicit MemberMeta(osmium::object_id_type member_id, size_t relation_pos=0, size_t member_pos=0) noexcept :
|
explicit MemberMeta(osmium::object_id_type member_id, size_t relation_pos, size_t member_pos) noexcept :
|
||||||
m_member_id(member_id),
|
m_member_id(member_id),
|
||||||
m_relation_pos(relation_pos),
|
m_relation_pos(relation_pos),
|
||||||
m_member_pos(member_pos) {
|
m_member_pos(member_pos) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create new MemberMeta. This constructor is used to create
|
||||||
|
* dummy MemberMeta objects that can be compared to the
|
||||||
|
* MemberMetas in a vector using the equal_range algorithm.
|
||||||
|
*/
|
||||||
|
explicit MemberMeta(osmium::object_id_type member_id) noexcept :
|
||||||
|
m_member_id(member_id),
|
||||||
|
m_relation_pos(0),
|
||||||
|
m_member_pos(0) {
|
||||||
|
}
|
||||||
|
|
||||||
osmium::object_id_type member_id() const noexcept {
|
osmium::object_id_type member_id() const noexcept {
|
||||||
return m_member_id;
|
return m_member_id;
|
||||||
}
|
}
|
||||||
@ -107,6 +128,11 @@ namespace osmium {
|
|||||||
|
|
||||||
void set_buffer_offset(size_t offset) noexcept {
|
void set_buffer_offset(size_t offset) noexcept {
|
||||||
m_buffer_offset = offset;
|
m_buffer_offset = offset;
|
||||||
|
m_available = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_available() const noexcept {
|
||||||
|
return m_available;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool removed() const noexcept {
|
bool removed() const noexcept {
|
||||||
@ -124,8 +150,8 @@ namespace osmium {
|
|||||||
* Used to sort a vector of MemberMeta objects and to later find
|
* Used to sort a vector of MemberMeta objects and to later find
|
||||||
* them using binary search.
|
* them using binary search.
|
||||||
*/
|
*/
|
||||||
inline bool operator<(const MemberMeta& a, const MemberMeta& b) noexcept {
|
inline bool operator<(const MemberMeta& lhs, const MemberMeta& rhs) noexcept {
|
||||||
return a.member_id() < b.member_id();
|
return lhs.member_id() < rhs.member_id();
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename TChar, typename TTraits>
|
template <typename TChar, typename TTraits>
|
||||||
|
@ -51,7 +51,7 @@ namespace osmium {
|
|||||||
|
|
||||||
namespace thread {
|
namespace thread {
|
||||||
|
|
||||||
static const std::chrono::milliseconds full_queue_sleep_duration { 10 }; // XXX
|
static const std::chrono::milliseconds max_wait{10};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A thread-safe queue.
|
* A thread-safe queue.
|
||||||
@ -70,9 +70,12 @@ namespace osmium {
|
|||||||
|
|
||||||
std::queue<T> m_queue;
|
std::queue<T> m_queue;
|
||||||
|
|
||||||
/// Used to signal readers when data is available in the queue.
|
/// Used to signal consumers when data is available in the queue.
|
||||||
std::condition_variable m_data_available;
|
std::condition_variable m_data_available;
|
||||||
|
|
||||||
|
/// Used to signal producers when queue is not full.
|
||||||
|
std::condition_variable m_space_available;
|
||||||
|
|
||||||
#ifdef OSMIUM_DEBUG_QUEUE_SIZE
|
#ifdef OSMIUM_DEBUG_QUEUE_SIZE
|
||||||
/// The largest size the queue has been so far.
|
/// The largest size the queue has been so far.
|
||||||
size_t m_largest_size;
|
size_t m_largest_size;
|
||||||
@ -109,7 +112,8 @@ namespace osmium {
|
|||||||
m_name(name),
|
m_name(name),
|
||||||
m_mutex(),
|
m_mutex(),
|
||||||
m_queue(),
|
m_queue(),
|
||||||
m_data_available()
|
m_data_available(),
|
||||||
|
m_space_available()
|
||||||
#ifdef OSMIUM_DEBUG_QUEUE_SIZE
|
#ifdef OSMIUM_DEBUG_QUEUE_SIZE
|
||||||
,
|
,
|
||||||
m_largest_size(0),
|
m_largest_size(0),
|
||||||
@ -123,13 +127,20 @@ namespace osmium {
|
|||||||
|
|
||||||
~Queue() {
|
~Queue() {
|
||||||
#ifdef OSMIUM_DEBUG_QUEUE_SIZE
|
#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 in " << m_push_counter << " push() calls and was empty " << m_empty_counter << " times in " << m_pop_counter << " pop() calls\n";
|
std::cerr << "queue '" << m_name
|
||||||
|
<< "' with max_size=" << m_max_size
|
||||||
|
<< " had largest size " << m_largest_size
|
||||||
|
<< " and was full " << m_full_counter
|
||||||
|
<< " times in " << m_push_counter
|
||||||
|
<< " push() calls and was empty " << m_empty_counter
|
||||||
|
<< " times in " << m_pop_counter
|
||||||
|
<< " pop() calls\n";
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Push an element onto the queue. If the queue has a max size, this
|
* Push an element onto the queue. If the queue has a max size,
|
||||||
* call will block if the queue is full.
|
* this call will block if the queue is full.
|
||||||
*/
|
*/
|
||||||
void push(T value) {
|
void push(T value) {
|
||||||
#ifdef OSMIUM_DEBUG_QUEUE_SIZE
|
#ifdef OSMIUM_DEBUG_QUEUE_SIZE
|
||||||
@ -137,13 +148,16 @@ namespace osmium {
|
|||||||
#endif
|
#endif
|
||||||
if (m_max_size) {
|
if (m_max_size) {
|
||||||
while (size() >= m_max_size) {
|
while (size() >= m_max_size) {
|
||||||
std::this_thread::sleep_for(full_queue_sleep_duration);
|
std::unique_lock<std::mutex> lock{m_mutex};
|
||||||
|
m_space_available.wait_for(lock, max_wait, [this] {
|
||||||
|
return m_queue.size() < m_max_size;
|
||||||
|
});
|
||||||
#ifdef OSMIUM_DEBUG_QUEUE_SIZE
|
#ifdef OSMIUM_DEBUG_QUEUE_SIZE
|
||||||
++m_full_counter;
|
++m_full_counter;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
std::lock_guard<std::mutex> lock(m_mutex);
|
std::lock_guard<std::mutex> lock{m_mutex};
|
||||||
m_queue.push(std::move(value));
|
m_queue.push(std::move(value));
|
||||||
#ifdef OSMIUM_DEBUG_QUEUE_SIZE
|
#ifdef OSMIUM_DEBUG_QUEUE_SIZE
|
||||||
if (m_largest_size < m_queue.size()) {
|
if (m_largest_size < m_queue.size()) {
|
||||||
@ -157,7 +171,7 @@ namespace osmium {
|
|||||||
#ifdef OSMIUM_DEBUG_QUEUE_SIZE
|
#ifdef OSMIUM_DEBUG_QUEUE_SIZE
|
||||||
++m_pop_counter;
|
++m_pop_counter;
|
||||||
#endif
|
#endif
|
||||||
std::unique_lock<std::mutex> lock(m_mutex);
|
std::unique_lock<std::mutex> lock{m_mutex};
|
||||||
#ifdef OSMIUM_DEBUG_QUEUE_SIZE
|
#ifdef OSMIUM_DEBUG_QUEUE_SIZE
|
||||||
if (m_queue.empty()) {
|
if (m_queue.empty()) {
|
||||||
++m_empty_counter;
|
++m_empty_counter;
|
||||||
@ -169,6 +183,10 @@ namespace osmium {
|
|||||||
if (!m_queue.empty()) {
|
if (!m_queue.empty()) {
|
||||||
value = std::move(m_queue.front());
|
value = std::move(m_queue.front());
|
||||||
m_queue.pop();
|
m_queue.pop();
|
||||||
|
lock.unlock();
|
||||||
|
if (m_max_size) {
|
||||||
|
m_space_available.notify_one();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -176,25 +194,30 @@ namespace osmium {
|
|||||||
#ifdef OSMIUM_DEBUG_QUEUE_SIZE
|
#ifdef OSMIUM_DEBUG_QUEUE_SIZE
|
||||||
++m_pop_counter;
|
++m_pop_counter;
|
||||||
#endif
|
#endif
|
||||||
std::lock_guard<std::mutex> lock(m_mutex);
|
{
|
||||||
if (m_queue.empty()) {
|
std::lock_guard<std::mutex> lock{m_mutex};
|
||||||
|
if (m_queue.empty()) {
|
||||||
#ifdef OSMIUM_DEBUG_QUEUE_SIZE
|
#ifdef OSMIUM_DEBUG_QUEUE_SIZE
|
||||||
++m_empty_counter;
|
++m_empty_counter;
|
||||||
#endif
|
#endif
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
value = std::move(m_queue.front());
|
||||||
|
m_queue.pop();
|
||||||
|
}
|
||||||
|
if (m_max_size) {
|
||||||
|
m_space_available.notify_one();
|
||||||
}
|
}
|
||||||
value = std::move(m_queue.front());
|
|
||||||
m_queue.pop();
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool empty() const {
|
bool empty() const {
|
||||||
std::lock_guard<std::mutex> lock(m_mutex);
|
std::lock_guard<std::mutex> lock{m_mutex};
|
||||||
return m_queue.empty();
|
return m_queue.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t size() const {
|
size_t size() const {
|
||||||
std::lock_guard<std::mutex> lock(m_mutex);
|
std::lock_guard<std::mutex> lock{m_mutex};
|
||||||
return m_queue.size();
|
return m_queue.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -172,6 +172,18 @@ namespace osmium {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes the progress bar. Call this before doing any other output.
|
||||||
|
* The next time update() is called, the progress bar will be visible
|
||||||
|
* again.
|
||||||
|
*/
|
||||||
|
void remove() {
|
||||||
|
if (m_enable) {
|
||||||
|
std::cerr << spc() << " \r";
|
||||||
|
m_prev_percent = 100 + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}; // class ProgressBar
|
}; // class ProgressBar
|
||||||
|
|
||||||
} // namespace osmium
|
} // namespace osmium
|
||||||
|
@ -34,9 +34,9 @@ DEALINGS IN THE SOFTWARE.
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#define LIBOSMIUM_VERSION_MAJOR 2
|
#define LIBOSMIUM_VERSION_MAJOR 2
|
||||||
#define LIBOSMIUM_VERSION_MINOR 9
|
#define LIBOSMIUM_VERSION_MINOR 10
|
||||||
#define LIBOSMIUM_VERSION_PATCH 0
|
#define LIBOSMIUM_VERSION_PATCH 0
|
||||||
|
|
||||||
#define LIBOSMIUM_VERSION_STRING "2.9.0"
|
#define LIBOSMIUM_VERSION_STRING "2.10.0"
|
||||||
|
|
||||||
#endif // OSMIUM_VERSION_HPP
|
#endif // OSMIUM_VERSION_HPP
|
||||||
|
50
third_party/libosmium/test/CMakeLists.txt
vendored
50
third_party/libosmium/test/CMakeLists.txt
vendored
@ -112,12 +112,6 @@ if(NOT Threads_FOUND)
|
|||||||
set(Threads_FOUND FALSE)
|
set(Threads_FOUND FALSE)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(GEOS_FOUND AND PROJ_FOUND)
|
|
||||||
set(GEOS_AND_PROJ_FOUND TRUE)
|
|
||||||
else()
|
|
||||||
set(GEOS_AND_PROJ_FOUND FALSE)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
|
|
||||||
#-----------------------------------------------------------------------------
|
#-----------------------------------------------------------------------------
|
||||||
#
|
#
|
||||||
@ -127,45 +121,45 @@ endif()
|
|||||||
add_unit_test(area test_area_id)
|
add_unit_test(area test_area_id)
|
||||||
add_unit_test(area test_node_ref_segment)
|
add_unit_test(area test_node_ref_segment)
|
||||||
|
|
||||||
add_unit_test(basic test_area)
|
add_unit_test(osm test_area)
|
||||||
add_unit_test(basic test_box)
|
add_unit_test(osm test_box)
|
||||||
add_unit_test(basic test_changeset)
|
add_unit_test(osm test_changeset)
|
||||||
add_unit_test(basic test_crc)
|
add_unit_test(osm test_crc)
|
||||||
add_unit_test(basic test_entity_bits)
|
add_unit_test(osm test_entity_bits)
|
||||||
add_unit_test(basic test_location)
|
add_unit_test(osm test_location)
|
||||||
add_unit_test(basic test_node)
|
add_unit_test(osm test_node)
|
||||||
add_unit_test(basic test_node_ref)
|
add_unit_test(osm test_node_ref)
|
||||||
add_unit_test(basic test_object_comparisons)
|
add_unit_test(osm test_object_comparisons)
|
||||||
add_unit_test(basic test_relation)
|
add_unit_test(osm test_relation)
|
||||||
add_unit_test(basic test_timestamp)
|
add_unit_test(osm test_timestamp)
|
||||||
add_unit_test(basic test_types_from_string)
|
add_unit_test(osm test_types_from_string)
|
||||||
add_unit_test(basic test_way)
|
add_unit_test(osm test_way)
|
||||||
|
|
||||||
add_unit_test(buffer test_buffer_basics)
|
add_unit_test(memory test_buffer_basics)
|
||||||
add_unit_test(buffer test_buffer_node)
|
add_unit_test(memory test_buffer_node)
|
||||||
add_unit_test(buffer test_buffer_purge)
|
add_unit_test(memory test_buffer_purge)
|
||||||
|
|
||||||
add_unit_test(builder test_attr)
|
add_unit_test(builder test_attr)
|
||||||
|
add_unit_test(builder test_object_builder)
|
||||||
add_unit_test(geom test_factory_with_projection
|
|
||||||
ENABLE_IF ${GEOS_AND_PROJ_FOUND}
|
|
||||||
LIBS ${GEOS_LIBRARY} ${PROJ_LIBRARY})
|
|
||||||
|
|
||||||
add_unit_test(geom test_crs ENABLE_IF ${PROJ_FOUND} LIBS ${PROJ_LIBRARY})
|
add_unit_test(geom test_crs ENABLE_IF ${PROJ_FOUND} LIBS ${PROJ_LIBRARY})
|
||||||
add_unit_test(geom test_exception)
|
add_unit_test(geom test_exception)
|
||||||
|
add_unit_test(geom test_factory_with_projection ENABLE_IF ${PROJ_FOUND} LIBS ${PROJ_LIBRARY})
|
||||||
add_unit_test(geom test_geojson)
|
add_unit_test(geom test_geojson)
|
||||||
add_unit_test(geom test_geos ENABLE_IF ${GEOS_FOUND} LIBS ${GEOS_LIBRARY})
|
add_unit_test(geom test_geos ENABLE_IF ${GEOS_FOUND} LIBS ${GEOS_LIBRARY})
|
||||||
add_unit_test(geom test_geos_wkb ENABLE_IF ${GEOS_FOUND} LIBS ${GEOS_LIBRARY})
|
|
||||||
add_unit_test(geom test_mercator)
|
add_unit_test(geom test_mercator)
|
||||||
add_unit_test(geom test_ogr ENABLE_IF ${GDAL_FOUND} LIBS ${GDAL_LIBRARY})
|
add_unit_test(geom test_ogr ENABLE_IF ${GDAL_FOUND} LIBS ${GDAL_LIBRARY})
|
||||||
|
add_unit_test(geom test_ogr_wkb ENABLE_IF ${GDAL_FOUND} LIBS ${GDAL_LIBRARY})
|
||||||
add_unit_test(geom test_projection ENABLE_IF ${PROJ_FOUND} LIBS ${PROJ_LIBRARY})
|
add_unit_test(geom test_projection ENABLE_IF ${PROJ_FOUND} LIBS ${PROJ_LIBRARY})
|
||||||
add_unit_test(geom test_tile ENABLE_IF ${GEOS_FOUND})
|
add_unit_test(geom test_tile)
|
||||||
add_unit_test(geom test_wkb)
|
add_unit_test(geom test_wkb)
|
||||||
add_unit_test(geom test_wkt)
|
add_unit_test(geom test_wkt)
|
||||||
|
|
||||||
|
add_unit_test(index test_id_set)
|
||||||
add_unit_test(index test_id_to_location ENABLE_IF ${SPARSEHASH_FOUND})
|
add_unit_test(index test_id_to_location ENABLE_IF ${SPARSEHASH_FOUND})
|
||||||
add_unit_test(index test_file_based_index)
|
add_unit_test(index test_file_based_index)
|
||||||
|
|
||||||
|
add_unit_test(io test_compression_factory)
|
||||||
add_unit_test(io test_bzip2 ENABLE_IF ${BZIP2_FOUND} LIBS ${BZIP2_LIBRARIES})
|
add_unit_test(io test_bzip2 ENABLE_IF ${BZIP2_FOUND} LIBS ${BZIP2_LIBRARIES})
|
||||||
add_unit_test(io test_file_formats)
|
add_unit_test(io test_file_formats)
|
||||||
add_unit_test(io test_reader LIBS "${OSMIUM_XML_LIBRARIES};${OSMIUM_PBF_LIBRARIES}")
|
add_unit_test(io test_reader LIBS "${OSMIUM_XML_LIBRARIES};${OSMIUM_PBF_LIBRARIES}")
|
||||||
|
@ -83,7 +83,7 @@ header_buffer_type parse_xml(std::string input) {
|
|||||||
osmium::io::detail::add_to_queue(input_queue, std::move(input));
|
osmium::io::detail::add_to_queue(input_queue, std::move(input));
|
||||||
osmium::io::detail::add_to_queue(input_queue, std::string{});
|
osmium::io::detail::add_to_queue(input_queue, std::string{});
|
||||||
|
|
||||||
osmium::io::detail::XMLParser parser{input_queue, output_queue, header_promise, osmium::osm_entity_bits::all};
|
osmium::io::detail::XMLParser parser{input_queue, output_queue, header_promise, osmium::io::detail::reader_options{}};
|
||||||
parser.parse();
|
parser.parse();
|
||||||
|
|
||||||
header_buffer_type result;
|
header_buffer_type result;
|
||||||
|
21
third_party/libosmium/test/examples/CMakeLists.txt
vendored
Normal file
21
third_party/libosmium/test/examples/CMakeLists.txt
vendored
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
#
|
||||||
|
# CMake Config
|
||||||
|
#
|
||||||
|
# Libosmium example tests
|
||||||
|
#
|
||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
message(STATUS "Configuring example tests")
|
||||||
|
|
||||||
|
file(GLOB _dirs RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/t/*)
|
||||||
|
|
||||||
|
foreach(_dir ${_dirs})
|
||||||
|
message(STATUS " adding test: ${_dir}")
|
||||||
|
add_subdirectory("${_dir}")
|
||||||
|
endforeach()
|
||||||
|
|
||||||
|
message(STATUS "Configuring example tests - done")
|
||||||
|
|
||||||
|
|
||||||
|
#-----------------------------------------------------------------------------
|
7
third_party/libosmium/test/examples/t/pub_names/CMakeLists.txt
vendored
Normal file
7
third_party/libosmium/test/examples/t/pub_names/CMakeLists.txt
vendored
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
|
||||||
|
add_test(NAME examples_pub_names
|
||||||
|
COMMAND osmium_pub_names ${CMAKE_CURRENT_SOURCE_DIR}/pubs.osm)
|
||||||
|
|
||||||
|
set_tests_properties(examples_pub_names PROPERTIES
|
||||||
|
PASS_REGULAR_EXPRESSION "^Im Holze\n$")
|
||||||
|
|
7
third_party/libosmium/test/examples/t/pub_names/pubs.osm
vendored
Normal file
7
third_party/libosmium/test/examples/t/pub_names/pubs.osm
vendored
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
<?xml version='1.0' encoding='UTF-8'?>
|
||||||
|
<osm version="0.6">
|
||||||
|
<node id="167199652" version="3" timestamp="2010-12-27T13:15:02Z" uid="57645" user="KartoGrapHiti" changeset="6777507" lat="53.0526516" lon="8.8919477">
|
||||||
|
<tag k="amenity" v="pub"/>
|
||||||
|
<tag k="name" v="Im Holze"/>
|
||||||
|
</node>
|
||||||
|
</osm>
|
8
third_party/libosmium/test/examples/t/road_length/CMakeLists.txt
vendored
Normal file
8
third_party/libosmium/test/examples/t/road_length/CMakeLists.txt
vendored
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
|
||||||
|
add_test(NAME examples_road_length
|
||||||
|
COMMAND osmium_road_length ${CMAKE_CURRENT_SOURCE_DIR}/road.osm)
|
||||||
|
|
||||||
|
set_tests_properties(examples_road_length PROPERTIES
|
||||||
|
PASS_REGULAR_EXPRESSION "^Length: 0\\.405.*km\n$"
|
||||||
|
)
|
||||||
|
|
59
third_party/libosmium/test/examples/t/road_length/road.osm
vendored
Normal file
59
third_party/libosmium/test/examples/t/road_length/road.osm
vendored
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<osm version="0.6" generator="CGImap 0.3.3 (31041 thorn-01.openstreetmap.org)" copyright="OpenStreetMap and contributors" attribution="http://www.openstreetmap.org/copyright" license="http://opendatacommons.org/licenses/odbl/1-0/">
|
||||||
|
<node id="5599384" visible="true" version="5" changeset="829716" timestamp="2009-03-18T17:16:26Z" user="burts" uid="97529" lat="51.0271601" lon="13.7252197"/>
|
||||||
|
<node id="250384970" visible="true" version="3" changeset="855544" timestamp="2009-01-30T21:58:37Z" user="saftl" uid="7989" lat="51.0288568" lon="13.7248159">
|
||||||
|
<tag k="created_by" v="JOSM"/>
|
||||||
|
</node>
|
||||||
|
<node id="250996316" visible="true" version="5" changeset="838711" timestamp="2009-03-21T13:10:39Z" user="burts" uid="97529" lat="51.0274683" lon="13.7251464"/>
|
||||||
|
<node id="250996321" visible="true" version="3" changeset="855544" timestamp="2009-01-30T21:59:14Z" user="saftl" uid="7989" lat="51.0284283" lon="13.7249179">
|
||||||
|
<tag k="created_by" v="JOSM"/>
|
||||||
|
</node>
|
||||||
|
<node id="252587568" visible="true" version="3" changeset="855544" timestamp="2009-01-30T21:58:45Z" user="saftl" uid="7989" lat="51.0275477" lon="13.7251275">
|
||||||
|
<tag k="created_by" v="JOSM"/>
|
||||||
|
</node>
|
||||||
|
<node id="5599381" visible="true" version="6" changeset="15768585" timestamp="2013-04-18T01:20:26Z" user="Wolle DD" uid="1161559" lat="51.0307642" lon="13.7243263"/>
|
||||||
|
<node id="1122039499" visible="true" version="2" changeset="26063898" timestamp="2014-10-14T04:09:11Z" user="Seandebasti" uid="550560" lat="51.0285248" lon="13.7248970"/>
|
||||||
|
<node id="1122039521" visible="true" version="2" changeset="12753110" timestamp="2012-08-16T17:03:47Z" user="TEAM_CN_TUD" uid="716608" lat="51.0277456" lon="13.7250806"/>
|
||||||
|
<node id="5599382" visible="true" version="6" changeset="8191054" timestamp="2011-05-19T16:19:51Z" user="stw1701" uid="102899" lat="51.0297991" lon="13.7245892"/>
|
||||||
|
<node id="1299329303" visible="true" version="1" changeset="8242335" timestamp="2011-05-25T07:46:01Z" user="bigbug21" uid="15748" lat="51.0290875" lon="13.7247628"/>
|
||||||
|
<node id="1868844753" visible="true" version="2" changeset="13260925" timestamp="2012-09-26T15:26:31Z" user="TEAM_CN_TUD" uid="716608" lat="51.0289617" lon="13.7247917"/>
|
||||||
|
<node id="1868844765" visible="true" version="2" changeset="13260925" timestamp="2012-09-26T15:26:31Z" user="TEAM_CN_TUD" uid="716608" lat="51.0292872" lon="13.7247140"/>
|
||||||
|
<node id="1868844782" visible="true" version="2" changeset="13260925" timestamp="2012-09-26T15:26:31Z" user="TEAM_CN_TUD" uid="716608" lat="51.0295717" lon="13.7246429"/>
|
||||||
|
<node id="1922091528" visible="true" version="2" changeset="13260925" timestamp="2012-09-26T15:26:31Z" user="TEAM_CN_TUD" uid="716608" lat="51.0281700" lon="13.7249813"/>
|
||||||
|
<node id="1953249124" visible="true" version="1" changeset="13418280" timestamp="2012-10-08T20:18:35Z" user="TEAM_CN_TUD" uid="716608" lat="51.0292437" lon="13.7247246"/>
|
||||||
|
<node id="2015120752" visible="true" version="1" changeset="13883494" timestamp="2012-11-15T14:22:31Z" user="TEAM_CN_TUD" uid="716608" lat="51.0293536" lon="13.7246974"/>
|
||||||
|
<node id="2056871900" visible="true" version="1" changeset="14207491" timestamp="2012-12-09T00:03:11Z" user="bigbug21" uid="15748" lat="51.0305821" lon="13.7243895"/>
|
||||||
|
<node id="2458246647" visible="true" version="1" changeset="17836591" timestamp="2013-09-14T17:05:06Z" user="bigbug21" uid="15748" lat="51.0295979" lon="13.7246367"/>
|
||||||
|
<node id="250384969" visible="true" version="4" changeset="17857555" timestamp="2013-09-15T20:17:55Z" user="4b696d" uid="1420318" lat="51.0282021" lon="13.7249734"/>
|
||||||
|
<node id="3128723784" visible="true" version="1" changeset="26063898" timestamp="2014-10-14T04:09:07Z" user="Seandebasti" uid="550560" lat="51.0281018" lon="13.7249973"/>
|
||||||
|
<way id="4428564" visible="true" version="21" changeset="26063898" timestamp="2014-10-14T04:09:13Z" user="Seandebasti" uid="550560">
|
||||||
|
<nd ref="5599381"/>
|
||||||
|
<nd ref="2056871900"/>
|
||||||
|
<nd ref="5599382"/>
|
||||||
|
<nd ref="2458246647"/>
|
||||||
|
<nd ref="1868844782"/>
|
||||||
|
<nd ref="2015120752"/>
|
||||||
|
<nd ref="1868844765"/>
|
||||||
|
<nd ref="1953249124"/>
|
||||||
|
<nd ref="1299329303"/>
|
||||||
|
<nd ref="1868844753"/>
|
||||||
|
<nd ref="250384970"/>
|
||||||
|
<nd ref="1122039499"/>
|
||||||
|
<nd ref="250996321"/>
|
||||||
|
<nd ref="250384969"/>
|
||||||
|
<nd ref="1922091528"/>
|
||||||
|
<nd ref="3128723784"/>
|
||||||
|
<nd ref="1122039521"/>
|
||||||
|
<nd ref="252587568"/>
|
||||||
|
<nd ref="250996316"/>
|
||||||
|
<nd ref="5599384"/>
|
||||||
|
<tag k="highway" v="residential"/>
|
||||||
|
<tag k="lit" v="yes"/>
|
||||||
|
<tag k="maxspeed" v="30"/>
|
||||||
|
<tag k="name" v="Helmholtzstraße"/>
|
||||||
|
<tag k="postal_code" v="01069"/>
|
||||||
|
<tag k="sidewalk" v="both"/>
|
||||||
|
<tag k="smoothness" v="good"/>
|
||||||
|
<tag k="surface" v="asphalt"/>
|
||||||
|
</way>
|
||||||
|
</osm>
|
50
third_party/libosmium/test/include/catch.hpp
vendored
50
third_party/libosmium/test/include/catch.hpp
vendored
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Catch v1.5.6
|
* Catch v1.5.8
|
||||||
* Generated: 2016-06-09 19:20:41.460328
|
* Generated: 2016-10-26 12:07:30.938259
|
||||||
* ----------------------------------------------------------
|
* ----------------------------------------------------------
|
||||||
* This file has been merged from multiple headers. Please don't edit it directly
|
* This file has been merged from multiple headers. Please don't edit it directly
|
||||||
* Copyright (c) 2012 Two Blue Cubes Ltd. All rights reserved.
|
* Copyright (c) 2012 Two Blue Cubes Ltd. All rights reserved.
|
||||||
@ -3223,10 +3223,11 @@ namespace Catch {
|
|||||||
|
|
||||||
bool matches( TestCaseInfo const& testCase ) const {
|
bool matches( TestCaseInfo const& testCase ) const {
|
||||||
// All patterns in a filter must match for the filter to be a match
|
// All patterns in a filter must match for the filter to be a match
|
||||||
for( std::vector<Ptr<Pattern> >::const_iterator it = m_patterns.begin(), itEnd = m_patterns.end(); it != itEnd; ++it )
|
for( std::vector<Ptr<Pattern> >::const_iterator it = m_patterns.begin(), itEnd = m_patterns.end(); it != itEnd; ++it ) {
|
||||||
if( !(*it)->matches( testCase ) )
|
if( !(*it)->matches( testCase ) )
|
||||||
return false;
|
return false;
|
||||||
return true;
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -4719,8 +4720,11 @@ namespace Catch {
|
|||||||
std::string line;
|
std::string line;
|
||||||
while( std::getline( f, line ) ) {
|
while( std::getline( f, line ) ) {
|
||||||
line = trim(line);
|
line = trim(line);
|
||||||
if( !line.empty() && !startsWith( line, "#" ) )
|
if( !line.empty() && !startsWith( line, "#" ) ) {
|
||||||
addTestOrTags( config, "\"" + line + "\"," );
|
if( !startsWith( line, "\"" ) )
|
||||||
|
line = "\"" + line + "\"";
|
||||||
|
addTestOrTags( config, line + "," );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -5368,7 +5372,10 @@ namespace Catch {
|
|||||||
++it ) {
|
++it ) {
|
||||||
matchedTests++;
|
matchedTests++;
|
||||||
TestCaseInfo const& testCaseInfo = it->getTestCaseInfo();
|
TestCaseInfo const& testCaseInfo = it->getTestCaseInfo();
|
||||||
Catch::cout() << testCaseInfo.name << std::endl;
|
if( startsWith( testCaseInfo.name, "#" ) )
|
||||||
|
Catch::cout() << "\"" << testCaseInfo.name << "\"" << std::endl;
|
||||||
|
else
|
||||||
|
Catch::cout() << testCaseInfo.name << std::endl;
|
||||||
}
|
}
|
||||||
return matchedTests;
|
return matchedTests;
|
||||||
}
|
}
|
||||||
@ -6454,7 +6461,7 @@ namespace Catch {
|
|||||||
namespace Catch {
|
namespace Catch {
|
||||||
|
|
||||||
struct RandomNumberGenerator {
|
struct RandomNumberGenerator {
|
||||||
typedef int result_type;
|
typedef std::ptrdiff_t result_type;
|
||||||
|
|
||||||
result_type operator()( result_type n ) const { return std::rand() % n; }
|
result_type operator()( result_type n ) const { return std::rand() % n; }
|
||||||
|
|
||||||
@ -7571,7 +7578,7 @@ namespace Catch {
|
|||||||
return os;
|
return os;
|
||||||
}
|
}
|
||||||
|
|
||||||
Version libraryVersion( 1, 5, 6, "", 0 );
|
Version libraryVersion( 1, 5, 8, "", 0 );
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -7802,8 +7809,11 @@ namespace Catch {
|
|||||||
bool contains( std::string const& s, std::string const& infix ) {
|
bool contains( std::string const& s, std::string const& infix ) {
|
||||||
return s.find( infix ) != std::string::npos;
|
return s.find( infix ) != std::string::npos;
|
||||||
}
|
}
|
||||||
|
char toLowerCh(char c) {
|
||||||
|
return static_cast<char>( ::tolower( c ) );
|
||||||
|
}
|
||||||
void toLowerInPlace( std::string& s ) {
|
void toLowerInPlace( std::string& s ) {
|
||||||
std::transform( s.begin(), s.end(), s.begin(), ::tolower );
|
std::transform( s.begin(), s.end(), s.begin(), toLowerCh );
|
||||||
}
|
}
|
||||||
std::string toLower( std::string const& s ) {
|
std::string toLower( std::string const& s ) {
|
||||||
std::string lc = s;
|
std::string lc = s;
|
||||||
@ -8951,9 +8961,10 @@ namespace Catch {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
// Escape control chars - based on contribution by @espenalb in PR #465
|
// Escape control chars - based on contribution by @espenalb in PR #465 and
|
||||||
|
// by @mrpi PR #588
|
||||||
if ( ( c < '\x09' ) || ( c > '\x0D' && c < '\x20') || c=='\x7F' )
|
if ( ( c < '\x09' ) || ( c > '\x0D' && c < '\x20') || c=='\x7F' )
|
||||||
os << "&#x" << std::uppercase << std::hex << static_cast<int>( c );
|
os << "&#x" << std::uppercase << std::hex << std::setfill('0') << std::setw(2) << static_cast<int>( c ) << ';';
|
||||||
else
|
else
|
||||||
os << c;
|
os << c;
|
||||||
}
|
}
|
||||||
@ -9008,13 +9019,20 @@ namespace Catch {
|
|||||||
: m_tagIsOpen( false ),
|
: m_tagIsOpen( false ),
|
||||||
m_needsNewline( false ),
|
m_needsNewline( false ),
|
||||||
m_os( &Catch::cout() )
|
m_os( &Catch::cout() )
|
||||||
{}
|
{
|
||||||
|
// We encode control characters, which requires
|
||||||
|
// XML 1.1
|
||||||
|
// see http://stackoverflow.com/questions/404107/why-are-control-characters-illegal-in-xml-1-0
|
||||||
|
*m_os << "<?xml version=\"1.1\" encoding=\"UTF-8\"?>\n";
|
||||||
|
}
|
||||||
|
|
||||||
XmlWriter( std::ostream& os )
|
XmlWriter( std::ostream& os )
|
||||||
: m_tagIsOpen( false ),
|
: m_tagIsOpen( false ),
|
||||||
m_needsNewline( false ),
|
m_needsNewline( false ),
|
||||||
m_os( &os )
|
m_os( &os )
|
||||||
{}
|
{
|
||||||
|
*m_os << "<?xml version=\"1.1\" encoding=\"UTF-8\"?>\n";
|
||||||
|
}
|
||||||
|
|
||||||
~XmlWriter() {
|
~XmlWriter() {
|
||||||
while( !m_tags.empty() )
|
while( !m_tags.empty() )
|
||||||
@ -9181,7 +9199,7 @@ namespace Catch {
|
|||||||
|
|
||||||
virtual void testCaseStarting( TestCaseInfo const& testInfo ) CATCH_OVERRIDE {
|
virtual void testCaseStarting( TestCaseInfo const& testInfo ) CATCH_OVERRIDE {
|
||||||
StreamingReporterBase::testCaseStarting(testInfo);
|
StreamingReporterBase::testCaseStarting(testInfo);
|
||||||
m_xml.startElement( "TestCase" ).writeAttribute( "name", trim( testInfo.name ) );
|
m_xml.startElement( "TestCase" ).writeAttribute( "name", testInfo.name );
|
||||||
|
|
||||||
if ( m_config->showDurations() == ShowDurations::Always )
|
if ( m_config->showDurations() == ShowDurations::Always )
|
||||||
m_testCaseTimer.start();
|
m_testCaseTimer.start();
|
||||||
@ -9243,7 +9261,7 @@ namespace Catch {
|
|||||||
.writeText( assertionResult.getMessage() );
|
.writeText( assertionResult.getMessage() );
|
||||||
break;
|
break;
|
||||||
case ResultWas::FatalErrorCondition:
|
case ResultWas::FatalErrorCondition:
|
||||||
m_xml.scopedElement( "Fatal Error Condition" )
|
m_xml.scopedElement( "FatalErrorCondition" )
|
||||||
.writeAttribute( "filename", assertionResult.getSourceInfo().file )
|
.writeAttribute( "filename", assertionResult.getSourceInfo().file )
|
||||||
.writeAttribute( "line", assertionResult.getSourceInfo().line )
|
.writeAttribute( "line", assertionResult.getSourceInfo().line )
|
||||||
.writeText( assertionResult.getMessage() );
|
.writeText( assertionResult.getMessage() );
|
||||||
|
@ -1,32 +0,0 @@
|
|||||||
#include "catch.hpp"
|
|
||||||
|
|
||||||
#include <osmium/osm/entity_bits.hpp>
|
|
||||||
|
|
||||||
TEST_CASE("entity_bits") {
|
|
||||||
|
|
||||||
SECTION("can_be_set_and_checked") {
|
|
||||||
osmium::osm_entity_bits::type entities = osmium::osm_entity_bits::node | osmium::osm_entity_bits::way;
|
|
||||||
REQUIRE(entities == (osmium::osm_entity_bits::node | osmium::osm_entity_bits::way));
|
|
||||||
|
|
||||||
entities |= osmium::osm_entity_bits::relation;
|
|
||||||
REQUIRE((entities & osmium::osm_entity_bits::object));
|
|
||||||
|
|
||||||
entities |= osmium::osm_entity_bits::area;
|
|
||||||
REQUIRE(entities == osmium::osm_entity_bits::object);
|
|
||||||
|
|
||||||
REQUIRE(! (entities & osmium::osm_entity_bits::changeset));
|
|
||||||
|
|
||||||
entities &= osmium::osm_entity_bits::node;
|
|
||||||
REQUIRE((entities & osmium::osm_entity_bits::node));
|
|
||||||
REQUIRE(! (entities & osmium::osm_entity_bits::way));
|
|
||||||
REQUIRE(entities == osmium::osm_entity_bits::node);
|
|
||||||
|
|
||||||
REQUIRE(osmium::osm_entity_bits::nothing == osmium::osm_entity_bits::from_item_type(osmium::item_type::undefined));
|
|
||||||
REQUIRE(osmium::osm_entity_bits::node == osmium::osm_entity_bits::from_item_type(osmium::item_type::node));
|
|
||||||
REQUIRE(osmium::osm_entity_bits::way == osmium::osm_entity_bits::from_item_type(osmium::item_type::way));
|
|
||||||
REQUIRE(osmium::osm_entity_bits::relation == osmium::osm_entity_bits::from_item_type(osmium::item_type::relation));
|
|
||||||
REQUIRE(osmium::osm_entity_bits::changeset == osmium::osm_entity_bits::from_item_type(osmium::item_type::changeset));
|
|
||||||
REQUIRE(osmium::osm_entity_bits::area == osmium::osm_entity_bits::from_item_type(osmium::item_type::area));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
444
third_party/libosmium/test/t/builder/test_object_builder.cpp
vendored
Normal file
444
third_party/libosmium/test/t/builder/test_object_builder.cpp
vendored
Normal file
@ -0,0 +1,444 @@
|
|||||||
|
|
||||||
|
#include "catch.hpp"
|
||||||
|
|
||||||
|
#include <osmium/builder/osm_object_builder.hpp>
|
||||||
|
#include <osmium/memory/buffer.hpp>
|
||||||
|
#include <osmium/osm.hpp>
|
||||||
|
|
||||||
|
TEST_CASE("create objects using builder") {
|
||||||
|
osmium::memory::Buffer buffer{1024*10};
|
||||||
|
std::string user;
|
||||||
|
|
||||||
|
SECTION("complete node with tags") {
|
||||||
|
SECTION("user length 0") {
|
||||||
|
user = "";
|
||||||
|
}
|
||||||
|
SECTION("user length 1") {
|
||||||
|
user = "1";
|
||||||
|
}
|
||||||
|
SECTION("user length 2") {
|
||||||
|
user = "12";
|
||||||
|
}
|
||||||
|
SECTION("user length 3") {
|
||||||
|
user = "123";
|
||||||
|
}
|
||||||
|
SECTION("user length 4") {
|
||||||
|
user = "1234";
|
||||||
|
}
|
||||||
|
SECTION("user length 5") {
|
||||||
|
user = "12345";
|
||||||
|
}
|
||||||
|
SECTION("user length 6") {
|
||||||
|
user = "123456";
|
||||||
|
}
|
||||||
|
SECTION("user length 7") {
|
||||||
|
user = "1234567";
|
||||||
|
}
|
||||||
|
SECTION("user length 8") {
|
||||||
|
user = "12345678";
|
||||||
|
}
|
||||||
|
SECTION("user length 9") {
|
||||||
|
user = "123456789";
|
||||||
|
}
|
||||||
|
SECTION("user length 10") {
|
||||||
|
user = "1234567890";
|
||||||
|
}
|
||||||
|
SECTION("user length 11") {
|
||||||
|
user = "12345678901";
|
||||||
|
}
|
||||||
|
SECTION("user length 12") {
|
||||||
|
user = "123456789012";
|
||||||
|
}
|
||||||
|
SECTION("user length 13") {
|
||||||
|
user = "1234567890123";
|
||||||
|
}
|
||||||
|
SECTION("user length 14") {
|
||||||
|
user = "12345678901234";
|
||||||
|
}
|
||||||
|
SECTION("user length 15") {
|
||||||
|
user = "123456789012345";
|
||||||
|
}
|
||||||
|
SECTION("user length 16") {
|
||||||
|
user = "1234567890123456";
|
||||||
|
}
|
||||||
|
SECTION("user length 17") {
|
||||||
|
user = "12345678901234567";
|
||||||
|
}
|
||||||
|
SECTION("user length 18") {
|
||||||
|
user = "123456789012345678";
|
||||||
|
}
|
||||||
|
|
||||||
|
osmium::Location loc{1.2, 3.4};
|
||||||
|
|
||||||
|
{
|
||||||
|
osmium::builder::NodeBuilder builder{buffer};
|
||||||
|
|
||||||
|
builder.set_id(17)
|
||||||
|
.set_visible(true)
|
||||||
|
.set_version(1)
|
||||||
|
.set_changeset(123)
|
||||||
|
.set_uid(555)
|
||||||
|
.set_timestamp("2015-07-01T00:00:01Z")
|
||||||
|
.set_location(loc)
|
||||||
|
.set_user(user);
|
||||||
|
|
||||||
|
builder.add_tags({{"highway", "primary"}, {"oneway", "yes"}});
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto& node = buffer.get<osmium::Node>(buffer.commit());
|
||||||
|
|
||||||
|
REQUIRE(node.id() == 17);
|
||||||
|
REQUIRE(node.version() == 1);
|
||||||
|
REQUIRE(node.changeset() == 123);
|
||||||
|
REQUIRE(node.uid() == 555);
|
||||||
|
REQUIRE(node.timestamp() == osmium::Timestamp{"2015-07-01T00:00:01Z"});
|
||||||
|
REQUIRE(node.location() == loc);
|
||||||
|
|
||||||
|
REQUIRE(user == node.user());
|
||||||
|
|
||||||
|
REQUIRE(node.tags().size() == 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("complete way with tags") {
|
||||||
|
SECTION("user length 0") {
|
||||||
|
user = "";
|
||||||
|
}
|
||||||
|
SECTION("user length 1") {
|
||||||
|
user = "1";
|
||||||
|
}
|
||||||
|
SECTION("user length 2") {
|
||||||
|
user = "12";
|
||||||
|
}
|
||||||
|
SECTION("user length 3") {
|
||||||
|
user = "123";
|
||||||
|
}
|
||||||
|
SECTION("user length 4") {
|
||||||
|
user = "1234";
|
||||||
|
}
|
||||||
|
SECTION("user length 5") {
|
||||||
|
user = "12345";
|
||||||
|
}
|
||||||
|
SECTION("user length 6") {
|
||||||
|
user = "123456";
|
||||||
|
}
|
||||||
|
SECTION("user length 7") {
|
||||||
|
user = "1234567";
|
||||||
|
}
|
||||||
|
SECTION("user length 8") {
|
||||||
|
user = "12345678";
|
||||||
|
}
|
||||||
|
SECTION("user length 9") {
|
||||||
|
user = "123456789";
|
||||||
|
}
|
||||||
|
SECTION("user length 10") {
|
||||||
|
user = "1234567890";
|
||||||
|
}
|
||||||
|
SECTION("user length 11") {
|
||||||
|
user = "12345678901";
|
||||||
|
}
|
||||||
|
SECTION("user length 12") {
|
||||||
|
user = "123456789012";
|
||||||
|
}
|
||||||
|
SECTION("user length 13") {
|
||||||
|
user = "1234567890123";
|
||||||
|
}
|
||||||
|
SECTION("user length 14") {
|
||||||
|
user = "12345678901234";
|
||||||
|
}
|
||||||
|
SECTION("user length 15") {
|
||||||
|
user = "123456789012345";
|
||||||
|
}
|
||||||
|
SECTION("user length 16") {
|
||||||
|
user = "1234567890123456";
|
||||||
|
}
|
||||||
|
SECTION("user length 17") {
|
||||||
|
user = "12345678901234567";
|
||||||
|
}
|
||||||
|
SECTION("user length 18") {
|
||||||
|
user = "123456789012345678";
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
osmium::builder::WayBuilder builder{buffer};
|
||||||
|
|
||||||
|
builder.set_id(17)
|
||||||
|
.set_visible(true)
|
||||||
|
.set_version(1)
|
||||||
|
.set_changeset(123)
|
||||||
|
.set_uid(555)
|
||||||
|
.set_timestamp("2015-07-01T00:00:01Z")
|
||||||
|
.set_user(user);
|
||||||
|
|
||||||
|
builder.add_tags({{"highway", "primary"}, {"oneway", "yes"}});
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto& way = buffer.get<osmium::Way>(buffer.commit());
|
||||||
|
|
||||||
|
REQUIRE(way.id() == 17);
|
||||||
|
REQUIRE(way.version() == 1);
|
||||||
|
REQUIRE(way.changeset() == 123);
|
||||||
|
REQUIRE(way.uid() == 555);
|
||||||
|
REQUIRE(way.timestamp() == osmium::Timestamp{"2015-07-01T00:00:01Z"});
|
||||||
|
|
||||||
|
REQUIRE(user == way.user());
|
||||||
|
|
||||||
|
REQUIRE(way.tags().size() == 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("complete relation with tags") {
|
||||||
|
SECTION("user length 0") {
|
||||||
|
user = "";
|
||||||
|
}
|
||||||
|
SECTION("user length 1") {
|
||||||
|
user = "1";
|
||||||
|
}
|
||||||
|
SECTION("user length 2") {
|
||||||
|
user = "12";
|
||||||
|
}
|
||||||
|
SECTION("user length 3") {
|
||||||
|
user = "123";
|
||||||
|
}
|
||||||
|
SECTION("user length 4") {
|
||||||
|
user = "1234";
|
||||||
|
}
|
||||||
|
SECTION("user length 5") {
|
||||||
|
user = "12345";
|
||||||
|
}
|
||||||
|
SECTION("user length 6") {
|
||||||
|
user = "123456";
|
||||||
|
}
|
||||||
|
SECTION("user length 7") {
|
||||||
|
user = "1234567";
|
||||||
|
}
|
||||||
|
SECTION("user length 8") {
|
||||||
|
user = "12345678";
|
||||||
|
}
|
||||||
|
SECTION("user length 9") {
|
||||||
|
user = "123456789";
|
||||||
|
}
|
||||||
|
SECTION("user length 10") {
|
||||||
|
user = "1234567890";
|
||||||
|
}
|
||||||
|
SECTION("user length 11") {
|
||||||
|
user = "12345678901";
|
||||||
|
}
|
||||||
|
SECTION("user length 12") {
|
||||||
|
user = "123456789012";
|
||||||
|
}
|
||||||
|
SECTION("user length 13") {
|
||||||
|
user = "1234567890123";
|
||||||
|
}
|
||||||
|
SECTION("user length 14") {
|
||||||
|
user = "12345678901234";
|
||||||
|
}
|
||||||
|
SECTION("user length 15") {
|
||||||
|
user = "123456789012345";
|
||||||
|
}
|
||||||
|
SECTION("user length 16") {
|
||||||
|
user = "1234567890123456";
|
||||||
|
}
|
||||||
|
SECTION("user length 17") {
|
||||||
|
user = "12345678901234567";
|
||||||
|
}
|
||||||
|
SECTION("user length 18") {
|
||||||
|
user = "123456789012345678";
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
osmium::builder::RelationBuilder builder{buffer};
|
||||||
|
|
||||||
|
builder.set_id(17)
|
||||||
|
.set_visible(true)
|
||||||
|
.set_version(1)
|
||||||
|
.set_changeset(123)
|
||||||
|
.set_uid(555)
|
||||||
|
.set_timestamp("2015-07-01T00:00:01Z")
|
||||||
|
.set_user(user);
|
||||||
|
|
||||||
|
builder.add_tags({{"highway", "primary"}, {"oneway", "yes"}});
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto& relation = buffer.get<osmium::Relation>(buffer.commit());
|
||||||
|
|
||||||
|
REQUIRE(relation.id() == 17);
|
||||||
|
REQUIRE(relation.version() == 1);
|
||||||
|
REQUIRE(relation.changeset() == 123);
|
||||||
|
REQUIRE(relation.uid() == 555);
|
||||||
|
REQUIRE(relation.timestamp() == osmium::Timestamp{"2015-07-01T00:00:01Z"});
|
||||||
|
|
||||||
|
REQUIRE(user == relation.user());
|
||||||
|
|
||||||
|
REQUIRE(relation.tags().size() == 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("complete changeset with tags") {
|
||||||
|
osmium::Location bl{-1.2, -3.4};
|
||||||
|
osmium::Location tr{1.2, 3.4};
|
||||||
|
|
||||||
|
SECTION("user length 0") {
|
||||||
|
user = "";
|
||||||
|
}
|
||||||
|
SECTION("user length 1") {
|
||||||
|
user = "1";
|
||||||
|
}
|
||||||
|
SECTION("user length 2") {
|
||||||
|
user = "12";
|
||||||
|
}
|
||||||
|
SECTION("user length 3") {
|
||||||
|
user = "123";
|
||||||
|
}
|
||||||
|
SECTION("user length 4") {
|
||||||
|
user = "1234";
|
||||||
|
}
|
||||||
|
SECTION("user length 5") {
|
||||||
|
user = "12345";
|
||||||
|
}
|
||||||
|
SECTION("user length 6") {
|
||||||
|
user = "123456";
|
||||||
|
}
|
||||||
|
SECTION("user length 7") {
|
||||||
|
user = "1234567";
|
||||||
|
}
|
||||||
|
SECTION("user length 8") {
|
||||||
|
user = "12345678";
|
||||||
|
}
|
||||||
|
SECTION("user length 9") {
|
||||||
|
user = "123456789";
|
||||||
|
}
|
||||||
|
SECTION("user length 10") {
|
||||||
|
user = "1234567890";
|
||||||
|
}
|
||||||
|
SECTION("user length 11") {
|
||||||
|
user = "12345678901";
|
||||||
|
}
|
||||||
|
SECTION("user length 12") {
|
||||||
|
user = "123456789012";
|
||||||
|
}
|
||||||
|
SECTION("user length 13") {
|
||||||
|
user = "1234567890123";
|
||||||
|
}
|
||||||
|
SECTION("user length 14") {
|
||||||
|
user = "12345678901234";
|
||||||
|
}
|
||||||
|
SECTION("user length 15") {
|
||||||
|
user = "123456789012345";
|
||||||
|
}
|
||||||
|
SECTION("user length 16") {
|
||||||
|
user = "1234567890123456";
|
||||||
|
}
|
||||||
|
SECTION("user length 17") {
|
||||||
|
user = "12345678901234567";
|
||||||
|
}
|
||||||
|
SECTION("user length 18") {
|
||||||
|
user = "123456789012345678";
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
osmium::builder::ChangesetBuilder builder{buffer};
|
||||||
|
|
||||||
|
builder.set_id(17)
|
||||||
|
.set_uid(222)
|
||||||
|
.set_created_at(osmium::Timestamp{"2016-07-03T01:23:45Z"})
|
||||||
|
.set_closed_at(osmium::Timestamp{"2016-07-03T01:23:48Z"})
|
||||||
|
.set_num_changes(3)
|
||||||
|
.set_num_comments(2)
|
||||||
|
.set_bounds(osmium::Box{bl, tr})
|
||||||
|
.set_user(user);
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto& changeset = buffer.get<osmium::Changeset>(buffer.commit());
|
||||||
|
|
||||||
|
REQUIRE(changeset.id() == 17);
|
||||||
|
REQUIRE(changeset.uid() == 222);
|
||||||
|
REQUIRE(changeset.created_at() == osmium::Timestamp{"2016-07-03T01:23:45Z"});
|
||||||
|
REQUIRE(changeset.closed_at() == osmium::Timestamp{"2016-07-03T01:23:48Z"});
|
||||||
|
REQUIRE(changeset.num_changes() == 3);
|
||||||
|
REQUIRE(changeset.num_comments() == 2);
|
||||||
|
|
||||||
|
const auto& box = changeset.bounds();
|
||||||
|
REQUIRE(box.bottom_left() == bl);
|
||||||
|
REQUIRE(box.top_right() == tr);
|
||||||
|
|
||||||
|
REQUIRE(user == changeset.user());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("no call to set_user on node") {
|
||||||
|
osmium::memory::Buffer buffer{1024*10};
|
||||||
|
|
||||||
|
{
|
||||||
|
osmium::builder::NodeBuilder builder{buffer};
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto& node = buffer.get<osmium::Node>(buffer.commit());
|
||||||
|
|
||||||
|
REQUIRE(*node.user() == '\0');
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("set_user with length on node") {
|
||||||
|
osmium::memory::Buffer buffer{1024*10};
|
||||||
|
std::string user = "userx";
|
||||||
|
|
||||||
|
{
|
||||||
|
osmium::builder::NodeBuilder builder{buffer};
|
||||||
|
builder.set_user(user.c_str(), 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto& node = buffer.get<osmium::Node>(buffer.commit());
|
||||||
|
|
||||||
|
REQUIRE(std::string{"user"} == node.user());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("no call to set_user on way") {
|
||||||
|
osmium::memory::Buffer buffer{1024*10};
|
||||||
|
|
||||||
|
{
|
||||||
|
osmium::builder::WayBuilder builder{buffer};
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto& way = buffer.get<osmium::Way>(buffer.commit());
|
||||||
|
|
||||||
|
REQUIRE(*way.user() == '\0');
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("set_user with length on way") {
|
||||||
|
osmium::memory::Buffer buffer{1024*10};
|
||||||
|
std::string user = "userx";
|
||||||
|
|
||||||
|
{
|
||||||
|
osmium::builder::WayBuilder builder{buffer};
|
||||||
|
builder.set_user(user.c_str(), 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto& way = buffer.get<osmium::Way>(buffer.commit());
|
||||||
|
|
||||||
|
REQUIRE(std::string{"user"} == way.user());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("no call to set_user on changeset") {
|
||||||
|
osmium::memory::Buffer buffer{1024*10};
|
||||||
|
|
||||||
|
{
|
||||||
|
osmium::builder::ChangesetBuilder builder{buffer};
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto& changeset = buffer.get<osmium::Changeset>(buffer.commit());
|
||||||
|
|
||||||
|
REQUIRE(*changeset.user() == '\0');
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("set_user with length on changeset") {
|
||||||
|
osmium::memory::Buffer buffer{1024*10};
|
||||||
|
std::string user = "userx";
|
||||||
|
|
||||||
|
{
|
||||||
|
osmium::builder::ChangesetBuilder builder{buffer};
|
||||||
|
builder.set_user(user.c_str(), 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto& changeset = buffer.get<osmium::Changeset>(buffer.commit());
|
||||||
|
|
||||||
|
REQUIRE(std::string{"user"} == changeset.user());
|
||||||
|
}
|
||||||
|
|
15
third_party/libosmium/test/t/geom/helper.hpp
vendored
15
third_party/libosmium/test/t/geom/helper.hpp
vendored
@ -1,15 +0,0 @@
|
|||||||
#ifndef TEST_GEOM_HELPER_HPP
|
|
||||||
#define TEST_GEOM_HELPER_HPP
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
#include <geos/io/WKBWriter.h>
|
|
||||||
|
|
||||||
inline std::string geos_to_wkb(const geos::geom::Geometry* geometry) {
|
|
||||||
std::stringstream ss;
|
|
||||||
geos::io::WKBWriter wkb_writer;
|
|
||||||
wkb_writer.writeHEX(*geometry, ss);
|
|
||||||
return ss.str();
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // TEST_GEOM_HELPER_HPP
|
|
10
third_party/libosmium/test/t/geom/test_crs.cpp
vendored
10
third_party/libosmium/test/t/geom/test_crs.cpp
vendored
@ -5,12 +5,12 @@
|
|||||||
#include <osmium/geom/projection.hpp>
|
#include <osmium/geom/projection.hpp>
|
||||||
|
|
||||||
TEST_CASE("CRS") {
|
TEST_CASE("CRS") {
|
||||||
osmium::geom::CRS wgs84{4326};
|
const osmium::geom::CRS wgs84{4326};
|
||||||
osmium::geom::CRS mercator{3857};
|
const osmium::geom::CRS mercator{3857};
|
||||||
|
|
||||||
osmium::geom::Coordinates c{osmium::geom::deg_to_rad(1.2), osmium::geom::deg_to_rad(3.4)};
|
const osmium::geom::Coordinates c{osmium::geom::deg_to_rad(1.2), osmium::geom::deg_to_rad(3.4)};
|
||||||
auto ct = osmium::geom::transform(wgs84, mercator, c);
|
const auto ct = osmium::geom::transform(wgs84, mercator, c);
|
||||||
auto c2 = osmium::geom::transform(mercator, wgs84, ct);
|
const auto c2 = osmium::geom::transform(mercator, wgs84, ct);
|
||||||
|
|
||||||
REQUIRE(c.x == Approx(c2.x));
|
REQUIRE(c.x == Approx(c2.x));
|
||||||
REQUIRE(c.y == Approx(c2.y));
|
REQUIRE(c.y == Approx(c2.y));
|
||||||
|
@ -6,11 +6,9 @@
|
|||||||
|
|
||||||
TEST_CASE("Geometry exception") {
|
TEST_CASE("Geometry exception") {
|
||||||
|
|
||||||
SECTION("geometry_error") {
|
osmium::geometry_error e{"some error message", "node", 17};
|
||||||
osmium::geometry_error e("some error message", "node", 17);
|
REQUIRE(e.id() == 17);
|
||||||
REQUIRE(e.id() == 17);
|
REQUIRE(std::string{e.what()} == "some error message (node_id=17)");
|
||||||
REQUIRE(std::string(e.what()) == "some error message (node_id=17)");
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,41 +1,21 @@
|
|||||||
#include "catch.hpp"
|
#include "catch.hpp"
|
||||||
|
|
||||||
#include <osmium/geom/geos.hpp>
|
|
||||||
#include <osmium/geom/mercator_projection.hpp>
|
#include <osmium/geom/mercator_projection.hpp>
|
||||||
#include <osmium/geom/projection.hpp>
|
#include <osmium/geom/projection.hpp>
|
||||||
#include <osmium/geom/wkb.hpp>
|
#include <osmium/geom/wkb.hpp>
|
||||||
#include <osmium/geom/wkt.hpp>
|
#include <osmium/geom/wkt.hpp>
|
||||||
|
|
||||||
#include "helper.hpp"
|
TEST_CASE("Projection using MercatorProjection class to WKT") {
|
||||||
|
osmium::geom::WKTFactory<osmium::geom::MercatorProjection> factory{2};
|
||||||
TEST_CASE("Projection") {
|
|
||||||
|
|
||||||
SECTION("point_mercator") {
|
|
||||||
osmium::geom::WKTFactory<osmium::geom::MercatorProjection> factory(2);
|
|
||||||
|
|
||||||
std::string wkt {factory.create_point(osmium::Location(3.2, 4.2))};
|
|
||||||
REQUIRE(std::string {"POINT(356222.37 467961.14)"} == wkt);
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("point_epsg_3857") {
|
|
||||||
osmium::geom::WKTFactory<osmium::geom::Projection> factory(osmium::geom::Projection(3857), 2);
|
|
||||||
|
|
||||||
std::string wkt {factory.create_point(osmium::Location(3.2, 4.2))};
|
|
||||||
REQUIRE(std::string {"POINT(356222.37 467961.14)"} == wkt);
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("wkb_with_parameter") {
|
|
||||||
osmium::geom::WKBFactory<osmium::geom::Projection> wkb_factory(osmium::geom::Projection(3857), osmium::geom::wkb_type::wkb, osmium::geom::out_type::hex);
|
|
||||||
osmium::geom::GEOSFactory<osmium::geom::Projection> geos_factory(osmium::geom::Projection(3857));
|
|
||||||
|
|
||||||
std::string wkb = wkb_factory.create_point(osmium::Location(3.2, 4.2));
|
|
||||||
std::unique_ptr<geos::geom::Point> geos_point = geos_factory.create_point(osmium::Location(3.2, 4.2));
|
|
||||||
REQUIRE(geos_to_wkb(geos_point.get()) == wkb);
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("cleanup") {
|
|
||||||
// trying to make valgrind happy, but there is still a memory leak in proj library
|
|
||||||
pj_deallocate_grids();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
const std::string wkt{factory.create_point(osmium::Location{3.2, 4.2})};
|
||||||
|
REQUIRE(wkt == "POINT(356222.37 467961.14)");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE("Projection using Projection class to WKT") {
|
||||||
|
osmium::geom::WKTFactory<osmium::geom::Projection> factory{osmium::geom::Projection{3857}, 2};
|
||||||
|
|
||||||
|
const std::string wkt{factory.create_point(osmium::Location{3.2, 4.2})};
|
||||||
|
REQUIRE(wkt == "POINT(356222.37 467961.14)");
|
||||||
|
}
|
||||||
|
|
||||||
|
203
third_party/libosmium/test/t/geom/test_geojson.cpp
vendored
203
third_party/libosmium/test/t/geom/test_geojson.cpp
vendored
@ -5,162 +5,143 @@
|
|||||||
#include "area_helper.hpp"
|
#include "area_helper.hpp"
|
||||||
#include "wnl_helper.hpp"
|
#include "wnl_helper.hpp"
|
||||||
|
|
||||||
TEST_CASE("GeoJSON_Geometry") {
|
TEST_CASE("GeoJSON point geometry") {
|
||||||
|
|
||||||
SECTION("point") {
|
|
||||||
osmium::geom::GeoJSONFactory<> factory;
|
osmium::geom::GeoJSONFactory<> factory;
|
||||||
|
|
||||||
std::string json {factory.create_point(osmium::Location(3.2, 4.2))};
|
SECTION("point") {
|
||||||
REQUIRE(std::string{"{\"type\":\"Point\",\"coordinates\":[3.2,4.2]}"} == json);
|
const std::string json{factory.create_point(osmium::Location{3.2, 4.2})};
|
||||||
|
REQUIRE(std::string{"{\"type\":\"Point\",\"coordinates\":[3.2,4.2]}"} == json);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("empty_point") {
|
||||||
|
REQUIRE_THROWS_AS(factory.create_point(osmium::Location{}), osmium::invalid_location);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("empty_point") {
|
TEST_CASE("GeoJSON linestring geometry") {
|
||||||
osmium::geom::GeoJSONFactory<> factory;
|
osmium::geom::GeoJSONFactory<> factory;
|
||||||
|
osmium::memory::Buffer buffer{1000};
|
||||||
|
|
||||||
REQUIRE_THROWS_AS(factory.create_point(osmium::Location()), osmium::invalid_location);
|
SECTION("linestring, default") {
|
||||||
}
|
const auto& wnl = create_test_wnl_okay(buffer);
|
||||||
|
const std::string json{factory.create_linestring(wnl)};
|
||||||
SECTION("linestring") {
|
|
||||||
osmium::geom::GeoJSONFactory<> factory;
|
|
||||||
|
|
||||||
osmium::memory::Buffer buffer(1000);
|
|
||||||
auto &wnl = create_test_wnl_okay(buffer);
|
|
||||||
|
|
||||||
{
|
|
||||||
std::string json {factory.create_linestring(wnl)};
|
|
||||||
REQUIRE(std::string{"{\"type\":\"LineString\",\"coordinates\":[[3.2,4.2],[3.5,4.7],[3.6,4.9]]}"} == json);
|
REQUIRE(std::string{"{\"type\":\"LineString\",\"coordinates\":[[3.2,4.2],[3.5,4.7],[3.6,4.9]]}"} == json);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
SECTION("linestring, unique, backwards") {
|
||||||
std::string json {factory.create_linestring(wnl, osmium::geom::use_nodes::unique, osmium::geom::direction::backward)};
|
const auto& wnl = create_test_wnl_okay(buffer);
|
||||||
|
const std::string json{factory.create_linestring(wnl, osmium::geom::use_nodes::unique, osmium::geom::direction::backward)};
|
||||||
REQUIRE(std::string{"{\"type\":\"LineString\",\"coordinates\":[[3.6,4.9],[3.5,4.7],[3.2,4.2]]}"} == json);
|
REQUIRE(std::string{"{\"type\":\"LineString\",\"coordinates\":[[3.6,4.9],[3.5,4.7],[3.2,4.2]]}"} == json);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
SECTION("linestring, all") {
|
||||||
std::string json {factory.create_linestring(wnl, osmium::geom::use_nodes::all)};
|
const auto& wnl = create_test_wnl_okay(buffer);
|
||||||
|
const std::string json{factory.create_linestring(wnl, osmium::geom::use_nodes::all)};
|
||||||
REQUIRE(std::string{"{\"type\":\"LineString\",\"coordinates\":[[3.2,4.2],[3.5,4.7],[3.5,4.7],[3.6,4.9]]}"} == json);
|
REQUIRE(std::string{"{\"type\":\"LineString\",\"coordinates\":[[3.2,4.2],[3.5,4.7],[3.5,4.7],[3.6,4.9]]}"} == json);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
SECTION("linestring, all, backwards") {
|
||||||
std::string json {factory.create_linestring(wnl, osmium::geom::use_nodes::all, osmium::geom::direction::backward)};
|
const auto& wnl = create_test_wnl_okay(buffer);
|
||||||
|
const std::string json{factory.create_linestring(wnl, osmium::geom::use_nodes::all, osmium::geom::direction::backward)};
|
||||||
REQUIRE(std::string{"{\"type\":\"LineString\",\"coordinates\":[[3.6,4.9],[3.5,4.7],[3.5,4.7],[3.2,4.2]]}"} == json);
|
REQUIRE(std::string{"{\"type\":\"LineString\",\"coordinates\":[[3.6,4.9],[3.5,4.7],[3.5,4.7],[3.2,4.2]]}"} == json);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("empty_linestring") {
|
SECTION("empty_linestring") {
|
||||||
osmium::geom::GeoJSONFactory<> factory;
|
const auto& wnl = create_test_wnl_empty(buffer);
|
||||||
|
|
||||||
osmium::memory::Buffer buffer(1000);
|
REQUIRE_THROWS_AS(factory.create_linestring(wnl), osmium::geometry_error);
|
||||||
auto& wnl = create_test_wnl_empty(buffer);
|
REQUIRE_THROWS_AS(factory.create_linestring(wnl, osmium::geom::use_nodes::unique, osmium::geom::direction::backward), osmium::geometry_error);
|
||||||
|
REQUIRE_THROWS_AS(factory.create_linestring(wnl, osmium::geom::use_nodes::all), osmium::geometry_error);
|
||||||
REQUIRE_THROWS_AS(factory.create_linestring(wnl), osmium::geometry_error);
|
REQUIRE_THROWS_AS(factory.create_linestring(wnl, osmium::geom::use_nodes::all, osmium::geom::direction::backward), osmium::geometry_error);
|
||||||
REQUIRE_THROWS_AS(factory.create_linestring(wnl, osmium::geom::use_nodes::unique, osmium::geom::direction::backward), osmium::geometry_error);
|
|
||||||
REQUIRE_THROWS_AS(factory.create_linestring(wnl, osmium::geom::use_nodes::all), osmium::geometry_error);
|
|
||||||
REQUIRE_THROWS_AS(factory.create_linestring(wnl, osmium::geom::use_nodes::all, osmium::geom::direction::backward), osmium::geometry_error);
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("linestring_with_two_same_locations") {
|
|
||||||
osmium::geom::GeoJSONFactory<> factory;
|
|
||||||
|
|
||||||
osmium::memory::Buffer buffer(1000);
|
|
||||||
auto& wnl = create_test_wnl_same_location(buffer);
|
|
||||||
|
|
||||||
REQUIRE_THROWS_AS(factory.create_linestring(wnl), osmium::geometry_error);
|
|
||||||
REQUIRE_THROWS_AS(factory.create_linestring(wnl, osmium::geom::use_nodes::unique, osmium::geom::direction::backward), osmium::geometry_error);
|
|
||||||
|
|
||||||
{
|
|
||||||
std::string json {factory.create_linestring(wnl, osmium::geom::use_nodes::all)};
|
|
||||||
REQUIRE(std::string{"{\"type\":\"LineString\",\"coordinates\":[[3.5,4.7],[3.5,4.7]]}"} == json);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
SECTION("linestring with two same locations") {
|
||||||
std::string json {factory.create_linestring(wnl, osmium::geom::use_nodes::all, osmium::geom::direction::backward)};
|
const auto& wnl = create_test_wnl_same_location(buffer);
|
||||||
REQUIRE(std::string{"{\"type\":\"LineString\",\"coordinates\":[[3.5,4.7],[3.5,4.7]]}"} == json);
|
|
||||||
|
REQUIRE_THROWS_AS(factory.create_linestring(wnl), osmium::geometry_error);
|
||||||
|
REQUIRE_THROWS_AS(factory.create_linestring(wnl, osmium::geom::use_nodes::unique, osmium::geom::direction::backward), osmium::geometry_error);
|
||||||
|
|
||||||
|
{
|
||||||
|
const std::string json{factory.create_linestring(wnl, osmium::geom::use_nodes::all)};
|
||||||
|
REQUIRE(std::string{"{\"type\":\"LineString\",\"coordinates\":[[3.5,4.7],[3.5,4.7]]}"} == json);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
const std::string json{factory.create_linestring(wnl, osmium::geom::use_nodes::all, osmium::geom::direction::backward)};
|
||||||
|
REQUIRE(std::string{"{\"type\":\"LineString\",\"coordinates\":[[3.5,4.7],[3.5,4.7]]}"} == json);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SECTION("linestring with undefined location") {
|
||||||
|
const auto& wnl = create_test_wnl_undefined_location(buffer);
|
||||||
|
REQUIRE_THROWS_AS(factory.create_linestring(wnl), osmium::invalid_location);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("linestring_with_undefined_location") {
|
TEST_CASE("GeoJSON area geometry") {
|
||||||
osmium::geom::GeoJSONFactory<> factory;
|
osmium::geom::GeoJSONFactory<> factory;
|
||||||
|
osmium::memory::Buffer buffer{1000};
|
||||||
|
|
||||||
osmium::memory::Buffer buffer(1000);
|
SECTION("area_1outer_0inner") {
|
||||||
auto& wnl = create_test_wnl_undefined_location(buffer);
|
const osmium::Area& area = create_test_area_1outer_0inner(buffer);
|
||||||
|
|
||||||
REQUIRE_THROWS_AS(factory.create_linestring(wnl), osmium::invalid_location);
|
REQUIRE(!area.is_multipolygon());
|
||||||
}
|
REQUIRE(std::distance(area.cbegin(), area.cend()) == 2);
|
||||||
|
REQUIRE(area.subitems<osmium::OuterRing>().size() == area.num_rings().first);
|
||||||
|
|
||||||
SECTION("area_1outer_0inner") {
|
std::string json{factory.create_multipolygon(area)};
|
||||||
osmium::geom::GeoJSONFactory<> factory;
|
|
||||||
|
|
||||||
osmium::memory::Buffer buffer(1000);
|
|
||||||
const osmium::Area& area = create_test_area_1outer_0inner(buffer);
|
|
||||||
|
|
||||||
REQUIRE(!area.is_multipolygon());
|
|
||||||
REQUIRE(std::distance(area.cbegin(), area.cend()) == 2);
|
|
||||||
REQUIRE(area.subitems<osmium::OuterRing>().size() == area.num_rings().first);
|
|
||||||
|
|
||||||
{
|
|
||||||
std::string json {factory.create_multipolygon(area)};
|
|
||||||
REQUIRE(std::string{"{\"type\":\"MultiPolygon\",\"coordinates\":[[[[3.2,4.2],[3.5,4.7],[3.6,4.9],[3.2,4.2]]]]}"} == json);
|
REQUIRE(std::string{"{\"type\":\"MultiPolygon\",\"coordinates\":[[[[3.2,4.2],[3.5,4.7],[3.6,4.9],[3.2,4.2]]]]}"} == json);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("area_1outer_1inner") {
|
SECTION("area_1outer_1inner") {
|
||||||
osmium::geom::GeoJSONFactory<> factory;
|
const osmium::Area& area = create_test_area_1outer_1inner(buffer);
|
||||||
|
|
||||||
osmium::memory::Buffer buffer(1000);
|
REQUIRE(!area.is_multipolygon());
|
||||||
const osmium::Area& area = create_test_area_1outer_1inner(buffer);
|
REQUIRE(std::distance(area.cbegin(), area.cend()) == 3);
|
||||||
|
REQUIRE(area.subitems<osmium::OuterRing>().size() == area.num_rings().first);
|
||||||
|
REQUIRE(area.subitems<osmium::InnerRing>().size() == area.num_rings().second);
|
||||||
|
|
||||||
REQUIRE(!area.is_multipolygon());
|
std::string json{factory.create_multipolygon(area)};
|
||||||
REQUIRE(std::distance(area.cbegin(), area.cend()) == 3);
|
|
||||||
REQUIRE(area.subitems<osmium::OuterRing>().size() == area.num_rings().first);
|
|
||||||
REQUIRE(area.subitems<osmium::InnerRing>().size() == area.num_rings().second);
|
|
||||||
|
|
||||||
{
|
|
||||||
std::string json {factory.create_multipolygon(area)};
|
|
||||||
REQUIRE(std::string{"{\"type\":\"MultiPolygon\",\"coordinates\":[[[[0.1,0.1],[9.1,0.1],[9.1,9.1],[0.1,9.1],[0.1,0.1]],[[1,1],[8,1],[8,8],[1,8],[1,1]]]]}"} == json);
|
REQUIRE(std::string{"{\"type\":\"MultiPolygon\",\"coordinates\":[[[[0.1,0.1],[9.1,0.1],[9.1,9.1],[0.1,9.1],[0.1,0.1]],[[1,1],[8,1],[8,8],[1,8],[1,1]]]]}"} == json);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("area_2outer_2inner") {
|
SECTION("area_2outer_2inner") {
|
||||||
osmium::geom::GeoJSONFactory<> factory;
|
const osmium::Area& area = create_test_area_2outer_2inner(buffer);
|
||||||
|
|
||||||
osmium::memory::Buffer buffer(1000);
|
REQUIRE(area.is_multipolygon());
|
||||||
const osmium::Area& area = create_test_area_2outer_2inner(buffer);
|
REQUIRE(std::distance(area.cbegin(), area.cend()) == 5);
|
||||||
|
REQUIRE(area.subitems<osmium::OuterRing>().size() == area.num_rings().first);
|
||||||
|
REQUIRE(area.subitems<osmium::InnerRing>().size() == area.num_rings().second);
|
||||||
|
|
||||||
REQUIRE(area.is_multipolygon());
|
int outer_ring=0;
|
||||||
REQUIRE(std::distance(area.cbegin(), area.cend()) == 5);
|
int inner_ring=0;
|
||||||
REQUIRE(area.subitems<osmium::OuterRing>().size() == area.num_rings().first);
|
for (const auto& outer : area.outer_rings()) {
|
||||||
REQUIRE(area.subitems<osmium::InnerRing>().size() == area.num_rings().second);
|
if (outer_ring == 0) {
|
||||||
|
REQUIRE(outer.front().ref() == 1);
|
||||||
int outer_ring=0;
|
} else if (outer_ring == 1) {
|
||||||
int inner_ring=0;
|
REQUIRE(outer.front().ref() == 100);
|
||||||
for (const auto& outer : area.outer_rings()) {
|
|
||||||
if (outer_ring == 0) {
|
|
||||||
REQUIRE(outer.front().ref() == 1);
|
|
||||||
} else if (outer_ring == 1) {
|
|
||||||
REQUIRE(outer.front().ref() == 100);
|
|
||||||
} else {
|
|
||||||
REQUIRE(false);
|
|
||||||
}
|
|
||||||
for (const auto& inner : area.inner_rings(outer)) {
|
|
||||||
if (outer_ring == 0 && inner_ring == 0) {
|
|
||||||
REQUIRE(inner.front().ref() == 5);
|
|
||||||
} else if (outer_ring == 0 && inner_ring == 1) {
|
|
||||||
REQUIRE(inner.front().ref() == 10);
|
|
||||||
} else {
|
} else {
|
||||||
REQUIRE(false);
|
REQUIRE(false);
|
||||||
}
|
}
|
||||||
++inner_ring;
|
for (const auto& inner : area.inner_rings(outer)) {
|
||||||
|
if (outer_ring == 0 && inner_ring == 0) {
|
||||||
|
REQUIRE(inner.front().ref() == 5);
|
||||||
|
} else if (outer_ring == 0 && inner_ring == 1) {
|
||||||
|
REQUIRE(inner.front().ref() == 10);
|
||||||
|
} else {
|
||||||
|
REQUIRE(false);
|
||||||
|
}
|
||||||
|
++inner_ring;
|
||||||
|
}
|
||||||
|
inner_ring = 0;
|
||||||
|
++outer_ring;
|
||||||
}
|
}
|
||||||
inner_ring = 0;
|
|
||||||
++outer_ring;
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
std::string json{factory.create_multipolygon(area)};
|
||||||
std::string json {factory.create_multipolygon(area)};
|
|
||||||
REQUIRE(std::string{"{\"type\":\"MultiPolygon\",\"coordinates\":[[[[0.1,0.1],[9.1,0.1],[9.1,9.1],[0.1,9.1],[0.1,0.1]],[[1,1],[4,1],[4,4],[1,4],[1,1]],[[5,5],[5,7],[7,7],[5,5]]],[[[10,10],[11,10],[11,11],[10,11],[10,10]]]]}"} == json);
|
REQUIRE(std::string{"{\"type\":\"MultiPolygon\",\"coordinates\":[[[[0.1,0.1],[9.1,0.1],[9.1,9.1],[0.1,9.1],[0.1,0.1]],[[1,1],[4,1],[4,4],[1,4],[1,1]],[[5,5],[5,7],[7,7],[5,5]]],[[[10,10],[11,10],[11,11],[10,11],[10,10]]]]}"} == json);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
56
third_party/libosmium/test/t/geom/test_geos.cpp
vendored
56
third_party/libosmium/test/t/geom/test_geos.cpp
vendored
@ -1,6 +1,10 @@
|
|||||||
#include "catch.hpp"
|
|
||||||
|
|
||||||
#include <osmium/geom/geos.hpp>
|
#include <osmium/geom/geos.hpp>
|
||||||
|
|
||||||
|
#ifdef OSMIUM_WITH_GEOS
|
||||||
|
|
||||||
|
#include "catch.hpp"
|
||||||
|
|
||||||
#include <osmium/geom/mercator_projection.hpp>
|
#include <osmium/geom/mercator_projection.hpp>
|
||||||
|
|
||||||
#include "area_helper.hpp"
|
#include "area_helper.hpp"
|
||||||
@ -9,7 +13,7 @@
|
|||||||
TEST_CASE("GEOS geometry factory - create point") {
|
TEST_CASE("GEOS geometry factory - create point") {
|
||||||
osmium::geom::GEOSFactory<> factory;
|
osmium::geom::GEOSFactory<> factory;
|
||||||
|
|
||||||
std::unique_ptr<geos::geom::Point> point {factory.create_point(osmium::Location(3.2, 4.2))};
|
const std::unique_ptr<geos::geom::Point> point{factory.create_point(osmium::Location{3.2, 4.2})};
|
||||||
REQUIRE(3.2 == point->getX());
|
REQUIRE(3.2 == point->getX());
|
||||||
REQUIRE(4.2 == point->getY());
|
REQUIRE(4.2 == point->getY());
|
||||||
REQUIRE(4326 == point->getSRID());
|
REQUIRE(4326 == point->getSRID());
|
||||||
@ -18,7 +22,7 @@ TEST_CASE("GEOS geometry factory - create point") {
|
|||||||
TEST_CASE("GEOS geometry factory - create point in web mercator") {
|
TEST_CASE("GEOS geometry factory - create point in web mercator") {
|
||||||
osmium::geom::GEOSFactory<osmium::geom::MercatorProjection> factory;
|
osmium::geom::GEOSFactory<osmium::geom::MercatorProjection> factory;
|
||||||
|
|
||||||
std::unique_ptr<geos::geom::Point> point {factory.create_point(osmium::Location(3.2, 4.2))};
|
const std::unique_ptr<geos::geom::Point> point{factory.create_point(osmium::Location{3.2, 4.2})};
|
||||||
REQUIRE(Approx(356222.3705384755l) == point->getX());
|
REQUIRE(Approx(356222.3705384755l) == point->getX());
|
||||||
REQUIRE(Approx(467961.143605213l) == point->getY());
|
REQUIRE(Approx(467961.143605213l) == point->getY());
|
||||||
REQUIRE(3857 == point->getSRID());
|
REQUIRE(3857 == point->getSRID());
|
||||||
@ -26,9 +30,9 @@ TEST_CASE("GEOS geometry factory - create point in web mercator") {
|
|||||||
|
|
||||||
TEST_CASE("GEOS geometry factory - create point with externally created GEOS factory") {
|
TEST_CASE("GEOS geometry factory - create point with externally created GEOS factory") {
|
||||||
geos::geom::GeometryFactory geos_factory;
|
geos::geom::GeometryFactory geos_factory;
|
||||||
osmium::geom::GEOSFactory<> factory(geos_factory);
|
osmium::geom::GEOSFactory<> factory{geos_factory};
|
||||||
|
|
||||||
std::unique_ptr<geos::geom::Point> point {factory.create_point(osmium::Location(3.2, 4.2))};
|
const std::unique_ptr<geos::geom::Point> point{factory.create_point(osmium::Location{3.2, 4.2})};
|
||||||
REQUIRE(3.2 == point->getX());
|
REQUIRE(3.2 == point->getX());
|
||||||
REQUIRE(4.2 == point->getY());
|
REQUIRE(4.2 == point->getY());
|
||||||
REQUIRE(0 == point->getSRID());
|
REQUIRE(0 == point->getSRID());
|
||||||
@ -37,45 +41,45 @@ TEST_CASE("GEOS geometry factory - create point with externally created GEOS fac
|
|||||||
TEST_CASE("GEOS geometry factory - can not create from invalid location") {
|
TEST_CASE("GEOS geometry factory - can not create from invalid location") {
|
||||||
osmium::geom::GEOSFactory<> factory;
|
osmium::geom::GEOSFactory<> factory;
|
||||||
|
|
||||||
REQUIRE_THROWS_AS(factory.create_point(osmium::Location()), osmium::invalid_location);
|
REQUIRE_THROWS_AS(factory.create_point(osmium::Location{}), osmium::invalid_location);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("GEOS geometry factory - create linestring") {
|
TEST_CASE("GEOS geometry factory - create linestring") {
|
||||||
osmium::geom::GEOSFactory<> factory;
|
osmium::geom::GEOSFactory<> factory;
|
||||||
|
|
||||||
osmium::memory::Buffer buffer(10000);
|
osmium::memory::Buffer buffer{10000};
|
||||||
auto &wnl = create_test_wnl_okay(buffer);
|
const auto& wnl = create_test_wnl_okay(buffer);
|
||||||
|
|
||||||
SECTION("from way node list") {
|
SECTION("from way node list") {
|
||||||
std::unique_ptr<geos::geom::LineString> linestring {factory.create_linestring(wnl)};
|
const std::unique_ptr<geos::geom::LineString> linestring{factory.create_linestring(wnl)};
|
||||||
REQUIRE(3 == linestring->getNumPoints());
|
REQUIRE(3 == linestring->getNumPoints());
|
||||||
|
|
||||||
std::unique_ptr<geos::geom::Point> p0 = std::unique_ptr<geos::geom::Point>(linestring->getPointN(0));
|
const auto p0 = std::unique_ptr<geos::geom::Point>(linestring->getPointN(0));
|
||||||
REQUIRE(3.2 == p0->getX());
|
REQUIRE(3.2 == p0->getX());
|
||||||
std::unique_ptr<geos::geom::Point> p2 = std::unique_ptr<geos::geom::Point>(linestring->getPointN(2));
|
const auto p2 = std::unique_ptr<geos::geom::Point>(linestring->getPointN(2));
|
||||||
REQUIRE(3.6 == p2->getX());
|
REQUIRE(3.6 == p2->getX());
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("without duplicates and backwards") {
|
SECTION("without duplicates and backwards") {
|
||||||
std::unique_ptr<geos::geom::LineString> linestring {factory.create_linestring(wnl, osmium::geom::use_nodes::unique, osmium::geom::direction::backward)};
|
const std::unique_ptr<geos::geom::LineString> linestring{factory.create_linestring(wnl, osmium::geom::use_nodes::unique, osmium::geom::direction::backward)};
|
||||||
REQUIRE(3 == linestring->getNumPoints());
|
REQUIRE(3 == linestring->getNumPoints());
|
||||||
std::unique_ptr<geos::geom::Point> p0 = std::unique_ptr<geos::geom::Point>(linestring->getPointN(0));
|
const auto p0 = std::unique_ptr<geos::geom::Point>(linestring->getPointN(0));
|
||||||
REQUIRE(3.6 == p0->getX());
|
REQUIRE(3.6 == p0->getX());
|
||||||
std::unique_ptr<geos::geom::Point> p2 = std::unique_ptr<geos::geom::Point>(linestring->getPointN(2));
|
const auto p2 = std::unique_ptr<geos::geom::Point>(linestring->getPointN(2));
|
||||||
REQUIRE(3.2 == p2->getX());
|
REQUIRE(3.2 == p2->getX());
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("with duplicates") {
|
SECTION("with duplicates") {
|
||||||
std::unique_ptr<geos::geom::LineString> linestring {factory.create_linestring(wnl, osmium::geom::use_nodes::all)};
|
const std::unique_ptr<geos::geom::LineString> linestring{factory.create_linestring(wnl, osmium::geom::use_nodes::all)};
|
||||||
REQUIRE(4 == linestring->getNumPoints());
|
REQUIRE(4 == linestring->getNumPoints());
|
||||||
std::unique_ptr<geos::geom::Point> p0 = std::unique_ptr<geos::geom::Point>(linestring->getPointN(0));
|
const auto p0 = std::unique_ptr<geos::geom::Point>(linestring->getPointN(0));
|
||||||
REQUIRE(3.2 == p0->getX());
|
REQUIRE(3.2 == p0->getX());
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("with duplicates and backwards") {
|
SECTION("with duplicates and backwards") {
|
||||||
std::unique_ptr<geos::geom::LineString> linestring {factory.create_linestring(wnl, osmium::geom::use_nodes::all, osmium::geom::direction::backward)};
|
const std::unique_ptr<geos::geom::LineString> linestring{factory.create_linestring(wnl, osmium::geom::use_nodes::all, osmium::geom::direction::backward)};
|
||||||
REQUIRE(4 == linestring->getNumPoints());
|
REQUIRE(4 == linestring->getNumPoints());
|
||||||
std::unique_ptr<geos::geom::Point> p0 = std::unique_ptr<geos::geom::Point>(linestring->getPointN(0));
|
const auto p0 = std::unique_ptr<geos::geom::Point>(linestring->getPointN(0));
|
||||||
REQUIRE(3.6 == p0->getX());
|
REQUIRE(3.6 == p0->getX());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -83,10 +87,10 @@ TEST_CASE("GEOS geometry factory - create linestring") {
|
|||||||
TEST_CASE("GEOS geometry factory - create area with one outer and no inner rings") {
|
TEST_CASE("GEOS geometry factory - create area with one outer and no inner rings") {
|
||||||
osmium::geom::GEOSFactory<> factory;
|
osmium::geom::GEOSFactory<> factory;
|
||||||
|
|
||||||
osmium::memory::Buffer buffer(10000);
|
osmium::memory::Buffer buffer{10000};
|
||||||
const osmium::Area& area = create_test_area_1outer_0inner(buffer);
|
const osmium::Area& area = create_test_area_1outer_0inner(buffer);
|
||||||
|
|
||||||
std::unique_ptr<geos::geom::MultiPolygon> mp {factory.create_multipolygon(area)};
|
const std::unique_ptr<geos::geom::MultiPolygon> mp{factory.create_multipolygon(area)};
|
||||||
REQUIRE(1 == mp->getNumGeometries());
|
REQUIRE(1 == mp->getNumGeometries());
|
||||||
|
|
||||||
const geos::geom::Polygon* p0 = dynamic_cast<const geos::geom::Polygon*>(mp->getGeometryN(0));
|
const geos::geom::Polygon* p0 = dynamic_cast<const geos::geom::Polygon*>(mp->getGeometryN(0));
|
||||||
@ -96,17 +100,17 @@ TEST_CASE("GEOS geometry factory - create area with one outer and no inner rings
|
|||||||
const geos::geom::LineString* l0e = p0->getExteriorRing();
|
const geos::geom::LineString* l0e = p0->getExteriorRing();
|
||||||
REQUIRE(4 == l0e->getNumPoints());
|
REQUIRE(4 == l0e->getNumPoints());
|
||||||
|
|
||||||
std::unique_ptr<geos::geom::Point> l0e_p0 = std::unique_ptr<geos::geom::Point>(l0e->getPointN(1));
|
const auto l0e_p0 = std::unique_ptr<geos::geom::Point>(l0e->getPointN(1));
|
||||||
REQUIRE(3.5 == l0e_p0->getX());
|
REQUIRE(3.5 == l0e_p0->getX());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("GEOS geometry factory - create area with one outer and one inner ring") {
|
TEST_CASE("GEOS geometry factory - create area with one outer and one inner ring") {
|
||||||
osmium::geom::GEOSFactory<> factory;
|
osmium::geom::GEOSFactory<> factory;
|
||||||
|
|
||||||
osmium::memory::Buffer buffer(10000);
|
osmium::memory::Buffer buffer{10000};
|
||||||
const osmium::Area& area = create_test_area_1outer_1inner(buffer);
|
const osmium::Area& area = create_test_area_1outer_1inner(buffer);
|
||||||
|
|
||||||
std::unique_ptr<geos::geom::MultiPolygon> mp {factory.create_multipolygon(area)};
|
const std::unique_ptr<geos::geom::MultiPolygon> mp{factory.create_multipolygon(area)};
|
||||||
REQUIRE(1 == mp->getNumGeometries());
|
REQUIRE(1 == mp->getNumGeometries());
|
||||||
|
|
||||||
const geos::geom::Polygon* p0 = dynamic_cast<const geos::geom::Polygon*>(mp->getGeometryN(0));
|
const geos::geom::Polygon* p0 = dynamic_cast<const geos::geom::Polygon*>(mp->getGeometryN(0));
|
||||||
@ -123,10 +127,10 @@ TEST_CASE("GEOS geometry factory - create area with one outer and one inner ring
|
|||||||
TEST_CASE("GEOS geometry factory - create area with two outer and two inner rings") {
|
TEST_CASE("GEOS geometry factory - create area with two outer and two inner rings") {
|
||||||
osmium::geom::GEOSFactory<> factory;
|
osmium::geom::GEOSFactory<> factory;
|
||||||
|
|
||||||
osmium::memory::Buffer buffer(10000);
|
osmium::memory::Buffer buffer{10000};
|
||||||
const osmium::Area& area = create_test_area_2outer_2inner(buffer);
|
const osmium::Area& area = create_test_area_2outer_2inner(buffer);
|
||||||
|
|
||||||
std::unique_ptr<geos::geom::MultiPolygon> mp {factory.create_multipolygon(area)};
|
const std::unique_ptr<geos::geom::MultiPolygon> mp{factory.create_multipolygon(area)};
|
||||||
REQUIRE(2 == mp->getNumGeometries());
|
REQUIRE(2 == mp->getNumGeometries());
|
||||||
|
|
||||||
const geos::geom::Polygon* p0 = dynamic_cast<const geos::geom::Polygon*>(mp->getGeometryN(0));
|
const geos::geom::Polygon* p0 = dynamic_cast<const geos::geom::Polygon*>(mp->getGeometryN(0));
|
||||||
@ -144,3 +148,5 @@ TEST_CASE("GEOS geometry factory - create area with two outer and two inner ring
|
|||||||
REQUIRE(5 == l1e->getNumPoints());
|
REQUIRE(5 == l1e->getNumPoints());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
@ -1,92 +0,0 @@
|
|||||||
#include "catch.hpp"
|
|
||||||
|
|
||||||
#include <osmium/geom/geos.hpp>
|
|
||||||
#include <osmium/geom/wkb.hpp>
|
|
||||||
|
|
||||||
#include "helper.hpp"
|
|
||||||
#include "area_helper.hpp"
|
|
||||||
#include "wnl_helper.hpp"
|
|
||||||
|
|
||||||
TEST_CASE("WKB_Geometry_with_GEOS") {
|
|
||||||
|
|
||||||
SECTION("point") {
|
|
||||||
osmium::geom::WKBFactory<> wkb_factory(osmium::geom::wkb_type::wkb, osmium::geom::out_type::hex);
|
|
||||||
osmium::geom::GEOSFactory<> geos_factory;
|
|
||||||
|
|
||||||
std::string wkb {wkb_factory.create_point(osmium::Location(3.2, 4.2))};
|
|
||||||
|
|
||||||
std::unique_ptr<geos::geom::Point> geos_point = geos_factory.create_point(osmium::Location(3.2, 4.2));
|
|
||||||
REQUIRE(geos_to_wkb(geos_point.get()) == wkb);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
SECTION("linestring") {
|
|
||||||
osmium::geom::WKBFactory<> wkb_factory(osmium::geom::wkb_type::wkb, osmium::geom::out_type::hex);
|
|
||||||
osmium::geom::GEOSFactory<> geos_factory;
|
|
||||||
|
|
||||||
osmium::memory::Buffer buffer(10000);
|
|
||||||
auto &wnl = create_test_wnl_okay(buffer);
|
|
||||||
|
|
||||||
{
|
|
||||||
std::string wkb = wkb_factory.create_linestring(wnl);
|
|
||||||
std::unique_ptr<geos::geom::LineString> geos = geos_factory.create_linestring(wnl);
|
|
||||||
REQUIRE(geos_to_wkb(geos.get()) == wkb);
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
std::string wkb = wkb_factory.create_linestring(wnl, osmium::geom::use_nodes::unique, osmium::geom::direction::backward);
|
|
||||||
std::unique_ptr<geos::geom::LineString> geos = geos_factory.create_linestring(wnl, osmium::geom::use_nodes::unique, osmium::geom::direction::backward);
|
|
||||||
REQUIRE(geos_to_wkb(geos.get()) == wkb);
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
std::string wkb = wkb_factory.create_linestring(wnl, osmium::geom::use_nodes::all);
|
|
||||||
std::unique_ptr<geos::geom::LineString> geos = geos_factory.create_linestring(wnl, osmium::geom::use_nodes::all);
|
|
||||||
REQUIRE(geos_to_wkb(geos.get()) == wkb);
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
std::string wkb = wkb_factory.create_linestring(wnl, osmium::geom::use_nodes::all, osmium::geom::direction::backward);
|
|
||||||
std::unique_ptr<geos::geom::LineString> geos = geos_factory.create_linestring(wnl, osmium::geom::use_nodes::all, osmium::geom::direction::backward);
|
|
||||||
REQUIRE(geos_to_wkb(geos.get()) == wkb);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("area_1outer_0inner") {
|
|
||||||
osmium::geom::WKBFactory<> wkb_factory(osmium::geom::wkb_type::wkb, osmium::geom::out_type::hex);
|
|
||||||
osmium::geom::GEOSFactory<> geos_factory;
|
|
||||||
|
|
||||||
osmium::memory::Buffer buffer(10000);
|
|
||||||
const osmium::Area& area = create_test_area_1outer_0inner(buffer);
|
|
||||||
|
|
||||||
std::string wkb = wkb_factory.create_multipolygon(area);
|
|
||||||
std::unique_ptr<geos::geom::MultiPolygon> geos = geos_factory.create_multipolygon(area);
|
|
||||||
REQUIRE(geos_to_wkb(geos.get()) == wkb);
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("area_1outer_1inner") {
|
|
||||||
osmium::geom::WKBFactory<> wkb_factory(osmium::geom::wkb_type::wkb, osmium::geom::out_type::hex);
|
|
||||||
osmium::geom::GEOSFactory<> geos_factory;
|
|
||||||
|
|
||||||
osmium::memory::Buffer buffer(10000);
|
|
||||||
const osmium::Area& area = create_test_area_1outer_1inner(buffer);
|
|
||||||
|
|
||||||
std::string wkb = wkb_factory.create_multipolygon(area);
|
|
||||||
std::unique_ptr<geos::geom::MultiPolygon> geos = geos_factory.create_multipolygon(area);
|
|
||||||
REQUIRE(geos_to_wkb(geos.get()) == wkb);
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("area_2outer_2inner") {
|
|
||||||
osmium::geom::WKBFactory<> wkb_factory(osmium::geom::wkb_type::wkb, osmium::geom::out_type::hex);
|
|
||||||
osmium::geom::GEOSFactory<> geos_factory;
|
|
||||||
|
|
||||||
osmium::memory::Buffer buffer(10000);
|
|
||||||
const osmium::Area& area = create_test_area_2outer_2inner(buffer);
|
|
||||||
|
|
||||||
std::string wkb = wkb_factory.create_multipolygon(area);
|
|
||||||
std::unique_ptr<geos::geom::MultiPolygon> geos = geos_factory.create_multipolygon(area);
|
|
||||||
REQUIRE(geos_to_wkb(geos.get()) == wkb);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
132
third_party/libosmium/test/t/geom/test_ogr.cpp
vendored
132
third_party/libosmium/test/t/geom/test_ogr.cpp
vendored
@ -5,121 +5,115 @@
|
|||||||
#include "area_helper.hpp"
|
#include "area_helper.hpp"
|
||||||
#include "wnl_helper.hpp"
|
#include "wnl_helper.hpp"
|
||||||
|
|
||||||
TEST_CASE("OGR_Geometry") {
|
TEST_CASE("OGR point geometry") {
|
||||||
|
|
||||||
SECTION("point") {
|
|
||||||
osmium::geom::OGRFactory<> factory;
|
osmium::geom::OGRFactory<> factory;
|
||||||
|
|
||||||
std::unique_ptr<OGRPoint> point {factory.create_point(osmium::Location(3.2, 4.2))};
|
SECTION("point") {
|
||||||
REQUIRE(3.2 == point->getX());
|
std::unique_ptr<OGRPoint> point{factory.create_point(osmium::Location{3.2, 4.2})};
|
||||||
REQUIRE(4.2 == point->getY());
|
REQUIRE(3.2 == point->getX());
|
||||||
|
REQUIRE(4.2 == point->getY());
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("empty_point") {
|
||||||
|
REQUIRE_THROWS_AS(factory.create_point(osmium::Location()), osmium::invalid_location);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("empty_point") {
|
TEST_CASE("OGR linestring geometry") {
|
||||||
osmium::geom::OGRFactory<> factory;
|
osmium::geom::OGRFactory<> factory;
|
||||||
|
osmium::memory::Buffer buffer{10000};
|
||||||
|
const auto& wnl = create_test_wnl_okay(buffer);
|
||||||
|
|
||||||
REQUIRE_THROWS_AS(factory.create_point(osmium::Location()), osmium::invalid_location);
|
SECTION("linestring, default") {
|
||||||
}
|
std::unique_ptr<OGRLineString> linestring{factory.create_linestring(wnl)};
|
||||||
|
|
||||||
SECTION("linestring") {
|
|
||||||
osmium::geom::OGRFactory<> factory;
|
|
||||||
|
|
||||||
osmium::memory::Buffer buffer(10000);
|
|
||||||
auto &wnl = create_test_wnl_okay(buffer);
|
|
||||||
|
|
||||||
{
|
|
||||||
std::unique_ptr<OGRLineString> linestring {factory.create_linestring(wnl)};
|
|
||||||
REQUIRE(3 == linestring->getNumPoints());
|
REQUIRE(3 == linestring->getNumPoints());
|
||||||
|
|
||||||
REQUIRE(3.2 == linestring->getX(0));
|
REQUIRE(3.2 == linestring->getX(0));
|
||||||
REQUIRE(3.6 == linestring->getX(2));
|
REQUIRE(3.6 == linestring->getX(2));
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
SECTION("linestring, unique nodes, backwards") {
|
||||||
std::unique_ptr<OGRLineString> linestring {factory.create_linestring(wnl, osmium::geom::use_nodes::unique, osmium::geom::direction::backward)};
|
std::unique_ptr<OGRLineString> linestring{factory.create_linestring(wnl, osmium::geom::use_nodes::unique, osmium::geom::direction::backward)};
|
||||||
REQUIRE(3 == linestring->getNumPoints());
|
REQUIRE(3 == linestring->getNumPoints());
|
||||||
|
|
||||||
REQUIRE(3.6 == linestring->getX(0));
|
REQUIRE(3.6 == linestring->getX(0));
|
||||||
REQUIRE(3.2 == linestring->getX(2));
|
REQUIRE(3.2 == linestring->getX(2));
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
SECTION("linestring, all nodes") {
|
||||||
std::unique_ptr<OGRLineString> linestring {factory.create_linestring(wnl, osmium::geom::use_nodes::all)};
|
std::unique_ptr<OGRLineString> linestring{factory.create_linestring(wnl, osmium::geom::use_nodes::all)};
|
||||||
REQUIRE(4 == linestring->getNumPoints());
|
REQUIRE(4 == linestring->getNumPoints());
|
||||||
|
|
||||||
REQUIRE(3.2 == linestring->getX(0));
|
REQUIRE(3.2 == linestring->getX(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
SECTION("linestring, all nodes, backwards") {
|
||||||
std::unique_ptr<OGRLineString> linestring {factory.create_linestring(wnl, osmium::geom::use_nodes::all, osmium::geom::direction::backward)};
|
std::unique_ptr<OGRLineString> linestring{factory.create_linestring(wnl, osmium::geom::use_nodes::all, osmium::geom::direction::backward)};
|
||||||
REQUIRE(4 == linestring->getNumPoints());
|
REQUIRE(4 == linestring->getNumPoints());
|
||||||
|
|
||||||
REQUIRE(3.6 == linestring->getX(0));
|
REQUIRE(3.6 == linestring->getX(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("area_1outer_0inner") {
|
TEST_CASE("OGR area geometry") {
|
||||||
osmium::geom::OGRFactory<> factory;
|
osmium::geom::OGRFactory<> factory;
|
||||||
|
osmium::memory::Buffer buffer{10000};
|
||||||
|
|
||||||
osmium::memory::Buffer buffer(10000);
|
SECTION("area_1outer_0inner") {
|
||||||
const osmium::Area& area = create_test_area_1outer_0inner(buffer);
|
const osmium::Area& area = create_test_area_1outer_0inner(buffer);
|
||||||
|
|
||||||
std::unique_ptr<OGRMultiPolygon> mp {factory.create_multipolygon(area)};
|
std::unique_ptr<OGRMultiPolygon> mp {factory.create_multipolygon(area)};
|
||||||
REQUIRE(1 == mp->getNumGeometries());
|
REQUIRE(1 == mp->getNumGeometries());
|
||||||
|
|
||||||
const OGRPolygon* p0 = dynamic_cast<const OGRPolygon*>(mp->getGeometryRef(0));
|
const OGRPolygon* p0 = dynamic_cast<const OGRPolygon*>(mp->getGeometryRef(0));
|
||||||
REQUIRE(p0);
|
REQUIRE(p0);
|
||||||
REQUIRE(0 == p0->getNumInteriorRings());
|
REQUIRE(0 == p0->getNumInteriorRings());
|
||||||
|
|
||||||
const OGRLineString* l0e = p0->getExteriorRing();
|
const OGRLineString* l0e = p0->getExteriorRing();
|
||||||
REQUIRE(4 == l0e->getNumPoints());
|
REQUIRE(4 == l0e->getNumPoints());
|
||||||
|
|
||||||
REQUIRE(3.5 == l0e->getX(1));
|
REQUIRE(3.5 == l0e->getX(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("area_1outer_1inner") {
|
SECTION("area_1outer_1inner") {
|
||||||
osmium::geom::OGRFactory<> factory;
|
const osmium::Area& area = create_test_area_1outer_1inner(buffer);
|
||||||
|
|
||||||
osmium::memory::Buffer buffer(10000);
|
std::unique_ptr<OGRMultiPolygon> mp {factory.create_multipolygon(area)};
|
||||||
const osmium::Area& area = create_test_area_1outer_1inner(buffer);
|
REQUIRE(1 == mp->getNumGeometries());
|
||||||
|
|
||||||
std::unique_ptr<OGRMultiPolygon> mp {factory.create_multipolygon(area)};
|
const OGRPolygon* p0 = dynamic_cast<const OGRPolygon*>(mp->getGeometryRef(0));
|
||||||
REQUIRE(1 == mp->getNumGeometries());
|
REQUIRE(p0);
|
||||||
|
REQUIRE(1 == p0->getNumInteriorRings());
|
||||||
|
|
||||||
const OGRPolygon* p0 = dynamic_cast<const OGRPolygon*>(mp->getGeometryRef(0));
|
const OGRLineString* l0e = p0->getExteriorRing();
|
||||||
REQUIRE(p0);
|
REQUIRE(5 == l0e->getNumPoints());
|
||||||
REQUIRE(1 == p0->getNumInteriorRings());
|
|
||||||
|
|
||||||
const OGRLineString* l0e = p0->getExteriorRing();
|
const OGRLineString* l0i0 = p0->getInteriorRing(0);
|
||||||
REQUIRE(5 == l0e->getNumPoints());
|
REQUIRE(5 == l0i0->getNumPoints());
|
||||||
|
}
|
||||||
|
|
||||||
const OGRLineString* l0i0 = p0->getInteriorRing(0);
|
SECTION("area_2outer_2inner") {
|
||||||
REQUIRE(5 == l0i0->getNumPoints());
|
const osmium::Area& area = create_test_area_2outer_2inner(buffer);
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("area_2outer_2inner") {
|
std::unique_ptr<OGRMultiPolygon> mp {factory.create_multipolygon(area)};
|
||||||
osmium::geom::OGRFactory<> factory;
|
REQUIRE(2 == mp->getNumGeometries());
|
||||||
|
|
||||||
osmium::memory::Buffer buffer(10000);
|
const OGRPolygon* p0 = dynamic_cast<const OGRPolygon*>(mp->getGeometryRef(0));
|
||||||
const osmium::Area& area = create_test_area_2outer_2inner(buffer);
|
REQUIRE(p0);
|
||||||
|
REQUIRE(2 == p0->getNumInteriorRings());
|
||||||
|
|
||||||
std::unique_ptr<OGRMultiPolygon> mp {factory.create_multipolygon(area)};
|
const OGRLineString* l0e = p0->getExteriorRing();
|
||||||
REQUIRE(2 == mp->getNumGeometries());
|
REQUIRE(5 == l0e->getNumPoints());
|
||||||
|
|
||||||
const OGRPolygon* p0 = dynamic_cast<const OGRPolygon*>(mp->getGeometryRef(0));
|
const OGRPolygon* p1 = dynamic_cast<const OGRPolygon*>(mp->getGeometryRef(1));
|
||||||
REQUIRE(p0);
|
REQUIRE(p1);
|
||||||
REQUIRE(2 == p0->getNumInteriorRings());
|
REQUIRE(0 == p1->getNumInteriorRings());
|
||||||
|
|
||||||
const OGRLineString* l0e = p0->getExteriorRing();
|
const OGRLineString* l1e = p1->getExteriorRing();
|
||||||
REQUIRE(5 == l0e->getNumPoints());
|
REQUIRE(5 == l1e->getNumPoints());
|
||||||
|
}
|
||||||
const OGRPolygon* p1 = dynamic_cast<const OGRPolygon*>(mp->getGeometryRef(1));
|
|
||||||
REQUIRE(p1);
|
|
||||||
REQUIRE(0 == p1->getNumInteriorRings());
|
|
||||||
|
|
||||||
const OGRLineString* l1e = p1->getExteriorRing();
|
|
||||||
REQUIRE(5 == l1e->getNumPoints());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
100
third_party/libosmium/test/t/geom/test_ogr_wkb.cpp
vendored
Normal file
100
third_party/libosmium/test/t/geom/test_ogr_wkb.cpp
vendored
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
|
||||||
|
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
||||||
|
|
||||||
|
#include "catch.hpp"
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <sstream>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include <osmium/geom/ogr.hpp>
|
||||||
|
#include <osmium/geom/wkb.hpp>
|
||||||
|
|
||||||
|
#include "area_helper.hpp"
|
||||||
|
#include "wnl_helper.hpp"
|
||||||
|
|
||||||
|
std::string to_wkb(const OGRGeometry* geometry) {
|
||||||
|
std::string buffer;
|
||||||
|
buffer.resize(geometry->WkbSize());
|
||||||
|
|
||||||
|
geometry->exportToWkb(wkbNDR, const_cast<unsigned char*>(reinterpret_cast<const unsigned char*>(buffer.data())));
|
||||||
|
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("compare WKB point against GDAL/OGR") {
|
||||||
|
osmium::geom::WKBFactory<> wkb_factory{osmium::geom::wkb_type::wkb};
|
||||||
|
osmium::geom::OGRFactory<> ogr_factory;
|
||||||
|
|
||||||
|
osmium::Location loc{3.2, 4.2};
|
||||||
|
const std::string wkb{wkb_factory.create_point(loc)};
|
||||||
|
const std::unique_ptr<OGRPoint> geometry = ogr_factory.create_point(loc);
|
||||||
|
REQUIRE(to_wkb(geometry.get()) == wkb);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("compare WKB linestring against GDAL/OGR") {
|
||||||
|
osmium::geom::WKBFactory<> wkb_factory{osmium::geom::wkb_type::wkb};
|
||||||
|
osmium::geom::OGRFactory<> ogr_factory;
|
||||||
|
osmium::memory::Buffer buffer{10000};
|
||||||
|
|
||||||
|
const auto& wnl = create_test_wnl_okay(buffer);
|
||||||
|
|
||||||
|
SECTION("linestring") {
|
||||||
|
const std::string wkb{wkb_factory.create_linestring(wnl)};
|
||||||
|
const std::unique_ptr<OGRLineString> geometry = ogr_factory.create_linestring(wnl);
|
||||||
|
REQUIRE(to_wkb(geometry.get()) == wkb);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("linestring, unique nodes, backwards") {
|
||||||
|
const std::string wkb{wkb_factory.create_linestring(wnl, osmium::geom::use_nodes::unique, osmium::geom::direction::backward)};
|
||||||
|
const std::unique_ptr<OGRLineString> geometry = ogr_factory.create_linestring(wnl, osmium::geom::use_nodes::unique, osmium::geom::direction::backward);
|
||||||
|
REQUIRE(to_wkb(geometry.get()) == wkb);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("linestring, all nodes, forwards") {
|
||||||
|
const std::string wkb{wkb_factory.create_linestring(wnl, osmium::geom::use_nodes::all)};
|
||||||
|
const std::unique_ptr<OGRLineString> geometry = ogr_factory.create_linestring(wnl, osmium::geom::use_nodes::all);
|
||||||
|
REQUIRE(to_wkb(geometry.get()) == wkb);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("linestring, all nodes, backwards") {
|
||||||
|
const std::string wkb{wkb_factory.create_linestring(wnl, osmium::geom::use_nodes::all, osmium::geom::direction::backward)};
|
||||||
|
const std::unique_ptr<OGRLineString> geometry = ogr_factory.create_linestring(wnl, osmium::geom::use_nodes::all, osmium::geom::direction::backward);
|
||||||
|
REQUIRE(to_wkb(geometry.get()) == wkb);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("compare WKB area against GDAL/OGR") {
|
||||||
|
osmium::geom::WKBFactory<> wkb_factory{osmium::geom::wkb_type::wkb};
|
||||||
|
osmium::geom::OGRFactory<> ogr_factory;
|
||||||
|
osmium::memory::Buffer buffer{10000};
|
||||||
|
|
||||||
|
SECTION("area_1outer_0inner") {
|
||||||
|
const osmium::Area& area = create_test_area_1outer_0inner(buffer);
|
||||||
|
|
||||||
|
const std::string wkb{wkb_factory.create_multipolygon(area)};
|
||||||
|
const std::unique_ptr<OGRMultiPolygon> geometry = ogr_factory.create_multipolygon(area);
|
||||||
|
REQUIRE(to_wkb(geometry.get()) == wkb);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("area_1outer_1inner") {
|
||||||
|
const osmium::Area& area = create_test_area_1outer_1inner(buffer);
|
||||||
|
|
||||||
|
const std::string wkb{wkb_factory.create_multipolygon(area)};
|
||||||
|
const std::unique_ptr<OGRMultiPolygon> geometry = ogr_factory.create_multipolygon(area);
|
||||||
|
REQUIRE(to_wkb(geometry.get()) == wkb);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("area_2outer_2inner") {
|
||||||
|
const osmium::Area& area = create_test_area_2outer_2inner(buffer);
|
||||||
|
|
||||||
|
const std::string wkb{wkb_factory.create_multipolygon(area)};
|
||||||
|
const std::unique_ptr<OGRMultiPolygon> geometry = ogr_factory.create_multipolygon(area);
|
||||||
|
REQUIRE(to_wkb(geometry.get()) == wkb);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -6,144 +6,121 @@
|
|||||||
#include <osmium/geom/mercator_projection.hpp>
|
#include <osmium/geom/mercator_projection.hpp>
|
||||||
#include <osmium/geom/projection.hpp>
|
#include <osmium/geom/projection.hpp>
|
||||||
|
|
||||||
TEST_CASE("Projection") {
|
TEST_CASE("Indentity Projection") {
|
||||||
|
|
||||||
SECTION("identity_projection") {
|
|
||||||
osmium::geom::IdentityProjection projection;
|
osmium::geom::IdentityProjection projection;
|
||||||
REQUIRE(4326 == projection.epsg());
|
REQUIRE(4326 == projection.epsg());
|
||||||
REQUIRE("+proj=longlat +datum=WGS84 +no_defs" == projection.proj_string());
|
REQUIRE("+proj=longlat +datum=WGS84 +no_defs" == projection.proj_string());
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("project_location_4326") {
|
TEST_CASE("Projection 4326") {
|
||||||
osmium::geom::Projection projection(4326);
|
osmium::geom::Projection projection{4326};
|
||||||
REQUIRE(4326 == projection.epsg());
|
REQUIRE(4326 == projection.epsg());
|
||||||
REQUIRE("+init=epsg:4326" == projection.proj_string());
|
REQUIRE("+init=epsg:4326" == projection.proj_string());
|
||||||
|
|
||||||
const osmium::Location loc(1.0, 2.0);
|
const osmium::Location loc{1.0, 2.0};
|
||||||
const osmium::geom::Coordinates c {1.0, 2.0};
|
const osmium::geom::Coordinates c{1.0, 2.0};
|
||||||
REQUIRE(c == projection(loc));
|
REQUIRE(c == projection(loc));
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("project_location_4326_string") {
|
TEST_CASE("Projection 4326 from init string") {
|
||||||
osmium::geom::Projection projection("+init=epsg:4326");
|
osmium::geom::Projection projection{"+init=epsg:4326"};
|
||||||
REQUIRE(-1 == projection.epsg());
|
REQUIRE(-1 == projection.epsg());
|
||||||
REQUIRE("+init=epsg:4326" == projection.proj_string());
|
REQUIRE("+init=epsg:4326" == projection.proj_string());
|
||||||
|
|
||||||
const osmium::Location loc(1.0, 2.0);
|
const osmium::Location loc{1.0, 2.0};
|
||||||
const osmium::geom::Coordinates c {1.0, 2.0};
|
const osmium::geom::Coordinates c{1.0, 2.0};
|
||||||
REQUIRE(c == projection(loc));
|
REQUIRE(c == projection(loc));
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("unknown_projection_string") {
|
TEST_CASE("Creating projection from unknown init string") {
|
||||||
REQUIRE_THROWS_AS(osmium::geom::Projection projection("abc"), osmium::projection_error);
|
REQUIRE_THROWS_AS(osmium::geom::Projection projection{"abc"}, osmium::projection_error);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("unknown_epsg_code") {
|
TEST_CASE("Creating projection from unknown EPSG code") {
|
||||||
REQUIRE_THROWS_AS(osmium::geom::Projection projection(9999999), osmium::projection_error);
|
REQUIRE_THROWS_AS(osmium::geom::Projection projection{9999999}, osmium::projection_error);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("project_location_3857") {
|
TEST_CASE("Projection 3857") {
|
||||||
osmium::geom::Projection projection(3857);
|
osmium::geom::Projection projection{3857};
|
||||||
REQUIRE(3857 == projection.epsg());
|
REQUIRE(3857 == projection.epsg());
|
||||||
REQUIRE("+init=epsg:3857" == projection.proj_string());
|
REQUIRE("+init=epsg:3857" == projection.proj_string());
|
||||||
|
|
||||||
{
|
SECTION("Zero coordinates") {
|
||||||
const osmium::Location loc(0.0, 0.0);
|
const osmium::Location loc{0.0, 0.0};
|
||||||
const osmium::geom::Coordinates c {0.0, 0.0};
|
const osmium::geom::Coordinates c{0.0, 0.0};
|
||||||
REQUIRE(projection(loc).x == Approx(c.x).epsilon(0.1));
|
REQUIRE(projection(loc).x == Approx(c.x).epsilon(0.1));
|
||||||
REQUIRE(projection(loc).y == Approx(c.y).epsilon(0.1));
|
REQUIRE(projection(loc).y == Approx(c.y).epsilon(0.1));
|
||||||
}
|
}
|
||||||
{
|
|
||||||
const osmium::Location loc(180.0, 0.0);
|
SECTION("Max longitude") {
|
||||||
const osmium::geom::Coordinates c {20037508.34, 0.0};
|
const osmium::Location loc{180.0, 0.0};
|
||||||
|
const osmium::geom::Coordinates c{20037508.34, 0.0};
|
||||||
REQUIRE(projection(loc).x == Approx(c.x).epsilon(0.1));
|
REQUIRE(projection(loc).x == Approx(c.x).epsilon(0.1));
|
||||||
REQUIRE(projection(loc).y == Approx(c.y).epsilon(0.1));
|
REQUIRE(projection(loc).y == Approx(c.y).epsilon(0.1));
|
||||||
}
|
}
|
||||||
{
|
|
||||||
const osmium::Location loc(180.0, 0.0);
|
SECTION("Min longitude") {
|
||||||
const osmium::geom::Coordinates c {20037508.34, 0.0};
|
const osmium::Location loc{-180.0, 0.0};
|
||||||
|
const osmium::geom::Coordinates c{-20037508.34, 0.0};
|
||||||
REQUIRE(projection(loc).x == Approx(c.x).epsilon(0.1));
|
REQUIRE(projection(loc).x == Approx(c.x).epsilon(0.1));
|
||||||
REQUIRE(projection(loc).y == Approx(c.y).epsilon(0.1));
|
REQUIRE(projection(loc).y == Approx(c.y).epsilon(0.1));
|
||||||
}
|
}
|
||||||
{
|
|
||||||
const osmium::Location loc(0.0, 85.0511288);
|
SECTION("Max latitude") {
|
||||||
const osmium::geom::Coordinates c {0.0, 20037508.34};
|
const osmium::Location loc{0.0, 85.0511288};
|
||||||
|
const osmium::geom::Coordinates c{0.0, 20037508.34};
|
||||||
REQUIRE(projection(loc).x == Approx(c.x).epsilon(0.1));
|
REQUIRE(projection(loc).x == Approx(c.x).epsilon(0.1));
|
||||||
REQUIRE(projection(loc).y == Approx(c.y).epsilon(0.1));
|
REQUIRE(projection(loc).y == Approx(c.y).epsilon(0.1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("project_location_mercator") {
|
TEST_CASE("MercatorProjection") {
|
||||||
osmium::geom::MercatorProjection projection;
|
osmium::geom::MercatorProjection projection;
|
||||||
|
|
||||||
{
|
SECTION("Zero coordinates") {
|
||||||
const osmium::Location loc(0.0, 0.0);
|
const osmium::Location loc{0.0, 0.0};
|
||||||
const osmium::geom::Coordinates c {0.0, 0.0};
|
const osmium::geom::Coordinates c{0.0, 0.0};
|
||||||
REQUIRE(projection(loc).x == Approx(c.x).epsilon(0.1));
|
REQUIRE(projection(loc).x == Approx(c.x).epsilon(0.1));
|
||||||
REQUIRE(projection(loc).y == Approx(c.y).epsilon(0.1));
|
REQUIRE(projection(loc).y == Approx(c.y).epsilon(0.1));
|
||||||
}
|
}
|
||||||
{
|
|
||||||
const osmium::Location loc(180.0, 0.0);
|
SECTION("Max longitude") {
|
||||||
const osmium::geom::Coordinates c {20037508.34, 0.0};
|
const osmium::Location loc{180.0, 0.0};
|
||||||
|
const osmium::geom::Coordinates c{20037508.34, 0.0};
|
||||||
REQUIRE(projection(loc).x == Approx(c.x).epsilon(0.1));
|
REQUIRE(projection(loc).x == Approx(c.x).epsilon(0.1));
|
||||||
REQUIRE(projection(loc).y == Approx(c.y).epsilon(0.1));
|
REQUIRE(projection(loc).y == Approx(c.y).epsilon(0.1));
|
||||||
}
|
}
|
||||||
{
|
|
||||||
const osmium::Location loc(180.0, 0.0);
|
SECTION("Min longitude") {
|
||||||
const osmium::geom::Coordinates c {20037508.34, 0.0};
|
const osmium::Location loc{-180.0, 0.0};
|
||||||
|
const osmium::geom::Coordinates c{-20037508.34, 0.0};
|
||||||
REQUIRE(projection(loc).x == Approx(c.x).epsilon(0.1));
|
REQUIRE(projection(loc).x == Approx(c.x).epsilon(0.1));
|
||||||
REQUIRE(projection(loc).y == Approx(c.y).epsilon(0.1));
|
REQUIRE(projection(loc).y == Approx(c.y).epsilon(0.1));
|
||||||
}
|
}
|
||||||
{
|
|
||||||
const osmium::Location loc(0.0, 85.0511288);
|
SECTION("Max latitude") {
|
||||||
const osmium::geom::Coordinates c {0.0, 20037508.34};
|
const osmium::Location loc{0.0, 85.0511288};
|
||||||
|
const osmium::geom::Coordinates c{0.0, 20037508.34};
|
||||||
REQUIRE(projection(loc).x == Approx(c.x).epsilon(0.1));
|
REQUIRE(projection(loc).x == Approx(c.x).epsilon(0.1));
|
||||||
REQUIRE(projection(loc).y == Approx(c.y).epsilon(0.1));
|
REQUIRE(projection(loc).y == Approx(c.y).epsilon(0.1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("compare_mercators") {
|
TEST_CASE("Compare mercator implementations") {
|
||||||
osmium::geom::MercatorProjection projection_merc;
|
osmium::geom::MercatorProjection projection_merc;
|
||||||
osmium::geom::Projection projection_3857(3857);
|
osmium::geom::Projection projection_3857{3857};
|
||||||
REQUIRE(3857 == projection_3857.epsg());
|
|
||||||
REQUIRE("+init=epsg:3857" == projection_3857.proj_string());
|
|
||||||
|
|
||||||
{
|
SECTION("random coordinates") {
|
||||||
const osmium::Location loc(4.2, 27.3);
|
std::random_device rd;
|
||||||
REQUIRE(projection_merc(loc).x == Approx(projection_3857(loc).x).epsilon(0.1));
|
std::mt19937 gen{rd()};
|
||||||
REQUIRE(projection_merc(loc).y == Approx(projection_3857(loc).y).epsilon(0.1));
|
std::uniform_real_distribution<> dis_x{-180.0, 180.0};
|
||||||
}
|
std::uniform_real_distribution<> dis_y{-90.0, 90.0};
|
||||||
{
|
|
||||||
const osmium::Location loc(160.789, -42.42);
|
|
||||||
REQUIRE(projection_merc(loc).x == Approx(projection_3857(loc).x).epsilon(0.1));
|
|
||||||
REQUIRE(projection_merc(loc).y == Approx(projection_3857(loc).y).epsilon(0.1));
|
|
||||||
}
|
|
||||||
{
|
|
||||||
const osmium::Location loc(-0.001, 0.001);
|
|
||||||
REQUIRE(projection_merc(loc).x == Approx(projection_3857(loc).x).epsilon(0.1));
|
|
||||||
REQUIRE(projection_merc(loc).y == Approx(projection_3857(loc).y).epsilon(0.1));
|
|
||||||
}
|
|
||||||
{
|
|
||||||
const osmium::Location loc(-85.2, -85.2);
|
|
||||||
REQUIRE(projection_merc(loc).x == Approx(projection_3857(loc).x).epsilon(0.1));
|
|
||||||
REQUIRE(projection_merc(loc).y == Approx(projection_3857(loc).y).epsilon(0.1));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("compare_mercators") {
|
for (int n = 0; n < 10000; ++n) {
|
||||||
osmium::geom::MercatorProjection projection_merc;
|
const osmium::Location loc{dis_x(gen), dis_y(gen)};
|
||||||
osmium::geom::Projection projection_3857(3857);
|
REQUIRE(projection_merc(loc).x == Approx(projection_3857(loc).x).epsilon(0.1));
|
||||||
|
REQUIRE(projection_merc(loc).y == Approx(projection_3857(loc).y).epsilon(0.1));
|
||||||
std::random_device rd;
|
}
|
||||||
std::mt19937 gen(rd());
|
|
||||||
std::uniform_real_distribution<> dis_x(-180.0, 180.0);
|
|
||||||
std::uniform_real_distribution<> dis_y(-90.0, 90.0);
|
|
||||||
|
|
||||||
for (int n = 0; n < 100000; ++n) {
|
|
||||||
const osmium::Location loc(dis_x(gen), dis_y(gen));
|
|
||||||
REQUIRE(projection_merc(loc).x == Approx(projection_3857(loc).x).epsilon(0.1));
|
|
||||||
REQUIRE(projection_merc(loc).y == Approx(projection_3857(loc).y).epsilon(0.1));
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -4,8 +4,6 @@
|
|||||||
|
|
||||||
#include <osmium/geom/tile.hpp>
|
#include <osmium/geom/tile.hpp>
|
||||||
|
|
||||||
#include "helper.hpp"
|
|
||||||
|
|
||||||
#include "test_tile_data.hpp"
|
#include "test_tile_data.hpp"
|
||||||
|
|
||||||
TEST_CASE("Tile from x0.0 y0.0 at zoom 0") {
|
TEST_CASE("Tile from x0.0 y0.0 at zoom 0") {
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user